rnd-20020803-1-src
[rocksndiamonds.git] / src / libgame / setup.c
index 57ba732a18e2dcdeecbd253e9b46540add7ed35c..2567ebb1de35e0e874557384db81d37eeefa04e4 100644 (file)
@@ -11,8 +11,9 @@
 * setup.c                                                  *
 ***********************************************************/
 
-#include <dirent.h>
+#include <sys/types.h>
 #include <sys/stat.h>
+#include <dirent.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -84,6 +85,27 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
 
 #define MAX_COOKIE_LEN                 256
 
+#define ARTWORKINFO_FILENAME(type)     ((type) == TREE_TYPE_GRAPHICS_DIR ? \
+                                        GRAPHICSINFO_FILENAME :            \
+                                        (type) == TREE_TYPE_SOUNDS_DIR ?   \
+                                        SOUNDSINFO_FILENAME :              \
+                                        (type) == TREE_TYPE_MUSIC_DIR ?    \
+                                        MUSICINFO_FILENAME : "")
+
+#define ARTWORK_DIRECTORY(type)                ((type) == TREE_TYPE_GRAPHICS_DIR ? \
+                                        GRAPHICS_DIRECTORY :               \
+                                        (type) == TREE_TYPE_SOUNDS_DIR ?   \
+                                        SOUNDS_DIRECTORY :                 \
+                                        (type) == TREE_TYPE_MUSIC_DIR ?    \
+                                        MUSIC_DIRECTORY : "")
+
+#define OPTIONS_ARTWORK_DIRECTORY(type)        ((type) == TREE_TYPE_GRAPHICS_DIR ? \
+                                        options.graphics_directory :       \
+                                        (type) == TREE_TYPE_SOUNDS_DIR ?   \
+                                        options.sounds_directory :         \
+                                        (type) == TREE_TYPE_MUSIC_DIR ?    \
+                                        options.music_directory : "")
+
 
 /* ------------------------------------------------------------------------- */
 /* file functions                                                            */
@@ -167,23 +189,27 @@ static char *getLevelSetupDir(char *level_subdir)
   return levelsetup_dir;
 }
 
-static char *getCurrentLevelDir()
+static char *getLevelDirFromTreeInfo(TreeInfo *node)
 {
   static char *level_dir = NULL;
 
+  if (node == NULL)
+    return options.level_directory;
+
   if (level_dir)
     free(level_dir);
 
-  if (leveldir_current == NULL)
-    return options.level_directory;
-
-  level_dir = getPath2((leveldir_current->user_defined ?
-                       getUserLevelDir(NULL) : options.level_directory),
-                      leveldir_current->fullpath);
+  level_dir = getPath2((node->user_defined ? getUserLevelDir(NULL) :
+                       options.level_directory), node->fullpath);
 
   return level_dir;
 }
 
+static char *getCurrentLevelDir()
+{
+  return getLevelDirFromTreeInfo(leveldir_current);
+}
+
 static char *getDefaultGraphicsDir(char *graphics_subdir)
 {
   static char *graphics_dir = NULL;
@@ -360,32 +386,30 @@ char *getCustomImageFilename(char *basename)
 
   basename = getCorrectedImageBasename(basename);
 
-  /* 1st try: look for special artwork in current level series directory */
-  filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
-  if (fileExists(filename))
-    return filename;
-
-  /* 2nd try: look for special artwork in private artwork directory */
-  filename = getPath2(getUserGraphicsDir(), basename);
-  if (fileExists(filename))
-    return filename;
+  if (!setup.override_level_graphics)
+  {
+    /* 1st try: look for special artwork in current level series directory */
+    filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
+    if (fileExists(filename))
+      return filename;
+  }
 
-  /* 3rd try: look for special artwork in configured artwork directory */
+  /* 2nd try: look for special artwork in configured artwork directory */
   filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename);
   if (fileExists(filename))
     return filename;
 
-  /* 4th try: look for default artwork in new default artwork directory */
+  /* 3rd try: look for default artwork in new default artwork directory */
   filename = getPath2(getDefaultGraphicsDir(GRAPHICS_SUBDIR), basename);
   if (fileExists(filename))
     return filename;
 
-  /* 5th try: look for default artwork in old default artwork directory */
+  /* 4th try: look for default artwork in old default artwork directory */
   filename = getPath2(options.graphics_directory, basename);
   if (fileExists(filename))
     return filename;
 
-  return NULL;                                 /* cannot find image file */
+  return NULL;         /* cannot find specified artwork file anywhere */
 }
 
 char *getCustomSoundFilename(char *basename)
