latest code update

- app icon
- starting with map view
- code cleanup

Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
2026-02-14 09:43:19 +01:00
parent 7f039e9cda
commit fe79f46d44
21 changed files with 637 additions and 170 deletions

View File

@@ -9,6 +9,7 @@ extern "C" {
#include <fstream>
#include <sstream>
#include <set>
#include <cstdio>
namespace wherigo {
@@ -82,10 +83,42 @@ void LuaPersistence::serializeValue(lua_State* L, int index, std::string& output
case LUA_TSTRING: {
const char* str = lua_tostring(L, index);
output += "\"";
// Escape special characters
// Properly escape all special characters for Lua strings
for (const char* p = str; *p; ++p) {
if (*p == '"' || *p == '\\') output += '\\';
output += *p;
unsigned char c = (unsigned char)*p;
switch (c) {
case '"':
output += "\\\"";
break;
case '\\':
output += "\\\\";
break;
case '\n':
output += "\\n";
break;
case '\r':
output += "\\r";
break;
case '\t':
output += "\\t";
break;
case '\b':
output += "\\b";
break;
case '\f':
output += "\\f";
break;
default:
// For control characters and high bytes, use decimal escape
if (c < 32 || c >= 127) {
char hex[6];
snprintf(hex, sizeof(hex), "\\%d", c);
output += hex;
} else {
output += c;
}
break;
}
}
output += "\"";
break;
@@ -199,23 +232,120 @@ bool LuaPersistence::loadGlobals(lua_State* L, const std::string& filePath) {
return false;
}
// Restore globals
// Restore globals - but for tables (Wherigo objects), merge instead of replace
// Strategy: For each saved object, find the matching existing object and merge
int count = 0;
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_isstring(L, -2)) {
const char* key = lua_tostring(L, -2);
if (lua_isstring(L, -2) && lua_istable(L, -1)) {
const char* savedKey = lua_tostring(L, -2);
wxLogDebug("Restoring global: %s", savedKey);
int stackBefore = lua_gettop(L);
// Set the global
lua_pushvalue(L, -1); // duplicate value
lua_setglobal(L, key);
// Get the Name field of the saved object (if it exists)
lua_getfield(L, -1, "Name");
std::string savedName;
if (lua_isstring(L, -1)) {
savedName = lua_tostring(L, -1);
}
lua_pop(L, 1);
// Try to find matching existing object
bool merged = false;
if (!savedName.empty()) {
// Search for existing object with same Name
lua_getglobal(L, "_G");
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "Name");
if (lua_isstring(L, -1)) {
if (savedName == lua_tostring(L, -1)) {
lua_pop(L, 1); // pop Name
// Found matching object! Merge data
lua_pushnil(L);
while (lua_next(L, -3) != 0) {
if (lua_isstring(L, -2)) {
const char* field = lua_tostring(L, -2);
if (!lua_isfunction(L, -1)) {
lua_pushvalue(L, -1);
lua_setfield(L, -4, field);
}
}
lua_pop(L, 1);
}
merged = true;
lua_pop(L, 2); // pop iterator and object
break;
}
}
lua_pop(L, 1);
}
lua_pop(L, 1);
}
lua_pop(L, 1); // pop _G
}
if (!merged) {
// No match found or no Name field - use key matching
lua_getglobal(L, savedKey);
if (lua_istable(L, -1)) {
// Object exists by key - merge it
lua_pushnil(L);
while (lua_next(L, -3) != 0) {
if (lua_isstring(L, -2)) {
const char* field = lua_tostring(L, -2);
if (!lua_isfunction(L, -1)) {
lua_getfield(L, -3, field); // get existing value
if (lua_istable(L, -1) && lua_istable(L, -2)) {
// Both are tables: merge recursively
lua_pushnil(L);
while (lua_next(L, -3) != 0) {
if (lua_isstring(L, -2)) {
const char* subfield = lua_tostring(L, -2);
if (!lua_isfunction(L, -1)) {
lua_pushvalue(L, -1);
lua_setfield(L, -5, subfield); // merge into existing table
}
}
lua_pop(L, 1);
}
lua_pop(L, 1); // pop existing value
} else {
lua_pop(L, 1); // pop existing value
lua_pushvalue(L, -1);
lua_setfield(L, -3, field);
}
}
}
lua_pop(L, 1);
}
lua_pop(L, 1); // pop existing object
merged = true;
} else {
lua_pop(L, 1); // pop nil
}
}
if (!merged) {
// No existing object found - create new global
lua_pushvalue(L, -1);
lua_setglobal(L, savedKey);
}
int stackAfter = lua_gettop(L);
if (stackBefore != stackAfter) {
wxLogError("Stack imbalance detected for global %s: before=%d after=%d", savedKey, stackBefore, stackAfter);
}
count++;
}
lua_pop(L, 1); // pop value
lua_pop(L, 1); // pop value from lua_next
}
lua_pop(L, 1); // pop table
lua_pop(L, 1); // pop table
wxLogDebug("Restored %d globals from %s", count, filePath);
return true;
}