]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
Refine the logic about initialize questions value
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Ui.c
index 01909e46491897bb5318b3b9cd3bacae72092ea7..137115196c6f526972cc569aeafb87b40ef890bc 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility functions for User Interface functions.\r
 \r
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -731,8 +731,10 @@ UiAddMenuOption (
     }\r
     MenuOption->Sequence = Index;\r
 \r
-    if (Statement->GrayOutExpression != NULL) {\r
-      MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b;\r
+    if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut ) {\r
+      MenuOption->GrayOut = TRUE;\r
+    } else {\r
+      MenuOption->GrayOut = FALSE;\r
     }\r
 \r
     //\r
@@ -850,8 +852,6 @@ CreateDialog (
   ASSERT (TempString);\r
   ASSERT (BufferedString);\r
 \r
-  VA_START (Marker, KeyValue);\r
-\r
   //\r
   // Zero the outgoing buffer\r
   //\r
@@ -873,6 +873,8 @@ CreateDialog (
 \r
   LargestString = 0;\r
 \r
+  VA_START (Marker, KeyValue);\r
+\r
   //\r
   // Determine the largest string in the dialog box\r
   // Notice we are starting with 1 since String is the first string\r
@@ -1306,101 +1308,174 @@ GetWidth (
 /**\r
   Will copy LineWidth amount of a string in the OutputString buffer and return the\r
   number of CHAR16 characters that were copied into the OutputString buffer.\r
+  The output string format is:\r
+    Glyph Info + String info + '\0'.\r
+\r
+  In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
 \r
   @param  InputString            String description for this option.\r
   @param  LineWidth              Width of the desired string to extract in CHAR16\r
                                  characters\r
+  @param  GlyphWidth             The glyph width of the begin of the char in the string.\r
   @param  Index                  Where in InputString to start the copy process\r
   @param  OutputString           Buffer to copy the string into\r
 \r
-  @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
+  @return Returns the number of CHAR16 characters that were copied into the OutputString \r
+  buffer, include extra glyph info and '\0' info.\r
 \r
 **/\r
 UINT16\r
 GetLineByWidth (\r
   IN      CHAR16                      *InputString,\r
   IN      UINT16                      LineWidth,\r
+  IN OUT  UINT16                      *GlyphWidth,\r
   IN OUT  UINTN                       *Index,\r
   OUT     CHAR16                      **OutputString\r
   )\r
 {\r
-  UINT16          Count;\r
-  UINT16          Count2;\r
+  UINT16          StrOffset;\r
+  UINT16          GlyphOffset;\r
+  UINT16          OriginalGlyphWidth;\r
+  BOOLEAN         ReturnFlag;\r
+  UINT16          LastSpaceOffset;\r
+  UINT16          LastGlyphWidth;\r
+\r
+  if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
+    return 0;\r
+  }\r
 \r
-  if (GetLineByWidthFinished) {\r
-    GetLineByWidthFinished = FALSE;\r
-    return (UINT16) 0;\r
+  if (LineWidth == 0 || *GlyphWidth == 0) {\r
+    return 0;\r
   }\r
 \r
-  Count         = LineWidth;\r
-  Count2        = 0;\r
+  //\r
+  // Save original glyph width.\r
+  //\r
+  OriginalGlyphWidth = *GlyphWidth;\r
+  LastGlyphWidth     = OriginalGlyphWidth;\r
+  ReturnFlag         = FALSE;\r
+  LastSpaceOffset    = 0;\r
 \r
-  *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));\r
+  //\r
+  // NARROW_CHAR can not be printed in screen, so if a line only contain  the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line  in Screen.\r
+  // To avoid displaying this  empty line in screen,  just skip  the two CHARs here.\r
+  //\r
+  if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
+    *Index = *Index + 2;\r
+  }\r
 \r
   //\r
-  // Ensure we have got a valid buffer\r
+  // Fast-forward the string and see if there is a carriage-return in the string\r
   //\r
-  if (*OutputString != NULL) {\r
+  for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {\r
+    switch (InputString[*Index + StrOffset]) {\r
+      case NARROW_CHAR:\r
+        *GlyphWidth = 1;\r
+        break;\r
 \r
-    //\r
-    //NARROW_CHAR can not be printed in screen, so if a line only contain  the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line  in Screen.\r
-    //To avoid displaying this  empty line in screen,  just skip  the two CHARs here.\r
-    //\r
-   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
-     *Index = *Index + 2;\r
-   }\r
+      case WIDE_CHAR:\r
+        *GlyphWidth = 2;\r
+        break;\r
 \r
-    //\r
-    // Fast-forward the string and see if there is a carriage-return in the string\r
-    //\r
-    for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)\r
-      ;\r
+      case CHAR_CARRIAGE_RETURN:\r
+      case CHAR_LINEFEED:\r
+      case CHAR_NULL:\r
+        ReturnFlag = TRUE;\r
+        break;\r
+\r
+      default:\r
+        GlyphOffset = GlyphOffset + *GlyphWidth;\r
 \r
+        //\r
+        // Record the last space info in this line. Will be used in rewind.\r
+        //\r
+        if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {\r
+          LastSpaceOffset = StrOffset;\r
+          LastGlyphWidth  = *GlyphWidth;\r
+        }\r
+        break;\r
+    }\r
+\r
+    if (ReturnFlag) {\r
+      break;\r
+    }\r
+  } \r
+\r
+  //\r
+  // Rewind the string from the maximum size until we see a space to break the line\r
+  //\r
+  if (GlyphOffset > LineWidth) {\r
     //\r
-    // Copy the desired LineWidth of data to the output buffer.\r
-    // Also make sure that we don't copy more than the string.\r
-    // Also make sure that if there are linefeeds, we account for them.\r
+    // Rewind the string to last space char in this line.\r
     //\r
-    if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&\r
-        (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))\r
-        ) {\r
+    if (LastSpaceOffset != 0) {\r
+      StrOffset   = LastSpaceOffset;\r
+      *GlyphWidth = LastGlyphWidth;\r
+    } else {\r
       //\r
-      // Convert to CHAR16 value and show that we are done with this operation\r
+      // Roll back to last char in the line width.\r
       //\r
-      LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);\r
-      if (LineWidth != 0) {\r
-        GetLineByWidthFinished = TRUE;\r
-      }\r
-    } else {\r
-      if (Count2 == LineWidth) {\r
-        //\r
-        // Rewind the string from the maximum size until we see a space to break the line\r
-        //\r
-        for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)\r
-          ;\r
-        if (LineWidth == 0) {\r
-          LineWidth = Count;\r
-        }\r
-      } else {\r
-        LineWidth = Count2;\r
-      }\r
+      StrOffset--;\r
     }\r
