Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2019-01-31 Thread Arty
Sorry, I am very busy lately and was not able to do anything Widelands-related 
or even look here at all. This will likely continue for quite some time, but 
I'll have a look at it this weekend.
-- 
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358718
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/robust-file-saving.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2018-12-25 Thread Arty
Merry Christmas, and thanks for testing.

As for "ways to break it", there *should* at least be no new ways to do so. 
After all, the main purpose of this branch is to prevent any such breaking when 
we save maps/games. (And there aren't a lot of new things that could break on 
their own.) The actual saving routine itself could potentially break somewhere 
(I didn't change anything there), but as long as that involves throwing an 
exception, it will be caught.

Under Windows I tested this quite a lot myself. Usually, errors should 
"normally" not happen without someone trying to force them. Error scenarios 
that could be forced for testing would be:
1) after choosing a dir and filename, replace the dir by a non-dir file of that 
name, then try saving -> dir creation fails
2) lock a file (e.g. open it with a zip packer or so that locks the file), then 
try saving to that file -> renaming (for backup) fails
3) make a file read-only, then try saving to that file -> deleting backup 
(renamed file) fails (no ingame message though)
4) try saving on a read-only medium -> saving data fails
(There might be slight differences between platforms, especially with the file 
locking.)

Other errors would actually be hard to set off on purpose. That would likely 
require different processes to access the same file at the same time. Hard to 
even force, and extremely unlikely to happen by accident, but such errors are 
caught just in case. (In my testing for those scenarios I just temporarily 
added exceptions throws at some places.)

-- 
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358718
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/robust-file-saving.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bugfix-1805042-S2map-preloader-checks into lp:widelands

2018-12-11 Thread Arty
Arty has proposed merging 
lp:~widelands-dev/widelands/bugfix-1805042-S2map-preloader-checks into 
lp:widelands.

Commit message:
validity checks for S2 map headers to avoid crashes when preloading invalid S2 
map files

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1805042 in widelands: "segfault when trying to preload invalid file"
  https://bugs.launchpad.net/widelands/+bug/1805042

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bugfix-1805042-S2map-preloader-checks/+merge/360762
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bugfix-1805042-S2map-preloader-checks into 
lp:widelands.
=== modified file 'src/map_io/s2map.cc'
--- src/map_io/s2map.cc	2018-04-11 06:55:01 +
+++ src/map_io/s2map.cc	2018-12-12 00:02:20 +
@@ -61,6 +61,29 @@
 	char bulk[2290];  // unknown
 } /* size 2352 */;
 
+// Some basic checks to identify obviously invalid headers
+bool is_valid_header(const S2MapDescrHeader& header) {
+	if (strncmp(header.magic, "WORLD_V1.0", 10)) {
+		return false;
+	}
+	if (header.name[19]) {
+		return false;
+	}
+	if (header.w <= 0 || header.h <= 0) {
+		return false;
+	}
+	if (header.uses_world < 0 || header.uses_world > 2) {
+		return false;
+	}
+	if (header.nplayers < 0 || header.nplayers > 7) {
+		return false;
+	}
+	if (header.author[19]) {
+		return false;
+	}
+	return true;
+}
+
 // TODO(unknown): the following bob types appear in S2 maps but are unknown
 //  Somebody who can run Settlers II please check them out
 //  11 (0x0B)
@@ -400,9 +423,11 @@
 }
 
 /**
- * Load informational data of an S2 map
+ * Loads informational data of an S2 map.
+ * Throws exception if data is invalid.
  */
 void S2MapLoader::load_s2mf_header(FileRead& fr) {
+	// no need to check file size: fr.data(..) already throws if the file is too small
 	S2MapDescrHeader header;
 	memcpy(&header, fr.data(sizeof(header)), sizeof(header));
 
@@ -414,6 +439,11 @@
 	header.h = swap_16(header.h);
 #endif
 
+	// Check header validity to prevent unexpected crashes later
+	if (!is_valid_header(header)) {
+		throw wexception("invalid S2 file");
+	}
+
 	//  don't really set size, but make the structures valid
 	map_.width_ = header.w;
 	map_.height_ = header.h;

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2018-11-28 Thread Arty
The proposal to merge lp:~widelands-dev/widelands/robust-file-saving into 
lp:widelands has been updated.

Commit message changed to:

Introduces a new class to robustly handle saving of files (incl. dealing with 
backups, handling errors, etc.) and use it whenever maps/games are being saved.

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358718
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-file-saving into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/io-dependency-fix into lp:widelands

2018-11-28 Thread Arty
The proposal to merge lp:~widelands-dev/widelands/io-dependency-fix into 
lp:widelands has been updated.

Commit message changed to:

Remove a few superfluous includes which also breaks a small dependency cycle

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/io-dependency-fix/+merge/359658
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/io-dependency-fix into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/io-dependency-fix into lp:widelands

2018-11-27 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/io-dependency-fix into 
lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/io-dependency-fix/+merge/359658
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/io-dependency-fix into lp:widelands.
=== modified file 'src/io/filesystem/CMakeLists.txt'
--- src/io/filesystem/CMakeLists.txt	2018-05-16 13:51:48 +
+++ src/io/filesystem/CMakeLists.txt	2018-11-27 23:25:38 +
@@ -18,7 +18,6 @@
 base_log
 base_macros
 graphic_text_layout
-io_fileread
 io_stream
 third_party_minizip
 )

=== modified file 'src/io/filesystem/disk_filesystem.cc'
--- src/io/filesystem/disk_filesystem.cc	2018-11-14 10:14:50 +
+++ src/io/filesystem/disk_filesystem.cc	2018-11-27 23:25:38 +
@@ -41,7 +41,6 @@
 #include 
 #endif
 
-#include "base/log.h"
 #include "base/macros.h"
 #include "base/wexception.h"
 #include "io/filesystem/filesystem_exceptions.h"

=== modified file 'src/io/filesystem/layered_filesystem.cc'
--- src/io/filesystem/layered_filesystem.cc	2018-05-17 05:01:45 +
+++ src/io/filesystem/layered_filesystem.cc	2018-11-27 23:25:38 +
@@ -22,9 +22,7 @@
 #include 
 #include 
 
-#include "base/log.h"
 #include "base/wexception.h"
-#include "io/fileread.h"
 #include "io/streamread.h"
 
 LayeredFileSystem* g_fs;

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1796364-blinking-buildings into lp:widelands

2018-11-26 Thread Arty
I finished looking over it but admittedly not too deeply because it's just old 
code re-enabled. Code looks fine (aside from the ~ operator mentioned in the 
diff comment).
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1796364-blinking-buildings/+merge/359348
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-1796364-blinking-buildings into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1796364-blinking-buildings into lp:widelands

2018-11-26 Thread Arty
Started reviewing the code. Have one diff comment so far. Will continue later 
tonight.

Diff comments:

