ui.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,158 行 · 第 1/5 页
C
2,158 行
*Index = (UINT16) (*Index + LineWidth);
return LineWidth;
} else {
return (UINT16) 0;
}
}
VOID
UpdateOptionSkipLines (
IN EFI_IFR_DATA_ARRAY *PageData,
IN UI_MENU_OPTION *MenuOption,
IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
IN CHAR16 **OptionalString,
IN UINTN SkipValue
)
{
UINTN Index;
UINTN Loop;
UINT16 Width;
UINTN Row;
UINTN OriginalRow;
CHAR16 *OutputString;
CHAR16 *OptionString;
Row = 0;
OptionString = *OptionalString;
OutputString = NULL;
ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
if (OptionString != NULL) {
//
// If leading spaces on OptionString - remove the spaces
//
for (Index = 0; OptionString[Index] == L' '; Index++)
;
for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {
OptionString[Loop] = OptionString[Index];
Loop++;
}
OptionString[Loop] = CHAR_NULL;
Width = (UINT16) gOptionBlockWidth;
OriginalRow = Row;
for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
//
// If there is more string to process print on the next row and increment the Skip value
//
if (EfiStrLen (&OptionString[Index])) {
if (SkipValue == 0) {
Row++;
//
// Since the Number of lines for this menu entry may or may not be reflected accurately
// since the prompt might be 1 lines and option might be many, and vice versa, we need to do
// some testing to ensure we are keeping this in-sync.
//
// If the difference in rows is greater than or equal to the skip value, increase the skip value
//
if ((Row - OriginalRow) >= MenuOption->Skip) {
MenuOption->Skip++;
}
}
}
gBS->FreePool (OutputString);
if (SkipValue != 0) {
SkipValue--;
}
}
Row = OriginalRow;
}
*OptionalString = OptionString;
}
//
// Search table for UiDisplayMenu()
//
SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {
SCAN_UP,
UiUp,
SCAN_DOWN,
UiDown,
SCAN_PAGE_UP,
UiPageUp,
SCAN_PAGE_DOWN,
UiPageDown,
SCAN_ESC,
UiReset,
SCAN_F2,
UiPrevious,
SCAN_LEFT,
UiLeft,
SCAN_RIGHT,
UiRight,
SCAN_F9,
UiDefault,
SCAN_F10,
UiSave
};
SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {
UiNoOperation,
CfUiNoOperation,
UiDefault,
CfUiDefault,
UiSelect,
CfUiSelect,
UiUp,
CfUiUp,
UiDown,
CfUiDown,
UiLeft,
CfUiLeft,
UiRight,
CfUiRight,
UiReset,
CfUiReset,
UiSave,
CfUiSave,
UiPrevious,
CfUiPrevious,
UiPageUp,
CfUiPageUp,
UiPageDown,
CfUiPageDown
};
UI_MENU_OPTION *
UiDisplayMenu (
IN BOOLEAN SubMenu,
IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
OUT EFI_IFR_DATA_ARRAY *PageData
)
/*++
Routine Description:
Display menu and wait for user to select one menu option, then return it.
If AutoBoot is enabled, then if user doesn't select any option,
after period of time, it will automatically return the first menu option.
Arguments:
SubMenu - Indicate is sub menu.
FileFormTagsHead - A pointer to the EFI_FILE_FORM_TAGS structure.
PageData - A pointer to the EFI_IFR_DATA_ARRAY.
Returns:
Return the pointer of the menu which selected,
otherwise return NULL.
--*/
{
INTN SkipValue;
INTN Difference;
INTN OldSkipValue;
UINTN Row;
UINTN Col;
UINTN Temp;
UINTN Temp2;
UINTN TopRow;
UINTN BottomRow;
UINTN OriginalRow;
UINTN Index;
UINTN DataAndTimeLineNumberPad;
UINT32 Count;
UINT16 OriginalTimeOut;
UINT8 *Location;
UINT16 Width;
CHAR16 *StringPtr;
CHAR16 *OptionString;
CHAR16 *OutputString;
CHAR16 *FormattedString;
CHAR16 YesResponse;
CHAR16 NoResponse;
BOOLEAN NewLine;
BOOLEAN Repaint;
BOOLEAN SavedValue;
EFI_STATUS Status;
UI_MENU_LIST *UiMenuList;
EFI_INPUT_KEY Key;
EFI_LIST_ENTRY *Link;
EFI_LIST_ENTRY *NewPos;
EFI_LIST_ENTRY *TopOfScreen;
EFI_LIST_ENTRY *SavedListEntry;
UI_MENU_OPTION *Selection;
UI_MENU_OPTION *MenuOption;
UI_MENU_OPTION *NextMenuOption;
UI_MENU_OPTION *SavedMenuOption;
UI_MENU_OPTION *PreviousMenuOption;
EFI_IFR_BINARY *IfrBinary;
UI_CONTROL_FLAG ControlFlag;
SCREEN_DESCRIPTOR LocalScreen;
EFI_FILE_FORM_TAGS *FileFormTags;
MENU_REFRESH_ENTRY *MenuRefreshEntry;
MENU_REFRESH_ENTRY *OldMenuRefreshEntry;
UI_SCREEN_OPERATION ScreenOperation;
EFI_VARIABLE_DEFINITION *VariableDefinition;
EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
EFI_HII_VARIABLE_PACK_LIST *NvMapListHead;
EFI_HII_VARIABLE_PACK_LIST *NvMapListNode;
VOID *NvMap;
UINTN NvMapSize;
EfiCopyMem (&LocalScreen, &gScreenDimensions, sizeof (SCREEN_DESCRIPTOR));
VariableDefinition = NULL;
Status = EFI_SUCCESS;
FormattedString = NULL;
OptionString = NULL;
ScreenOperation = UiNoOperation;
NewLine = TRUE;
FormCallback = NULL;
FileFormTags = NULL;
OutputString = NULL;
gUpArrow = FALSE;
gDownArrow = FALSE;
SkipValue = 0;
OldSkipValue = 0;
MenuRefreshEntry = gMenuRefreshHead;
OldMenuRefreshEntry = gMenuRefreshHead;
NextMenuOption = NULL;
PreviousMenuOption = NULL;
SavedMenuOption = NULL;
IfrBinary = NULL;
NvMap = NULL;
NvMapSize = 0;
EfiZeroMem (&Key, sizeof (EFI_INPUT_KEY));
if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
} else {
TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
}
if (SubMenu) {
Col = LocalScreen.LeftColumn;
} else {
Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;
}
BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;
TopOfScreen = Menu.ForwardLink;
Repaint = TRUE;
MenuOption = NULL;
//
// Get user's selection
//
Selection = NULL;
NewPos = Menu.ForwardLink;
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
ControlFlag = CfInitialization;
while (TRUE) {
switch (ControlFlag) {
case CfInitialization:
ControlFlag = CfCheckSelection;
if (gExitRequired) {
ScreenOperation = UiReset;
ControlFlag = CfScreenOperation;
} else if (gSaveRequired) {
ScreenOperation = UiSave;
ControlFlag = CfScreenOperation;
} else if (IsListEmpty (&Menu)) {
ControlFlag = CfReadKey;
}
break;
case CfCheckSelection:
if (Selection != NULL) {
ControlFlag = CfExit;
} else {
ControlFlag = CfRepaint;
}
FileFormTags = FileFormTagsHead;
break;
case CfRepaint:
ControlFlag = CfRefreshHighLight;
if (Repaint) {
//
// Display menu
//
SavedMenuOption = MenuOption;
gDownArrow = FALSE;
gUpArrow = FALSE;
Row = TopRow;
Temp = SkipValue;
Temp2 = SkipValue;
ClearLines (
LocalScreen.LeftColumn,
LocalScreen.RightColumn,
TopRow - SCROLL_ARROW_HEIGHT,
BottomRow + SCROLL_ARROW_HEIGHT,
FIELD_TEXT | FIELD_BACKGROUND
);
while (gMenuRefreshHead != NULL) {
OldMenuRefreshEntry = gMenuRefreshHead->Next;
gBS->FreePool (gMenuRefreshHead);
gMenuRefreshHead = OldMenuRefreshEntry;
}
for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
MenuOption->Row = Row;
OriginalRow = Row;
MenuOption->Col = Col;
MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
if (SubMenu) {
if (MenuOption->ThisTag->GrayOut) {
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
} else {
if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
}
}
Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
OriginalRow = Row;
for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
if ((Temp == 0) && (Row <= BottomRow)) {
PrintStringAt (Col, Row, OutputString);
}
//
// If there is more string to process print on the next row and increment the Skip value
//
if (EfiStrLen (&MenuOption->Description[Index])) {
if (Temp == 0) {
Row++;
}
}
gBS->FreePool (OutputString);
if (Temp != 0) {
Temp--;
}
}
Temp = 0;
Row = OriginalRow;
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
if (OptionString != NULL) {
//
// If leading spaces on OptionString - remove the spaces
//
for (Index = 0; OptionString[Index] == L' '; Index++) {
MenuOption->OptCol++;
}
for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
OptionString[Count] = OptionString[Index];
Count++;
}
OptionString[Count] = CHAR_NULL;
//
// If this is a date or time op-code and is used to reflect an RTC, register the op-code
//
if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) &&
(MenuOption->ThisTag->StorageStart >= FileFormTags->FormTags.Tags[0].NvDataSize)) {
if (gMenuRefreshHead == NULL) {
MenuRefreshEntry = EfiLibAllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
ASSERT (MenuRefreshEntry != NULL);
MenuRefreshEntry->MenuOption = MenuOption;
MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead;
MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
MenuRefreshEntry->CurrentRow = MenuOption->Row;
MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
gMenuRefreshHead = MenuRefreshEntry;
} else {
//
// Advance to the last entry
//
for (MenuRefreshEntry = gMenuRefreshHead;
MenuRefreshEntry->Next != NULL;
MenuRefreshEntry = MenuRefreshEntry->Next
)
;
MenuRefreshEntry->Next = EfiLibAllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
ASSERT (MenuRefreshEntry->Next != NULL);
MenuRefreshEntry = MenuRefreshEntry->Next;
MenuRefreshEntry->MenuOption = MenuOption;
MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead;
MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
MenuRefreshEntry->CurrentRow = MenuOption->Row;
MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
}
}
Width = (UINT16) gOptionBlockWidth;
OriginalRow = Row;
for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
if ((Temp2 == 0) && (Row <= BottomRow)) {
PrintStringAt (MenuOption->OptCol, Row, OutputString);
}
//
// If there is more string to process print on the next row and increment the Skip value
//
if (EfiStrLen (&OptionString[Index])) {
if (Temp2 == 0) {
Row++;
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?