+ free(s_lower);
+
+ return result;
+}
+
+int get_switch3_from_string(char *s)
+{
+ char *s_lower = getStringToLower(s);
+ int result = FALSE;
+
+ if (strEqual(s_lower, "true") ||
+ strEqual(s_lower, "yes") ||
+ strEqual(s_lower, "on") ||
+ get_integer_from_string(s) == 1)
+ result = TRUE;
+ else if (strEqual(s_lower, "auto"))
+ result = AUTO;
+
+ free(s_lower);
+
+ return result;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* functions for generic lists */
+/* ------------------------------------------------------------------------- */
+
+ListNode *newListNode()
+{
+ return checked_calloc(sizeof(ListNode));
+}
+
+void addNodeToList(ListNode **node_first, char *key, void *content)
+{
+ ListNode *node_new = newListNode();
+
+ node_new->key = getStringCopy(key);
+ node_new->content = content;
+ node_new->next = *node_first;
+
+ if (*node_first)
+ (*node_first)->prev = node_new;
+
+ *node_first = node_new;
+}
+
+void deleteNodeFromList(ListNode **node_first, char *key,
+ void (*destructor_function)(void *))
+{
+ if (node_first == NULL || *node_first == NULL)
+ return;
+
+ if (strEqual((*node_first)->key, key))
+ {
+ checked_free((*node_first)->key);
+
+ if (destructor_function)
+ destructor_function((*node_first)->content);
+
+ if ((*node_first)->next)
+ (*node_first)->next->prev = (*node_first)->prev;
+
+ checked_free(*node_first);
+
+ *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 (strEqual(node_first->key, key))
+ 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 file handling */
+/* ------------------------------------------------------------------------- */
+
+File *openFile(char *filename, char *mode)
+{
+ File *file = checked_calloc(sizeof(File));
+
+ file->file = fopen(filename, mode);
+
+ if (file->file != NULL)
+ {
+ file->filename = getStringCopy(filename);
+
+ return file;
+ }
+
+#if defined(PLATFORM_ANDROID)
+ file->asset_file = SDL_RWFromFile(filename, mode);
+
+ if (file->asset_file != NULL)
+ {
+ file->file_is_asset = TRUE;
+ file->filename = getStringCopy(filename);
+
+ return file;
+ }
+#endif
+
+ checked_free(file);
+
+ return NULL;
+}
+
+int closeFile(File *file)
+{
+ if (file == NULL)
+ return -1;
+
+ int result = 0;
+
+#if defined(PLATFORM_ANDROID)
+ if (file->asset_file)
+ result = SDL_RWclose(file->asset_file);
+#endif
+
+ if (file->file)
+ result = fclose(file->file);
+
+ checked_free(file->filename);
+ checked_free(file);