+static int compareLevelDirInfoEntries(const void *object1, const void *object2)
+{
+ const struct LevelDirInfo *entry1 = object1;
+ const struct LevelDirInfo *entry2 = object2;
+ int compare_result;
+
+ if (entry1->sort_priority != entry2->sort_priority)
+ compare_result = entry1->sort_priority - entry2->sort_priority;
+ else
+ {
+ char *name1 = getStringToLower(entry1->name);
+ char *name2 = getStringToLower(entry2->name);
+
+ compare_result = strcmp(name1, name2);
+
+ free(name1);
+ free(name2);
+ }
+
+ return compare_result;
+}
+
+static int LoadLevelInfoFromLevelDir(char *level_directory, int start_entry)
+{
+ DIR *dir;
+ struct stat file_status;
+ char *directory = NULL;
+ char *filename = NULL;
+ struct SetupFileList *setup_file_list = NULL;
+ struct dirent *dir_entry;
+ int i, current_entry = start_entry;
+
+ if ((dir = opendir(level_directory)) == NULL)
+ {
+ Error(ERR_WARN, "cannot read level directory '%s'", level_directory);
+ return current_entry;
+ }
+
+ while (current_entry < MAX_LEVDIR_ENTRIES)
+ {
+ if ((dir_entry = readdir(dir)) == NULL) /* last directory entry */
+ break;
+
+ /* skip entries for current and parent directory */
+ if (strcmp(dir_entry->d_name, ".") == 0 ||
+ strcmp(dir_entry->d_name, "..") == 0)
+ continue;
+
+ /* find out if directory entry is itself a directory */
+ directory = getPath2(level_directory, dir_entry->d_name);
+ if (stat(directory, &file_status) != 0 || /* cannot stat file */
+ (file_status.st_mode & S_IFMT) != S_IFDIR) /* not a directory */
+ {
+ free(directory);
+ continue;
+ }
+
+ filename = getPath2(directory, LEVELINFO_FILENAME);
+ setup_file_list = loadSetupFileList(filename);
+
+ if (setup_file_list)
+ {
+ checkSetupFileListIdentifier(setup_file_list, LEVELINFO_COOKIE);
+ setLevelDirInfoToDefaults(&leveldir[current_entry]);
+
+ ldi = leveldir[current_entry];
+ for (i=FIRST_LEVELINFO_TOKEN; i<=LAST_LEVELINFO_TOKEN; i++)
+ setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text));
+ leveldir[current_entry] = ldi;
+
+ leveldir[current_entry].filename = getStringCopy(dir_entry->d_name);
+ leveldir[current_entry].last_level =
+ leveldir[current_entry].first_level +
+ leveldir[current_entry].levels - 1;
+ leveldir[current_entry].user_defined =
+ (level_directory == options.level_directory ? FALSE : TRUE);
+ leveldir[current_entry].color = LEVELCOLOR(current_entry);
+
+ freeSetupFileList(setup_file_list);
+ current_entry++;
+ }
+ else
+ Error(ERR_WARN, "ignoring level directory '%s'", directory);
+
+ free(directory);
+ free(filename);
+ }
+
+ if (current_entry == MAX_LEVDIR_ENTRIES)
+ Error(ERR_WARN, "using %d level directories -- ignoring the rest",
+ current_entry);
+
+ closedir(dir);
+
+ if (current_entry == start_entry)
+ Error(ERR_WARN, "cannot find any valid level series in directory '%s'",
+ level_directory);
+
+ return current_entry;
+}
+
+void LoadLevelInfo()
+{
+ InitUserLevelDirectory(getLoginName());
+
+ num_leveldirs = 0;
+ leveldir_nr = 0;
+
+ num_leveldirs = LoadLevelInfoFromLevelDir(options.level_directory,
+ num_leveldirs);
+ num_leveldirs = LoadLevelInfoFromLevelDir(getUserLevelDir(""),
+ num_leveldirs);
+
+ if (num_leveldirs == 0)
+ Error(ERR_EXIT, "cannot find any valid level series in any directory");
+
+ if (num_leveldirs > 1)
+ qsort(leveldir, num_leveldirs, sizeof(struct LevelDirInfo),
+ compareLevelDirInfoEntries);
+}
+
+static void SaveUserLevelInfo()
+{
+ char *filename;
+ FILE *file;
+ int i;
+
+ filename = getPath2(getUserLevelDir(getLoginName()), LEVELINFO_FILENAME);
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot write level info file '%s'", filename);
+ free(filename);
+ return;
+ }
+
+ /* always start with reliable default values */
+ setLevelDirInfoToDefaults(&ldi);
+
+ ldi.name = getLoginName();
+ ldi.author = getRealName();
+ ldi.levels = 100;
+ ldi.first_level = 1;
+ ldi.sort_priority = LEVELCLASS_USER_START;
+ ldi.readonly = FALSE;
+
+ fprintf(file, "%s\n\n",
+ getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, LEVELINFO_COOKIE));
+
+ for (i=FIRST_LEVELINFO_TOKEN; i<=LAST_LEVELINFO_TOKEN; i++)
+ fprintf(file, "%s\n", getSetupLine("", i));
+
+ fclose(file);
+ free(filename);
+
+ chmod(filename, SETUP_PERMS);
+}
+