]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
Update question validation logic, move the check pointer from after user input to...
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
index 5dfc482f3d0bb2a62beb06ea87e022947d79b714..df0fbfee7c21284f7b059ca23d9878b58323776e 100644 (file)
@@ -1478,6 +1478,7 @@ FindTopMenu (
   UI_MENU_OPTION                  *SavedMenuOption;\r
   UINTN                           TmpValue;\r
 \r
+  TmpValue  = 0;\r
   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
 \r
@@ -1521,23 +1522,42 @@ FindTopMenu (
   UpdateOptionSkipLines (SavedMenuOption);\r
 \r
   //\r
-  // If highlight opcode is date/time, keep the highlight row info not change.\r
+  // FormRefreshEvent != NULL means this form will auto exit at an interval, display engine \r
+  // will try to keep highlight on the current position after this form exit and re-enter.\r
   //\r
-  if ((SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) &&\r
-      (gHighligthMenuInfo.QuestionId != 0) && \r
-      (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode))) {\r
-    //\r
-    // Still show the highlight menu before exit from display engine.\r
-    //\r
-    BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
+  // HiiHandle + QuestionId can find the only one question in the system.\r
+  //\r
+  // If this question has question id, save the question id info to find the question.\r
+  // else save the opcode buffer to find it.\r
+  //\r
+  if (gFormData->FormRefreshEvent != NULL && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) {\r
+    if (gHighligthMenuInfo.QuestionId != 0) { \r
+      if (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode)) {\r
+        BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
+        //\r
+        // SkipValue only used for menu at the top of the form.\r
+        // If Highlight menu is not at the top, this value will be update later.\r
+        //\r
+        TmpValue = gHighligthMenuInfo.SkipValue;\r
+      }\r
+    } else if (gHighligthMenuInfo.OpCode != NULL){\r
+      if (!CompareMem (gHighligthMenuInfo.OpCode, SavedMenuOption->ThisTag->OpCode, gHighligthMenuInfo.OpCode->Length)) {\r
+        BottomRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
+        //\r
+        // SkipValue only used for menu at the top of the form.\r
+        // If Highlight menu is not at the top, this value will be update later.\r
+        //\r
+        TmpValue = gHighligthMenuInfo.SkipValue;\r
+      }\r
+    }\r
   }\r
 \r
   if (SavedMenuOption->Skip >= BottomRow - TopRow) {\r
-    TmpValue = 0;\r
     *TopOfScreen = NewPos;\r
   } else {\r
     *TopOfScreen = FindTopOfScreenMenu(NewPos, BottomRow - TopRow - SavedMenuOption->Skip, &TmpValue);\r
   }\r
+  AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
 \r
   *SkipValue   = TmpValue;\r
 }\r
