fixed info screen menu handling to correctly use 'menu.list_size.INFO'
[rocksndiamonds.git] / src / screens.c
index 6757061efb78766868ebd0b08f354ca4073d4aca..cb979767cbd2360bbeaddcefc1b4493bd668004b 100644 (file)
                                         MENU_SCREEN_INFO_YSTART2 -     \
                                         TILEY / 2)
 #define MAX_INFO_ELEMENTS_ON_SCREEN    128
-#define NUM_INFO_ELEMENTS_ON_SCREEN    MIN(MENU_SCREEN_INFO_YSIZE /    \
-                                            MENU_SCREEN_INFO_YSTEP,    \
-                                            MAX_INFO_ELEMENTS_ON_SCREEN)
+#define STD_INFO_ELEMENTS_ON_SCREEN    (MENU_SCREEN_INFO_YSIZE /       \
+                                        MENU_SCREEN_INFO_YSTEP)
+#define NUM_INFO_ELEMENTS_FROM_CONF    \
+  (menu.list_size_info[GFX_SPECIAL_ARG_INFO_ELEMENTS] > 0 ?            \
+   menu.list_size_info[GFX_SPECIAL_ARG_INFO_ELEMENTS] :                        \
+   MAX_MENU_ENTRIES_ON_SCREEN)
+#define NUM_INFO_ELEMENTS_ON_SCREEN    MIN(MIN(STD_INFO_ELEMENTS_ON_SCREEN, \
+                                                MAX_INFO_ELEMENTS_ON_SCREEN), \
+                                           NUM_INFO_ELEMENTS_FROM_CONF)
 #define MAX_MENU_ENTRIES_ON_SCREEN     (SCR_FIELDY - MENU_SCREEN_START_YPOS)
 #define MAX_MENU_TEXT_LENGTH_BIG       13
 #define MAX_MENU_TEXT_LENGTH_MEDIUM    (MAX_MENU_TEXT_LENGTH_BIG * 2)
@@ -504,9 +510,6 @@ static char *main_text_level_year           = NULL;
 static char *main_text_level_imported_from     = NULL;
 static char *main_text_level_imported_by       = NULL;
 static char *main_text_level_tested_by         = NULL;
-static char *main_text_title_1                 = PROGRAM_TITLE_STRING;
-static char *main_text_title_2                 = PROGRAM_COPYRIGHT_STRING;
-static char *main_text_title_3                 = PROGRAM_GAME_BY_STRING;
 
 struct MainControlInfo
 {
@@ -656,19 +659,19 @@ static struct MainControlInfo main_controls[] =
   {
     MAIN_CONTROL_TITLE_1,
     NULL,                              -1,
-    &menu.main.text.title_1,           &main_text_title_1,
+    &menu.main.text.title_1,           &setup.internal.program_title,
     NULL,                              NULL,
   },
   {
     MAIN_CONTROL_TITLE_2,
     NULL,                              -1,
-    &menu.main.text.title_2,           &main_text_title_2,
+    &menu.main.text.title_2,           &setup.internal.program_copyright,
     NULL,                              NULL,
   },
   {
     MAIN_CONTROL_TITLE_3,
     NULL,                              -1,
-    &menu.main.text.title_3,           &main_text_title_3,
+    &menu.main.text.title_3,           &setup.internal.program_company,
     NULL,                              NULL,
   },
 
@@ -1165,6 +1168,38 @@ static boolean insideTextPosRect(struct TextPosInfo *rect, int x, int y)
          y >= rect_y && y < rect_y + rect->height);
 }
 
