EFI_STATUS Status;\r
UI_MENU_SELECTION *Selection;\r
FORM_BROWSER_STATEMENT *Question;\r
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
\r
if (gMenuRefreshHead != NULL) {\r
\r
mHiiPackageListUpdated = FALSE;\r
\r
do {\r
- gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
-\r
Selection = MenuRefreshEntry->Selection;\r
Question = MenuRefreshEntry->MenuOption->ThisTag;\r
\r
for (Index = 0; OptionString[Index] == L' '; Index++)\r
;\r
\r
+ //\r
+ // If old Text is longer than new string, need to clean the old string before paint the newer.\r
+ // This option is no need for time/date opcode, because time/data opcode has fixed string length.\r
+ //\r
+ if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) &&\r
+ (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) {\r
+ ClearLines (\r
+ MenuRefreshEntry->CurrentColumn, \r
+ MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1,\r
+ MenuRefreshEntry->CurrentRow,\r
+ MenuRefreshEntry->CurrentRow,\r
+ PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
+ );\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, &OptionString[Index]);\r
FreePool (OptionString);\r
}\r
//\r
// Question value may be changed, need invoke its Callback()\r
//\r
- ConfigAccess = Selection->FormSet->ConfigAccess;\r
- if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
- Status = ConfigAccess->Callback (\r
- ConfigAccess,\r
- EFI_BROWSER_ACTION_CHANGING,\r
- Question->QuestionId,\r
- Question->HiiValue.Type,\r
- &Question->HiiValue.Value,\r
- &ActionRequest\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- switch (ActionRequest) {\r
- case EFI_BROWSER_ACTION_REQUEST_RESET:\r
- gResetRequired = TRUE;\r
- break;\r
-\r
- case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
- SubmitForm (Selection->FormSet, Selection->Form);\r
- break;\r
-\r
- case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
- Selection->Action = UI_ACTION_EXIT;\r
- gNvUpdateRequired = FALSE;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- }\r
+ Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
MenuRefreshEntry = MenuRefreshEntry->Next;\r
MenuOption->IsQuestion = TRUE;\r
break;\r
\r
+ case EFI_IFR_TEXT_OP:\r
+ if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {\r
+ //\r
+ // Initializing GrayOut option as TRUE for Text setup options \r
+ // so that those options will be Gray in colour and un selectable.\r
+ //\r
+ MenuOption->GrayOut = TRUE;\r
+ }\r
+\r
default:\r
MenuOption->IsQuestion = FALSE;\r
break;\r
/**\r
Update status bar on the bottom of menu.\r
\r
+ @param Selection Current Selction info.\r
@param MessageType The type of message to be shown.\r
@param Flags The flags in Question header.\r
@param State Set or clear.\r
**/\r
VOID\r
UpdateStatusBar (\r
+ IN UI_MENU_SELECTION *Selection,\r
IN UINTN MessageType,\r
IN UINT8 Flags,\r
IN BOOLEAN State\r
);\r
gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));\r
\r
- gNvUpdateRequired = TRUE;\r
+ if (Selection != NULL) {\r
+ Selection->Form->NvUpdateRequired = TRUE;\r
+ }\r
} else {\r
gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {\r
);\r
}\r
\r
- gNvUpdateRequired = FALSE;\r
+ if (Selection != NULL) {\r
+ Selection->Form->NvUpdateRequired = FALSE;\r
+ }\r
}\r
}\r
break;\r
\r
case REFRESH_STATUS_BAR:\r
if (mInputError) {\r
- UpdateStatusBar (INPUT_ERROR, Flags, TRUE);\r
+ UpdateStatusBar (Selection, INPUT_ERROR, Flags, TRUE);\r
}\r
\r
- if (gNvUpdateRequired) {\r
- UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);\r
+ if (IsNvUpdateRequired(Selection->FormSet)) {\r
+ UpdateStatusBar (NULL, NV_UPDATE_REQUIRED, Flags, TRUE);\r
}\r
break;\r
\r
)\r
{\r
LIST_ENTRY *Temp;\r
- UI_MENU_OPTION *MenuOption;\r
\r
Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
\r
return TRUE;\r
}\r
\r
- for (; Temp != &gMenuOption; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {\r
- MenuOption = MENU_OPTION_FROM_LINK (Temp);\r
- if (IsSelectable (MenuOption)) {\r
- return FALSE;\r
- }\r
- }\r
-\r
- return TRUE;\r
+ return FALSE;\r
}\r
\r
\r
\r
@param GoUp The navigation direction. TRUE: up, FALSE: down.\r
@param CurrentPosition Current position.\r
+ @param GapToTop Gap position to top or bottom.\r
\r
@return The row distance from current MenuOption to next selectable MenuOption.\r
\r
INTN\r
MoveToNextStatement (\r
IN BOOLEAN GoUp,\r
- IN OUT LIST_ENTRY **CurrentPosition\r
+ IN OUT LIST_ENTRY **CurrentPosition,\r
+ IN UINTN GapToTop\r
)\r
{\r
INTN Distance;\r
LIST_ENTRY *Pos;\r
- BOOLEAN HitEnd;\r
UI_MENU_OPTION *NextMenuOption;\r
+ UI_MENU_OPTION *PreMenuOption;\r
\r
- Distance = 0;\r
- Pos = *CurrentPosition;\r
- HitEnd = FALSE;\r
+ Distance = 0;\r
+ Pos = *CurrentPosition;\r
+ PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
\r
while (TRUE) {\r
NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+ if (GoUp && (PreMenuOption != NextMenuOption)) {\r
+ //\r
+ // Current Position doesn't need to be caculated when go up.\r
+ // Caculate distanct at first when go up\r
+ //\r
+ if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+ NextMenuOption = PreMenuOption;\r
+ break;\r
+ }\r
+ Distance += NextMenuOption->Skip;\r
+ }\r
if (IsSelectable (NextMenuOption)) {\r
break;\r
}\r
if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
- HitEnd = TRUE;\r
+ //\r
+ // Arrive at top.\r
+ //\r
+ Distance = -1;\r
break;\r
}\r
- Distance += NextMenuOption->Skip;\r
- Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
- }\r
-\r
- if (HitEnd) {\r
- //\r
- // If we hit end there is still no statement can be focused,\r
- // we go backwards to find the statement can be focused.\r
- //\r
- Distance = 0;\r
- Pos = *CurrentPosition;\r
-\r
- while (TRUE) {\r
- NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
- if (IsSelectable (NextMenuOption)) {\r
- break;\r
- }\r
- if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
- ASSERT (FALSE);\r
+ if (!GoUp) {\r
+ //\r
+ // Caculate distanct at later when go down\r
+ //\r
+ if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+ NextMenuOption = PreMenuOption;\r
break;\r
}\r
- Distance -= NextMenuOption->Skip;\r
- Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+ Distance += NextMenuOption->Skip;\r
}\r
+ PreMenuOption = NextMenuOption;\r
+ Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
}\r
\r
*CurrentPosition = &NextMenuOption->Link;\r
CHAR16 *OptionString;\r
CHAR16 *OutputString;\r
CHAR16 *FormattedString;\r
- CHAR16 YesResponse;\r
- CHAR16 NoResponse;\r
BOOLEAN NewLine;\r
BOOLEAN Repaint;\r
BOOLEAN SavedValue;\r
BOOLEAN UpArrow;\r
BOOLEAN DownArrow;\r
+ BOOLEAN InitializedFlag;\r
EFI_STATUS Status;\r
EFI_INPUT_KEY Key;\r
LIST_ENTRY *Link;\r
CurrentMenu = UiAddMenuList (NULL, &Selection->FormSetGuid, Selection->FormId);\r
}\r
ASSERT (CurrentMenu != NULL);\r
+ Selection->CurrentMenu = CurrentMenu;\r
\r
if (Selection->QuestionId == 0) {\r
//\r
}\r
\r
//\r
- // Get user's selection\r
+ // Init option as the current user's selection\r
//\r
+ InitializedFlag = TRUE;\r
NewPos = gMenuOption.ForwardLink;\r
\r
gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
- UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);\r
+ UpdateStatusBar (Selection, REFRESH_STATUS_BAR, (UINT8) 0, TRUE);\r
\r
ControlFlag = CfInitialization;\r
Selection->Action = UI_ACTION_NONE;\r
Width = GetWidth (Statement, MenuOption->Handle);\r
OriginalRow = Row;\r
\r
- if (Statement->Operand == EFI_IFR_REF_OP && \r
- MenuOption->Col >= 2) {\r
+ if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
//\r
// Print Arrow for Goto button.\r
//\r
// NewPos: Current menu option that need to hilight\r
//\r
ControlFlag = CfUpdateHelpString;\r
+ if (InitializedFlag) {\r
+ InitializedFlag = FALSE;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ }\r
\r
//\r
// Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily\r
}\r
\r
//\r
- // This is only possible if we entered this page and the first menu option is\r
- // a "non-menu" item. In that case, force it UiDown\r
+ // This is the current selected statement\r
//\r
MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ Statement = MenuOption->ThisTag;\r
+ Selection->Statement = Statement;\r
if (!IsSelectable (MenuOption)) {\r
- ASSERT (ScreenOperation == UiNoOperation);\r
- ScreenOperation = UiDown;\r
- ControlFlag = CfScreenOperation;\r
+ Repaint = SavedValue;\r
+ UpdateKeyHelp (Selection, MenuOption, FALSE);\r
break;\r
}\r
\r
- //\r
- // This is the current selected statement\r
- //\r
- Statement = MenuOption->ThisTag;\r
- Selection->Statement = Statement;\r
//\r
// Record highlight for current menu\r
//\r
//\r
if (gMenuRefreshHead != NULL) {\r
for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {\r
- if (MenuOption->GrayOut) {\r
+ if (MenuRefreshEntry->MenuOption->GrayOut) {\r
MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
} else { \r
MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
case CfUpdateHelpString:\r
ControlFlag = CfPrepareToReadKey;\r
\r
- if (Repaint || NewLine) {\r
+ if (Repaint || NewLine) {\r
//\r
// Don't print anything if it is a NULL help token\r
//\r
ASSERT(MenuOption != NULL);\r
- if (MenuOption->ThisTag->Help == 0) {\r
+ if (MenuOption->ThisTag->Help == 0 || !IsSelectable (MenuOption)) {\r
StringPtr = L"\0";\r
} else {\r
StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
ControlFlag = CfReadKey;\r
break;\r
}\r
- //\r
- // if there is nothing logical to place a cursor on, just move on to wait for a key.\r
- //\r
- for (Link = gMenuOption.ForwardLink; Link != &gMenuOption; Link = Link->ForwardLink) {\r
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- if (IsSelectable (NextMenuOption)) {\r
- break;\r
- }\r
- }\r
-\r
- if (Link == &gMenuOption) {\r
- ControlFlag = CfPrepareToReadKey;\r
- break;\r
- }\r
}\r
\r
for (Index = 0;\r
// We come here when someone press ESC\r
//\r
ControlFlag = CfCheckSelection;\r
-\r
- if (CurrentMenu->Parent != NULL) {\r
- //\r
- // we have a parent, so go to the parent menu\r
- //\r
- if (CompareGuid (&CurrentMenu->FormSetGuid, &CurrentMenu->Parent->FormSetGuid)) {\r
- //\r
- // The parent menu and current menu are in the same formset\r
- //\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- } else {\r
- Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
- }\r
- Selection->Statement = NULL;\r
-\r
- Selection->FormId = CurrentMenu->Parent->FormId;\r
- Selection->QuestionId = CurrentMenu->Parent->QuestionId;\r
-\r
- //\r
- // Clear highlight record for this menu\r
- //\r
- CurrentMenu->QuestionId = 0;\r
- break;\r
- }\r
-\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
- //\r
- // We never exit FrontPage, so skip the ESC\r
- //\r
- Selection->Action = UI_ACTION_NONE;\r
- break;\r
- }\r
-\r
- //\r
- // We are going to leave current FormSet, so check uncommited data in this FormSet\r
- //\r
- if (gNvUpdateRequired) {\r
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
- YesResponse = gYesResponse[0];\r
- NoResponse = gNoResponse[0];\r
-\r
- //\r
- // If NV flag is up, prompt user\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
- } while\r
- (\r
- (Key.ScanCode != SCAN_ESC) &&\r
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
- );\r
-\r
- if (Key.ScanCode == SCAN_ESC) {\r
- //\r
- // User hits the ESC key\r
- //\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
-\r
- Selection->Action = UI_ACTION_NONE;\r
- break;\r
- }\r
-\r
- //\r
- // If the user hits the YesResponse key\r
- //\r
- if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
- Status = SubmitForm (Selection->FormSet, Selection->Form);\r
- }\r
- }\r
-\r
- Selection->Action = UI_ACTION_EXIT;\r
- Selection->Statement = NULL;\r
- CurrentMenu->QuestionId = 0;\r
-\r
- return EFI_SUCCESS;\r
+ if (FindNextMenu (Selection, &Repaint, &NewLine)) {\r
+ return EFI_SUCCESS;\r
+ } \r
+ break;\r
\r
case CfUiLeft:\r
ControlFlag = CfCheckSelection;\r
case CfUiUp:\r
ControlFlag = CfCheckSelection;\r
\r
- SavedListEntry = TopOfScreen;\r
+ SavedListEntry = NewPos;\r
\r
ASSERT(NewPos != NULL);\r
+ //\r
+ // Adjust Date/Time position before we advance forward.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
if (NewPos->BackLink != &gMenuOption) {\r
- NewLine = TRUE;\r
- //\r
- // Adjust Date/Time position before we advance forward.\r
- //\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
-\r
- //\r
- // Caution that we have already rewind to the top, don't go backward in this situation.\r
- //\r
- if (NewPos->BackLink != &gMenuOption) {\r
- NewPos = NewPos->BackLink;\r
- }\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ NewLine = TRUE;\r
+ NewPos = NewPos->BackLink;\r
\r
- Difference = MoveToNextStatement (TRUE, &NewPos);\r
PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
DistanceValue = PreviousMenuOption->Skip;\r
-\r
- //\r
- // Since the behavior of hitting the up arrow on a Date/Time op-code is intended\r
- // to be one that back to the previous set of op-codes, we need to advance to the sencond\r
- // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
- // checking can be done.\r
- //\r
- DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);\r
- \r
+ Difference = 0;\r
+ if (MenuOption->Row >= DistanceValue + TopRow) {\r
+ Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);\r
+ }\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ \r
ASSERT (MenuOption != NULL);\r
if (Difference < 0) {\r
//\r
- // We want to goto previous MenuOption, but finally we go down.\r
- // it means that we hit the begining MenuOption that can be focused\r
- // so we simply scroll to the top\r
+ // We hit the begining MenuOption that can be focused\r
+ // so we simply scroll to the top.\r
//\r
- if (SavedListEntry != gMenuOption.ForwardLink) {\r
+ if (TopOfScreen != gMenuOption.ForwardLink) {\r
TopOfScreen = gMenuOption.ForwardLink;\r
Repaint = TRUE;\r
+ } else {\r
+ //\r
+ // Scroll up to the last page when we have arrived at top page.\r
+ //\r
+ NewPos = &gMenuOption;\r
+ TopOfScreen = &gMenuOption;\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ ScreenOperation = UiPageUp;\r
+ ControlFlag = CfScreenOperation;\r
+ break;\r
}\r
- } else if ((INTN) MenuOption->Row - (INTN) DistanceValue - Difference < (INTN) TopRow) {\r
+ } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {\r
//\r
// Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
//\r
Repaint = TRUE;\r
SkipValue = 0;\r
OldSkipValue = 0;\r
+ } else if (!IsSelectable (NextMenuOption)) {\r
+ //\r
+ // Continue to go up until scroll to next page or the selectable option is found.\r
+ //\r
+ ScreenOperation = UiUp;\r
+ ControlFlag = CfScreenOperation;\r
}\r
\r
//\r
// If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
//\r
AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
-\r
- UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
} else {\r
- SavedMenuOption = MenuOption;\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- if (!IsSelectable (MenuOption)) {\r
- //\r
- // If we are at the end of the list and sitting on a text op, we need to more forward\r
- //\r
- ScreenOperation = UiDown;\r
- ControlFlag = CfScreenOperation;\r
- break;\r
- }\r
-\r
- MenuOption = SavedMenuOption;\r
+ //\r
+ // Scroll up to the last page.\r
+ //\r
+ NewPos = &gMenuOption;\r
+ TopOfScreen = &gMenuOption;\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ ScreenOperation = UiPageUp;\r
+ ControlFlag = CfScreenOperation;\r
}\r
break;\r
\r
NewLine = TRUE;\r
Repaint = TRUE;\r
Link = TopOfScreen;\r
- PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- Index = BottomRow;\r
+ Index = BottomRow;\r
while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) {\r
- Index = Index - PreviousMenuOption->Skip;\r
Link = Link->BackLink;\r
PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ if (Index < PreviousMenuOption->Skip) {\r
+ Index = 0;\r
+ break;\r
+ }\r
+ Index = Index - PreviousMenuOption->Skip;\r
}\r
+ \r
+ if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
+ if (TopOfScreen == &gMenuOption) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ NewPos = gMenuOption.BackLink;\r
+ MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
+ Repaint = FALSE;\r
+ } else if (TopOfScreen != Link) {\r
+ TopOfScreen = Link;\r
+ NewPos = Link;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ } else {\r
+ //\r
+ // Finally we know that NewPos is the last MenuOption can be focused.\r
+ //\r
+ Repaint = FALSE;\r
+ NewPos = Link;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ }\r
+ } else {\r
+ if (Index + 1 < TopRow) {\r
+ //\r
+ // Back up the previous option.\r
+ //\r
+ Link = Link->ForwardLink;\r
+ }\r
\r
- TopOfScreen = Link;\r
- Difference = MoveToNextStatement (TRUE, &Link);\r
- if (Difference > 0) {\r
//\r
- // The focus MenuOption is above the TopOfScreen\r
+ // Move to the option in Next page.\r
//\r
- TopOfScreen = Link;\r
- } else if (Difference < 0) {\r
+ if (TopOfScreen == &gMenuOption) {\r
+ NewPos = gMenuOption.BackLink;\r
+ MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
+ } else {\r
+ NewPos = Link;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ }\r
+\r
//\r
- // This happens when there is no MenuOption can be focused from\r
- // Current MenuOption to the first MenuOption\r
+ // There are more MenuOption needing scrolling up.\r
//\r
- TopOfScreen = gMenuOption.ForwardLink;\r
- }\r
- Index += Difference;\r
- if (Index < TopRow) {\r
- MenuOption = NULL;\r
- }\r
-\r
- if (NewPos == Link) {\r
- Repaint = FALSE;\r
- NewLine = FALSE;\r
- } else {\r
- NewPos = Link;\r
+ TopOfScreen = Link;\r
+ MenuOption = NULL;\r
}\r
\r
//\r
NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
}\r
\r
- Index += MoveToNextStatement (FALSE, &Link);\r
- if (Index > BottomRow) {\r
+ if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow)) {\r
+ //\r
+ // Finally we know that NewPos is the last MenuOption can be focused.\r
+ //\r
+ Repaint = FALSE;\r
+ MoveToNextStatement (TRUE, &Link, Index - TopRow);\r
+ } else {\r
+ if (Index - 1 > BottomRow) {\r
+ //\r
+ // Back up the previous option.\r
+ //\r
+ Link = Link->BackLink;\r
+ }\r
//\r
- // There are more MenuOption needing scrolling\r
+ // There are more MenuOption needing scrolling down.\r
//\r
TopOfScreen = Link;\r
MenuOption = NULL;\r
- }\r
- if (NewPos == Link && Index <= BottomRow) {\r
//\r
- // Finally we know that NewPos is the last MenuOption can be focused.\r
+ // Move to the option in Next page.\r
//\r
- NewLine = FALSE;\r
- Repaint = FALSE;\r
- } else {\r
- NewPos = Link;\r
+ MoveToNextStatement (FALSE, &Link, BottomRow - TopRow);\r
}\r
\r
//\r
// If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
// Don't do this when we are already in the last page.\r
//\r
+ NewPos = Link;\r
AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
AdjustDateAndTimePosition (TRUE, &NewPos);\r
break;\r
// the Date/Time op-code.\r
//\r
SavedListEntry = NewPos;\r
- DistanceValue = AdjustDateAndTimePosition (FALSE, &NewPos);\r
+ AdjustDateAndTimePosition (FALSE, &NewPos);\r
\r
if (NewPos->ForwardLink != &gMenuOption) {\r
MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
NewLine = TRUE;\r
NewPos = NewPos->ForwardLink;\r
\r
- DistanceValue += MoveToNextStatement (FALSE, &NewPos);\r
+ Difference = 0;\r
+ if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
+ Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
+ //\r
+ // We hit the end of MenuOption that can be focused\r
+ // so we simply scroll to the first page.\r
+ //\r
+ if (Difference < 0) {\r
+ //\r
+ // Scroll to the first page.\r
+ //\r
+ if (TopOfScreen != gMenuOption.ForwardLink) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ Repaint = TRUE;\r
+ MenuOption = NULL;\r
+ } else {\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ }\r
+ NewPos = gMenuOption.ForwardLink;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ \r
+ //\r
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+ }\r
+ }\r
NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
\r
//\r
// An option might be multi-line, so we need to reflect that data in the overall skip value\r
//\r
UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, (UINTN) SkipValue);\r
- DistanceValue += NextMenuOption->Skip;\r
+ DistanceValue = Difference + NextMenuOption->Skip;\r
\r
Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
\r
Repaint = TRUE;\r
OldSkipValue = SkipValue;\r
+ } else if (!IsSelectable (NextMenuOption)) {\r
+ //\r
+ // Continue to go down until scroll to next page or the selectable option is found.\r
+ //\r
+ ScreenOperation = UiDown;\r
+ ControlFlag = CfScreenOperation;\r
}\r
\r
MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
\r
- UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+ UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
\r
} else {\r
- SavedMenuOption = MenuOption;\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- if (!IsSelectable (MenuOption)) {\r
- //\r
- // If we are at the end of the list and sitting on a text op, we need to more forward\r
- //\r
- ScreenOperation = UiUp;\r
- ControlFlag = CfScreenOperation;\r
- break;\r
- }\r
-\r
- MenuOption = SavedMenuOption;\r
//\r
- // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+ // Scroll to the first page.\r
//\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ if (TopOfScreen != gMenuOption.ForwardLink) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ Repaint = TRUE;\r
+ MenuOption = NULL;\r
+ } else {\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ }\r
+ NewLine = TRUE;\r
+ NewPos = gMenuOption.ForwardLink;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
}\r
+\r
+ //\r
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
break;\r
\r
case CfUiSave:\r
//\r
// Submit the form\r
//\r
- Status = SubmitForm (Selection->FormSet, Selection->Form);\r
+ Status = SubmitForm (Selection->FormSet, Selection->Form, FALSE);\r
\r
if (!EFI_ERROR (Status)) {\r
ASSERT(MenuOption != NULL);\r
- UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
- UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+ UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+ UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
} else {\r
do {\r
CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveFailed, gPressEnter, gEmptyString);\r
//\r
// Show NV update flag on status bar\r
//\r
- gNvUpdateRequired = TRUE;\r
+ UpdateNvInfoInForm(Selection->FormSet, TRUE);\r
+ gResetRequired = TRUE;\r
}\r
break;\r
\r