fixed bugs with wrong newline handling in envelopes (game and editor)
authorHolger Schemel <holger.schemel@virtion.de>
Tue, 4 Jun 2024 21:13:07 +0000 (23:13 +0200)
committerHolger Schemel <holger.schemel@virtion.de>
Tue, 4 Jun 2024 21:13:07 +0000 (23:13 +0200)
This is the second (and hopefully final) attempt to fix a bug that was
already thought to be fixed with commit e567cb7f (which only fixed the
bug partially, and introduced new problems).

See the detailed description in function "LoadLevel_FixEnvelopes()"
for more details on the problem and the solution.

src/files.c
src/libgame/text.c

index e15996394b425f80a04db6a99e767ecbe97c4c8f..1fe2d9543d644d1cc29a0f9af9376934bf48d958 100644 (file)
@@ -7551,6 +7551,66 @@ void LoadLevelFromFilename(struct LevelInfo *level, char *filename)
   LoadLevelFromFileInfo(level, &level_file_info, FALSE);
 }
 
+static void LoadLevel_FixEnvelopes(struct LevelInfo *level, boolean skip_single_lines)
+{
+  // This function removes newlines in envelopes after lines of text ending in the last column
+  // of the envelope. In earlier versions, these newlines were removed when displaying envelopes,
+  // but caused trouble in the level editor. In version 4.3.2.3, this problem was partially
+  // fixed in the level editor (but only for single full-width text lines followed by a newline,
+  // not for multiple lines ending in the last column, followed by a newline), but now produced
+  // unwanted newlines in the game for envelopes stored by previous game versions, which was not
+  // intended by the level author (and sometimes caused text lines not being displayed anymore at
+  // the bottom of the envelope).
+  //
+  // This function should solve these problems by removing such newline characters from envelopes
+  // stored by older game versions.
+
+  int envelope_nr;
+
+  for (envelope_nr = 0; envelope_nr < NUM_ENVELOPES; envelope_nr++)
+  {
+    char *envelope_ptr = level->envelope[envelope_nr].text;
+    int envelope_xsize = level->envelope[envelope_nr].xsize;
+    int envelope_size = strlen(envelope_ptr);
+    int start = 0;
+    int i;
+
+    for (i = 0; i < envelope_size; i++)
+    {
+      // check for newlines in envelope
+      if (envelope_ptr[i] == '\n')
+      {
+        int line_length = i - start;
+
+        // check for (non-empty) lines that are a multiple of the envelope width,
+        // causing a line break inside the envelope (text area in editor and in game)
+        if (line_length > 0 && line_length % envelope_xsize == 0)
+        {
+          // special case: skip fixing single lines for newer versions
+          boolean skip_fixing_line = (line_length == 1 && skip_single_lines);
+
+          if (!skip_fixing_line)
+          {
+            int j;
+
+            // remove newline character from string
+            for (j = i; j < envelope_size; j++)
+              envelope_ptr[j] = envelope_ptr[j + 1];
+          }
+
+          // continue with next line (that was copied over the newline)
+          start = i;
+        }
+        else
+        {
+          // continue with next character after newline
+          start = i + 1;
+        }
+      }
+    }
+  }
+}
+
 static void LoadLevel_InitVersion(struct LevelInfo *level)
 {
   int i, j;
@@ -7742,6 +7802,10 @@ static void LoadLevel_InitVersion(struct LevelInfo *level)
   // CE changing to player was kept under the player if walkable up to 4.2.3.1
   if (level->game_version <= VERSION_IDENT(4,2,3,1))
     level->keep_walkable_ce = TRUE;
+
+  // envelopes may contain broken or too many line breaks before 4.4.0.0
+  if (level->game_version < VERSION_IDENT(4,4,0,0))
+    LoadLevel_FixEnvelopes(level, (level->game_version >= VERSION_IDENT(4,3,2,3)));
 }
 
 static void LoadLevel_InitSettings_SB(struct LevelInfo *level)
index 446a873b23dcfd9c137ed1792b1399f1525ed1d6..1db4848f0170a0964414be29d4b64c784d13a3b3 100644 (file)
@@ -589,8 +589,8 @@ static int DrawTextBufferExt(int x, int y, char *text_buffer, int base_font_nr,
     {
       if ((line[i] = *text_buffer++) == '\n')
       {
-       // in text areas, 'line_length' sized lines cause additional empty line
-       if (i == line_length && is_text_area)
+       // in text areas, do not skip newline after text ending at last column
+       if (i > 0 && i % line_length == 0 && is_text_area)
          text_buffer--;
 
        break;