]> code.delx.au - refind/blobdiff - refind/menu.c
New "editor" option to the "hideui" configuration file token.
[refind] / refind / menu.c
index ad8d39c05926ac21ba58d1befe5ccaaa219ef051..7b74e517940b8a9bfe77b9e921107e7ec4bb0636 100644 (file)
 #include "menu.h"
 #include "config.h"
 #include "libeg.h"
-#include "refit_call_wrapper.h"
+#include "../include/refit_call_wrapper.h"
 
-#include "egemb_back_selected_small.h"
-#include "egemb_arrow_left.h"
-#include "egemb_arrow_right.h"
+#include "../include/egemb_back_selected_small.h"
+#include "../include/egemb_arrow_left.h"
+#include "../include/egemb_arrow_right.h"
 
 // other menu definitions
 
@@ -61,6 +61,7 @@
 #define MENU_FUNCTION_PAINT_ALL       (2)
 #define MENU_FUNCTION_PAINT_SELECTION (3)
 #define MENU_FUNCTION_PAINT_TIMEOUT   (4)
+#define MENU_FUNCTION_PAINT_HINTS     (5)
 
 typedef VOID (*MENU_STYLE_FUNC)(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText);
 
@@ -85,9 +86,6 @@ static EG_IMAGE *SelectionImages[4] = { NULL, NULL, NULL, NULL };
 static EG_PIXEL SelectionBackgroundPixel = { 0xff, 0xff, 0xff, 0 };
 static EG_IMAGE *TextBuffer = NULL;
 
-// Used in MainMenuStyle(), but must be persistent....
-UINTN row0PosX = 0, row0PosXRunning = 0, row1PosY = 0, row0Loaders = 0;
-
 //
 // Graphics helper functions
 //
