]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
MdeModulePkg: Add match2 opcode support in SetupBrowserDxe and sample code in DriverS...
[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
5Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
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
259 switch (OpCodeData->OpCode) {\r
260 case EFI_IFR_GUID_OP: \r
261 if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
262 //\r
263 // Tiano specific GUIDed opcodes\r
264 //\r
265 switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
266 case EFI_IFR_EXTEND_OP_LABEL:\r
267 //\r
268 // just ignore label\r
269 //\r
270 break;\r
271\r
272 case EFI_IFR_EXTEND_OP_BANNER:\r
273 //\r
274 // Only in front page form set, we care about the banner data.\r
275 //\r
5a9f73bf 276 if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
7c6c064c
ED
277 //\r
278 // Initialize Driver private data\r
279 //\r
280 if (gBannerData == NULL) {\r
281 gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
282 ASSERT (gBannerData != NULL);\r
283 }\r
284 \r
285 CopyMem (\r
286 &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][\r
287 ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],\r
288 &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,\r
289 sizeof (EFI_STRING_ID)\r
290 );\r
291 }\r
292 break;\r
293\r
294 case EFI_IFR_EXTEND_OP_SUBCLASS:\r
295 if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
296 gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
297 }\r
298 break;\r
299\r
300 default:\r
301 break;\r
302 }\r
303 }\r
304 break;\r
305\r
306 default:\r
307 break;\r
308 }\r
309}\r
310\r
311/**\r
312 Process some op codes which is out side of current form.\r
313 \r
314 @param FormData Pointer to the form data.\r
315\r
316 @return EFI_SUCCESS Pass the statement success.\r
317\r
318**/\r
319VOID\r
320ProcessExternedOpcode (\r
321 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
322 )\r
323{\r
324 LIST_ENTRY *Link;\r
077c7aee 325 LIST_ENTRY *NestLink;\r
7c6c064c 326 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
077c7aee 327 FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;\r
7c6c064c
ED
328\r
329 Link = GetFirstNode (&FormData->StatementListOSF);\r
330 while (!IsNull (&FormData->StatementListOSF, Link)) {\r
331 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
332 Link = GetNextNode (&FormData->StatementListOSF, Link);\r
333\r
334 ProcessUserOpcode(Statement->OpCode);\r
335 }\r
336\r
337 Link = GetFirstNode (&FormData->StatementListHead);\r
338 while (!IsNull (&FormData->StatementListHead, Link)) {\r
339 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
340 Link = GetNextNode (&FormData->StatementListHead, Link);\r
341\r
342 ProcessUserOpcode(Statement->OpCode);\r
077c7aee
ED
343\r
344 NestLink = GetFirstNode (&Statement->NestStatementList);\r
345 while (!IsNull (&Statement->NestStatementList, NestLink)) {\r
346 NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);\r
347 NestLink = GetNextNode (&Statement->NestStatementList, NestLink);\r
348\r
349 ProcessUserOpcode(NestStatement->OpCode);\r
350 }\r
351\r
7c6c064c
ED
352 }\r
353}\r
354\r
355/**\r
356 Validate the input screen diemenstion info.\r
357\r
358 @param FormData The input form data info.\r
359\r
360 @return EFI_SUCCESS The input screen info is acceptable.\r
361 @return EFI_INVALID_PARAMETER The input screen info is not acceptable.\r
362\r
363**/\r
364EFI_STATUS \r
365ScreenDiemensionInfoValidate (\r
366 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
367 )\r
368{\r
369 LIST_ENTRY *Link;\r
370 UINTN Index;\r
371\r
372 //\r
373 // Calculate total number of Register HotKeys. \r
374 //\r
375 Index = 0;\r
376 if (!IsListEmpty (&FormData->HotKeyListHead)){\r
377 Link = GetFirstNode (&FormData->HotKeyListHead);\r
378 while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
379 Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
380 Index ++;\r
381 }\r
382 }\r
383\r
384 //\r
385 // Show three HotKeys help information on one row.\r
386 //\r
387 gFooterHeight = FOOTER_HEIGHT + (Index / 3);\r
388\r
389\r
390 ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
391 gST->ConOut->QueryMode (\r
392 gST->ConOut,\r
393 gST->ConOut->Mode->Mode,\r
394 &gScreenDimensions.RightColumn,\r
395 &gScreenDimensions.BottomRow\r
396 );\r
397\r
398 //\r
399 // Check local dimension vs. global dimension.\r
400 //\r
401 if (FormData->ScreenDimensions != NULL) {\r
402 if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) ||\r
403 (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow)\r
404 ) {\r
405 return EFI_INVALID_PARAMETER;\r
406 } else {\r
407 //\r
408 // Local dimension validation.\r
409 //\r
410 if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) &&\r
411 (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) &&\r
412 ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) &&\r
413 ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
414 FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) {\r
415 CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
416 } else {\r
417 return EFI_INVALID_PARAMETER;\r
418 }\r
419 }\r
420 }\r
421\r
422 return EFI_SUCCESS;\r
423}\r
424\r
425/**\r
426 Get the string based on the StringId and HII Package List Handle.\r
427\r
428 @param Token The String's ID.\r
429 @param HiiHandle The package list in the HII database to search for\r
430 the specified string.\r
431\r
432 @return The output string.\r
433\r
434**/\r
435CHAR16 *\r
436LibGetToken (\r
437 IN EFI_STRING_ID Token,\r
438 IN EFI_HII_HANDLE HiiHandle\r
439 )\r
440{\r
441 EFI_STRING String;\r
442\r
443 String = HiiGetString (HiiHandle, Token, NULL);\r
444 if (String == NULL) {\r
445 String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString);\r
446 ASSERT (String != NULL);\r
447 }\r
448\r
449 return (CHAR16 *) String;\r
450}\r
451\r
452\r
453/**\r
454 Count the storage space of a Unicode string.\r
455\r
456 This function handles the Unicode string with NARROW_CHAR\r
457 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
458 does not count in the resultant output. If a WIDE_CHAR is\r
459 hit, then 2 Unicode character will consume an output storage\r
460 space with size of CHAR16 till a NARROW_CHAR is hit.\r
461\r
462 If String is NULL, then ASSERT ().\r
463\r
464 @param String The input string to be counted.\r
465\r
466 @return Storage space for the input string.\r
467\r
468**/\r
469UINTN\r
470LibGetStringWidth (\r
471 IN CHAR16 *String\r
472 )\r
473{\r
474 UINTN Index;\r
475 UINTN Count;\r
476 UINTN IncrementValue;\r
477\r
478 ASSERT (String != NULL);\r
479 if (String == NULL) {\r
480 return 0;\r
481 }\r
482\r
483 Index = 0;\r
484 Count = 0;\r
485 IncrementValue = 1;\r
486\r
487 do {\r
488 //\r
489 // Advance to the null-terminator or to the first width directive\r
490 //\r
491 for (;\r
492 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
493 Index++, Count = Count + IncrementValue\r
494 )\r
495 ;\r
496\r
497 //\r
498 // We hit the null-terminator, we now have a count\r
499 //\r
500 if (String[Index] == 0) {\r
501 break;\r
502 }\r
503 //\r
504 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
505 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
506 //\r
507 if (String[Index] == NARROW_CHAR) {\r
508 //\r
509 // Skip to the next character\r
510 //\r
511 Index++;\r
512 IncrementValue = 1;\r
513 } else {\r
514 //\r
515 // Skip to the next character\r
516 //\r
517 Index++;\r
518 IncrementValue = 2;\r
519 }\r
520 } while (String[Index] != 0);\r
521\r
522 //\r
523 // Increment by one to include the null-terminator in the size\r
524 //\r
525 Count++;\r
526\r
527 return Count * sizeof (CHAR16);\r
528}\r
529\r
530/**\r
531 Show all registered HotKey help strings on bottom Rows.\r
532\r
533 @param FormData The curent input form data info.\r
af047db7 534 @param SetState Set HotKey or Clear HotKey\r
7c6c064c
ED
535\r
536**/\r
537VOID\r
538PrintHotKeyHelpString (\r
af047db7
ED
539 IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
540 IN BOOLEAN SetState\r
7c6c064c
ED
541 )\r
542{\r
543 UINTN CurrentCol;\r
544 UINTN CurrentRow;\r
545 UINTN BottomRowOfHotKeyHelp;\r
af047db7 546 UINTN ColumnIndexWidth;\r
7c6c064c 547 UINTN ColumnWidth;\r
af047db7 548 UINTN ColumnIndex;\r
7c6c064c
ED
549 UINTN Index;\r
550 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
551 LIST_ENTRY *Link;\r
552 BROWSER_HOT_KEY *HotKey;\r
af047db7
ED
553 CHAR16 BakChar;\r
554 CHAR16 *ColumnStr;\r
7c6c064c
ED
555\r
556 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
557 ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
558 BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
af047db7 559 ColumnStr = gLibEmptyString;\r
7c6c064c
ED
560\r
561 //\r
562 // Calculate total number of Register HotKeys. \r
563 //\r
564 Index = 0;\r
565 Link = GetFirstNode (&FormData->HotKeyListHead);\r
566 while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
567 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
568 //\r
7c6c064c
ED
569 // Calculate help information Column and Row.\r
570 //\r
af047db7
ED
571 ColumnIndex = Index % 3;\r
572 if (ColumnIndex == 0) {\r
573 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;\r
574 ColumnIndexWidth = ColumnWidth - 1;\r
575 } else if (ColumnIndex == 1) {\r
576 CurrentCol = LocalScreen.LeftColumn + ColumnWidth;\r
577 ColumnIndexWidth = ColumnWidth;\r
7c6c064c 578 } else {\r
af047db7
ED
579 CurrentCol = LocalScreen.LeftColumn + 2;\r
580 ColumnIndexWidth = ColumnWidth - 2;\r
7c6c064c
ED
581 }\r
582 CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
af047db7
ED
583\r
584 //\r
585 // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
586 //\r
587 BakChar = L'\0';\r
588 if (StrLen (HotKey->HelpString) > ColumnIndexWidth) {\r
589 BakChar = HotKey->HelpString[ColumnIndexWidth];\r
590 HotKey->HelpString[ColumnIndexWidth] = L'\0';\r
591 }\r
592\r
7c6c064c
ED
593 //\r
594 // Print HotKey help string on bottom Row.\r
595 //\r
af047db7
ED
596 if (SetState) {\r
597 ColumnStr = HotKey->HelpString;\r
598 }\r
599 PrintStringAtWithWidth (CurrentCol, CurrentRow, ColumnStr, ColumnIndexWidth);\r
7c6c064c 600\r
af047db7
ED
601 if (BakChar != L'\0') {\r
602 HotKey->HelpString[ColumnIndexWidth] = BakChar;\r
603 }\r
7c6c064c
ED
604 //\r
605 // Get Next Hot Key.\r
606 //\r
607 Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
608 Index ++;\r
609 }\r
610 \r
af047db7
ED
611 if (SetState) {\r
612 //\r
613 // Clear KeyHelp\r
614 //\r
615 CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
616 ColumnIndex = Index % 3;\r
617 if (ColumnIndex == 0) {\r
618 CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;\r
619 ColumnIndexWidth = ColumnWidth - 1;\r
620 ColumnIndex ++;\r
621 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);\r
622 }\r
623 if (ColumnIndex == 1) {\r
624 CurrentCol = LocalScreen.LeftColumn + ColumnWidth;\r
625 ColumnIndexWidth = ColumnWidth;\r
626 PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);\r
627 }\r
628 }\r
629 \r
7c6c064c
ED
630 return;\r
631}\r
632\r
633/**\r
634 Get step info from numeric opcode.\r
635 \r
636 @param[in] OpCode The input numeric op code.\r
637\r
638 @return step info for this opcode.\r
639**/\r
640UINT64\r
641LibGetFieldFromNum (\r
642 IN EFI_IFR_OP_HEADER *OpCode\r
643 )\r
644{\r
645 EFI_IFR_NUMERIC *NumericOp;\r
646 UINT64 Step;\r
647\r
648 NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
649 \r
650 switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
651 case EFI_IFR_NUMERIC_SIZE_1:\r
652 Step = NumericOp->data.u8.Step;\r
653 break;\r
654 \r
655 case EFI_IFR_NUMERIC_SIZE_2:\r
656 Step = NumericOp->data.u16.Step;\r
657 break;\r
658 \r
659 case EFI_IFR_NUMERIC_SIZE_4:\r
660 Step = NumericOp->data.u32.Step;\r
661 break;\r
662 \r
663 case EFI_IFR_NUMERIC_SIZE_8:\r
664 Step = NumericOp->data.u64.Step;\r
665 break;\r
666 \r
667 default:\r
668 Step = 0;\r
669 break;\r
670 }\r
671\r
672 return Step;\r
673}\r
674\r
675/**\r
676 Initialize the HII String Token to the correct values.\r
677\r
678**/\r
679VOID\r
680InitializeLibStrings (\r
681 VOID\r
682 )\r
683{\r
684 mLibUnknownString = L"!";\r
685\r
686 gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle);\r
687 gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle);\r
688 gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle);\r
689 gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle);\r
690 gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle);\r
691 gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle);\r
692 gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle);\r
693 gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle);\r
694\r
695 gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle);\r
696 gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle);\r
697 gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle);\r
698 gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle);\r
699 gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle);\r
700 gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle);\r
701 gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle);\r
702\r
703 gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle);\r
704\r
705 gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle);\r
706 gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle);\r
707 \r
708 //\r
709 // SpaceBuffer;\r
710 //\r
711 mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16));\r
712 ASSERT (mSpaceBuffer != NULL);\r
713 LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' ');\r
714 mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0';\r
715}\r
716\r
717\r
718/**\r
719 Free the HII String.\r
720\r
721**/\r
722VOID\r
723FreeLibStrings (\r
724 VOID\r
725 )\r
726{\r
727 FreePool (gEnterString);\r
728 FreePool (gEnterCommitString);\r
729 FreePool (gEnterEscapeString);\r
730 FreePool (gEscapeString);\r
731 FreePool (gMoveHighlight);\r
732 FreePool (gDecNumericInput);\r
733 FreePool (gHexNumericInput);\r
734 FreePool (gToggleCheckBox);\r
735\r
736 FreePool (gAreYouSure);\r
737 FreePool (gYesResponse);\r
738 FreePool (gNoResponse);\r
739 FreePool (gPlusString);\r
740 FreePool (gMinusString);\r
741 FreePool (gAdjustNumber);\r
742 FreePool (gSaveChanges);\r
743\r
744 FreePool (gLibEmptyString);\r
745\r
746 FreePool (gNvUpdateMessage);\r
747 FreePool (gInputErrorMessage);\r
748 \r
749 FreePool (mSpaceBuffer);\r
750}\r
751\r
752/**\r
753 Wait for a key to be pressed by user.\r
754\r
755 @param Key The key which is pressed by user.\r
756\r
757 @retval EFI_SUCCESS The function always completed successfully.\r
758\r
759**/\r
760EFI_STATUS\r
761WaitForKeyStroke (\r
762 OUT EFI_INPUT_KEY *Key\r
763 )\r
764{\r
765 EFI_STATUS Status;\r
766 UINTN Index;\r
767\r
768 while (TRUE) {\r
769 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
770 if (!EFI_ERROR (Status)) {\r
771 break;\r
772 }\r
773\r
774 if (Status != EFI_NOT_READY) {\r
775 continue;\r
776 }\r
777 \r
778 gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
779 }\r
780 return Status;\r
781}\r
782\r
783\r
784/**\r
785 Set Buffer to Value for Size bytes.\r
786\r
787 @param Buffer Memory to set.\r
788 @param Size Number of bytes to set\r
789 @param Value Value of the set operation.\r
790\r
791**/\r
792VOID\r
793LibSetUnicodeMem (\r
794 IN VOID *Buffer,\r
795 IN UINTN Size,\r
796 IN CHAR16 Value\r
797 )\r
798{\r
799 CHAR16 *Ptr;\r
800\r
801 Ptr = Buffer;\r
802 while ((Size--) != 0) {\r
803 *(Ptr++) = Value;\r
804 }\r
805}\r
806\r
807/**\r
808 The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
809 protocol instance.\r
810\r
811 @param Width Width of string to be print.\r
812 @param Column The position of the output string.\r
813 @param Row The position of the output string.\r
814 @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.\r
815 @param Fmt The format string.\r
816 @param Args The additional argument for the variables in the format string.\r
817\r
818 @return Number of Unicode character printed.\r
819\r
820**/\r
821UINTN\r
822PrintInternal (\r
823 IN UINTN Width, \r
824 IN UINTN Column,\r
825 IN UINTN Row,\r
826 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,\r
827 IN CHAR16 *Fmt,\r
828 IN VA_LIST Args\r
829 )\r
830{\r
831 CHAR16 *Buffer;\r
832 CHAR16 *BackupBuffer;\r
833 UINTN Index;\r
834 UINTN PreviousIndex;\r
835 UINTN Count;\r
af047db7 836 UINTN TotalCount;\r
7c6c064c
ED
837 UINTN PrintWidth;\r
838 UINTN CharWidth;\r
839\r
840 //\r
841 // For now, allocate an arbitrarily long buffer\r
842 //\r
843 Buffer = AllocateZeroPool (0x10000);\r
844 BackupBuffer = AllocateZeroPool (0x10000);\r
845 ASSERT (Buffer);\r
846 ASSERT (BackupBuffer);\r
847\r
848 if (Column != (UINTN) -1) {\r
849 Out->SetCursorPosition (Out, Column, Row);\r
850 }\r
851\r
852 UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);\r
853\r
854 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
855\r
856 Out->SetAttribute (Out, Out->Mode->Attribute);\r
857\r
858 Index = 0;\r
859 PreviousIndex = 0;\r
860 Count = 0;\r
af047db7 861 TotalCount = 0;\r
7c6c064c
ED
862 PrintWidth = 0;\r
863 CharWidth = 1;\r
864\r
865 do {\r
866 for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {\r
867 BackupBuffer[Index] = Buffer[Index];\r
868 }\r
869\r
870 if (Buffer[Index] == 0) {\r
871 break;\r
872 }\r
7c6c064c
ED
873\r
874 //\r
875 // Print this out, we are about to switch widths\r
876 //\r
877 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
af047db7 878 Count = StrLen (&BackupBuffer[PreviousIndex]);\r
7c6c064c 879 PrintWidth += Count * CharWidth;\r
af047db7 880 TotalCount += Count;\r
7c6c064c
ED
881\r
882 //\r
883 // Preserve the current index + 1, since this is where we will start printing from next\r
884 //\r
885 PreviousIndex = Index + 1;\r
886\r
887 //\r
888 // We are at a narrow or wide character directive. Set attributes and strip it and print it\r
889 //\r
890 if (Buffer[Index] == NARROW_CHAR) {\r
891 //\r
892 // Preserve bits 0 - 6 and zero out the rest\r
893 //\r
894 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
895 Out->SetAttribute (Out, Out->Mode->Attribute);\r
896 CharWidth = 1;\r
897 } else {\r
898 //\r
899 // Must be wide, set bit 7 ON\r
900 //\r
901 Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;\r
902 Out->SetAttribute (Out, Out->Mode->Attribute);\r
903 CharWidth = 2;\r
904 }\r
905\r
906 Index++;\r
907\r
908 } while (Buffer[Index] != 0);\r
909\r
910 //\r
911 // We hit the end of the string - print it\r
912 //\r
913 Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
af047db7 914 Count = StrLen (&BackupBuffer[PreviousIndex]);\r
7c6c064c 915 PrintWidth += Count * CharWidth;\r
af047db7 916 TotalCount += Count;\r
7c6c064c
ED
917 if (PrintWidth < Width) {\r
918 Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
919 Out->SetAttribute (Out, Out->Mode->Attribute);\r
920 Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]);\r
921 }\r
922\r
923 FreePool (Buffer);\r
924 FreePool (BackupBuffer);\r
af047db7 925 return TotalCount;\r
7c6c064c
ED
926}\r
927\r
928/**\r
929 Prints a formatted unicode string to the default console, at\r
930 the supplied cursor position.\r
931\r
932 @param Width Width of String to be printed.\r
933 @param Column The cursor position to print the string at.\r
934 @param Row The cursor position to print the string at.\r
935 @param Fmt Format string.\r
936 @param ... Variable argument list for format string.\r
937\r
938 @return Length of string printed to the console\r
939\r
940**/\r
941UINTN\r
942EFIAPI\r
943PrintAt (\r
944 IN UINTN Width,\r
945 IN UINTN Column,\r
946 IN UINTN Row,\r
947 IN CHAR16 *Fmt,\r
948 ...\r
949 )\r
950{\r
951 VA_LIST Args;\r
952 UINTN LengthOfPrinted;\r
953\r
954 VA_START (Args, Fmt);\r
955 LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args);\r
956 VA_END (Args);\r
957 return LengthOfPrinted;\r
958}\r
959\r