]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
Refine the logic about processing options for oneof opcode.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / InputHandler.c
index 3e7979f7331fec841d309032d7fe441d9e87cd3e..844590770a68d9a867bf4294dc189a48dad2dc67 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
 Implementation for handling user input from the User Interfaces.\r
 \r
-Copyright (c) 2004 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -20,7 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
   @param  MenuOption        Pointer to the current input menu.\r
   @param  Prompt            The prompt string shown on popup window.\r
-  @param  StringPtr         Destination for use input string.\r
+  @param  StringPtr         Old user input and destination for use input string.\r
 \r
   @retval EFI_SUCCESS       If string input is read successfully\r
   @retval EFI_DEVICE_ERROR  If operation fails\r
@@ -28,9 +28,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 EFI_STATUS\r
 ReadString (\r
-  IN  UI_MENU_OPTION              *MenuOption,\r
-  IN  CHAR16                      *Prompt,\r
-  OUT CHAR16                      *StringPtr\r
+  IN     UI_MENU_OPTION              *MenuOption,\r
+  IN     CHAR16                      *Prompt,\r
+  IN OUT CHAR16                      *StringPtr\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -42,11 +42,13 @@ ReadString (
   CHAR16                  *TempString;\r
   CHAR16                  *BufferedString;\r
   UINTN                   Index;\r
+  UINTN                   Index2;\r
   UINTN                   Count;\r
   UINTN                   Start;\r
   UINTN                   Top;\r
   UINTN                   DimensionsWidth;\r
   UINTN                   DimensionsHeight;\r
+  UINTN                   CurrentCursor;\r
   BOOLEAN                 CursorVisible;\r
   UINTN                   Minimum;\r
   UINTN                   Maximum;\r
@@ -98,6 +100,40 @@ ReadString (
   CursorVisible = gST->ConOut->Mode->CursorVisible;\r
   gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
 \r
+  CurrentCursor = GetStringWidth (StringPtr) / 2 - 1;\r
+  if (CurrentCursor != 0) {\r
+    //\r
+    // Show the string which has beed saved before.\r
+    //\r
+    SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');\r
+    PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+\r
+    if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {\r
+      Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;\r
+    } else {\r
+      Index = 0;\r
+    }\r
+\r
+    if (IsPassword) {\r
+      gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);\r
+    }\r
+\r
+    for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {\r
+      BufferedString[Count] = StringPtr[Index];\r
+\r
+      if (IsPassword) {\r
+        PrintChar (L'*');\r
+      }\r
+    }\r
+\r
+    if (!IsPassword) {\r
+      PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+    }\r
+    \r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);\r
+  }\r
+  \r
   do {\r
     Status = WaitForKeyStroke (&Key);\r
     ASSERT_EFI_ERROR (Status);\r
@@ -107,9 +143,15 @@ ReadString (
     case CHAR_NULL:\r
       switch (Key.ScanCode) {\r
       case SCAN_LEFT:\r
+        if (CurrentCursor > 0) {\r
+          CurrentCursor--;\r
+        }\r
         break;\r
 \r
       case SCAN_RIGHT:\r
+        if (CurrentCursor < (GetStringWidth (StringPtr) / 2 - 1)) {\r
+          CurrentCursor++;\r
+        }\r
         break;\r
 \r
       case SCAN_ESC:\r
@@ -152,15 +194,22 @@ ReadString (
       break;\r
 \r
     case CHAR_BACKSPACE:\r
-      if (StringPtr[0] != CHAR_NULL) {\r
-        for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {\r
+      if (StringPtr[0] != CHAR_NULL && CurrentCursor != 0) {\r
+        for (Index = 0; Index < CurrentCursor - 1; Index++) {\r
           TempString[Index] = StringPtr[Index];\r
         }\r
+        Count = GetStringWidth (StringPtr) / 2 - 1;\r
+        if (Count >= CurrentCursor) {\r
+          for (Index = CurrentCursor - 1, Index2 = CurrentCursor; Index2 < Count; Index++, Index2++) {\r
+            TempString[Index] = StringPtr[Index2];\r
+          }\r
+          TempString[Index] = CHAR_NULL;\r
+        }\r
         //\r
         // Effectively truncate string by 1 character\r
         //\r
-        TempString[Index - 1] = CHAR_NULL;\r
         StrCpy (StringPtr, TempString);\r
+        CurrentCursor --;\r
       }\r
 \r
     default:\r
@@ -169,12 +218,23 @@ ReadString (
       //\r
       if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
         StrnCpy (StringPtr, &Key.UnicodeChar, 1);\r
-        StrnCpy (TempString, &Key.UnicodeChar, 1);\r
+        CurrentCursor++;\r
       } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
         KeyPad[0] = Key.UnicodeChar;\r
         KeyPad[1] = CHAR_NULL;\r
-        StrCat (StringPtr, KeyPad);\r
-        StrCat (TempString, KeyPad);\r
+        Count = GetStringWidth (StringPtr) / 2 - 1;\r
+        if (CurrentCursor < Count) {\r
+          for (Index = 0; Index < CurrentCursor; Index++) {\r
+            TempString[Index] = StringPtr[Index];\r
+          }\r
+                 TempString[Index] = CHAR_NULL;\r
+          StrCat (TempString, KeyPad);\r
+          StrCat (TempString, StringPtr + CurrentCursor);\r
+          StrCpy (StringPtr, TempString);\r
+        } else {\r
+          StrCat (StringPtr, KeyPad);\r
+        }\r
+        CurrentCursor++;\r
       }\r
 \r
       //\r
@@ -209,11 +269,75 @@ ReadString (
     }\r
 \r
     gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
-    gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, Start + CurrentCursor + 1, Top + 3);\r
   } while (TRUE);\r
 \r
 }\r
 \r
+/**\r
+  Adjust the value to the correct one. Rules follow the sample:\r
+  like:  Year change:  2012.02.29 -> 2013.02.29 -> 2013.02.01\r
+         Month change: 2013.03.29 -> 2013.02.29 -> 2013.02.28\r
+\r
+  @param  Question          Pointer to current question.\r
+  @param  Sequence          The sequence of the field in the question.\r
+**/\r
+VOID\r
+AdjustQuestionValue (\r
+  IN  FORM_BROWSER_STATEMENT  *Question,\r
+  IN  UINT8                   Sequence\r
+  )\r
+{\r
+  UINT8     Month;\r
+  UINT16    Year;\r
+  UINT8     Maximum;\r
+  UINT8     Minimum;\r
+\r
+  if (Question->Operand != EFI_IFR_DATE_OP) {\r
+    return;\r
+  }\r
+\r
+  Month   = Question->HiiValue.Value.date.Month;\r
+  Year    = Question->HiiValue.Value.date.Year;\r
+  Minimum = 1;\r
+\r
+  switch (Month) {\r
+  case 2:\r
+    if ((Year % 4) == 0 && ((Year % 100) != 0 || (Year % 400) == 0)) {\r
+      Maximum = 29;\r
+    } else {\r
+      Maximum = 28;\r
+    }\r
+    break;\r
+  case 4:\r
+  case 6:\r
+  case 9:\r
+  case 11:\r
+    Maximum = 30;\r
+    break;\r
+  default:\r
+    Maximum = 31;\r
+    break;\r
+  }\r
+\r
+  //\r
+  // Change the month area.\r
+  //\r
+  if (Sequence == 0) {\r
+    if (Question->HiiValue.Value.date.Day > Maximum) {\r
+      Question->HiiValue.Value.date.Day = Maximum;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Change the Year area.\r
+  //\r
+  if (Sequence == 2) {\r
+    if (Question->HiiValue.Value.date.Day > Maximum) {\r
+      Question->HiiValue.Value.date.Day = Minimum;\r
+    }\r
+  }\r
+}\r
 \r
 /**\r
   This routine reads a numeric value from the user input.\r
@@ -270,6 +394,12 @@ GetNumericInput (
   Minimum       = Question->Minimum;\r
   Maximum       = Question->Maximum;\r
 \r
+  //\r
+  // Only two case, user can enter to this function: Enter and +/- case.\r
+  // In Enter case, gDirection = 0; in +/- case, gDirection = SCAN_LEFT/SCAN_WRIGHT\r
+  //\r
+  ManualInput        = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE);\r
+\r
   if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
     DateOrTime = TRUE;\r
   } else {\r
@@ -293,7 +423,27 @@ GetNumericInput (
       break;\r
 \r
     case 1:\r
-      Maximum = 31;\r
+      switch (QuestionValue->Value.date.Month) {\r
+      case 2:\r
+        if ((QuestionValue->Value.date.Year % 4) == 0  && \r
+            ((QuestionValue->Value.date.Year % 100) != 0 || \r
+            (QuestionValue->Value.date.Year % 400) == 0)) {\r
+          Maximum = 29;\r
+        } else {\r
+          Maximum = 28;\r
+        }\r
+        break;\r
+      case 4:\r
+      case 6:\r
+      case 9:\r
+      case 11:\r
+        Maximum = 30;\r
+        break;\r
+      default:\r
+        Maximum = 31;\r
+        break;\r
+      } \r
+\r
       EraseLen = 3;\r
       EditValue = QuestionValue->Value.date.Day;\r
       break;\r
@@ -344,12 +494,6 @@ GetNumericInput (
     }\r
   }\r
 \r
-  if (Step == 0) {\r
-    ManualInput = TRUE;\r
-  } else {\r
-    ManualInput = FALSE;\r
-  }\r
-\r
   if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&\r
       ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {\r
     HexInput = TRUE;\r
@@ -357,41 +501,96 @@ GetNumericInput (
     HexInput = FALSE;\r
   }\r
 \r
+  //\r
+  // Enter from "Enter" input, clear the old word showing.\r
+  //\r
   if (ManualInput) {\r
-    if (HexInput) {\r
-      InputWidth = Question->StorageWidth * 2;\r
-    } else {\r
-      switch (Question->StorageWidth) {\r
-      case 1:\r
-        InputWidth = 3;\r
-        break;\r
+    if (Question->Operand == EFI_IFR_NUMERIC_OP) {\r
+      if (HexInput) {\r
+        InputWidth = Question->StorageWidth * 2;\r
+      } else {\r
+        switch (Question->StorageWidth) {\r
+        case 1:\r
+          InputWidth = 3;\r
+          break;\r
 \r
-      case 2:\r
-        InputWidth = 5;\r
-        break;\r
+        case 2:\r
+          InputWidth = 5;\r
+          break;\r
 \r
-      case 4:\r
-        InputWidth = 10;\r
-        break;\r
+        case 4:\r
+          InputWidth = 10;\r
+          break;\r
 \r
-      case 8:\r
-        InputWidth = 20;\r
-        break;\r
+        case 8:\r
+          InputWidth = 20;\r
+          break;\r
 \r
-      default:\r
-        InputWidth = 0;\r
-        break;\r
+        default:\r
+          InputWidth = 0;\r
+          break;\r
+        }\r
+      }\r
+\r
+      InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+      SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+      ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH);\r
+      InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+      InputText[InputWidth + 2] = L'\0';\r
+\r
+      PrintAt (Column, Row, InputText);\r
+      Column++;\r
+    }\r
+\r
+    if (Question->Operand == EFI_IFR_DATE_OP) {\r
+      if (MenuOption->Sequence == 2) {\r
+        InputWidth = 4;\r
+      } else {\r
+        InputWidth = 2;\r
+      }\r
+\r
+      if (MenuOption->Sequence == 0) {\r
+        InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+        SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+      } else {\r
+        SetUnicodeMem (InputText, InputWidth, L' ');\r
+      }\r
+\r
+      if (MenuOption->Sequence == 2) {\r
+        InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+      } else {\r
+        InputText[InputWidth + 1] = DATE_SEPARATOR;\r
+      }\r
+      InputText[InputWidth + 2] = L'\0';\r
+\r
+      PrintAt (Column, Row, InputText);\r
+      if (MenuOption->Sequence == 0) {\r
+        Column++;\r
       }\r
     }\r
 \r
-    InputText[0] = LEFT_NUMERIC_DELIMITER;\r
-    SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
-    ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH);\r
-    InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
-    InputText[InputWidth + 2] = L'\0';\r
+    if (Question->Operand == EFI_IFR_TIME_OP) {\r
+      InputWidth = 2;\r
+\r
+      if (MenuOption->Sequence == 0) {\r
+        InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+        SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+      } else {\r
+        SetUnicodeMem (InputText, InputWidth, L' ');\r
+      }\r
 \r
-    PrintAt (Column, Row, InputText);\r
-    Column++;\r
+      if (MenuOption->Sequence == 2) {\r
+        InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+      } else {\r
+        InputText[InputWidth + 1] = TIME_SEPARATOR;\r
+      }\r
+      InputText[InputWidth + 2] = L'\0';\r
+\r
+      PrintAt (Column, Row, InputText);\r
+      if (MenuOption->Sequence == 0) {\r
+        Column++;\r
+      }\r
+    }\r
   }\r
 \r
   //\r
@@ -425,7 +624,7 @@ TheKey2:
       switch (Key.ScanCode) {\r
       case SCAN_LEFT:\r
       case SCAN_RIGHT:\r
-        if (DateOrTime) {\r
+        if (DateOrTime && !ManualInput) {\r
           //\r
           // By setting this value, we will return back to the caller.\r
           // We need to do this since an auto-refresh will destroy the adjustment\r
@@ -435,17 +634,22 @@ TheKey2:
           gDirection = SCAN_DOWN;\r
         }\r
 \r
-        if (!ManualInput) {\r
+        if ((Step != 0) && !ManualInput) {\r
           if (Key.ScanCode == SCAN_LEFT) {\r
-            if (EditValue > Step) {\r
+            if (EditValue >= Minimum + Step) {\r
               EditValue = EditValue - Step;\r
-            } else {\r
+            } else if (EditValue > Minimum){\r
               EditValue = Minimum;\r
+            } else {\r
+              EditValue = Maximum;\r
             }\r
           } else if (Key.ScanCode == SCAN_RIGHT) {\r
-            EditValue = EditValue + Step;\r
-            if (EditValue > Maximum) {\r
+            if (EditValue + Step <= Maximum) {\r
+              EditValue = EditValue + Step;\r
+            } else if (EditValue < Maximum) {\r
               EditValue = Maximum;\r
+            } else {\r
+              EditValue = Minimum;\r
             }\r
           }\r
 \r
@@ -455,25 +659,29 @@ TheKey2:
               //\r
               // Year\r
               //\r
-              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", EditValue);\r
+              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", (UINT16) EditValue);\r
             } else {\r
               //\r
               // Month/Day\r
               //\r
-              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);\r
+              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);\r
             }\r
 \r
             if (MenuOption->Sequence == 0) {\r
+              ASSERT (EraseLen >= 2);\r
               FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;\r
             } else if (MenuOption->Sequence == 1) {\r
+              ASSERT (EraseLen >= 1);\r
               FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;\r
             }\r
           } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
-            UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);\r
+            UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);\r
 \r
             if (MenuOption->Sequence == 0) {\r
+              ASSERT (EraseLen >= 2);\r
               FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;\r
             } else if (MenuOption->Sequence == 1) {\r
+              ASSERT (EraseLen >= 1);\r
               FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;\r
             }\r
           } else {\r
@@ -481,11 +689,11 @@ TheKey2:
             PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
           }\r
 \r
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+          gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
           for (Loop = 0; Loop < EraseLen; Loop++) {\r
             PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");\r
           }\r
-          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);\r
+          gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));\r
 \r
           if (MenuOption->Sequence == 0) {\r
             PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);\r
@@ -518,6 +726,16 @@ TheKey2:
 EnterCarriageReturn:\r
 \r
     case CHAR_CARRIAGE_RETURN:\r
+      //\r
+      // Validate input value with Minimum value.\r
+      //\r
+      if (EditValue < Minimum) {\r
+        UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+        break;\r
+      } else {\r
+        UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);\r
+      }\r
+\r
       //\r
       // Store Edit value back to Question\r
       //\r
@@ -562,6 +780,16 @@ EnterCarriageReturn:
         QuestionValue->Value.u64 = EditValue;\r
       }\r
 \r
+      //\r
+      // Adjust the value to the correct one.\r
+      // Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01\r
+      //              2013.03.29 -> 2013.02.29 -> 2013.02.28\r
+      //\r
+      if (Question->Operand == EFI_IFR_DATE_OP && \r
+        (MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) {\r
+        AdjustQuestionValue (Question, (UINT8)MenuOption->Sequence);\r
+      }\r
+\r
       //\r
       // Check to see if the Value is something reasonable against consistency limitations.\r
       // If not, let's kick the error specified.\r
@@ -571,14 +799,14 @@ EnterCarriageReturn:
         //\r
         // Input value is not valid, restore Question Value\r
         //\r
-        GetQuestionValue (FormSet, Form, Question, TRUE);\r
+        GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
       } else {\r
-        SetQuestionValue (FormSet, Form, Question, TRUE);\r
+        SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
         if (!DateOrTime || (Question->Storage != NULL)) {\r
           //\r
           // NV flag is unnecessary for RTC type of Date/Time\r
           //\r
-          UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+          UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
         }\r
       }\r
 \r
@@ -594,7 +822,7 @@ EnterCarriageReturn:
         // Remove a character\r
         //\r
         EditValue = PreviousNumber[Count - 1];\r
-        UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);\r
+        UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);\r
         Count--;\r
         Column--;\r
         PrintAt (Column, Row, L" ");\r
@@ -611,12 +839,12 @@ EnterCarriageReturn:
           } else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) {\r
             Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A);\r
           } else {\r
-            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+            UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
             break;\r
           }\r
         } else {\r
           if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {\r
-            UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+            UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
             break;\r
           }\r
         }\r
@@ -645,12 +873,12 @@ EnterCarriageReturn:
         }\r
 \r
         if (EditValue > Maximum) {\r
-          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+          UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
           ASSERT (Count < sizeof (PreviousNumber) / sizeof (PreviousNumber[0]));\r
           EditValue = PreviousNumber[Count];\r
           break;\r
         } else {\r
-          UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);\r
+          UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);\r
         }\r
 \r
         Count++;\r
@@ -713,6 +941,7 @@ GetSelectionInputPopUp (
   QUESTION_OPTION         *OneOfOption;\r
   QUESTION_OPTION         *CurrentOption;\r
   FORM_BROWSER_STATEMENT  *Question;\r
+  INTN                    Result;\r
 \r
   DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
 \r
@@ -758,48 +987,49 @@ GetSelectionInputPopUp (
   }\r
 \r
   //\r
-  // Prepare HiiValue array\r
+  // Move valid Option to list head.\r
   //\r
-  HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));\r
-  ASSERT (HiiValueArray != NULL);\r
-  Link = GetFirstNode (&Question->OptionListHead);\r
-  for (Index = 0; Index < OptionCount; Index++) {\r
-    if (OrderedList) {\r
+  PopUpMenuLines = 0;\r
+  if (OrderedList) {\r
+    //\r
+    // Prepare HiiValue array\r
+    //  \r
+    HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));\r
+    ASSERT (HiiValueArray != NULL);\r
+    for (Index = 0; Index < OptionCount; Index++) {\r
       HiiValueArray[Index].Type = ValueType;\r
       HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
-    } else {\r
-      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
-      CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));\r
-      Link = GetNextNode (&Question->OptionListHead, Link);\r
     }\r
-  }\r
 \r
-  //\r
-  // Move Suppressed Option to list tail\r
-  //\r
-  PopUpMenuLines = 0;\r
-  for (Index = 0; Index < OptionCount; Index++) {\r
-    OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);\r
-    if (OneOfOption == NULL) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
+    for (Index = 0; Index < OptionCount; Index++) {\r
+      OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);\r
+      if (OneOfOption == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
 \r
-    RemoveEntryList (&OneOfOption->Link);\r
+      RemoveEntryList (&OneOfOption->Link);\r
 \r
-    if ((OneOfOption->SuppressExpression != NULL) &&\r
-        (OneOfOption->SuppressExpression->Result.Value.b)) {\r
-      //\r
-      // This option is suppressed, insert to tail\r
-      //\r
-      InsertTailList (&Question->OptionListHead, &OneOfOption->Link);\r
-    } else {\r
       //\r
-      // Insert to head\r
+      // Insert to head.\r
       //\r
       InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);\r
 \r
       PopUpMenuLines++;\r
     }\r
+\r
+    FreePool (HiiValueArray);\r
+  } else {\r
+    Link = GetFirstNode (&Question->OptionListHead);\r
+    for (Index = 0; Index < OptionCount; Index++) {\r
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+      Link = GetNextNode (&Question->OptionListHead, Link);\r
+      if ((OneOfOption->SuppressExpression != NULL) &&\r
+          EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
+        continue;\r
+      } else {\r
+        PopUpMenuLines++;\r
+      }\r
+    }\r
   }\r
 \r
   //\r
@@ -810,6 +1040,13 @@ GetSelectionInputPopUp (
   Link = GetFirstNode (&Question->OptionListHead);\r
   for (Index = 0; Index < PopUpMenuLines; Index++) {\r
     OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+    Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+    if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&\r
+        EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
+      Index--;\r
+      continue;\r
+    }\r
 \r
     StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
     if (StrLen (StringPtr) > PopUpWidth) {\r
@@ -817,14 +1054,12 @@ GetSelectionInputPopUp (
     }\r
     FreePool (StringPtr);\r
 \r
-    if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) {\r
+    if (!OrderedList && (CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
       //\r
       // Find current selected Option for OneOf\r
       //\r
       HighlightOptionIndex = Index;\r
     }\r
-\r
-    Link = GetNextNode (&Question->OptionListHead, Link);\r
   }\r
 \r
   //\r
@@ -842,7 +1077,7 @@ GetSelectionInputPopUp (
   Start  = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;\r
   End    = Start + PopUpWidth + POPUP_FRAME_WIDTH;\r
   Top    = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;\r
-  Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1;\r
+  Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - 1;\r
 \r
   MenuLinesInView = Bottom - Top - 1;\r
   if (MenuLinesInView >= PopUpMenuLines) {\r
@@ -893,6 +1128,13 @@ GetSelectionInputPopUp (
     Link = GetFirstNode (&Question->OptionListHead);\r
     for (Index = 0; Index < TopOptionIndex; Index++) {\r
       Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+      OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+      if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&\r
+          EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
+        Index--;\r
+        continue;\r
+      }\r
     }\r
 \r
     //\r
@@ -903,7 +1145,14 @@ GetSelectionInputPopUp (
       OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
       Link = GetNextNode (&Question->OptionListHead, Link);\r
 \r
+      if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&\r
+          EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
+        Index--;\r
+        continue;\r
+      }\r
+\r
       StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
+      ASSERT (StringPtr != NULL);\r
       //\r
       // If the string occupies multiple lines, truncate it to fit in one line,\r
       // and append a "..." for indication.\r
@@ -1080,7 +1329,6 @@ TheKey:
           }\r
         }\r
 \r
-        FreePool (HiiValueArray);\r
         return EFI_DEVICE_ERROR;\r
 \r
       default:\r
@@ -1098,6 +1346,12 @@ TheKey:
         Link = GetFirstNode (&Question->OptionListHead);\r
         while (!IsNull (&Question->OptionListHead, Link)) {\r
           OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+          Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+          if ((OneOfOption->SuppressExpression != NULL) &&\r
+              EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+            continue;\r
+          }\r
 \r
           SetArrayData (ValueArray, ValueType, Index, OneOfOption->Value.Value.u64);\r
 \r
@@ -1105,8 +1359,6 @@ TheKey:
           if (Index > Question->MaxContainers) {\r
             break;\r
           }\r
-\r
-          Link = GetNextNode (&Question->OptionListHead, Link);\r
         }\r
       } else {\r
         ASSERT (CurrentOption != NULL);\r
@@ -1114,17 +1366,16 @@ TheKey:
       }\r
 \r
       gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
-      FreePool (HiiValueArray);\r
 \r
       Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
       if (EFI_ERROR (Status)) {\r
         //\r
         // Input value is not valid, restore Question Value\r
         //\r
-        GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
+        GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
       } else {\r
-        SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
-        UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+        SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
+        UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
       }\r
 \r
       return Status;\r
@@ -1151,10 +1402,17 @@ WaitForKeyStroke (
 {\r
   EFI_STATUS  Status;\r
 \r
-  do {\r
-    UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);\r
+  while (TRUE) {\r
     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
-  } while (EFI_ERROR(Status));\r
+    if (!EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    if (Status != EFI_NOT_READY) {\r
+      continue;\r
+    }\r
 \r
+    UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);\r
+  }\r
   return Status;\r
 }\r