]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
The original code does not initialize the global width constants before creating...
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
index e2c6b292255aebadad5918feda84fe7d57863839..0db450e078d1f7a750730bcd4969c59a87715691 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
 Entry and initialization module for the browser.\r
 \r
-Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<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
@@ -117,6 +118,12 @@ CHAR16            *gFormNotFound;
 CHAR16            *gNoSubmitIf;\r
 CHAR16            *gBrwoserError;\r
 CHAR16            *gSaveFailed;\r
+CHAR16            *gNoSubmitIfFailed;\r
+CHAR16            *gSaveProcess;\r
+CHAR16            *gSaveNoSubmitProcess;\r
+CHAR16            *gDiscardChange;\r
+CHAR16            *gJumpToFormSet;\r
+CHAR16            *gCheckError;\r
 CHAR16            *gPromptForData;\r
 CHAR16            *gPromptForPassword;\r
 CHAR16            *gPromptForNewPassword;\r
@@ -186,6 +193,12 @@ InitializeDisplayStrings (
 {\r
   mUnknownString        = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);\r
   gSaveFailed           = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
+  gNoSubmitIfFailed     = GetToken (STRING_TOKEN (NO_SUBMIT_IF_CHECK_FAILED), gHiiHandle);\r
+  gSaveProcess          = GetToken (STRING_TOKEN (DISCARD_OR_JUMP), gHiiHandle);\r
+  gSaveNoSubmitProcess  = GetToken (STRING_TOKEN (DISCARD_OR_CHECK), gHiiHandle);\r
+  gDiscardChange        = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_DISCARD), gHiiHandle);\r
+  gJumpToFormSet        = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_JUMP), gHiiHandle);\r
+  gCheckError           = GetToken (STRING_TOKEN (DISCARD_OR_CHECK_CHECK), gHiiHandle);\r
   gPromptForData        = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
   gPromptForPassword    = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
   gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
@@ -216,6 +229,12 @@ FreeDisplayStrings (
   FreePool (mUnknownString);\r
   FreePool (gEmptyString);\r
   FreePool (gSaveFailed);\r
+  FreePool (gNoSubmitIfFailed);\r
+  FreePool (gSaveProcess);\r
+  FreePool (gSaveNoSubmitProcess);\r
+  FreePool (gDiscardChange);\r
+  FreePool (gJumpToFormSet);\r
+  FreePool (gCheckError);\r
   FreePool (gPromptForData);\r
   FreePool (gPromptForPassword);\r
   FreePool (gPromptForNewPassword);\r
@@ -699,6 +718,13 @@ ConvertStatementToMenu (
       NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);\r
       NestLink = GetNextNode (&Statement->NestStatementList, NestLink);\r
 \r
+      //\r
+      // Skip the opcode not recognized by Display core.\r
+      //\r
+      if (NestStatement->OpCode->OpCode == EFI_IFR_GUID_OP) {\r
+        continue;\r
+      }\r
+\r
       UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);\r
     }\r
   }\r
@@ -1471,6 +1497,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
@@ -1514,23 +1541,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
@@ -1539,11 +1585,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
@@ -1560,14 +1609,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
@@ -1713,6 +1787,7 @@ HasOptionString (
   @param  SkipLine                 The skip line for this menu. \r
   @param  BottomRow                The bottom row for this form.\r
   @param  Highlight                Whether this menu will be highlight.\r
+  @param  UpdateCol                Whether need to update the column info for Date/Time.\r
 \r
   @retval EFI_SUCESSS              Process the user selection success.\r
 \r
@@ -1724,7 +1799,8 @@ DisplayOneMenu (
   IN UINTN                           BeginCol,\r
   IN UINTN                           SkipLine,\r
   IN UINTN                           BottomRow,\r
-  IN BOOLEAN                         Highlight\r
+  IN BOOLEAN                         Highlight,\r
+  IN BOOLEAN                         UpdateCol\r
   )\r
 {\r
   FORM_DISPLAY_ENGINE_STATEMENT   *Statement;\r
@@ -1773,7 +1849,7 @@ DisplayOneMenu (
       //\r
       // Adjust option string for date/time opcode.\r
       //\r
-      ProcessStringForDateTime(MenuOption, OptionString, TRUE);\r
+      ProcessStringForDateTime(MenuOption, OptionString, UpdateCol);\r
     }\r
   \r
     Width       = (UINT16) gOptionBlockWidth - 1;\r
@@ -1798,8 +1874,9 @@ DisplayOneMenu (
           } else {\r
             //\r
             // For date/ time, print the first and second past (year for date and second for time)\r
-            //                \r
-            DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString), Highlight);\r
+            // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string, \r
+            // so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it.\r
+            DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString) - 1, Highlight);\r
           }\r
         } else {\r
           DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
@@ -2049,16 +2126,7 @@ UiDisplayMenu (
 \r
   ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
 \r
-  //\r
-  //  Left                                              right\r
-  //   |<-.->|<-.........->|<- .........->|<-...........->|\r
-  //     Skip    Prompt         Option         Help \r
-  //\r
-  Width             = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3);\r
-  gOptionBlockWidth = Width + 1; \r
-  gHelpBlockWidth   = (CHAR16) (Width - LEFT_SKIPPED_COLUMNS);\r
-  gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * Width - 1);\r
-\r
+  Width     = (UINT16)gOptionBlockWidth - 1;\r
   TopRow    = gStatementDimensions.TopRow    + SCROLL_ARROW_HEIGHT;\r
   BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;\r
 \r
@@ -2160,7 +2228,8 @@ UiDisplayMenu (
                             gStatementDimensions.LeftColumn + gModalSkipColumn, \r
                             Link == TopOfScreen ? SkipValue : 0, \r
                             BottomRow,\r
-                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption))\r
+                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
+                            TRUE\r
                             );\r
           } else {\r
             Status = DisplayOneMenu (MenuOption, \r
@@ -2168,8 +2237,9 @@ UiDisplayMenu (
                             gStatementDimensions.LeftColumn, \r
                             Link == TopOfScreen ? SkipValue : 0, \r
                             BottomRow,\r
-                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption))\r
-                            );         \r
+                            (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
+                            TRUE\r
+                            );\r
           }\r
 \r
           if (EFI_ERROR (Status)) {\r
@@ -2239,7 +2309,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
@@ -2272,6 +2342,7 @@ UiDisplayMenu (
                           gStatementDimensions.LeftColumn, \r
                           Temp, \r
                           BottomRow,\r
+                          FALSE,\r
                           FALSE\r
                           );\r
         }\r
@@ -2282,7 +2353,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
@@ -2293,7 +2364,8 @@ UiDisplayMenu (
                         gStatementDimensions.LeftColumn, \r
                         Temp2, \r
                         BottomRow,\r
-                        TRUE\r
+                        TRUE,\r
+                        FALSE\r
                         );\r
       }\r
       break;\r
@@ -2548,12 +2620,12 @@ UiDisplayMenu (
         // If the screen has no menu items, and the user didn't select UiReset\r
         // ignore the selection and go back to reading keys.\r
         //\r
+        ASSERT(MenuOption != NULL);\r
         if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
           ControlFlag = CfReadKey;\r
           break;\r
         }\r
 \r
-        ASSERT(MenuOption != NULL);\r
         Statement = MenuOption->ThisTag;\r
         if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)\r
           || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)\r
@@ -2736,7 +2808,8 @@ UiDisplayMenu (
 \r
     case CfUiHotKey:\r
       ControlFlag = CfRepaint;\r
-      \r
+\r
+      ASSERT (HotKey != NULL);\r
       gUserInput->Action = HotKey->Action;\r
       ControlFlag = CfExit;\r
       break;\r
@@ -2774,16 +2847,16 @@ UiDisplayMenu (
       NewLine     = TRUE;\r
 \r
       SavedListEntry = NewPos;\r
-\r
       ASSERT(NewPos != NULL);\r
+\r
+      MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+      ASSERT (MenuOption != NULL);\r
+\r
       //\r
       // Adjust Date/Time position before we advance forward.\r
       //\r
       AdjustDateAndTimePosition (TRUE, &NewPos);\r
 \r
-      MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-      ASSERT (MenuOption != NULL);\r
-\r
       NewPos     = NewPos->BackLink;\r
       //\r
       // Find next selectable menu or the first menu beyond current form.\r
@@ -2855,7 +2928,7 @@ UiDisplayMenu (
       //\r
       // First minus the menu of the top screen, it's value is SkipValue.\r
       //\r
-      if (SkipValue >= (INTN) (BottomRow - TopRow + 1)) {\r
+      if (SkipValue >= BottomRow - TopRow + 1) {\r
         //\r
         // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
         // form of options to be show, so just update the SkipValue to show the next\r
@@ -3134,14 +3207,56 @@ 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
+  CHAR16             DiscardChange;\r
+  CHAR16             JumpToFormSet;\r
+  CHAR16             *PrintString;\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
@@ -3149,10 +3264,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
@@ -3165,18 +3276,98 @@ BrowserStatusProcess (
       ErrorInfo = gProtocolNotFound;\r
       break;\r
 \r
+    case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
+      ErrorInfo = gNoSubmitIfFailed;\r
+      break;\r
+\r
     default:\r
       ErrorInfo = gBrwoserError;\r
       break;\r
     }\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
+  switch (gFormData->BrowserStatus) {\r
+  case BROWSER_SUBMIT_FAIL:\r
+  case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
+    ASSERT (gUserInput != NULL);\r
+    if (gFormData->BrowserStatus == (BROWSER_SUBMIT_FAIL)) {\r
+      PrintString = gSaveProcess;\r
+      JumpToFormSet = gJumpToFormSet[0];\r
+    } else {\r
+      PrintString = gSaveNoSubmitProcess;\r
+      JumpToFormSet = gCheckError[0];\r
+    }\r
+    DiscardChange = gDiscardChange[0];\r
+\r
+    do {\r
+      CreateDialog (&Key, gEmptyString, ErrorInfo, PrintString, gEmptyString, NULL);\r
+    } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (DiscardChange | UPPER_LOWER_CASE_OFFSET)) &&\r
+             ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (JumpToFormSet | UPPER_LOWER_CASE_OFFSET)));\r
+\r
+    if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (DiscardChange | UPPER_LOWER_CASE_OFFSET)) {\r
+      gUserInput->Action = BROWSER_ACTION_DISCARD;\r
+    } else {\r
+      gUserInput->Action = BROWSER_ACTION_GOTO;\r
+    }\r
+    break;\r
+\r
+  default:\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
+      gBS->CloseEvent (TimeOutEvent);\r
+      gBS->CloseEvent (RefreshIntervalEvent);\r
+    }\r
+    break;\r
+  }\r
+\r
+  if (StringToken != 0) {\r
+    FreePool (ErrorInfo);\r
+  }\r
 }\r
 \r
 /**\r
@@ -3211,20 +3402,33 @@ FormDisplay (
   // Process the status info first.\r
   //\r
   BrowserStatusProcess();\r
-  if (UserInputData == NULL) {\r
+  if (gFormData->BrowserStatus != BROWSER_SUCCESS) {\r
     //\r
-    // UserInputData == NULL, means only need to print the error info, return here.\r
+    // gFormData->BrowserStatus != BROWSER_SUCCESS, means only need to print the error info, return here.\r
     //\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  ConvertStatementToMenu();\r
-\r
   Status = DisplayPageFrame (FormData, &gStatementDimensions);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
+  //\r
+  // Global Widths should be initialized before any MenuOption creation\r
+  // or the GetWidth() used in UiAddMenuOption() will return incorrect value.\r
+  //\r
+  //\r
+  //  Left                                              right\r
+  //   |<-.->|<-.........->|<- .........->|<-...........->|\r
+  //     Skip    Prompt         Option         Help \r
+  //\r
+  gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3) + 1;\r
+  gHelpBlockWidth   = (CHAR16) (gOptionBlockWidth - 1 - LEFT_SKIPPED_COLUMNS);\r
+  gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gOptionBlockWidth - 1) - 1);\r
+\r
+  ConvertStatementToMenu();\r
+\r
   //\r
   // Check whether layout is changed.\r
   //\r
@@ -3377,5 +3581,9 @@ UnloadDisplayEngine (
 \r
   FreeDisplayStrings ();\r
 \r
+  if (gHighligthMenuInfo.OpCode != NULL) {\r
+    FreePool (gHighligthMenuInfo.OpCode);\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r