[FREELDR] Check for any user keypress in menu even when the timeout is zero.
[reactos.git] / boot / freeldr / freeldr / ui / tuimenu.c
index 055e1b4..86690af 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         FreeLoader
- * FILE:            freeldr/ui/tuimenu.c
+ * FILE:            boot/freeldr/freeldr/ui/tuimenu.c
  * PURPOSE:         UI Menu Functions
  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  *                  Brian Palmer (brianp@sginet.com)
 /* FUNCTIONS *****************************************************************/
 
 BOOLEAN
-TuiDisplayMenu(PCSTR MenuItemList[],
+TuiDisplayMenu(PCSTR MenuHeader,
+               PCSTR MenuFooter,
+               BOOLEAN ShowBootOptions,
+               PCSTR MenuItemList[],
                ULONG MenuItemCount,
                ULONG DefaultMenuItem,
                LONG MenuTimeOut,
@@ -27,8 +30,40 @@ TuiDisplayMenu(PCSTR MenuItemList[],
     ULONG CurrentClockSecond;
     ULONG KeyPress;
 
+    //
+    // Before taking any default action if there is no timeout,
+    // check whether the supplied key filter callback function
+    // may handle a specific user keypress. If it does, the
+    // timeout is cancelled.
+    //
+    if (!MenuTimeOut && KeyPressFilter && MachConsKbHit())
+    {
+        //
+        // Get the key
+        //
+        KeyPress = MachConsGetCh();
+
+        //
+        // Is it extended? Then get the extended key
+        //
+        if (!KeyPress) KeyPress = MachConsGetCh();
+
+        //
+        // Call the supplied key filter callback function to see
+        // if it is going to handle this keypress.
+        //
+        if (KeyPressFilter(KeyPress))
+        {
+            //
+            // It processed the key character, cancel the timeout
+            //
+            MenuTimeOut = -1;
+        }
+    }
+
     //
     // Check if there's no timeout
+    //
     if (!MenuTimeOut)
     {
         //
@@ -41,6 +76,9 @@ TuiDisplayMenu(PCSTR MenuItemList[],
     //
     // Setup the MENU_INFO structure
     //
+    MenuInformation.MenuHeader = MenuHeader;
+    MenuInformation.MenuFooter = MenuFooter;
+    MenuInformation.ShowBootOptions = ShowBootOptions;
     MenuInformation.MenuItemList = MenuItemList;
     MenuInformation.MenuItemCount = MenuItemCount;
     MenuInformation.MenuTimeRemaining = MenuTimeOut;
@@ -87,7 +125,7 @@ TuiDisplayMenu(PCSTR MenuItemList[],
         //
         // Check if there is a countdown
         //
-        if (MenuInformation.MenuTimeRemaining)
+        if (MenuInformation.MenuTimeRemaining > 0)
         {
             //
             // Get the updated time, seconds only
@@ -112,13 +150,15 @@ TuiDisplayMenu(PCSTR MenuItemList[],
                 VideoCopyOffScreenBufferToVRAM();
             }
         }
-        else
+        else if (MenuInformation.MenuTimeRemaining == 0)
         {
             //
             // A time out occurred, exit this loop and return default OS
             //
             break;
         }
+
+        MachHwIdle();
     }
 
     //
@@ -151,8 +191,11 @@ TuiCalcMenuBoxSize(PUI_MENU_INFO MenuInfo)
         //
         // Get the string length and make it become the new width if necessary
         //
-        Length = strlen(MenuInfo->MenuItemList[i]);
-        if (Length > Width) Width = Length;
+        if (MenuInfo->MenuItemList[i])
+        {
+            Length = (ULONG)strlen(MenuInfo->MenuItemList[i]);
+            if (Length > Width) Width = Length;
+        }
     }
 
     //
@@ -201,7 +244,7 @@ TuiDrawMenu(PUI_MENU_INFO MenuInfo)
     //
     // Update the status bar
     //
-    UiVtbl.DrawStatusText("Use \x18\x19 to select, then press ENTER.");
+    UiVtbl.DrawStatusText("Use \x18 and \x19 to select, then press ENTER.");
 
     //
     // Draw the menu box
@@ -211,7 +254,17 @@ TuiDrawMenu(PUI_MENU_INFO MenuInfo)
     //
     // Draw each line of the menu
     //
-    for (i = 0; i < MenuInfo->MenuItemCount; i++) TuiDrawMenuItem(MenuInfo, i);
+    for (i = 0; i < MenuInfo->MenuItemCount; i++)
+    {
+        TuiDrawMenuItem(MenuInfo, i);
+    }
+
+    /* Display the boot options if needed */
+    if (MenuInfo->ShowBootOptions)
+    {
+        DisplayBootTimeOptions();
+    }
+
     VideoCopyOffScreenBufferToVRAM();
 }
 
@@ -219,8 +272,7 @@ VOID
 NTAPI
 TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
 {
-    CHAR MenuLineText[80];
-    CHAR TempString[80];
+    CHAR MenuLineText[80], TempString[80];
     ULONG i;
 
     //
@@ -235,7 +287,7 @@ TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
                   D_VERT,
                   D_HORZ,
                   FALSE,        // Filled
-                  TRUE,        // Shadow
+                  TRUE,         // Shadow
                   ATTR(UiMenuFgColor, UiMenuBgColor));
     }
 
@@ -248,7 +300,7 @@ TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
         // Copy the integral time text string, and remove the last 2 chars
         //
         strcpy(TempString, UiTimeText);
-        i = strlen(TempString);
+        i = (ULONG)strlen(TempString);
         TempString[i - 2] = 0;
 
         //
@@ -271,7 +323,7 @@ TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
             //
             // Display it in the center of the menu
             //
-            UiDrawText(MenuInfo->Right - strlen(MenuLineText) - 1,
+            UiDrawText(MenuInfo->Right - (ULONG)strlen(MenuLineText) - 1,
                        MenuInfo->Bottom,
                        MenuLineText,
                        ATTR(UiMenuFgColor, UiMenuBgColor));
@@ -282,7 +334,7 @@ TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
             // Display under the menu directly
             //
             UiDrawText(0,
-                       MenuInfo->Bottom + 3,
+                       MenuInfo->Bottom + 4,
                        MenuLineText,
                        ATTR(UiMenuFgColor, UiMenuBgColor));
         }
@@ -303,7 +355,7 @@ TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
         //
         if (UiCenterMenu)
         {
-            UiDrawText(MenuInfo->Right - strlen(MenuLineText) - 1,
+            UiDrawText(MenuInfo->Right - (ULONG)strlen(MenuLineText) - 1,
                        MenuInfo->Bottom,
                        MenuLineText,
                        ATTR(UiMenuFgColor, UiMenuBgColor));
@@ -311,7 +363,7 @@ TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
         else
         {
             UiDrawText(0,
-                       MenuInfo->Bottom + 3,
+                       MenuInfo->Bottom + 4,
                        MenuLineText,
                        ATTR(UiMenuFgColor, UiMenuBgColor));
         }
@@ -325,7 +377,7 @@ TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
         //
         // Check if it's a separator
         //
-        if (!(_stricmp(MenuInfo->MenuItemList[i], "SEPARATOR")))
+        if (MenuInfo->MenuItemList[i] == NULL)
         {
             //
             // Draw the separator line
@@ -364,7 +416,8 @@ TuiDrawMenuItem(PUI_MENU_INFO MenuInfo,
         // how many spaces will be to the left and right
         //
         SpaceTotal = (MenuInfo->Right - MenuInfo->Left - 2) -
-                     strlen(MenuInfo->MenuItemList[MenuItemNumber]);
+                     (ULONG)(MenuInfo->MenuItemList[MenuItemNumber] ?
+                             strlen(MenuInfo->MenuItemList[MenuItemNumber]) : 0);
         SpaceLeft = (SpaceTotal / 2) + 1;
         SpaceRight = (SpaceTotal - SpaceLeft) + 1;
 
@@ -386,7 +439,8 @@ TuiDrawMenuItem(PUI_MENU_INFO MenuInfo,
     //
     // Now append the text string
     //
-    strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
+    if (MenuInfo->MenuItemList[MenuItemNumber])
+        strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
 
     //
     // Check if using centered menu, and add spaces on the right if so
@@ -396,7 +450,7 @@ TuiDrawMenuItem(PUI_MENU_INFO MenuInfo,
     //
     // If it is a separator
     //
-    if (!(_stricmp(MenuInfo->MenuItemList[MenuItemNumber], "SEPARATOR")))
+    if (MenuInfo->MenuItemList[MenuItemNumber] == NULL)
     {
         //
         // Make it a separator line and use menu colors
@@ -473,7 +527,8 @@ TuiProcessMenuKeyboardEvent(PUI_MENU_INFO MenuInfo,
         //
         // Process the key
         //
-        if ((KeyEvent == KEY_UP) || (KeyEvent == KEY_DOWN))
+        if ((KeyEvent == KEY_UP  ) || (KeyEvent == KEY_DOWN) ||
+            (KeyEvent == KEY_HOME) || (KeyEvent == KEY_END ))
         {
             //
             // Get the current selected item and count
@@ -482,28 +537,37 @@ TuiProcessMenuKeyboardEvent(PUI_MENU_INFO MenuInfo,
             Count = MenuInfo->MenuItemCount - 1;
 
             //
-            // Check if this was a key up and there's a selected menu item
+            // Check the key and change the selected menu item
             //
-            if ((KeyEvent == KEY_UP) && (Selected))
+            if ((KeyEvent == KEY_UP) && (Selected > 0))
             {
                 //
-                // Update the menu (Deselect previous item)
+                // Deselect previous item and go up
                 //
                 MenuInfo->SelectedMenuItem--;
                 TuiDrawMenuItem(MenuInfo, Selected);
                 Selected--;
 
                 // Skip past any separators
-                if ((Selected) &&
-                    !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
+                if ((Selected > 0) &&
+                    (MenuInfo->MenuItemList[Selected] == NULL))
                 {
                     MenuInfo->SelectedMenuItem--;
                 }
             }
+            else if ( ((KeyEvent == KEY_UP) && (Selected == 0)) ||
+                       (KeyEvent == KEY_END) )
+            {
+                //
+                // Go to the end
+                //
+                MenuInfo->SelectedMenuItem = Count;
+                TuiDrawMenuItem(MenuInfo, Selected);
+            }
             else if ((KeyEvent == KEY_DOWN) && (Selected < Count))
             {
                 //
-                // Update the menu (deselect previous item)
+                // Deselect previous item and go down
                 //
                 MenuInfo->SelectedMenuItem++;
                 TuiDrawMenuItem(MenuInfo, Selected);
@@ -511,11 +575,20 @@ TuiProcessMenuKeyboardEvent(PUI_MENU_INFO MenuInfo,
 
                 // Skip past any separators
                 if ((Selected < Count) &&
-                    !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
+                    (MenuInfo->MenuItemList[Selected] == NULL))
                 {
                     MenuInfo->SelectedMenuItem++;
                 }
             }
+            else if ( ((KeyEvent == KEY_DOWN) && (Selected == Count)) ||
+                       (KeyEvent == KEY_HOME) )
+            {
+                //
+                // Go to the beginning
+                //
+                MenuInfo->SelectedMenuItem = 0;
+                TuiDrawMenuItem(MenuInfo, Selected);
+            }
 
             //
             // Select new item and update video buffer