rnd-20070113-1-src
[rocksndiamonds.git] / src / libgame / setup.c
index 9a65d0f1252ba861c81c66bd2b186831605c1cb4..496b867b42440951bdc8144d4bcef043f1ef99df 100644 (file)
@@ -86,14 +86,17 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
 
 #define MAX_COOKIE_LEN                         256
 
+
 static void setTreeInfoToDefaults(TreeInfo *, int);
+static TreeInfo *getTreeInfoCopy(TreeInfo *ti);
 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_old = NULL;
-static SetupFileHash *artworkinfo_hash_new = NULL;
+static SetupFileHash *artworkinfo_cache_old = NULL;
+static SetupFileHash *artworkinfo_cache_new = NULL;
+static boolean use_artworkinfo_cache = TRUE;
 
 
 /* ------------------------------------------------------------------------- */
@@ -158,6 +161,16 @@ static char *getLevelSetupDir(char *level_subdir)
   return levelsetup_dir;
 }
 
+static char *getCacheDir()
+{
+  static char *cache_dir = NULL;
+
+  if (cache_dir == NULL)
+    cache_dir = getPath2(getUserGameDataDir(), CACHE_DIRECTORY);
+
+  return cache_dir;
+}
+
 static char *getLevelDirFromTreeInfo(TreeInfo *node)
 {
   static char *level_dir = NULL;
@@ -485,6 +498,35 @@ char *getLevelSetInfoFilename()
   return NULL;
 }
 
+char *getLevelSetMessageFilename()
+{
+  static char *filename = NULL;
+  char *basenames[] =
+  {
+    "MESSAGE",
+    "MESSAGE.TXT",
+    "MESSAGE.txt",
+    "Message",
+    "Message.txt",
+    "message",
+    "message.txt",
+
+    NULL
+  };
+  int i;
+
+  for (i = 0; basenames[i] != NULL; i++)
+  {
+    checked_free(filename);
+    filename = getPath2(getCurrentLevelDir(), basenames[i]);
+
+    if (fileExists(filename))
+      return filename;
+  }
+
+  return NULL;
+}
+
 static char *getCorrectedArtworkBasename(char *basename)
 {
   char *basename_corrected = basename;
@@ -797,7 +839,7 @@ void InitUserLevelDirectory(char *level_subdir)
   {
     createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE);
     createDirectory(getUserLevelDir(NULL), "main user level", PERMS_PRIVATE);
-    createDirectory(getUserLevelDir(level_subdir), "user level",PERMS_PRIVATE);
+    createDirectory(getUserLevelDir(level_subdir), "user level", PERMS_PRIVATE);
 
     SaveUserLevelInfo();
   }
@@ -807,7 +849,13 @@ void InitLevelSetupDirectory(char *level_subdir)
 {
   createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE);
   createDirectory(getLevelSetupDir(NULL), "main level setup", PERMS_PRIVATE);
-  createDirectory(getLevelSetupDir(level_subdir), "level setup",PERMS_PRIVATE);
+  createDirectory(getLevelSetupDir(level_subdir), "level setup", PERMS_PRIVATE);
+}
+
+void InitCacheDirectory()
+{
+  createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE);
+  createDirectory(getCacheDir(), "cache data", PERMS_PRIVATE);
 }
 
 
@@ -962,9 +1010,13 @@ TreeInfo *cloneTreeNode(TreeInfo **node_top, TreeInfo *node_parent,
     return cloneTreeNode(node_top, node_parent, node->next,
                         skip_sets_without_levels);
 
+#if 1
+  node_new = getTreeInfoCopy(node);            /* copy complete node */
+#else
   node_new = newTreeInfo();
 
   *node_new = *node;                           /* copy complete node */
+#endif
 
   node_new->node_top = node_top;               /* correct top node link */
   node_new->node_parent = node_parent;         /* correct parent node link */
@@ -1970,6 +2022,68 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent)
   }
 }
 
