/***********************************************************
* Artsoft Retro-Game Library *
*----------------------------------------------------------*
-* (c) 1994-2002 Artsoft Entertainment *
+* (c) 1994-2006 Artsoft Entertainment *
* Holger Schemel *
* Detmolder Strasse 189 *
* 33604 Bielefeld *
#include <string.h>
#include <unistd.h>
+#include "platform.h"
+
+#if !defined(PLATFORM_WIN32)
+#include <pwd.h>
+#include <sys/param.h>
+#endif
+
#include "setup.h"
#include "joystick.h"
#include "text.h"
#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_cache_old = NULL;
+static SetupFileHash *artworkinfo_cache_new = NULL;
+static boolean use_artworkinfo_cache = TRUE;
+
/* ------------------------------------------------------------------------- */
/* file functions */
/* ------------------------------------------------------------------------- */
-static char *getLevelClassDescription(TreeInfo *ldi)
+static char *getLevelClassDescription(TreeInfo *ti)
{
- int position = ldi->sort_priority / 100;
+ int position = ti->sort_priority / 100;
if (position >= 0 && position < NUM_LEVELCLASS_DESC)
return levelclass_desc[position];
static char *getUserLevelDir(char *level_subdir)
{
static char *userlevel_dir = NULL;
- char *data_dir = getUserDataDir();
+ char *data_dir = getUserGameDataDir();
char *userlevel_subdir = LEVELS_DIRECTORY;
checked_free(userlevel_dir);
static char *getLevelSetupDir(char *level_subdir)
{
static char *levelsetup_dir = NULL;
- char *data_dir = getUserDataDir();
+ char *data_dir = getUserGameDataDir();
char *levelsetup_subdir = LEVELSETUP_DIRECTORY;
checked_free(levelsetup_dir);
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;
static char *getTapeDir(char *level_subdir)
{
static char *tape_dir = NULL;
- char *data_dir = getUserDataDir();
+ char *data_dir = getUserGameDataDir();
char *tape_subdir = TAPES_DIRECTORY;
checked_free(tape_dir);
static char *usergraphics_dir = NULL;
if (usergraphics_dir == NULL)
- usergraphics_dir = getPath2(getUserDataDir(), GRAPHICS_DIRECTORY);
+ usergraphics_dir = getPath2(getUserGameDataDir(), GRAPHICS_DIRECTORY);
return usergraphics_dir;
}
static char *usersounds_dir = NULL;
if (usersounds_dir == NULL)
- usersounds_dir = getPath2(getUserDataDir(), SOUNDS_DIRECTORY);
+ usersounds_dir = getPath2(getUserGameDataDir(), SOUNDS_DIRECTORY);
return usersounds_dir;
}
static char *usermusic_dir = NULL;
if (usermusic_dir == NULL)
- usermusic_dir = getPath2(getUserDataDir(), MUSIC_DIRECTORY);
+ usermusic_dir = getPath2(getUserGameDataDir(), MUSIC_DIRECTORY);
return usermusic_dir;
}
return NULL;
}
+char *getLevelSetTitleMessageFilename(int nr, boolean initial)
+{
+ static char *filename = NULL;
+ char basename[32];
+
+ sprintf(basename, "%s_%d.txt",
+ (initial ? "titlemessage_initial" : "titlemessage"), nr + 1);
+
+ checked_free(filename);
+ filename = getPath2(getCurrentLevelDir(), basename);
+
+ if (fileExists(filename))
+ return filename;
+
+ return NULL;
+}
+
static char *getCorrectedArtworkBasename(char *basename)
{
char *basename_corrected = basename;
if (!setup.override_level_graphics)
{
-#if 1
- /* try special ECS graphics */
- filename = getPath3(getCurrentLevelDir(), GRAPHICS_ECS_DIRECTORY, basename);
- if (fileExists(filename) && !setup.prefer_aga_graphics)
- return filename;
-
- free(filename);
-
- /* try special AGA graphics */
- filename = getPath3(getCurrentLevelDir(), GRAPHICS_AGA_DIRECTORY, basename);
- if (fileExists(filename) && setup.prefer_aga_graphics)
- return filename;
-
- free(filename);
-#endif
-
/* 1st try: look for special artwork in current level series directory */
filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
if (fileExists(filename))
free(filename);
-#if 1
- if (leveldir_current)
- printf("::: A -> '%s' [%s]\n", leveldir_current->graphics_set,
- leveldir_current->subdir);
-#endif
-
/* check if there is special artwork configured in level series config */
if (getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) != NULL)
{
-#if 1
- printf("::: B -> '%s' ---------> '%s'\n",
- getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS),
- leveldir_current->graphics_path);
- /* -> getLevelArtworkDir(ARTWORK_TYPE_GRAPHICS)); */
-#endif
-
/* 2nd try: look for special artwork configured in level series config */
filename = getPath2(getLevelArtworkDir(ARTWORK_TYPE_GRAPHICS), basename);
if (fileExists(filename))
void InitTapeDirectory(char *level_subdir)
{
- createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE);
+ createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE);
createDirectory(getTapeDir(NULL), "main tape", PERMS_PRIVATE);
createDirectory(getTapeDir(level_subdir), "level tape", PERMS_PRIVATE);
}
{
if (!fileExists(getUserLevelDir(level_subdir)))
{
- createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE);
+ 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();
}
void InitLevelSetupDirectory(char *level_subdir)
{
- createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE);
+ 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);
}
return checked_calloc(sizeof(TreeInfo));
}
+TreeInfo *newTreeInfo_setDefaults(int type)
+{
+ TreeInfo *ti = newTreeInfo();
+
+ setTreeInfoToDefaults(ti, type);
+
+ return ti;
+}
+
void pushTreeInfo(TreeInfo **node_first, TreeInfo *node_new)
{
node_new->next = *node_first;
}
else if (!node->parent_link)
{
- if (strcmp(identifier, node->identifier) == 0)
+ if (strEqual(identifier, node->identifier))
return node;
}
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 */
*ti_new = ti_cloned;
}
-static boolean adjustTreeGraphics(TreeInfo *node)
+static boolean adjustTreeGraphicsForEMC(TreeInfo *node)
{
boolean settings_changed = FALSE;
while (node)
{
-#if 1
- if (node->graphics_ecs_set && !setup.prefer_aga_graphics)
+ if (node->graphics_set_ecs && !setup.prefer_aga_graphics &&
+ !strEqual(node->graphics_set, node->graphics_set_ecs))
{
- setString(&node->graphics_set, node->graphics_ecs_set);
-#if 0
- printf("::: setting graphics for set '%s' to '%s' [ECS]\n",
- node->subdir, node->graphics_set);
-#endif
-
+ setString(&node->graphics_set, node->graphics_set_ecs);
settings_changed = TRUE;
}
- else if (node->graphics_aga_set && setup.prefer_aga_graphics)
+ else if (node->graphics_set_aga && setup.prefer_aga_graphics &&
+ !strEqual(node->graphics_set, node->graphics_set_aga))
{
- setString(&node->graphics_set, node->graphics_aga_set);
-#if 0
- printf("::: setting graphics for set '%s' to '%s' [AGA]\n",
- node->subdir, node->graphics_set);
-#endif
-
+ setString(&node->graphics_set, node->graphics_set_aga);
settings_changed = TRUE;
}
- else if (node->graphics_set == NULL)
- {
-#if 0
- printf("::: cannot set graphics_set for set '%s'\n", node->subdir);
-#endif
- }
-#else
- if (node->graphics_ecs_set)
- printf("::: SET '%s': found ECS set '%s'\n",
- node->subdir, node->graphics_ecs_set);
-
- if (node->graphics_aga_set)
- printf("::: SET '%s': found AGA set '%s'\n",
- node->subdir, node->graphics_aga_set);
-#endif
if (node->node_group != NULL)
- settings_changed |= adjustTreeGraphics(node->node_group);
+ settings_changed |= adjustTreeGraphicsForEMC(node->node_group);
node = node->next;
}
}
}
-void sortTreeInfo(TreeInfo **node_first,
- int (*compare_function)(const void *, const void *))
+void sortTreeInfoBySortFunction(TreeInfo **node_first,
+ int (*compare_function)(const void *,
+ const void *))
{
int num_nodes = numTreeInfo(*node_first);
TreeInfo **sort_array;
while (node)
{
if (node->node_group != NULL)
- sortTreeInfo(&node->node_group, compare_function);
+ sortTreeInfoBySortFunction(&node->node_group, compare_function);
node = node->next;
}
}
+void sortTreeInfo(TreeInfo **node_first)
+{
+ sortTreeInfoBySortFunction(node_first, compareTreeInfoEntries);
+}
+
/* ========================================================================= */
/* some stuff from "files.c" */
#define FILE_PERMS_PRIVATE (MODE_R_ALL | MODE_W_PRIVATE)
#define FILE_PERMS_PUBLIC (MODE_R_ALL | MODE_W_PUBLIC)
-char *getUserDataDir(void)
+char *getHomeDir()
{
- static char *userdata_dir = NULL;
+ static char *dir = NULL;
- if (userdata_dir == NULL)
- userdata_dir = getPath2(getHomeDir(), program.userdata_directory);
+#if defined(PLATFORM_WIN32)
+ if (dir == NULL)
+ {
+ dir = checked_malloc(MAX_PATH + 1);
+
+ if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, dir)))
+ strcpy(dir, ".");
+ }
+#elif defined(PLATFORM_UNIX)
+ if (dir == NULL)
+ {
+ if ((dir = getenv("HOME")) == NULL)
+ {
+ struct passwd *pwd;
+
+ if ((pwd = getpwuid(getuid())) != NULL)
+ dir = getStringCopy(pwd->pw_dir);
+ else
+ dir = ".";
+ }
+ }
+#else
+ dir = ".";
+#endif
- return userdata_dir;
+ return dir;
}
char *getCommonDataDir(void)
char *dir = checked_malloc(MAX_PATH + 1);
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, 0, dir))
- && strcmp(dir, "") != 0) /* empty for Windows 95/98 */
- common_data_dir = getPath2(dir, program.userdata_directory);
+ && !strEqual(dir, "")) /* empty for Windows 95/98 */
+ common_data_dir = getPath2(dir, program.userdata_subdir);
else
common_data_dir = options.rw_base_directory;
}
return common_data_dir;
}
+char *getPersonalDataDir(void)
+{
+ static char *personal_data_dir = NULL;
+
+#if defined(PLATFORM_MACOSX)
+ if (personal_data_dir == NULL)
+ personal_data_dir = getPath2(getHomeDir(), "Documents");
+#else
+ if (personal_data_dir == NULL)
+ personal_data_dir = getHomeDir();
+#endif
+
+ return personal_data_dir;
+}
+
+char *getUserGameDataDir(void)
+{
+ static char *user_game_data_dir = NULL;
+
+ if (user_game_data_dir == NULL)
+ user_game_data_dir = getPath2(getPersonalDataDir(),
+ program.userdata_subdir);
+
+ return user_game_data_dir;
+}
+
+void updateUserGameDataDir()
+{
+#if defined(PLATFORM_MACOSX)
+ char *userdata_dir_old = getPath2(getHomeDir(), program.userdata_subdir_unix);
+ char *userdata_dir_new = getUserGameDataDir(); /* do not free() this */
+
+ /* convert old Unix style game data directory to Mac OS X style, if needed */
+ if (fileExists(userdata_dir_old) && !fileExists(userdata_dir_new))
+ {
+ if (rename(userdata_dir_old, userdata_dir_new) != 0)
+ {
+ Error(ERR_WARN, "cannot move game data directory '%s' to '%s'",
+ userdata_dir_old, userdata_dir_new);
+
+ /* continue using Unix style data directory -- this should not happen */
+ program.userdata_path = getPath2(getPersonalDataDir(),
+ program.userdata_subdir_unix);
+ }
+ }
+
+ free(userdata_dir_old);
+#endif
+}
+
char *getSetupDir()
{
- return getUserDataDir();
+ return getUserGameDataDir();
}
static mode_t posix_umask(mode_t mask)
void InitUserDataDirectory()
{
- createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE);
+ createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE);
}
void SetFilePermissions(char *filename, int permission_class)
if (list == NULL)
return NULL;
- if (strcmp(list->token, token) == 0)
+ if (strEqual(list->token, token))
return list->value;
else
return getListEntry(list->next, token);
if (list == NULL)
return NULL;
- if (strcmp(list->token, token) == 0)
+ if (strEqual(list->token, token))
{
checked_free(list->value);
static int keys_are_equal(void *key1, void *key2)
{
- return (strcmp((char *)key1, (char *)key2) == 0);
+ return (strEqual((char *)key1, (char *)key2));
}
SetupFileHash *newSetupFileHash()
}
#endif
-static void *loadSetupFileData(char *filename, boolean use_hash)
+#define ALLOW_TOKEN_VALUE_SEPARATOR_BEING_WHITESPACE 1
+#define CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING 0
+
+static void loadSetupFileData(void *setup_file_data, char *filename,
+ boolean top_recursion_level, boolean is_hash)
{
- char line[MAX_LINE_LEN], previous_line[MAX_LINE_LEN];
+ static SetupFileHash *include_filename_hash = NULL;
+ char line[MAX_LINE_LEN], line_raw[MAX_LINE_LEN], previous_line[MAX_LINE_LEN];
char *token, *value, *line_ptr;
- void *setup_file_data, *insert_ptr = NULL;
+ void *insert_ptr = NULL;
boolean read_continued_line = FALSE;
+ boolean token_value_separator_found;
+#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
+ boolean token_value_separator_warning = FALSE;
+#endif
FILE *file;
+ int line_nr = 0;
+ int token_count = 0;
if (!(file = fopen(filename, MODE_READ)))
{
Error(ERR_WARN, "cannot open configuration file '%s'", filename);
- return NULL;
+ return;
}
- if (use_hash)
- setup_file_data = newSetupFileHash();
- else
- insert_ptr = setup_file_data = newSetupFileList("", "");
+ /* use "insert pointer" to store list end for constant insertion complexity */
+ if (!is_hash)
+ insert_ptr = setup_file_data;
+
+ /* on top invocation, create hash to mark included files (to prevent loops) */
+ if (top_recursion_level)
+ include_filename_hash = newSetupFileHash();
+
+ /* mark this file as already included (to prevent including it again) */
+ setHashEntry(include_filename_hash, getBaseNamePtr(filename), "true");
while (!feof(file))
{
if (!fgets(line, MAX_LINE_LEN, file))
break;
- /* cut trailing newline or carriage return */
+ /* check if line was completely read and is terminated by line break */
+ if (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
+ line_nr++;
+
+ /* cut trailing line break (this can be newline and/or carriage return) */
for (line_ptr = &line[strlen(line)]; line_ptr >= line; line_ptr--)
if ((*line_ptr == '\n' || *line_ptr == '\r') && *(line_ptr + 1) == '\0')
*line_ptr = '\0';
+ /* copy raw input line for later use (mainly debugging output) */
+ strcpy(line_raw, line);
+
if (read_continued_line)
{
/* cut leading whitespaces from input line */
/* start with empty value as reliable default */
value = "";
+ token_value_separator_found = FALSE;
+
/* find end of token to determine start of value */
for (line_ptr = token; *line_ptr; line_ptr++)
{
+#if 1
+ /* first look for an explicit token/value separator, like ':' or '=' */
+ if (*line_ptr == ':' || *line_ptr == '=')
+#else
if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':')
+#endif
{
*line_ptr = '\0'; /* terminate token string */
value = line_ptr + 1; /* set beginning of value */
+ token_value_separator_found = TRUE;
+
break;
}
}
+#if ALLOW_TOKEN_VALUE_SEPARATOR_BEING_WHITESPACE
+ /* fallback: if no token/value separator found, also allow whitespaces */
+ if (!token_value_separator_found)
+ {
+ for (line_ptr = token; *line_ptr; line_ptr++)
+ {
+ if (*line_ptr == ' ' || *line_ptr == '\t')
+ {
+ *line_ptr = '\0'; /* terminate token string */
+ value = line_ptr + 1; /* set beginning of value */
+
+ token_value_separator_found = TRUE;
+
+ break;
+ }
+ }
+
+#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
+ if (token_value_separator_found)
+ {
+ if (!token_value_separator_warning)
+ {
+ Error(ERR_INFO_LINE, "-");
+ Error(ERR_WARN, "missing token/value separator(s) in config file:");
+ Error(ERR_INFO, "- config file: '%s'", filename);
+
+ token_value_separator_warning = TRUE;
+ }
+
+ Error(ERR_INFO, "- line %d: '%s'", line_nr, line_raw);
+ }
+#endif
+ }
+#endif
+
+ /* cut trailing whitespaces from token */
+ for (line_ptr = &token[strlen(token)]; line_ptr >= token; line_ptr--)
+ if ((*line_ptr == ' ' || *line_ptr == '\t') && *(line_ptr + 1) == '\0')
+ *line_ptr = '\0';
+
/* cut leading whitespaces from value */
for (; *value; value++)
if (*value != ' ' && *value != '\t')
if (*token)
{
- if (use_hash)
- setHashEntry((SetupFileHash *)setup_file_data, token, value);
+ if (strEqual(token, "include"))
+ {
+ if (getHashEntry(include_filename_hash, value) == NULL)
+ {
+ char *basepath = getBasePath(filename);
+ char *basename = getBaseName(value);
+ char *filename_include = getPath2(basepath, basename);
+
+#if 0
+ Error(ERR_INFO, "[including file '%s']", filename_include);
+#endif
+
+ loadSetupFileData(setup_file_data, filename_include, FALSE, is_hash);
+
+ free(basepath);
+ free(basename);
+ free(filename_include);
+ }
+ else
+ {
+ Error(ERR_WARN, "ignoring already processed file '%s'", value);
+ }
+ }
else
- insert_ptr = addListEntry((SetupFileList *)insert_ptr, token, value);
+ {
+ if (is_hash)
+ setHashEntry((SetupFileHash *)setup_file_data, token, value);
+ else
+ insert_ptr = addListEntry((SetupFileList *)insert_ptr, token, value);
+
+ token_count++;
+ }
}
}
fclose(file);
- if (use_hash)
- {
- if (hashtable_count((SetupFileHash *)setup_file_data) == 0)
- Error(ERR_WARN, "configuration file '%s' is empty", filename);
- }
- else
+#if CHECK_TOKEN_VALUE_SEPARATOR__WARN_IF_MISSING
+ if (token_value_separator_warning)
+ Error(ERR_INFO_LINE, "-");
+#endif
+
+ if (token_count == 0)
+ Error(ERR_WARN, "configuration file '%s' is empty", filename);
+
+ if (top_recursion_level)
+ freeSetupFileHash(include_filename_hash);
+}
+
+void saveSetupFileHash(SetupFileHash *hash, char *filename)
+{
+ FILE *file;
+
+ if (!(file = fopen(filename, MODE_WRITE)))
{
- SetupFileList *setup_file_list = (SetupFileList *)setup_file_data;
- SetupFileList *first_valid_list_entry = setup_file_list->next;
+ Error(ERR_WARN, "cannot write configuration file '%s'", filename);
- /* free empty list header */
- setup_file_list->next = NULL;
- freeSetupFileList(setup_file_list);
- setup_file_data = first_valid_list_entry;
+ return;
+ }
- if (first_valid_list_entry == NULL)
- Error(ERR_WARN, "configuration file '%s' is empty", filename);
+ BEGIN_HASH_ITERATION(hash, itr)
+ {
+ fprintf(file, "%s\n", getFormattedSetupEntry(HASH_ITERATION_TOKEN(itr),
+ HASH_ITERATION_VALUE(itr)));
}
+ END_HASH_ITERATION(hash, itr)
- return setup_file_data;
+ fclose(file);
}
SetupFileList *loadSetupFileList(char *filename)
{
- return (SetupFileList *)loadSetupFileData(filename, FALSE);
+ SetupFileList *setup_file_list = newSetupFileList("", "");
+ SetupFileList *first_valid_list_entry;
+
+ loadSetupFileData(setup_file_list, filename, TRUE, FALSE);
+
+ first_valid_list_entry = setup_file_list->next;
+
+ /* free empty list header */
+ setup_file_list->next = NULL;
+ freeSetupFileList(setup_file_list);
+
+ return first_valid_list_entry;
}
SetupFileHash *loadSetupFileHash(char *filename)
{
- return (SetupFileHash *)loadSetupFileData(filename, TRUE);
+ SetupFileHash *setup_file_hash = newSetupFileHash();
+
+ loadSetupFileData(setup_file_hash, filename, TRUE, TRUE);
+
+ return setup_file_hash;
}
void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
#define LEVELINFO_TOKEN_LATEST_ENGINE 9
#define LEVELINFO_TOKEN_LEVEL_GROUP 10
#define LEVELINFO_TOKEN_READONLY 11
-#define LEVELINFO_TOKEN_GRAPHICS_ECS_SET 12
-#define LEVELINFO_TOKEN_GRAPHICS_AGA_SET 13
+#define LEVELINFO_TOKEN_GRAPHICS_SET_ECS 12
+#define LEVELINFO_TOKEN_GRAPHICS_SET_AGA 13
#define LEVELINFO_TOKEN_GRAPHICS_SET 14
#define LEVELINFO_TOKEN_SOUNDS_SET 15
#define LEVELINFO_TOKEN_MUSIC_SET 16
{ TYPE_BOOLEAN, &ldi.latest_engine, "latest_engine" },
{ TYPE_BOOLEAN, &ldi.level_group, "level_group" },
{ TYPE_BOOLEAN, &ldi.readonly, "readonly" },
- { TYPE_STRING, &ldi.graphics_ecs_set, "graphics_ecs_set" },
- { TYPE_STRING, &ldi.graphics_aga_set, "graphics_aga_set" },
+ { TYPE_STRING, &ldi.graphics_set_ecs, "graphics_set.ecs" },
+ { TYPE_STRING, &ldi.graphics_set_aga, "graphics_set.aga" },
{ TYPE_STRING, &ldi.graphics_set, "graphics_set" },
{ TYPE_STRING, &ldi.sounds_set, "sounds_set" },
{ TYPE_STRING, &ldi.music_set, "music_set" },
{ TYPE_BOOLEAN, &ldi.skip_levels, "skip_levels" }
};
-static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
+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)
{
- ldi->type = type;
+ ti->type = type;
- ldi->node_top = (ldi->type == TREE_TYPE_LEVEL_DIR ? &leveldir_first :
- ldi->type == TREE_TYPE_GRAPHICS_DIR ? &artwork.gfx_first :
- ldi->type == TREE_TYPE_SOUNDS_DIR ? &artwork.snd_first :
- ldi->type == TREE_TYPE_MUSIC_DIR ? &artwork.mus_first :
- NULL);
+ ti->node_top = (ti->type == TREE_TYPE_LEVEL_DIR ? &leveldir_first :
+ ti->type == TREE_TYPE_GRAPHICS_DIR ? &artwork.gfx_first :
+ ti->type == TREE_TYPE_SOUNDS_DIR ? &artwork.snd_first :
+ ti->type == TREE_TYPE_MUSIC_DIR ? &artwork.mus_first :
+ NULL);
- ldi->node_parent = NULL;
- ldi->node_group = NULL;
- ldi->next = NULL;
+ ti->node_parent = NULL;
+ ti->node_group = NULL;
+ ti->next = NULL;
- ldi->cl_first = -1;
- ldi->cl_cursor = -1;
+ ti->cl_first = -1;
+ ti->cl_cursor = -1;
- ldi->subdir = NULL;
- ldi->fullpath = NULL;
- ldi->basepath = NULL;
- ldi->identifier = NULL;
- ldi->name = getStringCopy(ANONYMOUS_NAME);
- ldi->name_sorting = NULL;
- ldi->author = getStringCopy(ANONYMOUS_NAME);
+ ti->subdir = NULL;
+ ti->fullpath = NULL;
+ ti->basepath = NULL;
+ ti->identifier = NULL;
+ ti->name = getStringCopy(ANONYMOUS_NAME);
+ ti->name_sorting = NULL;
+ ti->author = getStringCopy(ANONYMOUS_NAME);
- ldi->sort_priority = LEVELCLASS_UNDEFINED; /* default: least priority */
- ldi->latest_engine = FALSE; /* default: get from level */
- ldi->parent_link = FALSE;
- ldi->in_user_dir = FALSE;
- ldi->user_defined = FALSE;
- ldi->color = 0;
- ldi->class_desc = NULL;
+ ti->sort_priority = LEVELCLASS_UNDEFINED; /* default: least priority */
+ ti->latest_engine = FALSE; /* default: get from level */
+ ti->parent_link = FALSE;
+ ti->in_user_dir = FALSE;
+ ti->user_defined = FALSE;
+ ti->color = 0;
+ ti->class_desc = NULL;
- if (ldi->type == TREE_TYPE_LEVEL_DIR)
+ ti->infotext = getStringCopy(TREE_INFOTEXT(ti->type));
+
+ if (ti->type == TREE_TYPE_LEVEL_DIR)
{
- ldi->imported_from = NULL;
- ldi->imported_by = NULL;
+ ti->imported_from = NULL;
+ ti->imported_by = NULL;
- ldi->graphics_ecs_set = NULL;
- ldi->graphics_aga_set = NULL;
- ldi->graphics_set = NULL;
- ldi->sounds_set = NULL;
- ldi->music_set = NULL;
- ldi->graphics_path = getStringCopy(UNDEFINED_FILENAME);
- ldi->sounds_path = getStringCopy(UNDEFINED_FILENAME);
- ldi->music_path = getStringCopy(UNDEFINED_FILENAME);
+ ti->graphics_set_ecs = NULL;
+ ti->graphics_set_aga = NULL;
+ ti->graphics_set = NULL;
+ ti->sounds_set = NULL;
+ ti->music_set = NULL;
+ ti->graphics_path = getStringCopy(UNDEFINED_FILENAME);
+ ti->sounds_path = getStringCopy(UNDEFINED_FILENAME);
+ ti->music_path = getStringCopy(UNDEFINED_FILENAME);
- ldi->level_filename = NULL;
- ldi->level_filetype = NULL;
+ ti->level_filename = NULL;
+ ti->level_filetype = NULL;
- ldi->levels = 0;
- ldi->first_level = 0;
- ldi->last_level = 0;
- ldi->level_group = FALSE;
- ldi->handicap_level = 0;
- ldi->readonly = TRUE;
- ldi->handicap = TRUE;
- ldi->skip_levels = FALSE;
+ ti->levels = 0;
+ ti->first_level = 0;
+ ti->last_level = 0;
+ ti->level_group = FALSE;
+ ti->handicap_level = 0;
+ ti->readonly = TRUE;
+ ti->handicap = TRUE;
+ ti->skip_levels = FALSE;
}
}
-static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
+static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent)
{
if (parent == NULL)
{
Error(ERR_WARN, "setTreeInfoToDefaultsFromParent(): parent == NULL");
- setTreeInfoToDefaults(ldi, TREE_TYPE_UNDEFINED);
+ setTreeInfoToDefaults(ti, TREE_TYPE_UNDEFINED);
return;
}
/* copy all values from the parent structure */
- ldi->type = parent->type;
-
- ldi->node_top = parent->node_top;
- ldi->node_parent = parent;
- ldi->node_group = NULL;
- ldi->next = NULL;
+ ti->type = parent->type;
- ldi->cl_first = -1;
- ldi->cl_cursor = -1;
+ ti->node_top = parent->node_top;
+ ti->node_parent = parent;
+ ti->node_group = NULL;
+ ti->next = NULL;
+
+ ti->cl_first = -1;
+ ti->cl_cursor = -1;
+
+ ti->subdir = NULL;
+ ti->fullpath = NULL;
+ ti->basepath = NULL;
+ ti->identifier = NULL;
+ ti->name = getStringCopy(ANONYMOUS_NAME);
+ ti->name_sorting = NULL;
+ ti->author = getStringCopy(parent->author);
- 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);
+ ti->sort_priority = parent->sort_priority;
+ ti->latest_engine = parent->latest_engine;
+ ti->parent_link = FALSE;
+ ti->in_user_dir = parent->in_user_dir;
+ ti->user_defined = parent->user_defined;
+ ti->color = parent->color;
+ ti->class_desc = getStringCopy(parent->class_desc);
- ldi->sort_priority = parent->sort_priority;
- ldi->latest_engine = parent->latest_engine;
- ldi->parent_link = FALSE;
- ldi->in_user_dir = parent->in_user_dir;
- ldi->user_defined = parent->user_defined;
- ldi->color = parent->color;
- ldi->class_desc = getStringCopy(parent->class_desc);
+ ti->infotext = getStringCopy(parent->infotext);
- if (ldi->type == TREE_TYPE_LEVEL_DIR)
+ if (ti->type == TREE_TYPE_LEVEL_DIR)
{
- ldi->imported_from = getStringCopy(parent->imported_from);
- ldi->imported_by = getStringCopy(parent->imported_by);
+ ti->imported_from = getStringCopy(parent->imported_from);
+ ti->imported_by = getStringCopy(parent->imported_by);
- ldi->graphics_ecs_set = NULL;
- ldi->graphics_aga_set = NULL;
- ldi->graphics_set = NULL;
- ldi->sounds_set = NULL;
- ldi->music_set = NULL;
- ldi->graphics_path = getStringCopy(UNDEFINED_FILENAME);
- ldi->sounds_path = getStringCopy(UNDEFINED_FILENAME);
- ldi->music_path = getStringCopy(UNDEFINED_FILENAME);
+ ti->graphics_set_ecs = NULL;
+ ti->graphics_set_aga = NULL;
+ ti->graphics_set = NULL;
+ ti->sounds_set = NULL;
+ ti->music_set = NULL;
+ ti->graphics_path = getStringCopy(UNDEFINED_FILENAME);
+ ti->sounds_path = getStringCopy(UNDEFINED_FILENAME);
+ ti->music_path = getStringCopy(UNDEFINED_FILENAME);
- ldi->level_filename = NULL;
- ldi->level_filetype = NULL;
+ ti->level_filename = NULL;
+ ti->level_filetype = NULL;
- ldi->levels = 0;
- ldi->first_level = 0;
- ldi->last_level = 0;
- ldi->level_group = FALSE;
- ldi->handicap_level = 0;
- ldi->readonly = TRUE;
- ldi->handicap = TRUE;
- ldi->skip_levels = FALSE;
+ ti->levels = 0;
+ ti->first_level = 0;
+ ti->last_level = 0;
+ ti->level_group = FALSE;
+ ti->handicap_level = 0;
+ ti->readonly = TRUE;
+ ti->handicap = TRUE;
+ ti->skip_levels = FALSE;
}
}
-static void freeTreeInfo(TreeInfo *ldi)
+static TreeInfo *getTreeInfoCopy(TreeInfo *ti)
{
- checked_free(ldi->subdir);
- checked_free(ldi->fullpath);
- checked_free(ldi->basepath);
- checked_free(ldi->identifier);
+ 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;
- checked_free(ldi->name);
- checked_free(ldi->name_sorting);
- checked_free(ldi->author);
+ 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);
- checked_free(ldi->class_desc);
+ 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)
+ return;
- if (ldi->type == TREE_TYPE_LEVEL_DIR)
+ checked_free(ti->subdir);
+ checked_free(ti->fullpath);
+ checked_free(ti->basepath);
+ checked_free(ti->identifier);
+
+ checked_free(ti->name);
+ checked_free(ti->name_sorting);
+ checked_free(ti->author);
+
+ checked_free(ti->class_desc);
+
+ checked_free(ti->infotext);
+
+ if (ti->type == TREE_TYPE_LEVEL_DIR)
{
- checked_free(ldi->imported_from);
- checked_free(ldi->imported_by);
+ checked_free(ti->imported_from);
+ checked_free(ti->imported_by);
- checked_free(ldi->graphics_ecs_set);
- checked_free(ldi->graphics_aga_set);
- checked_free(ldi->graphics_set);
- checked_free(ldi->sounds_set);
- checked_free(ldi->music_set);
+ checked_free(ti->graphics_set_ecs);
+ checked_free(ti->graphics_set_aga);
+ checked_free(ti->graphics_set);
+ checked_free(ti->sounds_set);
+ checked_free(ti->music_set);
- checked_free(ldi->graphics_path);
- checked_free(ldi->sounds_path);
- checked_free(ldi->music_path);
+ checked_free(ti->graphics_path);
+ checked_free(ti->sounds_path);
+ checked_free(ti->music_path);
- checked_free(ldi->level_filename);
- checked_free(ldi->level_filetype);
+ checked_free(ti->level_filename);
+ checked_free(ti->level_filetype);
}
+
+ checked_free(ti);
}
void setSetupInfo(struct TokenInfo *token_info,
pushTreeInfo(&node_parent->node_group, ti_new);
}
+
+/* -------------------------------------------------------------------------- */
+/* functions for handling level and custom artwork info cache */
+/* -------------------------------------------------------------------------- */
+
+static void LoadArtworkInfoCache()
+{
+ InitCacheDirectory();
+
+ if (artworkinfo_cache_old == NULL)
+ {
+ char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE);
+
+ /* try to load artwork info hash from already existing cache file */
+ artworkinfo_cache_old = loadSetupFileHash(filename);
+
+ /* if no artwork info cache file was found, start with empty hash */
+ if (artworkinfo_cache_old == NULL)
+ artworkinfo_cache_old = newSetupFileHash();
+
+ free(filename);
+ }
+
+ if (artworkinfo_cache_new == NULL)
+ artworkinfo_cache_new = newSetupFileHash();
+}
+
+static void SaveArtworkInfoCache()
+{
+ char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE);
+
+ InitCacheDirectory();
+
+ saveSetupFileHash(artworkinfo_cache_new, filename);
+
+ free(filename);
+}
+
+static char *getCacheTokenPrefix(char *prefix1, char *prefix2)
+{
+ static char *prefix = NULL;
+
+ checked_free(prefix);
+
+ prefix = getStringCat2WithSeparator(prefix1, prefix2, ".");
+
+ return prefix;
+}
+
+/* (identical to above function, but separate string buffer needed -- nasty) */
+static char *getCacheToken(char *prefix, char *suffix)
+{
+ static char *token = NULL;
+
+ checked_free(token);
+
+ token = getStringCat2WithSeparator(prefix, suffix, ".");
+
+ return token;
+}
+
+static char *getFileTimestamp(char *filename)
+{
+ struct stat file_status;
+
+ if (stat(filename, &file_status) != 0) /* cannot stat file */
+ return getStringCopy(i_to_a(0));
+
+ return getStringCopy(i_to_a(file_status.st_mtime));
+}
+
+static boolean modifiedFileTimestamp(char *filename, char *timestamp_string)
+{
+ struct stat file_status;
+
+ if (timestamp_string == NULL)
+ return TRUE;
+
+ if (stat(filename, &file_status) != 0) /* cannot stat file */
+ return TRUE;
+
+ return (file_status.st_mtime != atoi(timestamp_string));
+}
+
+static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type)
+{
+ char *identifier = level_node->subdir;
+ 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_cache_old, token_main);
+ boolean cached = (cache_entry != NULL && strEqual(cache_entry, "true"));
+ TreeInfo *artwork_info = NULL;
+
+ if (!use_artworkinfo_cache)
+ return NULL;
+
+ if (cached)
+ {
+ int i;
+
+ artwork_info = newTreeInfo();
+ setTreeInfoToDefaults(artwork_info, type);
+
+ /* set all structure fields according to the token/value pairs */
+ ldi = *artwork_info;
+ for (i = 0; artworkinfo_tokens[i].type != -1; i++)
+ {
+ char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text);
+ 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 1
+ Error(ERR_WARN, "cache entry '%s' invalid", token);
+#endif
+
+ cached = FALSE;
+ }
+ }
+
+ *artwork_info = ldi;
+ }
+
+ if (cached)
+ {
+ char *filename_levelinfo = getPath2(getLevelDirFromTreeInfo(level_node),
+ LEVELINFO_FILENAME);
+ char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info),
+ ARTWORKINFO_FILENAME(type));
+
+ /* check if corresponding "levelinfo.conf" file has changed */
+ token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO");
+ 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_cache_old, token_main);
+
+ if (modifiedFileTimestamp(filename_artworkinfo, cache_entry))
+ cached = FALSE;
+
+#if 0
+ if (!cached)
+ printf("::: '%s': INVALIDATED FROM CACHE BY TIMESTAMP\n", identifier);
+#endif
+
+ checked_free(filename_levelinfo);
+ checked_free(filename_artworkinfo);
+ }
+
+ if (!cached && artwork_info != NULL)
+ {
+ freeTreeInfo(artwork_info);
+
+ return NULL;
+ }
+
+ return artwork_info;
+}
+
+static void setArtworkInfoCacheEntry(TreeInfo *artwork_info,
+ LevelDirTree *level_node, int type)
+{
+ char *identifier = level_node->subdir;
+ char *type_string = ARTWORK_DIRECTORY(type);
+ char *token_prefix = getCacheTokenPrefix(type_string, identifier);
+ char *token_main = getCacheToken(token_prefix, "CACHED");
+ boolean set_cache_timestamps = TRUE;
+ int i;
+
+ setHashEntry(artworkinfo_cache_new, token_main, "true");
+
+ if (set_cache_timestamps)
+ {
+ char *filename_levelinfo = getPath2(getLevelDirFromTreeInfo(level_node),
+ LEVELINFO_FILENAME);
+ char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info),
+ ARTWORKINFO_FILENAME(type));
+ char *timestamp_levelinfo = getFileTimestamp(filename_levelinfo);
+ char *timestamp_artworkinfo = getFileTimestamp(filename_artworkinfo);
+
+ token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO");
+ setHashEntry(artworkinfo_cache_new, token_main, timestamp_levelinfo);
+
+ token_main = getCacheToken(token_prefix, "TIMESTAMP_ARTWORKINFO");
+ setHashEntry(artworkinfo_cache_new, token_main, timestamp_artworkinfo);
+
+ checked_free(filename_levelinfo);
+ checked_free(filename_artworkinfo);
+ checked_free(timestamp_levelinfo);
+ checked_free(timestamp_artworkinfo);
+ }
+
+ ldi = *artwork_info;
+ for (i = 0; artworkinfo_tokens[i].type != -1; i++)
+ {
+ char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text);
+ char *value = getSetupValue(artworkinfo_tokens[i].type,
+ artworkinfo_tokens[i].value);
+ if (value != NULL)
+ setHashEntry(artworkinfo_cache_new, token, value);
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* functions for loading level info and custom artwork info */
+/* -------------------------------------------------------------------------- */
+
/* forward declaration for recursive call by "LoadLevelInfoFromLevelDir()" */
static void LoadLevelInfoFromLevelDir(TreeInfo **, TreeInfo *, char *);
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;
getHashEntry(setup_file_hash, levelinfo_tokens[i].text));
*leveldir_new = ldi;
- if (strcmp(leveldir_new->name, ANONYMOUS_NAME) == 0)
+ 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);
leveldir_new->first_level + leveldir_new->levels - 1;
leveldir_new->in_user_dir =
- (strcmp(leveldir_new->basepath, options.level_directory) != 0);
+ (!strEqual(leveldir_new->basepath, options.level_directory));
/* 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->name, getLoginName()) == 0 ||
- strcmp(leveldir_new->author, getRealName()) == 0))
+ (strEqual(leveldir_new->subdir, getLoginName()) ||
+ strEqual(leveldir_new->name, getLoginName()) ||
+ strEqual(leveldir_new->author, getRealName())))
{
leveldir_new->sort_priority = LEVELCLASS_PRIVATE_START;
leveldir_new->readonly = FALSE;
(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
/* 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);
}
char *directory_path = getPath2(level_directory, directory_name);
/* skip entries for current and parent directory */
- if (strcmp(directory_name, ".") == 0 ||
- strcmp(directory_name, "..") == 0)
+ if (strEqual(directory_name, ".") ||
+ strEqual(directory_name, ".."))
{
free(directory_path);
continue;
free(directory_path);
- if (strcmp(directory_name, GRAPHICS_DIRECTORY) == 0 ||
- strcmp(directory_name, SOUNDS_DIRECTORY) == 0 ||
- strcmp(directory_name, MUSIC_DIRECTORY) == 0)
+ if (strEqual(directory_name, GRAPHICS_DIRECTORY) ||
+ strEqual(directory_name, SOUNDS_DIRECTORY) ||
+ strEqual(directory_name, MUSIC_DIRECTORY))
continue;
valid_entry_found |= LoadLevelInfoFromLevelConf(node_first, node_parent,
{
boolean settings_changed = FALSE;
-#if 1
- printf("::: AdjustGraphicsForEMC()\n");
-
- settings_changed |= adjustTreeGraphics(leveldir_first_all);
- settings_changed |= adjustTreeGraphics(leveldir_first);
-
- if (leveldir_current)
- printf("::: X -> '%s'\n", leveldir_current->graphics_set);
- else
- printf("::: X (leveldir_current == NULL)\n");
-#endif
+ settings_changed |= adjustTreeGraphicsForEMC(leveldir_first_all);
+ settings_changed |= adjustTreeGraphicsForEMC(leveldir_first);
return settings_changed;
}
{
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));
-#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
AdjustGraphicsForEMC();
if (leveldir_first == NULL)
Error(ERR_EXIT, "cannot find any valid level series in any directory");
- sortTreeInfo(&leveldir_first, compareTreeInfoEntries);
+ sortTreeInfo(&leveldir_first);
#if 0
dumpTreeInfo(leveldir_first, 0);
TreeInfo *artwork_new = NULL;
int i;
-#if 0
- printf("::: CHECKING FOR CONFIG FILE '%s'\n", filename);
-#endif
-
if (fileExists(filename))
setup_file_hash = loadSetupFileHash(filename);
if (!valid_file_found)
{
- if (strcmp(directory_name, ".") != 0)
+ if (!strEqual(directory_name, "."))
Error(ERR_WARN, "ignoring artwork directory '%s'", directory_path);
free(directory_path);
getHashEntry(setup_file_hash, levelinfo_tokens[i].text));
*artwork_new = ldi;
- if (strcmp(artwork_new->name, ANONYMOUS_NAME) == 0)
+ 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);
}
artwork_new->in_user_dir =
- (strcmp(artwork_new->basepath, OPTIONS_ARTWORK_DIRECTORY(type)) != 0);
+ (!strEqual(artwork_new->basepath, OPTIONS_ARTWORK_DIRECTORY(type)));
/* (may use ".sort_priority" from "setup_file_hash" above) */
artwork_new->color = ARTWORKCOLOR(artwork_new);
if (setup_file_hash == NULL) /* (after determining ".user_defined") */
{
- if (strcmp(artwork_new->subdir, ".") == 0)
+ if (strEqual(artwork_new->subdir, "."))
{
if (artwork_new->user_defined)
{
setString(&artwork_new->name_sorting, artwork_new->name);
}
+#if 0
DrawInitText(artwork_new->name, 150, FC_YELLOW);
+#endif
pushTreeInfo(node_first, artwork_new);
struct dirent *dir_entry;
boolean valid_entry_found = FALSE;
-#if 0
- printf("::: CHECKING BASE DIR '%s'\n", base_directory);
-#endif
-
if ((dir = opendir(base_directory)) == NULL)
{
/* display error if directory is main "options.graphics_directory" etc. */
char *directory_path = getPath2(base_directory, directory_name);
/* skip directory entries for current and parent directory */
- if (strcmp(directory_name, ".") == 0 ||
- strcmp(directory_name, "..") == 0)
+ if (strEqual(directory_name, ".") ||
+ strEqual(directory_name, ".."))
{
free(directory_path);
continue;
void LoadArtworkInfo()
{
- DrawInitText("Looking for custom artwork:", 120, FC_GREEN);
+ LoadArtworkInfoCache();
+
+ DrawInitText("Looking for custom artwork", 120, FC_GREEN);
LoadArtworkInfoFromArtworkDir(&artwork.gfx_first, NULL,
options.graphics_directory,
printf("music set == %s\n\n", artwork.mus_current_identifier);
#endif
- sortTreeInfo(&artwork.gfx_first, compareTreeInfoEntries);
- sortTreeInfo(&artwork.snd_first, compareTreeInfoEntries);
- sortTreeInfo(&artwork.mus_first, compareTreeInfoEntries);
+ sortTreeInfo(&artwork.gfx_first);
+ sortTreeInfo(&artwork.snd_first);
+ sortTreeInfo(&artwork.mus_first);
#if 0
dumpTreeInfo(artwork.gfx_first, 0);
#endif
}
-void LoadArtworkInfoFromLevelNode(ArtworkDirTree **artwork_node,
- LevelDirTree *level_node,
- char *artwork_directory)
-{
- TreeInfo *topnode_last = *artwork_node;
- char *path = getPath2(getLevelDirFromTreeInfo(level_node), artwork_directory);
-
-#if 1
- printf("::: CHECKING '%s' ...\n", path);
-#endif
-
- LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path,(*artwork_node)->type);
-
- if (topnode_last != *artwork_node)
- {
- free((*artwork_node)->identifier);
- free((*artwork_node)->name);
- free((*artwork_node)->name_sorting);
-
- (*artwork_node)->identifier = getStringCopy(level_node->subdir);
- (*artwork_node)->name = getStringCopy(level_node->name);
- (*artwork_node)->name_sorting = getStringCopy(level_node->name);
-
- (*artwork_node)->sort_priority = level_node->sort_priority;
- (*artwork_node)->color = LEVELCOLOR((*artwork_node));
- }
-
- free(path);
-}
-
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 */
while (level_node)
/* check all tree entries for artwork, but skip parent link entries */
if (!level_node->parent_link)
{
-#if 1
- struct
+ TreeInfo *artwork_new = getArtworkInfoCacheEntry(level_node, type);
+ boolean cached = (artwork_new != NULL);
+
+ if (cached)
{
- int type;
- char *dir;
+ pushTreeInfo(artwork_node, artwork_new);
}
- artwork_type_dirs[] =
+ else
{
- { ARTWORK_TYPE_GRAPHICS, GRAPHICS_DIRECTORY },
- { ARTWORK_TYPE_GRAPHICS, GRAPHICS_ECS_DIRECTORY },
- { ARTWORK_TYPE_GRAPHICS, GRAPHICS_AGA_DIRECTORY },
- { ARTWORK_TYPE_SOUNDS, SOUNDS_DIRECTORY },
- { ARTWORK_TYPE_MUSIC, MUSIC_DIRECTORY },
- { -1, NULL }
- };
- int i;
-
- for (i = 0; artwork_type_dirs[i].type != -1; i++)
- if ((*artwork_node)->type == artwork_type_dirs[i].type)
- LoadArtworkInfoFromLevelNode(artwork_node, level_node,
- artwork_type_dirs[i].dir);
-#else
- TreeInfo *topnode_last = *artwork_node;
- char *path = getPath2(getLevelDirFromTreeInfo(level_node),
- ARTWORK_DIRECTORY((*artwork_node)->type));
+ TreeInfo *topnode_last = *artwork_node;
+ char *path = getPath2(getLevelDirFromTreeInfo(level_node),
+ ARTWORK_DIRECTORY(type));
- LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path,
- (*artwork_node)->type);
+ LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, type);
- if (topnode_last != *artwork_node)
- {
- free((*artwork_node)->identifier);
- free((*artwork_node)->name);
- free((*artwork_node)->name_sorting);
+ if (topnode_last != *artwork_node) /* check for newly added node */
+ {
+ artwork_new = *artwork_node;
- (*artwork_node)->identifier = getStringCopy(level_node->subdir);
- (*artwork_node)->name = getStringCopy(level_node->name);
- (*artwork_node)->name_sorting = getStringCopy(level_node->name);
+ setString(&artwork_new->identifier, level_node->subdir);
+ setString(&artwork_new->name, level_node->name);
+ setString(&artwork_new->name_sorting, level_node->name_sorting);
- (*artwork_node)->sort_priority = level_node->sort_priority;
- (*artwork_node)->color = LEVELCOLOR((*artwork_node));
+ artwork_new->sort_priority = level_node->sort_priority;
+ artwork_new->color = LEVELCOLOR(artwork_new);
+ }
+
+ free(path);
}
- free(path);
-#endif
+ /* insert artwork info (from old cache or filesystem) into new cache */
+ if (artwork_new != NULL)
+ 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);
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);
LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first_all);
+ SaveArtworkInfoCache();
+
/* needed for reloading level artwork not known at ealier stage */
- if (strcmp(artwork.gfx_current_identifier, setup.graphics_set) != 0)
+ if (!strEqual(artwork.gfx_current_identifier, setup.graphics_set))
{
artwork.gfx_current =
getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set);
artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first);
}
- if (strcmp(artwork.snd_current_identifier, setup.sounds_set) != 0)
+ if (!strEqual(artwork.snd_current_identifier, setup.sounds_set))
{
artwork.snd_current =
getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
}
- if (strcmp(artwork.mus_current_identifier, setup.music_set) != 0)
+ if (!strEqual(artwork.mus_current_identifier, setup.music_set))
{
artwork.mus_current =
getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
}
- sortTreeInfo(&artwork.gfx_first, compareTreeInfoEntries);
- sortTreeInfo(&artwork.snd_first, compareTreeInfoEntries);
- sortTreeInfo(&artwork.mus_first, compareTreeInfoEntries);
+ sortTreeInfo(&artwork.gfx_first);
+ sortTreeInfo(&artwork.snd_first);
+ sortTreeInfo(&artwork.mus_first);
#if 0
dumpTreeInfo(artwork.gfx_first, 0);
break;
case TYPE_STRING:
+ if (*(char **)value == NULL)
+ return NULL;
+
strcpy(value_string, *(char **)value);
break;
char *keyname = getKeyNameFromKey(key);
/* add comment, if useful */
- if (strcmp(keyname, "(undefined)") != 0 &&
- strcmp(keyname, "(unknown)") != 0)
+ if (!strEqual(keyname, "(undefined)") &&
+ !strEqual(keyname, "(unknown)"))
{
/* add at least one whitespace */
strcat(line, " ");
{
if (strlen(dir_entry->d_name) > 4 &&
dir_entry->d_name[3] == '.' &&
- strcmp(&dir_entry->d_name[4], LEVELFILE_EXTENSION) == 0)
+ strEqual(&dir_entry->d_name[4], LEVELFILE_EXTENSION))
{
char levelnum_str[4];
int levelnum_value;