2 This module provide help function for displaying unicode string.
4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "UefiLibInternal.h"
23 } UNICODE_WIDTH_ENTRY
;
25 #define NARROW_CHAR 0xFFF0
26 #define WIDE_CHAR 0xFFF1
28 GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable
[] = {
30 // General script area
34 * Merge the blocks and replace them with the above entry as they fall to
35 * the same category and they are all narrow glyph. This will reduce search
36 * time and table size. The merge will omit the reserved code.
38 * Remove the above item if below is un-commented.
40 {(CHAR16)0x007F, 1}, // C0 controls and basic Latin. 0x0000-0x007F
41 {(CHAR16)0x00FF, 1}, // C1 controls and Latin-1 support. 0x0080-0x00FF
42 {(CHAR16)0x017F, 1}, // Latin extended-A. 0x0100-0x017F
43 {(CHAR16)0x024F, 1}, // Latin extended-B. 0x0180-0x024F
44 {(CHAR16)0x02AF, 1}, // IPA extensions. 0x0250-0x02AF
45 {(CHAR16)0x02FF, 1}, // Spacing modifier letters. 0x02B0-0x02FF
46 {(CHAR16)0x036F, 1}, // Combining diacritical marks. 0x0300-0x036F
47 {(CHAR16)0x03FF, 1}, // Greek. 0x0370-0x03FF
48 {(CHAR16)0x04FF, 1}, // Cyrillic. 0x0400-0x04FF
49 {(CHAR16)0x052F, 0}, // Unassigned. As Armenian in ver3.0. 0x0500-0x052F
50 {(CHAR16)0x058F, 1}, // Armenian. 0x0530-0x058F
51 {(CHAR16)0x05FF, 1}, // Hebrew. 0x0590-0x05FF
52 {(CHAR16)0x06FF, 1}, // Arabic. 0x0600-0x06FF
53 {(CHAR16)0x08FF, 0}, // Unassigned. 0x0700-0x08FF
54 {(CHAR16)0x097F, 1}, // Devanagari. 0x0900-0x097F
55 {(CHAR16)0x09FF, 1}, // Bengali. 0x0980-0x09FF
56 {(CHAR16)0x0A7F, 1}, // Gurmukhi. 0x0A00-0x0A7F
57 {(CHAR16)0x0AFF, 1}, // Gujarati. 0x0A80-0x0AFF
58 {(CHAR16)0x0B7F, 1}, // Oriya. 0x0B00-0x0B7F
59 {(CHAR16)0x0BFF, 1}, // Tamil. (See page 7-92). 0x0B80-0x0BFF
60 {(CHAR16)0x0C7F, 1}, // Telugu. 0x0C00-0x0C7F
61 {(CHAR16)0x0CFF, 1}, // Kannada. (See page 7-100). 0x0C80-0x0CFF
62 {(CHAR16)0x0D7F, 1}, // Malayalam (See page 7-104). 0x0D00-0x0D7F
63 {(CHAR16)0x0DFF, 0}, // Unassigned. 0x0D80-0x0DFF
64 {(CHAR16)0x0E7F, 1}, // Thai. 0x0E00-0x0E7F
65 {(CHAR16)0x0EFF, 1}, // Lao. 0x0E80-0x0EFF
66 {(CHAR16)0x0FBF, 1}, // Tibetan. 0x0F00-0x0FBF
67 {(CHAR16)0x109F, 0}, // Unassigned. 0x0FC0-0x109F
68 {(CHAR16)0x10FF, 1}, // Georgian. 0x10A0-0x10FF
69 {(CHAR16)0x11FF, 1}, // Hangul Jamo. 0x1100-0x11FF
70 {(CHAR16)0x1DFF, 0}, // Unassigned. 0x1200-0x1DFF
71 {(CHAR16)0x1EFF, 1}, // Latin extended additional. 0x1E00-0x1EFF
72 {(CHAR16)0x1FFF, 1}, // Greek extended. 0x1F00-0x1FFF
81 * Merge the blocks and replace them with the above entry as they fall to
82 * the same category and they are all narrow glyph. This will reduce search
83 * time and table size. The merge will omit the reserved code.
85 * Remove the above item if below is un-commented.
87 {(CHAR16)0x206F, 1}, // General punctuation. (See page7-154). 0x200-0x206F
88 {(CHAR16)0x209F, 1}, // Superscripts and subscripts. 0x2070-0x209F
89 {(CHAR16)0x20CF, 1}, // Currency symbols. 0x20A0-0x20CF
90 {(CHAR16)0x20FF, 1}, // Combining diacritical marks for symbols. 0x20D0-0x20FF
91 {(CHAR16)0x214F, 1}, // Letterlike sympbols. 0x2100-0x214F
92 {(CHAR16)0x218F, 1}, // Number forms. 0x2150-0x218F
93 {(CHAR16)0x21FF, 1}, // Arrows. 0x2190-0x21FF
94 {(CHAR16)0x22FF, 1}, // Mathematical operators. 0x2200-0x22FF
95 {(CHAR16)0x23FF, 1}, // Miscellaneous technical. 0x2300-0x23FF
96 {(CHAR16)0x243F, 1}, // Control pictures. 0x2400-0x243F
97 {(CHAR16)0x245F, 1}, // Optical character recognition. 0x2440-0x245F
98 {(CHAR16)0x24FF, 1}, // Enclosed alphanumerics. 0x2460-0x24FF
99 {(CHAR16)0x257F, 1}, // Box drawing. 0x2500-0x257F
100 {(CHAR16)0x259F, 1}, // Block elements. 0x2580-0x259F
101 {(CHAR16)0x25FF, 1}, // Geometric shapes. 0x25A0-0x25FF
102 {(CHAR16)0x26FF, 1}, // Miscellaneous symbols. 0x2600-0x26FF
103 {(CHAR16)0x27BF, 1}, // Dingbats. 0x2700-0x27BF
104 {(CHAR16)0x2FFF, 0}, // Reserved. 0x27C0-0x2FFF
109 // CJK phonetics and symbol area
113 * Merge the blocks and replace them with the above entry as they fall to
114 * the same category and they are all wide glyph. This will reduce search
115 * time and table size. The merge will omit the reserved code.
117 * Remove the above item if below is un-commented.
119 {(CHAR16)0x303F, 2}, // CJK symbols and punctuation. 0x3000-0x303F
120 {(CHAR16)0x309F, 2}, // Hiragana. 0x3040-0x309F
121 {(CHAR16)0x30FF, 2}, // Katakana. 0x30A0-0x30FF
122 {(CHAR16)0x312F, 2}, // Bopomofo. 0x3100-0x312F
123 {(CHAR16)0x318F, 2}, // Hangul compatibility jamo. 0x3130-0x318F
124 {(CHAR16)0x319F, 2}, // Kanbun. 0x3190-0x319F
125 {(CHAR16)0x31FF, 0}, // Reserved. As Bopomofo extended in ver3.0. 0x31A0-0x31FF
126 {(CHAR16)0x32FF, 2}, // Enclosed CJK letters and months. 0x3200-0x32FF
127 {(CHAR16)0x33FF, 2}, // CJK compatibility. 0x3300-0x33FF
132 // CJK ideograph area
136 * Merge the blocks and replace them with the above entry as they fall to
137 * the same category and they are all wide glyph. This will reduce search
138 * time and table size. The merge will omit the reserved code.
140 * Remove the above item if below is un-commented.
142 {(CHAR16)0x4DFF, 0}, // Reserved. 0x3400-0x4DBF as CJK unified ideographs
143 // extension A in ver3.0. 0x3400-0x4DFF
144 {(CHAR16)0x9FFF, 2}, // CJK unified ideographs. 0x4E00-0x9FFF
151 {(CHAR16
)0xABFF, 0}, // Reserved. 0xA000-0xA490 as Yi syllables. 0xA490-0xA4D0
152 // as Yi radicals in ver3.0. 0xA000-0xABFF
158 * Merge the blocks and replace them with the above entry as they fall to
159 * the same category and they are all wide glyph. This will reduce search
160 * time and table size. The merge will omit the reserved code.
162 * Remove the above item if below is un-commented.
164 {(CHAR16)0xD7A3, 2}, // Hangul syllables. 0xAC00-0xD7A3
165 {(CHAR16)0xD7FF, 0}, // Reserved. 0xD7A3-0xD7FF
172 {(CHAR16
)0xDFFF, 0}, // Surrogates, not used now. 0xD800-0xDFFF
177 {(CHAR16
)0xF8FF, 0}, // Private use area. 0xE000-0xF8FF
180 // Compatibility area and specials
182 {(CHAR16
)0xFAFF, 2}, // CJK compatibility ideographs. 0xF900-0xFAFF
183 {(CHAR16
)0xFB4F, 1}, // Alphabetic presentation forms. 0xFB00-0xFB4F
184 {(CHAR16
)0xFDFF, 1}, // Arabic presentation forms-A. 0xFB50-0xFDFF
185 {(CHAR16
)0xFE1F, 0}, // Reserved. As variation selectors in ver3.0. 0xFE00-0xFE1F
186 {(CHAR16
)0xFE2F, 1}, // Combining half marks. 0xFE20-0xFE2F
187 {(CHAR16
)0xFE4F, 2}, // CJK compatibility forms. 0xFE30-0xFE4F
188 {(CHAR16
)0xFE6F, 1}, // Small Form Variants. 0xFE50-0xFE6F
189 {(CHAR16
)0xFEFF, 1}, // Arabic presentation forms-B. 0xFE70-0xFEFF
190 {(CHAR16
)0xFFEF, 1}, // Half width and full width forms. 0xFF00-0xFFEF
191 {(CHAR16
)0xFFFF, 0}, // Speicials. 0xFFF0-0xFFFF
195 Retrieves the width of a Unicode character.
197 This function computes and returns the width of the Unicode character specified
200 @param UnicodeChar A Unicode character.
202 @retval 0 The width if UnicodeChar could not be determined.
203 @retval 1 UnicodeChar is a narrow glyph.
204 @retval 2 UnicodeChar is a wide glyph.
210 IN CHAR16 UnicodeChar
216 CONST UNICODE_WIDTH_ENTRY
*Item
;
220 High
= (sizeof (mUnicodeWidthTable
)) / (sizeof (UNICODE_WIDTH_ENTRY
)) - 1;
221 while (Low
<= High
) {
222 Index
= (Low
+ High
) >> 1;
223 Item
= &(mUnicodeWidthTable
[Index
]);
225 if (UnicodeChar
<= Item
->WChar
) {
232 if (UnicodeChar
> Item
->WChar
) {
234 } else if (UnicodeChar
<= mUnicodeWidthTable
[Index
- 1].WChar
) {
238 // Index - 1 < UnicodeChar <= Index. Found
252 Computes the display length of a Null-terminated Unicode String.
254 This function computes and returns the display length of the Null-terminated
255 Unicode string specified by String. If String is NULL then 0 is returned. If
256 any of the widths of the Unicode characters in String can not be determined,
257 then 0 is returned. The display width of String can be computed by summing the
258 display widths of each Unicode character in String. Unicode characters that
259 are narrow glyphs have a width of 1, and Unicode characters that are width glyphs
260 have a width of 2. If String is not aligned on a 16-bit boundary, then ASSERT().
262 @param String A pointer to a Null-terminated Unicode string.
264 @return The display length of the Null-terminated Unicode string specified by String.
269 UnicodeStringDisplayLength (
270 IN CONST CHAR16
*String
276 if (String
== NULL
) {
281 while (*String
!= 0) {
282 Width
= GetGlyphWidth (*String
);
295 Count the storage space of a Unicode string.
297 This function handles the Unicode string with NARROW_CHAR
298 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
299 does not count in the resultant output. If a WIDE_CHAR is
300 hit, then 2 Unicode character will consume an output storage
301 space with size of CHAR16 till a NARROW_CHAR is hit.
303 @param String The input string to be counted.
304 @param LimitLen Whether need to limit the string length.
305 @param MaxWidth The max length this function supported.
306 @param Offset The max index of the string can be show out.
308 @return Storage space for the input string.
312 UefiLibGetStringWidth (
321 UINTN IncrementValue
;
323 if (String
== NULL
) {
333 // Advance to the null-terminator or to the first width directive
335 for (;(String
[Index
] != NARROW_CHAR
) && (String
[Index
] != WIDE_CHAR
) && (String
[Index
] != 0);
336 Index
++, Count
= Count
+ IncrementValue
) {
337 if (LimitLen
&& Count
> MaxWidth
) {
343 // We hit the null-terminator, we now have a count
345 if (String
[Index
] == 0) {
349 if (LimitLen
&& Count
> MaxWidth
) {
355 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
356 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
358 if (String
[Index
] == NARROW_CHAR
) {
360 // Skip to the next character
366 // Skip to the next character
371 } while (String
[Index
] != 0);
374 // Increment by one to include the null-terminator in the size
380 return Count
* sizeof (CHAR16
);
384 Draws a dialog box to the console output device specified by
385 ConOut defined in the EFI_SYSTEM_TABLE and waits for a keystroke
386 from the console input device specified by ConIn defined in the
389 If there are no strings in the variable argument list, then ASSERT().
390 If all the strings in the variable argument list are empty, then ASSERT().
392 @param[in] Attribute Specifies the foreground and background color of the popup.
393 @param[out] Key A pointer to the EFI_KEY value of the key that was
394 pressed. This is an optional parameter that may be NULL.
395 If it is NULL then no wait for a keypress will be performed.
396 @param[in] ... The variable argument list that contains pointers to Null-
397 terminated Unicode strings to display in the dialog box.
398 The variable argument list is terminated by a NULL.
405 OUT EFI_INPUT_KEY
*Key
, OPTIONAL
410 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*ConOut
;
411 EFI_SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode
;
424 // Determine the length of the longest line in the popup and the the total
425 // number of lines in the popup
427 VA_START (Args
, Key
);
430 while ((String
= VA_ARG (Args
, CHAR16
*)) != NULL
) {
431 MaxLength
= MAX (MaxLength
, UefiLibGetStringWidth (String
, FALSE
, 0, NULL
) / 2);
437 // If the total number of lines in the popup is zero, then ASSERT()
439 ASSERT (NumberOfLines
!= 0);
442 // If the maximum length of all the strings is zero, then ASSERT()
444 ASSERT (MaxLength
!= 0);
447 // Cache a pointer to the Simple Text Output Protocol in the EFI System Table
449 ConOut
= gST
->ConOut
;
452 // Save the current console cursor position and attributes
454 CopyMem (&SavedConsoleMode
, ConOut
->Mode
, sizeof (SavedConsoleMode
));
457 // Retrieve the number of columns and rows in the current console mode
459 ConOut
->QueryMode (ConOut
, SavedConsoleMode
.Mode
, &Columns
, &Rows
);
462 // Disable cursor and set the foreground and background colors specified by Attribute
464 ConOut
->EnableCursor (ConOut
, FALSE
);
465 ConOut
->SetAttribute (ConOut
, Attribute
);
468 // Limit NumberOfLines to height of the screen minus 3 rows for the box itself
470 NumberOfLines
= MIN (NumberOfLines
, Rows
- 3);
473 // Limit MaxLength to width of the screen minus 2 columns for the box itself
475 MaxLength
= MIN (MaxLength
, Columns
- 2);
478 // Compute the starting row and starting column for the popup
480 Row
= (Rows
- (NumberOfLines
+ 3)) / 2;
481 Column
= (Columns
- (MaxLength
+ 2)) / 2;
484 // Allocate a buffer for a single line of the popup with borders and a Null-terminator
486 Line
= AllocateZeroPool ((MaxLength
+ 3) * sizeof (CHAR16
));
487 ASSERT (Line
!= NULL
);
490 // Draw top of popup box
492 SetMem16 (Line
, (MaxLength
+ 2) * 2, BOXDRAW_HORIZONTAL
);
493 Line
[0] = BOXDRAW_DOWN_RIGHT
;
494 Line
[MaxLength
+ 1] = BOXDRAW_DOWN_LEFT
;
495 Line
[MaxLength
+ 2] = L
'\0';
496 ConOut
->SetCursorPosition (ConOut
, Column
, Row
++);
497 ConOut
->OutputString (ConOut
, Line
);
500 // Draw middle of the popup with strings
502 VA_START (Args
, Key
);
503 while ((String
= VA_ARG (Args
, CHAR16
*)) != NULL
&& NumberOfLines
> 0) {
504 SetMem16 (Line
, (MaxLength
+ 2) * 2, L
' ');
505 Line
[0] = BOXDRAW_VERTICAL
;
506 Line
[MaxLength
+ 1] = BOXDRAW_VERTICAL
;
507 Line
[MaxLength
+ 2] = L
'\0';
508 ConOut
->SetCursorPosition (ConOut
, Column
, Row
);
509 ConOut
->OutputString (ConOut
, Line
);
510 Length
= UefiLibGetStringWidth (String
, FALSE
, 0, NULL
) / 2;
511 if (Length
<= MaxLength
) {
513 // Length <= MaxLength
515 ConOut
->SetCursorPosition (ConOut
, Column
+ 1 + (MaxLength
- Length
) / 2, Row
++);
516 ConOut
->OutputString (ConOut
, String
);
519 // Length > MaxLength
521 UefiLibGetStringWidth (String
, TRUE
, MaxLength
, &Length
);
522 String
[Length
] = L
'\0';
524 ConOut
->SetCursorPosition (ConOut
, Column
+ 1, Row
++);
525 ConOut
->OutputString (ConOut
, String
);
532 // Draw bottom of popup box
534 SetMem16 (Line
, (MaxLength
+ 2) * 2, BOXDRAW_HORIZONTAL
);
535 Line
[0] = BOXDRAW_UP_RIGHT
;
536 Line
[MaxLength
+ 1] = BOXDRAW_UP_LEFT
;
537 Line
[MaxLength
+ 2] = L
'\0';
538 ConOut
->SetCursorPosition (ConOut
, Column
, Row
++);
539 ConOut
->OutputString (ConOut
, Line
);
542 // Free the allocated line buffer
547 // Restore the cursor visibility, position, and attributes
549 ConOut
->EnableCursor (ConOut
, SavedConsoleMode
.CursorVisible
);
550 ConOut
->SetCursorPosition (ConOut
, SavedConsoleMode
.CursorColumn
, SavedConsoleMode
.CursorRow
);
551 ConOut
->SetAttribute (ConOut
, SavedConsoleMode
.Attribute
);
554 // Wait for a keystroke
557 gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &EventIndex
);
558 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, Key
);