\r
Row = 0;\r
OptionString = NULL;\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ OriginalRow = 0;\r
+ GlyphWidth = 1;\r
+ \r
ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+ if (OptionString == NULL) {\r
+ return;\r
+ }\r
\r
- if (OptionString != NULL) {\r
- Width = (UINT16) gOptionBlockWidth;\r
-\r
- OriginalRow = Row;\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &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 (&OptionString[Index]) != 0) {\r
+ Row++;\r
//\r
- // If there is more string to process print on the next row and increment the Skip value\r
+ // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+ // some testing to ensure we are keeping this in-sync.\r
//\r
- if (StrLen (&OptionString[Index]) != 0) {\r
- Row++;\r
- //\r
- // Since the Number of lines for this menu entry may or may not be reflected accurately\r
- // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
- // some testing to ensure we are keeping this in-sync.\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
- MenuOption->Skip++;\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
+ MenuOption->Skip++;\r
}\r
-\r
- FreePool (OutputString);\r
}\r
\r
- Row = OriginalRow;\r
+ FreePool (OutputString);\r
}\r
\r
if (OptionString != NULL) {\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
+\r
**/\r
INTN\r
MoveToNextStatement (\r
\r
while (TRUE) {\r
NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+ //\r
+ // NextMenuOption->Row == 0 means this menu has not calculate\r
+ // the NextMenuOption->Skip value yet, just calculate here.\r
+ //\r
if (NextMenuOption->Row == 0) {\r
UpdateOptionSkipLines (Selection, NextMenuOption);\r
}\r
\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
+ // 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
}\r
+\r
if (IsSelectable (NextMenuOption)) {\r
break;\r
}\r
+\r
+ //\r
+ // Arrive at begin of the menu list.\r
+ //\r
if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
- //\r
- // Arrive at top.\r
- //\r
Distance = -1;\r
break;\r
}\r
+\r
if (!GoUp) {\r
//\r
- // Caculate distanct at later when go down\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
}\r
{\r
INTN SkipValue;\r
INTN Difference;\r
- INTN OldSkipValue;\r
UINTN DistanceValue;\r
UINTN Row;\r
UINTN Col;\r
UpArrow = FALSE;\r
DownArrow = FALSE;\r
SkipValue = 0;\r
- OldSkipValue = 0;\r
MenuRefreshEntry = gMenuRefreshHead;\r
\r
NextMenuOption = NULL;\r
Temp = (UINTN) SkipValue;\r
Temp2 = (UINTN) SkipValue;\r
\r
+ //\r
+ // 1. Clear the screen.\r
+ //\r
if (Selection->Form->ModalForm) {\r
ClearLines (\r
LocalScreen.LeftColumn + ModalSkipColumn,\r
UiFreeRefreshList ();\r
MinRefreshInterval = 0;\r
\r
+ //\r
+ // 2.Paint the menu.\r
+ //\r
for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {\r
MenuOption = MENU_OPTION_FROM_LINK (Link);\r
MenuOption->Row = Row;\r
);\r
}\r
\r
+ //\r
+ // 2.1. Paint the description.\r
+ //\r
for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ //\r
+ // Temp means need to skip how many lines from the start.\r
+ //\r
if ((Temp == 0) && (Row <= BottomRow)) {\r
PrintStringAt (MenuOption->Col, Row, OutputString);\r
}\r
Temp = 0;\r
Row = OriginalRow;\r
\r
+ //\r
+ // 2.2. Paint the option string.\r
+ //\r
Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
if (EFI_ERROR (Status)) {\r
//\r
}\r
\r
//\r
- // If Question has refresh guid, register the op-code.\r
+ // 2.4 Special process for Test opcode with test two.\r
//\r
if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
if (gMenuEventGuidRefreshHead == NULL) {\r
gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
\r
//\r
- // Need to handle the bottom of the display\r
+ // 3. Update the row info which will be used by next menu.\r
//\r
- if (MenuOption->Skip > 1) {\r
+ if (Link == TopOfScreen) {\r
Row += MenuOption->Skip - SkipValue;\r
- SkipValue = 0;\r
} else {\r
Row += MenuOption->Skip;\r
}\r
// NewPos: Current menu option that need to hilight\r
//\r
ControlFlag = CfUpdateHelpString;\r
+ if (TopOfScreen == &MenuOption->Link) {\r
+ Temp = SkipValue;\r
+ } else {\r
+ Temp = 0;\r
+ }\r
+ if (NewPos == TopOfScreen) {\r
+ Temp2 = SkipValue;\r
+ } else {\r
+ Temp2 = 0;\r
+ }\r
if (InitializedFlag) {\r
InitializedFlag = FALSE;\r
MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
Index += SavedMenuOption->Skip;\r
if (Link == TopOfScreen) {\r
- Index -= OldSkipValue;\r
+ Index -= SkipValue;\r
}\r
Link = Link->ForwardLink;\r
}\r
//\r
SkipValue = 0;\r
TopOfScreen = Link;\r
- OldSkipValue = SkipValue;\r
} else {\r
//\r
// Check whether need to skip some line for menu shows at the top of the page.\r
SkipValue = Index - BottomRow - 1;\r
if (SkipValue > 0 && SkipValue < (INTN) SavedMenuOption->Skip) {\r
TopOfScreen = Link;\r
- OldSkipValue = SkipValue;\r
} else {\r
SkipValue = 0;\r
TopOfScreen = Link->ForwardLink;\r
GlyphWidth = 1;\r
\r
for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\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
- MenuOption->Row++;\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
GlyphWidth = 1;\r
\r
for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\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
- MenuOption->Row++;\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
GlyphWidth = 1;\r
\r
for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\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
GlyphWidth = 1;\r
\r
for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\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
- MenuOption->Row++;\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
TopOfScreen = NewPos;\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
break;\r
\r
case CfUiPageUp:\r
+ //\r
+ // SkipValue means lines is skipped when show the top menu option.\r
+ //\r
ControlFlag = CfCheckSelection;\r
\r
ASSERT(NewPos != NULL);\r
+ //\r
+ // Already at the first menu option, so do nothing.\r
+ //\r
if (NewPos->BackLink == &gMenuOption) {\r
NewLine = FALSE;\r
Repaint = FALSE;\r
\r
NewLine = TRUE;\r
Repaint = TRUE;\r
+\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
+ //\r
+ if (SkipValue > (INTN) (BottomRow - TopRow + 1)) {\r
+ SkipValue -= BottomRow - TopRow + 1;\r
+ break;\r
+ }\r
+\r
Link = TopOfScreen;\r
- Index = BottomRow;\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
UpdateOptionSkipLines (Selection, PreviousMenuOption);\r
} \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
+ SkipValue = 0;\r
if (TopOfScreen == &gMenuOption) {\r
TopOfScreen = gMenuOption.ForwardLink;\r
NewPos = gMenuOption.BackLink;\r
MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
}\r
} else {\r
- if (Index + 1 < TopRow) {\r
+ if (Index >= TopRow) {\r
//\r
- // Back up the previous option.\r
+ // At here, only case "Index < PreviousMenuOption->Skip" can reach here.\r
//\r
+ SkipValue = PreviousMenuOption->Skip - (Index - TopRow);\r
+ } else {\r
+ SkipValue = PreviousMenuOption->Skip - (TopRow - Index);\r
Link = Link->ForwardLink;\r
}\r
\r
break;\r
\r
case CfUiPageDown:\r
+ //\r
+ // SkipValue means lines is skipped when show the top menu option.\r
+ //\r
ControlFlag = CfCheckSelection;\r
\r
ASSERT (NewPos != NULL);\r
Repaint = TRUE;\r
Link = TopOfScreen;\r
NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- Index = TopRow;\r
- while ((Index <= BottomRow) && (Link->ForwardLink != &gMenuOption)) {\r
- Index = Index + NextMenuOption->Skip;\r
+ Index = TopRow + NextMenuOption->Skip - SkipValue;\r
+ //\r
+ // Count to the menu option which will show at the top of the next form.\r
+ //\r
+ while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {\r
Link = Link->ForwardLink;\r
NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ Index = Index + NextMenuOption->Skip;\r
}\r
\r
- if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow)) {\r
+ if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {\r
//\r
// Finally we know that NewPos is the last MenuOption can be focused.\r
//\r
Repaint = FALSE;\r
MoveToNextStatement (Selection, TRUE, &Link, Index - TopRow);\r
+ SkipValue = 0;\r
} else {\r
- if (Index - 1 > BottomRow) {\r
+ //\r
+ // Calculate the skip line for top of screen menu.\r
+ //\r
+ if (Link == TopOfScreen) {\r
//\r
- // Back up the previous option.\r
+ // The top of screen menu option occupies the entire form.\r
//\r
- Link = Link->BackLink;\r
+ SkipValue += BottomRow - TopRow + 1;\r
+ } else {\r
+ SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));\r
}\r
- //\r
- // There are more MenuOption needing scrolling down.\r
- //\r
+\r
TopOfScreen = Link;\r
MenuOption = NULL;\r
//\r
- // Move to the option in Next page.\r
+ // Move to the Next selectable menu.\r
//\r
MoveToNextStatement (Selection, FALSE, &Link, BottomRow - TopRow);\r
}\r
\r
+ //\r
+ // Save the menu as the next highlight menu.\r
+ //\r
+ NewPos = Link;\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
\r
case CfUiDown:\r
+ //\r
+ // SkipValue means lines is skipped when show the top menu option.\r
+ // NewPos points to the menu which is highlighted now.\r
+ //\r
ControlFlag = CfCheckSelection;\r
//\r
// Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
NewPos = NewPos->ForwardLink;\r
\r
Difference = 0;\r
+ //\r
+ // Current menu not at the bottom of the form.\r
+ //\r
if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
- Difference = MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
+ //\r
+ // Find the next selectable menu.\r
+ //\r
+ Difference = MoveToNextStatement (Selection, 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
NewPos = gMenuOption.ForwardLink;\r
MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
- \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
}\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);\r
+ if (NextMenuOption->Row == 0) {\r
+ UpdateOptionSkipLines (Selection, NextMenuOption);\r
+ }\r
DistanceValue = Difference + NextMenuOption->Skip;\r
\r
Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\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) || (MenuOption->Skip > 1)) {\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 - OldSkipValue)) {\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 - OldSkipValue);\r
-\r
- OldSkipValue = Difference;\r
+ Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
\r
SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
\r
// SkipValue, set the skips to one less than what is required.\r
//\r
SkipValue = Difference - 1;\r
-\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 = OldSkipValue + (Temp - BottomRow) - 1;\r
+ SkipValue += (Temp - BottomRow) - 1;\r
}\r
} else {\r
- if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
+ if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
TopOfScreen = TopOfScreen->ForwardLink;\r
break;\r
- } else {\r
- SkipValue = OldSkipValue;\r
}\r
}\r
//\r
} while (SavedMenuOption->Skip == 0);\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
Repaint = TRUE;\r
MenuOption = NULL;\r
} else {\r
+ //\r
+ // Need to remove the current highlight menu.\r
+ // MenuOption saved the last highlight menu info.\r
+ //\r
MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
}\r
+\r
+ SkipValue = 0;\r
NewLine = TRUE;\r
+ //\r
+ // Get the next highlight menu.\r
+ //\r
NewPos = gMenuOption.ForwardLink;\r
MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
}\r