FormDisplay.c revision 336c8e116b3e2e11dccdac163d0a85fc3c58fd3d
17c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/** @file
27c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEntry and initialization module for the browser.
37c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4f0c5095b274b2b35867d5245119aa1aba0acc87eEric DongCopyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
57c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongThis program and the accompanying materials
67c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dongare licensed and made available under the terms and conditions of the BSD License
77c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dongwhich accompanies this distribution.  The full text of the license may be found at
87c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Donghttp://opensource.org/licenses/bsd-license.php
97c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong#include "FormDisplay.h"
167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong//
187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong// Search table for UiDisplayMenu()
197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong//
207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongSCAN_CODE_TO_SCREEN_OPERATION     gScanCodeToOperation[] = {
217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SCAN_UP,
237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiUp,
247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SCAN_DOWN,
277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiDown,
287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SCAN_PAGE_UP,
317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiPageUp,
327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SCAN_PAGE_DOWN,
357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiPageDown,
367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SCAN_ESC,
397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiReset,
407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SCAN_LEFT,
437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiLeft,
447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SCAN_RIGHT,
477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiRight,
487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong};
507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]);
527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongSCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiNoOperation,
567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiNoOperation,
577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiSelect,
607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiSelect,
617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiUp,
647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiUp,
657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiDown,
687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiDown,
697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiLeft,
727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiLeft,
737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiRight,
767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiRight,
777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiReset,
807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiReset,
817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiPageUp,
847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiPageUp,
857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiPageDown,
887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiPageDown
897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  },
907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiHotKey,
927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CfUiHotKey
937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong};
957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_GUID  gDisplayEngineGuid = {
977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62}
987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong};
997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1005a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongFORM_ENTRY_INFO               gFormEntryInfo;
1017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINTN                         gSequence;
1027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_SCREEN_DESCRIPTOR         gStatementDimensions;
1037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongBOOLEAN                       mStatementLayoutIsChanged = TRUE;
1047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUSER_INPUT                    *gUserInput;
1057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongFORM_DISPLAY_ENGINE_FORM      *gFormData;
1067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_HII_HANDLE                gHiiHandle;
1077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINT16                        gDirection;
1087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongLIST_ENTRY                    gMenuOption;
1097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongDISPLAY_HIGHLIGHT_MENU_INFO   gHighligthMenuInfo = {0};
1105a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongBOOLEAN                       mIsFirstForm = TRUE;
1115a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongFORM_ENTRY_INFO               gOldFormEntry = {0};
1127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong//
1147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong// Browser Global Strings
1157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong//
1167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gFormNotFound;
1177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gNoSubmitIf;
1187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gBrwoserError;
1197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gSaveFailed;
1207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gPromptForData;
1217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gPromptForPassword;
1227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gPromptForNewPassword;
1237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gConfirmPassword;
1247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gConfirmError;
1257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gPassowordInvalid;
1267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gPressEnter;
1277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gEmptyString;
1287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gMiniString;
1297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gOptionMismatch;
1307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gFormSuppress;
1317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *gProtocolNotFound;
1327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
133af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongCHAR16            gModalSkipColumn;
1347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            gPromptBlockWidth;
1357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            gOptionBlockWidth;
1367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            gHelpBlockWidth;
1377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16            *mUnknownString;
1387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongFORM_DISPLAY_DRIVER_PRIVATE_DATA  mPrivateData = {
1407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FORM_DISPLAY_DRIVER_SIGNATURE,
1417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  NULL,
1427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  {
1437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    FormDisplay,
1445a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong    DriverClearDisplayPage,
1457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    ConfirmDataChange
1467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
1477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong};
1487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
1517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Get the string based on the StringId and HII Package List Handle.
1527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  Token                  The String's ID.
1547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  HiiHandle              The package list in the HII database to search for
1557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                                 the specified string.
1567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return The output string.
1587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
1607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongCHAR16 *
1617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetToken (
1627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  EFI_STRING_ID                Token,
1637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  EFI_HII_HANDLE               HiiHandle
1647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
1657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
1667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STRING  String;
1677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  String = HiiGetString (HiiHandle, Token, NULL);
1697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (String == NULL) {
1707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);
1717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    ASSERT (String != NULL);
1727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
1737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return (CHAR16 *) String;
1757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
1767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
1797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Initialize the HII String Token to the correct values.
1807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
1827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
1837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongInitializeDisplayStrings (
1847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  VOID
1857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
1867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
1877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  mUnknownString        = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);
1887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
1897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
1907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
1917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
1927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gConfirmPassword      = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
1937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gConfirmError         = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
1947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gPassowordInvalid     = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
1957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gPressEnter           = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
1967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gEmptyString          = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
1977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gMiniString           = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
1987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gOptionMismatch       = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);
1997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gFormSuppress         = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);
2007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gProtocolNotFound     = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);
2017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gFormNotFound         = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle);
2027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gNoSubmitIf           = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle);
2037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gBrwoserError         = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);
2047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
2057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
2077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Free up the resource allocated for all strings required
2087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  by Setup Browser.
2097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
2117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
2127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongFreeDisplayStrings (
2137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  VOID
2147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
2157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
2167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (mUnknownString);
2177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gEmptyString);
2187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gSaveFailed);
2197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gPromptForData);
2207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gPromptForPassword);
2217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gPromptForNewPassword);
2227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gConfirmPassword);
2237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gConfirmError);
2247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gPassowordInvalid);
2257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gPressEnter);
2267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gMiniString);
2277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gOptionMismatch);
2287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gFormSuppress);
2297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gProtocolNotFound);
2307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gBrwoserError);
2317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gNoSubmitIf);
2327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreePool (gFormNotFound);
2337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
2347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
2367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Get prompt string id from the opcode data buffer.
2377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  OpCode                 The input opcode buffer.
2397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return The prompt string id.
2417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
2437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_STRING_ID
2447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetPrompt (
2457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN EFI_IFR_OP_HEADER     *OpCode
2467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
2477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
2487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_IFR_STATEMENT_HEADER  *Header;
2497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (OpCode->Length <= sizeof (EFI_IFR_OP_HEADER)) {
2517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return 0;
2527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
2537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Header = (EFI_IFR_STATEMENT_HEADER  *) (OpCode + 1);
2557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return Header->Prompt;
2577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
2587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
2607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Get the supported width for a particular op-code
2617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2626f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  @param  MenuOption             The menu option.
263af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  AdjustWidth            The width which is saved for the space.
2647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return Returns the number of CHAR16 characters that is support.
2667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
2687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINT16
2697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetWidth (
2706f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  IN  UI_MENU_OPTION     *MenuOption,
2716f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  OUT UINT16             *AdjustWidth
2727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
2737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
2746f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  CHAR16                        *String;
2756f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  UINTN                         Size;
2766f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  EFI_IFR_TEXT                  *TestOp;
2776f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  UINT16                        ReturnWidth;
2786f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  FORM_DISPLAY_ENGINE_STATEMENT *Statement;
2796f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong
2806f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  Statement = MenuOption->ThisTag;
2817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
282af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
283af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // For modal form, clean the entire row.
284af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
285af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if ((gFormData->Attribute & HII_DISPLAY_MODAL) != 0) {
286ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong    if (AdjustWidth  != NULL) {
287ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong      *AdjustWidth = LEFT_SKIPPED_COLUMNS;
288ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong    }
289ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong    return (UINT16)(gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gModalSkipColumn + LEFT_SKIPPED_COLUMNS));
290af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
291af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
2927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Size = 0;
2937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
2957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // See if the second text parameter is really NULL
2967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
2977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
2987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    TestOp = (EFI_IFR_TEXT *) Statement->OpCode;
2997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (TestOp->TextTwo != 0) {
3007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);
3017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Size   = StrLen (String);
3027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      FreePool (String);
3037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
3047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
3057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
3077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||
3087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||
3097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||
3107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||
3117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
3127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Allow a wide display if text op-code and no secondary text op-code
3137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
3147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))
3157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ) {
316af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
317af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    //
318af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    // Return the space width.
319af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    //
320af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    if (AdjustWidth != NULL) {
321af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      *AdjustWidth = 2;
322af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    }
323af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    //
324af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    // Keep consistent with current behavior.
325af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    //
3266f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    ReturnWidth = (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2);
3276f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  } else {
3286f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    if (AdjustWidth != NULL) {
3296f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      *AdjustWidth = 1;
3306f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    }
3316f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong
3326f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    ReturnWidth =  (UINT16) (gPromptBlockWidth - 1);
3337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
3347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3356f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  //
3366f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  // For nest in statement, should the subtitle indent.
3376f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  //
3386f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  if (MenuOption->NestInStatement) {
3396f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    ReturnWidth -= SUBTITLE_INDENT;
340af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
3416f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong
3426f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  return ReturnWidth;
3437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
3447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
3467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Will copy LineWidth amount of a string in the OutputString buffer and return the
3477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  number of CHAR16 characters that were copied into the OutputString buffer.
3487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  The output string format is:
3497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Glyph Info + String info + '\0'.
3507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
3527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  InputString            String description for this option.
3547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  LineWidth              Width of the desired string to extract in CHAR16
3557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                                 characters
3567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  GlyphWidth             The glyph width of the begin of the char in the string.
3577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  Index                  Where in InputString to start the copy process
3587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  OutputString           Buffer to copy the string into
3597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return Returns the number of CHAR16 characters that were copied into the OutputString
3617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  buffer, include extra glyph info and '\0' info.
3627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
3647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINT16
3657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetLineByWidth (
3667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN      CHAR16                      *InputString,
3677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN      UINT16                      LineWidth,
3687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN OUT  UINT16                      *GlyphWidth,
3697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN OUT  UINTN                       *Index,
3707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OUT     CHAR16                      **OutputString
3717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
3727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
3737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16          StrOffset;
3747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16          GlyphOffset;
3757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16          OriginalGlyphWidth;
3767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BOOLEAN         ReturnFlag;
3777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16          LastSpaceOffset;
3787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16          LastGlyphWidth;
3797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (InputString == NULL || Index == NULL || OutputString == NULL) {
3817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return 0;
3827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
3837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (LineWidth == 0 || *GlyphWidth == 0) {
3857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return 0;
3867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
3877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
3897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Save original glyph width.
3907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
3917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OriginalGlyphWidth = *GlyphWidth;
3927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LastGlyphWidth     = OriginalGlyphWidth;
3937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ReturnFlag         = FALSE;
3947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LastSpaceOffset    = 0;
3957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
3977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // 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.
3987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
3997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
4017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *Index = *Index + 2;
4027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
4037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Fast-forward the string and see if there is a carriage-return in the string
4067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {
4087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    switch (InputString[*Index + StrOffset]) {
4097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case NARROW_CHAR:
4107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        *GlyphWidth = 1;
4117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
4127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case WIDE_CHAR:
4147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        *GlyphWidth = 2;
4157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
4167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case CHAR_CARRIAGE_RETURN:
4187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case CHAR_LINEFEED:
4197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case CHAR_NULL:
4207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ReturnFlag = TRUE;
4217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
4227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      default:
4247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        GlyphOffset = GlyphOffset + *GlyphWidth;
4257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
4277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // Record the last space info in this line. Will be used in rewind.
4287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
4297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {
4307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          LastSpaceOffset = StrOffset;
4317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          LastGlyphWidth  = *GlyphWidth;
4327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
4337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
4347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
4357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (ReturnFlag) {
4377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
4387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
4397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
4407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Rewind the string from the maximum size until we see a space to break the line
4437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (GlyphOffset > LineWidth) {
4457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
4467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Rewind the string to last space char in this line.
4477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
4487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (LastSpaceOffset != 0) {
4497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      StrOffset   = LastSpaceOffset;
4507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      *GlyphWidth = LastGlyphWidth;
4517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else {
4527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
4537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Roll back to last char in the line width.
4547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
4557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      StrOffset--;
4567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
4577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
4587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // The CHAR_NULL has process last time, this time just return 0 to stand for the end.
4617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {
4637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return 0;
4647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
4657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Need extra glyph info and '\0' info, so +2.
4687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));
4707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (*OutputString == NULL) {
4717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return 0;
4727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
4737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Save the glyph info at the begin of the string, will used by Print function.
4767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
4777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (OriginalGlyphWidth == 1) {
4787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *(*OutputString) = NARROW_CHAR;
4797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else  {
4807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *(*OutputString) = WIDE_CHAR;
4817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
4827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));
4847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
4857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (InputString[*Index + StrOffset] == CHAR_SPACE) {
4867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
4877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Skip the space info at the begin of next line.
4887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
4897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *Index = (UINT16) (*Index + StrOffset + 1);
4907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {
4917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
4927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Skip the /n or /n/r info.
4937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
4947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {
4957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      *Index = (UINT16) (*Index + StrOffset + 2);
4967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else {
4977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      *Index = (UINT16) (*Index + StrOffset + 1);
4987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
4997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {
5007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
5017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Skip the /r or /r/n info.
5027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
5037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {
5047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      *Index = (UINT16) (*Index + StrOffset + 2);
5057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else {
5067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      *Index = (UINT16) (*Index + StrOffset + 1);
5077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
5087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else {
5097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *Index = (UINT16) (*Index + StrOffset);
5107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
5117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
5137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Include extra glyph info and '\0' info, so +2.
5147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
5157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return StrOffset + 2;
5167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
5177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
5197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Add one menu option by specified description and context.
5207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  Statement              Statement of this Menu Option.
5227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  MenuItemCount          The index for this Option in the Menu.
5237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  NestIn                 Whether this statement is nest in another statement.
5247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
5267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
5277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUiAddMenuOption (
5287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN FORM_DISPLAY_ENGINE_STATEMENT   *Statement,
5297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN UINT16                          *MenuItemCount,
5307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN BOOLEAN                         NestIn
5317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
5327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
5337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION   *MenuOption;
5347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN            Index;
5357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN            Count;
5367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16           *String;
5377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16           NumberOfLines;
5387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16           GlyphWidth;
5397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16           Width;
5407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN            ArrayEntry;
5417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16           *OutputString;
5427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STRING_ID    PromptId;
5437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  NumberOfLines = 1;
5457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ArrayEntry    = 0;
5467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  GlyphWidth    = 1;
5477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Count         = 1;
5487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  MenuOption    = NULL;
5497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  PromptId = GetPrompt (Statement->OpCode);
5517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT (PromptId != 0);
5527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  String = GetToken (PromptId, gFormData->HiiHandle);
5547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT (String != NULL);
5557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
5577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Count = 3;
5587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
5597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  for (Index = 0; Index < Count; Index++) {
5617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
5627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    ASSERT (MenuOption);
5637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->Signature   = UI_MENU_OPTION_SIGNATURE;
5657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->Description = String;
5667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->Handle      = gFormData->HiiHandle;
5677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->ThisTag     = Statement;
5687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->NestInStatement = NestIn;
5697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->EntryNumber = *MenuItemCount;
5707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->Sequence = Index;
5727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) {
5747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->GrayOut = TRUE;
5757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else {
5767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->GrayOut = FALSE;
5777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
5787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if ((Statement->Attribute & HII_DISPLAY_LOCK) != 0 || (gFormData->Attribute & HII_DISPLAY_LOCK) != 0) {
5807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->GrayOut = TRUE;
5817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
5827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
5847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // If the form or the question has the lock attribute, deal same as grayout.
5857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
5867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if ((gFormData->Attribute & HII_DISPLAY_LOCK) != 0 || (Statement->Attribute & HII_DISPLAY_LOCK) != 0) {
5877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->GrayOut = TRUE;
5887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
5897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
5907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    switch (Statement->OpCode->OpCode) {
5917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_ORDERED_LIST_OP:
5927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_ONE_OF_OP:
5937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_NUMERIC_OP:
5947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_TIME_OP:
5957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_DATE_OP:
5967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_CHECKBOX_OP:
5977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_PASSWORD_OP:
5987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_STRING_OP:
5997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
6007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // User could change the value of these items
6017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
6027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->IsQuestion = TRUE;
6037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
6047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case EFI_IFR_TEXT_OP:
6057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {
6067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
6077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // Initializing GrayOut option as TRUE for Text setup options
6087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // so that those options will be Gray in colour and un selectable.
6097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
6107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        MenuOption->GrayOut = TRUE;
6117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
6127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
6137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    default:
6147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->IsQuestion = FALSE;
6157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
6167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
6177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if ((Statement->Attribute & HII_DISPLAY_READONLY) != 0) {
6197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->ReadOnly = TRUE;
6207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) {
6217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        MenuOption->GrayOut = TRUE;
6227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
6237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
6247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6256f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    if (Index == 0 &&
6266f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) &&
6276f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      (Statement->OpCode->OpCode != EFI_IFR_TIME_OP)) {
6286f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      Width  = GetWidth (MenuOption, NULL);
6296f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {
6306f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        //
6316f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        // If there is more string to process print on the next row and increment the Skip value
6326f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        //
6336f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        if (StrLen (&String[ArrayEntry]) != 0) {
6346f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong          NumberOfLines++;
6356f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        }
6366f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        FreePool (OutputString);
6376f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      }
6386f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    } else {
6396f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      //
6406f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      // Add three MenuOptions for Date/Time
6416f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      // Data format :      [01/02/2004]      [11:22:33]
6426f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      // Line number :        0  0    1         0  0  1
6436f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      //
6446f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      NumberOfLines = 0;
6456f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    }
6466f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong
6476f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    if (Index == 2) {
6486f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      //
6496f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      // Override LineNumber for the MenuOption in Date/Time sequence
6506f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      //
6516f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      MenuOption->Skip = 1;
6526f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    } else {
6536f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong      MenuOption->Skip = NumberOfLines;
6546f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong    }
6556f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong
6567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    InsertTailList (&gMenuOption, &MenuOption->Link);
6577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
6587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  (*MenuItemCount)++;
6607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
6617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
6637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Create the menu list base on the form data info.
6647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
6667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
6677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongConvertStatementToMenu (
6687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  VOID
6697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
6707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
6717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16                        MenuItemCount;
6727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY                    *Link;
6737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY                    *NestLink;
6747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FORM_DISPLAY_ENGINE_STATEMENT *Statement;
6757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;
6767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  MenuItemCount = 0;
6787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  InitializeListHead (&gMenuOption);
6797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Link = GetFirstNode (&gFormData->StatementListHead);
6817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  while (!IsNull (&gFormData->StatementListHead, Link)) {
6827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
6837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Link = GetNextNode (&gFormData->StatementListHead, Link);
6847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
6867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Skip the opcode not recognized by Display core.
6877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
6887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (Statement->OpCode->OpCode == EFI_IFR_GUID_OP) {
6897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      continue;
6907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
6917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UiAddMenuOption (Statement, &MenuItemCount, FALSE);
6937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
6947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
6957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Check the statement nest in this host statement.
6967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
6977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    NestLink = GetFirstNode (&Statement->NestStatementList);
6987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    while (!IsNull (&Statement->NestStatementList, NestLink)) {
6997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);
7007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      NestLink = GetNextNode (&Statement->NestStatementList, NestLink);
7017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
702077c7aeec07361fc36f8090be46959adb7d38873Eric Dong      //
703077c7aeec07361fc36f8090be46959adb7d38873Eric Dong      // Skip the opcode not recognized by Display core.
704077c7aeec07361fc36f8090be46959adb7d38873Eric Dong      //
705077c7aeec07361fc36f8090be46959adb7d38873Eric Dong      if (NestStatement->OpCode->OpCode == EFI_IFR_GUID_OP) {
706077c7aeec07361fc36f8090be46959adb7d38873Eric Dong        continue;
707077c7aeec07361fc36f8090be46959adb7d38873Eric Dong      }
708077c7aeec07361fc36f8090be46959adb7d38873Eric Dong
7097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);
7107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
7117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
7127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
7137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
7157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Count the storage space of a Unicode string.
7167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  This function handles the Unicode string with NARROW_CHAR
7187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
7197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  does not count in the resultant output. If a WIDE_CHAR is
7207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  hit, then 2 Unicode character will consume an output storage
7217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  space with size of CHAR16 till a NARROW_CHAR is hit.
7227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  If String is NULL, then ASSERT ().
7247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param String          The input string to be counted.
7267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return Storage space for the input string.
7287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
7307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINTN
7317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetStringWidth (
7327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN CHAR16               *String
7337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
7347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
7357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN Index;
7367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN Count;
7377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN IncrementValue;
7387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT (String != NULL);
7407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (String == NULL) {
7417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return 0;
7427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
7437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Index           = 0;
7457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Count           = 0;
7467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IncrementValue  = 1;
7477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  do {
7497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
7507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Advance to the null-terminator or to the first width directive
7517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
7527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    for (;
7537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong         (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
7547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong         Index++, Count = Count + IncrementValue
7557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        )
7567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ;
7577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
7597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // We hit the null-terminator, we now have a count
7607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
7617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (String[Index] == 0) {
7627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
7637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
7647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
7657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
7667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
7677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
7687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (String[Index] == NARROW_CHAR) {
7697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
7707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Skip to the next character
7717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
7727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Index++;
7737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      IncrementValue = 1;
7747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else {
7757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
7767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Skip to the next character
7777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
7787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Index++;
7797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      IncrementValue = 2;
7807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
7817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } while (String[Index] != 0);
7827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
7847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Increment by one to include the null-terminator in the size
7857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
7867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Count++;
7877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return Count * sizeof (CHAR16);
7897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
7907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
7927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Base on the input option string to update the skip value for a menu option.
7937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  MenuOption             The MenuOption to be checked.
7957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  OptionString           The input option string.
7967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
7977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
7987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
7997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUpdateSkipInfoForMenu (
8007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN UI_MENU_OPTION               *MenuOption,
8017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN CHAR16                       *OptionString
8027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
8037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
8047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN   Index;
8057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16  Width;
8067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN   Row;
8077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16  *OutputString;
8087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16  GlyphWidth;
8097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Width         = (UINT16) gOptionBlockWidth;
8117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  GlyphWidth    = 1;
8127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Row           = 1;
8137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
8157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (StrLen (&OptionString[Index]) != 0) {
8167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Row++;
8177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
8187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    FreePool (OutputString);
8207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
8217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if ((Row > MenuOption->Skip) &&
8237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) &&
8247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP)) {
8257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    MenuOption->Skip = Row;
8267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
8277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
8287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
8307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Update display lines for a Menu Option.
8317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  MenuOption             The MenuOption to be checked.
8337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
8357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
8367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUpdateOptionSkipLines (
8377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN UI_MENU_OPTION               *MenuOption
8387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
8397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
8407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16  *OptionString;
8417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OptionString  = NULL;
8437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);
8457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (OptionString != NULL) {
8467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    UpdateSkipInfoForMenu (MenuOption, OptionString);
8477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    FreePool (OptionString);
8497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
8507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if ((MenuOption->ThisTag->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {
8527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    OptionString   = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);
8537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (OptionString != NULL) {
8557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      UpdateSkipInfoForMenu (MenuOption, OptionString);
8567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      FreePool (OptionString);
8587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
8597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
8607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
8617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
8627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
863ab369468265cd29a90b385a6e950eda3da16636dEric Dong  Check whether this Menu Option could be print.
864ab369468265cd29a90b385a6e950eda3da16636dEric Dong
865ab369468265cd29a90b385a6e950eda3da16636dEric Dong  Check Prompt string, option string or text two string not NULL.
866ab369468265cd29a90b385a6e950eda3da16636dEric Dong
867ab369468265cd29a90b385a6e950eda3da16636dEric Dong  This is an internal function.
868ab369468265cd29a90b385a6e950eda3da16636dEric Dong
869ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @param  MenuOption             The MenuOption to be checked.
870ab369468265cd29a90b385a6e950eda3da16636dEric Dong
871ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @retval TRUE                   This Menu Option is printable.
872ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @retval FALSE                  This Menu Option could not be printable.
873ab369468265cd29a90b385a6e950eda3da16636dEric Dong
874ab369468265cd29a90b385a6e950eda3da16636dEric Dong**/
875ab369468265cd29a90b385a6e950eda3da16636dEric DongBOOLEAN
876ab369468265cd29a90b385a6e950eda3da16636dEric DongPrintableMenu (
877ab369468265cd29a90b385a6e950eda3da16636dEric Dong  UI_MENU_OPTION   *MenuOption
878ab369468265cd29a90b385a6e950eda3da16636dEric Dong  )
879ab369468265cd29a90b385a6e950eda3da16636dEric Dong{
880ab369468265cd29a90b385a6e950eda3da16636dEric Dong  EFI_STATUS    Status;
881ab369468265cd29a90b385a6e950eda3da16636dEric Dong  EFI_STRING    OptionString;
882ab369468265cd29a90b385a6e950eda3da16636dEric Dong
883ab369468265cd29a90b385a6e950eda3da16636dEric Dong  OptionString = NULL;
884ab369468265cd29a90b385a6e950eda3da16636dEric Dong
885ab369468265cd29a90b385a6e950eda3da16636dEric Dong  if (MenuOption->Description[0] != '\0') {
886ab369468265cd29a90b385a6e950eda3da16636dEric Dong    return TRUE;
887ab369468265cd29a90b385a6e950eda3da16636dEric Dong  }
888ab369468265cd29a90b385a6e950eda3da16636dEric Dong
889ab369468265cd29a90b385a6e950eda3da16636dEric Dong  Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);
890ab369468265cd29a90b385a6e950eda3da16636dEric Dong  if (EFI_ERROR (Status)) {
891ab369468265cd29a90b385a6e950eda3da16636dEric Dong    return FALSE;
892ab369468265cd29a90b385a6e950eda3da16636dEric Dong  }
893ab369468265cd29a90b385a6e950eda3da16636dEric Dong  if (OptionString != NULL && OptionString[0] != '\0') {
894ab369468265cd29a90b385a6e950eda3da16636dEric Dong    FreePool (OptionString);
895ab369468265cd29a90b385a6e950eda3da16636dEric Dong    return TRUE;
896ab369468265cd29a90b385a6e950eda3da16636dEric Dong  }
897ab369468265cd29a90b385a6e950eda3da16636dEric Dong
898ab369468265cd29a90b385a6e950eda3da16636dEric Dong  if ((MenuOption->ThisTag->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {
899ab369468265cd29a90b385a6e950eda3da16636dEric Dong    OptionString   = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);
900ab369468265cd29a90b385a6e950eda3da16636dEric Dong    ASSERT (OptionString != NULL);
901ab369468265cd29a90b385a6e950eda3da16636dEric Dong    if (OptionString[0] != '\0'){
902ab369468265cd29a90b385a6e950eda3da16636dEric Dong      FreePool (OptionString);
903ab369468265cd29a90b385a6e950eda3da16636dEric Dong      return TRUE;
904ab369468265cd29a90b385a6e950eda3da16636dEric Dong    }
905ab369468265cd29a90b385a6e950eda3da16636dEric Dong  }
906ab369468265cd29a90b385a6e950eda3da16636dEric Dong
907ab369468265cd29a90b385a6e950eda3da16636dEric Dong  return FALSE;
908ab369468265cd29a90b385a6e950eda3da16636dEric Dong}
909ab369468265cd29a90b385a6e950eda3da16636dEric Dong
910ab369468265cd29a90b385a6e950eda3da16636dEric Dong/**
9117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Check whether this Menu Option could be highlighted.
9127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  This is an internal function.
9147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  MenuOption             The MenuOption to be checked.
9167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval TRUE                   This Menu Option is selectable.
9187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval FALSE                  This Menu Option could not be selected.
9197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
9217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongBOOLEAN
9227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongIsSelectable (
9237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION   *MenuOption
9247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
9257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
9267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
927ab369468265cd29a90b385a6e950eda3da16636dEric Dong      MenuOption->GrayOut || MenuOption->ReadOnly || !PrintableMenu (MenuOption)) {
9287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return FALSE;
9297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else {
9307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return TRUE;
9317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
9327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
9337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
9357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Move to next selectable statement.
9367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  This is an internal function.
9387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  GoUp                   The navigation direction. TRUE: up, FALSE: down.
9407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  CurrentPosition        Current position.
9417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  GapToTop               Gap position to top or bottom.
942ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @param  FindInForm             Whether find menu in current form or beyond.
9437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return The row distance from current MenuOption to next selectable MenuOption.
9457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval -1       Reach the begin of the menu, still can't find the selectable menu.
947ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @retval Value    Find the selectable menu, maybe the truly selectable, maybe the
948ab369468265cd29a90b385a6e950eda3da16636dEric Dong                   first menu showing beyond current form or last menu showing in
949ab369468265cd29a90b385a6e950eda3da16636dEric Dong                   current form.
950ab369468265cd29a90b385a6e950eda3da16636dEric Dong                   The value is the line number between the new selected menu and the
951ab369468265cd29a90b385a6e950eda3da16636dEric Dong                   current select menu, not include the new selected menu.
9527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
9547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongINTN
9557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongMoveToNextStatement (
9567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN     BOOLEAN                   GoUp,
9577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN OUT LIST_ENTRY                **CurrentPosition,
958ab369468265cd29a90b385a6e950eda3da16636dEric Dong  IN     UINTN                     GapToTop,
959ab369468265cd29a90b385a6e950eda3da16636dEric Dong  IN     BOOLEAN                   FindInForm
9607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
9617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
9627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  INTN             Distance;
9637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY       *Pos;
9647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION   *NextMenuOption;
9657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION   *PreMenuOption;
9667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Distance      = 0;
9687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Pos           = *CurrentPosition;
969ab369468265cd29a90b385a6e950eda3da16636dEric Dong
970ab369468265cd29a90b385a6e950eda3da16636dEric Dong  if (Pos == &gMenuOption) {
971ab369468265cd29a90b385a6e950eda3da16636dEric Dong    return -1;
972ab369468265cd29a90b385a6e950eda3da16636dEric Dong  }
973ab369468265cd29a90b385a6e950eda3da16636dEric Dong
9747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  PreMenuOption = MENU_OPTION_FROM_LINK (Pos);
9757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
9767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  while (TRUE) {
9777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
9787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
9797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // NextMenuOption->Row == 0 means this menu has not calculate
9807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // the NextMenuOption->Skip value yet, just calculate here.
9817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
9827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (NextMenuOption->Row == 0) {
9837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      UpdateOptionSkipLines (NextMenuOption);
9847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
9857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
986ab369468265cd29a90b385a6e950eda3da16636dEric Dong    if (IsSelectable (NextMenuOption)) {
987ab369468265cd29a90b385a6e950eda3da16636dEric Dong      break;
9887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
9897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
990ab369468265cd29a90b385a6e950eda3da16636dEric Dong    //
991ab369468265cd29a90b385a6e950eda3da16636dEric Dong    // In this case, still can't find the selectable menu,
992ab369468265cd29a90b385a6e950eda3da16636dEric Dong    // return the first one beyond the showing form.
993ab369468265cd29a90b385a6e950eda3da16636dEric Dong    //
994ab369468265cd29a90b385a6e950eda3da16636dEric Dong    if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {
995ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (FindInForm) {
996ab369468265cd29a90b385a6e950eda3da16636dEric Dong        NextMenuOption = PreMenuOption;
997ab369468265cd29a90b385a6e950eda3da16636dEric Dong      }
9987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
9997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
10007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1001ab369468265cd29a90b385a6e950eda3da16636dEric Dong    Distance += NextMenuOption->Skip;
1002ab369468265cd29a90b385a6e950eda3da16636dEric Dong
10037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
10047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Arrive at begin of the menu list.
10057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
10067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {
10077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Distance = -1;
10087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
10097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
10107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);
1012ab369468265cd29a90b385a6e950eda3da16636dEric Dong    PreMenuOption = NextMenuOption;
10137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
10147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  *CurrentPosition = &NextMenuOption->Link;
10167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return Distance;
10177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
10187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
10217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Process option string for date/time opcode.
10227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  MenuOption              Menu option point to date/time.
10247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  OptionString            Option string input for process.
10257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  AddOptCol               Whether need to update MenuOption->OptCol.
10267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
10287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
10297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongProcessStringForDateTime (
10307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION                  *MenuOption,
10317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16                          *OptionString,
10327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BOOLEAN                         AddOptCol
10337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
10347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
10357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN Index;
10367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN Count;
10377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FORM_DISPLAY_ENGINE_STATEMENT          *Statement;
10387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_IFR_DATE                           *Date;
10397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_IFR_TIME                           *Time;
10407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT (MenuOption != NULL && OptionString != NULL);
10427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Statement = MenuOption->ThisTag;
10447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Date      = NULL;
10457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Time      = NULL;
10467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
10477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Date = (EFI_IFR_DATE *) Statement->OpCode;
10487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
10497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Time = (EFI_IFR_TIME *) Statement->OpCode;
10507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
10517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
10537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // If leading spaces on OptionString - remove the spaces
10547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
10557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  for (Index = 0; OptionString[Index] == L' '; Index++) {
10567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
10577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Base on the blockspace to get the option column info.
10587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
10597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (AddOptCol) {
10607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption->OptCol++;
10617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
10627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
10637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
10657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    OptionString[Count] = OptionString[Index];
10667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Count++;
10677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
10687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OptionString[Count] = CHAR_NULL;
10697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
10707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
10717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Enable to suppress field in the opcode base on the flag.
10727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
10737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
10747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
10757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // OptionString format is: <**:  **: ****>
10767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //                        |month|day|year|
10777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //                          4     3    5
10787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
10797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {
10807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
10817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // At this point, only "<**:" in the optionstring.
10827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Clean the day's ** field, after clean, the format is "<  :"
10837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
10847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      SetUnicodeMem (&OptionString[1], 2, L' ');
10857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {
10867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
10877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // At this point, only "**:" in the optionstring.
10887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Clean the month's "**" field, after clean, the format is "  :"
10897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
10907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      SetUnicodeMem (&OptionString[0], 2, L' ');
10917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {
10927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
10937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // At this point, only "****>" in the optionstring.
10947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Clean the year's "****" field, after clean, the format is "  >"
10957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
10967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      SetUnicodeMem (&OptionString[0], 4, L' ');
10977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
10987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
10997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
11007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // OptionString format is: <**:  **:    **>
11017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //                        |hour|minute|second|
11027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //                          4     3      3
11037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
11047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {
11057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // At this point, only "<**:" in the optionstring.
11077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Clean the hour's ** field, after clean, the format is "<  :"
11087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      SetUnicodeMem (&OptionString[1], 2, L' ');
11107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {
11117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // At this point, only "**:" in the optionstring.
11137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Clean the minute's "**" field, after clean, the format is "  :"
11147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      SetUnicodeMem (&OptionString[0], 2, L' ');
11167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {
11177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // At this point, only "**>" in the optionstring.
11197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Clean the second's "**" field, after clean, the format is "  >"
11207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      SetUnicodeMem (&OptionString[0], 2, L' ');
11227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
11237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
11247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
11257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
11287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Adjust Data and Time position accordingly.
11297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Data format :      [01/02/2004]      [11:22:33]
11307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Line number :        0  0    1         0  0  1
11317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  This is an internal function.
11337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  DirectionUp            the up or down direction. False is down. True is
11357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                                 up.
11367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  CurrentPosition        Current position. On return: Point to the last
11377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                                 Option (Year or Second) if up; Point to the first
11387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                                 Option (Month or Hour) if down.
11397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return Return line number to pad. It is possible that we stand on a zero-advance
11417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
11427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
11447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINTN
11457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongAdjustDateAndTimePosition (
11467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN     BOOLEAN                     DirectionUp,
11477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN OUT LIST_ENTRY                  **CurrentPosition
11487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
11497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
11507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN           Count;
11517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY      *NewPosition;
11527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION  *MenuOption;
11537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN           PadLineNumber;
11547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  PadLineNumber = 0;
11567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  NewPosition   = *CurrentPosition;
11577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
11587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||
11607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
11617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
11627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Calculate the distance from current position to the last Date/Time MenuOption
11637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
11647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Count = 0;
11657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    while (MenuOption->Skip == 0) {
11667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Count++;
11677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      NewPosition   = NewPosition->ForwardLink;
11687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      MenuOption    = MENU_OPTION_FROM_LINK (NewPosition);
11697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      PadLineNumber = 1;
11707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
11717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    NewPosition = *CurrentPosition;
11737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (DirectionUp) {
11747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
11767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // to be one that back to the previous set of MenuOptions, we need to advance to the first
11777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate
11787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // checking can be done.
11797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      while (Count++ < 2) {
11817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        NewPosition = NewPosition->BackLink;
11827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
11837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else {
11847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended
11867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // to be one that progresses to the next set of MenuOptions, we need to advance to the last
11877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate
11887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // checking can be done.
11897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
11907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      while (Count-- > 0) {
11917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        NewPosition = NewPosition->ForwardLink;
11927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
11937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
11947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *CurrentPosition = NewPosition;
11967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
11977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
11987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return PadLineNumber;
11997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
12007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
12027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Get step info from numeric opcode.
12037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param[in] OpCode     The input numeric op code.
12057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return step info for this opcode.
12077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
12087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUINT64
12097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetFieldFromNum (
12107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  EFI_IFR_OP_HEADER     *OpCode
12117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
12127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
12137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_IFR_NUMERIC       *NumericOp;
12147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT64                Step;
12157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  NumericOp = (EFI_IFR_NUMERIC *) OpCode;
12177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {
12197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  case EFI_IFR_NUMERIC_SIZE_1:
12207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Step    = NumericOp->data.u8.Step;
12217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    break;
12227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  case EFI_IFR_NUMERIC_SIZE_2:
12247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Step    = NumericOp->data.u16.Step;
12257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    break;
12267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  case EFI_IFR_NUMERIC_SIZE_4:
12287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Step    = NumericOp->data.u32.Step;
12297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    break;
12307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  case EFI_IFR_NUMERIC_SIZE_8:
12327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Step    = NumericOp->data.u64.Step;
12337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    break;
12347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  default:
12367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Step = 0;
12377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    break;
12387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
12397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return Step;
12417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
12427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
12447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Find the registered HotKey based on KeyData.
12457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param[in] KeyData     A pointer to a buffer that describes the keystroke
12477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                         information for the hot key.
12487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return The registered HotKey context. If no found, NULL will return.
12507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
12517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongBROWSER_HOT_KEY *
12527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetHotKeyFromRegisterList (
12537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN EFI_INPUT_KEY *KeyData
12547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
12557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
12567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY       *Link;
12577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BROWSER_HOT_KEY  *HotKey;
12587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Link = GetFirstNode (&gFormData->HotKeyListHead);
12607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  while (!IsNull (&gFormData->HotKeyListHead, Link)) {
12617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
12627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {
12647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      return HotKey;
12657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
12667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Link = GetNextNode (&gFormData->HotKeyListHead, Link);
12687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
12697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return NULL;
12717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
12727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
12757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Determine if the menu is the last menu that can be selected.
12767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  This is an internal function.
12787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  Direction              The scroll direction. False is down. True is up.
12807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  CurrentPos             The current focus.
12817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return FALSE -- the menu isn't the last menu that can be selected.
12837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return TRUE  -- the menu is the last menu that can be selected.
12847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
12867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongBOOLEAN
12877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongValueIsScroll (
12887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  BOOLEAN                     Direction,
12897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  LIST_ENTRY                  *CurrentPos
12907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
12917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
12927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY      *Temp;
12937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
12957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
12967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Temp == &gMenuOption) {
12977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return TRUE;
12987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
12997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return FALSE;
13017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
13027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
13047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Wait for a given event to fire, or for an optional timeout to expire.
13057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  Event                  The event to wait for
13077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval UI_EVENT_TYPE          The type of the event which is trigged.
13097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
13117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUI_EVENT_TYPE
13127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUiWaitForEvent (
13137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN EFI_EVENT                Event
13147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
13157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
13167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STATUS  Status;
13177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN       Index;
13187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN       EventNum;
13197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT64      Timeout;
13207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_EVENT   TimerEvent;
13217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_EVENT   WaitList[3];
13227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_EVENT_TYPE  EventType;
13237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  TimerEvent = NULL;
13257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Timeout    = FormExitTimeout(gFormData);
13267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Timeout != 0) {
13287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
13297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
13317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Set the timer event
13327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
13337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    gBS->SetTimer (
13347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          TimerEvent,
13357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          TimerRelative,
13367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          Timeout
13377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          );
13387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
13397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  WaitList[0] = Event;
13417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EventNum    = 1;
13427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (gFormData->FormRefreshEvent != NULL) {
13437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    WaitList[EventNum] = gFormData->FormRefreshEvent;
13447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    EventNum ++;
13457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
13467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Timeout != 0) {
13487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    WaitList[EventNum] = TimerEvent;
13497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    EventNum ++;
13507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
13517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Status = gBS->WaitForEvent (EventNum, WaitList, &Index);
13537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT_EFI_ERROR (Status);
13547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  switch (Index) {
13567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  case 0:
13577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong   EventType = UIEventKey;
13587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong   break;
13597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  case 1:
13617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (gFormData->FormRefreshEvent != NULL) {
13627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      EventType = UIEventDriver;
13637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    } else {
13647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ASSERT (Timeout != 0 && EventNum == 2);
13657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      EventType = UIEventTimeOut;
13667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
13677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    break;
13687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  default:
13707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    ASSERT (Index == 2 && EventNum == 3);
13717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    EventType = UIEventTimeOut;
13727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    break;
13737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
13747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (Timeout != 0) {
13767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    gBS->CloseEvent (TimerEvent);
13777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
13787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return EventType;
13807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
13817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
13837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Get question id info from the input opcode header.
13847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  OpCode                 The input opcode header pointer.
13867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval                        The question id for this opcode.
13887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
13907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_QUESTION_ID
13917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongGetQuestionIdInfo (
13927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN   EFI_IFR_OP_HEADER     *OpCode
13937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
13947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
13957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_IFR_QUESTION_HEADER   *QuestionHeader;
13967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
13977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (OpCode->Length < sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER)) {
13987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return 0;
13997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
14007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
14017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  QuestionHeader = (EFI_IFR_QUESTION_HEADER *)((UINT8 *) OpCode + sizeof(EFI_IFR_OP_HEADER));
14027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
14037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return QuestionHeader->QuestionId;
14047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
14057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1406ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1407ab369468265cd29a90b385a6e950eda3da16636dEric Dong/**
1408ab369468265cd29a90b385a6e950eda3da16636dEric Dong  Find the top of screen menu base on the current menu.
1409ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1410ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @param  CurPos                 Current input menu.
1411ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @param  Rows                   Totol screen rows.
1412ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @param  SkipValue              SkipValue for this new form.
1413ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1414ab369468265cd29a90b385a6e950eda3da16636dEric Dong  @retval TopOfScreen            Top of screen menu for the new form.
1415ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1416ab369468265cd29a90b385a6e950eda3da16636dEric Dong**/
1417ab369468265cd29a90b385a6e950eda3da16636dEric DongLIST_ENTRY *
1418ab369468265cd29a90b385a6e950eda3da16636dEric DongFindTopOfScreenMenu (
1419ab369468265cd29a90b385a6e950eda3da16636dEric Dong  IN  LIST_ENTRY                      *CurPos,
1420ab369468265cd29a90b385a6e950eda3da16636dEric Dong  IN  UINTN                           Rows,
1421ab369468265cd29a90b385a6e950eda3da16636dEric Dong  OUT UINTN                           *SkipValue
1422ab369468265cd29a90b385a6e950eda3da16636dEric Dong  )
1423ab369468265cd29a90b385a6e950eda3da16636dEric Dong{
1424ab369468265cd29a90b385a6e950eda3da16636dEric Dong  LIST_ENTRY        *Link;
1425ab369468265cd29a90b385a6e950eda3da16636dEric Dong  LIST_ENTRY        *TopOfScreen;
1426ab369468265cd29a90b385a6e950eda3da16636dEric Dong  UI_MENU_OPTION    *PreviousMenuOption;
1427ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1428ab369468265cd29a90b385a6e950eda3da16636dEric Dong  Link = CurPos;
1429ab369468265cd29a90b385a6e950eda3da16636dEric Dong  PreviousMenuOption = NULL;
1430ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1431ab369468265cd29a90b385a6e950eda3da16636dEric Dong  while (Link->BackLink != &gMenuOption) {
1432ab369468265cd29a90b385a6e950eda3da16636dEric Dong    Link = Link->BackLink;
1433ab369468265cd29a90b385a6e950eda3da16636dEric Dong    PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
1434ab369468265cd29a90b385a6e950eda3da16636dEric Dong    if (PreviousMenuOption->Row == 0) {
1435ab369468265cd29a90b385a6e950eda3da16636dEric Dong      UpdateOptionSkipLines (PreviousMenuOption);
1436ab369468265cd29a90b385a6e950eda3da16636dEric Dong    }
1437ab369468265cd29a90b385a6e950eda3da16636dEric Dong    if (Rows <= PreviousMenuOption->Skip) {
1438ab369468265cd29a90b385a6e950eda3da16636dEric Dong      break;
1439ab369468265cd29a90b385a6e950eda3da16636dEric Dong    }
1440ab369468265cd29a90b385a6e950eda3da16636dEric Dong    Rows = Rows - PreviousMenuOption->Skip;
1441ab369468265cd29a90b385a6e950eda3da16636dEric Dong  }
1442ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1443ab369468265cd29a90b385a6e950eda3da16636dEric Dong  if (Link->BackLink == &gMenuOption) {
1444ab369468265cd29a90b385a6e950eda3da16636dEric Dong    TopOfScreen = gMenuOption.ForwardLink;
1445ab369468265cd29a90b385a6e950eda3da16636dEric Dong    if (PreviousMenuOption != NULL && Rows < PreviousMenuOption->Skip) {
1446ab369468265cd29a90b385a6e950eda3da16636dEric Dong      *SkipValue = PreviousMenuOption->Skip - Rows;
1447ab369468265cd29a90b385a6e950eda3da16636dEric Dong    } else {
1448ab369468265cd29a90b385a6e950eda3da16636dEric Dong      *SkipValue = 0;
1449ab369468265cd29a90b385a6e950eda3da16636dEric Dong    }
1450ab369468265cd29a90b385a6e950eda3da16636dEric Dong  } else {
1451ab369468265cd29a90b385a6e950eda3da16636dEric Dong    TopOfScreen = Link;
1452ab369468265cd29a90b385a6e950eda3da16636dEric Dong    *SkipValue = PreviousMenuOption->Skip - Rows;
1453ab369468265cd29a90b385a6e950eda3da16636dEric Dong  }
1454ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1455ab369468265cd29a90b385a6e950eda3da16636dEric Dong  return TopOfScreen;
1456ab369468265cd29a90b385a6e950eda3da16636dEric Dong}
1457ab369468265cd29a90b385a6e950eda3da16636dEric Dong
14587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
14597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Find the first menu which will be show at the top.
14607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
14617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  FormData               The data info for this form.
14627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  TopOfScreen            The link_entry pointer to top menu.
14637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  HighlightMenu          The menu which will be highlight.
14647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  SkipValue              The skip value for the top menu.
14657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
14667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
14677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
14687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongFindTopMenu (
14697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  FORM_DISPLAY_ENGINE_FORM  *FormData,
14707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OUT LIST_ENTRY                **TopOfScreen,
14717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OUT LIST_ENTRY                **HighlightMenu,
1472ab369468265cd29a90b385a6e950eda3da16636dEric Dong  OUT UINTN                     *SkipValue
14737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
14747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
14757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY                      *NewPos;
14767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           TopRow;
14777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           BottomRow;
14787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION                  *SavedMenuOption;
1479ab369468265cd29a90b385a6e950eda3da16636dEric Dong  UINTN                           TmpValue;
14807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1481336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  TmpValue  = 0;
14827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;
14837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;
14847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
14857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
14867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // If not has input highlight statement, just return the first one in this form.
14877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
14887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (FormData->HighLightedStatement == NULL) {
14897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *TopOfScreen   = gMenuOption.ForwardLink;
14907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *HighlightMenu = gMenuOption.ForwardLink;
14917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (!IsListEmpty (&gMenuOption)) {
1492ab369468265cd29a90b385a6e950eda3da16636dEric Dong      MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);
14937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
14947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    *SkipValue     = 0;
14957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return;
14967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
14977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
14987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
14997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Now base on the input highlight menu to find the top menu in this page.
15007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Will base on the highlight menu show at the bottom to find the top menu.
15017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
15027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  NewPos = gMenuOption.ForwardLink;
15037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
15047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
15057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) ||
15067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong         (SavedMenuOption->Sequence != gSequence)) {
15077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    NewPos     = NewPos->ForwardLink;
15087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    if (NewPos == &gMenuOption) {
15097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
15107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Not Found it, break
15117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
15127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
15137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
15147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
15157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
15167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement);
15177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
15187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  *HighlightMenu = NewPos;
15197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
15207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  AdjustDateAndTimePosition(FALSE, &NewPos);
15217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
15227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UpdateOptionSkipLines (SavedMenuOption);
15237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
15247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
1525336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // FormRefreshEvent != NULL means this form will auto exit at an interval, display engine
1526336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // will try to keep highlight on the current position after this form exit and re-enter.
15277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
1528336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // HiiHandle + QuestionId can find the only one question in the system.
1529336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  //
1530336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // If this question has question id, save the question id info to find the question.
1531336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // else save the opcode buffer to find it.
1532336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  //
1533336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  if (gFormData->FormRefreshEvent != NULL && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) {
1534336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    if (gHighligthMenuInfo.QuestionId != 0) {
1535336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      if (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode)) {
1536336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;
1537336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        //
1538336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        // SkipValue only used for menu at the top of the form.
1539336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        // If Highlight menu is not at the top, this value will be update later.
1540336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        //
1541336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        TmpValue = gHighligthMenuInfo.SkipValue;
1542336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      }
1543336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    } else if (gHighligthMenuInfo.OpCode != NULL){
1544336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      if (!CompareMem (gHighligthMenuInfo.OpCode, SavedMenuOption->ThisTag->OpCode, gHighligthMenuInfo.OpCode->Length)) {
1545336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;
1546336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        //
1547336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        // SkipValue only used for menu at the top of the form.
1548336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        // If Highlight menu is not at the top, this value will be update later.
1549336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        //
1550336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        TmpValue = gHighligthMenuInfo.SkipValue;
1551336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      }
1552336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    }
15537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
15547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
1555ab369468265cd29a90b385a6e950eda3da16636dEric Dong  if (SavedMenuOption->Skip >= BottomRow - TopRow) {
1556ab369468265cd29a90b385a6e950eda3da16636dEric Dong    *TopOfScreen = NewPos;
15577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else {
1558ab369468265cd29a90b385a6e950eda3da16636dEric Dong    *TopOfScreen = FindTopOfScreenMenu(NewPos, BottomRow - TopRow - SavedMenuOption->Skip, &TmpValue);
15597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
1560c8d54a6d8dd259a28d02bf95ed7e48efb251e414Eric Dong  AdjustDateAndTimePosition(TRUE, TopOfScreen);
1561ab369468265cd29a90b385a6e950eda3da16636dEric Dong
1562ab369468265cd29a90b385a6e950eda3da16636dEric Dong  *SkipValue   = TmpValue;
15637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
15647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
15657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
1566af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Update highlight menu info.
1567af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1568af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  MenuOption               The menu opton which is highlight.
1569336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  @param  SkipValue                The skipvalue info for this menu.
1570336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong                                   SkipValue only used for the menu at the top of the form.
1571af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1572af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong**/
1573af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongVOID
1574af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongUpdateHighlightMenuInfo (
1575336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  IN UI_MENU_OPTION            *MenuOption,
1576336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  IN UINTN                     SkipValue
1577af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  )
1578af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong{
1579af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;
1580af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1581af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1582af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // This is the current selected statement
1583af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1584af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Statement = MenuOption->ThisTag;
1585af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1586af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1587af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // Get the highlight statement.
1588af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1589af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  gUserInput->SelectedStatement = Statement;
1590af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  gSequence = (UINT16) MenuOption->Sequence;
1591af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1592af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1593336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // FormRefreshEvent != NULL means this form will auto exit at an interval, display engine
1594336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // will try to keep highlight on the current position after this form exit and re-enter.
1595af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1596336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // HiiHandle + QuestionId can find the only one question in the system.
1597336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  //
1598336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // If this question has question id, base on the question id info to find the question.
1599336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  // else base on the opcode buffer to find it.
1600336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  //
1601336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  if (gFormData->FormRefreshEvent != NULL) {
1602336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    gHighligthMenuInfo.HiiHandle  = gFormData->HiiHandle;
1603af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode);
1604336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong
1605336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    //
1606336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    // if question id == 0, save the opcode buffer for later use.
1607336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    //
1608336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    if (gHighligthMenuInfo.QuestionId == 0) {
1609336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      if (gHighligthMenuInfo.OpCode != NULL) {
1610336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        FreePool (gHighligthMenuInfo.OpCode);
1611336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      }
1612336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      gHighligthMenuInfo.OpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);
1613336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      ASSERT (gHighligthMenuInfo.OpCode != NULL);
1614336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    }
1615af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row;
1616336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    gHighligthMenuInfo.SkipValue  = (UINT16) SkipValue;
1617af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  } else {
1618336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    gHighligthMenuInfo.HiiHandle  = NULL;
1619af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    gHighligthMenuInfo.QuestionId = 0;
1620336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    if (gHighligthMenuInfo.OpCode != NULL) {
1621336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      FreePool (gHighligthMenuInfo.OpCode);
1622336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong      gHighligthMenuInfo.OpCode = NULL;
1623336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    }
1624af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    gHighligthMenuInfo.DisplayRow = 0;
1625336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    gHighligthMenuInfo.SkipValue  = 0;
1626af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1627af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1628af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  RefreshKeyHelp(gFormData, Statement, FALSE);
1629af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong}
1630af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1631af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong/**
1632af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Update attribut for this menu.
1633af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1634af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  MenuOption               The menu opton which this attribut used to.
1635af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  Highlight                Whether this menu will be highlight.
1636af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1637af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong**/
1638af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongVOID
1639af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongSetDisplayAttribute (
1640af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UI_MENU_OPTION                  *MenuOption,
1641af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN BOOLEAN                         Highlight
1642af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  )
1643af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong{
1644af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;
1645af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1646af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Statement = MenuOption->ThisTag;
1647af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1648af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if (Highlight) {
1649af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());
1650af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    return;
1651af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1652af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1653af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if (MenuOption->GrayOut) {
1654af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());
1655af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  } else {
1656af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {
1657af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());
1658af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    } else {
1659af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
1660af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    }
1661af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1662af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong}
1663af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1664af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong/**
1665af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Print string for this menu option.
1666af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1667af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  MenuOption               The menu opton which this attribut used to.
1668af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  Col                      The column that this string will be print at.
1669af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  Row                      The row that this string will be print at.
1670af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  String                   The string which need to print.
1671af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  Width                    The width need to print, if string is less than the
1672af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong                                   width, the block space will be used.
1673af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  Highlight                Whether this menu will be highlight.
1674af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1675af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong**/
1676af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongVOID
1677af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongDisplayMenuString (
1678af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UI_MENU_OPTION         *MenuOption,
1679af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UINTN                  Col,
1680af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UINTN                  Row,
1681af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN CHAR16                 *String,
1682af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UINTN                  Width,
1683af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN BOOLEAN                Highlight
1684af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  )
1685af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong{
1686af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN            Length;
1687af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1688af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1689af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // Print string with normal color.
1690af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1691af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if (!Highlight) {
1692af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    PrintStringAtWithWidth (Col, Row, String, Width);
1693af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    return;
1694af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1695af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1696af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1697af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // Print the highlight menu string.
1698af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // First print the highlight string.
1699af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1700af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  SetDisplayAttribute(MenuOption, TRUE);
1701af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Length = PrintStringAt (Col, Row, String);
1702af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1703af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1704af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // Second, clean the empty after the string.
1705af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1706af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  SetDisplayAttribute(MenuOption, FALSE);
1707af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);
1708af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong}
1709af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1710af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong/**
171128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  Check whether this menu can has option string.
171228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
171328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  @param  MenuOption               The menu opton which this attribut used to.
171428401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
171528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  @retval TRUE                     This menu option can have option string.
171628401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  @retval FALSE                    This menu option can't have option string.
171728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
171828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong**/
171928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric DongBOOLEAN
172028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric DongHasOptionString (
172128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  IN UI_MENU_OPTION                  *MenuOption
172228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  )
172328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong{
172428401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;
172528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  CHAR16                          *String;
172628401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  UINTN                           Size;
172728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  EFI_IFR_TEXT                    *TestOp;
172828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
172928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  Size = 0;
173028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  Statement = MenuOption->ThisTag;
173128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
173228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  //
173328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  // See if the second text parameter is really NULL
173428401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  //
173528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
173628401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    TestOp = (EFI_IFR_TEXT *) Statement->OpCode;
173728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    if (TestOp->TextTwo != 0) {
173828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong      String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);
173928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong      Size   = StrLen (String);
174028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong      FreePool (String);
174128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    }
174228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  }
174328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
174428401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
174528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||
174628401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||
174728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||
174828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||
174928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    //
175028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    // Allow a wide display if text op-code and no secondary text op-code
175128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    //
175228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))
175328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    ) {
175428401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
175528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    return FALSE;
175628401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  }
175728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
175828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  return TRUE;
175928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong}
176028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
176128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
176228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong/**
1763af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Print string for this menu option.
1764af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1765af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  MenuOption               The menu opton which this attribut used to.
1766af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  SkipWidth                The skip width between the left to the start of the prompt.
1767af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  BeginCol                 The begin column for one menu.
1768af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  SkipLine                 The skip line for this menu.
1769af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  BottomRow                The bottom row for this form.
1770af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @param  Highlight                Whether this menu will be highlight.
1771f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong  @param  UpdateCol                Whether need to update the column info for Date/Time.
1772af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1773af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  @retval EFI_SUCESSS              Process the user selection success.
1774af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1775af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong**/
1776af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongEFI_STATUS
1777af047db78d297ca33dd74e5e749166bb17a4cc4eEric DongDisplayOneMenu (
1778af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UI_MENU_OPTION                  *MenuOption,
1779af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UINTN                           SkipWidth,
1780af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UINTN                           BeginCol,
1781af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UINTN                           SkipLine,
1782af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  IN UINTN                           BottomRow,
1783f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong  IN BOOLEAN                         Highlight,
1784f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong  IN BOOLEAN                         UpdateCol
1785af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  )
1786af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong{
1787af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;
1788af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN                           Index;
1789af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINT16                          Width;
1790af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINT16                          PromptWidth;
1791af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  CHAR16                          *StringPtr;
1792af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  CHAR16                          *OptionString;
1793af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  CHAR16                          *OutputString;
1794af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINT16                          GlyphWidth;
1795af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN                           Temp;
1796af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN                           Temp2;
1797af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN                           Temp3;
1798af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  EFI_STATUS                      Status;
1799af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN                           Row;
1800af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN                           Col;
1801af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  UINTN                           PromptLineNum;
180228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  UINTN                           OptionLineNum;
1803af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  CHAR16                          AdjustValue;
180428401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  UINTN                           MaxRow;
1805af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1806af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Statement = MenuOption->ThisTag;
1807af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Temp      = SkipLine;
1808af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Temp2     = SkipLine;
1809af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Temp3     = SkipLine;
181028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  AdjustValue   = 0;
181128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  PromptLineNum = 0;
181228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  OptionLineNum = 0;
181328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  MaxRow        = 0;
1814af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1815af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1816af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // Set default color.
1817af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1818af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  SetDisplayAttribute (MenuOption, FALSE);
1819af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1820af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1821af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  // 1. Paint the option string.
1822af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1823af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);
1824af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if (EFI_ERROR (Status)) {
1825af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    return Status;
1826af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1827af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1828af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if (OptionString != NULL) {
1829af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
1830af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1831af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      // Adjust option string for date/time opcode.
1832af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1833f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong      ProcessStringForDateTime(MenuOption, OptionString, UpdateCol);
1834af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    }
1835af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1836af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    Width       = (UINT16) gOptionBlockWidth - 1;
183728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    Row         = MenuOption->Row;
1838af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    GlyphWidth  = 1;
183928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    OptionLineNum = 0;
1840af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1841af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
1842af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (((Temp2 == 0)) && (Row <= BottomRow)) {
1843af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
1844af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          //
1845af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // For date/time question, it has three menu options for this qustion.
1846af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // The first/second menu options with the skip value is 0. the last one
1847af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // with skip value is 1.
1848af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          //
1849af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          if (MenuOption->Skip != 0) {
1850af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            //
1851af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            // For date/ time, print the last past (year for date and second for time)
1852af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            // - 7 means skip [##/##/ for date and [##:##: for time.
1853af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            //
1854af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            DisplayMenuString (MenuOption,MenuOption->OptCol, Row, OutputString, Width + 1 - 7, Highlight);
1855af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          } else {
1856af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            //
1857af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            // For date/ time, print the first and second past (year for date and second for time)
1858f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong            // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string,
1859f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong            // so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it.
1860f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong            DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString) - 1, Highlight);
1861af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          }
1862af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        } else {
1863af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);
1864af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        }
186528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong        OptionLineNum++;
1866af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1867af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1868af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1869af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      // If there is more string to process print on the next row and increment the Skip value
1870af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1871af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (StrLen (&OptionString[Index]) != 0) {
1872af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        if (Temp2 == 0) {
1873af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          Row++;
1874af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          //
1875af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // Since the Number of lines for this menu entry may or may not be reflected accurately
1876af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
1877af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // some testing to ensure we are keeping this in-sync.
1878af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          //
1879af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // If the difference in rows is greater than or equal to the skip value, increase the skip value
1880af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          //
188128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong          if ((Row - MenuOption->Row) >= MenuOption->Skip) {
1882af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            MenuOption->Skip++;
1883af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          }
1884af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        }
1885af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1886af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1887af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      FreePool (OutputString);
1888af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (Temp2 != 0) {
1889af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        Temp2--;
1890af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1891af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    }
1892af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1893af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    Highlight = FALSE;
1894af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1895af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    FreePool (OptionString);
1896af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1897af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1898af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
189928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  // 2. Paint the description.
1900af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
19016f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong  PromptWidth   = GetWidth (MenuOption, &AdjustValue);
190228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  Row           = MenuOption->Row;
1903af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  GlyphWidth    = 1;
1904af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  PromptLineNum = 0;
1905af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1906af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if (MenuOption->Description == NULL || MenuOption->Description[0] == '\0') {
190728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);
190828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    PromptLineNum++;
1909af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  } else {
1910af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
1911af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if ((Temp == 0) && (Row <= BottomRow)) {
1912af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
1913af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        // 1.Clean the start LEFT_SKIPPED_COLUMNS
1914af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
1915af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        PrintStringAtWithWidth (BeginCol, Row, L"", SkipWidth);
1916af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1917af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2) {
1918af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          //
1919af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // Print Arrow for Goto button.
1920af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          //
1921af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          PrintCharAt (
1922af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            MenuOption->Col - 2,
1923af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            Row,
1924af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            GEOMETRICSHAPE_RIGHT_TRIANGLE
1925af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            );
1926af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        }
1927af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        DisplayMenuString (MenuOption, MenuOption->Col, Row, OutputString, PromptWidth + AdjustValue, Highlight);
1928af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        PromptLineNum ++;
1929af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1930af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1931af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      // If there is more string to process print on the next row and increment the Skip value
1932af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1933af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (StrLen (&MenuOption->Description[Index]) != 0) {
1934af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        if (Temp == 0) {
1935af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          Row++;
1936af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        }
1937af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1938af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1939af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      FreePool (OutputString);
1940af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (Temp != 0) {
1941af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        Temp--;
1942af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1943af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    }
1944af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1945af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    Highlight = FALSE;
1946af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1947af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1948af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1949af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
195028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  // 3. If this is a text op with secondary text information
1951af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
1952af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  if ((Statement->OpCode->OpCode  == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {
1953af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    StringPtr   = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);
1954af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1955af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    Width       = (UINT16) gOptionBlockWidth - 1;
195628401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    Row         = MenuOption->Row;
1957af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    GlyphWidth  = 1;
195828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    OptionLineNum = 0;
1959af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1960af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
1961af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if ((Temp3 == 0) && (Row <= BottomRow)) {
1962af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);
196328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong        OptionLineNum++;
1964af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1965af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1966af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      // If there is more string to process print on the next row and increment the Skip value
1967af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      //
1968af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (StrLen (&StringPtr[Index]) != 0) {
1969af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        if (Temp3 == 0) {
1970af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          Row++;
1971a6a2a95632172022229f0c3d20f0b9adb15dc2faEric Dong          //
1972a6a2a95632172022229f0c3d20f0b9adb15dc2faEric Dong          // If the rows for text two is greater than or equal to the skip value, increase the skip value
1973a6a2a95632172022229f0c3d20f0b9adb15dc2faEric Dong          //
1974a6a2a95632172022229f0c3d20f0b9adb15dc2faEric Dong          if ((Row - MenuOption->Row) >= MenuOption->Skip) {
1975a6a2a95632172022229f0c3d20f0b9adb15dc2faEric Dong            MenuOption->Skip++;
1976a6a2a95632172022229f0c3d20f0b9adb15dc2faEric Dong          }
1977af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        }
1978af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1979af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
1980af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      FreePool (OutputString);
1981af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (Temp3 != 0) {
1982af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        Temp3--;
1983af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
1984af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    }
198528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
1986af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    FreePool (StringPtr);
1987af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  }
1988af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
198928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  //
199028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  // 4.Line number for Option string and prompt string are not equal.
199128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  //  Clean the column whose line number is less.
199228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  //
199328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  if (HasOptionString(MenuOption) && (OptionLineNum != PromptLineNum)) {
199428401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    Col    =  OptionLineNum < PromptLineNum ? MenuOption->OptCol : BeginCol;
199528401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    Row    = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row;
199628401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    Width  = (UINT16) (OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth);
199728401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1;
199828401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
199928401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    while (Row <= MaxRow) {
200028401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong      DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE);
200128401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong    }
200228401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong  }
200328401a651c65cc3004fbd5a6e9f56fd89c41dbb4Eric Dong
2004af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  return EFI_SUCCESS;
2005af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong}
2006af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
2007af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong/**
20087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Display menu and wait for user to select one menu option, then return it.
20097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  If AutoBoot is enabled, then if user doesn't select any option,
20107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  after period of time, it will automatically return the first menu option.
20117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
20127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param  FormData               The current form data info.
20137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
20147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval EFI_SUCESSS            Process the user selection success.
20157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval EFI_NOT_FOUND          Process option string for orderedlist/Oneof fail.
20167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
20177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
20187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_STATUS
20197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUiDisplayMenu (
20207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  FORM_DISPLAY_ENGINE_FORM  *FormData
20217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
20227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
2023ab369468265cd29a90b385a6e950eda3da16636dEric Dong  UINTN                           SkipValue;
20247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  INTN                            Difference;
20257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           DistanceValue;
20267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           Row;
20277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           Col;
20287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           Temp;
20297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           Temp2;
20307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           TopRow;
20317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           BottomRow;
20327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           Index;
20337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16                          Width;
20347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16                          *StringPtr;
20357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16                          *OptionString;
20367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16                          *OutputString;
20377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16                          *HelpString;
20387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16                          *HelpHeaderString;
20397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16                          *HelpBottomString;
20407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BOOLEAN                         NewLine;
20417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BOOLEAN                         Repaint;
20427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BOOLEAN                         UpArrow;
20437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BOOLEAN                         DownArrow;
20447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STATUS                      Status;
20457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_INPUT_KEY                   Key;
20467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY                      *Link;
20477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY                      *NewPos;
20487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY                      *TopOfScreen;
20497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  LIST_ENTRY                      *SavedListEntry;
20507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION                  *MenuOption;
20517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION                  *NextMenuOption;
20527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION                  *SavedMenuOption;
20537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_MENU_OPTION                  *PreviousMenuOption;
20547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_CONTROL_FLAG                 ControlFlag;
20557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_SCREEN_OPERATION             ScreenOperation;
20567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16                          DefaultId;
20577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FORM_DISPLAY_ENGINE_STATEMENT   *Statement;
20587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BROWSER_HOT_KEY                 *HotKey;
20597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           HelpPageIndex;
20607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           HelpPageCount;
20617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           RowCount;
20627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           HelpLine;
20637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           HelpHeaderLine;
20647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINTN                           HelpBottomLine;
20657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BOOLEAN                         MultiHelpPage;
20667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16                          EachLineWidth;
20677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16                          HeaderLineWidth;
20687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UINT16                          BottomLineWidth;
20697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STRING_ID                   HelpInfo;
20707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UI_EVENT_TYPE                   EventType;
20717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FORM_DISPLAY_ENGINE_STATEMENT   *InitialHighlight;
2072af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  BOOLEAN                         SkipHighLight;
20737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
20747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EventType           = UIEventNone;
20757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Status              = EFI_SUCCESS;
20767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpString          = NULL;
20777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpHeaderString    = NULL;
20787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpBottomString    = NULL;
20797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OptionString        = NULL;
20807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ScreenOperation     = UiNoOperation;
20817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  NewLine             = TRUE;
20827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  DefaultId           = 0;
20837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpPageCount       = 0;
20847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpLine            = 0;
20857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  RowCount            = 0;
20867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpBottomLine      = 0;
20877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpHeaderLine      = 0;
20887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HelpPageIndex       = 0;
20897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  MultiHelpPage       = FALSE;
20907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EachLineWidth       = 0;
20917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HeaderLineWidth     = 0;
20927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BottomLineWidth     = 0;
20937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OutputString        = NULL;
20947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  UpArrow             = FALSE;
20957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  DownArrow           = FALSE;
20967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  SkipValue           = 0;
2097af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  SkipHighLight       = FALSE;
20987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
20997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  NextMenuOption      = NULL;
21007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  PreviousMenuOption  = NULL;
21017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  SavedMenuOption     = NULL;
21027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HotKey              = NULL;
21037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Repaint             = TRUE;
21047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  MenuOption          = NULL;
2105af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  gModalSkipColumn    = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6;
21067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  InitialHighlight    = gFormData->HighLightedStatement;
21077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
21097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2110af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
2111af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //  Left                                              right
2112af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //   |<-.->|<-.........->|<- .........->|<-...........->|
2113af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //     Skip    Prompt         Option         Help
2114af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  //
2115af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  Width             = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3);
2116af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  gOptionBlockWidth = Width + 1;
2117af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  gHelpBlockWidth   = (CHAR16) (Width - LEFT_SKIPPED_COLUMNS);
2118af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong  gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * Width - 1);
21197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;
21217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;
21227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Row = TopRow;
21247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
2125af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong    Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gModalSkipColumn;
21267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else {
21277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS;
21287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
21297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue);
21317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
21337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ControlFlag = CfInitialization;
21357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  while (TRUE) {
21367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    switch (ControlFlag) {
21377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfInitialization:
2138af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) ||
2139af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))) {
2140af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
2141af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        // Clear Statement range if different formset is painted.
2142af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
2143af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        ClearLines (
2144af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          gStatementDimensions.LeftColumn,
2145af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          gStatementDimensions.RightColumn,
2146af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          TopRow - SCROLL_ARROW_HEIGHT,
2147af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          BottomRow + SCROLL_ARROW_HEIGHT,
2148af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          GetFieldTextColor ()
2149af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          );
21507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
2152af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      ControlFlag = CfRepaint;
21537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
21547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfRepaint:
21567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRefreshHighLight;
21577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (Repaint) {
21597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
21607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // Display menu
21617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
21627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        DownArrow       = FALSE;
21637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        UpArrow         = FALSE;
21647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Row             = TopRow;
21657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2166af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
2167af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
21687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2169af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        // 1. Check whether need to print the arrow up.
21707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2171af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        if (!ValueIsScroll (TRUE, TopOfScreen)) {
2172af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          UpArrow = TRUE;
2173af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        }
2174af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
2175ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong        if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
2176ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong          PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);
2177ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong        } else {
2178ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong          PrintStringAtWithWidth(gStatementDimensions.LeftColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);
2179ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong        }
2180af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        if (UpArrow) {
2181af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());
2182af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          PrintCharAt (
2183af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
21847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            TopRow - SCROLL_ARROW_HEIGHT,
2185af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            ARROW_UP
21867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
2187af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
21887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
21897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
21907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
21917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // 2.Paint the menu.
21927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
21937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {
21947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          MenuOption          = MENU_OPTION_FROM_LINK (Link);
21957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          MenuOption->Row     = Row;
21967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          MenuOption->Col     = Col;
21977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
2198af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            MenuOption->OptCol  = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth + gModalSkipColumn;
21997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          } else {
2200af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            MenuOption->OptCol  = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth;
22017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
22027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
22037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (MenuOption->NestInStatement) {
22047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            MenuOption->Col += SUBTITLE_INDENT;
22057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
22067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
22077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
2208af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          // Save the highlight menu, will be used in CfRefreshHighLight case.
22097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
2210af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          if (Link == NewPos) {
2211af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            SavedMenuOption = MenuOption;
2212af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            SkipHighLight   = TRUE;
22137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
2214ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong
2215ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong          if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
221672f2eca287ec08dcc32adbf1bb6756b5b97b6f34Eric Dong            Status = DisplayOneMenu (MenuOption,
22176f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong                            MenuOption->Col - gStatementDimensions.LeftColumn,
2218ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong                            gStatementDimensions.LeftColumn + gModalSkipColumn,
2219ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong                            Link == TopOfScreen ? SkipValue : 0,
2220ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong                            BottomRow,
2221f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),
2222f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                            TRUE
2223ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong                            );
2224ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong          } else {
222572f2eca287ec08dcc32adbf1bb6756b5b97b6f34Eric Dong            Status = DisplayOneMenu (MenuOption,
22266f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong                            MenuOption->Col - gStatementDimensions.LeftColumn,
2227ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong                            gStatementDimensions.LeftColumn,
2228ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong                            Link == TopOfScreen ? SkipValue : 0,
2229ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong                            BottomRow,
2230f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),
2231f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                            TRUE
2232f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                            );
2233ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong          }
22347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
223572f2eca287ec08dcc32adbf1bb6756b5b97b6f34Eric Dong          if (EFI_ERROR (Status)) {
223672f2eca287ec08dcc32adbf1bb6756b5b97b6f34Eric Dong            return Status;
223772f2eca287ec08dcc32adbf1bb6756b5b97b6f34Eric Dong          }
22387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
22397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // 3. Update the row info which will be used by next menu.
22407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
22417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (Link == TopOfScreen) {
22427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Row += MenuOption->Skip - SkipValue;
22437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          } else {
22447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Row += MenuOption->Skip;
22457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
22467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
22477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (Row > BottomRow) {
22487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            if (!ValueIsScroll (FALSE, Link)) {
22497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              DownArrow = TRUE;
22507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            }
22517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
22527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Row = BottomRow + 1;
22537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            break;
22547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
22557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
22567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2257af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
2258af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        // 3. Menus in this form may not cover all form, clean the remain field.
2259af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
2260af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        while (Row <= BottomRow) {
2261af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
2262ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong            PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, Row++, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);
2263af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          } else {
2264af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong            PrintStringAtWithWidth(gStatementDimensions.LeftColumn, Row++, L"", gStatementDimensions.RightColumn - gHelpBlockWidth - gStatementDimensions.LeftColumn);
2265af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong          }
22667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
22677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2268af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
2269af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        // 4. Print the down arrow row.
2270af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        //
2271ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong        if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
2272ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong          PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 *  + gModalSkipColumn);
2273ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong        } else {
2274ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong          PrintStringAtWithWidth(gStatementDimensions.LeftColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);
2275ae4f5746efc0dde9bb64b537f3a41e66c8729f4dEric Dong        }
22767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (DownArrow) {
22777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());
22787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          PrintCharAt (
22797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
22807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            BottomRow + SCROLL_ARROW_HEIGHT,
22817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            ARROW_DOWN
22827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
22837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
22847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
22857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
22867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        MenuOption = NULL;
22877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
22887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
22897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
22907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfRefreshHighLight:
22917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
22927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
22937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // MenuOption: Last menu option that need to remove hilight
22947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //             MenuOption is set to NULL in Repaint
22957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // NewPos:     Current menu option that need to hilight
22967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
22977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfUpdateHelpString;
22987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2299af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      if (SkipHighLight) {
2300af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        MenuOption    = SavedMenuOption;
2301af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        SkipHighLight = FALSE;
2302336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        UpdateHighlightMenuInfo (MenuOption, TopOfScreen == &MenuOption->Link ? SkipValue : 0);
2303af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong        break;
2304af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong      }
2305af047db78d297ca33dd74e5e749166bb17a4cc4eEric Dong
23068924aecd470f84968369982a69aa30acc7c387dfEric Dong      if (IsListEmpty (&gMenuOption)) {
23078924aecd470f84968369982a69aa30acc7c387dfEric Dong        //
23088924aecd470f84968369982a69aa30acc7c387dfEric Dong        // No menu option, just update the hotkey filed.
23098924aecd470f84968369982a69aa30acc7c387dfEric Dong        //
23108924aecd470f84968369982a69aa30acc7c387dfEric Dong        RefreshKeyHelp(gFormData, NULL, FALSE);
23118924aecd470f84968369982a69aa30acc7c387dfEric Dong        break;
23128924aecd470f84968369982a69aa30acc7c387dfEric Dong      }
23138924aecd470f84968369982a69aa30acc7c387dfEric Dong
23147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) {
23157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Temp = SkipValue;
23167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      } else {
23177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Temp = 0;
23187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
23197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (NewPos == TopOfScreen) {
23207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Temp2 = SkipValue;
23217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      } else {
23227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Temp2 = 0;
23237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
23247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
23257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {
23267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (MenuOption != NULL) {
23277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
2328ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // Remove the old highlight menu.
23297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
2330ab369468265cd29a90b385a6e950eda3da16636dEric Dong          Status = DisplayOneMenu (MenuOption,
2331ab369468265cd29a90b385a6e950eda3da16636dEric Dong                          MenuOption->Col - gStatementDimensions.LeftColumn,
2332ab369468265cd29a90b385a6e950eda3da16636dEric Dong                          gStatementDimensions.LeftColumn,
2333ab369468265cd29a90b385a6e950eda3da16636dEric Dong                          Temp,
2334ab369468265cd29a90b385a6e950eda3da16636dEric Dong                          BottomRow,
2335f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                          FALSE,
2336ab369468265cd29a90b385a6e950eda3da16636dEric Dong                          FALSE
2337ab369468265cd29a90b385a6e950eda3da16636dEric Dong                          );
23387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
23397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
23407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
23417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // This is the current selected statement
23427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
23437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        MenuOption = MENU_OPTION_FROM_LINK (NewPos);
23447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Statement = MenuOption->ThisTag;
23457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2346336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong        UpdateHighlightMenuInfo (MenuOption, Temp2);
23477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
23487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (!IsSelectable (MenuOption)) {
23497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
23507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
23517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2352ab369468265cd29a90b385a6e950eda3da16636dEric Dong        Status = DisplayOneMenu (MenuOption,
2353ab369468265cd29a90b385a6e950eda3da16636dEric Dong                        MenuOption->Col - gStatementDimensions.LeftColumn,
2354ab369468265cd29a90b385a6e950eda3da16636dEric Dong                        gStatementDimensions.LeftColumn,
2355ab369468265cd29a90b385a6e950eda3da16636dEric Dong                        Temp2,
2356ab369468265cd29a90b385a6e950eda3da16636dEric Dong                        BottomRow,
2357f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                        TRUE,
2358f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong                        FALSE
2359ab369468265cd29a90b385a6e950eda3da16636dEric Dong                        );
23607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
23617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
23627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
23637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUpdateHelpString:
23647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfPrepareToReadKey;
23657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
23667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
23677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
23687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2369ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
2370ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // NewLine means only update highlight menu (remove old highlight and highlith
2371ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // the new one), not need to full repain the form.
2372ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
23737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (Repaint || NewLine) {
23748924aecd470f84968369982a69aa30acc7c387dfEric Dong        if (IsListEmpty (&gMenuOption)) {
23758924aecd470f84968369982a69aa30acc7c387dfEric Dong          //
23768924aecd470f84968369982a69aa30acc7c387dfEric Dong          // Don't print anything if no mwnu option.
23778924aecd470f84968369982a69aa30acc7c387dfEric Dong          //
23787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
23797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        } else {
23808924aecd470f84968369982a69aa30acc7c387dfEric Dong          //
23818924aecd470f84968369982a69aa30acc7c387dfEric Dong          // Don't print anything if it is a NULL help token
23828924aecd470f84968369982a69aa30acc7c387dfEric Dong          //
23838924aecd470f84968369982a69aa30acc7c387dfEric Dong          ASSERT(MenuOption != NULL);
23848924aecd470f84968369982a69aa30acc7c387dfEric Dong          HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;
23858924aecd470f84968369982a69aa30acc7c387dfEric Dong          if (HelpInfo == 0 || !IsSelectable (MenuOption)) {
23868924aecd470f84968369982a69aa30acc7c387dfEric Dong            StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
23878924aecd470f84968369982a69aa30acc7c387dfEric Dong          } else {
23888924aecd470f84968369982a69aa30acc7c387dfEric Dong            StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);
23898924aecd470f84968369982a69aa30acc7c387dfEric Dong          }
23907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
23917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
23927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        RowCount      = BottomRow - TopRow + 1;
23937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        HelpPageIndex = 0;
23947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
23957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // 1.Calculate how many line the help string need to print.
23967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
23977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (HelpString != NULL) {
23987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          FreePool (HelpString);
23997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          HelpString = NULL;
24007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
24017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);
24027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        FreePool (StringPtr);
24037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
24047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (HelpLine > RowCount) {
24057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          MultiHelpPage   = TRUE;
24067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          StringPtr       = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);
24077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (HelpHeaderString != NULL) {
24087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            FreePool (HelpHeaderString);
24097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            HelpHeaderString = NULL;
24107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
24117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          HelpHeaderLine  = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, 0);
24127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          FreePool (StringPtr);
24137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          StringPtr       = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);
24147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (HelpBottomString != NULL) {
24157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            FreePool (HelpBottomString);
24167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            HelpBottomString = NULL;
24177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
24187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          HelpBottomLine  = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, 0);
24197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          FreePool (StringPtr);
24207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
24217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // Calculate the help page count.
24227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
24237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (HelpLine > 2 * RowCount - 2) {
24247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;
24257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {
24267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              HelpPageCount += 1;
24277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            }
24287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          } else {
24297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            HelpPageCount = 2;
24307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
24317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        } else {
24327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          MultiHelpPage = FALSE;
24337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
24347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
24357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
24367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
24377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Check whether need to show the 'More(U/u)' at the begin.
24387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Base on current direct info, here shows aligned to the right side of the column.
24397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // If the direction is multi line and aligned to right side may have problem, so
24407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // add ASSERT code here.
24417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
24427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (HelpPageIndex > 0) {
24437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());
24447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        for (Index = 0; Index < HelpHeaderLine; Index++) {
24457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ASSERT (HelpHeaderLine == 1);
24467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));
24477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          PrintStringAtWithWidth (
24487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gStatementDimensions.RightColumn - gHelpBlockWidth,
24497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Index + TopRow,
24507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gEmptyString,
24517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gHelpBlockWidth
24527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
24537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          PrintStringAt (
24547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gStatementDimensions.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,
24557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Index + TopRow,
24567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            &HelpHeaderString[Index * HeaderLineWidth]
24577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
24587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
24597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
24607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
24617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      gST->ConOut->SetAttribute (gST->ConOut, GetHelpTextColor ());
24627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
24637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Print the help string info.
24647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
24657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (!MultiHelpPage) {
24667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        for (Index = 0; Index < HelpLine; Index++) {
24677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          PrintStringAtWithWidth (
24687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gStatementDimensions.RightColumn - gHelpBlockWidth,
24697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Index + TopRow,
24707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            &HelpString[Index * EachLineWidth],
24717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gHelpBlockWidth
24727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
24737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
24747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        for (; Index < RowCount; Index ++) {
24757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          PrintStringAtWithWidth (
24767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gStatementDimensions.RightColumn - gHelpBlockWidth,
24777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Index + TopRow,
24787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gEmptyString,
24797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gHelpBlockWidth
24807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
24817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
24827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);
24837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      } else  {
24847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (HelpPageIndex == 0) {
24857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {
24867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            PrintStringAtWithWidth (
24877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              gStatementDimensions.RightColumn - gHelpBlockWidth,
24887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              Index + TopRow,
24897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              &HelpString[Index * EachLineWidth],
24907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              gHelpBlockWidth
24917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              );
24927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
24937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        } else {
24947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) &&
24957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {
24967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            PrintStringAtWithWidth (
24977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              gStatementDimensions.RightColumn - gHelpBlockWidth,
24987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              Index + TopRow + HelpHeaderLine,
24997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth],
25007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              gHelpBlockWidth
25017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              );
25027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
25037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (HelpPageIndex == HelpPageCount - 1) {
25047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            for (; Index < RowCount - HelpHeaderLine; Index ++) {
25057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong              PrintStringAtWithWidth (
25067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                gStatementDimensions.RightColumn - gHelpBlockWidth,
25077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                Index + TopRow + HelpHeaderLine,
25087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                gEmptyString,
25097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                gHelpBlockWidth
25107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                );
25117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            }
25127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);
25137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
25147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
25157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
25167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
25187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Check whether need to print the 'More(D/d)' at the bottom.
25197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Base on current direct info, here shows aligned to the right side of the column.
25207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // If the direction is multi line and aligned to right side may have problem, so
25217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // add ASSERT code here.
25227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
25237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {
25247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());
25257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        for (Index = 0; Index < HelpBottomLine; Index++) {
25267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ASSERT (HelpBottomLine == 1);
25277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1));
25287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          PrintStringAtWithWidth (
25297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gStatementDimensions.RightColumn - gHelpBlockWidth,
25307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            BottomRow + Index - HelpBottomLine + 1,
25317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gEmptyString,
25327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gHelpBlockWidth
25337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
25347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          PrintStringAt (
25357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gStatementDimensions.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,
25367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            BottomRow + Index - HelpBottomLine + 1,
25377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            &HelpBottomString[Index * BottomLineWidth]
25387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            );
25397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
25407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
25417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
25427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Reset this flag every time we finish using it.
25437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
25447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Repaint = FALSE;
25457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      NewLine = FALSE;
25467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
25477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfPrepareToReadKey:
25497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfReadKey;
25507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ScreenOperation = UiNoOperation;
25517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
25527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfReadKey:
25547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfScreenOperation;
25557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
25577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Wait for user's selection
25587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
25597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      while (TRUE) {
25607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
25617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (!EFI_ERROR (Status)) {
25627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          EventType = UIEventKey;
25637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
25647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
25657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
25677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // If we encounter error, continue to read another key in.
25687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
25697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (Status != EFI_NOT_READY) {
25707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          continue;
25717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
25727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        EventType = UiWaitForEvent(gST->ConIn->WaitForKey);
25747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (EventType == UIEventKey) {
25757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
25767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
25777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
25787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
25797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (EventType == UIEventDriver) {
25817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        gUserInput->Action = BROWSER_ACTION_NONE;
25827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ControlFlag = CfExit;
25837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
25847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
25857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (EventType == UIEventTimeOut) {
25877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        gUserInput->Action = BROWSER_ACTION_FORM_EXIT;
25887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ControlFlag = CfExit;
25897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
25907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
25917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      switch (Key.UnicodeChar) {
25937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case CHAR_CARRIAGE_RETURN:
25947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if(MenuOption == NULL || MenuOption->GrayOut || MenuOption->ReadOnly) {
25957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfReadKey;
25967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
25977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
25987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
25997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ScreenOperation = UiSelect;
26007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        gDirection      = 0;
26017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
26027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
26047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // We will push the adjustment of these numeric values directly to the input handler
26057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //  NOTE: we won't handle manual input numeric
26067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
26077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case '+':
26087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case '-':
26097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
26107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // If the screen has no menu items, and the user didn't select UiReset
26117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // ignore the selection and go back to reading keys.
26127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
261305de47ef04864cd9d55228b2065d7397387e54acEric Dong        ASSERT(MenuOption != NULL);
26147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {
26157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfReadKey;
26167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
26177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
26187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Statement = MenuOption->ThisTag;
26207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)
26217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)
26227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          || ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (GetFieldFromNum(Statement->OpCode) != 0))
26237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ){
26247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (Key.UnicodeChar == '+') {
26257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gDirection = SCAN_RIGHT;
26267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          } else {
26277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            gDirection = SCAN_LEFT;
26287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
26297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);
26317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (OptionString != NULL) {
26327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            FreePool (OptionString);
26337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
26347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (EFI_ERROR (Status)) {
26357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            //
26367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            // Repaint to clear possible error prompt pop-up
26377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            //
26387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            Repaint = TRUE;
26397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            NewLine = TRUE;
26407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          } else {
26417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            ControlFlag = CfExit;
26427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
26437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
26447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
26457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case '^':
26477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ScreenOperation = UiUp;
26487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
26497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case 'V':
26517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case 'v':
26527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ScreenOperation = UiDown;
26537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
26547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case ' ':
26567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if(IsListEmpty (&gMenuOption)) {
26577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfReadKey;
26587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
26597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
26607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ASSERT(MenuOption != NULL);
26627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {
26637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ScreenOperation = UiSelect;
26647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
26657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
26667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case 'D':
26687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case 'd':
26697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (!MultiHelpPage) {
26707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfReadKey;
26717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
26727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
26737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ControlFlag    = CfUpdateHelpString;
26747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        HelpPageIndex  = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;
26757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
26767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case 'U':
26787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case 'u':
26797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (!MultiHelpPage) {
26807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfReadKey;
26817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
26827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
26837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ControlFlag    = CfUpdateHelpString;
26847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        HelpPageIndex  = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;
26857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
26867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case CHAR_NULL:
26887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        for (Index = 0; Index < mScanCodeNumber; Index++) {
26897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
26907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
26917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            break;
26927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
26937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
26947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
26957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {
26967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
26977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // ModalForm has no ESC key and Hot Key.
26987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
26997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfReadKey;
27007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        } else if (Index == mScanCodeNumber) {
27017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
27027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // Check whether Key matches the registered hot key.
27037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
27047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          HotKey = NULL;
27057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          HotKey = GetHotKeyFromRegisterList (&Key);
27067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          if (HotKey != NULL) {
27077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            ScreenOperation = UiHotKey;
27087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          }
27097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
27107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
27117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
27127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
27137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfScreenOperation:
27158924aecd470f84968369982a69aa30acc7c387dfEric Dong      if ((ScreenOperation != UiReset) && (ScreenOperation != UiHotKey)) {
27167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
27178924aecd470f84968369982a69aa30acc7c387dfEric Dong        // If the screen has no menu items, and the user didn't select UiReset or UiHotKey
27187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // ignore the selection and go back to reading keys.
27197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
27207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (IsListEmpty (&gMenuOption)) {
27217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfReadKey;
27227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
27237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
27247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
27257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      for (Index = 0;
27277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong           Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
27287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong           Index++
27297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ) {
27307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
27317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
27327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
27337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
27347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
27357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
27367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiSelect:
27387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRepaint;
27397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ASSERT(MenuOption != NULL);
27417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Statement = MenuOption->ThisTag;
27427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
27437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
27447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
27457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      switch (Statement->OpCode->OpCode) {
27477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case EFI_IFR_REF_OP:
27487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case EFI_IFR_ACTION_OP:
27497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      case EFI_IFR_RESET_BUTTON_OP:
27507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ControlFlag = CfExit;
27517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
27527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      default:
27547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
27557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
27567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
27577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        RefreshKeyHelp (gFormData, Statement, TRUE);
27587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);
27597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (OptionString != NULL) {
27617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          FreePool (OptionString);
27627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
27637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (EFI_ERROR (Status)) {
27657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          Repaint = TRUE;
27667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          NewLine = TRUE;
27677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          RefreshKeyHelp (gFormData, Statement, FALSE);
27687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
27697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        } else {
27707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ControlFlag = CfExit;
27717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          break;
27727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
27737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
27747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
27757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiReset:
27777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
27787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // We come here when someone press ESC
27797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // If the policy is not exit front page when user press ESC, process here.
27807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
27817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (!FormExitPolicy()) {
27827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Repaint     = TRUE;
27837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        NewLine     = TRUE;
27847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        ControlFlag = CfRepaint;
27857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        break;
27867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
27877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
27897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // When user press ESC, it will try to show another menu, should clean the gSequence info.
27907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
27917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (gSequence != 0) {
27927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        gSequence = 0;
27937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
27947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      gUserInput->Action = BROWSER_ACTION_FORM_EXIT;
27967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfExit;
27977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
27987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
27997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiHotKey:
28007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRepaint;
280105de47ef04864cd9d55228b2065d7397387e54acEric Dong
280205de47ef04864cd9d55228b2065d7397387e54acEric Dong      ASSERT (HotKey != NULL);
28037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      gUserInput->Action = HotKey->Action;
28047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfExit;
28057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
28067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
28077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiLeft:
28087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRepaint;
28097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ASSERT(MenuOption != NULL);
28107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
28117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (MenuOption->Sequence != 0) {
28127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
28137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // In the middle or tail of the Date/Time op-code set, go left.
28147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
28157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ASSERT(NewPos != NULL);
28167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          NewPos = NewPos->BackLink;
28177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
28187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
28197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
28207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
28217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiRight:
28227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRepaint;
28237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ASSERT(MenuOption != NULL);
28247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
28257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (MenuOption->Sequence != 2) {
28267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
28277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // In the middle or tail of the Date/Time op-code set, go left.
28287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
28297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          ASSERT(NewPos != NULL);
28307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          NewPos = NewPos->ForwardLink;
28317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
28327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
28337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
28347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
28357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiUp:
28367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRepaint;
2837ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NewLine     = TRUE;
28387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
28397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      SavedListEntry = NewPos;
28407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ASSERT(NewPos != NULL);
2841f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong
2842f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong      MenuOption = MENU_OPTION_FROM_LINK (NewPos);
2843f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong      ASSERT (MenuOption != NULL);
2844f0c5095b274b2b35867d5245119aa1aba0acc87eEric Dong
28457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
28467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Adjust Date/Time position before we advance forward.
28477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
28487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (TRUE, &NewPos);
28497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2850ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NewPos     = NewPos->BackLink;
2851ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
2852ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // Find next selectable menu or the first menu beyond current form.
2853ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
2854ab369468265cd29a90b385a6e950eda3da16636dEric Dong      Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow, FALSE);
2855ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (Difference < 0) {
2856ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
2857ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // We hit the begining MenuOption that can be focused
2858ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // so we simply scroll to the top.
2859ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
2860ab369468265cd29a90b385a6e950eda3da16636dEric Dong        Repaint     = TRUE;
2861ab369468265cd29a90b385a6e950eda3da16636dEric Dong        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {
2862ab369468265cd29a90b385a6e950eda3da16636dEric Dong          TopOfScreen = gMenuOption.ForwardLink;
2863ab369468265cd29a90b385a6e950eda3da16636dEric Dong          NewPos      = SavedListEntry;
2864ab369468265cd29a90b385a6e950eda3da16636dEric Dong          SkipValue = 0;
2865ab369468265cd29a90b385a6e950eda3da16636dEric Dong        } else {
28667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
2867ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // Scroll up to the last page when we have arrived at top page.
28687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
2869ab369468265cd29a90b385a6e950eda3da16636dEric Dong          TopOfScreen = FindTopOfScreenMenu (gMenuOption.BackLink, BottomRow - TopRow, &SkipValue);
2870ab369468265cd29a90b385a6e950eda3da16636dEric Dong          NewPos = gMenuOption.BackLink;
2871ab369468265cd29a90b385a6e950eda3da16636dEric Dong          MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow, TRUE);
2872ab369468265cd29a90b385a6e950eda3da16636dEric Dong        }
2873ab369468265cd29a90b385a6e950eda3da16636dEric Dong      } else {
2874ab369468265cd29a90b385a6e950eda3da16636dEric Dong        NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
2875ab369468265cd29a90b385a6e950eda3da16636dEric Dong
2876ab369468265cd29a90b385a6e950eda3da16636dEric Dong        if (MenuOption->Row < TopRow + Difference + NextMenuOption->Skip) {
28777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
28787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
28797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
28807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          TopOfScreen = NewPos;
28817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          Repaint     = TRUE;
2882ab369468265cd29a90b385a6e950eda3da16636dEric Dong          SkipValue   = 0;
28837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
28847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
28857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2886ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Check whether new highlight menu is selectable, if not, keep highlight on the old one.
28877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2888ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // BottomRow - TopRow + 1 means the total rows current forms supported.
2889ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu
2890ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // and new top menu. New top menu will all shows in next form, but last highlight menu
2891ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the
2892ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // last highlight menu.
2893ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
2894ab369468265cd29a90b385a6e950eda3da16636dEric Dong        if (!IsSelectable(NextMenuOption) && IsSelectable(MenuOption) &&
2895ab369468265cd29a90b385a6e950eda3da16636dEric Dong            (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {
2896ab369468265cd29a90b385a6e950eda3da16636dEric Dong          NewPos = SavedListEntry;
28976f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        }
28987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
28997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2900ab369468265cd29a90b385a6e950eda3da16636dEric Dong      UpdateStatusBar (INPUT_ERROR, FALSE);
29017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
29027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
2903ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
29047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
2905ab369468265cd29a90b385a6e950eda3da16636dEric Dong      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
2906ab369468265cd29a90b385a6e950eda3da16636dEric Dong      AdjustDateAndTimePosition (TRUE, &NewPos);
2907ab369468265cd29a90b385a6e950eda3da16636dEric Dong      break;
29087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2909ab369468265cd29a90b385a6e950eda3da16636dEric Dong    case CfUiPageUp:
29107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
2911ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // SkipValue means lines is skipped when show the top menu option.
29127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
2913ab369468265cd29a90b385a6e950eda3da16636dEric Dong      ControlFlag = CfRepaint;
2914ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NewLine     = TRUE;
2915ab369468265cd29a90b385a6e950eda3da16636dEric Dong      Repaint     = TRUE;
29167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
29177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Link      = TopOfScreen;
29187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // First minus the menu of the top screen, it's value is SkipValue.
29207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29212e7183ba91b90ac0a257a206080fe84849887cdcEric Dong      if (SkipValue >= BottomRow - TopRow + 1) {
29227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2923ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one
2924ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // form of options to be show, so just update the SkipValue to show the next
2925ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // parts of options.
29267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2927ab369468265cd29a90b385a6e950eda3da16636dEric Dong        SkipValue -= BottomRow - TopRow + 1;
2928ab369468265cd29a90b385a6e950eda3da16636dEric Dong        NewPos     = TopOfScreen;
2929ab369468265cd29a90b385a6e950eda3da16636dEric Dong        break;
2930ab369468265cd29a90b385a6e950eda3da16636dEric Dong      } else {
2931ab369468265cd29a90b385a6e950eda3da16636dEric Dong        Index     = (BottomRow + 1) - SkipValue - TopRow;
29327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
2933ab369468265cd29a90b385a6e950eda3da16636dEric Dong
2934ab369468265cd29a90b385a6e950eda3da16636dEric Dong      TopOfScreen = FindTopOfScreenMenu(TopOfScreen, Index, &SkipValue);
2935ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NewPos = TopOfScreen;
2936ab369468265cd29a90b385a6e950eda3da16636dEric Dong      MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE);
2937ab369468265cd29a90b385a6e950eda3da16636dEric Dong
2938ab369468265cd29a90b385a6e950eda3da16636dEric Dong      UpdateStatusBar (INPUT_ERROR, FALSE);
29397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
29407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
29427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Don't do this when we are already in the first page.
29437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
29457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (TRUE, &NewPos);
29467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
29477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
29487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiPageDown:
29497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // SkipValue means lines is skipped when show the top menu option.
29517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
2952ab369468265cd29a90b385a6e950eda3da16636dEric Dong      ControlFlag = CfRepaint;
2953ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NewLine     = TRUE;
2954ab369468265cd29a90b385a6e950eda3da16636dEric Dong      Repaint     = TRUE;
29557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
29567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Link    = TopOfScreen;
29577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      NextMenuOption = MENU_OPTION_FROM_LINK (Link);
29587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      Index = TopRow + NextMenuOption->Skip - SkipValue;
29597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Count to the menu option which will show at the top of the next form.
29617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {
29637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Link           = Link->ForwardLink;
29647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        NextMenuOption = MENU_OPTION_FROM_LINK (Link);
29657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Index = Index + NextMenuOption->Skip;
29667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
29677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
29687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {
29697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2970ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Highlight on the last menu which can be highlight.
29717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
29727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        Repaint = FALSE;
2973ab369468265cd29a90b385a6e950eda3da16636dEric Dong        MoveToNextStatement (TRUE, &Link, Index - TopRow, TRUE);
29747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      } else {
29757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
29767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // Calculate the skip line for top of screen menu.
29777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
29787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        if (Link == TopOfScreen) {
29797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
29807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          // The top of screen menu option occupies the entire form.
29817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
29827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          SkipValue += BottomRow - TopRow + 1;
29837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        } else {
29847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));
29857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
29867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        TopOfScreen = Link;
29877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        MenuOption = NULL;
29887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
29897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        // Move to the Next selectable menu.
29907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
2991ab369468265cd29a90b385a6e950eda3da16636dEric Dong        MoveToNextStatement (FALSE, &Link, BottomRow - TopRow, TRUE);
29927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
29937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
29947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Save the menu as the next highlight menu.
29967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
29977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      NewPos  = Link;
29987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
2999ab369468265cd29a90b385a6e950eda3da16636dEric Dong      UpdateStatusBar (INPUT_ERROR, FALSE);
3000ab369468265cd29a90b385a6e950eda3da16636dEric Dong
30017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
30027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
30037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Don't do this when we are already in the last page.
30047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
30057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
30067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (TRUE, &NewPos);
30077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
30087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
30097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiDown:
30107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
30117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // SkipValue means lines is skipped when show the top menu option.
30127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // NewPos  points to the menu which is highlighted now.
30137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
30147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRepaint;
3015ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NewLine     = TRUE;
30167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3017ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (NewPos == TopOfScreen) {
3018ab369468265cd29a90b385a6e950eda3da16636dEric Dong        Temp2 = SkipValue;
3019ab369468265cd29a90b385a6e950eda3da16636dEric Dong      } else {
3020ab369468265cd29a90b385a6e950eda3da16636dEric Dong        Temp2 = 0;
3021ab369468265cd29a90b385a6e950eda3da16636dEric Dong      }
3022ab369468265cd29a90b385a6e950eda3da16636dEric Dong
3023ab369468265cd29a90b385a6e950eda3da16636dEric Dong      SavedListEntry = NewPos;
30247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
30257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
30267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // to be one that progresses to the next set of op-codes, we need to advance to the last
30277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
30287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // checking can be done.  The only other logic we need to introduce is that if a Date/Time
30297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // op-code is the last entry in the menu, we need to rewind back to the first op-code of
30307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // the Date/Time op-code.
30317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
30327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (FALSE, &NewPos);
30337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3034ab369468265cd29a90b385a6e950eda3da16636dEric Dong      MenuOption = MENU_OPTION_FROM_LINK (NewPos);
3035ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NewPos     = NewPos->ForwardLink;
3036ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3037ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // Find the next selectable menu.
3038ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3039ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) {
3040ab369468265cd29a90b385a6e950eda3da16636dEric Dong        if (gMenuOption.ForwardLink == NewPos || &gMenuOption == NewPos) {
3041ab369468265cd29a90b385a6e950eda3da16636dEric Dong          Difference = -1;
3042ab369468265cd29a90b385a6e950eda3da16636dEric Dong        } else {
3043ab369468265cd29a90b385a6e950eda3da16636dEric Dong          Difference = 0;
3044ab369468265cd29a90b385a6e950eda3da16636dEric Dong        }
3045ab369468265cd29a90b385a6e950eda3da16636dEric Dong      } else {
3046ab369468265cd29a90b385a6e950eda3da16636dEric Dong        Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE);
3047ab369468265cd29a90b385a6e950eda3da16636dEric Dong      }
3048ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (Difference < 0) {
3049ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
3050ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Scroll to the first page.
3051ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
3052ab369468265cd29a90b385a6e950eda3da16636dEric Dong        if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {
3053ab369468265cd29a90b385a6e950eda3da16636dEric Dong          TopOfScreen = gMenuOption.ForwardLink;
3054ab369468265cd29a90b385a6e950eda3da16636dEric Dong          Repaint     = TRUE;
3055ab369468265cd29a90b385a6e950eda3da16636dEric Dong          MenuOption  = NULL;
30566f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        } else {
3057ab369468265cd29a90b385a6e950eda3da16636dEric Dong          MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
30586f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong        }
3059ab369468265cd29a90b385a6e950eda3da16636dEric Dong        NewPos        = gMenuOption.ForwardLink;
3060ab369468265cd29a90b385a6e950eda3da16636dEric Dong        MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, TRUE);
30616f05c02325fff475d695edacd0b0b003e5b1fcf3Eric Dong
3062ab369468265cd29a90b385a6e950eda3da16636dEric Dong        SkipValue = 0;
3063ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
3064ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
3065ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
3066ab369468265cd29a90b385a6e950eda3da16636dEric Dong        AdjustDateAndTimePosition (TRUE, &TopOfScreen);
3067ab369468265cd29a90b385a6e950eda3da16636dEric Dong        AdjustDateAndTimePosition (TRUE, &NewPos);
3068ab369468265cd29a90b385a6e950eda3da16636dEric Dong        break;
3069ab369468265cd29a90b385a6e950eda3da16636dEric Dong      }
30707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3071ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3072ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // Get next selected menu info.
3073ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3074ab369468265cd29a90b385a6e950eda3da16636dEric Dong      AdjustDateAndTimePosition (FALSE, &NewPos);
3075ab369468265cd29a90b385a6e950eda3da16636dEric Dong      NextMenuOption  = MENU_OPTION_FROM_LINK (NewPos);
3076ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (NextMenuOption->Row == 0) {
3077ab369468265cd29a90b385a6e950eda3da16636dEric Dong        UpdateOptionSkipLines (NextMenuOption);
3078ab369468265cd29a90b385a6e950eda3da16636dEric Dong      }
3079ab369468265cd29a90b385a6e950eda3da16636dEric Dong
3080ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3081ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // Calculate new highlight menu end row.
3082ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3083ab369468265cd29a90b385a6e950eda3da16636dEric Dong      Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1;
3084ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (Temp > BottomRow) {
30857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
3086ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Get the top screen menu info.
30877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
3088ab369468265cd29a90b385a6e950eda3da16636dEric Dong        AdjustDateAndTimePosition (FALSE, &TopOfScreen);
3089ab369468265cd29a90b385a6e950eda3da16636dEric Dong        SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
3090ab369468265cd29a90b385a6e950eda3da16636dEric Dong
3091ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
3092ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows.
3093ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows.
3094ab369468265cd29a90b385a6e950eda3da16636dEric Dong        //
3095ab369468265cd29a90b385a6e950eda3da16636dEric Dong        if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {
30967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
3097ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // Skip the top op-code
30987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
3099ab369468265cd29a90b385a6e950eda3da16636dEric Dong          TopOfScreen   = TopOfScreen->ForwardLink;
3100ab369468265cd29a90b385a6e950eda3da16636dEric Dong          DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);
31017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3102ab369468265cd29a90b385a6e950eda3da16636dEric Dong          SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
31037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3104ab369468265cd29a90b385a6e950eda3da16636dEric Dong          //
3105ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // If we have a remainder, skip that many more op-codes until we drain the remainder
3106ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // Special case is the selected highlight menu has more than one form of menus.
3107ab369468265cd29a90b385a6e950eda3da16636dEric Dong          //
3108ab369468265cd29a90b385a6e950eda3da16636dEric Dong          while (DistanceValue >= SavedMenuOption->Skip && TopOfScreen != NewPos) {
31097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            //
3110ab369468265cd29a90b385a6e950eda3da16636dEric Dong            // Since the Difference is greater than or equal to this op-code's skip value, skip it
31117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            //
3112ab369468265cd29a90b385a6e950eda3da16636dEric Dong            DistanceValue   = DistanceValue - (INTN) SavedMenuOption->Skip;
3113ab369468265cd29a90b385a6e950eda3da16636dEric Dong            TopOfScreen     = TopOfScreen->ForwardLink;
31147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong            SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
3115ab369468265cd29a90b385a6e950eda3da16636dEric Dong          }
31167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
3117ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // Since we will act on this op-code in the next routine, and increment the
3118ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // SkipValue, set the skips to one less than what is required.
31197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
3120ab369468265cd29a90b385a6e950eda3da16636dEric Dong          if (TopOfScreen != NewPos) {
3121ab369468265cd29a90b385a6e950eda3da16636dEric Dong            SkipValue = DistanceValue;
3122ab369468265cd29a90b385a6e950eda3da16636dEric Dong          } else {
3123ab369468265cd29a90b385a6e950eda3da16636dEric Dong            SkipValue = 0;
3124ab369468265cd29a90b385a6e950eda3da16636dEric Dong          }
31257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        } else {
31267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
3127ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // Since we will act on this op-code in the next routine, and increment the
3128ab369468265cd29a90b385a6e950eda3da16636dEric Dong          // SkipValue, set the skips to one less than what is required.
31297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong          //
3130ab369468265cd29a90b385a6e950eda3da16636dEric Dong          SkipValue += Temp - BottomRow;
31317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        }
3132ab369468265cd29a90b385a6e950eda3da16636dEric Dong        Repaint       = TRUE;
3133ab369468265cd29a90b385a6e950eda3da16636dEric Dong      } else if (!IsSelectable (NextMenuOption)) {
31347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
3135ab369468265cd29a90b385a6e950eda3da16636dEric Dong        // Continue to go down until scroll to next page or the selectable option is found.
31367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        //
3137ab369468265cd29a90b385a6e950eda3da16636dEric Dong        ScreenOperation = UiDown;
3138ab369468265cd29a90b385a6e950eda3da16636dEric Dong        ControlFlag     = CfScreenOperation;
3139ab369468265cd29a90b385a6e950eda3da16636dEric Dong        break;
3140ab369468265cd29a90b385a6e950eda3da16636dEric Dong      }
3141ab369468265cd29a90b385a6e950eda3da16636dEric Dong
3142ab369468265cd29a90b385a6e950eda3da16636dEric Dong      MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
3143ab369468265cd29a90b385a6e950eda3da16636dEric Dong
3144ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3145ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // Check whether new highlight menu is selectable, if not, keep highlight on the old one.
3146ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3147ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // BottomRow - TopRow + 1 means the total rows current forms supported.
3148ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu
3149ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // and new top menu. New top menu will all shows in next form, but last highlight menu
3150ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the
3151ab369468265cd29a90b385a6e950eda3da16636dEric Dong      // last highlight menu.
3152ab369468265cd29a90b385a6e950eda3da16636dEric Dong      //
3153ab369468265cd29a90b385a6e950eda3da16636dEric Dong      if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) &&
3154ab369468265cd29a90b385a6e950eda3da16636dEric Dong         (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {
3155ab369468265cd29a90b385a6e950eda3da16636dEric Dong        NewPos = SavedListEntry;
31567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
31577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3158ab369468265cd29a90b385a6e950eda3da16636dEric Dong      UpdateStatusBar (INPUT_ERROR, FALSE);
3159ab369468265cd29a90b385a6e950eda3da16636dEric Dong
31607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
31617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
31627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      //
31637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (TRUE, &TopOfScreen);
31647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      AdjustDateAndTimePosition (TRUE, &NewPos);
31657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
31667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
31677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfUiNoOperation:
31687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ControlFlag = CfRepaint;
31697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
31707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
31717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case CfExit:
31725a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
31737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (HelpString != NULL) {
31747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        FreePool (HelpString);
31757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
31767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (HelpHeaderString != NULL) {
31777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        FreePool (HelpHeaderString);
31787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
31797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      if (HelpBottomString != NULL) {
31807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong        FreePool (HelpBottomString);
31817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      }
31827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      return EFI_SUCCESS;
31837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
31847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    default:
31857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
31867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
31877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
31887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
31897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
31907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
31917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
31927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Base on the browser status info to show an pop up message.
31937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
31947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
31957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongVOID
31967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongBrowserStatusProcess (
31977c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  VOID
31987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
31997c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
32007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  CHAR16         *ErrorInfo;
32017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_INPUT_KEY  Key;
32027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (gFormData->BrowserStatus == BROWSER_SUCCESS) {
32047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return;
32057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
32067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (gFormData->ErrorString != NULL) {
32087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    ErrorInfo = gFormData->ErrorString;
32097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } else {
32107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    switch (gFormData->BrowserStatus) {
32117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case BROWSER_SUBMIT_FAIL:
32127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ErrorInfo = gSaveFailed;
32137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
32147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case BROWSER_NO_SUBMIT_IF:
32167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ErrorInfo = gNoSubmitIf;
32177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
32187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case BROWSER_FORM_NOT_FOUND:
32207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ErrorInfo = gFormNotFound;
32217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
32227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case BROWSER_FORM_SUPPRESS:
32247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ErrorInfo = gFormSuppress;
32257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
32267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    case BROWSER_PROTOCOL_NOT_FOUND:
32287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ErrorInfo = gProtocolNotFound;
32297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
32307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    default:
32327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      ErrorInfo = gBrwoserError;
32337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong      break;
32347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    }
32357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
32367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
32387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Error occur, prompt error message.
32397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
32407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  do {
32417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);
32427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
32437c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
32447c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32457c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
32467c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Display one form, and return user input.
32477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param FormData                Form Data to be shown.
32497c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param UserInputData           User input data.
32507c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32517c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval EFI_SUCCESS            1.Form Data is shown, and user input is got.
32527c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                                 2.Error info has show and return.
32537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval EFI_INVALID_PARAMETER  The input screen dimension is not valid
32547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval EFI_NOT_FOUND          New form data has some error.
32557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
32567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_STATUS
32577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFIAPI
32587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongFormDisplay (
32597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN  FORM_DISPLAY_ENGINE_FORM  *FormData,
32607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  OUT USER_INPUT                *UserInputData
32617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
32627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
32637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STATUS  Status;
32647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT (FormData != NULL);
32667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (FormData == NULL) {
32677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return EFI_INVALID_PARAMETER;
32687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
32697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gUserInput = UserInputData;
32717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gFormData  = FormData;
32727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
32747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Process the status info first.
32757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
32767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  BrowserStatusProcess();
32777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (UserInputData == NULL) {
32787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
32797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // UserInputData == NULL, means only need to print the error info, return here.
32807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
32817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return EFI_SUCCESS;
32827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
32837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ConvertStatementToMenu();
32857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Status = DisplayPageFrame (FormData, &gStatementDimensions);
32877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (EFI_ERROR (Status)) {
32887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    return Status;
32897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
32907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
32915a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  //
32925a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  // Check whether layout is changed.
32935a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  //
32945a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  if (mIsFirstForm
32955a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong      || (gOldFormEntry.HiiHandle != FormData->HiiHandle)
32965a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong      || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))
32975a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong      || (gOldFormEntry.FormId != FormData->FormId)) {
32987c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    mStatementLayoutIsChanged = TRUE;
32995a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  } else {
33005a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong    mStatementLayoutIsChanged = FALSE;
33017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
33027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Status = UiDisplayMenu(FormData);
33045a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong
33055a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  //
33065a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  // Backup last form info.
33075a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  //
33085a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  mIsFirstForm            = FALSE;
33095a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  gOldFormEntry.HiiHandle = FormData->HiiHandle;
33105a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid);
33115a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  gOldFormEntry.FormId    = FormData->FormId;
33127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return Status;
33147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
33157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
33175a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  Clear Screen to the initial state.
33185a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong**/
33195a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongVOID
33205a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongEFIAPI
33215a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongDriverClearDisplayPage (
33225a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  VOID
33235a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  )
33245a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong{
33255a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  ClearDisplayPage ();
33265a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  mIsFirstForm = TRUE;
33275a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong}
33285a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong
33295a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong/**
33305a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  Set Buffer to Value for Size bytes.
33315a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong
33325a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  @param  Buffer                 Memory to set.
33335a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  @param  Size                   Number of bytes to set
33345a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  @param  Value                  Value of the set operation.
33355a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong
33365a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong**/
33375a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongVOID
33385a9f73bf065eda6b830445dc907e778f4a13d8d7Eric DongSetUnicodeMem (
33395a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  IN VOID   *Buffer,
33405a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  IN UINTN  Size,
33415a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  IN CHAR16 Value
33425a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  )
33435a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong{
33445a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  CHAR16  *Ptr;
33455a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong
33465a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  Ptr = Buffer;
33475a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  while ((Size--)  != 0) {
33485a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong    *(Ptr++) = Value;
33495a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  }
33505a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong}
33515a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong
33525a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong/**
33537c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Initialize Setup Browser driver.
33547c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33557c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param ImageHandle     The image handle.
33567c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param SystemTable     The system table.
33577c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33587c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval EFI_SUCCESS    The Setup Browser module is initialized correctly..
33597c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @return Other value if failed to initialize the Setup Browser module.
33607c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33617c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
33627c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_STATUS
33637c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFIAPI
33647c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongInitializeDisplayEngine (
33657c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN EFI_HANDLE           ImageHandle,
33667c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN EFI_SYSTEM_TABLE     *SystemTable
33677c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
33687c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
33697c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STATUS                          Status;
33707c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_INPUT_KEY                       HotKey;
33717c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EFI_STRING                          NewString;
33727c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;
33737c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33747c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
33757c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Publish our HII data
33767c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
33777c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  gHiiHandle = HiiAddPackages (
33787c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                 &gDisplayEngineGuid,
33797c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                 ImageHandle,
33807c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                 DisplayEngineStrings,
33817c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                 NULL
33827c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                 );
33837c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT (gHiiHandle != NULL);
33847c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33857c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
33867c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Install Form Display protocol
33877c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
33887c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Status = gBS->InstallProtocolInterface (
33897c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                  &mPrivateData.Handle,
33907c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                  &gEdkiiFormDisplayEngineProtocolGuid,
33917c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                  EFI_NATIVE_INTERFACE,
33927c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                  &mPrivateData.FromDisplayProt
33937c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong                  );
33947c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  ASSERT_EFI_ERROR (Status);
33957c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
33967c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  InitializeDisplayStrings();
33975a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong
33985a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));
33995a9f73bf065eda6b830445dc907e778f4a13d8d7Eric Dong  ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));
34007c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34017c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
34027c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  // Use BrowserEx2 protocol to register HotKey.
34037c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  //
34047c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);
34057c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  if (!EFI_ERROR (Status)) {
34067c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
34077c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    // Register the default HotKey F9 and F10 again.
34087c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    //
34097c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    HotKey.UnicodeChar = CHAR_NULL;
34107c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    HotKey.ScanCode   = SCAN_F10;
34117c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    NewString         = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
34127c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    ASSERT (NewString != NULL);
34137c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
34147c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34157c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    HotKey.ScanCode   = SCAN_F9;
34167c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    NewString         = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
34177c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    ASSERT (NewString != NULL);
34187c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong    FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
34197c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  }
34207c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34217c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return EFI_SUCCESS;
34227c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
34237c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34247c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong/**
34257c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  This is the default unload handle for display core drivers.
34267c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34277c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @param[in]  ImageHandle       The drivers' driver image.
34287c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34297c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval EFI_SUCCESS           The image is unloaded.
34307c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  @retval Others                Failed to unload the image.
34317c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34327c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong**/
34337c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFI_STATUS
34347c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongEFIAPI
34357c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric DongUnloadDisplayEngine (
34367c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  IN EFI_HANDLE             ImageHandle
34377c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  )
34387c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong{
34397c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  HiiRemovePackages(gHiiHandle);
34407c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
34417c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  FreeDisplayStrings ();
34427c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong
3443336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  if (gHighligthMenuInfo.OpCode != NULL) {
3444336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong    FreePool (gHighligthMenuInfo.OpCode);
3445336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong  }
3446336c8e116b3e2e11dccdac163d0a85fc3c58fd3dEric Dong
34477c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong  return EFI_SUCCESS;
34487c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1Eric Dong}
3449