@@ -180,7 +178,7 @@ static VOID InitScroll(OUT SCROLL_STATE *State, IN UINTN ItemCount, IN UINTN Vis
 
 // Adjust variables relating to the scrolling of tags, for when a selected icon isn't
 // visible given the current scrolling condition....
-static VOID AdjustScrollState(/* IN REFIT_MENU_SCREEN *Screen, */ IN SCROLL_STATE *State) {
+static VOID AdjustScrollState(IN SCROLL_STATE *State) {
    if (State->CurrentSelection > State->LastVisible) {
       State->LastVisible = State->CurrentSelection;
       State->FirstVisible = 1 + State->CurrentSelection - State->MaxVisible;
@@ -295,7 +293,7 @@ static VOID UpdateScroll(IN OUT SCROLL_STATE *State, IN UINTN Movement)
     if (!State->PaintAll && State->CurrentSelection != State->PreviousSelection)
         State->PaintSelection = TRUE;
     State->LastVisible = State->FirstVisible + State->MaxVisible - 1;
-}
+} // static VOID UpdateScroll()
 
 //
 // menu helper functions
@@ -311,11 +309,6 @@ VOID AddMenuEntry(IN REFIT_MENU_SCREEN *Screen, IN REFIT_MENU_ENTRY *Entry)
     AddListElement((VOID ***) &(Screen->Entries), &(Screen->EntryCount), Entry);
 }
 
-VOID FreeMenu(IN REFIT_MENU_SCREEN *Screen)
-{
-    if (Screen->Entries)
-        FreePool(Screen->Entries);
-}
 
 static INTN FindMenuShortcutEntry(IN REFIT_MENU_SCREEN *Screen, IN CHAR16 *Shortcut)
 {
@@ -365,7 +358,8 @@ static VOID IdentifyRows(IN SCROLL_STATE *State, IN REFIT_MENU_SCREEN *Screen) {
 //
 // generic menu function
 //
-static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC StyleFunc, IN INTN DefaultEntryIndex, OUT REFIT_MENU_ENTRY **ChosenEntry)
+static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC StyleFunc, IN OUT INTN *DefaultEntryIndex,
+                            OUT REFIT_MENU_ENTRY **ChosenEntry)
 {
     SCROLL_STATE State;
     EFI_STATUS Status;
@@ -374,7 +368,7 @@ static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC Sty
     INTN ShortcutEntry;
     BOOLEAN HaveTimeout = FALSE;
     UINTN TimeoutCountdown = 0;
-    CHAR16 *TimeoutMessage;
+    CHAR16 TimeoutMessage[256];
     CHAR16 KeyAsString[2];
     UINTN MenuExit;
 
@@ -387,10 +381,11 @@ static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC Sty
     StyleFunc(Screen, &State, MENU_FUNCTION_INIT, NULL);
     IdentifyRows(&State, Screen);
     // override the starting selection with the default index, if any
-    if (DefaultEntryIndex >= 0 && DefaultEntryIndex <= State.MaxIndex) {
-        State.CurrentSelection = DefaultEntryIndex;
+    if (*DefaultEntryIndex >= 0 && *DefaultEntryIndex <= State.MaxIndex) {
+        State.CurrentSelection = *DefaultEntryIndex;
         UpdateScroll(&State, SCROLL_NONE);
     }
+    State.PaintAll = TRUE;
 
     while (!MenuExit) {
         // update the screen
@@ -403,9 +398,8 @@ static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC Sty
         }
 
         if (HaveTimeout) {
-            TimeoutMessage = PoolPrint(L"%s in %d seconds", Screen->TimeoutText, (TimeoutCountdown + 5) / 10);
+            SPrint(TimeoutMessage, 255, L"%s in %d seconds", Screen->TimeoutText, (TimeoutCountdown + 5) / 10);
             StyleFunc(Screen, &State, MENU_FUNCTION_PAINT_TIMEOUT, TimeoutMessage);
-            FreePool(TimeoutMessage);
         }
 
         // read key press (and wait for it if applicable)
@@ -464,6 +458,10 @@ static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC Sty
             case SCAN_F10:
                 egScreenShot();
                 break;
+            case 0x0016: // F12
+               if (EjectMedia())
+                  MenuExit = MENU_EXIT_ESCAPE;
+               break;
         }
         switch (key.UnicodeChar) {
             case CHAR_LINEFEED:
@@ -490,8 +488,9 @@ static UINTN RunGenericMenu(IN REFIT_MENU_SCREEN *Screen, IN MENU_STYLE_FUNC Sty
 
     if (ChosenEntry)
         *ChosenEntry = Screen->Entries[State.CurrentSelection];
+    *DefaultEntryIndex = State.CurrentSelection;
     return MenuExit;
-} /* static UINTN RunGenericMenu( */
+} /* static UINTN RunGenericMenu() */
 
 //
 // text-mode generic style
@@ -503,7 +502,7 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
     UINTN MenuWidth, ItemWidth, MenuHeight;
     static UINTN MenuPosY;
     static CHAR16 **DisplayStrings;
-    CHAR16 *TimeoutMessage;
+    CHAR16 TimeoutMessage[256];
 
     State->ScrollMode = SCROLL_MODE_TEXT;
     switch (Function) {
@@ -513,7 +512,7 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
             MenuPosY = 4;
             if (Screen->InfoLineCount > 0)
                 MenuPosY += Screen->InfoLineCount + 1;
-            MenuHeight = ConHeight - MenuPosY;
+            MenuHeight = ConHeight - MenuPosY - 2;
             if (Screen->TimeoutSeconds > 0)
                 MenuHeight -= 2;
             InitScroll(State, Screen->EntryCount, MenuHeight);
@@ -525,16 +524,32 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
                 if (MenuWidth < ItemWidth)
                     MenuWidth = ItemWidth;
             }
-            if (MenuWidth > ConWidth - 6)
-                MenuWidth = ConWidth - 6;
+            MenuWidth += 2;
+            if (MenuWidth > ConWidth - 3)
+                MenuWidth = ConWidth - 3;
 
             // prepare strings for display
             DisplayStrings = AllocatePool(sizeof(CHAR16 *) * Screen->EntryCount);
-            for (i = 0; i <= State->MaxIndex; i++)
-                DisplayStrings[i] = PoolPrint(L" %-.*s ", MenuWidth, Screen->Entries[i]->Title);
-            // TODO: shorten strings that are too long (PoolPrint doesn't do that...)
-            // TODO: use more elaborate techniques for shortening too long strings (ellipses in the middle)
-            // TODO: account for double-width characters
+            for (i = 0; i <= State->MaxIndex; i++) {
+                // Note: Theoretically, SPrint() is a cleaner way to do this; but the
+                // description of the StrSize parameter to SPrint implies it's measured
+                // in characters, but in practice both TianoCore and GNU-EFI seem to
+                // use bytes instead, resulting in truncated displays. I could just
+                // double the size of the StrSize parameter, but that seems unsafe in
+                // case a future library change starts treating this as characters, so
+                // I'm doing it the hard way in this instance.
+                // TODO: Review the above and possibly change other uses of SPrint()
+                DisplayStrings[i] = AllocateZeroPool(2 * sizeof(CHAR16));
+                DisplayStrings[i][0] = L' ';
+                MergeStrings(&DisplayStrings[i], Screen->Entries[i]->Title, 0);
+                if (StrLen(DisplayStrings[i]) > MenuWidth)
+                   DisplayStrings[i][MenuWidth - 1] = 0;
+//                DisplayStrings[i] = AllocateZeroPool(256 * sizeof(CHAR16));
+//                SPrint(DisplayStrings[i], ((MenuWidth < 255) ? MenuWidth : 255) * sizeof(CHAR16),
+//                       L" %s ", Screen->Entries[i]->Title);
+                // TODO: use more elaborate techniques for shortening too long strings (ellipses in the middle)
+                // TODO: account for double-width characters
+            } // for
 
             // initial painting
             BeginTextScreen(Screen->Title);
@@ -551,8 +566,8 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
         case MENU_FUNCTION_CLEANUP:
             // release temporary memory
             for (i = 0; i <= State->MaxIndex; i++)
-                FreePool(DisplayStrings[i]);
-            FreePool(DisplayStrings);
+                MyFreePool(DisplayStrings[i]);
+            MyFreePool(DisplayStrings);
             break;
 
         case MENU_FUNCTION_PAINT_ALL:
@@ -579,6 +594,11 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
                refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, ArrowDown);
             else
                refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, L" ");
