rnd-20060226-3-src
[rocksndiamonds.git] / src / libgame / setup.c
index 967fbcfacd60a10e9f36eacfdcd74b3fbd11a3a7..c96316f6e56fb4d9e117bb0a74a0a4f1b3980d73 100644 (file)
@@ -302,8 +302,8 @@ char *setLevelArtworkDir(TreeInfo *ti)
   if (ti == NULL || leveldir_current == NULL)
     return NULL;
 
-  artwork_path_ptr = &(LEVELDIR_ARTWORK_PATH(leveldir_current, ti->type));
-  artwork_set_ptr  = &(LEVELDIR_ARTWORK_SET( leveldir_current, ti->type));
+  artwork_path_ptr = LEVELDIR_ARTWORK_PATH_PTR(leveldir_current, ti->type);
+  artwork_set_ptr  = LEVELDIR_ARTWORK_SET_PTR( leveldir_current, ti->type);
 
   checked_free(*artwork_path_ptr);
 
@@ -799,7 +799,7 @@ void InitLevelSetupDirectory(char *level_subdir)
 
 
 /* ------------------------------------------------------------------------- */
-/* some functions to handle lists of level directories                       */
+/* some functions to handle lists of level and artwork directories           */
 /* ------------------------------------------------------------------------- */
 
 TreeInfo *newTreeInfo()
@@ -927,6 +927,43 @@ TreeInfo *getTreeInfoFromIdentifier(TreeInfo *node, char *identifier)
   return NULL;
 }
 
+TreeInfo *cloneTreeNode(TreeInfo **node_top, TreeInfo *node_parent,
+                       TreeInfo *node, boolean skip_sets_without_levels)
+{
+  TreeInfo *node_new;
+
+  if (node == NULL)
+    return NULL;
+
+  if (!node->parent_link && !node->level_group &&
+      skip_sets_without_levels && node->levels == 0)
+    return cloneTreeNode(node_top, node_parent, node->next,
+                        skip_sets_without_levels);
+
+  node_new = newTreeInfo();
+
+  *node_new = *node;                           /* copy complete node */
+
+  node_new->node_top = node_top;               /* correct top node link */
+  node_new->node_parent = node_parent;         /* correct parent node link */
+
+  if (node->level_group)
+    node_new->node_group = cloneTreeNode(node_top, node_new, node->node_group,
+                                        skip_sets_without_levels);
+
+  node_new->next = cloneTreeNode(node_top, node_parent, node->next,
+                                skip_sets_without_levels);
+  
+  return node_new;
+}
+
+void cloneTree(TreeInfo **ti_new, TreeInfo *ti, boolean skip_empty_sets)
+{
+  TreeInfo *ti_cloned = cloneTreeNode(ti_new, NULL, ti, skip_empty_sets);
+
+  *ti_new = ti_cloned;
+}
+
 void dumpTreeInfo(TreeInfo *node, int depth)
 {
   int i;
@@ -938,13 +975,8 @@ void dumpTreeInfo(TreeInfo *node, int depth)
     for (i = 0; i < (depth + 1) * 3; i++)
       printf(" ");
 
-#if 1
     printf("subdir == '%s' ['%s', '%s'] [%d])\n",
           node->subdir, node->fullpath, node->basepath, node->in_user_dir);
-#else
-    printf("subdir == '%s' (%s) [%s] (%d)\n",
-          node->subdir, node->name, node->identifier, node->sort_priority);
-#endif
 
     if (node->node_group != NULL)
       dumpTreeInfo(node->node_group, depth + 1);
@@ -1396,7 +1428,6 @@ char *removeHashEntry(SetupFileHash *hash, char *token)
 }
 
 #if 0
-#ifdef DEBUG
 static void printSetupFileHash(SetupFileHash *hash)
 {
   BEGIN_HASH_ITERATION(hash, itr)
@@ -1407,7 +1438,6 @@ static void printSetupFileHash(SetupFileHash *hash)
   END_HASH_ITERATION(hash, itr)
 }
 #endif
-#endif
 
 static void *loadSetupFileData(char *filename, boolean use_hash)
 {
@@ -1560,14 +1590,14 @@ SetupFileHash *loadSetupFileHash(char *filename)
 }
 
 void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
