/**\r
Get the supported width for a particular op-code\r
\r
- @param Statement The curent statement.\r
+ @param MenuOption The menu option.\r
@param AdjustWidth The width which is saved for the space.\r
\r
@return Returns the number of CHAR16 characters that is support.\r
**/\r
UINT16\r
GetWidth (\r
- IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
- OUT UINT16 *AdjustWidth\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ OUT UINT16 *AdjustWidth\r
)\r
{\r
- CHAR16 *String;\r
- UINTN Size;\r
- EFI_IFR_TEXT *TestOp;\r
+ CHAR16 *String;\r
+ UINTN Size;\r
+ EFI_IFR_TEXT *TestOp;\r
+ UINT16 ReturnWidth;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+\r
+ Statement = MenuOption->ThisTag;\r
\r
//\r
// For modal form, clean the entire row.\r
//\r
// Keep consistent with current behavior.\r
//\r
- return (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2);\r
+ ReturnWidth = (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2);\r
+ } else {\r
+ if (AdjustWidth != NULL) {\r
+ *AdjustWidth = 1;\r
+ }\r
+\r
+ ReturnWidth = (UINT16) (gPromptBlockWidth - 1);\r
}\r
\r
- if (AdjustWidth != NULL) {\r
- *AdjustWidth = 1;\r
+ //\r
+ // For nest in statement, should the subtitle indent.\r
+ //\r
+ if (MenuOption->NestInStatement) {\r
+ ReturnWidth -= SUBTITLE_INDENT;\r
}\r
- return (UINT16) (gPromptBlockWidth - 1);\r
+\r
+ return ReturnWidth;\r
}\r
\r
/**\r
String = GetToken (PromptId, gFormData->HiiHandle);\r
ASSERT (String != NULL);\r
\r
- Width = GetWidth (Statement, NULL);\r
- for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&String[ArrayEntry]) != 0) {\r
- NumberOfLines++;\r
- }\r
- FreePool (OutputString);\r
- }\r
-\r
if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
- //\r
- // Add three MenuOptions for Date/Time\r
- // Data format : [01/02/2004] [11:22:33]\r
- // Line number : 0 0 1 0 0 1\r
- //\r
- NumberOfLines = 0;\r
Count = 3;\r
}\r
\r
MenuOption->NestInStatement = NestIn;\r
MenuOption->EntryNumber = *MenuItemCount;\r
\r
- if (Index == 2) {\r
- //\r
- // Override LineNumber for the MenuOption in Date/Time sequence\r
- //\r
- MenuOption->Skip = 1;\r
- } else {\r
- MenuOption->Skip = NumberOfLines;\r
- }\r
MenuOption->Sequence = Index;\r
\r
if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) {\r
}\r
}\r
\r
+ if (Index == 0 && \r
+ (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) && \r
+ (Statement->OpCode->OpCode != EFI_IFR_TIME_OP)) {\r
+ Width = GetWidth (MenuOption, NULL);\r
+ for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&String[ArrayEntry]) != 0) {\r
+ NumberOfLines++;\r
+ }\r
+ FreePool (OutputString);\r
+ }\r
+ } else {\r
+ //\r
+ // Add three MenuOptions for Date/Time\r
+ // Data format : [01/02/2004] [11:22:33]\r
+ // Line number : 0 0 1 0 0 1\r
+ // \r
+ NumberOfLines = 0;\r
+ }\r
+\r
+ if (Index == 2) {\r
+ //\r
+ // Override LineNumber for the MenuOption in Date/Time sequence\r
+ //\r
+ MenuOption->Skip = 1;\r
+ } else {\r
+ MenuOption->Skip = NumberOfLines;\r
+ }\r
+\r
InsertTailList (&gMenuOption, &MenuOption->Link);\r
}\r
\r
NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);\r
NestLink = GetNextNode (&Statement->NestStatementList, NestLink);\r
\r
+ //\r
+ // Skip the opcode not recognized by Display core.\r
+ //\r
+ if (NestStatement->OpCode->OpCode == EFI_IFR_GUID_OP) {\r
+ continue;\r
+ }\r
+\r
UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);\r
}\r
}\r
}\r
}\r
\r
+/**\r
+ Check whether this Menu Option could be print.\r
+\r
+ Check Prompt string, option string or text two string not NULL.\r
+\r
+ This is an internal function.\r
+\r
+ @param MenuOption The MenuOption to be checked.\r
+\r
+ @retval TRUE This Menu Option is printable.\r
+ @retval FALSE This Menu Option could not be printable.\r
+\r
+**/\r
+BOOLEAN\r
+PrintableMenu (\r
+ UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING OptionString;\r
+\r
+ OptionString = NULL;\r
+\r
+ if (MenuOption->Description[0] != '\0') {\r
+ return TRUE;\r
+ }\r
+\r
+ Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+ if (OptionString != NULL && OptionString[0] != '\0') {\r
+ FreePool (OptionString);\r
+ return TRUE;\r
+ }\r
+\r
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {\r
+ OptionString = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);\r
+ ASSERT (OptionString != NULL);\r
+ if (OptionString[0] != '\0'){\r
+ FreePool (OptionString);\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
/**\r
Check whether this Menu Option could be highlighted.\r
\r
)\r
{\r
if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
- MenuOption->GrayOut || MenuOption->ReadOnly) {\r
+ MenuOption->GrayOut || MenuOption->ReadOnly || !PrintableMenu (MenuOption)) {\r
return FALSE;\r
} else {\r
return TRUE;\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
+ @param FindInForm Whether find menu in current form or beyond.\r
\r
@return The row distance from current MenuOption to next selectable MenuOption.\r
\r
@retval -1 Reach the begin of the menu, still can't find the selectable menu.\r
- @retval Value Find the selectable menu, maybe the truly selectable, maybe the l\r
- last menu showing at current form.\r
+ @retval Value Find the selectable menu, maybe the truly selectable, maybe the \r
+ first menu showing beyond current form or last menu showing in \r
+ current form.\r
+ The value is the line number between the new selected menu and the\r
+ current select menu, not include the new selected menu.\r
\r
**/\r
INTN\r
MoveToNextStatement (\r
IN BOOLEAN GoUp,\r
IN OUT LIST_ENTRY **CurrentPosition,\r
- IN UINTN GapToTop\r
+ IN UINTN GapToTop,\r
+ IN BOOLEAN FindInForm\r
)\r
{\r
INTN Distance;\r
\r
Distance = 0;\r
Pos = *CurrentPosition;\r
+\r
+ if (Pos == &gMenuOption) {\r
+ return -1;\r
+ }\r
+\r
PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
\r
while (TRUE) {\r
if (NextMenuOption->Row == 0) {\r
UpdateOptionSkipLines (NextMenuOption);\r
}\r
- \r
- if (GoUp && (PreMenuOption != NextMenuOption)) {\r
- //\r
- // In this case, still can't find the selectable menu,\r
- // return the last one in the showing form.\r
- //\r
- if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
- NextMenuOption = PreMenuOption;\r
- break;\r
- }\r
\r
- //\r
- // Current Position doesn't need to be caculated when go up.\r
- // Caculate distanct at first when go up\r
- // \r
- Distance += NextMenuOption->Skip;\r
+ if (IsSelectable (NextMenuOption)) {\r
+ break;\r
}\r
\r
- if (IsSelectable (NextMenuOption)) {\r
+ //\r
+ // In this case, still can't find the selectable menu,\r
+ // return the first one beyond the showing form.\r
+ //\r
+ if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+ if (FindInForm) {\r
+ NextMenuOption = PreMenuOption;\r
+ }\r
break;\r
}\r
\r
+ Distance += NextMenuOption->Skip;\r
+\r
//\r
// Arrive at begin of the menu list.\r
//\r
break;\r
}\r
\r
- if (!GoUp) {\r
- //\r
- // In this case, still can't find the selectable menu,\r
- // return the last one in the showing form.\r
- //\r
- if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
- NextMenuOption = PreMenuOption;\r
- break;\r
- }\r
-\r
- Distance += NextMenuOption->Skip;\r
- }\r
-\r
- PreMenuOption = NextMenuOption;\r
Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+ PreMenuOption = NextMenuOption;\r
}\r
\r
*CurrentPosition = &NextMenuOption->Link;\r
return QuestionHeader->QuestionId;\r
}\r
\r
+\r
+/**\r
+ Find the top of screen menu base on the current menu.\r
+\r
+ @param CurPos Current input menu.\r
+ @param Rows Totol screen rows.\r
+ @param SkipValue SkipValue for this new form.\r
+\r
+ @retval TopOfScreen Top of screen menu for the new form.\r
+\r
+**/\r
+LIST_ENTRY *\r
+FindTopOfScreenMenu (\r
+ IN LIST_ENTRY *CurPos,\r
+ IN UINTN Rows,\r
+ OUT UINTN *SkipValue\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *TopOfScreen;\r
+ UI_MENU_OPTION *PreviousMenuOption;\r
+\r
+ Link = CurPos;\r
+ PreviousMenuOption = NULL;\r
+\r
+ while (Link->BackLink != &gMenuOption) {\r
+ Link = Link->BackLink;\r
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ if (PreviousMenuOption->Row == 0) {\r
+ UpdateOptionSkipLines (PreviousMenuOption);\r
+ }\r
+ if (Rows <= PreviousMenuOption->Skip) {\r
+ break;\r
+ }\r
+ Rows = Rows - PreviousMenuOption->Skip;\r
+ }\r
+\r
+ if (Link->BackLink == &gMenuOption) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ if (PreviousMenuOption != NULL && Rows < PreviousMenuOption->Skip) {\r
+ *SkipValue = PreviousMenuOption->Skip - Rows;\r
+ } else {\r
+ *SkipValue = 0;\r
+ }\r
+ } else {\r
+ TopOfScreen = Link;\r
+ *SkipValue = PreviousMenuOption->Skip - Rows;\r
+ }\r
+\r
+ return TopOfScreen;\r
+}\r
+\r
/**\r
Find the first menu which will be show at the top.\r
\r
IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
OUT LIST_ENTRY **TopOfScreen,\r
OUT LIST_ENTRY **HighlightMenu,\r
- OUT INTN *SkipValue\r
+ OUT UINTN *SkipValue\r
)\r
{\r
- LIST_ENTRY *Link;\r
LIST_ENTRY *NewPos;\r
UINTN TopRow;\r
UINTN BottomRow;\r
- UINTN Index;\r
UI_MENU_OPTION *SavedMenuOption;\r
- UINTN EndRow;\r
+ UINTN TmpValue;\r
\r
TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
*TopOfScreen = gMenuOption.ForwardLink;\r
*HighlightMenu = gMenuOption.ForwardLink;\r
if (!IsListEmpty (&gMenuOption)) {\r
- MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow);\r
+ MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
}\r
*SkipValue = 0;\r
return;\r
//\r
// Still show the highlight menu before exit from display engine.\r
//\r
- EndRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
- } else {\r
- EndRow = BottomRow;\r
+ BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
}\r
\r
- //\r
- // Base on the selected menu will show at the bottome of next page, \r
- // select the menu show at the top of the next page. \r
- //\r
- Link = NewPos;\r
- for (Index = TopRow + SavedMenuOption->Skip; Index <= EndRow; ) {\r
- Link = Link->BackLink;\r
- //\r
- // Already find the first menu in this form, means highlight menu \r
- // will show in first page of this form.\r
- //\r
- if (Link == &gMenuOption) {\r
- *TopOfScreen = gMenuOption.ForwardLink;\r
- *SkipValue = 0;\r
- return;\r
- }\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- UpdateOptionSkipLines (SavedMenuOption);\r
- Index += SavedMenuOption->Skip;\r
- }\r
-\r
- //\r
- // Found the menu which will show at the top of the page.\r
- //\r
- if (Link == NewPos) {\r
- //\r
- // The menu can show more than one pages, just show the menu at the top of the page.\r
- //\r
- *SkipValue = 0;\r
- *TopOfScreen = Link;\r
+ if (SavedMenuOption->Skip >= BottomRow - TopRow) {\r
+ TmpValue = 0;\r
+ *TopOfScreen = NewPos;\r
} else {\r
- //\r
- // Check whether need to skip some line for menu shows at the top of the page.\r
- //\r
- *SkipValue = Index - EndRow;\r
- if (*SkipValue > 0 && *SkipValue < (INTN) SavedMenuOption->Skip) {\r
- *TopOfScreen = Link;\r
- } else {\r
- *SkipValue = 0;\r
- *TopOfScreen = Link->ForwardLink;\r
- }\r
+ *TopOfScreen = FindTopOfScreenMenu(NewPos, BottomRow - TopRow - SavedMenuOption->Skip, &TmpValue);\r
}\r
+\r
+ *SkipValue = TmpValue;\r
}\r
\r
/**\r
PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);\r
}\r
\r
+/**\r
+ Check whether this menu can has option string.\r
+\r
+ @param MenuOption The menu opton which this attribut used to.\r
+\r
+ @retval TRUE This menu option can have option string.\r
+ @retval FALSE This menu option can't have option string.\r
+\r
+**/\r
+BOOLEAN \r
+HasOptionString (\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+ CHAR16 *String;\r
+ UINTN Size;\r
+ EFI_IFR_TEXT *TestOp;\r
+\r
+ Size = 0;\r
+ Statement = MenuOption->ThisTag;\r
+\r
+ //\r
+ // See if the second text parameter is really NULL\r
+ //\r
+ if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
+ TestOp = (EFI_IFR_TEXT *) Statement->OpCode;\r
+ if (TestOp->TextTwo != 0) {\r
+ String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);\r
+ Size = StrLen (String);\r
+ FreePool (String);\r
+ }\r
+ }\r
+\r
+ if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||\r
+ //\r
+ // Allow a wide display if text op-code and no secondary text op-code\r
+ //\r
+ ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))\r
+ ) {\r
+\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
/**\r
Print string for this menu option.\r
\r
CHAR16 *StringPtr;\r
CHAR16 *OptionString;\r
CHAR16 *OutputString;\r
- UINTN OriginalRow;\r
UINT16 GlyphWidth;\r
UINTN Temp;\r
UINTN Temp2;\r
UINTN Row;\r
UINTN Col;\r
UINTN PromptLineNum;\r
+ UINTN OptionLineNum;\r
CHAR16 AdjustValue;\r
+ UINTN MaxRow;\r
\r
Statement = MenuOption->ThisTag;\r
- Col = MenuOption->Col;\r
- Row = MenuOption->Row;\r
Temp = SkipLine;\r
Temp2 = SkipLine;\r
Temp3 = SkipLine;\r
- AdjustValue = 0;\r
+ AdjustValue = 0;\r
+ PromptLineNum = 0;\r
+ OptionLineNum = 0;\r
+ MaxRow = 0;\r
\r
//\r
// Set default color.\r
}\r
\r
Width = (UINT16) gOptionBlockWidth - 1;\r
- OriginalRow = Row;\r
+ Row = MenuOption->Row;\r
GlyphWidth = 1;\r
+ OptionLineNum = 0;\r
\r
for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if (((Temp2 == 0)) && (Row <= BottomRow)) {\r
} else {\r
DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
}\r
+ OptionLineNum++;\r
}\r
\r
//\r
//\r
// If the difference in rows is greater than or equal to the skip value, increase the skip value\r
//\r
- if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+ if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
MenuOption->Skip++;\r
}\r
}\r
}\r
}\r
\r
- Row = OriginalRow;\r
Highlight = FALSE;\r
\r
FreePool (OptionString);\r
}\r
- Temp2 = 0;\r
-\r
-\r
- //\r
- // 2. Pre calculate the skip value.\r
- //\r
- if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
- StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
- \r
- Width = (UINT16) gOptionBlockWidth - 1;\r
- OriginalRow = Row;\r
- GlyphWidth = 1;\r
- for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
- if (StrLen (&StringPtr[Index]) != 0) {\r
- Row++;\r
- if ((Row - OriginalRow) >= MenuOption->Skip) {\r
- MenuOption->Skip++;\r
- }\r
- }\r
- FreePool (OutputString);\r
- }\r
- \r
- Row = OriginalRow;\r
- FreePool (StringPtr);\r
- }\r
-\r
\r
//\r
- // 3. Paint the description.\r
+ // 2. Paint the description.\r
//\r
- PromptWidth = GetWidth (Statement, &AdjustValue);\r
- OriginalRow = Row;\r
+ PromptWidth = GetWidth (MenuOption, &AdjustValue);\r
+ Row = MenuOption->Row;\r
GlyphWidth = 1;\r
PromptLineNum = 0;\r
\r
if (MenuOption->Description == NULL || MenuOption->Description[0] == '\0') {\r
- while (Temp++ < MenuOption->Skip) {\r
- PrintStringAtWithWidth (BeginCol, Row++, L"", PromptWidth + AdjustValue + SkipWidth);\r
- } \r
+ PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);\r
+ PromptLineNum++;\r
} else {\r
for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
if ((Temp == 0) && (Row <= BottomRow)) { \r
}\r
\r
Highlight = FALSE;\r
-\r
- //\r
- // Clean the empty prompt line.\r
- // These line is used by option string but not prompt, so clean them here.\r
- //\r
- Row = OriginalRow + PromptLineNum;\r
- while (PromptLineNum + SkipLine < MenuOption->Skip && Row <= BottomRow) {\r
- PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);\r
- PromptLineNum ++;\r
- Row ++;\r
- }\r
}\r
- Row = OriginalRow;\r
\r
\r
//\r
- // 4. If this is a text op with secondary text information\r
+ // 3. If this is a text op with secondary text information\r
//\r
if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
\r
Width = (UINT16) gOptionBlockWidth - 1;\r
- OriginalRow = Row;\r
+ Row = MenuOption->Row;\r
GlyphWidth = 1;\r
+ OptionLineNum = 0;\r
\r
for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
if ((Temp3 == 0) && (Row <= BottomRow)) {\r
DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
+ OptionLineNum++;\r
}\r
//\r
// If there is more string to process print on the next row and increment the Skip value\r
if (StrLen (&StringPtr[Index]) != 0) {\r
if (Temp3 == 0) {\r
Row++;\r
+ //\r
+ // If the rows for text two is greater than or equal to the skip value, increase the skip value\r
+ //\r
+ if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
+ MenuOption->Skip++;\r
+ }\r
}\r
}\r
\r
Temp3--;\r
}\r
}\r
- \r
- Row = OriginalRow;\r
+\r
FreePool (StringPtr);\r
}\r
\r
+ //\r
+ // 4.Line number for Option string and prompt string are not equal.\r
+ // Clean the column whose line number is less.\r
+ //\r
+ if (HasOptionString(MenuOption) && (OptionLineNum != PromptLineNum)) {\r
+ Col = OptionLineNum < PromptLineNum ? MenuOption->OptCol : BeginCol;\r
+ Row = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row;\r
+ Width = (UINT16) (OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth);\r
+ MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1;\r
+ \r
+ while (Row <= MaxRow) {\r
+ DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE);\r
+ }\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
IN FORM_DISPLAY_ENGINE_FORM *FormData\r
)\r
{\r
- INTN SkipValue;\r
+ UINTN SkipValue;\r
INTN Difference;\r
UINTN DistanceValue;\r
UINTN Row;\r
UINTN Temp2;\r
UINTN TopRow;\r
UINTN BottomRow;\r
- UINTN OriginalRow;\r
UINTN Index;\r
UINT16 Width;\r
CHAR16 *StringPtr;\r
UINTN HelpHeaderLine;\r
UINTN HelpBottomLine;\r
BOOLEAN MultiHelpPage;\r
- UINT16 GlyphWidth;\r
UINT16 EachLineWidth;\r
UINT16 HeaderLineWidth;\r
UINT16 BottomLineWidth;\r
}\r
\r
if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
- DisplayOneMenu (MenuOption, \r
- LEFT_SKIPPED_COLUMNS,\r
+ Status = DisplayOneMenu (MenuOption, \r
+ MenuOption->Col - gStatementDimensions.LeftColumn,\r
gStatementDimensions.LeftColumn + gModalSkipColumn, \r
Link == TopOfScreen ? SkipValue : 0, \r
BottomRow,\r
(BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption))\r
);\r
} else {\r
- DisplayOneMenu (MenuOption, \r
- LEFT_SKIPPED_COLUMNS,\r
+ Status = DisplayOneMenu (MenuOption, \r
+ MenuOption->Col - gStatementDimensions.LeftColumn,\r
gStatementDimensions.LeftColumn, \r
Link == TopOfScreen ? SkipValue : 0, \r
BottomRow,\r
); \r
}\r
\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
//\r
// 3. Update the row info which will be used by next menu.\r
//\r
}\r
\r
MenuOption = NULL;\r
-\r
- if (IsListEmpty (&gMenuOption)) { \r
- ControlFlag = CfReadKey;\r
- }\r
}\r
break;\r
\r
break;\r
}\r
\r
+ if (IsListEmpty (&gMenuOption)) {\r
+ //\r
+ // No menu option, just update the hotkey filed.\r
+ //\r
+ RefreshKeyHelp(gFormData, NULL, FALSE);\r
+ break;\r
+ }\r
+\r
if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) {\r
Temp = SkipValue;\r
} else {\r
if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
if (MenuOption != NULL) {\r
//\r
- // Remove highlight on last Menu Option\r
+ // Remove the old highlight menu.\r
//\r
- gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
- ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
- gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
- if (OptionString != NULL) {\r
- if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||\r
- (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)\r
- ) {\r
- ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
- }\r
-\r
- Width = (UINT16) gOptionBlockWidth;\r
- OriginalRow = MenuOption->Row;\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
- PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&OptionString[Index]) != 0) {\r
- if (Temp == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp != 0) {\r
- Temp--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
-\r
- FreePool (OptionString);\r
- } else {\r
- if (NewLine) {\r
- if (MenuOption->GrayOut) {\r
- gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
- } else if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
- gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
- }\r
-\r
- OriginalRow = MenuOption->Row;\r
- Width = GetWidth (MenuOption->ThisTag, NULL);\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
- PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&MenuOption->Description[Index]) != 0) {\r
- if (Temp == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp != 0) {\r
- Temp--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
- gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
- }\r
- }\r
+ Status = DisplayOneMenu (MenuOption, \r
+ MenuOption->Col - gStatementDimensions.LeftColumn,\r
+ gStatementDimensions.LeftColumn, \r
+ Temp, \r
+ BottomRow,\r
+ FALSE\r
+ );\r
}\r
\r
//\r
break;\r
}\r
\r
- //\r
- // Set reverse attribute\r
- //\r
- gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
- gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
-\r
- ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
- if (OptionString != NULL) {\r
- if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
- ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
- }\r
- Width = (UINT16) gOptionBlockWidth;\r
-\r
- OriginalRow = MenuOption->Row;\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
- PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&OptionString[Index]) != 0) {\r
- if (Temp2 == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp2 != 0) {\r
- Temp2--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
-\r
- FreePool (OptionString);\r
- } else {\r
- if (NewLine) {\r
- OriginalRow = MenuOption->Row;\r
-\r
- Width = GetWidth (Statement, NULL);\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
- PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&MenuOption->Description[Index]) != 0) {\r
- if (Temp2 == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp2 != 0) {\r
- Temp2--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
-\r
- }\r
- }\r
-\r
- //\r
- // Clear reverse attribute\r
- //\r
- gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+ Status = DisplayOneMenu (MenuOption, \r
+ MenuOption->Col - gStatementDimensions.LeftColumn,\r
+ gStatementDimensions.LeftColumn, \r
+ Temp2, \r
+ BottomRow,\r
+ TRUE\r
+ );\r
}\r
break;\r
\r
break;\r
}\r
\r
+ //\r
+ // NewLine means only update highlight menu (remove old highlight and highlith\r
+ // the new one), not need to full repain the form.\r
+ //\r
if (Repaint || NewLine) {\r
- //\r
- // Don't print anything if it is a NULL help token\r
- //\r
- ASSERT(MenuOption != NULL);\r
- HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
- if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
+ if (IsListEmpty (&gMenuOption)) {\r
+ //\r
+ // Don't print anything if no mwnu option.\r
+ //\r
StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
} else {\r
- StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+ //\r
+ // Don't print anything if it is a NULL help token\r
+ //\r
+ ASSERT(MenuOption != NULL);\r
+ HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
+ if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
+ StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ } else {\r
+ StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+ }\r
}\r
\r
RowCount = BottomRow - TopRow + 1;\r
// If the screen has no menu items, and the user didn't select UiReset\r
// ignore the selection and go back to reading keys.\r
//\r
+ ASSERT(MenuOption != NULL);\r
if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
ControlFlag = CfReadKey;\r
break;\r
}\r
\r
- ASSERT(MenuOption != NULL);\r
Statement = MenuOption->ThisTag;\r
if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)\r
|| (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)\r
break;\r
\r
case CfScreenOperation:\r
- if (ScreenOperation != UiReset) {\r
+ if ((ScreenOperation != UiReset) && (ScreenOperation != UiHotKey)) {\r
//\r
- // If the screen has no menu items, and the user didn't select UiReset\r
+ // If the screen has no menu items, and the user didn't select UiReset or UiHotKey\r
// ignore the selection and go back to reading keys.\r
//\r
if (IsListEmpty (&gMenuOption)) {\r
\r
case CfUiHotKey:\r
ControlFlag = CfRepaint;\r
- \r
+\r
+ ASSERT (HotKey != NULL);\r
gUserInput->Action = HotKey->Action;\r
ControlFlag = CfExit;\r
break;\r
\r
case CfUiUp:\r
ControlFlag = CfRepaint;\r
+ NewLine = TRUE;\r
\r
SavedListEntry = NewPos;\r
\r
// Adjust Date/Time position before we advance forward.\r
//\r
AdjustDateAndTimePosition (TRUE, &NewPos);\r
- if (NewPos->BackLink != &gMenuOption) {\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- ASSERT (MenuOption != NULL);\r
- NewLine = TRUE;\r
- NewPos = NewPos->BackLink;\r
\r
- PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- if (PreviousMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (PreviousMenuOption);\r
- }\r
- DistanceValue = PreviousMenuOption->Skip;\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
- if (Difference < 0) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ ASSERT (MenuOption != NULL);\r
+\r
+ NewPos = NewPos->BackLink;\r
+ //\r
+ // Find next selectable menu or the first menu beyond current form.\r
+ //\r
+ Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow, FALSE);\r
+ if (Difference < 0) {\r
+ //\r
+ // We hit the begining MenuOption that can be focused\r
+ // so we simply scroll to the top.\r
+ //\r
+ Repaint = TRUE;\r
+ if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ NewPos = SavedListEntry;\r
+ SkipValue = 0;\r
+ } else {\r
//\r
- // We hit the begining MenuOption that can be focused\r
- // so we simply scroll to the top.\r
+ // Scroll up to the last page when we have arrived at top page.\r
//\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 (MenuOption->Row < TopRow + DistanceValue + Difference) {\r
+ TopOfScreen = FindTopOfScreenMenu (gMenuOption.BackLink, BottomRow - TopRow, &SkipValue);\r
+ NewPos = gMenuOption.BackLink;\r
+ MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow, TRUE);\r
+ }\r
+ } else {\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+ if (MenuOption->Row < TopRow + Difference + NextMenuOption->Skip) {\r
//\r
// Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
//\r
TopOfScreen = NewPos;\r
Repaint = TRUE;\r
- SkipValue = 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
+ SkipValue = 0;\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
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
- UpdateStatusBar (INPUT_ERROR, FALSE);\r
- } else {\r
- //\r
- // Scroll up to the last page.\r
+ // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
//\r
- NewPos = &gMenuOption;\r
- TopOfScreen = &gMenuOption;\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
- ScreenOperation = UiPageUp;\r
- ControlFlag = CfScreenOperation;\r
+ // BottomRow - TopRow + 1 means the total rows current forms supported.\r
+ // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu \r
+ // and new top menu. New top menu will all shows in next form, but last highlight menu \r
+ // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the \r
+ // last highlight menu.\r
+ // \r
+ if (!IsSelectable(NextMenuOption) && IsSelectable(MenuOption) && \r
+ (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
+ NewPos = SavedListEntry;\r
+ }\r
}\r
- break;\r
\r
- case CfUiPageUp:\r
- //\r
- // SkipValue means lines is skipped when show the top menu option.\r
- //\r
- ControlFlag = CfRepaint;\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\r
\r
- ASSERT(NewPos != NULL);\r
//\r
- // Already at the first menu option, Check the skip value.\r
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
//\r
- if (NewPos->BackLink == &gMenuOption) {\r
- if (SkipValue == 0) {\r
- NewLine = FALSE;\r
- Repaint = FALSE;\r
- } else {\r
- NewLine = TRUE;\r
- Repaint = TRUE;\r
- SkipValue = 0;\r
- }\r
- break;\r
- }\r
-\r
- NewLine = TRUE;\r
- Repaint = TRUE;\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
\r
+ case CfUiPageUp:\r
//\r
- // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
- // form of options to be show, so just update the SkipValue to show the next\r
- // parts of options.\r
+ // SkipValue means lines is skipped when show the top menu option.\r
//\r
- if (SkipValue > (INTN) (BottomRow - TopRow + 1)) {\r
- SkipValue -= BottomRow - TopRow + 1;\r
- break;\r
- }\r
+ ControlFlag = CfRepaint;\r
+ NewLine = TRUE;\r
+ Repaint = TRUE;\r
\r
Link = TopOfScreen;\r
//\r
// First minus the menu of the top screen, it's value is SkipValue.\r
//\r
- Index = (BottomRow + 1) - SkipValue;\r
- while ((Index > TopRow) && (Link->BackLink != &gMenuOption)) {\r
- Link = Link->BackLink;\r
- PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- if (PreviousMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (PreviousMenuOption);\r
- } \r
- if (Index < PreviousMenuOption->Skip) {\r
- break;\r
- }\r
- Index = Index - PreviousMenuOption->Skip;\r
- }\r
- \r
- if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
- SkipValue = 0;\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 > TopRow) {\r
- //\r
- // At here, only case "Index < PreviousMenuOption->Skip" can reach here.\r
- //\r
- SkipValue = PreviousMenuOption->Skip - (Index - TopRow);\r
- } else if (Index == TopRow) {\r
- SkipValue = 0;\r
- } else {\r
- SkipValue = TopRow - Index;\r
- }\r
-\r
+ if (SkipValue >= BottomRow - TopRow + 1) {\r
//\r
- // Move to the option in Next page.\r
+ // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
+ // form of options to be show, so just update the SkipValue to show the next\r
+ // parts of options.\r
//\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
- // There are more MenuOption needing scrolling up.\r
- //\r
- TopOfScreen = Link;\r
- MenuOption = NULL;\r
+ SkipValue -= BottomRow - TopRow + 1;\r
+ NewPos = TopOfScreen;\r
+ break;\r
+ } else {\r
+ Index = (BottomRow + 1) - SkipValue - TopRow;\r
}\r
+ \r
+ TopOfScreen = FindTopOfScreenMenu(TopOfScreen, Index, &SkipValue);\r
+ NewPos = TopOfScreen;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE);\r
+ \r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\r
\r
//\r
// If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
//\r
// SkipValue means lines is skipped when show the top menu option.\r
//\r
- ControlFlag = CfRepaint;\r
-\r
- ASSERT (NewPos != NULL);\r
- if (NewPos->ForwardLink == &gMenuOption) {\r
- NewLine = FALSE;\r
- Repaint = FALSE;\r
- break;\r
- }\r
+ ControlFlag = CfRepaint;\r
+ NewLine = TRUE;\r
+ Repaint = TRUE;\r
\r
- NewLine = TRUE;\r
- Repaint = TRUE;\r
Link = TopOfScreen;\r
NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
Index = TopRow + NextMenuOption->Skip - SkipValue;\r
\r
if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {\r
//\r
- // Finally we know that NewPos is the last MenuOption can be focused.\r
+ // Highlight on the last menu which can be highlight.\r
//\r
Repaint = FALSE;\r
- MoveToNextStatement (TRUE, &Link, Index - TopRow);\r
+ MoveToNextStatement (TRUE, &Link, Index - TopRow, TRUE);\r
} else {\r
//\r
// Calculate the skip line for top of screen menu.\r
} else {\r
SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));\r
}\r
-\r
TopOfScreen = Link;\r
MenuOption = NULL;\r
//\r
// Move to the Next selectable menu.\r
//\r
- MoveToNextStatement (FALSE, &Link, BottomRow - TopRow);\r
+ MoveToNextStatement (FALSE, &Link, BottomRow - TopRow, TRUE);\r
}\r
\r
//\r
//\r
NewPos = Link;\r
\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\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
// NewPos points to the menu which is highlighted now.\r
//\r
ControlFlag = CfRepaint;\r
+ NewLine = TRUE;\r
\r
+ if (NewPos == TopOfScreen) {\r
+ Temp2 = SkipValue;\r
+ } else {\r
+ Temp2 = 0;\r
+ }\r
+\r
+ SavedListEntry = NewPos;\r
//\r
// Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
// to be one that progresses to the next set of op-codes, we need to advance to the last\r
// op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
// the Date/Time op-code.\r
//\r
- SavedListEntry = 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
- Difference = 0;\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ NewPos = NewPos->ForwardLink;\r
+ //\r
+ // Find the next selectable menu.\r
+ //\r
+ if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) {\r
+ if (gMenuOption.ForwardLink == NewPos || &gMenuOption == NewPos) {\r
+ Difference = -1;\r
+ } else {\r
+ Difference = 0;\r
+ }\r
+ } else {\r
+ Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE);\r
+ }\r
+ if (Difference < 0) {\r
//\r
- // Current menu not at the bottom of the form.\r
+ // Scroll to the first page.\r
//\r
- if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
- //\r
- // Find the next selectable menu.\r
- //\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
- SkipValue = 0;\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
- if (NextMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (NextMenuOption);\r
- }\r
- DistanceValue = Difference + NextMenuOption->Skip;\r
-\r
- Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
- if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
- (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP ||\r
- NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)\r
- ) {\r
- Temp ++;\r
+ if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) { \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, TRUE);\r
\r
+ SkipValue = 0;\r
//\r
- // If we are going to scroll, update TopOfScreen\r
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
//\r
- if (Temp > BottomRow) {\r
- do {\r
- //\r
- // Is the current top of screen a zero-advance op-code?\r
- // If so, keep moving forward till we hit a >0 advance op-code\r
- //\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+ } \r
\r
- //\r
- // If bottom op-code is more than one line or top op-code is more than one line\r
- //\r
- if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) {\r
- //\r
- // Is the bottom op-code greater than or equal in size to the top op-code?\r
- //\r
- if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
- //\r
- // Skip the top op-code\r
- //\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
-\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-\r
- //\r
- // If we have a remainder, skip that many more op-codes until we drain the remainder\r
- //\r
- while (Difference >= (INTN) SavedMenuOption->Skip) {\r
- //\r
- // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
- //\r
- Difference = Difference - (INTN) SavedMenuOption->Skip;\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
- }\r
- //\r
- // Since we will act on this op-code in the next routine, and increment the\r
- // SkipValue, set the skips to one less than what is required.\r
- //\r
- SkipValue = Difference - 1;\r
- } else {\r
- //\r
- // Since we will act on this op-code in the next routine, and increment the\r
- // SkipValue, set the skips to one less than what is required.\r
- //\r
- SkipValue += (Temp - BottomRow) - 1;\r
- }\r
- } else {\r
- if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- break;\r
- }\r
- }\r
- //\r
- // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
- // Let's set a skip flag to smoothly scroll the top of the screen.\r
- //\r
- if (SavedMenuOption->Skip > 1) {\r
- if (SavedMenuOption == NextMenuOption) {\r
- SkipValue = 0;\r
- } else {\r
- SkipValue++;\r
- }\r
- } else if (SavedMenuOption->Skip == 1) {\r
- SkipValue = 0;\r
- } else {\r
- SkipValue = 0;\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- }\r
- } while (SavedMenuOption->Skip == 0);\r
+ //\r
+ // Get next selected menu info.\r
+ //\r
+ AdjustDateAndTimePosition (FALSE, &NewPos);\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ if (NextMenuOption->Row == 0) {\r
+ UpdateOptionSkipLines (NextMenuOption);\r
+ }\r
\r
- Repaint = TRUE;\r
- } else if (!IsSelectable (NextMenuOption)) {\r
+ //\r
+ // Calculate new highlight menu end row.\r
+ //\r
+ Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1;\r
+ if (Temp > BottomRow) {\r
+ //\r
+ // Get the top screen menu info.\r
+ //\r
+ AdjustDateAndTimePosition (FALSE, &TopOfScreen);\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+\r
+ //\r
+ // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows.\r
+ // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows.\r
+ //\r
+ if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
//\r
- // Continue to go down until scroll to next page or the selectable option is found.\r
+ // Skip the top op-code\r
//\r
- ScreenOperation = UiDown;\r
- ControlFlag = CfScreenOperation;\r
- }\r
-\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
\r
- UpdateStatusBar (INPUT_ERROR, FALSE);\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
\r
- } else {\r
- //\r
- // Scroll to the first page.\r
- //\r
- if (TopOfScreen != gMenuOption.ForwardLink) {\r
- TopOfScreen = gMenuOption.ForwardLink;\r
- Repaint = TRUE;\r
- MenuOption = NULL;\r
+ //\r
+ // If we have a remainder, skip that many more op-codes until we drain the remainder\r
+ // Special case is the selected highlight menu has more than one form of menus.\r
+ //\r
+ while (DistanceValue >= SavedMenuOption->Skip && TopOfScreen != NewPos) {\r
+ //\r
+ // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
+ //\r
+ DistanceValue = DistanceValue - (INTN) SavedMenuOption->Skip;\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+ }\r
+ //\r
+ // Since we will act on this op-code in the next routine, and increment the\r
+ // SkipValue, set the skips to one less than what is required.\r
+ //\r
+ if (TopOfScreen != NewPos) {\r
+ SkipValue = DistanceValue;\r
+ } else {\r
+ SkipValue = 0;\r
+ }\r
} else {\r
//\r
- // Need to remove the current highlight menu.\r
- // MenuOption saved the last highlight menu info.\r
+ // Since we will act on this op-code in the next routine, and increment the\r
+ // SkipValue, set the skips to one less than what is required.\r
//\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ SkipValue += Temp - BottomRow;\r
}\r
-\r
- SkipValue = 0;\r
- NewLine = TRUE;\r
+ Repaint = TRUE;\r
+ } else if (!IsSelectable (NextMenuOption)) {\r
//\r
- // Get the next highlight menu.\r
+ // Continue to go down until scroll to next page or the selectable option is found.\r
//\r
- NewPos = gMenuOption.ForwardLink;\r
- MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ ScreenOperation = UiDown;\r
+ ControlFlag = CfScreenOperation;\r
+ break;\r
}\r
\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+\r
+ //\r
+ // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
+ //\r
+ // BottomRow - TopRow + 1 means the total rows current forms supported.\r
+ // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu \r
+ // and new top menu. New top menu will all shows in next form, but last highlight menu \r
+ // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the \r
+ // last highlight menu.\r
+ // \r
+ if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) && \r
+ (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
+ NewPos = SavedListEntry;\r
+ }\r
+\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\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