]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
Enable wide string for title and help string
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Ui.c
index 6999f625dba0a44bb43f2cd5002c30458ef7d4d1..d59109317df6cc3a86f769e22466806bd1e96e16 100644 (file)
@@ -1308,102 +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 or linefeed in the string\r
-    //\r
-    for (; (InputString[*Index + Count2] != CHAR_LINEFEED) && (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
+  //\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, &InputString[*Index], LineWidth * 2);\r
+  CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
 \r
+  if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
     //\r
-    // If currently pointing to a space or carriage-return or linefeed, increment the index to the first non-space character\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
-    for (;\r
-         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN)|| (InputString[*Index + LineWidth] == CHAR_LINEFEED);\r
-         (*Index)++\r
-        )\r
-      ;\r
-    *Index = (UINT16) (*Index + LineWidth);\r
-    return LineWidth;\r
+    // Skip the /n or /n/r info.\r
+    //\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
@@ -1426,6 +1498,7 @@ UpdateOptionSkipLines (
   UINTN   OriginalRow;\r
   CHAR16  *OutputString;\r
   CHAR16  *OptionString;\r
+  UINT16  GlyphWidth;\r
 \r
   Row           = 0;\r
   OptionString  = NULL;\r
@@ -1435,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
@@ -2128,6 +2202,10 @@ UiDisplayMenu (
   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
@@ -2147,7 +2225,9 @@ UiDisplayMenu (
   HelpHeaderLine      = 0;\r
   HelpPageIndex       = 0;\r
   MultiHelpPage       = FALSE;\r
-\r
+  EachLineWidth       = 0;\r
+  HeaderLineWidth     = 0;\r
+  BottomLineWidth     = 0;\r
   OutputString        = NULL;\r
   UpArrow             = FALSE;\r
   DownArrow           = FALSE;\r
@@ -2298,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
@@ -2311,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
@@ -2351,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
@@ -2459,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
@@ -2688,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
@@ -2716,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
@@ -2787,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
@@ -2810,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
@@ -2866,13 +2953,22 @@ UiDisplayMenu (
         //\r
         // 1.Calculate how many line the help string need to print.\r
         //\r
-        HelpLine = ProcessHelpString (StringPtr, &HelpString, RowCount);\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
-          HelpHeaderLine  = ProcessHelpString (StringPtr, &HelpHeaderString, RowCount);\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
-          HelpBottomLine  = ProcessHelpString (StringPtr, &HelpBottomString, RowCount);\r
+          if (HelpBottomString != NULL) {\r
+            FreePool (HelpBottomString);\r
+          }\r
+          HelpBottomLine  = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);\r
           //\r
           // Calculate the help page count.\r
           //\r
@@ -2900,7 +2996,6 @@ UiDisplayMenu (
         PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
         );\r
 \r
-      gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\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
@@ -2908,13 +3003,14 @@ UiDisplayMenu (
       // 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 * gHelpBlockWidth * 2]\r
+            &HelpHeaderString[Index * HeaderLineWidth]\r
             );\r
         }\r
       }\r
@@ -2928,16 +3024,17 @@ UiDisplayMenu (
           PrintStringAt (\r
             LocalScreen.RightColumn - gHelpBlockWidth,\r
             Index + TopRow,\r
-            &HelpString[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 * gHelpBlockWidth * 2]\r
+              &HelpString[Index * EachLineWidth]\r
               );\r
           }\r
         } else {\r
@@ -2946,13 +3043,15 @@ UiDisplayMenu (
             PrintStringAt (\r
               LocalScreen.RightColumn - gHelpBlockWidth,\r
               Index + TopRow + HelpHeaderLine,\r
-              &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* gHelpBlockWidth * 2]\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
-      gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\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
@@ -2960,13 +3059,14 @@ UiDisplayMenu (
       // 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 * gHelpBlockWidth * 2]\r
+            &HelpBottomString[Index * BottomLineWidth]\r
             );\r
         }\r
       }\r
@@ -3785,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