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; i<depth * 3; i++)
+ printf(" ");
+
+ printf("filename == '%s'\n", node->filename);
+
+ 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; i<num_nodes - 1; i++)
+ sort_array[i]->next = 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