]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Update FormBrowser to conform to UEFI spec Table 197. Callback Behavior for Cross...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for UI presentation.\r
3\r
6d3ea23f 4Copyright (c) 2004 - 2009, Intel Corporation\r
7936fb6a 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
16#include "Ui.h"\r
17\r
18BOOLEAN mHiiPackageListUpdated;\r
19UI_MENU_SELECTION *gCurrentSelection;\r
20\r
21\r
22/**\r
23 Clear retangle with specified text attribute.\r
24\r
25 @param LeftColumn Left column of retangle.\r
26 @param RightColumn Right column of retangle.\r
27 @param TopRow Start row of retangle.\r
28 @param BottomRow End row of retangle.\r
29 @param TextAttribute The character foreground and background.\r
30\r
31**/\r
32VOID\r
33ClearLines (\r
34 UINTN LeftColumn,\r
35 UINTN RightColumn,\r
36 UINTN TopRow,\r
37 UINTN BottomRow,\r
38 UINTN TextAttribute\r
39 )\r
40{\r
41 CHAR16 *Buffer;\r
42 UINTN Row;\r
43\r
44 //\r
45 // For now, allocate an arbitrarily long buffer\r
46 //\r
47 Buffer = AllocateZeroPool (0x10000);\r
48 ASSERT (Buffer != NULL);\r
49\r
50 //\r
51 // Set foreground and background as defined\r
52 //\r
53 gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\r
54\r
55 //\r
56 // Much faster to buffer the long string instead of print it a character at a time\r
57 //\r
58 SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\r
59\r
60 //\r
61 // Clear the desired area with the appropriate foreground/background\r
62 //\r
63 for (Row = TopRow; Row <= BottomRow; Row++) {\r
64 PrintStringAt (LeftColumn, Row, Buffer);\r
65 }\r
66\r
67 gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
68\r
f4113e1f 69 FreePool (Buffer);\r
7936fb6a 70 return ;\r
71}\r
72\r
73/**\r
74 Concatenate a narrow string to another string.\r
75\r
76 @param Destination The destination string.\r
77 @param Source The source string. The string to be concatenated.\r
78 to the end of Destination.\r
79\r
80**/\r
81VOID\r
82NewStrCat (\r
83 CHAR16 *Destination,\r
84 CHAR16 *Source\r
85 )\r
86{\r
87 UINTN Length;\r
88\r
89 for (Length = 0; Destination[Length] != 0; Length++)\r
90 ;\r
91\r
92 //\r
93 // We now have the length of the original string\r
94 // We can safely assume for now that we are concatenating a narrow value to this string.\r
95 // For instance, the string is "XYZ" and cat'ing ">"\r
96 // If this assumption changes, we need to make this routine a bit more complex\r
97 //\r
98 Destination[Length] = NARROW_CHAR;\r
99 Length++;\r
100\r
101 StrCpy (Destination + Length, Source);\r
102}\r
103\r
104/**\r
105 Count the storage space of a Unicode string.\r
106\r
107 This function handles the Unicode string with NARROW_CHAR\r
108 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
d66e6c16 109 does not count in the resultant output. If a WIDE_CHAR is\r
7936fb6a 110 hit, then 2 Unicode character will consume an output storage\r
111 space with size of CHAR16 till a NARROW_CHAR is hit.\r
112\r
113 @param String The input string to be counted.\r
114\r
115 @return Storage space for the input string.\r
116\r
117**/\r
118UINTN\r
119GetStringWidth (\r
120 CHAR16 *String\r
121 )\r
122{\r
123 UINTN Index;\r
124 UINTN Count;\r
125 UINTN IncrementValue;\r
126\r
127 Index = 0;\r
128 Count = 0;\r
129 IncrementValue = 1;\r
130\r
131 do {\r
132 //\r
133 // Advance to the null-terminator or to the first width directive\r
134 //\r
135 for (;\r
136 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
137 Index++, Count = Count + IncrementValue\r
138 )\r
139 ;\r
140\r
141 //\r
142 // We hit the null-terminator, we now have a count\r
143 //\r
144 if (String[Index] == 0) {\r
145 break;\r
146 }\r
147 //\r
148 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
149 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
150 //\r
151 if (String[Index] == NARROW_CHAR) {\r
152 //\r
153 // Skip to the next character\r
154 //\r
155 Index++;\r
156 IncrementValue = 1;\r
157 } else {\r
158 //\r
159 // Skip to the next character\r
160 //\r
161 Index++;\r
162 IncrementValue = 2;\r
163 }\r
164 } while (String[Index] != 0);\r
165\r
166 //\r
167 // Increment by one to include the null-terminator in the size\r
168 //\r
169 Count++;\r
170\r
171 return Count * sizeof (CHAR16);\r
172}\r
173\r
174/**\r
175 This function displays the page frame.\r
176\r
177**/\r
178VOID\r
179DisplayPageFrame (\r
180 VOID\r
181 )\r
182{\r
183 UINTN Index;\r
184 UINT8 Line;\r
185 UINT8 Alignment;\r
186 CHAR16 Character;\r
187 CHAR16 *Buffer;\r
188 CHAR16 *StrFrontPageBanner;\r
189 UINTN Row;\r
190 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
db0bd81c 191 UINT8 RowIdx;\r
192 UINT8 ColumnIdx;\r
7936fb6a 193\r
194 ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
195 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
196 ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
197\r
198 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
199\r
200 //\r
201 // For now, allocate an arbitrarily long buffer\r
202 //\r
203 Buffer = AllocateZeroPool (0x10000);\r
204 ASSERT (Buffer != NULL);\r
205\r
206 Character = BOXDRAW_HORIZONTAL;\r
207\r
208 for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
209 Buffer[Index] = Character;\r
210 }\r
211\r
0a1147ed 212 if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
7936fb6a 213 //\r
214 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
215 //\r
216 ClearLines (\r
217 LocalScreen.LeftColumn,\r
218 LocalScreen.RightColumn,\r
219 LocalScreen.TopRow,\r
220 FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
221 BANNER_TEXT | BANNER_BACKGROUND\r
222 );\r
223 //\r
224 // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
225 //\r
226 for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
227 //\r
228 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
229 //\r
230 for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
231 Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
232 Alignment++\r
233 ) {\r
89c18a1e 234 RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow);\r
235 ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn);\r
40a06b0c 236\r
237 ASSERT (RowIdx < BANNER_HEIGHT);\r
238 ASSERT (ColumnIdx < BANNER_COLUMNS);\r
d66e6c16 239\r
0a1147ed 240 if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
7936fb6a 241 StrFrontPageBanner = GetToken (\r
0a1147ed
LG
242 gBannerData->Banner[RowIdx][ColumnIdx],\r
243 gFrontPageHandle\r
7936fb6a 244 );\r
245 } else {\r
246 continue;\r
247 }\r
248\r
249 switch (Alignment - LocalScreen.LeftColumn) {\r
250 case 0:\r
251 //\r
252 // Handle left column\r
253 //\r
254 PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);\r
255 break;\r
256\r
257 case 1:\r
258 //\r
259 // Handle center column\r
260 //\r
261 PrintStringAt (\r
262 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
263 Line,\r
264 StrFrontPageBanner\r
265 );\r
266 break;\r
267\r
268 case 2:\r
269 //\r
270 // Handle right column\r
271 //\r
272 PrintStringAt (\r
273 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
274 Line,\r
275 StrFrontPageBanner\r
276 );\r
277 break;\r
278 }\r
279\r
f4113e1f 280 FreePool (StrFrontPageBanner);\r
7936fb6a 281 }\r
282 }\r
283 }\r
284\r
285 ClearLines (\r
286 LocalScreen.LeftColumn,\r
287 LocalScreen.RightColumn,\r
288 LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,\r
289 LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
290 KEYHELP_TEXT | KEYHELP_BACKGROUND\r
291 );\r
292\r
0a1147ed 293 if (gClassOfVfr != FORMSET_CLASS_FRONT_PAGE) {\r
7936fb6a 294 ClearLines (\r
295 LocalScreen.LeftColumn,\r
296 LocalScreen.RightColumn,\r
297 LocalScreen.TopRow,\r
298 LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
299 TITLE_TEXT | TITLE_BACKGROUND\r
300 );\r
301 //\r
302 // Print Top border line\r
303 // +------------------------------------------------------------------------------+\r
304 // ? ?\r
305 // +------------------------------------------------------------------------------+\r
306 //\r
307 Character = BOXDRAW_DOWN_RIGHT;\r
308\r
309 PrintChar (Character);\r
310 PrintString (Buffer);\r
311\r
312 Character = BOXDRAW_DOWN_LEFT;\r
313 PrintChar (Character);\r
314\r
315 Character = BOXDRAW_VERTICAL;\r
316 for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
317 PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
318 PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
319 }\r
320\r
321 Character = BOXDRAW_UP_RIGHT;\r
322 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
323 PrintString (Buffer);\r
324\r
325 Character = BOXDRAW_UP_LEFT;\r
326 PrintChar (Character);\r
327\r
0a1147ed 328 if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
7936fb6a 329 //\r
330 // Print Bottom border line\r
331 // +------------------------------------------------------------------------------+\r
332 // ? ?\r
333 // +------------------------------------------------------------------------------+\r
334 //\r
335 Character = BOXDRAW_DOWN_RIGHT;\r
336 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);\r
337\r
338 PrintString (Buffer);\r
339\r
340 Character = BOXDRAW_DOWN_LEFT;\r
341 PrintChar (Character);\r
342 Character = BOXDRAW_VERTICAL;\r
343 for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;\r
344 Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
345 Row++\r
346 ) {\r
347 PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
348 PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
349 }\r
350\r
351 Character = BOXDRAW_UP_RIGHT;\r
352 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
353\r
354 PrintString (Buffer);\r
355\r
356 Character = BOXDRAW_UP_LEFT;\r
357 PrintChar (Character);\r
358 }\r
359 }\r
360\r
f4113e1f 361 FreePool (Buffer);\r
7936fb6a 362\r
363}\r
364\r
365\r
366/**\r
367 Evaluate all expressions in a Form.\r
368\r
369 @param FormSet FormSet this Form belongs to.\r
370 @param Form The Form.\r
371\r
372 @retval EFI_SUCCESS The expression evaluated successfuly\r
373\r
374**/\r
375EFI_STATUS\r
376EvaluateFormExpressions (\r
377 IN FORM_BROWSER_FORMSET *FormSet,\r
378 IN FORM_BROWSER_FORM *Form\r
379 )\r
380{\r
381 EFI_STATUS Status;\r
382 LIST_ENTRY *Link;\r
383 FORM_EXPRESSION *Expression;\r
384\r
385 Link = GetFirstNode (&Form->ExpressionListHead);\r
386 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
387 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
388 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
389\r
390 if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
391 Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
392 //\r
393 // Postpone Form validation to Question editing or Form submiting\r
394 //\r
395 continue;\r
396 }\r
397\r
398 Status = EvaluateExpression (FormSet, Form, Expression);\r
399 if (EFI_ERROR (Status)) {\r
400 return Status;\r
401 }\r
402 }\r
403\r
404 return EFI_SUCCESS;\r
405}\r
406\r
407/*\r
408+------------------------------------------------------------------------------+\r
d66e6c16 409? Setup Page ?\r
7936fb6a 410+------------------------------------------------------------------------------+\r
411\r
412\r
413\r
414\r
415\r
416\r
417\r
418\r
419\r
420\r
421\r
422\r
423\r
424\r
425\r
426\r
427\r
428+------------------------------------------------------------------------------+\r
429?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?\r
430| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |\r
431+------------------------------------------------------------------------------+\r
432*/\r
433\r
434/**\r
435\r
d66e6c16 436\r
7936fb6a 437 Display form and wait for user to select one menu option, then return it.\r
d66e6c16 438\r
7936fb6a 439 @param Selection On input, Selection tell setup browser the information\r
440 about the Selection, form and formset to be displayed.\r
441 On output, Selection return the screen item that is selected\r
442 by user.\r
443 @retval EFI_SUCESSS This function always return successfully for now.\r
444\r
445**/\r
446EFI_STATUS\r
447DisplayForm (\r
448 IN OUT UI_MENU_SELECTION *Selection\r
449 )\r
450{\r
451 CHAR16 *StringPtr;\r
452 UINT16 MenuItemCount;\r
453 EFI_HII_HANDLE Handle;\r
454 BOOLEAN Suppress;\r
455 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
456 UINT16 Width;\r
457 UINTN ArrayEntry;\r
458 CHAR16 *OutputString;\r
459 LIST_ENTRY *Link;\r
460 FORM_BROWSER_STATEMENT *Statement;\r
461 UINT16 NumberOfLines;\r
462 EFI_STATUS Status;\r
463\r
464 Handle = Selection->Handle;\r
465 MenuItemCount = 0;\r
466 ArrayEntry = 0;\r
467 OutputString = NULL;\r
468\r
469 UiInitMenu ();\r
470\r
471 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
472\r
e8e36190 473 StringPtr = GetToken (Selection->Form->FormTitle, Handle);\r
7936fb6a 474\r
0a1147ed 475 if (gClassOfVfr != FORMSET_CLASS_FRONT_PAGE) {\r
7936fb6a 476 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
477 PrintStringAt (\r
478 (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
479 LocalScreen.TopRow + 1,\r
480 StringPtr\r
481 );\r
482 }\r
483\r
7936fb6a 484 //\r
485 // Remove Buffer allocated for StringPtr after it has been used.\r
486 //\r
f4113e1f 487 FreePool (StringPtr);\r
7936fb6a 488\r
489 //\r
490 // Evaluate all the Expressions in this Form\r
491 //\r
492 Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
493 if (EFI_ERROR (Status)) {\r
494 return Status;\r
495 }\r
496\r
497 Link = GetFirstNode (&Selection->Form->StatementListHead);\r
498 while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
499 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
500\r
501 if (Statement->SuppressExpression != NULL) {\r
502 Suppress = Statement->SuppressExpression->Result.Value.b;\r
503 } else {\r
504 Suppress = FALSE;\r
505 }\r
506\r
0a1147ed 507 if (Statement->DisableExpression != NULL) {\r
7da73676 508 Suppress = (BOOLEAN) (Suppress || Statement->DisableExpression->Result.Value.b);\r
0a1147ed
LG
509 }\r
510\r
7936fb6a 511 if (!Suppress) {\r
512 StringPtr = GetToken (Statement->Prompt, Handle);\r
513\r
514 Width = GetWidth (Statement, Handle);\r
515\r
516 NumberOfLines = 1;\r
517 ArrayEntry = 0;\r
518 for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
519 //\r
520 // If there is more string to process print on the next row and increment the Skip value\r
521 //\r
d1a54e2c 522 if (StrLen (&StringPtr[ArrayEntry]) != 0) {\r
7936fb6a 523 NumberOfLines++;\r
524 }\r
525\r
f4113e1f 526 FreePool (OutputString);\r
7936fb6a 527 }\r
528\r
529 //\r
530 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
531 // it in UiFreeMenu.\r
532 //\r
533 UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
534 MenuItemCount++;\r
535 }\r
536\r
537 Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
538 }\r
539\r
540 Status = UiDisplayMenu (Selection);\r
541\r
542 UiFreeMenu ();\r
543\r
544 return Status;\r
545}\r
546\r
547/**\r
548 Initialize the HII String Token to the correct values.\r
549\r
550**/\r
551VOID\r
552InitializeBrowserStrings (\r
553 VOID\r
554 )\r
555{\r
556 gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);\r
7936fb6a 557 gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
558 gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
559 gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
560 gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
8d00a0f1 561 gEnterEscapeString = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);\r
7936fb6a 562 gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
563 gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
564 gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
565 gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
566 gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
567 gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
568 gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
569 gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
570 gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
571 gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
572 gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
573 gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
574 gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
575 gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
576 gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
577 gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
578 gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
579 gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
580 gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
581 gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
582 gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
583 gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
ebe43565 584 gSaveChanges = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);\r
8d00a0f1 585 gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
7936fb6a 586 return ;\r
587}\r
588\r
589/**\r
590 Free up the resource allocated for all strings required\r
591 by Setup Browser.\r
592\r
593**/\r
594VOID\r
595FreeBrowserStrings (\r
596 VOID\r
597 )\r
598{\r
676df92c 599 FreePool (gFunctionOneString);\r
676df92c 600 FreePool (gFunctionNineString);\r
601 FreePool (gFunctionTenString);\r
602 FreePool (gEnterString);\r
603 FreePool (gEnterCommitString);\r
8d00a0f1 604 FreePool (gEnterEscapeString);\r
676df92c 605 FreePool (gEscapeString);\r
606 FreePool (gMoveHighlight);\r
607 FreePool (gMakeSelection);\r
608 FreePool (gDecNumericInput);\r
609 FreePool (gHexNumericInput);\r
610 FreePool (gToggleCheckBox);\r
611 FreePool (gPromptForData);\r
612 FreePool (gPromptForPassword);\r
613 FreePool (gPromptForNewPassword);\r
614 FreePool (gConfirmPassword);\r
615 FreePool (gPassowordInvalid);\r
616 FreePool (gConfirmError);\r
617 FreePool (gPressEnter);\r
618 FreePool (gEmptyString);\r
619 FreePool (gAreYouSure);\r
620 FreePool (gYesResponse);\r
621 FreePool (gNoResponse);\r
622 FreePool (gMiniString);\r
623 FreePool (gPlusString);\r
624 FreePool (gMinusString);\r
625 FreePool (gAdjustNumber);\r
626 FreePool (gSaveChanges);\r
8d00a0f1 627 FreePool (gOptionMismatch);\r
7936fb6a 628 return ;\r
629}\r
630\r
631\r
632/**\r
633 Update key's help imformation.\r
634\r
635 @param MenuOption The Menu option\r
636 @param Selected Whether or not a tag be selected\r
637\r
638**/\r
639VOID\r
640UpdateKeyHelp (\r
641 IN UI_MENU_OPTION *MenuOption,\r
642 IN BOOLEAN Selected\r
643 )\r
644{\r
645 UINTN SecCol;\r
646 UINTN ThdCol;\r
647 UINTN LeftColumnOfHelp;\r
648 UINTN RightColumnOfHelp;\r
649 UINTN TopRowOfHelp;\r
650 UINTN BottomRowOfHelp;\r
651 UINTN StartColumnOfHelp;\r
652 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
653 FORM_BROWSER_STATEMENT *Statement;\r
654\r
655 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
656\r
657 SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
658 ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;\r
659\r
660 StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
661 LeftColumnOfHelp = LocalScreen.LeftColumn + 1;\r
662 RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
663 TopRowOfHelp = LocalScreen.BottomRow - 4;\r
664 BottomRowOfHelp = LocalScreen.BottomRow - 3;\r
665\r
7936fb6a 666 gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
667\r
668 Statement = MenuOption->ThisTag;\r
669 switch (Statement->Operand) {\r
670 case EFI_IFR_ORDERED_LIST_OP:\r
671 case EFI_IFR_ONE_OF_OP:\r
672 case EFI_IFR_NUMERIC_OP:\r
673 case EFI_IFR_TIME_OP:\r
674 case EFI_IFR_DATE_OP:\r
675 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
676\r
677 if (!Selected) {\r
0a1147ed 678 if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
7936fb6a 679 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
680 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
681 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
682 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
683 }\r
684\r
685 if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
8d00a0f1 686 (Statement->Operand == EFI_IFR_TIME_OP)) {\r
7936fb6a 687 PrintAt (\r
688 StartColumnOfHelp,\r
689 BottomRowOfHelp,\r
690 L"%c%c%c%c%s",\r
691 ARROW_UP,\r
692 ARROW_DOWN,\r
693 ARROW_RIGHT,\r
694 ARROW_LEFT,\r
695 gMoveHighlight\r
696 );\r
697 PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
698 } else {\r
699 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
8d00a0f1 700 if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {\r
701 PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
702 } else {\r
703 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
704 }\r
7936fb6a 705 }\r
706 } else {\r
707 PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
708\r
709 //\r
710 // If it is a selected numeric with manual input, display different message\r
711 //\r
712 if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {\r
713 PrintStringAt (\r
714 SecCol,\r
715 TopRowOfHelp,\r
716 ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
717 );\r
718 } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
719 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
720 }\r
721\r
722 if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
723 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
724 PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
725 }\r
726\r
8d00a0f1 727 PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
7936fb6a 728 }\r
729 break;\r
730\r
731 case EFI_IFR_CHECKBOX_OP:\r
732 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
733\r
0a1147ed 734 if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
7936fb6a 735 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
736 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
737 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
738 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
739 }\r
740\r
741 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
742 PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
743 break;\r
744\r
745 case EFI_IFR_REF_OP:\r
746 case EFI_IFR_PASSWORD_OP:\r
747 case EFI_IFR_STRING_OP:\r
748 case EFI_IFR_TEXT_OP:\r
749 case EFI_IFR_ACTION_OP:\r
750 case EFI_IFR_RESET_BUTTON_OP:\r
751 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
752\r
753 if (!Selected) {\r
0a1147ed 754 if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
7936fb6a 755 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
756 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
757 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
758 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
759 }\r
760\r
761 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
762 if (Statement->Operand != EFI_IFR_TEXT_OP) {\r
763 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
764 }\r
765 } else {\r
766 if (Statement->Operand != EFI_IFR_REF_OP) {\r
767 PrintStringAt (\r
768 (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
769 BottomRowOfHelp,\r
770 gEnterCommitString\r
771 );\r
8d00a0f1 772 PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
7936fb6a 773 }\r
774 }\r
775 break;\r
776\r
777 default:\r
778 break;\r
779 }\r
780}\r
781\r
782/**\r
783 Functions which are registered to receive notification of\r
784 database events have this prototype. The actual event is encoded\r
785 in NotifyType. The following table describes how PackageType,\r
786 PackageGuid, Handle, and Package are used for each of the\r
787 notification types.\r
788\r
789 @param PackageType Package type of the notification.\r
790\r
791 @param PackageGuid If PackageType is\r
792 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
793 the pointer to the GUID from the Guid\r
794 field of EFI_HII_PACKAGE_GUID_HEADER.\r
795 Otherwise, it must be NULL.\r
796\r
797 @param Package Points to the package referred to by the\r
798 notification Handle The handle of the package\r
799 list which contains the specified package.\r
800\r
801 @param Handle The HII handle.\r
802\r
803 @param NotifyType The type of change concerning the\r
804 database. See\r
805 EFI_HII_DATABASE_NOTIFY_TYPE.\r
806\r
807**/\r
808EFI_STATUS\r
6d3ea23f 809EFIAPI\r
7936fb6a 810FormUpdateNotify (\r
811 IN UINT8 PackageType,\r
812 IN CONST EFI_GUID *PackageGuid,\r
813 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
814 IN EFI_HII_HANDLE Handle,\r
815 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
816 )\r
817{\r
818 mHiiPackageListUpdated = TRUE;\r
819\r
820 return EFI_SUCCESS;\r
821}\r
822\r
823/**\r
824 The worker function that send the displays to the screen. On output,\r
825 the selection made by user is returned.\r
826\r
827 @param Selection On input, Selection tell setup browser the information\r
828 about the Selection, form and formset to be displayed.\r
829 On output, Selection return the screen item that is selected\r
830 by user.\r
831\r
832 @retval EFI_SUCCESS The page is displayed successfully.\r
833 @return Other value if the page failed to be diplayed.\r
834\r
835**/\r
836EFI_STATUS\r
837SetupBrowser (\r
838 IN OUT UI_MENU_SELECTION *Selection\r
839 )\r
840{\r
841 EFI_STATUS Status;\r
842 LIST_ENTRY *Link;\r
843 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
844 EFI_HANDLE NotifyHandle;\r
845 EFI_HII_VALUE *HiiValue;\r
846 FORM_BROWSER_STATEMENT *Statement;\r
847 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
d66e6c16 848 FORM_BROWSER_FORMSET *FormSet;\r
7936fb6a 849\r
850 gMenuRefreshHead = NULL;\r
851 gResetRequired = FALSE;\r
d66e6c16 852 FormSet = Selection->FormSet;\r
7936fb6a 853\r
854 //\r
855 // Register notify for Form package update\r
856 //\r
857 Status = mHiiDatabase->RegisterPackageNotify (\r
858 mHiiDatabase,\r
8d00a0f1 859 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 860 NULL,\r
861 FormUpdateNotify,\r
862 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
863 &NotifyHandle\r
864 );\r
865 if (EFI_ERROR (Status)) {\r
866 return Status;\r
867 }\r
868\r
d66e6c16 869 //\r
870 // Initialize current settings of Questions in this FormSet\r
871 //\r
872 Status = InitializeCurrentSetting (Selection->FormSet);\r
873 if (EFI_ERROR (Status)) {\r
874 Selection->Action = UI_ACTION_EXIT;\r
875 goto Done;\r
876 }\r
877\r
7936fb6a 878 do {\r
7936fb6a 879 //\r
880 // Initialize Selection->Form\r
881 //\r
882 if (Selection->FormId == 0) {\r
883 //\r
884 // Zero FormId indicates display the first Form in a FormSet\r
885 //\r
886 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
887\r
888 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
889 Selection->FormId = Selection->Form->FormId;\r
890 } else {\r
891 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
892 }\r
893\r
0a1147ed
LG
894 if (Selection->Form == NULL) {\r
895 //\r
896 // No Form to display\r
897 //\r
898 return EFI_NOT_FOUND;\r
899 }\r
900\r
7936fb6a 901 //\r
902 // Load Questions' Value for display\r
903 //\r
d66e6c16 904 Status = LoadFormSetConfig (Selection->FormSet);\r
7936fb6a 905 if (EFI_ERROR (Status)) {\r
906 return Status;\r
907 }\r
908\r
d02847d3 909 //\r
910 // Displays the Header and Footer borders\r
911 //\r
912 DisplayPageFrame ();\r
913\r
7936fb6a 914 //\r
915 // Display form\r
916 //\r
917 Status = DisplayForm (Selection);\r
918 if (EFI_ERROR (Status)) {\r
919 return Status;\r
920 }\r
921\r
922 //\r
923 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
924 //\r
925 Statement = Selection->Statement;\r
926 if (Statement != NULL) {\r
927 if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
928 gResetRequired = TRUE;\r
929 }\r
930\r
931 //\r
932 // Reset FormPackage update flag\r
933 //\r
934 mHiiPackageListUpdated = FALSE;\r
935\r
936 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
937 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
938\r
939 HiiValue = &Statement->HiiValue;\r
940 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
941 //\r
942 // Create String in HII database for Configuration Driver to retrieve\r
943 //\r
944 HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
945 }\r
946\r
947 ConfigAccess = Selection->FormSet->ConfigAccess;\r
948 if (ConfigAccess == NULL) {\r
949 return EFI_UNSUPPORTED;\r
950 }\r
951 Status = ConfigAccess->Callback (\r
952 ConfigAccess,\r
953 EFI_BROWSER_ACTION_CHANGING,\r
954 Statement->QuestionId,\r
955 HiiValue->Type,\r
956 &HiiValue->Value,\r
957 &ActionRequest\r
958 );\r
959\r
960 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
961 //\r
962 // Clean the String in HII Database\r
963 //\r
964 DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
965 }\r
966\r
967 if (!EFI_ERROR (Status)) {\r
968 switch (ActionRequest) {\r
969 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
970 gResetRequired = TRUE;\r
971 break;\r
972\r
973 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
974 SubmitForm (Selection->FormSet, Selection->Form);\r
975 break;\r
976\r
977 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
978 Selection->Action = UI_ACTION_EXIT;\r
979 gNvUpdateRequired = FALSE;\r
980 break;\r
981\r
982 default:\r
983 break;\r
984 }\r
3dde743f 985 } else if (Status != EFI_UNSUPPORTED) {\r
986 //\r
987 // Callback return error status other than EFI_UNSUPPORTED\r
988 //\r
989 if (Statement->Operand == EFI_IFR_REF_OP) {\r
990 //\r
991 // Cross reference will not be taken\r
992 //\r
993 Selection->FormId = Selection->Form->FormId;\r
994 Selection->QuestionId = 0;\r
995 }\r
7936fb6a 996 }\r
997 }\r
998\r
999 //\r
1000 // Check whether Form Package has been updated during Callback\r
1001 //\r
1002 if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
1003 //\r
1004 // Force to reparse IFR binary of target Formset\r
1005 //\r
1006 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
1007 }\r
1008 }\r
1009 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
1010\r
d66e6c16 1011 //\r
1012 // Record the old formset\r
1013 //\r
1014 if (gOldFormSet != NULL) {\r
1015 DestroyFormSet (gOldFormSet);\r
1016 }\r
1017 gOldFormSet = FormSet;\r
1018\r
1019Done:\r
7936fb6a 1020 //\r
1021 // Unregister notify for Form package update\r
1022 //\r
1023 Status = mHiiDatabase->UnregisterPackageNotify (\r
1024 mHiiDatabase,\r
1025 NotifyHandle\r
1026 );\r
1027 return Status;\r
1028}\r