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