+static void AdjustScrollbar(int id, int items_max, int items_visible,
+                           int item_position)
+{
+  struct GadgetInfo *gi = screen_gadget[id];
+
+  if (item_position > items_max - items_visible)
+    item_position = items_max - items_visible;
+
+  ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
+              GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
+              GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
+}
+
+static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti)
+{
+  AdjustScrollbar(id, numTreeInfoInGroup(ti), NUM_MENU_ENTRIES_ON_SCREEN,
+                 first_entry);
+}
+
+static void clearMenuListArea()
+{
+  int scrollbar_xpos = mSX + SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset;
+
+  /* correct scrollbar position if placed outside menu (playfield) area */
+  if (scrollbar_xpos > SX + SC_SCROLLBAR_XPOS)
+    scrollbar_xpos = SX + SC_SCROLLBAR_XPOS;
+
+  /* clear menu list area, but not title or scrollbar */
+  DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
+                 scrollbar_xpos - mSX, NUM_MENU_ENTRIES_ON_SCREEN * 32);
+}
+
 static void drawCursorExt(int xpos, int ypos, boolean active, int graphic)
 {
   static int cursor_array[MAX_LEV_FIELDY];
@@ -1212,8 +1247,9 @@ static void drawChooseTreeCursor(int ypos, boolean active)
 
 void DrawHeadline()
 {
-  DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, PROGRAM_TITLE_STRING);
-  DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2, PROGRAM_COPYRIGHT_STRING);
+  DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, getProgramTitleString());
+  DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2,
+                   setup.internal.program_copyright);
 }
 
 int effectiveGameStatus()
@@ -1473,11 +1509,11 @@ void DrawMainMenu()
   DrawMainMenuExt(REDRAW_ALL, FALSE);
 }
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
 static void gotoTopLevelDir()
 {
-  /* move upwards to top level directory */
-  while (leveldir_current->node_parent)
+  /* move upwards until inside (but not above) top level directory */
+  while (leveldir_current->node_parent &&
+        !strEqual(leveldir_current->node_parent->subdir, STRING_TOP_DIRECTORY))
   {
     /* write a "path" into level tree for easy navigation to last level */
     if (leveldir_current->node_parent->node_group->cl_first == -1)
@@ -1502,7 +1538,6 @@ static void gotoTopLevelDir()
     leveldir_current = leveldir_current->node_parent;
   }
 }
