changed color of unselected tree info nodes from yellow to green
[rocksndiamonds.git] / src / libgame / setup.c
index 8f98ff010db474365fb4c7fd9500e27a5d35f167..4cee439fcafd47cda4d9dcc700e0777733174e34 100644 (file)
@@ -43,14 +43,13 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
   "DX Boulderdash"
 };
 
-
 #define LEVELCOLOR(n)  (IS_LEVELCLASS_TUTORIAL(n) ?            FC_BLUE :    \
                         IS_LEVELCLASS_CLASSICS(n) ?            FC_RED :     \
-                        IS_LEVELCLASS_BD(n) ?                  FC_YELLOW :  \
-                        IS_LEVELCLASS_EM(n) ?                  FC_YELLOW :  \
-                        IS_LEVELCLASS_SP(n) ?                  FC_YELLOW :  \
-                        IS_LEVELCLASS_DX(n) ?                  FC_YELLOW :  \
-                        IS_LEVELCLASS_SB(n) ?                  FC_YELLOW :  \
+                        IS_LEVELCLASS_BD(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_EM(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_SP(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_DX(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_SB(n) ?                  FC_GREEN :   \
                         IS_LEVELCLASS_CONTRIB(n) ?             FC_GREEN :   \
                         IS_LEVELCLASS_PRIVATE(n) ?             FC_RED :     \
                         FC_BLUE)
@@ -69,7 +68,7 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
 #define ARTWORKCOLOR(n)        (IS_ARTWORKCLASS_CLASSICS(n) ?          FC_RED :     \
                         IS_ARTWORKCLASS_CONTRIB(n) ?           FC_GREEN :   \
                         IS_ARTWORKCLASS_PRIVATE(n) ?           FC_RED :     \
-                        IS_ARTWORKCLASS_LEVEL(n) ?             FC_YELLOW :  \
+                        IS_ARTWORKCLASS_LEVEL(n) ?             FC_GREEN :   \
                         FC_BLUE)
 
 #define ARTWORKSORTING(n) (IS_ARTWORKCLASS_CLASSICS(n) ?       0 :     \
@@ -96,6 +95,7 @@ static SetupFileHash *artworkinfo_cache_old = NULL;
 static SetupFileHash *artworkinfo_cache_new = NULL;
 static SetupFileHash *optional_tokens_hash = NULL;
 static boolean use_artworkinfo_cache = TRUE;
+static boolean update_artworkinfo_cache = FALSE;
 
 
 // ----------------------------------------------------------------------------
@@ -2325,25 +2325,51 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
   return TRUE;
 }
 
+static int compareSetupFileData(const void *object1, const void *object2)
+{
+  const struct ConfigInfo *entry1 = (struct ConfigInfo *)object1;
+  const struct ConfigInfo *entry2 = (struct ConfigInfo *)object2;
+
+  return strcmp(entry1->token, entry2->token);
+}
+
 static void saveSetupFileHash(SetupFileHash *hash, char *filename)
 {
+  int item_count = hashtable_count(hash);
+  int item_size = sizeof(struct ConfigInfo);
+  struct ConfigInfo *sort_array = checked_malloc(item_count * item_size);
   FILE *file;
+  int i = 0;
 
-  if (!(file = fopen(filename, MODE_WRITE)))
+  // copy string pointers from hash to array
+  BEGIN_HASH_ITERATION(hash, itr)
   {
-    Warn("cannot write configuration file '%s'", filename);
+    sort_array[i].token = HASH_ITERATION_TOKEN(itr);
+    sort_array[i].value = HASH_ITERATION_VALUE(itr);
 
-    return;
+    i++;
+
+    if (i > item_count)                // should never happen
+      break;
   }
+  END_HASH_ITERATION(hash, itr)
 
-  BEGIN_HASH_ITERATION(hash, itr)
+  // sort string pointers from hash in array
+  qsort(sort_array, item_count, item_size, compareSetupFileData);
+
+  if (!(file = fopen(filename, MODE_WRITE)))
   {
-    fprintf(file, "%s\n", getFormattedSetupEntry(HASH_ITERATION_TOKEN(itr),
-                                                HASH_ITERATION_VALUE(itr)));
+    Warn("cannot write configuration file '%s'", filename);
+
+    return;
   }
-  END_HASH_ITERATION(hash, itr)
 
+  for (i = 0; i < item_count; i++)
+    fprintf(file, "%s\n", getFormattedSetupEntry(sort_array[i].token,
+                                                sort_array[i].value));
   fclose(file);
+
+  checked_free(sort_array);
 }
 
 SetupFileList *loadSetupFileList(char *filename)
@@ -2850,16 +2876,10 @@ static int compareTreeInfoEntries(const void *object1, const void *object2)
 
   if (entry1->parent_link || entry2->parent_link)
     compare_result = (entry1->parent_link ? -1 : +1);
+  else if (entry1->level_group != entry2->level_group)
+    compare_result = (entry1->level_group ? -1 : +1);
   else if (entry1->sort_priority == entry2->sort_priority)
-  {
-    char *name1 = getStringToLower(entry1->name_sorting);
-    char *name2 = getStringToLower(entry2->name_sorting);
-
-    compare_result = strcmp(name1, name2);
-
-    free(name1);
-    free(name2);
-  }
+    compare_result = strcasecmp(entry1->name_sorting, entry2->name_sorting);
   else if (class_sorting1 == class_sorting2)
     compare_result = entry1->sort_priority - entry2->sort_priority;
   else
@@ -2928,12 +2948,25 @@ static TreeInfo *createTopTreeInfoNode(TreeInfo *node_first)
 
   TreeInfo *ti_new2 = createParentTreeInfoNode(ti_new);
 
-  setString(&ti_new2->name, BACKLINK_TEXT_MAIN);
+  setString(&ti_new2->name, TREE_BACKLINK_TEXT(type));
   setString(&ti_new2->name_sorting, ti_new2->name);
 
   return ti_new;
 }
 
