#include "misc.h"
#include "setup.h"
#include "random.h"
+#include "text.h"
#if defined(PLATFORM_MSDOS)
if (mode & ERR_WARN && !options.verbose)
return;
-#if !defined(PLATFORM_UNIX)
+#if defined(PLATFORM_MSDOS)
newline = "\r\n";
if ((error = openErrorFile()) == NULL)
}
+/* ========================================================================= */
+/* functions for generic lists */
+/* ========================================================================= */
+
+ListNode *newListNode()
+{
+ return checked_calloc(sizeof(ListNode));
+}
+
+void addNodeToList(ListNode **node_first, char *key, void *content)
+{
+ ListNode *node_new = newListNode();
+
+#if 0
+ printf("LIST: adding node with key '%s'\n", key);
+#endif
+
+ node_new->key = getStringCopy(key);
+ node_new->content = content;
+ node_new->next = *node_first;
+ *node_first = node_new;
+}
+
+void deleteNodeFromList(ListNode **node_first, char *key,
+ void (*destructor_function)(void *))
+{
+ if (node_first == NULL || *node_first == NULL)
+ return;
+
+#if 0
+ printf("[CHECKING LIST KEY '%s' == '%s']\n",
+ (*node_first)->key, key);
+#endif
+
+ if (strcmp((*node_first)->key, key) == 0)
+ {
+#if 0
+ printf("[DELETING LIST ENTRY]\n");
+#endif
+
+ free((*node_first)->key);
+ if (destructor_function)
+ destructor_function((*node_first)->content);
+ *node_first = (*node_first)->next;
+ }
+ else
+ deleteNodeFromList(&(*node_first)->next, key, destructor_function);
+}
+
+ListNode *getNodeFromKey(ListNode *node_first, char *key)
+{
+ if (node_first == NULL)
+ return NULL;
+
+ if (strcmp(node_first->key, key) == 0)
+ return node_first;
+ else
+ return getNodeFromKey(node_first->next, key);
+}
+
+int getNumNodes(ListNode *node_first)
+{
+ return (node_first ? 1 + getNumNodes(node_first->next) : 0);
+}
+
+void dumpList(ListNode *node_first)
+{
+ ListNode *node = node_first;
+
+ while (node)
+ {
+ printf("['%s' (%d)]\n", node->key,
+ ((struct ListNodeInfo *)node->content)->num_references);
+ node = node->next;
+ }
+
+ printf("[%d nodes]\n", getNumNodes(node_first));
+}
+
+
/* ========================================================================= */
/* functions for checking filenames */
/* ========================================================================= */
return FALSE;
}
-
/* ========================================================================= */
-/* functions only needed for non-Unix (non-command-line) systems */
+/* functions for loading artwork configuration information */
/* ========================================================================= */
-#if !defined(PLATFORM_UNIX)
+struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
+ char *suffix_list[],
+ int num_list_entries)
+{
+ struct FileInfo *file_list =
+ checked_calloc(num_list_entries * sizeof(struct FileInfo));
+ int list_pos = 0;
+ int i, j;
-#define ERROR_FILENAME "error.out"
+ for (i=0; config_list[i].token != NULL; i++)
+ {
+ int len_config_token = strlen(config_list[i].token);
+ boolean is_file_entry = TRUE;
-void initErrorFile()
+ for (j=0; suffix_list[j] != NULL; j++)
+ {
+ int len_suffix = strlen(suffix_list[j]);
+
+ if (len_suffix < len_config_token &&
+ strcmp(&config_list[i].token[len_config_token - len_suffix],
+ suffix_list[j]) == 0)
+ {
+ is_file_entry = FALSE;
+ break;
+ }
+ }
+
+ if (is_file_entry)
+ {
+ if (list_pos >= num_list_entries)
+ Error(ERR_EXIT, "inconsistant config list information -- please fix");
+
+ file_list[list_pos].token = config_list[i].token;
+ file_list[list_pos].default_filename = config_list[i].value;
+
+ list_pos++;
+ }
+ }
+
+ if (list_pos != num_list_entries)
+ Error(ERR_EXIT, "inconsistant config list information -- please fix");
+
+ return file_list;
+}
+
+static void LoadArtworkConfig(struct ArtworkListInfo *artwork_info)
{
- char *filename;
+ int num_list_entries = artwork_info->num_list_entries;
+ struct FileInfo *file_list = artwork_info->file_list;
+ char *filename = getCustomArtworkConfigFilename(artwork_info->type);
+ struct SetupFileList *setup_file_list;
+ int i;
+
+#if 0
+ printf("GOT CUSTOM ARTWORK CONFIG FILE '%s'\n", filename);
+#endif
+
+ /* always start with reliable default values */
+ for (i=0; i<num_list_entries; i++)
+ file_list[i].filename = NULL;
+
+ if (filename == NULL)
+ return;
+
+ if ((setup_file_list = loadSetupFileList(filename)))
+ {
+ for (i=0; i<num_list_entries; i++)
+ file_list[i].filename =
+ getStringCopy(getTokenValue(setup_file_list, file_list[i].token));
- InitUserDataDirectory();
+ freeSetupFileList(setup_file_list);
- filename = getPath2(getUserDataDir(), ERROR_FILENAME);
- unlink(filename);
- free(filename);
+#if 0
+ for (i=0; i<num_list_entries; i++)
+ {
+ printf("'%s' ", file_list[i].token);
+ if (file_list[i].filename)
+ printf("-> '%s'\n", file_list[i].filename);
+ else
+ printf("-> UNDEFINED [-> '%s']\n", file_list[i].default_filename);
+ }
+#endif
+ }
}
-FILE *openErrorFile()
+static void deleteArtworkListEntry(struct ArtworkListInfo *artwork_info,
+ struct ListNodeInfo **listnode)
{
- char *filename;
- FILE *error_file;
+ if (*listnode)
+ {
+ char *filename = (*listnode)->source_filename;
+
+#if 0
+ printf("[decrementing reference counter of artwork '%s']\n", filename);
+#endif
- filename = getPath2(getUserDataDir(), ERROR_FILENAME);
- error_file = fopen(filename, MODE_APPEND);
- free(filename);
+ if (--(*listnode)->num_references <= 0)
+ {
+#if 0
+ printf("[deleting artwork '%s']\n", filename);
+#endif
- return error_file;
+ deleteNodeFromList(&artwork_info->content_list, filename,
+ artwork_info->free_artwork);
+ }
+
+ *listnode = NULL;
+ }
}
-void dumpErrorFile()
+static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
+ struct ListNodeInfo **listnode,
+ char *filename)
{
- char *filename;
- FILE *error_file;
+ ListNode *node;
+
+ /* check if the old and the new artwork file are the same */
+ if (*listnode && strcmp((*listnode)->source_filename, filename) == 0)
+ {
+ /* The old and new artwork are the same (have the same filename and path).
+ This usually means that this artwork does not exist in this artwork set
+ and a fallback to the existing artwork is done. */
+
+#if 0
+ printf("[artwork '%s' already exists (same list entry)]\n", filename);
+#endif
- filename = getPath2(getUserDataDir(), ERROR_FILENAME);
- error_file = fopen(filename, MODE_READ);
- free(filename);
+ return;
+ }
+
+ /* delete existing artwork file entry */
+ deleteArtworkListEntry(artwork_info, listnode);
+
+ /* check if the new artwork file already exists in the list of artworks */
+ if ((node = getNodeFromKey(artwork_info->content_list, filename)) != NULL)
+ {
+#if 0
+ printf("[artwork '%s' already exists (other list entry)]\n", filename);
+#endif
+
+ *listnode = (struct ListNodeInfo *)node->content;
+ (*listnode)->num_references++;
+ }
+ else if ((*listnode = artwork_info->load_artwork(filename)) != NULL)
+ {
+ (*listnode)->num_references = 1;
+ addNodeToList(&artwork_info->content_list, (*listnode)->source_filename,
+ *listnode);
+ }
+}
+
+static void LoadCustomArtwork(struct ArtworkListInfo *artwork_info,
+ struct ListNodeInfo **listnode,
+ char *basename)
+{
+ char *filename = getCustomArtworkFilename(basename, artwork_info->type);
+
+#if 0
+ printf("GOT CUSTOM ARTWORK FILE '%s'\n", filename);
+#endif
+
+ if (strcmp(basename, UNDEFINED_FILENAME) == 0)
+ {
+ deleteArtworkListEntry(artwork_info, listnode);
+ return;
+ }
+
+ if (filename == NULL)
+ {
+ Error(ERR_WARN, "cannot find artwork file '%s'", basename);
+ return;
+ }
+
+ replaceArtworkListEntry(artwork_info, listnode, filename);
+}
+
+static void LoadArtworkToList(struct ArtworkListInfo *artwork_info,
+ char *basename, int list_pos)
+{
+ if (artwork_info->artwork_list == NULL ||
+ list_pos >= artwork_info->num_list_entries)
+ return;
+
+#if 0
+ printf("loading artwork '%s' ... [%d]\n",
+ basename, getNumNodes(artwork_info->content_list));
+#endif
+
+ LoadCustomArtwork(artwork_info, &artwork_info->artwork_list[list_pos],
+ basename);
+
+#if 0
+ printf("loading artwork '%s' done [%d]\n",
+ basename, getNumNodes(artwork_info->content_list));
+#endif
+}
+
+void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
+{
+ static struct
+ {
+ char *text;
+ boolean do_it;
+ }
+ draw_init[] =
+ {
+ { "", FALSE },
+ { "Loading graphics:", TRUE },
+ { "Loading sounds:", TRUE },
+ { "Loading music:", TRUE }
+ };
+
+ int num_list_entries = artwork_info->num_list_entries;
+ struct FileInfo *file_list = artwork_info->file_list;
+ int i;
+
+ LoadArtworkConfig(artwork_info);
+
+ if (draw_init[artwork_info->type].do_it)
+ DrawInitText(draw_init[artwork_info->type].text, 120, FC_GREEN);
+
+#if 0
+ printf("DEBUG: reloading %d sounds ...\n", num_list_entries);
+#endif
+
+ for(i=0; i<num_list_entries; i++)
+ {
+ if (draw_init[artwork_info->type].do_it)
+ DrawInitText(file_list[i].token, 150, FC_YELLOW);
+
+ if (file_list[i].filename)
+ LoadArtworkToList(artwork_info, file_list[i].filename, i);
+ else
+ LoadArtworkToList(artwork_info, file_list[i].default_filename, i);
+ }
+
+ draw_init[artwork_info->type].do_it = FALSE;
+
+ /*
+ printf("list size == %d\n", getNumNodes(artwork_info->content_list));
+ */
+
+#if 0
+ dumpList(artwork_info->content_list);
+#endif
+}
+
+void FreeCustomArtworkList(struct ArtworkListInfo *artwork_info)
+{
+ int i;
+
+ if (artwork_info->artwork_list == NULL)
+ return;
+
+#if 0
+ printf("%s: FREEING ARTWORK ...\n",
+ IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
+#endif
+
+ for(i=0; i<artwork_info->num_list_entries; i++)
+ deleteArtworkListEntry(artwork_info, &artwork_info->artwork_list[i]);
+
+#if 0
+ printf("%s: FREEING ARTWORK -- DONE\n",
+ IS_CHILD_PROCESS(audio.mixer_pid) ? "CHILD" : "PARENT");
+#endif
+
+ free(artwork_info->artwork_list);
+
+ artwork_info->artwork_list = NULL;
+ artwork_info->num_list_entries = 0;
+}
+
+
+/* ========================================================================= */
+/* functions only needed for non-Unix (non-command-line) systems */
+/* (MS-DOS only; SDL/Windows creates files "stdout.txt" and "stderr.txt") */
+/* ========================================================================= */
+
+#if defined(PLATFORM_MSDOS)
+
+#define ERROR_FILENAME "stderr.txt"
+
+void initErrorFile()
+{
+ unlink(ERROR_FILENAME);
+}
+
+FILE *openErrorFile()
+{
+ return fopen(ERROR_FILENAME, MODE_APPEND);
+}
+
+void dumpErrorFile()
+{
+ FILE *error_file = fopen(ERROR_FILENAME, MODE_READ);
if (error_file != NULL)
{