+static TreeInfo *getTreeInfoCopy(TreeInfo *ti)
+{
+  TreeInfo *ti_copy = newTreeInfo();
+
+  /* copy all values from the original structure */
+
+  ti_copy->type                        = ti->type;
+
+  ti_copy->node_top            = ti->node_top;
+  ti_copy->node_parent         = ti->node_parent;
+  ti_copy->node_group          = ti->node_group;
+  ti_copy->next                        = ti->next;
+
+  ti_copy->cl_first            = ti->cl_first;
+  ti_copy->cl_cursor           = ti->cl_cursor;
+
+  ti_copy->subdir              = getStringCopy(ti->subdir);
+  ti_copy->fullpath            = getStringCopy(ti->fullpath);
+  ti_copy->basepath            = getStringCopy(ti->basepath);
+  ti_copy->identifier          = getStringCopy(ti->identifier);
+  ti_copy->name                        = getStringCopy(ti->name);
+  ti_copy->name_sorting                = getStringCopy(ti->name_sorting);
+  ti_copy->author              = getStringCopy(ti->author);
+  ti_copy->imported_from       = getStringCopy(ti->imported_from);
+  ti_copy->imported_by         = getStringCopy(ti->imported_by);
+
+  ti_copy->graphics_set_ecs    = getStringCopy(ti->graphics_set_ecs);
+  ti_copy->graphics_set_aga    = getStringCopy(ti->graphics_set_aga);
+  ti_copy->graphics_set                = getStringCopy(ti->graphics_set);
+  ti_copy->sounds_set          = getStringCopy(ti->sounds_set);
+  ti_copy->music_set           = getStringCopy(ti->music_set);
+  ti_copy->graphics_path       = getStringCopy(ti->graphics_path);
+  ti_copy->sounds_path         = getStringCopy(ti->sounds_path);
+  ti_copy->music_path          = getStringCopy(ti->music_path);
+
+  ti_copy->level_filename      = getStringCopy(ti->level_filename);
+  ti_copy->level_filetype      = getStringCopy(ti->level_filetype);
+
+  ti_copy->levels              = ti->levels;
+  ti_copy->first_level         = ti->first_level;
+  ti_copy->last_level          = ti->last_level;
+  ti_copy->sort_priority       = ti->sort_priority;
+
+  ti_copy->latest_engine       = ti->latest_engine;
+
+  ti_copy->level_group         = ti->level_group;
+  ti_copy->parent_link         = ti->parent_link;
+  ti_copy->in_user_dir         = ti->in_user_dir;
+  ti_copy->user_defined                = ti->user_defined;
+  ti_copy->readonly            = ti->readonly;
+  ti_copy->handicap            = ti->handicap;
+  ti_copy->skip_levels         = ti->skip_levels;
+
+  ti_copy->color               = ti->color;
+  ti_copy->class_desc          = getStringCopy(ti->class_desc);
+  ti_copy->handicap_level      = ti->handicap_level;
+
+  ti_copy->infotext            = getStringCopy(ti->infotext);
+
+  return ti_copy;
+}
+
 static void freeTreeInfo(TreeInfo *ti)
 {
   if (ti == NULL)
@@ -2117,36 +2231,38 @@ static void createParentTreeInfoNode(TreeInfo *node_parent)
 
 
 /* -------------------------------------------------------------------------- */
-/* functions for handling custom artwork info cache                           */
+/* functions for handling level and custom artwork info cache                 */
 /* -------------------------------------------------------------------------- */
 
-#define ARTWORKINFO_CACHE_FILENAME     "cache.conf"
-
 static void LoadArtworkInfoCache()
 {
-  if (artworkinfo_hash_old == NULL)
+  InitCacheDirectory();
+
+  if (artworkinfo_cache_old == NULL)
   {
-    char *filename = getPath2(getSetupDir(), ARTWORKINFO_CACHE_FILENAME);
+    char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE);
 
     /* try to load artwork info hash from already existing cache file */
-    artworkinfo_hash_old = loadSetupFileHash(filename);
+    artworkinfo_cache_old = loadSetupFileHash(filename);
 
     /* if no artwork info cache file was found, start with empty hash */
-    if (artworkinfo_hash_old == NULL)
-      artworkinfo_hash_old = newSetupFileHash();
+    if (artworkinfo_cache_old == NULL)
+      artworkinfo_cache_old = newSetupFileHash();
 
     free(filename);
   }
 
-  if (artworkinfo_hash_new == NULL)
-    artworkinfo_hash_new = newSetupFileHash();
+  if (artworkinfo_cache_new == NULL)
+    artworkinfo_cache_new = newSetupFileHash();
 }
 
 static void SaveArtworkInfoCache()
 {
-  char *filename = getPath2(getSetupDir(), ARTWORKINFO_CACHE_FILENAME);
+  char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE);
+
+  InitCacheDirectory();
 
-  saveSetupFileHash(artworkinfo_hash_new, filename);
+  saveSetupFileHash(artworkinfo_cache_new, filename);
 
   free(filename);
 }
@@ -2203,22 +2319,17 @@ static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type)
   char *type_string = ARTWORK_DIRECTORY(type);
   char *token_prefix = getCacheTokenPrefix(type_string, identifier);
   char *token_main = getCacheToken(token_prefix, "CACHED");
