moved code to check for file in level directories to separate function
[rocksndiamonds.git] / src / files.c
index ad0686319b94adfa80143698cd0233df7ad0bd41..5c4209d7c45ecc5da189f2092765cf38cd4beb70 100644 (file)
@@ -274,7 +274,7 @@ static struct LevelFileConfigInfo chunk_config_INFO[] =
   {
     -1,                                        -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(6),
-    &li.bd_cycle_delay_ms,             200
+    &li.bd_cycle_delay_ms,             160
   },
   {
     -1,                                        -1,
@@ -2929,26 +2929,7 @@ char *getLocalLevelTemplateFilename(void)
 
 char *getGlobalLevelTemplateFilename(void)
 {
-  // global variable "leveldir_current" must be modified in the loop below
-  LevelDirTree *leveldir_current_last = leveldir_current;
-  char *filename = NULL;
-
-  // check for template level in path from current to topmost tree node
-
-  while (leveldir_current != NULL)
-  {
-    filename = getDefaultLevelFilename(-1);
-
-    if (fileExists(filename))
-      break;
-
-    leveldir_current = leveldir_current->node_parent;
-  }
-
-  // restore global variable "leveldir_current" modified in above loop
-  leveldir_current = leveldir_current_last;
-
-  return filename;
+  return getFilenameFromCurrentLevelDirUpward(LEVELTEMPLATE_FILENAME);
 }
 
 static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
@@ -4645,11 +4626,9 @@ static void CopyNativeLevel_BD_to_RND(struct LevelInfo *level)
 
   // level name
   char *cave_name_latin1 = getLatin1FromUTF8(cave->name);
-  char *cave_name_final;
-  if (gd_caveset_has_levels())
-    cave_name_final = getStringPrint("%s / %d", cave_name_latin1, bd_level_nr + 1);
-  else
-    cave_name_final = getStringCopy(cave_name_latin1);
+  char *cave_name_final = (gd_caveset_has_levels() ?
+                           getStringPrint("%s / %d", cave_name_latin1, bd_level_nr + 1) :
+                           getStringCopy(cave_name_latin1));
 
   strncpy(level->name, cave_name_final, MAX_LEVEL_NAME_LEN);
   level->name[MAX_LEVEL_NAME_LEN] = '\0';
@@ -7553,6 +7532,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;
@@ -7744,6 +7783,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)
@@ -10848,7 +10891,7 @@ static struct TokenInfo global_setup_tokens[] =
   },
   {
     TYPE_SWITCH_3_STATES,
-    &setup.bd_skip_falling_sounds,             "bd_skip_falling_sounds"
+    &setup.bd_falling_sounds,                  "bd_falling_sounds"
   },
   {
     TYPE_INTEGER,
@@ -11066,6 +11109,10 @@ static struct TokenInfo editor_setup_tokens[] =
     TYPE_SWITCH,
     &setup.editor.show_element_token,          "editor.show_element_token"
   },
+  {
+    TYPE_SWITCH,
+    &setup.editor.fast_game_start,             "editor.fast_game_start"
+  },
   {
     TYPE_SWITCH,
     &setup.editor.show_read_only_warning,      "editor.show_read_only_warning"
@@ -11715,7 +11762,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->bd_smooth_movements = STATE_TRUE;
   si->bd_pushing_graphics = STATE_TRUE;
   si->bd_up_down_graphics = STATE_TRUE;
-  si->bd_skip_falling_sounds = STATE_TRUE;
+  si->bd_falling_sounds = STATE_AUTO;
   si->bd_palette_c64 = GD_DEFAULT_PALETTE_C64;
   si->bd_palette_c64dtv = GD_DEFAULT_PALETTE_C64DTV;
   si->bd_palette_atari = GD_DEFAULT_PALETTE_ATARI;
@@ -11828,6 +11875,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->editor.el_headlines              = TRUE;
 
   si->editor.show_element_token                = FALSE;
+  si->editor.fast_game_start           = FALSE;
 
   si->editor.show_read_only_warning    = TRUE;