]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
MdeModulePkg DxeCore: Fix issue to print GUID value %g without pointer
[mirror_edk2.git] / MdeModulePkg / Library / CustomizedDisplayLib / CustomizedDisplayLibInternal.c
CommitLineData
7c6c064c
ED
1/** @file\r
2\r
3 This library class defines a set of interfaces to customize Display module\r
4\r
5e30b69e 5Copyright (c) 2013-2015, Intel Corporation. All rights reserved.<BR>\r
7c6c064c
ED
6This program and the accompanying materials are licensed and made available under \r
7the terms and conditions of the BSD License that accompanies this distribution. \r
8The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php. \r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15#include "CustomizedDisplayLibInternal.h"\r
16\r
17EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
18CHAR16 *mLibUnknownString;\r
19extern EFI_HII_HANDLE mCDLStringPackHandle;\r
20CHAR16 *mSpaceBuffer;\r
21#define SPACE_BUFFER_SIZE 1000\r
22\r
23//\r
24// Browser Global Strings\r
25//\r
26CHAR16 *gEnterString;\r
27CHAR16 *gEnterCommitString;\r
28CHAR16 *gEnterEscapeString;\r
29CHAR16 *gEscapeString;\r
30CHAR16 *gMoveHighlight;\r
31CHAR16 *gDecNumericInput;\r
32CHAR16 *gHexNumericInput;\r
33CHAR16 *gToggleCheckBox;\r
34CHAR16 *gLibEmptyString;\r
35CHAR16 *gAreYouSure;\r
36CHAR16 *gYesResponse;\r
37CHAR16 *gNoResponse;\r
38CHAR16 *gPlusString;\r
39CHAR16 *gMinusString;\r
40CHAR16 *gAdjustNumber;\r
41CHAR16 *gSaveChanges;\r
42CHAR16 *gNvUpdateMessage;\r
43CHAR16 *gInputErrorMessage;\r
44\r
45/**\r
46\r
47 Print banner info for front page.\r
48\r
49 @param[in] FormData Form Data to be shown in Page\r
50 \r
51**/\r
52VOID\r
53PrintBannerInfo ( \r
54 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
55 )\r
56{\r
57 UINT8 Line;\r
58 UINT8 Alignment;\r
59 CHAR16 *StrFrontPageBanner;\r
60 UINT8 RowIdx;\r
61 UINT8 ColumnIdx;\r
62\r
63 //\r
64 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
65 //\r
66 ClearLines (\r
67 gScreenDimensions.LeftColumn,\r
68 gScreenDimensions.RightColumn,\r
69 gScreenDimensions.TopRow,\r
70 FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow,\r
71 BANNER_TEXT | BANNER_BACKGROUND\r
72 );\r
73\r
74 //\r
75 // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
76 //\r
77 for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) {\r
78 //\r
79 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
80 //\r
81 for (Alignment = (UINT8) gScreenDimensions.LeftColumn;\r
82 Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn;\r
83 Alignment++\r
84 ) {\r
85 RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow);\r
86 ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn);\r
87 \r
88 ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS);\r
89 \r
90 if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
91 StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle);\r
92 } else {\r
93 continue;\r
94 }\r
95 \r
96 switch (Alignment - gScreenDimensions.LeftColumn) {\r
97 case 0:\r
98 //\r
99 // Handle left column\r
100 //\r
101 PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);\r
102 break;\r
103 \r
104 case 1:\r
105 //\r
106 // Handle center column\r
107 //\r
108 PrintStringAt (\r
109 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3,\r
110 Line,\r
111 StrFrontPageBanner\r
112 );\r
113 break;\r
114 \r
115 case 2:\r
116 //\r
117 // Handle right column\r
118 //\r
119 PrintStringAt (\r
120 gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3,\r
121 Line,\r
122 StrFrontPageBanner\r
123 );\r
124 break;\r
125 }\r
126 \r
127 FreePool (StrFrontPageBanner);\r
128 }\r
129 }\r
130}\r
131\r
132/**\r
5a9f73bf 133 Print framework and form title for a page.\r
7c6c064c 134\r
5a9f73bf 135 @param[in] FormData Form Data to be shown in Page\r
7c6c064c
ED
136**/\r
137VOID\r
138PrintFramework (\r
5a9f73bf 139 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
7c6c064c
ED
140 )\r
141{\r
142 UINTN Index;\r
143 CHAR16 Character;\r
144 CHAR16 *Buffer;\r
145 UINTN Row;\r
5a9f73bf 146 CHAR16 *TitleStr;\r
af047db7 147 UINTN TitleColumn;\r
7c6c064c 148\r
5a9f73bf
ED
149 if (gClassOfVfr != FORMSET_CLASS_PLATFORM_SETUP) {\r
150 //\r
151 // Only Setup page needs Framework\r
152 //\r
153 ClearLines (\r
154 gScreenDimensions.LeftColumn,\r
155 gScreenDimensions.RightColumn,\r
156 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,\r
157 gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1,\r
158 KEYHELP_TEXT | KEYHELP_BACKGROUND\r
159 );\r
160 return;\r
161 }\r
162 \r
7c6c064c
ED
163 Buffer = AllocateZeroPool (0x10000);\r
164 ASSERT (Buffer != NULL);\r
165 Character = BOXDRAW_HORIZONTAL;\r
166 for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) {\r
167 Buffer[Index] = Character;\r
168 }\r
169\r
5a9f73bf
ED
170 //\r
171 // Print Top border line\r
172 // +------------------------------------------------------------------------------+\r
173 // ? ?\r
174 // +------------------------------------------------------------------------------+\r
175 //\r
176 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
177 Character = BOXDRAW_DOWN_RIGHT;\r
7c6c064c 178\r
5a9f73bf
ED
179 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow, Character);\r
180 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
7c6c064c 181\r
5a9f73bf
ED
182 Character = BOXDRAW_DOWN_LEFT;\r
183 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
7c6c064c 184\r
5a9f73bf
ED
185 Character = BOXDRAW_VERTICAL;\r
186 for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
187 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);\r
188 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);\r
7c6c064c
ED
189 }\r
190 \r
5a9f73bf
ED
191 //\r
192 // Print Form Title\r
193 //\r
5a9f73bf
ED
194 TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle);\r
195 ASSERT (TitleStr != NULL);\r
af047db7
ED
196 TitleColumn = (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2;\r
197 PrintStringAtWithWidth (gScreenDimensions.LeftColumn + 1, gScreenDimensions.TopRow + 1, gLibEmptyString, TitleColumn - gScreenDimensions.LeftColumn - 1);\r
198 PrintStringAtWithWidth (\r
199 TitleColumn,\r
7c6c064c 200 gScreenDimensions.TopRow + 1,\r
af047db7
ED
201 TitleStr,\r
202 gScreenDimensions.RightColumn - 1 - TitleColumn\r
7c6c064c 203 );\r
7c6c064c 204 FreePool (TitleStr);\r
5a9f73bf
ED
205\r
206 Character = BOXDRAW_UP_RIGHT;\r
207 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
208 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
209\r
210 Character = BOXDRAW_UP_LEFT;\r
211 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
212\r
213 //\r
214 // Print Bottom border line\r
215 // +------------------------------------------------------------------------------+\r
216 // ? ?\r
217 // +------------------------------------------------------------------------------+\r
218 //\r
219 Character = BOXDRAW_DOWN_RIGHT;\r
220 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);\r
221\r
222 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
223\r
224 Character = BOXDRAW_DOWN_LEFT;\r
225 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
226 Character = BOXDRAW_VERTICAL;\r
227 for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
228 Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;\r
229 Row++\r
230 ) {\r
231 PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);\r
232 PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);\r
233 }\r
234\r
235 Character = BOXDRAW_UP_RIGHT;\r
236 PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
237\r
238 PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
239\r
240 Character = BOXDRAW_UP_LEFT;\r
241 PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
242 \r
243 FreePool (Buffer);\r
7c6c064c
ED
244}\r
245\r
246/**\r
247 Process some op code which is not recognized by browser core.\r
248\r
249 @param OpCodeData The pointer to the op code buffer.\r
250\r
251 @return EFI_SUCCESS Pass the statement success.\r
252\r
253**/\r
254VOID\r
255ProcessUserOpcode(\r
256 IN EFI_IFR_OP_HEADER *OpCodeData\r
257 )\r
258{\r
5e30b69e
DB
259 EFI_GUID * ClassGuid;\r
260 UINT8 ClassGuidNum;\r
261\r
262 ClassGuid = NULL;\r
263 ClassGuidNum = 0;\r
264\r
7c6c064c 265 switch (OpCodeData->OpCode) {\r
5e30b69e
DB
266 case EFI_IFR_FORM_SET_OP:\r
267 //\r
268 // process the statement outside of form,if it is formset op, get its formsetguid or classguid and compared with gFrontPageFormSetGuid\r
269 //\r
986ede74 270 if (CompareMem (PcdGetPtr (PcdFrontPageFormSetGuid), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) == 0){\r
5e30b69e
DB
271 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
272 } else{\r
273 ClassGuidNum = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);\r
274 ClassGuid = (EFI_GUID *)(VOID *)((UINT8 *)OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
275 while (ClassGuidNum-- > 0){\r
276 if (CompareGuid((EFI_GUID*)PcdGetPtr (PcdFrontPageFormSetGuid),ClassGuid)){\r
277 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
278 break;\r
279 }\r
280 ClassGuid ++;\r
281 }\r
282 }\r
283 break;\r
284\r
7c6c064c
ED
285 case EFI_IFR_GUID_OP: \r
286 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
287 //\r
288 // Tiano specific GUIDed opcodes\r
289 //\r
290 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
291 case EFI_IFR_EXTEND_OP_LABEL:\r
292 //\r
293 // just ignore label\r
294 //\r
295 break;\r
296\r
297 case EFI_IFR_EXTEND_OP_BANNER:\r
298 //\r
299 // Only in front page form set, we care about the banner data.\r
300 //\r
5a9f73bf 301 if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
7c6c064c
ED
302 //\r
303 // Initialize Driver private data\r
304 //\r
305 if (gBannerData == NULL) {\r
306 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
307 ASSERT (gBannerData != NULL);\r
308 }\r
309 \r
310 CopyMem (\r
311 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][\r
312 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],\r
313 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,\r
314 sizeof (EFI_STRING_ID)\r
315 );\r
316 }\r
317 break;\r
318\r
319 case EFI_IFR_EXTEND_OP_SUBCLASS:\r
320 if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
321 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
322 }\r
323 break;\r
324\r
325 default:\r
326 break;\r
327 }\r
328 }\r
329 break;\r
330\r
331 default:\r
332 break;\r
333 }\r
334}\r
335\r
336/**\r
337 Process some op codes which is out side of current form.\r
338 \r
339 @param FormData Pointer to the form data.\r
340\r
341 @return EFI_SUCCESS Pass the statement success.\r
342\r
343**/\r
344VOID\r
345ProcessExternedOpcode (\r
346 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
347 )\r
348{\r
349 LIST_ENTRY *Link;\r
077c7aee 350 LIST_ENTRY *NestLink;\r
7c6c064c 351 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
077c7aee 352 FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;\r
7c6c064c
ED
353\r
354 Link = GetFirstNode (&FormData->StatementListOSF);\r
355 while (!IsNull (&FormData->StatementListOSF, Link)) {\r
356 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
357 Link = GetNextNode (&FormData->StatementListOSF, Link);\r
358\r
359 ProcessUserOpcode(Statement->OpCode);\r
360 }\r
361\r
362 Link = GetFirstNode (&FormData->StatementListHead);\r
363 while (!IsNull (&FormData->StatementListHead, Link)) {\r
364 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
365 Link = GetNextNode (&FormData->StatementListHead, Link);\r
366\r
367 ProcessUserOpcode(Statement->OpCode);\r
077c7aee
ED
368\r
369 NestLink = GetFirstNode (&Statement->NestStatementList);\r
370 while (!IsNull (&Statement->NestStatementList, NestLink)) {\r
371 NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);\r
372 NestLink = GetNextNode (&Statement->NestStatementList, NestLink);\r
373\r
374 ProcessUserOpcode(NestStatement->OpCode);\r
375 }\r
376\r
7c6c064c
ED
377 }\r
378}\r
379\r
380/**\r
381 Validate the input screen diemenstion info.\r
382\r
383 @param FormData The input form data info.\r
384\r
385 @return EFI_SUCCESS The input screen info is acceptable.\r
386 @return EFI_INVALID_PARAMETER The input screen info is not acceptable.\r
387\r
388**/\r
389EFI_STATUS \r
390ScreenDiemensionInfoValidate (\r
391 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
392 )\r
393{\r
394 LIST_ENTRY *Link;\r
395 UINTN Index;\r
396\r
397 //\r
398 // Calculate total number of Register HotKeys. \r
399 //\r
400 Index = 0;\r
401 if (!IsListEmpty (&FormData->HotKeyListHead)){\r
402 Link = GetFirstNode (&FormData->HotKeyListHead);\r
403 while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
404 Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
405 Index ++;\r
406 }\r
407 }\r
408\r
409 //\r
410 // Show three HotKeys help information on one row.\r
411 //\r
412 gFooterHeight = FOOTER_HEIGHT + (Index / 3);\r
413\r
414\r
415 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
416 gST->ConOut->QueryMode (\r
417 gST->ConOut,\r
418 gST->ConOut->Mode->Mode,\r
419 &gScreenDimensions.RightColumn,\r
420 &gScreenDimensions.BottomRow\r
421 );\r
422\r
423 //\r
424 // Check local dimension vs. global dimension.\r
425 //\r
426 if (FormData->ScreenDimensions != NULL) {\r
427 if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) ||\r
428 (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow)\r
429 ) {\r
430 return EFI_INVALID_PARAMETER;\r
431 } else {\r
432 //\r
433 // Local dimension validation.\r
434 //\r
435 if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) &&\r
436 (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) &&\r
437 ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) &&\r
438 ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
439 FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) {\r
440 CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
441 } else {\r
442 return EFI_INVALID_PARAMETER;\r
443 }\r
444 }\r
445 }\r
446\r
447 return EFI_SUCCESS;\r
448}\r
449\r
450/**\r
451 Get the string based on the StringId and HII Package List Handle.\r
452\r
453 @param Token The String's ID.\r
454 @param HiiHandle The package list in the HII database to search for\r
455 the specified string.\r
456\r
457 @return The output string.\r
458\r
459**/\r
460CHAR16 *\r
461LibGetToken (\r
462 IN EFI_STRING_ID Token,\r
463 IN EFI_HII_HANDLE HiiHandle\r
464 )\r
465{\r
466 EFI_STRING String;\r
467\r
468 String = HiiGetString (HiiHandle, Token, NULL);\r
469 if (String == NULL) {\r
470 String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString);\r
471 ASSERT (String != NULL);\r
472 }\r
473\r
474 return (CHAR16 *) String;\r
475}\r
476\r
477\r
478/**\r
479 Count the storage space of a Unicode string.\r
480\r
481 This function handles the Unicode string with NARROW_CHAR\r
482 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
483 does not count in the resultant output. If a WIDE_CHAR is\r
484 hit, then 2 Unicode character will consume an output storage\r
485 space with size of CHAR16 till a NARROW_CHAR is hit.\r
486\r
487 If String is NULL, then ASSERT ().\r
488\r
489 @param String The input string to be counted.\r
490\r
491 @return Storage space for the input string.\r
492\r
493**/\r
494UINTN\r
495LibGetStringWidth (\r
496 IN CHAR16 *String\r
497 )\r
498{\r
499 UINTN Index;\r
500 UINTN Count;\r
501 UINTN IncrementValue;\r
502\r
503 ASSERT (String != NULL);\r
504 if (String == NULL) {\r
505 return 0;\r
506 }\r
507\r
508 Index = 0;\r
509 Count = 0;\r
510 IncrementValue = 1;\r
511\r
512 do {\r
513 //\r
514 // Advance to the null-terminator or to the first width directive\r
515 //\r
516 for (;\r
517 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
518 Index++, Count = Count + IncrementValue\r
519 )\r
520 ;\r
521\r
522 //\r
523 // We hit the null-terminator, we now have a count\r
524 //\r
525 if (String[Index] == 0) {\r
526 break;\r
527 }\r
528 //\r
529 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
530 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
531 //\r
532 if (String[Index] == NARROW_CHAR) {\r
533 //\r
534 // Skip to the next character\r
535 //\r
536 Index++;\r
537 IncrementValue = 1;\r
538 } else {\r
539 //\r
540 // Skip to the next character\r
541 //\r
542 Index++;\r
543 IncrementValue = 2;\r
544 }\r
545 } while (String[Index] != 0);\r
546\r
547 //\r
548 // Increment by one to include the null-terminator in the size\r
549 //\r
550 Count++;\r
551\r
552 return Count * sizeof (CHAR16);\r
553}\r
554\r
555/**\r
556 Show all registered HotKey help strings on bottom Rows.\r
557\r
558 @param FormData The curent input form data info.\r
af047db7 559 @param SetState Set HotKey or Clear HotKey\r
7c6c064c
ED
560\r
561**/\r
562VOID\r
563PrintHotKeyHelpString (\r
af047db7
ED
564 IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
565 IN BOOLEAN SetState\r
7c6c064c
ED
566 )\r
567{\r
568 UINTN CurrentCol;\r
569 UINTN CurrentRow;\r
570 UINTN BottomRowOfHotKeyHelp;\r
af047db7 571 UINTN ColumnIndexWidth;\r
7c6c064c 572 UINTN ColumnWidth;\r
af047db7 573 UINTN ColumnIndex;\r
7c6c064c
ED
574 UINTN Index;\r
575 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
576 LIST_ENTRY *Link;\r
577 BROWSER_HOT_KEY *HotKey;\r
af047db7
ED
578 CHAR16 BakChar;\r
579 CHAR16 *ColumnStr;\r
7c6c064c
ED
580\r
581 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
582 ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
583 BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
af047db7 584 ColumnStr = gLibEmptyString;\r
7c6c064c
ED
585\r
586 //\r
587 // Calculate total number of Register HotKeys. \r
588 //\r
589 Index = 0;\r
590 Link = GetFirstNode (&FormData->HotKeyListHead);\r
591 while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
592 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
593 //\r
7c6c064c
ED
594 // Calculate help information Column and Row.\r
595 //\r
af047db7
ED
596 ColumnIndex = Index % 3;\r
597 if (ColumnIndex == 0) {\r
598 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;\r
599 ColumnIndexWidth = ColumnWidth - 1;\r
600 } else if (ColumnIndex == 1) {\r
601 CurrentCol = LocalScreen.LeftColumn + ColumnWidth;\r
602 ColumnIndexWidth = ColumnWidth;\r
7c6c064c 603 } else {\r
af047db7
ED
604 CurrentCol = LocalScreen.LeftColumn + 2;\r
605 ColumnIndexWidth = ColumnWidth - 2;\r
7c6c064c
ED
606 }\r
607 CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
af047db7
ED
608\r
609 //\r
610 // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
611 //\r
612 BakChar = L'\0';\r
613 if (StrLen (HotKey->HelpString) > ColumnIndexWidth) {\r
614 BakChar = HotKey->HelpString[ColumnIndexWidth];\r
615 HotKey->HelpString[ColumnIndexWidth] = L'\0';\r
616 }\r
617\r
7c6c064c
ED
618 //\r
619 // Print HotKey help string on bottom Row.\r
620 //\r
af047db7
ED
621 if (SetState) {\r
622 ColumnStr = HotKey->HelpString;\r
623 }\r
624 PrintStringAtWithWidth (CurrentCol, CurrentRow, ColumnStr, ColumnIndexWidth);\r
7c6c064c 625\r
af047db7
ED
626 if (BakChar != L'\0') {\r
627 HotKey->HelpString[ColumnIndexWidth] = BakChar;\r
628 }\r
7c6c064c
ED
629 //\r
630 // Get Next Hot Key.\r
631 //\r
632 Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
633 Index ++;\r
634 }\r
635 \r
af047db7
ED
636 if (SetState) {\r
637 //\r
638 // Clear KeyHelp\r
639 //\r
640 CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
641 ColumnIndex = Index % 3;\r
642 if (ColumnIndex == 0) {\r
643 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;\r
644 ColumnIndexWidth = ColumnWidth - 1;\r
645 ColumnIndex ++;\r
646 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);\r
647 }\r
648 if (ColumnIndex == 1) {\r
649 CurrentCol = LocalScreen.LeftColumn + ColumnWidth;\r
650 ColumnIndexWidth = ColumnWidth;\r
651 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);\r
652 }\r
653 }\r
654 \r
7c6c064c
ED
655 return;\r
656}\r
657\r
658/**\r
659 Get step info from numeric opcode.\r
660 \r
661 @param[in] OpCode The input numeric op code.\r
662\r
663 @return step info for this opcode.\r
664**/\r
665UINT64\r
666LibGetFieldFromNum (\r
667 IN EFI_IFR_OP_HEADER *OpCode\r
668 )\r
669{\r
670 EFI_IFR_NUMERIC *NumericOp;\r
671 UINT64 Step;\r
672\r
673 NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
674 \r
675 switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
676 case EFI_IFR_NUMERIC_SIZE_1:\r
677 Step = NumericOp->data.u8.Step;\r
678 break;\r
679 \r
680 case EFI_IFR_NUMERIC_SIZE_2:\r
681 Step = NumericOp->data.u16.Step;\r
682 break;\r
683 \r
684 case EFI_IFR_NUMERIC_SIZE_4:\r
685 Step = NumericOp->data.u32.Step;\r
686 break;\r
687 \r
688 case EFI_IFR_NUMERIC_SIZE_8:\r
689 Step = NumericOp->data.u64.Step;\r
690 break;\r
691 \r
692 default:\r
693 Step = 0;\r
694 break;\r
695 }\r
696\r
697 return Step;\r
698}\r
699\r
700/**\r
701 Initialize the HII String Token to the correct values.\r
702\r
703**/\r
704VOID\r
705InitializeLibStrings (\r
706 VOID\r
707 )\r
708{\r
709 mLibUnknownString = L"!";\r
710\r
711 gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle);\r
712 gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle);\r
713 gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle);\r
714 gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle);\r
715 gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle);\r
716 gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle);\r
717 gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle);\r
718 gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle);\r
719\r
720 gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle);\r
721 gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle);\r
722 gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle);\r
723 gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle);\r
724 gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle);\r
725 gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle);\r
726 gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle);\r
727\r
728 gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle);\r
729\r
730 gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle);\r
731 gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle);\r
732 \r
733 //\r
734 // SpaceBuffer;\r
735 //\r
736 mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16));\r
737 ASSERT (mSpaceBuffer != NULL);\r
738 LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' ');\r
739 mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0';\r
740}\r
741\r
742\r
743/**\r
744 Free the HII String.\r
745\r
746**/\r
747VOID\r
748FreeLibStrings (\r
749 VOID\r
750 )\r
751{\r
752 FreePool (gEnterString);\r
753 FreePool (gEnterCommitString);\r
754 FreePool (gEnterEscapeString);\r
755 FreePool (gEscapeString);\r
756 FreePool (gMoveHighlight);\r
757 FreePool (gDecNumericInput);\r
758 FreePool (gHexNumericInput);\r
759 FreePool (gToggleCheckBox);\r
760\r
761 FreePool (gAreYouSure);\r
762 FreePool (gYesResponse);\r
763 FreePool (gNoResponse);\r
764 FreePool (gPlusString);\r
765 FreePool (gMinusString);\r
766 FreePool (gAdjustNumber);\r
767 FreePool (gSaveChanges);\r
768\r
769 FreePool (gLibEmptyString);\r
770\r
771 FreePool (gNvUpdateMessage);\r
772 FreePool (gInputErrorMessage);\r
773 \r
774 FreePool (mSpaceBuffer);\r
775}\r
776\r
777/**\r
778 Wait for a key to be pressed by user.\r
779\r
780 @param Key The key which is pressed by user.\r
781\r
782 @retval EFI_SUCCESS The function always completed successfully.\r
783\r
784**/\r
785EFI_STATUS\r
786WaitForKeyStroke (\r
787 OUT EFI_INPUT_KEY *Key\r
788 )\r
789{\r
790 EFI_STATUS Status;\r
791 UINTN Index;\r
792\r
793 while (TRUE) {\r
794 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
795 if (!EFI_ERROR (Status)) {\r
796 break;\r
797 }\r
798\r
799 if (Status != EFI_NOT_READY) {\r
800 continue;\r
801 }\r
802 \r
803 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
804 }\r
805 return Status;\r
806}\r
807\r
808\r
809/**\r
810 Set Buffer to Value for Size bytes.\r
811\r
812 @param Buffer Memory to set.\r
813 @param Size Number of bytes to set\r
814 @param Value Value of the set operation.\r
815\r
816**/\r
817VOID\r
818LibSetUnicodeMem (\r
819 IN VOID *Buffer,\r
820 IN UINTN Size,\r
821 IN CHAR16 Value\r
822 )\r
823{\r
824 CHAR16 *Ptr;\r
825\r
826 Ptr = Buffer;\r
827 while ((Size--) != 0) {\r
828 *(Ptr++) = Value;\r
829 }\r
830}\r
831\r
832/**\r
833 The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
834 protocol instance.\r
835\r
836 @param Width Width of string to be print.\r
837 @param Column The position of the output string.\r
838 @param Row The position of the output string.\r
839 @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.\r
840 @param Fmt The format string.\r
841 @param Args The additional argument for the variables in the format string.\r
842\r
843 @return Number of Unicode character printed.\r
844\r
845**/\r
846UINTN\r
847PrintInternal (\r
848 IN UINTN Width, \r
849 IN UINTN Column,\r
850 IN UINTN Row,\r
851 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,\r
852 IN CHAR16 *Fmt,\r
853 IN VA_LIST Args\r
854 )\r
855{\r
856 CHAR16 *Buffer;\r
857 CHAR16 *BackupBuffer;\r
858 UINTN Index;\r
859 UINTN PreviousIndex;\r
860 UINTN Count;\r
af047db7 861 UINTN TotalCount;\r
7c6c064c
ED
862 UINTN PrintWidth;\r
863 UINTN CharWidth;\r
864\r
865 //\r
866 // For now, allocate an arbitrarily long buffer\r
867 //\r
868 Buffer = AllocateZeroPool (0x10000);\r
869 BackupBuffer = AllocateZeroPool (0x10000);\r
870 ASSERT (Buffer);\r
871 ASSERT (BackupBuffer);\r
872\r
873 if (Column != (UINTN) -1) {\r
874 Out->SetCursorPosition (Out, Column, Row);\r
875 }\r
876\r
877 UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);\r
878\r
879 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
880\r
881 Out->SetAttribute (Out, Out->Mode->Attribute);\r
882\r
883 Index = 0;\r
884 PreviousIndex = 0;\r
885 Count = 0;\r
af047db7 886 TotalCount = 0;\r
7c6c064c
ED
887 PrintWidth = 0;\r
888 CharWidth = 1;\r
889\r
890 do {\r
891 for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {\r
892 BackupBuffer[Index] = Buffer[Index];\r
893 }\r
894\r
895 if (Buffer[Index] == 0) {\r
896 break;\r
897 }\r
7c6c064c
ED
898\r
899 //\r
900 // Print this out, we are about to switch widths\r
901 //\r
902 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
af047db7 903 Count = StrLen (&BackupBuffer[PreviousIndex]);\r
7c6c064c 904 PrintWidth += Count * CharWidth;\r
af047db7 905 TotalCount += Count;\r
7c6c064c
ED
906\r
907 //\r
908 // Preserve the current index + 1, since this is where we will start printing from next\r
909 //\r
910 PreviousIndex = Index + 1;\r
911\r
912 //\r
913 // We are at a narrow or wide character directive. Set attributes and strip it and print it\r
914 //\r
915 if (Buffer[Index] == NARROW_CHAR) {\r
916 //\r
917 // Preserve bits 0 - 6 and zero out the rest\r
918 //\r
919 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
920 Out->SetAttribute (Out, Out->Mode->Attribute);\r
921 CharWidth = 1;\r
922 } else {\r
923 //\r
924 // Must be wide, set bit 7 ON\r
925 //\r
926 Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;\r
927 Out->SetAttribute (Out, Out->Mode->Attribute);\r
928 CharWidth = 2;\r
929 }\r
930\r
931 Index++;\r
932\r
933 } while (Buffer[Index] != 0);\r
934\r
935 //\r
936 // We hit the end of the string - print it\r
937 //\r
938 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
af047db7 939 Count = StrLen (&BackupBuffer[PreviousIndex]);\r
7c6c064c 940 PrintWidth += Count * CharWidth;\r
af047db7 941 TotalCount += Count;\r
7c6c064c
ED
942 if (PrintWidth < Width) {\r
943 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
944 Out->SetAttribute (Out, Out->Mode->Attribute);\r
945 Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]);\r
946 }\r
947\r
948 FreePool (Buffer);\r
949 FreePool (BackupBuffer);\r
af047db7 950 return TotalCount;\r
7c6c064c
ED
951}\r
952\r
953/**\r
954 Prints a formatted unicode string to the default console, at\r
955 the supplied cursor position.\r
956\r
957 @param Width Width of String to be printed.\r
958 @param Column The cursor position to print the string at.\r
959 @param Row The cursor position to print the string at.\r
960 @param Fmt Format string.\r
961 @param ... Variable argument list for format string.\r
962\r
963 @return Length of string printed to the console\r
964\r
965**/\r
966UINTN\r
967EFIAPI\r
968PrintAt (\r
969 IN UINTN Width,\r
970 IN UINTN Column,\r
971 IN UINTN Row,\r
972 IN CHAR16 *Fmt,\r
973 ...\r
974 )\r
975{\r
976 VA_LIST Args;\r
977 UINTN LengthOfPrinted;\r
978\r
979 VA_START (Args, Fmt);\r
980 LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args);\r
981 VA_END (Args);\r
982 return LengthOfPrinted;\r
983}\r
984\r