ui.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,158 行 · 第 1/5 页
C
2,158 行
// 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 (Temp2 != 0) {
Temp2--;
}
}
Temp2 = 0;
Row = OriginalRow;
}
//
// If this is a text op with secondary text information
//
if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP) && (MenuOption->ThisTag->TextTwo != 0)) {
StringPtr = GetToken (MenuOption->ThisTag->TextTwo, MenuOption->Handle);
Width = (UINT16) gOptionBlockWidth;
OriginalRow = Row;
for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
if ((Temp == 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 (&StringPtr[Index])) {
if (Temp2 == 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 (Temp2 != 0) {
Temp2--;
}
}
Row = OriginalRow;
gBS->FreePool (StringPtr);
}
} else {
//
// For now, assume left-justified 72 width max setup entries
//
PrintStringAt (Col, Row, MenuOption->Description);
}
//
// Tracker 6210 - need to handle the bottom of the display
//
if (MenuOption->Skip > 1) {
Row += MenuOption->Skip - SkipValue;
SkipValue = 0;
} else {
Row += MenuOption->Skip;
}
if (Row > BottomRow) {
if (!ValueIsScroll (FALSE, Link)) {
gDownArrow = TRUE;
}
Row = BottomRow + 1;
break;
}
}
if (!ValueIsScroll (TRUE, TopOfScreen)) {
gUpArrow = TRUE;
}
if (gUpArrow) {
gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
PrintAt (
LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
TopRow - SCROLL_ARROW_HEIGHT,
L"%c",
ARROW_UP
);
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
}
if (gDownArrow) {
gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
PrintAt (
LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
BottomRow + SCROLL_ARROW_HEIGHT,
L"%c",
ARROW_DOWN
);
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
}
if (SavedMenuOption != NULL) {
MenuOption = SavedMenuOption;
}
}
break;
case CfRefreshHighLight:
ControlFlag = CfUpdateHelpString;
//
// Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
// reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
//
SavedValue = Repaint;
Repaint = FALSE;
if (NewPos != NULL) {
gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
if (SubMenu) {
if (gLastOpr && (gEntryNumber != -1)) {
MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
if (gEntryNumber != MenuOption->EntryNumber) {
ScreenOperation = UiDown;
ControlFlag = CfScreenOperation;
break;
} else {
gLastOpr = FALSE;
}
}
ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
if (OptionString != NULL) {
//
// If leading spaces on OptionString - remove the spaces
//
for (Index = 0; OptionString[Index] == L' '; Index++)
;
for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
OptionString[Count] = OptionString[Index];
Count++;
}
OptionString[Count] = CHAR_NULL;
Width = (UINT16) gOptionBlockWidth;
OriginalRow = MenuOption->Row;
for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
}
//
// If there is more string to process print on the next row and increment the Skip value
//
if (EfiStrLen (&OptionString[Index])) {
MenuOption->Row++;
}
gBS->FreePool (OutputString);
}
MenuOption->Row = OriginalRow;
} else {
if (NewLine) {
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);
}
}
OriginalRow = MenuOption->Row;
Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
PrintStringAt (Col, MenuOption->Row, OutputString);
}
//
// If there is more string to process print on the next row and increment the Skip value
//
if (EfiStrLen (&MenuOption->Description[Index])) {
MenuOption->Row++;
}
gBS->FreePool (OutputString);
}
MenuOption->Row = OriginalRow;
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
}
}
} else {
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
}
MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
if ((gPriorMenuEntry != 0) && (MenuOption->EntryNumber != gPriorMenuEntry) && (NewPos->ForwardLink != &Menu)) {
ScreenOperation = UiDown;
ControlFlag = CfScreenOperation;
break;
} else {
gPriorMenuEntry = 0;
}
//
// This is only possible if we entered this page and the first menu option is
// a "non-menu" item. In that case, force it UiDown
//
if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) {
//
// If we previously hit an UP command and we are still sitting on a text operation
// we must continue going up
//
if (ScreenOperation == UiUp) {
ControlFlag = CfScreenOperation;
break;
} else {
ScreenOperation = UiDown;
ControlFlag = CfScreenOperation;
break;
}
}
//
// Set reverse attribute
//
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
//
// Assuming that we have a refresh linked-list created, lets annotate the
// appropriate entry that we are highlighting with its new attribute. Just prior to this
// lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
//
if (gMenuRefreshHead != NULL) {
for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {
MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
if (MenuRefreshEntry->MenuOption == MenuOption) {
MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;
}
}
}
if (SubMenu) {
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 (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
OptionString[Count] = OptionString[Index];
Count++;
}
OptionString[Count] = CHAR_NULL;
Width = (UINT16) gOptionBlockWidth;
OriginalRow = MenuOption->Row;
for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
}
//
// If there is more string to process print on the next row and increment the Skip value
//
if (EfiStrLen (&OptionString[Index])) {
MenuOption->Row++;
}
gBS->FreePool (OutputString);
}
MenuOption->Row = OriginalRow;
} else {
if (NewLine) {
OriginalRow = MenuOption->Row;
Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
PrintStringAt (Col, MenuOption->Row, OutputString);
}
//
// If there is more string to process print on the next row and increment the Skip value
//
if (EfiStrLen (&MenuOption->Description[Index])) {
MenuOption->Row++;
}
gBS->FreePool (OutputString);
}
MenuOption->Row = OriginalRow;
}
}
if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||
((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||
(ScreenOperation == UiNoOperation)
) {
UpdateKeyHelp (MenuOption, FALSE);
}
} else {
gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
}
//
// Clear reverse attribute
//
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
}
//
// Repaint flag will be used when process CfUpdateHelpString, so restore its value
// if we didn't break halfway when process CfRefreshHighLight.
//
Repaint = SavedValue;
break;
case CfUpdateHelpString:
ControlFlag = CfPrepareToReadKey;
if (SubMenu &&
(Repaint || NewLine ||
(MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
(MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) &&
!(gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS)) {
//
// Don't print anything if it is a NULL help token
//
if (MenuOption->ThisTag->Help == 0x00000000) {
StringPtr = L"\0";
} else {
StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
}
ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);
gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
for (Index = 0; Index < BottomRow - TopRow; Index++) {
//
// Pad String with spaces to simulate a clearing of the previous line
//
for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth]) / 2 < gHelpBlockWidth;) {
EfiStrCat (&FormattedString[Index * gHelpBlockWidth], L" ");
}
PrintStringAt (
LocalScreen.RightColumn - gHelpBlockWidth,
Index + TopRow,
&FormattedString[Index * gHelpBlockWidth]
);
}
}
//
// Reset this flag every time we finish using it.
//
Repaint = FALSE;
NewLine = FALSE;
break;
case CfPrepareToReadKey:
ControlFlag = CfReadKey;
for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
FileFormTags = FileFormTags->NextFile;
}
ScreenOperation = UiNoOperation;
Status = gBS->HandleProtocol (
(VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
&gEfiFormCallbackProtocolGuid,
&FormCallback
);
break;
case CfReadKey:
ControlFlag = CfScreenOperation;
OriginalTimeOut = FrontPageTimeOutValue;
do {
if (FrontPageTimeOutValue >= 0 && (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) && FrontPageTimeOutValue != 0xFFFF) {
//
// Remember that if set to 0, must immediately boot an option
//
if (FrontPageTimeOutValue == 0) {
FrontPageTimeOutValue = 0xFFFF;
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if (EFI_ERROR (Status)) {
Status = EFI_TIMEOUT;
}
break;
}
Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
if (Status == EFI_TIMEOUT) {
PageData->EntryCount = 1;
Count = (UINT32) ((OriginalTimeOut - FrontPageTimeOutValue) * 100 / OriginalTimeOut);
EfiCopyMem (&PageData->Data->Data, &Count, sizeof (UINT32));
if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
FormCallback->Callback (
FormCallbac
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?