X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FDisplayEngineDxe%2FFormDisplay.c;h=3b034a1c82688700601910d5a4fff8a55677f535;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hp=d265a25ec921100d642ee8dbd4c6ac1213f635fa;hpb=72f2eca287ec08dcc32adbf1bb6756b5b97b6f34;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c index d265a25ec9..3b034a1c82 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c @@ -1,14 +1,9 @@ /** @file Entry and initialization module for the browser. -Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -48,7 +43,7 @@ SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = { } }; -UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); +UINTN mScanCodeNumber = ARRAY_SIZE (gScanCodeToOperation); SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { { @@ -86,7 +81,7 @@ SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { { UiPageDown, CfUiPageDown - }, + }, { UiHotKey, CfUiHotKey @@ -97,8 +92,7 @@ EFI_GUID gDisplayEngineGuid = { 0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62} }; -FORM_ENTRY_INFO gFormEntryInfo; -UINTN gSequence; +BOOLEAN gMisMatch; EFI_SCREEN_DESCRIPTOR gStatementDimensions; BOOLEAN mStatementLayoutIsChanged = TRUE; USER_INPUT *gUserInput; @@ -113,10 +107,20 @@ FORM_ENTRY_INFO gOldFormEntry = {0}; // // Browser Global Strings // +CHAR16 *gReconnectConfirmChanges; +CHAR16 *gReconnectFail; +CHAR16 *gReconnectRequired; +CHAR16 *gChangesOpt; CHAR16 *gFormNotFound; CHAR16 *gNoSubmitIf; -CHAR16 *gBrwoserError; +CHAR16 *gBrowserError; CHAR16 *gSaveFailed; +CHAR16 *gNoSubmitIfFailed; +CHAR16 *gSaveProcess; +CHAR16 *gSaveNoSubmitProcess; +CHAR16 *gDiscardChange; +CHAR16 *gJumpToFormSet; +CHAR16 *gCheckError; CHAR16 *gPromptForData; CHAR16 *gPromptForPassword; CHAR16 *gPromptForNewPassword; @@ -129,7 +133,30 @@ CHAR16 *gMiniString; CHAR16 *gOptionMismatch; CHAR16 *gFormSuppress; CHAR16 *gProtocolNotFound; - +CHAR16 *gConfirmDefaultMsg; +CHAR16 *gConfirmSubmitMsg; +CHAR16 *gConfirmDiscardMsg; +CHAR16 *gConfirmResetMsg; +CHAR16 *gConfirmExitMsg; +CHAR16 *gConfirmSubmitMsg2nd; +CHAR16 *gConfirmDefaultMsg2nd; +CHAR16 *gConfirmResetMsg2nd; +CHAR16 *gConfirmExitMsg2nd; +CHAR16 *gConfirmOpt; +CHAR16 *gConfirmOptYes; +CHAR16 *gConfirmOptNo; +CHAR16 *gConfirmOptOk; +CHAR16 *gConfirmOptCancel; +CHAR16 *gYesOption; +CHAR16 *gNoOption; +CHAR16 *gOkOption; +CHAR16 *gCancelOption; +CHAR16 *gErrorPopup; +CHAR16 *gWarningPopup; +CHAR16 *gInfoPopup; +CHAR16 *gConfirmMsgConnect; +CHAR16 *gConfirmMsgEnd; +CHAR16 *gPasswordUnsupported; CHAR16 gModalSkipColumn; CHAR16 gPromptBlockWidth; CHAR16 gOptionBlockWidth; @@ -143,6 +170,10 @@ FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData = { FormDisplay, DriverClearDisplayPage, ConfirmDataChange + }, + { + EFI_HII_POPUP_PROTOCOL_REVISION, + CreatePopup } }; @@ -184,8 +215,18 @@ InitializeDisplayStrings ( VOID ) { + gReconnectConfirmChanges = GetToken (STRING_TOKEN (RECONNECT_CONFIRM_CHANGES), gHiiHandle); mUnknownString = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle); gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle); + gNoSubmitIfFailed = GetToken (STRING_TOKEN (NO_SUBMIT_IF_CHECK_FAILED), gHiiHandle); + gReconnectFail = GetToken (STRING_TOKEN (RECONNECT_FAILED), gHiiHandle); + gReconnectRequired = GetToken (STRING_TOKEN (RECONNECT_REQUIRED), gHiiHandle); + gChangesOpt = GetToken (STRING_TOKEN (RECONNECT_CHANGES_OPTIONS), gHiiHandle); + gSaveProcess = GetToken (STRING_TOKEN (DISCARD_OR_JUMP), gHiiHandle); + gSaveNoSubmitProcess = GetToken (STRING_TOKEN (DISCARD_OR_CHECK), gHiiHandle); + gDiscardChange = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_DISCARD), gHiiHandle); + gJumpToFormSet = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_JUMP), gHiiHandle); + gCheckError = GetToken (STRING_TOKEN (DISCARD_OR_CHECK_CHECK), gHiiHandle); gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle); gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle); gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle); @@ -200,7 +241,31 @@ InitializeDisplayStrings ( gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle); gFormNotFound = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle); gNoSubmitIf = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle); - gBrwoserError = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle); + gBrowserError = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle); + gConfirmDefaultMsg = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE), gHiiHandle); + gConfirmDiscardMsg = GetToken (STRING_TOKEN (CONFIRM_DISCARD_MESSAGE), gHiiHandle); + gConfirmSubmitMsg = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE), gHiiHandle); + gConfirmResetMsg = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE), gHiiHandle); + gConfirmExitMsg = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE), gHiiHandle); + gConfirmDefaultMsg2nd = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE_2ND), gHiiHandle); + gConfirmSubmitMsg2nd = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE_2ND), gHiiHandle); + gConfirmResetMsg2nd = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE_2ND), gHiiHandle); + gConfirmExitMsg2nd = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE_2ND), gHiiHandle); + gConfirmOpt = GetToken (STRING_TOKEN (CONFIRM_OPTION), gHiiHandle); + gConfirmOptYes = GetToken (STRING_TOKEN (CONFIRM_OPTION_YES), gHiiHandle); + gConfirmOptNo = GetToken (STRING_TOKEN (CONFIRM_OPTION_NO), gHiiHandle); + gConfirmOptOk = GetToken (STRING_TOKEN (CONFIRM_OPTION_OK), gHiiHandle); + gConfirmOptCancel = GetToken (STRING_TOKEN (CONFIRM_OPTION_CANCEL), gHiiHandle); + gYesOption = GetToken (STRING_TOKEN (YES_SELECTABLE_OPTION), gHiiHandle); + gNoOption = GetToken (STRING_TOKEN (NO_SELECTABLE_OPTION), gHiiHandle); + gOkOption = GetToken (STRING_TOKEN (OK_SELECTABLE_OPTION), gHiiHandle); + gCancelOption = GetToken (STRING_TOKEN (CANCEL_SELECTABLE_OPTION), gHiiHandle); + gErrorPopup = GetToken (STRING_TOKEN (ERROR_POPUP_STRING), gHiiHandle); + gWarningPopup = GetToken (STRING_TOKEN (WARNING_POPUP_STRING), gHiiHandle); + gInfoPopup = GetToken (STRING_TOKEN (INFO_POPUP_STRING), gHiiHandle); + gConfirmMsgConnect = GetToken (STRING_TOKEN (CONFIRM_OPTION_CONNECT), gHiiHandle); + gConfirmMsgEnd = GetToken (STRING_TOKEN (CONFIRM_OPTION_END), gHiiHandle); + gPasswordUnsupported = GetToken (STRING_TOKEN (PASSWORD_NOT_SUPPORTED ), gHiiHandle); } /** @@ -216,6 +281,16 @@ FreeDisplayStrings ( FreePool (mUnknownString); FreePool (gEmptyString); FreePool (gSaveFailed); + FreePool (gNoSubmitIfFailed); + FreePool (gReconnectFail); + FreePool (gReconnectRequired); + FreePool (gChangesOpt); + FreePool (gReconnectConfirmChanges); + FreePool (gSaveProcess); + FreePool (gSaveNoSubmitProcess); + FreePool (gDiscardChange); + FreePool (gJumpToFormSet); + FreePool (gCheckError); FreePool (gPromptForData); FreePool (gPromptForPassword); FreePool (gPromptForNewPassword); @@ -227,9 +302,33 @@ FreeDisplayStrings ( FreePool (gOptionMismatch); FreePool (gFormSuppress); FreePool (gProtocolNotFound); - FreePool (gBrwoserError); + FreePool (gBrowserError); FreePool (gNoSubmitIf); FreePool (gFormNotFound); + FreePool (gConfirmDefaultMsg); + FreePool (gConfirmSubmitMsg); + FreePool (gConfirmDiscardMsg); + FreePool (gConfirmResetMsg); + FreePool (gConfirmExitMsg); + FreePool (gConfirmDefaultMsg2nd); + FreePool (gConfirmSubmitMsg2nd); + FreePool (gConfirmResetMsg2nd); + FreePool (gConfirmExitMsg2nd); + FreePool (gConfirmOpt); + FreePool (gConfirmOptYes); + FreePool (gConfirmOptNo); + FreePool (gConfirmOptOk); + FreePool (gConfirmOptCancel); + FreePool (gYesOption); + FreePool (gNoOption); + FreePool (gOkOption); + FreePool (gCancelOption); + FreePool (gErrorPopup); + FreePool (gWarningPopup); + FreePool (gInfoPopup); + FreePool (gConfirmMsgConnect); + FreePool (gConfirmMsgEnd); + FreePool (gPasswordUnsupported); } /** @@ -259,7 +358,7 @@ GetPrompt ( /** Get the supported width for a particular op-code - @param Statement The curent statement. + @param MenuOption The menu option. @param AdjustWidth The width which is saved for the space. @return Returns the number of CHAR16 characters that is support. @@ -267,13 +366,17 @@ GetPrompt ( **/ UINT16 GetWidth ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - OUT UINT16 *AdjustWidth + IN UI_MENU_OPTION *MenuOption, + OUT UINT16 *AdjustWidth ) { - CHAR16 *String; - UINTN Size; - EFI_IFR_TEXT *TestOp; + CHAR16 *String; + UINTN Size; + EFI_IFR_TEXT *TestOp; + UINT16 ReturnWidth; + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + + Statement = MenuOption->ThisTag; // // For modal form, clean the entire row. @@ -309,23 +412,33 @@ GetWidth ( // ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0)) ) { - + // // Return the space width. - // + // if (AdjustWidth != NULL) { *AdjustWidth = 2; } // // Keep consistent with current behavior. // - return (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2); + ReturnWidth = (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2); + } else { + if (AdjustWidth != NULL) { + *AdjustWidth = 1; + } + + ReturnWidth = (UINT16) (gPromptBlockWidth - 1); } - if (AdjustWidth != NULL) { - *AdjustWidth = 1; + // + // For nest in statement, should the subtitle indent. + // + if (MenuOption->NestInStatement) { + ReturnWidth -= SUBTITLE_INDENT; } - return (UINT16) (gPromptBlockWidth - 1); + + return ReturnWidth; } /** @@ -343,7 +456,7 @@ GetWidth ( @param Index Where in InputString to start the copy process @param OutputString Buffer to copy the string into - @return Returns the number of CHAR16 characters that were copied into the OutputString + @return Returns the number of CHAR16 characters that were copied into the OutputString buffer, include extra glyph info and '\0' info. **/ @@ -422,7 +535,7 @@ GetLineByWidth ( if (ReturnFlag) { break; } - } + } // // Rewind the string from the maximum size until we see a space to break the line @@ -452,7 +565,7 @@ GetLineByWidth ( // // Need extra glyph info and '\0' info, so +2. // - *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16))); + *OutputString = AllocateZeroPool ((StrOffset + 2) * sizeof(CHAR16)); if (*OutputString == NULL) { return 0; } @@ -471,7 +584,7 @@ GetLineByWidth ( if (InputString[*Index + StrOffset] == CHAR_SPACE) { // // Skip the space info at the begin of next line. - // + // *Index = (UINT16) (*Index + StrOffset + 1); } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) { // @@ -485,7 +598,7 @@ GetLineByWidth ( } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) { // // Skip the /r or /r/n info. - // + // if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) { *Index = (UINT16) (*Index + StrOffset + 2); } else { @@ -519,7 +632,6 @@ UiAddMenuOption ( UI_MENU_OPTION *MenuOption; UINTN Index; UINTN Count; - CHAR16 *String; UINT16 NumberOfLines; UINT16 GlyphWidth; UINT16 Width; @@ -536,27 +648,7 @@ UiAddMenuOption ( PromptId = GetPrompt (Statement->OpCode); ASSERT (PromptId != 0); - String = GetToken (PromptId, gFormData->HiiHandle); - ASSERT (String != NULL); - - Width = GetWidth (Statement, NULL); - for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) { - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&String[ArrayEntry]) != 0) { - NumberOfLines++; - } - FreePool (OutputString); - } - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - // - // Add three MenuOptions for Date/Time - // Data format : [01/02/2004] [11:22:33] - // Line number : 0 0 1 0 0 1 - // - NumberOfLines = 0; Count = 3; } @@ -565,20 +657,12 @@ UiAddMenuOption ( ASSERT (MenuOption); MenuOption->Signature = UI_MENU_OPTION_SIGNATURE; - MenuOption->Description = String; + MenuOption->Description = GetToken (PromptId, gFormData->HiiHandle); MenuOption->Handle = gFormData->HiiHandle; MenuOption->ThisTag = Statement; MenuOption->NestInStatement = NestIn; MenuOption->EntryNumber = *MenuItemCount; - if (Index == 2) { - // - // Override LineNumber for the MenuOption in Date/Time sequence - // - MenuOption->Skip = 1; - } else { - MenuOption->Skip = NumberOfLines; - } MenuOption->Sequence = Index; if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) { @@ -615,7 +699,7 @@ UiAddMenuOption ( case EFI_IFR_TEXT_OP: if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) { // - // Initializing GrayOut option as TRUE for Text setup options + // Initializing GrayOut option as TRUE for Text setup options // so that those options will be Gray in colour and un selectable. // MenuOption->GrayOut = TRUE; @@ -633,6 +717,37 @@ UiAddMenuOption ( } } + if (Index == 0 && + (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) && + (Statement->OpCode->OpCode != EFI_IFR_TIME_OP)) { + Width = GetWidth (MenuOption, NULL); + for (; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) { + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&MenuOption->Description[ArrayEntry]) != 0) { + NumberOfLines++; + } + FreePool (OutputString); + } + } else { + // + // Add three MenuOptions for Date/Time + // Data format : [01/02/2004] [11:22:33] + // Line number : 0 0 1 0 0 1 + // + NumberOfLines = 0; + } + + if (Index == 2) { + // + // Override LineNumber for the MenuOption in Date/Time sequence + // + MenuOption->Skip = 1; + } else { + MenuOption->Skip = NumberOfLines; + } + InsertTailList (&gMenuOption, &MenuOption->Link); } @@ -679,6 +794,13 @@ ConvertStatementToMenu ( NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink); NestLink = GetNextNode (&Statement->NestStatementList, NestLink); + // + // Skip the opcode not recognized by Display core. + // + if (NestStatement->OpCode->OpCode == EFI_IFR_GUID_OP) { + continue; + } + UiAddMenuOption (NestStatement, &MenuItemCount, TRUE); } } @@ -780,7 +902,7 @@ UpdateSkipInfoForMenu ( CHAR16 *OutputString; UINT16 GlyphWidth; - Width = (UINT16) gOptionBlockWidth; + Width = (UINT16) gOptionBlockWidth - 1; GlyphWidth = 1; Row = 1; @@ -792,8 +914,8 @@ UpdateSkipInfoForMenu ( FreePool (OutputString); } - if ((Row > MenuOption->Skip) && - (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) && + if ((Row > MenuOption->Skip) && + (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) && (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP)) { MenuOption->Skip = Row; } @@ -832,6 +954,54 @@ UpdateOptionSkipLines ( } } +/** + Check whether this Menu Option could be print. + + Check Prompt string, option string or text two string not NULL. + + This is an internal function. + + @param MenuOption The MenuOption to be checked. + + @retval TRUE This Menu Option is printable. + @retval FALSE This Menu Option could not be printable. + +**/ +BOOLEAN +PrintableMenu ( + UI_MENU_OPTION *MenuOption + ) +{ + EFI_STATUS Status; + EFI_STRING OptionString; + + OptionString = NULL; + + if (MenuOption->Description[0] != '\0') { + return TRUE; + } + + Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE); + if (EFI_ERROR (Status)) { + return FALSE; + } + if (OptionString != NULL && OptionString[0] != '\0') { + FreePool (OptionString); + return TRUE; + } + + if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) { + OptionString = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle); + ASSERT (OptionString != NULL); + if (OptionString[0] != '\0'){ + FreePool (OptionString); + return TRUE; + } + } + + return FALSE; +} + /** Check whether this Menu Option could be highlighted. @@ -849,7 +1019,7 @@ IsSelectable ( ) { if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) || - MenuOption->GrayOut || MenuOption->ReadOnly) { + MenuOption->GrayOut || MenuOption->ReadOnly || !PrintableMenu (MenuOption)) { return FALSE; } else { return TRUE; @@ -864,19 +1034,24 @@ IsSelectable ( @param GoUp The navigation direction. TRUE: up, FALSE: down. @param CurrentPosition Current position. @param GapToTop Gap position to top or bottom. + @param FindInForm Whether find menu in current form or beyond. @return The row distance from current MenuOption to next selectable MenuOption. @retval -1 Reach the begin of the menu, still can't find the selectable menu. - @retval Value Find the selectable menu, maybe the truly selectable, maybe the l - last menu showing at current form. + @retval Value Find the selectable menu, maybe the truly selectable, maybe the + first menu showing beyond current form or last menu showing in + current form. + The value is the line number between the new selected menu and the + current select menu, not include the new selected menu. **/ INTN MoveToNextStatement ( IN BOOLEAN GoUp, IN OUT LIST_ENTRY **CurrentPosition, - IN UINTN GapToTop + IN UINTN GapToTop, + IN BOOLEAN FindInForm ) { INTN Distance; @@ -886,6 +1061,11 @@ MoveToNextStatement ( Distance = 0; Pos = *CurrentPosition; + + if (Pos == &gMenuOption) { + return -1; + } + PreMenuOption = MENU_OPTION_FROM_LINK (Pos); while (TRUE) { @@ -897,28 +1077,27 @@ MoveToNextStatement ( if (NextMenuOption->Row == 0) { UpdateOptionSkipLines (NextMenuOption); } - - if (GoUp && (PreMenuOption != NextMenuOption)) { - // - // In this case, still can't find the selectable menu, - // return the last one in the showing form. - // - if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) { + + // + // Check whether the menu is beyond current showing form, + // return the first one beyond the showing form. + // + if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) { + if (FindInForm) { NextMenuOption = PreMenuOption; - break; } - - // - // Current Position doesn't need to be caculated when go up. - // Caculate distanct at first when go up - // - Distance += NextMenuOption->Skip; + break; } + // + // return the selectable menu in the showing form. + // if (IsSelectable (NextMenuOption)) { break; } + Distance += NextMenuOption->Skip; + // // Arrive at begin of the menu list. // @@ -927,21 +1106,8 @@ MoveToNextStatement ( break; } - if (!GoUp) { - // - // In this case, still can't find the selectable menu, - // return the last one in the showing form. - // - if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) { - NextMenuOption = PreMenuOption; - break; - } - - Distance += NextMenuOption->Skip; - } - - PreMenuOption = NextMenuOption; Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink); + PreMenuOption = NextMenuOption; } *CurrentPosition = &NextMenuOption->Link; @@ -954,10 +1120,10 @@ MoveToNextStatement ( @param MenuOption Menu option point to date/time. @param OptionString Option string input for process. - @param AddOptCol Whether need to update MenuOption->OptCol. + @param AddOptCol Whether need to update MenuOption->OptCol. **/ -VOID +VOID ProcessStringForDateTime ( UI_MENU_OPTION *MenuOption, CHAR16 *OptionString, @@ -971,7 +1137,7 @@ ProcessStringForDateTime ( EFI_IFR_TIME *Time; ASSERT (MenuOption != NULL && OptionString != NULL); - + Statement = MenuOption->ThisTag; Date = NULL; Time = NULL; @@ -980,7 +1146,7 @@ ProcessStringForDateTime ( } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { Time = (EFI_IFR_TIME *) Statement->OpCode; } - + // // If leading spaces on OptionString - remove the spaces // @@ -992,13 +1158,13 @@ ProcessStringForDateTime ( MenuOption->OptCol++; } } - + for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { OptionString[Count] = OptionString[Index]; Count++; } OptionString[Count] = CHAR_NULL; - + // // Enable to suppress field in the opcode base on the flag. // @@ -1010,21 +1176,21 @@ ProcessStringForDateTime ( // if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) { // - // At this point, only "<**:" in the optionstring. + // At this point, only "<**:" in the optionstring. // Clean the day's ** field, after clean, the format is "< :" // SetUnicodeMem (&OptionString[1], 2, L' '); } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) { // - // At this point, only "**:" in the optionstring. + // At this point, only "**:" in the optionstring. // Clean the month's "**" field, after clean, the format is " :" - // + // SetUnicodeMem (&OptionString[0], 2, L' '); } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) { // - // At this point, only "****>" in the optionstring. + // At this point, only "****>" in the optionstring. // Clean the year's "****" field, after clean, the format is " >" - // + // SetUnicodeMem (&OptionString[0], 4, L' '); } } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { @@ -1035,21 +1201,21 @@ ProcessStringForDateTime ( // if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) { // - // At this point, only "<**:" in the optionstring. + // At this point, only "<**:" in the optionstring. // Clean the hour's ** field, after clean, the format is "< :" // SetUnicodeMem (&OptionString[1], 2, L' '); } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) { // - // At this point, only "**:" in the optionstring. + // At this point, only "**:" in the optionstring. // Clean the minute's "**" field, after clean, the format is " :" - // + // SetUnicodeMem (&OptionString[0], 2, L' '); } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) { // - // At this point, only "**>" in the optionstring. + // At this point, only "**>" in the optionstring. // Clean the second's "**" field, after clean, the format is " >" - // + // SetUnicodeMem (&OptionString[0], 2, L' '); } } @@ -1132,7 +1298,7 @@ AdjustDateAndTimePosition ( /** Get step info from numeric opcode. - + @param[in] OpCode The input numeric op code. @return step info for this opcode. @@ -1146,24 +1312,24 @@ GetFieldFromNum ( UINT64 Step; NumericOp = (EFI_IFR_NUMERIC *) OpCode; - + switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) { case EFI_IFR_NUMERIC_SIZE_1: Step = NumericOp->data.u8.Step; break; - + case EFI_IFR_NUMERIC_SIZE_2: Step = NumericOp->data.u16.Step; break; - + case EFI_IFR_NUMERIC_SIZE_4: Step = NumericOp->data.u32.Step; break; - + case EFI_IFR_NUMERIC_SIZE_8: Step = NumericOp->data.u64.Step; break; - + default: Step = 0; break; @@ -1174,7 +1340,7 @@ GetFieldFromNum ( /** Find the registered HotKey based on KeyData. - + @param[in] KeyData A pointer to a buffer that describes the keystroke information for the hot key. @@ -1191,14 +1357,14 @@ GetHotKeyFromRegisterList ( Link = GetFirstNode (&gFormData->HotKeyListHead); while (!IsNull (&gFormData->HotKeyListHead, Link)) { HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); - + if (HotKey->KeyData->ScanCode == KeyData->ScanCode) { return HotKey; } Link = GetNextNode (&gFormData->HotKeyListHead, Link); } - + return NULL; } @@ -1268,13 +1434,13 @@ UiWaitForEvent ( Timeout ); } - + WaitList[0] = Event; EventNum = 1; if (gFormData->FormRefreshEvent != NULL) { WaitList[EventNum] = gFormData->FormRefreshEvent; EventNum ++; - } + } if (Timeout != 0) { WaitList[EventNum] = TimerEvent; @@ -1307,7 +1473,7 @@ UiWaitForEvent ( if (Timeout != 0) { gBS->CloseEvent (TimerEvent); } - + return EventType; } @@ -1335,198 +1501,604 @@ GetQuestionIdInfo ( return QuestionHeader->QuestionId; } + /** - Find the first menu which will be show at the top. + Find the top of screen menu base on the current menu. - @param FormData The data info for this form. - @param TopOfScreen The link_entry pointer to top menu. - @param HighlightMenu The menu which will be highlight. - @param SkipValue The skip value for the top menu. + @param CurPos Current input menu. + @param Rows Totol screen rows. + @param SkipValue SkipValue for this new form. + + @retval TopOfScreen Top of screen menu for the new form. **/ -VOID -FindTopMenu ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - OUT LIST_ENTRY **TopOfScreen, - OUT LIST_ENTRY **HighlightMenu, - OUT INTN *SkipValue +LIST_ENTRY * +FindTopOfScreenMenu ( + IN LIST_ENTRY *CurPos, + IN UINTN Rows, + OUT UINTN *SkipValue ) { - LIST_ENTRY *Link; - LIST_ENTRY *NewPos; - UINTN TopRow; - UINTN BottomRow; - UINTN Index; - UI_MENU_OPTION *SavedMenuOption; - UINTN EndRow; + LIST_ENTRY *Link; + LIST_ENTRY *TopOfScreen; + UI_MENU_OPTION *PreviousMenuOption; - TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; - BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT; + Link = CurPos; + PreviousMenuOption = NULL; - // - // If not has input highlight statement, just return the first one in this form. - // - if (FormData->HighLightedStatement == NULL) { - *TopOfScreen = gMenuOption.ForwardLink; - *HighlightMenu = gMenuOption.ForwardLink; - if (!IsListEmpty (&gMenuOption)) { - MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow); + while (Link->BackLink != &gMenuOption) { + Link = Link->BackLink; + PreviousMenuOption = MENU_OPTION_FROM_LINK (Link); + if (PreviousMenuOption->Row == 0) { + UpdateOptionSkipLines (PreviousMenuOption); } - *SkipValue = 0; - return; - } - - // - // Now base on the input highlight menu to find the top menu in this page. - // Will base on the highlight menu show at the bottom to find the top menu. - // - NewPos = gMenuOption.ForwardLink; - SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); - - while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) || - (SavedMenuOption->Sequence != gSequence)) { - NewPos = NewPos->ForwardLink; - if (NewPos == &gMenuOption) { - // - // Not Found it, break - // + if (Rows <= PreviousMenuOption->Skip) { break; } - SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); - } - ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement); - - *HighlightMenu = NewPos; - - AdjustDateAndTimePosition(FALSE, &NewPos); - SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); - UpdateOptionSkipLines (SavedMenuOption); - - // - // If highlight opcode is date/time, keep the highlight row info not change. - // - if ((SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) && - (gHighligthMenuInfo.QuestionId != 0) && - (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode))) { - // - // Still show the highlight menu before exit from display engine. - // - EndRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip; - } else { - EndRow = BottomRow; - } - - // - // Base on the selected menu will show at the bottome of next page, - // select the menu show at the top of the next page. - // - Link = NewPos; - for (Index = TopRow + SavedMenuOption->Skip; Index <= EndRow; ) { - Link = Link->BackLink; - // - // Already find the first menu in this form, means highlight menu - // will show in first page of this form. - // - if (Link == &gMenuOption) { - *TopOfScreen = gMenuOption.ForwardLink; - *SkipValue = 0; - return; - } - SavedMenuOption = MENU_OPTION_FROM_LINK (Link); - UpdateOptionSkipLines (SavedMenuOption); - Index += SavedMenuOption->Skip; + Rows = Rows - PreviousMenuOption->Skip; } - // - // Found the menu which will show at the top of the page. - // - if (Link == NewPos) { - // - // The menu can show more than one pages, just show the menu at the top of the page. - // - *SkipValue = 0; - *TopOfScreen = Link; - } else { - // - // Check whether need to skip some line for menu shows at the top of the page. - // - *SkipValue = Index - EndRow; - if (*SkipValue > 0 && *SkipValue < (INTN) SavedMenuOption->Skip) { - *TopOfScreen = Link; + if (Link->BackLink == &gMenuOption) { + TopOfScreen = gMenuOption.ForwardLink; + if (PreviousMenuOption != NULL && Rows < PreviousMenuOption->Skip) { + *SkipValue = PreviousMenuOption->Skip - Rows; } else { - *SkipValue = 0; - *TopOfScreen = Link->ForwardLink; + *SkipValue = 0; } + } else { + TopOfScreen = Link; + *SkipValue = PreviousMenuOption->Skip - Rows; } + + return TopOfScreen; } /** - Update highlight menu info. + Get the index info for this opcode. + + @param OpCode The input opcode for the statement. - @param MenuOption The menu opton which is highlight. + @retval The index of this statement. **/ -VOID -UpdateHighlightMenuInfo ( - IN UI_MENU_OPTION *MenuOption +UINTN +GetIndexInfoForOpcode ( + IN EFI_IFR_OP_HEADER *OpCode ) { - FORM_DISPLAY_ENGINE_STATEMENT *Statement; + LIST_ENTRY *NewPos; + UI_MENU_OPTION *MenuOption; + UINTN Index; - // - // This is the current selected statement - // - Statement = MenuOption->ThisTag; + NewPos = gMenuOption.ForwardLink; + Index = 0; - // - // Get the highlight statement. - // - gUserInput->SelectedStatement = Statement; - gSequence = (UINT16) MenuOption->Sequence; + for (NewPos = gMenuOption.ForwardLink; NewPos != &gMenuOption; NewPos = NewPos->ForwardLink){ + MenuOption = MENU_OPTION_FROM_LINK (NewPos); - // - // Record highlight row info for date/time opcode. - // - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode); - gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row; - } else { - gHighligthMenuInfo.QuestionId = 0; - gHighligthMenuInfo.DisplayRow = 0; + if (CompareMem (MenuOption->ThisTag->OpCode, OpCode, OpCode->Length) == 0) { + if (MenuOption->ThisTag->OpCode == OpCode) { + return Index; + } + + Index ++; + } } - RefreshKeyHelp(gFormData, Statement, FALSE); + return Index; } /** - Update attribut for this menu. + Is this the saved highlight statement. - @param MenuOption The menu opton which this attribut used to. - @param Highlight Whether this menu will be highlight. + @param HighLightedStatement The input highlight statement. + + @retval TRUE This is the highlight statement. + @retval FALSE This is not the highlight statement. **/ -VOID -SetDisplayAttribute ( - IN UI_MENU_OPTION *MenuOption, - IN BOOLEAN Highlight +BOOLEAN +IsSavedHighlightStatement ( + IN FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement ) { - FORM_DISPLAY_ENGINE_STATEMENT *Statement; - - Statement = MenuOption->ThisTag; - - if (Highlight) { - gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); - return; - } - - if (MenuOption->GrayOut) { - gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ()); - } else { - if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) { - gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ()); + if ((gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) && + (gFormData->FormId == gHighligthMenuInfo.FormId)) { + if (gHighligthMenuInfo.HLTQuestionId != 0) { + return (BOOLEAN) (gHighligthMenuInfo.HLTQuestionId == GetQuestionIdInfo (HighLightedStatement->OpCode)); } else { - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); + if (CompareMem (gHighligthMenuInfo.HLTOpCode, HighLightedStatement->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) { + if (gHighligthMenuInfo.HLTIndex == 0 || gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode(HighLightedStatement->OpCode)) { + return TRUE; + } else { + return FALSE; + } + } + } + } + + return FALSE; +} + +/** + Is this the highlight menu. + + @param MenuOption The input Menu option. + + @retval TRUE This is the highlight menu option. + @retval FALSE This is not the highlight menu option. + +**/ +BOOLEAN +IsHighLightMenuOption ( + IN UI_MENU_OPTION *MenuOption + ) +{ + if (gHighligthMenuInfo.HLTQuestionId != 0) { + if (GetQuestionIdInfo(MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.HLTQuestionId) { + return (BOOLEAN) (MenuOption->Sequence == gHighligthMenuInfo.HLTSequence); + } + } else { + if(CompareMem (gHighligthMenuInfo.HLTOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) { + if (gHighligthMenuInfo.HLTIndex == 0 || gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode(MenuOption->ThisTag->OpCode)) { + return (BOOLEAN) (MenuOption->Sequence == gHighligthMenuInfo.HLTSequence); + } else { + return FALSE; + } + } + } + + return FALSE; +} + +/** + Find the highlight menu. + + If the input is NULL, base on the record highlight info in + gHighligthMenuInfo to find the last highlight menu. + + @param HighLightedStatement The input highlight statement. + + @retval The highlight menu index. + +**/ +LIST_ENTRY * +FindHighLightMenuOption ( + IN FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement + ) +{ + LIST_ENTRY *NewPos; + UI_MENU_OPTION *MenuOption; + + NewPos = gMenuOption.ForwardLink; + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + + if (HighLightedStatement != NULL) { + while (MenuOption->ThisTag != HighLightedStatement) { + NewPos = NewPos->ForwardLink; + if (NewPos == &gMenuOption) { + // + // Not Found it, break + // + break; + } + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + } + + // + // Must find the highlight statement. + // + ASSERT (NewPos != &gMenuOption); + + } else { + while (!IsHighLightMenuOption (MenuOption)) { + NewPos = NewPos->ForwardLink; + if (NewPos == &gMenuOption) { + // + // Not Found it, break + // + break; + } + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + } + + // + // Highlight statement has disappear (suppressed/disableed) + // + if (NewPos == &gMenuOption) { + NewPos = NULL; + } + } + + return NewPos; +} + +/** + Is this the Top of screen menu. + + @param MenuOption The input Menu option. + + @retval TRUE This is the Top of screen menu option. + @retval FALSE This is not the Top of screen menu option. + +**/ +BOOLEAN +IsTopOfScreeMenuOption ( + IN UI_MENU_OPTION *MenuOption + ) +{ + if (gHighligthMenuInfo.TOSQuestionId != 0) { + return (BOOLEAN) (GetQuestionIdInfo(MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.TOSQuestionId); + } + + if(CompareMem (gHighligthMenuInfo.TOSOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.TOSOpCode->Length) == 0) { + if (gHighligthMenuInfo.TOSIndex == 0 || gHighligthMenuInfo.TOSIndex == GetIndexInfoForOpcode(MenuOption->ThisTag->OpCode)) { + return TRUE; + } else { + return FALSE; + } + } + + return FALSE; +} + +/** + Calculate the distance between two menus and include the skip value of StartMenu. + + @param StartMenu The link_entry pointer to start menu. + @param EndMenu The link_entry pointer to end menu. + +**/ +UINTN +GetDistanceBetweenMenus( + IN LIST_ENTRY *StartMenu, + IN LIST_ENTRY *EndMenu +) +{ + LIST_ENTRY *Link; + UI_MENU_OPTION *MenuOption; + UINTN Distance; + + Distance = 0; + + Link = StartMenu; + while (Link != EndMenu) { + MenuOption = MENU_OPTION_FROM_LINK (Link); + if (MenuOption->Row == 0) { + UpdateOptionSkipLines (MenuOption); + } + Distance += MenuOption->Skip; + Link = Link->BackLink; + } + return Distance; +} + +/** + Find the top of screen menu base on the previous record menu info. + + @param HighLightMenu The link_entry pointer to highlight menu. + + @retval Return the the link_entry pointer top of screen menu. + +**/ +LIST_ENTRY * +FindTopOfScreenMenuOption ( + IN LIST_ENTRY *HighLightMenu + ) +{ + LIST_ENTRY *NewPos; + UI_MENU_OPTION *MenuOption; + UINTN TopRow; + UINTN BottomRow; + + TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; + BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT; + + NewPos = gMenuOption.ForwardLink; + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + + while (!IsTopOfScreeMenuOption(MenuOption)) { + NewPos = NewPos->ForwardLink; + if (NewPos == &gMenuOption) { + // + // Not Found it, break + // + break; + } + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + } + + // + // Last time top of screen menu has disappeared. + // + if (NewPos == &gMenuOption) { + return NULL; + } + // + // Check whether highlight menu and top of screen menu can be shown within one page, + // if can't, return NULL to re-calcaulate the top of scrren menu. Because some new menus + // may be dynamically inserted between highlightmenu and previous top of screen menu, + // So previous record top of screen menu is not appropriate for current display. + // + if (GetDistanceBetweenMenus (HighLightMenu, NewPos) + 1 > BottomRow - TopRow) { + return NULL; + } + + return NewPos; +} + +/** + Find the first menu which will be show at the top. + + @param FormData The data info for this form. + @param TopOfScreen The link_entry pointer to top menu. + @param HighlightMenu The menu which will be highlight. + @param SkipValue The skip value for the top menu. + +**/ +VOID +FindTopMenu ( + IN FORM_DISPLAY_ENGINE_FORM *FormData, + OUT LIST_ENTRY **TopOfScreen, + OUT LIST_ENTRY **HighlightMenu, + OUT UINTN *SkipValue + ) +{ + UINTN TopRow; + UINTN BottomRow; + UI_MENU_OPTION *MenuOption; + UINTN TmpValue; + + TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; + BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT; + // + // When option mismatch happens,there exist two cases,one is reenter the form, just like the if case below, + // and the other is exit current form and enter last form, it can be covered by the else case. + // + if (gMisMatch && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle && gFormData->FormId == gHighligthMenuInfo.FormId) { + // + // Reenter caused by option mismatch or auto exit caused by refresh form(refresh interval/guid), + // base on the record highlight info to find the highlight menu. + // + + *HighlightMenu = FindHighLightMenuOption(NULL); + if (*HighlightMenu != NULL) { + // + // Update skip info for this highlight menu. + // + MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu); + UpdateOptionSkipLines (MenuOption); + + // + // Found the last time highlight menu. + // + *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu); + if (*TopOfScreen != NULL) { + // + // Found the last time selectable top of screen menu. + // + AdjustDateAndTimePosition(TRUE, TopOfScreen); + MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen); + UpdateOptionSkipLines (MenuOption); + + *SkipValue = gHighligthMenuInfo.SkipValue; + } else { + // + // Not found last time top of screen menu, so base on current highlight menu + // to find the new top of screen menu. + // Make the current highlight menu at the bottom of the form to calculate the + // top of screen menu. + // + if (MenuOption->Skip >= BottomRow - TopRow) { + *TopOfScreen = *HighlightMenu; + TmpValue = 0; + } else { + *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue); + } + + *SkipValue = TmpValue; + } + } else { + // + // Last time highlight menu has disappear, find the first highlightable menu as the default one. + // + *HighlightMenu = gMenuOption.ForwardLink; + if (!IsListEmpty (&gMenuOption)) { + MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE); + } + *TopOfScreen = gMenuOption.ForwardLink; + *SkipValue = 0; + } + + } else if (FormData->HighLightedStatement != NULL) { + if (IsSavedHighlightStatement (FormData->HighLightedStatement)) { + // + // Input highlight menu is same as last time highlight menu. + // Base on last time highlight menu to set the top of screen menu and highlight menu. + // + *HighlightMenu = FindHighLightMenuOption(NULL); + ASSERT (*HighlightMenu != NULL); + + // + // Update skip info for this highlight menu. + // + MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu); + UpdateOptionSkipLines (MenuOption); + + *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu); + if (*TopOfScreen == NULL) { + // + // Not found last time top of screen menu, so base on current highlight menu + // to find the new top of screen menu. + // Make the current highlight menu at the bottom of the form to calculate the + // top of screen menu. + // + if (MenuOption->Skip >= BottomRow - TopRow) { + *TopOfScreen = *HighlightMenu; + TmpValue = 0; + } else { + *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue); + } + + *SkipValue = TmpValue; + } else { + AdjustDateAndTimePosition(TRUE, TopOfScreen); + MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen); + UpdateOptionSkipLines (MenuOption); + + *SkipValue = gHighligthMenuInfo.SkipValue; + } + AdjustDateAndTimePosition(TRUE, TopOfScreen); + } else { + // + // Input highlight menu is not save as last time highlight menu. + // + *HighlightMenu = FindHighLightMenuOption(FormData->HighLightedStatement); + MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu); + UpdateOptionSkipLines (MenuOption); + + // + // Make the current highlight menu at the bottom of the form to calculate the + // top of screen menu. + // + if (MenuOption->Skip >= BottomRow - TopRow) { + *TopOfScreen = *HighlightMenu; + TmpValue = 0; + } else { + *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue); + } + + *SkipValue = TmpValue; + } + AdjustDateAndTimePosition(TRUE, TopOfScreen); + } else { + // + // If not has input highlight statement, just return the first one in this form. + // + *TopOfScreen = gMenuOption.ForwardLink; + *HighlightMenu = gMenuOption.ForwardLink; + if (!IsListEmpty (&gMenuOption)) { + MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE); + } + *SkipValue = 0; + } + + gMisMatch = FALSE; + + // + // First enter to show the menu, update highlight info. + // + UpdateHighlightMenuInfo (*HighlightMenu, *TopOfScreen, *SkipValue); +} + +/** + Record the highlight menu and top of screen menu info. + + @param Highlight The menu opton which is highlight. + @param TopOfScreen The menu opton which is at the top of the form. + @param SkipValue The skip line info for the top of screen menu. + +**/ +VOID +UpdateHighlightMenuInfo ( + IN LIST_ENTRY *Highlight, + IN LIST_ENTRY *TopOfScreen, + IN UINTN SkipValue + ) +{ + UI_MENU_OPTION *MenuOption; + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + + gHighligthMenuInfo.HiiHandle = gFormData->HiiHandle; + gHighligthMenuInfo.FormId = gFormData->FormId; + gHighligthMenuInfo.SkipValue = (UINT16)SkipValue; + + if (!IsListEmpty (&gMenuOption)) { + MenuOption = MENU_OPTION_FROM_LINK (Highlight); + Statement = MenuOption->ThisTag; + + gUserInput->SelectedStatement = Statement; + + gHighligthMenuInfo.HLTSequence = MenuOption->Sequence; + gHighligthMenuInfo.HLTQuestionId = GetQuestionIdInfo(Statement->OpCode); + if (gHighligthMenuInfo.HLTQuestionId == 0) { + // + // if question id == 0, save the opcode buffer.. + // + if (gHighligthMenuInfo.HLTOpCode != NULL) { + FreePool (gHighligthMenuInfo.HLTOpCode); + } + gHighligthMenuInfo.HLTOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode); + ASSERT (gHighligthMenuInfo.HLTOpCode != NULL); + + gHighligthMenuInfo.HLTIndex = GetIndexInfoForOpcode(Statement->OpCode); + } + + MenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); + Statement = MenuOption->ThisTag; + + gHighligthMenuInfo.TOSQuestionId = GetQuestionIdInfo(Statement->OpCode); + if (gHighligthMenuInfo.TOSQuestionId == 0) { + // + // if question id == 0, save the opcode buffer.. + // + if (gHighligthMenuInfo.TOSOpCode != NULL) { + FreePool (gHighligthMenuInfo.TOSOpCode); + } + gHighligthMenuInfo.TOSOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode); + ASSERT (gHighligthMenuInfo.TOSOpCode != NULL); + + gHighligthMenuInfo.TOSIndex = GetIndexInfoForOpcode(Statement->OpCode); + } + } else { + gUserInput->SelectedStatement = NULL; + + gHighligthMenuInfo.HLTSequence = 0; + gHighligthMenuInfo.HLTQuestionId = 0; + if (gHighligthMenuInfo.HLTOpCode != NULL) { + FreePool (gHighligthMenuInfo.HLTOpCode); + } + gHighligthMenuInfo.HLTOpCode = NULL; + gHighligthMenuInfo.HLTIndex = 0; + + gHighligthMenuInfo.TOSQuestionId = 0; + if (gHighligthMenuInfo.TOSOpCode != NULL) { + FreePool (gHighligthMenuInfo.TOSOpCode); + } + gHighligthMenuInfo.TOSOpCode = NULL; + gHighligthMenuInfo.TOSIndex = 0; + } +} + +/** + Update attribut for this menu. + + @param MenuOption The menu opton which this attribut used to. + @param Highlight Whether this menu will be highlight. + +**/ +VOID +SetDisplayAttribute ( + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Highlight + ) +{ + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + + Statement = MenuOption->ThisTag; + + if (Highlight) { + gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); + return; + } + + if (MenuOption->GrayOut) { + gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ()); + } else { + if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) { + gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ()); + } else { + gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); } } } @@ -1562,11 +2134,11 @@ DisplayMenuString ( PrintStringAtWithWidth (Col, Row, String, Width); return; } - + // // Print the highlight menu string. // First print the highlight string. - // + // SetDisplayAttribute(MenuOption, TRUE); Length = PrintStringAt (Col, Row, String); @@ -1586,7 +2158,7 @@ DisplayMenuString ( @retval FALSE This menu option can't have option string. **/ -BOOLEAN +BOOLEAN HasOptionString ( IN UI_MENU_OPTION *MenuOption ) @@ -1628,6 +2200,149 @@ HasOptionString ( return TRUE; } +/** + Double confirm with user about the action. + + @param Action The user input action. + + @retval TRUE User confirm with the input or not need user confirm. + @retval FALSE User want ignore this input. + +**/ +BOOLEAN +FxConfirmPopup ( + IN UINT32 Action + ) +{ + EFI_INPUT_KEY Key; + CHAR16 *CfmStr; + UINTN CfmStrLen; + UINT32 CheckFlags; + BOOLEAN RetVal; + UINTN CatLen; + UINTN MaxLen; + + CfmStrLen = 0; + CatLen = StrLen (gConfirmMsgConnect); + + // + // Below action need extra popup dialog to confirm. + // + CheckFlags = BROWSER_ACTION_DISCARD | + BROWSER_ACTION_DEFAULT | + BROWSER_ACTION_SUBMIT | + BROWSER_ACTION_RESET | + BROWSER_ACTION_EXIT; + + // + // Not need to confirm with user, just return TRUE. + // + if ((Action & CheckFlags) == 0) { + return TRUE; + } + + if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) { + CfmStrLen += StrLen (gConfirmDiscardMsg); + } + + if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { + if (CfmStrLen != 0) { + CfmStrLen += CatLen; + } + + CfmStrLen += StrLen (gConfirmDefaultMsg); + } + + if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { + if (CfmStrLen != 0) { + CfmStrLen += CatLen; + } + + CfmStrLen += StrLen (gConfirmSubmitMsg); + } + + if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) { + if (CfmStrLen != 0) { + CfmStrLen += CatLen; + } + + CfmStrLen += StrLen (gConfirmResetMsg); + } + + if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) { + if (CfmStrLen != 0) { + CfmStrLen += CatLen; + } + + CfmStrLen += StrLen (gConfirmExitMsg); + } + + // + // Allocate buffer to save the string. + // String + "?" + "\0" + // + MaxLen = CfmStrLen + 1 + 1; + CfmStr = AllocateZeroPool (MaxLen * sizeof (CHAR16)); + ASSERT (CfmStr != NULL); + + if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) { + StrCpyS (CfmStr, MaxLen, gConfirmDiscardMsg); + } + + if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { + if (CfmStr[0] != 0) { + StrCatS (CfmStr, MaxLen, gConfirmMsgConnect); + StrCatS (CfmStr, MaxLen, gConfirmDefaultMsg2nd); + } else { + StrCpyS (CfmStr, MaxLen, gConfirmDefaultMsg); + } + } + + if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { + if (CfmStr[0] != 0) { + StrCatS (CfmStr, MaxLen, gConfirmMsgConnect); + StrCatS (CfmStr, MaxLen, gConfirmSubmitMsg2nd); + } else { + StrCpyS (CfmStr, MaxLen, gConfirmSubmitMsg); + } + } + + if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) { + if (CfmStr[0] != 0) { + StrCatS (CfmStr, MaxLen, gConfirmMsgConnect); + StrCatS (CfmStr, MaxLen, gConfirmResetMsg2nd); + } else { + StrCpyS (CfmStr, MaxLen, gConfirmResetMsg); + } + } + + if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) { + if (CfmStr[0] != 0) { + StrCatS (CfmStr, MaxLen, gConfirmMsgConnect); + StrCatS (CfmStr, MaxLen, gConfirmExitMsg2nd); + } else { + StrCpyS (CfmStr, MaxLen, gConfirmExitMsg); + } + } + + StrCatS (CfmStr, MaxLen, gConfirmMsgEnd); + + do { + CreateDialog (&Key, gEmptyString, CfmStr, gConfirmOpt, gEmptyString, NULL); + } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptNo[0] | UPPER_LOWER_CASE_OFFSET)) && + (Key.ScanCode != SCAN_ESC)); + + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) { + RetVal = TRUE; + } else { + RetVal = FALSE; + } + + FreePool (CfmStr); + + return RetVal; +} /** Print string for this menu option. @@ -1635,9 +2350,10 @@ HasOptionString ( @param MenuOption The menu opton which this attribut used to. @param SkipWidth The skip width between the left to the start of the prompt. @param BeginCol The begin column for one menu. - @param SkipLine The skip line for this menu. + @param SkipLine The skip line for this menu. @param BottomRow The bottom row for this form. @param Highlight Whether this menu will be highlight. + @param UpdateCol Whether need to update the column info for Date/Time. @retval EFI_SUCESSS Process the user selection success. @@ -1649,7 +2365,8 @@ DisplayOneMenu ( IN UINTN BeginCol, IN UINTN SkipLine, IN UINTN BottomRow, - IN BOOLEAN Highlight + IN BOOLEAN Highlight, + IN BOOLEAN UpdateCol ) { FORM_DISPLAY_ENGINE_STATEMENT *Statement; @@ -1665,6 +2382,7 @@ DisplayOneMenu ( UINTN Temp3; EFI_STATUS Status; UINTN Row; + BOOLEAN IsProcessingFirstRow; UINTN Col; UINTN PromptLineNum; UINTN OptionLineNum; @@ -1679,6 +2397,7 @@ DisplayOneMenu ( PromptLineNum = 0; OptionLineNum = 0; MaxRow = 0; + IsProcessingFirstRow = TRUE; // // Set default color. @@ -1698,14 +2417,14 @@ DisplayOneMenu ( // // Adjust option string for date/time opcode. // - ProcessStringForDateTime(MenuOption, OptionString, TRUE); + ProcessStringForDateTime(MenuOption, OptionString, UpdateCol); } - + Width = (UINT16) gOptionBlockWidth - 1; Row = MenuOption->Row; GlyphWidth = 1; OptionLineNum = 0; - + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if (((Temp2 == 0)) && (Row <= BottomRow)) { if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { @@ -1723,15 +2442,16 @@ DisplayOneMenu ( } else { // // For date/ time, print the first and second past (year for date and second for time) - // - DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString), Highlight); + // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string, + // so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it. + DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString) - 1, Highlight); } } else { DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight); } OptionLineNum++; } - + // // If there is more string to process print on the next row and increment the Skip value // @@ -1750,13 +2470,13 @@ DisplayOneMenu ( } } } - + FreePool (OutputString); if (Temp2 != 0) { Temp2--; } } - + Highlight = FALSE; FreePool (OptionString); @@ -1765,7 +2485,7 @@ DisplayOneMenu ( // // 2. Paint the description. // - PromptWidth = GetWidth (Statement, &AdjustValue); + PromptWidth = GetWidth (MenuOption, &AdjustValue); Row = MenuOption->Row; GlyphWidth = 1; PromptLineNum = 0; @@ -1774,14 +2494,14 @@ DisplayOneMenu ( PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth); PromptLineNum++; } else { - for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp == 0) && (Row <= BottomRow)) { + for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + if ((Temp == 0) && (Row <= BottomRow)) { // - // 1.Clean the start LEFT_SKIPPED_COLUMNS + // 1.Clean the start LEFT_SKIPPED_COLUMNS // PrintStringAtWithWidth (BeginCol, Row, L"", SkipWidth); - - if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2) { + + if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2 && IsProcessingFirstRow) { // // Print Arrow for Goto button. // @@ -1790,6 +2510,7 @@ DisplayOneMenu ( Row, GEOMETRICSHAPE_RIGHT_TRIANGLE ); + IsProcessingFirstRow = FALSE; } DisplayMenuString (MenuOption, MenuOption->Col, Row, OutputString, PromptWidth + AdjustValue, Highlight); PromptLineNum ++; @@ -1818,13 +2539,13 @@ DisplayOneMenu ( // if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) { StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle); - + Width = (UINT16) gOptionBlockWidth - 1; Row = MenuOption->Row; GlyphWidth = 1; OptionLineNum = 0; - for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if ((Temp3 == 0) && (Row <= BottomRow)) { DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight); OptionLineNum++; @@ -1835,9 +2556,15 @@ DisplayOneMenu ( if (StrLen (&StringPtr[Index]) != 0) { if (Temp3 == 0) { Row++; + // + // If the rows for text two is greater than or equal to the skip value, increase the skip value + // + if ((Row - MenuOption->Row) >= MenuOption->Skip) { + MenuOption->Skip++; + } } } - + FreePool (OutputString); if (Temp3 != 0) { Temp3--; @@ -1856,7 +2583,7 @@ DisplayOneMenu ( Row = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row; Width = (UINT16) (OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth); MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1; - + while (Row <= MaxRow) { DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE); } @@ -1881,7 +2608,7 @@ UiDisplayMenu ( IN FORM_DISPLAY_ENGINE_FORM *FormData ) { - INTN SkipValue; + UINTN SkipValue; INTN Difference; UINTN DistanceValue; UINTN Row; @@ -1890,12 +2617,11 @@ UiDisplayMenu ( UINTN Temp2; UINTN TopRow; UINTN BottomRow; - UINTN OriginalRow; UINTN Index; - UINT16 Width; CHAR16 *StringPtr; + CHAR16 *StringRightPtr; + CHAR16 *StringErrorPtr; CHAR16 *OptionString; - CHAR16 *OutputString; CHAR16 *HelpString; CHAR16 *HelpHeaderString; CHAR16 *HelpBottomString; @@ -1912,10 +2638,8 @@ UiDisplayMenu ( UI_MENU_OPTION *MenuOption; UI_MENU_OPTION *NextMenuOption; UI_MENU_OPTION *SavedMenuOption; - UI_MENU_OPTION *PreviousMenuOption; UI_CONTROL_FLAG ControlFlag; UI_SCREEN_OPERATION ScreenOperation; - UINT16 DefaultId; FORM_DISPLAY_ENGINE_STATEMENT *Statement; BROWSER_HOT_KEY *HotKey; UINTN HelpPageIndex; @@ -1925,14 +2649,13 @@ UiDisplayMenu ( UINTN HelpHeaderLine; UINTN HelpBottomLine; BOOLEAN MultiHelpPage; - UINT16 GlyphWidth; UINT16 EachLineWidth; UINT16 HeaderLineWidth; UINT16 BottomLineWidth; EFI_STRING_ID HelpInfo; UI_EVENT_TYPE EventType; - FORM_DISPLAY_ENGINE_STATEMENT *InitialHighlight; BOOLEAN SkipHighLight; + EFI_HII_VALUE *StatementValue; EventType = UIEventNone; Status = EFI_SUCCESS; @@ -1942,7 +2665,6 @@ UiDisplayMenu ( OptionString = NULL; ScreenOperation = UiNoOperation; NewLine = TRUE; - DefaultId = 0; HelpPageCount = 0; HelpLine = 0; RowCount = 0; @@ -1953,33 +2675,20 @@ UiDisplayMenu ( EachLineWidth = 0; HeaderLineWidth = 0; BottomLineWidth = 0; - OutputString = NULL; UpArrow = FALSE; DownArrow = FALSE; SkipValue = 0; SkipHighLight = FALSE; NextMenuOption = NULL; - PreviousMenuOption = NULL; SavedMenuOption = NULL; HotKey = NULL; Repaint = TRUE; MenuOption = NULL; gModalSkipColumn = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6; - InitialHighlight = gFormData->HighLightedStatement; ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); - // - // Left right - // |<-.->|<-.........->|<- .........->|<-...........->| - // Skip Prompt Option Help - // - Width = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3); - gOptionBlockWidth = Width + 1; - gHelpBlockWidth = (CHAR16) (Width - LEFT_SKIPPED_COLUMNS); - gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * Width - 1); - TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1; @@ -1991,6 +2700,10 @@ UiDisplayMenu ( } FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue); + if (!IsListEmpty (&gMenuOption)) { + NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); + gUserInput->SelectedStatement = NextMenuOption->ThisTag; + } gST->ConOut->EnableCursor (gST->ConOut, FALSE); @@ -1998,7 +2711,7 @@ UiDisplayMenu ( while (TRUE) { switch (ControlFlag) { case CfInitialization: - if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) || + if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))) { // // Clear Statement range if different formset is painted. @@ -2027,7 +2740,7 @@ UiDisplayMenu ( Row = TopRow; gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - + // // 1. Check whether need to print the arrow up. // @@ -2076,25 +2789,31 @@ UiDisplayMenu ( } if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - Status = DisplayOneMenu (MenuOption, - LEFT_SKIPPED_COLUMNS, - gStatementDimensions.LeftColumn + gModalSkipColumn, - Link == TopOfScreen ? SkipValue : 0, + Status = DisplayOneMenu (MenuOption, + MenuOption->Col - gStatementDimensions.LeftColumn, + gStatementDimensions.LeftColumn + gModalSkipColumn, + Link == TopOfScreen ? SkipValue : 0, BottomRow, - (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)) + (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)), + TRUE ); } else { - Status = DisplayOneMenu (MenuOption, - LEFT_SKIPPED_COLUMNS, - gStatementDimensions.LeftColumn, - Link == TopOfScreen ? SkipValue : 0, + Status = DisplayOneMenu (MenuOption, + MenuOption->Col - gStatementDimensions.LeftColumn, + gStatementDimensions.LeftColumn, + Link == TopOfScreen ? SkipValue : 0, BottomRow, - (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)) - ); + (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)), + TRUE + ); } if (EFI_ERROR (Status)) { - return Status; + if (gMisMatch) { + return EFI_SUCCESS; + } else { + return Status; + } } // // 3. Update the row info which will be used by next menu. @@ -2145,10 +2864,6 @@ UiDisplayMenu ( } MenuOption = NULL; - - if (IsListEmpty (&gMenuOption)) { - ControlFlag = CfReadKey; - } } break; @@ -2161,10 +2876,21 @@ UiDisplayMenu ( // ControlFlag = CfUpdateHelpString; + ASSERT (NewPos != NULL); + UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue); + if (SkipHighLight) { - MenuOption = SavedMenuOption; SkipHighLight = FALSE; - UpdateHighlightMenuInfo (MenuOption); + MenuOption = SavedMenuOption; + RefreshKeyHelp(gFormData, SavedMenuOption->ThisTag, FALSE); + break; + } + + if (IsListEmpty (&gMenuOption)) { + // + // No menu option, just update the hotkey filed. + // + RefreshKeyHelp(gFormData, NULL, FALSE); break; } @@ -2179,169 +2905,39 @@ UiDisplayMenu ( Temp2 = 0; } - if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) { + if (MenuOption == NULL || NewPos != &MenuOption->Link) { if (MenuOption != NULL) { // - // Remove highlight on last Menu Option + // Remove the old highlight menu. // - gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); - ProcessOptions (MenuOption, FALSE, &OptionString, TRUE); - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - if (OptionString != NULL) { - if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || - (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) - ) { - ProcessStringForDateTime(MenuOption, OptionString, FALSE); - } - - Width = (UINT16) gOptionBlockWidth; - OriginalRow = MenuOption->Row; - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) { - PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index]) != 0) { - if (Temp == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp != 0) { - Temp--; - } - } - - MenuOption->Row = OriginalRow; - - FreePool (OptionString); - } else { - if (NewLine) { - if (MenuOption->GrayOut) { - gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ()); - } else if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) { - gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ()); - } - - OriginalRow = MenuOption->Row; - Width = GetWidth (MenuOption->ThisTag, NULL); - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) { - PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index]) != 0) { - if (Temp == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp != 0) { - Temp--; - } - } - - MenuOption->Row = OriginalRow; - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - } - } + Status = DisplayOneMenu (MenuOption, + MenuOption->Col - gStatementDimensions.LeftColumn, + gStatementDimensions.LeftColumn, + Temp, + BottomRow, + FALSE, + FALSE + ); } // // This is the current selected statement // MenuOption = MENU_OPTION_FROM_LINK (NewPos); - Statement = MenuOption->ThisTag; - - UpdateHighlightMenuInfo (MenuOption); + RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE); if (!IsSelectable (MenuOption)) { break; } - // - // Set reverse attribute - // - gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); - gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); - - ProcessOptions (MenuOption, FALSE, &OptionString, TRUE); - if (OptionString != NULL) { - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - ProcessStringForDateTime(MenuOption, OptionString, FALSE); - } - Width = (UINT16) gOptionBlockWidth; - - OriginalRow = MenuOption->Row; - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) { - PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index]) != 0) { - if (Temp2 == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp2 != 0) { - Temp2--; - } - } - - MenuOption->Row = OriginalRow; - - FreePool (OptionString); - } else { - if (NewLine) { - OriginalRow = MenuOption->Row; - - Width = GetWidth (Statement, NULL); - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) { - PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index]) != 0) { - if (Temp2 == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp2 != 0) { - Temp2--; - } - } - - MenuOption->Row = OriginalRow; - - } - } - - // - // Clear reverse attribute - // - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); + Status = DisplayOneMenu (MenuOption, + MenuOption->Col - gStatementDimensions.LeftColumn, + gStatementDimensions.LeftColumn, + Temp2, + BottomRow, + TRUE, + FALSE + ); } break; @@ -2351,16 +2947,43 @@ UiDisplayMenu ( break; } + // + // NewLine means only update highlight menu (remove old highlight and highlith + // the new one), not need to full repain the form. + // if (Repaint || NewLine) { - // - // Don't print anything if it is a NULL help token - // - ASSERT(MenuOption != NULL); - HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help; - if (HelpInfo == 0 || !IsSelectable (MenuOption)) { + if (IsListEmpty (&gMenuOption)) { + // + // Don't print anything if no mwnu option. + // StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); } else { - StringPtr = GetToken (HelpInfo, gFormData->HiiHandle); + // + // Don't print anything if it is a NULL help token + // + ASSERT(MenuOption != NULL); + HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help; + Statement = MenuOption->ThisTag; + StatementValue = &Statement->CurrentValue; + if (HelpInfo == 0 || !IsSelectable (MenuOption)) { + if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP && StatementValue->Value.date.Month== 0xff)||(Statement->OpCode->OpCode == EFI_IFR_TIME_OP && StatementValue->Value.time.Hour == 0xff)){ + StringPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle); + } else { + StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + } + } else { + if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP && StatementValue->Value.date.Month== 0xff)||(Statement->OpCode->OpCode == EFI_IFR_TIME_OP && StatementValue->Value.time.Hour == 0xff)){ + StringRightPtr = GetToken (HelpInfo, gFormData->HiiHandle); + StringErrorPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle); + StringPtr = AllocateZeroPool ((StrLen (StringRightPtr) + StrLen (StringErrorPtr)+ 1 ) * sizeof (CHAR16)); + StrCpyS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringRightPtr); + StrCatS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringErrorPtr); + FreePool (StringRightPtr); + FreePool (StringErrorPtr); + } else { + StringPtr = GetToken (HelpInfo, gFormData->HiiHandle); + } + } } RowCount = BottomRow - TopRow + 1; @@ -2396,7 +3019,7 @@ UiDisplayMenu ( // if (HelpLine > 2 * RowCount - 2) { HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1; - if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) { + if ((HelpLine - RowCount + 1) % (RowCount - 2) != 0) { HelpPageCount += 1; } } else { @@ -2410,14 +3033,14 @@ UiDisplayMenu ( // // Check whether need to show the 'More(U/u)' at the begin. // Base on current direct info, here shows aligned to the right side of the column. - // If the direction is multi line and aligned to right side may have problem, so + // If the direction is multi line and aligned to right side may have problem, so // add ASSERT code here. // if (HelpPageIndex > 0) { gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ()); for (Index = 0; Index < HelpHeaderLine; Index++) { ASSERT (HelpHeaderLine == 1); - ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1)); + ASSERT (GetStringWidth (HelpHeaderString) / 2 < ((UINT32) gHelpBlockWidth - 1)); PrintStringAtWithWidth ( gStatementDimensions.RightColumn - gHelpBlockWidth, Index + TopRow, @@ -2465,7 +3088,7 @@ UiDisplayMenu ( ); } } else { - for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && + for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) { PrintStringAtWithWidth ( gStatementDimensions.RightColumn - gHelpBlockWidth, @@ -2485,20 +3108,20 @@ UiDisplayMenu ( } gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow); } - } + } } // // Check whether need to print the 'More(D/d)' at the bottom. // Base on current direct info, here shows aligned to the right side of the column. - // If the direction is multi line and aligned to right side may have problem, so + // If the direction is multi line and aligned to right side may have problem, so // add ASSERT code here. // if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) { gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ()); for (Index = 0; Index < HelpBottomLine; Index++) { ASSERT (HelpBottomLine == 1); - ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); + ASSERT (GetStringWidth (HelpBottomString) / 2 < ((UINT32) gHelpBlockWidth - 1)); PrintStringAtWithWidth ( gStatementDimensions.RightColumn - gHelpBlockWidth, BottomRow + Index - HelpBottomLine + 1, @@ -2543,7 +3166,7 @@ UiDisplayMenu ( if (Status != EFI_NOT_READY) { continue; } - + EventType = UiWaitForEvent(gST->ConIn->WaitForKey); if (EventType == UIEventKey) { gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); @@ -2552,11 +3175,12 @@ UiDisplayMenu ( } if (EventType == UIEventDriver) { + gMisMatch = TRUE; gUserInput->Action = BROWSER_ACTION_NONE; ControlFlag = CfExit; break; } - + if (EventType == UIEventTimeOut) { gUserInput->Action = BROWSER_ACTION_FORM_EXIT; ControlFlag = CfExit; @@ -2584,12 +3208,12 @@ UiDisplayMenu ( // If the screen has no menu items, and the user didn't select UiReset // ignore the selection and go back to reading keys. // + ASSERT(MenuOption != NULL); if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) { ControlFlag = CfReadKey; break; } - ASSERT(MenuOption != NULL); Statement = MenuOption->ThisTag; if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) @@ -2600,7 +3224,7 @@ UiDisplayMenu ( } else { gDirection = SCAN_LEFT; } - + Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE); if (OptionString != NULL) { FreePool (OptionString); @@ -2631,7 +3255,7 @@ UiDisplayMenu ( ControlFlag = CfReadKey; break; } - + ASSERT(MenuOption != NULL); if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) { ScreenOperation = UiSelect; @@ -2665,7 +3289,7 @@ UiDisplayMenu ( break; } } - + if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) { // // ModalForm has no ESC key and Hot Key. @@ -2686,9 +3310,9 @@ UiDisplayMenu ( break; case CfScreenOperation: - if (ScreenOperation != UiReset) { + if ((ScreenOperation != UiReset) && (ScreenOperation != UiHotKey)) { // - // If the screen has no menu items, and the user didn't select UiReset + // If the screen has no menu items, and the user didn't select UiReset or UiHotKey // ignore the selection and go back to reading keys. // if (IsListEmpty (&gMenuOption)) { @@ -2698,7 +3322,7 @@ UiDisplayMenu ( } for (Index = 0; - Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]); + Index < ARRAY_SIZE (gScreenOperationToControlFlag); Index++ ) { if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) { @@ -2730,11 +3354,11 @@ UiDisplayMenu ( // RefreshKeyHelp (gFormData, Statement, TRUE); Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE); - + if (OptionString != NULL) { FreePool (OptionString); } - + if (EFI_ERROR (Status)) { Repaint = TRUE; NewLine = TRUE; @@ -2759,22 +3383,27 @@ UiDisplayMenu ( break; } - // - // When user press ESC, it will try to show another menu, should clean the gSequence info. - // - if (gSequence != 0) { - gSequence = 0; - } - gUserInput->Action = BROWSER_ACTION_FORM_EXIT; ControlFlag = CfExit; break; case CfUiHotKey: ControlFlag = CfRepaint; - - gUserInput->Action = HotKey->Action; - ControlFlag = CfExit; + + ASSERT (HotKey != NULL); + + if (FxConfirmPopup(HotKey->Action)) { + gUserInput->Action = HotKey->Action; + if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { + gUserInput->DefaultId = HotKey->DefaultId; + } + ControlFlag = CfExit; + } else { + Repaint = TRUE; + NewLine = TRUE; + ControlFlag = CfRepaint; + } + break; case CfUiLeft: @@ -2807,208 +3436,129 @@ UiDisplayMenu ( case CfUiUp: ControlFlag = CfRepaint; + NewLine = TRUE; SavedListEntry = NewPos; - ASSERT(NewPos != NULL); - // - // Adjust Date/Time position before we advance forward. - // - AdjustDateAndTimePosition (TRUE, &NewPos); - if (NewPos->BackLink != &gMenuOption) { - MenuOption = MENU_OPTION_FROM_LINK (NewPos); - ASSERT (MenuOption != NULL); - NewLine = TRUE; - NewPos = NewPos->BackLink; - - PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos); - if (PreviousMenuOption->Row == 0) { - UpdateOptionSkipLines (PreviousMenuOption); - } - DistanceValue = PreviousMenuOption->Skip; - Difference = 0; - if (MenuOption->Row >= DistanceValue + TopRow) { - Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue); - } - NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); - - if (Difference < 0) { - // - // We hit the begining MenuOption that can be focused - // so we simply scroll to the top. - // - if (TopOfScreen != gMenuOption.ForwardLink) { - TopOfScreen = gMenuOption.ForwardLink; - Repaint = TRUE; - } else { - // - // Scroll up to the last page when we have arrived at top page. - // - NewPos = &gMenuOption; - TopOfScreen = &gMenuOption; - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - ScreenOperation = UiPageUp; - ControlFlag = CfScreenOperation; - break; - } - } else if (MenuOption->Row < TopRow + DistanceValue + Difference) { - // - // Previous focus MenuOption is above the TopOfScreen, so we need to scroll - // - TopOfScreen = NewPos; - Repaint = TRUE; - SkipValue = 0; - } else if (!IsSelectable (NextMenuOption)) { - // - // Continue to go up until scroll to next page or the selectable option is found. - // - ScreenOperation = UiUp; - ControlFlag = CfScreenOperation; - } - - // - // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - UpdateStatusBar (INPUT_ERROR, FALSE); - } else { - // - // Scroll up to the last page. - // - NewPos = &gMenuOption; - TopOfScreen = &gMenuOption; - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - ScreenOperation = UiPageUp; - ControlFlag = CfScreenOperation; - } - break; - - case CfUiPageUp: - // - // SkipValue means lines is skipped when show the top menu option. - // - ControlFlag = CfRepaint; - - ASSERT(NewPos != NULL); - // - // Already at the first menu option, Check the skip value. - // - if (NewPos->BackLink == &gMenuOption) { - if (SkipValue == 0) { - NewLine = FALSE; - Repaint = FALSE; - } else { - NewLine = TRUE; - Repaint = TRUE; - SkipValue = 0; - } - break; - } - NewLine = TRUE; - Repaint = TRUE; + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + ASSERT (MenuOption != NULL); // - // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one - // form of options to be show, so just update the SkipValue to show the next - // parts of options. + // Adjust Date/Time position before we advance forward. // - if (SkipValue > (INTN) (BottomRow - TopRow + 1)) { - SkipValue -= BottomRow - TopRow + 1; - break; - } + AdjustDateAndTimePosition (TRUE, &NewPos); - Link = TopOfScreen; + NewPos = NewPos->BackLink; // - // First minus the menu of the top screen, it's value is SkipValue. + // Find next selectable menu or the first menu beyond current form. // - Index = (BottomRow + 1) - SkipValue; - while ((Index > TopRow) && (Link->BackLink != &gMenuOption)) { - Link = Link->BackLink; - PreviousMenuOption = MENU_OPTION_FROM_LINK (Link); - if (PreviousMenuOption->Row == 0) { - UpdateOptionSkipLines (PreviousMenuOption); - } - if (Index < PreviousMenuOption->Skip) { - break; - } - Index = Index - PreviousMenuOption->Skip; - } - - if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) { - SkipValue = 0; - if (TopOfScreen == &gMenuOption) { + Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow, FALSE); + if (Difference < 0) { + // + // We hit the begining MenuOption that can be focused + // so we simply scroll to the top. + // + Repaint = TRUE; + if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) { TopOfScreen = gMenuOption.ForwardLink; - NewPos = gMenuOption.BackLink; - MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow); - Repaint = FALSE; - } else if (TopOfScreen != Link) { - TopOfScreen = Link; - NewPos = Link; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); + NewPos = SavedListEntry; + SkipValue = 0; } else { // - // Finally we know that NewPos is the last MenuOption can be focused. + // Scroll up to the last page when we have arrived at top page. // - Repaint = FALSE; - NewPos = Link; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); + TopOfScreen = FindTopOfScreenMenu (gMenuOption.BackLink, BottomRow - TopRow, &SkipValue); + NewPos = gMenuOption.BackLink; + MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow, TRUE); } } else { - if (Index > TopRow) { + NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); + + if (MenuOption->Row < TopRow + Difference + NextMenuOption->Skip) { // - // At here, only case "Index < PreviousMenuOption->Skip" can reach here. + // Previous focus MenuOption is above the TopOfScreen, so we need to scroll // - SkipValue = PreviousMenuOption->Skip - (Index - TopRow); - } else if (Index == TopRow) { - SkipValue = 0; - } else { - SkipValue = TopRow - Index; + TopOfScreen = NewPos; + Repaint = TRUE; + SkipValue = 0; } // - // Move to the option in Next page. + // Check whether new highlight menu is selectable, if not, keep highlight on the old one. // - if (TopOfScreen == &gMenuOption) { - NewPos = gMenuOption.BackLink; - MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow); - } else { - NewPos = Link; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); + // BottomRow - TopRow + 1 means the total rows current forms supported. + // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu + // and new top menu. New top menu will all shows in next form, but last highlight menu + // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the + // last highlight menu. + // + if (!IsSelectable(NextMenuOption) && IsSelectable(MenuOption) && + (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) { + NewPos = SavedListEntry; } + } + + UpdateStatusBar (INPUT_ERROR, FALSE); + // + // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + + UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue); + break; + + case CfUiPageUp: + // + // SkipValue means lines is skipped when show the top menu option. + // + ControlFlag = CfRepaint; + NewLine = TRUE; + Repaint = TRUE; + + Link = TopOfScreen; + // + // First minus the menu of the top screen, it's value is SkipValue. + // + if (SkipValue >= BottomRow - TopRow + 1) { // - // There are more MenuOption needing scrolling up. + // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one + // form of options to be show, so just update the SkipValue to show the next + // parts of options. // - TopOfScreen = Link; - MenuOption = NULL; + SkipValue -= BottomRow - TopRow + 1; + NewPos = TopOfScreen; + break; + } else { + Index = (BottomRow + 1) - SkipValue - TopRow; } + TopOfScreen = FindTopOfScreenMenu(TopOfScreen, Index, &SkipValue); + NewPos = TopOfScreen; + MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE); + + UpdateStatusBar (INPUT_ERROR, FALSE); + // // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. // Don't do this when we are already in the first page. // AdjustDateAndTimePosition (TRUE, &TopOfScreen); AdjustDateAndTimePosition (TRUE, &NewPos); + + UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue); break; case CfUiPageDown: // // SkipValue means lines is skipped when show the top menu option. // - ControlFlag = CfRepaint; - - ASSERT (NewPos != NULL); - if (NewPos->ForwardLink == &gMenuOption) { - NewLine = FALSE; - Repaint = FALSE; - break; - } + ControlFlag = CfRepaint; + NewLine = TRUE; + Repaint = TRUE; - NewLine = TRUE; - Repaint = TRUE; Link = TopOfScreen; NextMenuOption = MENU_OPTION_FROM_LINK (Link); Index = TopRow + NextMenuOption->Skip - SkipValue; @@ -3023,10 +3573,10 @@ UiDisplayMenu ( if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) { // - // Finally we know that NewPos is the last MenuOption can be focused. + // Highlight on the last menu which can be highlight. // Repaint = FALSE; - MoveToNextStatement (TRUE, &Link, Index - TopRow); + MoveToNextStatement (TRUE, &Link, Index - TopRow, TRUE); } else { // // Calculate the skip line for top of screen menu. @@ -3039,13 +3589,12 @@ UiDisplayMenu ( } else { SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1)); } - TopOfScreen = Link; MenuOption = NULL; // // Move to the Next selectable menu. // - MoveToNextStatement (FALSE, &Link, BottomRow - TopRow); + MoveToNextStatement (FALSE, &Link, BottomRow - TopRow, TRUE); } // @@ -3053,12 +3602,16 @@ UiDisplayMenu ( // NewPos = Link; + UpdateStatusBar (INPUT_ERROR, FALSE); + // // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. // Don't do this when we are already in the last page. // AdjustDateAndTimePosition (TRUE, &TopOfScreen); AdjustDateAndTimePosition (TRUE, &NewPos); + + UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue); break; case CfUiDown: @@ -3067,7 +3620,15 @@ UiDisplayMenu ( // NewPos points to the menu which is highlighted now. // ControlFlag = CfRepaint; + NewLine = TRUE; + + if (NewPos == TopOfScreen) { + Temp2 = SkipValue; + } else { + Temp2 = 0; + } + SavedListEntry = NewPos; // // Since the behavior of hitting the down arrow on a Date/Time op-code is intended // to be one that progresses to the next set of op-codes, we need to advance to the last @@ -3076,181 +3637,143 @@ UiDisplayMenu ( // op-code is the last entry in the menu, we need to rewind back to the first op-code of // the Date/Time op-code. // - SavedListEntry = NewPos; AdjustDateAndTimePosition (FALSE, &NewPos); - if (NewPos->ForwardLink != &gMenuOption) { - MenuOption = MENU_OPTION_FROM_LINK (NewPos); - NewLine = TRUE; - NewPos = NewPos->ForwardLink; - - Difference = 0; + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + NewPos = NewPos->ForwardLink; + // + // Find the next selectable menu. + // + if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) { + if (gMenuOption.ForwardLink == NewPos || &gMenuOption == NewPos) { + Difference = -1; + } else { + Difference = 0; + } + } else { + Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE); + } + if (Difference < 0) { // - // Current menu not at the bottom of the form. + // Scroll to the first page. // - if (BottomRow >= MenuOption->Row + MenuOption->Skip) { - // - // Find the next selectable menu. - // - Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip); - // - // We hit the end of MenuOption that can be focused - // so we simply scroll to the first page. - // - if (Difference < 0) { - // - // Scroll to the first page. - // - if (TopOfScreen != gMenuOption.ForwardLink) { - TopOfScreen = gMenuOption.ForwardLink; - Repaint = TRUE; - MenuOption = NULL; - } else { - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - } - NewPos = gMenuOption.ForwardLink; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); - - SkipValue = 0; - // - // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - break; - } - } - NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); - if (NextMenuOption->Row == 0) { - UpdateOptionSkipLines (NextMenuOption); - } - DistanceValue = Difference + NextMenuOption->Skip; - - Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1; - if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) && - (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || - NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) - ) { - Temp ++; + if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) { + TopOfScreen = gMenuOption.ForwardLink; + Repaint = TRUE; + MenuOption = NULL; + } else { + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); } + NewPos = gMenuOption.ForwardLink; + MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, TRUE); + SkipValue = 0; // - // If we are going to scroll, update TopOfScreen + // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. // - if (Temp > BottomRow) { - do { - // - // Is the current top of screen a zero-advance op-code? - // If so, keep moving forward till we hit a >0 advance op-code - // - SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - - // - // If bottom op-code is more than one line or top op-code is more than one line - // - if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) { - // - // Is the bottom op-code greater than or equal in size to the top op-code? - // - if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) { - // - // Skip the top op-code - // - TopOfScreen = TopOfScreen->ForwardLink; - Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue); - - SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - - // - // If we have a remainder, skip that many more op-codes until we drain the remainder - // - while (Difference >= (INTN) SavedMenuOption->Skip) { - // - // Since the Difference is greater than or equal to this op-code's skip value, skip it - // - Difference = Difference - (INTN) SavedMenuOption->Skip; - TopOfScreen = TopOfScreen->ForwardLink; - SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - } - // - // Since we will act on this op-code in the next routine, and increment the - // SkipValue, set the skips to one less than what is required. - // - SkipValue = Difference - 1; - } else { - // - // Since we will act on this op-code in the next routine, and increment the - // SkipValue, set the skips to one less than what is required. - // - SkipValue += (Temp - BottomRow) - 1; - } - } else { - if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) { - TopOfScreen = TopOfScreen->ForwardLink; - break; - } - } - // - // If the op-code at the top of the screen is more than one line, let's not skip it yet - // Let's set a skip flag to smoothly scroll the top of the screen. - // - if (SavedMenuOption->Skip > 1) { - if (SavedMenuOption == NextMenuOption) { - SkipValue = 0; - } else { - SkipValue++; - } - } else if (SavedMenuOption->Skip == 1) { - SkipValue = 0; - } else { - SkipValue = 0; - TopOfScreen = TopOfScreen->ForwardLink; - } - } while (SavedMenuOption->Skip == 0); + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); - Repaint = TRUE; - } else if (!IsSelectable (NextMenuOption)) { - // - // Continue to go down until scroll to next page or the selectable option is found. - // - ScreenOperation = UiDown; - ControlFlag = CfScreenOperation; - } + UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue); + break; + } - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + // + // Get next selected menu info. + // + AdjustDateAndTimePosition (FALSE, &NewPos); + NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); + if (NextMenuOption->Row == 0) { + UpdateOptionSkipLines (NextMenuOption); + } - UpdateStatusBar (INPUT_ERROR, FALSE); + // + // Calculate new highlight menu end row. + // + Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1; + if (Temp > BottomRow) { + // + // Get the top screen menu info. + // + AdjustDateAndTimePosition (FALSE, &TopOfScreen); + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - } else { // - // Scroll to the first page. + // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows. + // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows. // - if (TopOfScreen != gMenuOption.ForwardLink) { - TopOfScreen = gMenuOption.ForwardLink; - Repaint = TRUE; - MenuOption = NULL; + if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) { + // + // Skip the top op-code + // + TopOfScreen = TopOfScreen->ForwardLink; + DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue); + + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); + + // + // If we have a remainder, skip that many more op-codes until we drain the remainder + // Special case is the selected highlight menu has more than one form of menus. + // + while (DistanceValue >= SavedMenuOption->Skip && TopOfScreen != NewPos) { + // + // Since the Difference is greater than or equal to this op-code's skip value, skip it + // + DistanceValue = DistanceValue - (INTN) SavedMenuOption->Skip; + TopOfScreen = TopOfScreen->ForwardLink; + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); + } + // + // Since we will act on this op-code in the next routine, and increment the + // SkipValue, set the skips to one less than what is required. + // + if (TopOfScreen != NewPos) { + SkipValue = DistanceValue; + } else { + SkipValue = 0; + } } else { // - // Need to remove the current highlight menu. - // MenuOption saved the last highlight menu info. + // Since we will act on this op-code in the next routine, and increment the + // SkipValue, set the skips to one less than what is required. // - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + SkipValue += Temp - BottomRow; } - - SkipValue = 0; - NewLine = TRUE; + Repaint = TRUE; + } else if (!IsSelectable (NextMenuOption)) { // - // Get the next highlight menu. + // Continue to go down until scroll to next page or the selectable option is found. // - NewPos = gMenuOption.ForwardLink; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); + ScreenOperation = UiDown; + ControlFlag = CfScreenOperation; + break; + } + + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + + // + // Check whether new highlight menu is selectable, if not, keep highlight on the old one. + // + // BottomRow - TopRow + 1 means the total rows current forms supported. + // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu + // and new top menu. New top menu will all shows in next form, but last highlight menu + // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the + // last highlight menu. + // + if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) && + (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) { + NewPos = SavedListEntry; } + UpdateStatusBar (INPUT_ERROR, FALSE); + // // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. // AdjustDateAndTimePosition (TRUE, &TopOfScreen); AdjustDateAndTimePosition (TRUE, &NewPos); + + UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue); break; case CfUiNoOperation: @@ -3276,6 +3799,34 @@ UiDisplayMenu ( } } +/** + Free the UI Menu Option structure data. + + @param MenuOptionList Point to the menu option list which need to be free. + +**/ +VOID +FreeMenuOptionData( + LIST_ENTRY *MenuOptionList + ) +{ + LIST_ENTRY *Link; + UI_MENU_OPTION *Option; + + // + // Free menu option list + // + while (!IsListEmpty (MenuOptionList)) { + Link = GetFirstNode (MenuOptionList); + Option = MENU_OPTION_FROM_LINK (Link); + if (Option->Description != NULL){ + FreePool(Option->Description); + } + RemoveEntryList (&Option->Link); + FreePool (Option); + } +} + /** Base on the browser status info to show an pop up message. @@ -3286,14 +3837,56 @@ BrowserStatusProcess ( VOID ) { - CHAR16 *ErrorInfo; - EFI_INPUT_KEY Key; + CHAR16 *ErrorInfo; + EFI_INPUT_KEY Key; + EFI_EVENT WaitList[2]; + EFI_EVENT RefreshIntervalEvent; + EFI_EVENT TimeOutEvent; + UINT8 TimeOut; + EFI_STATUS Status; + UINTN Index; + WARNING_IF_CONTEXT EventContext; + EFI_IFR_OP_HEADER *OpCodeBuf; + EFI_STRING_ID StringToken; + CHAR16 DiscardChange; + CHAR16 JumpToFormSet; + CHAR16 *PrintString; if (gFormData->BrowserStatus == BROWSER_SUCCESS) { return; } - if (gFormData->ErrorString != NULL) { + StringToken = 0; + TimeOutEvent = NULL; + RefreshIntervalEvent = NULL; + OpCodeBuf = NULL; + if (gFormData->HighLightedStatement != NULL) { + OpCodeBuf = gFormData->HighLightedStatement->OpCode; + } + + if (gFormData->BrowserStatus == (BROWSER_WARNING_IF)) { + ASSERT (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_WARNING_IF_OP); + + TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->TimeOut; + StringToken = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->Warning; + } else { + TimeOut = 0; + if ((gFormData->BrowserStatus == (BROWSER_NO_SUBMIT_IF)) && + (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_NO_SUBMIT_IF_OP)) { + StringToken = ((EFI_IFR_NO_SUBMIT_IF *) OpCodeBuf)->Error; + } else if ((gFormData->BrowserStatus == (BROWSER_INCONSISTENT_IF)) && + (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_INCONSISTENT_IF_OP)) { + StringToken = ((EFI_IFR_INCONSISTENT_IF *) OpCodeBuf)->Error; + } + } + + if (StringToken != 0) { + ErrorInfo = GetToken (StringToken, gFormData->HiiHandle); + } else if (gFormData->ErrorString != NULL) { + // + // Only used to compatible with old setup browser. + // Not use this field in new browser core. + // ErrorInfo = gFormData->ErrorString; } else { switch (gFormData->BrowserStatus) { @@ -3301,10 +3894,6 @@ BrowserStatusProcess ( ErrorInfo = gSaveFailed; break; - case BROWSER_NO_SUBMIT_IF: - ErrorInfo = gNoSubmitIf; - break; - case BROWSER_FORM_NOT_FOUND: ErrorInfo = gFormNotFound; break; @@ -3317,33 +3906,131 @@ BrowserStatusProcess ( ErrorInfo = gProtocolNotFound; break; + case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF: + ErrorInfo = gNoSubmitIfFailed; + break; + + case BROWSER_RECONNECT_FAIL: + ErrorInfo = gReconnectFail; + break; + + case BROWSER_RECONNECT_SAVE_CHANGES: + ErrorInfo = gReconnectConfirmChanges; + break; + + case BROWSER_RECONNECT_REQUIRED: + ErrorInfo = gReconnectRequired; + break; + default: - ErrorInfo = gBrwoserError; + ErrorInfo = gBrowserError; break; } } - // - // Error occur, prompt error message. - // - do { - CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + switch (gFormData->BrowserStatus) { + case BROWSER_SUBMIT_FAIL: + case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF: + case BROWSER_RECONNECT_SAVE_CHANGES: + ASSERT (gUserInput != NULL); + if (gFormData->BrowserStatus == (BROWSER_SUBMIT_FAIL)) { + PrintString = gSaveProcess; + JumpToFormSet = gJumpToFormSet[0]; + DiscardChange = gDiscardChange[0]; + } else if (gFormData->BrowserStatus == (BROWSER_RECONNECT_SAVE_CHANGES)){ + PrintString = gChangesOpt; + JumpToFormSet = gConfirmOptYes[0]; + DiscardChange = gConfirmOptNo[0]; + } else { + PrintString = gSaveNoSubmitProcess; + JumpToFormSet = gCheckError[0]; + DiscardChange = gDiscardChange[0]; + } + + do { + CreateDialog (&Key, gEmptyString, ErrorInfo, PrintString, gEmptyString, NULL); + } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (DiscardChange | UPPER_LOWER_CASE_OFFSET)) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (JumpToFormSet | UPPER_LOWER_CASE_OFFSET))); + + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (DiscardChange | UPPER_LOWER_CASE_OFFSET)) { + gUserInput->Action = BROWSER_ACTION_DISCARD; + } else { + gUserInput->Action = BROWSER_ACTION_GOTO; + } + break; + + default: + if (TimeOut == 0) { + do { + CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } else { + Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent); + ASSERT_EFI_ERROR (Status); + + EventContext.SyncEvent = TimeOutEvent; + EventContext.TimeOut = &TimeOut; + EventContext.ErrorInfo = ErrorInfo; + + Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent); + ASSERT_EFI_ERROR (Status); + + // + // Show the dialog first to avoid long time not reaction. + // + gBS->SignalEvent (RefreshIntervalEvent); + + Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND); + ASSERT_EFI_ERROR (Status); + + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + break; + } + + if (Status != EFI_NOT_READY) { + continue; + } + + WaitList[0] = TimeOutEvent; + WaitList[1] = gST->ConIn->WaitForKey; + + Status = gBS->WaitForEvent (2, WaitList, &Index); + ASSERT_EFI_ERROR (Status); + + if (Index == 0) { + // + // Timeout occur, close the hoot time out event. + // + break; + } + } + + gBS->CloseEvent (TimeOutEvent); + gBS->CloseEvent (RefreshIntervalEvent); + } + break; + } + + if (StringToken != 0) { + FreePool (ErrorInfo); + } } /** Display one form, and return user input. - + @param FormData Form Data to be shown. @param UserInputData User input data. - + @retval EFI_SUCCESS 1.Form Data is shown, and user input is got. 2.Error info has show and return. @retval EFI_INVALID_PARAMETER The input screen dimension is not valid @retval EFI_NOT_FOUND New form data has some error. **/ EFI_STATUS -EFIAPI +EFIAPI FormDisplay ( IN FORM_DISPLAY_ENGINE_FORM *FormData, OUT USER_INPUT *UserInputData @@ -3363,24 +4050,37 @@ FormDisplay ( // Process the status info first. // BrowserStatusProcess(); - if (UserInputData == NULL) { + if (gFormData->BrowserStatus != BROWSER_SUCCESS) { // - // UserInputData == NULL, means only need to print the error info, return here. + // gFormData->BrowserStatus != BROWSER_SUCCESS, means only need to print the error info, return here. // return EFI_SUCCESS; } - ConvertStatementToMenu(); - Status = DisplayPageFrame (FormData, &gStatementDimensions); if (EFI_ERROR (Status)) { return Status; } + // + // Global Widths should be initialized before any MenuOption creation + // or the GetWidth() used in UiAddMenuOption() will return incorrect value. + // + // + // Left right + // |<-.->|<-.........->|<- .........->|<-...........->| + // Skip Prompt Option Help + // + gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3) + 1; + gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - 1 - LEFT_SKIPPED_COLUMNS); + gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gOptionBlockWidth - 1) - 1); + + ConvertStatementToMenu(); + // // Check whether layout is changed. // - if (mIsFirstForm + if (mIsFirstForm || (gOldFormEntry.HiiHandle != FormData->HiiHandle) || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid)) || (gOldFormEntry.FormId != FormData->FormId)) { @@ -3390,7 +4090,7 @@ FormDisplay ( } Status = UiDisplayMenu(FormData); - + // // Backup last form info. // @@ -3399,6 +4099,11 @@ FormDisplay ( CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid); gOldFormEntry.FormId = FormData->FormId; + // + //Free the Ui menu option list. + // + FreeMenuOptionData(&gMenuOption); + return Status; } @@ -3406,7 +4111,7 @@ FormDisplay ( Clear Screen to the initial state. **/ VOID -EFIAPI +EFIAPI DriverClearDisplayPage ( VOID ) @@ -3482,14 +4187,25 @@ InitializeDisplayEngine ( ); ASSERT_EFI_ERROR (Status); + // + // Install HII Popup Protocol. + // + Status = gBS->InstallProtocolInterface ( + &mPrivateData.Handle, + &gEfiHiiPopupProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPrivateData.HiiPopup + ); + ASSERT_EFI_ERROR (Status); + InitializeDisplayStrings(); - + ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo)); ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry)); // // Use BrowserEx2 protocol to register HotKey. - // + // Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2); if (!EFI_ERROR (Status)) { // @@ -3500,11 +4216,13 @@ InitializeDisplayEngine ( NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL); ASSERT (NewString != NULL); FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString); + FreePool (NewString); HotKey.ScanCode = SCAN_F9; NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL); ASSERT (NewString != NULL); FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString); + FreePool (NewString); } return EFI_SUCCESS; @@ -3529,5 +4247,13 @@ UnloadDisplayEngine ( FreeDisplayStrings (); + if (gHighligthMenuInfo.HLTOpCode != NULL) { + FreePool (gHighligthMenuInfo.HLTOpCode); + } + + if (gHighligthMenuInfo.TOSOpCode != NULL) { + FreePool (gHighligthMenuInfo.TOSOpCode); + } + return EFI_SUCCESS; }