+static boolean AddUserArtworkSetToArtworkInfoExt(char *artwork_subdir_new,
+ int type)
+{
+ // get artwork info tree node of first artwork set
+ TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
+ char *artwork_user_dir = USER_ARTWORK_DIRECTORY(type);
+
+ int draw_deactivation_mask = GetDrawDeactivationMask();
+
+ // override draw deactivation mask (temporarily disable drawing)
+ SetDrawDeactivationMask(REDRAW_ALL);
+
+ // load new artwork set config and add it next to first artwork set
+ LoadArtworkInfoFromArtworkConf(&artwork_first_node->next, NULL,
+ artwork_user_dir, artwork_subdir_new, type);
+
+ // set draw deactivation mask to previous value
+ SetDrawDeactivationMask(draw_deactivation_mask);
+
+ // get artwork info tree node of newly added artwork set
+ LevelDirTree *artwork_new = getTreeInfoFromIdentifier(artwork_first_node,
+ artwork_subdir_new);
+ if (artwork_new == NULL) // should not happen
+ return FALSE;
+
+ // correct top link and parent node link of newly created tree node
+ artwork_new->node_top = artwork_first_node->node_top;
+ artwork_new->node_parent = artwork_first_node->node_parent;
+
+ // sort artwork info tree to adjust position of newly added artwork set
+ sortTreeInfo(&artwork_first_node);
+
+ return TRUE;
+}
+
+void AddUserArtworkSetToArtworkInfo(char *artwork_subdir_new, int type)
+{
+ if (!AddUserArtworkSetToArtworkInfoExt(artwork_subdir_new, type))
+ Error(ERR_EXIT, "internal artwork set structure corrupted -- aborting");
+}
+
+static boolean AddUserTreeSetToTreeInfoExt(char *tree_subdir_new, int type)
+{
+ TreeInfo **tree_node_first, *tree_node_old, *tree_node_new;
+ char *tree_user_dir = TREE_USERDIR(type);
+
+ if (tree_user_dir == NULL) // should not happen
+ return FALSE;
+
+ // get first node of level or artwork tree
+ tree_node_first = TREE_FIRST_NODE_PTR(type);
+
+ if (tree_node_first == NULL) // should not happen
+ return FALSE;
+
+ if (type == TREE_TYPE_LEVEL_DIR)
+ {
+ // get level info tree node of personal user level set
+ tree_node_old = getTreeInfoFromIdentifier(*tree_node_first, getLoginName());
+ }
+ else
+ {
+ // get artwork info tree node of first artwork set
+ tree_node_old = *tree_node_first;
+ }
+
+ if (tree_node_old == NULL) // should not happen
+ return FALSE;
+
+ int draw_deactivation_mask = GetDrawDeactivationMask();
+
+ // override draw deactivation mask (temporarily disable drawing)
+ SetDrawDeactivationMask(REDRAW_ALL);
+
+ if (type == TREE_TYPE_LEVEL_DIR)
+ {
+ // load new level set config and add it next to first user level set
+ LoadLevelInfoFromLevelConf(&tree_node_old->next, NULL,
+ tree_user_dir, tree_subdir_new);
+ }
+ else
+ {
+ // load new artwork set config and add it next to first artwork set
+ LoadArtworkInfoFromArtworkConf(&tree_node_old->next, NULL,
+ tree_user_dir, tree_subdir_new, type);
+ }
+
+ // set draw deactivation mask to previous value
+ SetDrawDeactivationMask(draw_deactivation_mask);
+
+ // get tree info tree node of newly added tree set
+ tree_node_new = getTreeInfoFromIdentifier(*tree_node_first, tree_subdir_new);
+
+ if (tree_node_new == NULL) // should not happen
+ return FALSE;
+
+ // correct top link and parent node link of newly created tree node
+ tree_node_new->node_top = tree_node_old->node_top;
+ tree_node_new->node_parent = tree_node_old->node_parent;
+
+ // sort tree info tree to adjust position of newly added tree set
+ sortTreeInfo(tree_node_first);
+
+ return TRUE;
+}
+
+void AddUserTreeSetToTreeInfo(char *tree_subdir_new, int type)
+{
+ if (!AddUserTreeSetToTreeInfoExt(tree_subdir_new, type))
+ Error(ERR_EXIT, "internal tree set structure corrupted -- aborting");
+}
+
+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);
+
+ return getTreeInfoFromIdentifier(artwork_first_node, artwork_set);
+}
+
+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)