+ // sort tree info to adjust position of newly added tree set
+ sortTreeInfo(tree_node_first);
+
+ return TRUE;
+}
+
+void AddTreeSetToTreeInfo(TreeInfo *tree_node, char *tree_dir,
+ char *tree_subdir_new, int type)
+{
+ if (!AddTreeSetToTreeInfoExt(tree_node, tree_dir, tree_subdir_new, type))
+ Fail("internal tree info structure corrupted -- aborting");
+}
+
+void AddUserLevelSetToLevelInfo(char *level_subdir_new)
+{
+ AddTreeSetToTreeInfo(NULL, NULL, level_subdir_new, TREE_TYPE_LEVEL_DIR);
+}
+
+char *getArtworkIdentifierForUserLevelSet(int type)
+{
+ char *classic_artwork_set = getClassicArtworkSet(type);
+
+ // check for custom artwork configured in "levelinfo.conf"
+ char *leveldir_artwork_set =
+ *LEVELDIR_ARTWORK_SET_PTR(leveldir_current, type);
+ boolean has_leveldir_artwork_set =
+ (leveldir_artwork_set != NULL && !strEqual(leveldir_artwork_set,
+ classic_artwork_set));
+
+ // check for custom artwork in sub-directory "graphics" etc.
+ TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
+ char *leveldir_identifier = leveldir_current->identifier;
+ boolean has_artwork_subdir =
+ (getTreeInfoFromIdentifier(artwork_first_node,
+ leveldir_identifier) != NULL);
+
+ return (has_leveldir_artwork_set ? leveldir_artwork_set :
+ has_artwork_subdir ? leveldir_identifier :
+ classic_artwork_set);
+}
+
+TreeInfo *getArtworkTreeInfoForUserLevelSet(int type)
+{
+ char *artwork_set = getArtworkIdentifierForUserLevelSet(type);
+ TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
+ TreeInfo *ti = getTreeInfoFromIdentifier(artwork_first_node, artwork_set);
+
+ if (ti == NULL)
+ {
+ ti = getTreeInfoFromIdentifier(artwork_first_node,
+ ARTWORK_DEFAULT_SUBDIR(type));
+ if (ti == NULL)
+ Fail("cannot find default graphics -- should not happen");
+ }
+
+ return ti;
+}
+
+boolean checkIfCustomArtworkExistsForCurrentLevelSet(void)
+{
+ char *graphics_set =
+ getArtworkIdentifierForUserLevelSet(ARTWORK_TYPE_GRAPHICS);
+ char *sounds_set =
+ getArtworkIdentifierForUserLevelSet(ARTWORK_TYPE_SOUNDS);
+ char *music_set =
+ getArtworkIdentifierForUserLevelSet(ARTWORK_TYPE_MUSIC);
+
+ return (!strEqual(graphics_set, GFX_CLASSIC_SUBDIR) ||
+ !strEqual(sounds_set, SND_CLASSIC_SUBDIR) ||
+ !strEqual(music_set, MUS_CLASSIC_SUBDIR));
+}
+
+boolean UpdateUserLevelSet(char *level_subdir, char *level_name,
+ char *level_author, int num_levels)
+{
+ char *filename = getPath2(getUserLevelDir(level_subdir), LEVELINFO_FILENAME);
+ char *filename_tmp = getStringCat2(filename, ".tmp");
+ FILE *file = NULL;
+ FILE *file_tmp = NULL;
+ char line[MAX_LINE_LEN];
+ boolean success = FALSE;
+ LevelDirTree *leveldir = getTreeInfoFromIdentifier(leveldir_first,
+ level_subdir);
+ // update values in level directory tree
+
+ if (level_name != NULL)
+ setString(&leveldir->name, level_name);
+
+ if (level_author != NULL)
+ setString(&leveldir->author, level_author);
+
+ if (num_levels != -1)
+ leveldir->levels = num_levels;
+
+ // update values that depend on other values
+
+ setString(&leveldir->name_sorting, leveldir->name);
+
+ leveldir->last_level = leveldir->first_level + leveldir->levels - 1;
+
+ // sort order of level sets may have changed
+ sortTreeInfo(&leveldir_first);
+
+ if ((file = fopen(filename, MODE_READ)) &&
+ (file_tmp = fopen(filename_tmp, MODE_WRITE)))
+ {
+ while (fgets(line, MAX_LINE_LEN, file))
+ {
+ if (strPrefix(line, "name:") && level_name != NULL)
+ fprintf(file_tmp, "%-32s%s\n", "name:", level_name);
+ else if (strPrefix(line, "author:") && level_author != NULL)
+ fprintf(file_tmp, "%-32s%s\n", "author:", level_author);
+ else if (strPrefix(line, "levels:") && num_levels != -1)
+ fprintf(file_tmp, "%-32s%d\n", "levels:", num_levels);
+ else
+ fputs(line, file_tmp);
+ }
+
+ success = TRUE;
+ }
+
+ if (file)
+ fclose(file);
+
+ if (file_tmp)
+ fclose(file_tmp);
+
+ if (success)
+ success = (rename(filename_tmp, filename) == 0);
+
+ free(filename);
+ free(filename_tmp);
+
+ return success;
+}
+
+boolean CreateUserLevelSet(char *level_subdir, char *level_name,
+ char *level_author, int num_levels,
+ boolean use_artwork_set)
+{
+ LevelDirTree *level_info;
+ char *filename;
+ FILE *file;
+ int i;
+
+ // create user level sub-directory, if needed
+ createDirectory(getUserLevelDir(level_subdir), "user level", PERMS_PRIVATE);
+
+ filename = getPath2(getUserLevelDir(level_subdir), LEVELINFO_FILENAME);
+
+ if (!(file = fopen(filename, MODE_WRITE)))
+ {
+ Warn("cannot write level info file '%s'", filename);
+
+ free(filename);
+
+ return FALSE;
+ }
+
+ level_info = newTreeInfo();
+
+ // always start with reliable default values
+ setTreeInfoToDefaults(level_info, TREE_TYPE_LEVEL_DIR);
+
+ setString(&level_info->name, level_name);
+ setString(&level_info->author, level_author);
+ level_info->levels = num_levels;
+ level_info->first_level = 1;
+ level_info->sort_priority = LEVELCLASS_PRIVATE_START;
+ level_info->readonly = FALSE;
+
+ if (use_artwork_set)
+ {
+ level_info->graphics_set =
+ getStringCopy(getArtworkIdentifierForUserLevelSet(ARTWORK_TYPE_GRAPHICS));
+ level_info->sounds_set =
+ getStringCopy(getArtworkIdentifierForUserLevelSet(ARTWORK_TYPE_SOUNDS));
+ level_info->music_set =
+ getStringCopy(getArtworkIdentifierForUserLevelSet(ARTWORK_TYPE_MUSIC));
+ }
+
+ token_value_position = TOKEN_VALUE_POSITION_SHORT;
+
+ fprintFileHeader(file, LEVELINFO_FILENAME);
+
+ ldi = *level_info;