-                                 char *identifier)
+                                 char *filename, char *identifier)
 {
   char *value = getHashEntry(setup_file_hash, TOKEN_STR_FILE_IDENTIFIER);
 
   if (value == NULL)
-    Error(ERR_WARN, "configuration file has no file identifier");
+    Error(ERR_WARN, "config file '%s' has no file identifier", filename);
   else if (!checkCookieString(value, identifier))
-    Error(ERR_WARN, "configuration file has wrong file identifier");
+    Error(ERR_WARN, "config file '%s' has wrong file identifier", filename);
 }
 
 
@@ -1698,7 +1728,6 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
     return;
   }
 
-#if 1
   /* copy all values from the parent structure */
 
   ldi->type = parent->type;
@@ -1751,47 +1780,6 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
     ldi->handicap = TRUE;
     ldi->skip_levels = FALSE;
   }
-
-#else
-
-  /* first copy all values from the parent structure ... */
-  *ldi = *parent;
-
-  /* ... then set all fields to default that cannot be inherited from parent.
-     This is especially important for all those fields that can be set from
-     the 'levelinfo.conf' config file, because the function 'setSetupInfo()'
-     calls 'free()' for all already set token values which requires that no
-     other structure's pointer may point to them!
-  */
-
-  ldi->subdir = NULL;
-  ldi->fullpath = NULL;
-  ldi->basepath = NULL;
-  ldi->identifier = NULL;
-  ldi->name = getStringCopy(ANONYMOUS_NAME);
-  ldi->name_sorting = NULL;
-  ldi->author = getStringCopy(parent->author);
-
-  ldi->imported_from = getStringCopy(parent->imported_from);
-  ldi->imported_by = getStringCopy(parent->imported_by);
-  ldi->class_desc = getStringCopy(parent->class_desc);
-
-  ldi->graphics_set = NULL;
-  ldi->sounds_set = NULL;
-  ldi->music_set = NULL;
-  ldi->graphics_path = NULL;
-  ldi->sounds_path = NULL;
-  ldi->music_path = NULL;
-
-  ldi->level_group = FALSE;
-  ldi->parent_link = FALSE;
-
-  ldi->node_top = parent->node_top;
-  ldi->node_parent = parent;
-  ldi->node_group = NULL;
-  ldi->next = NULL;
-
-#endif
 }
 
 static void freeTreeInfo(TreeInfo *ldi)
@@ -1915,7 +1903,6 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
   ti_new->node_parent = node_parent;
   ti_new->parent_link = TRUE;
 
-#if 1
   setString(&ti_new->identifier, node_parent->identifier);
   setString(&ti_new->name, ".. (parent directory)");
   setString(&ti_new->name_sorting, ti_new->name);
@@ -1927,19 +1914,6 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
   ti_new->latest_engine = node_parent->latest_engine;
 
   setString(&ti_new->class_desc, getLevelClassDescription(ti_new));
-#else
-  ti_new->identifier = getStringCopy(node_parent->identifier);
-  ti_new->name = ".. (parent directory)";
-  ti_new->name_sorting = getStringCopy(ti_new->name);
-
-  ti_new->subdir = "..";
-  ti_new->fullpath = getStringCopy(node_parent->fullpath);
-
-  ti_new->sort_priority = node_parent->sort_priority;
-  ti_new->latest_engine = node_parent->latest_engine;
-
-  ti_new->class_desc = getLevelClassDescription(ti_new);
-#endif
 
   pushTreeInfo(&node_parent->node_group, ti_new);
 }
@@ -1988,7 +1962,8 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
 
   leveldir_new->subdir = getStringCopy(directory_name);
 
-  checkSetupFileHashIdentifier(setup_file_hash, getCookie("LEVELINFO"));
+  checkSetupFileHashIdentifier(setup_file_hash, filename,
+                              getCookie("LEVELINFO"));
 
   /* set all structure fields according to the token/value pairs */
   ldi = *leveldir_new;
@@ -1997,16 +1972,8 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
                 getHashEntry(setup_file_hash, levelinfo_tokens[i].text));
   *leveldir_new = ldi;
 
-#if 1
   if (strcmp(leveldir_new->name, ANONYMOUS_NAME) == 0)
     setString(&leveldir_new->name, leveldir_new->subdir);
-#else
-  if (strcmp(leveldir_new->name, ANONYMOUS_NAME) == 0)
-  {
-    free(leveldir_new->name);
-    leveldir_new->name = getStringCopy(leveldir_new->subdir);
-  }
-#endif
 
   DrawInitText(leveldir_new->name, 150, FC_YELLOW);
 
