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;
 | 
						|
}
 |