+static void setTreeInfoParentNodes(TreeInfo *node, TreeInfo *node_parent)
+{
+  while (node)
+  {
+    if (node->node_group)
+      setTreeInfoParentNodes(node->node_group, node);
+
+    node->node_parent = node_parent;
+
+    node = node->next;
+  }
+}
+
 
 // ----------------------------------------------------------------------------
 // functions for handling level and custom artwork info cache
@@ -2959,10 +2992,15 @@ static void LoadArtworkInfoCache(void)
 
   if (artworkinfo_cache_new == NULL)
     artworkinfo_cache_new = newSetupFileHash();
+
+  update_artworkinfo_cache = FALSE;
 }
 
 static void SaveArtworkInfoCache(void)
 {
+  if (!update_artworkinfo_cache)
+    return;
+
   char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE);
 
   InitCacheDirectory();
@@ -3007,6 +3045,9 @@ static boolean modifiedFileTimestamp(char *filename, char *timestamp_string)
   if (timestamp_string == NULL)
     return TRUE;
 
+  if (!fileExists(filename))                   // file does not exist
+    return (atoi(timestamp_string) != 0);
+
   if (stat(filename, &file_status) != 0)       // cannot stat file
     return TRUE;
 
@@ -3926,7 +3967,7 @@ void LoadArtworkInfo(void)
 static void MoveArtworkInfoIntoSubTree(ArtworkDirTree **artwork_node)
 {
   ArtworkDirTree *artwork_new = newTreeInfo();
-  char *top_node_name = "dedicated custom artwork";
+  char *top_node_name = "standalone artwork";
 
   setTreeInfoToDefaults(artwork_new, (*artwork_node)->type);
 
@@ -3987,6 +4028,8 @@ static void LoadArtworkInfoFromLevelInfoExt(ArtworkDirTree **artwork_node,
 
          artwork_new->sort_priority = level_node->sort_priority;
          artwork_new->color = LEVELCOLOR(artwork_new);
+
+         update_artworkinfo_cache = TRUE;
        }
 
        free(path);
@@ -4015,8 +4058,8 @@ static void LoadArtworkInfoFromLevelInfoExt(ArtworkDirTree **artwork_node,
       if (node_parent == NULL)         // check for top tree node
       {
        char *top_node_name = (empty_level_set_mode ?
-                              "artwork-only level sets" :
-                              "artwork from level sets");
+                              "artwork for certain level sets" :
+                              "artwork included in level sets");
 
        setString(&artwork_new->name,         top_node_name);
        setString(&artwork_new->name_sorting, top_node_name);
@@ -4048,10 +4091,18 @@ static void LoadArtworkInfoFromLevelInfoExt(ArtworkDirTree **artwork_node,
 
 static void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node)
 {
+  // move peviously loaded artwork tree into separate sub-tree
   MoveArtworkInfoIntoSubTree(artwork_node);
 
+  // load artwork from level sets into separate sub-trees
   LoadArtworkInfoFromLevelInfoExt(artwork_node, NULL, leveldir_first_all, TRUE);
   LoadArtworkInfoFromLevelInfoExt(artwork_node, NULL, leveldir_first_all, FALSE);
+
+  // add top tree node over all three separate sub-trees
+  *artwork_node = createTopTreeInfoNode(*artwork_node);
+
+  // set all parent links (back links) in complete artwork tree
+  setTreeInfoParentNodes(*artwork_node, NULL);
 }
 
 void LoadLevelArtworkInfo(void)