> 
> === added file 'src/logic/map_objects/draw_text.h'
> --- src/logic/map_objects/draw_text.h 1970-01-01 00:00:00 +
> +++ src/logic/map_objects/draw_text.h 2018-11-24 07:43:42 +
> @@ -0,0 +1,39 @@
> +/*
> + * Copyright (C) 2006-2018 by the Widelands Development Team
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H
> +#define WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H
> +
> +enum class TextToDraw {
> + kNone = 0,
> + kCensus = 1,
> + kStatistics = 2,
> +};
> +
> +inline TextToDraw operator|(TextToDraw a, TextToDraw b) {
> + return static_cast(static_cast(a) | 
> static_cast(b));
> +}
> +inline TextToDraw operator&(TextToDraw a, TextToDraw b) {
> + return static_cast(static_cast(a) & 
> static_cast(b));
> +}
> +inline TextToDraw operator~(TextToDraw a) {
> + return static_cast(~static_cast(a));

That might be dangerous. The result of the ~ is out of the range of the enum, 
and - as far as I could find out - that means that the actual result is 
unspecified, i.e., compilers might do unexpected things.

I coudn't actually find a lot where this is explicitly mentioned, but it's 
mentioned for example in 
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf (page 12, 
first paragraph) which I think was the latest proposal for enum class which 
eventually got accepted.

A safe version would be
static_cast(3 & ~static_cast(a))
althought this "3" would have to be adjusted if at some point the enum gets 
extended.
Or maybe we could just not define this operator. Simple checks can also easily 
be done without it. (And generally there shouldn't be any need for elobrate 
expressions where the operator would come in handy.)

> +}
> +
> +#endif  // end of include guard: WL_LOGIC_MAP_OBJECTS_DRAW_TEXT_H


-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1796364-blinking-buildings/+merge/359348
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-1796364-blinking-buildings into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/terrain_affinity_as_int into lp:widelands

2018-11-23 Thread Arty
Review: Approve

Looks good now.

The comment with the assciativity is kinda obsolete now though.

And using int64_t wasn't really necessary now that you use the weights linearly.
-- 
https://code.launchpad.net/~widelands-dev/widelands/terrain_affinity_as_int/+merge/358299
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/terrain_affinity_as_int.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/terrain_affinity_as_int into lp:widelands

2018-11-22 Thread Arty
Yes, the exponential function is the problem. Approximating it with highish 
precision using only integer calculations would require a lot of computation, 
which isn't really feasible. There are reasonable options though if we don't 
mind straying a little. The function we use here is basically a 
three-dimensional Gauß-curve, and I think we could find an alternative that 
roughly preserves the shape and can be done with a small number of integer 
operations.
It's probably not necessary though, but if we keep getting desyncs because of 
such platform/compiler-dependent computation differences, this would provide an 
option.

I also replied to your replies.

Diff comments:

> 
> === modified file 'src/logic/map_objects/terrain_affinity.cc'
> --- src/logic/map_objects/terrain_affinity.cc 2018-04-07 16:59:00 +
> +++ src/logic/map_objects/terrain_affinity.cc 2018-11-16 06:27:07 +
> @@ -33,85 +33,92 @@
>  
>  namespace {
>  
> +// Literature on cross-platform floating point precision-problems:
> +// https://arxiv.org/abs/cs/0701192
> +// Monniaux, David (2008): "The pitfalls of verifying floating-point 
> computations",
> +// in: ACM Transactions on Programming Languages and Systems 30, 3 (2008) 12.
> +//
> +// Recommends using heximal float constants, but we'd need to switch to 
> C++17 for that.
> +//
> +// 
> https://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/
> +
>  constexpr double pow2(const double& a) {
>   return a * a;
>  }
>  
>  // Helper function for probability_to_grow
>  // Calculates the probability to grow for the given affinity and terrain 
> values
> -double calculate_probability_to_grow(const TerrainAffinity& affinity,
> - double terrain_humidity,
> - double terrain_fertility,
> - double terrain_temperature) {
> -
> - constexpr double kHumidityWeight = 0.500086642549548;
> - constexpr double kFertilityWeight = 0.5292268046607387;
> - constexpr double kTemperatureWeight = 61.31300863608306;
> -
> - const double sigma_humidity = (1. - affinity.pickiness());
> - const double sigma_temperature = (1. - affinity.pickiness());
> - const double sigma_fertility = (1. - affinity.pickiness());
> -
> - return exp((-pow2((affinity.preferred_fertility() - terrain_fertility) /
> -   (kFertilityWeight * sigma_fertility)) -
> - pow2((affinity.preferred_humidity() - terrain_humidity) /
> -  (kHumidityWeight * sigma_humidity)) -
> - pow2((affinity.preferred_temperature() - 
> terrain_temperature) /
> -  (kTemperatureWeight * sigma_temperature))) /
> -2);
> +inline unsigned int calculate_probability_to_grow(const TerrainAffinity& 
> affinity,
> + int terrain_humidity,
> + int terrain_fertility,
> + int terrain_temperature) {
> + constexpr double kHumidityWeight = 5.00086642549548;
> + constexpr double kFertilityWeight = 5.292268046607387;
> + constexpr double kTemperatureWeight = 0.6131300863608306;
> +
> +// Avoid division by 0
> +assert(affinity.pickiness() < 100);
> + const double sigma = std::floor(100.0 - affinity.pickiness());
> +
> + const double result = exp(-
> +  (pow2(((affinity.preferred_fertility() - 
> terrain_fertility) / kFertilityWeight) / sigma) +
> +   (pow2(((affinity.preferred_humidity() - 
> terrain_humidity) / kHumidityWeight) / sigma) +

The operator "+" is left-to-right associative in C++ 
(https://en.cppreference.com/w/cpp/language/operator_precedence) so without 
those extra brackets the evaluation (inside the "exp(-(...))") would always be
"(fertility_part + humidity_part) + temperature_part".
for every compiler. You are simply forcing it to always be
"fertility_part + (humidity_part + temperature_part)", which is different but 
not inherently better.
Of course those two different evaluation orders could have slightly different 
results, but the order is specified by the expression, so every compiler would 
use the same order anyway.
Operator associativity is defined by the C++ standard, so compiler 
optimizations should not be able to change the order, but if they were then the 
extra brackets wouldn't stop them either.

Anyway, it doesn't really matter which way, I just think that with such a big 
expression we don't need to make it even harder to read by more brackets, 
especially not to separate those three semantically similar terms.

> +pow2(((affinity.preferred_temperature() - 
> terrain_temperature) / kTemperatureWeight) / sigma))) / 2.0);
> +
> +return static_cast(std::max(0.0, std::floor(result * 
> static_cast(TerrainAffinity::kPrecisionFactor;
>  }
>  
>  }  // n

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/empire04_unused_key_return_on_dismantle into lp:widelands

2018-11-21 Thread Arty
Review: Needs Fixing

Reviewed the code and tested quite a lot. Looks pretty good, but still doesn't 
work quite right. Not hard to fix though.

1) Now that you changed the design to requiring the buildcost table to be empty 
instead of listing wares with amount 0, the dismantle button does not appear 
for such empty tables. This is easily fixed in ‘wui/buildingwindow.cc’ by 
removing a ware check, i.e., removing lines 287 and 297 (and unindenting the 
block inbetween). I already tested this, it works fine.

2) Having no items shown in the box when hovering over the dismantle button 
looks good enough for me, but I can imagine that some might find this not nice. 
Maybe adding a little text “nothing” or so might be good. And (at a later 
point) maybe even a little icon.

3) See diff comments.


Diff comments:

> 
> === modified file 'data/campaigns/emp04.wmf/scripting/tribes/farm1.lua'
> --- data/campaigns/emp04.wmf/scripting/tribes/farm1.lua   2018-09-09 
> 17:58:55 +
> +++ data/campaigns/emp04.wmf/scripting/tribes/farm1.lua   2018-11-21 
> 09:48:10 +
> @@ -10,10 +10,6 @@
> enhancement = "empire_farm2",
>  
> return_on_dismantle = {
> -  planks = 0,
> -  granite = 0,
> -  marble = 0,
> -  marble_column = 0
> },

For farm1, return_on_dismantle should now be gone completely for the campaign 
to work properly. (The farm click check relies on having no dismantle button, 
and the text also says that the farms can't be dismantled.)

>  
> animations = {
> 
> === modified file 'src/logic/map_objects/buildcost.cc'
> --- src/logic/map_objects/buildcost.cc2018-04-07 16:59:00 +
> +++ src/logic/map_objects/buildcost.cc2018-11-21 09:48:10 +
> @@ -37,32 +35,37 @@
>  Buildcost::Buildcost(std::unique_ptr table, const Tribes& tribes)
> : std::map() {
>   for (const std::string& warename : table->keys()) {
> - int32_t value = INVALID_INDEX;
> - try {
> - DescriptionIndex const idx = 
> tribes.safe_ware_index(warename);
> - if (count(idx)) {
> - throw GameDataError(
> -"A buildcost item of this ware type has 
> already been defined: %s", warename.c_str());
> - }
> - value = table->get_int(warename);
> - const uint8_t ware_count = value;
> - if (ware_count != value) {
> - throw GameDataError("Ware count is out of range 
> 1 .. 255");
> - }
> - insert(std::pair(idx, 
> ware_count));
> - } catch (const WException& e) {
> - throw GameDataError("[buildcost] \"%s=%d\": %s", 
> warename.c_str(), value, e.what());
> - }
> + // Read ware index
> + if (!tribes.ware_exists(warename)) {
> + throw GameDataError("Buildcost: Unknown ware: %s", 
> warename.c_str());
> + }
> + DescriptionIndex const idx = tribes.safe_ware_index(warename);
> + if (count(idx) != 0) {

This condition is actually never true, because table->keys() returns a 
std::set, so even if a key appears multiple times in a lua table, it only 
occurs once in the set, so this loop also touches each key only once.

This is unrelated to this branch though, but we should probably fix this at 
some point. Maybe this should be fixed more generally anyway. (Not even sure if 
multiple occurrences of the same key make sense somewhere.) I guess I’ll make a 
proper bug report after thinking about it a bit more. But if you know a simple 
way to check this properly here, you can just add a fix here.

> + throw GameDataError(
> +"Buildcost: Ware '%s' is listed twice", 
> warename.c_str());
> + }
> +
> + // Read value
> + int32_t value = table->get_int(warename);
> + if (value < 1) {
> + throw GameDataError("Buildcost: Ware count needs to be 
> > 0 in \"%s=%d\".\nEmpty buildcost tables are allowed if you wish to have an 
> amount of 0.", warename.c_str(), value);
> + } else if (value > 255) {
> + throw GameDataError("Buildcost: Ware count needs to be 
> <= 255 0 in \"%s=%d\".", warename.c_str(), value);

1) The 0 after 255 should go away.
2) This throw actually crashes the whole application. The problem is the “<” in 
the text which - I assume - causes a crash in the rich text handling (attempt 
to interpret it as opening a tag) when trying to show the message box with the 
error. (Didn’t check this thoroughly yet, but simply deleting the “<” from the 
message avoids the crash. I’ll check this properly and make a bug report.)
For now, just replace the “<=” by “at most” or so.

> + }
> +
> + // Add
> + insert(std::pair(idx, value));
>   }
>  }

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/terrain_affinity_as_int into lp:widelands

2018-11-20 Thread Arty
Review: Needs Fixing

I reviewed the code and also tested somewhat. Still has a few issues, most of 
them minor though. See diff comments.

The file data\world\immovables\bush1\init.lua still has a few comments (lines 
86-94) referring to the floating point values, this should also be changed in 
this branch.

Overall it should be much less likely now to get different results based on 
platform/compiler dependent precision choices, but they might still happen. 
There are still things based on floating point calculations (like the main 
probability calculation in calculate_probability_to_grow) but they might be 
difficult to replace with pure integer based stuff.
That said, considering that the ratios of the final probabilities of the six 
best immovables already change significantly with this branch, we could 
possibly also change the basic probability calculation to somewhat that uses 
only integer operations but is not too far off from the current approach (which 
seems to have been based roughly on multivariate normal distributions).

Btw, where did those three weight constants in calculate_probability_to_grow 
originally come from? Their precision is too high to be from a simple "try and 
error until it feels right" approach. They still feel quite arbitrary though.

Diff comments:

> 
> === modified file 'src/logic/map_objects/terrain_affinity.cc'
> --- src/logic/map_objects/terrain_affinity.cc 2018-04-07 16:59:00 +
> +++ src/logic/map_objects/terrain_affinity.cc 2018-11-16 06:27:07 +
> @@ -33,85 +33,92 @@
>  
>  namespace {
>  
> +// Literature on cross-platform floating point precision-problems:
> +// https://arxiv.org/abs/cs/0701192
> +// Monniaux, David (2008): "The pitfalls of verifying floating-point 
> computations",
> +// in: ACM Transactions on Programming Languages and Systems 30, 3 (2008) 12.
> +//
> +// Recommends using heximal float constants, but we'd need to switch to 
> C++17 for that.
> +//
> +// 
> https://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/
> +
>  constexpr double pow2(const double& a) {

Can you please rename that to "sqr" or some such? ("pow2" usually stands for 
computing powers of two. It's really irritating here.) The function is only 
used three times in the function below, so a renaming is also quick to apply.

>   return a * a;
>  }
>  
>  // Helper function for probability_to_grow
>  // Calculates the probability to grow for the given affinity and terrain 
> values
> -double calculate_probability_to_grow(const TerrainAffinity& affinity,
> - double terrain_humidity,
> - double terrain_fertility,
> - double terrain_temperature) {
> -
> - constexpr double kHumidityWeight = 0.500086642549548;
> - constexpr double kFertilityWeight = 0.5292268046607387;
> - constexpr double kTemperatureWeight = 61.31300863608306;
> -
> - const double sigma_humidity = (1. - affinity.pickiness());
> - const double sigma_temperature = (1. - affinity.pickiness());
> - const double sigma_fertility = (1. - affinity.pickiness());
> -
> - return exp((-pow2((affinity.preferred_fertility() - terrain_fertility) /
> -   (kFertilityWeight * sigma_fertility)) -
> - pow2((affinity.preferred_humidity() - terrain_humidity) /
> -  (kHumidityWeight * sigma_humidity)) -
> - pow2((affinity.preferred_temperature() - 
> terrain_temperature) /
> -  (kTemperatureWeight * sigma_temperature))) /
> -2);
> +inline unsigned int calculate_probability_to_grow(const TerrainAffinity& 
> affinity,
> + int terrain_humidity,
> + int terrain_fertility,
> + int terrain_temperature) {
> + constexpr double kHumidityWeight = 5.00086642549548;
> + constexpr double kFertilityWeight = 5.292268046607387;
> + constexpr double kTemperatureWeight = 0.6131300863608306;
> +
> +// Avoid division by 0
> +assert(affinity.pickiness() < 100);
> + const double sigma = std::floor(100.0 - affinity.pickiness());
> +
> + const double result = exp(-
> +  (pow2(((affinity.preferred_fertility() - 
> terrain_fertility) / kFertilityWeight) / sigma) +
> +   (pow2(((affinity.preferred_humidity() - 
> terrain_humidity) / kHumidityWeight) / sigma) +

One pair of brackets is obsolete: The opening bracket before "pow2" in the line 
above, and the corresponding closing bracket in the line below. (The just group 
the humidity and temperature part together in the sum, but the swapped 
summation order won't give any benefit here.)

> +pow2(((affinity.preferred_temperature() - 
> terrain_temperature) / kTemperatureWeight) / sigma))) / 2.0);
> +
> +return stat

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/empire04_unused_key_return_on_dismantle into lp:widelands

2018-11-20 Thread Arty
I got ninja'd yesterday when I reviewed the code. :-)


As for the "needs positive return on dismantle" condition, I don't have a 
strong opinion, but I'd prefer to not have it, even though in most 
circumstances dismantling without return would be useless. My reasons:

1) The condition - even though it makes sense - doesn't really add anything. 
The game would work fine without it. And regular buildings (and most special 
builidings in campaigns) have proper return on dismantle amounts anyway, so I 
wouldn't expect "false" bug reports about this.

2) Not having the condition allows for a little more flavour in missions. Like 
in emp04. Or maybe there'll be a mission where destroying would come with a 
fire hazard to neighboring buildings, possibly destroying them, too. (Not sure 
this is possibly atm, i.e., whether we can detect the difference between 
dismantling and destroying via mission scripts. Just a general idea.)

3) If the building is not far from a warehouse with a builder available, 
dismantling without return is even a little faster than destroying. Difference 
is minor though.
-- 
https://code.launchpad.net/~widelands-dev/widelands/empire04_unused_key_return_on_dismantle/+merge/358273
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/empire04_unused_key_return_on_dismantle.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/empire04_unused_key_return_on_dismantle_no_ui into lp:widelands

2018-11-19 Thread Arty
Code looks good in principle, but haven't tested yet whether it really works as 
intended.

Two minor nits:
1) see diff comment
2) All the new lines (except when they were copied over) are indented with 
spaces instead of tabs.


Diff comments:

> === modified file 'src/logic/map_objects/tribes/building.cc'
> --- src/logic/map_objects/tribes/building.cc  2018-09-23 11:10:56 +
> +++ src/logic/map_objects/tribes/building.cc  2018-11-16 06:07:58 +
> @@ -151,9 +156,9 @@
>   return_enhanced_ =
>  
> Buildcost(table.get_table("return_on_dismantle_on_enhanced"), 
> egbase_.tribes());
>   } catch (const WException& e) {
> - throw wexception("An enhanced building must define 
> \"enhancement_cost\""
> + throw wexception("The enhanced building '%s' must 
> define \"enhancement_cost\""

This message is (and was before) not really related to this catch. If this 
catch block is reached then either because the other key 
("return_on_dismantle_on_enhanced") wasn't defined or because the Buildcost 
constructor threw when trying to read one of the table.

I think you should just get rid of the whole try-catch here and do it the same 
way you already did in the "buildcost" part above, i.e., check if the second 
key ("return_on_dismantle_on_enhanced") is defined and throw if not, but don't 
actually catch any exceptions. The Buildcost constructor will throw with a 
proper message anyway if it fails, no need to catch that and throw again with a 
message that is possibly even unrelated.

>"and 
> \"return_on_dismantle_on_enhanced\": %s",
> -  e.what());
> +  name().c_str(), e.what());
>   }
>   }
>  


-- 
https://code.launchpad.net/~widelands-dev/widelands/empire04_unused_key_return_on_dismantle_no_ui/+merge/358305
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/empire04_unused_key_return_on_dismantle_no_ui.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1798297-locale-C into lp:widelands

2018-11-19 Thread Arty
Code LGTM, just some minor indentation irregularities (see comments below).

Not tested because I don't have a working Linux system atm.

Diff comments:

> === modified file 'src/base/i18n.cc'
> --- src/base/i18n.cc  2018-08-12 06:47:11 +
> +++ src/base/i18n.cc  2018-11-16 06:30:53 +
> @@ -290,15 +290,26 @@
>   found = alt_str.find(',', 0);
>   }
>   if (leave_while) {
> - setenv("LANG", locale.c_str(), 1);
> + setenv("LC_ALL", locale.c_str(), 1);
> +setenv("LANG", locale.c_str(), 1);

indent should be tabs instead of spaces

>   setenv("LANGUAGE", locale.c_str(), 1);
>   } else {
> - log("No corresponding locale found - trying to set it via 
> LANGUAGE=%s, LANG=%s\n",
> - lang.c_str(), lang.c_str());
> + log("No corresponding locale found\n");
> +log(" - Set LANGUAGE, LANG and LC_ALL to '%s'\n",

indent again

> + lang.c_str());
> +
>   setenv("LANGUAGE", lang.c_str(), 1);
>   setenv("LANG", lang.c_str(), 1);
> - SETLOCALE(LC_MESSAGES, "");  // set locale according to the 
> env. variables
> -  // --> see  $ man 3 setlocale
> +setenv("LC_ALL", lang.c_str(), 1);
> +
> +try {
> +SETLOCALE(LC_MESSAGES, "en_US.utf8");  // set locale according 
> to the env. variables
> + // --> see  $ man 3 setlocale
> +log(" - Set system locale to 'en_US.utf8' to make '%s' 
> accessible to libintl\n", lang.c_str());
> +} catch (std::exception&) {
> +SETLOCALE(LC_MESSAGES, "");  // set locale according to the env. 
> variables
> + // --> see  $ man 3 setlocale
> +}
>   // assume that it worked

indent again (in all 10 lines above)

>   // maybe, do another check with the return value (?)
>   locale = lang;


-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1798297-locale-C/+merge/358364
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-1798297-locale-C into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2018-11-17 Thread Arty
Oops, forgot to enable codecheck again. Will be fixed in the next round.
-- 
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358718
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-file-saving into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2018-11-16 Thread Arty
Switched to a type safe error type.
-- 
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358718
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-file-saving into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/handling-various-fs-errors into lp:widelands

2018-11-15 Thread Arty
Fixed those things.

Sure, I can do code reviews. I have looked at other active reviews before but 
mostly ignored them because they were either trivial one-line fixes or part of 
the code I wasn't familiar with at all yet.
Anything in particular I should look out for in code reviews?

Diff comments:

> 
> === modified file 'src/wui/load_or_save_game.cc'
> --- src/wui/load_or_save_game.cc  2018-10-26 07:09:29 +
> +++ src/wui/load_or_save_game.cc  2018-11-14 12:37:16 +
> @@ -269,12 +276,69 @@
>   table_.focus();
>   }
>   if (do_delete) {
> + // Failed deletions aren't a serious problem, we just catch the 
> errors
> + // and keep track to notify the player.
> + std::set failed_selections;
> + bool failed;
>   for (const uint32_t index : selections) {
> + failed = false;
>   const std::string& deleteme = get_filename(index);
> - g_fs->fs_unlink(deleteme);
> - if (filetype_ == FileType::kReplay) {
> - g_fs->fs_unlink(deleteme + kSavegameExtension);
> - }
> + try {
> + g_fs->fs_unlink(deleteme);
> + } catch (const FileError& e) {
> + log("player-requested file deletion failed: 
> %s", e.what());
> + failed = true;
> + }
> + if (filetype_ == FileType::kReplay) {
> + try {
> + g_fs->fs_unlink(deleteme + 
> kSavegameExtension);
> + // If at least one of the two relevant 
> files of a replay are
> + // successfully deleted then count it 
> as success.
> + // (From the player perspective the 
> replay is gone.)

Technically, in this branch a remaining savegame (when the deletion of the 
replay file succeeded) would not be cleaned up (but this issue was there 
before).
This is already fixed in the "robust file saving" branch though. When I added 
the new cleanup routine there, I also fixed the other cleanup routines with it 
(mainly catching file errors but also fixing this particular issue).

> + failed = false;
> + // If it was a multiplayer replay, also 
> delete the synchstream. Do
> + // it here, so it's only attempted if 
> replay deletion was successful.
> + if (g_fs->file_exists(deleteme + 
> kSyncstreamExtension)) {
> + g_fs->fs_unlink(deleteme + 
> kSyncstreamExtension);
> + }
> + } catch (const FileError& e) {
> + log("player-requested file deletion 
> failed: %s", e.what());
> + }
> + }
> + if (failed) {
> + failed_selections.insert(index);
> + }
> + }
> + if (!failed_selections.empty()) {
> + // Notify the player.
> + std::string caption = ngettext("Error Deleting File!",

I actually thought about this, but saw that in a Russian po-file all the 
plurals are defined for strings without placeholder anyway. Should also have 
checked whether it's actually displayed properly.
There was another older wrong use of this in this cc-file, I fixed this one, 
too. (Or shouldn't I have? I figured there'd be new translations to do anyway.)

> +"Error Deleting Files!", failed_selections.size());
> + if (filetype_ == FileType::kReplay) {
> + if (selections.size() == 1) {
> + header = _("The replay could not be 
> deleted.");
> + } else {
> + header =
> +(boost::format(ngettext("%s replay 
> could not be deleted.",
> +"%s replays could not be deleted.", 
> failed_selections.size()))
> +% failed_selections.size()).str();
> + }
> + } else {
> + if (selections.size() == 1) {
> + header = _("The game could not be 
> deleted.");
> + } else {
> + header =
> +(boost::format(ngettext("%s game 
> could not be deleted.",
> +"%s games could not be deleted.", 
> failed_selections.size(

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2018-11-15 Thread Arty
I admit the bitmask stuff is still my default way from before C++11, without 
having to re-define operators or typecast all the time. But you are right, I 
should do this properly with enum class now. I'll do that.


As for the code duplication between the game saving and map saving, I feel that 
this doesn't really belong into the GenericSaveHandler. I wanted to keep it on 
a separate abstraction level, in particular without relying on any UI stuff or 
other user interaction. (I am not even sure I should have put the generation of 
localized messages in there.)

The duplication part you pointed out isn't even that big (and half of it just 
comments), but there is overall a lot of code duplication between the map 
saving UI and the game saving UI. I think we should rather try to merge those 
into a single class. There are of course a few key differences between handling 
games and maps there, but those could possibly be dealt with via overloading or 
templates or even just via some parameters (including using lambda functions). 
Same goes for the loading UI and possibly a few others. I wouldn't mind looking 
into that, but that would be a somewhat bigger change (and require some more 
consideration how feasible this even is), so that would rather be something for 
the build21.
-- 
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358718
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-file-saving into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/handling-various-fs-errors into lp:widelands

2018-11-14 Thread Arty
Arty has proposed merging 
lp:~widelands-dev/widelands/handling-various-fs-errors into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1798816 in widelands: "Replay menu does not respect Show filenames after 
deleting a replay"
  https://bugs.launchpad.net/widelands/+bug/1798816

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/handling-various-fs-errors/+merge/358767
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/handling-various-fs-errors into lp:widelands.
=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2018-11-12 06:52:50 +
+++ src/editor/ui_menus/main_menu_save_map.cc	2018-11-14 12:37:16 +
@@ -156,14 +156,35 @@
 	/** TRANSLATORS: A folder that hasn't been given a name yet */
 	MainMenuSaveMapMakeDirectory md(this, _("unnamed"));
 	if (md.run() == UI::Panel::Returncodes::kOk) {
-		g_fs->ensure_directory_exists(curdir_);
-		//  Create directory.
 		std::string fullname = curdir_ + g_fs->file_separator() + md.get_dirname();
 		// Trim it for preceding/trailing whitespaces in user input
 		boost::trim(fullname);
-		g_fs->make_directory(fullname);
-		fill_table();
+		if (g_fs->file_exists(fullname)) {
+			const std::string s = "A file or directory with that name already exists.";
+			UI::WLMessageBox mbox(this, _("Error Creating Directory!"), s,
+			  UI::WLMessageBox::MBoxType::kOk);
+			mbox.run();
+		} else {
+			try {
+g_fs->ensure_directory_exists(curdir_);
+//  Create directory.
+g_fs->make_directory(fullname);
+			} catch (const FileError& e) {
+log("directory creation failed in MainMenuSaveMap::"
+"clicked_make_directory: %s\n", e.what());
+const std::string s =
+   (boost::format(_("Creating directory ‘%s’ failed."))
+   % fullname).str();
+UI::WLMessageBox mbox(this, _("Error Creating Directory!"), s,
+  UI::WLMessageBox::MBoxType::kOk);
+mbox.run();
+			}
+			fill_table();
+		}
 	}
