]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/UefiLib/Console.c
MdePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdePkg / Library / UefiLib / Console.c
index 737c69b46e6415c971b913ddee3cc5ddaf3828c3..17ec31c96634b01d5b6eeb5cdf8b5b96aebee5d1 100644 (file)
@@ -1,22 +1,14 @@
 /** @file\r
   This module provide help function for displaying unicode string.\r
 \r
-  Copyright (c) 2006, Intel Corporation<BR>\r
-  All rights reserved. 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
-  http://opensource.org/licenses/bsd-license.php                                            \r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 \r
 \r
-//\r
-// Include common header file for this module.\r
-//\r
+\r
 #include "UefiLibInternal.h"\r
 \r
 typedef struct {\r
@@ -24,13 +16,16 @@ typedef struct {
   UINT32  Width;\r
 } UNICODE_WIDTH_ENTRY;\r
 \r
+#define NARROW_CHAR         0xFFF0\r
+#define WIDE_CHAR           0xFFF1\r
+\r
 GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = {\r
   //\r
   // General script area\r
   //\r
   {(CHAR16)0x1FFF,  1},\r
   /*\r
-   * Merge the blocks and replace them with the above entry as they fall to \r
+   * Merge the blocks and replace them with the above entry as they fall to\r
    * the same category and they are all narrow glyph. This will reduce search\r
    * time and table size. The merge will omit the reserved code.\r
    *\r
@@ -77,7 +72,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = {
   //\r
   {(CHAR16)0x2FFF,  1},\r
   /*\r
-   * Merge the blocks and replace them with the above entry as they fall to \r
+   * Merge the blocks and replace them with the above entry as they fall to\r
    * the same category and they are all narrow glyph. This will reduce search\r
    * time and table size. The merge will omit the reserved code.\r
    *\r
@@ -109,7 +104,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = {
   //\r
   {(CHAR16)0x33FF,  2},\r
   /*\r
-   * Merge the blocks and replace them with the above entry as they fall to \r
+   * Merge the blocks and replace them with the above entry as they fall to\r
    * the same category and they are all wide glyph. This will reduce search\r
    * time and table size. The merge will omit the reserved code.\r
    *\r
@@ -132,13 +127,13 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = {
   //\r
   {(CHAR16)0x9FFF,  2},\r
   /*\r
-   * Merge the blocks and replace them with the above entry as they fall to \r
+   * Merge the blocks and replace them with the above entry as they fall to\r
    * the same category and they are all wide glyph. This will reduce search\r
    * time and table size. The merge will omit the reserved code.\r
    *\r
    * Remove the above item if below is un-commented.\r
    *\r
-  {(CHAR16)0x4DFF,  0},       // Reserved. 0x3400-0x4DBF as CJK unified ideographs \r
+  {(CHAR16)0x4DFF,  0},       // Reserved. 0x3400-0x4DBF as CJK unified ideographs\r
                       // extension A in ver3.0. 0x3400-0x4DFF\r
   {(CHAR16)0x9FFF,  2},       // CJK unified ideographs. 0x4E00-0x9FFF\r
   *\r
@@ -154,7 +149,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = {
   //\r
   {(CHAR16)0xD7FF,  2},\r
   /*\r
-   * Merge the blocks and replace them with the above entry as they fall to \r
+   * Merge the blocks and replace them with the above entry as they fall to\r
    * the same category and they are all wide glyph. This will reduce search\r
    * time and table size. The merge will omit the reserved code.\r
    *\r
@@ -191,8 +186,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = {
 };\r
 \r
 /**\r
-  This function computes and returns the width of the Unicode character \r
-  specified by UnicodeChar.\r
+  Retrieves the width of a Unicode character.\r
+\r
+  This function computes and returns the width of the Unicode character specified\r
+  by UnicodeChar.\r
 \r
   @param  UnicodeChar   A Unicode character.\r
 \r
@@ -246,16 +243,20 @@ GetGlyphWidth (
 }\r
 \r
 /**\r
-  This function computes and returns the display length of\r
-  the Null-terminated Unicode string specified by String.\r
-  If String is NULL, then 0 is returned.\r
-  If any of the widths of the Unicode characters in String\r
-  can not be determined, then 0 is returned.\r
+  Computes the display length of a Null-terminated Unicode String.\r
+\r
+  This function computes and returns the display length of the Null-terminated\r
+  Unicode string specified by String.  If String is NULL then 0 is returned. If\r
+  any of the widths of the Unicode characters in String can not be determined,\r
+  then 0 is returned. The display width of String can be computed by summing the\r
+  display widths of each Unicode character in String.  Unicode characters that\r
+  are narrow glyphs have a width of 1, and Unicode characters that are width glyphs\r
+  have a width of 2.  If String is not aligned on a 16-bit boundary, then ASSERT().\r
 \r
   @param  String      A pointer to a Null-terminated Unicode string.\r
 \r
   @return The display length of the Null-terminated Unicode string specified by String.\r
-  \r
+\r
 **/\r
 UINTN\r
 EFIAPI\r
