From 6c310dfb78cdbda612b9f5850097580a5e3aa95c Mon Sep 17 00:00:00 2001
From: ydong10 <ydong10@6f19259b-4bc3-4df7-8a09-765794883524>
Date: Tue, 29 May 2012 11:07:05 +0000
Subject: [PATCH] Enable wide string for title and help string

Sign-off-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13371 6f19259b-4bc3-4df7-8a09-765794883524
---
 .../Universal/SetupBrowserDxe/Presentation.c  |   4 +-
 .../SetupBrowserDxe/ProcessOptions.c          |  42 ++-
 MdeModulePkg/Universal/SetupBrowserDxe/Ui.c   | 267 ++++++++++++------
 MdeModulePkg/Universal/SetupBrowserDxe/Ui.h   |  11 +-
 4 files changed, 232 insertions(+), 92 deletions(-)

diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
index 28ed0348ed..7edbdb6229 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -477,6 +477,7 @@ DisplayForm (
   UINT16                 NumberOfLines;
   EFI_STATUS             Status;
   UI_MENU_OPTION         *MenuOption;
+  UINT16                 GlyphWidth;
 
   Handle        = Selection->Handle;
   MenuItemCount = 0;
@@ -528,7 +529,8 @@ DisplayForm (
 
       NumberOfLines = 1;
       ArrayEntry = 0;
-      for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
+      GlyphWidth = 1;
+      for (; GetLineByWidth (StringPtr, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {
         //
         // If there is more string to process print on the next row and increment the Skip value
         //
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
index 82907df092..2a51af8e2f 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
@@ -978,6 +978,7 @@ ProcessOptions (
 
   @param  StringPtr              The entire help string.
   @param  FormattedString        The oupput formatted string.
+  @param  EachLineWidth          The max string length of each line in the formatted string.
   @param  RowCount               TRUE: if Question is selected.
 
 **/
@@ -985,6 +986,7 @@ UINTN
 ProcessHelpString (
   IN  CHAR16  *StringPtr,
   OUT CHAR16  **FormattedString,
+  OUT UINT16  *EachLineWidth,
   IN  UINTN   RowCount
   )
 {
@@ -992,27 +994,49 @@ ProcessHelpString (
   CHAR16  *OutputString;
   UINTN   TotalRowNum;
   UINTN   CheckedNum;
+  UINT16  GlyphWidth;
+  UINT16  LineWidth;
+  UINT16  MaxStringLen;
+  UINT16  StringLen;
 
-  TotalRowNum = 0;
-  CheckedNum  = 0;
+  TotalRowNum    = 0;
+  CheckedNum     = 0;
+  GlyphWidth     = 1;
+  Index          = 0;
+  MaxStringLen   = 0;
+  StringLen      = 0;
+
+  //
+  // Set default help string width.
+  //
+  LineWidth      = (UINT16) (gHelpBlockWidth - 1);
 
   //
   // Get row number of the String.
   //
-  for (Index = 0; GetLineByWidth (StringPtr, (UINT16) (gHelpBlockWidth - 1), &Index, &OutputString) != 0x0000; ) {
+  while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
+    if (StringLen > MaxStringLen) {
+      MaxStringLen = StringLen;
+    }
+
     TotalRowNum ++;
     FreePool (OutputString);
   }
-  
-  *FormattedString = AllocateZeroPool (TotalRowNum * gHelpBlockWidth * sizeof (CHAR16) * 2);
+  *EachLineWidth = MaxStringLen;
+
+  *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));
   ASSERT (*FormattedString != NULL);
 
-  for (Index = 0; GetLineByWidth (StringPtr, (UINT16) (gHelpBlockWidth - 1), &Index, &OutputString) != 0x0000; CheckedNum ++) {
-    CopyMem (*FormattedString + CheckedNum * gHelpBlockWidth * sizeof (CHAR16), OutputString, gHelpBlockWidth * sizeof (CHAR16));
+  //
+  // Generate formatted help string array.
+  //
+  GlyphWidth  = 1;
+  Index       = 0;
+  while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
+    CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));
+    CheckedNum ++;
     FreePool (OutputString);
   }
 
-  ASSERT (CheckedNum == TotalRowNum);
-
   return TotalRowNum; 
 }
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
index 6999f625db..d59109317d 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
@@ -1308,102 +1308,174 @@ GetWidth (
 /**
   Will copy LineWidth amount of a string in the OutputString buffer and return the
   number of CHAR16 characters that were copied into the OutputString buffer.
+  The output string format is:
+    Glyph Info + String info + '\0'.
+
   In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
 
   @param  InputString            String description for this option.
   @param  LineWidth              Width of the desired string to extract in CHAR16
                                  characters
+  @param  GlyphWidth             The glyph width of the begin of the char in the string.
   @param  Index                  Where in InputString to start the copy process
   @param  OutputString           Buffer to copy the string into
 
-  @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.
+  @return Returns the number of CHAR16 characters that were copied into the OutputString 
+  buffer, include extra glyph info and '\0' info.
 
 **/
 UINT16
 GetLineByWidth (
   IN      CHAR16                      *InputString,
   IN      UINT16                      LineWidth,
+  IN OUT  UINT16                      *GlyphWidth,
   IN OUT  UINTN                       *Index,
   OUT     CHAR16                      **OutputString
   )
 {
-  UINT16          Count;
-  UINT16          Count2;
+  UINT16          StrOffset;
+  UINT16          GlyphOffset;
+  UINT16          OriginalGlyphWidth;
+  BOOLEAN         ReturnFlag;
+  UINT16          LastSpaceOffset;
+  UINT16          LastGlyphWidth;
 
-  if (GetLineByWidthFinished) {
-    GetLineByWidthFinished = FALSE;
-    return (UINT16) 0;
+  if (InputString == NULL || Index == NULL || OutputString == NULL) {
+    return 0;
   }
 
-  Count         = LineWidth;
-  Count2        = 0;
-
-  *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));
+  if (LineWidth == 0 || *GlyphWidth == 0) {
+    return 0;
+  }
 
   //
-  // Ensure we have got a valid buffer
+  // Save original glyph width.
   //
-  if (*OutputString != NULL) {
+  OriginalGlyphWidth = *GlyphWidth;
+  LastGlyphWidth     = OriginalGlyphWidth;
+  ReturnFlag         = FALSE;
+  LastSpaceOffset    = 0;
 
-    //
-    //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.
-    //To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
-    //
-   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
-     *Index = *Index + 2;
-   }
+  //
+  // 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.
+  // To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
+  //
+  if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
+    *Index = *Index + 2;
+  }
 
-    //
-    // Fast-forward the string and see if there is a carriage-return or linefeed in the string
-    //
-    for (; (InputString[*Index + Count2] != CHAR_LINEFEED) && (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
-      ;
+  //
+  // Fast-forward the string and see if there is a carriage-return in the string
+  //
+  for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {
+    switch (InputString[*Index + StrOffset]) {
+      case NARROW_CHAR:
+        *GlyphWidth = 1;
+        break;
+
+      case WIDE_CHAR:
+        *GlyphWidth = 2;
+        break;
+
+      case CHAR_CARRIAGE_RETURN:
+      case CHAR_LINEFEED:
+      case CHAR_NULL:
+        ReturnFlag = TRUE;
+        break;
+
+      default:
+        GlyphOffset = GlyphOffset + *GlyphWidth;
 
-    //
-    // Copy the desired LineWidth of data to the output buffer.
-    // Also make sure that we don't copy more than the string.
-    // Also make sure that if there are linefeeds, we account for them.
-    //
-    if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
-        (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
-        ) {
-      //
-      // Convert to CHAR16 value and show that we are done with this operation
-      //
-      LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);
-      if (LineWidth != 0) {
-        GetLineByWidthFinished = TRUE;
-      }
-    } else {
-      if (Count2 == LineWidth) {
         //
-        // Rewind the string from the maximum size until we see a space to break the line
+        // Record the last space info in this line. Will be used in rewind.
         //
-        for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
-          ;
-        if (LineWidth == 0) {
-          LineWidth = Count;
+        if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {
+          LastSpaceOffset = StrOffset;
+          LastGlyphWidth  = *GlyphWidth;
         }
-      } else {
-        LineWidth = Count2;
-      }
+        break;
     }
 
-    CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);
+    if (ReturnFlag) {
+      break;
+    }
+  } 
 
+  //
+  // Rewind the string from the maximum size until we see a space to break the line
+  //
+  if (GlyphOffset > LineWidth) {
     //
-    // If currently pointing to a space or carriage-return or linefeed, increment the index to the first non-space character
+    // Rewind the string to last space char in this line.
     //
-    for (;
-         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN)|| (InputString[*Index + LineWidth] == CHAR_LINEFEED);
-         (*Index)++
-        )
-      ;
-    *Index = (UINT16) (*Index + LineWidth);
-    return LineWidth;
-  } else {
-    return (UINT16) 0;
+    if (LastSpaceOffset != 0) {
+      StrOffset   = LastSpaceOffset;
+      *GlyphWidth = LastGlyphWidth;
+    } else {
+      //
+      // Roll back to last char in the line width.
+      //
+      StrOffset--;
+    }
   }
+
+  //
+  // The CHAR_NULL has process last time, this time just return 0 to stand for the end.
+  //
+  if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {
+    return 0;
+  }
+
+  //
+  // Need extra glyph info and '\0' info, so +2.
+  //
+  *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));
+  if (*OutputString == NULL) {
+    return 0;
+  }
+
+  //
+  // Save the glyph info at the begin of the string, will used by Print function.
+  //
+  if (OriginalGlyphWidth == 1) {
+    *(*OutputString) = NARROW_CHAR;
+  } else  {
+    *(*OutputString) = WIDE_CHAR;
+  }
+
+  CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));
+
+  if (InputString[*Index + StrOffset] == CHAR_SPACE) {
+    //
+    // Skip the space info at the begin of next line.
+    //  
+    *Index = (UINT16) (*Index + StrOffset + 1);
+  } else if ((InputString[*Index + StrOffset] == CHAR_LINEFEED)) {
+    //
+    // Skip the /n or /n/r info.
+    //
+    if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {
+      *Index = (UINT16) (*Index + StrOffset + 2);
+    } else {
+      *Index = (UINT16) (*Index + StrOffset + 1);
+    }
+  } else if ((InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN)) {
+    //
+    // Skip the /r or /r/n info.
+    //  
+    if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {
+      *Index = (UINT16) (*Index + StrOffset + 2);
+    } else {
+      *Index = (UINT16) (*Index + StrOffset + 1);
+    }
+  } else {
+    *Index = (UINT16) (*Index + StrOffset);
+  }
+
+  //
+  // Include extra glyph info and '\0' info, so +2.
+  //
+  return StrOffset + 2;
 }
 
 