@@ -2027,42 +1994,55 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
     leveldir_new->fullpath = getPath2(node_parent->fullpath, directory_name);
   }
 
+#if 0
   if (leveldir_new->levels < 1)
     leveldir_new->levels = 1;
+#endif
 
   leveldir_new->last_level =
     leveldir_new->first_level + leveldir_new->levels - 1;
 
-#if 1
   leveldir_new->in_user_dir =
     (strcmp(leveldir_new->basepath, options.level_directory) != 0);
-#else
-  leveldir_new->in_user_dir =
-    (leveldir_new->basepath == options.level_directory ? FALSE : TRUE);
-#endif
 
-#if 1
-  /* adjust sort priority if user's private level directory was detected */
+  /* adjust some settings if user's private level directory was detected */
   if (leveldir_new->sort_priority == LEVELCLASS_UNDEFINED &&
       leveldir_new->in_user_dir &&
-      strcmp(leveldir_new->subdir, getLoginName()) == 0)
+      (strcmp(leveldir_new->subdir, getLoginName()) == 0 ||
+       strcmp(leveldir_new->name,   getLoginName()) == 0 ||
+       strcmp(leveldir_new->author, getRealName())  == 0))
+  {
     leveldir_new->sort_priority = LEVELCLASS_PRIVATE_START;
-#endif
+    leveldir_new->readonly = FALSE;
+  }
 
   leveldir_new->user_defined =
     (leveldir_new->in_user_dir && IS_LEVELCLASS_PRIVATE(leveldir_new));
 
   leveldir_new->color = LEVELCOLOR(leveldir_new);
-#if 1
+
   setString(&leveldir_new->class_desc, getLevelClassDescription(leveldir_new));
-#else
-  leveldir_new->class_desc = getLevelClassDescription(leveldir_new);
-#endif
 
   leveldir_new->handicap_level =       /* set handicap to default value */
     (leveldir_new->user_defined || !leveldir_new->handicap ?
      leveldir_new->last_level : leveldir_new->first_level);
 
+#if 0
+  /* !!! don't skip sets without levels (else artwork base sets are missing) */
+#if 1
+  if (leveldir_new->levels < 1 && !leveldir_new->level_group)
+  {
+    /* skip level sets without levels (which are probably artwork base sets) */
+
+    freeSetupFileHash(setup_file_hash);
+    free(directory_path);
+    free(filename);
+
+    return FALSE;
+  }
+#endif
+#endif
+
   pushTreeInfo(node_first, leveldir_new);
 
   freeSetupFileHash(setup_file_hash);
@@ -2154,6 +2134,15 @@ void LoadLevelInfo()
   LoadLevelInfoFromLevelDir(&leveldir_first, NULL, options.level_directory);
   LoadLevelInfoFromLevelDir(&leveldir_first, NULL, getUserLevelDir(NULL));
 
+#if 1
+  /* after loading all level set information, clone the level directory tree
+     and remove all level sets without levels (these may still contain artwork
+     to be offered in the setup menu as "custom artwork", and are therefore
+     checked for existing artwork in the function "LoadLevelArtworkInfo()") */
+  leveldir_first_all = leveldir_first;
+  cloneTree(&leveldir_first, leveldir_first_all, TRUE);
+#endif
+
   /* before sorting, the first entries will be from the user directory */
   leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
 
@@ -2227,7 +2216,7 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
   if (setup_file_hash) /* (before defining ".color" and ".class_desc") */
   {
 #if 0
-    checkSetupFileHashIdentifier(setup_file_hash, getCookie("..."));
+    checkSetupFileHashIdentifier(setup_file_hash, filename, getCookie("..."));
 #endif
 
     /* set all structure fields according to the token/value pairs */
@@ -2237,16 +2226,8 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
                   getHashEntry(setup_file_hash, levelinfo_tokens[i].text));
     *artwork_new = ldi;
 
-#if 1
     if (strcmp(artwork_new->name, ANONYMOUS_NAME) == 0)
       setString(&artwork_new->name, artwork_new->subdir);
-#else
-    if (strcmp(artwork_new->name, ANONYMOUS_NAME) == 0)
-    {
-      free(artwork_new->name);
-      artwork_new->name = getStringCopy(artwork_new->subdir);
-    }
-#endif
 
 #if 0
     DrawInitText(artwork_new->name, 150, FC_YELLOW);