@@ -395,36 +419,30 @@ char *getCustomSoundFilename(char *basename)
   if (filename != NULL)
     free(filename);
 
-#if 0
-  /* 1st try: look for special artwork in current level series directory */
-  filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename);
-  if (fileExists(filename))
-    return filename;
-#endif
-
-#if 0
-  /* 2nd try: look for special artwork in private artwork directory */
-  filename = getPath2(getUserSoundsDir(), basename);
-  if (fileExists(filename))
-    return filename;
-#endif
+  if (!setup.override_level_sounds)
+  {
+    /* 1st try: look for special artwork in current level series directory */
+    filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename);
+    if (fileExists(filename))
+      return filename;
+  }
 
-  /* 3rd try: look for special artwork in configured artwork directory */
+  /* 2nd try: look for special artwork in configured artwork directory */
   filename = getPath2(getSetupArtworkDir(artwork.snd_current), basename);
   if (fileExists(filename))
     return filename;
 
-  /* 4th try: look for default artwork in new default artwork directory */
+  /* 3rd try: look for default artwork in new default artwork directory */
   filename = getPath2(getDefaultSoundsDir(SOUNDS_SUBDIR), basename);
   if (fileExists(filename))
     return filename;
 
-  /* 5th try: look for default artwork in old default artwork directory */
+  /* 4th try: look for default artwork in old default artwork directory */
   filename = getPath2(options.sounds_directory, basename);
   if (fileExists(filename))
     return filename;
 
-  return NULL;                                 /* cannot find image file */
+  return NULL;         /* cannot find specified artwork file anywhere */
 }
 
 char *getCustomSoundConfigFilename()
@@ -439,32 +457,30 @@ char *getCustomMusicDirectory(void)
   if (directory != NULL)
     free(directory);
 
-  /* 1st try: look for special artwork in current level series directory */
-  directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
-  if (fileExists(directory))
-    return directory;
-
-  /* 2nd try: look for special artwork in private artwork directory */
-  directory = getStringCopy(getUserMusicDir());
-  if (fileExists(directory))
-    return directory;
+  if (!setup.override_level_music)
+  {
+    /* 1st try: look for special artwork in current level series directory */
+    directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
+    if (fileExists(directory))
+      return directory;
+  }
 
-  /* 3rd try: look for special artwork in configured artwork directory */
+  /* 2nd try: look for special artwork in configured artwork directory */
   directory = getStringCopy(getSetupArtworkDir(artwork.mus_current));
   if (fileExists(directory))
     return directory;
 
-  /* 4th try: look for default artwork in new default artwork directory */
+  /* 3rd try: look for default artwork in new default artwork directory */
   directory = getStringCopy(getDefaultMusicDir(MUSIC_SUBDIR));
   if (fileExists(directory))
     return directory;
 
-  /* 5th try: look for default artwork in old default artwork directory */
+  /* 4th try: look for default artwork in old default artwork directory */
   directory = getStringCopy(options.music_directory);
   if (fileExists(directory))
     return directory;
 
-  return NULL;                                 /* cannot find image file */
+  return NULL;         /* cannot find specified artwork file anywhere */
 }
 
 void InitTapeDirectory(char *level_subdir)
@@ -501,50 +517,6 @@ void InitLevelSetupDirectory(char *level_subdir)
   createDirectory(getLevelSetupDir(level_subdir), "level setup",PERMS_PRIVATE);
 }
 
-void ReadChunk_VERS(FILE *file, int *file_version, int *game_version)
-{
-  int file_version_major, file_version_minor, file_version_patch;
-  int game_version_major, game_version_minor, game_version_patch;
-
-  file_version_major = fgetc(file);
-  file_version_minor = fgetc(file);
-  file_version_patch = fgetc(file);
-  fgetc(file);         /* not used */
-
-  game_version_major = fgetc(file);
-  game_version_minor = fgetc(file);
-  game_version_patch = fgetc(file);
-  fgetc(file);         /* not used */
-
-  *file_version = VERSION_IDENT(file_version_major,
-                               file_version_minor,
-                               file_version_patch);
-
-  *game_version = VERSION_IDENT(game_version_major,
-                               game_version_minor,
-                               game_version_patch);
-}
-
-void WriteChunk_VERS(FILE *file, int file_version, int game_version)
-{
-  int file_version_major = VERSION_MAJOR(file_version);
-  int file_version_minor = VERSION_MINOR(file_version);
-  int file_version_patch = VERSION_PATCH(file_version);
-  int game_version_major = VERSION_MAJOR(game_version);
-  int game_version_minor = VERSION_MINOR(game_version);
-  int game_version_patch = VERSION_PATCH(game_version);
-
-  fputc(file_version_major, file);
-  fputc(file_version_minor, file);
-  fputc(file_version_patch, file);
-  fputc(0, file);      /* not used */
-
-  fputc(game_version_major, file);
-  fputc(game_version_minor, file);
-  fputc(game_version_patch, file);
-  fputc(0, file);      /* not used */
-}
-
 
 /* ------------------------------------------------------------------------- */
 /* some functions to handle lists of level directories                       */
