+SetupFileHash *loadSetupFileHash(char *filename)
+{
+ SetupFileHash *setup_file_hash = newSetupFileHash();
+
+ if (!loadSetupFileData(setup_file_hash, filename, TRUE, TRUE))
+ {
+ freeSetupFileHash(setup_file_hash);
+
+ return NULL;
+ }
+
+ return setup_file_hash;
+}
+
+void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
+ char *filename, char *identifier)
+{
+ char *value = getHashEntry(setup_file_hash, TOKEN_STR_FILE_IDENTIFIER);
+
+ if (value == NULL)
+ Error(ERR_WARN, "config file '%s' has no file identifier", filename);
+ else if (!checkCookieString(value, identifier))
+ Error(ERR_WARN, "config file '%s' has wrong file identifier", filename);
+}
+
+
+/* ========================================================================= */
+/* setup file stuff */
+/* ========================================================================= */
+
+#define TOKEN_STR_LAST_LEVEL_SERIES "last_level_series"
+#define TOKEN_STR_LAST_PLAYED_LEVEL "last_played_level"
+#define TOKEN_STR_HANDICAP_LEVEL "handicap_level"
+
+/* level directory info */
+#define LEVELINFO_TOKEN_IDENTIFIER 0
+#define LEVELINFO_TOKEN_NAME 1
+#define LEVELINFO_TOKEN_NAME_SORTING 2
+#define LEVELINFO_TOKEN_AUTHOR 3
+#define LEVELINFO_TOKEN_YEAR 4
+#define LEVELINFO_TOKEN_IMPORTED_FROM 5
+#define LEVELINFO_TOKEN_IMPORTED_BY 6
+#define LEVELINFO_TOKEN_TESTED_BY 7
+#define LEVELINFO_TOKEN_LEVELS 8
+#define LEVELINFO_TOKEN_FIRST_LEVEL 9
+#define LEVELINFO_TOKEN_SORT_PRIORITY 10
+#define LEVELINFO_TOKEN_LATEST_ENGINE 11
+#define LEVELINFO_TOKEN_LEVEL_GROUP 12
+#define LEVELINFO_TOKEN_READONLY 13
+#define LEVELINFO_TOKEN_GRAPHICS_SET_ECS 14
+#define LEVELINFO_TOKEN_GRAPHICS_SET_AGA 15
+#define LEVELINFO_TOKEN_GRAPHICS_SET 16
+#define LEVELINFO_TOKEN_SOUNDS_SET 17
+#define LEVELINFO_TOKEN_MUSIC_SET 18
+#define LEVELINFO_TOKEN_FILENAME 19
+#define LEVELINFO_TOKEN_FILETYPE 20
+#define LEVELINFO_TOKEN_HANDICAP 21
+#define LEVELINFO_TOKEN_SKIP_LEVELS 22
+
+#define NUM_LEVELINFO_TOKENS 23
+
+static LevelDirTree ldi;
+
+static struct TokenInfo levelinfo_tokens[] =
+{
+ /* level directory info */
+ { TYPE_STRING, &ldi.identifier, "identifier" },
+ { TYPE_STRING, &ldi.name, "name" },
+ { TYPE_STRING, &ldi.name_sorting, "name_sorting" },
+ { TYPE_STRING, &ldi.author, "author" },
+ { TYPE_STRING, &ldi.year, "year" },
+ { TYPE_STRING, &ldi.imported_from, "imported_from" },
+ { TYPE_STRING, &ldi.imported_by, "imported_by" },
+ { TYPE_STRING, &ldi.tested_by, "tested_by" },
+ { TYPE_INTEGER, &ldi.levels, "levels" },
+ { TYPE_INTEGER, &ldi.first_level, "first_level" },
+ { TYPE_INTEGER, &ldi.sort_priority, "sort_priority" },
+ { TYPE_BOOLEAN, &ldi.latest_engine, "latest_engine" },
+ { TYPE_BOOLEAN, &ldi.level_group, "level_group" },
+ { TYPE_BOOLEAN, &ldi.readonly, "readonly" },
+ { 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_STRING, &ldi.level_filename, "filename" },
+ { TYPE_STRING, &ldi.level_filetype, "filetype" },
+ { TYPE_BOOLEAN, &ldi.handicap, "handicap" },
+ { TYPE_BOOLEAN, &ldi.skip_levels, "skip_levels" }
+};
+
+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)