+	table_.focus();
+	// TODO(Arty): In case of successful dir creation we should select the
+	// new dir in the table.
 }
 
 void MainMenuSaveMap::clicked_edit_options() {

=== modified file 'src/editor/ui_menus/main_menu_save_map_make_directory.cc'
--- src/editor/ui_menus/main_menu_save_map_make_directory.cc	2018-07-08 13:53:45 +
+++ src/editor/ui_menus/main_menu_save_map_make_directory.cc	2018-11-14 12:37:16 +
@@ -19,9 +19,12 @@
 
 #include "editor/ui_menus/main_menu_save_map_make_directory.h"
 
+#include 
+
 #include "base/i18n.h"
 #include "graphic/font_handler.h"
 #include "io/filesystem/layered_filesystem.h"
+#include "logic/filesystem_constants.h"
 
 MainMenuSaveMapMakeDirectory::MainMenuSaveMapMakeDirectory(UI::Panel* const parent,
char const* dirname)
@@ -63,10 +66,12 @@
 	vbox_.set_size(get_inner_w() - 2 * padding_, get_inner_h() - 3 * padding_ - buth_);
 
 	edit_.set_text(dirname_);
-	edit_.changed.connect(boost::bind(&MainMenuSaveMapMakeDirectory::edit_changed, this));
+	edit_.changed.connect(
+	   boost::bind(&MainMenuSaveMapMakeDirectory::edit_changed, this));
+	edit_.ok.connect(
+	   boost::bind(&MainMenuSaveMapMakeDirectory::clicked_ok, this));
 	ok_button_.sigclicked.connect(
-	   boost::bind(&MainMenuSaveMapMakeDirectory::end_modal,
-	   boost::ref(*this), UI::Panel::Returncodes::kOk));
+	   boost::bind(&MainMenuSaveMapMakeDirectory::clicked_ok, this));
 	ok_button_.set_enabled(!dirname_.empty());
 	cancel_button_.sigclicked.connect(
 	   boost::bind(&MainMenuSaveMapMakeDirectory::end_modal,
@@ -82,7 +87,24 @@
 	const std::string& text = edit_.text();
 	// Prevent the user from creating nonsense directory names, like e.g. ".." or "...".
 	const bool is_legal_filename = FileSystem::is_legal_filename(text);
-	ok_button_.set_enabled(is_legal_filename);
-	edit_.set_tooltip(is_legal_filename ? "" : illegal_filename_tooltip_);
+	// Prevent the user from creating directory names that the game would
+	// try to interpret as maps
+	const bool has_map_extension =
+		 boost::iends_with(text, kWidelandsMapExtension) ||
+		 boost::iends_with(text, kS2MapExtension1) ||
+		 boost::iends_with(text, kS2MapExtension2);
+	ok_button_.set_enabled(is_legal_filename && !has_map_extension);
+	edit_.set_tooltip(is_legal_filename ?
+	   (has_map_extension ? _("This extension is reserved!") : "" ) :
+	   illegal_filename_tooltip_);
 	dirname_ = text;
 }
+
+/**
+ * Clicked OK button oder pressed Enter in edit box
+ */
+void MainMenuSaveMapMakeDirectory::clicked_ok() {
+	if (!o

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/handling-various-fs-errors into lp:widelands

2018-11-14 Thread Arty
Some of the "handling" is just catching and logging.

In GameClient::handle_packet, when renaming a file to a backup fails, we could 
possibly handle this by finding another filename to save to, but I think this 
would have to be agreed upon by the participating clients. I didn't attempt 
this, because I am not yet familiar with the network code.
-- 
https://code.launchpad.net/~widelands-dev/widelands/handling-various-fs-errors/+merge/358767
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/handling-various-fs-errors into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2018-11-13 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/robust-file-saving into 
lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358718
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-file-saving into lp:widelands.
=== modified file 'src/editor/CMakeLists.txt'
--- src/editor/CMakeLists.txt	2018-07-19 16:43:14 +
+++ src/editor/CMakeLists.txt	2018-11-13 16:47:56 +
@@ -99,6 +99,7 @@
 logic
 logic_constants
 logic_filesystem_constants
+logic_generic_save_handler
 logic_tribe_basic_info
 logic_widelands_geometry
 map_io

=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2018-11-11 20:42:54 +
+++ src/editor/ui_menus/main_menu_save_map.cc	2018-11-13 16:47:56 +
@@ -37,6 +37,7 @@
 #include "io/filesystem/layered_filesystem.h"
 #include "io/filesystem/zip_filesystem.h"
 #include "logic/filesystem_constants.h"
+#include "logic/generic_save_handler.h"
 #include "map_io/map_saver.h"
 #include "map_io/widelands_map_loader.h"
 #include "ui_basic/messagebox.h"
@@ -119,7 +120,9 @@
  * Called when the ok button was pressed or a file in list was double clicked.
  */
 void MainMenuSaveMap::clicked_ok() {
-	assert(ok_.enabled());
+	if (!ok_.enabled()) {
+		return;
+	}
 	std::string filename = editbox_->text();
 	std::string complete_filename;
 
@@ -243,15 +246,12 @@
 
 /**
  * Save the map in the current directory with
- * the current filename
+ * the given filename
  *
  * returns true if dialog should close, false if it
  * should stay open
  */
 bool MainMenuSaveMap::save_map(std::string filename, bool binary) {
-	//  Make sure that the current directory exists and is writeable.
-	g_fs->ensure_directory_exists(curdir_);
-
 	// Trim it for preceding/trailing whitespaces in user input
 	boost::trim(filename);
 
@@ -272,6 +272,7 @@
 		if (mbox.run() == UI::Panel::Returncodes::kBack)
 			return false;
 	}
+<<<<<<< TREE
 
 	//  Try deleting file (if it exists). If it fails, give a message and let the player choose a new
 	//  name.
@@ -288,6 +289,8 @@
 		mbox.run();
 		return false;
 	}
+===
+>>>>>>> MERGE-SOURCE
 
 	Widelands::EditorGameBase& egbase = eia().egbase();
 	Widelands::Map* map = egbase.mutable_map();
@@ -305,6 +308,7 @@
 	} else {
 		map->delete_tag("artifacts");
 	}
+<<<<<<< TREE
 
 	//  Try saving.
 	try {
@@ -322,5 +326,38 @@
 	}
 
 	die();
+===
+
+	// Try saving the map.
+	GenericSaveHandler gsh(
+		[&egbase](FileSystem& fs) {
+			Widelands::MapSaver wms(fs, egbase);
+			wms.save();
+		},
+		complete_filename,
+		binary ? FileSystem::ZIP : FileSystem::DIR
+	);
+	uint32_t error = gsh.save();
+	if (error == GenericSaveHandler::kSuccess ||
+	error == GenericSaveHandler::kDeletingBackupFailed) {
+			// No need to bother the player if only the temporary backup couldn't
+			// be deleted. Automatic cleanup will try to deal with it later.
+		egbase.get_ibase()->log_message(_("Map saved"));
+		return true;
+	}
+
+	std::string msg = gsh.localized_formatted_result_message();
+	UI::WLMessageBox mbox(
+	   this, _("Error Saving Map!"), msg, UI::WLMessageBox::MBoxType::kOk);
+	mbox.run();
+
+	// If only the backup failed (likely just because of a file lock),
+	// then leave the dialog open for the player to try with a new filename.
+	if (error == GenericSaveHandler::kBackupFailed) {
+	  return false;
+	}
+
+	// In the other error cases close the dialog.
+>>>>>>> MERGE-SOURCE
 	return true;
 }

=== modified file 'src/io/filesystem/disk_filesystem.cc'
--- src/io/filesystem/disk_filesystem.cc	2018-04-07 16:59:00 +
+++ src/io/filesystem/disk_filesystem.cc	2018-11-13 16:47:56 +
@@ -167,15 +167,13 @@
 }
 
 /**
- * Create a sub filesystem out of this filesystem
+ * Make a sub filesystem out of this filesystem
  */
 FileSystem* RealFSImpl::make_sub_file_system(const std::string& path) {
 	FileSystemPath fspath(canonicalize_name(path));
 
 	if (!fspath.exists_) {
-		throw wexception("RealFSImpl: unable to create sub filesystem, path does not exist for '%s'"
-		 " in directory '%s'",
-		 fspath.c_str(), directory_.c_str());
+		throw FileNotFoundError("RealFSImpl::make_sub_file_system", fspath);
 	}
 
 	if (fspath.is_directory_)
@@ -190,10 +188,7 @@
 FileSystem* RealFSImpl::create_sub_file_system(const std::string& path, Type const fs) {
 	FileSystemPath fspath(canonicalize_name(path));
 	if (fspath.exists_)
-		throw wexception(
-		   "path '%s'' already exists in directory &#

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/filesystem-errors into lp:widelands

2018-11-12 Thread Arty
Good to know, thanks. So I guess I shouldn't even make any child branches at 
all before the parent branch is fully revised and scheduled for merging into 
trunk. Or maybe just not push them online or at least not bother anyone else 
with them via merge requests; and then later resolve merge conflicts on my own 
(possibly just copying it over into a new branch) before making everything 
available. I feel that this kinda destroys what I thought to be a big advantage 
of this whole branching concept.
-- 
https://code.launchpad.net/~widelands-dev/widelands/filesystem-errors/+merge/358219
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/filesystem-errors.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/filesystem-errors into lp:widelands

2018-11-12 Thread Arty
Oh okay, then I'll leave it.

I am still somewhat fuzzy about some specifics with bazaar, specifically merge 
conflicts.
Let's say for examply I'd fix all those little things in disk_filesystem.cc, 
then merge the result into my two child branches (which itself should be fine 
because those don't make any changes to the file themselve). Then - if I got 
this right - the only conflicts would arise if someone else is doing other 
changes to a version of the branches from before the merge (which of course is 
easily possible during the review) or if someone is changing the file in some 
other branch. Right?


-- 
https://code.launchpad.net/~widelands-dev/widelands/filesystem-errors/+merge/358219
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/filesystem-errors.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/filesystem-errors into lp:widelands

2018-11-12 Thread Arty
regarding code review:

There're plenty more long lines and if-blocks without curly braces in there. 
I'll fix this tonight.

Do we generally follow a strict rule of curly braces even for short single line 
blocks?
-- 
https://code.launchpad.net/~widelands-dev/widelands/filesystem-errors/+merge/358219
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/filesystem-errors.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/RTL-alignment-fix into lp:widelands

2018-11-11 Thread Arty
I am not actually sure there is a place where this currently makes any 
difference visually.

Most text areas are used in automove mode and automatically change their 
position and size based on the text, so text alignment doesn't matter unless 
they are resized from the outside. In the cases where such resizing is done 
(e.g. window titles) the alignment is kCenter. So visially nothing has changed 
yet.

I made the fix mainly so that RTL would be displayed correctly when we use 
single-line textareas in non-center mode and with properly set layout. And we 
already do the same adjustment for multi-line textareas.

Where it theoretically could make a difference is the campaign select menu. 
That one uses some single-line textareas, but we don't have a layout defined 
there that would resize the text areas, so they stay collapsed to the text 
width and don't react to my fix yet. (And we might even put everything there in 
a multi-line textarea when we do a proper box layout.)

If you want to just quickly test it, set one of the menu title alignments to 
Left or Right. Without the fix, language doesn't make a diffence, with the fix 
alignment is swapped properly for Arabic.


Side note: Even the menus where we have defined a proper layout with multi-line 
textareas, some of them are not resized properly (like game/map name in the 
description area), so RTL is ignored.

I guess all this RTL stuff has very low priority anyway. Aside from a small 
amount of Arabic, we don't even seem to have translations.
-- 
https://code.launchpad.net/~widelands-dev/widelands/RTL-alignment-fix/+merge/358596
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/RTL-alignment-fix into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/fix-language-entry-ms into lp:widelands

2018-11-10 Thread Arty
Disclosure: I actually don't speak the language nor do I know anyone who does.

I only stumbled upon this by accident when I checked RTL stuff and found weird 
behaviour: The language entry in the options menu was arabic looking and RTL, 
but all the translations were in Latin script and - even though aligned right 
(probably because if the font setting) - seemed to be meant for reading 
left-to-right.

Acording to Google+Wikipedia there still is an arabic script for the language 
but also Latin one, which is much more widespread and also the official script. 
And it's not RTL. Given that (as far as I could see) all our existing ms 
translations use the Latin script, I thought we should change the entry in the 
lua file, so the options menu shows the Latin name and the alignment is not 
automatically switched.
-- 
https://code.launchpad.net/~widelands-dev/widelands/fix-language-entry-ms/+merge/358597
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/fix-language-entry-ms into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/fix-language-entry-ms into lp:widelands

2018-11-10 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/fix-language-entry-ms 
into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/fix-language-entry-ms/+merge/358597
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/fix-language-entry-ms into lp:widelands.
=== modified file 'data/i18n/locales.lua'
--- data/i18n/locales.lua	2018-11-10 09:20:09 +
+++ data/i18n/locales.lua	2018-11-10 18:49:34 +
@@ -249,9 +249,9 @@
},
 
ms = {
-  name = "بهاس ملايو",
+  name = "Bahasa Melayu",
   sort_name = "Melayu",
-  font = "arabic"
+  font = "default"
},
 
my = {

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/RTL-alignment-fix into lp:widelands

2018-11-10 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/RTL-alignment-fix into 
lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/RTL-alignment-fix/+merge/358596
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/RTL-alignment-fix into lp:widelands.
=== modified file 'src/ui_basic/textarea.cc'
--- src/ui_basic/textarea.cc	2018-07-08 13:53:45 +
+++ src/ui_basic/textarea.cc	2018-11-10 18:48:51 +
@@ -125,9 +125,10 @@
  */
 void Textarea::draw(RenderTarget& dst) {
 	if (!text_.empty()) {
+		Align alignment = mirror_alignment(align_, text_);
 		Vector2i anchor(
-		   (align_ == Align::kCenter) ? get_w() / 2 : (align_ == UI::Align::kRight) ? get_w() : 0, 0);
-		rendered_text_->draw(dst, anchor, align_);
+		   (alignment == Align::kCenter) ? get_w() / 2 : (alignment == UI::Align::kRight) ? get_w() : 0, 0);
+		rendered_text_->draw(dst, anchor, alignment);
 	}
 }
 

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bugfix-1801208 into lp:widelands

2018-11-10 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/bugfix-1801208 into 
lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1801208 in widelands: "Message boxes with long unbreakable strings show 
empty "
  https://bugs.launchpad.net/widelands/+bug/1801208

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bugfix-1801208/+merge/358594
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bugfix-1801208 into lp:widelands.
=== modified file 'src/ui_basic/multilinetextarea.cc'
--- src/ui_basic/multilinetextarea.cc	2018-08-12 16:35:30 +
+++ src/ui_basic/multilinetextarea.cc	2018-11-10 17:41:58 +
@@ -30,7 +30,8 @@
 
 namespace UI {
 
-static const uint32_t RICHTEXT_MARGIN = 2;
+// int instead of uint because of overflow situations
+static const int32_t RICHTEXT_MARGIN = 2;
 
 MultilineTextarea::MultilineTextarea(Panel* const parent,
  const int32_t x,
@@ -141,11 +142,19 @@
 	int anchor = 0;
 	Align alignment = mirror_alignment(align_, text_);
 	switch (alignment) {
+	// TODO(Arty): We might want to revisit this after the font renderer can handle long strings
+	// without whitespaces differently.
+	// Currently, such long unbreakable strings are silently assumed to fit the line exactly,
+	// which means that rendered_text_->width() might actually be larger than the effective width
+	// of the textarea. If we'd allow the anchor here to become negative in this case, it would
+	// properly position the longest line (just truncated), BUT the positioning of shorter lines
+	// would be off (possibly even outside the textarea, thus invisible) because their positioning
+	// is calculated without regard for overlong lines.
 	case UI::Align::kCenter:
-		anchor = (get_eff_w() - rendered_text_->width()) / 2;
+		anchor = std::max(0, (get_eff_w() - rendered_text_->width()) / 2);
 		break;
 	case UI::Align::kRight:
-		anchor = get_eff_w() - rendered_text_->width() - RICHTEXT_MARGIN;
+		anchor = std::max(0, get_eff_w() - rendered_text_->width() - RICHTEXT_MARGIN);
 		break;
 	case UI::Align::kLeft:
 		anchor = RICHTEXT_MARGIN;

=== modified file 'src/ui_basic/multilinetextarea.h'
--- src/ui_basic/multilinetextarea.h	2018-07-08 09:18:33 +
+++ src/ui_basic/multilinetextarea.h	2018-11-10 17:41:58 +
@@ -60,7 +60,8 @@
 	}
 
 	void set_text(const std::string&);
-	uint32_t get_eff_w() const {
+	// int instead of uint because of overflow situations
+	int32_t get_eff_w() const {
 		return scrollbar_.is_enabled() ? get_w() - Scrollbar::kSize : get_w();
 	}
 

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into lp:widelands

2018-11-09 Thread Arty
Oh, now I see where your original comments are. Don't know why I didn't notice 
them before. Sorry about that.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1753230-working-with-tempfiles/+merge/357656
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into lp:widelands

2018-11-09 Thread Arty
Oh, I see you had some other nits that you fixed. Fair enough. I should have 
checked more thoroughly. Or did you mention some specifics before somewhere and 
I had missed them?

As for the naming of the temp dir, I also had it named "temp" first but felt 
that might encourage players to just delete it (possibly while the game is up, 
thus messing up their next save). I guess I was overreacting because a friend 
of mine notoriously does this kind of thing, always complaining that stupid 
programmers never clean up their temp stuff. But honestly, "temp" is perfectly 
fine.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1753230-working-with-tempfiles/+merge/357656
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into lp:widelands

2018-11-09 Thread Arty
Huh? I had already fixed them. Did I miss something?
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1753230-working-with-tempfiles/+merge/357656
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-file-saving into lp:widelands

2018-11-07 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/robust-file-saving into 
lp:widelands with 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles as a 
prerequisite.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/robust-file-saving/+merge/358473
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-file-saving into lp:widelands.
=== modified file 'src/editor/CMakeLists.txt'
--- src/editor/CMakeLists.txt	2018-07-19 16:43:14 +
+++ src/editor/CMakeLists.txt	2018-11-08 02:11:06 +
@@ -99,6 +99,7 @@
 logic
 logic_constants
 logic_filesystem_constants
+logic_generic_save_handler
 logic_tribe_basic_info
 logic_widelands_geometry
 map_io

=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2018-11-08 02:11:06 +
+++ src/editor/ui_menus/main_menu_save_map.cc	2018-11-08 02:11:06 +
@@ -29,6 +29,7 @@
 
 #include "base/i18n.h"
 #include "base/macros.h"
+#include "base/time_string.h"
 #include "base/wexception.h"
 #include "editor/editorinteractive.h"
 #include "editor/ui_menus/main_menu_map_options.h"
@@ -37,6 +38,7 @@
 #include "io/filesystem/layered_filesystem.h"
 #include "io/filesystem/zip_filesystem.h"
 #include "logic/filesystem_constants.h"
+#include "logic/generic_save_handler.h"
 #include "map_io/map_saver.h"
 #include "map_io/widelands_map_loader.h"
 #include "ui_basic/messagebox.h"
@@ -119,7 +121,8 @@
  * Called when the ok button was pressed or a file in list was double clicked.
  */
 void MainMenuSaveMap::clicked_ok() {
-	assert(ok_.enabled());
+	if (!ok_.enabled())
+		return;
 	std::string filename = editbox_->text();
 	std::string complete_filename;
 
@@ -243,15 +246,12 @@
 
 /**
  * Save the map in the current directory with
- * the current filename
+ * the given filename
  *
  * returns true if dialog should close, false if it
  * should stay open
  */
 bool MainMenuSaveMap::save_map(std::string filename, bool binary) {
-	//  Make sure that the current directory exists and is writeable.
-	g_fs->ensure_directory_exists(curdir_);
-
 	// Trim it for preceding/trailing whitespaces in user input
 	boost::trim(filename);
 
@@ -272,18 +272,6 @@
 		if (mbox.run() == UI::Panel::Returncodes::kBack)
 			return false;
 	}
-	
-	//  Try deleting file (if it exists). If it fails, give a message and let the player choose a new name.
-	try {
-		g_fs->fs_unlink(complete_filename);
-	} catch (const std::exception& e) {
-		const std::string s =
-		   (boost::format(_("File ‘%s.tmp’ could not be deleted.")) % FileSystem::fs_filename(filename.c_str())).str()
-		   + " " + _("Try saving under a different name!");
-		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
-		mbox.run();
-		return false;
-	}
 
 	Widelands::EditorGameBase& egbase = eia().egbase();
 	Widelands::Map* map = egbase.mutable_map();
@@ -301,23 +289,34 @@
 	} else {
 		map->delete_tag("artifacts");
 	}
-	
-	//  Try saving.
-	try {
-		std::unique_ptr fs(
-		   g_fs->create_sub_file_system(complete_filename, binary ? FileSystem::ZIP : FileSystem::DIR));
-		Widelands::MapSaver* wms = new Widelands::MapSaver(*fs, egbase);
-		wms->save();
-		delete wms;
-		fs.reset();
-	} catch (const std::exception& e) {
-		std::string s = _("Error Saving Map!\nSaved map file may be corrupt!\n\nReason "
-		  "given:\n");
-		s += e.what();
-		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
-		mbox.run();
+
+	// Try saving the map.
+	GenericSaveHandler gsh(
+		[&egbase](FileSystem& fs) {
+			Widelands::MapSaver wms(fs, egbase);
+			wms.save();
+		},
+		complete_filename,
+		binary ? FileSystem::ZIP : FileSystem::DIR
+	);
+	uint32_t error = gsh.save();
+	if (error == GenericSaveHandler::kSuccess ||
+	error == GenericSaveHandler::kDeletingBackupFailed) {
+			// No need to bother the player if only the temporary backup couldn't be deleted.
+			// Automatic cleanup will try to deal with it later.
+		egbase.get_ibase()->log_message(_("Map saved"));
+		return true;
 	}
 
-	die();
+	std::string msg = gsh.localized_formatted_result_message();
+	UI::WLMessageBox mbox(this, _("Error Saving Map!"), msg, UI::WLMessageBox::MBoxType::kOk);
+	mbox.run();
+
+	// If only the backup failed (likely just because of a file lock),
+	// then leave the dialog open for the player to try with a new filename.
+	if (error == GenericSaveHandler::kBackupFailed)
+	  return false;
+
+	// In the other error cases close the dialog.
 	return true;
 }

==

Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1800182-focus-save-menu into lp:widelands

2018-11-06 Thread Arty
Bug report is up.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1800182-focus-save-menu/+merge/358284
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-1800182-focus-save-menu.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1800182-focus-save-menu into lp:widelands

2018-11-05 Thread Arty
Or rather than letting the save menu (and possibly some others) deal with 
"let's not accidentally refer key handling to the game window" issues, maybe 
the game window needs a "state" variable to distinguish between "game is 
running normally", "game is paused in background behind some other window" (and 
possibly other states), and then any key handling is suspended in certain 
states.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1800182-focus-save-menu/+merge/358284
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-1800182-focus-save-menu.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1800182-focus-save-menu into lp:widelands

2018-11-05 Thread Arty
That keypresses affect the game window from the save menu is a more general 
issue that should be resolved. Sure, the name edit box grabs the keys when it 
has the focus, but as soon as the filename table is focued (which happends 
naturally when someone selects a name there), key handling (aside from a few 
keys like Up/Down) seems to be referred to the game window in the background.

We should generally prevent that. (Not necessarily in this branch.) Maybe it's 
enough to have the LoadOrSave table simply grab the keys instead of referring 
the key handling to something else. Hard to say right now, I haven't even 
checked which route the key handling takes to end up at the game window.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1800182-focus-save-menu/+merge/358284
Your team Widelands Developers is subscribed to branch 
lp:~widelands-dev/widelands/bug-1800182-focus-save-menu.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into lp:widelands

2018-11-05 Thread Arty
No, I didn't. :-)

The string is already in the last trunk. I just noticed it and removed it 
together with the other small fix I commited. (It just didn't feel important 
enough to mention it in the log.)
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1753230-working-with-tempfiles/+merge/357656
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into 
lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-saving into lp:widelands

2018-11-02 Thread Arty
Oops, I just realized that I my commit log isn't quite correct.

GameMainMenuSaveGame actually uses GenericSaveHandler directly, not via 
SaveHandler. I did it this way, so the formatted message (to show the player if 
something went wrong) could be accessed without having to change SaveHandler to 
allow routing it through there. Basically SaveHandler is now only used for 
autosaves (timed and requested via lua scripts) and to store the current 
filename for use in the Save Menu.
-- 
https://code.launchpad.net/~widelands-dev/widelands/robust-saving/+merge/358220
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-saving into lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into lp:widelands

2018-11-02 Thread Arty
Btw, this autosave-thing you observed was a (I think even relatively recently 
introduced and somewhat dirty) error handling attempt by someone. When the 
wl_autosave_00.wgf couldn't be renamed (for backup purposes) then there was 
some "let's just try other filenames" approach, and the game would just find 
the next autosave filename (up to 09) where there didn't exist any file. At 09 
it would just stop and not check any further, but use this as the target name, 
so from this point on wl_autosave_09.wgf would just have been overwritten with 
every autosave. (Which worked in your case, because this one wasn't 
file-locked.)

My latest branch is stricter in this regard. If some relevant renaming or 
deletion fails, then the autosaving is simply aborted, and there is a little 
message. I don't think the game needs to handle this in some special way. The 
player gets a message and can try to fix a problem (if there's a file lock for 
example) or has to save manually.
-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1753230-working-with-tempfiles/+merge/357656
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into 
lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


Re: [Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into lp:widelands

2018-11-02 Thread Arty
1. Regarding the autosave stuff:

This wasn't anything this branch tried to solve. It only solved the the 
conflicts that arose from trying to modify files where the map fs pointed to, 
resulting in either some crash or error (if the file was currently locked) or 
resulting in corrupt savefiles.

Those other file conflicts (like trying to modify a savefile that is locked 
because you have it open with 7zip, or having a file write-protected or some 
such) are solved with the latest branch: 
https://code.launchpad.net/~widelands-dev/widelands/robust-saving

As for trying to specifically test "is_writable" instead of "file_exists" (or 
other potentially problematic file states) beforehand, I don't think it's worth 
it. For one thing, we might have to deal with the specifics of the various 
access control models on the different platforms. (Just looking at this stuff 
makes me nauseaous.) There is also the more general problem with any filesystem 
stuff that you can never be sure that the file state you just checked is still 
the same when you try your file operation next. Sure, it's very likely, but 
there can always be race conditions, and some other process might just have 
snatched the file away between your state check and your attempt to operate on 
a file.
So aside from a few minor exist checks I favour a simple, practical approach: 
just try the file operation, but catch and handle any errors. The error codes 
give a hint about what the actual problem was, but usually that doesn't matter 
much anyway: either it worked and we continue or it didn't and we abort.
Anyway, the latest branch 
https://code.launchpad.net/~widelands-dev/widelands/robust-saving does exactly 
that and handles file errors in all the map/game saving routines and cleanup 
routines. I still need to check in what other places we don't catch file errors 
but should. (Definitely when deleting files in the load/save menu, maybe 
synchstream creation, probably some other places.) That's going to be part of 
future branches though.


2. Those travis build errors

I hadn't actually seen this before. (I'm still a noob on Launchpad and don't 
know my way around very well, but I am trying to catch up. If there are any 
important features I might not but should know about, feel free to point 
something out.)

Anyway, those errors seem like minor nitpicks. I'll fix them.
Btw, are those builds made automatically here for any new branches? Or do I 
have to initiate them manually? (I haven't checked out the online building 
possibilities yet. Still on my todo list.)

-- 
https://code.launchpad.net/~widelands-dev/widelands/bug-1753230-working-with-tempfiles/+merge/357656
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into 
lp:widelands.

___
Mailing list: https://launchpad.net/~widelands-dev
Post to : widelands-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~widelands-dev
More help   : https://help.launchpad.net/ListHelp


[Widelands-dev] [Merge] lp:~widelands-dev/widelands/robust-saving into lp:widelands

2018-11-02 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/robust-saving into 
lp:widelands with 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles as a 
prerequisite.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/robust-saving/+merge/358220
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/robust-saving into lp:widelands.
=== modified file 'src/editor/CMakeLists.txt'
--- src/editor/CMakeLists.txt	2018-07-19 16:43:14 +
+++ src/editor/CMakeLists.txt	2018-11-02 11:15:15 +
@@ -99,6 +99,7 @@
 logic
 logic_constants
 logic_filesystem_constants
+logic_generic_save_handler
 logic_tribe_basic_info
 logic_widelands_geometry
 map_io

=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2018-11-02 11:15:14 +
+++ src/editor/ui_menus/main_menu_save_map.cc	2018-11-02 11:15:15 +
@@ -29,6 +29,7 @@
 
 #include "base/i18n.h"
 #include "base/macros.h"
+#include "base/time_string.h"
 #include "base/wexception.h"
 #include "editor/editorinteractive.h"
 #include "editor/ui_menus/main_menu_map_options.h"
@@ -37,12 +38,13 @@
 #include "io/filesystem/layered_filesystem.h"
 #include "io/filesystem/zip_filesystem.h"
 #include "logic/filesystem_constants.h"
+#include "logic/generic_save_handler.h"
 #include "map_io/map_saver.h"
 #include "map_io/widelands_map_loader.h"
 #include "ui_basic/messagebox.h"
 #include "wui/mapdetails.h"
 #include "wui/maptable.h"
-
+#include 
 inline EditorInteractive& MainMenuSaveMap::eia() {
 	return dynamic_cast(*get_parent());
 }
@@ -119,7 +121,8 @@
  * Called when the ok button was pressed or a file in list was double clicked.
  */
 void MainMenuSaveMap::clicked_ok() {
-	assert(ok_.enabled());
+	if (!ok_.enabled())
+		return;
 	std::string filename = editbox_->text();
 	std::string complete_filename;
 
@@ -243,15 +246,12 @@
 
 /**
  * Save the map in the current directory with
- * the current filename
+ * the given filename
  *
  * returns true if dialog should close, false if it
  * should stay open
  */
 bool MainMenuSaveMap::save_map(std::string filename, bool binary) {
-	//  Make sure that the current directory exists and is writeable.
-	g_fs->ensure_directory_exists(curdir_);
-
 	// Trim it for preceding/trailing whitespaces in user input
 	boost::trim(filename);
 
@@ -272,18 +272,6 @@
 		if (mbox.run() == UI::Panel::Returncodes::kBack)
 			return false;
 	}
-	
-	//  Try deleting file (if it exists). If it fails, give a message and let the player choose a new name.
-	try {
-		g_fs->fs_unlink(complete_filename);
-	} catch (const std::exception& e) {
-		const std::string s =
-		   (boost::format(_("File ‘%s.tmp’ could not be deleted.")) % FileSystem::fs_filename(filename.c_str())).str()
-		   + " " + _("Try saving under a different name!");
-		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
-		mbox.run();
-		return false;
-	}
 
 	Widelands::EditorGameBase& egbase = eia().egbase();
 	Widelands::Map* map = egbase.mutable_map();
@@ -301,23 +289,34 @@
 	} else {
 		map->delete_tag("artifacts");
 	}
-	
-	//  Try saving.
-	try {
-		std::unique_ptr fs(
-		   g_fs->create_sub_file_system(complete_filename, binary ? FileSystem::ZIP : FileSystem::DIR));
-		Widelands::MapSaver* wms = new Widelands::MapSaver(*fs, egbase);
-		wms->save();
-		delete wms;
-		fs.reset();
-	} catch (const std::exception& e) {
-		std::string s = _("Error Saving Map!\nSaved map file may be corrupt!\n\nReason "
-		  "given:\n");
-		s += e.what();
-		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
-		mbox.run();
+
+	// Try saving the map.
+	GenericSaveHandler gsh(
+		[&egbase](FileSystem& fs) {
+			Widelands::MapSaver wms(fs, egbase);
+			wms.save();
+		},
+		complete_filename,
+		binary ? FileSystem::ZIP : FileSystem::DIR
+	);
+	uint32_t error = gsh.save();
+	if (error == GenericSaveHandler::kSuccess ||
+	error == GenericSaveHandler::kDeletingBackupFailed) {
+			// No need to bother the player if only the temporary backup couldn't be deleted.
+			// Automatic cleanup will try to deal with it later.
+		egbase.get_ibase()->log_message(_("Map saved"));
+		return true;
 	}
 
-	die();
+	std::string msg = gsh.localized_formatted_result_message();
+	UI::WLMessageBox mbox(this, _("Error Saving Map!"), msg, UI::WLMessageBox::MBoxType::kOk);
+	mbox.run();
+
+	// If only the backup failed (likely just because of a file lock),
+	// then leave the dialog op

[Widelands-dev] [Merge] lp:~widelands-dev/widelands/filesystem-errors into lp:widelands

2018-11-02 Thread Arty
Arty has proposed merging lp:~widelands-dev/widelands/filesystem-errors into 
lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/filesystem-errors/+merge/358219
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/filesystem-errors into lp:widelands.
=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2018-09-25 06:32:35 +
+++ src/editor/editorinteractive.cc	2018-11-02 11:11:32 +
@@ -187,6 +187,7 @@
 	}
 
 	ml->load_map_complete(egbase(), Widelands::MapLoader::LoadType::kEditor);
+	egbase().postload();
 	egbase().load_graphics(loader_ui);
 	map_changed(MapWas::kReplaced);
 }

=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2018-06-01 08:50:29 +
+++ src/editor/ui_menus/main_menu_save_map.cc	2018-11-02 11:11:32 +
@@ -272,16 +272,14 @@
 		if (mbox.run() == UI::Panel::Returncodes::kBack)
 			return false;
 	}
-
-	// save to a tmp file/dir first, rename later
-	// (important to keep script files in the script directory)
-	const std::string tmp_name = complete_filename + ".tmp";
-	if (g_fs->file_exists(tmp_name)) {
+	
+	//  Try deleting file (if it exists). If it fails, give a message and let the player choose a new name.
+	try {
+		g_fs->fs_unlink(complete_filename);
+	} catch (const std::exception& e) {
 		const std::string s =
-		   (boost::format(
-		   _("A file with the name ‘%s.tmp’ already exists. You have to remove it manually.")) %
-		FileSystem::fs_filename(filename.c_str()))
-		  .str();
+		   (boost::format(_("File ‘%s.tmp’ could not be deleted.")) % FileSystem::fs_filename(filename.c_str())).str()
+		   + " " + _("Try saving under a different name!");
 		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
 		mbox.run();
 		return false;
@@ -290,51 +288,35 @@
 	Widelands::EditorGameBase& egbase = eia().egbase();
 	Widelands::Map* map = egbase.mutable_map();
 
-	{  // fs scope
+	// Recompute seafaring tag
+	map->cleanup_port_spaces(egbase.world());
+	if (map->allows_seafaring()) {
+		map->add_tag("seafaring");
+	} else {
+		map->delete_tag("seafaring");
+	}
+
+	if (map->has_artifacts()) {
+		map->add_tag("artifacts");
+	} else {
+		map->delete_tag("artifacts");
+	}
+	
+	//  Try saving.
+	try {
 		std::unique_ptr fs(
-		   g_fs->create_sub_file_system(tmp_name, binary ? FileSystem::ZIP : FileSystem::DIR));
-
-		// Recompute seafaring tag
-		map->cleanup_port_spaces(egbase.world());
-		if (map->allows_seafaring()) {
-			map->add_tag("seafaring");
-		} else {
-			map->delete_tag("seafaring");
-		}
-
-		if (map->has_artifacts()) {
-			map->add_tag("artifacts");
-		} else {
-			map->delete_tag("artifacts");
-		}
-
-		try {
-			Widelands::MapSaver* wms = new Widelands::MapSaver(*fs, egbase);
-			wms->save();
-			delete wms;
-			// Reset filesystem to avoid file locks on saves
-			fs.reset();
-			map->reset_filesystem();
-			eia().set_need_save(false);
-			g_fs->fs_unlink(complete_filename);
-			g_fs->fs_rename(tmp_name, complete_filename);
-			// Also change fs, as we assign it to the map below
-			fs.reset(g_fs->make_sub_file_system(complete_filename));
-			// Set the filesystem of the map to the current save file / directory
-			map->swap_filesystem(fs);
-			// DONT use fs as of here, its garbage now!
-
-		} catch (const std::exception& e) {
-			std::string s = _("Error Saving Map!\nSaved map file may be corrupt!\n\nReason "
-			  "given:\n");
-			s += e.what();
-			UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
-			mbox.run();
-
-			// cleanup tmp file if it was created
-			g_fs->fs_unlink(tmp_name);
-		}
-	}  // end fs scope, dont use it
+		   g_fs->create_sub_file_system(complete_filename, binary ? FileSystem::ZIP : FileSystem::DIR));
+		Widelands::MapSaver* wms = new Widelands::MapSaver(*fs, egbase);
+		wms->save();
+		delete wms;
+		fs.reset();
+	} catch (const std::exception& e) {
+		std::string s = _("Error Saving Map!\nSaved map file may be corrupt!\n\nReason "
+		  "given:\n");
+		s += e.what();
+		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
+		mbox.run();
+	}
 
 	die();
 	return true;

=== modified file 'src/io/filesystem/disk_filesystem.cc'
--- src/io/filesystem/disk_filesystem.cc	2018-04-07 16:59:00 +
+++ src/io/filesystem/disk_filesystem.cc	2018-11-02 11:11:32 +
@@ -167,15 +167,13 @@
 }
 
 /**
- * Creat

[Widelands-dev] [Merge] lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into lp:widelands

2018-10-22 Thread Arty
Arty has proposed merging 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into 
lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1753230 in widelands: "Scenarios: Some files get removed on autosave"
  https://bugs.launchpad.net/widelands/+bug/1753230

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1753230-working-with-tempfiles/+merge/357656
-- 
Your team Widelands Developers is requested to review the proposed merge of 
lp:~widelands-dev/widelands/bug-1753230-working-with-tempfiles into 
lp:widelands.
=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2018-09-25 06:32:35 +
+++ src/editor/editorinteractive.cc	2018-10-22 18:50:51 +
@@ -187,6 +187,7 @@
 	}
 
 	ml->load_map_complete(egbase(), Widelands::MapLoader::LoadType::kEditor);
+	egbase().postload();
 	egbase().load_graphics(loader_ui);
 	map_changed(MapWas::kReplaced);
 }

=== modified file 'src/editor/ui_menus/main_menu_save_map.cc'
--- src/editor/ui_menus/main_menu_save_map.cc	2018-06-01 08:50:29 +
+++ src/editor/ui_menus/main_menu_save_map.cc	2018-10-22 18:50:51 +
@@ -272,16 +272,14 @@
 		if (mbox.run() == UI::Panel::Returncodes::kBack)
 			return false;
 	}
-
-	// save to a tmp file/dir first, rename later
-	// (important to keep script files in the script directory)
-	const std::string tmp_name = complete_filename + ".tmp";
-	if (g_fs->file_exists(tmp_name)) {
+	
+	//  Try deleting file (if it exists). If it fails, give a message and let the player choose a new name.
+	try {
+		g_fs->fs_unlink(complete_filename);
+	} catch (const std::exception& e) {
 		const std::string s =
-		   (boost::format(
-		   _("A file with the name ‘%s.tmp’ already exists. You have to remove it manually.")) %
-		FileSystem::fs_filename(filename.c_str()))
-		  .str();
+		   (boost::format(_("File ‘%s.tmp’ could not be deleted.")) % FileSystem::fs_filename(filename.c_str())).str()
+		   + " " + _("Try saving under a different name!");
 		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
 		mbox.run();
 		return false;
@@ -290,51 +288,35 @@
 	Widelands::EditorGameBase& egbase = eia().egbase();
 	Widelands::Map* map = egbase.mutable_map();
 
-	{  // fs scope
+	// Recompute seafaring tag
+	map->cleanup_port_spaces(egbase.world());
+	if (map->allows_seafaring()) {
+		map->add_tag("seafaring");
+	} else {
+		map->delete_tag("seafaring");
+	}
+
+	if (map->has_artifacts()) {
+		map->add_tag("artifacts");
+	} else {
+		map->delete_tag("artifacts");
+	}
+	
+	//  Try saving.
+	try {
 		std::unique_ptr fs(
-		   g_fs->create_sub_file_system(tmp_name, binary ? FileSystem::ZIP : FileSystem::DIR));
-
-		// Recompute seafaring tag
-		map->cleanup_port_spaces(egbase.world());
-		if (map->allows_seafaring()) {
-			map->add_tag("seafaring");
-		} else {
-			map->delete_tag("seafaring");
-		}
-
-		if (map->has_artifacts()) {
-			map->add_tag("artifacts");
-		} else {
-			map->delete_tag("artifacts");
-		}
-
-		try {
-			Widelands::MapSaver* wms = new Widelands::MapSaver(*fs, egbase);
-			wms->save();
-			delete wms;
-			// Reset filesystem to avoid file locks on saves
-			fs.reset();
-			map->reset_filesystem();
-			eia().set_need_save(false);
-			g_fs->fs_unlink(complete_filename);
-			g_fs->fs_rename(tmp_name, complete_filename);
-			// Also change fs, as we assign it to the map below
-			fs.reset(g_fs->make_sub_file_system(complete_filename));
-			// Set the filesystem of the map to the current save file / directory
-			map->swap_filesystem(fs);
-			// DONT use fs as of here, its garbage now!
-
-		} catch (const std::exception& e) {
-			std::string s = _("Error Saving Map!\nSaved map file may be corrupt!\n\nReason "
-			  "given:\n");
-			s += e.what();
-			UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
-			mbox.run();
-
-			// cleanup tmp file if it was created
-			g_fs->fs_unlink(tmp_name);
-		}
-	}  // end fs scope, dont use it
+		   g_fs->create_sub_file_system(complete_filename, binary ? FileSystem::ZIP : FileSystem::DIR));
+		Widelands::MapSaver* wms = new Widelands::MapSaver(*fs, egbase);
+		wms->save();
+		delete wms;
+		fs.reset();
+	} catch (const std::exception& e) {
+		std::string s = _("Error Saving Map!\nSaved map file may be corrupt!\n\nReason "
+		  "given:\n");
+		s += e.what();
+		UI::WLMessageBox mbox(&eia(), _("Error Saving Map!"), s, UI::WLMessageBox::MBoxType::kOk);
+		mbox.run();
+	}
 
 	die();
 	return true;

=== modified file 'src/io/filesystem/zip_fil