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