@@ -2270,86 +2251,42 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
     artwork_new->fullpath = getPath2(node_parent->fullpath, directory_name);
   }
 
-#if 1
   artwork_new->in_user_dir =
     (strcmp(artwork_new->basepath, OPTIONS_ARTWORK_DIRECTORY(type)) != 0);
-#else
-  artwork_new->in_user_dir =
-    (artwork_new->basepath == OPTIONS_ARTWORK_DIRECTORY(type) ? FALSE : TRUE);
-#endif
 
   /* (may use ".sort_priority" from "setup_file_hash" above) */
   artwork_new->color = ARTWORKCOLOR(artwork_new);
-#if 1
+
   setString(&artwork_new->class_desc, getLevelClassDescription(artwork_new));
-#else
-  artwork_new->class_desc = getLevelClassDescription(artwork_new);
-#endif
 
   if (setup_file_hash == NULL) /* (after determining ".user_defined") */
   {
-#if 0
-    if (artwork_new->name != NULL)
-    {
-      free(artwork_new->name);
-      artwork_new->name = NULL;
-    }
-#endif
-
-#if 0
-    if (artwork_new->identifier != NULL)
-    {
-      free(artwork_new->identifier);
-      artwork_new->identifier = NULL;
-    }
-#endif
-
     if (strcmp(artwork_new->subdir, ".") == 0)
     {
       if (artwork_new->user_defined)
       {
-#if 1
        setString(&artwork_new->identifier, "private");
-#else
-       artwork_new->identifier = getStringCopy("private");
-#endif
        artwork_new->sort_priority = ARTWORKCLASS_PRIVATE;
       }
       else
       {
-#if 1
        setString(&artwork_new->identifier, "classic");
-#else
-       artwork_new->identifier = getStringCopy("classic");
-#endif
        artwork_new->sort_priority = ARTWORKCLASS_CLASSICS;
       }
 
       /* set to new values after changing ".sort_priority" */
       artwork_new->color = ARTWORKCOLOR(artwork_new);
-#if 1
+
       setString(&artwork_new->class_desc,
                getLevelClassDescription(artwork_new));
-#else
-      artwork_new->class_desc = getLevelClassDescription(artwork_new);
-#endif
     }
     else
     {
-#if 1
       setString(&artwork_new->identifier, artwork_new->subdir);
-#else
-      artwork_new->identifier = getStringCopy(artwork_new->subdir);
-#endif
     }
 
-#if 1
     setString(&artwork_new->name, artwork_new->identifier);
     setString(&artwork_new->name_sorting, artwork_new->name);
-#else
-    artwork_new->name = getStringCopy(artwork_new->identifier);
-    artwork_new->name_sorting = getStringCopy(artwork_new->name);
-#endif
   }
 
   DrawInitText(artwork_new->name, 150, FC_YELLOW);
@@ -2427,7 +2364,6 @@ static TreeInfo *getDummyArtworkInfo(int type)
 
   setTreeInfoToDefaults(artwork_new, type);
 
-#if 1
   setString(&artwork_new->subdir,   UNDEFINED_FILENAME);
   setString(&artwork_new->fullpath, UNDEFINED_FILENAME);
   setString(&artwork_new->basepath, UNDEFINED_FILENAME);
@@ -2435,17 +2371,6 @@ static TreeInfo *getDummyArtworkInfo(int type)
   setString(&artwork_new->identifier,   UNDEFINED_FILENAME);
   setString(&artwork_new->name,         UNDEFINED_FILENAME);
   setString(&artwork_new->name_sorting, UNDEFINED_FILENAME);
-#else
-  artwork_new->subdir   = getStringCopy(UNDEFINED_FILENAME);
-  artwork_new->fullpath = getStringCopy(UNDEFINED_FILENAME);
-  artwork_new->basepath = getStringCopy(UNDEFINED_FILENAME);
-
-  checked_free(artwork_new->name);
-
-  artwork_new->identifier   = getStringCopy(UNDEFINED_FILENAME);
-  artwork_new->name         = getStringCopy(UNDEFINED_FILENAME);
-  artwork_new->name_sorting = getStringCopy(UNDEFINED_FILENAME);
-#endif
 
   return artwork_new;
 }