@@ -283,3 +284,283 @@ UnicodeStringDisplayLength (
 \r
   return Length;\r
 }\r
+\r
+/**\r
+  Count the storage space of a Unicode string.\r
+\r
+  This function handles the Unicode string with NARROW_CHAR\r
+  and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
+  does not count in the resultant output. If a WIDE_CHAR is\r
+  hit, then 2 Unicode character will consume an output storage\r
+  space with size of CHAR16 till a NARROW_CHAR is hit.\r
+\r
+  @param String          The input string to be counted.\r
+  @param LimitLen        Whether need to limit the string length.\r
+  @param MaxWidth        The max length this function supported.\r
+  @param Offset          The max index of the string can be show out.\r
+\r
+  @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+UefiLibGetStringWidth (\r
+  IN  CHAR16               *String,\r
+  IN  BOOLEAN              LimitLen,\r
+  IN  UINTN                MaxWidth,\r
+  OUT UINTN                *Offset\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINTN Count;\r
+  UINTN IncrementValue;\r
+\r
+  if (String == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  Index           = 0;\r
+  Count           = 0;\r
+  IncrementValue  = 1;\r
+\r
+  do {\r
+    //\r
+    // Advance to the null-terminator or to the first width directive\r
+    //\r
+    for (;(String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); Index++) {\r
+      Count = Count + IncrementValue;\r
+\r
+      if (LimitLen && Count > MaxWidth) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    // We hit the null-terminator, we now have a count\r
+    //\r
+    if (String[Index] == 0) {\r
+      break;\r
+    }\r
+\r
+    if (LimitLen && Count > MaxWidth) {\r
+      *Offset = Index;\r
+      break;\r
+    }\r
+\r
+    //\r
+    // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
+    // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
+    //\r
+    if (String[Index] == NARROW_CHAR) {\r
+      //\r
+      // Skip to the next character\r
+      //\r
+      Index++;\r
+      IncrementValue = 1;\r
+    } else {\r
+      //\r
+      // Skip to the next character\r
+      //\r
+      Index++;\r
+      IncrementValue = 2;\r
+    }\r
+  } while (String[Index] != 0);\r
+\r
+  return Count * sizeof (CHAR16);\r
+}\r
+\r
+/**\r
+  Draws a dialog box to the console output device specified by\r
+  ConOut defined in the EFI_SYSTEM_TABLE and waits for a keystroke\r
+  from the console input device specified by ConIn defined in the\r
+  EFI_SYSTEM_TABLE.\r
+\r
+  If there are no strings in the variable argument list, then ASSERT().\r
+  If all the strings in the variable argument list are empty, then ASSERT().\r
+\r
+  @param[in]   Attribute  Specifies the foreground and background color of the popup.\r
+  @param[out]  Key        A pointer to the EFI_KEY value of the key that was\r
+                          pressed.  This is an optional parameter that may be NULL.\r
+                          If it is NULL then no wait for a keypress will be performed.\r
+  @param[in]  ...         The variable argument list that contains pointers to Null-\r
+                          terminated Unicode strings to display in the dialog box.\r
+                          The variable argument list is terminated by a NULL.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CreatePopUp (\r
+  IN  UINTN          Attribute,\r
+  OUT EFI_INPUT_KEY  *Key,      OPTIONAL\r
+  ...\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  VA_LIST                          Args;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;\r
+  EFI_SIMPLE_TEXT_OUTPUT_MODE      SavedConsoleMode;\r
+  UINTN                            Columns;\r
+  UINTN                            Rows;\r
+  UINTN                            Column;\r
+  UINTN                            Row;\r
+  UINTN                            NumberOfLines;\r
+  UINTN                            MaxLength;\r
+  CHAR16                           *String;\r
+  UINTN                            Length;\r
+  CHAR16                           *Line;\r
+  UINTN                            EventIndex;\r
+  CHAR16                           *TmpString;\r
+\r
+  //\r
+  // Determine the length of the longest line in the popup and the the total\r
+  // number of lines in the popup\r
+  //\r
+  VA_START (Args, Key);\r
+  MaxLength = 0;\r
+  NumberOfLines = 0;\r
+  while ((String = VA_ARG (Args, CHAR16 *)) != NULL) {\r
+    MaxLength = MAX (MaxLength, UefiLibGetStringWidth (String, FALSE, 0, NULL) / 2);\r
+    NumberOfLines++;\r
+  }\r
+  VA_END (Args);\r
+\r
+  //\r
+  // If the total number of lines in the popup is zero, then ASSERT()\r
+  //\r
+  ASSERT (NumberOfLines != 0);\r
+\r
+  //\r
+  // If the maximum length of all the strings is zero, then ASSERT()\r
+  //\r
+  ASSERT (MaxLength != 0);\r
+\r
+  //\r
+  // Cache a pointer to the Simple Text Output Protocol in the EFI System Table\r
+  //\r
+  ConOut = gST->ConOut;\r
+\r
+  //\r
+  // Save the current console cursor position and attributes\r
+  //\r
+  CopyMem (&SavedConsoleMode, ConOut->Mode, sizeof (SavedConsoleMode));\r
+\r
+  //\r
+  // Retrieve the number of columns and rows in the current console mode\r
+  //\r
+  ConOut->QueryMode (ConOut, SavedConsoleMode.Mode, &Columns, &Rows);\r
+\r
+  //\r
+  // Disable cursor and set the foreground and background colors specified by Attribute\r
+  //\r
+  ConOut->EnableCursor (ConOut, FALSE);\r
+  ConOut->SetAttribute (ConOut, Attribute);\r
+\r
+  //\r
+  // Limit NumberOfLines to height of the screen minus 3 rows for the box itself\r
+  //\r
+  NumberOfLines = MIN (NumberOfLines, Rows - 3);\r
+\r
+  //\r
+  // Limit MaxLength to width of the screen minus 2 columns for the box itself\r
+  //\r
+  MaxLength = MIN (MaxLength, Columns - 2);\r
+\r
+  //\r
+  // Compute the starting row and starting column for the popup\r
+  //\r
+  Row    = (Rows - (NumberOfLines + 3)) / 2;\r
+  Column = (Columns - (MaxLength + 2)) / 2;\r
+\r
+  //\r
+  // Allocate a buffer for a single line of the popup with borders and a Null-terminator\r
+  //\r
+  Line = AllocateZeroPool ((MaxLength + 3) * sizeof (CHAR16));\r
+  ASSERT (Line != NULL);\r
+\r
+  //\r
+  // Draw top of popup box\r
+  //\r
+  SetMem16 (Line, (MaxLength + 2) * 2, BOXDRAW_HORIZONTAL);\r
+  Line[0]             = BOXDRAW_DOWN_RIGHT;\r
+  Line[MaxLength + 1] = BOXDRAW_DOWN_LEFT;\r
+  Line[MaxLength + 2] = L'\0';\r
+  ConOut->SetCursorPosition (ConOut, Column, Row++);\r
+  ConOut->OutputString (ConOut, Line);\r
+\r
+  //\r
+  // Draw middle of the popup with strings\r
+  //\r
+  VA_START (Args, Key);\r
+  while ((String = VA_ARG (Args, CHAR16 *)) != NULL && NumberOfLines > 0) {\r
+    SetMem16 (Line, (MaxLength + 2) * 2, L' ');\r
+    Line[0]             = BOXDRAW_VERTICAL;\r
+    Line[MaxLength + 1] = BOXDRAW_VERTICAL;\r
+    Line[MaxLength + 2] = L'\0';\r
+    ConOut->SetCursorPosition (ConOut, Column, Row);\r
+    ConOut->OutputString (ConOut, Line);\r
+    Length = UefiLibGetStringWidth (String, FALSE, 0, NULL) / 2;\r
+    if (Length <= MaxLength) {\r
+      //\r
+      // Length <= MaxLength\r
+      //\r
+      ConOut->SetCursorPosition (ConOut, Column + 1 + (MaxLength - Length) / 2, Row++);\r
+      ConOut->OutputString (ConOut, String);\r
+    } else {\r
+      //\r
+      // Length > MaxLength\r
+      //\r
+      UefiLibGetStringWidth (String, TRUE, MaxLength, &Length);\r
+      TmpString = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+      ASSERT (TmpString != NULL);\r
+      StrnCpyS (TmpString, Length + 1, String, Length - 3);\r
+      StrCatS (TmpString, Length + 1, L"...");\r
+\r
+      ConOut->SetCursorPosition (ConOut, Column + 1, Row++);\r
+      ConOut->OutputString (ConOut, TmpString);\r
+      FreePool (TmpString);\r
+    }\r
+    NumberOfLines--;\r
+  }\r
+  VA_END (Args);\r
+\r
+  //\r
+  // Draw bottom of popup box\r
+  //\r
+  SetMem16 (Line, (MaxLength + 2) * 2, BOXDRAW_HORIZONTAL);\r
+  Line[0]             = BOXDRAW_UP_RIGHT;\r
+  Line[MaxLength + 1] = BOXDRAW_UP_LEFT;\r
+  Line[MaxLength + 2] = L'\0';\r
+  ConOut->SetCursorPosition (ConOut, Column, Row++);\r
+  ConOut->OutputString (ConOut, Line);\r
+\r
+  //\r
+  // Free the allocated line buffer\r
+  //\r
+  FreePool (Line);\r
+\r
+  //\r
+  // Restore the cursor visibility, position, and attributes\r
+  //\r
+  ConOut->EnableCursor      (ConOut, SavedConsoleMode.CursorVisible);\r
+  ConOut->SetCursorPosition (ConOut, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow);\r
+  ConOut->SetAttribute      (ConOut, SavedConsoleMode.Attribute);\r
+\r
+  //\r
+  // Wait for a keystroke\r
+  //\r
+  if (Key != NULL) {\r
+    while (TRUE) {\r
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
+      if (!EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+\r
+      //\r
+      // If we encounter error, continue to read another key in.\r
+      //\r
+      if (Status != EFI_NOT_READY) {\r
+        continue;\r
+      }\r
+      gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+    }\r
+  }\r
+}\r