-#endif
 
 void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
 {
@@ -1764,7 +1799,14 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
       button_pressed = TRUE;
 
     if (button_pressed != button_pressed_last)
+    {
       DrawCursorAndText_Main(choice, TRUE, button_pressed);
+
+      if (button_pressed)
+       PlaySound(SND_MENU_BUTTON_PRESSING);
+      else
+       PlaySound(SND_MENU_BUTTON_RELEASING);
+    }
   }
   else if (dx || dy)   /* keyboard input */
   {
@@ -1828,9 +1870,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
          SaveLevelSetup_LastSeries();
          SaveLevelSetup_SeriesInfo();
 
-#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
-         gotoTopLevelDir();
-#endif
+         if (setup.internal.choose_from_top_leveldir)
+           gotoTopLevelDir();
 
          ChangeViewportPropertiesIfNeeded();
 
@@ -1901,7 +1942,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 /* ========================================================================= */
 
 static struct TokenInfo *info_info;
-static int num_info_info;
+static int num_info_info;      /* number of info entries shown on screen */
+static int max_info_info;      /* total number of info entries in list */
 
 static void execInfoTitleScreen()
 {
@@ -1974,19 +2016,54 @@ static struct TokenInfo info_info_main[] =
   { 0,                 NULL,                   NULL                    }
 };
 
-static void DrawCursorAndText_Info(int pos, boolean active)
+static void DrawCursorAndText_Info(int screen_pos, int info_info_pos_raw,
+                                   boolean active)
 {
+  int ii_pos = (info_info_pos_raw < 0 ? screen_pos : info_info_pos_raw);
+  struct TokenInfo *ii = &info_info[ii_pos];
   int xpos = MENU_SCREEN_START_XPOS;
-  int ypos = MENU_SCREEN_START_YPOS + pos;
+  int ypos = MENU_SCREEN_START_YPOS + screen_pos;
   int font_nr = FONT_MENU_1;
 
   if (active)
     font_nr = FONT_ACTIVE(font_nr);
 
-  DrawText(mSX + xpos * 32, mSY + ypos * 32, info_info[pos].text, font_nr);
+  DrawText(mSX + xpos * 32, mSY + ypos * 32, ii->text, font_nr);
+
+  if (ii->type & ~TYPE_SKIP_ENTRY)
+    drawCursor(screen_pos, active);
+}
+
+static void drawInfoInfoList(struct TokenInfo *info_info,
+                            int first_entry, int num_page_entries)
+{
+  int i;
+
+  if (num_page_entries > NUM_MENU_ENTRIES_ON_SCREEN)
+    num_page_entries = NUM_MENU_ENTRIES_ON_SCREEN;
+
+  if (num_page_entries > max_info_info)
+    num_page_entries = max_info_info;
+
+  if (first_entry + num_page_entries > max_info_info)
+    first_entry = 0;
+
+  clearMenuListArea();
+
+  for (i = 0; i < num_page_entries; i++)
+  {
+    int info_info_pos = first_entry + i;
+    struct TokenInfo *ii = &info_info[info_info_pos];
+
+    if (ii->type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
+      initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
+    else if (ii->type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST))
+      initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
+    else if (ii->type & ~TYPE_SKIP_ENTRY)
+      initCursor(i, IMG_MENU_BUTTON);
 
-  if (info_info[pos].type & ~TYPE_SKIP_ENTRY)
-    drawCursor(pos, active);
+    DrawCursorAndText_Info(i, info_info_pos, FALSE);
+  }
 }
 
 static void DrawInfoScreen_Main(int fade_mask, boolean do_fading)
@@ -1994,6 +2071,10 @@ static void DrawInfoScreen_Main(int fade_mask, boolean do_fading)
   int i;
 
   UnmapAllGadgets();
+
+  FreeScreenGadgets();
+  CreateScreenGadgets();
+
   CloseDoor(DOOR_CLOSE_2);
 
   /* (needed after displaying title screens which disable auto repeat) */
@@ -2015,24 +2096,21 @@ static void DrawInfoScreen_Main(int fade_mask, boolean do_fading)
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Info Screen");
 
   info_info = info_info_main;
-  num_info_info = 0;
 
+  // determine maximal number of info entries that can be displayed on screen
+  num_info_info = 0;
   for (i = 0; info_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
-  {
-    if (info_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
-      initCursor(i, IMG_MENU_BUTTON_ENTER_MENU);
-    else if (info_info[i].type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST))
-      initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU);
-    else if (info_info[i].type & ~TYPE_SKIP_ENTRY)
-      initCursor(i, IMG_MENU_BUTTON);
-
-    DrawCursorAndText_Info(i, FALSE);
-
     num_info_info++;
-  }
+
+  // determine maximal number of info entries available for menu of info screen
+  max_info_info = 0;
+  for (i = 0; info_info[i].type != 0; i++)
+    max_info_info++;
 
   HandleInfoScreen_Main(0, 0, 0, 0, MB_MENU_INITIALIZE);
 
+  MapScreenGadgets(max_info_info);
+
   PlayMenuSound();
   PlayMenuMusic();
 
@@ -2046,19 +2124,69 @@ static void DrawInfoScreen_Main(int fade_mask, boolean do_fading)
 void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button)
 {
   static int choice_store[MAX_INFO_MODES];
-  int choice = choice_store[info_mode];                /* always starts with 0 */
+  static int first_entry_store[MAX_INFO_MODES];
+  static int num_page_entries_last = 0;
+  int choice = choice_store[info_mode];                        /* starts with 0 */
+  int first_entry = first_entry_store[info_mode];      /* starts with 0 */
   int x = 0;
-  int y = choice;
+  int y = choice - first_entry;
+  int y_old = y;
+  boolean position_set_by_scrollbar = (dx == 999);
+  int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
+  int num_page_entries;
+
+  num_page_entries = MIN(max_info_info, NUM_MENU_ENTRIES_ON_SCREEN);
 
   if (button == MB_MENU_INITIALIZE)
   {
+    // check if number of menu page entries has changed (may happen by change
+    // of custom artwork definition value for 'list_size' for this menu screen)
+    // (in this case, the last menu position most probably has to be corrected)
+    if (num_page_entries != num_page_entries_last)
+    {
+      int i;
+
+      for (i = 0; i < MAX_INFO_MODES; i++)
+       choice_store[i] = first_entry_store[i] = 0;
+
+      num_page_entries_last = num_page_entries;
+
+      HandleInfoScreen_Main(mx, my, dx, dy, button);
+
+      return;
+    }
+
     /* advance to first valid menu entry */
     while (choice < num_info_info &&
           info_info[choice].type & TYPE_SKIP_ENTRY)
       choice++;
+
+    if (position_set_by_scrollbar)
+      first_entry = first_entry_store[info_mode] = dy;
+    else
+      AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_info_info,
+                     NUM_MENU_ENTRIES_ON_SCREEN, first_entry);
+
+    drawInfoInfoList(info_info, first_entry, NUM_MENU_ENTRIES_ON_SCREEN);
+
+    if (choice < first_entry)
+    {
+      choice = first_entry;
+
+      if (info_info[choice].type & TYPE_SKIP_ENTRY)
+       choice++;
+    }
+    else if (choice > first_entry + num_page_entries - 1)
+    {
+      choice = first_entry + num_page_entries - 1;
+
+      if (info_info[choice].type & TYPE_SKIP_ENTRY)
+       choice--;
+    }
+
     choice_store[info_mode] = choice;
 
-    DrawCursorAndText_Info(choice, TRUE);
+    DrawCursorAndText_Info(choice - first_entry, choice, TRUE);
 
     return;
   }
