X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FDisplayEngineDxe%2FFormDisplay.c;h=7390f954b67f1ec13d41b3dea404964096356563;hp=9f6c963153cb3b1c30471597e9eb391e913d536d;hb=9090c8b533013078c6df773e128070c76d917830;hpb=6f05c02325fff475d695edacd0b0b003e5b1fcf3 diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c index 9f6c963153..7390f954b6 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c @@ -1,7 +1,8 @@ /** @file Entry and initialization module for the browser. -Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.
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 @@ -48,7 +49,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 +87,7 @@ SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { { UiPageDown, CfUiPageDown - }, + }, { UiHotKey, CfUiHotKey @@ -97,8 +98,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 +113,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 +139,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 +176,10 @@ FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData = { FormDisplay, DriverClearDisplayPage, ConfirmDataChange + }, + { + EFI_HII_POPUP_PROTOCOL_REVISION, + CreatePopup } }; @@ -184,8 +221,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 +247,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 +287,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 +308,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); } /** @@ -313,10 +418,10 @@ GetWidth ( // ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0)) ) { - + // // Return the space width. - // + // if (AdjustWidth != NULL) { *AdjustWidth = 2; } @@ -357,7 +462,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. **/ @@ -436,7 +541,7 @@ GetLineByWidth ( if (ReturnFlag) { break; } - } + } // // Rewind the string from the maximum size until we see a space to break the line @@ -466,7 +571,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; } @@ -485,7 +590,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) { // @@ -499,7 +604,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 { @@ -533,7 +638,6 @@ UiAddMenuOption ( UI_MENU_OPTION *MenuOption; UINTN Index; UINTN Count; - CHAR16 *String; UINT16 NumberOfLines; UINT16 GlyphWidth; UINT16 Width; @@ -550,9 +654,6 @@ UiAddMenuOption ( PromptId = GetPrompt (Statement->OpCode); ASSERT (PromptId != 0); - String = GetToken (PromptId, gFormData->HiiHandle); - ASSERT (String != NULL); - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { Count = 3; } @@ -562,7 +663,7 @@ 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; @@ -604,7 +705,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; @@ -622,15 +723,15 @@ UiAddMenuOption ( } } - if (Index == 0 && - (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) && + if (Index == 0 && + (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) && (Statement->OpCode->OpCode != EFI_IFR_TIME_OP)) { Width = GetWidth (MenuOption, NULL); - for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) { + 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 (&String[ArrayEntry]) != 0) { + if (StrLen (&MenuOption->Description[ArrayEntry]) != 0) { NumberOfLines++; } FreePool (OutputString); @@ -640,7 +741,7 @@ UiAddMenuOption ( // Add three MenuOptions for Date/Time // Data format : [01/02/2004] [11:22:33] // Line number : 0 0 1 0 0 1 - // + // NumberOfLines = 0; } @@ -699,6 +800,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); } } @@ -800,7 +908,7 @@ UpdateSkipInfoForMenu ( CHAR16 *OutputString; UINT16 GlyphWidth; - Width = (UINT16) gOptionBlockWidth; + Width = (UINT16) gOptionBlockWidth - 1; GlyphWidth = 1; Row = 1; @@ -812,8 +920,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; } @@ -852,6 +960,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. @@ -869,7 +1025,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; @@ -884,19 +1040,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; @@ -906,6 +1067,11 @@ MoveToNextStatement ( Distance = 0; Pos = *CurrentPosition; + + if (Pos == &gMenuOption) { + return -1; + } + PreMenuOption = MENU_OPTION_FROM_LINK (Pos); while (TRUE) { @@ -917,28 +1083,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. // @@ -947,21 +1112,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; @@ -974,10 +1126,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, @@ -991,7 +1143,7 @@ ProcessStringForDateTime ( EFI_IFR_TIME *Time; ASSERT (MenuOption != NULL && OptionString != NULL); - + Statement = MenuOption->ThisTag; Date = NULL; Time = NULL; @@ -1000,7 +1152,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 // @@ -1012,13 +1164,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. // @@ -1030,21 +1182,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) { @@ -1055,21 +1207,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' '); } } @@ -1152,7 +1304,7 @@ AdjustDateAndTimePosition ( /** Get step info from numeric opcode. - + @param[in] OpCode The input numeric op code. @return step info for this opcode. @@ -1166,24 +1318,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; @@ -1194,7 +1346,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. @@ -1211,14 +1363,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; } @@ -1288,13 +1440,13 @@ UiWaitForEvent ( Timeout ); } - + WaitList[0] = Event; EventNum = 1; if (gFormData->FormRefreshEvent != NULL) { WaitList[EventNum] = gFormData->FormRefreshEvent; EventNum ++; - } + } if (Timeout != 0) { WaitList[EventNum] = TimerEvent; @@ -1327,7 +1479,7 @@ UiWaitForEvent ( if (Timeout != 0) { gBS->CloseEvent (TimerEvent); } - + return EventType; } @@ -1355,299 +1507,848 @@ 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; } /** - Print string for this menu option. + Is this the highlight menu. - @param MenuOption The menu opton which this attribut used to. - @param Col The column that this string will be print at. - @param Row The row that this string will be print at. - @param String The string which need to print. - @param Width The width need to print, if string is less than the - width, the block space will be used. - @param Highlight Whether this menu will be highlight. + @param MenuOption The input Menu option. + + @retval TRUE This is the highlight menu option. + @retval FALSE This is not the highlight menu option. **/ -VOID -DisplayMenuString ( - IN UI_MENU_OPTION *MenuOption, - IN UINTN Col, - IN UINTN Row, - IN CHAR16 *String, - IN UINTN Width, - IN BOOLEAN Highlight +BOOLEAN +IsHighLightMenuOption ( + IN UI_MENU_OPTION *MenuOption ) { - UINTN Length; - - // - // Print string with normal color. - // - if (!Highlight) { - PrintStringAtWithWidth (Col, Row, String, Width); - return; + 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; + } + } } - - // - // Print the highlight menu string. - // First print the highlight string. - // - SetDisplayAttribute(MenuOption, TRUE); - Length = PrintStringAt (Col, Row, String); - // - // Second, clean the empty after the string. - // - SetDisplayAttribute(MenuOption, FALSE); - PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length); + return FALSE; } /** - Check whether this menu can has option string. + Find the highlight menu. - @param MenuOption The menu opton which this attribut used to. + If the input is NULL, base on the record highlight info in + gHighligthMenuInfo to find the last highlight menu. + + @param HighLightedStatement The input highlight statement. + + @retval The highlight menu index. + +**/ +LIST_ENTRY * +FindHighLightMenuOption ( + IN FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement + ) +{ + LIST_ENTRY *NewPos; + UI_MENU_OPTION *MenuOption; + + NewPos = gMenuOption.ForwardLink; + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + + if (HighLightedStatement != NULL) { + while (MenuOption->ThisTag != HighLightedStatement) { + NewPos = NewPos->ForwardLink; + if (NewPos == &gMenuOption) { + // + // Not Found it, break + // + break; + } + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + } + + // + // Must find the highlight statement. + // + ASSERT (NewPos != &gMenuOption); + + } else { + while (!IsHighLightMenuOption (MenuOption)) { + NewPos = NewPos->ForwardLink; + if (NewPos == &gMenuOption) { + // + // Not Found it, break + // + break; + } + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + } + + // + // Highlight statement has disappear (suppressed/disableed) + // + if (NewPos == &gMenuOption) { + NewPos = NULL; + } + } + + return NewPos; +} + +/** + Is this the Top of screen menu. + + @param MenuOption The input Menu option. + + @retval TRUE This is the Top of screen menu option. + @retval FALSE This is not the Top of screen menu option. + +**/ +BOOLEAN +IsTopOfScreeMenuOption ( + IN UI_MENU_OPTION *MenuOption + ) +{ + if (gHighligthMenuInfo.TOSQuestionId != 0) { + return (BOOLEAN) (GetQuestionIdInfo(MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.TOSQuestionId); + } + + if(CompareMem (gHighligthMenuInfo.TOSOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.TOSOpCode->Length) == 0) { + if (gHighligthMenuInfo.TOSIndex == 0 || gHighligthMenuInfo.TOSIndex == GetIndexInfoForOpcode(MenuOption->ThisTag->OpCode)) { + return TRUE; + } else { + return FALSE; + } + } + + return FALSE; +} + +/** + Calculate the distance between two menus and include the skip value of StartMenu. + + @param StartMenu The link_entry pointer to start menu. + @param EndMenu The link_entry pointer to end menu. + +**/ +UINTN +GetDistanceBetweenMenus( + IN LIST_ENTRY *StartMenu, + IN LIST_ENTRY *EndMenu +) +{ + LIST_ENTRY *Link; + UI_MENU_OPTION *MenuOption; + UINTN Distance; + + Distance = 0; + + Link = StartMenu; + while (Link != EndMenu) { + MenuOption = MENU_OPTION_FROM_LINK (Link); + if (MenuOption->Row == 0) { + UpdateOptionSkipLines (MenuOption); + } + Distance += MenuOption->Skip; + Link = Link->BackLink; + } + return Distance; +} + +/** + Find the top of screen menu base on the previous record menu info. + + @param HighLightMenu The link_entry pointer to highlight menu. + + @retval Return the the link_entry pointer top of screen menu. + +**/ +LIST_ENTRY * +FindTopOfScreenMenuOption ( + IN LIST_ENTRY *HighLightMenu + ) +{ + LIST_ENTRY *NewPos; + UI_MENU_OPTION *MenuOption; + UINTN TopRow; + UINTN BottomRow; + + TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; + BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT; + + NewPos = gMenuOption.ForwardLink; + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + + while (!IsTopOfScreeMenuOption(MenuOption)) { + NewPos = NewPos->ForwardLink; + if (NewPos == &gMenuOption) { + // + // Not Found it, break + // + break; + } + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + } + + // + // Last time top of screen menu has disappeared. + // + if (NewPos == &gMenuOption) { + return NULL; + } + // + // Check whether highlight menu and top of screen menu can be shown within one page, + // if can't, return NULL to re-calcaulate the top of scrren menu. Because some new menus + // may be dynamically inserted between highlightmenu and previous top of screen menu, + // So previous record top of screen menu is not appropriate for current display. + // + if (GetDistanceBetweenMenus (HighLightMenu, NewPos) + 1 > BottomRow - TopRow) { + return NULL; + } + + return NewPos; +} + +/** + Find the first menu which will be show at the top. + + @param FormData The data info for this form. + @param TopOfScreen The link_entry pointer to top menu. + @param HighlightMenu The menu which will be highlight. + @param SkipValue The skip value for the top menu. + +**/ +VOID +FindTopMenu ( + IN FORM_DISPLAY_ENGINE_FORM *FormData, + OUT LIST_ENTRY **TopOfScreen, + OUT LIST_ENTRY **HighlightMenu, + OUT UINTN *SkipValue + ) +{ + UINTN TopRow; + UINTN BottomRow; + UI_MENU_OPTION *MenuOption; + UINTN TmpValue; + + TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; + BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT; + // + // When option mismatch happens,there exist two cases,one is reenter the form, just like the if case below, + // and the other is exit current form and enter last form, it can be covered by the else case. + // + if (gMisMatch && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle && gFormData->FormId == gHighligthMenuInfo.FormId) { + // + // Reenter caused by option mismatch or auto exit caused by refresh form(refresh interval/guid), + // base on the record highlight info to find the highlight menu. + // + + *HighlightMenu = FindHighLightMenuOption(NULL); + if (*HighlightMenu != NULL) { + // + // Update skip info for this highlight menu. + // + MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu); + UpdateOptionSkipLines (MenuOption); + + // + // Found the last time highlight menu. + // + *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu); + if (*TopOfScreen != NULL) { + // + // Found the last time selectable top of screen menu. + // + AdjustDateAndTimePosition(TRUE, TopOfScreen); + MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen); + UpdateOptionSkipLines (MenuOption); + + *SkipValue = gHighligthMenuInfo.SkipValue; + } else { + // + // Not found last time top of screen menu, so base on current highlight menu + // to find the new top of screen menu. + // Make the current highlight menu at the bottom of the form to calculate the + // top of screen menu. + // + if (MenuOption->Skip >= BottomRow - TopRow) { + *TopOfScreen = *HighlightMenu; + TmpValue = 0; + } else { + *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue); + } + + *SkipValue = TmpValue; + } + } else { + // + // Last time highlight menu has disappear, find the first highlightable menu as the default one. + // + *HighlightMenu = gMenuOption.ForwardLink; + if (!IsListEmpty (&gMenuOption)) { + MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE); + } + *TopOfScreen = gMenuOption.ForwardLink; + *SkipValue = 0; + } + + } else if (FormData->HighLightedStatement != NULL) { + if (IsSavedHighlightStatement (FormData->HighLightedStatement)) { + // + // Input highlight menu is same as last time highlight menu. + // Base on last time highlight menu to set the top of screen menu and highlight menu. + // + *HighlightMenu = FindHighLightMenuOption(NULL); + ASSERT (*HighlightMenu != NULL); + + // + // Update skip info for this highlight menu. + // + MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu); + UpdateOptionSkipLines (MenuOption); + + *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu); + if (*TopOfScreen == NULL) { + // + // Not found last time top of screen menu, so base on current highlight menu + // to find the new top of screen menu. + // Make the current highlight menu at the bottom of the form to calculate the + // top of screen menu. + // + if (MenuOption->Skip >= BottomRow - TopRow) { + *TopOfScreen = *HighlightMenu; + TmpValue = 0; + } else { + *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue); + } + + *SkipValue = TmpValue; + } else { + AdjustDateAndTimePosition(TRUE, TopOfScreen); + MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen); + UpdateOptionSkipLines (MenuOption); + + *SkipValue = gHighligthMenuInfo.SkipValue; + } + AdjustDateAndTimePosition(TRUE, TopOfScreen); + } else { + // + // Input highlight menu is not save as last time highlight menu. + // + *HighlightMenu = FindHighLightMenuOption(FormData->HighLightedStatement); + MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu); + UpdateOptionSkipLines (MenuOption); + + // + // Make the current highlight menu at the bottom of the form to calculate the + // top of screen menu. + // + if (MenuOption->Skip >= BottomRow - TopRow) { + *TopOfScreen = *HighlightMenu; + TmpValue = 0; + } else { + *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue); + } + + *SkipValue = TmpValue; + } + AdjustDateAndTimePosition(TRUE, TopOfScreen); + } else { + // + // If not has input highlight statement, just return the first one in this form. + // + *TopOfScreen = gMenuOption.ForwardLink; + *HighlightMenu = gMenuOption.ForwardLink; + if (!IsListEmpty (&gMenuOption)) { + MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE); + } + *SkipValue = 0; + } + + gMisMatch = FALSE; + + // + // First enter to show the menu, update highlight info. + // + UpdateHighlightMenuInfo (*HighlightMenu, *TopOfScreen, *SkipValue); +} + +/** + Record the highlight menu and top of screen menu info. + + @param Highlight The menu opton which is highlight. + @param TopOfScreen The menu opton which is at the top of the form. + @param SkipValue The skip line info for the top of screen menu. + +**/ +VOID +UpdateHighlightMenuInfo ( + IN LIST_ENTRY *Highlight, + IN LIST_ENTRY *TopOfScreen, + IN UINTN SkipValue + ) +{ + UI_MENU_OPTION *MenuOption; + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + + gHighligthMenuInfo.HiiHandle = gFormData->HiiHandle; + gHighligthMenuInfo.FormId = gFormData->FormId; + gHighligthMenuInfo.SkipValue = (UINT16)SkipValue; + + if (!IsListEmpty (&gMenuOption)) { + MenuOption = MENU_OPTION_FROM_LINK (Highlight); + Statement = MenuOption->ThisTag; + + gUserInput->SelectedStatement = Statement; + + gHighligthMenuInfo.HLTSequence = MenuOption->Sequence; + gHighligthMenuInfo.HLTQuestionId = GetQuestionIdInfo(Statement->OpCode); + if (gHighligthMenuInfo.HLTQuestionId == 0) { + // + // if question id == 0, save the opcode buffer.. + // + if (gHighligthMenuInfo.HLTOpCode != NULL) { + FreePool (gHighligthMenuInfo.HLTOpCode); + } + gHighligthMenuInfo.HLTOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode); + ASSERT (gHighligthMenuInfo.HLTOpCode != NULL); + + gHighligthMenuInfo.HLTIndex = GetIndexInfoForOpcode(Statement->OpCode); + } + + MenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); + Statement = MenuOption->ThisTag; + + gHighligthMenuInfo.TOSQuestionId = GetQuestionIdInfo(Statement->OpCode); + if (gHighligthMenuInfo.TOSQuestionId == 0) { + // + // if question id == 0, save the opcode buffer.. + // + if (gHighligthMenuInfo.TOSOpCode != NULL) { + FreePool (gHighligthMenuInfo.TOSOpCode); + } + gHighligthMenuInfo.TOSOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode); + ASSERT (gHighligthMenuInfo.TOSOpCode != NULL); + + gHighligthMenuInfo.TOSIndex = GetIndexInfoForOpcode(Statement->OpCode); + } + } else { + gUserInput->SelectedStatement = NULL; + + gHighligthMenuInfo.HLTSequence = 0; + gHighligthMenuInfo.HLTQuestionId = 0; + if (gHighligthMenuInfo.HLTOpCode != NULL) { + FreePool (gHighligthMenuInfo.HLTOpCode); + } + gHighligthMenuInfo.HLTOpCode = NULL; + gHighligthMenuInfo.HLTIndex = 0; + + gHighligthMenuInfo.TOSQuestionId = 0; + if (gHighligthMenuInfo.TOSOpCode != NULL) { + FreePool (gHighligthMenuInfo.TOSOpCode); + } + gHighligthMenuInfo.TOSOpCode = NULL; + gHighligthMenuInfo.TOSIndex = 0; + } +} + +/** + Update attribut for this menu. + + @param MenuOption The menu opton which this attribut used to. + @param Highlight Whether this menu will be highlight. + +**/ +VOID +SetDisplayAttribute ( + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Highlight + ) +{ + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + + Statement = MenuOption->ThisTag; + + if (Highlight) { + gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); + return; + } + + if (MenuOption->GrayOut) { + gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ()); + } else { + if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) { + gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ()); + } else { + gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); + } + } +} + +/** + Print string for this menu option. + + @param MenuOption The menu opton which this attribut used to. + @param Col The column that this string will be print at. + @param Row The row that this string will be print at. + @param String The string which need to print. + @param Width The width need to print, if string is less than the + width, the block space will be used. + @param Highlight Whether this menu will be highlight. + +**/ +VOID +DisplayMenuString ( + IN UI_MENU_OPTION *MenuOption, + IN UINTN Col, + IN UINTN Row, + IN CHAR16 *String, + IN UINTN Width, + IN BOOLEAN Highlight + ) +{ + UINTN Length; + + // + // Print string with normal color. + // + if (!Highlight) { + PrintStringAtWithWidth (Col, Row, String, Width); + return; + } + + // + // Print the highlight menu string. + // First print the highlight string. + // + SetDisplayAttribute(MenuOption, TRUE); + Length = PrintStringAt (Col, Row, String); + + // + // Second, clean the empty after the string. + // + SetDisplayAttribute(MenuOption, FALSE); + PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length); +} + +/** + Check whether this menu can has option string. + + @param MenuOption The menu opton which this attribut used to. @retval TRUE This menu option can have option string. @retval FALSE This menu option can't have option string. -**/ -BOOLEAN -HasOptionString ( - IN UI_MENU_OPTION *MenuOption - ) -{ - FORM_DISPLAY_ENGINE_STATEMENT *Statement; - CHAR16 *String; - UINTN Size; - EFI_IFR_TEXT *TestOp; +**/ +BOOLEAN +HasOptionString ( + IN UI_MENU_OPTION *MenuOption + ) +{ + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + CHAR16 *String; + UINTN Size; + EFI_IFR_TEXT *TestOp; + + Size = 0; + Statement = MenuOption->ThisTag; + + // + // See if the second text parameter is really NULL + // + if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) { + TestOp = (EFI_IFR_TEXT *) Statement->OpCode; + if (TestOp->TextTwo != 0) { + String = GetToken (TestOp->TextTwo, gFormData->HiiHandle); + Size = StrLen (String); + FreePool (String); + } + } + + if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) || + (Statement->OpCode->OpCode == EFI_IFR_REF_OP) || + (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) || + (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) || + (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) || + // + // Allow a wide display if text op-code and no secondary text op-code + // + ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0)) + ) { + + return FALSE; + } + + return TRUE; +} + +/** + Double confirm with user about the action. + + @param Action The user input action. + + @retval TRUE User confirm with the input or not need user confirm. + @retval FALSE User want ignore this input. + +**/ +BOOLEAN +FxConfirmPopup ( + IN UINT32 Action + ) +{ + EFI_INPUT_KEY Key; + CHAR16 *CfmStr; + UINTN CfmStrLen; + UINT32 CheckFlags; + BOOLEAN RetVal; + UINTN CatLen; + UINTN MaxLen; + + CfmStrLen = 0; + CatLen = StrLen (gConfirmMsgConnect); + + // + // Below action need extra popup dialog to confirm. + // + CheckFlags = BROWSER_ACTION_DISCARD | + BROWSER_ACTION_DEFAULT | + BROWSER_ACTION_SUBMIT | + BROWSER_ACTION_RESET | + BROWSER_ACTION_EXIT; + + // + // Not need to confirm with user, just return TRUE. + // + if ((Action & CheckFlags) == 0) { + return TRUE; + } + + if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) { + CfmStrLen += StrLen (gConfirmDiscardMsg); + } + + if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { + if (CfmStrLen != 0) { + CfmStrLen += CatLen; + } + + CfmStrLen += StrLen (gConfirmDefaultMsg); + } + + if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { + if (CfmStrLen != 0) { + CfmStrLen += CatLen; + } + + CfmStrLen += StrLen (gConfirmSubmitMsg); + } - Size = 0; - Statement = MenuOption->ThisTag; + 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); + } // - // See if the second text parameter is really NULL + // Allocate buffer to save the string. + // String + "?" + "\0" // - if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) { - TestOp = (EFI_IFR_TEXT *) Statement->OpCode; - if (TestOp->TextTwo != 0) { - String = GetToken (TestOp->TextTwo, gFormData->HiiHandle); - Size = StrLen (String); - FreePool (String); + 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 ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) || - (Statement->OpCode->OpCode == EFI_IFR_REF_OP) || - (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) || - (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) || - (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) || - // - // Allow a wide display if text op-code and no secondary text op-code - // - ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0)) - ) { + 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); + } + } - return FALSE; + 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); + } } - return TRUE; -} + 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. @@ -1655,9 +2356,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. @@ -1669,7 +2371,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; @@ -1685,6 +2388,7 @@ DisplayOneMenu ( UINTN Temp3; EFI_STATUS Status; UINTN Row; + BOOLEAN IsProcessingFirstRow; UINTN Col; UINTN PromptLineNum; UINTN OptionLineNum; @@ -1699,6 +2403,7 @@ DisplayOneMenu ( PromptLineNum = 0; OptionLineNum = 0; MaxRow = 0; + IsProcessingFirstRow = TRUE; // // Set default color. @@ -1718,14 +2423,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) { @@ -1743,15 +2448,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 // @@ -1770,13 +2476,13 @@ DisplayOneMenu ( } } } - + FreePool (OutputString); if (Temp2 != 0) { Temp2--; } } - + Highlight = FALSE; FreePool (OptionString); @@ -1794,14 +2500,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. // @@ -1810,6 +2516,7 @@ DisplayOneMenu ( Row, GEOMETRICSHAPE_RIGHT_TRIANGLE ); + IsProcessingFirstRow = FALSE; } DisplayMenuString (MenuOption, MenuOption->Col, Row, OutputString, PromptWidth + AdjustValue, Highlight); PromptLineNum ++; @@ -1838,13 +2545,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++; @@ -1855,9 +2562,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--; @@ -1876,7 +2589,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); } @@ -1901,7 +2614,7 @@ UiDisplayMenu ( IN FORM_DISPLAY_ENGINE_FORM *FormData ) { - INTN SkipValue; + UINTN SkipValue; INTN Difference; UINTN DistanceValue; UINTN Row; @@ -1910,12 +2623,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; @@ -1932,10 +2644,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; @@ -1945,14 +2655,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; @@ -1962,7 +2671,6 @@ UiDisplayMenu ( OptionString = NULL; ScreenOperation = UiNoOperation; NewLine = TRUE; - DefaultId = 0; HelpPageCount = 0; HelpLine = 0; RowCount = 0; @@ -1973,33 +2681,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; @@ -2011,6 +2706,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); @@ -2018,7 +2717,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. @@ -2047,7 +2746,7 @@ UiDisplayMenu ( Row = TopRow; gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - + // // 1. Check whether need to print the arrow up. // @@ -2096,25 +2795,31 @@ UiDisplayMenu ( } if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - Status = DisplayOneMenu (MenuOption, + Status = DisplayOneMenu (MenuOption, MenuOption->Col - gStatementDimensions.LeftColumn, - gStatementDimensions.LeftColumn + gModalSkipColumn, - Link == TopOfScreen ? SkipValue : 0, + gStatementDimensions.LeftColumn + gModalSkipColumn, + Link == TopOfScreen ? SkipValue : 0, BottomRow, - (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)) + (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)), + TRUE ); } else { - Status = DisplayOneMenu (MenuOption, + Status = DisplayOneMenu (MenuOption, MenuOption->Col - gStatementDimensions.LeftColumn, - gStatementDimensions.LeftColumn, - Link == TopOfScreen ? SkipValue : 0, + 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. @@ -2165,10 +2870,6 @@ UiDisplayMenu ( } MenuOption = NULL; - - if (IsListEmpty (&gMenuOption)) { - ControlFlag = CfReadKey; - } } break; @@ -2181,10 +2882,20 @@ UiDisplayMenu ( // ControlFlag = CfUpdateHelpString; + 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; } @@ -2202,166 +2913,36 @@ UiDisplayMenu ( if (NewPos != NULL && (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 - 1; - 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, 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 - 1; - - 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 (MenuOption, 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; @@ -2371,16 +2952,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; @@ -2416,7 +3024,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 { @@ -2430,14 +3038,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, @@ -2485,7 +3093,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, @@ -2505,20 +3113,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, @@ -2563,7 +3171,7 @@ UiDisplayMenu ( if (Status != EFI_NOT_READY) { continue; } - + EventType = UiWaitForEvent(gST->ConIn->WaitForKey); if (EventType == UIEventKey) { gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); @@ -2572,11 +3180,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; @@ -2604,12 +3213,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) @@ -2620,7 +3229,7 @@ UiDisplayMenu ( } else { gDirection = SCAN_LEFT; } - + Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE); if (OptionString != NULL) { FreePool (OptionString); @@ -2651,7 +3260,7 @@ UiDisplayMenu ( ControlFlag = CfReadKey; break; } - + ASSERT(MenuOption != NULL); if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) { ScreenOperation = UiSelect; @@ -2685,7 +3294,7 @@ UiDisplayMenu ( break; } } - + if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) { // // ModalForm has no ESC key and Hot Key. @@ -2706,9 +3315,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)) { @@ -2718,7 +3327,7 @@ UiDisplayMenu ( } for (Index = 0; - Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]); + Index < ARRAY_SIZE (gScreenOperationToControlFlag); Index++ ) { if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) { @@ -2750,11 +3359,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; @@ -2779,22 +3388,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: @@ -2827,230 +3441,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 { - if (NewPos->ForwardLink == &gMenuOption) { - NewLine = FALSE; - Repaint = FALSE; - break; - } - // - // Scroll up to the last page. - // - NewPos = &gMenuOption; - TopOfScreen = &gMenuOption; - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - ScreenOperation = UiPageUp; - ControlFlag = CfScreenOperation; - SkipValue = 0; - } - 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)) { - 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); - if (Index < PreviousMenuOption->Skip) { - Repaint = TRUE; - SkipValue = PreviousMenuOption->Skip - (Index - TopRow); - } else { - Repaint = FALSE; - SkipValue = 0; - } - } 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. // - if (SkipValue == 0) { - Repaint = FALSE; - } - NewPos = Link; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); - SkipValue = 0; + 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) { - MenuOption = MENU_OPTION_FROM_LINK (NewPos); - if (SkipValue + BottomRow - TopRow + 1 < MenuOption->Skip) { - SkipValue += BottomRow - TopRow + 1; - NewLine = TRUE; - Repaint = TRUE; - break; - } - 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; @@ -3065,10 +3578,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. @@ -3081,13 +3594,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); } // @@ -3095,12 +3607,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: @@ -3109,7 +3625,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 @@ -3118,187 +3642,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) { - if (NewPos == TopOfScreen) { - Temp2 = SkipValue; + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + NewPos = NewPos->ForwardLink; + // + // Find the next selectable menu. + // + if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) { + if (gMenuOption.ForwardLink == NewPos || &gMenuOption == NewPos) { + Difference = -1; + } else { + Difference = 0; + } + } else { + Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE); + } + if (Difference < 0) { + // + // Scroll to the first page. + // + if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) { + TopOfScreen = gMenuOption.ForwardLink; + Repaint = TRUE; + MenuOption = NULL; } else { - Temp2 = 0; + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); } + NewPos = gMenuOption.ForwardLink; + MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, TRUE); + + SkipValue = 0; + // + // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); - MenuOption = MENU_OPTION_FROM_LINK (NewPos); - NewLine = TRUE; - NewPos = NewPos->ForwardLink; + UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue); + break; + } + + // + // Get next selected menu info. + // + AdjustDateAndTimePosition (FALSE, &NewPos); + NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); + if (NextMenuOption->Row == 0) { + UpdateOptionSkipLines (NextMenuOption); + } + + // + // Calculate new highlight menu end row. + // + Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1; + if (Temp > BottomRow) { + // + // Get the top screen menu info. + // + AdjustDateAndTimePosition (FALSE, &TopOfScreen); + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - Difference = 0; // - // Current menu not at the bottom of the form. + // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows. + // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows. // - if (BottomRow >= MenuOption->Row + MenuOption->Skip - Temp2) { + if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) { // - // Find the next selectable menu. + // Skip the top op-code // - Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip + Temp2); - // - // 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); + TopOfScreen = TopOfScreen->ForwardLink; + DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue); - 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 - Temp2; - - Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1; - if ((MenuOption->Row + MenuOption->Skip - Temp2 == BottomRow + 1) && - (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || - NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) - ) { - Temp ++; - } + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - // - // If we are going to scroll, update TopOfScreen - // - if (Temp > BottomRow) { - do { + // + // 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) { // - // Is the current top of screen a zero-advance op-code? - // If so, keep moving forward till we hit a >0 advance op-code + // 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); - - // - // 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); - - Repaint = TRUE; - } else if (!IsSelectable (NextMenuOption)) { + } // - // Continue to go down until scroll to next page or the selectable option is found. + // 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. // - ScreenOperation = UiDown; - ControlFlag = CfScreenOperation; - } - - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - - UpdateStatusBar (INPUT_ERROR, FALSE); - - } else { - // - // Scroll to the first page. - // - if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) { - TopOfScreen = gMenuOption.ForwardLink; - Repaint = TRUE; - MenuOption = NULL; + 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: @@ -3324,6 +3804,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. @@ -3334,14 +3842,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) { @@ -3349,10 +3899,6 @@ BrowserStatusProcess ( ErrorInfo = gSaveFailed; break; - case BROWSER_NO_SUBMIT_IF: - ErrorInfo = gNoSubmitIf; - break; - case BROWSER_FORM_NOT_FOUND: ErrorInfo = gFormNotFound; break; @@ -3365,33 +3911,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 @@ -3411,24 +4055,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)) { @@ -3438,7 +4095,7 @@ FormDisplay ( } Status = UiDisplayMenu(FormData); - + // // Backup last form info. // @@ -3447,6 +4104,11 @@ FormDisplay ( CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid); gOldFormEntry.FormId = FormData->FormId; + // + //Free the Ui menu option list. + // + FreeMenuOptionData(&gMenuOption); + return Status; } @@ -3454,7 +4116,7 @@ FormDisplay ( Clear Screen to the initial state. **/ VOID -EFIAPI +EFIAPI DriverClearDisplayPage ( VOID ) @@ -3530,14 +4192,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)) { // @@ -3548,11 +4221,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; @@ -3577,5 +4252,13 @@ UnloadDisplayEngine ( FreeDisplayStrings (); + if (gHighligthMenuInfo.HLTOpCode != NULL) { + FreePool (gHighligthMenuInfo.HLTOpCode); + } + + if (gHighligthMenuInfo.TOSOpCode != NULL) { + FreePool (gHighligthMenuInfo.TOSOpCode); + } + return EFI_SUCCESS; }