Change the FormBrowser behavior of "Pressing ESC":

The old behavior is: if press ESC, it will exit the whole Formset.
The new behavior is: if press ESC, it will return to the parent Form; if current Form is the root Form of a FormSet, it will exit the whole FormSet.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9359 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
xdu2
2009-10-26 03:03:12 +00:00
parent 0ce94f384e
commit d66e6c1687
6 changed files with 464 additions and 276 deletions

View File

@@ -1,7 +1,7 @@
/** @file
Utility functions for User Interface functions.
Copyright (c) 2004 - 2008, Intel Corporation
Copyright (c) 2004 - 2009, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -16,7 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "Setup.h"
LIST_ENTRY Menu;
LIST_ENTRY gMenuList;
LIST_ENTRY gMenuList = INITIALIZE_LIST_HEAD_VARIABLE (gMenuList);
MENU_REFRESH_ENTRY *gMenuRefreshHead;
//
@@ -43,10 +43,6 @@ SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {
SCAN_ESC,
UiReset,
},
{
SCAN_F2,
UiPrevious,
},
{
SCAN_LEFT,
UiLeft,
@@ -102,10 +98,6 @@ SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {
UiSave,
CfUiSave,
},
{
UiPrevious,
CfUiPrevious,
},
{
UiPageUp,
CfUiPageUp,
@@ -127,8 +119,6 @@ BOOLEAN GetLineByWidthFinished = FALSE;
@param Size Number of bytes to set
@param Value Value of the set operation.
@return Value.
**/
VOID
SetUnicodeMem (
@@ -159,86 +149,6 @@ UiInitMenu (
}
/**
Initialize Menu option list.
**/
VOID
UiInitMenuList (
VOID
)
{
InitializeListHead (&gMenuList);
}
/**
Remove a Menu in list, and return FormId/QuestionId for previous Menu.
@param Selection Menu selection.
**/
VOID
UiRemoveMenuListEntry (
OUT UI_MENU_SELECTION *Selection
)
{
UI_MENU_LIST *UiMenuList;
if (!IsListEmpty (&gMenuList)) {
UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
Selection->FormId = UiMenuList->FormId;
Selection->QuestionId = UiMenuList->QuestionId;
RemoveEntryList (&UiMenuList->MenuLink);
FreePool (UiMenuList);
}
}
/**
Free Menu option linked list.
**/
VOID
UiFreeMenuList (
VOID
)
{
UI_MENU_LIST *UiMenuList;
while (!IsListEmpty (&gMenuList)) {
UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
RemoveEntryList (&UiMenuList->MenuLink);
FreePool (UiMenuList);
}
}
/**
Add one menu entry to the linked lst
@param Selection Menu selection.
**/
VOID
UiAddMenuListEntry (
IN UI_MENU_SELECTION *Selection
)
{
UI_MENU_LIST *UiMenuList;
UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
ASSERT (UiMenuList != NULL);
UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;
UiMenuList->FormId = Selection->FormId;
UiMenuList->QuestionId = Selection->QuestionId;
InsertHeadList (&gMenuList, &UiMenuList->MenuLink);
}
/**
Free Menu option linked list.
@@ -270,6 +180,130 @@ UiFreeMenu (
}
/**
Create a menu with specified formset GUID and form ID, and add it as a child
of the given parent menu.
@param Parent The parent of menu to be added.
@param FormSetGuid The Formset Guid of menu to be added.
@param FormId The Form ID of menu to be added.
@return A pointer to the newly added menu or NULL if memory is insufficient.
**/
UI_MENU_LIST *
UiAddMenuList (
IN OUT UI_MENU_LIST *Parent,
IN EFI_GUID *FormSetGuid,
IN UINT16 FormId
)
{
UI_MENU_LIST *MenuList;
MenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
if (MenuList == NULL) {
return NULL;
}
MenuList->Signature = UI_MENU_LIST_SIGNATURE;
InitializeListHead (&MenuList->ChildListHead);
CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
MenuList->FormId = FormId;
MenuList->Parent = Parent;
if (Parent == NULL) {
//
// If parent is not specified, it is the root Form of a Formset
//
InsertTailList (&gMenuList, &MenuList->Link);
} else {
InsertTailList (&Parent->ChildListHead, &MenuList->Link);
}
return MenuList;
}
/**
Search Menu with given FormId in the parent menu and all its child menus.
@param Parent The parent of menu to search.
@param FormId The Form ID of menu to search.
@return A pointer to menu found or NULL if not found.
**/
UI_MENU_LIST *
UiFindChildMenuList (
IN UI_MENU_LIST *Parent,
IN UINT16 FormId
)
{
LIST_ENTRY *Link;
UI_MENU_LIST *Child;
UI_MENU_LIST *MenuList;
if (Parent->FormId == FormId) {
return Parent;
}
Link = GetFirstNode (&Parent->ChildListHead);
while (!IsNull (&Parent->ChildListHead, Link)) {
Child = UI_MENU_LIST_FROM_LINK (Link);
MenuList = UiFindChildMenuList (Child, FormId);
if (MenuList != NULL) {
return MenuList;
}
Link = GetNextNode (&Parent->ChildListHead, Link);
}
return NULL;
}
/**
Search Menu with given FormSetGuid and FormId in all cached menu list.
@param FormSetGuid The Formset GUID of the menu to search.
@param FormId The Form ID of menu to search.
@return A pointer to menu found or NULL if not found.
**/
UI_MENU_LIST *
UiFindMenuList (
IN EFI_GUID *FormSetGuid,
IN UINT16 FormId
)
{
LIST_ENTRY *Link;
UI_MENU_LIST *MenuList;
UI_MENU_LIST *Child;
Link = GetFirstNode (&gMenuList);
while (!IsNull (&gMenuList, Link)) {
MenuList = UI_MENU_LIST_FROM_LINK (Link);
if (CompareGuid (FormSetGuid, &MenuList->FormSetGuid)) {
//
// This is the formset we are looking for, find the form in this formset
//
Child = UiFindChildMenuList (MenuList, FormId);
if (Child != NULL) {
return Child;
}
}
Link = GetNextNode (&gMenuList, Link);
}
return NULL;
}
/**
Free Menu option linked list.
@@ -929,7 +963,7 @@ CreateMultiStringPopUp (
VA_LIST Marker;
VA_START (Marker, NumberOfLines);
CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);
VA_END (Marker);
@@ -1275,7 +1309,7 @@ IsSelectable (
Determine if the menu is the last menu that can be selected.
This is an internal function.
@param Direction The scroll direction. False is down. True is up.
@param CurrentPos The current focus.
@@ -1311,9 +1345,9 @@ ValueIsScroll (
/**
Move to next selectable statement.
This is an internal function.
@param GoUp The navigation direction. TRUE: up, FALSE: down.
@param CurrentPosition Current position.
@@ -1379,7 +1413,7 @@ MoveToNextStatement (
Adjust Data and Time position accordingly.
Data format : [01/02/2004] [11:22:33]
Line number : 0 0 1 0 0 1
This is an internal function.
@param DirectionUp the up or down direction. False is down. True is
@@ -1606,6 +1640,8 @@ UiDisplayMenu (
CHAR16 TemStr[2];
UINT8 *DevicePathBuffer;
UINT8 DigitUint8;
UI_MENU_LIST *CurrentMenu;
UI_MENU_LIST *MenuList;
CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
@@ -1651,6 +1687,25 @@ UiDisplayMenu (
Repaint = TRUE;
MenuOption = NULL;
//
// Find current Menu
//
CurrentMenu = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId);
if (CurrentMenu == NULL) {
//
// Current menu not found, add it to the menu tree
//
CurrentMenu = UiAddMenuList (NULL, &Selection->FormSetGuid, Selection->FormId);
}
ASSERT (CurrentMenu != NULL);
if (Selection->QuestionId == 0) {
//
// Highlight not specified, fetch it from cached menu
//
Selection->QuestionId = CurrentMenu->QuestionId;
}
//
// Get user's selection
//
@@ -2103,6 +2158,10 @@ UiDisplayMenu (
//
Statement = MenuOption->ThisTag;
Selection->Statement = Statement;
//
// Record highlight for current menu
//
CurrentMenu->QuestionId = Statement->QuestionId;
//
// Set reverse attribute
@@ -2258,27 +2317,19 @@ UiDisplayMenu (
//
// IFR is updated in Callback of refresh opcode, re-parse it
//
ControlFlag = CfUiReset;
Selection->Statement = NULL;
break;
return EFI_SUCCESS;
}
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
//
// if we encounter error, continue to read another key in.
// If we encounter error, continue to read another key in.
//
if (EFI_ERROR (Status)) {
ControlFlag = CfReadKey;
break;
}
if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {
//
// If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
//
break;
}
switch (Key.UnicodeChar) {
case CHAR_CARRIAGE_RETURN:
ScreenOperation = UiSelect;
@@ -2334,7 +2385,6 @@ UiDisplayMenu (
case CHAR_NULL:
if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||
((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||
((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||
((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))
) {
@@ -2360,9 +2410,9 @@ UiDisplayMenu (
break;
case CfScreenOperation:
if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {
if (ScreenOperation != UiReset) {
//
// If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
// If the screen has no menu items, and the user didn't select UiReset
// ignore the selection and go back to reading keys.
//
if (IsListEmpty (&Menu)) {
@@ -2383,12 +2433,6 @@ UiDisplayMenu (
ControlFlag = CfPrepareToReadKey;
break;
}
} else if (ScreenOperation == UiReset) {
//
// Press ESC to exit FormSet
//
Selection->Action = UI_ACTION_EXIT;
Selection->Statement = NULL;
}
for (Index = 0;
@@ -2402,26 +2446,6 @@ UiDisplayMenu (
}
break;
case CfUiPrevious:
ControlFlag = CfCheckSelection;
if (IsListEmpty (&gMenuList)) {
Selection->Action = UI_ACTION_NONE;
if (IsListEmpty (&Menu)) {
ControlFlag = CfReadKey;
}
break;
}
//
// Remove the Cached page entry
//
UiRemoveMenuListEntry (Selection);
Selection->Action = UI_ACTION_REFRESH_FORM;
Selection->Statement = NULL;
break;
case CfUiSelect:
ControlFlag = CfCheckSelection;
@@ -2444,7 +2468,7 @@ UiDisplayMenu (
//
// Goto another Hii Package list
//
ControlFlag = CfUiReset;
ControlFlag = CfCheckSelection;
Selection->Action = UI_ACTION_REFRESH_FORMSET;
StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);
@@ -2458,7 +2482,7 @@ UiDisplayMenu (
}
BufferSize = StrLen (StringPtr) / 2;
DevicePath = AllocatePool (BufferSize);
//
// Convert from Device Path String to DevicePath Buffer in the reverse order.
//
@@ -2499,7 +2523,7 @@ UiDisplayMenu (
//
// Goto another Formset, check for uncommitted data
//
ControlFlag = CfUiReset;
ControlFlag = CfCheckSelection;
Selection->Action = UI_ACTION_REFRESH_FORMSET;
CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
@@ -2512,9 +2536,12 @@ UiDisplayMenu (
Selection->Action = UI_ACTION_REFRESH_FORM;
//
// Link current form so that we can always go back when someone hits the UiPrevious
// Link current form so that we can always go back when someone hits the ESC
//
UiAddMenuListEntry (Selection);
MenuList = UiFindMenuList (&Selection->FormSetGuid, Statement->RefFormId);
if (MenuList == NULL) {
MenuList = UiAddMenuList (CurrentMenu, &Selection->FormSetGuid, Statement->RefFormId);
}
Selection->FormId = Statement->RefFormId;
Selection->QuestionId = Statement->RefQuestionId;
@@ -2582,21 +2609,44 @@ UiDisplayMenu (
case CfUiReset:
//
// We are going to leave current FormSet, so check uncommited data in this FormSet
// We come here when someone press ESC
//
ControlFlag = CfCheckSelection;
if (CurrentMenu->Parent != NULL) {
//
// we have a parent, so go to the parent menu
//
if (CompareGuid (&CurrentMenu->FormSetGuid, &CurrentMenu->Parent->FormSetGuid)) {
//
// The parent menu and current menu are in the same formset
//
Selection->Action = UI_ACTION_REFRESH_FORM;
} else {
Selection->Action = UI_ACTION_REFRESH_FORMSET;
}
Selection->Statement = NULL;
Selection->FormId = CurrentMenu->Parent->FormId;
Selection->QuestionId = CurrentMenu->Parent->QuestionId;
//
// Clear highlight record for this menu
//
CurrentMenu->QuestionId = 0;
break;
}
if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
//
// There is no parent menu for FrontPage
// We never exit FrontPage, so skip the ESC
//
Selection->Action = UI_ACTION_NONE;
Selection->Statement = MenuOption->ThisTag;
break;
}
//
// If NV flag is up, prompt user
// We are going to leave current FormSet, so check uncommited data in this FormSet
//
if (gNvUpdateRequired) {
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
@@ -2604,8 +2654,11 @@ UiDisplayMenu (
YesResponse = gYesResponse[0];
NoResponse = gNoResponse[0];
//
// If NV flag is up, prompt user
//
do {
CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);
CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);
} while
(
(Key.ScanCode != SCAN_ESC) &&
@@ -2613,24 +2666,29 @@ UiDisplayMenu (
((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
);
//
// If the user hits the YesResponse key
//
if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
} else {
if (Key.ScanCode == SCAN_ESC) {
//
// User hits the ESC key
//
Repaint = TRUE;
NewLine = TRUE;
Selection->Action = UI_ACTION_NONE;
break;
}
//
// If the user hits the YesResponse key
//
if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
Status = SubmitForm (Selection->FormSet, Selection->Form);
}
}
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
Selection->Action = UI_ACTION_EXIT;
Selection->Statement = NULL;
CurrentMenu->QuestionId = 0;
UiFreeMenuList ();
gST->ConOut->ClearScreen (gST->ConOut);
return EFI_SUCCESS;
case CfUiLeft:
@@ -2696,19 +2754,19 @@ UiDisplayMenu (
TopOfScreen = NewPos;
}
Difference = MoveToNextStatement (TRUE, &NewPos);
Difference = MoveToNextStatement (TRUE, &NewPos);
PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);
DistanceValue += PreviousMenuOption->Skip;
if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
if (Difference > 0) {
//
// Previous focus MenuOption is above the TopOfScreen, so we need to scroll
//
TopOfScreen = NewPos;
Repaint = TRUE;
SkipValue = 0;
OldSkipValue = 0;
SkipValue = 0;
OldSkipValue = 0;
}
}
if (Difference < 0) {