+            if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) {
+               refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 1);
+               refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut,
+                                   L"Use arrow keys to move cursor; Enter to boot; Insert or F2 for more options");
+            }
             break;
 
         case MENU_FUNCTION_PAINT_SELECTION:
@@ -595,15 +615,14 @@ static VOID TextMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
             if (ParamText[0] == 0) {
                 // clear message
                 refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC);
-                refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 1);
+                refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, ConHeight - 2);
                 refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, BlankLine + 1);
             } else {
                 // paint or update message
                 refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_ERROR);
-                refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, ConHeight - 1);
-                TimeoutMessage = PoolPrint(L"%s  ", ParamText);
+                refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, ConHeight - 2);
+                SPrint(TimeoutMessage, 255, L"%s  ", ParamText);
                 refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, TimeoutMessage);
-                FreePool(TimeoutMessage);
             }
             break;
 
@@ -695,6 +714,17 @@ static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *Sta
                 DrawMenuText(Screen->Entries[i]->Title, (i == State->CurrentSelection) ? MenuWidth : 0,
                              EntriesPosX, EntriesPosY + i * TEXT_LINE_HEIGHT);
             }
+            if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) {
+               if (GlobalConfig.HideUIFlags & HIDEUI_FLAG_EDITOR) {
+                  DrawMenuText(L"Use arrow keys to move cursor; Enter to boot", 0,
+                               (UGAWidth - (45 * FONT_CELL_WIDTH)) / 2, UGAHeight - (FONT_CELL_HEIGHT * 3));
+               } else {
+                  DrawMenuText(L"Use arrow keys to move cursor; Enter to boot;", 0,
+                               (UGAWidth - (45 * FONT_CELL_WIDTH)) / 2, UGAHeight - (FONT_CELL_HEIGHT * 3));
+                  DrawMenuText(L"Insert or F2 to edit options", 0,
+                               (UGAWidth - (28 * FONT_CELL_WIDTH)) / 2, UGAHeight - (FONT_CELL_HEIGHT * 2));
+               } // if/else
+            } // if
             break;
 
         case MENU_FUNCTION_PAINT_SELECTION:
@@ -710,7 +740,7 @@ static VOID GraphicsMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *Sta
             break;
 
     }
-}
+} // static VOID GraphicsMenuStyle()
 
 //
 // graphical main menu style
@@ -765,6 +795,13 @@ static VOID PaintAll(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, UINTN
    if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL))
       DrawMainMenuText(Screen->Entries[State->CurrentSelection]->Title,
                        (UGAWidth - LAYOUT_TEXT_WIDTH) >> 1, textPosY);