@@ -1546,11 +1566,14 @@ FindTopMenu (
   Update highlight menu info.\r
 \r
   @param  MenuOption               The menu opton which is highlight.\r
+  @param  SkipValue                The skipvalue info for this menu.\r
+                                   SkipValue only used for the menu at the top of the form.\r
 \r
 **/\r
 VOID\r
 UpdateHighlightMenuInfo (\r
-  IN UI_MENU_OPTION            *MenuOption\r
+  IN UI_MENU_OPTION            *MenuOption,\r
+  IN UINTN                     SkipValue\r
   )\r
 {\r
   FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
@@ -1567,14 +1590,39 @@ UpdateHighlightMenuInfo (
   gSequence = (UINT16) MenuOption->Sequence;\r
 \r
   //\r
-  // Record highlight row info for date/time opcode.\r
+  // FormRefreshEvent != NULL means this form will auto exit at an interval, display engine \r
+  // will try to keep highlight on the current position after this form exit and re-enter.\r
   //\r
-  if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+  // HiiHandle + QuestionId can find the only one question in the system.\r
+  //\r
+  // If this question has question id, base on the question id info to find the question.\r
+  // else base on the opcode buffer to find it.\r
+  //\r
+  if (gFormData->FormRefreshEvent != NULL) {\r
+    gHighligthMenuInfo.HiiHandle  = gFormData->HiiHandle;\r
     gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode);\r
+\r
+    //\r
+    // if question id == 0, save the opcode buffer for later use.\r
+    //\r
+    if (gHighligthMenuInfo.QuestionId == 0) {\r
+      if (gHighligthMenuInfo.OpCode != NULL) {\r
+        FreePool (gHighligthMenuInfo.OpCode);\r
+      }\r
+      gHighligthMenuInfo.OpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
+      ASSERT (gHighligthMenuInfo.OpCode != NULL);\r
+    }\r
     gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row;\r
+    gHighligthMenuInfo.SkipValue  = (UINT16) SkipValue;\r
   } else {\r
+    gHighligthMenuInfo.HiiHandle  = NULL;\r
     gHighligthMenuInfo.QuestionId = 0;\r
+    if (gHighligthMenuInfo.OpCode != NULL) {\r
+      FreePool (gHighligthMenuInfo.OpCode);\r
+      gHighligthMenuInfo.OpCode = NULL;\r
+    }\r
     gHighligthMenuInfo.DisplayRow = 0;\r
+    gHighligthMenuInfo.SkipValue  = 0;\r
   }\r
 \r
   RefreshKeyHelp(gFormData, Statement, FALSE);\r
@@ -2251,7 +2299,7 @@ UiDisplayMenu (
       if (SkipHighLight) {\r
         MenuOption    = SavedMenuOption;\r
         SkipHighLight = FALSE;\r
-        UpdateHighlightMenuInfo (MenuOption);\r
+        UpdateHighlightMenuInfo (MenuOption, TopOfScreen == &MenuOption->Link ? SkipValue : 0);\r
         break;\r
       }\r
 \r
@@ -2295,7 +2343,7 @@ UiDisplayMenu (
         MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
         Statement = MenuOption->ThisTag;\r
 \r
-        UpdateHighlightMenuInfo (MenuOption);\r
+        UpdateHighlightMenuInfo (MenuOption, Temp2);\r
 \r
         if (!IsSelectable (MenuOption)) {\r
           break;\r
@@ -3149,14 +3197,53 @@ BrowserStatusProcess (
   VOID\r
   )\r
 {\r
-  CHAR16         *ErrorInfo;\r
-  EFI_INPUT_KEY  Key;\r
+  CHAR16             *ErrorInfo;\r
+  EFI_INPUT_KEY      Key;\r
+  EFI_EVENT          WaitList[2];\r
+  EFI_EVENT          RefreshIntervalEvent;\r
+  EFI_EVENT          TimeOutEvent;\r
+  UINT8              TimeOut;\r
+  EFI_STATUS         Status;\r
+  UINTN              Index;\r
+  WARNING_IF_CONTEXT EventContext;\r
+  EFI_IFR_OP_HEADER  *OpCodeBuf;\r
+  EFI_STRING_ID      StringToken;\r
 \r
   if (gFormData->BrowserStatus == BROWSER_SUCCESS) {\r
     return;\r
   }\r
 \r
-  if (gFormData->ErrorString != NULL) {\r
+  StringToken          = 0;\r
+  TimeOutEvent         = NULL;\r
+  RefreshIntervalEvent = NULL;\r
+  OpCodeBuf            = NULL;\r
+  if (gFormData->HighLightedStatement != NULL) {\r
+    OpCodeBuf = gFormData->HighLightedStatement->OpCode;\r
+  }\r
+\r
+  if (gFormData->BrowserStatus == (BROWSER_WARNING_IF)) {\r
+    ASSERT (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_WARNING_IF_OP);\r
+\r
+    TimeOut     = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->TimeOut;\r
+    StringToken = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->Warning;\r
+  } else {\r
+    TimeOut = 0;\r
+    if ((gFormData->BrowserStatus == (BROWSER_NO_SUBMIT_IF)) &&\r
+        (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_NO_SUBMIT_IF_OP)) {\r
+      StringToken = ((EFI_IFR_NO_SUBMIT_IF *) OpCodeBuf)->Error;\r
+    } else if ((gFormData->BrowserStatus == (BROWSER_INCONSISTENT_IF)) &&\r
+               (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_INCONSISTENT_IF_OP)) {\r
+      StringToken = ((EFI_IFR_INCONSISTENT_IF *) OpCodeBuf)->Error;\r
+    }\r
+  }\r
+\r
+  if (StringToken != 0) {\r
+    ErrorInfo = GetToken (StringToken, gFormData->HiiHandle);\r
+  } else if (gFormData->ErrorString != NULL) {\r
+    //\r
+    // Only used to compatible with old setup browser.\r
+    // Not use this field in new browser core.\r
+    //\r
     ErrorInfo = gFormData->ErrorString;\r
   } else {\r
     switch (gFormData->BrowserStatus) {\r
@@ -3164,10 +3251,6 @@ BrowserStatusProcess (
       ErrorInfo = gSaveFailed;\r
       break;\r
 \r
-    case BROWSER_NO_SUBMIT_IF:\r
-      ErrorInfo = gNoSubmitIf;\r
-      break;\r
-\r
     case BROWSER_FORM_NOT_FOUND:\r
       ErrorInfo = gFormNotFound;\r
       break;\r
@@ -3186,12 +3269,60 @@ BrowserStatusProcess (
     }\r
   }\r
 \r
-  //\r
-  // Error occur, prompt error message.\r
-  //\r
-  do {\r
-    CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
-  } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+  if (TimeOut == 0) {\r
+    do {\r
+      CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+  } else {\r
+    Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    EventContext.SyncEvent = TimeOutEvent;\r
+    EventContext.TimeOut   = &TimeOut;\r
+    EventContext.ErrorInfo = ErrorInfo;\r
+\r
+    Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Show the dialog first to avoid long time not reaction.\r
+    //\r
+    gBS->SignalEvent (RefreshIntervalEvent);\r
+\r
+    Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    while (TRUE) {\r
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+      if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+        break;\r
+      }\r
+\r
+      if (Status != EFI_NOT_READY) {\r
+        continue;\r
+      }\r
+\r
+      WaitList[0] = TimeOutEvent;\r
+      WaitList[1] = gST->ConIn->WaitForKey;\r
+\r
+      Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      if (Index == 0) {\r
+        //\r
+        // Timeout occur, close the hoot time out event.\r
+        //\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  gBS->CloseEvent (TimeOutEvent);\r
+  gBS->CloseEvent (RefreshIntervalEvent);\r
+\r
+  if (StringToken != 0) {\r
+    FreePool (ErrorInfo);\r
+  }\r
 }\r
 \r
 /**\r
@@ -3392,5 +3523,9 @@ UnloadDisplayEngine (
 \r
   FreeDisplayStrings ();\r
 \r
+  if (gHighligthMenuInfo.OpCode != NULL) {\r
+    FreePool (gHighligthMenuInfo.OpCode);\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r