@@ -2086,51 +2214,165 @@ void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button)
     x = (mx - mSX) / 32;
     y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS;
   }
-  else if (dx || dy)   /* keyboard input */
+  else if (dx || dy)   /* keyboard or scrollbar/scrollbutton input */
   {
+    /* move cursor instead of scrolling when already at start/end of list */
+    if (dy == -1 * SCROLL_LINE && first_entry == 0)
+      dy = -1;
+    else if (dy == +1 * SCROLL_LINE &&
+            first_entry + num_page_entries == max_info_info)
+      dy = 1;
+
+    /* handle scrolling screen one line or page */
+    if (y + dy < 0 ||
+       y + dy > num_page_entries - 1)
+    {
+      boolean redraw = FALSE;
+
+      if (ABS(dy) == SCROLL_PAGE)
+       step = num_page_entries - 1;
+
+      if (dy < 0 && first_entry > 0)
+      {
+       /* scroll page/line up */
+
+       first_entry -= step;
+       if (first_entry < 0)
+         first_entry = 0;
+
+       redraw = TRUE;
+      }
+      else if (dy > 0 && first_entry + num_page_entries < max_info_info)
+      {
+       /* scroll page/line down */
+
+       first_entry += step;
+       if (first_entry + num_page_entries > max_info_info)
+         first_entry = MAX(0, max_info_info - num_page_entries);
+
+       redraw = TRUE;
+      }
+
+      if (redraw)
+      {
+       choice += first_entry - first_entry_store[info_mode];
+
+       if (choice < first_entry)
+       {
+         choice = first_entry;
+
+         if (info_info[choice].type & TYPE_SKIP_ENTRY)
+           choice++;
+       }
+       else if (choice > first_entry + num_page_entries - 1)
+       {
+         choice = first_entry + num_page_entries - 1;
+
+         if (info_info[choice].type & TYPE_SKIP_ENTRY)
+           choice--;
+       }
+       else if (info_info[choice].type & TYPE_SKIP_ENTRY)
+       {
+         choice += SIGN(dy);
+
+         if (choice < first_entry ||
+             choice > first_entry + num_page_entries - 1)
+         first_entry += SIGN(dy);
+       }
+
+       first_entry_store[info_mode] = first_entry;
+       choice_store[info_mode] = choice;
+
+       drawInfoInfoList(info_info, first_entry, NUM_MENU_ENTRIES_ON_SCREEN);
+
+       DrawCursorAndText_Info(choice - first_entry, choice, TRUE);
+
+       AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_info_info,
+                       NUM_MENU_ENTRIES_ON_SCREEN, first_entry);
+      }
+
+      return;
+    }
+
     if (dx)
     {
       int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER);
 
       if (info_info[choice].type & menu_navigation_type ||
-         info_info[choice].type & TYPE_ENTER_SCREEN ||
          info_info[choice].type & TYPE_BOOLEAN_STYLE ||
          info_info[choice].type & TYPE_YES_NO_AUTO)
        button = MB_MENU_CHOICE;
     }
     else if (dy)
-      y = choice + dy;
+      y += dy;
 
     /* jump to next non-empty menu entry (up or down) */
-    while (y > 0 && y < num_info_info - 1 &&
-          info_info[y].type & TYPE_SKIP_ENTRY)
+    while (first_entry + y > 0 &&
+          first_entry + y < max_info_info - 1 &&
+          info_info[first_entry + y].type & TYPE_SKIP_ENTRY)
       y += dy;