@@ -1426,6 +1498,7 @@ UpdateOptionSkipLines (
   UINTN   OriginalRow;
   CHAR16  *OutputString;
   CHAR16  *OptionString;
+  UINT16  GlyphWidth;
 
   Row           = 0;
   OptionString  = NULL;
@@ -1435,8 +1508,9 @@ UpdateOptionSkipLines (
     Width               = (UINT16) gOptionBlockWidth;
 
     OriginalRow         = Row;
+    GlyphWidth          = 1;
 
-    for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+    for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
       //
       // If there is more string to process print on the next row and increment the Skip value
       //
@@ -2128,6 +2202,10 @@ UiDisplayMenu (
   UINTN                           HelpHeaderLine;
   UINTN                           HelpBottomLine;
   BOOLEAN                         MultiHelpPage;
+  UINT16                          GlyphWidth;
+  UINT16                          EachLineWidth;
+  UINT16                          HeaderLineWidth;
+  UINT16                          BottomLineWidth;
 
   CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
 
@@ -2147,7 +2225,9 @@ UiDisplayMenu (
   HelpHeaderLine      = 0;
   HelpPageIndex       = 0;
   MultiHelpPage       = FALSE;
-
+  EachLineWidth       = 0;
+  HeaderLineWidth     = 0;
+  BottomLineWidth     = 0;
   OutputString        = NULL;
   UpArrow             = FALSE;
   DownArrow           = FALSE;
@@ -2298,6 +2378,7 @@ UiDisplayMenu (
 
           Width       = GetWidth (Statement, MenuOption->Handle);
           OriginalRow = Row;
+          GlyphWidth  = 1;
 
           if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {
             //
@@ -2311,7 +2392,7 @@ UiDisplayMenu (
               );
           }
 
-          for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+          for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
             if ((Temp == 0) && (Row <= BottomRow)) {
               PrintStringAt (MenuOption->Col, Row, OutputString);
             }
@@ -2351,8 +2432,9 @@ UiDisplayMenu (
 
             Width       = (UINT16) gOptionBlockWidth;
             OriginalRow = Row;
+            GlyphWidth  = 1;
 
-            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+            for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
               if ((Temp2 == 0) && (Row <= BottomRow)) {
                 PrintStringAt (MenuOption->OptCol, Row, OutputString);
               }
@@ -2459,8 +2541,9 @@ UiDisplayMenu (
 
             Width       = (UINT16) gOptionBlockWidth;
             OriginalRow = Row;
+            GlyphWidth = 1;
 
-            for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
+            for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
               if ((Temp == 0) && (Row <= BottomRow)) {
                 PrintStringAt (MenuOption->OptCol, Row, OutputString);
               }
@@ -2688,8 +2771,9 @@ UiDisplayMenu (
 
             Width               = (UINT16) gOptionBlockWidth;
             OriginalRow         = MenuOption->Row;
+            GlyphWidth          = 1;
 
-            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+            for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
               if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
                 PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
               }
@@ -2716,8 +2800,9 @@ UiDisplayMenu (
 
               OriginalRow = MenuOption->Row;
               Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
+              GlyphWidth  = 1;
 
-              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
                 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
                   PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
                 }
@@ -2787,8 +2872,9 @@ UiDisplayMenu (
           Width               = (UINT16) gOptionBlockWidth;
 
           OriginalRow         = MenuOption->Row;
+          GlyphWidth          = 1;
 
-          for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+          for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
             if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
               PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
             }
@@ -2810,8 +2896,9 @@ UiDisplayMenu (
             OriginalRow = MenuOption->Row;
 
             Width       = GetWidth (Statement, MenuOption->Handle);
+            GlyphWidth          = 1;
 
-            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
               if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
                 PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
               }
@@ -2866,13 +2953,22 @@ UiDisplayMenu (
         //
         // 1.Calculate how many line the help string need to print.
         //
-        HelpLine = ProcessHelpString (StringPtr, &HelpString, RowCount);
+        if (HelpString != NULL) {
+          FreePool (HelpString);
+        }
+        HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);
         if (HelpLine > RowCount) {
           MultiHelpPage   = TRUE;
           StringPtr       = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);
-          HelpHeaderLine  = ProcessHelpString (StringPtr, &HelpHeaderString, RowCount);
+          if (HelpHeaderString != NULL) {
+            FreePool (HelpHeaderString);
+          }
+          HelpHeaderLine  = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount);
           StringPtr       = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);
-          HelpBottomLine  = ProcessHelpString (StringPtr, &HelpBottomString, RowCount);
+          if (HelpBottomString != NULL) {
+            FreePool (HelpBottomString);
+          }
+          HelpBottomLine  = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);
           //
           // Calculate the help page count.
           //
@@ -2900,7 +2996,6 @@ UiDisplayMenu (
         PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND
         );
 
-      gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);
       //
       // Check whether need to show the 'More(U/u)' at the begin.
       // Base on current direct info, here shows aligned to the right side of the column.
@@ -2908,13 +3003,14 @@ UiDisplayMenu (
       // add ASSERT code here.
       //
       if (HelpPageIndex > 0) {
+        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);
         for (Index = 0; Index < HelpHeaderLine; Index++) {
           ASSERT (HelpHeaderLine == 1);
           ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));
           PrintStringAt (
             LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,
             Index + TopRow,
-            &HelpHeaderString[Index * gHelpBlockWidth * 2]
+            &HelpHeaderString[Index * HeaderLineWidth]
             );
         }
       }
@@ -2928,16 +3024,17 @@ UiDisplayMenu (
           PrintStringAt (
             LocalScreen.RightColumn - gHelpBlockWidth,
             Index + TopRow,
-            &HelpString[Index * gHelpBlockWidth * 2]
+            &HelpString[Index * EachLineWidth]
             );
         }
+        gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);
       } else  {
         if (HelpPageIndex == 0) {
           for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {
             PrintStringAt (
               LocalScreen.RightColumn - gHelpBlockWidth,
               Index + TopRow,
-              &HelpString[Index * gHelpBlockWidth * 2]
+              &HelpString[Index * EachLineWidth]
               );
           }
         } else {
@@ -2946,13 +3043,15 @@ UiDisplayMenu (
             PrintStringAt (
               LocalScreen.RightColumn - gHelpBlockWidth,
               Index + TopRow + HelpHeaderLine,
-              &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* gHelpBlockWidth * 2]
+              &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth]
               );
           }