@@ -582,13 +554,9 @@ boolean validLevelSeries(TreeInfo *node)
 TreeInfo *getFirstValidTreeInfoEntry(TreeInfo *node)
 {
   if (node == NULL)
-  {
-    if (node->node_top)                /* start with first tree entry */
-      return getFirstValidTreeInfoEntry(*node->node_top);
-    else
-      return NULL;
-  }
-  else if (node->node_group)   /* enter level group (step down into tree) */
+    return NULL;
+
+  if (node->node_group)                /* enter level group (step down into tree) */
     return getFirstValidTreeInfoEntry(node->node_group);
   else if (node->parent_link)  /* skip start entry of level group */
   {
@@ -671,6 +639,12 @@ TreeInfo *getTreeInfoFromFilenameExt(TreeInfo *node, char *filename)
     {
       if (strcmp(filename, node->filename) == 0)
        return node;
+
+      /* special case when looking for level series artwork:
+        node->name_short contains level series filename */
+      if (strcmp(node->filename, ".") == 0 &&
+         strcmp(filename, node->name_short) == 0)
+       return node;
     }
 
     node = node->next;
@@ -1427,6 +1401,8 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
   else
     setTreeInfoToDefaults(leveldir_new, TREE_TYPE_LEVEL_DIR);
 
+  leveldir_new->filename = getStringCopy(directory_name);
+
   checkSetupFileListIdentifier(setup_file_list, getCookie("LEVELINFO"));
 
   /* set all structure fields according to the token/value pairs */
@@ -1450,8 +1426,6 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
   if (leveldir_new->name_sorting == NULL)
     leveldir_new->name_sorting = getStringCopy(leveldir_new->name);
 
-  leveldir_new->filename = getStringCopy(directory_name);
-
   if (node_parent == NULL)             /* top level group */
   {
     leveldir_new->basepath = level_directory;
@@ -1590,14 +1564,9 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
                                              char *directory_name, int type)
 {
   char *directory_path = getPath2(base_directory, directory_name);
-  char *filename =
-    getPath2(directory_path,
-            (type == TREE_TYPE_GRAPHICS_DIR ? GRAPHICSINFO_FILENAME :
-             type == TREE_TYPE_SOUNDS_DIR ? SOUNDSINFO_FILENAME :
-             type == TREE_TYPE_MUSIC_DIR ? MUSICINFO_FILENAME : ""));
+  char *filename = getPath2(directory_path, ARTWORKINFO_FILENAME(type));
   struct SetupFileList *setup_file_list = NULL;
   TreeInfo *artwork_new = NULL;
-  char *check_dir = NULL;
   int i;
 
   if (access(filename, F_OK) == 0)             /* file exists */
@@ -1615,9 +1584,7 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
       {
        char *entry_name = dir_entry->d_name;
 
-       if ((type == TREE_TYPE_GRAPHICS_DIR && FileIsGraphic(entry_name)) ||
-           (type == TREE_TYPE_SOUNDS_DIR && FileIsSound(entry_name)) ||
-           (type == TREE_TYPE_MUSIC_DIR && FileIsMusic(entry_name)))
+       if (FileIsArtworkType(entry_name, type))
        {
          valid_file_found = TRUE;
          break;
@@ -1667,7 +1634,9 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
       artwork_new->name = getStringCopy(artwork_new->filename);
     }
 
+#if 0
     DrawInitText(artwork_new->name, 150, FC_YELLOW);
+#endif
 
     if (artwork_new->name_short == NULL)
       artwork_new->name_short = getStringCopy(artwork_new->name);
@@ -1687,11 +1656,8 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
     artwork_new->fullpath = getPath2(node_parent->fullpath, directory_name);
   }
 
-  check_dir = (type == TREE_TYPE_GRAPHICS_DIR ? options.graphics_directory :
-              type == TREE_TYPE_SOUNDS_DIR ? options.sounds_directory :
-              type == TREE_TYPE_MUSIC_DIR ? options.music_directory : "");
   artwork_new->user_defined =
-    (artwork_new->basepath == check_dir ? FALSE : TRUE);
+    (artwork_new->basepath == OPTIONS_ARTWORK_DIRECTORY(type) ? FALSE : TRUE);
 
   /* (may use ".sort_priority" from "setup_file_list" above) */
   artwork_new->color = LEVELCOLOR(artwork_new);
@@ -1725,6 +1691,8 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
     artwork_new->name_sorting = getStringCopy(artwork_new->name);
   }
 
+  DrawInitText(artwork_new->name, 150, FC_YELLOW);
+
   pushTreeInfo(node_first, artwork_new);
 
   freeSetupFileList(setup_file_list);
@@ -1745,12 +1713,7 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first,
 
   if ((dir = opendir(base_directory)) == NULL)
   {
-    if ((type == TREE_TYPE_GRAPHICS_DIR &&
-        base_directory == options.graphics_directory) ||
-       (type == TREE_TYPE_SOUNDS_DIR &&
-        base_directory == options.sounds_directory) ||
-       (type == TREE_TYPE_MUSIC_DIR &&
-        base_directory == options.music_directory))
+    if (base_directory == OPTIONS_ARTWORK_DIRECTORY(type))
       Error(ERR_WARN, "cannot read directory '%s'", base_directory);
     return;
   }
@@ -1796,6 +1759,27 @@ static void LoadArtworkInfoFromArtworkDir(TreeInfo **node_first,
          base_directory);
 }
 
+static TreeInfo *getDummyArtworkInfo(int type)
+{
+  /* this is only needed when there is completely no artwork available */
+  TreeInfo *artwork_new = newTreeInfo();
+
+  setTreeInfoToDefaults(artwork_new, type);
+
+  artwork_new->filename = getStringCopy(NOT_AVAILABLE);
+  artwork_new->fullpath = getStringCopy(NOT_AVAILABLE);
+  artwork_new->basepath = getStringCopy(NOT_AVAILABLE);
+
+  if (artwork_new->name != NULL)
+    free(artwork_new->name);
+
+  artwork_new->name         = getStringCopy(NOT_AVAILABLE);
+  artwork_new->name_short   = getStringCopy(NOT_AVAILABLE);
+  artwork_new->name_sorting = getStringCopy(NOT_AVAILABLE);
+
+  return artwork_new;
+}
+
 void LoadArtworkInfo()
 {
   DrawInitText("Looking for custom artwork:", 120, FC_GREEN);
@@ -1821,6 +1805,13 @@ void LoadArtworkInfo()
                                getUserMusicDir(),
                                TREE_TYPE_MUSIC_DIR);
 
+  if (artwork.gfx_first == NULL)
+    artwork.gfx_first = getDummyArtworkInfo(TREE_TYPE_GRAPHICS_DIR);
+  if (artwork.snd_first == NULL)
+    artwork.snd_first = getDummyArtworkInfo(TREE_TYPE_SOUNDS_DIR);
+  if (artwork.mus_first == NULL)
+    artwork.mus_first = getDummyArtworkInfo(TREE_TYPE_MUSIC_DIR);
+
   /* before sorting, the first entries will be from the user directory */
   artwork.gfx_current =
     getTreeInfoFromFilename(artwork.gfx_first, setup.graphics_set);
@@ -1830,21 +1821,21 @@ void LoadArtworkInfo()
   artwork.snd_current =
     getTreeInfoFromFilename(artwork.snd_first, setup.sounds_set);
   if (artwork.snd_current == NULL)
-  artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
+    artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
 
   artwork.mus_current =
     getTreeInfoFromFilename(artwork.mus_first, setup.music_set);
   if (artwork.mus_current == NULL)
-  artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
+    artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
 
-  artwork.graphics_set_current = artwork.gfx_current->name;
-  artwork.sounds_set_current = artwork.snd_current->name;
-  artwork.music_set_current = artwork.mus_current->name;
+  artwork.graphics_set_current_name = artwork.gfx_current->name;
+  artwork.sounds_set_current_name = artwork.snd_current->name;
+  artwork.music_set_current_name = artwork.mus_current->name;
 
 #if 0
-  printf("graphics set == %s\n\n", artwork.graphics_set_current);
-  printf("sounds set == %s\n\n", artwork.sounds_set_current);
-  printf("music set == %s\n\n", artwork.music_set_current);
+  printf("graphics set == %s\n\n", artwork.graphics_set_current_name);
+  printf("sounds set == %s\n\n", artwork.sounds_set_current_name);
+  printf("music set == %s\n\n", artwork.music_set_current_name);
 #endif
 
   sortTreeInfo(&artwork.gfx_first, compareTreeInfoEntries);
@@ -1858,53 +1849,50 @@ void LoadArtworkInfo()
 #endif
 }
 