-  char *cache_entry = getHashEntry(artworkinfo_hash_old, token_main);
+  char *cache_entry = getHashEntry(artworkinfo_cache_old, token_main);
   boolean cached = (cache_entry != NULL && strEqual(cache_entry, "true"));
   TreeInfo *artwork_info = NULL;
 
-#if 0
-  printf("::: '%s' in cache: %d\n", token_main, cached);
-#endif
+  if (!use_artworkinfo_cache)
+    return NULL;
 
   if (cached)
   {
     int i;
 
-#if 0
-    printf("::: LOADING existing hash entry for '%s' ...\n", identifier);
-#endif
-
     artwork_info = newTreeInfo();
     setTreeInfoToDefaults(artwork_info, type);
 
@@ -2227,19 +2338,15 @@ static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type)
     for (i = 0; artworkinfo_tokens[i].type != -1; i++)
     {
       char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text);
-      char *value = getHashEntry(artworkinfo_hash_old, token);
-
-#if 0
-      printf("::: - setting '%s' => '%s'\n", token, value);
-#endif
+      char *value = getHashEntry(artworkinfo_cache_old, token);
 
       setSetupInfo(artworkinfo_tokens, i, value);
 
       /* check if cache entry for this item is invalid or incomplete */
       if (value == NULL)
       {
-#if 0
-       printf("::: - WARNING: cache entry '%s' invalid\n", token);
+#if 1
+       Error(ERR_WARN, "cache entry '%s' invalid", token);
 #endif
 
        cached = FALSE;
@@ -2257,21 +2364,21 @@ static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type)
 
     /* check if corresponding "levelinfo.conf" file has changed */
     token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO");
-    cache_entry = getHashEntry(artworkinfo_hash_old, token_main);
+    cache_entry = getHashEntry(artworkinfo_cache_old, token_main);
 
     if (modifiedFileTimestamp(filename_levelinfo, cache_entry))
       cached = FALSE;
 
     /* check if corresponding "<artworkinfo>.conf" file has changed */
     token_main = getCacheToken(token_prefix, "TIMESTAMP_ARTWORKINFO");
-    cache_entry = getHashEntry(artworkinfo_hash_old, token_main);
+    cache_entry = getHashEntry(artworkinfo_cache_old, token_main);
 
     if (modifiedFileTimestamp(filename_artworkinfo, cache_entry))
       cached = FALSE;
 
 #if 0
     if (!cached)
-      printf("::: '%s': INVALIDATED FROM CACHE\n", identifier);
+      printf("::: '%s': INVALIDATED FROM CACHE BY TIMESTAMP\n", identifier);
 #endif
 
     checked_free(filename_levelinfo);
