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