]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
1) Fix GCC version EBC interpreter bug.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / InputHandler.c
index 360a6d75ecff552d852d05298d4f1558488aa121..2522d16deb1b1c6d434d34020baeb7a833809f55 100644 (file)
@@ -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
@@ -299,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
@@ -492,15 +636,20 @@ TheKey2:
 \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
@@ -621,6 +770,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
@@ -637,7 +796,7 @@ EnterCarriageReturn:
           //\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
@@ -653,7 +812,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
@@ -670,12 +829,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
@@ -704,12 +863,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
@@ -901,7 +1060,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
@@ -963,6 +1122,7 @@ GetSelectionInputPopUp (
       Link = GetNextNode (&Question->OptionListHead, Link);\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
@@ -1183,7 +1343,7 @@ TheKey:
         GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
       } else {\r
         SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
-        UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+        UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
       }\r
 \r
       return Status;\r