+
+    if (!IN_VIS_MENU(x, y))
+    {
+      choice += y - y_old;
+
+      if (choice < first_entry)
+       first_entry = choice;
+      else if (choice > first_entry + num_page_entries - 1)
+       first_entry = choice - num_page_entries + 1;
+
+      if (first_entry >= 0 &&
+         first_entry + num_page_entries <= max_info_info)
+      {
+       first_entry_store[info_mode] = first_entry;
+
+       if (choice < first_entry)
+         choice = first_entry;
+       else if (choice > first_entry + num_page_entries - 1)
+         choice = first_entry + num_page_entries - 1;
+
+       choice_store[info_mode] = choice;
+
+       drawInfoInfoList(info_info, first_entry, NUM_MENU_ENTRIES_ON_SCREEN);
+
+       DrawCursorAndText_Info(choice - first_entry, choice, TRUE);
+
+       AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_info_info,
+                       NUM_MENU_ENTRIES_ON_SCREEN, first_entry);
+      }
+
+      return;
+    }
   }
 
-  if (IN_VIS_MENU(x, y) &&
-      y >= 0 && y < num_info_info && info_info[y].type & ~TYPE_SKIP_ENTRY)
+  if (!anyScrollbarGadgetActive() &&
+      IN_VIS_MENU(x, y) &&
+      mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x &&
+      y >= 0 && y < num_page_entries)
   {
     if (button)
     {
-      if (y != choice)
+      if (first_entry + y != choice &&
+         info_info[first_entry + y].type & ~TYPE_SKIP_ENTRY)
       {
        PlaySound(SND_MENU_ITEM_ACTIVATING);
 
-       DrawCursorAndText_Info(choice, FALSE);
-       DrawCursorAndText_Info(y, TRUE);
+       DrawCursorAndText_Info(choice - first_entry, choice, FALSE);
+       DrawCursorAndText_Info(y, first_entry + y, TRUE);
 
-       choice = choice_store[info_mode] = y;
+       choice = choice_store[info_mode] = first_entry + y;
       }
     }
-    else if (!(info_info[y].type & TYPE_GHOSTED))
+    else if (!(info_info[first_entry + y].type & TYPE_GHOSTED))
     {
       PlaySound(SND_MENU_ITEM_SELECTING);
 
-      if (info_info[y].type & TYPE_ENTER_OR_LEAVE)
+      if (info_info[first_entry + y].type & TYPE_ENTER_OR_LEAVE)
       {
-       void (*menu_callback_function)(void) = info_info[choice].value;
+       void (*menu_callback_function)(void) =
+         info_info[first_entry + y].value;
 
-       FadeSetFromType(info_info[y].type);
+       FadeSetFromType(info_info[first_entry + y].type);
 
        menu_callback_function();
       }
@@ -2848,11 +3090,11 @@ void DrawInfoScreen_Program()
   DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_2,
                    "If you like it, send e-mail to:");
   DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_3,
-                   PROGRAM_EMAIL_STRING);
+                   setup.internal.program_email);
   DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2,
                    "More information and levels:");
   DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3,
-                   PROGRAM_WEBSITE_STRING);
+                   setup.internal.program_website);
   DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_2,
                    "If you have created new levels,");
   DrawTextSCentered(ystart2 + 8 * ystep, FONT_TEXT_2,
@@ -2924,7 +3166,7 @@ void DrawInfoScreen_Version()
   DrawTextSCentered(ystart1, FONT_TEXT_1, "Version Information:");
 
   DrawTextF(xstart1, ystart2, font_header, "Name");
-  DrawTextF(xstart2, ystart2, font_text, PROGRAM_TITLE_STRING);
+  DrawTextF(xstart2, ystart2, font_text, getProgramTitleString());
 
   ystart2 += ystep;
   DrawTextF(xstart1, ystart2, font_header, "Version");
@@ -3335,38 +3577,6 @@ static void DrawChooseTree(TreeInfo **ti_ptr)
   InitAnimation();
 }
 
