Home | History | Annotate | Download | only in CustomizedDisplayLib
      1 /** @file
      2 
      3   This library class defines a set of interfaces to customize Display module
      4 
      5 Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials are licensed and made available under
      7 the terms and conditions of the BSD License that accompanies this distribution.
      8 The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php.
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 #include "CustomizedDisplayLibInternal.h"
     16 
     17 EFI_GUID          gCustomizedDisplayLibGuid = { 0x99fdc8fd, 0x849b, 0x4eba, { 0xad, 0x13, 0xfb, 0x96, 0x99, 0xc9, 0xa, 0x4d } };
     18 
     19 EFI_HII_HANDLE    mCDLStringPackHandle;
     20 UINT16            gClassOfVfr;                 // Formset class information
     21 BOOLEAN           gLibIsFirstForm = TRUE;
     22 BANNER_DATA       *gBannerData;
     23 
     24 UINTN             gFooterHeight;
     25 
     26 /**
     27 +------------------------------------------------------------------------------+
     28 |                                 Setup Page                                   |
     29 +------------------------------------------------------------------------------+
     30 
     31 Statement
     32 Statement
     33 Statement
     34 
     35 
     36 
     37 
     38 
     39 +------------------------------------------------------------------------------+
     40 |                                F9=Reset to Defaults        F10=Save          |
     41 | ^"=Move Highlight          <Spacebar> Toggles Checkbox     Esc=Exit          |
     42 +------------------------------------------------------------------------------+
     43   StatusBar
     44 **/
     45 
     46 /**
     47   This funtion defines Page Frame and Backgroud.
     48 
     49   Based on the above layout, it will be responsible for HeaderHeight, FooterHeight,
     50   StatusBarHeight and Backgroud. And, it will reserve Screen for Statement.
     51 
     52   @param[in]  FormData             Form Data to be shown in Page.
     53   @param[out] ScreenForStatement   Screen to be used for Statement. (Prompt, Value and Help)
     54 
     55   @return Status
     56 **/
     57 EFI_STATUS
     58 EFIAPI
     59 DisplayPageFrame (
     60   IN FORM_DISPLAY_ENGINE_FORM       *FormData,
     61   OUT EFI_SCREEN_DESCRIPTOR         *ScreenForStatement
     62   )
     63 {
     64   EFI_STATUS             Status;
     65 
     66   ASSERT (FormData != NULL && ScreenForStatement != NULL);
     67   if (FormData == NULL || ScreenForStatement == NULL) {
     68     return EFI_INVALID_PARAMETER;
     69   }
     70 
     71   Status = ScreenDiemensionInfoValidate (FormData);
     72   if (EFI_ERROR (Status)) {
     73     return Status;
     74   }
     75 
     76   gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;
     77 
     78   ProcessExternedOpcode(FormData);
     79 
     80   //
     81   // Calculate the ScreenForStatement.
     82   //
     83   ScreenForStatement->BottomRow   = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight;
     84   if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
     85     ScreenForStatement->TopRow    = gScreenDimensions.TopRow + FRONT_PAGE_HEADER_HEIGHT;
     86   } else {
     87     ScreenForStatement->TopRow    = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
     88   }
     89   ScreenForStatement->LeftColumn  = gScreenDimensions.LeftColumn;
     90   ScreenForStatement->RightColumn = gScreenDimensions.RightColumn;
     91 
     92   if ((gLibIsFirstForm) || ((FormData->Attribute & HII_DISPLAY_MODAL) != 0)) {
     93     //
     94     // Ensure we are in Text mode
     95     //
     96     gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
     97     ClearLines (0, gScreenDimensions.RightColumn, 0, gScreenDimensions.BottomRow, KEYHELP_BACKGROUND);
     98     gLibIsFirstForm = FALSE;
     99   }
    100 
    101   //
    102   // Don't print frame for modal form.
    103   //
    104   if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
    105     return EFI_SUCCESS;
    106   }
    107 
    108   if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
    109     PrintBannerInfo (FormData);
    110   }
    111 
    112   PrintFramework (FormData);
    113 
    114   UpdateStatusBar(NV_UPDATE_REQUIRED, FormData->SettingChangedFlag);
    115 
    116   return EFI_SUCCESS;
    117 }
    118 
    119 /**
    120   This function updates customized key panel's help information.
    121   The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-.
    122   and arrange them in Footer panel.
    123 
    124   @param[in]  FormData       Form Data to be shown in Page. FormData has the highlighted statement.
    125   @param[in]  Statement      The statement current selected.
    126   @param[in]  Selected       Whether or not a tag be selected. TRUE means Enter has hit this question.
    127 **/
    128 VOID
    129 EFIAPI
    130 RefreshKeyHelp (
    131   IN FORM_DISPLAY_ENGINE_FORM      *FormData,
    132   IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
    133   IN  BOOLEAN                      Selected
    134   )
    135 {
    136   UINTN                  SecCol;
    137   UINTN                  ThdCol;
    138   UINTN                  RightColumnOfHelp;
    139   UINTN                  TopRowOfHelp;
    140   UINTN                  BottomRowOfHelp;
    141   UINTN                  StartColumnOfHelp;
    142   EFI_IFR_NUMERIC        *NumericOp;
    143   EFI_IFR_DATE           *DateOp;
    144   EFI_IFR_TIME           *TimeOp;
    145   BOOLEAN                HexDisplay;
    146   UINTN                  ColumnWidth1;
    147   UINTN                  ColumnWidth2;
    148   UINTN                  ColumnWidth3;
    149   CHAR16                 *ColumnStr1;
    150   CHAR16                 *ColumnStr2;
    151   CHAR16                 *ColumnStr3;
    152 
    153   ASSERT (FormData != NULL);
    154   if (FormData == NULL) {
    155     return;
    156   }
    157 
    158   gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
    159 
    160   if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
    161     return;
    162   }
    163 
    164   SecCol            = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3;
    165   ThdCol            = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3 * 2;
    166 
    167   //
    168   // + 2 means leave 1 space before the first hotkey info.
    169   //
    170   StartColumnOfHelp = gScreenDimensions.LeftColumn + 2;
    171   RightColumnOfHelp = gScreenDimensions.RightColumn - 1;
    172   TopRowOfHelp      = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;
    173   BottomRowOfHelp   = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;
    174 
    175   ColumnWidth1      = SecCol - StartColumnOfHelp;
    176   ColumnWidth2      = ThdCol - SecCol;
    177   ColumnWidth3      = RightColumnOfHelp - ThdCol;
    178   ColumnStr1        = gLibEmptyString;
    179   ColumnStr2        = gLibEmptyString;
    180   ColumnStr3        = gLibEmptyString;
    181 
    182   //
    183   // Clean the space at gScreenDimensions.LeftColumn + 1.
    184   //
    185   PrintStringAtWithWidth (StartColumnOfHelp - 1, BottomRowOfHelp, gLibEmptyString, 1);
    186   PrintStringAtWithWidth (StartColumnOfHelp - 1, TopRowOfHelp, gLibEmptyString, 1);
    187 
    188   if (Statement == NULL) {
    189     //
    190     // Print Key for Form without showable statement.
    191     //
    192     PrintHotKeyHelpString (FormData, TRUE);
    193     PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, gLibEmptyString, ColumnWidth1);
    194     PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gLibEmptyString, ColumnWidth2);
    195     PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gLibEmptyString, ColumnWidth1);
    196     if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
    197       ColumnStr3 = gEscapeString;
    198     }
    199     PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
    200 
    201     return;
    202   }
    203 
    204   HexDisplay = FALSE;
    205   NumericOp = NULL;
    206   DateOp    = NULL;
    207   TimeOp    = NULL;
    208   if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {
    209     NumericOp = (EFI_IFR_NUMERIC *) Statement->OpCode;
    210     HexDisplay = (NumericOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
    211   } else if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
    212     DateOp   = (EFI_IFR_DATE *) Statement->OpCode;
    213     HexDisplay = (DateOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
    214   } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
    215     TimeOp  = (EFI_IFR_TIME *) Statement->OpCode;
    216     HexDisplay = (TimeOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
    217   }
    218   switch (Statement->OpCode->OpCode) {
    219   case EFI_IFR_ORDERED_LIST_OP:
    220   case EFI_IFR_ONE_OF_OP:
    221   case EFI_IFR_NUMERIC_OP:
    222   case EFI_IFR_TIME_OP:
    223   case EFI_IFR_DATE_OP:
    224     if (!Selected) {
    225       PrintHotKeyHelpString (FormData, TRUE);
    226 
    227       if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
    228         ColumnStr3 = gEscapeString;
    229       }
    230       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
    231 
    232       if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||
    233           (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
    234         PrintAt (
    235           ColumnWidth1,
    236           StartColumnOfHelp,
    237           BottomRowOfHelp,
    238           L"%c%c%c%c%s",
    239           ARROW_UP,
    240           ARROW_DOWN,
    241           ARROW_RIGHT,
    242           ARROW_LEFT,
    243           gMoveHighlight
    244           );
    245         PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterString, ColumnWidth2);
    246         PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber, ColumnWidth1);
    247       } else {
    248         PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
    249         if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP && NumericOp != NULL && LibGetFieldFromNum(Statement->OpCode) != 0) {
    250           ColumnStr1 = gAdjustNumber;
    251         }
    252         PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
    253         PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterString, ColumnWidth2);
    254       }
    255     } else {
    256       PrintHotKeyHelpString (FormData, FALSE);
    257       PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterCommitString, ColumnWidth2);
    258 
    259       //
    260       // If it is a selected numeric with manual input, display different message
    261       //
    262       if ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) ||
    263           (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||
    264           (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
    265         ColumnStr2 = HexDisplay ? gHexNumericInput : gDecNumericInput;
    266         PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, gLibEmptyString, ColumnWidth1);
    267       } else {
    268         PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
    269       }
    270 
    271       if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
    272         ColumnStr1 = gPlusString;
    273         ColumnStr3 = gMinusString;
    274       }
    275       PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
    276       PrintStringAtWithWidth (ThdCol, TopRowOfHelp, ColumnStr3, ColumnWidth3);
    277       PrintStringAtWithWidth (SecCol, TopRowOfHelp, ColumnStr2, ColumnWidth2);
    278 
    279       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, gEnterEscapeString, ColumnWidth3);
    280     }
    281     break;
    282 
    283   case EFI_IFR_CHECKBOX_OP:
    284     PrintHotKeyHelpString (FormData, TRUE);
    285 
    286     if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
    287       ColumnStr3 = gEscapeString;
    288     }
    289     PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
    290 
    291     PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
    292     PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gToggleCheckBox, ColumnWidth2);
    293     PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gLibEmptyString, ColumnWidth1);
    294     break;
    295 
    296   case EFI_IFR_REF_OP:
    297   case EFI_IFR_PASSWORD_OP:
    298   case EFI_IFR_STRING_OP:
    299   case EFI_IFR_TEXT_OP:
    300   case EFI_IFR_ACTION_OP:
    301   case EFI_IFR_RESET_BUTTON_OP:
    302   case EFI_IFR_SUBTITLE_OP:
    303      if (!Selected) {
    304       PrintHotKeyHelpString (FormData, TRUE);
    305 
    306       if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
    307         ColumnStr3 = gEscapeString;
    308       }
    309       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
    310 
    311       PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
    312       if (Statement->OpCode->OpCode != EFI_IFR_TEXT_OP && Statement->OpCode->OpCode != EFI_IFR_SUBTITLE_OP) {
    313         ColumnStr2 = gEnterString;
    314       }
    315       PrintStringAtWithWidth (SecCol, BottomRowOfHelp, ColumnStr2, ColumnWidth2);
    316       PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
    317     } else {
    318       PrintHotKeyHelpString (FormData, FALSE);
    319       if (Statement->OpCode->OpCode != EFI_IFR_REF_OP) {
    320         ColumnStr2 = gEnterCommitString;
    321         ColumnStr3 = gEnterEscapeString;
    322       }
    323       PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1);
    324       PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, ColumnStr1, ColumnWidth1);
    325       PrintStringAtWithWidth (SecCol, BottomRowOfHelp, ColumnStr2, ColumnWidth2);
    326       PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3);
    327     }
    328     break;
    329 
    330   default:
    331     break;
    332   }
    333 }
    334 
    335 /**
    336   Update status bar.
    337 
    338   This function updates the status bar on the bottom of menu screen. It just shows StatusBar.
    339   Original logic in this function should be splitted out.
    340 
    341   @param[in]  MessageType            The type of message to be shown. InputError or Configuration Changed.
    342   @param[in]  State                  Show or Clear Message.
    343 **/
    344 VOID
    345 EFIAPI
    346 UpdateStatusBar (
    347   IN  UINTN                  MessageType,
    348   IN  BOOLEAN                State
    349   )
    350 {
    351   UINTN           Index;
    352   CHAR16          OptionWidth;
    353 
    354   OptionWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
    355 
    356   switch (MessageType) {
    357   case INPUT_ERROR:
    358     if (State) {
    359       gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
    360       PrintStringAt (
    361         gScreenDimensions.LeftColumn + OptionWidth,
    362         gScreenDimensions.BottomRow - 1,
    363         gInputErrorMessage
    364         );
    365     } else {
    366       gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);
    367       for (Index = 0; Index < (LibGetStringWidth (gInputErrorMessage) - 2) / 2; Index++) {
    368         PrintStringAt (gScreenDimensions.LeftColumn + OptionWidth + Index, gScreenDimensions.BottomRow - 1, L"  ");
    369       }
    370     }
    371     break;
    372 
    373   case NV_UPDATE_REQUIRED:
    374     //
    375     // Global setting support. Show configuration change on every form.
    376     //
    377     if (State) {
    378       gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
    379       PrintStringAt (
    380         gScreenDimensions.LeftColumn + OptionWidth * 2,
    381         gScreenDimensions.BottomRow - 1,
    382         gNvUpdateMessage
    383         );
    384     } else {
    385       gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);
    386       for (Index = 0; Index < (LibGetStringWidth (gNvUpdateMessage) - 2) / 2; Index++) {
    387         PrintStringAt (
    388           (gScreenDimensions.LeftColumn + OptionWidth * 2 + Index),
    389           gScreenDimensions.BottomRow - 1,
    390           L"  "
    391           );
    392       }
    393     }
    394     break;
    395 
    396   default:
    397     break;
    398   }
    399 }
    400 
    401 /**
    402   Create popup window. It will replace CreateDialog().
    403 
    404   This function draws OEM/Vendor specific pop up windows.
    405 
    406   @param[out]  Key    User Input Key
    407   @param       ...    String to be shown in Popup. The variable argument list is terminated by a NULL.
    408 
    409 **/
    410 VOID
    411 EFIAPI
    412 CreateDialog (
    413   OUT EFI_INPUT_KEY  *Key,        OPTIONAL
    414   ...
    415   )
    416 {
    417   VA_LIST       Marker;
    418   EFI_INPUT_KEY KeyValue;
    419   EFI_STATUS    Status;
    420   UINTN         LargestString;
    421   UINTN         LineNum;
    422   UINTN   Index;
    423   UINTN   Count;
    424   CHAR16  Character;
    425   UINTN   Start;
    426   UINTN   End;
    427   UINTN   Top;
    428   UINTN   Bottom;
    429   CHAR16  *String;
    430   UINTN   DimensionsWidth;
    431   UINTN   DimensionsHeight;
    432   UINTN   CurrentAttribute;
    433   BOOLEAN CursorVisible;
    434 
    435   //
    436   // If screen dimension info is not ready, get it from console.
    437   //
    438   if (gScreenDimensions.RightColumn == 0 || gScreenDimensions.BottomRow == 0) {
    439     ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
    440     gST->ConOut->QueryMode (
    441                    gST->ConOut,
    442                    gST->ConOut->Mode->Mode,
    443                    &gScreenDimensions.RightColumn,
    444                    &gScreenDimensions.BottomRow
    445                    );
    446   }
    447 
    448   DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
    449   DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
    450 
    451   LargestString = 0;
    452   LineNum       = 0;
    453   VA_START (Marker, Key);
    454   while  ((String = VA_ARG (Marker, CHAR16 *)) != NULL) {
    455     LineNum ++;
    456 
    457     if ((LibGetStringWidth (String) / 2) > LargestString) {
    458       LargestString = (LibGetStringWidth (String) / 2);
    459     }
    460   }
    461   VA_END (Marker);
    462 
    463   if ((LargestString + 2) > DimensionsWidth) {
    464     LargestString = DimensionsWidth - 2;
    465   }
    466 
    467   CurrentAttribute  = gST->ConOut->Mode->Attribute;
    468   CursorVisible     = gST->ConOut->Mode->CursorVisible;
    469   gST->ConOut->EnableCursor (gST->ConOut, FALSE);
    470   gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
    471 
    472   //
    473   // Subtract the PopUp width from total Columns, allow for one space extra on
    474   // each end plus a border.
    475   //
    476   Start     = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
    477   End       = Start + LargestString + 1;
    478 
    479   Top       = ((DimensionsHeight - LineNum - 2) / 2) + gScreenDimensions.TopRow - 1;
    480   Bottom    = Top + LineNum + 2;
    481 
    482   Character = BOXDRAW_DOWN_RIGHT;
    483   PrintCharAt (Start, Top, Character);
    484   Character = BOXDRAW_HORIZONTAL;
    485   for (Index = Start; Index + 2 < End; Index++) {
    486     PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
    487   }
    488 
    489   Character = BOXDRAW_DOWN_LEFT;
    490   PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
    491   Character = BOXDRAW_VERTICAL;
    492 
    493   Count = 0;
    494   VA_START (Marker, Key);
    495   for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
    496     String = VA_ARG (Marker, CHAR16*);
    497 
    498     if (String[0] == CHAR_NULL) {
    499       //
    500       // Passing in a NULL results in a blank space
    501       //
    502       ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
    503     } else if (String[0] == L' ') {
    504       //
    505       // Passing in a space results in the assumption that this is where typing will occur
    506       //
    507       ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
    508       PrintStringAt (
    509         ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
    510         Index + 1,
    511         String + 1
    512         );
    513     } else {
    514       //
    515       // This will clear the background of the line - we never know who might have been
    516       // here before us.  This differs from the next clear in that it used the non-reverse
    517       // video for normal printing.
    518       //
    519       ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
    520       PrintStringAt (
    521         ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
    522         Index + 1,
    523         String
    524         );
    525     }
    526 
    527     gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
    528     PrintCharAt (Start, Index + 1, Character);
    529     PrintCharAt (End - 1, Index + 1, Character);
    530   }
    531   VA_END (Marker);
    532 
    533   Character = BOXDRAW_UP_RIGHT;
    534   PrintCharAt (Start, Bottom - 1, Character);
    535   Character = BOXDRAW_HORIZONTAL;
    536   for (Index = Start; Index + 2 < End; Index++) {
    537     PrintCharAt ((UINTN)-1, (UINTN) -1, Character);
    538   }
    539 
    540   Character = BOXDRAW_UP_LEFT;
    541   PrintCharAt ((UINTN)-1, (UINTN) -1, Character);
    542 
    543   if (Key != NULL) {
    544     Status = WaitForKeyStroke (&KeyValue);
    545     ASSERT_EFI_ERROR (Status);
    546     CopyMem (Key, &KeyValue, sizeof (EFI_INPUT_KEY));
    547   }
    548 
    549   gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
    550   gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
    551 }
    552 
    553 /**
    554   Confirm how to handle the changed data.
    555 
    556   @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values.
    557 **/
    558 UINTN
    559 EFIAPI
    560 ConfirmDataChange (
    561   VOID
    562   )
    563 {
    564   CHAR16                  YesResponse;
    565   CHAR16                  NoResponse;
    566   EFI_INPUT_KEY           Key;
    567 
    568   gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
    569 
    570   YesResponse = gYesResponse[0];
    571   NoResponse  = gNoResponse[0];
    572 
    573   //
    574   // If NV flag is up, prompt user
    575   //
    576   do {
    577     CreateDialog (&Key, gLibEmptyString, gSaveChanges, gAreYouSure, gLibEmptyString, NULL);
    578   } while
    579   (
    580     (Key.ScanCode != SCAN_ESC) &&
    581     ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
    582     ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
    583   );
    584 
    585   if (Key.ScanCode == SCAN_ESC) {
    586     return BROWSER_ACTION_NONE;
    587   } else if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
    588     return BROWSER_ACTION_SUBMIT;
    589   } else {
    590     return BROWSER_ACTION_DISCARD;
    591   }
    592 }
    593 
    594 /**
    595   OEM specifies whether Setup exits Page by ESC key.
    596 
    597   This function customized the behavior that whether Setup exits Page so that
    598   system able to boot when configuration is not changed.
    599 
    600   @retval  TRUE     Exits FrontPage
    601   @retval  FALSE    Don't exit FrontPage.
    602 **/
    603 BOOLEAN
    604 EFIAPI
    605 FormExitPolicy (
    606   VOID
    607   )
    608 {
    609   return gClassOfVfr == FORMSET_CLASS_FRONT_PAGE ? FALSE : TRUE;
    610 }
    611 
    612 /**
    613   Set Timeout value for a ceratain Form to get user response.
    614 
    615   This function allows to set timeout value on a ceratain form if necessary.
    616   If timeout is not zero, the form will exit if user has no response in timeout.
    617 
    618   @param[in]  FormData   Form Data to be shown in Page
    619 
    620   @return 0     No timeout for this form.
    621   @return > 0   Timeout value in 100 ns units.
    622 **/
    623 UINT64
    624 EFIAPI
    625 FormExitTimeout (
    626   IN FORM_DISPLAY_ENGINE_FORM      *FormData
    627   )
    628 {
    629   return 0;
    630 }
    631 //
    632 // Print Functions
    633 //
    634 /**
    635   Prints a unicode string to the default console, at
    636   the supplied cursor position, using L"%s" format.
    637 
    638   @param  Column     The cursor position to print the string at. When it is -1, use current Position.
    639   @param  Row        The cursor position to print the string at. When it is -1, use current Position.
    640   @param  String     String pointer.
    641 
    642   @return Length of string printed to the console
    643 
    644 **/
    645 UINTN
    646 EFIAPI
    647 PrintStringAt (
    648   IN UINTN     Column,
    649   IN UINTN     Row,
    650   IN CHAR16    *String
    651   )
    652 {
    653   return PrintAt (0, Column, Row, L"%s", String);
    654 }
    655 
    656 /**
    657   Prints a unicode string to the default console, at
    658   the supplied cursor position, using L"%s" format.
    659 
    660   @param  Column     The cursor position to print the string at. When it is -1, use current Position.
    661   @param  Row        The cursor position to print the string at. When it is -1, use current Position.
    662   @param  String     String pointer.
    663   @param  Width      Width for String.
    664 
    665   @return Length of string printed to the console
    666 
    667 **/
    668 UINTN
    669 EFIAPI
    670 PrintStringAtWithWidth (
    671   IN UINTN     Column,
    672   IN UINTN     Row,
    673   IN CHAR16    *String,
    674   IN UINTN     Width
    675   )
    676 {
    677   return PrintAt (Width, Column, Row, L"%s", String);
    678 }
    679 
    680 /**
    681   Prints a character to the default console, at
    682   the supplied cursor position, using L"%c" format.
    683 
    684   @param  Column     The cursor position to print the string at. When it is -1, use current Position.
    685   @param  Row        The cursor position to print the string at. When it is -1, use current Position.
    686   @param  Character  Character to print.
    687 
    688   @return Length of string printed to the console.
    689 
    690 **/
    691 UINTN
    692 EFIAPI
    693 PrintCharAt (
    694   IN UINTN     Column,
    695   IN UINTN     Row,
    696   CHAR16       Character
    697   )
    698 {
    699   return PrintAt (0, Column, Row, L"%c", Character);
    700 }
    701 
    702 /**
    703   Clear retangle with specified text attribute.
    704 
    705   @param  LeftColumn     Left column of retangle.
    706   @param  RightColumn    Right column of retangle.
    707   @param  TopRow         Start row of retangle.
    708   @param  BottomRow      End row of retangle.
    709   @param  TextAttribute  The character foreground and background.
    710 
    711 **/
    712 VOID
    713 EFIAPI
    714 ClearLines (
    715   IN UINTN               LeftColumn,
    716   IN UINTN               RightColumn,
    717   IN UINTN               TopRow,
    718   IN UINTN               BottomRow,
    719   IN UINTN               TextAttribute
    720   )
    721 {
    722   CHAR16  *Buffer;
    723   UINTN   Row;
    724 
    725   //
    726   // For now, allocate an arbitrarily long buffer
    727   //
    728   Buffer = AllocateZeroPool (0x10000);
    729   ASSERT (Buffer != NULL);
    730 
    731   //
    732   // Set foreground and background as defined
    733   //
    734   gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
    735 
    736   //
    737   // Much faster to buffer the long string instead of print it a character at a time
    738   //
    739   LibSetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
    740 
    741   //
    742   // Clear the desired area with the appropriate foreground/background
    743   //
    744   for (Row = TopRow; Row <= BottomRow; Row++) {
    745     PrintStringAt (LeftColumn, Row, Buffer);
    746   }
    747 
    748   gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
    749 
    750   FreePool (Buffer);
    751 }
    752 
    753 //
    754 // Color Setting Functions
    755 //
    756 
    757 /**
    758   Get OEM/Vendor specific popup attribute colors.
    759 
    760   @retval  Byte code color setting for popup color.
    761 **/
    762 UINT8
    763 EFIAPI
    764 GetPopupColor (
    765   VOID
    766   )
    767 {
    768   return POPUP_TEXT | POPUP_BACKGROUND;
    769 }
    770 
    771 /**
    772   Get OEM/Vendor specific popup attribute colors.
    773 
    774   @retval  Byte code color setting for popup inverse color.
    775 **/
    776 UINT8
    777 EFIAPI
    778 GetPopupInverseColor (
    779   VOID
    780   )
    781 {
    782   return POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND;
    783 }
    784 
    785 /**
    786   Get OEM/Vendor specific PickList color attribute.
    787 
    788   @retval  Byte code color setting for pick list color.
    789 **/
    790 UINT8
    791 EFIAPI
    792 GetPickListColor (
    793   VOID
    794   )
    795 {
    796   return PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND;
    797 }
    798 
    799 /**
    800   Get OEM/Vendor specific arrow color attribute.
    801 
    802   @retval  Byte code color setting for arrow color.
    803 **/
    804 UINT8
    805 EFIAPI
    806 GetArrowColor (
    807   VOID
    808   )
    809 {
    810   return ARROW_TEXT | ARROW_BACKGROUND;
    811 }
    812 
    813 /**
    814   Get OEM/Vendor specific info text color attribute.
    815 
    816   @retval  Byte code color setting for info text color.
    817 **/
    818 UINT8
    819 EFIAPI
    820 GetInfoTextColor (
    821   VOID
    822   )
    823 {
    824   return INFO_TEXT | FIELD_BACKGROUND;
    825 }
    826 
    827 /**
    828   Get OEM/Vendor specific help text color attribute.
    829 
    830   @retval  Byte code color setting for help text color.
    831 **/
    832 UINT8
    833 EFIAPI
    834 GetHelpTextColor (
    835   VOID
    836   )
    837 {
    838   return HELP_TEXT | FIELD_BACKGROUND;
    839 }
    840 
    841 /**
    842   Get OEM/Vendor specific grayed out text color attribute.
    843 
    844   @retval  Byte code color setting for grayed out text color.
    845 **/
    846 UINT8
    847 EFIAPI
    848 GetGrayedTextColor (
    849   VOID
    850   )
    851 {
    852   return FIELD_TEXT_GRAYED | FIELD_BACKGROUND;
    853 }
    854 
    855 /**
    856   Get OEM/Vendor specific highlighted text color attribute.
    857 
    858   @retval  Byte code color setting for highlight text color.
    859 **/
    860 UINT8
    861 EFIAPI
    862 GetHighlightTextColor (
    863   VOID
    864   )
    865 {
    866   return PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);
    867 }
    868 
    869 /**
    870   Get OEM/Vendor specific field text color attribute.
    871 
    872   @retval  Byte code color setting for field text color.
    873 **/
    874 UINT8
    875 EFIAPI
    876 GetFieldTextColor (
    877   VOID
    878   )
    879 {
    880   return PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;
    881 }
    882 
    883 /**
    884   Get OEM/Vendor specific subtitle text color attribute.
    885 
    886   @retval  Byte code color setting for subtitle text color.
    887 **/
    888 UINT8
    889 EFIAPI
    890 GetSubTitleTextColor (
    891   VOID
    892   )
    893 {
    894   return PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND;
    895 }
    896 
    897 /**
    898   Clear Screen to the initial state.
    899 **/
    900 VOID
    901 EFIAPI
    902 ClearDisplayPage (
    903   VOID
    904   )
    905 {
    906   gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
    907   gST->ConOut->ClearScreen (gST->ConOut);
    908   gLibIsFirstForm = TRUE;
    909 }
    910 
    911 /**
    912   Constructor of Customized Display Library Instance.
    913 
    914   @param  ImageHandle   The firmware allocated handle for the EFI image.
    915   @param  SystemTable   A pointer to the EFI System Table.
    916 
    917   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
    918 
    919 **/
    920 EFI_STATUS
    921 EFIAPI
    922 CustomizedDisplayLibConstructor (
    923   IN      EFI_HANDLE                ImageHandle,
    924   IN      EFI_SYSTEM_TABLE          *SystemTable
    925   )
    926 {
    927   mCDLStringPackHandle = HiiAddPackages (&gCustomizedDisplayLibGuid, ImageHandle, CustomizedDisplayLibStrings, NULL);
    928   ASSERT (mCDLStringPackHandle != NULL);
    929 
    930   InitializeLibStrings();
    931 
    932   return EFI_SUCCESS;
    933 }
    934 
    935 /**
    936   Destructor of Customized Display Library Instance.
    937 
    938   @param  ImageHandle   The firmware allocated handle for the EFI image.
    939   @param  SystemTable   A pointer to the EFI System Table.
    940 
    941   @retval EFI_SUCCESS   The destructor completed successfully.
    942   @retval Other value   The destructor did not complete successfully.
    943 
    944 **/
    945 EFI_STATUS
    946 EFIAPI
    947 CustomizedDisplayLibDestructor (
    948   IN EFI_HANDLE        ImageHandle,
    949   IN EFI_SYSTEM_TABLE  *SystemTable
    950   )
    951 {
    952   HiiRemovePackages(mCDLStringPackHandle);
    953 
    954   FreeLibStrings ();
    955 
    956   return EFI_SUCCESS;
    957 }
    958 
    959