mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 03:03:46 +01:00 
			
		
		
		
	REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			4338 lines
		
	
	
		
			131 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			4338 lines
		
	
	
		
			131 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| Entry and initialization module for the browser.
 | |
| 
 | |
| Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "FormDisplay.h"
 | |
| 
 | |
| //
 | |
| // Search table for UiDisplayMenu()
 | |
| //
 | |
| SCAN_CODE_TO_SCREEN_OPERATION  gScanCodeToOperation[] = {
 | |
|   {
 | |
|     SCAN_UP,
 | |
|     UiUp,
 | |
|   },
 | |
|   {
 | |
|     SCAN_DOWN,
 | |
|     UiDown,
 | |
|   },
 | |
|   {
 | |
|     SCAN_PAGE_UP,
 | |
|     UiPageUp,
 | |
|   },
 | |
|   {
 | |
|     SCAN_PAGE_DOWN,
 | |
|     UiPageDown,
 | |
|   },
 | |
|   {
 | |
|     SCAN_ESC,
 | |
|     UiReset,
 | |
|   },
 | |
|   {
 | |
|     SCAN_LEFT,
 | |
|     UiLeft,
 | |
|   },
 | |
|   {
 | |
|     SCAN_RIGHT,
 | |
|     UiRight,
 | |
|   }
 | |
| };
 | |
| 
 | |
| UINTN  mScanCodeNumber = ARRAY_SIZE (gScanCodeToOperation);
 | |
| 
 | |
| SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
 | |
|   {
 | |
|     UiNoOperation,
 | |
|     CfUiNoOperation,
 | |
|   },
 | |
|   {
 | |
|     UiSelect,
 | |
|     CfUiSelect,
 | |
|   },
 | |
|   {
 | |
|     UiUp,
 | |
|     CfUiUp,
 | |
|   },
 | |
|   {
 | |
|     UiDown,
 | |
|     CfUiDown,
 | |
|   },
 | |
|   {
 | |
|     UiLeft,
 | |
|     CfUiLeft,
 | |
|   },
 | |
|   {
 | |
|     UiRight,
 | |
|     CfUiRight,
 | |
|   },
 | |
|   {
 | |
|     UiReset,
 | |
|     CfUiReset,
 | |
|   },
 | |
|   {
 | |
|     UiPageUp,
 | |
|     CfUiPageUp,
 | |
|   },
 | |
|   {
 | |
|     UiPageDown,
 | |
|     CfUiPageDown
 | |
|   },
 | |
|   {
 | |
|     UiHotKey,
 | |
|     CfUiHotKey
 | |
|   }
 | |
| };
 | |
| 
 | |
| EFI_GUID  gDisplayEngineGuid = {
 | |
|   0xE38C1029, 0xE38F, 0x45b9, { 0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62 }
 | |
| };
 | |
| 
 | |
| BOOLEAN                      gMisMatch;
 | |
| EFI_SCREEN_DESCRIPTOR        gStatementDimensions;
 | |
| BOOLEAN                      mStatementLayoutIsChanged = TRUE;
 | |
| USER_INPUT                   *gUserInput;
 | |
| FORM_DISPLAY_ENGINE_FORM     *gFormData;
 | |
| EFI_HII_HANDLE               gHiiHandle;
 | |
| UINT16                       gDirection;
 | |
| LIST_ENTRY                   gMenuOption;
 | |
| DISPLAY_HIGHLIGHT_MENU_INFO  gHighligthMenuInfo = { 0 };
 | |
| BOOLEAN                      mIsFirstForm       = TRUE;
 | |
| FORM_ENTRY_INFO              gOldFormEntry      = { 0 };
 | |
| 
 | |
| //
 | |
| // Browser Global Strings
 | |
| //
 | |
| CHAR16  *gReconnectConfirmChanges;
 | |
| CHAR16  *gReconnectFail;
 | |
| CHAR16  *gReconnectRequired;
 | |
| CHAR16  *gChangesOpt;
 | |
| CHAR16  *gFormNotFound;
 | |
| CHAR16  *gNoSubmitIf;
 | |
| CHAR16  *gBrowserError;
 | |
| CHAR16  *gSaveFailed;
 | |
| CHAR16  *gNoSubmitIfFailed;
 | |
| CHAR16  *gSaveProcess;
 | |
| CHAR16  *gSaveNoSubmitProcess;
 | |
| CHAR16  *gDiscardChange;
 | |
| CHAR16  *gJumpToFormSet;
 | |
| CHAR16  *gCheckError;
 | |
| CHAR16  *gPromptForData;
 | |
| CHAR16  *gPromptForPassword;
 | |
| CHAR16  *gPromptForNewPassword;
 | |
| CHAR16  *gConfirmPassword;
 | |
| CHAR16  *gConfirmError;
 | |
| CHAR16  *gPassowordInvalid;
 | |
| CHAR16  *gPressEnter;
 | |
| CHAR16  *gEmptyString;
 | |
| CHAR16  *gMiniString;
 | |
| CHAR16  *gOptionMismatch;
 | |
| CHAR16  *gFormSuppress;
 | |
| CHAR16  *gProtocolNotFound;
 | |
| CHAR16  *gConfirmDefaultMsg;
 | |
| CHAR16  *gConfirmSubmitMsg;
 | |
| CHAR16  *gConfirmDiscardMsg;
 | |
| CHAR16  *gConfirmResetMsg;
 | |
| CHAR16  *gConfirmExitMsg;
 | |
| CHAR16  *gConfirmSubmitMsg2nd;
 | |
| CHAR16  *gConfirmDefaultMsg2nd;
 | |
| CHAR16  *gConfirmResetMsg2nd;
 | |
| CHAR16  *gConfirmExitMsg2nd;
 | |
| CHAR16  *gConfirmOpt;
 | |
| CHAR16  *gConfirmOptYes;
 | |
| CHAR16  *gConfirmOptNo;
 | |
| CHAR16  *gConfirmOptOk;
 | |
| CHAR16  *gConfirmOptCancel;
 | |
| CHAR16  *gYesOption;
 | |
| CHAR16  *gNoOption;
 | |
| CHAR16  *gOkOption;
 | |
| CHAR16  *gCancelOption;
 | |
| CHAR16  *gErrorPopup;
 | |
| CHAR16  *gWarningPopup;
 | |
| CHAR16  *gInfoPopup;
 | |
| CHAR16  *gConfirmMsgConnect;
 | |
| CHAR16  *gConfirmMsgEnd;
 | |
| CHAR16  *gPasswordUnsupported;
 | |
| CHAR16  gModalSkipColumn;
 | |
| CHAR16  gPromptBlockWidth;
 | |
| CHAR16  gOptionBlockWidth;
 | |
| CHAR16  gHelpBlockWidth;
 | |
| CHAR16  *mUnknownString;
 | |
| 
 | |
| FORM_DISPLAY_DRIVER_PRIVATE_DATA  mPrivateData = {
 | |
|   FORM_DISPLAY_DRIVER_SIGNATURE,
 | |
|   NULL,
 | |
|   {
 | |
|     FormDisplay,
 | |
|     DriverClearDisplayPage,
 | |
|     ConfirmDataChange
 | |
|   },
 | |
|   {
 | |
|     EFI_HII_POPUP_PROTOCOL_REVISION,
 | |
|     CreatePopup
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Get the string based on the StringId and HII Package List Handle.
 | |
| 
 | |
|   @param  Token                  The String's ID.
 | |
|   @param  HiiHandle              The package list in the HII database to search for
 | |
|                                  the specified string.
 | |
| 
 | |
|   @return The output string.
 | |
| 
 | |
| **/
 | |
| CHAR16 *
 | |
| GetToken (
 | |
|   IN  EFI_STRING_ID   Token,
 | |
|   IN  EFI_HII_HANDLE  HiiHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STRING  String;
 | |
| 
 | |
|   String = HiiGetString (HiiHandle, Token, NULL);
 | |
|   if (String == NULL) {
 | |
|     String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);
 | |
|     ASSERT (String != NULL);
 | |
|   }
 | |
| 
 | |
|   return (CHAR16 *)String;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize the HII String Token to the correct values.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| InitializeDisplayStrings (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   gReconnectConfirmChanges = GetToken (STRING_TOKEN (RECONNECT_CONFIRM_CHANGES), gHiiHandle);
 | |
|   mUnknownString           = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);
 | |
|   gSaveFailed              = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
 | |
|   gNoSubmitIfFailed        = GetToken (STRING_TOKEN (NO_SUBMIT_IF_CHECK_FAILED), gHiiHandle);
 | |
|   gReconnectFail           = GetToken (STRING_TOKEN (RECONNECT_FAILED), gHiiHandle);
 | |
|   gReconnectRequired       = GetToken (STRING_TOKEN (RECONNECT_REQUIRED), gHiiHandle);
 | |
|   gChangesOpt              = GetToken (STRING_TOKEN (RECONNECT_CHANGES_OPTIONS), gHiiHandle);
 | |
|   gSaveProcess             = GetToken (STRING_TOKEN (DISCARD_OR_JUMP), gHiiHandle);
 | |
|   gSaveNoSubmitProcess     = GetToken (STRING_TOKEN (DISCARD_OR_CHECK), gHiiHandle);
 | |
|   gDiscardChange           = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_DISCARD), gHiiHandle);
 | |
|   gJumpToFormSet           = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_JUMP), gHiiHandle);
 | |
|   gCheckError              = GetToken (STRING_TOKEN (DISCARD_OR_CHECK_CHECK), gHiiHandle);
 | |
|   gPromptForData           = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
 | |
|   gPromptForPassword       = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
 | |
|   gPromptForNewPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
 | |
|   gConfirmPassword         = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
 | |
|   gConfirmError            = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
 | |
|   gPassowordInvalid        = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
 | |
|   gPressEnter              = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
 | |
|   gEmptyString             = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
 | |
|   gMiniString              = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
 | |
|   gOptionMismatch          = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);
 | |
|   gFormSuppress            = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);
 | |
|   gProtocolNotFound        = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);
 | |
|   gFormNotFound            = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle);
 | |
|   gNoSubmitIf              = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle);
 | |
|   gBrowserError            = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);
 | |
|   gConfirmDefaultMsg       = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE), gHiiHandle);
 | |
|   gConfirmDiscardMsg       = GetToken (STRING_TOKEN (CONFIRM_DISCARD_MESSAGE), gHiiHandle);
 | |
|   gConfirmSubmitMsg        = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE), gHiiHandle);
 | |
|   gConfirmResetMsg         = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE), gHiiHandle);
 | |
|   gConfirmExitMsg          = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE), gHiiHandle);
 | |
|   gConfirmDefaultMsg2nd    = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE_2ND), gHiiHandle);
 | |
|   gConfirmSubmitMsg2nd     = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE_2ND), gHiiHandle);
 | |
|   gConfirmResetMsg2nd      = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE_2ND), gHiiHandle);
 | |
|   gConfirmExitMsg2nd       = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE_2ND), gHiiHandle);
 | |
|   gConfirmOpt              = GetToken (STRING_TOKEN (CONFIRM_OPTION), gHiiHandle);
 | |
|   gConfirmOptYes           = GetToken (STRING_TOKEN (CONFIRM_OPTION_YES), gHiiHandle);
 | |
|   gConfirmOptNo            = GetToken (STRING_TOKEN (CONFIRM_OPTION_NO), gHiiHandle);
 | |
|   gConfirmOptOk            = GetToken (STRING_TOKEN (CONFIRM_OPTION_OK), gHiiHandle);
 | |
|   gConfirmOptCancel        = GetToken (STRING_TOKEN (CONFIRM_OPTION_CANCEL), gHiiHandle);
 | |
|   gYesOption               = GetToken (STRING_TOKEN (YES_SELECTABLE_OPTION), gHiiHandle);
 | |
|   gNoOption                = GetToken (STRING_TOKEN (NO_SELECTABLE_OPTION), gHiiHandle);
 | |
|   gOkOption                = GetToken (STRING_TOKEN (OK_SELECTABLE_OPTION), gHiiHandle);
 | |
|   gCancelOption            = GetToken (STRING_TOKEN (CANCEL_SELECTABLE_OPTION), gHiiHandle);
 | |
|   gErrorPopup              = GetToken (STRING_TOKEN (ERROR_POPUP_STRING), gHiiHandle);
 | |
|   gWarningPopup            = GetToken (STRING_TOKEN (WARNING_POPUP_STRING), gHiiHandle);
 | |
|   gInfoPopup               = GetToken (STRING_TOKEN (INFO_POPUP_STRING), gHiiHandle);
 | |
|   gConfirmMsgConnect       = GetToken (STRING_TOKEN (CONFIRM_OPTION_CONNECT), gHiiHandle);
 | |
|   gConfirmMsgEnd           = GetToken (STRING_TOKEN (CONFIRM_OPTION_END), gHiiHandle);
 | |
|   gPasswordUnsupported     = GetToken (STRING_TOKEN (PASSWORD_NOT_SUPPORTED), gHiiHandle);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Free up the resource allocated for all strings required
 | |
