]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
Code and comments have been checked with spec.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Presentation.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for UI presentation.\r
3\r
8d00a0f1 4Copyright (c) 2004 - 2008, 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
69 gBS->FreePool (Buffer);\r
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
109 does not count in the resultant output. If a WIDE_CHAR is \r
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
191\r
192 ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
193 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
194 ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
195\r
196 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
197\r
198 //\r
199 // For now, allocate an arbitrarily long buffer\r
200 //\r
201 Buffer = AllocateZeroPool (0x10000);\r
202 ASSERT (Buffer != NULL);\r
203\r
204 Character = BOXDRAW_HORIZONTAL;\r
205\r
206 for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
207 Buffer[Index] = Character;\r
208 }\r
209\r
210 if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
211 //\r
212 // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
213 //\r
214 ClearLines (\r
215 LocalScreen.LeftColumn,\r
216 LocalScreen.RightColumn,\r
217 LocalScreen.TopRow,\r
218 FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
219 BANNER_TEXT | BANNER_BACKGROUND\r
220 );\r
221 //\r
222 // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
223 //\r
224 for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
225 //\r
226 // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
227 //\r
228 for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
229 Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
230 Alignment++\r
231 ) {\r
232 if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {\r
233 StrFrontPageBanner = GetToken (\r
234 BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],\r
235 FrontPageHandle\r
236 );\r
237 } else {\r
238 continue;\r
239 }\r
240\r
241 switch (Alignment - LocalScreen.LeftColumn) {\r
242 case 0:\r
243 //\r
244 // Handle left column\r
245 //\r
246 PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);\r
247 break;\r
248\r
249 case 1:\r
250 //\r
251 // Handle center column\r
252 //\r
253 PrintStringAt (\r
254 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
255 Line,\r
256 StrFrontPageBanner\r
257 );\r
258 break;\r
259\r
260 case 2:\r
261 //\r
262 // Handle right column\r
263 //\r
264 PrintStringAt (\r
265 LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
266 Line,\r
267 StrFrontPageBanner\r
268 );\r
269 break;\r
270 }\r
271\r
272 gBS->FreePool (StrFrontPageBanner);\r
273 }\r
274 }\r
275 }\r
276\r
277 ClearLines (\r
278 LocalScreen.LeftColumn,\r
279 LocalScreen.RightColumn,\r
280 LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,\r
281 LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
282 KEYHELP_TEXT | KEYHELP_BACKGROUND\r
283 );\r
284\r
285 if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
286 ClearLines (\r
287 LocalScreen.LeftColumn,\r
288 LocalScreen.RightColumn,\r
289 LocalScreen.TopRow,\r
290 LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
291 TITLE_TEXT | TITLE_BACKGROUND\r
292 );\r
293 //\r
294 // Print Top border line\r
295 // +------------------------------------------------------------------------------+\r
296 // ? ?\r
297 // +------------------------------------------------------------------------------+\r
298 //\r
299 Character = BOXDRAW_DOWN_RIGHT;\r
300\r
301 PrintChar (Character);\r
302 PrintString (Buffer);\r
303\r
304 Character = BOXDRAW_DOWN_LEFT;\r
305 PrintChar (Character);\r
306\r
307 Character = BOXDRAW_VERTICAL;\r
308 for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
309 PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
310 PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
311 }\r
312\r
313 Character = BOXDRAW_UP_RIGHT;\r
314 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
315 PrintString (Buffer);\r
316\r
317 Character = BOXDRAW_UP_LEFT;\r
318 PrintChar (Character);\r
319\r
320 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
321 //\r
322 // Print Bottom border line\r
323 // +------------------------------------------------------------------------------+\r
324 // ? ?\r
325 // +------------------------------------------------------------------------------+\r
326 //\r
327 Character = BOXDRAW_DOWN_RIGHT;\r
328 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);\r
329\r
330 PrintString (Buffer);\r
331\r
332 Character = BOXDRAW_DOWN_LEFT;\r
333 PrintChar (Character);\r
334 Character = BOXDRAW_VERTICAL;\r
335 for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;\r
336 Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
337 Row++\r
338 ) {\r
339 PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
340 PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
341 }\r
342\r
343 Character = BOXDRAW_UP_RIGHT;\r
344 PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
345\r
346 PrintString (Buffer);\r
347\r
348 Character = BOXDRAW_UP_LEFT;\r
349 PrintChar (Character);\r
350 }\r
351 }\r
352\r
353 gBS->FreePool (Buffer);\r
354\r
355}\r
356\r
357\r
358/**\r
359 Evaluate all expressions in a Form.\r
360\r
361 @param FormSet FormSet this Form belongs to.\r
362 @param Form The Form.\r
363\r
364 @retval EFI_SUCCESS The expression evaluated successfuly\r
365\r
366**/\r
367EFI_STATUS\r
368EvaluateFormExpressions (\r
369 IN FORM_BROWSER_FORMSET *FormSet,\r
370 IN FORM_BROWSER_FORM *Form\r
371 )\r
372{\r
373 EFI_STATUS Status;\r
374 LIST_ENTRY *Link;\r
375 FORM_EXPRESSION *Expression;\r
376\r
377 Link = GetFirstNode (&Form->ExpressionListHead);\r
378 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
379 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
380 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
381\r
382 if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
383 Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
384 //\r
385 // Postpone Form validation to Question editing or Form submiting\r
386 //\r
387 continue;\r
388 }\r
389\r
390 Status = EvaluateExpression (FormSet, Form, Expression);\r
391 if (EFI_ERROR (Status)) {\r
392 return Status;\r
393 }\r
394 }\r
395\r
396 return EFI_SUCCESS;\r
397}\r
398\r
399/*\r
400+------------------------------------------------------------------------------+\r
401?F2=Previous Page Setup Page ?\r
402+------------------------------------------------------------------------------+\r
403\r
404\r
405\r
406\r
407\r
408\r
409\r
410\r
411\r
412\r
413\r
414\r
415\r
416\r
417\r
418\r
419\r
420+------------------------------------------------------------------------------+\r
421?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?\r
422| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |\r
423+------------------------------------------------------------------------------+\r
424*/\r
425\r
426/**\r
427\r
428 \r
429 Display form and wait for user to select one menu option, then return it.\r
430 \r
431 @param Selection On input, Selection tell setup browser the information\r
432 about the Selection, form and formset to be displayed.\r
433 On output, Selection return the screen item that is selected\r
434 by user.\r
435 @retval EFI_SUCESSS This function always return successfully for now.\r
436\r
437**/\r
438EFI_STATUS\r
439DisplayForm (\r
440 IN OUT UI_MENU_SELECTION *Selection\r
441 )\r
442{\r
443 CHAR16 *StringPtr;\r
444 UINT16 MenuItemCount;\r
445 EFI_HII_HANDLE Handle;\r
446 BOOLEAN Suppress;\r
447 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
448 UINT16 Width;\r
449 UINTN ArrayEntry;\r
450 CHAR16 *OutputString;\r
451 LIST_ENTRY *Link;\r
452 FORM_BROWSER_STATEMENT *Statement;\r
453 UINT16 NumberOfLines;\r
454 EFI_STATUS Status;\r
455\r
456 Handle = Selection->Handle;\r
457 MenuItemCount = 0;\r
458 ArrayEntry = 0;\r
459 OutputString = NULL;\r
460\r
461 UiInitMenu ();\r
462\r
463 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
464\r
e8e36190 465 StringPtr = GetToken (Selection->Form->FormTitle, Handle);\r
7936fb6a 466\r
467 if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
468 gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
469 PrintStringAt (\r
470 (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
471 LocalScreen.TopRow + 1,\r
472 StringPtr\r
473 );\r
474 }\r
475\r
476 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
477 gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
478\r
479 //\r
480 // Display the infrastructure strings\r
481 //\r
482 if (!IsListEmpty (&gMenuList)) {\r
483 PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);\r
484 }\r
7936fb6a 485 }\r
486 //\r
487 // Remove Buffer allocated for StringPtr after it has been used.\r
488 //\r
489 gBS->FreePool (StringPtr);\r
490\r
491 //\r
492 // Evaluate all the Expressions in this Form\r
493 //\r
494 Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
495 if (EFI_ERROR (Status)) {\r
496 return Status;\r
497 }\r
498\r
499 Link = GetFirstNode (&Selection->Form->StatementListHead);\r
500 while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
501 Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
502\r
503 if (Statement->SuppressExpression != NULL) {\r
504 Suppress = Statement->SuppressExpression->Result.Value.b;\r
505 } else {\r
506 Suppress = FALSE;\r
507 }\r
508\r
509 if (!Suppress) {\r
510 StringPtr = GetToken (Statement->Prompt, Handle);\r
511\r
512 Width = GetWidth (Statement, Handle);\r
513\r
514 NumberOfLines = 1;\r
515 ArrayEntry = 0;\r
516 for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
517 //\r
518 // If there is more string to process print on the next row and increment the Skip value\r
519 //\r
520 if (StrLen (&StringPtr[ArrayEntry])) {\r
521 NumberOfLines++;\r
522 }\r
523\r
524 gBS->FreePool (OutputString);\r
525 }\r
526\r
527 //\r
528 // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
529 // it in UiFreeMenu.\r
530 //\r
531 UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
532 MenuItemCount++;\r
533 }\r
534\r
535 Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
536 }\r
537\r
538 Status = UiDisplayMenu (Selection);\r
539\r
540 UiFreeMenu ();\r
541\r
542 return Status;\r
543}\r
544\r
545/**\r
546 Initialize the HII String Token to the correct values.\r
547\r
548**/\r
549VOID\r
550InitializeBrowserStrings (\r
551 VOID\r
552 )\r
553{\r
554 gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);\r
555 gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);\r
556 gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
557 gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
558 gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
559 gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
8d00a0f1 560 gEnterEscapeString = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);\r
7936fb6a 561 gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
562 gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
563 gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
564 gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
565 gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
566 gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
567 gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
568 gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
569 gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
570 gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
571 gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
572 gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
573 gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
574 gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
575 gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
576 gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
577 gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
578 gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
579 gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
580 gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
581 gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
582 gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
ebe43565 583 gSaveChanges = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);\r
8d00a0f1 584 gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
7936fb6a 585 return ;\r
586}\r
587\r
588/**\r
589 Free up the resource allocated for all strings required\r
590 by Setup Browser.\r
591\r
592**/\r
593VOID\r
594FreeBrowserStrings (\r
595 VOID\r
596 )\r
597{\r
676df92c 598 FreePool (gFunctionOneString);\r
599 FreePool (gFunctionTwoString);\r
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
666 if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {\r
667 return ;\r
668 }\r
669\r
670 gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
671\r
672 Statement = MenuOption->ThisTag;\r
673 switch (Statement->Operand) {\r
674 case EFI_IFR_ORDERED_LIST_OP:\r
675 case EFI_IFR_ONE_OF_OP:\r
676 case EFI_IFR_NUMERIC_OP:\r
677 case EFI_IFR_TIME_OP:\r
678 case EFI_IFR_DATE_OP:\r
679 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
680\r
681 if (!Selected) {\r
682 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
683 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
684 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
685 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
686 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
687 }\r
688\r
689 if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
8d00a0f1 690 (Statement->Operand == EFI_IFR_TIME_OP)) {\r
7936fb6a 691 PrintAt (\r
692 StartColumnOfHelp,\r
693 BottomRowOfHelp,\r
694 L"%c%c%c%c%s",\r
695 ARROW_UP,\r
696 ARROW_DOWN,\r
697 ARROW_RIGHT,\r
698 ARROW_LEFT,\r
699 gMoveHighlight\r
700 );\r
701 PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
702 } else {\r
703 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
8d00a0f1 704 if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {\r
705 PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
706 } else {\r
707 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
708 }\r
7936fb6a 709 }\r
710 } else {\r
711 PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
712\r
713 //\r
714 // If it is a selected numeric with manual input, display different message\r
715 //\r
716 if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {\r
717 PrintStringAt (\r
718 SecCol,\r
719 TopRowOfHelp,\r
720 ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
721 );\r
722 } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
723 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
724 }\r
725\r
726 if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
727 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
728 PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
729 }\r
730\r
8d00a0f1 731 PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
7936fb6a 732 }\r
733 break;\r
734\r
735 case EFI_IFR_CHECKBOX_OP:\r
736 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
737\r
738 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
739 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
740 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
741 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
742 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
743 }\r
744\r
745 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
746 PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
747 break;\r
748\r
749 case EFI_IFR_REF_OP:\r
750 case EFI_IFR_PASSWORD_OP:\r
751 case EFI_IFR_STRING_OP:\r
752 case EFI_IFR_TEXT_OP:\r
753 case EFI_IFR_ACTION_OP:\r
754 case EFI_IFR_RESET_BUTTON_OP:\r
755 ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
756\r
757 if (!Selected) {\r
758 if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
759 PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
760 PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
761 PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
762 PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
763 }\r
764\r
765 PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
766 if (Statement->Operand != EFI_IFR_TEXT_OP) {\r
767 PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
768 }\r
769 } else {\r
770 if (Statement->Operand != EFI_IFR_REF_OP) {\r
771 PrintStringAt (\r
772 (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
773 BottomRowOfHelp,\r
774 gEnterCommitString\r
775 );\r
8d00a0f1 776 PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
7936fb6a 777 }\r
778 }\r
779 break;\r
780\r
781 default:\r
782 break;\r
783 }\r
784}\r
785\r
786/**\r
787 Functions which are registered to receive notification of\r
788 database events have this prototype. The actual event is encoded\r
789 in NotifyType. The following table describes how PackageType,\r
790 PackageGuid, Handle, and Package are used for each of the\r
791 notification types.\r
792\r
793 @param PackageType Package type of the notification.\r
794\r
795 @param PackageGuid If PackageType is\r
796 EFI_HII_PACKAGE_TYPE_GUID, then this is\r
797 the pointer to the GUID from the Guid\r
798 field of EFI_HII_PACKAGE_GUID_HEADER.\r
799 Otherwise, it must be NULL.\r
800\r
801 @param Package Points to the package referred to by the\r
802 notification Handle The handle of the package\r
803 list which contains the specified package.\r
804\r
805 @param Handle The HII handle.\r
806\r
807 @param NotifyType The type of change concerning the\r
808 database. See\r
809 EFI_HII_DATABASE_NOTIFY_TYPE.\r
810\r
811**/\r
812EFI_STATUS\r
813FormUpdateNotify (\r
814 IN UINT8 PackageType,\r
815 IN CONST EFI_GUID *PackageGuid,\r
816 IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
817 IN EFI_HII_HANDLE Handle,\r
818 IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
819 )\r
820{\r
821 mHiiPackageListUpdated = TRUE;\r
822\r
823 return EFI_SUCCESS;\r
824}\r
825\r
826/**\r
827 The worker function that send the displays to the screen. On output,\r
828 the selection made by user is returned.\r
829\r
830 @param Selection On input, Selection tell setup browser the information\r
831 about the Selection, form and formset to be displayed.\r
832 On output, Selection return the screen item that is selected\r
833 by user.\r
834\r
835 @retval EFI_SUCCESS The page is displayed successfully.\r
836 @return Other value if the page failed to be diplayed.\r
837\r
838**/\r
839EFI_STATUS\r
840SetupBrowser (\r
841 IN OUT UI_MENU_SELECTION *Selection\r
842 )\r
843{\r
844 EFI_STATUS Status;\r
845 LIST_ENTRY *Link;\r
846 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
847 EFI_HANDLE NotifyHandle;\r
848 EFI_HII_VALUE *HiiValue;\r
849 FORM_BROWSER_STATEMENT *Statement;\r
850 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
ebe43565 851 EFI_INPUT_KEY Key;\r
852 CHAR16 YesResponse;\r
853 CHAR16 NoResponse;\r
7936fb6a 854\r
855 gMenuRefreshHead = NULL;\r
856 gResetRequired = FALSE;\r
857 gNvUpdateRequired = FALSE;\r
858\r
859 UiInitMenuList ();\r
860\r
861 //\r
862 // Register notify for Form package update\r
863 //\r
864 Status = mHiiDatabase->RegisterPackageNotify (\r
865 mHiiDatabase,\r
8d00a0f1 866 EFI_HII_PACKAGE_FORMS,\r
7936fb6a 867 NULL,\r
868 FormUpdateNotify,\r
869 EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
870 &NotifyHandle\r
871 );\r
872 if (EFI_ERROR (Status)) {\r
873 return Status;\r
874 }\r
875\r
876 do {\r
877 //\r
878 // Displays the Header and Footer borders\r
879 //\r
880 DisplayPageFrame ();\r
881\r
882 //\r
883 // Initialize Selection->Form\r
884 //\r
885 if (Selection->FormId == 0) {\r
886 //\r
887 // Zero FormId indicates display the first Form in a FormSet\r
888 //\r
889 Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
890\r
891 Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
892 Selection->FormId = Selection->Form->FormId;\r
893 } else {\r
894 Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
895 }\r
896\r
897 //\r
898 // Load Questions' Value for display\r
899 //\r
900 Status = LoadFormConfig (Selection->FormSet, Selection->Form);\r
901 if (EFI_ERROR (Status)) {\r
902 return Status;\r
903 }\r
904\r
905 //\r
906 // Display form\r
907 //\r
908 Status = DisplayForm (Selection);\r
909 if (EFI_ERROR (Status)) {\r
910 return Status;\r
911 }\r
912\r
913 //\r
914 // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
915 //\r
916 Statement = Selection->Statement;\r
917 if (Statement != NULL) {\r
918 if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
919 gResetRequired = TRUE;\r
920 }\r
921\r
922 //\r
923 // Reset FormPackage update flag\r
924 //\r
925 mHiiPackageListUpdated = FALSE;\r
926\r
927 if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
928 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
929\r
930 HiiValue = &Statement->HiiValue;\r
931 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
932 //\r
933 // Create String in HII database for Configuration Driver to retrieve\r
934 //\r
935 HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
936 }\r
937\r
938 ConfigAccess = Selection->FormSet->ConfigAccess;\r
939 if (ConfigAccess == NULL) {\r
940 return EFI_UNSUPPORTED;\r
941 }\r
942 Status = ConfigAccess->Callback (\r
943 ConfigAccess,\r
944 EFI_BROWSER_ACTION_CHANGING,\r
945 Statement->QuestionId,\r
946 HiiValue->Type,\r
947 &HiiValue->Value,\r
948 &ActionRequest\r
949 );\r
950\r
951 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
952 //\r
953 // Clean the String in HII Database\r
954 //\r
955 DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
956 }\r
957\r
958 if (!EFI_ERROR (Status)) {\r
959 switch (ActionRequest) {\r
960 case EFI_BROWSER_ACTION_REQUEST_RESET:\r
961 gResetRequired = TRUE;\r
962 break;\r
963\r
964 case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
965 SubmitForm (Selection->FormSet, Selection->Form);\r
966 break;\r
967\r
968 case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
969 Selection->Action = UI_ACTION_EXIT;\r
970 gNvUpdateRequired = FALSE;\r
971 break;\r
972\r
973 default:\r
974 break;\r
975 }\r
976 }\r
977 }\r
978\r
979 //\r
980 // Check whether Form Package has been updated during Callback\r
981 //\r
982 if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
983 //\r
984 // Force to reparse IFR binary of target Formset\r
985 //\r
986 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
ebe43565 987\r
988 //\r
989 // Uncommitted data will be lost after IFR binary re-pasing, so confirm on whether to save\r
990 //\r
991 if (gNvUpdateRequired) {\r
992 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
993\r
994 YesResponse = gYesResponse[0];\r
995 NoResponse = gNoResponse[0];\r
996\r
997 do {\r
998 CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gEmptyString);\r
999 } while\r
1000 (\r
1001 (Key.ScanCode != SCAN_ESC) &&\r
1002 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
1003 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
1004 );\r
1005\r
1006 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
1007 //\r
1008 // If the user hits the YesResponse key\r
1009 //\r
1010 SubmitForm (Selection->FormSet, Selection->Form);\r
1011 }\r
1012 }\r
7936fb6a 1013 }\r
1014 }\r
1015 } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
1016\r
1017 //\r
1018 // Unregister notify for Form package update\r
1019 //\r
1020 Status = mHiiDatabase->UnregisterPackageNotify (\r
1021 mHiiDatabase,\r
1022 NotifyHandle\r
1023 );\r
1024 return Status;\r
1025}\r