+
+   if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_HINTS)) {
+      DrawMainMenuText(L"Use arrow keys to move cursor; Enter to boot;",
+                       (UGAWidth - LAYOUT_TEXT_WIDTH) / 2, UGAHeight - (FONT_CELL_HEIGHT * 3));
+      DrawMainMenuText(L"Insert or F2 for more options",
+                       (UGAWidth - LAYOUT_TEXT_WIDTH) / 2, UGAHeight - (FONT_CELL_HEIGHT * 2));
+   } // if
 } // static VOID PaintAll()
 
 // Move the selection to State->CurrentSelection, adjusting icon row if necessary...
@@ -772,7 +809,7 @@ static VOID PaintSelection(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State,
                            UINTN row0PosY, UINTN row1PosY, UINTN textPosY) {
    UINTN XSelectPrev, XSelectCur, YPosPrev, YPosCur;
 
-   if (((State->CurrentSelection < State->LastVisible) && (State->CurrentSelection >= State->FirstVisible)) ||
+   if (((State->CurrentSelection <= State->LastVisible) && (State->CurrentSelection >= State->FirstVisible)) ||
        (State->CurrentSelection >= State->InitialRow1) ) {
       if (Screen->Entries[State->PreviousSelection]->Row == 0) {
          XSelectPrev = State->PreviousSelection - State->FirstVisible;
@@ -816,16 +853,17 @@ static VOID PaintIcon(IN EG_EMBEDDED_IMAGE *BuiltInIcon, IN CHAR16 *ExternalFile
          PosX -= Icon->Width;
       BltImageAlpha(Icon, PosX, PosY - (Icon->Height / 2), &MenuBackgroundPixel);
    }
-} // static VOID PaintArrow()
+} // static VOID PaintIcon()
 
 // Display main menu in graphics mode
 VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINTN Function, IN CHAR16 *ParamText)
 {
     INTN i;
-    extern UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders;
+    static UINTN row0PosX, row0PosXRunning, row1PosY, row0Loaders;
     UINTN row0Count, row1Count, row1PosX, row1PosXRunning;
     static UINTN *itemPosX;
     static UINTN row0PosY, textPosY;
+    CHAR16 FileName[256];
 
     State->ScrollMode = SCROLL_MODE_ICONS;
     switch (Function) {
@@ -873,7 +911,7 @@ VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT
             break;
 
         case MENU_FUNCTION_CLEANUP:
-            FreePool(itemPosX);
+            MyFreePool(itemPosX);
             break;
 
         case MENU_FUNCTION_PAINT_ALL:
@@ -882,13 +920,17 @@ VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT
             // For PaintIcon() calls, the starting Y position is moved to the midpoint
             // of the surrounding row; PaintIcon() adjusts this back up by half the
             // icon's height to properly center it.
-            if ((State->FirstVisible > 0) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS)))
-               PaintIcon(&egemb_arrow_left, L"icons\\arrow_left.icns", row0PosX - TILE_XSPACING,
+            if ((State->FirstVisible > 0) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS))) {
+               SPrint(FileName, 255, L"%s\\arrow_left.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR);
+               PaintIcon(&egemb_arrow_left, FileName, row0PosX - TILE_XSPACING,
                          row0PosY + (ROW0_TILESIZE / 2), ALIGN_RIGHT);
-            if ((State->LastVisible < (row0Loaders - 1)) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS)))
-               PaintIcon(&egemb_arrow_right, L"icons\\arrow_right.icns",
+            } // if
+            if ((State->LastVisible < (row0Loaders - 1)) && (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_ARROWS))) {
+               SPrint(FileName, 255, L"%s\\arrow_right.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR);
+               PaintIcon(&egemb_arrow_right, FileName,
                          (UGAWidth + (ROW0_TILESIZE + TILE_XSPACING) * State->MaxVisible) / 2 + TILE_XSPACING,
                          row0PosY + (ROW0_TILESIZE / 2), ALIGN_LEFT);
+            } // if
             break;
 
         case MENU_FUNCTION_PAINT_SELECTION:
@@ -901,7 +943,34 @@ VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT
             break;
 
     }