-void LoadArtworkInfoFromLevelInfo(TreeInfo *node)
+void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node,
+                                 LevelDirTree *level_node)
 {
-  while (node)
+  /* recursively check all level directories for artwork sub-directories */
+
+  while (level_node)
   {
-    char *path = getPath3((node->user_defined ?
-                          getUserLevelDir(NULL) : options.level_directory),
-                         node->fullpath, SOUNDS_DIRECTORY);
+    char *path = getPath2(getLevelDirFromTreeInfo(level_node),
+                         ARTWORK_DIRECTORY((*artwork_node)->type));
 
 #if 0
-    if (!node->parent_link)
+    if (!level_node->parent_link)
       printf("CHECKING '%s' ['%s', '%s'] ...\n", path,
-            node->filename, node->name);
+            level_node->filename, level_node->name);
 #endif
 
-    if (!node->parent_link)
+    if (!level_node->parent_link)
     {
-      TreeInfo *topnode_last = artwork.snd_first;
+      TreeInfo *topnode_last = *artwork_node;
 
-      LoadArtworkInfoFromArtworkDir(&artwork.snd_first, NULL,
-                                   path,
-                                   TREE_TYPE_SOUNDS_DIR);
+      LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path,
+                                   (*artwork_node)->type);
 
-      if (topnode_last != artwork.snd_first)
+      if (topnode_last != *artwork_node)
       {
-#if 0
-       printf("NEW NODE: '%s'\n", artwork.snd_first->name);
-#endif
-
-       free(artwork.snd_first->name);
-       free(artwork.snd_first->name_sorting);
-       free(artwork.snd_first->name_short);
+       free((*artwork_node)->name);
+       free((*artwork_node)->name_sorting);
+       free((*artwork_node)->name_short);
 
-       artwork.snd_first->name         = getStringCopy(node->name);
-       artwork.snd_first->name_sorting = getStringCopy(node->name);
-       artwork.snd_first->name_short   = getStringCopy(node->filename);
+       (*artwork_node)->name         = getStringCopy(level_node->name);
+       (*artwork_node)->name_sorting = getStringCopy(level_node->name);
+       (*artwork_node)->name_short   = getStringCopy(level_node->filename);
 
-       artwork.snd_first->sort_priority = node->sort_priority;
-       artwork.snd_first->color = LEVELCOLOR(artwork.snd_first);
+       (*artwork_node)->sort_priority = level_node->sort_priority;
+       (*artwork_node)->color = LEVELCOLOR((*artwork_node));
       }
     }
 
     free(path);
 
