inputhandler.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,569 行 · 第 1/4 页
C
1,569 行
FormattedNumber[2] = RIGHT_NUMERIC_DELIMITER;
FormattedNumber[1] = FormattedNumber[0];
FormattedNumber[0] = L'0';
Number = 8;
}
PrintStringAt (Column, Row, FormattedNumber);
if (Number == 10 && (NumericType == DATE_NUMERIC)) {
PrintChar (RIGHT_NUMERIC_DELIMITER);
}
if (NumericType == REGULAR_NUMERIC) {
PrintChar (RIGHT_NUMERIC_DELIMITER);
}
}
break;
case SCAN_UP:
case SCAN_DOWN:
goto EnterCarriageReturn;
case SCAN_ESC:
return EFI_DEVICE_ERROR;
default:
break;
}
break;
EnterCarriageReturn:
case CHAR_CARRIAGE_RETURN:
//
// Check to see if the Value is something reasonable against consistency limitations.
// If not, let's kick the error specified.
//
//
// This gives us visibility to the FileFormTags->NvRamMap to check things
// ActiveIfr is a global maintained by the menuing code to ensure that we
// are pointing to the correct formset's file data.
//
for (Count = 0; Count < gActiveIfr; Count++) {
FileFormTags = FileFormTags->NextFile;
}
ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
EfiCopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], &Tag->Value, Tag->StorageWidth);
//
// Data associated with a NULL device (in the fake NV storage)
//
if (Tag->StorageWidth == (UINT16) 0) {
EfiCopyMem (&VariableDefinition->FakeNvRamMap[Tag->StorageStart], &Tag->Value, 2);
}
//
// If a late check is required save off the information. This is used when consistency checks
// are required, but certain values might be bound by an impossible consistency check such as
// if two questions are bound by consistency checks and each only has two possible choices, there
// would be no way for a user to switch the values. Thus we require late checking.
//
if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) {
EfiCopyMem (&Tag->OldValue, &BackupValue, Tag->StorageWidth);
} else {
//
// In theory, passing the value and the Id are sufficient to determine what needs
// to be done. The Id is the key to look for the entry needed in the Inconsistency
// database. That will yields operand and ID data - and since the ID's correspond
// to the NV storage, we can determine the values for other IDs there.
//
if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) {
if (PopUp == 0x0000) {
SelectionComplete = TRUE;
break;
}
StringPtr = GetToken (PopUp, MenuOption->Handle);
CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter);
do {
Status = WaitForKeyStroke (&Key);
switch (Key.UnicodeChar) {
case CHAR_CARRIAGE_RETURN:
SelectionComplete = TRUE;
gBS->FreePool (StringPtr);
break;
default:
break;
}
} while (!SelectionComplete);
Tag->Value = BackupValue;
*Value = BackupValue;
EfiCopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], &Tag->Value, Tag->StorageWidth);
//
// Data associated with a NULL device (in the fake NV storage)
//
if (Tag->StorageWidth == (UINT16) 0) {
EfiCopyMem (&VariableDefinition->FakeNvRamMap[Tag->StorageStart], &Tag->Value, 2);
}
return EFI_DEVICE_ERROR;
}
}
return EFI_SUCCESS;
break;
case CHAR_BACKSPACE:
if (ManualInput) {
if (Count == 0) {
break;
}
//
// Remove a character
//
Number = PreviousNumber[Count - 1];
*Value = (UINT16) Number;
UpdateStatusBar (INPUT_ERROR, Tag->Flags, FALSE);
Count--;
Column--;
PrintAt (Column, Row, L" ");
}
break;
default:
if (ManualInput) {
if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
UpdateStatusBar (INPUT_ERROR, Tag->Flags, TRUE);
break;
}
//
// If Count 0-4 is complete, there is no way more is valid
//
if (Count > 4) {
break;
}
//
// Someone typed something valid!
//
if (Count != 0) {
Number = Number * 10 + (Key.UnicodeChar - L'0');
} else {
Number = Key.UnicodeChar - L'0';
}
if (Number > Tag->Maximum) {
UpdateStatusBar (INPUT_ERROR, Tag->Flags, TRUE);
Number = PreviousNumber[Count];
break;
} else {
UpdateStatusBar (INPUT_ERROR, Tag->Flags, FALSE);
}
Count++;
PreviousNumber[Count] = Number;
*Value = (UINT16) Number;
Tag->Value = (UINT16) Number;
PrintCharAt (Column, Row, Key.UnicodeChar);
Column++;
}
break;
}
} while (!SelectionComplete);
return EFI_SUCCESS;
}
//
// Notice that this is at least needed for the ordered list manipulation.
// Left/Right doesn't make sense for this op-code
//
EFI_STATUS
GetSelectionInputPopUp (
IN UI_MENU_OPTION *MenuOption,
IN EFI_TAG *Tag,
IN UINTN ValueCount,
OUT UINT16 *Value,
OUT UINT16 *KeyValue
)
{
EFI_STATUS Status;
EFI_INPUT_KEY Key;
UINTN Index;
UINTN TempIndex;
CHAR16 *StringPtr;
CHAR16 *TempStringPtr;
UINT16 Token;
UINTN Index2;
UINTN TopOptionIndex;
UINTN HighlightPosition;
UINTN Start;
UINTN End;
UINTN Top;
UINTN Bottom;
UINT16 TempValue;
UINTN Count;
UINTN PopUpMenuLines;
UINTN MenuLinesInView;
UINTN PopUpWidth;
CHAR16 Character;
UINTN FirstOption;
BOOLEAN FirstOptionFoundFlag;
INT32 SavedAttribute;
EFI_TAG TagBackup;
UINT8 *ValueArray;
UINT8 *ValueArrayBackup;
UINT8 ValueBackup;
BOOLEAN Initialized;
BOOLEAN KeyInitialized;
BOOLEAN ShowDownArrow;
BOOLEAN ShowUpArrow;
UINTN DimensionsWidth;
UINTN DimensionsHeight;
DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
TempValue = 0;
TempIndex = 0;
ValueArray = (UINT8 *) Value;
ValueArrayBackup = NULL;
Initialized = FALSE;
KeyInitialized = FALSE;
ShowDownArrow = FALSE;
ShowUpArrow = FALSE;
if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) {
ValueArrayBackup = EfiLibAllocateZeroPool (Tag->StorageWidth);
ASSERT (ValueArrayBackup != NULL);
EfiCopyMem (ValueArrayBackup, ValueArray, ValueCount);
TempValue = *(UINT8 *) (ValueArray);
if (ValueArray[0] != 0x00) {
Initialized = TRUE;
}
for (Index = 0; ValueArray[Index] != 0x00; Index++)
;
ValueCount = Index;
} else {
TempValue = *Value;
}
Count = 0;
PopUpWidth = 0;
FirstOption = MenuOption->TagIndex;
FirstOptionFoundFlag = FALSE;
StringPtr = EfiLibAllocateZeroPool ((gOptionBlockWidth + 1) * 2);
ASSERT (StringPtr);
//
// Initialization for "One of" pop-up menu
//
//
// Get the number of one of options present and its size
//
for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) {
if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP &&
!MenuOption->Tags[Index].Suppress) {
if (!FirstOptionFoundFlag) {
FirstOption = Index;
FirstOptionFoundFlag = TRUE;
}
Count++;
Token = MenuOption->Tags[Index].Text;
//
// If this is an ordered list that is initialized
//
if (Initialized) {
for (ValueBackup = (UINT8) MenuOption->TagIndex;
MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_OP;
ValueBackup++
) {
if (MenuOption->Tags[ValueBackup].Value == ((UINT8 *) ValueArrayBackup)[Index - MenuOption->TagIndex - 1]) {
StringPtr = GetToken (MenuOption->Tags[ValueBackup].Text, MenuOption->Handle);
break;
}
}
} else {
StringPtr = GetToken (Token, MenuOption->Handle);
}
if (EfiStrLen (StringPtr) > PopUpWidth) {
PopUpWidth = EfiStrLen (StringPtr);
}
gBS->FreePool (StringPtr);
}
}
//
// Perform popup menu initialization.
//
PopUpMenuLines = Count;
PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
SavedAttribute = gST->ConOut->Mode->Attribute;
gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
}
Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
End = Start + PopUpWidth + POPUP_FRAME_WIDTH;
Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT;
MenuLinesInView = Bottom - Top - 1;
if (MenuLinesInView >= PopUpMenuLines) {
Top = Top + (MenuLinesInView - PopUpMenuLines) / 2;
Bottom = Top + PopUpMenuLines + 1;
} else {
TempValue = MenuOption->Tags[MenuOption->TagIndex + 1].Value;
ShowDownArrow = TRUE;
}
TopOptionIndex = 1;
HighlightPosition = 0;
do {
if (Initialized) {
for (Index = MenuOption->TagIndex, Index2 = 0; Index2 < ValueCount; Index++, Index2++) {
//
// Set the value for the item we are looking for
//
Count = ValueArrayBackup[Index2];
//
// If we hit the end of the Array, we are complete
//
if (Count == 0) {
break;
}
if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
for (ValueBackup = (UINT8) MenuOption->TagIndex;
MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_ONE_OF_OP;
ValueBackup++
) {
//
// We just found what we are looking for
//
if (MenuOption->Tags[ValueBackup].Value == Count) {
//
// As long as the two indexes aren't the same, we have
// two different op-codes we need to swap internally
//
if (Index != ValueBackup) {
//
// Backup destination tag, then copy source to destination, then copy backup to source location
//
EfiCopyMem (&TagBackup, &MenuOption->Tags[Index], sizeof (EFI_TAG));
EfiCopyMem (&MenuOption->Tags[Index], &MenuOption->Tags[ValueBackup], sizeof (EFI_TAG));
EfiCopyMem (&MenuOption->Tags[ValueBackup], &TagBackup, sizeof (EFI_TAG));
} else {
//
// If the indexes are the same, then the op-code is where he belongs
//
}
}
}
} else {
//
// Since this wasn't an option op-code (likely the ordered list op-code) decerement Index2
//
Index2--;
}
}
}
//
// Clear that portion of the screen
//
ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
//
// Draw "One of" pop-up menu
//
Character = BOXDRAW_DOWN_RIGHT;
PrintCharAt (Start, Top, Character);
for (Index = Start; Index + 2 < End; Index++) {
if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {
Character = GEOMETRICSHAPE_UP_TRIANGLE;
} else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?