@@ -2538,12 +2463,6 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
     char *path = getPath2(getLevelDirFromTreeInfo(level_node),
                          ARTWORK_DIRECTORY((*artwork_node)->type));
 
-#if 0
-    if (!level_node->parent_link)
-      printf("CHECKING '%s' ['%s', '%s'] ...\n", path,
-            level_node->subdir, level_node->name);
-#endif
-
     if (!level_node->parent_link)
     {
       TreeInfo *topnode_last = *artwork_node;
@@ -2579,9 +2498,9 @@ void LoadLevelArtworkInfo()
 {
   DrawInitText("Looking for custom level artwork:", 120, FC_GREEN);
 
-  LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first);
-  LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first);
-  LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first);
+  LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first_all);
+  LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first_all);
+  LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first_all);
 
   /* needed for reloading level artwork not known at ealier stage */
 
@@ -2650,29 +2569,10 @@ static void SaveUserLevelInfo()
   /* always start with reliable default values */
   setTreeInfoToDefaults(level_info, TREE_TYPE_LEVEL_DIR);
 
-#if 1
   setString(&level_info->name, getLoginName());
   setString(&level_info->author, getRealName());
   level_info->levels = 100;
   level_info->first_level = 1;
-#if 0
-  level_info->sort_priority = LEVELCLASS_PRIVATE_START;
-  level_info->readonly = FALSE;
-  setString(&level_info->graphics_set, GFX_CLASSIC_SUBDIR);
-  setString(&level_info->sounds_set,   SND_CLASSIC_SUBDIR);
-  setString(&level_info->music_set,    MUS_CLASSIC_SUBDIR);
-#endif
-#else
-  ldi.name = getStringCopy(getLoginName());
-  ldi.author = getStringCopy(getRealName());
-  ldi.levels = 100;
-  ldi.first_level = 1;
-  ldi.sort_priority = LEVELCLASS_PRIVATE_START;
-  ldi.readonly = FALSE;
-  ldi.graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR);
-  ldi.sounds_set = getStringCopy(SND_CLASSIC_SUBDIR);
-  ldi.music_set = getStringCopy(MUS_CLASSIC_SUBDIR);
-#endif
 
   token_value_position = TOKEN_VALUE_POSITION_SHORT;
 
@@ -2682,7 +2582,6 @@ static void SaveUserLevelInfo()
   ldi = *level_info;
   for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
   {
-#if 1
     if (i == LEVELINFO_TOKEN_NAME ||
        i == LEVELINFO_TOKEN_AUTHOR ||
        i == LEVELINFO_TOKEN_LEVELS ||
@@ -2692,15 +2591,6 @@ static void SaveUserLevelInfo()
     /* just to make things nicer :) */
     if (i == LEVELINFO_TOKEN_AUTHOR)
       fprintf(file, "\n");     
-#else
-    if (i != LEVELINFO_TOKEN_IDENTIFIER &&
-       i != LEVELINFO_TOKEN_NAME_SORTING &&
-       i != LEVELINFO_TOKEN_IMPORTED_FROM &&
-       i != LEVELINFO_TOKEN_IMPORTED_BY &&
-       i != LEVELINFO_TOKEN_FILENAME &&
-       i != LEVELINFO_TOKEN_FILETYPE)
-      fprintf(file, "%s\n", getSetupLine(levelinfo_tokens, "", i));
-#endif
   }
 
   token_value_position = TOKEN_VALUE_POSITION_DEFAULT;
@@ -2818,7 +2708,8 @@ void LoadLevelSetup_LastSeries()
     if (leveldir_current == NULL)
       leveldir_current = getFirstValidTreeInfoEntry(leveldir_first);
 
-    checkSetupFileHashIdentifier(level_setup_hash, getCookie("LEVELSETUP"));
+    checkSetupFileHashIdentifier(level_setup_hash, filename,
+                                getCookie("LEVELSETUP"));
 
     freeSetupFileHash(level_setup_hash);
   }
@@ -2962,7 +2853,8 @@ void LoadLevelSetup_SeriesInfo()
       leveldir_current->handicap_level = level_nr;
     }
 
-    checkSetupFileHashIdentifier(level_setup_hash, getCookie("LEVELSETUP"));
+    checkSetupFileHashIdentifier(level_setup_hash, filename,
+                                getCookie("LEVELSETUP"));
 
     freeSetupFileHash(level_setup_hash);
   }