-}
+} // VOID MainMenuStyle()
+
+// Enable the user to edit boot loader options.
+// Returns TRUE if the user exited with edited options; FALSE if the user
+// pressed Esc to terminate the edit.
+static BOOLEAN EditOptions(LOADER_ENTRY *MenuEntry) {
+   UINTN x_max, y_max;
+   CHAR16 *EditedOptions;
+   BOOLEAN retval = FALSE;
+
+   if (GlobalConfig.HideUIFlags & HIDEUI_FLAG_EDITOR) {
+      return FALSE;
+   }
+
+   refit_call4_wrapper(ST->ConOut->QueryMode, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max);
+
+   if (!GlobalConfig.TextOnly)
+      SwitchToText(TRUE);
+
+   if (line_edit(MenuEntry->LoadOptions, &EditedOptions, x_max)) {
+      MyFreePool(MenuEntry->LoadOptions);
+      MenuEntry->LoadOptions = EditedOptions;
+      retval = TRUE;
+   } // if
+   if (!GlobalConfig.TextOnly)
+      SwitchToGraphics();
+   return retval;
+} // VOID EditOptions()
 
 //
 // user-callable dispatcher functions
@@ -909,12 +978,13 @@ VOID MainMenuStyle(IN REFIT_MENU_SCREEN *Screen, IN SCROLL_STATE *State, IN UINT
 
 UINTN RunMenu(IN REFIT_MENU_SCREEN *Screen, OUT REFIT_MENU_ENTRY **ChosenEntry)
 {
+    INTN            DefaultEntry = -1;
     MENU_STYLE_FUNC Style = TextMenuStyle;
 
     if (AllowGraphicsMode)
         Style = GraphicsMenuStyle;
 
-    return RunGenericMenu(Screen, Style, -1, ChosenEntry);
+    return RunGenericMenu(Screen, Style, &DefaultEntry, ChosenEntry);
 }
 
 UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT REFIT_MENU_ENTRY **ChosenEntry)
@@ -923,12 +993,12 @@ UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT
     MENU_STYLE_FUNC MainStyle = TextMenuStyle;
     REFIT_MENU_ENTRY *TempChosenEntry;
     UINTN MenuExit = 0;
-    UINTN DefaultEntryIndex = -1;
+    INTN DefaultEntryIndex = -1;
+    INTN DefaultSubmenuIndex = -1;
 
     if (DefaultSelection != NULL) {
         // Find a menu entry that includes *DefaultSelection as a substring
         DefaultEntryIndex = FindMenuShortcutEntry(Screen, DefaultSelection);
-        // If that didn't work, should we scan more characters?  For now, no.
     }
 
     if (AllowGraphicsMode) {
@@ -937,14 +1007,22 @@ UINTN RunMainMenu(IN REFIT_MENU_SCREEN *Screen, IN CHAR16* DefaultSelection, OUT
     }
 
     while (!MenuExit) {
-        MenuExit = RunGenericMenu(Screen, MainStyle, DefaultEntryIndex, &TempChosenEntry);
+        MenuExit = RunGenericMenu(Screen, MainStyle, &DefaultEntryIndex, &TempChosenEntry);
         Screen->TimeoutSeconds = 0;
 
-        if (MenuExit == MENU_EXIT_DETAILS && TempChosenEntry->SubScreen != NULL) {
-            MenuExit = RunGenericMenu(TempChosenEntry->SubScreen, Style, -1, &TempChosenEntry);
-            if (MenuExit == MENU_EXIT_ESCAPE || TempChosenEntry->Tag == TAG_RETURN)
-                MenuExit = 0;
-        }
+        if (MenuExit == MENU_EXIT_DETAILS) {
+            if (TempChosenEntry->SubScreen != NULL) {
+               MenuExit = RunGenericMenu(TempChosenEntry->SubScreen, Style, &DefaultSubmenuIndex, &TempChosenEntry);
+               if (MenuExit == MENU_EXIT_ESCAPE || TempChosenEntry->Tag == TAG_RETURN)
+                   MenuExit = 0;
+               if (MenuExit == MENU_EXIT_DETAILS) {
+                  if (!EditOptions((LOADER_ENTRY *) TempChosenEntry))
+                     MenuExit = 0;
+               } // if
+            } else { // no sub-screen; ignore keypress
+               MenuExit = 0;
+            }
+        } // Enter sub-screen
     }
 
     if (ChosenEntry)