+  }\r
 \r
-    CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);\r
+  //\r
+  // The CHAR_NULL has process last time, this time just return 0 to stand for the end.\r
+  //\r
+  if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
+    return 0;\r
+  }\r
 \r
+  //\r
+  // Need extra glyph info and '\0' info, so +2.\r
+  //\r
+  *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
+  if (*OutputString == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Save the glyph info at the begin of the string, will used by Print function.\r
+  //\r
+  if (OriginalGlyphWidth == 1) {\r
+    *(*OutputString) = NARROW_CHAR;\r
+  } else  {\r
+    *(*OutputString) = WIDE_CHAR;\r
+  }\r
+\r
+  CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
+\r
+  if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
+    //\r
+    // Skip the space info at the begin of next line.\r
+    //  \r
+    *Index = (UINT16) (*Index + StrOffset + 1);\r
+  } else if ((InputString[*Index + StrOffset] == CHAR_LINEFEED)) {\r
     //\r
-    // If currently pointing to a space, increment the index to the first non-space character\r
+    // Skip the /n or /n/r info.\r
     //\r
-    for (;\r
-         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);\r
-         (*Index)++\r
-        )\r
-      ;\r
-    *Index = (UINT16) (*Index + LineWidth);\r
-    return LineWidth;\r
+    if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
+      *Index = (UINT16) (*Index + StrOffset + 2);\r
+    } else {\r
+      *Index = (UINT16) (*Index + StrOffset + 1);\r
+    }\r
+  } else if ((InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN)) {\r
+    //\r
+    // Skip the /r or /r/n info.\r
+    //  \r
+    if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
+      *Index = (UINT16) (*Index + StrOffset + 2);\r
+    } else {\r
+      *Index = (UINT16) (*Index + StrOffset + 1);\r
+    }\r
   } else {\r
-    return (UINT16) 0;\r
+    *Index = (UINT16) (*Index + StrOffset);\r
   }\r