-    if (node->node_group != NULL)
-      LoadArtworkInfoFromLevelInfo(node->node_group);
+    if (level_node->node_group != NULL)
+      LoadArtworkInfoFromLevelInfo(artwork_node, level_node->node_group);
 
-    node = node->next;
+    level_node = level_node->next;
   }
 }
 
@@ -1912,12 +1900,18 @@ void LoadLevelArtworkInfo()
 {
   DrawInitText("Looking for custom level artwork:", 120, FC_GREEN);
 
-  LoadArtworkInfoFromLevelInfo(leveldir_first);
+  LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first);
+  LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first);
+  LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first);
 
+  sortTreeInfo(&artwork.gfx_first, compareTreeInfoEntries);
   sortTreeInfo(&artwork.snd_first, compareTreeInfoEntries);
+  sortTreeInfo(&artwork.mus_first, compareTreeInfoEntries);
 
-#if 1
+#if 0
+  dumpTreeInfo(artwork.gfx_first, 0);
   dumpTreeInfo(artwork.snd_first, 0);
+  dumpTreeInfo(artwork.mus_first, 0);
 #endif
 }
 
@@ -1939,8 +1933,8 @@ static void SaveUserLevelInfo()
   /* always start with reliable default values */
   setTreeInfoToDefaults(&ldi, TREE_TYPE_LEVEL_DIR);
 
-  ldi.name = getLoginName();
-  ldi.author = getRealName();
+  ldi.name = getStringCopy(getLoginName());
+  ldi.author = getStringCopy(getRealName());
   ldi.levels = 100;
   ldi.first_level = 1;
   ldi.sort_priority = LEVELCLASS_USER_START;
@@ -1965,6 +1959,9 @@ char *getSetupValue(int type, void *value)
 {
   static char value_string[MAX_LINE_LEN];
 
+  if (value == NULL)
+    return NULL;
+
   switch (type)
   {
     case TYPE_BOOLEAN: