+ boolean is_image = tci->is_image;
+ int initial = tci->initial;
+ int nr = tci->local_nr;
+ int mode = (initial ? GAME_MODE_TITLE_INITIAL : GAME_MODE_TITLE);
+ int base = (is_image ?
+ (initial ? SND_BACKGROUND_TITLESCREEN_INITIAL_1 :
+ SND_BACKGROUND_TITLESCREEN_1) :
+ (initial ? SND_BACKGROUND_TITLEMESSAGE_INITIAL_1 :
+ SND_BACKGROUND_TITLEMESSAGE_1));
+ int sound_global = menu.sound[mode];
+ int sound_local = base + nr;
+
+#if 0
+ printf("::: %d, %d, %d: %d ['%s'], %d ['%s']\n",
+ nr, initial, is_image,
+ sound_global, getSoundListEntry(sound_global)->filename,
+ sound_local, getSoundListEntry(sound_local)->filename);
+#endif
+
+ if (!strEqual(getSoundListEntry(sound_local)->filename, UNDEFINED_FILENAME))
+ return sound_local;
+
+ if (!strEqual(getSoundListEntry(sound_global)->filename, UNDEFINED_FILENAME))
+ return sound_global;
+
+ return SND_UNDEFINED;
+}
+
+static int getTitleMusic(struct TitleControlInfo *tci)
+{
+ boolean is_image = tci->is_image;
+ int initial = tci->initial;
+ int nr = tci->local_nr;
+ int mode = (initial ? GAME_MODE_TITLE_INITIAL : GAME_MODE_TITLE);
+ int base = (is_image ?
+ (initial ? MUS_BACKGROUND_TITLESCREEN_INITIAL_1 :
+ MUS_BACKGROUND_TITLESCREEN_1) :
+ (initial ? MUS_BACKGROUND_TITLEMESSAGE_INITIAL_1 :
+ MUS_BACKGROUND_TITLEMESSAGE_1));
+ int music_global = menu.music[mode];
+ int music_local = base + nr;
+
+#if 0
+ printf("::: %d, %d, %d: %d ['%s'], %d ['%s']\n",
+ nr, initial, is_image,
+ music_global, getMusicListEntry(music_global)->filename,
+ music_local, getMusicListEntry(music_local)->filename);
+#endif
+
+ if (!strEqual(getMusicListEntry(music_local)->filename, UNDEFINED_FILENAME))
+ return music_local;
+
+ if (!strEqual(getMusicListEntry(music_global)->filename, UNDEFINED_FILENAME))
+ return music_global;
+
+ return MUS_UNDEFINED;
+}
+
+static struct TitleFadingInfo getTitleFading(struct TitleControlInfo *tci)
+{
+ boolean is_image = tci->is_image;
+ int initial = tci->initial;
+ int nr = tci->local_nr;
+ struct TitleFadingInfo ti;
+
+ if (is_image)
+ {
+ int graphic = getTitleScreenGraphic(nr, initial);
+
+ /* initialize fading control values to default title config settings */
+ ti = (initial ? title_initial_default : title_default);
+
+ /* override default settings with image config settings, if defined */
+ if (graphic_info[graphic].fade_mode != FADE_MODE_DEFAULT)
+ ti.fade_mode = graphic_info[graphic].fade_mode;
+ if (graphic_info[graphic].fade_delay > -1)
+ ti.fade_delay = graphic_info[graphic].fade_delay;
+ if (graphic_info[graphic].post_delay > -1)
+ ti.post_delay = graphic_info[graphic].post_delay;
+ if (graphic_info[graphic].auto_delay > -1)
+ ti.auto_delay = graphic_info[graphic].auto_delay;
+ }
+ else
+ {
+ if (initial)
+ {
+ ti.fade_mode = titlemessage_initial[nr].fade_mode;
+ ti.fade_delay = titlemessage_initial[nr].fade_delay;
+ ti.post_delay = titlemessage_initial[nr].post_delay;
+ ti.auto_delay = titlemessage_initial[nr].auto_delay;
+ }
+ else
+ {
+ ti.fade_mode = titlemessage[nr].fade_mode;
+ ti.fade_delay = titlemessage[nr].fade_delay;
+ ti.post_delay = titlemessage[nr].post_delay;
+ ti.auto_delay = titlemessage[nr].auto_delay;
+ }
+ }
+
+#if 0
+ if (ti.anim_mode == ANIM_NONE)
+ ti.fade_delay = ti.post_delay = 0;
+#endif
+
+ return ti;
+}
+
+static int compareTitleControlInfo(const void *object1, const void *object2)
+{
+ const struct TitleControlInfo *tci1 = (struct TitleControlInfo *)object1;
+ const struct TitleControlInfo *tci2 = (struct TitleControlInfo *)object2;
+ int compare_result;
+
+ if (tci1->initial != tci2->initial)
+ compare_result = (tci1->initial ? -1 : +1);
+ else if (tci1->sort_priority != tci2->sort_priority)
+ compare_result = tci1->sort_priority - tci2->sort_priority;
+ else if (tci1->is_image != tci2->is_image)
+ compare_result = (tci1->is_image ? -1 : +1);
+ else
+ compare_result = tci1->local_nr - tci2->local_nr;
+
+ return compare_result;
+}
+
+static void InitializeTitleControlsExt_AddTitleInfo(boolean is_image,
+ boolean initial,
+ int nr, int sort_priority)
+{
+ title_controls[num_title_screens].is_image = is_image;
+ title_controls[num_title_screens].initial = initial;
+ title_controls[num_title_screens].local_nr = nr;
+ title_controls[num_title_screens].sort_priority = sort_priority;
+
+ num_title_screens++;
+}
+
+static void InitializeTitleControls_CheckTitleInfo(boolean initial)
+{
+ int i;
+
+ for (i = 0; i < MAX_NUM_TITLE_IMAGES; i++)
+ {
+ int graphic = getTitleScreenGraphic(i, initial);
+ Bitmap *bitmap = graphic_info[graphic].bitmap;
+ int sort_priority = graphic_info[graphic].sort_priority;
+
+#if 0
+ /* skip images and messages (fonts!) when using forced custom graphics */
+ if (setup.override_level_graphics && !initial)
+ continue;
+#endif
+
+ if (bitmap != NULL)
+ InitializeTitleControlsExt_AddTitleInfo(TRUE, initial, i, sort_priority);
+ }
+
+ for (i = 0; i < MAX_NUM_TITLE_MESSAGES; i++)
+ {
+ struct TitleMessageInfo *tmi = getTitleMessageInfo(i, initial);
+ char *filename = getLevelSetTitleMessageFilename(i, initial);
+ int sort_priority = tmi->sort_priority;
+
+#if 0
+ /* skip images and messages (fonts!) when using forced custom graphics */
+ if (setup.override_level_graphics)
+ continue;
+#endif
+
+ if (filename != NULL)
+ InitializeTitleControlsExt_AddTitleInfo(FALSE, initial, i, sort_priority);
+ }
+}
+
+static void InitializeTitleControls(boolean show_title_initial)
+{
+ num_title_screens = 0;
+
+#if 1
+ /* 1st step: initialize title screens for game start (only when starting) */
+ if (show_title_initial)
+ InitializeTitleControls_CheckTitleInfo(TRUE);
+#endif
+
+ /* 2nd step: initialize title screens for current level set */
+ InitializeTitleControls_CheckTitleInfo(FALSE);
+
+ /* sort title screens according to sort_priority and title number */
+ qsort(title_controls, num_title_screens, sizeof(struct TitleControlInfo),
+ compareTitleControlInfo);
+}
+
+static boolean visibleMenuPos(struct MenuPosInfo *pos)
+{
+ return (pos != NULL && pos->x != -1 && pos->y != -1);
+}
+
+static boolean visibleTextPos(struct TextPosInfo *pos)
+{
+ return (pos != NULL && pos->x != -1 && pos->y != -1);
+}
+
+static void InitializeMainControls()
+{
+ boolean local_team_mode = (!options.network && setup.team_mode);
+ int i;
+
+ /* set main control text values to dynamically determined values */
+ sprintf(main_text_name, "%s", local_team_mode ? "Team:" : "Name:");
+
+ strcpy(main_text_first_level, int2str(leveldir_current->first_level,
+ menu.main.text.first_level.size));
+ strcpy(main_text_last_level, int2str(leveldir_current->last_level,
+ menu.main.text.last_level.size));
+ strcpy(main_text_level_number, int2str(level_nr,
+ menu.main.text.level_number.size));
+
+ main_text_level_year = leveldir_current->year;
+ main_text_level_imported_from = leveldir_current->imported_from;
+ main_text_level_imported_by = leveldir_current->imported_by;
+ main_text_level_tested_by = leveldir_current->tested_by;
+
+ /* set main control screen positions to dynamically determined values */
+ for (i = 0; main_controls[i].nr != -1; i++)
+ {
+ struct MainControlInfo *mci = &main_controls[i];
+ int nr = mci->nr;
+ struct MenuPosInfo *pos_button = mci->pos_button;
+ struct TextPosInfo *pos_text = mci->pos_text;
+ struct TextPosInfo *pos_input = mci->pos_input;
+ char *text = (mci->text ? *mci->text : NULL);
+ char *input = (mci->input ? *mci->input : NULL);
+ int button_graphic = mci->button_graphic;
+#if 1
+ int font_text = (pos_text ? pos_text->font : -1);
+ int font_input = (pos_input ? pos_input->font : -1);
+#else
+ int font_text = mci->font_text;
+ int font_input = mci->font_input;
+#endif
+
+ int font_text_width = (font_text != -1 ? getFontWidth(font_text) : 0);
+ int font_text_height = (font_text != -1 ? getFontHeight(font_text) : 0);
+ int font_input_width = (font_input != -1 ? getFontWidth(font_input) : 0);
+ int font_input_height = (font_input != -1 ? getFontHeight(font_input) : 0);
+ int text_chars = (text != NULL ? strlen(text) : 0);
+ int input_chars = (input != NULL ? strlen(input) : 0);
+
+ int button_width =
+ (button_graphic != -1 ? graphic_info[button_graphic].width : 0);
+ int button_height =
+ (button_graphic != -1 ? graphic_info[button_graphic].height : 0);
+ int text_width = font_text_width * text_chars;
+ int text_height = font_text_height;
+ int input_width = font_input_width * input_chars;
+ int input_height = font_input_height;
+
+ if (nr == MAIN_CONTROL_NAME)
+ {
+#if 0
+ if (menu.main.input.name.x == -1)
+ menu.main.input.name.x = menu.main.text.name.x + text_width;
+ if (menu.main.input.name.y == -1)
+ menu.main.input.name.y = menu.main.text.name.y;
+#endif
+
+#if 1
+ menu.main.input.name.width = input_width;
+ menu.main.input.name.height = input_height;
+#else
+ menu.main.input.name.width = font_input_width * MAX_PLAYER_NAME_LEN;
+ menu.main.input.name.height = font_input_height;
+#endif
+ }
+
+ if (pos_button != NULL) /* (x/y may be -1/-1 here) */
+ {
+ if (pos_button->width == 0)
+ pos_button->width = button_width;
+ if (pos_button->height == 0)
+ pos_button->height = button_height;
+ }
+
+ if (pos_text != NULL) /* (x/y may be -1/-1 here) */
+ {
+ /* calculate width for non-clickable text -- needed for text alignment */
+ boolean calculate_text_width = (pos_button == NULL && text != NULL);
+
+ if (visibleMenuPos(pos_button))
+ {
+ if (pos_text->x == -1)
+ pos_text->x = pos_button->x + pos_button->width;
+ if (pos_text->y == -1)
+ pos_text->y = pos_button->y;
+ }
+
+ if (pos_text->width == -1 || calculate_text_width)
+ pos_text->width = text_width;
+ if (pos_text->height == -1)
+ pos_text->height = text_height;
+ }
+
+ if (pos_input != NULL) /* (x/y may be -1/-1 here) */
+ {
+ if (visibleTextPos(pos_text))
+ {
+ if (pos_input->x == -1)
+ pos_input->x = pos_text->x + pos_text->width;
+ if (pos_input->y == -1)
+ pos_input->y = pos_text->y;
+ }
+
+ if (pos_input->width == -1)
+ pos_input->width = input_width;
+ if (pos_input->height == -1)
+ pos_input->height = input_height;
+ }
+ }
+}
+
+static void DrawCursorAndText_Main_Ext(int nr, boolean active_text,
+ boolean active_input)
+{
+ int i;
+
+ for (i = 0; main_controls[i].nr != -1; i++)
+ {
+ struct MainControlInfo *mci = &main_controls[i];
+
+ if (mci->nr == nr || nr == -1)
+ {
+ struct MenuPosInfo *pos_button = mci->pos_button;
+ struct TextPosInfo *pos_text = mci->pos_text;
+ struct TextPosInfo *pos_input = mci->pos_input;
+ char *text = (mci->text ? *mci->text : NULL);
+ char *input = (mci->input ? *mci->input : NULL);
+ int button_graphic = mci->button_graphic;
+#if 1
+ int font_text = (pos_text ? pos_text->font : -1);
+ int font_input = (pos_input ? pos_input->font : -1);
+#else
+ int font_text = mci->font_text;
+ int font_input = mci->font_input;
+#endif
+
+ if (active_text)
+ {
+ button_graphic = BUTTON_ACTIVE(button_graphic);
+ font_text = FONT_ACTIVE(font_text);
+ }
+
+ if (active_input)
+ {
+ font_input = FONT_ACTIVE(font_input);
+ }
+
+ if (visibleMenuPos(pos_button))
+ {
+ struct MenuPosInfo *pos = pos_button;
+ int x = mSX + pos->x;
+ int y = mSY + pos->y;
+
+ DrawBackgroundForGraphic(x, y, pos->width, pos->height, button_graphic);
+ DrawGraphicThruMaskExt(drawto, x, y, button_graphic, 0);
+ }
+
+ if (visibleTextPos(pos_text) && text != NULL)
+ {
+ struct TextPosInfo *pos = pos_text;
+ int x = mSX + ALIGNED_TEXT_XPOS(pos);
+ int y = mSY + ALIGNED_TEXT_YPOS(pos);
+
+#if 1
+ /* (check why/if this is needed) */
+ DrawBackgroundForFont(x, y, pos->width, pos->height, font_text);
+#endif
+ DrawText(x, y, text, font_text);
+ }
+
+ if (visibleTextPos(pos_input) && input != NULL)
+ {
+ struct TextPosInfo *pos = pos_input;
+ int x = mSX + ALIGNED_TEXT_XPOS(pos);
+ int y = mSY + ALIGNED_TEXT_YPOS(pos);
+
+#if 1
+ /* (check why/if this is needed) */
+ DrawBackgroundForFont(x, y, pos->width, pos->height, font_input);
+#endif
+ DrawText(x, y, input, font_input);
+ }
+ }
+ }
+}
+
+static void DrawCursorAndText_Main(int nr, boolean active_text)
+{
+ DrawCursorAndText_Main_Ext(nr, active_text, FALSE);
+}
+
+#if 0
+static void DrawCursorAndText_Main_Input(int nr, boolean active_text)
+{
+ DrawCursorAndText_Main_Ext(nr, active_text, TRUE);
+}
+#endif
+
+static struct MainControlInfo *getMainControlInfo(int nr)
+{
+ int i;
+
+ for (i = 0; main_controls[i].nr != -1; i++)
+ if (main_controls[i].nr == nr)
+ return &main_controls[i];
+
+ return NULL;
+}
+
+static boolean insideMenuPosRect(struct MenuPosInfo *rect, int x, int y)
+{
+ if (rect == NULL)
+ return FALSE;
+
+ int rect_x = ALIGNED_TEXT_XPOS(rect);
+ int rect_y = ALIGNED_TEXT_YPOS(rect);
+
+ return (x >= rect_x && x < rect_x + rect->width &&
+ y >= rect_y && y < rect_y + rect->height);
+}
+
+static boolean insideTextPosRect(struct TextPosInfo *rect, int x, int y)
+{
+ if (rect == NULL)
+ return FALSE;
+
+ int rect_x = ALIGNED_TEXT_XPOS(rect);
+ int rect_y = ALIGNED_TEXT_YPOS(rect);
+
+ return (x >= rect_x && x < rect_x + rect->width &&
+ y >= rect_y && y < rect_y + rect->height);
+}
+
+static void drawCursorExt(int xpos, int ypos, boolean active, int graphic)
+{
+#if 1
+ static int cursor_array[MAX_LEV_FIELDY];
+#else