+          if (HelpPageIndex == HelpPageCount - 1) {
+            gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);
+          }
         } 
       }
 
-      gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);
       //
       // Check whether need to print the 'More(D/d)' at the bottom.
       // Base on current direct info, here shows aligned to the right side of the column.
@@ -2960,13 +3059,14 @@ UiDisplayMenu (
       // add ASSERT code here.
       //
       if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {
+        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);
         for (Index = 0; Index < HelpBottomLine; Index++) {
           ASSERT (HelpBottomLine == 1);
           ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); 
           PrintStringAt (
             LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,
             Index + BottomRow - HelpBottomLine,
-            &HelpBottomString[Index * gHelpBlockWidth * 2]
+            &HelpBottomString[Index * BottomLineWidth]
             );
         }
       }
@@ -3785,6 +3885,15 @@ UiDisplayMenu (
       gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
       gST->ConOut->EnableCursor (gST->ConOut, TRUE);
       gST->ConOut->OutputString (gST->ConOut, L"\n");
+      if (HelpString != NULL) {
+        FreePool (HelpString);
+      }
+      if (HelpHeaderString != NULL) {
+        FreePool (HelpHeaderString);
+      }
+      if (HelpBottomString != NULL) {
+        FreePool (HelpBottomString);
+      }
 
       return EFI_SUCCESS;
 
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
index 53309623cd..c9064f3144 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
@@ -604,14 +604,16 @@ ProcessOptions (
 
   @param  StringPtr              The entire help string.
   @param  FormattedString        The oupput formatted string.
+  @param  EachLineWidth          The string length of each line in the formatted string.
   @param  RowCount               TRUE: if Question is selected.
 
 **/
 UINTN
 ProcessHelpString (
-  IN  CHAR16                      *StringPtr,
-  OUT CHAR16                      **FormattedString,
-  IN  UINTN                       RowCount
+  IN  CHAR16  *StringPtr,
+  OUT CHAR16  **FormattedString,
+  OUT UINT16  *EachLineWidth,
+  IN  UINTN   RowCount
   );
 
 /**
@@ -672,10 +674,12 @@ GetStringWidth (
 /**
   Will copy LineWidth amount of a string in the OutputString buffer and return the
   number of CHAR16 characters that were copied into the OutputString buffer.
+  In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
 
   @param  InputString            String description for this option.
   @param  LineWidth              Width of the desired string to extract in CHAR16
                                  characters
+  @param  GlyphWidth             The glyph width of the beging char in the string.
   @param  Index                  Where in InputString to start the copy process
   @param  OutputString           Buffer to copy the string into
 
@@ -686,6 +690,7 @@ UINT16
 GetLineByWidth (
   IN      CHAR16                      *InputString,
   IN      UINT16                      LineWidth,
+  IN OUT  UINT16                      *GlyphWidth,
   IN OUT  UINTN                       *Index,
   OUT     CHAR16                      **OutputString
   );