rnd-20061030-3-src
[rocksndiamonds.git] / src / libgame / setup.c
index 4f00449473f8cadcb520d70c9a0ea542c40f4797..6d187a02ef97519c5125c1072ee20f5d39326dca 100644 (file)
@@ -92,6 +92,8 @@ static int compareTreeInfoEntries(const void *, const void *);
 static int token_value_position   = TOKEN_VALUE_POSITION_DEFAULT;
 static int token_comment_position = TOKEN_COMMENT_POSITION_DEFAULT;
 
+static SetupFileHash *artworkinfo_hash = NULL;
+
 
 /* ------------------------------------------------------------------------- */
 /* file functions                                                            */
@@ -1704,6 +1706,27 @@ static void *loadSetupFileData(char *filename, boolean use_hash)
   return setup_file_data;
 }
 
+void saveSetupFileHash(SetupFileHash *hash, char *filename)
+{
+  FILE *file;
+
+  if (!(file = fopen(filename, MODE_WRITE)))
+  {
+    Error(ERR_WARN, "cannot write configuration file '%s'", filename);
+
+    return;
+  }
+
+  BEGIN_HASH_ITERATION(hash, itr)
+  {
+    fprintf(file, "%s\n", getFormattedSetupEntry(HASH_ITERATION_TOKEN(itr),
+                                                HASH_ITERATION_VALUE(itr)));
+  }
+  END_HASH_ITERATION(hash, itr)
+
+  fclose(file);
+}
+
 SetupFileList *loadSetupFileList(char *filename)
 {
   return (SetupFileList *)loadSetupFileData(filename, FALSE);
@@ -1787,6 +1810,24 @@ static struct TokenInfo levelinfo_tokens[] =
   { TYPE_BOOLEAN,      &ldi.skip_levels,       "skip_levels"           }
 };
 
+static struct TokenInfo artworkinfo_tokens[] =
+{
+  /* artwork directory info */
+  { TYPE_STRING,       &ldi.identifier,        "identifier"            },
+  { TYPE_STRING,       &ldi.subdir,            "subdir"                },
+  { TYPE_STRING,       &ldi.name,              "name"                  },
+  { TYPE_STRING,       &ldi.name_sorting,      "name_sorting"          },
+  { TYPE_STRING,       &ldi.author,            "author"                },
+  { TYPE_INTEGER,      &ldi.sort_priority,     "sort_priority"         },
+  { TYPE_STRING,       &ldi.basepath,          "basepath"              },
+  { TYPE_STRING,       &ldi.fullpath,          "fullpath"              },
+  { TYPE_BOOLEAN,      &ldi.in_user_dir,       "in_user_dir"           },
+  { TYPE_INTEGER,      &ldi.color,             "color"                 },
+  { TYPE_STRING,       &ldi.class_desc,        "class_desc"            },
+
+  { -1,                        NULL,                   NULL                    },
+};
+
 static void setTreeInfoToDefaults(TreeInfo *ti, int type)
 {
   ti->type = type;
@@ -2059,6 +2100,94 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
   pushTreeInfo(&node_parent->node_group, ti_new);
 }
 