|   by Setup Browser.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FreeDisplayStrings (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   FreePool (mUnknownString);
 | |
|   FreePool (gEmptyString);
 | |
|   FreePool (gSaveFailed);
 | |
|   FreePool (gNoSubmitIfFailed);
 | |
|   FreePool (gReconnectFail);
 | |
|   FreePool (gReconnectRequired);
 | |
|   FreePool (gChangesOpt);
 | |
|   FreePool (gReconnectConfirmChanges);
 | |
|   FreePool (gSaveProcess);
 | |
|   FreePool (gSaveNoSubmitProcess);
 | |
|   FreePool (gDiscardChange);
 | |
|   FreePool (gJumpToFormSet);
 | |
|   FreePool (gCheckError);
 | |
|   FreePool (gPromptForData);
 | |
|   FreePool (gPromptForPassword);
 | |
|   FreePool (gPromptForNewPassword);
 | |
|   FreePool (gConfirmPassword);
 | |
|   FreePool (gConfirmError);
 | |
|   FreePool (gPassowordInvalid);
 | |
|   FreePool (gPressEnter);
 | |
|   FreePool (gMiniString);
 | |
|   FreePool (gOptionMismatch);
 | |
|   FreePool (gFormSuppress);
 | |
|   FreePool (gProtocolNotFound);
 | |
|   FreePool (gBrowserError);
 | |
|   FreePool (gNoSubmitIf);
 | |
|   FreePool (gFormNotFound);
 | |
|   FreePool (gConfirmDefaultMsg);
 | |
|   FreePool (gConfirmSubmitMsg);
 | |
|   FreePool (gConfirmDiscardMsg);
 | |
|   FreePool (gConfirmResetMsg);
 | |
|   FreePool (gConfirmExitMsg);
 | |
|   FreePool (gConfirmDefaultMsg2nd);
 | |
|   FreePool (gConfirmSubmitMsg2nd);
 | |
|   FreePool (gConfirmResetMsg2nd);
 | |
|   FreePool (gConfirmExitMsg2nd);
 | |
|   FreePool (gConfirmOpt);
 | |
|   FreePool (gConfirmOptYes);
 | |
|   FreePool (gConfirmOptNo);
 | |
|   FreePool (gConfirmOptOk);
 | |
|   FreePool (gConfirmOptCancel);
 | |
|   FreePool (gYesOption);
 | |
|   FreePool (gNoOption);
 | |
|   FreePool (gOkOption);
 | |
|   FreePool (gCancelOption);
 | |
|   FreePool (gErrorPopup);
 | |
|   FreePool (gWarningPopup);
 | |
|   FreePool (gInfoPopup);
 | |
|   FreePool (gConfirmMsgConnect);
 | |
|   FreePool (gConfirmMsgEnd);
 | |
|   FreePool (gPasswordUnsupported);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get prompt string id from the opcode data buffer.
 | |
| 
 | |
|   @param  OpCode                 The input opcode buffer.
 | |
| 
 | |
|   @return The prompt string id.
 | |
| 
 | |
| **/
 | |
| EFI_STRING_ID
 | |
| GetPrompt (
 | |
|   IN EFI_IFR_OP_HEADER  *OpCode
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_STATEMENT_HEADER  *Header;
 | |
| 
 | |
|   if (OpCode->Length <= sizeof (EFI_IFR_OP_HEADER)) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   Header = (EFI_IFR_STATEMENT_HEADER  *)(OpCode + 1);
 | |
| 
 | |
|   return Header->Prompt;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the supported width for a particular op-code
 | |
| 
 | |
|   @param  MenuOption             The menu option.
 | |
|   @param  AdjustWidth            The width which is saved for the space.
 | |
| 
 | |
|   @return Returns the number of CHAR16 characters that is support.
 | |
| 
 | |
| **/
 | |
| UINT16
 | |
| GetWidth (
 | |
|   IN  UI_MENU_OPTION  *MenuOption,
 | |
|   OUT UINT16          *AdjustWidth
 | |
|   )
 | |
| {
 | |
|   CHAR16                         *String;
 | |
|   UINTN                          Size;
 | |
|   EFI_IFR_TEXT                   *TextOp;
 | |
|   UINT16                         ReturnWidth;
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
| 
 | |
|   Statement = MenuOption->ThisTag;
 | |
| 
 | |
|   //
 | |
|   // For modal form, clean the entire row.
 | |
|   //
 | |
|   if ((gFormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|     if (AdjustWidth  != NULL) {
 | |
|       *AdjustWidth = LEFT_SKIPPED_COLUMNS;
 | |
|     }
 | |
| 
 | |
|     return (UINT16)(gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gModalSkipColumn + LEFT_SKIPPED_COLUMNS));
 | |
|   }
 | |
| 
 | |
|   Size = 0;
 | |
| 
 | |
|   //
 | |
|   // See if the second text parameter is really NULL
 | |
|   //
 | |
|   if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
 | |
|     TextOp = (EFI_IFR_TEXT *)Statement->OpCode;
 | |
|     if (TextOp->TextTwo != 0) {
 | |
|       String = GetToken (TextOp->TextTwo, gFormData->HiiHandle);
 | |
|       Size   = StrLen (String);
 | |
|       FreePool (String);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||
 | |
|       //
 | |
|       // Allow a wide display if text op-code and no secondary text op-code
 | |
|       //
 | |
|       ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))
 | |
|       )
 | |
|   {
 | |
|     //
 | |
|     // Return the space width.
 | |
|     //
 | |
|     if (AdjustWidth != NULL) {
 | |
|       *AdjustWidth = 2;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Keep consistent with current behavior.
 | |
|     //
 | |
|     ReturnWidth = (UINT16)(gPromptBlockWidth + gOptionBlockWidth - 2);
 | |
|   } else {
 | |
|     if (AdjustWidth != NULL) {
 | |
|       *AdjustWidth = 1;
 | |
|     }
 | |
| 
 | |
|     ReturnWidth =  (UINT16)(gPromptBlockWidth - 1);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // For nest in statement, should the subtitle indent.
 | |
|   //
 | |
|   if (MenuOption->NestInStatement) {
 | |
|     ReturnWidth -= SUBTITLE_INDENT;
 | |
|   }
 | |
| 
 | |
|   return ReturnWidth;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Will copy LineWidth amount of a string in the OutputString buffer and return the
 | |
|   number of CHAR16 characters that were copied into the OutputString buffer.
 | |
|   The output string format is:
 | |
|     Glyph Info + String info + '\0'.
 | |
| 
 | |
|   In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
 | |
| 
 | |
|   @param  InputString            String description for this option.
 | |
|   @param  LineWidth              Width of the desired string to extract in CHAR16
 | |
|                                  characters
 | |
|   @param  GlyphWidth             The glyph width of the begin of the char in the string.
 | |
|   @param  Index                  Where in InputString to start the copy process
 | |
|   @param  OutputString           Buffer to copy the string into
 | |
| 
 | |
|   @return Returns the number of CHAR16 characters that were copied into the OutputString
 | |
|   buffer, include extra glyph info and '\0' info.
 | |
| 
 | |
| **/
 | |
| UINT16
 | |
| GetLineByWidth (
 | |
|   IN      CHAR16  *InputString,
 | |
|   IN      UINT16  LineWidth,
 | |
|   IN OUT  UINT16  *GlyphWidth,
 | |
|   IN OUT  UINTN   *Index,
 | |
|   OUT     CHAR16  **OutputString
 | |
|   )
 | |
| {
 | |
|   UINT16   StrOffset;
 | |
|   UINT16   GlyphOffset;
 | |
|   UINT16   OriginalGlyphWidth;
 | |
|   BOOLEAN  ReturnFlag;
 | |
|   UINT16   LastSpaceOffset;
 | |
|   UINT16   LastGlyphWidth;
 | |
| 
 | |
|   if ((InputString == NULL) || (Index == NULL) || (OutputString == NULL)) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   if ((LineWidth == 0) || (*GlyphWidth == 0)) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Save original glyph width.
 | |
|   //
 | |
|   OriginalGlyphWidth = *GlyphWidth;
 | |
|   LastGlyphWidth     = OriginalGlyphWidth;
 | |
|   ReturnFlag         = FALSE;
 | |
|   LastSpaceOffset    = 0;
 | |
| 
 | |
|   //
 | |
|   // 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.
 | |
|   // To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
 | |
|   //
 | |
|   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
 | |
|     *Index = *Index + 2;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fast-forward the string and see if there is a carriage-return in the string
 | |
|   //
 | |
|   for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {
 | |
|     switch (InputString[*Index + StrOffset]) {
 | |
|       case NARROW_CHAR:
 | |
|         *GlyphWidth = 1;
 | |
|         break;
 | |
| 
 | |
|       case WIDE_CHAR:
 | |
|         *GlyphWidth = 2;
 | |
|         break;
 | |
| 
 | |
|       case CHAR_CARRIAGE_RETURN:
 | |
|       case CHAR_LINEFEED:
 | |
|       case CHAR_NULL:
 | |
|         ReturnFlag = TRUE;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         GlyphOffset = GlyphOffset + *GlyphWidth;
 | |
| 
 | |
|         //
 | |
|         // Record the last space info in this line. Will be used in rewind.
 | |
|         //
 | |
|         if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {
 | |
|           LastSpaceOffset = StrOffset;
 | |
|           LastGlyphWidth  = *GlyphWidth;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     if (ReturnFlag) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Rewind the string from the maximum size until we see a space to break the line
 | |
|   //
 | |
|   if (GlyphOffset > LineWidth) {
 | |
|     //
 | |
|     // Rewind the string to last space char in this line.
 | |
|     //
 | |
|     if (LastSpaceOffset != 0) {
 | |
|       StrOffset   = LastSpaceOffset;
 | |
|       *GlyphWidth = LastGlyphWidth;
 | |
|     } else {
 | |
|       //
 | |
|       // Roll back to last char in the line width.
 | |
|       //
 | |
|       StrOffset--;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // The CHAR_NULL has process last time, this time just return 0 to stand for the end.
 | |
|   //
 | |
|   if ((StrOffset == 0) && (InputString[*Index + StrOffset] == CHAR_NULL)) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Need extra glyph info and '\0' info, so +2.
 | |
|   //
 | |
|   *OutputString = AllocateZeroPool ((StrOffset + 2) * sizeof (CHAR16));
 | |
|   if (*OutputString == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Save the glyph info at the begin of the string, will used by Print function.
 | |
|   //
 | |
|   if (OriginalGlyphWidth == 1) {
 | |
|     *(*OutputString) = NARROW_CHAR;
 | |
|   } else {
 | |
|     *(*OutputString) = WIDE_CHAR;
 | |
|   }
 | |
| 
 | |
|   CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof (CHAR16));
 | |
| 
 | |
|   if (InputString[*Index + StrOffset] == CHAR_SPACE) {
 | |
|     //
 | |
|     // Skip the space info at the begin of next line.
 | |
|     //
 | |
|     *Index = (UINT16)(*Index + StrOffset + 1);
 | |
|   } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {
 | |
|     //
 | |
|     // Skip the /n or /n/r info.
 | |
|     //
 | |
|     if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {
 | |
|       *Index = (UINT16)(*Index + StrOffset + 2);
 | |
|     } else {
 | |
|       *Index = (UINT16)(*Index + StrOffset + 1);
 | |
|     }
 | |
|   } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {
 | |
|     //
 | |
|     // Skip the /r or /r/n info.
 | |
|     //
 | |
|     if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {
 | |
|       *Index = (UINT16)(*Index + StrOffset + 2);
 | |
|     } else {
 | |
|       *Index = (UINT16)(*Index + StrOffset + 1);
 | |
|     }
 | |
|   } else {
 | |
|     *Index = (UINT16)(*Index + StrOffset);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Include extra glyph info and '\0' info, so +2.
 | |
|   //
 | |
|   return StrOffset + 2;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Add one menu option by specified description and context.
 | |
| 
 | |
|   @param  Statement              Statement of this Menu Option.
 | |
|   @param  MenuItemCount          The index for this Option in the Menu.
 | |
|   @param  NestIn                 Whether this statement is nest in another statement.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UiAddMenuOption (
 | |
|   IN FORM_DISPLAY_ENGINE_STATEMENT  *Statement,
 | |
|   IN UINT16                         *MenuItemCount,
 | |
|   IN BOOLEAN                        NestIn
 | |
|   )
 | |
| {
 | |
|   UI_MENU_OPTION  *MenuOption;
 | |
|   UINTN           Index;
 | |
|   UINTN           Count;
 | |
|   UINT16          NumberOfLines;
 | |
|   UINT16          GlyphWidth;
 | |
|   UINT16          Width;
 | |
|   UINTN           ArrayEntry;
 | |
|   CHAR16          *OutputString;
 | |
|   EFI_STRING_ID   PromptId;
 | |
| 
 | |
|   NumberOfLines = 1;
 | |
|   ArrayEntry    = 0;
 | |
|   GlyphWidth    = 1;
 | |
|   Count         = 1;
 | |
|   MenuOption    = NULL;
 | |
| 
 | |
|   PromptId = GetPrompt (Statement->OpCode);
 | |
|   ASSERT (PromptId != 0);
 | |
| 
 | |
|   if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
 | |
|     Count = 3;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < Count; Index++) {
 | |
|     MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
 | |
|     ASSERT (MenuOption);
 | |
| 
 | |
|     MenuOption->Signature       = UI_MENU_OPTION_SIGNATURE;
 | |
|     MenuOption->Description     = GetToken (PromptId, gFormData->HiiHandle);
 | |
|     MenuOption->Handle          = gFormData->HiiHandle;
 | |
|     MenuOption->ThisTag         = Statement;
 | |
|     MenuOption->NestInStatement = NestIn;
 | |
|     MenuOption->EntryNumber     = *MenuItemCount;
 | |
| 
 | |
|     MenuOption->Sequence = Index;
 | |
| 
 | |
|     if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) {
 | |
|       MenuOption->GrayOut = TRUE;
 | |
|     } else {
 | |
|       MenuOption->GrayOut = FALSE;
 | |
|     }
 | |
| 
 | |
|     if (((Statement->Attribute & HII_DISPLAY_LOCK) != 0) || ((gFormData->Attribute & HII_DISPLAY_LOCK) != 0)) {
 | |
|       MenuOption->GrayOut = TRUE;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // If the form or the question has the lock attribute, deal same as grayout.
 | |
|     //
 | |
|     if (((gFormData->Attribute & HII_DISPLAY_LOCK) != 0) || ((Statement->Attribute & HII_DISPLAY_LOCK) != 0)) {
 | |
|       MenuOption->GrayOut = TRUE;
 | |
|     }
 | |
| 
 | |
|     switch (Statement->OpCode->OpCode) {
 | |
|       case EFI_IFR_ORDERED_LIST_OP:
 | |
|       case EFI_IFR_ONE_OF_OP:
 | |
|       case EFI_IFR_NUMERIC_OP:
 | |
|       case EFI_IFR_TIME_OP:
 | |
|       case EFI_IFR_DATE_OP:
 | |
|       case EFI_IFR_CHECKBOX_OP:
 | |
|       case EFI_IFR_PASSWORD_OP:
 | |
|       case EFI_IFR_STRING_OP:
 | |
|         //
 | |
|         // User could change the value of these items
 | |
|         //
 | |
|         MenuOption->IsQuestion = TRUE;
 | |
|         break;
 | |
|       case EFI_IFR_TEXT_OP:
 | |
|         if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {
 | |
|           //
 | |
|           // Initializing GrayOut option as TRUE for Text setup options
 | |
|           // so that those options will be Gray in colour and un selectable.
 | |
|           //
 | |
|           MenuOption->GrayOut = TRUE;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|       default:
 | |
|         MenuOption->IsQuestion = FALSE;
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     if ((Statement->Attribute & HII_DISPLAY_READONLY) != 0) {
 | |
|       MenuOption->ReadOnly = TRUE;
 | |
|       if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) {
 | |
|         MenuOption->GrayOut = TRUE;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if ((Index == 0) &&
 | |
|         (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) &&
 | |
|         (Statement->OpCode->OpCode != EFI_IFR_TIME_OP))
 | |
|     {
 | |
|       Width = GetWidth (MenuOption, NULL);
 | |
|       for ( ; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &ArrayEntry, &OutputString) != 0x0000;) {
 | |
|         //
 | |
|         // If there is more string to process print on the next row and increment the Skip value
 | |
|         //
 | |
|         if (StrLen (&MenuOption->Description[ArrayEntry]) != 0) {
 | |
|           NumberOfLines++;
 | |
|         }
 | |
| 
 | |
|         FreePool (OutputString);
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // Add three MenuOptions for Date/Time
 | |
|       // Data format :      [01/02/2004]      [11:22:33]
 | |
|       // Line number :        0  0    1         0  0  1
 | |
|       //
 | |
|       NumberOfLines = 0;
 | |
|     }
 | |
| 
 | |
|     if (Index == 2) {
 | |
|       //
 | |
|       // Override LineNumber for the MenuOption in Date/Time sequence
 | |
|       //
 | |
|       MenuOption->Skip = 1;
 | |
|     } else {
 | |
|       MenuOption->Skip = NumberOfLines;
 | |
|     }
 | |
| 
 | |
|     InsertTailList (&gMenuOption, &MenuOption->Link);
 | |
|   }
 | |
| 
 | |
|   (*MenuItemCount)++;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create the menu list base on the form data info.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ConvertStatementToMenu (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   UINT16                         MenuItemCount;
 | |
|   LIST_ENTRY                     *Link;
 | |
|   LIST_ENTRY                     *NestLink;
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *NestStatement;
 | |
| 
 | |
|   MenuItemCount = 0;
 | |
|   InitializeListHead (&gMenuOption);
 | |
| 
 | |
|   Link = GetFirstNode (&gFormData->StatementListHead);
 | |
|   while (!IsNull (&gFormData->StatementListHead, Link)) {
 | |
|     Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
 | |
|     Link      = GetNextNode (&gFormData->StatementListHead, Link);
 | |
| 
 | |
|     //
 | |
|     // Skip the opcode not recognized by Display core.
 | |
|     //
 | |
|     if (Statement->OpCode->OpCode == EFI_IFR_GUID_OP) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     UiAddMenuOption (Statement, &MenuItemCount, FALSE);
 | |
| 
 | |
|     //
 | |
|     // Check the statement nest in this host statement.
 | |
|     //
 | |
|     NestLink = GetFirstNode (&Statement->NestStatementList);
 | |
|     while (!IsNull (&Statement->NestStatementList, NestLink)) {
 | |
|       NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);
 | |
|       NestLink      = GetNextNode (&Statement->NestStatementList, NestLink);
 | |
| 
 | |
|       //
 | |
|       // Skip the opcode not recognized by Display core.
 | |
|       //
 | |
|       if (NestStatement->OpCode->OpCode == EFI_IFR_GUID_OP) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Count the storage space of a Unicode string.
 | |
| 
 | |
|   This function handles the Unicode string with NARROW_CHAR
 | |
|   and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
 | |
|   does not count in the resultant output. If a WIDE_CHAR is
 | |
|   hit, then 2 Unicode character will consume an output storage
 | |
|   space with size of CHAR16 till a NARROW_CHAR is hit.
 | |
| 
 | |
|   If String is NULL, then ASSERT ().
 | |
| 
 | |
|   @param String          The input string to be counted.
 | |
| 
 | |
|   @return Storage space for the input string.
 | |
| 
 | |
| **/
 | |
| UINTN
 | |
| GetStringWidth (
 | |
|   IN CHAR16  *String
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
|   UINTN  Count;
 | |
|   UINTN  IncrementValue;
 | |
| 
 | |
|   ASSERT (String != NULL);
 | |
|   if (String == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   Index          = 0;
 | |
|   Count          = 0;
 | |
|   IncrementValue = 1;
 | |
| 
 | |
|   do {
 | |
|     //
 | |
|     // Advance to the null-terminator or to the first width directive
 | |
|     //
 | |
|     for ( ;
 | |
|           (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
 | |
|           Index++, Count = Count + IncrementValue
 | |
|           )
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // We hit the null-terminator, we now have a count
 | |
|     //
 | |
|     if (String[Index] == 0) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
 | |
|     // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
 | |
|     //
 | |
|     if (String[Index] == NARROW_CHAR) {
 | |
|       //
 | |
|       // Skip to the next character
 | |
|       //
 | |
|       Index++;
 | |
|       IncrementValue = 1;
 | |
|     } else {
 | |
|       //
 | |
|       // Skip to the next character
 | |
|       //
 | |
|       Index++;
 | |
|       IncrementValue = 2;
 | |
|     }
 | |
|   } while (String[Index] != 0);
 | |
| 
 | |
|   //
 | |
|   // Increment by one to include the null-terminator in the size
 | |
|   //
 | |
|   Count++;
 | |
| 
 | |
|   return Count * sizeof (CHAR16);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Base on the input option string to update the skip value for a menu option.
 | |
| 
 | |
|   @param  MenuOption             The MenuOption to be checked.
 | |
|   @param  OptionString           The input option string.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateSkipInfoForMenu (
 | |
|   IN UI_MENU_OPTION  *MenuOption,
 | |
|   IN CHAR16          *OptionString
 | |
|   )
 | |
| {
 | |
|   UINTN   Index;
 | |
|   UINT16  Width;
 | |
|   UINTN   Row;
 | |
|   CHAR16  *OutputString;
 | |
|   UINT16  GlyphWidth;
 | |
| 
 | |
|   Width      = (UINT16)gOptionBlockWidth - 1;
 | |
|   GlyphWidth = 1;
 | |
|   Row        = 1;
 | |
| 
 | |
|   for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
 | |
|     if (StrLen (&OptionString[Index]) != 0) {
 | |
|       Row++;
 | |
|     }
 | |
| 
 | |
|     FreePool (OutputString);
 | |
|   }
 | |
| 
 | |
|   if ((Row > MenuOption->Skip) &&
 | |
|       (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) &&
 | |
|       (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP))
 | |
|   {
 | |
|     MenuOption->Skip = Row;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update display lines for a Menu Option.
 | |
| 
 | |
|   @param  MenuOption             The MenuOption to be checked.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateOptionSkipLines (
 | |
|   IN UI_MENU_OPTION  *MenuOption
 | |
|   )
 | |
| {
 | |
|   CHAR16  *OptionString;
 | |
| 
 | |
|   OptionString = NULL;
 | |
| 
 | |
|   ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);
 | |
|   if (OptionString != NULL) {
 | |
|     UpdateSkipInfoForMenu (MenuOption, OptionString);
 | |
| 
 | |
|     FreePool (OptionString);
 | |
|   }
 | |
| 
 | |
|   if ((MenuOption->ThisTag->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT *)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {
 | |
|     OptionString = GetToken (((EFI_IFR_TEXT *)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);
 | |
| 
 | |
|     if (OptionString != NULL) {
 | |
|       UpdateSkipInfoForMenu (MenuOption, OptionString);
 | |
| 
 | |
|       FreePool (OptionString);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether this Menu Option could be print.
 | |
| 
 | |
|   Check Prompt string, option string or text two string not NULL.
 | |
| 
 | |
|   This is an internal function.
 | |
| 
 | |
|   @param  MenuOption             The MenuOption to be checked.
 | |
| 
 | |
|   @retval TRUE                   This Menu Option is printable.
 | |
|   @retval FALSE                  This Menu Option could not be printable.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| PrintableMenu (
 | |
|   UI_MENU_OPTION  *MenuOption
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_STRING  OptionString;
 | |
| 
 | |
|   OptionString = NULL;
 | |
| 
 | |
|   if (MenuOption->Description[0] != '\0') {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if ((OptionString != NULL) && (OptionString[0] != '\0')) {
 | |
|     FreePool (OptionString);
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if ((MenuOption->ThisTag->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT *)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {
 | |
|     OptionString = GetToken (((EFI_IFR_TEXT *)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);
 | |
|     ASSERT (OptionString != NULL);
 | |
|     if (OptionString[0] != '\0') {
 | |
|       FreePool (OptionString);
 | |
|       return TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether this Menu Option could be highlighted.
 | |
| 
 | |
|   This is an internal function.
 | |
| 
 | |
|   @param  MenuOption             The MenuOption to be checked.
 | |
| 
 | |
|   @retval TRUE                   This Menu Option is selectable.
 | |
|   @retval FALSE                  This Menu Option could not be selected.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsSelectable (
 | |
|   UI_MENU_OPTION  *MenuOption
 | |
|   )
 | |
| {
 | |
|   if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
 | |
|       MenuOption->GrayOut || MenuOption->ReadOnly || !PrintableMenu (MenuOption))
 | |
|   {
 | |
|     return FALSE;
 | |
|   } else {
 | |
|     return TRUE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Move to next selectable statement.
 | |
| 
 | |
|   This is an internal function.
 | |
| 
 | |
|   @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.
 | |
|   @param  CurrentPosition        Current position.
 | |
|   @param  GapToTop               Gap position to top or bottom.
 | |
|   @param  FindInForm             Whether find menu in current form or beyond.
 | |
| 
 | |
|   @return The row distance from current MenuOption to next selectable MenuOption.
 | |
| 
 | |
|   @retval -1       Reach the begin of the menu, still can't find the selectable menu.
 | |
|   @retval Value    Find the selectable menu, maybe the truly selectable, maybe the
 | |
|                    first menu showing beyond current form or last menu showing in
 | |
|                    current form.
 | |
|                    The value is the line number between the new selected menu and the
 | |
|                    current select menu, not include the new selected menu.
 | |
| 
 | |
| **/
 | |
| INTN
 | |
| MoveToNextStatement (
 | |
|   IN     BOOLEAN     GoUp,
 | |
|   IN OUT LIST_ENTRY  **CurrentPosition,
 | |
|   IN     UINTN       GapToTop,
 | |
|   IN     BOOLEAN     FindInForm
 | |
|   )
 | |
| {
 | |
|   INTN            Distance;
 | |
|   LIST_ENTRY      *Pos;
 | |
|   UI_MENU_OPTION  *NextMenuOption;
 | |
|   UI_MENU_OPTION  *PreMenuOption;
 | |
| 
 | |
|   Distance = 0;
 | |
|   Pos      = *CurrentPosition;
 | |
| 
 | |
|   if (Pos == &gMenuOption) {
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   PreMenuOption = MENU_OPTION_FROM_LINK (Pos);
 | |
| 
 | |
|   while (TRUE) {
 | |
|     NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
 | |
|     //
 | |
|     // NextMenuOption->Row == 0 means this menu has not calculate
 | |
|     // the NextMenuOption->Skip value yet, just calculate here.
 | |
|     //
 | |
|     if (NextMenuOption->Row == 0) {
 | |
|       UpdateOptionSkipLines (NextMenuOption);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Check whether the menu is beyond current showing form,
 | |
|     // return the first one beyond the showing form.
 | |
|     //
 | |
|     if ((UINTN)Distance + NextMenuOption->Skip > GapToTop) {
 | |
|       if (FindInForm) {
 | |
|         NextMenuOption = PreMenuOption;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // return the selectable menu in the showing form.
 | |
|     //
 | |
|     if (IsSelectable (NextMenuOption)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Distance += NextMenuOption->Skip;
 | |
| 
 | |
|     //
 | |
|     // Arrive at begin of the menu list.
 | |
|     //
 | |
|     if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {
 | |
|       Distance = -1;
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Pos           = (GoUp ? Pos->BackLink : Pos->ForwardLink);
 | |
|     PreMenuOption = NextMenuOption;
 | |
|   }
 | |
| 
 | |
|   *CurrentPosition = &NextMenuOption->Link;
 | |
|   return Distance;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Process option string for date/time opcode.
 | |
| 
 | |
|   @param  MenuOption              Menu option point to date/time.
 | |
|   @param  OptionString            Option string input for process.
 | |
|   @param  AddOptCol               Whether need to update MenuOption->OptCol.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ProcessStringForDateTime (
 | |
|   UI_MENU_OPTION  *MenuOption,
 | |
|   CHAR16          *OptionString,
 | |
|   BOOLEAN         AddOptCol
 | |
|   )
 | |
| {
 | |
|   UINTN                          Index;
 | |
|   UINTN                          Count;
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
|   EFI_IFR_DATE                   *Date;
 | |
|   EFI_IFR_TIME                   *Time;
 | |
| 
 | |
|   ASSERT (MenuOption != NULL && OptionString != NULL);
 | |
| 
 | |
|   Statement = MenuOption->ThisTag;
 | |
|   Date      = NULL;
 | |
|   Time      = NULL;
 | |
|   if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
 | |
|     Date = (EFI_IFR_DATE *)Statement->OpCode;
 | |
|   } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
 | |
|     Time = (EFI_IFR_TIME *)Statement->OpCode;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If leading spaces on OptionString - remove the spaces
 | |
|   //
 | |
|   for (Index = 0; OptionString[Index] == L' '; Index++) {
 | |
|     //
 | |
|     // Base on the blockspace to get the option column info.
 | |
|     //
 | |
|     if (AddOptCol) {
 | |
|       MenuOption->OptCol++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
 | |
|     OptionString[Count] = OptionString[Index];
 | |
|     Count++;
 | |
|   }
 | |
| 
 | |
|   OptionString[Count] = CHAR_NULL;
 | |
| 
 | |
|   //
 | |
|   // Enable to suppress field in the opcode base on the flag.
 | |
|   //
 | |
|   if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
 | |
|     //
 | |
|     // OptionString format is: <**:  **: ****>
 | |
|     //                        |month|day|year|
 | |
|     //                          4     3    5
 | |
|     //
 | |
|     if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {
 | |
|       //
 | |
|       // At this point, only "<**:" in the optionstring.
 | |
|       // Clean the day's ** field, after clean, the format is "<  :"
 | |
|       //
 | |
|       SetUnicodeMem (&OptionString[1], 2, L' ');
 | |
|     } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {
 | |
|       //
 | |
|       // At this point, only "**:" in the optionstring.
 | |
|       // Clean the month's "**" field, after clean, the format is "  :"
 | |
|       //
 | |
|       SetUnicodeMem (&OptionString[0], 2, L' ');
 | |
|     } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {
 | |
|       //
 | |
|       // At this point, only "****>" in the optionstring.
 | |
|       // Clean the year's "****" field, after clean, the format is "  >"
 | |
|       //
 | |
|       SetUnicodeMem (&OptionString[0], 4, L' ');
 | |
|     }
 | |
|   } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
 | |
|     //
 | |
|     // OptionString format is: <**:  **:    **>
 | |
|     //                        |hour|minute|second|
 | |
|     //                          4     3      3
 | |
|     //
 | |
|     if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {
 | |
|       //
 | |
|       // At this point, only "<**:" in the optionstring.
 | |
|       // Clean the hour's ** field, after clean, the format is "<  :"
 | |
|       //
 | |
|       SetUnicodeMem (&OptionString[1], 2, L' ');
 | |
|     } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {
 | |
|       //
 | |
|       // At this point, only "**:" in the optionstring.
 | |
|       // Clean the minute's "**" field, after clean, the format is "  :"
 | |
|       //
 | |
|       SetUnicodeMem (&OptionString[0], 2, L' ');
 | |
|     } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {
 | |
|       //
 | |
|       // At this point, only "**>" in the optionstring.
 | |
|       // Clean the second's "**" field, after clean, the format is "  >"
 | |
|       //
 | |
|       SetUnicodeMem (&OptionString[0], 2, L' ');
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Adjust Data and Time position accordingly.
 | |
|   Data format :      [01/02/2004]      [11:22:33]
 | |
|   Line number :        0  0    1         0  0  1
 | |
| 
 | |
|   This is an internal function.
 | |
| 
 | |
|   @param  DirectionUp            the up or down direction. False is down. True is
 | |
|                                  up.
 | |
|   @param  CurrentPosition        Current position. On return: Point to the last
 | |
|                                  Option (Year or Second) if up; Point to the first
 | |
|                                  Option (Month or Hour) if down.
 | |
| 
 | |
|   @return Return line number to pad. It is possible that we stand on a zero-advance
 | |
|   @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
 | |
| 
 | |
| **/
 | |
| UINTN
 | |
| AdjustDateAndTimePosition (
 | |
|   IN     BOOLEAN     DirectionUp,
 | |
|   IN OUT LIST_ENTRY  **CurrentPosition
 | |
|   )
 | |
| {
 | |
|   UINTN           Count;
 | |
|   LIST_ENTRY      *NewPosition;
 | |
|   UI_MENU_OPTION  *MenuOption;
 | |
|   UINTN           PadLineNumber;
 | |
| 
 | |
|   PadLineNumber = 0;
 | |
|   NewPosition   = *CurrentPosition;
 | |
|   MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
 | |
| 
 | |
|   if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||
 | |
|       (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP))
 | |
|   {
 | |
|     //
 | |
|     // Calculate the distance from current position to the last Date/Time MenuOption
 | |
|     //
 | |
|     Count = 0;
 | |
|     while (MenuOption->Skip == 0) {
 | |
|       Count++;
 | |
|       NewPosition   = NewPosition->ForwardLink;
 | |
|       MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
 | |
|       PadLineNumber = 1;
 | |
|     }
 | |
| 
 | |
|     NewPosition = *CurrentPosition;
 | |
|     if (DirectionUp) {
 | |
|       //
 | |
|       // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
 | |
|       // to be one that back to the previous set of MenuOptions, we need to advance to the first
 | |
|       // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate
 | |
|       // checking can be done.
 | |
|       //
 | |
|       while (Count++ < 2) {
 | |
|         NewPosition = NewPosition->BackLink;
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended
 | |
|       // to be one that progresses to the next set of MenuOptions, we need to advance to the last
 | |
|       // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate
 | |
|       // checking can be done.
 | |
|       //
 | |
|       while (Count-- > 0) {
 | |
|         NewPosition = NewPosition->ForwardLink;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     *CurrentPosition = NewPosition;
 | |
|   }
 | |
| 
 | |
|   return PadLineNumber;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get step info from numeric opcode.
 | |
| 
 | |
|   @param[in] OpCode     The input numeric op code.
 | |
| 
 | |
|   @return step info for this opcode.
 | |
| **/
 | |
| UINT64
 | |
| GetFieldFromNum (
 | |
|   IN  EFI_IFR_OP_HEADER  *OpCode
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_NUMERIC  *NumericOp;
 | |
|   UINT64           Step;
 | |
| 
 | |
|   NumericOp = (EFI_IFR_NUMERIC *)OpCode;
 | |
| 
 | |
|   switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {
 | |
|     case EFI_IFR_NUMERIC_SIZE_1:
 | |
|       Step = NumericOp->data.u8.Step;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_SIZE_2:
 | |
|       Step = NumericOp->data.u16.Step;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_SIZE_4:
 | |
|       Step = NumericOp->data.u32.Step;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_SIZE_8:
 | |
|       Step = NumericOp->data.u64.Step;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       Step = 0;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   return Step;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Find the registered HotKey based on KeyData.
 | |
| 
 | |
|   @param[in] KeyData     A pointer to a buffer that describes the keystroke
 | |
|                          information for the hot key.
 | |
| 
 | |
|   @return The registered HotKey context. If no found, NULL will return.
 | |
| **/
 | |
| BROWSER_HOT_KEY *
 | |
| GetHotKeyFromRegisterList (
 | |
|   IN EFI_INPUT_KEY  *KeyData
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY       *Link;
 | |
|   BROWSER_HOT_KEY  *HotKey;
 | |
| 
 | |
|   Link = GetFirstNode (&gFormData->HotKeyListHead);
 | |
|   while (!IsNull (&gFormData->HotKeyListHead, Link)) {
 | |
|     HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
 | |
| 
 | |
|     if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {
 | |
|       return HotKey;
 | |
|     }
 | |
| 
 | |
|     Link = GetNextNode (&gFormData->HotKeyListHead, Link);
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Determine if the menu is the last menu that can be selected.
 | |
| 
 | |
|   This is an internal function.
 | |
| 
 | |
|   @param  Direction              The scroll direction. False is down. True is up.
 | |
|   @param  CurrentPos             The current focus.
 | |
| 
 | |
|   @return FALSE -- the menu isn't the last menu that can be selected.
 | |
|   @return TRUE  -- the menu is the last menu that can be selected.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| ValueIsScroll (
 | |
|   IN  BOOLEAN     Direction,
 | |
|   IN  LIST_ENTRY  *CurrentPos
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY  *Temp;
 | |
| 
 | |
|   Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
 | |
| 
 | |
|   if (Temp == &gMenuOption) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Wait for a given event to fire, or for an optional timeout to expire.
 | |
| 
 | |
|   @param  Event                  The event to wait for
 | |
| 
 | |
|   @retval UI_EVENT_TYPE          The type of the event which is trigged.
 | |
| 
 | |
| **/
 | |
| UI_EVENT_TYPE
 | |
| UiWaitForEvent (
 | |
|   IN EFI_EVENT  Event
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   UINTN          Index;
 | |
|   UINTN          EventNum;
 | |
|   UINT64         Timeout;
 | |
|   EFI_EVENT      TimerEvent;
 | |
|   EFI_EVENT      WaitList[3];
 | |
|   UI_EVENT_TYPE  EventType;
 | |
| 
 | |
|   TimerEvent = NULL;
 | |
|   Timeout    = FormExitTimeout (gFormData);
 | |
| 
 | |
|   if (Timeout != 0) {
 | |
|     Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
 | |
| 
 | |
|     //
 | |
|     // Set the timer event
 | |
|     //
 | |
|     gBS->SetTimer (
 | |
|            TimerEvent,
 | |
|            TimerRelative,
 | |
|            Timeout
 | |
|            );
 | |
|   }
 | |
| 
 | |
|   WaitList[0] = Event;
 | |
|   EventNum    = 1;
 | |
|   if (gFormData->FormRefreshEvent != NULL) {
 | |
|     WaitList[EventNum] = gFormData->FormRefreshEvent;
 | |
|     EventNum++;
 | |
|   }
 | |
| 
 | |
|   if (Timeout != 0) {
 | |
|     WaitList[EventNum] = TimerEvent;
 | |
|     EventNum++;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->WaitForEvent (EventNum, WaitList, &Index);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   switch (Index) {
 | |
|     case 0:
 | |
|       EventType = UIEventKey;
 | |
|       break;
 | |
| 
 | |
|     case 1:
 | |
|       if (gFormData->FormRefreshEvent != NULL) {
 | |
|         EventType = UIEventDriver;
 | |
|       } else {
 | |
|         ASSERT (Timeout != 0 && EventNum == 2);
 | |
|         EventType = UIEventTimeOut;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       ASSERT (Index == 2 && EventNum == 3);
 | |
|       EventType = UIEventTimeOut;
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   if (Timeout != 0) {
 | |
|     gBS->CloseEvent (TimerEvent);
 | |
|   }
 | |
| 
 | |
|   return EventType;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get question id info from the input opcode header.
 | |
| 
 | |
|   @param  OpCode                 The input opcode header pointer.
 | |
| 
 | |
|   @retval                        The question id for this opcode.
 | |
| 
 | |
| **/
 | |
| EFI_QUESTION_ID
 | |
| GetQuestionIdInfo (
 | |
|   IN   EFI_IFR_OP_HEADER  *OpCode
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_QUESTION_HEADER  *QuestionHeader;
 | |
| 
 | |
|   if (OpCode->Length < sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER)) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   QuestionHeader = (EFI_IFR_QUESTION_HEADER *)((UINT8 *)OpCode + sizeof (EFI_IFR_OP_HEADER));
 | |
| 
 | |
|   return QuestionHeader->QuestionId;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Find the top of screen menu base on the current menu.
 | |
| 
 | |
|   @param  CurPos                 Current input menu.
 | |
|   @param  Rows                   Totol screen rows.
 | |
|   @param  SkipValue              SkipValue for this new form.
 | |
| 
 | |
|   @retval TopOfScreen            Top of screen menu for the new form.
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| FindTopOfScreenMenu (
 | |
|   IN  LIST_ENTRY  *CurPos,
 | |
|   IN  UINTN       Rows,
 | |
|   OUT UINTN       *SkipValue
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY      *Link;
 | |
|   LIST_ENTRY      *TopOfScreen;
 | |
|   UI_MENU_OPTION  *PreviousMenuOption;
 | |
| 
 | |
|   Link               = CurPos;
 | |
|   PreviousMenuOption = NULL;
 | |
| 
 | |
|   while (Link->BackLink != &gMenuOption) {
 | |
|     Link               = Link->BackLink;
 | |
|     PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
 | |
|     if (PreviousMenuOption->Row == 0) {
 | |
|       UpdateOptionSkipLines (PreviousMenuOption);
 | |
|     }
 | |
| 
 | |
|     if (Rows <= PreviousMenuOption->Skip) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Rows = Rows - PreviousMenuOption->Skip;
 | |
|   }
 | |
| 
 | |
|   if (Link->BackLink == &gMenuOption) {
 | |
|     TopOfScreen = gMenuOption.ForwardLink;
 | |
|     if ((PreviousMenuOption != NULL) && (Rows < PreviousMenuOption->Skip)) {
 | |
|       *SkipValue = PreviousMenuOption->Skip - Rows;
 | |
|     } else {
 | |
|       *SkipValue = 0;
 | |
|     }
 | |
|   } else {
 | |
|     TopOfScreen = Link;
 | |
|     *SkipValue  = PreviousMenuOption->Skip - Rows;
 | |
|   }
 | |
| 
 | |
|   return TopOfScreen;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the index info for this opcode.
 | |
| 
 | |
|   @param  OpCode      The input opcode for the statement.
 | |
| 
 | |
|   @retval  The index of this statement.
 | |
| 
 | |
| **/
 | |
| UINTN
 | |
| GetIndexInfoForOpcode (
 | |
|   IN EFI_IFR_OP_HEADER  *OpCode
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY      *NewPos;
 | |
|   UI_MENU_OPTION  *MenuOption;
 | |
|   UINTN           Index;
 | |
| 
 | |
|   NewPos = gMenuOption.ForwardLink;
 | |
|   Index  = 0;
 | |
| 
 | |
|   for (NewPos = gMenuOption.ForwardLink; NewPos != &gMenuOption; NewPos = NewPos->ForwardLink) {
 | |
|     MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
| 
 | |
|     if (CompareMem (MenuOption->ThisTag->OpCode, OpCode, OpCode->Length) == 0) {
 | |
|       if (MenuOption->ThisTag->OpCode == OpCode) {
 | |
|         return Index;
 | |
|       }
 | |
| 
 | |
|       Index++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Index;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Is this the saved highlight statement.
 | |
| 
 | |
|   @param  HighLightedStatement      The input highlight statement.
 | |
| 
 | |
|   @retval  TRUE   This is the highlight statement.
 | |
|   @retval  FALSE  This is not the highlight statement.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsSavedHighlightStatement (
 | |
|   IN FORM_DISPLAY_ENGINE_STATEMENT  *HighLightedStatement
 | |
|   )
 | |
| {
 | |
|   if ((gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) &&
 | |
|       (gFormData->FormId == gHighligthMenuInfo.FormId))
 | |
|   {
 | |
|     if (gHighligthMenuInfo.HLTQuestionId != 0) {
 | |
|       return (BOOLEAN)(gHighligthMenuInfo.HLTQuestionId == GetQuestionIdInfo (HighLightedStatement->OpCode));
 | |
|     } else {
 | |
|       if (CompareMem (gHighligthMenuInfo.HLTOpCode, HighLightedStatement->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) {
 | |
|         if ((gHighligthMenuInfo.HLTIndex == 0) || (gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode (HighLightedStatement->OpCode))) {
 | |
|           return TRUE;
 | |
|         } else {
 | |
|           return FALSE;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Is this the highlight menu.
 | |
| 
 | |
|   @param  MenuOption      The input Menu option.
 | |
| 
 | |
|   @retval  TRUE   This is the highlight menu option.
 | |
|   @retval  FALSE  This is not the highlight menu option.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsHighLightMenuOption (
 | |
|   IN UI_MENU_OPTION  *MenuOption
 | |
|   )
 | |
| {
 | |
|   if (gHighligthMenuInfo.HLTQuestionId != 0) {
 | |
|     if (GetQuestionIdInfo (MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.HLTQuestionId) {
 | |
|       return (BOOLEAN)(MenuOption->Sequence == gHighligthMenuInfo.HLTSequence);
 | |
|     }
 | |
|   } else {
 | |
|     if (CompareMem (gHighligthMenuInfo.HLTOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) {
 | |
|       if ((gHighligthMenuInfo.HLTIndex == 0) || (gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode (MenuOption->ThisTag->OpCode))) {
 | |
|         return (BOOLEAN)(MenuOption->Sequence == gHighligthMenuInfo.HLTSequence);
 | |
|       } else {
 | |
|         return FALSE;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Find the highlight menu.
 | |
| 
 | |
|   If the input is NULL, base on the record highlight info in
 | |
|   gHighligthMenuInfo to find the last highlight menu.
 | |
| 
 | |
|   @param  HighLightedStatement      The input highlight statement.
 | |
| 
 | |
|   @retval  The highlight menu index.
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| FindHighLightMenuOption (
 | |
|   IN FORM_DISPLAY_ENGINE_STATEMENT  *HighLightedStatement
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY      *NewPos;
 | |
|   UI_MENU_OPTION  *MenuOption;
 | |
| 
 | |
|   NewPos     = gMenuOption.ForwardLink;
 | |
|   MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
| 
 | |
|   if (HighLightedStatement != NULL) {
 | |
|     while (MenuOption->ThisTag != HighLightedStatement) {
 | |
|       NewPos = NewPos->ForwardLink;
 | |
|       if (NewPos == &gMenuOption) {
 | |
|         //
 | |
|         // Not Found it, break
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Must find the highlight statement.
 | |
|     //
 | |
|     ASSERT (NewPos != &gMenuOption);
 | |
|   } else {
 | |
|     while (!IsHighLightMenuOption (MenuOption)) {
 | |
|       NewPos = NewPos->ForwardLink;
 | |
|       if (NewPos == &gMenuOption) {
 | |
|         //
 | |
|         // Not Found it, break
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Highlight statement has disappear (suppressed/disableed)
 | |
|     //
 | |
|     if (NewPos == &gMenuOption) {
 | |
|       NewPos = NULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NewPos;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Is this the Top of screen menu.
 | |
| 
 | |
|   @param  MenuOption      The input Menu option.
 | |
| 
 | |
|   @retval  TRUE   This is the Top of screen menu option.
 | |
|   @retval  FALSE  This is not the Top of screen menu option.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsTopOfScreeMenuOption (
 | |
|   IN UI_MENU_OPTION  *MenuOption
 | |
|   )
 | |
| {
 | |
|   if (gHighligthMenuInfo.TOSQuestionId != 0) {
 | |
|     return (BOOLEAN)(GetQuestionIdInfo (MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.TOSQuestionId);
 | |
|   }
 | |
| 
 | |
|   if (CompareMem (gHighligthMenuInfo.TOSOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.TOSOpCode->Length) == 0) {
 | |
|     if ((gHighligthMenuInfo.TOSIndex == 0) || (gHighligthMenuInfo.TOSIndex == GetIndexInfoForOpcode (MenuOption->ThisTag->OpCode))) {
 | |
|       return TRUE;
 | |
|     } else {
 | |
|       return FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Calculate the distance between two menus and include the skip value of StartMenu.
 | |
| 
 | |
|   @param  StartMenu             The link_entry pointer to start menu.
 | |
|   @param  EndMenu               The link_entry pointer to end menu.
 | |
| 
 | |
| **/
 | |
| UINTN
 | |
| GetDistanceBetweenMenus (
 | |
|   IN LIST_ENTRY  *StartMenu,
 | |
|   IN LIST_ENTRY  *EndMenu
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY      *Link;
 | |
|   UI_MENU_OPTION  *MenuOption;
 | |
|   UINTN           Distance;
 | |
| 
 | |
|   Distance = 0;
 | |
| 
 | |
|   Link = StartMenu;
 | |
|   while (Link != EndMenu) {
 | |
|     MenuOption = MENU_OPTION_FROM_LINK (Link);
 | |
|     if (MenuOption->Row == 0) {
 | |
|       UpdateOptionSkipLines (MenuOption);
 | |
|     }
 | |
| 
 | |
|     Distance += MenuOption->Skip;
 | |
|     Link      = Link->BackLink;
 | |
|   }
 | |
| 
 | |
|   return Distance;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Find the top of screen menu base on the previous record menu info.
 | |
| 
 | |
|   @param  HighLightMenu      The link_entry pointer to highlight menu.
 | |
| 
 | |
|   @retval  Return the the link_entry pointer top of screen menu.
 | |
| 
 | |
| **/
 | |
| LIST_ENTRY *
 | |
| FindTopOfScreenMenuOption (
 | |
|   IN LIST_ENTRY  *HighLightMenu
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY      *NewPos;
 | |
|   UI_MENU_OPTION  *MenuOption;
 | |
|   UINTN           TopRow;
 | |
|   UINTN           BottomRow;
 | |
| 
 | |
|   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;
 | |
|   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;
 | |
| 
 | |
|   NewPos     = gMenuOption.ForwardLink;
 | |
|   MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
| 
 | |
|   while (!IsTopOfScreeMenuOption (MenuOption)) {
 | |
|     NewPos = NewPos->ForwardLink;
 | |
|     if (NewPos == &gMenuOption) {
 | |
|       //
 | |
|       // Not Found it, break
 | |
|       //
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Last time top of screen menu has disappeared.
 | |
|   //
 | |
|   if (NewPos == &gMenuOption) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check whether highlight menu and top of screen menu can be shown within one page,
 | |
|   // if can't, return NULL to re-calcaulate the top of scrren menu. Because some new menus
 | |
|   // may be dynamically inserted between highlightmenu and previous top of screen menu,
 | |
|   // So previous record top of screen menu is not appropriate for current display.
 | |
|   //
 | |
|   if (GetDistanceBetweenMenus (HighLightMenu, NewPos) + 1 > BottomRow - TopRow) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   return NewPos;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Find the first menu which will be show at the top.
 | |
| 
 | |
|   @param  FormData               The data info for this form.
 | |
|   @param  TopOfScreen            The link_entry pointer to top menu.
 | |
|   @param  HighlightMenu          The menu which will be highlight.
 | |
|   @param  SkipValue              The skip value for the top menu.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FindTopMenu (
 | |
|   IN  FORM_DISPLAY_ENGINE_FORM  *FormData,
 | |
|   OUT LIST_ENTRY                **TopOfScreen,
 | |
|   OUT LIST_ENTRY                **HighlightMenu,
 | |
|   OUT UINTN                     *SkipValue
 | |
|   )
 | |
| {
 | |
|   UINTN           TopRow;
 | |
|   UINTN           BottomRow;
 | |
|   UI_MENU_OPTION  *MenuOption;
 | |
|   UINTN           TmpValue;
 | |
| 
 | |
|   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;
 | |
|   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;
 | |
|   //
 | |
|   // When option mismatch happens,there exist two cases,one is reenter the form, just like the if case below,
 | |
|   // and the other is exit current form and enter last form, it can be covered by the else case.
 | |
|   //
 | |
|   if (gMisMatch && (gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) && (gFormData->FormId == gHighligthMenuInfo.FormId)) {
 | |
|     //
 | |
|     // Reenter caused by option mismatch or auto exit caused by refresh form(refresh interval/guid),
 | |
|     // base on the record highlight info to find the highlight menu.
 | |
|     //
 | |
| 
 | |
|     *HighlightMenu = FindHighLightMenuOption (NULL);
 | |
|     if (*HighlightMenu != NULL) {
 | |
|       //
 | |
|       // Update skip info for this highlight menu.
 | |
|       //
 | |
|       MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);
 | |
|       UpdateOptionSkipLines (MenuOption);
 | |
| 
 | |
|       //
 | |
|       // Found the last time highlight menu.
 | |
|       //
 | |
|       *TopOfScreen = FindTopOfScreenMenuOption (*HighlightMenu);
 | |
|       if (*TopOfScreen != NULL) {
 | |
|         //
 | |
|         // Found the last time selectable top of screen menu.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (TRUE, TopOfScreen);
 | |
|         MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);
 | |
|         UpdateOptionSkipLines (MenuOption);
 | |
| 
 | |
|         *SkipValue = gHighligthMenuInfo.SkipValue;
 | |
|       } else {
 | |
|         //
 | |
|         // Not found last time top of screen menu, so base on current highlight menu
 | |
|         // to find the new top of screen menu.
 | |
|         // Make the current highlight menu at the bottom of the form to calculate the
 | |
|         // top of screen menu.
 | |
|         //
 | |
|         if (MenuOption->Skip >= BottomRow - TopRow) {
 | |
|           *TopOfScreen = *HighlightMenu;
 | |
|           TmpValue     = 0;
 | |
|         } else {
 | |
|           *TopOfScreen = FindTopOfScreenMenu (*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);
 | |
|         }
 | |
| 
 | |
|         *SkipValue = TmpValue;
 | |
|       }
 | |
|     } else {
 | |
|       //
 | |
|       // Last time highlight menu has disappear, find the first highlightable menu as the default one.
 | |
|       //
 | |
|       *HighlightMenu = gMenuOption.ForwardLink;
 | |
|       if (!IsListEmpty (&gMenuOption)) {
 | |
|         MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);
 | |
|       }
 | |
| 
 | |
|       *TopOfScreen = gMenuOption.ForwardLink;
 | |
|       *SkipValue   = 0;
 | |
|     }
 | |
|   } else if (FormData->HighLightedStatement != NULL) {
 | |
|     if (IsSavedHighlightStatement (FormData->HighLightedStatement)) {
 | |
|       //
 | |
|       // Input highlight menu is same as last time highlight menu.
 | |
|       // Base on last time highlight menu to set the top of screen menu and highlight menu.
 | |
|       //
 | |
|       *HighlightMenu = FindHighLightMenuOption (NULL);
 | |
|       ASSERT (*HighlightMenu != NULL);
 | |
| 
 | |
|       //
 | |
|       // Update skip info for this highlight menu.
 | |
|       //
 | |
|       MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);
 | |
|       UpdateOptionSkipLines (MenuOption);
 | |
| 
 | |
|       *TopOfScreen = FindTopOfScreenMenuOption (*HighlightMenu);
 | |
|       if (*TopOfScreen == NULL) {
 | |
|         //
 | |
|         // Not found last time top of screen menu, so base on current highlight menu
 | |
|         // to find the new top of screen menu.
 | |
|         // Make the current highlight menu at the bottom of the form to calculate the
 | |
|         // top of screen menu.
 | |
|         //
 | |
|         if (MenuOption->Skip >= BottomRow - TopRow) {
 | |
|           *TopOfScreen = *HighlightMenu;
 | |
|           TmpValue     = 0;
 | |
|         } else {
 | |
|           *TopOfScreen = FindTopOfScreenMenu (*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);
 | |
|         }
 | |
| 
 | |
|         *SkipValue = TmpValue;
 | |
|       } else {
 | |
|         AdjustDateAndTimePosition (TRUE, TopOfScreen);
 | |
|         MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);
 | |
|         UpdateOptionSkipLines (MenuOption);
 | |
| 
 | |
|         *SkipValue = gHighligthMenuInfo.SkipValue;
 | |
|       }
 | |
| 
 | |
|       AdjustDateAndTimePosition (TRUE, TopOfScreen);
 | |
|     } else {
 | |
|       //
 | |
|       // Input highlight menu is not save as last time highlight menu.
 | |
|       //
 | |
|       *HighlightMenu = FindHighLightMenuOption (FormData->HighLightedStatement);
 | |
|       MenuOption     = MENU_OPTION_FROM_LINK (*HighlightMenu);
 | |
|       UpdateOptionSkipLines (MenuOption);
 | |
| 
 | |
|       //
 | |
|       // Make the current highlight menu at the bottom of the form to calculate the
 | |
|       // top of screen menu.
 | |
|       //
 | |
|       if (MenuOption->Skip >= BottomRow - TopRow) {
 | |
|         *TopOfScreen = *HighlightMenu;
 | |
|         TmpValue     = 0;
 | |
|       } else {
 | |
|         *TopOfScreen = FindTopOfScreenMenu (*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);
 | |
|       }
 | |
| 
 | |
|       *SkipValue = TmpValue;
 | |
|     }
 | |
| 
 | |
|     AdjustDateAndTimePosition (TRUE, TopOfScreen);
 | |
|   } else {
 | |
|     //
 | |
|     // If not has input highlight statement, just return the first one in this form.
 | |
|     //
 | |
|     *TopOfScreen   = gMenuOption.ForwardLink;
 | |
|     *HighlightMenu = gMenuOption.ForwardLink;
 | |
|     if (!IsListEmpty (&gMenuOption)) {
 | |
|       MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);
 | |
|     }
 | |
| 
 | |
|     *SkipValue = 0;
 | |
|   }
 | |
| 
 | |
|   gMisMatch = FALSE;
 | |
| 
 | |
|   //
 | |
|   // First enter to show the menu, update highlight info.
 | |
|   //
 | |
|   UpdateHighlightMenuInfo (*HighlightMenu, *TopOfScreen, *SkipValue);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Record the highlight menu and top of screen menu info.
 | |
| 
 | |
|   @param  Highlight               The menu opton which is highlight.
 | |
|   @param  TopOfScreen             The menu opton which is at the top of the form.
 | |
|   @param  SkipValue               The skip line info for the top of screen menu.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateHighlightMenuInfo (
 | |
|   IN  LIST_ENTRY  *Highlight,
 | |
|   IN  LIST_ENTRY  *TopOfScreen,
 | |
|   IN  UINTN       SkipValue
 | |
|   )
 | |
| {
 | |
|   UI_MENU_OPTION                 *MenuOption;
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
| 
 | |
|   gHighligthMenuInfo.HiiHandle = gFormData->HiiHandle;
 | |
|   gHighligthMenuInfo.FormId    = gFormData->FormId;
 | |
|   gHighligthMenuInfo.SkipValue = (UINT16)SkipValue;
 | |
| 
 | |
|   if (!IsListEmpty (&gMenuOption)) {
 | |
|     MenuOption = MENU_OPTION_FROM_LINK (Highlight);
 | |
|     Statement  = MenuOption->ThisTag;
 | |
| 
 | |
|     gUserInput->SelectedStatement = Statement;
 | |
| 
 | |
|     gHighligthMenuInfo.HLTSequence   = MenuOption->Sequence;
 | |
|     gHighligthMenuInfo.HLTQuestionId = GetQuestionIdInfo (Statement->OpCode);
 | |
|     if (gHighligthMenuInfo.HLTQuestionId == 0) {
 | |
|       //
 | |
|       // if question id == 0, save the opcode buffer..
 | |
|       //
 | |
|       if (gHighligthMenuInfo.HLTOpCode != NULL) {
 | |
|         FreePool (gHighligthMenuInfo.HLTOpCode);
 | |
|       }
 | |
| 
 | |
|       gHighligthMenuInfo.HLTOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);
 | |
|       ASSERT (gHighligthMenuInfo.HLTOpCode != NULL);
 | |
| 
 | |
|       gHighligthMenuInfo.HLTIndex = GetIndexInfoForOpcode (Statement->OpCode);
 | |
|     }
 | |
| 
 | |
|     MenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
 | |
|     Statement  = MenuOption->ThisTag;
 | |
| 
 | |
|     gHighligthMenuInfo.TOSQuestionId = GetQuestionIdInfo (Statement->OpCode);
 | |
|     if (gHighligthMenuInfo.TOSQuestionId == 0) {
 | |
|       //
 | |
|       // if question id == 0, save the opcode buffer..
 | |
|       //
 | |
|       if (gHighligthMenuInfo.TOSOpCode != NULL) {
 | |
|         FreePool (gHighligthMenuInfo.TOSOpCode);
 | |
|       }
 | |
| 
 | |
|       gHighligthMenuInfo.TOSOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);
 | |
|       ASSERT (gHighligthMenuInfo.TOSOpCode != NULL);
 | |
| 
 | |
|       gHighligthMenuInfo.TOSIndex = GetIndexInfoForOpcode (Statement->OpCode);
 | |
|     }
 | |
|   } else {
 | |
|     gUserInput->SelectedStatement = NULL;
 | |
| 
 | |
|     gHighligthMenuInfo.HLTSequence   = 0;
 | |
|     gHighligthMenuInfo.HLTQuestionId = 0;
 | |
|     if (gHighligthMenuInfo.HLTOpCode != NULL) {
 | |
|       FreePool (gHighligthMenuInfo.HLTOpCode);
 | |
|     }
 | |
| 
 | |
|     gHighligthMenuInfo.HLTOpCode = NULL;
 | |
|     gHighligthMenuInfo.HLTIndex  = 0;
 | |
| 
 | |
|     gHighligthMenuInfo.TOSQuestionId = 0;
 | |
|     if (gHighligthMenuInfo.TOSOpCode != NULL) {
 | |
|       FreePool (gHighligthMenuInfo.TOSOpCode);
 | |
|     }
 | |
| 
 | |
|     gHighligthMenuInfo.TOSOpCode = NULL;
 | |
|     gHighligthMenuInfo.TOSIndex  = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update attribut for this menu.
 | |
| 
 | |
|   @param  MenuOption               The menu opton which this attribut used to.
 | |
|   @param  Highlight                Whether this menu will be highlight.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SetDisplayAttribute (
 | |
|   IN UI_MENU_OPTION  *MenuOption,
 | |
|   IN BOOLEAN         Highlight
 | |
|   )
 | |
| {
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
| 
 | |
|   Statement = MenuOption->ThisTag;
 | |
| 
 | |
|   if (Highlight) {
 | |
|     gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (MenuOption->GrayOut) {
 | |
|     gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());
 | |
|   } else {
 | |
|     if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {
 | |
|       gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());
 | |
|     } else {
 | |
|       gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Print string for this menu option.
 | |
| 
 | |
|   @param  MenuOption               The menu opton which this attribut used to.
 | |
|   @param  Col                      The column that this string will be print at.
 | |
|   @param  Row                      The row that this string will be print at.
 | |
|   @param  String                   The string which need to print.
 | |
|   @param  Width                    The width need to print, if string is less than the
 | |
|                                    width, the block space will be used.
 | |
|   @param  Highlight                Whether this menu will be highlight.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DisplayMenuString (
 | |
|   IN UI_MENU_OPTION  *MenuOption,
 | |
|   IN UINTN           Col,
 | |
|   IN UINTN           Row,
 | |
|   IN CHAR16          *String,
 | |
|   IN UINTN           Width,
 | |
|   IN BOOLEAN         Highlight
 | |
|   )
 | |
| {
 | |
|   UINTN  Length;
 | |
| 
 | |
|   //
 | |
|   // Print string with normal color.
 | |
|   //
 | |
|   if (!Highlight) {
 | |
|     PrintStringAtWithWidth (Col, Row, String, Width);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Print the highlight menu string.
 | |
|   // First print the highlight string.
 | |
|   //
 | |
|   SetDisplayAttribute (MenuOption, TRUE);
 | |
|   Length = PrintStringAt (Col, Row, String);
 | |
| 
 | |
|   //
 | |
|   // Second, clean the empty after the string.
 | |
|   //
 | |
|   SetDisplayAttribute (MenuOption, FALSE);
 | |
|   PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether this menu can has option string.
 | |
| 
 | |
|   @param  MenuOption               The menu opton which this attribut used to.
 | |
| 
 | |
|   @retval TRUE                     This menu option can have option string.
 | |
|   @retval FALSE                    This menu option can't have option string.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| HasOptionString (
 | |
|   IN UI_MENU_OPTION  *MenuOption
 | |
|   )
 | |
| {
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
|   CHAR16                         *String;
 | |
|   UINTN                          Size;
 | |
|   EFI_IFR_TEXT                   *TextOp;
 | |
| 
 | |
|   Size      = 0;
 | |
|   Statement = MenuOption->ThisTag;
 | |
| 
 | |
|   //
 | |
|   // See if the second text parameter is really NULL
 | |
|   //
 | |
|   if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
 | |
|     TextOp = (EFI_IFR_TEXT *)Statement->OpCode;
 | |
|     if (TextOp->TextTwo != 0) {
 | |
|       String = GetToken (TextOp->TextTwo, gFormData->HiiHandle);
 | |
|       Size   = StrLen (String);
 | |
|       FreePool (String);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||
 | |
|       (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||
 | |
|       //
 | |
|       // Allow a wide display if text op-code and no secondary text op-code
 | |
|       //
 | |
|       ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))
 | |
|       )
 | |
|   {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Double confirm with user about the action.
 | |
| 
 | |
|   @param  Action               The user input action.
 | |
| 
 | |
|   @retval TRUE                 User confirm with the input or not need user confirm.
 | |
|   @retval FALSE                User want ignore this input.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| FxConfirmPopup (
 | |
|   IN UINT32  Action
 | |
|   )
 | |
| {
 | |
|   EFI_INPUT_KEY  Key;
 | |
|   CHAR16         *CfmStr;
 | |
|   UINTN          CfmStrLen;
 | |
|   UINT32         CheckFlags;
 | |
|   BOOLEAN        RetVal;
 | |
|   UINTN          CatLen;
 | |
|   UINTN          MaxLen;
 | |
| 
 | |
|   CfmStrLen = 0;
 | |
|   CatLen    = StrLen (gConfirmMsgConnect);
 | |
| 
 | |
|   //
 | |
|   // Below action need extra popup dialog to confirm.
 | |
|   //
 | |
|   CheckFlags = BROWSER_ACTION_DISCARD |
 | |
|                BROWSER_ACTION_DEFAULT |
 | |
|                BROWSER_ACTION_SUBMIT |
 | |
|                BROWSER_ACTION_RESET |
 | |
|                BROWSER_ACTION_EXIT;
 | |
| 
 | |
|   //
 | |
|   // Not need to confirm with user, just return TRUE.
 | |
|   //
 | |
|   if ((Action & CheckFlags) == 0) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {
 | |
|     CfmStrLen += StrLen (gConfirmDiscardMsg);
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {
 | |
|     if (CfmStrLen != 0) {
 | |
|       CfmStrLen += CatLen;
 | |
|     }
 | |
| 
 | |
|     CfmStrLen += StrLen (gConfirmDefaultMsg);
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_SUBMIT)  == BROWSER_ACTION_SUBMIT) {
 | |
|     if (CfmStrLen != 0) {
 | |
|       CfmStrLen += CatLen;
 | |
|     }
 | |
| 
 | |
|     CfmStrLen += StrLen (gConfirmSubmitMsg);
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_RESET)  == BROWSER_ACTION_RESET) {
 | |
|     if (CfmStrLen != 0) {
 | |
|       CfmStrLen += CatLen;
 | |
|     }
 | |
| 
 | |
|     CfmStrLen += StrLen (gConfirmResetMsg);
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_EXIT)  == BROWSER_ACTION_EXIT) {
 | |
|     if (CfmStrLen != 0) {
 | |
|       CfmStrLen += CatLen;
 | |
|     }
 | |
| 
 | |
|     CfmStrLen += StrLen (gConfirmExitMsg);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Allocate buffer to save the string.
 | |
|   // String + "?" + "\0"
 | |
|   //
 | |
|   MaxLen = CfmStrLen + 1 + 1;
 | |
|   CfmStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
 | |
|   ASSERT (CfmStr != NULL);
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {
 | |
|     StrCpyS (CfmStr, MaxLen, gConfirmDiscardMsg);
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {
 | |
|     if (CfmStr[0] != 0) {
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmDefaultMsg2nd);
 | |
|     } else {
 | |
|       StrCpyS (CfmStr, MaxLen, gConfirmDefaultMsg);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_SUBMIT)  == BROWSER_ACTION_SUBMIT) {
 | |
|     if (CfmStr[0] != 0) {
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmSubmitMsg2nd);
 | |
|     } else {
 | |
|       StrCpyS (CfmStr, MaxLen, gConfirmSubmitMsg);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_RESET)  == BROWSER_ACTION_RESET) {
 | |
|     if (CfmStr[0] != 0) {
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmResetMsg2nd);
 | |
|     } else {
 | |
|       StrCpyS (CfmStr, MaxLen, gConfirmResetMsg);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((Action & BROWSER_ACTION_EXIT)  == BROWSER_ACTION_EXIT) {
 | |
|     if (CfmStr[0] != 0) {
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);
 | |
|       StrCatS (CfmStr, MaxLen, gConfirmExitMsg2nd);
 | |
|     } else {
 | |
|       StrCpyS (CfmStr, MaxLen, gConfirmExitMsg);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   StrCatS (CfmStr, MaxLen, gConfirmMsgEnd);
 | |
| 
 | |
|   do {
 | |
|     CreateDialog (&Key, gEmptyString, CfmStr, gConfirmOpt, gEmptyString, NULL);
 | |
|   } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) &&
 | |
|            ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptNo[0] | UPPER_LOWER_CASE_OFFSET)) &&
 | |
|            (Key.ScanCode != SCAN_ESC));
 | |
| 
 | |
|   if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) {
 | |
|     RetVal = TRUE;
 | |
|   } else {
 | |
|     RetVal = FALSE;
 | |
|   }
 | |
| 
 | |
|   FreePool (CfmStr);
 | |
| 
 | |
|   return RetVal;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Print string for this menu option.
 | |
| 
 | |
|   @param  MenuOption               The menu opton which this attribut used to.
 | |
|   @param  SkipWidth                The skip width between the left to the start of the prompt.
 | |
|   @param  BeginCol                 The begin column for one menu.
 | |
|   @param  SkipLine                 The skip line for this menu.
 | |
|   @param  BottomRow                The bottom row for this form.
 | |
|   @param  Highlight                Whether this menu will be highlight.
 | |
|   @param  UpdateCol                Whether need to update the column info for Date/Time.
 | |
| 
 | |
|   @retval EFI_SUCESSS              Process the user selection success.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| DisplayOneMenu (
 | |
|   IN UI_MENU_OPTION  *MenuOption,
 | |
|   IN UINTN           SkipWidth,
 | |
|   IN UINTN           BeginCol,
 | |
|   IN UINTN           SkipLine,
 | |
|   IN UINTN           BottomRow,
 | |
|   IN BOOLEAN         Highlight,
 | |
|   IN BOOLEAN         UpdateCol
 | |
|   )
 | |
| {
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
|   UINTN                          Index;
 | |
|   UINT16                         Width;
 | |
|   UINT16                         PromptWidth;
 | |
|   CHAR16                         *StringPtr;
 | |
|   CHAR16                         *OptionString;
 | |
|   CHAR16                         *OutputString;
 | |
|   UINT16                         GlyphWidth;
 | |
|   UINTN                          Temp;
 | |
|   UINTN                          Temp2;
 | |
|   UINTN                          Temp3;
 | |
|   EFI_STATUS                     Status;
 | |
|   UINTN                          Row;
 | |
|   BOOLEAN                        IsProcessingFirstRow;
 | |
|   UINTN                          Col;
 | |
|   UINTN                          PromptLineNum;
 | |
|   UINTN                          OptionLineNum;
 | |
|   CHAR16                         AdjustValue;
 | |
|   UINTN                          MaxRow;
 | |
| 
 | |
|   Statement            = MenuOption->ThisTag;
 | |
|   Temp                 = SkipLine;
 | |
|   Temp2                = SkipLine;
 | |
|   Temp3                = SkipLine;
 | |
|   AdjustValue          = 0;
 | |
|   PromptLineNum        = 0;
 | |
|   OptionLineNum        = 0;
 | |
|   MaxRow               = 0;
 | |
|   IsProcessingFirstRow = TRUE;
 | |
| 
 | |
|   //
 | |
|   // Set default color.
 | |
|   //
 | |
|   SetDisplayAttribute (MenuOption, FALSE);
 | |
| 
 | |
|   //
 | |
|   // 1. Paint the option string.
 | |
|   //
 | |
|   Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (OptionString != NULL) {
 | |
|     if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
 | |
|       //
 | |
|       // Adjust option string for date/time opcode.
 | |
|       //
 | |
|       ProcessStringForDateTime (MenuOption, OptionString, UpdateCol);
 | |
|     }
 | |
| 
 | |
|     Width         = (UINT16)gOptionBlockWidth - 1;
 | |
|     Row           = MenuOption->Row;
 | |
|     GlyphWidth    = 1;
 | |
|     OptionLineNum = 0;
 | |
| 
 | |
|     for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
 | |
|       if (((Temp2 == 0)) && (Row <= BottomRow)) {
 | |
|         if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
 | |
|           //
 | |
|           // For date/time question, it has three menu options for this qustion.
 | |
|           // The first/second menu options with the skip value is 0. the last one
 | |
|           // with skip value is 1.
 | |
|           //
 | |
|           if (MenuOption->Skip != 0) {
 | |
|             //
 | |
|             // For date/ time, print the last past (year for date and second for time)
 | |
|             // - 7 means skip [##/##/ for date and [##:##: for time.
 | |
|             //
 | |
|             DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1 - 7, Highlight);
 | |
|           } else {
 | |
|             //
 | |
|             // For date/ time, print the first and second past (year for date and second for time)
 | |
|             // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string,
 | |
|             // so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it.
 | |
|             DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString) - 1, Highlight);
 | |
|           }
 | |
|         } else {
 | |
|           DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);
 | |
|         }
 | |
| 
 | |
|         OptionLineNum++;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // If there is more string to process print on the next row and increment the Skip value
 | |
|       //
 | |
|       if (StrLen (&OptionString[Index]) != 0) {
 | |
|         if (Temp2 == 0) {
 | |
|           Row++;
 | |
|           //
 | |
|           // Since the Number of lines for this menu entry may or may not be reflected accurately
 | |
|           // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
 | |
|           // some testing to ensure we are keeping this in-sync.
 | |
|           //
 | |
|           // If the difference in rows is greater than or equal to the skip value, increase the skip value
 | |
|           //
 | |
|           if ((Row - MenuOption->Row) >= MenuOption->Skip) {
 | |
|             MenuOption->Skip++;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       FreePool (OutputString);
 | |
|       if (Temp2 != 0) {
 | |
|         Temp2--;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Highlight = FALSE;
 | |
| 
 | |
|     FreePool (OptionString);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 2. Paint the description.
 | |
|   //
 | |
|   PromptWidth   = GetWidth (MenuOption, &AdjustValue);
 | |
|   Row           = MenuOption->Row;
 | |
|   GlyphWidth    = 1;
 | |
|   PromptLineNum = 0;
 | |
| 
 | |
|   if ((MenuOption->Description == NULL) || (MenuOption->Description[0] == '\0')) {
 | |
|     PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);
 | |
|     PromptLineNum++;
 | |
|   } else {
 | |
|     for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
 | |
|       if ((Temp == 0) && (Row <= BottomRow)) {
 | |
|         //
 | |
|         // 1.Clean the start LEFT_SKIPPED_COLUMNS
 | |
|         //
 | |
|         PrintStringAtWithWidth (BeginCol, Row, L"", SkipWidth);
 | |
| 
 | |
|         if ((Statement->OpCode->OpCode == EFI_IFR_REF_OP) && (MenuOption->Col >= 2) && IsProcessingFirstRow) {
 | |
|           //
 | |
|           // Print Arrow for Goto button.
 | |
|           //
 | |
|           PrintCharAt (
 | |
|             MenuOption->Col - 2,
 | |
|             Row,
 | |
|             GEOMETRICSHAPE_RIGHT_TRIANGLE
 | |
|             );
 | |
|           IsProcessingFirstRow = FALSE;
 | |
|         }
 | |
| 
 | |
|         DisplayMenuString (MenuOption, MenuOption->Col, Row, OutputString, PromptWidth + AdjustValue, Highlight);
 | |
|         PromptLineNum++;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // If there is more string to process print on the next row and increment the Skip value
 | |
|       //
 | |
|       if (StrLen (&MenuOption->Description[Index]) != 0) {
 | |
|         if (Temp == 0) {
 | |
|           Row++;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       FreePool (OutputString);
 | |
|       if (Temp != 0) {
 | |
|         Temp--;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Highlight = FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 3. If this is a text op with secondary text information
 | |
|   //
 | |
|   if ((Statement->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT *)Statement->OpCode)->TextTwo != 0)) {
 | |
|     StringPtr = GetToken (((EFI_IFR_TEXT *)Statement->OpCode)->TextTwo, gFormData->HiiHandle);
 | |
| 
 | |
|     Width         = (UINT16)gOptionBlockWidth - 1;
 | |
|     Row           = MenuOption->Row;
 | |
|     GlyphWidth    = 1;
 | |
|     OptionLineNum = 0;
 | |
| 
 | |
|     for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
 | |
|       if ((Temp3 == 0) && (Row <= BottomRow)) {
 | |
|         DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);
 | |
|         OptionLineNum++;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // If there is more string to process print on the next row and increment the Skip value
 | |
|       //
 | |
|       if (StrLen (&StringPtr[Index]) != 0) {
 | |
|         if (Temp3 == 0) {
 | |
|           Row++;
 | |
|           //
 | |
|           // If the rows for text two is greater than or equal to the skip value, increase the skip value
 | |
|           //
 | |
|           if ((Row - MenuOption->Row) >= MenuOption->Skip) {
 | |
|             MenuOption->Skip++;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       FreePool (OutputString);
 | |
|       if (Temp3 != 0) {
 | |
|         Temp3--;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     FreePool (StringPtr);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 4.Line number for Option string and prompt string are not equal.
 | |
|   //  Clean the column whose line number is less.
 | |
|   //
 | |
|   if (HasOptionString (MenuOption) && (OptionLineNum != PromptLineNum)) {
 | |
|     Col    =  OptionLineNum < PromptLineNum ? MenuOption->OptCol : BeginCol;
 | |
|     Row    = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row;
 | |
|     Width  = (UINT16)(OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth);
 | |
|     MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1;
 | |
| 
 | |
|     while (Row <= MaxRow) {
 | |
|       DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Display menu and wait for user to select one menu option, then return it.
 | |
|   If AutoBoot is enabled, then if user doesn't select any option,
 | |
|   after period of time, it will automatically return the first menu option.
 | |
| 
 | |
|   @param  FormData               The current form data info.
 | |
| 
 | |
|   @retval EFI_SUCESSS            Process the user selection success.
 | |
|   @retval EFI_NOT_FOUND          Process option string for orderedlist/Oneof fail.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| UiDisplayMenu (
 | |
|   IN  FORM_DISPLAY_ENGINE_FORM  *FormData
 | |
|   )
 | |
| {
 | |
|   UINTN                          SkipValue;
 | |
|   INTN                           Difference;
 | |
|   UINTN                          DistanceValue;
 | |
|   UINTN                          Row;
 | |
|   UINTN                          Col;
 | |
|   UINTN                          Temp;
 | |
|   UINTN                          Temp2;
 | |
|   UINTN                          TopRow;
 | |
|   UINTN                          BottomRow;
 | |
|   UINTN                          Index;
 | |
|   CHAR16                         *StringPtr;
 | |
|   CHAR16                         *StringRightPtr;
 | |
|   CHAR16                         *StringErrorPtr;
 | |
|   CHAR16                         *OptionString;
 | |
|   CHAR16                         *HelpString;
 | |
|   CHAR16                         *HelpHeaderString;
 | |
|   CHAR16                         *HelpBottomString;
 | |
|   BOOLEAN                        NewLine;
 | |
|   BOOLEAN                        Repaint;
 | |
|   BOOLEAN                        UpArrow;
 | |
|   BOOLEAN                        DownArrow;
 | |
|   EFI_STATUS                     Status;
 | |
|   EFI_INPUT_KEY                  Key;
 | |
|   LIST_ENTRY                     *Link;
 | |
|   LIST_ENTRY                     *NewPos;
 | |
|   LIST_ENTRY                     *TopOfScreen;
 | |
|   LIST_ENTRY                     *SavedListEntry;
 | |
|   UI_MENU_OPTION                 *MenuOption;
 | |
|   UI_MENU_OPTION                 *NextMenuOption;
 | |
|   UI_MENU_OPTION                 *SavedMenuOption;
 | |
|   UI_CONTROL_FLAG                ControlFlag;
 | |
|   UI_SCREEN_OPERATION            ScreenOperation;
 | |
|   FORM_DISPLAY_ENGINE_STATEMENT  *Statement;
 | |
|   BROWSER_HOT_KEY                *HotKey;
 | |
|   UINTN                          HelpPageIndex;
 | |
|   UINTN                          HelpPageCount;
 | |
|   UINTN                          RowCount;
 | |
|   UINTN                          HelpLine;
 | |
|   UINTN                          HelpHeaderLine;
 | |
|   UINTN                          HelpBottomLine;
 | |
|   BOOLEAN                        MultiHelpPage;
 | |
|   UINT16                         EachLineWidth;
 | |
|   UINT16                         HeaderLineWidth;
 | |
|   UINT16                         BottomLineWidth;
 | |
|   EFI_STRING_ID                  HelpInfo;
 | |
|   UI_EVENT_TYPE                  EventType;
 | |
|   BOOLEAN                        SkipHighLight;
 | |
|   EFI_HII_VALUE                  *StatementValue;
 | |
| 
 | |
|   EventType        = UIEventNone;
 | |
|   Status           = EFI_SUCCESS;
 | |
|   HelpString       = NULL;
 | |
|   HelpHeaderString = NULL;
 | |
|   HelpBottomString = NULL;
 | |
|   OptionString     = NULL;
 | |
|   ScreenOperation  = UiNoOperation;
 | |
|   NewLine          = TRUE;
 | |
|   HelpPageCount    = 0;
 | |
|   HelpLine         = 0;
 | |
|   RowCount         = 0;
 | |
|   HelpBottomLine   = 0;
 | |
|   HelpHeaderLine   = 0;
 | |
|   HelpPageIndex    = 0;
 | |
|   MultiHelpPage    = FALSE;
 | |
|   EachLineWidth    = 0;
 | |
|   HeaderLineWidth  = 0;
 | |
|   BottomLineWidth  = 0;
 | |
|   UpArrow          = FALSE;
 | |
|   DownArrow        = FALSE;
 | |
|   SkipValue        = 0;
 | |
|   SkipHighLight    = FALSE;
 | |
| 
 | |
|   NextMenuOption   = NULL;
 | |
|   SavedMenuOption  = NULL;
 | |
|   HotKey           = NULL;
 | |
|   Repaint          = TRUE;
 | |
|   MenuOption       = NULL;
 | |
|   gModalSkipColumn = (CHAR16)(gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6;
 | |
| 
 | |
|   ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
 | |
| 
 | |
|   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;
 | |
|   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;
 | |
| 
 | |
|   Row = TopRow;
 | |
|   if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|     Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gModalSkipColumn;
 | |
|   } else {
 | |
|     Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS;
 | |
|   }
 | |
| 
 | |
|   FindTopMenu (FormData, &TopOfScreen, &NewPos, &SkipValue);
 | |
|   if (!IsListEmpty (&gMenuOption)) {
 | |
|     NextMenuOption                = MENU_OPTION_FROM_LINK (NewPos);
 | |
|     gUserInput->SelectedStatement = NextMenuOption->ThisTag;
 | |
|   }
 | |
| 
 | |
|   gST->ConOut->EnableCursor (gST->ConOut, FALSE);
 | |
| 
 | |
|   ControlFlag = CfInitialization;
 | |
|   while (TRUE) {
 | |
|     switch (ControlFlag) {
 | |
|       case CfInitialization:
 | |
|         if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) ||
 | |
|             (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid)))
 | |
|         {
 | |
|           //
 | |
|           // Clear Statement range if different formset is painted.
 | |
|           //
 | |
|           ClearLines (
 | |
|             gStatementDimensions.LeftColumn,
 | |
|             gStatementDimensions.RightColumn,
 | |
|             TopRow - SCROLL_ARROW_HEIGHT,
 | |
|             BottomRow + SCROLL_ARROW_HEIGHT,
 | |
|             GetFieldTextColor ()
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         ControlFlag = CfRepaint;
 | |
|         break;
 | |
| 
 | |
|       case CfRepaint:
 | |
|         ControlFlag = CfRefreshHighLight;
 | |
| 
 | |
|         if (Repaint) {
 | |
|           //
 | |
|           // Display menu
 | |
|           //
 | |
|           DownArrow = FALSE;
 | |
|           UpArrow   = FALSE;
 | |
|           Row       = TopRow;
 | |
| 
 | |
|           gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
 | |
| 
 | |
|           //
 | |
|           // 1. Check whether need to print the arrow up.
 | |
|           //
 | |
|           if (!ValueIsScroll (TRUE, TopOfScreen)) {
 | |
|             UpArrow = TRUE;
 | |
|           }
 | |
| 
 | |
|           if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|             PrintStringAtWithWidth (gStatementDimensions.LeftColumn + gModalSkipColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);
 | |
|           } else {
 | |
|             PrintStringAtWithWidth (gStatementDimensions.LeftColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);
 | |
|           }
 | |
| 
 | |
|           if (UpArrow) {
 | |
|             gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());
 | |
|             PrintCharAt (
 | |
|               gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
 | |
|               TopRow - SCROLL_ARROW_HEIGHT,
 | |
|               ARROW_UP
 | |
|               );
 | |
|             gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // 2.Paint the menu.
 | |
|           //
 | |
|           for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {
 | |
|             MenuOption      = MENU_OPTION_FROM_LINK (Link);
 | |
|             MenuOption->Row = Row;
 | |
|             MenuOption->Col = Col;
 | |
|             if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|               MenuOption->OptCol = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth + gModalSkipColumn;
 | |
|             } else {
 | |
|               MenuOption->OptCol = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth;
 | |
|             }
 | |
| 
 | |
|             if (MenuOption->NestInStatement) {
 | |
|               MenuOption->Col += SUBTITLE_INDENT;
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // Save the highlight menu, will be used in CfRefreshHighLight case.
 | |
|             //
 | |
|             if (Link == NewPos) {
 | |
|               SavedMenuOption = MenuOption;
 | |
|               SkipHighLight   = TRUE;
 | |
|             }
 | |
| 
 | |
|             if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|               Status = DisplayOneMenu (
 | |
|                          MenuOption,
 | |
|                          MenuOption->Col - gStatementDimensions.LeftColumn,
 | |
|                          gStatementDimensions.LeftColumn + gModalSkipColumn,
 | |
|                          Link == TopOfScreen ? SkipValue : 0,
 | |
|                          BottomRow,
 | |
|                          (BOOLEAN)((Link == NewPos) && IsSelectable (MenuOption)),
 | |
|                          TRUE
 | |
|                          );
 | |
|             } else {
 | |
|               Status = DisplayOneMenu (
 | |
|                          MenuOption,
 | |
|                          MenuOption->Col - gStatementDimensions.LeftColumn,
 | |
|                          gStatementDimensions.LeftColumn,
 | |
|                          Link == TopOfScreen ? SkipValue : 0,
 | |
|                          BottomRow,
 | |
|                          (BOOLEAN)((Link == NewPos) && IsSelectable (MenuOption)),
 | |
|                          TRUE
 | |
|                          );
 | |
|             }
 | |
| 
 | |
|             if (EFI_ERROR (Status)) {
 | |
|               if (gMisMatch) {
 | |
|                 return EFI_SUCCESS;
 | |
|               } else {
 | |
|                 return Status;
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // 3. Update the row info which will be used by next menu.
 | |
|             //
 | |
|             if (Link == TopOfScreen) {
 | |
|               Row += MenuOption->Skip - SkipValue;
 | |
|             } else {
 | |
|               Row += MenuOption->Skip;
 | |
|             }
 | |
| 
 | |
|             if (Row > BottomRow) {
 | |
|               if (!ValueIsScroll (FALSE, Link)) {
 | |
|                 DownArrow = TRUE;
 | |
|               }
 | |
| 
 | |
|               Row = BottomRow + 1;
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // 3. Menus in this form may not cover all form, clean the remain field.
 | |
|           //
 | |
|           while (Row <= BottomRow) {
 | |
|             if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|               PrintStringAtWithWidth (gStatementDimensions.LeftColumn + gModalSkipColumn, Row++, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);
 | |
|             } else {
 | |
|               PrintStringAtWithWidth (gStatementDimensions.LeftColumn, Row++, L"", gStatementDimensions.RightColumn - gHelpBlockWidth - gStatementDimensions.LeftColumn);
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // 4. Print the down arrow row.
 | |
|           //
 | |
|           if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|             PrintStringAtWithWidth (gStatementDimensions.LeftColumn + gModalSkipColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 *  +gModalSkipColumn);
 | |
|           } else {
 | |
|             PrintStringAtWithWidth (gStatementDimensions.LeftColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);
 | |
|           }
 | |
| 
 | |
|           if (DownArrow) {
 | |
|             gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());
 | |
|             PrintCharAt (
 | |
|               gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
 | |
|               BottomRow + SCROLL_ARROW_HEIGHT,
 | |
|               ARROW_DOWN
 | |
|               );
 | |
|             gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
 | |
|           }
 | |
| 
 | |
|           MenuOption = NULL;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfRefreshHighLight:
 | |
| 
 | |
|         //
 | |
|         // MenuOption: Last menu option that need to remove hilight
 | |
|         //             MenuOption is set to NULL in Repaint
 | |
|         // NewPos:     Current menu option that need to hilight
 | |
|         //
 | |
|         ControlFlag = CfUpdateHelpString;
 | |
| 
 | |
|         ASSERT (NewPos != NULL);
 | |
|         UpdateHighlightMenuInfo (NewPos, TopOfScreen, SkipValue);
 | |
| 
 | |
|         if (SkipHighLight) {
 | |
|           SkipHighLight = FALSE;
 | |
|           MenuOption    = SavedMenuOption;
 | |
|           RefreshKeyHelp (gFormData, SavedMenuOption->ThisTag, FALSE);
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (IsListEmpty (&gMenuOption)) {
 | |
|           //
 | |
|           // No menu option, just update the hotkey filed.
 | |
|           //
 | |
|           RefreshKeyHelp (gFormData, NULL, FALSE);
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if ((MenuOption != NULL) && (TopOfScreen == &MenuOption->Link)) {
 | |
|           Temp = SkipValue;
 | |
|         } else {
 | |
|           Temp = 0;
 | |
|         }
 | |
| 
 | |
|         if (NewPos == TopOfScreen) {
 | |
|           Temp2 = SkipValue;
 | |
|         } else {
 | |
|           Temp2 = 0;
 | |
|         }
 | |
| 
 | |
|         if ((MenuOption == NULL) || (NewPos != &MenuOption->Link)) {
 | |
|           if (MenuOption != NULL) {
 | |
|             //
 | |
|             // Remove the old highlight menu.
 | |
|             //
 | |
|             Status = DisplayOneMenu (
 | |
|                        MenuOption,
 | |
|                        MenuOption->Col - gStatementDimensions.LeftColumn,
 | |
|                        gStatementDimensions.LeftColumn,
 | |
|                        Temp,
 | |
|                        BottomRow,
 | |
|                        FALSE,
 | |
|                        FALSE
 | |
|                        );
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // This is the current selected statement
 | |
|           //
 | |
|           MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
|           RefreshKeyHelp (gFormData, MenuOption->ThisTag, FALSE);
 | |
| 
 | |
|           if (!IsSelectable (MenuOption)) {
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           Status = DisplayOneMenu (
 | |
|                      MenuOption,
 | |
|                      MenuOption->Col - gStatementDimensions.LeftColumn,
 | |
|                      gStatementDimensions.LeftColumn,
 | |
|                      Temp2,
 | |
|                      BottomRow,
 | |
|                      TRUE,
 | |
|                      FALSE
 | |
|                      );
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfUpdateHelpString:
 | |
|         ControlFlag = CfPrepareToReadKey;
 | |
|         if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // NewLine means only update highlight menu (remove old highlight and highlith
 | |
|         // the new one), not need to full repain the form.
 | |
|         //
 | |
|         if (Repaint || NewLine) {
 | |
|           if (IsListEmpty (&gMenuOption)) {
 | |
|             //
 | |
|             // Don't print anything if no mwnu option.
 | |
|             //
 | |
|             StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
 | |
|           } else {
 | |
|             //
 | |
|             // Don't print anything if it is a NULL help token
 | |
|             //
 | |
|             ASSERT (MenuOption != NULL);
 | |
|             HelpInfo       = ((EFI_IFR_STATEMENT_HEADER *)((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;
 | |
|             Statement      = MenuOption->ThisTag;
 | |
|             StatementValue = &Statement->CurrentValue;
 | |
|             if ((HelpInfo == 0) || !IsSelectable (MenuOption)) {
 | |
|               if (((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) && (StatementValue->Value.date.Month == 0xff)) || ((Statement->OpCode->OpCode == EFI_IFR_TIME_OP) && (StatementValue->Value.time.Hour == 0xff))) {
 | |
|                 StringPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);
 | |
|               } else {
 | |
|                 StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
 | |
|               }
 | |
|             } else {
 | |
|               if (((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) && (StatementValue->Value.date.Month == 0xff)) || ((Statement->OpCode->OpCode == EFI_IFR_TIME_OP) && (StatementValue->Value.time.Hour == 0xff))) {
 | |
|                 StringRightPtr = GetToken (HelpInfo, gFormData->HiiHandle);
 | |
|                 StringErrorPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);
 | |
|                 StringPtr      = AllocateZeroPool ((StrLen (StringRightPtr) + StrLen (StringErrorPtr)+ 1) * sizeof (CHAR16));
 | |
|                 StrCpyS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringRightPtr);
 | |
|                 StrCatS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringErrorPtr);
 | |
|                 FreePool (StringRightPtr);
 | |
|                 FreePool (StringErrorPtr);
 | |
|               } else {
 | |
|                 StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);
 | |
|               }
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           RowCount      = BottomRow - TopRow + 1;
 | |
|           HelpPageIndex = 0;
 | |
|           //
 | |
|           // 1.Calculate how many line the help string need to print.
 | |
|           //
 | |
|           if (HelpString != NULL) {
 | |
|             FreePool (HelpString);
 | |
|             HelpString = NULL;
 | |
|           }
 | |
| 
 | |
|           HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);
 | |
|           FreePool (StringPtr);
 | |
| 
 | |
|           if (HelpLine > RowCount) {
 | |
|             MultiHelpPage = TRUE;
 | |
|             StringPtr     = GetToken (STRING_TOKEN (ADJUST_HELP_PAGE_UP), gHiiHandle);
 | |
|             if (HelpHeaderString != NULL) {
 | |
|               FreePool (HelpHeaderString);
 | |
|               HelpHeaderString = NULL;
 | |
|             }
 | |
| 
 | |
|             HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, 0);
 | |
|             FreePool (StringPtr);
 | |
|             StringPtr = GetToken (STRING_TOKEN (ADJUST_HELP_PAGE_DOWN), gHiiHandle);
 | |
|             if (HelpBottomString != NULL) {
 | |
|               FreePool (HelpBottomString);
 | |
|               HelpBottomString = NULL;
 | |
|             }
 | |
| 
 | |
|             HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, 0);
 | |
|             FreePool (StringPtr);
 | |
|             //
 | |
|             // Calculate the help page count.
 | |
|             //
 | |
|             if (HelpLine > 2 * RowCount - 2) {
 | |
|               HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;
 | |
|               if ((HelpLine - RowCount + 1) % (RowCount - 2) != 0) {
 | |
|                 HelpPageCount += 1;
 | |
|               }
 | |
|             } else {
 | |
|               HelpPageCount = 2;
 | |
|             }
 | |
|           } else {
 | |
|             MultiHelpPage = FALSE;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Check whether need to show the 'More(U/u)' at the begin.
 | |
|         // Base on current direct info, here shows aligned to the right side of the column.
 | |
|         // If the direction is multi line and aligned to right side may have problem, so
 | |
|         // add ASSERT code here.
 | |
|         //
 | |
|         if (HelpPageIndex > 0) {
 | |
|           gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());
 | |
|           for (Index = 0; Index < HelpHeaderLine; Index++) {
 | |
|             ASSERT (HelpHeaderLine == 1);
 | |
|             ASSERT (GetStringWidth (HelpHeaderString) / 2 < ((UINT32)gHelpBlockWidth - 1));
 | |
|             PrintStringAtWithWidth (
 | |
|               gStatementDimensions.RightColumn - gHelpBlockWidth,
 | |
|               Index + TopRow,
 | |
|               gEmptyString,
 | |
|               gHelpBlockWidth
 | |
|               );
 | |
|             PrintStringAt (
 | |
|               gStatementDimensions.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,
 | |
|               Index + TopRow,
 | |
|               &HelpHeaderString[Index * HeaderLineWidth]
 | |
|               );
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         gST->ConOut->SetAttribute (gST->ConOut, GetHelpTextColor ());
 | |
|         //
 | |
|         // Print the help string info.
 | |
|         //
 | |
|         if (!MultiHelpPage) {
 | |
|           for (Index = 0; Index < HelpLine; Index++) {
 | |
|             PrintStringAtWithWidth (
 | |
|               gStatementDimensions.RightColumn - gHelpBlockWidth,
 | |
|               Index + TopRow,
 | |
|               &HelpString[Index * EachLineWidth],
 | |
|               gHelpBlockWidth
 | |
|               );
 | |
|           }
 | |
| 
 | |
|           for ( ; Index < RowCount; Index++) {
 | |
|             PrintStringAtWithWidth (
 | |
|               gStatementDimensions.RightColumn - gHelpBlockWidth,
 | |
|               Index + TopRow,
 | |
|               gEmptyString,
 | |
|               gHelpBlockWidth
 | |
|               );
 | |
|           }
 | |
| 
 | |
|           gST->ConOut->SetCursorPosition (gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);
 | |
|         } else {
 | |
|           if (HelpPageIndex == 0) {
 | |
|             for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {
 | |
|               PrintStringAtWithWidth (
 | |
|                 gStatementDimensions.RightColumn - gHelpBlockWidth,
 | |
|                 Index + TopRow,
 | |
|                 &HelpString[Index * EachLineWidth],
 | |
|                 gHelpBlockWidth
 | |
|                 );
 | |
|             }
 | |
|           } else {
 | |
|             for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) &&
 | |
|                  (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++)
 | |
|             {
 | |
|               PrintStringAtWithWidth (
 | |
|                 gStatementDimensions.RightColumn - gHelpBlockWidth,
 | |
|                 Index + TopRow + HelpHeaderLine,
 | |
|                 &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth],
 | |
|                 gHelpBlockWidth
 | |
|                 );
 | |
|             }
 | |
| 
 | |
|             if (HelpPageIndex == HelpPageCount - 1) {
 | |
|               for ( ; Index < RowCount - HelpHeaderLine; Index++) {
 | |
|                 PrintStringAtWithWidth (
 | |
|                   gStatementDimensions.RightColumn - gHelpBlockWidth,
 | |
|                   Index + TopRow + HelpHeaderLine,
 | |
|                   gEmptyString,
 | |
|                   gHelpBlockWidth
 | |
|                   );
 | |
|               }
 | |
| 
 | |
|               gST->ConOut->SetCursorPosition (gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);
 | |
|             }
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Check whether need to print the 'More(D/d)' at the bottom.
 | |
|         // Base on current direct info, here shows aligned to the right side of the column.
 | |
|         // If the direction is multi line and aligned to right side may have problem, so
 | |
|         // add ASSERT code here.
 | |
|         //
 | |
|         if ((HelpPageIndex < HelpPageCount - 1) && MultiHelpPage) {
 | |
|           gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());
 | |
|           for (Index = 0; Index < HelpBottomLine; Index++) {
 | |
|             ASSERT (HelpBottomLine == 1);
 | |
|             ASSERT (GetStringWidth (HelpBottomString) / 2 < ((UINT32)gHelpBlockWidth - 1));
 | |
|             PrintStringAtWithWidth (
 | |
|               gStatementDimensions.RightColumn - gHelpBlockWidth,
 | |
|               BottomRow + Index - HelpBottomLine + 1,
 | |
|               gEmptyString,
 | |
|               gHelpBlockWidth
 | |
|               );
 | |
|             PrintStringAt (
 | |
|               gStatementDimensions.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,
 | |
|               BottomRow + Index - HelpBottomLine + 1,
 | |
|               &HelpBottomString[Index * BottomLineWidth]
 | |
|               );
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Reset this flag every time we finish using it.
 | |
|         //
 | |
|         Repaint = FALSE;
 | |
|         NewLine = FALSE;
 | |
|         break;
 | |
| 
 | |
|       case CfPrepareToReadKey:
 | |
|         ControlFlag     = CfReadKey;
 | |
|         ScreenOperation = UiNoOperation;
 | |
|         break;
 | |
| 
 | |
|       case CfReadKey:
 | |
|         ControlFlag = CfScreenOperation;
 | |
| 
 | |
|         //
 | |
|         // Wait for user's selection
 | |
|         //
 | |
|         while (TRUE) {
 | |
|           Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | |
|           if (!EFI_ERROR (Status)) {
 | |
|             EventType = UIEventKey;
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // If we encounter error, continue to read another key in.
 | |
|           //
 | |
|           if (Status != EFI_NOT_READY) {
 | |
|             continue;
 | |
|           }
 | |
| 
 | |
|           EventType = UiWaitForEvent (gST->ConIn->WaitForKey);
 | |
|           if (EventType == UIEventKey) {
 | |
|             gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (EventType == UIEventDriver) {
 | |
|           gMisMatch          = TRUE;
 | |
|           gUserInput->Action = BROWSER_ACTION_NONE;
 | |
|           ControlFlag        = CfExit;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if (EventType == UIEventTimeOut) {
 | |
|           gUserInput->Action = BROWSER_ACTION_FORM_EXIT;
 | |
|           ControlFlag        = CfExit;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         switch (Key.UnicodeChar) {
 | |
|           case CHAR_CARRIAGE_RETURN:
 | |
|             if ((MenuOption == NULL) || MenuOption->GrayOut || MenuOption->ReadOnly) {
 | |
|               ControlFlag = CfReadKey;
 | |
|               break;
 | |
|             }
 | |
| 
 | |
|             ScreenOperation = UiSelect;
 | |
|             gDirection      = 0;
 | |
|             break;
 | |
| 
 | |
|           //
 | |
|           // We will push the adjustment of these numeric values directly to the input handler
 | |
|           //  NOTE: we won't handle manual input numeric
 | |
|           //
 | |
|           case '+':
 | |
|           case '-':
 | |
|             //
 | |
|             // If the screen has no menu items, and the user didn't select UiReset
 | |
|             // ignore the selection and go back to reading keys.
 | |
|             //
 | |
|             ASSERT (MenuOption != NULL);
 | |
|             if (IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {
 | |
|               ControlFlag = CfReadKey;
 | |
|               break;
 | |
|             }
 | |
| 
 | |
|             Statement = MenuOption->ThisTag;
 | |
|             if (  (Statement->OpCode->OpCode == EFI_IFR_DATE_OP)
 | |
|                || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)
 | |
|                || ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (GetFieldFromNum (Statement->OpCode) != 0))
 | |
|                   )
 | |
|             {
 | |
|               if (Key.UnicodeChar == '+') {
 | |
|                 gDirection = SCAN_RIGHT;
 | |
|               } else {
 | |
|                 gDirection = SCAN_LEFT;
 | |
|               }
 | |
| 
 | |
|               Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);
 | |
|               if (OptionString != NULL) {
 | |
|                 FreePool (OptionString);
 | |
|               }
 | |
| 
 | |
|               if (EFI_ERROR (Status)) {
 | |
|                 //
 | |
|                 // Repaint to clear possible error prompt pop-up
 | |
|                 //
 | |
|                 Repaint = TRUE;
 | |
|                 NewLine = TRUE;
 | |
|               } else {
 | |
|                 ControlFlag = CfExit;
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             break;
 | |
| 
 | |
|           case '^':
 | |
|             ScreenOperation = UiUp;
 | |
|             break;
 | |
| 
 | |
|           case 'V':
 | |
|           case 'v':
 | |
|             ScreenOperation = UiDown;
 | |
|             break;
 | |
| 
 | |
|           case ' ':
 | |
|             if (IsListEmpty (&gMenuOption)) {
 | |
|               ControlFlag = CfReadKey;
 | |
|               break;
 | |
|             }
 | |
| 
 | |
|             ASSERT (MenuOption != NULL);
 | |
|             if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP) && !MenuOption->GrayOut && !MenuOption->ReadOnly) {
 | |
|               ScreenOperation = UiSelect;
 | |
|             }
 | |
| 
 | |
|             break;
 | |
| 
 | |
|           case 'D':
 | |
|           case 'd':
 | |
|             if (!MultiHelpPage) {
 | |
|               ControlFlag = CfReadKey;
 | |
|               break;
 | |
|             }
 | |
| 
 | |
|             ControlFlag   = CfUpdateHelpString;
 | |
|             HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;
 | |
|             break;
 | |
| 
 | |
|           case 'U':
 | |
|           case 'u':
 | |
|             if (!MultiHelpPage) {
 | |
|               ControlFlag = CfReadKey;
 | |
|               break;
 | |
|             }
 | |
| 
 | |
|             ControlFlag   = CfUpdateHelpString;
 | |
|             HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;
 | |
|             break;
 | |
| 
 | |
|           case CHAR_NULL:
 | |
|             for (Index = 0; Index < mScanCodeNumber; Index++) {
 | |
|               if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
 | |
|                 ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
 | |
|                 break;
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && ((Key.ScanCode == SCAN_ESC) || (Index == mScanCodeNumber))) {
 | |
|               //
 | |
|               // ModalForm has no ESC key and Hot Key.
 | |
|               //
 | |
|               ControlFlag = CfReadKey;
 | |
|             } else if (Index == mScanCodeNumber) {
 | |
|               //
 | |
|               // Check whether Key matches the registered hot key.
 | |
|               //
 | |
|               HotKey = NULL;
 | |
|               HotKey = GetHotKeyFromRegisterList (&Key);
 | |
|               if (HotKey != NULL) {
 | |
|                 ScreenOperation = UiHotKey;
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfScreenOperation:
 | |
|         if ((ScreenOperation != UiReset) && (ScreenOperation != UiHotKey)) {
 | |
|           //
 | |
|           // If the screen has no menu items, and the user didn't select UiReset or UiHotKey
 | |
|           // ignore the selection and go back to reading keys.
 | |
|           //
 | |
|           if (IsListEmpty (&gMenuOption)) {
 | |
|             ControlFlag = CfReadKey;
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         for (Index = 0;
 | |
|              Index < ARRAY_SIZE (gScreenOperationToControlFlag);
 | |
|              Index++
 | |
|              )
 | |
|         {
 | |
|           if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
 | |
|             ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfUiSelect:
 | |
|         ControlFlag = CfRepaint;
 | |
| 
 | |
|         ASSERT (MenuOption != NULL);
 | |
|         Statement = MenuOption->ThisTag;
 | |
|         if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         switch (Statement->OpCode->OpCode) {
 | |
|           case EFI_IFR_REF_OP:
 | |
|           case EFI_IFR_ACTION_OP:
 | |
|           case EFI_IFR_RESET_BUTTON_OP:
 | |
|             ControlFlag = CfExit;
 | |
|             break;
 | |
| 
 | |
|           default:
 | |
|             //
 | |
|             // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
 | |
|             //
 | |
|             RefreshKeyHelp (gFormData, Statement, TRUE);
 | |
|             Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);
 | |
| 
 | |
|             if (OptionString != NULL) {
 | |
|               FreePool (OptionString);
 | |
|             }
 | |
| 
 | |
|             if (EFI_ERROR (Status)) {
 | |
|               Repaint = TRUE;
 | |
|               NewLine = TRUE;
 | |
|               RefreshKeyHelp (gFormData, Statement, FALSE);
 | |
|               break;
 | |
|             } else {
 | |
|               ControlFlag = CfExit;
 | |
|               break;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfUiReset:
 | |
|         //
 | |
|         // We come here when someone press ESC
 | |
|         // If the policy is not exit front page when user press ESC, process here.
 | |
|         //
 | |
|         if (!FormExitPolicy ()) {
 | |
|           Repaint     = TRUE;
 | |
|           NewLine     = TRUE;
 | |
|           ControlFlag = CfRepaint;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         gUserInput->Action = BROWSER_ACTION_FORM_EXIT;
 | |
|         ControlFlag        = CfExit;
 | |
|         break;
 | |
| 
 | |
|       case CfUiHotKey:
 | |
|         ControlFlag = CfRepaint;
 | |
| 
 | |
|         ASSERT (HotKey != NULL);
 | |
| 
 | |
|         if (FxConfirmPopup (HotKey->Action)) {
 | |
|           gUserInput->Action = HotKey->Action;
 | |
|           if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {
 | |
|             gUserInput->DefaultId = HotKey->DefaultId;
 | |
|           }
 | |
| 
 | |
|           ControlFlag = CfExit;
 | |
|         } else {
 | |
|           Repaint     = TRUE;
 | |
|           NewLine     = TRUE;
 | |
|           ControlFlag = CfRepaint;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfUiLeft:
 | |
|         ControlFlag = CfRepaint;
 | |
|         ASSERT (MenuOption != NULL);
 | |
|         if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
 | |
|           if (MenuOption->Sequence != 0) {
 | |
|             //
 | |
|             // In the middle or tail of the Date/Time op-code set, go left.
 | |
|             //
 | |
|             ASSERT (NewPos != NULL);
 | |
|             NewPos = NewPos->BackLink;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfUiRight:
 | |
|         ControlFlag = CfRepaint;
 | |
|         ASSERT (MenuOption != NULL);
 | |
|         if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
 | |
|           if (MenuOption->Sequence != 2) {
 | |
|             //
 | |
|             // In the middle or tail of the Date/Time op-code set, go left.
 | |
|             //
 | |
|             ASSERT (NewPos != NULL);
 | |
|             NewPos = NewPos->ForwardLink;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         break;
 | |
| 
 | |
|       case CfUiUp:
 | |
|         ControlFlag = CfRepaint;
 | |
|         NewLine     = TRUE;
 | |
| 
 | |
|         SavedListEntry = NewPos;
 | |
|         ASSERT (NewPos != NULL);
 | |
| 
 | |
|         MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
|         ASSERT (MenuOption != NULL);
 | |
| 
 | |
|         //
 | |
|         // Adjust Date/Time position before we advance forward.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (TRUE, &NewPos);
 | |
| 
 | |
|         NewPos = NewPos->BackLink;
 | |
|         //
 | |
|         // Find next selectable menu or the first menu beyond current form.
 | |
|         //
 | |
|         Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow, FALSE);
 | |
|         if (Difference < 0) {
 | |
|           //
 | |
|           // We hit the begining MenuOption that can be focused
 | |
|           // so we simply scroll to the top.
 | |
|           //
 | |
|           Repaint = TRUE;
 | |
|           if ((TopOfScreen != gMenuOption.ForwardLink) || (SkipValue != 0)) {
 | |
|             TopOfScreen = gMenuOption.ForwardLink;
 | |
|             NewPos      = SavedListEntry;
 | |
|             SkipValue   = 0;
 | |
|           } else {
 | |
|             //
 | |
|             // Scroll up to the last page when we have arrived at top page.
 | |
|             //
 | |
|             TopOfScreen = FindTopOfScreenMenu (gMenuOption.BackLink, BottomRow - TopRow, &SkipValue);
 | |
|             NewPos      = gMenuOption.BackLink;
 | |
|             MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow, TRUE);
 | |
|           }
 | |
|         } else {
 | |
|           NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
| 
 | |
|           if (MenuOption->Row < TopRow + Difference + NextMenuOption->Skip) {
 | |
|             //
 | |
|             // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
 | |
|             //
 | |
|             TopOfScreen = NewPos;
 | |
|             Repaint     = TRUE;
 | |
|             SkipValue   = 0;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Check whether new highlight menu is selectable, if not, keep highlight on the old one.
 | |
|           //
 | |
|           // BottomRow - TopRow + 1 means the total rows current forms supported.
 | |
|           // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu
 | |
|           // and new top menu. New top menu will all shows in next form, but last highlight menu
 | |
|           // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the
 | |
|           // last highlight menu.
 | |
|           //
 | |
|           if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) &&
 | |
|               (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1))
 | |
|           {
 | |
|             NewPos = SavedListEntry;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         UpdateStatusBar (INPUT_ERROR, FALSE);
 | |
| 
 | |
|         //
 | |
|         // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | |
|         AdjustDateAndTimePosition (TRUE, &NewPos);
 | |
| 
 | |
|         UpdateHighlightMenuInfo (NewPos, TopOfScreen, SkipValue);
 | |
|         break;
 | |
| 
 | |
|       case CfUiPageUp:
 | |
|         //
 | |
|         // SkipValue means lines is skipped when show the top menu option.
 | |
|         //
 | |
|         ControlFlag = CfRepaint;
 | |
|         NewLine     = TRUE;
 | |
|         Repaint     = TRUE;
 | |
| 
 | |
|         Link = TopOfScreen;
 | |
|         //
 | |
|         // First minus the menu of the top screen, it's value is SkipValue.
 | |
|         //
 | |
|         if (SkipValue >= BottomRow - TopRow + 1) {
 | |
|           //
 | |
|           // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one
 | |
|           // form of options to be show, so just update the SkipValue to show the next
 | |
|           // parts of options.
 | |
|           //
 | |
|           SkipValue -= BottomRow - TopRow + 1;
 | |
|           NewPos     = TopOfScreen;
 | |
|           break;
 | |
|         } else {
 | |
|           Index = (BottomRow + 1) - SkipValue - TopRow;
 | |
|         }
 | |
| 
 | |
|         TopOfScreen = FindTopOfScreenMenu (TopOfScreen, Index, &SkipValue);
 | |
|         NewPos      = TopOfScreen;
 | |
|         MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE);
 | |
| 
 | |
|         UpdateStatusBar (INPUT_ERROR, FALSE);
 | |
| 
 | |
|         //
 | |
|         // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
 | |
|         // Don't do this when we are already in the first page.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | |
|         AdjustDateAndTimePosition (TRUE, &NewPos);
 | |
| 
 | |
|         UpdateHighlightMenuInfo (NewPos, TopOfScreen, SkipValue);
 | |
|         break;
 | |
| 
 | |
|       case CfUiPageDown:
 | |
|         //
 | |
|         // SkipValue means lines is skipped when show the top menu option.
 | |
|         //
 | |
|         ControlFlag = CfRepaint;
 | |
|         NewLine     = TRUE;
 | |
|         Repaint     = TRUE;
 | |
| 
 | |
|         Link           = TopOfScreen;
 | |
|         NextMenuOption = MENU_OPTION_FROM_LINK (Link);
 | |
|         Index          = TopRow + NextMenuOption->Skip - SkipValue;
 | |
|         //
 | |
|         // Count to the menu option which will show at the top of the next form.
 | |
|         //
 | |
|         while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {
 | |
|           Link           = Link->ForwardLink;
 | |
|           NextMenuOption = MENU_OPTION_FROM_LINK (Link);
 | |
|           Index          = Index + NextMenuOption->Skip;
 | |
|         }
 | |
| 
 | |
|         if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {
 | |
|           //
 | |
|           // Highlight on the last menu which can be highlight.
 | |
|           //
 | |
|           Repaint = FALSE;
 | |
|           MoveToNextStatement (TRUE, &Link, Index - TopRow, TRUE);
 | |
|         } else {
 | |
|           //
 | |
|           // Calculate the skip line for top of screen menu.
 | |
|           //
 | |
|           if (Link == TopOfScreen) {
 | |
|             //
 | |
|             // The top of screen menu option occupies the entire form.
 | |
|             //
 | |
|             SkipValue += BottomRow - TopRow + 1;
 | |
|           } else {
 | |
|             SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));
 | |
|           }
 | |
| 
 | |
|           TopOfScreen = Link;
 | |
|           MenuOption  = NULL;
 | |
|           //
 | |
|           // Move to the Next selectable menu.
 | |
|           //
 | |
|           MoveToNextStatement (FALSE, &Link, BottomRow - TopRow, TRUE);
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Save the menu as the next highlight menu.
 | |
|         //
 | |
|         NewPos = Link;
 | |
| 
 | |
|         UpdateStatusBar (INPUT_ERROR, FALSE);
 | |
| 
 | |
|         //
 | |
|         // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
 | |
|         // Don't do this when we are already in the last page.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | |
|         AdjustDateAndTimePosition (TRUE, &NewPos);
 | |
| 
 | |
|         UpdateHighlightMenuInfo (NewPos, TopOfScreen, SkipValue);
 | |
|         break;
 | |
| 
 | |
|       case CfUiDown:
 | |
|         //
 | |
|         // SkipValue means lines is skipped when show the top menu option.
 | |
|         // NewPos  points to the menu which is highlighted now.
 | |
|         //
 | |
|         ControlFlag = CfRepaint;
 | |
|         NewLine     = TRUE;
 | |
| 
 | |
|         if (NewPos == TopOfScreen) {
 | |
|           Temp2 = SkipValue;
 | |
|         } else {
 | |
|           Temp2 = 0;
 | |
|         }
 | |
| 
 | |
|         SavedListEntry = NewPos;
 | |
|         //
 | |
|         // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
 | |
|         // to be one that progresses to the next set of op-codes, we need to advance to the last
 | |
|         // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
 | |
|         // checking can be done.  The only other logic we need to introduce is that if a Date/Time
 | |
|         // op-code is the last entry in the menu, we need to rewind back to the first op-code of
 | |
|         // the Date/Time op-code.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (FALSE, &NewPos);
 | |
| 
 | |
|         MenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
|         NewPos     = NewPos->ForwardLink;
 | |
|         //
 | |
|         // Find the next selectable menu.
 | |
|         //
 | |
|         if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) {
 | |
|           if ((gMenuOption.ForwardLink == NewPos) || (&gMenuOption == NewPos)) {
 | |
|             Difference = -1;
 | |
|           } else {
 | |
|             Difference = 0;
 | |
|           }
 | |
|         } else {
 | |
|           Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE);
 | |
|         }
 | |
| 
 | |
|         if (Difference < 0) {
 | |
|           //
 | |
|           // Scroll to the first page.
 | |
|           //
 | |
|           if ((TopOfScreen != gMenuOption.ForwardLink) || (SkipValue != 0)) {
 | |
|             TopOfScreen = gMenuOption.ForwardLink;
 | |
|             Repaint     = TRUE;
 | |
|             MenuOption  = NULL;
 | |
|           } else {
 | |
|             MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
 | |
|           }
 | |
| 
 | |
|           NewPos = gMenuOption.ForwardLink;
 | |
|           MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, TRUE);
 | |
| 
 | |
|           SkipValue = 0;
 | |
|           //
 | |
|           // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
 | |
|           //
 | |
|           AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | |
|           AdjustDateAndTimePosition (TRUE, &NewPos);
 | |
| 
 | |
|           UpdateHighlightMenuInfo (NewPos, TopOfScreen, SkipValue);
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Get next selected menu info.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (FALSE, &NewPos);
 | |
|         NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
 | |
|         if (NextMenuOption->Row == 0) {
 | |
|           UpdateOptionSkipLines (NextMenuOption);
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Calculate new highlight menu end row.
 | |
|         //
 | |
|         Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1;
 | |
|         if (Temp > BottomRow) {
 | |
|           //
 | |
|           // Get the top screen menu info.
 | |
|           //
 | |
|           AdjustDateAndTimePosition (FALSE, &TopOfScreen);
 | |
|           SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
 | |
| 
 | |
|           //
 | |
|           // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows.
 | |
|           // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows.
 | |
|           //
 | |
|           if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {
 | |
|             //
 | |
|             // Skip the top op-code
 | |
|             //
 | |
|             TopOfScreen   = TopOfScreen->ForwardLink;
 | |
|             DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);
 | |
| 
 | |
|             SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
 | |
| 
 | |
|             //
 | |
|             // If we have a remainder, skip that many more op-codes until we drain the remainder
 | |
|             // Special case is the selected highlight menu has more than one form of menus.
 | |
|             //
 | |
|             while (DistanceValue >= SavedMenuOption->Skip && TopOfScreen != NewPos) {
 | |
|               //
 | |
|               // Since the Difference is greater than or equal to this op-code's skip value, skip it
 | |
|               //
 | |
|               DistanceValue   = DistanceValue - (INTN)SavedMenuOption->Skip;
 | |
|               TopOfScreen     = TopOfScreen->ForwardLink;
 | |
|               SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // Since we will act on this op-code in the next routine, and increment the
 | |
|             // SkipValue, set the skips to one less than what is required.
 | |
|             //
 | |
|             if (TopOfScreen != NewPos) {
 | |
|               SkipValue = DistanceValue;
 | |
|             } else {
 | |
|               SkipValue = 0;
 | |
|             }
 | |
|           } else {
 | |
|             //
 | |
|             // Since we will act on this op-code in the next routine, and increment the
 | |
|             // SkipValue, set the skips to one less than what is required.
 | |
|             //
 | |
|             SkipValue += Temp - BottomRow;
 | |
|           }
 | |
| 
 | |
|           Repaint = TRUE;
 | |
|         } else if (!IsSelectable (NextMenuOption)) {
 | |
|           //
 | |
|           // Continue to go down until scroll to next page or the selectable option is found.
 | |
|           //
 | |
|           ScreenOperation = UiDown;
 | |
|           ControlFlag     = CfScreenOperation;
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
 | |
| 
 | |
|         //
 | |
|         // Check whether new highlight menu is selectable, if not, keep highlight on the old one.
 | |
|         //
 | |
|         // BottomRow - TopRow + 1 means the total rows current forms supported.
 | |
|         // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu
 | |
|         // and new top menu. New top menu will all shows in next form, but last highlight menu
 | |
|         // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the
 | |
|         // last highlight menu.
 | |
|         //
 | |
|         if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) &&
 | |
|             (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1))
 | |
|         {
 | |
|           NewPos = SavedListEntry;
 | |
|         }
 | |
| 
 | |
|         UpdateStatusBar (INPUT_ERROR, FALSE);
 | |
| 
 | |
|         //
 | |
|         // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
 | |
|         //
 | |
|         AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | |
|         AdjustDateAndTimePosition (TRUE, &NewPos);
 | |
| 
 | |
|         UpdateHighlightMenuInfo (NewPos, TopOfScreen, SkipValue);
 | |
|         break;
 | |
| 
 | |
|       case CfUiNoOperation:
 | |
|         ControlFlag = CfRepaint;
 | |
|         break;
 | |
| 
 | |
|       case CfExit:
 | |
|         gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
 | |
|         if (HelpString != NULL) {
 | |
|           FreePool (HelpString);
 | |
|         }
 | |
| 
 | |
|         if (HelpHeaderString != NULL) {
 | |
|           FreePool (HelpHeaderString);
 | |
|         }
 | |
| 
 | |
|         if (HelpBottomString != NULL) {
 | |
|           FreePool (HelpBottomString);
 | |
|         }
 | |
| 
 | |
|         return EFI_SUCCESS;
 | |
| 
 | |
|       default:
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Free the UI Menu Option structure data.
 | |
| 
 | |
|   @param   MenuOptionList         Point to the menu option list which need to be free.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FreeMenuOptionData (
 | |
|   LIST_ENTRY  *MenuOptionList
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY      *Link;
 | |
|   UI_MENU_OPTION  *Option;
 | |
| 
 | |
|   //
 | |
|   // Free menu option list
 | |
|   //
 | |
|   while (!IsListEmpty (MenuOptionList)) {
 | |
|     Link   = GetFirstNode (MenuOptionList);
 | |
|     Option = MENU_OPTION_FROM_LINK (Link);
 | |
|     if (Option->Description != NULL) {
 | |
|       FreePool (Option->Description);
 | |
|     }
 | |
| 
 | |
|     RemoveEntryList (&Option->Link);
 | |
|     FreePool (Option);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Base on the browser status info to show an pop up message.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| BrowserStatusProcess (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   CHAR16              *ErrorInfo;
 | |
|   EFI_INPUT_KEY       Key;
 | |
|   EFI_EVENT           WaitList[2];
 | |
|   EFI_EVENT           RefreshIntervalEvent;
 | |
|   EFI_EVENT           TimeOutEvent;
 | |
|   UINT8               TimeOut;
 | |
|   EFI_STATUS          Status;
 | |
|   UINTN               Index;
 | |
|   WARNING_IF_CONTEXT  EventContext;
 | |
|   EFI_IFR_OP_HEADER   *OpCodeBuf;
 | |
|   EFI_STRING_ID       StringToken;
 | |
|   CHAR16              DiscardChange;
 | |
|   CHAR16              JumpToFormSet;
 | |
|   CHAR16              *PrintString;
 | |
| 
 | |
|   if (gFormData->BrowserStatus == BROWSER_SUCCESS) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   StringToken          = 0;
 | |
|   TimeOutEvent         = NULL;
 | |
|   RefreshIntervalEvent = NULL;
 | |
|   OpCodeBuf            = NULL;
 | |
|   if (gFormData->HighLightedStatement != NULL) {
 | |
|     OpCodeBuf = gFormData->HighLightedStatement->OpCode;
 | |
|   }
 | |
| 
 | |
|   if (gFormData->BrowserStatus == (BROWSER_WARNING_IF)) {
 | |
|     ASSERT (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_WARNING_IF_OP);
 | |
| 
 | |
|     TimeOut     = ((EFI_IFR_WARNING_IF *)OpCodeBuf)->TimeOut;
 | |
|     StringToken = ((EFI_IFR_WARNING_IF *)OpCodeBuf)->Warning;
 | |
|   } else {
 | |
|     TimeOut = 0;
 | |
|     if ((gFormData->BrowserStatus == (BROWSER_NO_SUBMIT_IF)) &&
 | |
|         ((OpCodeBuf != NULL) && (OpCodeBuf->OpCode == EFI_IFR_NO_SUBMIT_IF_OP)))
 | |
|     {
 | |
|       StringToken = ((EFI_IFR_NO_SUBMIT_IF *)OpCodeBuf)->Error;
 | |
|     } else if ((gFormData->BrowserStatus == (BROWSER_INCONSISTENT_IF)) &&
 | |
|                ((OpCodeBuf != NULL) && (OpCodeBuf->OpCode == EFI_IFR_INCONSISTENT_IF_OP)))
 | |
|     {
 | |
|       StringToken = ((EFI_IFR_INCONSISTENT_IF *)OpCodeBuf)->Error;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (StringToken != 0) {
 | |
|     ErrorInfo = GetToken (StringToken, gFormData->HiiHandle);
 | |
|   } else if (gFormData->ErrorString != NULL) {
 | |
|     //
 | |
|     // Only used to compatible with old setup browser.
 | |
|     // Not use this field in new browser core.
 | |
|     //
 | |
|     ErrorInfo = gFormData->ErrorString;
 | |
|   } else {
 | |
|     switch (gFormData->BrowserStatus) {
 | |
|       case BROWSER_SUBMIT_FAIL:
 | |
|         ErrorInfo = gSaveFailed;
 | |
|         break;
 | |
| 
 | |
|       case BROWSER_FORM_NOT_FOUND:
 | |
|         ErrorInfo = gFormNotFound;
 | |
|         break;
 | |
| 
 | |
|       case BROWSER_FORM_SUPPRESS:
 | |
|         ErrorInfo = gFormSuppress;
 | |
|         break;
 | |
| 
 | |
|       case BROWSER_PROTOCOL_NOT_FOUND:
 | |
|         ErrorInfo = gProtocolNotFound;
 | |
|         break;
 | |
| 
 | |
|       case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:
 | |
|         ErrorInfo = gNoSubmitIfFailed;
 | |
|         break;
 | |
| 
 | |
|       case BROWSER_RECONNECT_FAIL:
 | |
|         ErrorInfo = gReconnectFail;
 | |
|         break;
 | |
| 
 | |
|       case BROWSER_RECONNECT_SAVE_CHANGES:
 | |
|         ErrorInfo = gReconnectConfirmChanges;
 | |
|         break;
 | |
| 
 | |
|       case BROWSER_RECONNECT_REQUIRED:
 | |
|         ErrorInfo = gReconnectRequired;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         ErrorInfo = gBrowserError;
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   switch (gFormData->BrowserStatus) {
 | |
|     case BROWSER_SUBMIT_FAIL:
 | |
|     case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:
 | |
|     case BROWSER_RECONNECT_SAVE_CHANGES:
 | |
|       ASSERT (gUserInput != NULL);
 | |
|       if (gFormData->BrowserStatus == (BROWSER_SUBMIT_FAIL)) {
 | |
|         PrintString   = gSaveProcess;
 | |
|         JumpToFormSet = gJumpToFormSet[0];
 | |
|         DiscardChange = gDiscardChange[0];
 | |
|       } else if (gFormData->BrowserStatus == (BROWSER_RECONNECT_SAVE_CHANGES)) {
 | |
|         PrintString   = gChangesOpt;
 | |
|         JumpToFormSet = gConfirmOptYes[0];
 | |
|         DiscardChange = gConfirmOptNo[0];
 | |
|       } else {
 | |
|         PrintString   = gSaveNoSubmitProcess;
 | |
|         JumpToFormSet = gCheckError[0];
 | |
|         DiscardChange = gDiscardChange[0];
 | |
|       }
 | |
| 
 | |
|       do {
 | |
|         CreateDialog (&Key, gEmptyString, ErrorInfo, PrintString, gEmptyString, NULL);
 | |
|       } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (DiscardChange | UPPER_LOWER_CASE_OFFSET)) &&
 | |
|                ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (JumpToFormSet | UPPER_LOWER_CASE_OFFSET)));
 | |
| 
 | |
|       if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (DiscardChange | UPPER_LOWER_CASE_OFFSET)) {
 | |
|         gUserInput->Action = BROWSER_ACTION_DISCARD;
 | |
|       } else {
 | |
|         gUserInput->Action = BROWSER_ACTION_GOTO;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       if (TimeOut == 0) {
 | |
|         do {
 | |
|           CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);
 | |
|         } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | |
|       } else {
 | |
|         Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent);
 | |
|         ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|         EventContext.SyncEvent = TimeOutEvent;
 | |
|         EventContext.TimeOut   = &TimeOut;
 | |
|         EventContext.ErrorInfo = ErrorInfo;
 | |
| 
 | |
|         Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent);
 | |
|         ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|         //
 | |
|         // Show the dialog first to avoid long time not reaction.
 | |
|         //
 | |
|         gBS->SignalEvent (RefreshIntervalEvent);
 | |
| 
 | |
|         Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND);
 | |
|         ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|         while (TRUE) {
 | |
|           Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | |
|           if (!EFI_ERROR (Status) && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           if (Status != EFI_NOT_READY) {
 | |
|             continue;
 | |
|           }
 | |
| 
 | |
|           WaitList[0] = TimeOutEvent;
 | |
|           WaitList[1] = gST->ConIn->WaitForKey;
 | |
| 
 | |
|           Status = gBS->WaitForEvent (2, WaitList, &Index);
 | |
|           ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|           if (Index == 0) {
 | |
|             //
 | |
|             // Timeout occur, close the hoot time out event.
 | |
|             //
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         gBS->CloseEvent (TimeOutEvent);
 | |
|         gBS->CloseEvent (RefreshIntervalEvent);
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   if (StringToken != 0) {
 | |
|     FreePool (ErrorInfo);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Display one form, and return user input.
 | |
| 
 | |
|   @param FormData                Form Data to be shown.
 | |
|   @param UserInputData           User input data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            1.Form Data is shown, and user input is got.
 | |
|                                  2.Error info has show and return.
 | |
|   @retval EFI_INVALID_PARAMETER  The input screen dimension is not valid
 | |
|   @retval EFI_NOT_FOUND          New form data has some error.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FormDisplay (
 | |
|   IN  FORM_DISPLAY_ENGINE_FORM  *FormData,
 | |
|   OUT USER_INPUT                *UserInputData
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   ASSERT (FormData != NULL);
 | |
|   if (FormData == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   gUserInput = UserInputData;
 | |
|   gFormData  = FormData;
 | |
| 
 | |
|   //
 | |
|   // Process the status info first.
 | |
|   //
 | |
|   BrowserStatusProcess ();
 | |
|   if (gFormData->BrowserStatus != BROWSER_SUCCESS) {
 | |
|     //
 | |
|     // gFormData->BrowserStatus != BROWSER_SUCCESS, means only need to print the error info, return here.
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Status = DisplayPageFrame (FormData, &gStatementDimensions);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Global Widths should be initialized before any MenuOption creation
 | |
|   // or the GetWidth() used in UiAddMenuOption() will return incorrect value.
 | |
|   //
 | |
|   //
 | |
|   //  Left                                              right
 | |
|   //   |<-.->|<-.........->|<- .........->|<-...........->|
 | |
|   //     Skip    Prompt         Option         Help
 | |
|   //
 | |
|   gOptionBlockWidth = (CHAR16)((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3) + 1;
 | |
|   gHelpBlockWidth   = (CHAR16)(gOptionBlockWidth - 1 - LEFT_SKIPPED_COLUMNS);
 | |
|   gPromptBlockWidth = (CHAR16)(gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gOptionBlockWidth - 1) - 1);
 | |
| 
 | |
|   ConvertStatementToMenu ();
 | |
| 
 | |
|   //
 | |
|   // Check whether layout is changed.
 | |
|   //
 | |
|   if (  mIsFirstForm
 | |
|      || (gOldFormEntry.HiiHandle != FormData->HiiHandle)
 | |
|      || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))
 | |
|      || (gOldFormEntry.FormId != FormData->FormId))
 | |
|   {
 | |
|     mStatementLayoutIsChanged = TRUE;
 | |
|   } else {
 | |
|     mStatementLayoutIsChanged = FALSE;
 | |
|   }
 | |
| 
 | |
|   Status = UiDisplayMenu (FormData);
 | |
| 
 | |
|   //
 | |
|   // Backup last form info.
 | |
|   //
 | |
|   mIsFirstForm            = FALSE;
 | |
|   gOldFormEntry.HiiHandle = FormData->HiiHandle;
 | |
|   CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid);
 | |
|   gOldFormEntry.FormId = FormData->FormId;
 | |
| 
 | |
|   //
 | |
|   // Free the Ui menu option list.
 | |
|   //
 | |
|   FreeMenuOptionData (&gMenuOption);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Clear Screen to the initial state.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| DriverClearDisplayPage (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   ClearDisplayPage ();
 | |
|   mIsFirstForm = TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set Buffer to Value for Size bytes.
 | |
| 
 | |
|   @param  Buffer                 Memory to set.
 | |
|   @param  Size                   Number of bytes to set
 | |
|   @param  Value                  Value of the set operation.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SetUnicodeMem (
 | |
|   IN VOID    *Buffer,
 | |
|   IN UINTN   Size,
 | |
|   IN CHAR16  Value
 | |
|   )
 | |
| {
 | |
|   CHAR16  *Ptr;
 | |
| 
 | |
|   Ptr = Buffer;
 | |
|   while ((Size--)  != 0) {
 | |
|     *(Ptr++) = Value;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize Setup Browser driver.
 | |
| 
 | |
|   @param ImageHandle     The image handle.
 | |
|   @param SystemTable     The system table.
 | |
| 
 | |
|   @retval EFI_SUCCESS    The Setup Browser module is initialized correctly..
 | |
|   @return Other value if failed to initialize the Setup Browser module.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InitializeDisplayEngine (
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                              Status;
 | |
|   EFI_INPUT_KEY                           HotKey;
 | |
|   EFI_STRING                              NewString;
 | |
|   EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL  *FormBrowserEx2;
 | |
| 
 | |
|   //
 | |
|   // Publish our HII data
 | |
|   //
 | |
|   gHiiHandle = HiiAddPackages (
 | |
|                  &gDisplayEngineGuid,
 | |
|                  ImageHandle,
 | |
|                  DisplayEngineStrings,
 | |
|                  NULL
 | |
|                  );
 | |
|   ASSERT (gHiiHandle != NULL);
 | |
| 
 | |
|   //
 | |
|   // Install Form Display protocol
 | |
|   //
 | |
|   Status = gBS->InstallProtocolInterface (
 | |
|                   &mPrivateData.Handle,
 | |
|                   &gEdkiiFormDisplayEngineProtocolGuid,
 | |
|                   EFI_NATIVE_INTERFACE,
 | |
|                   &mPrivateData.FromDisplayProt
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Install HII Popup Protocol.
 | |
|   //
 | |
|   Status = gBS->InstallProtocolInterface (
 | |
|                   &mPrivateData.Handle,
 | |
|                   &gEfiHiiPopupProtocolGuid,
 | |
|                   EFI_NATIVE_INTERFACE,
 | |
|                   &mPrivateData.HiiPopup
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   InitializeDisplayStrings ();
 | |
| 
 | |
|   ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));
 | |
|   ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));
 | |
| 
 | |
|   //
 | |
|   // Use BrowserEx2 protocol to register HotKey.
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **)&FormBrowserEx2);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Register the default HotKey F9 and F10 again.
 | |
|     //
 | |
|     HotKey.UnicodeChar = CHAR_NULL;
 | |
|     HotKey.ScanCode    = SCAN_F10;
 | |
|     NewString          = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
 | |
|     ASSERT (NewString != NULL);
 | |
|     FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
 | |
|     FreePool (NewString);
 | |
| 
 | |
|     HotKey.ScanCode = SCAN_F9;
 | |
|     NewString       = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
 | |
|     ASSERT (NewString != NULL);
 | |
|     FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
 | |
|     FreePool (NewString);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This is the default unload handle for display core drivers.
 | |
| 
 | |
|   @param[in]  ImageHandle       The drivers' driver image.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The image is unloaded.
 | |
|   @retval Others                Failed to unload the image.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnloadDisplayEngine (
 | |
|   IN EFI_HANDLE  ImageHandle
 | |
|   )
 | |
| {
 | |
|   HiiRemovePackages (gHiiHandle);
 | |
| 
 | |
|   FreeDisplayStrings ();
 | |
| 
 | |
|   if (gHighligthMenuInfo.HLTOpCode != NULL) {
 | |
|     FreePool (gHighligthMenuInfo.HLTOpCode);
 | |
|   }
 | |
| 
 | |
|   if (gHighligthMenuInfo.TOSOpCode != NULL) {
 | |
|     FreePool (gHighligthMenuInfo.TOSOpCode);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |