]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiLib/Console.c
MdePkg: Clean up source files
[mirror_edk2.git] / MdePkg / Library / UefiLib / Console.c
CommitLineData
e386b444 1/** @file\r
9edc73ad 2 This module provide help function for displaying unicode string.\r
e386b444 3\r
9095d37b
LG
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
e386b444 9\r
9095d37b
LG
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
e386b444 12\r
e386b444 13**/\r
14\r
15\r
16\r
1efcc4ae 17\r
f734a10a 18#include "UefiLibInternal.h"\r
e386b444 19\r
20typedef struct {\r
21 CHAR16 WChar;\r
22 UINT32 Width;\r
23} UNICODE_WIDTH_ENTRY;\r
24\r
33026ccf
ED
25#define NARROW_CHAR 0xFFF0\r
26#define WIDE_CHAR 0xFFF1\r
27\r
f80b0830 28GLOBAL_REMOVE_IF_UNREFERENCED CONST UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = {\r
e386b444 29 //\r
30 // General script area\r
31 //\r
32 {(CHAR16)0x1FFF, 1},\r
33 /*\r
9095d37b 34 * Merge the blocks and replace them with the above entry as they fall to\r
e386b444 35 * the same category and they are all narrow glyph. This will reduce search\r
36 * time and table size. The merge will omit the reserved code.\r
37 *\r
38 * Remove the above item if below is un-commented.\r
39 *\r
40 {(CHAR16)0x007F, 1}, // C0 controls and basic Latin. 0x0000-0x007F\r
41 {(CHAR16)0x00FF, 1}, // C1 controls and Latin-1 support. 0x0080-0x00FF\r
42 {(CHAR16)0x017F, 1}, // Latin extended-A. 0x0100-0x017F\r
43 {(CHAR16)0x024F, 1}, // Latin extended-B. 0x0180-0x024F\r
44 {(CHAR16)0x02AF, 1}, // IPA extensions. 0x0250-0x02AF\r
45 {(CHAR16)0x02FF, 1}, // Spacing modifier letters. 0x02B0-0x02FF\r
46 {(CHAR16)0x036F, 1}, // Combining diacritical marks. 0x0300-0x036F\r
47 {(CHAR16)0x03FF, 1}, // Greek. 0x0370-0x03FF\r
48 {(CHAR16)0x04FF, 1}, // Cyrillic. 0x0400-0x04FF\r
49 {(CHAR16)0x052F, 0}, // Unassigned. As Armenian in ver3.0. 0x0500-0x052F\r
50 {(CHAR16)0x058F, 1}, // Armenian. 0x0530-0x058F\r
51 {(CHAR16)0x05FF, 1}, // Hebrew. 0x0590-0x05FF\r
52 {(CHAR16)0x06FF, 1}, // Arabic. 0x0600-0x06FF\r
53 {(CHAR16)0x08FF, 0}, // Unassigned. 0x0700-0x08FF\r
54 {(CHAR16)0x097F, 1}, // Devanagari. 0x0900-0x097F\r
55 {(CHAR16)0x09FF, 1}, // Bengali. 0x0980-0x09FF\r
56 {(CHAR16)0x0A7F, 1}, // Gurmukhi. 0x0A00-0x0A7F\r
57 {(CHAR16)0x0AFF, 1}, // Gujarati. 0x0A80-0x0AFF\r
58 {(CHAR16)0x0B7F, 1}, // Oriya. 0x0B00-0x0B7F\r
59 {(CHAR16)0x0BFF, 1}, // Tamil. (See page 7-92). 0x0B80-0x0BFF\r
60 {(CHAR16)0x0C7F, 1}, // Telugu. 0x0C00-0x0C7F\r
61 {(CHAR16)0x0CFF, 1}, // Kannada. (See page 7-100). 0x0C80-0x0CFF\r
62 {(CHAR16)0x0D7F, 1}, // Malayalam (See page 7-104). 0x0D00-0x0D7F\r
63 {(CHAR16)0x0DFF, 0}, // Unassigned. 0x0D80-0x0DFF\r
64 {(CHAR16)0x0E7F, 1}, // Thai. 0x0E00-0x0E7F\r
65 {(CHAR16)0x0EFF, 1}, // Lao. 0x0E80-0x0EFF\r
66 {(CHAR16)0x0FBF, 1}, // Tibetan. 0x0F00-0x0FBF\r
67 {(CHAR16)0x109F, 0}, // Unassigned. 0x0FC0-0x109F\r
68 {(CHAR16)0x10FF, 1}, // Georgian. 0x10A0-0x10FF\r
69 {(CHAR16)0x11FF, 1}, // Hangul Jamo. 0x1100-0x11FF\r
70 {(CHAR16)0x1DFF, 0}, // Unassigned. 0x1200-0x1DFF\r
71 {(CHAR16)0x1EFF, 1}, // Latin extended additional. 0x1E00-0x1EFF\r
72 {(CHAR16)0x1FFF, 1}, // Greek extended. 0x1F00-0x1FFF\r
73 *\r
74 */\r
75\r
76 //\r
77 // Symbol area\r
78 //\r
79 {(CHAR16)0x2FFF, 1},\r
80 /*\r
9095d37b 81 * Merge the blocks and replace them with the above entry as they fall to\r
e386b444 82 * the same category and they are all narrow glyph. This will reduce search\r
83 * time and table size. The merge will omit the reserved code.\r
84 *\r
85 * Remove the above item if below is un-commented.\r
86 *\r
87 {(CHAR16)0x206F, 1}, // General punctuation. (See page7-154). 0x200-0x206F\r
88 {(CHAR16)0x209F, 1}, // Superscripts and subscripts. 0x2070-0x209F\r
89 {(CHAR16)0x20CF, 1}, // Currency symbols. 0x20A0-0x20CF\r
90 {(CHAR16)0x20FF, 1}, // Combining diacritical marks for symbols. 0x20D0-0x20FF\r
91 {(CHAR16)0x214F, 1}, // Letterlike sympbols. 0x2100-0x214F\r
92 {(CHAR16)0x218F, 1}, // Number forms. 0x2150-0x218F\r
93 {(CHAR16)0x21FF, 1}, // Arrows. 0x2190-0x21FF\r
94 {(CHAR16)0x22FF, 1}, // Mathematical operators. 0x2200-0x22FF\r
95 {(CHAR16)0x23FF, 1}, // Miscellaneous technical. 0x2300-0x23FF\r
96 {(CHAR16)0x243F, 1}, // Control pictures. 0x2400-0x243F\r
97 {(CHAR16)0x245F, 1}, // Optical character recognition. 0x2440-0x245F\r
98 {(CHAR16)0x24FF, 1}, // Enclosed alphanumerics. 0x2460-0x24FF\r
99 {(CHAR16)0x257F, 1}, // Box drawing. 0x2500-0x257F\r
100 {(CHAR16)0x259F, 1}, // Block elements. 0x2580-0x259F\r
101 {(CHAR16)0x25FF, 1}, // Geometric shapes. 0x25A0-0x25FF\r
102 {(CHAR16)0x26FF, 1}, // Miscellaneous symbols. 0x2600-0x26FF\r
103 {(CHAR16)0x27BF, 1}, // Dingbats. 0x2700-0x27BF\r
104 {(CHAR16)0x2FFF, 0}, // Reserved. 0x27C0-0x2FFF\r
105 *\r
106 */\r
107\r
108 //\r
109 // CJK phonetics and symbol area\r
110 //\r
111 {(CHAR16)0x33FF, 2},\r
112 /*\r
9095d37b 113 * Merge the blocks and replace them with the above entry as they fall to\r
e386b444 114 * the same category and they are all wide glyph. This will reduce search\r
115 * time and table size. The merge will omit the reserved code.\r
116 *\r
117 * Remove the above item if below is un-commented.\r
118 *\r
119 {(CHAR16)0x303F, 2}, // CJK symbols and punctuation. 0x3000-0x303F\r
120 {(CHAR16)0x309F, 2}, // Hiragana. 0x3040-0x309F\r
121 {(CHAR16)0x30FF, 2}, // Katakana. 0x30A0-0x30FF\r
122 {(CHAR16)0x312F, 2}, // Bopomofo. 0x3100-0x312F\r
123 {(CHAR16)0x318F, 2}, // Hangul compatibility jamo. 0x3130-0x318F\r
124 {(CHAR16)0x319F, 2}, // Kanbun. 0x3190-0x319F\r
125 {(CHAR16)0x31FF, 0}, // Reserved. As Bopomofo extended in ver3.0. 0x31A0-0x31FF\r
126 {(CHAR16)0x32FF, 2}, // Enclosed CJK letters and months. 0x3200-0x32FF\r
127 {(CHAR16)0x33FF, 2}, // CJK compatibility. 0x3300-0x33FF\r
128 *\r
129 */\r
130\r
131 //\r
132 // CJK ideograph area\r
133 //\r
134 {(CHAR16)0x9FFF, 2},\r
135 /*\r
9095d37b 136 * Merge the blocks and replace them with the above entry as they fall to\r
e386b444 137 * the same category and they are all wide glyph. This will reduce search\r
138 * time and table size. The merge will omit the reserved code.\r
139 *\r
140 * Remove the above item if below is un-commented.\r
141 *\r
9095d37b 142 {(CHAR16)0x4DFF, 0}, // Reserved. 0x3400-0x4DBF as CJK unified ideographs\r
e386b444 143 // extension A in ver3.0. 0x3400-0x4DFF\r
144 {(CHAR16)0x9FFF, 2}, // CJK unified ideographs. 0x4E00-0x9FFF\r
145 *\r
146 */\r
147\r
148 //\r
149 // Reserved\r
150 //\r
151 {(CHAR16)0xABFF, 0}, // Reserved. 0xA000-0xA490 as Yi syllables. 0xA490-0xA4D0\r
152 // as Yi radicals in ver3.0. 0xA000-0xABFF\r
153 //\r
154 // Hangul syllables\r
155 //\r
156 {(CHAR16)0xD7FF, 2},\r
157 /*\r
9095d37b 158 * Merge the blocks and replace them with the above entry as they fall to\r
e386b444 159 * the same category and they are all wide glyph. This will reduce search\r
160 * time and table size. The merge will omit the reserved code.\r
161 *\r
162 * Remove the above item if below is un-commented.\r
163 *\r
164 {(CHAR16)0xD7A3, 2}, // Hangul syllables. 0xAC00-0xD7A3\r
165 {(CHAR16)0xD7FF, 0}, // Reserved. 0xD7A3-0xD7FF\r
166 *\r
167 */\r
168\r
169 //\r
170 // Surrogates area\r
171 //\r
172 {(CHAR16)0xDFFF, 0}, // Surrogates, not used now. 0xD800-0xDFFF\r
173\r
174 //\r
175 // Private use area\r
176 //\r
177 {(CHAR16)0xF8FF, 0}, // Private use area. 0xE000-0xF8FF\r
178\r
179 //\r
180 // Compatibility area and specials\r
181 //\r
182 {(CHAR16)0xFAFF, 2}, // CJK compatibility ideographs. 0xF900-0xFAFF\r
183 {(CHAR16)0xFB4F, 1}, // Alphabetic presentation forms. 0xFB00-0xFB4F\r
184 {(CHAR16)0xFDFF, 1}, // Arabic presentation forms-A. 0xFB50-0xFDFF\r
185 {(CHAR16)0xFE1F, 0}, // Reserved. As variation selectors in ver3.0. 0xFE00-0xFE1F\r
186 {(CHAR16)0xFE2F, 1}, // Combining half marks. 0xFE20-0xFE2F\r
187 {(CHAR16)0xFE4F, 2}, // CJK compatibility forms. 0xFE30-0xFE4F\r
188 {(CHAR16)0xFE6F, 1}, // Small Form Variants. 0xFE50-0xFE6F\r
189 {(CHAR16)0xFEFF, 1}, // Arabic presentation forms-B. 0xFE70-0xFEFF\r
190 {(CHAR16)0xFFEF, 1}, // Half width and full width forms. 0xFF00-0xFFEF\r
191 {(CHAR16)0xFFFF, 0}, // Speicials. 0xFFF0-0xFFFF\r
192};\r
193\r
194/**\r
cf8ae2f6 195 Retrieves the width of a Unicode character.\r
196\r
197 This function computes and returns the width of the Unicode character specified\r
198 by UnicodeChar.\r
e386b444 199\r
200 @param UnicodeChar A Unicode character.\r
201\r
202 @retval 0 The width if UnicodeChar could not be determined.\r
203 @retval 1 UnicodeChar is a narrow glyph.\r
204 @retval 2 UnicodeChar is a wide glyph.\r
205\r
206**/\r
207UINTN\r
208EFIAPI\r
209GetGlyphWidth (\r
210 IN CHAR16 UnicodeChar\r
211 )\r
212{\r
1654531a 213 UINTN Index;\r
214 UINTN Low;\r
215 UINTN High;\r
216 CONST UNICODE_WIDTH_ENTRY *Item;\r
e386b444 217\r
218 Item = NULL;\r
219 Low = 0;\r
220 High = (sizeof (mUnicodeWidthTable)) / (sizeof (UNICODE_WIDTH_ENTRY)) - 1;\r
221 while (Low <= High) {\r
222 Index = (Low + High) >> 1;\r
223 Item = &(mUnicodeWidthTable[Index]);\r
224 if (Index == 0) {\r
225 if (UnicodeChar <= Item->WChar) {\r
226 break;\r
227 }\r
228\r
229 return 0;\r
230 }\r
231\r
232 if (UnicodeChar > Item->WChar) {\r
233 Low = Index + 1;\r
234 } else if (UnicodeChar <= mUnicodeWidthTable[Index - 1].WChar) {\r
235 High = Index - 1;\r
236 } else {\r
237 //\r
238 // Index - 1 < UnicodeChar <= Index. Found\r
239 //\r
240 break;\r
241 }\r
242 }\r
243\r
244 if (Low <= High) {\r
245 return Item->Width;\r
246 }\r
247\r
248 return 0;\r
249}\r
250\r
251/**\r
1d37ab9f 252 Computes the display length of a Null-terminated Unicode String.\r
253\r
9095d37b
LG
254 This function computes and returns the display length of the Null-terminated\r
255 Unicode string specified by String. If String is NULL then 0 is returned. If\r
256 any of the widths of the Unicode characters in String can not be determined,\r
257 then 0 is returned. The display width of String can be computed by summing the\r
258 display widths of each Unicode character in String. Unicode characters that\r
259 are narrow glyphs have a width of 1, and Unicode characters that are width glyphs\r
58380e9c 260 have a width of 2. If String is not aligned on a 16-bit boundary, then ASSERT().\r
e386b444 261\r
262 @param String A pointer to a Null-terminated Unicode string.\r
263\r
264 @return The display length of the Null-terminated Unicode string specified by String.\r
9095d37b 265\r
e386b444 266**/\r
267UINTN\r
268EFIAPI\r
269UnicodeStringDisplayLength (\r
270 IN CONST CHAR16 *String\r
271 )\r
272{\r
273 UINTN Length;\r
274 UINTN Width;\r
275\r
276 if (String == NULL) {\r
277 return 0;\r
278 }\r
279\r
280 Length = 0;\r
281 while (*String != 0) {\r
282 Width = GetGlyphWidth (*String);\r
283 if (Width == 0) {\r
284 return 0;\r
285 }\r
286\r
287 Length += Width;\r
288 String++;\r
289 }\r
290\r
291 return Length;\r
292}\r
db2ef756 293\r
33026ccf 294/**\r
9095d37b 295 Count the storage space of a Unicode string.\r
33026ccf
ED
296\r
297 This function handles the Unicode string with NARROW_CHAR\r
298 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
299 does not count in the resultant output. If a WIDE_CHAR is\r
300 hit, then 2 Unicode character will consume an output storage\r
301 space with size of CHAR16 till a NARROW_CHAR is hit.\r
302\r
303 @param String The input string to be counted.\r
304 @param LimitLen Whether need to limit the string length.\r
305 @param MaxWidth The max length this function supported.\r
9095d37b 306 @param Offset The max index of the string can be show out.\r
33026ccf
ED
307\r
308 @return Storage space for the input string.\r
309\r
310**/\r
311UINTN\r
312UefiLibGetStringWidth (\r
313 IN CHAR16 *String,\r
314 IN BOOLEAN LimitLen,\r
315 IN UINTN MaxWidth,\r
316 OUT UINTN *Offset\r
317 )\r
318{\r
319 UINTN Index;\r
320 UINTN Count;\r
321 UINTN IncrementValue;\r
322\r
323 if (String == NULL) {\r
324 return 0;\r
325 }\r
326\r
327 Index = 0;\r
328 Count = 0;\r
329 IncrementValue = 1;\r
330\r
331 do {\r
332 //\r
333 // Advance to the null-terminator or to the first width directive\r
334 //\r
8b5b3d42
ED
335 for (;(String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); Index++) {\r
336 Count = Count + IncrementValue;\r
337\r
33026ccf
ED
338 if (LimitLen && Count > MaxWidth) {\r
339 break;\r
340 }\r
341 }\r
342\r
343 //\r
344 // We hit the null-terminator, we now have a count\r
345 //\r
346 if (String[Index] == 0) {\r
347 break;\r
348 }\r
349\r
350 if (LimitLen && Count > MaxWidth) {\r
8b5b3d42 351 *Offset = Index;\r
33026ccf
ED
352 break;\r
353 }\r
354\r
355 //\r
356 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
357 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
358 //\r
359 if (String[Index] == NARROW_CHAR) {\r
360 //\r
361 // Skip to the next character\r
362 //\r
363 Index++;\r
364 IncrementValue = 1;\r
365 } else {\r
366 //\r
367 // Skip to the next character\r
368 //\r
369 Index++;\r
370 IncrementValue = 2;\r
371 }\r
372 } while (String[Index] != 0);\r
373\r
33026ccf
ED
374 return Count * sizeof (CHAR16);\r
375}\r
376\r
db2ef756 377/**\r
9095d37b 378 Draws a dialog box to the console output device specified by\r
db2ef756 379 ConOut defined in the EFI_SYSTEM_TABLE and waits for a keystroke\r
9095d37b 380 from the console input device specified by ConIn defined in the\r
db2ef756
LG
381 EFI_SYSTEM_TABLE.\r
382\r
383 If there are no strings in the variable argument list, then ASSERT().\r
384 If all the strings in the variable argument list are empty, then ASSERT().\r
385\r
386 @param[in] Attribute Specifies the foreground and background color of the popup.\r
9095d37b 387 @param[out] Key A pointer to the EFI_KEY value of the key that was\r
db2ef756
LG
388 pressed. This is an optional parameter that may be NULL.\r
389 If it is NULL then no wait for a keypress will be performed.\r
390 @param[in] ... The variable argument list that contains pointers to Null-\r
9095d37b 391 terminated Unicode strings to display in the dialog box.\r
db2ef756
LG
392 The variable argument list is terminated by a NULL.\r
393\r
394**/\r
395VOID\r
396EFIAPI\r
397CreatePopUp (\r
9095d37b 398 IN UINTN Attribute,\r
db2ef756
LG
399 OUT EFI_INPUT_KEY *Key, OPTIONAL\r
400 ...\r
401 )\r
402{\r
f04544be 403 EFI_STATUS Status;\r
db2ef756
LG
404 VA_LIST Args;\r
405 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
406 EFI_SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode;\r
407 UINTN Columns;\r
408 UINTN Rows;\r
409 UINTN Column;\r
410 UINTN Row;\r
411 UINTN NumberOfLines;\r
412 UINTN MaxLength;\r
413 CHAR16 *String;\r
414 UINTN Length;\r
415 CHAR16 *Line;\r
416 UINTN EventIndex;\r
8b5b3d42 417 CHAR16 *TmpString;\r
db2ef756
LG
418\r
419 //\r
9095d37b 420 // Determine the length of the longest line in the popup and the the total\r
db2ef756
LG
421 // number of lines in the popup\r
422 //\r
423 VA_START (Args, Key);\r
424 MaxLength = 0;\r
425 NumberOfLines = 0;\r
426 while ((String = VA_ARG (Args, CHAR16 *)) != NULL) {\r
33026ccf 427 MaxLength = MAX (MaxLength, UefiLibGetStringWidth (String, FALSE, 0, NULL) / 2);\r
db2ef756
LG
428 NumberOfLines++;\r
429 }\r
430 VA_END (Args);\r
431\r
432 //\r
433 // If the total number of lines in the popup is zero, then ASSERT()\r
434 //\r
435 ASSERT (NumberOfLines != 0);\r
436\r
437 //\r
438 // If the maximum length of all the strings is zero, then ASSERT()\r
439 //\r
440 ASSERT (MaxLength != 0);\r
441\r
442 //\r
443 // Cache a pointer to the Simple Text Output Protocol in the EFI System Table\r
444 //\r
445 ConOut = gST->ConOut;\r
9095d37b 446\r
db2ef756
LG
447 //\r
448 // Save the current console cursor position and attributes\r
449 //\r
450 CopyMem (&SavedConsoleMode, ConOut->Mode, sizeof (SavedConsoleMode));\r
451\r
452 //\r
453 // Retrieve the number of columns and rows in the current console mode\r
454 //\r
455 ConOut->QueryMode (ConOut, SavedConsoleMode.Mode, &Columns, &Rows);\r
456\r
457 //\r
458 // Disable cursor and set the foreground and background colors specified by Attribute\r
459 //\r
460 ConOut->EnableCursor (ConOut, FALSE);\r
461 ConOut->SetAttribute (ConOut, Attribute);\r
462\r
463 //\r
464 // Limit NumberOfLines to height of the screen minus 3 rows for the box itself\r
465 //\r
466 NumberOfLines = MIN (NumberOfLines, Rows - 3);\r
467\r
468 //\r
469 // Limit MaxLength to width of the screen minus 2 columns for the box itself\r
470 //\r
471 MaxLength = MIN (MaxLength, Columns - 2);\r
472\r
473 //\r
474 // Compute the starting row and starting column for the popup\r
475 //\r
476 Row = (Rows - (NumberOfLines + 3)) / 2;\r
477 Column = (Columns - (MaxLength + 2)) / 2;\r
478\r
479 //\r
480 // Allocate a buffer for a single line of the popup with borders and a Null-terminator\r
481 //\r
482 Line = AllocateZeroPool ((MaxLength + 3) * sizeof (CHAR16));\r
11171f03 483 ASSERT (Line != NULL);\r
db2ef756
LG
484\r
485 //\r
9095d37b 486 // Draw top of popup box\r
db2ef756
LG
487 //\r
488 SetMem16 (Line, (MaxLength + 2) * 2, BOXDRAW_HORIZONTAL);\r
489 Line[0] = BOXDRAW_DOWN_RIGHT;\r
490 Line[MaxLength + 1] = BOXDRAW_DOWN_LEFT;\r
491 Line[MaxLength + 2] = L'\0';\r
492 ConOut->SetCursorPosition (ConOut, Column, Row++);\r
493 ConOut->OutputString (ConOut, Line);\r
494\r
495 //\r
496 // Draw middle of the popup with strings\r
497 //\r
498 VA_START (Args, Key);\r
499 while ((String = VA_ARG (Args, CHAR16 *)) != NULL && NumberOfLines > 0) {\r
db2ef756 500 SetMem16 (Line, (MaxLength + 2) * 2, L' ');\r
33026ccf
ED
501 Line[0] = BOXDRAW_VERTICAL;\r
502 Line[MaxLength + 1] = BOXDRAW_VERTICAL;\r
503 Line[MaxLength + 2] = L'\0';\r
504 ConOut->SetCursorPosition (ConOut, Column, Row);\r
505 ConOut->OutputString (ConOut, Line);\r
506 Length = UefiLibGetStringWidth (String, FALSE, 0, NULL) / 2;\r
db2ef756
LG
507 if (Length <= MaxLength) {\r
508 //\r
509 // Length <= MaxLength\r
510 //\r
33026ccf
ED
511 ConOut->SetCursorPosition (ConOut, Column + 1 + (MaxLength - Length) / 2, Row++);\r
512 ConOut->OutputString (ConOut, String);\r
db2ef756
LG
513 } else {\r
514 //\r
515 // Length > MaxLength\r
516 //\r
33026ccf 517 UefiLibGetStringWidth (String, TRUE, MaxLength, &Length);\r
8b5b3d42
ED
518 TmpString = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
519 ASSERT (TmpString != NULL);\r
df1e74f5
HW
520 StrnCpyS (TmpString, Length + 1, String, Length - 3);\r
521 StrCatS (TmpString, Length + 1, L"...");\r
33026ccf
ED
522\r
523 ConOut->SetCursorPosition (ConOut, Column + 1, Row++);\r
8b5b3d42
ED
524 ConOut->OutputString (ConOut, TmpString);\r
525 FreePool (TmpString);\r
db2ef756 526 }\r
db2ef756
LG
527 NumberOfLines--;\r
528 }\r
529 VA_END (Args);\r
530\r
531 //\r
532 // Draw bottom of popup box\r
533 //\r
534 SetMem16 (Line, (MaxLength + 2) * 2, BOXDRAW_HORIZONTAL);\r
535 Line[0] = BOXDRAW_UP_RIGHT;\r
536 Line[MaxLength + 1] = BOXDRAW_UP_LEFT;\r
537 Line[MaxLength + 2] = L'\0';\r
538 ConOut->SetCursorPosition (ConOut, Column, Row++);\r
539 ConOut->OutputString (ConOut, Line);\r
540\r
541 //\r
542 // Free the allocated line buffer\r
543 //\r
544 FreePool (Line);\r
545\r
546 //\r
547 // Restore the cursor visibility, position, and attributes\r
548 //\r
549 ConOut->EnableCursor (ConOut, SavedConsoleMode.CursorVisible);\r
550 ConOut->SetCursorPosition (ConOut, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow);\r
551 ConOut->SetAttribute (ConOut, SavedConsoleMode.Attribute);\r
552\r
553 //\r
554 // Wait for a keystroke\r
555 //\r
556 if (Key != NULL) {\r
f04544be
RN
557 while (TRUE) {\r
558 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
559 if (!EFI_ERROR (Status)) {\r
560 break;\r
561 }\r
562\r
563 //\r
564 // If we encounter error, continue to read another key in.\r
565 //\r
566 if (Status != EFI_NOT_READY) {\r
567 continue;\r
568 }\r
569 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
570 }\r
db2ef756
LG
571 }\r
572}\r