+
+/* -------------------------------------------------------------------------- */
+/* functions for handling custom artwork info cache                           */
+/* -------------------------------------------------------------------------- */
+
+#define ARTWORKINFO_CACHE_FILENAME     "cache.conf"
+
+static void LoadArtworkInfoCache()
+{
+  if (artworkinfo_hash == NULL)
+  {
+    char *filename = getPath2(getSetupDir(), ARTWORKINFO_CACHE_FILENAME);
+
+    /* try to load artwork info hash from already existing cache file */
+    artworkinfo_hash = loadSetupFileHash(filename);
+
+    /* if no artwork info cache file was found, start with empty hash */
+    if (artworkinfo_hash == NULL)
+      artworkinfo_hash = newSetupFileHash();
+
+    free(filename);
+  }
+}
+
+static void SaveArtworkInfoCache()
+{
+  char *filename = getPath2(getSetupDir(), ARTWORKINFO_CACHE_FILENAME);
+
+  saveSetupFileHash(artworkinfo_hash, filename);
+
+  free(filename);
+}
+
+static TreeInfo *getArtworkInfoFromCache(char *identifier, int type)
+{
+  char *type_string = ARTWORK_DIRECTORY(type);
+  char *token_prefix = getStringCat2WithSeparator(type_string, identifier, ".");
+  char *cache_entry = getHashEntry(artworkinfo_hash, token_prefix);
+  boolean cached = (cache_entry != NULL && strEqual(cache_entry, "true"));
+  TreeInfo *artwork_new = NULL;
+
+  if (cached)
+  {
+    int i;
+
+    printf("::: LOADING existing hash entry for '%s' ...\n", identifier);
+
+    artwork_new = newTreeInfo();
+    setTreeInfoToDefaults(artwork_new, type);
+
+    /* set all structure fields according to the token/value pairs */
+    ldi = *artwork_new;
+    for (i = 0; artworkinfo_tokens[i].type != -1; i++)
+    {
+      char *token = getStringCat2WithSeparator(token_prefix,
+                                              artworkinfo_tokens[i].text, ".");
+      char *value = getHashEntry(artworkinfo_hash, token);
+
+      printf("::: - setting '%s' => '%s'\n", token, value);
+
+      setSetupInfo(artworkinfo_tokens, i, value);
+
+      /* check if cache entry for this item is invalid or incomplete */
+      if (value == NULL)
+      {
+       printf("::: - WARNING: cache entry '%s' invalid\n", token);
+
+       cached = FALSE;
+      }
+
+      checked_free(token);
+    }
+    *artwork_new = ldi;
+
+    if (!cached)
+      freeTreeInfo(artwork_new);
+  }
+
+  free(token_prefix);
+
+  return artwork_new;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* functions for loading level info and custom artwork info                   */
+/* -------------------------------------------------------------------------- */
+
 /* forward declaration for recursive call by "LoadLevelInfoFromLevelDir()" */
 static void LoadLevelInfoFromLevelDir(TreeInfo **, TreeInfo *, char *);
 
@@ -2531,6 +2660,8 @@ static TreeInfo *getDummyArtworkInfo(int type)
 
 void LoadArtworkInfo()
 {
+  LoadArtworkInfoCache();
+
   DrawInitText("Looking for custom artwork:", 120, FC_GREEN);
 
   LoadArtworkInfoFromArtworkDir(&artwork.gfx_first, NULL,
@@ -2620,11 +2751,26 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
       TreeInfo *topnode_last = *artwork_node;
       char *path = getPath2(getLevelDirFromTreeInfo(level_node),
                            ARTWORK_DIRECTORY((*artwork_node)->type));
+      TreeInfo *artwork_new = getArtworkInfoFromCache(level_node->subdir,
+                                                     (*artwork_node)->type);
+      boolean cached = FALSE;
 
-      LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path,
-                                   (*artwork_node)->type);
+      if (artwork_new != NULL)
+      {
+       pushTreeInfo(artwork_node, artwork_new);
+       cached = TRUE;
+      }
+      else
+      {
+       LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path,
+                                     (*artwork_node)->type);
+      }
 
+#if 1
+      if (!cached && topnode_last != *artwork_node)
+#else
       if (topnode_last != *artwork_node)
+#endif
       {
        free((*artwork_node)->identifier);
        free((*artwork_node)->name);
@@ -2636,6 +2782,41 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
 
        (*artwork_node)->sort_priority = level_node->sort_priority;
        (*artwork_node)->color = LEVELCOLOR((*artwork_node));
+
+#if 1
+       {
+         char *identifier = level_node->subdir;
+         char *type_string = ARTWORK_DIRECTORY((*artwork_node)->type);
+         char *type_identifier =
+           getStringCat2WithSeparator(type_string, identifier, ".");
+         int i;
+
+         printf("::: adding hash entry for set '%s' ...\n", type_identifier);
+
+         setHashEntry(artworkinfo_hash, type_identifier, "true");
+
+         ldi = **artwork_node;
+         for (i = 0; artworkinfo_tokens[i].type != -1; i++)
+         {
+           char *token = getStringCat2WithSeparator(type_identifier,
+                                                    artworkinfo_tokens[i].text,
+                                                    ".");
+           char *value = getSetupValue(artworkinfo_tokens[i].type,
+                                       artworkinfo_tokens[i].value);
+           if (value != NULL)
+           {
+             setHashEntry(artworkinfo_hash, token, value);
+
+             printf("::: - setting '%s' => '%s'\n\n",
+                    token, value);
+           }
+
+           checked_free(token);
+         }
+
+         free(type_identifier);
+       }
+#endif
       }
 
       free(path);
@@ -2656,6 +2837,8 @@ void LoadLevelArtworkInfo()
   LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first_all);
   LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first_all);
 
+  SaveArtworkInfoCache();
+
   /* needed for reloading level artwork not known at ealier stage */
 
   if (!strEqual(artwork.gfx_current_identifier, setup.graphics_set))
@@ -2795,6 +2978,9 @@ char *getSetupValue(int type, void *value)
       break;
 
     case TYPE_STRING:
+      if (*(char **)value == NULL)
+       return NULL;
+
       strcpy(value_string, *(char **)value);
       break;