@@ -2298,11 +2405,7 @@ static void setArtworkInfoCacheEntry(TreeInfo *artwork_info,
   boolean set_cache_timestamps = TRUE;
   int i;
 
-#if 0
-  printf("::: adding '%s' to cache!\n", token_main);
-#endif
-
-  setHashEntry(artworkinfo_hash_new, token_main, "true");
+  setHashEntry(artworkinfo_cache_new, token_main, "true");
 
   if (set_cache_timestamps)
   {
@@ -2314,10 +2417,10 @@ static void setArtworkInfoCacheEntry(TreeInfo *artwork_info,
     char *timestamp_artworkinfo = getFileTimestamp(filename_artworkinfo);
 
     token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO");
-    setHashEntry(artworkinfo_hash_new, token_main, timestamp_levelinfo);
+    setHashEntry(artworkinfo_cache_new, token_main, timestamp_levelinfo);
 
     token_main = getCacheToken(token_prefix, "TIMESTAMP_ARTWORKINFO");
-    setHashEntry(artworkinfo_hash_new, token_main, timestamp_artworkinfo);
+    setHashEntry(artworkinfo_cache_new, token_main, timestamp_artworkinfo);
 
     checked_free(filename_levelinfo);
     checked_free(filename_artworkinfo);
@@ -2332,13 +2435,7 @@ static void setArtworkInfoCacheEntry(TreeInfo *artwork_info,
     char *value = getSetupValue(artworkinfo_tokens[i].type,
                                artworkinfo_tokens[i].value);
     if (value != NULL)
-    {
-      setHashEntry(artworkinfo_hash_new, token, value);
-
-#if 0
-      printf("::: - setting '%s' => '%s'\n\n", token, value);
-#endif
-    }
+      setHashEntry(artworkinfo_cache_new, token, value);
   }
 }
 
@@ -2355,6 +2452,8 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
                                          char *level_directory,
                                          char *directory_name)
 {
+  static unsigned long progress_delay = 0;
+  unsigned long progress_delay_value = 100;    /* (in milliseconds) */
   char *directory_path = getPath2(level_directory, directory_name);
   char *filename = getPath2(directory_path, LEVELINFO_FILENAME);
   SetupFileHash *setup_file_hash;
@@ -2404,8 +2503,6 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
   if (strEqual(leveldir_new->name, ANONYMOUS_NAME))
     setString(&leveldir_new->name, leveldir_new->subdir);
 
-  DrawInitText(leveldir_new->name, 150, FC_YELLOW);
-
   if (leveldir_new->identifier == NULL)
     leveldir_new->identifier = getStringCopy(leveldir_new->subdir);
 
@@ -2456,6 +2553,14 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
     (leveldir_new->user_defined || !leveldir_new->handicap ?
      leveldir_new->last_level : leveldir_new->first_level);
 
+#if 1
+  if (leveldir_new->level_group ||
+      DelayReached(&progress_delay, progress_delay_value))
+    DrawInitText(leveldir_new->name, 150, FC_YELLOW);
+#else
+  DrawInitText(leveldir_new->name, 150, FC_YELLOW);
+#endif
+
 #if 0
   /* !!! don't skip sets without levels (else artwork base sets are missing) */
 #if 1
@@ -2481,7 +2586,7 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
     /* create node to link back to current level directory */
     createParentTreeInfoNode(leveldir_new);
 
-    /* step into sub-directory and look for more level series */
+    /* recursively step into sub-directory and look for more level series */
     LoadLevelInfoFromLevelDir(&leveldir_new->node_group,
                              leveldir_new, directory_path);
   }
@@ -2569,7 +2674,7 @@ void LoadLevelInfo()
 {
   InitUserLevelDirectory(getLoginName());
 
-  DrawInitText("Loading level series:", 120, FC_GREEN);
+  DrawInitText("Loading level series", 120, FC_GREEN);
 
   LoadLevelInfoFromLevelDir(&leveldir_first, NULL, options.level_directory);
   LoadLevelInfoFromLevelDir(&leveldir_first, NULL, getUserLevelDir(NULL));
@@ -2669,10 +2774,6 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
     if (strEqual(artwork_new->name, ANONYMOUS_NAME))
       setString(&artwork_new->name, artwork_new->subdir);
 
-#if 0
-    DrawInitText(artwork_new->name, 150, FC_YELLOW);
-#endif
-
     if (artwork_new->identifier == NULL)
       artwork_new->identifier = getStringCopy(artwork_new->subdir);
 
@@ -2729,7 +2830,9 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
     setString(&artwork_new->name_sorting, artwork_new->name);
   }
 
+#if 0
   DrawInitText(artwork_new->name, 150, FC_YELLOW);
+#endif
 
   pushTreeInfo(node_first, artwork_new);
 
@@ -2821,7 +2924,7 @@ void LoadArtworkInfo()
 {
   LoadArtworkInfoCache();
 
-  DrawInitText("Looking for custom artwork:", 120, FC_GREEN);
+  DrawInitText("Looking for custom artwork", 120, FC_GREEN);
 
   LoadArtworkInfoFromArtworkDir(&artwork.gfx_first, NULL,
                                options.graphics_directory,
@@ -2900,6 +3003,8 @@ void LoadArtworkInfo()
 void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
                                  LevelDirTree *level_node)
 {
+  static unsigned long progress_delay = 0;
+  unsigned long progress_delay_value = 100;    /* (in milliseconds) */
   int type = (*artwork_node)->type;
 
   /* recursively check all level directories for artwork sub-directories */
@@ -2944,6 +3049,12 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
        setArtworkInfoCacheEntry(artwork_new, level_node, type);
     }
 
+#if 1
+    if (level_node->level_group ||
+       DelayReached(&progress_delay, progress_delay_value))
+      DrawInitText(level_node->name, 150, FC_YELLOW);
+#endif
+
     if (level_node->node_group != NULL)
       LoadArtworkInfoFromLevelInfo(artwork_node, level_node->node_group);
 
@@ -2953,7 +3064,7 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
 
 void LoadLevelArtworkInfo()
 {
-  DrawInitText("Looking for custom level artwork:", 120, FC_GREEN);
+  DrawInitText("Looking for custom level artwork", 120, FC_GREEN);
 
   LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first_all);
   LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first_all);