+\r
+  //\r
+  // Include extra glyph info and '\0' info, so +2.\r
+  //\r
+  return StrOffset + 2;\r
 }\r
 \r
 \r
@@ -1423,6 +1498,7 @@ UpdateOptionSkipLines (
   UINTN   OriginalRow;\r
   CHAR16  *OutputString;\r
   CHAR16  *OptionString;\r
+  UINT16  GlyphWidth;\r
 \r
   Row           = 0;\r
   OptionString  = NULL;\r
@@ -1432,8 +1508,9 @@ UpdateOptionSkipLines (
     Width               = (UINT16) gOptionBlockWidth;\r
 \r
     OriginalRow         = Row;\r
+    GlyphWidth          = 1;\r
 \r
-    for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+    for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
       //\r
       // If there is more string to process print on the next row and increment the Skip value\r
       //\r
@@ -1999,12 +2076,7 @@ ProcessGotoOpCode (
     RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
 \r
     if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
-      Status = EvaluateExpression (Selection->FormSet, RefForm, RefForm->SuppressExpression);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-\r
-      if (RefForm->SuppressExpression->Result.Value.b) {\r
+      if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
         //\r
         // Form is suppressed. \r
         //\r
@@ -2093,7 +2165,9 @@ UiDisplayMenu (
   CHAR16                          *StringPtr;\r
   CHAR16                          *OptionString;\r
   CHAR16                          *OutputString;\r
-  CHAR16                          *FormattedString;\r
+  CHAR16                          *HelpString;\r
+  CHAR16                          *HelpHeaderString;\r
+  CHAR16                          *HelpBottomString;\r
   BOOLEAN                         NewLine;\r
   BOOLEAN                         Repaint;\r
   BOOLEAN                         SavedValue;\r
@@ -2121,17 +2195,39 @@ UiDisplayMenu (
   UI_MENU_LIST                    *CurrentMenu;\r
   UINTN                           ModalSkipColumn;\r
   BROWSER_HOT_KEY                 *HotKey;\r
+  UINTN                           HelpPageIndex;\r
+  UINTN                           HelpPageCount;\r
+  UINTN                           RowCount;\r
+  UINTN                           HelpLine;\r
+  UINTN                           HelpHeaderLine;\r
+  UINTN                           HelpBottomLine;\r
+  BOOLEAN                         MultiHelpPage;\r
+  UINT16                          GlyphWidth;\r
+  UINT16                          EachLineWidth;\r
+  UINT16                          HeaderLineWidth;\r
+  UINT16                          BottomLineWidth;\r
 \r
   CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
 \r
   Status              = EFI_SUCCESS;\r
-  FormattedString     = NULL;\r
+  HelpString          = NULL;\r
+  HelpHeaderString    = NULL;\r
+  HelpBottomString    = NULL;\r
   OptionString        = NULL;\r
   ScreenOperation     = UiNoOperation;\r
   NewLine             = TRUE;\r
   MinRefreshInterval  = 0;\r
   DefaultId           = 0;\r
-\r
+  HelpPageCount       = 0;\r
+  HelpLine            = 0;\r
+  RowCount            = 0;\r
+  HelpBottomLine      = 0;\r
+  HelpHeaderLine      = 0;\r
+  HelpPageIndex       = 0;\r
+  MultiHelpPage       = FALSE;\r
+  EachLineWidth       = 0;\r
+  HeaderLineWidth     = 0;\r
+  BottomLineWidth     = 0;\r
   OutputString        = NULL;\r
   UpArrow             = FALSE;\r
   DownArrow           = FALSE;\r
@@ -2282,6 +2378,7 @@ UiDisplayMenu (
 \r
           Width       = GetWidth (Statement, MenuOption->Handle);\r
           OriginalRow = Row;\r
+          GlyphWidth  = 1;\r
 \r
           if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
             //\r
@@ -2295,7 +2392,7 @@ UiDisplayMenu (
               );\r
           }\r
 \r
-          for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+          for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
             if ((Temp == 0) && (Row <= BottomRow)) {\r
               PrintStringAt (MenuOption->Col, Row, OutputString);\r
             }\r
@@ -2335,8 +2432,9 @@ UiDisplayMenu (
 \r
             Width       = (UINT16) gOptionBlockWidth;\r
             OriginalRow = Row;\r
+            GlyphWidth  = 1;\r
 \r
-            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+            for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
               if ((Temp2 == 0) && (Row <= BottomRow)) {\r
                 PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
               }\r
@@ -2443,8 +2541,9 @@ UiDisplayMenu (
 \r
             Width       = (UINT16) gOptionBlockWidth;\r
             OriginalRow = Row;\r
+            GlyphWidth = 1;\r
 \r
-            for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {\r
+            for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
               if ((Temp == 0) && (Row <= BottomRow)) {\r
                 PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
               }\r
@@ -2672,8 +2771,9 @@ UiDisplayMenu (
 \r
             Width               = (UINT16) gOptionBlockWidth;\r
             OriginalRow         = MenuOption->Row;\r
+            GlyphWidth          = 1;\r
 \r
-            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+            for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
               if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
                 PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
               }\r
@@ -2700,8 +2800,9 @@ UiDisplayMenu (
 \r
               OriginalRow = MenuOption->Row;\r
               Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);\r
+              GlyphWidth  = 1;\r
 \r
-              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
                 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
                   PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
                 }\r
@@ -2771,8 +2872,9 @@ UiDisplayMenu (
           Width               = (UINT16) gOptionBlockWidth;\r
 \r
           OriginalRow         = MenuOption->Row;\r
+          GlyphWidth          = 1;\r
 \r
-          for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+          for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
             if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
               PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
             }\r
@@ -2794,8 +2896,9 @@ UiDisplayMenu (
             OriginalRow = MenuOption->Row;\r
 \r
             Width       = GetWidth (Statement, MenuOption->Handle);\r
+            GlyphWidth          = 1;\r
 \r
-            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
               if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
                 PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
               }\r
@@ -2845,22 +2948,125 @@ UiDisplayMenu (
           StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
         }\r
 \r
-        ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);\r
-\r
-        gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);\r
-\r
-        for (Index = 0; Index < BottomRow - TopRow; Index++) {\r
+        RowCount      = BottomRow - TopRow;\r
+        HelpPageIndex = 0;\r
+        //\r
+        // 1.Calculate how many line the help string need to print.\r
+        //\r
+        if (HelpString != NULL) {\r
+          FreePool (HelpString);\r
+        }\r
+        HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
+        if (HelpLine > RowCount) {\r
+          MultiHelpPage   = TRUE;\r
+          StringPtr       = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
+          if (HelpHeaderString != NULL) {\r
+            FreePool (HelpHeaderString);\r
+          }\r
+          HelpHeaderLine  = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount);\r
+          StringPtr       = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
+          if (HelpBottomString != NULL) {\r
+            FreePool (HelpBottomString);\r
+          }\r
+          HelpBottomLine  = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);\r
           //\r
-          // Pad String with spaces to simulate a clearing of the previous line\r
+          // Calculate the help page count.\r
           //\r
-          for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {\r
-            StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" ");\r
+          if (HelpLine > 2 * RowCount - 2) {\r
+            HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
+            if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {\r
+              HelpPageCount += 1;\r
+            }\r
+          } else {\r
+            HelpPageCount = 2;\r
           }\r
+        } else {\r
+          MultiHelpPage = FALSE;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Clean the help field first.\r
+      //\r
+      ClearLines (\r
+        LocalScreen.RightColumn - gHelpBlockWidth,\r
+        LocalScreen.RightColumn,\r
+        TopRow,\r
+        BottomRow,\r
+        PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
+        );\r
+\r
+      //\r
+      // Check whether need to show the 'More(U/u)' at the begin.\r
+      // Base on current direct info, here shows aligned to the right side of the column.\r
+      // If the direction is multi line and aligned to right side may have problem, so \r
+      // add ASSERT code here.\r
+      //\r
+      if (HelpPageIndex > 0) {\r
+        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
+        for (Index = 0; Index < HelpHeaderLine; Index++) {\r
+          ASSERT (HelpHeaderLine == 1);\r
+          ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
+          PrintStringAt (\r
+            LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
+            Index + TopRow,\r
+            &HelpHeaderString[Index * HeaderLineWidth]\r
+            );\r
+        }\r
+      }\r
 \r
+      gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);\r
+      //\r
+      // Print the help string info.\r
+      //\r
+      if (!MultiHelpPage) {\r
+        for (Index = 0; Index < HelpLine; Index++) {\r
           PrintStringAt (\r
             LocalScreen.RightColumn - gHelpBlockWidth,\r
             Index + TopRow,\r
-            &FormattedString[Index * gHelpBlockWidth * 2]\r
+            &HelpString[Index * EachLineWidth]\r
+            );\r
+        }\r
+        gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
+      } else  {\r
+        if (HelpPageIndex == 0) {\r
+          for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
+            PrintStringAt (\r
+              LocalScreen.RightColumn - gHelpBlockWidth,\r
+              Index + TopRow,\r
+              &HelpString[Index * EachLineWidth]\r
+              );\r
+          }\r
+        } else {\r
+          for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && \r
+              (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
+            PrintStringAt (\r
+              LocalScreen.RightColumn - gHelpBlockWidth,\r
+              Index + TopRow + HelpHeaderLine,\r
+              &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth]\r
+              );\r
+          }\r
+          if (HelpPageIndex == HelpPageCount - 1) {\r
+            gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
+          }\r
+        } \r
+      }\r
+\r
+      //\r
+      // Check whether need to print the 'More(D/d)' at the bottom.\r
+      // Base on current direct info, here shows aligned to the right side of the column.\r
+      // If the direction is multi line and aligned to right side may have problem, so \r
+      // add ASSERT code here.\r
+      //\r
+      if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
+        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
+        for (Index = 0; Index < HelpBottomLine; Index++) {\r
+          ASSERT (HelpBottomLine == 1);\r
+          ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
+          PrintStringAt (\r
+            LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
+            Index + BottomRow - HelpBottomLine,\r
+            &HelpBottomString[Index * BottomLineWidth]\r
             );\r
         }\r
       }\r
@@ -2984,6 +3190,26 @@ UiDisplayMenu (
         }\r
         break;\r
 \r
+      case 'D':\r
+      case 'd':\r
+        if (!MultiHelpPage) {\r
+          ControlFlag = CfReadKey;\r
+          break;\r
+        }\r
+        ControlFlag    = CfUpdateHelpString;\r
+        HelpPageIndex  = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;\r
+        break;\r
+\r
+      case 'U':\r
+      case 'u':\r
+        if (!MultiHelpPage) {\r
+          ControlFlag = CfReadKey;\r
+          break;\r
+        }\r
+        ControlFlag    = CfUpdateHelpString;\r
+        HelpPageIndex  = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;\r
+        break;\r
+\r
       case CHAR_NULL:\r
         for (Index = 0; Index < mScanCodeNumber; Index++) {\r
           if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
@@ -3561,7 +3787,7 @@ UiDisplayMenu (
       // Reterieve default setting. After it. NV flag will be showed.\r
       //\r
       if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
-        Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope);\r
+        Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope, NULL);\r
         if (!EFI_ERROR (Status)) {\r
           Selection->Action = UI_ACTION_REFRESH_FORM;\r
           Selection->Statement = NULL;\r
@@ -3639,7 +3865,7 @@ UiDisplayMenu (
       //\r
       // Reset to default value for all forms in the whole system.\r
       //\r
-      Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel);\r
+      Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel, NULL);\r
 \r
       if (!EFI_ERROR (Status)) {\r
         Selection->Action = UI_ACTION_REFRESH_FORM;\r
@@ -3659,6 +3885,15 @@ UiDisplayMenu (
       gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);\r
       gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
       gST->ConOut->OutputString (gST->ConOut, L"\n");\r
+      if (HelpString != NULL) {\r
+        FreePool (HelpString);\r
+      }\r
+      if (HelpHeaderString != NULL) {\r
+        FreePool (HelpHeaderString);\r
+      }\r
+      if (HelpBottomString != NULL) {\r
+        FreePool (HelpBottomString);\r
+      }\r
 \r
       return EFI_SUCCESS;\r
 \r