]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
Clean the help string and hot key info if an empty form is painting.
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
index 8e5b890bf359dfed1e5328253735dc3ae2b480b1..fffc67d6954899e8a58a5c239f596762f6a84006 100644 (file)
@@ -259,7 +259,7 @@ GetPrompt (
 /**\r
   Get the supported width for a particular op-code\r
 \r
-  @param  Statement              The curent statement.\r
+  @param  MenuOption             The menu option.\r
   @param  AdjustWidth            The width which is saved for the space.\r
 \r
   @return Returns the number of CHAR16 characters that is support.\r
@@ -267,19 +267,26 @@ GetPrompt (
 **/\r
 UINT16\r
 GetWidth (\r
-  IN FORM_DISPLAY_ENGINE_STATEMENT        *Statement,\r
-  OUT UINT16                              *AdjustWidth\r
+  IN  UI_MENU_OPTION     *MenuOption,\r
+  OUT UINT16             *AdjustWidth\r
   )\r
 {\r
-  CHAR16       *String;\r
-  UINTN        Size;\r
-  EFI_IFR_TEXT *TestOp;\r
+  CHAR16                        *String;\r
+  UINTN                         Size;\r
+  EFI_IFR_TEXT                  *TestOp;\r
+  UINT16                        ReturnWidth;\r
+  FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+\r
+  Statement = MenuOption->ThisTag;\r
 \r
   //\r
   // For modal form, clean the entire row.\r
   //\r
   if ((gFormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
-    return (UINT16)(gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - gModalSkipColumn - SCROLL_ARROW_HEIGHT);\r
+    if (AdjustWidth  != NULL) {\r
+      *AdjustWidth = LEFT_SKIPPED_COLUMNS;\r
+    }\r
+    return (UINT16)(gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gModalSkipColumn + LEFT_SKIPPED_COLUMNS));\r
   }\r
 \r
   Size = 0;\r
@@ -316,13 +323,23 @@ GetWidth (
     //\r
     // Keep consistent with current behavior.\r
     //\r
-    return (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2);\r
+    ReturnWidth = (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2);\r
+  } else {\r
+    if (AdjustWidth != NULL) {\r
+      *AdjustWidth = 1;\r
+    }\r
+\r
+    ReturnWidth =  (UINT16) (gPromptBlockWidth - 1);\r
   }\r
 \r
-  if (AdjustWidth != NULL) {\r
-    *AdjustWidth = 1;\r
+  //\r
+  // For nest in statement, should the subtitle indent.\r
+  //\r
+  if (MenuOption->NestInStatement) {\r
+    ReturnWidth -= SUBTITLE_INDENT;\r
   }\r
-  return (UINT16) (gPromptBlockWidth - 1);\r
+\r
+  return ReturnWidth;\r
 }\r
 \r
 /**\r
@@ -536,24 +553,7 @@ UiAddMenuOption (
   String = GetToken (PromptId, gFormData->HiiHandle);\r
   ASSERT (String != NULL);\r
 \r
-  Width  = GetWidth (Statement, NULL);\r
-  for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
-    //\r
-    // If there is more string to process print on the next row and increment the Skip value\r
-    //\r
-    if (StrLen (&String[ArrayEntry]) != 0) {\r
-      NumberOfLines++;\r
-    }\r
-    FreePool (OutputString);\r
-  }\r
-\r
   if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
-    //\r
-    // Add three MenuOptions for Date/Time\r
-    // Data format :      [01/02/2004]      [11:22:33]\r
-    // Line number :        0  0    1         0  0  1\r
-    //\r
-    NumberOfLines = 0;\r
     Count = 3;\r
   }\r
 \r
@@ -568,14 +568,6 @@ UiAddMenuOption (
     MenuOption->NestInStatement = NestIn;\r
     MenuOption->EntryNumber = *MenuItemCount;\r
 \r
-    if (Index == 2) {\r
-      //\r
-      // Override LineNumber for the MenuOption in Date/Time sequence\r
-      //\r
-      MenuOption->Skip = 1;\r
-    } else {\r
-      MenuOption->Skip = NumberOfLines;\r
-    }\r
     MenuOption->Sequence = Index;\r
 \r
     if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) {\r
@@ -630,6 +622,37 @@ UiAddMenuOption (
       }\r
     }\r
 \r
+    if (Index == 0 && \r
+      (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) && \r
+      (Statement->OpCode->OpCode != EFI_IFR_TIME_OP)) {\r
+      Width  = GetWidth (MenuOption, NULL);\r
+      for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
+        //\r
+        // If there is more string to process print on the next row and increment the Skip value\r
+        //\r
+        if (StrLen (&String[ArrayEntry]) != 0) {\r
+          NumberOfLines++;\r
+        }\r
+        FreePool (OutputString);\r
+      }\r
+    } else {\r
+      //\r
+      // Add three MenuOptions for Date/Time\r
+      // Data format :      [01/02/2004]      [11:22:33]\r
+      // Line number :        0  0    1         0  0  1\r
+      //    \r
+      NumberOfLines = 0;\r
+    }\r
+\r
+    if (Index == 2) {\r
+      //\r
+      // Override LineNumber for the MenuOption in Date/Time sequence\r
+      //\r
+      MenuOption->Skip = 1;\r
+    } else {\r
+      MenuOption->Skip = NumberOfLines;\r
+    }\r
+\r
     InsertTailList (&gMenuOption, &MenuOption->Link);\r
   }\r
 \r
@@ -1574,6 +1597,58 @@ DisplayMenuString (
   PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);\r
 }\r
 \r
+/**\r
+  Check whether this menu can has option string.\r
+\r
+  @param  MenuOption               The menu opton which this attribut used to.\r
+\r
+  @retval TRUE                     This menu option can have option string.\r
+  @retval FALSE                    This menu option can't have option string.\r
+\r
+**/\r
+BOOLEAN \r
+HasOptionString (\r
+  IN UI_MENU_OPTION                  *MenuOption\r
+  )\r
+{\r
+  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
+  CHAR16                          *String;\r
+  UINTN                           Size;\r
+  EFI_IFR_TEXT                    *TestOp;\r
+\r
+  Size = 0;\r
+  Statement = MenuOption->ThisTag;\r
+\r
+  //\r
+  // See if the second text parameter is really NULL\r
+  //\r
+  if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
+    TestOp = (EFI_IFR_TEXT *) Statement->OpCode;\r
+    if (TestOp->TextTwo != 0) {\r
+      String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);\r
+      Size   = StrLen (String);\r
+      FreePool (String);\r
+    }\r
+  }\r
+\r
+  if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
+    (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||\r
+    (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||\r
+    (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||\r
+    (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||\r
+    //\r
+    // Allow a wide display if text op-code and no secondary text op-code\r
+    //\r
+    ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))\r
+    ) {\r
+\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
 /**\r
   Print string for this menu option.\r
 \r
@@ -1604,7 +1679,6 @@ DisplayOneMenu (
   CHAR16                          *StringPtr;\r
   CHAR16                          *OptionString;\r
   CHAR16                          *OutputString;\r
-  UINTN                           OriginalRow;\r
   UINT16                          GlyphWidth;\r
   UINTN                           Temp;\r
   UINTN                           Temp2;\r
@@ -1613,15 +1687,18 @@ DisplayOneMenu (
   UINTN                           Row;\r
   UINTN                           Col;\r
   UINTN                           PromptLineNum;\r
+  UINTN                           OptionLineNum;\r
   CHAR16                          AdjustValue;\r
+  UINTN                           MaxRow;\r
 \r
   Statement = MenuOption->ThisTag;\r
-  Col       = MenuOption->Col;\r
-  Row       = MenuOption->Row;\r
   Temp      = SkipLine;\r
   Temp2     = SkipLine;\r
   Temp3     = SkipLine;\r
-  AdjustValue = 0;\r
+  AdjustValue   = 0;\r
+  PromptLineNum = 0;\r
+  OptionLineNum = 0;\r
+  MaxRow        = 0;\r
 \r
   //\r
   // Set default color.\r
@@ -1645,8 +1722,9 @@ DisplayOneMenu (
     }\r
   \r
     Width       = (UINT16) gOptionBlockWidth - 1;\r
-    OriginalRow = Row;\r
+    Row         = MenuOption->Row;\r
     GlyphWidth  = 1;\r
+    OptionLineNum = 0;\r
   \r
     for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
       if (((Temp2 == 0)) && (Row <= BottomRow)) {\r
@@ -1671,6 +1749,7 @@ DisplayOneMenu (
         } else {\r
           DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
         }\r
+        OptionLineNum++;\r
       }\r
       \r
       //\r
@@ -1686,7 +1765,7 @@ DisplayOneMenu (
           //\r
           // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
           //\r
-          if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+          if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
             MenuOption->Skip++;\r
           }\r
         }\r
@@ -1698,50 +1777,22 @@ DisplayOneMenu (
       }\r
     }\r
   \r
-    Row   = OriginalRow;\r
     Highlight = FALSE;\r
 \r
     FreePool (OptionString);\r
   }\r
-  Temp2 = 0;\r
-\r
 \r
   //\r
-  // 2. Pre calculate the skip value.\r
+  // 2. Paint the description.\r
   //\r
-  if ((Statement->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
-    StringPtr   = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
-  \r
-    Width       = (UINT16) gOptionBlockWidth - 1;\r
-    OriginalRow = Row;\r
-    GlyphWidth    = 1;\r
-    for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
-      if (StrLen (&StringPtr[Index]) != 0) {\r
-        Row++;\r
-        if ((Row - OriginalRow) >= MenuOption->Skip) {\r
-          MenuOption->Skip++;\r
-        }\r
-      }\r
-      FreePool (OutputString);\r
-    }\r
-  \r
-    Row = OriginalRow;\r
-    FreePool (StringPtr);\r
-  }\r
-\r
-\r
-  //\r
-  // 3. Paint the description.\r
-  //\r
-  PromptWidth   = GetWidth (Statement, &AdjustValue);\r
-  OriginalRow   = Row;\r
+  PromptWidth   = GetWidth (MenuOption, &AdjustValue);\r
+  Row           = MenuOption->Row;\r
   GlyphWidth    = 1;\r
   PromptLineNum = 0;\r
 \r
   if (MenuOption->Description == NULL || MenuOption->Description[0] == '\0') {\r
-    while (Temp++ < MenuOption->Skip) {\r
-      PrintStringAtWithWidth (BeginCol, Row++, L"", PromptWidth + AdjustValue + SkipWidth);\r
-    } \r
+    PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);\r
+    PromptLineNum++;\r
   } else {\r
     for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) {      \r
       if ((Temp == 0) && (Row <= BottomRow)) { \r
@@ -1779,34 +1830,24 @@ DisplayOneMenu (
     }\r
 \r
     Highlight = FALSE;\r
-\r
-    //\r
-    // Clean the empty prompt line.\r
-    // These line is used by option string but not prompt, so clean them here.\r
-    //\r
-    Row = OriginalRow + PromptLineNum;\r
-    while (PromptLineNum + SkipLine < MenuOption->Skip && Row <= BottomRow) {\r
-      PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);\r
-      PromptLineNum ++;\r
-      Row ++;\r
-    }\r
   }\r
-  Row = OriginalRow;\r
 \r
 \r
   //\r
-  // 4. If this is a text op with secondary text information\r
+  // 3. If this is a text op with secondary text information\r
   //\r
   if ((Statement->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
     StringPtr   = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
   \r
     Width       = (UINT16) gOptionBlockWidth - 1;\r
-    OriginalRow = Row;\r
+    Row         = MenuOption->Row;\r
     GlyphWidth  = 1;\r
+    OptionLineNum = 0;\r
 \r
     for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
       if ((Temp3 == 0) && (Row <= BottomRow)) {\r
         DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
+        OptionLineNum++;\r
       }\r
       //\r
       // If there is more string to process print on the next row and increment the Skip value\r
@@ -1822,11 +1863,25 @@ DisplayOneMenu (
         Temp3--;\r
       }\r
     }\r
-  \r
-    Row = OriginalRow;\r
+\r
     FreePool (StringPtr);\r
   }\r
 \r
+  //\r
+  // 4.Line number for Option string and prompt string are not equal.\r
+  //  Clean the column whose line number is less.\r
+  //\r
+  if (HasOptionString(MenuOption) && (OptionLineNum != PromptLineNum)) {\r
+    Col    =  OptionLineNum < PromptLineNum ? MenuOption->OptCol : BeginCol;\r
+    Row    = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row;\r
+    Width  = (UINT16) (OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth);\r
+    MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1;\r
+    \r
+    while (Row <= MaxRow) {\r
+      DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE);\r
+    }\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1999,9 +2054,12 @@ UiDisplayMenu (
         if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
           UpArrow = TRUE;\r
         }\r
-        \r
-        PrintStringAtWithWidth(gStatementDimensions.LeftColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
 \r
+        if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+          PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);\r
+        } else {\r
+          PrintStringAtWithWidth(gStatementDimensions.LeftColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
+        }\r
         if (UpArrow) {\r
           gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
           PrintCharAt (\r
@@ -2036,15 +2094,28 @@ UiDisplayMenu (
             SavedMenuOption = MenuOption;\r
             SkipHighLight   = TRUE;\r
           }\r
-          \r
-          DisplayOneMenu (MenuOption, \r
-                          ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) ? LEFT_SKIPPED_COLUMNS + gModalSkipColumn : LEFT_SKIPPED_COLUMNS,\r
-                          gStatementDimensions.LeftColumn, \r
-                          Link == TopOfScreen ? SkipValue : 0, \r
-                          BottomRow,\r
-                          Link == NewPos && IsSelectable(MenuOption)\r
-                          );\r
 \r
+          if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+            Status = DisplayOneMenu (MenuOption, \r
+                            MenuOption->Col - gStatementDimensions.LeftColumn,\r
+                            gStatementDimensions.LeftColumn + gModalSkipColumn, \r
+                            Link == TopOfScreen ? SkipValue : 0, \r
+                            BottomRow,\r
+                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption))\r
+                            );\r
+          } else {\r
+            Status = DisplayOneMenu (MenuOption, \r
+                            MenuOption->Col - gStatementDimensions.LeftColumn,\r
+                            gStatementDimensions.LeftColumn, \r
+                            Link == TopOfScreen ? SkipValue : 0, \r
+                            BottomRow,\r
+                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption))\r
+                            );         \r
+          }\r
+\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
           //\r
           // 3. Update the row info which will be used by next menu.\r
           //\r
@@ -2069,7 +2140,7 @@ UiDisplayMenu (
         //\r
         while (Row <= BottomRow) {\r
           if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
-            PrintStringAtWithWidth(gStatementDimensions.LeftColumn, Row++, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
+            PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, Row++, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);\r
           } else {\r
             PrintStringAtWithWidth(gStatementDimensions.LeftColumn, Row++, L"", gStatementDimensions.RightColumn - gHelpBlockWidth - gStatementDimensions.LeftColumn);\r
           }\r
@@ -2078,8 +2149,11 @@ UiDisplayMenu (
         //\r
         // 4. Print the down arrow row.\r
         //\r
-        PrintStringAtWithWidth(gStatementDimensions.LeftColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
-       \r
+        if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+          PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 *  + gModalSkipColumn);\r
+        } else {\r
+          PrintStringAtWithWidth(gStatementDimensions.LeftColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
+        }\r
         if (DownArrow) {\r
           gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
           PrintCharAt (\r
@@ -2091,10 +2165,6 @@ UiDisplayMenu (
         }\r
 \r
         MenuOption = NULL;\r
-\r
-        if (IsListEmpty (&gMenuOption)) { \r
-          ControlFlag = CfReadKey;\r
-        }\r
       }\r
       break;\r
 \r
@@ -2114,6 +2184,14 @@ UiDisplayMenu (
         break;\r
       }\r
 \r
+      if (IsListEmpty (&gMenuOption)) {\r
+        //\r
+        // No menu option, just update the hotkey filed.\r
+        //\r
+        RefreshKeyHelp(gFormData, NULL, FALSE);\r
+        break;\r
+      }\r
+\r
       if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) {\r
         Temp = SkipValue;\r
       } else {\r
@@ -2140,7 +2218,7 @@ UiDisplayMenu (
               ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
             }\r
 \r
-            Width               = (UINT16) gOptionBlockWidth;\r
+            Width               = (UINT16) gOptionBlockWidth - 1;\r
             OriginalRow         = MenuOption->Row;\r
             GlyphWidth          = 1;\r
 \r
@@ -2175,7 +2253,7 @@ UiDisplayMenu (
               }\r
 \r
               OriginalRow = MenuOption->Row;\r
-              Width       = GetWidth (MenuOption->ThisTag, NULL);\r
+              Width       = GetWidth (MenuOption, NULL);\r
               GlyphWidth  = 1;\r
 \r
               for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
@@ -2226,7 +2304,7 @@ UiDisplayMenu (
           if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
             ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
           }\r
-          Width               = (UINT16) gOptionBlockWidth;\r
+          Width               = (UINT16) gOptionBlockWidth - 1;\r
 \r
           OriginalRow         = MenuOption->Row;\r
           GlyphWidth          = 1;\r
@@ -2257,7 +2335,7 @@ UiDisplayMenu (
           if (NewLine) {\r
             OriginalRow = MenuOption->Row;\r
 \r
-            Width       = GetWidth (Statement, NULL);\r
+            Width       = GetWidth (MenuOption, NULL);\r
             GlyphWidth          = 1;\r
 \r
             for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
@@ -2298,15 +2376,22 @@ UiDisplayMenu (
       }\r
 \r
       if (Repaint || NewLine) {\r
-        //\r
-        // Don't print anything if it is a NULL help token\r
-        //\r
-        ASSERT(MenuOption != NULL);\r
-        HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
-        if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
+        if (IsListEmpty (&gMenuOption)) {\r
+          //\r
+          // Don't print anything if no mwnu option.\r
+          //\r
           StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
         } else {\r
-          StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+          //\r
+          // Don't print anything if it is a NULL help token\r
+          //\r
+          ASSERT(MenuOption != NULL);\r
+          HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
+          if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
+            StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+          } else {\r
+            StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+          }\r
         }\r
 \r
         RowCount      = BottomRow - TopRow + 1;\r
@@ -2632,9 +2717,9 @@ UiDisplayMenu (
       break;\r
 \r
     case CfScreenOperation:\r
-      if (ScreenOperation != UiReset) {\r
+      if ((ScreenOperation != UiReset) && (ScreenOperation != UiHotKey)) {\r
         //\r
-        // If the screen has no menu items, and the user didn't select UiReset\r
+        // If the screen has no menu items, and the user didn't select UiReset or UiHotKey\r
         // ignore the selection and go back to reading keys.\r
         //\r
         if (IsListEmpty (&gMenuOption)) {\r
@@ -2820,6 +2905,11 @@ UiDisplayMenu (
         MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
         UpdateStatusBar (INPUT_ERROR, FALSE);\r
       } else {\r
+        if (NewPos->ForwardLink == &gMenuOption) {\r
+          NewLine   = FALSE;\r
+          Repaint   = FALSE;\r
+          break;\r
+        }\r
         //\r
         // Scroll up to the last page.\r
         //\r
@@ -2828,6 +2918,7 @@ UiDisplayMenu (
         MenuOption      = MENU_OPTION_FROM_LINK (SavedListEntry);\r
         ScreenOperation = UiPageUp;\r
         ControlFlag     = CfScreenOperation;\r
+        SkipValue       = 0;\r
       }\r
       break;\r
 \r
@@ -2884,23 +2975,32 @@ UiDisplayMenu (
       }\r
       \r
       if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
-        SkipValue = 0;\r
         if (TopOfScreen == &gMenuOption) {\r
           TopOfScreen = gMenuOption.ForwardLink;\r
           NewPos      = gMenuOption.BackLink;\r
           MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
-          Repaint = FALSE;\r
+          if (Index < PreviousMenuOption->Skip) {\r
+            Repaint = TRUE;\r
+            SkipValue = PreviousMenuOption->Skip - (Index - TopRow);\r
+          } else {\r
+            Repaint = FALSE;\r
+            SkipValue = 0;\r
+          }\r
         } else if (TopOfScreen != Link) {\r
           TopOfScreen = Link;\r
           NewPos      = Link;\r
           MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+          SkipValue = 0;\r
         } else {\r
           //\r
           // Finally we know that NewPos is the last MenuOption can be focused.\r
           //\r
-          Repaint = FALSE;\r
+          if (SkipValue == 0) {\r
+            Repaint = FALSE;\r
+          }\r
           NewPos  = Link;\r
           MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+          SkipValue = 0;\r
         }\r
       } else {\r
         if (Index > TopRow) {\r
@@ -2948,6 +3048,13 @@ UiDisplayMenu (
 \r
       ASSERT (NewPos != NULL);\r
       if (NewPos->ForwardLink == &gMenuOption) {\r
+        MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+        if (SkipValue + BottomRow - TopRow + 1 < MenuOption->Skip) {\r
+          SkipValue += BottomRow - TopRow + 1;\r
+          NewLine = TRUE;\r
+          Repaint = TRUE;\r
+          break;\r
+        }\r
         NewLine = FALSE;\r
         Repaint = FALSE;\r
         break;\r
@@ -3026,6 +3133,12 @@ UiDisplayMenu (
       AdjustDateAndTimePosition (FALSE, &NewPos);\r
 \r
       if (NewPos->ForwardLink != &gMenuOption) {\r
+        if (NewPos == TopOfScreen) {\r
+          Temp2 = SkipValue;\r
+        } else {\r
+          Temp2 = 0;\r
+        }\r
+\r
         MenuOption      = MENU_OPTION_FROM_LINK (NewPos);\r
         NewLine         = TRUE;\r
         NewPos          = NewPos->ForwardLink;\r
@@ -3034,11 +3147,11 @@ UiDisplayMenu (
         //\r
         // Current menu not at the bottom of the form.\r
         //\r
-        if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
+        if (BottomRow >= MenuOption->Row + MenuOption->Skip - Temp2) {\r
           //\r
           // Find the next selectable menu.\r
           //\r
-          Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
+          Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip + Temp2);\r
           //\r
           // We hit the end of MenuOption that can be focused\r
           // so we simply scroll to the first page.\r
@@ -3070,10 +3183,10 @@ UiDisplayMenu (
         if (NextMenuOption->Row == 0) {\r
           UpdateOptionSkipLines (NextMenuOption);\r
         }\r
-        DistanceValue  = Difference + NextMenuOption->Skip;\r
+        DistanceValue  = Difference + NextMenuOption->Skip - Temp2;\r
 \r
         Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
-        if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
+        if ((MenuOption->Row + MenuOption->Skip - Temp2 == BottomRow + 1) &&\r
             (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP ||\r
              NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)\r
             ) {\r
@@ -3171,7 +3284,7 @@ UiDisplayMenu (
         //\r
         // Scroll to the first page.\r
         //\r
-        if (TopOfScreen != gMenuOption.ForwardLink) {\r
+        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
           TopOfScreen = gMenuOption.ForwardLink;\r
           Repaint     = TRUE;\r
           MenuOption  = NULL;\r