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 + -
显示快捷键?