X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fmisc.c;h=c32aa55515b13650e2ba97a7f21cdfd85c38def3;hp=33db03d76a76cc080df7fda89735e48008b6596d;hb=c8dd3c1abd6a1daf4f7431a59db721ae7fba3d17;hpb=d2587727d750fdf2aae4eb8f4acb487a5c211041 diff --git a/src/misc.c b/src/misc.c index 33db03d7..c32aa555 100644 --- a/src/misc.c +++ b/src/misc.c @@ -334,7 +334,12 @@ char *getPath3(char *path1, char *path2, char *path3) char *getStringCopy(char *s) { - char *s_copy = checked_malloc(strlen(s) + 1); + char *s_copy; + + if (s == NULL) + return NULL; + + s_copy = checked_malloc(strlen(s) + 1); strcpy(s_copy, s); return s_copy; @@ -347,6 +352,7 @@ char *getStringToLower(char *s) while (*s) *s_ptr++ = tolower(*s++); + *s_ptr = '\0'; return s_copy; } @@ -437,7 +443,7 @@ void GetOptions(char *argv[]) "Options:\n" " -d, --display machine:0 X server display\n" " -b, --basepath directory alternative base directory\n" - " -l, --levels directory alternative level directory\n" + " -l, --level directory alternative level directory\n" " -s, --serveronly only start network server\n" " -n, --network network multiplayer game\n" " -v, --verbose verbose mode\n", @@ -1066,9 +1072,211 @@ int getJoystickNrFromDeviceName(char *device_name) return joystick_nr; } -/* ----------------------------------------------------------------- */ -/* the following is only for debugging purpose and normally not used */ -/* ----------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* some functions to handle lists of level directories */ +/* ------------------------------------------------------------------------- */ + +struct LevelDirInfo *newLevelDirInfo() +{ + return checked_calloc(sizeof(struct LevelDirInfo)); +} + +void pushLevelDirInfo(struct LevelDirInfo **node_first, + struct LevelDirInfo *node_new) +{ + node_new->next = *node_first; + *node_first = node_new; +} + +int numLevelDirInfo(struct LevelDirInfo *node) +{ + int num = 0; + + while (node) + { + num++; + node = node->next; + } + + return num; +} + +boolean validLevelSeries(struct LevelDirInfo *node) +{ + return (node != NULL && !node->node_group && !node->parent_link); +} + +struct LevelDirInfo *getFirstValidLevelSeries(struct LevelDirInfo *node) +{ + if (node == NULL) /* start with first level directory entry */ + return getFirstValidLevelSeries(leveldir_first); + else if (node->node_group) /* enter level group (step down into tree) */ + return getFirstValidLevelSeries(node->node_group); + else if (node->parent_link) /* skip start entry of level group */ + { + if (node->next) /* get first real level series entry */ + return getFirstValidLevelSeries(node->next); + else /* leave empty level group and go on */ + return getFirstValidLevelSeries(node->node_parent->next); + } + else /* this seems to be a regular level series */ + return node; +} + +struct LevelDirInfo *getLevelDirInfoFirstGroupEntry(struct LevelDirInfo *node) +{ + if (node == NULL) + return NULL; + + if (node->node_parent == NULL) /* top level group */ + return leveldir_first; + else /* sub level group */ + return node->node_parent->node_group; +} + +int numLevelDirInfoInGroup(struct LevelDirInfo *node) +{ + return numLevelDirInfo(getLevelDirInfoFirstGroupEntry(node)); +} + +int posLevelDirInfo(struct LevelDirInfo *node) +{ + struct LevelDirInfo *node_cmp = getLevelDirInfoFirstGroupEntry(node); + int pos = 0; + + while (node_cmp) + { + if (node_cmp == node) + return pos; + + pos++; + node_cmp = node_cmp->next; + } + + return 0; +} + +struct LevelDirInfo *getLevelDirInfoFromPos(struct LevelDirInfo *node, int pos) +{ + struct LevelDirInfo *node_default = node; + int pos_cmp = 0; + + while (node) + { + if (pos_cmp == pos) + return node; + + pos_cmp++; + node = node->next; + } + + return node_default; +} + +struct LevelDirInfo *getLevelDirInfoFromFilenameExt(struct LevelDirInfo *node, + char *filename) +{ + if (filename == NULL) + return NULL; + + while (node) + { + if (node->node_group) + { + struct LevelDirInfo *node_group; + + node_group = getLevelDirInfoFromFilenameExt(node->node_group, filename); + + if (node_group) + return node_group; + } + else if (!node->parent_link) + { + if (strcmp(filename, node->filename) == 0) + return node; + } + + node = node->next; + } + + return NULL; +} + +struct LevelDirInfo *getLevelDirInfoFromFilename(char *filename) +{ + return getLevelDirInfoFromFilenameExt(leveldir_first, filename); +} + +void dumpLevelDirInfo(struct LevelDirInfo *node, int depth) +{ + int i; + + while (node) + { + for (i=0; ifilename); + + if (node->node_group != NULL) + dumpLevelDirInfo(node->node_group, depth + 1); + + node = node->next; + } +} + +void sortLevelDirInfo(struct LevelDirInfo **node_first, + int (*compare_function)(const void *, const void *)) +{ + int num_nodes = numLevelDirInfo(*node_first); + struct LevelDirInfo **sort_array; + struct LevelDirInfo *node = *node_first; + int i = 0; + + if (num_nodes == 0) + return; + + /* allocate array for sorting structure pointers */ + sort_array = checked_calloc(num_nodes * sizeof(struct LevelDirInfo *)); + + /* writing structure pointers to sorting array */ + while (i < num_nodes && node) /* double boundary check... */ + { + sort_array[i] = node; + + i++; + node = node->next; + } + + /* sorting the structure pointers in the sorting array */ + qsort(sort_array, num_nodes, sizeof(struct LevelDirInfo *), + compare_function); + + /* update the linkage of list elements with the sorted node array */ + for (i=0; inext = sort_array[i + 1]; + sort_array[num_nodes - 1]->next = NULL; + + /* update the linkage of the main list anchor pointer */ + *node_first = sort_array[0]; + + free(sort_array); + + /* now recursively sort the level group structures */ + node = *node_first; + while (node) + { + if (node->node_group != NULL) + sortLevelDirInfo(&node->node_group, compare_function); + + node = node->next; + } +} + + +/* ------------------------------------------------------------------------- */ +/* the following is only for debugging purpose and normally not used */ +/* ------------------------------------------------------------------------- */ #define DEBUG_NUM_TIMESTAMPS 3