-static void AdjustScrollbar(int id, int items_max, int items_visible,
-                           int item_position)
-{
-  struct GadgetInfo *gi = screen_gadget[id];
-
-  if (item_position > items_max - items_visible)
-    item_position = items_max - items_visible;
-
-  ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
-              GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
-              GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
-}
-
-static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti)
-{
-  AdjustScrollbar(id, numTreeInfoInGroup(ti), NUM_MENU_ENTRIES_ON_SCREEN,
-                 first_entry);
-}
-
-static void clearMenuListArea()
-{
-  int scrollbar_xpos = mSX + SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset;
-
-  /* correct scrollbar position if placed outside menu (playfield) area */
-  if (scrollbar_xpos > SX + SC_SCROLLBAR_XPOS)
-    scrollbar_xpos = SX + SC_SCROLLBAR_XPOS;
-
-  /* clear menu list area, but not title or scrollbar */
-  DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
-                 scrollbar_xpos - mSX, NUM_MENU_ENTRIES_ON_SCREEN * 32);
-}
-
 static void drawChooseTreeList(int first_entry, int num_page_entries,
                               TreeInfo *ti)
 {
@@ -3451,7 +3661,7 @@ static void drawChooseTreeInfo(int entry_pos, TreeInfo *ti)
                      node->class_desc);
 
   /* let BackToFront() redraw only what is needed */
-  redraw_mask = last_redraw_mask | REDRAW_TILES;
+  redraw_mask = last_redraw_mask;
   for (x = 0; x < SCR_FIELDX; x++)
     MarkTileDirty(x, 1);
 }
@@ -3846,7 +4056,7 @@ void DrawHallOfFame(int highlight_position)
   SetDrawDeactivationMask(REDRAW_NONE);
   SetDrawBackgroundMask(REDRAW_FIELD);
 
-  CloseDoor(DOOR_CLOSE_2);
+  CloseDoor(DOOR_CLOSE_ALL);
 
   if (highlight_position < 0) 
     LoadScore(level_nr);
@@ -5632,6 +5842,7 @@ void HandleSetupScreen_Generic(int mx, int my, int dx, int dy, int button)
 {
   static int choice_store[MAX_SETUP_MODES];
   static int first_entry_store[MAX_SETUP_MODES];
+  static int num_page_entries_last = 0;
   int choice = choice_store[setup_mode];               /* starts with 0 */
   int first_entry = first_entry_store[setup_mode];     /* starts with 0 */
   int x = 0;
@@ -5645,6 +5856,23 @@ void HandleSetupScreen_Generic(int mx, int my, int dx, int dy, int button)
 
   if (button == MB_MENU_INITIALIZE)
   {
+    // check if number of menu page entries has changed (may happen by change
+    // of custom artwork definition value for 'list_size' for this menu screen)
+    // (in this case, the last menu position most probably has to be corrected)
+    if (num_page_entries != num_page_entries_last)
+    {
+      int i;
+
+      for (i = 0; i < MAX_INFO_MODES; i++)
+       choice_store[i] = first_entry_store[i] = 0;
+
+      num_page_entries_last = num_page_entries;
+
+      HandleSetupScreen_Generic(mx, my, dx, dy, button);
+
+      return;
+    }
+
     /* advance to first valid menu entry */
     while (choice < num_setup_info &&
           setup_info[choice].type & TYPE_SKIP_ENTRY)
@@ -7000,6 +7228,8 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
        HandleChooseLevelNr(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
       else if (game_status == GAME_MODE_SETUP)
        HandleSetupScreen(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
+      else if (game_status == GAME_MODE_INFO)
+       HandleInfoScreen(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK);
       break;
 
     case SCREEN_CTRL_ID_SCROLL_DOWN:
@@ -7009,6 +7239,8 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
        HandleChooseLevelNr(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
       else if (game_status == GAME_MODE_SETUP)
        HandleSetupScreen(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
+      else if (game_status == GAME_MODE_INFO)
+       HandleInfoScreen(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK);
       break;
 
     case SCREEN_CTRL_ID_SCROLL_VERTICAL:
@@ -7018,6 +7250,8 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
        HandleChooseLevelNr(0,0,999,gi->event.item_position,MB_MENU_INITIALIZE);
       else if (game_status == GAME_MODE_SETUP)
        HandleSetupScreen(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE);
+      else if (game_status == GAME_MODE_INFO)
+       HandleInfoScreen(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE);
       break;
 
     default: