2 Entry and initialization module for the browser.
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
5 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
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.
15 #include "FormDisplay.h"
18 // Search table for UiDisplayMenu()
20 SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation
[] = {
51 UINTN mScanCodeNumber
= sizeof (gScanCodeToOperation
) / sizeof (gScanCodeToOperation
[0]);
53 SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag
[] = {
96 EFI_GUID gDisplayEngineGuid
= {
97 0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62}
100 FORM_ENTRY_INFO gFormEntryInfo
;
102 EFI_SCREEN_DESCRIPTOR gStatementDimensions
;
103 BOOLEAN mStatementLayoutIsChanged
= TRUE
;
104 USER_INPUT
*gUserInput
;
105 FORM_DISPLAY_ENGINE_FORM
*gFormData
;
106 EFI_HII_HANDLE gHiiHandle
;
108 LIST_ENTRY gMenuOption
;
109 DISPLAY_HIGHLIGHT_MENU_INFO gHighligthMenuInfo
= {0};
110 BOOLEAN mIsFirstForm
= TRUE
;
111 FORM_ENTRY_INFO gOldFormEntry
= {0};
114 // Browser Global Strings
116 CHAR16
*gFormNotFound
;
118 CHAR16
*gBrwoserError
;
120 CHAR16
*gPromptForData
;
121 CHAR16
*gPromptForPassword
;
122 CHAR16
*gPromptForNewPassword
;
123 CHAR16
*gConfirmPassword
;
124 CHAR16
*gConfirmError
;
125 CHAR16
*gPassowordInvalid
;
127 CHAR16
*gEmptyString
;
129 CHAR16
*gOptionMismatch
;
130 CHAR16
*gFormSuppress
;
131 CHAR16
*gProtocolNotFound
;
133 CHAR16 gModalSkipColumn
;
134 CHAR16 gPromptBlockWidth
;
135 CHAR16 gOptionBlockWidth
;
136 CHAR16 gHelpBlockWidth
;
137 CHAR16
*mUnknownString
;
139 FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData
= {
140 FORM_DISPLAY_DRIVER_SIGNATURE
,
144 DriverClearDisplayPage
,
151 Get the string based on the StringId and HII Package List Handle.
153 @param Token The String's ID.
154 @param HiiHandle The package list in the HII database to search for
155 the specified string.
157 @return The output string.
162 IN EFI_STRING_ID Token
,
163 IN EFI_HII_HANDLE HiiHandle
168 String
= HiiGetString (HiiHandle
, Token
, NULL
);
169 if (String
== NULL
) {
170 String
= AllocateCopyPool (StrSize (mUnknownString
), mUnknownString
);
171 ASSERT (String
!= NULL
);
174 return (CHAR16
*) String
;
179 Initialize the HII String Token to the correct values.
183 InitializeDisplayStrings (
187 mUnknownString
= GetToken (STRING_TOKEN (UNKNOWN_STRING
), gHiiHandle
);
188 gSaveFailed
= GetToken (STRING_TOKEN (SAVE_FAILED
), gHiiHandle
);
189 gPromptForData
= GetToken (STRING_TOKEN (PROMPT_FOR_DATA
), gHiiHandle
);
190 gPromptForPassword
= GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD
), gHiiHandle
);
191 gPromptForNewPassword
= GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD
), gHiiHandle
);
192 gConfirmPassword
= GetToken (STRING_TOKEN (CONFIRM_PASSWORD
), gHiiHandle
);
193 gConfirmError
= GetToken (STRING_TOKEN (CONFIRM_ERROR
), gHiiHandle
);
194 gPassowordInvalid
= GetToken (STRING_TOKEN (PASSWORD_INVALID
), gHiiHandle
);
195 gPressEnter
= GetToken (STRING_TOKEN (PRESS_ENTER
), gHiiHandle
);
196 gEmptyString
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
197 gMiniString
= GetToken (STRING_TOKEN (MINI_STRING
), gHiiHandle
);
198 gOptionMismatch
= GetToken (STRING_TOKEN (OPTION_MISMATCH
), gHiiHandle
);
199 gFormSuppress
= GetToken (STRING_TOKEN (FORM_SUPPRESSED
), gHiiHandle
);
200 gProtocolNotFound
= GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND
), gHiiHandle
);
201 gFormNotFound
= GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND
), gHiiHandle
);
202 gNoSubmitIf
= GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF
), gHiiHandle
);
203 gBrwoserError
= GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR
), gHiiHandle
);
207 Free up the resource allocated for all strings required
216 FreePool (mUnknownString
);
217 FreePool (gEmptyString
);
218 FreePool (gSaveFailed
);
219 FreePool (gPromptForData
);
220 FreePool (gPromptForPassword
);
221 FreePool (gPromptForNewPassword
);
222 FreePool (gConfirmPassword
);
223 FreePool (gConfirmError
);
224 FreePool (gPassowordInvalid
);
225 FreePool (gPressEnter
);
226 FreePool (gMiniString
);
227 FreePool (gOptionMismatch
);
228 FreePool (gFormSuppress
);
229 FreePool (gProtocolNotFound
);
230 FreePool (gBrwoserError
);
231 FreePool (gNoSubmitIf
);
232 FreePool (gFormNotFound
);
236 Get prompt string id from the opcode data buffer.
238 @param OpCode The input opcode buffer.
240 @return The prompt string id.
245 IN EFI_IFR_OP_HEADER
*OpCode
248 EFI_IFR_STATEMENT_HEADER
*Header
;
250 if (OpCode
->Length
<= sizeof (EFI_IFR_OP_HEADER
)) {
254 Header
= (EFI_IFR_STATEMENT_HEADER
*) (OpCode
+ 1);
256 return Header
->Prompt
;
260 Get the supported width for a particular op-code
262 @param Statement The curent statement.
263 @param AdjustWidth The width which is saved for the space.
265 @return Returns the number of CHAR16 characters that is support.
270 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
271 OUT UINT16
*AdjustWidth
276 EFI_IFR_TEXT
*TestOp
;
279 // For modal form, clean the entire row.
281 if ((gFormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
282 if (AdjustWidth
!= NULL
) {
283 *AdjustWidth
= LEFT_SKIPPED_COLUMNS
;
285 return (UINT16
)(gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
- 2 * (gModalSkipColumn
+ LEFT_SKIPPED_COLUMNS
));
291 // See if the second text parameter is really NULL
293 if (Statement
->OpCode
->OpCode
== EFI_IFR_TEXT_OP
) {
294 TestOp
= (EFI_IFR_TEXT
*) Statement
->OpCode
;
295 if (TestOp
->TextTwo
!= 0) {
296 String
= GetToken (TestOp
->TextTwo
, gFormData
->HiiHandle
);
297 Size
= StrLen (String
);
302 if ((Statement
->OpCode
->OpCode
== EFI_IFR_SUBTITLE_OP
) ||
303 (Statement
->OpCode
->OpCode
== EFI_IFR_REF_OP
) ||
304 (Statement
->OpCode
->OpCode
== EFI_IFR_PASSWORD_OP
) ||
305 (Statement
->OpCode
->OpCode
== EFI_IFR_ACTION_OP
) ||
306 (Statement
->OpCode
->OpCode
== EFI_IFR_RESET_BUTTON_OP
) ||
308 // Allow a wide display if text op-code and no secondary text op-code
310 ((Statement
->OpCode
->OpCode
== EFI_IFR_TEXT_OP
) && (Size
== 0))
314 // Return the space width.
316 if (AdjustWidth
!= NULL
) {
320 // Keep consistent with current behavior.
322 return (UINT16
) (gPromptBlockWidth
+ gOptionBlockWidth
- 2);
325 if (AdjustWidth
!= NULL
) {
328 return (UINT16
) (gPromptBlockWidth
- 1);
332 Will copy LineWidth amount of a string in the OutputString buffer and return the
333 number of CHAR16 characters that were copied into the OutputString buffer.
334 The output string format is:
335 Glyph Info + String info + '\0'.
337 In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
339 @param InputString String description for this option.
340 @param LineWidth Width of the desired string to extract in CHAR16
342 @param GlyphWidth The glyph width of the begin of the char in the string.
343 @param Index Where in InputString to start the copy process
344 @param OutputString Buffer to copy the string into
346 @return Returns the number of CHAR16 characters that were copied into the OutputString
347 buffer, include extra glyph info and '\0' info.
352 IN CHAR16
*InputString
,
354 IN OUT UINT16
*GlyphWidth
,
356 OUT CHAR16
**OutputString
361 UINT16 OriginalGlyphWidth
;
363 UINT16 LastSpaceOffset
;
364 UINT16 LastGlyphWidth
;
366 if (InputString
== NULL
|| Index
== NULL
|| OutputString
== NULL
) {
370 if (LineWidth
== 0 || *GlyphWidth
== 0) {
375 // Save original glyph width.
377 OriginalGlyphWidth
= *GlyphWidth
;
378 LastGlyphWidth
= OriginalGlyphWidth
;
383 // NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.
384 // To avoid displaying this empty line in screen, just skip the two CHARs here.
386 if ((InputString
[*Index
] == NARROW_CHAR
) && (InputString
[*Index
+ 1] == CHAR_CARRIAGE_RETURN
)) {
391 // Fast-forward the string and see if there is a carriage-return in the string
393 for (StrOffset
= 0, GlyphOffset
= 0; GlyphOffset
<= LineWidth
; StrOffset
++) {
394 switch (InputString
[*Index
+ StrOffset
]) {
403 case CHAR_CARRIAGE_RETURN
:
410 GlyphOffset
= GlyphOffset
+ *GlyphWidth
;
413 // Record the last space info in this line. Will be used in rewind.
415 if ((InputString
[*Index
+ StrOffset
] == CHAR_SPACE
) && (GlyphOffset
<= LineWidth
)) {
416 LastSpaceOffset
= StrOffset
;
417 LastGlyphWidth
= *GlyphWidth
;
428 // Rewind the string from the maximum size until we see a space to break the line
430 if (GlyphOffset
> LineWidth
) {
432 // Rewind the string to last space char in this line.
434 if (LastSpaceOffset
!= 0) {
435 StrOffset
= LastSpaceOffset
;
436 *GlyphWidth
= LastGlyphWidth
;
439 // Roll back to last char in the line width.
446 // The CHAR_NULL has process last time, this time just return 0 to stand for the end.
448 if (StrOffset
== 0 && (InputString
[*Index
+ StrOffset
] == CHAR_NULL
)) {
453 // Need extra glyph info and '\0' info, so +2.
455 *OutputString
= AllocateZeroPool (((UINTN
) (StrOffset
+ 2) * sizeof(CHAR16
)));
456 if (*OutputString
== NULL
) {
461 // Save the glyph info at the begin of the string, will used by Print function.
463 if (OriginalGlyphWidth
== 1) {
464 *(*OutputString
) = NARROW_CHAR
;
466 *(*OutputString
) = WIDE_CHAR
;
469 CopyMem ((*OutputString
) + 1, &InputString
[*Index
], StrOffset
* sizeof(CHAR16
));
471 if (InputString
[*Index
+ StrOffset
] == CHAR_SPACE
) {
473 // Skip the space info at the begin of next line.
475 *Index
= (UINT16
) (*Index
+ StrOffset
+ 1);
476 } else if (InputString
[*Index
+ StrOffset
] == CHAR_LINEFEED
) {
478 // Skip the /n or /n/r info.
480 if (InputString
[*Index
+ StrOffset
+ 1] == CHAR_CARRIAGE_RETURN
) {
481 *Index
= (UINT16
) (*Index
+ StrOffset
+ 2);
483 *Index
= (UINT16
) (*Index
+ StrOffset
+ 1);
485 } else if (InputString
[*Index
+ StrOffset
] == CHAR_CARRIAGE_RETURN
) {
487 // Skip the /r or /r/n info.
489 if (InputString
[*Index
+ StrOffset
+ 1] == CHAR_LINEFEED
) {
490 *Index
= (UINT16
) (*Index
+ StrOffset
+ 2);
492 *Index
= (UINT16
) (*Index
+ StrOffset
+ 1);
495 *Index
= (UINT16
) (*Index
+ StrOffset
);
499 // Include extra glyph info and '\0' info, so +2.
501 return StrOffset
+ 2;
505 Add one menu option by specified description and context.
507 @param Statement Statement of this Menu Option.
508 @param MenuItemCount The index for this Option in the Menu.
509 @param NestIn Whether this statement is nest in another statement.
514 IN FORM_DISPLAY_ENGINE_STATEMENT
*Statement
,
515 IN UINT16
*MenuItemCount
,
519 UI_MENU_OPTION
*MenuOption
;
523 UINT16 NumberOfLines
;
527 CHAR16
*OutputString
;
528 EFI_STRING_ID PromptId
;
536 PromptId
= GetPrompt (Statement
->OpCode
);
537 ASSERT (PromptId
!= 0);
539 String
= GetToken (PromptId
, gFormData
->HiiHandle
);
540 ASSERT (String
!= NULL
);
542 Width
= GetWidth (Statement
, NULL
);
543 for (; GetLineByWidth (String
, Width
, &GlyphWidth
,&ArrayEntry
, &OutputString
) != 0x0000;) {
545 // If there is more string to process print on the next row and increment the Skip value
547 if (StrLen (&String
[ArrayEntry
]) != 0) {
550 FreePool (OutputString
);
553 if (Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
|| Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) {
555 // Add three MenuOptions for Date/Time
556 // Data format : [01/02/2004] [11:22:33]
557 // Line number : 0 0 1 0 0 1
563 for (Index
= 0; Index
< Count
; Index
++) {
564 MenuOption
= AllocateZeroPool (sizeof (UI_MENU_OPTION
));
567 MenuOption
->Signature
= UI_MENU_OPTION_SIGNATURE
;
568 MenuOption
->Description
= String
;
569 MenuOption
->Handle
= gFormData
->HiiHandle
;
570 MenuOption
->ThisTag
= Statement
;
571 MenuOption
->NestInStatement
= NestIn
;
572 MenuOption
->EntryNumber
= *MenuItemCount
;
576 // Override LineNumber for the MenuOption in Date/Time sequence
578 MenuOption
->Skip
= 1;
580 MenuOption
->Skip
= NumberOfLines
;
582 MenuOption
->Sequence
= Index
;
584 if ((Statement
->Attribute
& HII_DISPLAY_GRAYOUT
) != 0) {
585 MenuOption
->GrayOut
= TRUE
;
587 MenuOption
->GrayOut
= FALSE
;
590 if ((Statement
->Attribute
& HII_DISPLAY_LOCK
) != 0 || (gFormData
->Attribute
& HII_DISPLAY_LOCK
) != 0) {
591 MenuOption
->GrayOut
= TRUE
;
595 // If the form or the question has the lock attribute, deal same as grayout.
597 if ((gFormData
->Attribute
& HII_DISPLAY_LOCK
) != 0 || (Statement
->Attribute
& HII_DISPLAY_LOCK
) != 0) {
598 MenuOption
->GrayOut
= TRUE
;
601 switch (Statement
->OpCode
->OpCode
) {
602 case EFI_IFR_ORDERED_LIST_OP
:
603 case EFI_IFR_ONE_OF_OP
:
604 case EFI_IFR_NUMERIC_OP
:
605 case EFI_IFR_TIME_OP
:
606 case EFI_IFR_DATE_OP
:
607 case EFI_IFR_CHECKBOX_OP
:
608 case EFI_IFR_PASSWORD_OP
:
609 case EFI_IFR_STRING_OP
:
611 // User could change the value of these items
613 MenuOption
->IsQuestion
= TRUE
;
615 case EFI_IFR_TEXT_OP
:
616 if (FeaturePcdGet (PcdBrowserGrayOutTextStatement
)) {
618 // Initializing GrayOut option as TRUE for Text setup options
619 // so that those options will be Gray in colour and un selectable.
621 MenuOption
->GrayOut
= TRUE
;
625 MenuOption
->IsQuestion
= FALSE
;
629 if ((Statement
->Attribute
& HII_DISPLAY_READONLY
) != 0) {
630 MenuOption
->ReadOnly
= TRUE
;
631 if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu
)) {
632 MenuOption
->GrayOut
= TRUE
;
636 InsertTailList (&gMenuOption
, &MenuOption
->Link
);
643 Create the menu list base on the form data info.
647 ConvertStatementToMenu (
651 UINT16 MenuItemCount
;
653 LIST_ENTRY
*NestLink
;
654 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
655 FORM_DISPLAY_ENGINE_STATEMENT
*NestStatement
;
658 InitializeListHead (&gMenuOption
);
660 Link
= GetFirstNode (&gFormData
->StatementListHead
);
661 while (!IsNull (&gFormData
->StatementListHead
, Link
)) {
662 Statement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link
);
663 Link
= GetNextNode (&gFormData
->StatementListHead
, Link
);
666 // Skip the opcode not recognized by Display core.
668 if (Statement
->OpCode
->OpCode
== EFI_IFR_GUID_OP
) {
672 UiAddMenuOption (Statement
, &MenuItemCount
, FALSE
);
675 // Check the statement nest in this host statement.
677 NestLink
= GetFirstNode (&Statement
->NestStatementList
);
678 while (!IsNull (&Statement
->NestStatementList
, NestLink
)) {
679 NestStatement
= FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink
);
680 NestLink
= GetNextNode (&Statement
->NestStatementList
, NestLink
);
682 UiAddMenuOption (NestStatement
, &MenuItemCount
, TRUE
);
688 Count the storage space of a Unicode string.
690 This function handles the Unicode string with NARROW_CHAR
691 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
692 does not count in the resultant output. If a WIDE_CHAR is
693 hit, then 2 Unicode character will consume an output storage
694 space with size of CHAR16 till a NARROW_CHAR is hit.
696 If String is NULL, then ASSERT ().
698 @param String The input string to be counted.
700 @return Storage space for the input string.
710 UINTN IncrementValue
;
712 ASSERT (String
!= NULL
);
713 if (String
== NULL
) {
723 // Advance to the null-terminator or to the first width directive
726 (String
[Index
] != NARROW_CHAR
) && (String
[Index
] != WIDE_CHAR
) && (String
[Index
] != 0);
727 Index
++, Count
= Count
+ IncrementValue
732 // We hit the null-terminator, we now have a count
734 if (String
[Index
] == 0) {
738 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
739 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
741 if (String
[Index
] == NARROW_CHAR
) {
743 // Skip to the next character
749 // Skip to the next character
754 } while (String
[Index
] != 0);
757 // Increment by one to include the null-terminator in the size
761 return Count
* sizeof (CHAR16
);
765 Base on the input option string to update the skip value for a menu option.
767 @param MenuOption The MenuOption to be checked.
768 @param OptionString The input option string.
772 UpdateSkipInfoForMenu (
773 IN UI_MENU_OPTION
*MenuOption
,
774 IN CHAR16
*OptionString
780 CHAR16
*OutputString
;
783 Width
= (UINT16
) gOptionBlockWidth
;
787 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
788 if (StrLen (&OptionString
[Index
]) != 0) {
792 FreePool (OutputString
);
795 if ((Row
> MenuOption
->Skip
) &&
796 (MenuOption
->ThisTag
->OpCode
->OpCode
!= EFI_IFR_DATE_OP
) &&
797 (MenuOption
->ThisTag
->OpCode
->OpCode
!= EFI_IFR_TIME_OP
)) {
798 MenuOption
->Skip
= Row
;
803 Update display lines for a Menu Option.
805 @param MenuOption The MenuOption to be checked.
809 UpdateOptionSkipLines (
810 IN UI_MENU_OPTION
*MenuOption
813 CHAR16
*OptionString
;
817 ProcessOptions (MenuOption
, FALSE
, &OptionString
, TRUE
);
818 if (OptionString
!= NULL
) {
819 UpdateSkipInfoForMenu (MenuOption
, OptionString
);
821 FreePool (OptionString
);
824 if ((MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_TEXT_OP
) && (((EFI_IFR_TEXT
*)MenuOption
->ThisTag
->OpCode
)->TextTwo
!= 0)) {
825 OptionString
= GetToken (((EFI_IFR_TEXT
*)MenuOption
->ThisTag
->OpCode
)->TextTwo
, gFormData
->HiiHandle
);
827 if (OptionString
!= NULL
) {
828 UpdateSkipInfoForMenu (MenuOption
, OptionString
);
830 FreePool (OptionString
);
836 Check whether this Menu Option could be highlighted.
838 This is an internal function.
840 @param MenuOption The MenuOption to be checked.
842 @retval TRUE This Menu Option is selectable.
843 @retval FALSE This Menu Option could not be selected.
848 UI_MENU_OPTION
*MenuOption
851 if ((MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_SUBTITLE_OP
) ||
852 MenuOption
->GrayOut
|| MenuOption
->ReadOnly
) {
860 Move to next selectable statement.
862 This is an internal function.
864 @param GoUp The navigation direction. TRUE: up, FALSE: down.
865 @param CurrentPosition Current position.
866 @param GapToTop Gap position to top or bottom.
868 @return The row distance from current MenuOption to next selectable MenuOption.
870 @retval -1 Reach the begin of the menu, still can't find the selectable menu.
871 @retval Value Find the selectable menu, maybe the truly selectable, maybe the l
872 last menu showing at current form.
876 MoveToNextStatement (
878 IN OUT LIST_ENTRY
**CurrentPosition
,
884 UI_MENU_OPTION
*NextMenuOption
;
885 UI_MENU_OPTION
*PreMenuOption
;
888 Pos
= *CurrentPosition
;
889 PreMenuOption
= MENU_OPTION_FROM_LINK (Pos
);
892 NextMenuOption
= MENU_OPTION_FROM_LINK (Pos
);
894 // NextMenuOption->Row == 0 means this menu has not calculate
895 // the NextMenuOption->Skip value yet, just calculate here.
897 if (NextMenuOption
->Row
== 0) {
898 UpdateOptionSkipLines (NextMenuOption
);
901 if (GoUp
&& (PreMenuOption
!= NextMenuOption
)) {
903 // In this case, still can't find the selectable menu,
904 // return the last one in the showing form.
906 if ((UINTN
) Distance
+ NextMenuOption
->Skip
> GapToTop
) {
907 NextMenuOption
= PreMenuOption
;
912 // Current Position doesn't need to be caculated when go up.
913 // Caculate distanct at first when go up
915 Distance
+= NextMenuOption
->Skip
;
918 if (IsSelectable (NextMenuOption
)) {
923 // Arrive at begin of the menu list.
925 if ((GoUp
? Pos
->BackLink
: Pos
->ForwardLink
) == &gMenuOption
) {
932 // In this case, still can't find the selectable menu,
933 // return the last one in the showing form.
935 if ((UINTN
) Distance
+ NextMenuOption
->Skip
> GapToTop
) {
936 NextMenuOption
= PreMenuOption
;
940 Distance
+= NextMenuOption
->Skip
;
943 PreMenuOption
= NextMenuOption
;
944 Pos
= (GoUp
? Pos
->BackLink
: Pos
->ForwardLink
);
947 *CurrentPosition
= &NextMenuOption
->Link
;
953 Process option string for date/time opcode.
955 @param MenuOption Menu option point to date/time.
956 @param OptionString Option string input for process.
957 @param AddOptCol Whether need to update MenuOption->OptCol.
961 ProcessStringForDateTime (
962 UI_MENU_OPTION
*MenuOption
,
963 CHAR16
*OptionString
,
969 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
973 ASSERT (MenuOption
!= NULL
&& OptionString
!= NULL
);
975 Statement
= MenuOption
->ThisTag
;
978 if (Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
) {
979 Date
= (EFI_IFR_DATE
*) Statement
->OpCode
;
980 } else if (Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) {
981 Time
= (EFI_IFR_TIME
*) Statement
->OpCode
;
985 // If leading spaces on OptionString - remove the spaces
987 for (Index
= 0; OptionString
[Index
] == L
' '; Index
++) {
989 // Base on the blockspace to get the option column info.
992 MenuOption
->OptCol
++;
996 for (Count
= 0; OptionString
[Index
] != CHAR_NULL
; Index
++) {
997 OptionString
[Count
] = OptionString
[Index
];
1000 OptionString
[Count
] = CHAR_NULL
;
1003 // Enable to suppress field in the opcode base on the flag.
1005 if (Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
) {
1007 // OptionString format is: <**: **: ****>
1011 if ((Date
->Flags
& EFI_QF_DATE_MONTH_SUPPRESS
) && (MenuOption
->Sequence
== 0)) {
1013 // At this point, only "<**:" in the optionstring.
1014 // Clean the day's ** field, after clean, the format is "< :"
1016 SetUnicodeMem (&OptionString
[1], 2, L
' ');
1017 } else if ((Date
->Flags
& EFI_QF_DATE_DAY_SUPPRESS
) && (MenuOption
->Sequence
== 1)) {
1019 // At this point, only "**:" in the optionstring.
1020 // Clean the month's "**" field, after clean, the format is " :"
1022 SetUnicodeMem (&OptionString
[0], 2, L
' ');
1023 } else if ((Date
->Flags
& EFI_QF_DATE_YEAR_SUPPRESS
) && (MenuOption
->Sequence
== 2)) {
1025 // At this point, only "****>" in the optionstring.
1026 // Clean the year's "****" field, after clean, the format is " >"
1028 SetUnicodeMem (&OptionString
[0], 4, L
' ');
1030 } else if (Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) {
1032 // OptionString format is: <**: **: **>
1033 // |hour|minute|second|
1036 if ((Time
->Flags
& QF_TIME_HOUR_SUPPRESS
) && (MenuOption
->Sequence
== 0)) {
1038 // At this point, only "<**:" in the optionstring.
1039 // Clean the hour's ** field, after clean, the format is "< :"
1041 SetUnicodeMem (&OptionString
[1], 2, L
' ');
1042 } else if ((Time
->Flags
& QF_TIME_MINUTE_SUPPRESS
) && (MenuOption
->Sequence
== 1)) {
1044 // At this point, only "**:" in the optionstring.
1045 // Clean the minute's "**" field, after clean, the format is " :"
1047 SetUnicodeMem (&OptionString
[0], 2, L
' ');
1048 } else if ((Time
->Flags
& QF_TIME_SECOND_SUPPRESS
) && (MenuOption
->Sequence
== 2)) {
1050 // At this point, only "**>" in the optionstring.
1051 // Clean the second's "**" field, after clean, the format is " >"
1053 SetUnicodeMem (&OptionString
[0], 2, L
' ');
1060 Adjust Data and Time position accordingly.
1061 Data format : [01/02/2004] [11:22:33]
1062 Line number : 0 0 1 0 0 1
1064 This is an internal function.
1066 @param DirectionUp the up or down direction. False is down. True is
1068 @param CurrentPosition Current position. On return: Point to the last
1069 Option (Year or Second) if up; Point to the first
1070 Option (Month or Hour) if down.
1072 @return Return line number to pad. It is possible that we stand on a zero-advance
1073 @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
1077 AdjustDateAndTimePosition (
1078 IN BOOLEAN DirectionUp
,
1079 IN OUT LIST_ENTRY
**CurrentPosition
1083 LIST_ENTRY
*NewPosition
;
1084 UI_MENU_OPTION
*MenuOption
;
1085 UINTN PadLineNumber
;
1088 NewPosition
= *CurrentPosition
;
1089 MenuOption
= MENU_OPTION_FROM_LINK (NewPosition
);
1091 if ((MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_DATE_OP
) ||
1092 (MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_TIME_OP
)) {
1094 // Calculate the distance from current position to the last Date/Time MenuOption
1097 while (MenuOption
->Skip
== 0) {
1099 NewPosition
= NewPosition
->ForwardLink
;
1100 MenuOption
= MENU_OPTION_FROM_LINK (NewPosition
);
1104 NewPosition
= *CurrentPosition
;
1107 // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
1108 // to be one that back to the previous set of MenuOptions, we need to advance to the first
1109 // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate
1110 // checking can be done.
1112 while (Count
++ < 2) {
1113 NewPosition
= NewPosition
->BackLink
;
1117 // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended
1118 // to be one that progresses to the next set of MenuOptions, we need to advance to the last
1119 // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate
1120 // checking can be done.
1122 while (Count
-- > 0) {
1123 NewPosition
= NewPosition
->ForwardLink
;
1127 *CurrentPosition
= NewPosition
;
1130 return PadLineNumber
;
1134 Get step info from numeric opcode.
1136 @param[in] OpCode The input numeric op code.
1138 @return step info for this opcode.
1142 IN EFI_IFR_OP_HEADER
*OpCode
1145 EFI_IFR_NUMERIC
*NumericOp
;
1148 NumericOp
= (EFI_IFR_NUMERIC
*) OpCode
;
1150 switch (NumericOp
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1151 case EFI_IFR_NUMERIC_SIZE_1
:
1152 Step
= NumericOp
->data
.u8
.Step
;
1155 case EFI_IFR_NUMERIC_SIZE_2
:
1156 Step
= NumericOp
->data
.u16
.Step
;
1159 case EFI_IFR_NUMERIC_SIZE_4
:
1160 Step
= NumericOp
->data
.u32
.Step
;
1163 case EFI_IFR_NUMERIC_SIZE_8
:
1164 Step
= NumericOp
->data
.u64
.Step
;
1176 Find the registered HotKey based on KeyData.
1178 @param[in] KeyData A pointer to a buffer that describes the keystroke
1179 information for the hot key.
1181 @return The registered HotKey context. If no found, NULL will return.
1184 GetHotKeyFromRegisterList (
1185 IN EFI_INPUT_KEY
*KeyData
1189 BROWSER_HOT_KEY
*HotKey
;
1191 Link
= GetFirstNode (&gFormData
->HotKeyListHead
);
1192 while (!IsNull (&gFormData
->HotKeyListHead
, Link
)) {
1193 HotKey
= BROWSER_HOT_KEY_FROM_LINK (Link
);
1195 if (HotKey
->KeyData
->ScanCode
== KeyData
->ScanCode
) {
1199 Link
= GetNextNode (&gFormData
->HotKeyListHead
, Link
);
1207 Determine if the menu is the last menu that can be selected.
1209 This is an internal function.
1211 @param Direction The scroll direction. False is down. True is up.
1212 @param CurrentPos The current focus.
1214 @return FALSE -- the menu isn't the last menu that can be selected.
1215 @return TRUE -- the menu is the last menu that can be selected.
1220 IN BOOLEAN Direction
,
1221 IN LIST_ENTRY
*CurrentPos
1226 Temp
= Direction
? CurrentPos
->BackLink
: CurrentPos
->ForwardLink
;
1228 if (Temp
== &gMenuOption
) {
1236 Wait for a given event to fire, or for an optional timeout to expire.
1238 @param Event The event to wait for
1240 @retval UI_EVENT_TYPE The type of the event which is trigged.
1252 EFI_EVENT TimerEvent
;
1253 EFI_EVENT WaitList
[3];
1254 UI_EVENT_TYPE EventType
;
1257 Timeout
= FormExitTimeout(gFormData
);
1260 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
1263 // Set the timer event
1272 WaitList
[0] = Event
;
1274 if (gFormData
->FormRefreshEvent
!= NULL
) {
1275 WaitList
[EventNum
] = gFormData
->FormRefreshEvent
;
1280 WaitList
[EventNum
] = TimerEvent
;
1284 Status
= gBS
->WaitForEvent (EventNum
, WaitList
, &Index
);
1285 ASSERT_EFI_ERROR (Status
);
1289 EventType
= UIEventKey
;
1293 if (gFormData
->FormRefreshEvent
!= NULL
) {
1294 EventType
= UIEventDriver
;
1296 ASSERT (Timeout
!= 0 && EventNum
== 2);
1297 EventType
= UIEventTimeOut
;
1302 ASSERT (Index
== 2 && EventNum
== 3);
1303 EventType
= UIEventTimeOut
;
1308 gBS
->CloseEvent (TimerEvent
);
1315 Get question id info from the input opcode header.
1317 @param OpCode The input opcode header pointer.
1319 @retval The question id for this opcode.
1324 IN EFI_IFR_OP_HEADER
*OpCode
1327 EFI_IFR_QUESTION_HEADER
*QuestionHeader
;
1329 if (OpCode
->Length
< sizeof (EFI_IFR_OP_HEADER
) + sizeof (EFI_IFR_QUESTION_HEADER
)) {
1333 QuestionHeader
= (EFI_IFR_QUESTION_HEADER
*)((UINT8
*) OpCode
+ sizeof(EFI_IFR_OP_HEADER
));
1335 return QuestionHeader
->QuestionId
;
1339 Find the first menu which will be show at the top.
1341 @param FormData The data info for this form.
1342 @param TopOfScreen The link_entry pointer to top menu.
1343 @param HighlightMenu The menu which will be highlight.
1344 @param SkipValue The skip value for the top menu.
1349 IN FORM_DISPLAY_ENGINE_FORM
*FormData
,
1350 OUT LIST_ENTRY
**TopOfScreen
,
1351 OUT LIST_ENTRY
**HighlightMenu
,
1360 UI_MENU_OPTION
*SavedMenuOption
;
1363 TopRow
= gStatementDimensions
.TopRow
+ SCROLL_ARROW_HEIGHT
;
1364 BottomRow
= gStatementDimensions
.BottomRow
- SCROLL_ARROW_HEIGHT
;
1367 // If not has input highlight statement, just return the first one in this form.
1369 if (FormData
->HighLightedStatement
== NULL
) {
1370 *TopOfScreen
= gMenuOption
.ForwardLink
;
1371 *HighlightMenu
= gMenuOption
.ForwardLink
;
1372 if (!IsListEmpty (&gMenuOption
)) {
1373 MoveToNextStatement (FALSE
, HighlightMenu
, BottomRow
- TopRow
);
1380 // Now base on the input highlight menu to find the top menu in this page.
1381 // Will base on the highlight menu show at the bottom to find the top menu.
1383 NewPos
= gMenuOption
.ForwardLink
;
1384 SavedMenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
1386 while ((SavedMenuOption
->ThisTag
!= FormData
->HighLightedStatement
) ||
1387 (SavedMenuOption
->Sequence
!= gSequence
)) {
1388 NewPos
= NewPos
->ForwardLink
;
1389 if (NewPos
== &gMenuOption
) {
1391 // Not Found it, break
1395 SavedMenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
1397 ASSERT (SavedMenuOption
->ThisTag
== FormData
->HighLightedStatement
);
1399 *HighlightMenu
= NewPos
;
1401 AdjustDateAndTimePosition(FALSE
, &NewPos
);
1402 SavedMenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
1403 UpdateOptionSkipLines (SavedMenuOption
);
1406 // If highlight opcode is date/time, keep the highlight row info not change.
1408 if ((SavedMenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_DATE_OP
|| SavedMenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) &&
1409 (gHighligthMenuInfo
.QuestionId
!= 0) &&
1410 (gHighligthMenuInfo
.QuestionId
== GetQuestionIdInfo(SavedMenuOption
->ThisTag
->OpCode
))) {
1412 // Still show the highlight menu before exit from display engine.
1414 EndRow
= gHighligthMenuInfo
.DisplayRow
+ SavedMenuOption
->Skip
;
1420 // Base on the selected menu will show at the bottome of next page,
1421 // select the menu show at the top of the next page.
1424 for (Index
= TopRow
+ SavedMenuOption
->Skip
; Index
<= EndRow
; ) {
1425 Link
= Link
->BackLink
;
1427 // Already find the first menu in this form, means highlight menu
1428 // will show in first page of this form.
1430 if (Link
== &gMenuOption
) {
1431 *TopOfScreen
= gMenuOption
.ForwardLink
;
1435 SavedMenuOption
= MENU_OPTION_FROM_LINK (Link
);
1436 UpdateOptionSkipLines (SavedMenuOption
);
1437 Index
+= SavedMenuOption
->Skip
;
1441 // Found the menu which will show at the top of the page.
1443 if (Link
== NewPos
) {
1445 // The menu can show more than one pages, just show the menu at the top of the page.
1448 *TopOfScreen
= Link
;
1451 // Check whether need to skip some line for menu shows at the top of the page.
1453 *SkipValue
= Index
- EndRow
;
1454 if (*SkipValue
> 0 && *SkipValue
< (INTN
) SavedMenuOption
->Skip
) {
1455 *TopOfScreen
= Link
;
1458 *TopOfScreen
= Link
->ForwardLink
;
1464 Update highlight menu info.
1466 @param MenuOption The menu opton which is highlight.
1470 UpdateHighlightMenuInfo (
1471 IN UI_MENU_OPTION
*MenuOption
1474 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
1477 // This is the current selected statement
1479 Statement
= MenuOption
->ThisTag
;
1482 // Get the highlight statement.
1484 gUserInput
->SelectedStatement
= Statement
;
1485 gSequence
= (UINT16
) MenuOption
->Sequence
;
1488 // Record highlight row info for date/time opcode.
1490 if (Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
|| Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) {
1491 gHighligthMenuInfo
.QuestionId
= GetQuestionIdInfo(Statement
->OpCode
);
1492 gHighligthMenuInfo
.DisplayRow
= (UINT16
) MenuOption
->Row
;
1494 gHighligthMenuInfo
.QuestionId
= 0;
1495 gHighligthMenuInfo
.DisplayRow
= 0;
1498 RefreshKeyHelp(gFormData
, Statement
, FALSE
);
1502 Update attribut for this menu.
1504 @param MenuOption The menu opton which this attribut used to.
1505 @param Highlight Whether this menu will be highlight.
1509 SetDisplayAttribute (
1510 IN UI_MENU_OPTION
*MenuOption
,
1511 IN BOOLEAN Highlight
1514 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
1516 Statement
= MenuOption
->ThisTag
;
1519 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetHighlightTextColor ());
1523 if (MenuOption
->GrayOut
) {
1524 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetGrayedTextColor ());
1526 if (Statement
->OpCode
->OpCode
== EFI_IFR_SUBTITLE_OP
) {
1527 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetSubTitleTextColor ());
1529 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetFieldTextColor ());
1535 Print string for this menu option.
1537 @param MenuOption The menu opton which this attribut used to.
1538 @param Col The column that this string will be print at.
1539 @param Row The row that this string will be print at.
1540 @param String The string which need to print.
1541 @param Width The width need to print, if string is less than the
1542 width, the block space will be used.
1543 @param Highlight Whether this menu will be highlight.
1548 IN UI_MENU_OPTION
*MenuOption
,
1553 IN BOOLEAN Highlight
1559 // Print string with normal color.
1562 PrintStringAtWithWidth (Col
, Row
, String
, Width
);
1567 // Print the highlight menu string.
1568 // First print the highlight string.
1570 SetDisplayAttribute(MenuOption
, TRUE
);
1571 Length
= PrintStringAt (Col
, Row
, String
);
1574 // Second, clean the empty after the string.
1576 SetDisplayAttribute(MenuOption
, FALSE
);
1577 PrintStringAtWithWidth (Col
+ Length
, Row
, L
"", Width
- Length
);
1581 Check whether this menu can has option string.
1583 @param MenuOption The menu opton which this attribut used to.
1585 @retval TRUE This menu option can have option string.
1586 @retval FALSE This menu option can't have option string.
1591 IN UI_MENU_OPTION
*MenuOption
1594 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
1597 EFI_IFR_TEXT
*TestOp
;
1600 Statement
= MenuOption
->ThisTag
;
1603 // See if the second text parameter is really NULL
1605 if (Statement
->OpCode
->OpCode
== EFI_IFR_TEXT_OP
) {
1606 TestOp
= (EFI_IFR_TEXT
*) Statement
->OpCode
;
1607 if (TestOp
->TextTwo
!= 0) {
1608 String
= GetToken (TestOp
->TextTwo
, gFormData
->HiiHandle
);
1609 Size
= StrLen (String
);
1614 if ((Statement
->OpCode
->OpCode
== EFI_IFR_SUBTITLE_OP
) ||
1615 (Statement
->OpCode
->OpCode
== EFI_IFR_REF_OP
) ||
1616 (Statement
->OpCode
->OpCode
== EFI_IFR_PASSWORD_OP
) ||
1617 (Statement
->OpCode
->OpCode
== EFI_IFR_ACTION_OP
) ||
1618 (Statement
->OpCode
->OpCode
== EFI_IFR_RESET_BUTTON_OP
) ||
1620 // Allow a wide display if text op-code and no secondary text op-code
1622 ((Statement
->OpCode
->OpCode
== EFI_IFR_TEXT_OP
) && (Size
== 0))
1633 Print string for this menu option.
1635 @param MenuOption The menu opton which this attribut used to.
1636 @param SkipWidth The skip width between the left to the start of the prompt.
1637 @param BeginCol The begin column for one menu.
1638 @param SkipLine The skip line for this menu.
1639 @param BottomRow The bottom row for this form.
1640 @param Highlight Whether this menu will be highlight.
1642 @retval EFI_SUCESSS Process the user selection success.
1647 IN UI_MENU_OPTION
*MenuOption
,
1652 IN BOOLEAN Highlight
1655 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
1660 CHAR16
*OptionString
;
1661 CHAR16
*OutputString
;
1669 UINTN PromptLineNum
;
1670 UINTN OptionLineNum
;
1674 Statement
= MenuOption
->ThisTag
;
1684 // Set default color.
1686 SetDisplayAttribute (MenuOption
, FALSE
);
1689 // 1. Paint the option string.
1691 Status
= ProcessOptions (MenuOption
, FALSE
, &OptionString
, FALSE
);
1692 if (EFI_ERROR (Status
)) {
1696 if (OptionString
!= NULL
) {
1697 if (Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
|| Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) {
1699 // Adjust option string for date/time opcode.
1701 ProcessStringForDateTime(MenuOption
, OptionString
, TRUE
);
1704 Width
= (UINT16
) gOptionBlockWidth
- 1;
1705 Row
= MenuOption
->Row
;
1709 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
1710 if (((Temp2
== 0)) && (Row
<= BottomRow
)) {
1711 if (Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
|| Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) {
1713 // For date/time question, it has three menu options for this qustion.
1714 // The first/second menu options with the skip value is 0. the last one
1715 // with skip value is 1.
1717 if (MenuOption
->Skip
!= 0) {
1719 // For date/ time, print the last past (year for date and second for time)
1720 // - 7 means skip [##/##/ for date and [##:##: for time.
1722 DisplayMenuString (MenuOption
,MenuOption
->OptCol
, Row
, OutputString
, Width
+ 1 - 7, Highlight
);
1725 // For date/ time, print the first and second past (year for date and second for time)
1727 DisplayMenuString (MenuOption
, MenuOption
->OptCol
, Row
, OutputString
, StrLen (OutputString
), Highlight
);
1730 DisplayMenuString (MenuOption
, MenuOption
->OptCol
, Row
, OutputString
, Width
+ 1, Highlight
);
1736 // If there is more string to process print on the next row and increment the Skip value
1738 if (StrLen (&OptionString
[Index
]) != 0) {
1742 // Since the Number of lines for this menu entry may or may not be reflected accurately
1743 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1744 // some testing to ensure we are keeping this in-sync.
1746 // If the difference in rows is greater than or equal to the skip value, increase the skip value
1748 if ((Row
- MenuOption
->Row
) >= MenuOption
->Skip
) {
1754 FreePool (OutputString
);
1762 FreePool (OptionString
);
1766 // 2. Paint the description.
1768 PromptWidth
= GetWidth (Statement
, &AdjustValue
);
1769 Row
= MenuOption
->Row
;
1773 if (MenuOption
->Description
== NULL
|| MenuOption
->Description
[0] == '\0') {
1774 PrintStringAtWithWidth (BeginCol
, Row
, L
"", PromptWidth
+ AdjustValue
+ SkipWidth
);
1777 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, PromptWidth
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
1778 if ((Temp
== 0) && (Row
<= BottomRow
)) {
1780 // 1.Clean the start LEFT_SKIPPED_COLUMNS
1782 PrintStringAtWithWidth (BeginCol
, Row
, L
"", SkipWidth
);
1784 if (Statement
->OpCode
->OpCode
== EFI_IFR_REF_OP
&& MenuOption
->Col
>= 2) {
1786 // Print Arrow for Goto button.
1789 MenuOption
->Col
- 2,
1791 GEOMETRICSHAPE_RIGHT_TRIANGLE
1794 DisplayMenuString (MenuOption
, MenuOption
->Col
, Row
, OutputString
, PromptWidth
+ AdjustValue
, Highlight
);
1798 // If there is more string to process print on the next row and increment the Skip value
1800 if (StrLen (&MenuOption
->Description
[Index
]) != 0) {
1806 FreePool (OutputString
);
1817 // 3. If this is a text op with secondary text information
1819 if ((Statement
->OpCode
->OpCode
== EFI_IFR_TEXT_OP
) && (((EFI_IFR_TEXT
*)Statement
->OpCode
)->TextTwo
!= 0)) {
1820 StringPtr
= GetToken (((EFI_IFR_TEXT
*)Statement
->OpCode
)->TextTwo
, gFormData
->HiiHandle
);
1822 Width
= (UINT16
) gOptionBlockWidth
- 1;
1823 Row
= MenuOption
->Row
;
1827 for (Index
= 0; GetLineByWidth (StringPtr
, Width
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
1828 if ((Temp3
== 0) && (Row
<= BottomRow
)) {
1829 DisplayMenuString (MenuOption
, MenuOption
->OptCol
, Row
, OutputString
, Width
+ 1, Highlight
);
1833 // If there is more string to process print on the next row and increment the Skip value
1835 if (StrLen (&StringPtr
[Index
]) != 0) {
1841 FreePool (OutputString
);
1847 FreePool (StringPtr
);
1851 // 4.Line number for Option string and prompt string are not equal.
1852 // Clean the column whose line number is less.
1854 if (HasOptionString(MenuOption
) && (OptionLineNum
!= PromptLineNum
)) {
1855 Col
= OptionLineNum
< PromptLineNum
? MenuOption
->OptCol
: BeginCol
;
1856 Row
= (OptionLineNum
< PromptLineNum
? OptionLineNum
: PromptLineNum
) + MenuOption
->Row
;
1857 Width
= (UINT16
) (OptionLineNum
< PromptLineNum
? gOptionBlockWidth
: PromptWidth
+ AdjustValue
+ SkipWidth
);
1858 MaxRow
= (OptionLineNum
< PromptLineNum
? PromptLineNum
: OptionLineNum
) + MenuOption
->Row
- 1;
1860 while (Row
<= MaxRow
) {
1861 DisplayMenuString (MenuOption
, Col
, Row
++, L
"", Width
, FALSE
);
1869 Display menu and wait for user to select one menu option, then return it.
1870 If AutoBoot is enabled, then if user doesn't select any option,
1871 after period of time, it will automatically return the first menu option.
1873 @param FormData The current form data info.
1875 @retval EFI_SUCESSS Process the user selection success.
1876 @retval EFI_NOT_FOUND Process option string for orderedlist/Oneof fail.
1881 IN FORM_DISPLAY_ENGINE_FORM
*FormData
1886 UINTN DistanceValue
;
1897 CHAR16
*OptionString
;
1898 CHAR16
*OutputString
;
1900 CHAR16
*HelpHeaderString
;
1901 CHAR16
*HelpBottomString
;
1910 LIST_ENTRY
*TopOfScreen
;
1911 LIST_ENTRY
*SavedListEntry
;
1912 UI_MENU_OPTION
*MenuOption
;
1913 UI_MENU_OPTION
*NextMenuOption
;
1914 UI_MENU_OPTION
*SavedMenuOption
;
1915 UI_MENU_OPTION
*PreviousMenuOption
;
1916 UI_CONTROL_FLAG ControlFlag
;
1917 UI_SCREEN_OPERATION ScreenOperation
;
1919 FORM_DISPLAY_ENGINE_STATEMENT
*Statement
;
1920 BROWSER_HOT_KEY
*HotKey
;
1921 UINTN HelpPageIndex
;
1922 UINTN HelpPageCount
;
1925 UINTN HelpHeaderLine
;
1926 UINTN HelpBottomLine
;
1927 BOOLEAN MultiHelpPage
;
1929 UINT16 EachLineWidth
;
1930 UINT16 HeaderLineWidth
;
1931 UINT16 BottomLineWidth
;
1932 EFI_STRING_ID HelpInfo
;
1933 UI_EVENT_TYPE EventType
;
1934 FORM_DISPLAY_ENGINE_STATEMENT
*InitialHighlight
;
1935 BOOLEAN SkipHighLight
;
1937 EventType
= UIEventNone
;
1938 Status
= EFI_SUCCESS
;
1940 HelpHeaderString
= NULL
;
1941 HelpBottomString
= NULL
;
1942 OptionString
= NULL
;
1943 ScreenOperation
= UiNoOperation
;
1952 MultiHelpPage
= FALSE
;
1954 HeaderLineWidth
= 0;
1955 BottomLineWidth
= 0;
1956 OutputString
= NULL
;
1960 SkipHighLight
= FALSE
;
1962 NextMenuOption
= NULL
;
1963 PreviousMenuOption
= NULL
;
1964 SavedMenuOption
= NULL
;
1968 gModalSkipColumn
= (CHAR16
) (gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
) / 6;
1969 InitialHighlight
= gFormData
->HighLightedStatement
;
1971 ZeroMem (&Key
, sizeof (EFI_INPUT_KEY
));
1975 // |<-.->|<-.........->|<- .........->|<-...........->|
1976 // Skip Prompt Option Help
1978 Width
= (CHAR16
) ((gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
) / 3);
1979 gOptionBlockWidth
= Width
+ 1;
1980 gHelpBlockWidth
= (CHAR16
) (Width
- LEFT_SKIPPED_COLUMNS
);
1981 gPromptBlockWidth
= (CHAR16
) (gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
- 2 * Width
- 1);
1983 TopRow
= gStatementDimensions
.TopRow
+ SCROLL_ARROW_HEIGHT
;
1984 BottomRow
= gStatementDimensions
.BottomRow
- SCROLL_ARROW_HEIGHT
- 1;
1987 if ((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
1988 Col
= gStatementDimensions
.LeftColumn
+ LEFT_SKIPPED_COLUMNS
+ gModalSkipColumn
;
1990 Col
= gStatementDimensions
.LeftColumn
+ LEFT_SKIPPED_COLUMNS
;
1993 FindTopMenu(FormData
, &TopOfScreen
, &NewPos
, &SkipValue
);
1995 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
1997 ControlFlag
= CfInitialization
;
1999 switch (ControlFlag
) {
2000 case CfInitialization
:
2001 if ((gOldFormEntry
.HiiHandle
!= FormData
->HiiHandle
) ||
2002 (!CompareGuid (&gOldFormEntry
.FormSetGuid
, &FormData
->FormSetGuid
))) {
2004 // Clear Statement range if different formset is painted.
2007 gStatementDimensions
.LeftColumn
,
2008 gStatementDimensions
.RightColumn
,
2009 TopRow
- SCROLL_ARROW_HEIGHT
,
2010 BottomRow
+ SCROLL_ARROW_HEIGHT
,
2011 GetFieldTextColor ()
2015 ControlFlag
= CfRepaint
;
2019 ControlFlag
= CfRefreshHighLight
;
2029 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetFieldTextColor ());
2032 // 1. Check whether need to print the arrow up.
2034 if (!ValueIsScroll (TRUE
, TopOfScreen
)) {
2038 if ((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
2039 PrintStringAtWithWidth(gStatementDimensions
.LeftColumn
+ gModalSkipColumn
, TopRow
- 1, L
"", gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
- 2 * gModalSkipColumn
);
2041 PrintStringAtWithWidth(gStatementDimensions
.LeftColumn
, TopRow
- 1, L
"", gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
);
2044 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetArrowColor ());
2046 gStatementDimensions
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
2047 TopRow
- SCROLL_ARROW_HEIGHT
,
2050 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetFieldTextColor ());
2054 // 2.Paint the menu.
2056 for (Link
= TopOfScreen
; Link
!= &gMenuOption
; Link
= Link
->ForwardLink
) {
2057 MenuOption
= MENU_OPTION_FROM_LINK (Link
);
2058 MenuOption
->Row
= Row
;
2059 MenuOption
->Col
= Col
;
2060 if ((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
2061 MenuOption
->OptCol
= gStatementDimensions
.LeftColumn
+ LEFT_SKIPPED_COLUMNS
+ gPromptBlockWidth
+ gModalSkipColumn
;
2063 MenuOption
->OptCol
= gStatementDimensions
.LeftColumn
+ LEFT_SKIPPED_COLUMNS
+ gPromptBlockWidth
;
2066 if (MenuOption
->NestInStatement
) {
2067 MenuOption
->Col
+= SUBTITLE_INDENT
;
2071 // Save the highlight menu, will be used in CfRefreshHighLight case.
2073 if (Link
== NewPos
) {
2074 SavedMenuOption
= MenuOption
;
2075 SkipHighLight
= TRUE
;
2078 if ((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
2079 Status
= DisplayOneMenu (MenuOption
,
2080 LEFT_SKIPPED_COLUMNS
,
2081 gStatementDimensions
.LeftColumn
+ gModalSkipColumn
,
2082 Link
== TopOfScreen
? SkipValue
: 0,
2084 (BOOLEAN
) ((Link
== NewPos
) && IsSelectable(MenuOption
))
2087 Status
= DisplayOneMenu (MenuOption
,
2088 LEFT_SKIPPED_COLUMNS
,
2089 gStatementDimensions
.LeftColumn
,
2090 Link
== TopOfScreen
? SkipValue
: 0,
2092 (BOOLEAN
) ((Link
== NewPos
) && IsSelectable(MenuOption
))
2096 if (EFI_ERROR (Status
)) {
2100 // 3. Update the row info which will be used by next menu.
2102 if (Link
== TopOfScreen
) {
2103 Row
+= MenuOption
->Skip
- SkipValue
;
2105 Row
+= MenuOption
->Skip
;
2108 if (Row
> BottomRow
) {
2109 if (!ValueIsScroll (FALSE
, Link
)) {
2113 Row
= BottomRow
+ 1;
2119 // 3. Menus in this form may not cover all form, clean the remain field.
2121 while (Row
<= BottomRow
) {
2122 if ((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
2123 PrintStringAtWithWidth(gStatementDimensions
.LeftColumn
+ gModalSkipColumn
, Row
++, L
"", gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
- 2 * gModalSkipColumn
);
2125 PrintStringAtWithWidth(gStatementDimensions
.LeftColumn
, Row
++, L
"", gStatementDimensions
.RightColumn
- gHelpBlockWidth
- gStatementDimensions
.LeftColumn
);
2130 // 4. Print the down arrow row.
2132 if ((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
2133 PrintStringAtWithWidth(gStatementDimensions
.LeftColumn
+ gModalSkipColumn
, BottomRow
+ 1, L
"", gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
- 2 * + gModalSkipColumn
);
2135 PrintStringAtWithWidth(gStatementDimensions
.LeftColumn
, BottomRow
+ 1, L
"", gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
);
2138 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetArrowColor ());
2140 gStatementDimensions
.LeftColumn
+ gPromptBlockWidth
+ gOptionBlockWidth
+ 1,
2141 BottomRow
+ SCROLL_ARROW_HEIGHT
,
2144 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetFieldTextColor ());
2149 if (IsListEmpty (&gMenuOption
)) {
2150 ControlFlag
= CfReadKey
;
2155 case CfRefreshHighLight
:
2158 // MenuOption: Last menu option that need to remove hilight
2159 // MenuOption is set to NULL in Repaint
2160 // NewPos: Current menu option that need to hilight
2162 ControlFlag
= CfUpdateHelpString
;
2164 if (SkipHighLight
) {
2165 MenuOption
= SavedMenuOption
;
2166 SkipHighLight
= FALSE
;
2167 UpdateHighlightMenuInfo (MenuOption
);
2171 if (MenuOption
!= NULL
&& TopOfScreen
== &MenuOption
->Link
) {
2176 if (NewPos
== TopOfScreen
) {
2182 if (NewPos
!= NULL
&& (MenuOption
== NULL
|| NewPos
!= &MenuOption
->Link
)) {
2183 if (MenuOption
!= NULL
) {
2185 // Remove highlight on last Menu Option
2187 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
2188 ProcessOptions (MenuOption
, FALSE
, &OptionString
, TRUE
);
2189 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetFieldTextColor ());
2190 if (OptionString
!= NULL
) {
2191 if ((MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_DATE_OP
) ||
2192 (MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_TIME_OP
)
2194 ProcessStringForDateTime(MenuOption
, OptionString
, FALSE
);
2197 Width
= (UINT16
) gOptionBlockWidth
;
2198 OriginalRow
= MenuOption
->Row
;
2201 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
2202 if ((Temp
== 0) && (MenuOption
->Row
>= TopRow
) && (MenuOption
->Row
<= BottomRow
)) {
2203 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
2206 // If there is more string to process print on the next row and increment the Skip value
2208 if (StrLen (&OptionString
[Index
]) != 0) {
2214 FreePool (OutputString
);
2220 MenuOption
->Row
= OriginalRow
;
2222 FreePool (OptionString
);
2225 if (MenuOption
->GrayOut
) {
2226 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetGrayedTextColor ());
2227 } else if (MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_SUBTITLE_OP
) {
2228 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetSubTitleTextColor ());
2231 OriginalRow
= MenuOption
->Row
;
2232 Width
= GetWidth (MenuOption
->ThisTag
, NULL
);
2235 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
2236 if ((Temp
== 0) && (MenuOption
->Row
>= TopRow
) && (MenuOption
->Row
<= BottomRow
)) {
2237 PrintStringAt (MenuOption
->Col
, MenuOption
->Row
, OutputString
);
2240 // If there is more string to process print on the next row and increment the Skip value
2242 if (StrLen (&MenuOption
->Description
[Index
]) != 0) {
2248 FreePool (OutputString
);
2254 MenuOption
->Row
= OriginalRow
;
2255 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetFieldTextColor ());
2261 // This is the current selected statement
2263 MenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
2264 Statement
= MenuOption
->ThisTag
;
2266 UpdateHighlightMenuInfo (MenuOption
);
2268 if (!IsSelectable (MenuOption
)) {
2273 // Set reverse attribute
2275 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetHighlightTextColor ());
2276 gST
->ConOut
->SetCursorPosition (gST
->ConOut
, MenuOption
->Col
, MenuOption
->Row
);
2278 ProcessOptions (MenuOption
, FALSE
, &OptionString
, TRUE
);
2279 if (OptionString
!= NULL
) {
2280 if (Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
|| Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
) {
2281 ProcessStringForDateTime(MenuOption
, OptionString
, FALSE
);
2283 Width
= (UINT16
) gOptionBlockWidth
;
2285 OriginalRow
= MenuOption
->Row
;
2288 for (Index
= 0; GetLineByWidth (OptionString
, Width
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
2289 if ((Temp2
== 0) && (MenuOption
->Row
>= TopRow
) && (MenuOption
->Row
<= BottomRow
) ) {
2290 PrintStringAt (MenuOption
->OptCol
, MenuOption
->Row
, OutputString
);
2293 // If there is more string to process print on the next row and increment the Skip value
2295 if (StrLen (&OptionString
[Index
]) != 0) {
2301 FreePool (OutputString
);
2307 MenuOption
->Row
= OriginalRow
;
2309 FreePool (OptionString
);
2312 OriginalRow
= MenuOption
->Row
;
2314 Width
= GetWidth (Statement
, NULL
);
2317 for (Index
= 0; GetLineByWidth (MenuOption
->Description
, Width
, &GlyphWidth
, &Index
, &OutputString
) != 0x0000;) {
2318 if ((Temp2
== 0) && (MenuOption
->Row
>= TopRow
) && (MenuOption
->Row
<= BottomRow
) ) {
2319 PrintStringAt (MenuOption
->Col
, MenuOption
->Row
, OutputString
);
2322 // If there is more string to process print on the next row and increment the Skip value
2324 if (StrLen (&MenuOption
->Description
[Index
]) != 0) {
2330 FreePool (OutputString
);
2336 MenuOption
->Row
= OriginalRow
;
2342 // Clear reverse attribute
2344 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetFieldTextColor ());
2348 case CfUpdateHelpString
:
2349 ControlFlag
= CfPrepareToReadKey
;
2350 if ((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) {
2354 if (Repaint
|| NewLine
) {
2356 // Don't print anything if it is a NULL help token
2358 ASSERT(MenuOption
!= NULL
);
2359 HelpInfo
= ((EFI_IFR_STATEMENT_HEADER
*) ((CHAR8
*)MenuOption
->ThisTag
->OpCode
+ sizeof (EFI_IFR_OP_HEADER
)))->Help
;
2360 if (HelpInfo
== 0 || !IsSelectable (MenuOption
)) {
2361 StringPtr
= GetToken (STRING_TOKEN (EMPTY_STRING
), gHiiHandle
);
2363 StringPtr
= GetToken (HelpInfo
, gFormData
->HiiHandle
);
2366 RowCount
= BottomRow
- TopRow
+ 1;
2369 // 1.Calculate how many line the help string need to print.
2371 if (HelpString
!= NULL
) {
2372 FreePool (HelpString
);
2375 HelpLine
= ProcessHelpString (StringPtr
, &HelpString
, &EachLineWidth
, RowCount
);
2376 FreePool (StringPtr
);
2378 if (HelpLine
> RowCount
) {
2379 MultiHelpPage
= TRUE
;
2380 StringPtr
= GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP
), gHiiHandle
);
2381 if (HelpHeaderString
!= NULL
) {
2382 FreePool (HelpHeaderString
);
2383 HelpHeaderString
= NULL
;
2385 HelpHeaderLine
= ProcessHelpString (StringPtr
, &HelpHeaderString
, &HeaderLineWidth
, 0);
2386 FreePool (StringPtr
);
2387 StringPtr
= GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN
), gHiiHandle
);
2388 if (HelpBottomString
!= NULL
) {
2389 FreePool (HelpBottomString
);
2390 HelpBottomString
= NULL
;
2392 HelpBottomLine
= ProcessHelpString (StringPtr
, &HelpBottomString
, &BottomLineWidth
, 0);
2393 FreePool (StringPtr
);
2395 // Calculate the help page count.
2397 if (HelpLine
> 2 * RowCount
- 2) {
2398 HelpPageCount
= (HelpLine
- RowCount
+ 1) / (RowCount
- 2) + 1;
2399 if ((HelpLine
- RowCount
+ 1) % (RowCount
- 2) > 1) {
2406 MultiHelpPage
= FALSE
;
2411 // Check whether need to show the 'More(U/u)' at the begin.
2412 // Base on current direct info, here shows aligned to the right side of the column.
2413 // If the direction is multi line and aligned to right side may have problem, so
2414 // add ASSERT code here.
2416 if (HelpPageIndex
> 0) {
2417 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetInfoTextColor ());
2418 for (Index
= 0; Index
< HelpHeaderLine
; Index
++) {
2419 ASSERT (HelpHeaderLine
== 1);
2420 ASSERT (GetStringWidth (HelpHeaderString
) / 2 < (UINTN
) (gHelpBlockWidth
- 1));
2421 PrintStringAtWithWidth (
2422 gStatementDimensions
.RightColumn
- gHelpBlockWidth
,
2428 gStatementDimensions
.RightColumn
- GetStringWidth (HelpHeaderString
) / 2 - 1,
2430 &HelpHeaderString
[Index
* HeaderLineWidth
]
2435 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetHelpTextColor ());
2437 // Print the help string info.
2439 if (!MultiHelpPage
) {
2440 for (Index
= 0; Index
< HelpLine
; Index
++) {
2441 PrintStringAtWithWidth (
2442 gStatementDimensions
.RightColumn
- gHelpBlockWidth
,
2444 &HelpString
[Index
* EachLineWidth
],
2448 for (; Index
< RowCount
; Index
++) {
2449 PrintStringAtWithWidth (
2450 gStatementDimensions
.RightColumn
- gHelpBlockWidth
,
2456 gST
->ConOut
->SetCursorPosition(gST
->ConOut
, gStatementDimensions
.RightColumn
-1, BottomRow
);
2458 if (HelpPageIndex
== 0) {
2459 for (Index
= 0; Index
< RowCount
- HelpBottomLine
; Index
++) {
2460 PrintStringAtWithWidth (
2461 gStatementDimensions
.RightColumn
- gHelpBlockWidth
,
2463 &HelpString
[Index
* EachLineWidth
],
2468 for (Index
= 0; (Index
< RowCount
- HelpBottomLine
- HelpHeaderLine
) &&
2469 (Index
+ HelpPageIndex
* (RowCount
- 2) + 1 < HelpLine
); Index
++) {
2470 PrintStringAtWithWidth (
2471 gStatementDimensions
.RightColumn
- gHelpBlockWidth
,
2472 Index
+ TopRow
+ HelpHeaderLine
,
2473 &HelpString
[(Index
+ HelpPageIndex
* (RowCount
- 2) + 1)* EachLineWidth
],
2477 if (HelpPageIndex
== HelpPageCount
- 1) {
2478 for (; Index
< RowCount
- HelpHeaderLine
; Index
++) {
2479 PrintStringAtWithWidth (
2480 gStatementDimensions
.RightColumn
- gHelpBlockWidth
,
2481 Index
+ TopRow
+ HelpHeaderLine
,
2486 gST
->ConOut
->SetCursorPosition(gST
->ConOut
, gStatementDimensions
.RightColumn
-1, BottomRow
);
2492 // Check whether need to print the 'More(D/d)' at the bottom.
2493 // Base on current direct info, here shows aligned to the right side of the column.
2494 // If the direction is multi line and aligned to right side may have problem, so
2495 // add ASSERT code here.
2497 if (HelpPageIndex
< HelpPageCount
- 1 && MultiHelpPage
) {
2498 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetInfoTextColor ());
2499 for (Index
= 0; Index
< HelpBottomLine
; Index
++) {
2500 ASSERT (HelpBottomLine
== 1);
2501 ASSERT (GetStringWidth (HelpBottomString
) / 2 < (UINTN
) (gHelpBlockWidth
- 1));
2502 PrintStringAtWithWidth (
2503 gStatementDimensions
.RightColumn
- gHelpBlockWidth
,
2504 BottomRow
+ Index
- HelpBottomLine
+ 1,
2509 gStatementDimensions
.RightColumn
- GetStringWidth (HelpBottomString
) / 2 - 1,
2510 BottomRow
+ Index
- HelpBottomLine
+ 1,
2511 &HelpBottomString
[Index
* BottomLineWidth
]
2516 // Reset this flag every time we finish using it.
2522 case CfPrepareToReadKey
:
2523 ControlFlag
= CfReadKey
;
2524 ScreenOperation
= UiNoOperation
;
2528 ControlFlag
= CfScreenOperation
;
2531 // Wait for user's selection
2534 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2535 if (!EFI_ERROR (Status
)) {
2536 EventType
= UIEventKey
;
2541 // If we encounter error, continue to read another key in.
2543 if (Status
!= EFI_NOT_READY
) {
2547 EventType
= UiWaitForEvent(gST
->ConIn
->WaitForKey
);
2548 if (EventType
== UIEventKey
) {
2549 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
2554 if (EventType
== UIEventDriver
) {
2555 gUserInput
->Action
= BROWSER_ACTION_NONE
;
2556 ControlFlag
= CfExit
;
2560 if (EventType
== UIEventTimeOut
) {
2561 gUserInput
->Action
= BROWSER_ACTION_FORM_EXIT
;
2562 ControlFlag
= CfExit
;
2566 switch (Key
.UnicodeChar
) {
2567 case CHAR_CARRIAGE_RETURN
:
2568 if(MenuOption
== NULL
|| MenuOption
->GrayOut
|| MenuOption
->ReadOnly
) {
2569 ControlFlag
= CfReadKey
;
2573 ScreenOperation
= UiSelect
;
2578 // We will push the adjustment of these numeric values directly to the input handler
2579 // NOTE: we won't handle manual input numeric
2584 // If the screen has no menu items, and the user didn't select UiReset
2585 // ignore the selection and go back to reading keys.
2587 if(IsListEmpty (&gMenuOption
) || MenuOption
->GrayOut
|| MenuOption
->ReadOnly
) {
2588 ControlFlag
= CfReadKey
;
2592 ASSERT(MenuOption
!= NULL
);
2593 Statement
= MenuOption
->ThisTag
;
2594 if ((Statement
->OpCode
->OpCode
== EFI_IFR_DATE_OP
)
2595 || (Statement
->OpCode
->OpCode
== EFI_IFR_TIME_OP
)
2596 || ((Statement
->OpCode
->OpCode
== EFI_IFR_NUMERIC_OP
) && (GetFieldFromNum(Statement
->OpCode
) != 0))
2598 if (Key
.UnicodeChar
== '+') {
2599 gDirection
= SCAN_RIGHT
;
2601 gDirection
= SCAN_LEFT
;
2604 Status
= ProcessOptions (MenuOption
, TRUE
, &OptionString
, TRUE
);
2605 if (OptionString
!= NULL
) {
2606 FreePool (OptionString
);
2608 if (EFI_ERROR (Status
)) {
2610 // Repaint to clear possible error prompt pop-up
2615 ControlFlag
= CfExit
;
2621 ScreenOperation
= UiUp
;
2626 ScreenOperation
= UiDown
;
2630 if(IsListEmpty (&gMenuOption
)) {
2631 ControlFlag
= CfReadKey
;
2635 ASSERT(MenuOption
!= NULL
);
2636 if (MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_CHECKBOX_OP
&& !MenuOption
->GrayOut
&& !MenuOption
->ReadOnly
) {
2637 ScreenOperation
= UiSelect
;
2643 if (!MultiHelpPage
) {
2644 ControlFlag
= CfReadKey
;
2647 ControlFlag
= CfUpdateHelpString
;
2648 HelpPageIndex
= HelpPageIndex
< HelpPageCount
- 1 ? HelpPageIndex
+ 1 : HelpPageCount
- 1;
2653 if (!MultiHelpPage
) {
2654 ControlFlag
= CfReadKey
;
2657 ControlFlag
= CfUpdateHelpString
;
2658 HelpPageIndex
= HelpPageIndex
> 0 ? HelpPageIndex
- 1 : 0;
2662 for (Index
= 0; Index
< mScanCodeNumber
; Index
++) {
2663 if (Key
.ScanCode
== gScanCodeToOperation
[Index
].ScanCode
) {
2664 ScreenOperation
= gScanCodeToOperation
[Index
].ScreenOperation
;
2669 if (((FormData
->Attribute
& HII_DISPLAY_MODAL
) != 0) && (Key
.ScanCode
== SCAN_ESC
|| Index
== mScanCodeNumber
)) {
2671 // ModalForm has no ESC key and Hot Key.
2673 ControlFlag
= CfReadKey
;
2674 } else if (Index
== mScanCodeNumber
) {
2676 // Check whether Key matches the registered hot key.
2679 HotKey
= GetHotKeyFromRegisterList (&Key
);
2680 if (HotKey
!= NULL
) {
2681 ScreenOperation
= UiHotKey
;
2688 case CfScreenOperation
:
2689 if (ScreenOperation
!= UiReset
) {
2691 // If the screen has no menu items, and the user didn't select UiReset
2692 // ignore the selection and go back to reading keys.
2694 if (IsListEmpty (&gMenuOption
)) {
2695 ControlFlag
= CfReadKey
;
2701 Index
< sizeof (gScreenOperationToControlFlag
) / sizeof (gScreenOperationToControlFlag
[0]);
2704 if (ScreenOperation
== gScreenOperationToControlFlag
[Index
].ScreenOperation
) {
2705 ControlFlag
= gScreenOperationToControlFlag
[Index
].ControlFlag
;
2712 ControlFlag
= CfRepaint
;
2714 ASSERT(MenuOption
!= NULL
);
2715 Statement
= MenuOption
->ThisTag
;
2716 if (Statement
->OpCode
->OpCode
== EFI_IFR_TEXT_OP
) {
2720 switch (Statement
->OpCode
->OpCode
) {
2721 case EFI_IFR_REF_OP
:
2722 case EFI_IFR_ACTION_OP
:
2723 case EFI_IFR_RESET_BUTTON_OP
:
2724 ControlFlag
= CfExit
;
2729 // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
2731 RefreshKeyHelp (gFormData
, Statement
, TRUE
);
2732 Status
= ProcessOptions (MenuOption
, TRUE
, &OptionString
, TRUE
);
2734 if (OptionString
!= NULL
) {
2735 FreePool (OptionString
);
2738 if (EFI_ERROR (Status
)) {
2741 RefreshKeyHelp (gFormData
, Statement
, FALSE
);
2744 ControlFlag
= CfExit
;
2752 // We come here when someone press ESC
2753 // If the policy is not exit front page when user press ESC, process here.
2755 if (!FormExitPolicy()) {
2758 ControlFlag
= CfRepaint
;
2763 // When user press ESC, it will try to show another menu, should clean the gSequence info.
2765 if (gSequence
!= 0) {
2769 gUserInput
->Action
= BROWSER_ACTION_FORM_EXIT
;
2770 ControlFlag
= CfExit
;
2774 ControlFlag
= CfRepaint
;
2776 gUserInput
->Action
= HotKey
->Action
;
2777 ControlFlag
= CfExit
;
2781 ControlFlag
= CfRepaint
;
2782 ASSERT(MenuOption
!= NULL
);
2783 if ((MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_TIME_OP
)) {
2784 if (MenuOption
->Sequence
!= 0) {
2786 // In the middle or tail of the Date/Time op-code set, go left.
2788 ASSERT(NewPos
!= NULL
);
2789 NewPos
= NewPos
->BackLink
;
2795 ControlFlag
= CfRepaint
;
2796 ASSERT(MenuOption
!= NULL
);
2797 if ((MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_DATE_OP
) || (MenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_TIME_OP
)) {
2798 if (MenuOption
->Sequence
!= 2) {
2800 // In the middle or tail of the Date/Time op-code set, go left.
2802 ASSERT(NewPos
!= NULL
);
2803 NewPos
= NewPos
->ForwardLink
;
2809 ControlFlag
= CfRepaint
;
2811 SavedListEntry
= NewPos
;
2813 ASSERT(NewPos
!= NULL
);
2815 // Adjust Date/Time position before we advance forward.
2817 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2818 if (NewPos
->BackLink
!= &gMenuOption
) {
2819 MenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
2820 ASSERT (MenuOption
!= NULL
);
2822 NewPos
= NewPos
->BackLink
;
2824 PreviousMenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
2825 if (PreviousMenuOption
->Row
== 0) {
2826 UpdateOptionSkipLines (PreviousMenuOption
);
2828 DistanceValue
= PreviousMenuOption
->Skip
;
2830 if (MenuOption
->Row
>= DistanceValue
+ TopRow
) {
2831 Difference
= MoveToNextStatement (TRUE
, &NewPos
, MenuOption
->Row
- TopRow
- DistanceValue
);
2833 NextMenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
2835 if (Difference
< 0) {
2837 // We hit the begining MenuOption that can be focused
2838 // so we simply scroll to the top.
2840 if (TopOfScreen
!= gMenuOption
.ForwardLink
) {
2841 TopOfScreen
= gMenuOption
.ForwardLink
;
2845 // Scroll up to the last page when we have arrived at top page.
2847 NewPos
= &gMenuOption
;
2848 TopOfScreen
= &gMenuOption
;
2849 MenuOption
= MENU_OPTION_FROM_LINK (SavedListEntry
);
2850 ScreenOperation
= UiPageUp
;
2851 ControlFlag
= CfScreenOperation
;
2854 } else if (MenuOption
->Row
< TopRow
+ DistanceValue
+ Difference
) {
2856 // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
2858 TopOfScreen
= NewPos
;
2861 } else if (!IsSelectable (NextMenuOption
)) {
2863 // Continue to go up until scroll to next page or the selectable option is found.
2865 ScreenOperation
= UiUp
;
2866 ControlFlag
= CfScreenOperation
;
2870 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2872 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2873 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2874 MenuOption
= MENU_OPTION_FROM_LINK (SavedListEntry
);
2875 UpdateStatusBar (INPUT_ERROR
, FALSE
);
2878 // Scroll up to the last page.
2880 NewPos
= &gMenuOption
;
2881 TopOfScreen
= &gMenuOption
;
2882 MenuOption
= MENU_OPTION_FROM_LINK (SavedListEntry
);
2883 ScreenOperation
= UiPageUp
;
2884 ControlFlag
= CfScreenOperation
;
2890 // SkipValue means lines is skipped when show the top menu option.
2892 ControlFlag
= CfRepaint
;
2894 ASSERT(NewPos
!= NULL
);
2896 // Already at the first menu option, Check the skip value.
2898 if (NewPos
->BackLink
== &gMenuOption
) {
2899 if (SkipValue
== 0) {
2914 // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one
2915 // form of options to be show, so just update the SkipValue to show the next
2916 // parts of options.
2918 if (SkipValue
> (INTN
) (BottomRow
- TopRow
+ 1)) {
2919 SkipValue
-= BottomRow
- TopRow
+ 1;
2925 // First minus the menu of the top screen, it's value is SkipValue.
2927 Index
= (BottomRow
+ 1) - SkipValue
;
2928 while ((Index
> TopRow
) && (Link
->BackLink
!= &gMenuOption
)) {
2929 Link
= Link
->BackLink
;
2930 PreviousMenuOption
= MENU_OPTION_FROM_LINK (Link
);
2931 if (PreviousMenuOption
->Row
== 0) {
2932 UpdateOptionSkipLines (PreviousMenuOption
);
2934 if (Index
< PreviousMenuOption
->Skip
) {
2937 Index
= Index
- PreviousMenuOption
->Skip
;
2940 if ((Link
->BackLink
== &gMenuOption
) && (Index
>= TopRow
)) {
2942 if (TopOfScreen
== &gMenuOption
) {
2943 TopOfScreen
= gMenuOption
.ForwardLink
;
2944 NewPos
= gMenuOption
.BackLink
;
2945 MoveToNextStatement (TRUE
, &NewPos
, BottomRow
- TopRow
);
2947 } else if (TopOfScreen
!= Link
) {
2950 MoveToNextStatement (FALSE
, &NewPos
, BottomRow
- TopRow
);
2953 // Finally we know that NewPos is the last MenuOption can be focused.
2957 MoveToNextStatement (FALSE
, &NewPos
, BottomRow
- TopRow
);
2960 if (Index
> TopRow
) {
2962 // At here, only case "Index < PreviousMenuOption->Skip" can reach here.
2964 SkipValue
= PreviousMenuOption
->Skip
- (Index
- TopRow
);
2965 } else if (Index
== TopRow
) {
2968 SkipValue
= TopRow
- Index
;
2972 // Move to the option in Next page.
2974 if (TopOfScreen
== &gMenuOption
) {
2975 NewPos
= gMenuOption
.BackLink
;
2976 MoveToNextStatement (TRUE
, &NewPos
, BottomRow
- TopRow
);
2979 MoveToNextStatement (FALSE
, &NewPos
, BottomRow
- TopRow
);
2983 // There are more MenuOption needing scrolling up.
2990 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
2991 // Don't do this when we are already in the first page.
2993 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
2994 AdjustDateAndTimePosition (TRUE
, &NewPos
);
2999 // SkipValue means lines is skipped when show the top menu option.
3001 ControlFlag
= CfRepaint
;
3003 ASSERT (NewPos
!= NULL
);
3004 if (NewPos
->ForwardLink
== &gMenuOption
) {
3013 NextMenuOption
= MENU_OPTION_FROM_LINK (Link
);
3014 Index
= TopRow
+ NextMenuOption
->Skip
- SkipValue
;
3016 // Count to the menu option which will show at the top of the next form.
3018 while ((Index
<= BottomRow
+ 1) && (Link
->ForwardLink
!= &gMenuOption
)) {
3019 Link
= Link
->ForwardLink
;
3020 NextMenuOption
= MENU_OPTION_FROM_LINK (Link
);
3021 Index
= Index
+ NextMenuOption
->Skip
;
3024 if ((Link
->ForwardLink
== &gMenuOption
) && (Index
<= BottomRow
+ 1)) {
3026 // Finally we know that NewPos is the last MenuOption can be focused.
3029 MoveToNextStatement (TRUE
, &Link
, Index
- TopRow
);
3032 // Calculate the skip line for top of screen menu.
3034 if (Link
== TopOfScreen
) {
3036 // The top of screen menu option occupies the entire form.
3038 SkipValue
+= BottomRow
- TopRow
+ 1;
3040 SkipValue
= NextMenuOption
->Skip
- (Index
- (BottomRow
+ 1));
3046 // Move to the Next selectable menu.
3048 MoveToNextStatement (FALSE
, &Link
, BottomRow
- TopRow
);
3052 // Save the menu as the next highlight menu.
3057 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
3058 // Don't do this when we are already in the last page.
3060 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
3061 AdjustDateAndTimePosition (TRUE
, &NewPos
);
3066 // SkipValue means lines is skipped when show the top menu option.
3067 // NewPos points to the menu which is highlighted now.
3069 ControlFlag
= CfRepaint
;
3072 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
3073 // to be one that progresses to the next set of op-codes, we need to advance to the last
3074 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
3075 // checking can be done. The only other logic we need to introduce is that if a Date/Time
3076 // op-code is the last entry in the menu, we need to rewind back to the first op-code of
3077 // the Date/Time op-code.
3079 SavedListEntry
= NewPos
;
3080 AdjustDateAndTimePosition (FALSE
, &NewPos
);
3082 if (NewPos
->ForwardLink
!= &gMenuOption
) {
3083 MenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
3085 NewPos
= NewPos
->ForwardLink
;
3089 // Current menu not at the bottom of the form.
3091 if (BottomRow
>= MenuOption
->Row
+ MenuOption
->Skip
) {
3093 // Find the next selectable menu.
3095 Difference
= MoveToNextStatement (FALSE
, &NewPos
, BottomRow
- MenuOption
->Row
- MenuOption
->Skip
);
3097 // We hit the end of MenuOption that can be focused
3098 // so we simply scroll to the first page.
3100 if (Difference
< 0) {
3102 // Scroll to the first page.
3104 if (TopOfScreen
!= gMenuOption
.ForwardLink
) {
3105 TopOfScreen
= gMenuOption
.ForwardLink
;
3109 MenuOption
= MENU_OPTION_FROM_LINK (SavedListEntry
);
3111 NewPos
= gMenuOption
.ForwardLink
;
3112 MoveToNextStatement (FALSE
, &NewPos
, BottomRow
- TopRow
);
3116 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
3118 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
3119 AdjustDateAndTimePosition (TRUE
, &NewPos
);
3123 NextMenuOption
= MENU_OPTION_FROM_LINK (NewPos
);
3124 if (NextMenuOption
->Row
== 0) {
3125 UpdateOptionSkipLines (NextMenuOption
);
3127 DistanceValue
= Difference
+ NextMenuOption
->Skip
;
3129 Temp
= MenuOption
->Row
+ MenuOption
->Skip
+ DistanceValue
- 1;
3130 if ((MenuOption
->Row
+ MenuOption
->Skip
== BottomRow
+ 1) &&
3131 (NextMenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_DATE_OP
||
3132 NextMenuOption
->ThisTag
->OpCode
->OpCode
== EFI_IFR_TIME_OP
)
3138 // If we are going to scroll, update TopOfScreen
3140 if (Temp
> BottomRow
) {
3143 // Is the current top of screen a zero-advance op-code?
3144 // If so, keep moving forward till we hit a >0 advance op-code
3146 SavedMenuOption
= MENU_OPTION_FROM_LINK (TopOfScreen
);
3149 // If bottom op-code is more than one line or top op-code is more than one line
3151 if ((DistanceValue
> 1) || (SavedMenuOption
->Skip
> 1)) {
3153 // Is the bottom op-code greater than or equal in size to the top op-code?
3155 if ((Temp
- BottomRow
) >= (SavedMenuOption
->Skip
- SkipValue
)) {
3157 // Skip the top op-code
3159 TopOfScreen
= TopOfScreen
->ForwardLink
;
3160 Difference
= (Temp
- BottomRow
) - (SavedMenuOption
->Skip
- SkipValue
);
3162 SavedMenuOption
= MENU_OPTION_FROM_LINK (TopOfScreen
);
3165 // If we have a remainder, skip that many more op-codes until we drain the remainder
3167 while (Difference
>= (INTN
) SavedMenuOption
->Skip
) {
3169 // Since the Difference is greater than or equal to this op-code's skip value, skip it
3171 Difference
= Difference
- (INTN
) SavedMenuOption
->Skip
;
3172 TopOfScreen
= TopOfScreen
->ForwardLink
;
3173 SavedMenuOption
= MENU_OPTION_FROM_LINK (TopOfScreen
);
3176 // Since we will act on this op-code in the next routine, and increment the
3177 // SkipValue, set the skips to one less than what is required.
3179 SkipValue
= Difference
- 1;
3182 // Since we will act on this op-code in the next routine, and increment the
3183 // SkipValue, set the skips to one less than what is required.
3185 SkipValue
+= (Temp
- BottomRow
) - 1;
3188 if ((SkipValue
+ 1) == (INTN
) SavedMenuOption
->Skip
) {
3189 TopOfScreen
= TopOfScreen
->ForwardLink
;
3194 // If the op-code at the top of the screen is more than one line, let's not skip it yet
3195 // Let's set a skip flag to smoothly scroll the top of the screen.
3197 if (SavedMenuOption
->Skip
> 1) {
3198 if (SavedMenuOption
== NextMenuOption
) {
3203 } else if (SavedMenuOption
->Skip
== 1) {
3207 TopOfScreen
= TopOfScreen
->ForwardLink
;
3209 } while (SavedMenuOption
->Skip
== 0);
3212 } else if (!IsSelectable (NextMenuOption
)) {
3214 // Continue to go down until scroll to next page or the selectable option is found.
3216 ScreenOperation
= UiDown
;
3217 ControlFlag
= CfScreenOperation
;
3220 MenuOption
= MENU_OPTION_FROM_LINK (SavedListEntry
);
3222 UpdateStatusBar (INPUT_ERROR
, FALSE
);
3226 // Scroll to the first page.
3228 if (TopOfScreen
!= gMenuOption
.ForwardLink
) {
3229 TopOfScreen
= gMenuOption
.ForwardLink
;
3234 // Need to remove the current highlight menu.
3235 // MenuOption saved the last highlight menu info.
3237 MenuOption
= MENU_OPTION_FROM_LINK (SavedListEntry
);
3243 // Get the next highlight menu.
3245 NewPos
= gMenuOption
.ForwardLink
;
3246 MoveToNextStatement (FALSE
, &NewPos
, BottomRow
- TopRow
);
3250 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
3252 AdjustDateAndTimePosition (TRUE
, &TopOfScreen
);
3253 AdjustDateAndTimePosition (TRUE
, &NewPos
);
3256 case CfUiNoOperation
:
3257 ControlFlag
= CfRepaint
;
3261 gST
->ConOut
->SetAttribute (gST
->ConOut
, EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
));
3262 if (HelpString
!= NULL
) {
3263 FreePool (HelpString
);
3265 if (HelpHeaderString
!= NULL
) {
3266 FreePool (HelpHeaderString
);
3268 if (HelpBottomString
!= NULL
) {
3269 FreePool (HelpBottomString
);
3281 Base on the browser status info to show an pop up message.
3285 BrowserStatusProcess (
3292 if (gFormData
->BrowserStatus
== BROWSER_SUCCESS
) {
3296 if (gFormData
->ErrorString
!= NULL
) {
3297 ErrorInfo
= gFormData
->ErrorString
;
3299 switch (gFormData
->BrowserStatus
) {
3300 case BROWSER_SUBMIT_FAIL
:
3301 ErrorInfo
= gSaveFailed
;
3304 case BROWSER_NO_SUBMIT_IF
:
3305 ErrorInfo
= gNoSubmitIf
;
3308 case BROWSER_FORM_NOT_FOUND
:
3309 ErrorInfo
= gFormNotFound
;
3312 case BROWSER_FORM_SUPPRESS
:
3313 ErrorInfo
= gFormSuppress
;
3316 case BROWSER_PROTOCOL_NOT_FOUND
:
3317 ErrorInfo
= gProtocolNotFound
;
3321 ErrorInfo
= gBrwoserError
;
3327 // Error occur, prompt error message.
3330 CreateDialog (&Key
, gEmptyString
, ErrorInfo
, gPressEnter
, gEmptyString
, NULL
);
3331 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
3335 Display one form, and return user input.
3337 @param FormData Form Data to be shown.
3338 @param UserInputData User input data.
3340 @retval EFI_SUCCESS 1.Form Data is shown, and user input is got.
3341 2.Error info has show and return.
3342 @retval EFI_INVALID_PARAMETER The input screen dimension is not valid
3343 @retval EFI_NOT_FOUND New form data has some error.
3348 IN FORM_DISPLAY_ENGINE_FORM
*FormData
,
3349 OUT USER_INPUT
*UserInputData
3354 ASSERT (FormData
!= NULL
);
3355 if (FormData
== NULL
) {
3356 return EFI_INVALID_PARAMETER
;
3359 gUserInput
= UserInputData
;
3360 gFormData
= FormData
;
3363 // Process the status info first.
3365 BrowserStatusProcess();
3366 if (UserInputData
== NULL
) {
3368 // UserInputData == NULL, means only need to print the error info, return here.
3373 ConvertStatementToMenu();
3375 Status
= DisplayPageFrame (FormData
, &gStatementDimensions
);
3376 if (EFI_ERROR (Status
)) {
3381 // Check whether layout is changed.
3384 || (gOldFormEntry
.HiiHandle
!= FormData
->HiiHandle
)
3385 || (!CompareGuid (&gOldFormEntry
.FormSetGuid
, &FormData
->FormSetGuid
))
3386 || (gOldFormEntry
.FormId
!= FormData
->FormId
)) {
3387 mStatementLayoutIsChanged
= TRUE
;
3389 mStatementLayoutIsChanged
= FALSE
;
3392 Status
= UiDisplayMenu(FormData
);
3395 // Backup last form info.
3397 mIsFirstForm
= FALSE
;
3398 gOldFormEntry
.HiiHandle
= FormData
->HiiHandle
;
3399 CopyGuid (&gOldFormEntry
.FormSetGuid
, &FormData
->FormSetGuid
);
3400 gOldFormEntry
.FormId
= FormData
->FormId
;
3406 Clear Screen to the initial state.
3410 DriverClearDisplayPage (
3414 ClearDisplayPage ();
3415 mIsFirstForm
= TRUE
;
3419 Set Buffer to Value for Size bytes.
3421 @param Buffer Memory to set.
3422 @param Size Number of bytes to set
3423 @param Value Value of the set operation.
3436 while ((Size
--) != 0) {
3442 Initialize Setup Browser driver.
3444 @param ImageHandle The image handle.
3445 @param SystemTable The system table.
3447 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
3448 @return Other value if failed to initialize the Setup Browser module.
3453 InitializeDisplayEngine (
3454 IN EFI_HANDLE ImageHandle
,
3455 IN EFI_SYSTEM_TABLE
*SystemTable
3459 EFI_INPUT_KEY HotKey
;
3460 EFI_STRING NewString
;
3461 EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL
*FormBrowserEx2
;
3464 // Publish our HII data
3466 gHiiHandle
= HiiAddPackages (
3467 &gDisplayEngineGuid
,
3469 DisplayEngineStrings
,
3472 ASSERT (gHiiHandle
!= NULL
);
3475 // Install Form Display protocol
3477 Status
= gBS
->InstallProtocolInterface (
3478 &mPrivateData
.Handle
,
3479 &gEdkiiFormDisplayEngineProtocolGuid
,
3480 EFI_NATIVE_INTERFACE
,
3481 &mPrivateData
.FromDisplayProt
3483 ASSERT_EFI_ERROR (Status
);
3485 InitializeDisplayStrings();
3487 ZeroMem (&gHighligthMenuInfo
, sizeof (gHighligthMenuInfo
));
3488 ZeroMem (&gOldFormEntry
, sizeof (gOldFormEntry
));
3491 // Use BrowserEx2 protocol to register HotKey.
3493 Status
= gBS
->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid
, NULL
, (VOID
**) &FormBrowserEx2
);
3494 if (!EFI_ERROR (Status
)) {
3496 // Register the default HotKey F9 and F10 again.
3498 HotKey
.UnicodeChar
= CHAR_NULL
;
3499 HotKey
.ScanCode
= SCAN_F10
;
3500 NewString
= HiiGetString (gHiiHandle
, STRING_TOKEN (FUNCTION_TEN_STRING
), NULL
);
3501 ASSERT (NewString
!= NULL
);
3502 FormBrowserEx2
->RegisterHotKey (&HotKey
, BROWSER_ACTION_SUBMIT
, 0, NewString
);
3504 HotKey
.ScanCode
= SCAN_F9
;
3505 NewString
= HiiGetString (gHiiHandle
, STRING_TOKEN (FUNCTION_NINE_STRING
), NULL
);
3506 ASSERT (NewString
!= NULL
);
3507 FormBrowserEx2
->RegisterHotKey (&HotKey
, BROWSER_ACTION_DEFAULT
, EFI_HII_DEFAULT_CLASS_STANDARD
, NewString
);
3514 This is the default unload handle for display core drivers.
3516 @param[in] ImageHandle The drivers' driver image.
3518 @retval EFI_SUCCESS The image is unloaded.
3519 @retval Others Failed to unload the image.
3524 UnloadDisplayEngine (
3525 IN EFI_HANDLE ImageHandle
3528 HiiRemovePackages(gHiiHandle
);
3530 FreeDisplayStrings ();