]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
CommitLineData
7c6c064c
ED
1/** @file\r
2Entry and initialization module for the browser.\r
3\r
d1102dba 4Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
c4866c77 5Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>\r
7c6c064c
ED
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "FormDisplay.h"\r
17\r
18//\r
19// Search table for UiDisplayMenu()\r
20//\r
21SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {\r
22 {\r
23 SCAN_UP,\r
24 UiUp,\r
25 },\r
26 {\r
27 SCAN_DOWN,\r
28 UiDown,\r
29 },\r
30 {\r
31 SCAN_PAGE_UP,\r
32 UiPageUp,\r
33 },\r
34 {\r
35 SCAN_PAGE_DOWN,\r
36 UiPageDown,\r
37 },\r
38 {\r
39 SCAN_ESC,\r
40 UiReset,\r
41 },\r
42 {\r
43 SCAN_LEFT,\r
44 UiLeft,\r
45 },\r
46 {\r
47 SCAN_RIGHT,\r
48 UiRight,\r
49 }\r
50};\r
51\r
bce1d8a8 52UINTN mScanCodeNumber = ARRAY_SIZE (gScanCodeToOperation);\r
7c6c064c
ED
53\r
54SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {\r
55 {\r
56 UiNoOperation,\r
57 CfUiNoOperation,\r
58 },\r
59 {\r
60 UiSelect,\r
61 CfUiSelect,\r
62 },\r
63 {\r
64 UiUp,\r
65 CfUiUp,\r
66 },\r
67 {\r
68 UiDown,\r
69 CfUiDown,\r
70 },\r
71 {\r
72 UiLeft,\r
73 CfUiLeft,\r
74 },\r
75 {\r
76 UiRight,\r
77 CfUiRight,\r
78 },\r
79 {\r
80 UiReset,\r
81 CfUiReset,\r
82 },\r
83 {\r
84 UiPageUp,\r
85 CfUiPageUp,\r
86 },\r
87 {\r
88 UiPageDown,\r
89 CfUiPageDown\r
d1102dba 90 },\r
7c6c064c
ED
91 {\r
92 UiHotKey,\r
93 CfUiHotKey\r
94 }\r
95};\r
96\r
97EFI_GUID gDisplayEngineGuid = {\r
98 0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62}\r
99};\r
100\r
42645c3d 101BOOLEAN gMisMatch;\r
7c6c064c 102EFI_SCREEN_DESCRIPTOR gStatementDimensions;\r
7c6c064c
ED
103BOOLEAN mStatementLayoutIsChanged = TRUE;\r
104USER_INPUT *gUserInput;\r
105FORM_DISPLAY_ENGINE_FORM *gFormData;\r
106EFI_HII_HANDLE gHiiHandle;\r
107UINT16 gDirection;\r
108LIST_ENTRY gMenuOption;\r
109DISPLAY_HIGHLIGHT_MENU_INFO gHighligthMenuInfo = {0};\r
5a9f73bf
ED
110BOOLEAN mIsFirstForm = TRUE;\r
111FORM_ENTRY_INFO gOldFormEntry = {0};\r
7c6c064c
ED
112\r
113//\r
114// Browser Global Strings\r
115//\r
f2e7732e
ED
116CHAR16 *gReconnectConfirmChanges;\r
117CHAR16 *gReconnectFail;\r
118CHAR16 *gReconnectRequired;\r
119CHAR16 *gChangesOpt;\r
7c6c064c
ED
120CHAR16 *gFormNotFound;\r
121CHAR16 *gNoSubmitIf;\r
f2e7732e 122CHAR16 *gBrowserError;\r
7c6c064c 123CHAR16 *gSaveFailed;\r
4d4deaac
ED
124CHAR16 *gNoSubmitIfFailed;\r
125CHAR16 *gSaveProcess;\r
126CHAR16 *gSaveNoSubmitProcess;\r
127CHAR16 *gDiscardChange;\r
128CHAR16 *gJumpToFormSet;\r
129CHAR16 *gCheckError;\r
7c6c064c
ED
130CHAR16 *gPromptForData;\r
131CHAR16 *gPromptForPassword;\r
132CHAR16 *gPromptForNewPassword;\r
133CHAR16 *gConfirmPassword;\r
134CHAR16 *gConfirmError;\r
135CHAR16 *gPassowordInvalid;\r
136CHAR16 *gPressEnter;\r
137CHAR16 *gEmptyString;\r
138CHAR16 *gMiniString;\r
139CHAR16 *gOptionMismatch;\r
140CHAR16 *gFormSuppress;\r
141CHAR16 *gProtocolNotFound;\r
23c7d425
ED
142CHAR16 *gConfirmDefaultMsg;\r
143CHAR16 *gConfirmSubmitMsg;\r
144CHAR16 *gConfirmDiscardMsg;\r
145CHAR16 *gConfirmResetMsg;\r
146CHAR16 *gConfirmExitMsg;\r
147CHAR16 *gConfirmSubmitMsg2nd;\r
148CHAR16 *gConfirmDefaultMsg2nd;\r
149CHAR16 *gConfirmResetMsg2nd;\r
150CHAR16 *gConfirmExitMsg2nd;\r
151CHAR16 *gConfirmOpt;\r
152CHAR16 *gConfirmOptYes;\r
153CHAR16 *gConfirmOptNo;\r
06aad9a2
DB
154CHAR16 *gConfirmOptOk;\r
155CHAR16 *gConfirmOptCancel;\r
156CHAR16 *gYesOption;\r
157CHAR16 *gNoOption;\r
158CHAR16 *gOkOption;\r
159CHAR16 *gCancelOption;\r
160CHAR16 *gErrorPopup;\r
161CHAR16 *gWarningPopup;\r
162CHAR16 *gInfoPopup;\r
23c7d425
ED
163CHAR16 *gConfirmMsgConnect;\r
164CHAR16 *gConfirmMsgEnd;\r
88f0c4e2 165CHAR16 *gPasswordUnsupported;\r
af047db7 166CHAR16 gModalSkipColumn;\r
7c6c064c
ED
167CHAR16 gPromptBlockWidth;\r
168CHAR16 gOptionBlockWidth;\r
169CHAR16 gHelpBlockWidth;\r
170CHAR16 *mUnknownString;\r
171\r
172FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData = {\r
173 FORM_DISPLAY_DRIVER_SIGNATURE,\r
174 NULL,\r
175 {\r
176 FormDisplay,\r
5a9f73bf 177 DriverClearDisplayPage,\r
7c6c064c 178 ConfirmDataChange\r
06aad9a2
DB
179 },\r
180 {\r
181 EFI_HII_POPUP_PROTOCOL_REVISION,\r
182 CreatePopup\r
7c6c064c
ED
183 }\r
184};\r
185\r
186\r
187/**\r
188 Get the string based on the StringId and HII Package List Handle.\r
189\r
190 @param Token The String's ID.\r
191 @param HiiHandle The package list in the HII database to search for\r
192 the specified string.\r
193\r
194 @return The output string.\r
195\r
196**/\r
197CHAR16 *\r
198GetToken (\r
199 IN EFI_STRING_ID Token,\r
200 IN EFI_HII_HANDLE HiiHandle\r
201 )\r
202{\r
203 EFI_STRING String;\r
204\r
205 String = HiiGetString (HiiHandle, Token, NULL);\r
206 if (String == NULL) {\r
207 String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
208 ASSERT (String != NULL);\r
209 }\r
210\r
211 return (CHAR16 *) String;\r
212}\r
213\r
214\r
215/**\r
216 Initialize the HII String Token to the correct values.\r
217\r
218**/\r
219VOID\r
220InitializeDisplayStrings (\r
221 VOID\r
222 )\r
223{\r
f2e7732e 224 gReconnectConfirmChanges = GetToken (STRING_TOKEN (RECONNECT_CONFIRM_CHANGES), gHiiHandle);\r
7c6c064c
ED
225 mUnknownString = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);\r
226 gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
4d4deaac 227 gNoSubmitIfFailed = GetToken (STRING_TOKEN (NO_SUBMIT_IF_CHECK_FAILED), gHiiHandle);\r
f2e7732e
ED
228 gReconnectFail = GetToken (STRING_TOKEN (RECONNECT_FAILED), gHiiHandle);\r
229 gReconnectRequired = GetToken (STRING_TOKEN (RECONNECT_REQUIRED), gHiiHandle);\r
230 gChangesOpt = GetToken (STRING_TOKEN (RECONNECT_CHANGES_OPTIONS), gHiiHandle);\r
4d4deaac
ED
231 gSaveProcess = GetToken (STRING_TOKEN (DISCARD_OR_JUMP), gHiiHandle);\r
232 gSaveNoSubmitProcess = GetToken (STRING_TOKEN (DISCARD_OR_CHECK), gHiiHandle);\r
233 gDiscardChange = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_DISCARD), gHiiHandle);\r
234 gJumpToFormSet = GetToken (STRING_TOKEN (DISCARD_OR_JUMP_JUMP), gHiiHandle);\r
235 gCheckError = GetToken (STRING_TOKEN (DISCARD_OR_CHECK_CHECK), gHiiHandle);\r
7c6c064c
ED
236 gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
237 gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
238 gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
239 gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
240 gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
241 gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
242 gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
243 gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
244 gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
245 gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
246 gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);\r
247 gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);\r
248 gFormNotFound = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle);\r
249 gNoSubmitIf = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle);\r
f2e7732e 250 gBrowserError = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);\r
23c7d425
ED
251 gConfirmDefaultMsg = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE), gHiiHandle);\r
252 gConfirmDiscardMsg = GetToken (STRING_TOKEN (CONFIRM_DISCARD_MESSAGE), gHiiHandle);\r
253 gConfirmSubmitMsg = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE), gHiiHandle);\r
254 gConfirmResetMsg = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE), gHiiHandle);\r
255 gConfirmExitMsg = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE), gHiiHandle);\r
256 gConfirmDefaultMsg2nd = GetToken (STRING_TOKEN (CONFIRM_DEFAULT_MESSAGE_2ND), gHiiHandle);\r
257 gConfirmSubmitMsg2nd = GetToken (STRING_TOKEN (CONFIRM_SUBMIT_MESSAGE_2ND), gHiiHandle);\r
258 gConfirmResetMsg2nd = GetToken (STRING_TOKEN (CONFIRM_RESET_MESSAGE_2ND), gHiiHandle);\r
259 gConfirmExitMsg2nd = GetToken (STRING_TOKEN (CONFIRM_EXIT_MESSAGE_2ND), gHiiHandle);\r
260 gConfirmOpt = GetToken (STRING_TOKEN (CONFIRM_OPTION), gHiiHandle);\r
261 gConfirmOptYes = GetToken (STRING_TOKEN (CONFIRM_OPTION_YES), gHiiHandle);\r
262 gConfirmOptNo = GetToken (STRING_TOKEN (CONFIRM_OPTION_NO), gHiiHandle);\r
06aad9a2
DB
263 gConfirmOptOk = GetToken (STRING_TOKEN (CONFIRM_OPTION_OK), gHiiHandle);\r
264 gConfirmOptCancel = GetToken (STRING_TOKEN (CONFIRM_OPTION_CANCEL), gHiiHandle);\r
265 gYesOption = GetToken (STRING_TOKEN (YES_SELECTABLE_OPTION), gHiiHandle);\r
266 gNoOption = GetToken (STRING_TOKEN (NO_SELECTABLE_OPTION), gHiiHandle);\r
267 gOkOption = GetToken (STRING_TOKEN (OK_SELECTABLE_OPTION), gHiiHandle);\r
268 gCancelOption = GetToken (STRING_TOKEN (CANCEL_SELECTABLE_OPTION), gHiiHandle);\r
269 gErrorPopup = GetToken (STRING_TOKEN (ERROR_POPUP_STRING), gHiiHandle);\r
270 gWarningPopup = GetToken (STRING_TOKEN (WARNING_POPUP_STRING), gHiiHandle);\r
271 gInfoPopup = GetToken (STRING_TOKEN (INFO_POPUP_STRING), gHiiHandle);\r
23c7d425
ED
272 gConfirmMsgConnect = GetToken (STRING_TOKEN (CONFIRM_OPTION_CONNECT), gHiiHandle);\r
273 gConfirmMsgEnd = GetToken (STRING_TOKEN (CONFIRM_OPTION_END), gHiiHandle);\r
88f0c4e2 274 gPasswordUnsupported = GetToken (STRING_TOKEN (PASSWORD_NOT_SUPPORTED ), gHiiHandle);\r
7c6c064c
ED
275}\r
276\r
277/**\r
278 Free up the resource allocated for all strings required\r
279 by Setup Browser.\r
280\r
281**/\r
282VOID\r
283FreeDisplayStrings (\r
284 VOID\r
285 )\r
286{\r
287 FreePool (mUnknownString);\r
288 FreePool (gEmptyString);\r
289 FreePool (gSaveFailed);\r
4d4deaac 290 FreePool (gNoSubmitIfFailed);\r
f2e7732e
ED
291 FreePool (gReconnectFail);\r
292 FreePool (gReconnectRequired);\r
293 FreePool (gChangesOpt);\r
294 FreePool (gReconnectConfirmChanges);\r
4d4deaac
ED
295 FreePool (gSaveProcess);\r
296 FreePool (gSaveNoSubmitProcess);\r
297 FreePool (gDiscardChange);\r
298 FreePool (gJumpToFormSet);\r
299 FreePool (gCheckError);\r
7c6c064c
ED
300 FreePool (gPromptForData);\r
301 FreePool (gPromptForPassword);\r
302 FreePool (gPromptForNewPassword);\r
303 FreePool (gConfirmPassword);\r
304 FreePool (gConfirmError);\r
305 FreePool (gPassowordInvalid);\r
306 FreePool (gPressEnter);\r
307 FreePool (gMiniString);\r
308 FreePool (gOptionMismatch);\r
309 FreePool (gFormSuppress);\r
310 FreePool (gProtocolNotFound);\r
f2e7732e 311 FreePool (gBrowserError);\r
7c6c064c
ED
312 FreePool (gNoSubmitIf);\r
313 FreePool (gFormNotFound);\r
23c7d425
ED
314 FreePool (gConfirmDefaultMsg);\r
315 FreePool (gConfirmSubmitMsg);\r
316 FreePool (gConfirmDiscardMsg);\r
317 FreePool (gConfirmResetMsg);\r
318 FreePool (gConfirmExitMsg);\r
319 FreePool (gConfirmDefaultMsg2nd);\r
320 FreePool (gConfirmSubmitMsg2nd);\r
321 FreePool (gConfirmResetMsg2nd);\r
322 FreePool (gConfirmExitMsg2nd);\r
323 FreePool (gConfirmOpt);\r
324 FreePool (gConfirmOptYes);\r
325 FreePool (gConfirmOptNo);\r
06aad9a2
DB
326 FreePool (gConfirmOptOk);\r
327 FreePool (gConfirmOptCancel);\r
328 FreePool (gYesOption);\r
329 FreePool (gNoOption);\r
330 FreePool (gOkOption);\r
331 FreePool (gCancelOption);\r
332 FreePool (gErrorPopup);\r
333 FreePool (gWarningPopup);\r
334 FreePool (gInfoPopup);\r
23c7d425
ED
335 FreePool (gConfirmMsgConnect);\r
336 FreePool (gConfirmMsgEnd);\r
88f0c4e2 337 FreePool (gPasswordUnsupported);\r
7c6c064c
ED
338}\r
339\r
340/**\r
341 Get prompt string id from the opcode data buffer.\r
342\r
343 @param OpCode The input opcode buffer.\r
344\r
345 @return The prompt string id.\r
346\r
347**/\r
348EFI_STRING_ID\r
349GetPrompt (\r
350 IN EFI_IFR_OP_HEADER *OpCode\r
351 )\r
352{\r
353 EFI_IFR_STATEMENT_HEADER *Header;\r
354\r
355 if (OpCode->Length <= sizeof (EFI_IFR_OP_HEADER)) {\r
356 return 0;\r
357 }\r
358\r
359 Header = (EFI_IFR_STATEMENT_HEADER *) (OpCode + 1);\r
360\r
361 return Header->Prompt;\r
362}\r
363\r
364/**\r
365 Get the supported width for a particular op-code\r
366\r
6f05c023 367 @param MenuOption The menu option.\r
af047db7 368 @param AdjustWidth The width which is saved for the space.\r
7c6c064c
ED
369\r
370 @return Returns the number of CHAR16 characters that is support.\r
371\r
372**/\r
373UINT16\r
374GetWidth (\r
6f05c023
ED
375 IN UI_MENU_OPTION *MenuOption,\r
376 OUT UINT16 *AdjustWidth\r
7c6c064c
ED
377 )\r
378{\r
6f05c023
ED
379 CHAR16 *String;\r
380 UINTN Size;\r
381 EFI_IFR_TEXT *TestOp;\r
382 UINT16 ReturnWidth;\r
383 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
384\r
385 Statement = MenuOption->ThisTag;\r
7c6c064c 386\r
af047db7
ED
387 //\r
388 // For modal form, clean the entire row.\r
389 //\r
390 if ((gFormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
ae4f5746
ED
391 if (AdjustWidth != NULL) {\r
392 *AdjustWidth = LEFT_SKIPPED_COLUMNS;\r
393 }\r
394 return (UINT16)(gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gModalSkipColumn + LEFT_SKIPPED_COLUMNS));\r
af047db7
ED
395 }\r
396\r
7c6c064c
ED
397 Size = 0;\r
398\r
399 //\r
400 // See if the second text parameter is really NULL\r
401 //\r
402 if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
403 TestOp = (EFI_IFR_TEXT *) Statement->OpCode;\r
404 if (TestOp->TextTwo != 0) {\r
405 String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);\r
406 Size = StrLen (String);\r
407 FreePool (String);\r
408 }\r
409 }\r
410\r
411 if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
412 (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||\r
413 (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||\r
414 (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||\r
415 (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||\r
416 //\r
417 // Allow a wide display if text op-code and no secondary text op-code\r
418 //\r
419 ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))\r
420 ) {\r
d1102dba 421\r
af047db7
ED
422 //\r
423 // Return the space width.\r
d1102dba 424 //\r
af047db7
ED
425 if (AdjustWidth != NULL) {\r
426 *AdjustWidth = 2;\r
427 }\r
428 //\r
429 // Keep consistent with current behavior.\r
430 //\r
6f05c023
ED
431 ReturnWidth = (UINT16) (gPromptBlockWidth + gOptionBlockWidth - 2);\r
432 } else {\r
433 if (AdjustWidth != NULL) {\r
434 *AdjustWidth = 1;\r
435 }\r
436\r
437 ReturnWidth = (UINT16) (gPromptBlockWidth - 1);\r
7c6c064c
ED
438 }\r
439\r
6f05c023
ED
440 //\r
441 // For nest in statement, should the subtitle indent.\r
442 //\r
443 if (MenuOption->NestInStatement) {\r
444 ReturnWidth -= SUBTITLE_INDENT;\r
af047db7 445 }\r
6f05c023
ED
446\r
447 return ReturnWidth;\r
7c6c064c
ED
448}\r
449\r
450/**\r
451 Will copy LineWidth amount of a string in the OutputString buffer and return the\r
452 number of CHAR16 characters that were copied into the OutputString buffer.\r
453 The output string format is:\r
454 Glyph Info + String info + '\0'.\r
455\r
456 In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
457\r
458 @param InputString String description for this option.\r
459 @param LineWidth Width of the desired string to extract in CHAR16\r
460 characters\r
461 @param GlyphWidth The glyph width of the begin of the char in the string.\r
462 @param Index Where in InputString to start the copy process\r
463 @param OutputString Buffer to copy the string into\r
464\r
d1102dba 465 @return Returns the number of CHAR16 characters that were copied into the OutputString\r
7c6c064c
ED
466 buffer, include extra glyph info and '\0' info.\r
467\r
468**/\r
469UINT16\r
470GetLineByWidth (\r
471 IN CHAR16 *InputString,\r
472 IN UINT16 LineWidth,\r
473 IN OUT UINT16 *GlyphWidth,\r
474 IN OUT UINTN *Index,\r
475 OUT CHAR16 **OutputString\r
476 )\r
477{\r
478 UINT16 StrOffset;\r
479 UINT16 GlyphOffset;\r
480 UINT16 OriginalGlyphWidth;\r
481 BOOLEAN ReturnFlag;\r
482 UINT16 LastSpaceOffset;\r
483 UINT16 LastGlyphWidth;\r
484\r
485 if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
486 return 0;\r
487 }\r
488\r
489 if (LineWidth == 0 || *GlyphWidth == 0) {\r
490 return 0;\r
491 }\r
492\r
493 //\r
494 // Save original glyph width.\r
495 //\r
496 OriginalGlyphWidth = *GlyphWidth;\r
497 LastGlyphWidth = OriginalGlyphWidth;\r
498 ReturnFlag = FALSE;\r
499 LastSpaceOffset = 0;\r
500\r
501 //\r
502 // NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.\r
503 // To avoid displaying this empty line in screen, just skip the two CHARs here.\r
504 //\r
505 if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
506 *Index = *Index + 2;\r
507 }\r
508\r
509 //\r
510 // Fast-forward the string and see if there is a carriage-return in the string\r
511 //\r
512 for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {\r
513 switch (InputString[*Index + StrOffset]) {\r
514 case NARROW_CHAR:\r
515 *GlyphWidth = 1;\r
516 break;\r
517\r
518 case WIDE_CHAR:\r
519 *GlyphWidth = 2;\r
520 break;\r
521\r
522 case CHAR_CARRIAGE_RETURN:\r
523 case CHAR_LINEFEED:\r
524 case CHAR_NULL:\r
525 ReturnFlag = TRUE;\r
526 break;\r
527\r
528 default:\r
529 GlyphOffset = GlyphOffset + *GlyphWidth;\r
530\r
531 //\r
532 // Record the last space info in this line. Will be used in rewind.\r
533 //\r
534 if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {\r
535 LastSpaceOffset = StrOffset;\r
536 LastGlyphWidth = *GlyphWidth;\r
537 }\r
538 break;\r
539 }\r
540\r
541 if (ReturnFlag) {\r
542 break;\r
543 }\r
d1102dba 544 }\r
7c6c064c
ED
545\r
546 //\r
547 // Rewind the string from the maximum size until we see a space to break the line\r
548 //\r
549 if (GlyphOffset > LineWidth) {\r
550 //\r
551 // Rewind the string to last space char in this line.\r
552 //\r
553 if (LastSpaceOffset != 0) {\r
554 StrOffset = LastSpaceOffset;\r
555 *GlyphWidth = LastGlyphWidth;\r
556 } else {\r
557 //\r
558 // Roll back to last char in the line width.\r
559 //\r
560 StrOffset--;\r
561 }\r
562 }\r
563\r
564 //\r
565 // The CHAR_NULL has process last time, this time just return 0 to stand for the end.\r
566 //\r
567 if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
568 return 0;\r
569 }\r
570\r
571 //\r
572 // Need extra glyph info and '\0' info, so +2.\r
573 //\r
16f69227 574 *OutputString = AllocateZeroPool ((StrOffset + 2) * sizeof(CHAR16));\r
7c6c064c
ED
575 if (*OutputString == NULL) {\r
576 return 0;\r
577 }\r
578\r
579 //\r
580 // Save the glyph info at the begin of the string, will used by Print function.\r
581 //\r
582 if (OriginalGlyphWidth == 1) {\r
583 *(*OutputString) = NARROW_CHAR;\r
584 } else {\r
585 *(*OutputString) = WIDE_CHAR;\r
586 }\r
587\r
588 CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
589\r
590 if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
591 //\r
592 // Skip the space info at the begin of next line.\r
d1102dba 593 //\r
7c6c064c
ED
594 *Index = (UINT16) (*Index + StrOffset + 1);\r
595 } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {\r
596 //\r
597 // Skip the /n or /n/r info.\r
598 //\r
599 if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
600 *Index = (UINT16) (*Index + StrOffset + 2);\r
601 } else {\r
602 *Index = (UINT16) (*Index + StrOffset + 1);\r
603 }\r
604 } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {\r
605 //\r
606 // Skip the /r or /r/n info.\r
d1102dba 607 //\r
7c6c064c
ED
608 if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
609 *Index = (UINT16) (*Index + StrOffset + 2);\r
610 } else {\r
611 *Index = (UINT16) (*Index + StrOffset + 1);\r
612 }\r
613 } else {\r
614 *Index = (UINT16) (*Index + StrOffset);\r
615 }\r
616\r
617 //\r
618 // Include extra glyph info and '\0' info, so +2.\r
619 //\r
620 return StrOffset + 2;\r
621}\r
622\r
623/**\r
624 Add one menu option by specified description and context.\r
625\r
626 @param Statement Statement of this Menu Option.\r
627 @param MenuItemCount The index for this Option in the Menu.\r
628 @param NestIn Whether this statement is nest in another statement.\r
629\r
630**/\r
631VOID\r
632UiAddMenuOption (\r
633 IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
634 IN UINT16 *MenuItemCount,\r
635 IN BOOLEAN NestIn\r
636 )\r
637{\r
638 UI_MENU_OPTION *MenuOption;\r
639 UINTN Index;\r
640 UINTN Count;\r
7c6c064c
ED
641 UINT16 NumberOfLines;\r
642 UINT16 GlyphWidth;\r
643 UINT16 Width;\r
644 UINTN ArrayEntry;\r
645 CHAR16 *OutputString;\r
646 EFI_STRING_ID PromptId;\r
647\r
648 NumberOfLines = 1;\r
649 ArrayEntry = 0;\r
650 GlyphWidth = 1;\r
651 Count = 1;\r
652 MenuOption = NULL;\r
653\r
654 PromptId = GetPrompt (Statement->OpCode);\r
655 ASSERT (PromptId != 0);\r
656\r
7c6c064c 657 if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
7c6c064c
ED
658 Count = 3;\r
659 }\r
660\r
661 for (Index = 0; Index < Count; Index++) {\r
662 MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));\r
663 ASSERT (MenuOption);\r
664\r
665 MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;\r
0196c24a 666 MenuOption->Description = GetToken (PromptId, gFormData->HiiHandle);\r
7c6c064c
ED
667 MenuOption->Handle = gFormData->HiiHandle;\r
668 MenuOption->ThisTag = Statement;\r
669 MenuOption->NestInStatement = NestIn;\r
670 MenuOption->EntryNumber = *MenuItemCount;\r
671\r
7c6c064c
ED
672 MenuOption->Sequence = Index;\r
673\r
674 if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) {\r
675 MenuOption->GrayOut = TRUE;\r
676 } else {\r
677 MenuOption->GrayOut = FALSE;\r
678 }\r
679\r
680 if ((Statement->Attribute & HII_DISPLAY_LOCK) != 0 || (gFormData->Attribute & HII_DISPLAY_LOCK) != 0) {\r
681 MenuOption->GrayOut = TRUE;\r
682 }\r
683\r
684 //\r
685 // If the form or the question has the lock attribute, deal same as grayout.\r
686 //\r
687 if ((gFormData->Attribute & HII_DISPLAY_LOCK) != 0 || (Statement->Attribute & HII_DISPLAY_LOCK) != 0) {\r
688 MenuOption->GrayOut = TRUE;\r
689 }\r
690\r
691 switch (Statement->OpCode->OpCode) {\r
692 case EFI_IFR_ORDERED_LIST_OP:\r
693 case EFI_IFR_ONE_OF_OP:\r
694 case EFI_IFR_NUMERIC_OP:\r
695 case EFI_IFR_TIME_OP:\r
696 case EFI_IFR_DATE_OP:\r
697 case EFI_IFR_CHECKBOX_OP:\r
698 case EFI_IFR_PASSWORD_OP:\r
699 case EFI_IFR_STRING_OP:\r
700 //\r
701 // User could change the value of these items\r
702 //\r
703 MenuOption->IsQuestion = TRUE;\r
704 break;\r
705 case EFI_IFR_TEXT_OP:\r
706 if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {\r
707 //\r
d1102dba 708 // Initializing GrayOut option as TRUE for Text setup options\r
7c6c064c
ED
709 // so that those options will be Gray in colour and un selectable.\r
710 //\r
711 MenuOption->GrayOut = TRUE;\r
712 }\r
713 break;\r
714 default:\r
715 MenuOption->IsQuestion = FALSE;\r
716 break;\r
717 }\r
718\r
719 if ((Statement->Attribute & HII_DISPLAY_READONLY) != 0) {\r
720 MenuOption->ReadOnly = TRUE;\r
721 if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) {\r
722 MenuOption->GrayOut = TRUE;\r
723 }\r
724 }\r
725\r
d1102dba
LG
726 if (Index == 0 &&\r
727 (Statement->OpCode->OpCode != EFI_IFR_DATE_OP) &&\r
6f05c023
ED
728 (Statement->OpCode->OpCode != EFI_IFR_TIME_OP)) {\r
729 Width = GetWidth (MenuOption, NULL);\r
0196c24a 730 for (; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
6f05c023
ED
731 //\r
732 // If there is more string to process print on the next row and increment the Skip value\r
733 //\r
0196c24a 734 if (StrLen (&MenuOption->Description[ArrayEntry]) != 0) {\r
6f05c023
ED
735 NumberOfLines++;\r
736 }\r
737 FreePool (OutputString);\r
738 }\r
739 } else {\r
740 //\r
741 // Add three MenuOptions for Date/Time\r
742 // Data format : [01/02/2004] [11:22:33]\r
743 // Line number : 0 0 1 0 0 1\r
d1102dba 744 //\r
6f05c023
ED
745 NumberOfLines = 0;\r
746 }\r
747\r
748 if (Index == 2) {\r
749 //\r
750 // Override LineNumber for the MenuOption in Date/Time sequence\r
751 //\r
752 MenuOption->Skip = 1;\r
753 } else {\r
754 MenuOption->Skip = NumberOfLines;\r
755 }\r
756\r
7c6c064c
ED
757 InsertTailList (&gMenuOption, &MenuOption->Link);\r
758 }\r
759\r
760 (*MenuItemCount)++;\r
761}\r
762\r
763/**\r
764 Create the menu list base on the form data info.\r
765\r
766**/\r
767VOID\r
768ConvertStatementToMenu (\r
769 VOID\r
770 )\r
771{\r
772 UINT16 MenuItemCount;\r
773 LIST_ENTRY *Link;\r
774 LIST_ENTRY *NestLink;\r
775 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
776 FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;\r
777\r
778 MenuItemCount = 0;\r
779 InitializeListHead (&gMenuOption);\r
780\r
781 Link = GetFirstNode (&gFormData->StatementListHead);\r
782 while (!IsNull (&gFormData->StatementListHead, Link)) {\r
783 Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
784 Link = GetNextNode (&gFormData->StatementListHead, Link);\r
785\r
786 //\r
787 // Skip the opcode not recognized by Display core.\r
788 //\r
789 if (Statement->OpCode->OpCode == EFI_IFR_GUID_OP) {\r
790 continue;\r
791 }\r
792\r
793 UiAddMenuOption (Statement, &MenuItemCount, FALSE);\r
794\r
795 //\r
796 // Check the statement nest in this host statement.\r
797 //\r
798 NestLink = GetFirstNode (&Statement->NestStatementList);\r
799 while (!IsNull (&Statement->NestStatementList, NestLink)) {\r
800 NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);\r
801 NestLink = GetNextNode (&Statement->NestStatementList, NestLink);\r
802\r
077c7aee
ED
803 //\r
804 // Skip the opcode not recognized by Display core.\r
805 //\r
806 if (NestStatement->OpCode->OpCode == EFI_IFR_GUID_OP) {\r
807 continue;\r
808 }\r
809\r
7c6c064c
ED
810 UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);\r
811 }\r
812 }\r
813}\r
814\r
815/**\r
816 Count the storage space of a Unicode string.\r
817\r
818 This function handles the Unicode string with NARROW_CHAR\r
819 and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
820 does not count in the resultant output. If a WIDE_CHAR is\r
821 hit, then 2 Unicode character will consume an output storage\r
822 space with size of CHAR16 till a NARROW_CHAR is hit.\r
823\r
824 If String is NULL, then ASSERT ().\r
825\r
826 @param String The input string to be counted.\r
827\r
828 @return Storage space for the input string.\r
829\r
830**/\r
831UINTN\r
832GetStringWidth (\r
833 IN CHAR16 *String\r
834 )\r
835{\r
836 UINTN Index;\r
837 UINTN Count;\r
838 UINTN IncrementValue;\r
839\r
840 ASSERT (String != NULL);\r
841 if (String == NULL) {\r
842 return 0;\r
843 }\r
844\r
845 Index = 0;\r
846 Count = 0;\r
847 IncrementValue = 1;\r
848\r
849 do {\r
850 //\r
851 // Advance to the null-terminator or to the first width directive\r
852 //\r
853 for (;\r
854 (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
855 Index++, Count = Count + IncrementValue\r
856 )\r
857 ;\r
858\r
859 //\r
860 // We hit the null-terminator, we now have a count\r
861 //\r
862 if (String[Index] == 0) {\r
863 break;\r
864 }\r
865 //\r
866 // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
867 // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
868 //\r
869 if (String[Index] == NARROW_CHAR) {\r
870 //\r
871 // Skip to the next character\r
872 //\r
873 Index++;\r
874 IncrementValue = 1;\r
875 } else {\r
876 //\r
877 // Skip to the next character\r
878 //\r
879 Index++;\r
880 IncrementValue = 2;\r
881 }\r
882 } while (String[Index] != 0);\r
883\r
884 //\r
885 // Increment by one to include the null-terminator in the size\r
886 //\r
887 Count++;\r
888\r
889 return Count * sizeof (CHAR16);\r
890}\r
891\r
892/**\r
893 Base on the input option string to update the skip value for a menu option.\r
894\r
895 @param MenuOption The MenuOption to be checked.\r
896 @param OptionString The input option string.\r
897\r
898**/\r
899VOID\r
900UpdateSkipInfoForMenu (\r
901 IN UI_MENU_OPTION *MenuOption,\r
902 IN CHAR16 *OptionString\r
903 )\r
904{\r
905 UINTN Index;\r
906 UINT16 Width;\r
907 UINTN Row;\r
908 CHAR16 *OutputString;\r
909 UINT16 GlyphWidth;\r
910\r
df591499 911 Width = (UINT16) gOptionBlockWidth - 1;\r
7c6c064c
ED
912 GlyphWidth = 1;\r
913 Row = 1;\r
914\r
915 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
916 if (StrLen (&OptionString[Index]) != 0) {\r
917 Row++;\r
918 }\r
919\r
920 FreePool (OutputString);\r
921 }\r
922\r
d1102dba
LG
923 if ((Row > MenuOption->Skip) &&\r
924 (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) &&\r
7c6c064c
ED
925 (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP)) {\r
926 MenuOption->Skip = Row;\r
927 }\r
928}\r
929\r
930/**\r
931 Update display lines for a Menu Option.\r
932\r
933 @param MenuOption The MenuOption to be checked.\r
934\r
935**/\r
936VOID\r
937UpdateOptionSkipLines (\r
938 IN UI_MENU_OPTION *MenuOption\r
939 )\r
940{\r
941 CHAR16 *OptionString;\r
942\r
943 OptionString = NULL;\r
944\r
945 ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
946 if (OptionString != NULL) {\r
947 UpdateSkipInfoForMenu (MenuOption, OptionString);\r
948\r
949 FreePool (OptionString);\r
950 }\r
951\r
952 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {\r
953 OptionString = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);\r
954\r
955 if (OptionString != NULL) {\r
956 UpdateSkipInfoForMenu (MenuOption, OptionString);\r
957\r
958 FreePool (OptionString);\r
959 }\r
960 }\r
961}\r
962\r
ab369468
ED
963/**\r
964 Check whether this Menu Option could be print.\r
965\r
966 Check Prompt string, option string or text two string not NULL.\r
967\r
968 This is an internal function.\r
969\r
970 @param MenuOption The MenuOption to be checked.\r
971\r
972 @retval TRUE This Menu Option is printable.\r
973 @retval FALSE This Menu Option could not be printable.\r
974\r
975**/\r
976BOOLEAN\r
977PrintableMenu (\r
978 UI_MENU_OPTION *MenuOption\r
979 )\r
980{\r
981 EFI_STATUS Status;\r
982 EFI_STRING OptionString;\r
983\r
984 OptionString = NULL;\r
985\r
986 if (MenuOption->Description[0] != '\0') {\r
987 return TRUE;\r
988 }\r
989\r
990 Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);\r
991 if (EFI_ERROR (Status)) {\r
992 return FALSE;\r
993 }\r
994 if (OptionString != NULL && OptionString[0] != '\0') {\r
995 FreePool (OptionString);\r
996 return TRUE;\r
997 }\r
998\r
999 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {\r
1000 OptionString = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);\r
1001 ASSERT (OptionString != NULL);\r
1002 if (OptionString[0] != '\0'){\r
1003 FreePool (OptionString);\r
1004 return TRUE;\r
1005 }\r
1006 }\r
1007\r
1008 return FALSE;\r
1009}\r
1010\r
7c6c064c
ED
1011/**\r
1012 Check whether this Menu Option could be highlighted.\r
1013\r
1014 This is an internal function.\r
1015\r
1016 @param MenuOption The MenuOption to be checked.\r
1017\r
1018 @retval TRUE This Menu Option is selectable.\r
1019 @retval FALSE This Menu Option could not be selected.\r
1020\r
1021**/\r
1022BOOLEAN\r
1023IsSelectable (\r
1024 UI_MENU_OPTION *MenuOption\r
1025 )\r
1026{\r
1027 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
ab369468 1028 MenuOption->GrayOut || MenuOption->ReadOnly || !PrintableMenu (MenuOption)) {\r
7c6c064c
ED
1029 return FALSE;\r
1030 } else {\r
1031 return TRUE;\r
1032 }\r
1033}\r
1034\r
1035/**\r
1036 Move to next selectable statement.\r
1037\r
1038 This is an internal function.\r
1039\r
1040 @param GoUp The navigation direction. TRUE: up, FALSE: down.\r
1041 @param CurrentPosition Current position.\r
1042 @param GapToTop Gap position to top or bottom.\r
ab369468 1043 @param FindInForm Whether find menu in current form or beyond.\r
7c6c064c
ED
1044\r
1045 @return The row distance from current MenuOption to next selectable MenuOption.\r
1046\r
1047 @retval -1 Reach the begin of the menu, still can't find the selectable menu.\r
d1102dba
LG
1048 @retval Value Find the selectable menu, maybe the truly selectable, maybe the\r
1049 first menu showing beyond current form or last menu showing in\r
ab369468
ED
1050 current form.\r
1051 The value is the line number between the new selected menu and the\r
1052 current select menu, not include the new selected menu.\r
7c6c064c
ED
1053\r
1054**/\r
1055INTN\r
1056MoveToNextStatement (\r
1057 IN BOOLEAN GoUp,\r
1058 IN OUT LIST_ENTRY **CurrentPosition,\r
ab369468
ED
1059 IN UINTN GapToTop,\r
1060 IN BOOLEAN FindInForm\r
7c6c064c
ED
1061 )\r
1062{\r
1063 INTN Distance;\r
1064 LIST_ENTRY *Pos;\r
1065 UI_MENU_OPTION *NextMenuOption;\r
1066 UI_MENU_OPTION *PreMenuOption;\r
1067\r
1068 Distance = 0;\r
1069 Pos = *CurrentPosition;\r
ab369468
ED
1070\r
1071 if (Pos == &gMenuOption) {\r
1072 return -1;\r
1073 }\r
1074\r
7c6c064c
ED
1075 PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
1076\r
1077 while (TRUE) {\r
1078 NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
1079 //\r
1080 // NextMenuOption->Row == 0 means this menu has not calculate\r
1081 // the NextMenuOption->Skip value yet, just calculate here.\r
1082 //\r
1083 if (NextMenuOption->Row == 0) {\r
1084 UpdateOptionSkipLines (NextMenuOption);\r
1085 }\r
7c6c064c 1086\r
ab369468 1087 //\r
0265811d 1088 // Check whether the menu is beyond current showing form,\r
ab369468
ED
1089 // return the first one beyond the showing form.\r
1090 //\r
1091 if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
1092 if (FindInForm) {\r
1093 NextMenuOption = PreMenuOption;\r
1094 }\r
7c6c064c
ED
1095 break;\r
1096 }\r
1097\r
0265811d
DB
1098 //\r
1099 // return the selectable menu in the showing form.\r
1100 //\r
1101 if (IsSelectable (NextMenuOption)) {\r
1102 break;\r
1103 }\r
1104\r
ab369468
ED
1105 Distance += NextMenuOption->Skip;\r
1106\r
7c6c064c
ED
1107 //\r
1108 // Arrive at begin of the menu list.\r
1109 //\r
1110 if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
1111 Distance = -1;\r
1112 break;\r
1113 }\r
1114\r
7c6c064c 1115 Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
ab369468 1116 PreMenuOption = NextMenuOption;\r
7c6c064c
ED
1117 }\r
1118\r
1119 *CurrentPosition = &NextMenuOption->Link;\r
1120 return Distance;\r
1121}\r
1122\r
1123\r
1124/**\r
1125 Process option string for date/time opcode.\r
1126\r
1127 @param MenuOption Menu option point to date/time.\r
1128 @param OptionString Option string input for process.\r
d1102dba 1129 @param AddOptCol Whether need to update MenuOption->OptCol.\r
7c6c064c
ED
1130\r
1131**/\r
d1102dba 1132VOID\r
7c6c064c
ED
1133ProcessStringForDateTime (\r
1134 UI_MENU_OPTION *MenuOption,\r
1135 CHAR16 *OptionString,\r
1136 BOOLEAN AddOptCol\r
1137 )\r
1138{\r
1139 UINTN Index;\r
1140 UINTN Count;\r
1141 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
1142 EFI_IFR_DATE *Date;\r
1143 EFI_IFR_TIME *Time;\r
1144\r
1145 ASSERT (MenuOption != NULL && OptionString != NULL);\r
d1102dba 1146\r
7c6c064c
ED
1147 Statement = MenuOption->ThisTag;\r
1148 Date = NULL;\r
1149 Time = NULL;\r
1150 if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
1151 Date = (EFI_IFR_DATE *) Statement->OpCode;\r
1152 } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
1153 Time = (EFI_IFR_TIME *) Statement->OpCode;\r
1154 }\r
d1102dba 1155\r
7c6c064c
ED
1156 //\r
1157 // If leading spaces on OptionString - remove the spaces\r
1158 //\r
1159 for (Index = 0; OptionString[Index] == L' '; Index++) {\r
1160 //\r
1161 // Base on the blockspace to get the option column info.\r
1162 //\r
1163 if (AddOptCol) {\r
1164 MenuOption->OptCol++;\r
1165 }\r
1166 }\r
d1102dba 1167\r
7c6c064c
ED
1168 for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
1169 OptionString[Count] = OptionString[Index];\r
1170 Count++;\r
1171 }\r
1172 OptionString[Count] = CHAR_NULL;\r
d1102dba 1173\r
7c6c064c
ED
1174 //\r
1175 // Enable to suppress field in the opcode base on the flag.\r
1176 //\r
1177 if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
1178 //\r
1179 // OptionString format is: <**: **: ****>\r
1180 // |month|day|year|\r
1181 // 4 3 5\r
1182 //\r
1183 if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
1184 //\r
d1102dba 1185 // At this point, only "<**:" in the optionstring.\r
7c6c064c
ED
1186 // Clean the day's ** field, after clean, the format is "< :"\r
1187 //\r
1188 SetUnicodeMem (&OptionString[1], 2, L' ');\r
1189 } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
1190 //\r
d1102dba 1191 // At this point, only "**:" in the optionstring.\r
7c6c064c 1192 // Clean the month's "**" field, after clean, the format is " :"\r
d1102dba 1193 //\r
7c6c064c
ED
1194 SetUnicodeMem (&OptionString[0], 2, L' ');\r
1195 } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
1196 //\r
d1102dba 1197 // At this point, only "****>" in the optionstring.\r
7c6c064c 1198 // Clean the year's "****" field, after clean, the format is " >"\r
d1102dba 1199 //\r
7c6c064c
ED
1200 SetUnicodeMem (&OptionString[0], 4, L' ');\r
1201 }\r
1202 } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
1203 //\r
1204 // OptionString format is: <**: **: **>\r
1205 // |hour|minute|second|\r
1206 // 4 3 3\r
1207 //\r
1208 if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
1209 //\r
d1102dba 1210 // At this point, only "<**:" in the optionstring.\r
7c6c064c
ED
1211 // Clean the hour's ** field, after clean, the format is "< :"\r
1212 //\r
1213 SetUnicodeMem (&OptionString[1], 2, L' ');\r
1214 } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
1215 //\r
d1102dba 1216 // At this point, only "**:" in the optionstring.\r
7c6c064c 1217 // Clean the minute's "**" field, after clean, the format is " :"\r
d1102dba 1218 //\r
7c6c064c
ED
1219 SetUnicodeMem (&OptionString[0], 2, L' ');\r
1220 } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
1221 //\r
d1102dba 1222 // At this point, only "**>" in the optionstring.\r
7c6c064c 1223 // Clean the second's "**" field, after clean, the format is " >"\r
d1102dba 1224 //\r
7c6c064c
ED
1225 SetUnicodeMem (&OptionString[0], 2, L' ');\r
1226 }\r
1227 }\r
1228}\r
1229\r
1230\r
1231/**\r
1232 Adjust Data and Time position accordingly.\r
1233 Data format : [01/02/2004] [11:22:33]\r
1234 Line number : 0 0 1 0 0 1\r
1235\r
1236 This is an internal function.\r
1237\r
1238 @param DirectionUp the up or down direction. False is down. True is\r
1239 up.\r
1240 @param CurrentPosition Current position. On return: Point to the last\r
1241 Option (Year or Second) if up; Point to the first\r
1242 Option (Month or Hour) if down.\r
1243\r
1244 @return Return line number to pad. It is possible that we stand on a zero-advance\r
1245 @return data or time opcode, so pad one line when we judge if we are going to scroll outside.\r
1246\r
1247**/\r
1248UINTN\r
1249AdjustDateAndTimePosition (\r
1250 IN BOOLEAN DirectionUp,\r
1251 IN OUT LIST_ENTRY **CurrentPosition\r
1252 )\r
1253{\r
1254 UINTN Count;\r
1255 LIST_ENTRY *NewPosition;\r
1256 UI_MENU_OPTION *MenuOption;\r
1257 UINTN PadLineNumber;\r
1258\r
1259 PadLineNumber = 0;\r
1260 NewPosition = *CurrentPosition;\r
1261 MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
1262\r
1263 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||\r
1264 (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
1265 //\r
1266 // Calculate the distance from current position to the last Date/Time MenuOption\r
1267 //\r
1268 Count = 0;\r
1269 while (MenuOption->Skip == 0) {\r
1270 Count++;\r
1271 NewPosition = NewPosition->ForwardLink;\r
1272 MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
1273 PadLineNumber = 1;\r
1274 }\r
1275\r
1276 NewPosition = *CurrentPosition;\r
1277 if (DirectionUp) {\r
1278 //\r
1279 // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended\r
1280 // to be one that back to the previous set of MenuOptions, we need to advance to the first\r
1281 // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate\r
1282 // checking can be done.\r
1283 //\r
1284 while (Count++ < 2) {\r
1285 NewPosition = NewPosition->BackLink;\r
1286 }\r
1287 } else {\r
1288 //\r
1289 // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended\r
1290 // to be one that progresses to the next set of MenuOptions, we need to advance to the last\r
1291 // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate\r
1292 // checking can be done.\r
1293 //\r
1294 while (Count-- > 0) {\r
1295 NewPosition = NewPosition->ForwardLink;\r
1296 }\r
1297 }\r
1298\r
1299 *CurrentPosition = NewPosition;\r
1300 }\r
1301\r
1302 return PadLineNumber;\r
1303}\r
1304\r
1305/**\r
1306 Get step info from numeric opcode.\r
d1102dba 1307\r
7c6c064c
ED
1308 @param[in] OpCode The input numeric op code.\r
1309\r
1310 @return step info for this opcode.\r
1311**/\r
1312UINT64\r
1313GetFieldFromNum (\r
1314 IN EFI_IFR_OP_HEADER *OpCode\r
1315 )\r
1316{\r
1317 EFI_IFR_NUMERIC *NumericOp;\r
1318 UINT64 Step;\r
1319\r
1320 NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
d1102dba 1321\r
7c6c064c
ED
1322 switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
1323 case EFI_IFR_NUMERIC_SIZE_1:\r
1324 Step = NumericOp->data.u8.Step;\r
1325 break;\r
d1102dba 1326\r
7c6c064c
ED
1327 case EFI_IFR_NUMERIC_SIZE_2:\r
1328 Step = NumericOp->data.u16.Step;\r
1329 break;\r
d1102dba 1330\r
7c6c064c
ED
1331 case EFI_IFR_NUMERIC_SIZE_4:\r
1332 Step = NumericOp->data.u32.Step;\r
1333 break;\r
d1102dba 1334\r
7c6c064c
ED
1335 case EFI_IFR_NUMERIC_SIZE_8:\r
1336 Step = NumericOp->data.u64.Step;\r
1337 break;\r
d1102dba 1338\r
7c6c064c
ED
1339 default:\r
1340 Step = 0;\r
1341 break;\r
1342 }\r
1343\r
1344 return Step;\r
1345}\r
1346\r
1347/**\r
1348 Find the registered HotKey based on KeyData.\r
d1102dba 1349\r
7c6c064c
ED
1350 @param[in] KeyData A pointer to a buffer that describes the keystroke\r
1351 information for the hot key.\r
1352\r
1353 @return The registered HotKey context. If no found, NULL will return.\r
1354**/\r
1355BROWSER_HOT_KEY *\r
1356GetHotKeyFromRegisterList (\r
1357 IN EFI_INPUT_KEY *KeyData\r
1358 )\r
1359{\r
1360 LIST_ENTRY *Link;\r
1361 BROWSER_HOT_KEY *HotKey;\r
1362\r
1363 Link = GetFirstNode (&gFormData->HotKeyListHead);\r
1364 while (!IsNull (&gFormData->HotKeyListHead, Link)) {\r
1365 HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
d1102dba 1366\r
7c6c064c
ED
1367 if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
1368 return HotKey;\r
1369 }\r
1370\r
1371 Link = GetNextNode (&gFormData->HotKeyListHead, Link);\r
1372 }\r
d1102dba 1373\r
7c6c064c
ED
1374 return NULL;\r
1375}\r
1376\r
1377\r
1378/**\r
1379 Determine if the menu is the last menu that can be selected.\r
1380\r
1381 This is an internal function.\r
1382\r
1383 @param Direction The scroll direction. False is down. True is up.\r
1384 @param CurrentPos The current focus.\r
1385\r
1386 @return FALSE -- the menu isn't the last menu that can be selected.\r
1387 @return TRUE -- the menu is the last menu that can be selected.\r
1388\r
1389**/\r
1390BOOLEAN\r
1391ValueIsScroll (\r
1392 IN BOOLEAN Direction,\r
1393 IN LIST_ENTRY *CurrentPos\r
1394 )\r
1395{\r
1396 LIST_ENTRY *Temp;\r
1397\r
1398 Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
1399\r
1400 if (Temp == &gMenuOption) {\r
1401 return TRUE;\r
1402 }\r
1403\r
1404 return FALSE;\r
1405}\r
1406\r
1407/**\r
1408 Wait for a given event to fire, or for an optional timeout to expire.\r
1409\r
1410 @param Event The event to wait for\r
1411\r
1412 @retval UI_EVENT_TYPE The type of the event which is trigged.\r
1413\r
1414**/\r
1415UI_EVENT_TYPE\r
1416UiWaitForEvent (\r
1417 IN EFI_EVENT Event\r
1418 )\r
1419{\r
1420 EFI_STATUS Status;\r
1421 UINTN Index;\r
1422 UINTN EventNum;\r
1423 UINT64 Timeout;\r
1424 EFI_EVENT TimerEvent;\r
1425 EFI_EVENT WaitList[3];\r
1426 UI_EVENT_TYPE EventType;\r
1427\r
1428 TimerEvent = NULL;\r
1429 Timeout = FormExitTimeout(gFormData);\r
1430\r
1431 if (Timeout != 0) {\r
1432 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
1433\r
1434 //\r
1435 // Set the timer event\r
1436 //\r
1437 gBS->SetTimer (\r
1438 TimerEvent,\r
1439 TimerRelative,\r
1440 Timeout\r
1441 );\r
1442 }\r
d1102dba 1443\r
7c6c064c
ED
1444 WaitList[0] = Event;\r
1445 EventNum = 1;\r
1446 if (gFormData->FormRefreshEvent != NULL) {\r
1447 WaitList[EventNum] = gFormData->FormRefreshEvent;\r
1448 EventNum ++;\r
d1102dba 1449 }\r
7c6c064c
ED
1450\r
1451 if (Timeout != 0) {\r
1452 WaitList[EventNum] = TimerEvent;\r
1453 EventNum ++;\r
1454 }\r
1455\r
1456 Status = gBS->WaitForEvent (EventNum, WaitList, &Index);\r
1457 ASSERT_EFI_ERROR (Status);\r
1458\r
1459 switch (Index) {\r
1460 case 0:\r
1461 EventType = UIEventKey;\r
1462 break;\r
1463\r
1464 case 1:\r
1465 if (gFormData->FormRefreshEvent != NULL) {\r
1466 EventType = UIEventDriver;\r
1467 } else {\r
1468 ASSERT (Timeout != 0 && EventNum == 2);\r
1469 EventType = UIEventTimeOut;\r
1470 }\r
1471 break;\r
1472\r
1473 default:\r
1474 ASSERT (Index == 2 && EventNum == 3);\r
1475 EventType = UIEventTimeOut;\r
1476 break;\r
1477 }\r
1478\r
1479 if (Timeout != 0) {\r
1480 gBS->CloseEvent (TimerEvent);\r
1481 }\r
d1102dba 1482\r
7c6c064c
ED
1483 return EventType;\r
1484}\r
1485\r
1486/**\r
1487 Get question id info from the input opcode header.\r
1488\r
1489 @param OpCode The input opcode header pointer.\r
1490\r
1491 @retval The question id for this opcode.\r
1492\r
1493**/\r
1494EFI_QUESTION_ID\r
1495GetQuestionIdInfo (\r
1496 IN EFI_IFR_OP_HEADER *OpCode\r
1497 )\r
1498{\r
1499 EFI_IFR_QUESTION_HEADER *QuestionHeader;\r
1500\r
1501 if (OpCode->Length < sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER)) {\r
1502 return 0;\r
1503 }\r
1504\r
1505 QuestionHeader = (EFI_IFR_QUESTION_HEADER *)((UINT8 *) OpCode + sizeof(EFI_IFR_OP_HEADER));\r
1506\r
1507 return QuestionHeader->QuestionId;\r
1508}\r
1509\r
ab369468
ED
1510\r
1511/**\r
1512 Find the top of screen menu base on the current menu.\r
1513\r
1514 @param CurPos Current input menu.\r
1515 @param Rows Totol screen rows.\r
1516 @param SkipValue SkipValue for this new form.\r
1517\r
1518 @retval TopOfScreen Top of screen menu for the new form.\r
1519\r
1520**/\r
1521LIST_ENTRY *\r
1522FindTopOfScreenMenu (\r
1523 IN LIST_ENTRY *CurPos,\r
1524 IN UINTN Rows,\r
1525 OUT UINTN *SkipValue\r
1526 )\r
1527{\r
1528 LIST_ENTRY *Link;\r
1529 LIST_ENTRY *TopOfScreen;\r
1530 UI_MENU_OPTION *PreviousMenuOption;\r
1531\r
1532 Link = CurPos;\r
1533 PreviousMenuOption = NULL;\r
1534\r
1535 while (Link->BackLink != &gMenuOption) {\r
1536 Link = Link->BackLink;\r
1537 PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
1538 if (PreviousMenuOption->Row == 0) {\r
1539 UpdateOptionSkipLines (PreviousMenuOption);\r
1540 }\r
1541 if (Rows <= PreviousMenuOption->Skip) {\r
1542 break;\r
1543 }\r
1544 Rows = Rows - PreviousMenuOption->Skip;\r
1545 }\r
1546\r
1547 if (Link->BackLink == &gMenuOption) {\r
1548 TopOfScreen = gMenuOption.ForwardLink;\r
1549 if (PreviousMenuOption != NULL && Rows < PreviousMenuOption->Skip) {\r
1550 *SkipValue = PreviousMenuOption->Skip - Rows;\r
1551 } else {\r
1552 *SkipValue = 0;\r
1553 }\r
1554 } else {\r
1555 TopOfScreen = Link;\r
1556 *SkipValue = PreviousMenuOption->Skip - Rows;\r
1557 }\r
1558\r
1559 return TopOfScreen;\r
1560}\r
1561\r
42645c3d
ED
1562/**\r
1563 Get the index info for this opcode.\r
1564\r
1565 @param OpCode The input opcode for the statement.\r
1566\r
1567 @retval The index of this statement.\r
1568\r
1569**/\r
1570UINTN\r
1571GetIndexInfoForOpcode (\r
1572 IN EFI_IFR_OP_HEADER *OpCode\r
1573 )\r
1574{\r
1575 LIST_ENTRY *NewPos;\r
1576 UI_MENU_OPTION *MenuOption;\r
1577 UINTN Index;\r
1578\r
1579 NewPos = gMenuOption.ForwardLink;\r
1580 Index = 0;\r
1581\r
1582 for (NewPos = gMenuOption.ForwardLink; NewPos != &gMenuOption; NewPos = NewPos->ForwardLink){\r
1583 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1584\r
1585 if (CompareMem (MenuOption->ThisTag->OpCode, OpCode, OpCode->Length) == 0) {\r
1586 if (MenuOption->ThisTag->OpCode == OpCode) {\r
1587 return Index;\r
1588 }\r
1589\r
1590 Index ++;\r
1591 }\r
1592 }\r
1593\r
1594 return Index;\r
1595}\r
1596\r
1597/**\r
1598 Is this the saved highlight statement.\r
1599\r
1600 @param HighLightedStatement The input highlight statement.\r
1601\r
1602 @retval TRUE This is the highlight statement.\r
1603 @retval FALSE This is not the highlight statement.\r
1604\r
1605**/\r
d1102dba 1606BOOLEAN\r
42645c3d
ED
1607IsSavedHighlightStatement (\r
1608 IN FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement\r
1609 )\r
1610{\r
1611 if ((gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle) &&\r
1612 (gFormData->FormId == gHighligthMenuInfo.FormId)) {\r
1613 if (gHighligthMenuInfo.HLTQuestionId != 0) {\r
2e097165 1614 return (BOOLEAN) (gHighligthMenuInfo.HLTQuestionId == GetQuestionIdInfo (HighLightedStatement->OpCode));\r
42645c3d
ED
1615 } else {\r
1616 if (CompareMem (gHighligthMenuInfo.HLTOpCode, HighLightedStatement->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) {\r
1617 if (gHighligthMenuInfo.HLTIndex == 0 || gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode(HighLightedStatement->OpCode)) {\r
1618 return TRUE;\r
1619 } else {\r
1620 return FALSE;\r
1621 }\r
1622 }\r
1623 }\r
1624 }\r
1625\r
1626 return FALSE;\r
1627}\r
1628\r
1629/**\r
1630 Is this the highlight menu.\r
1631\r
1632 @param MenuOption The input Menu option.\r
1633\r
1634 @retval TRUE This is the highlight menu option.\r
1635 @retval FALSE This is not the highlight menu option.\r
1636\r
1637**/\r
1638BOOLEAN\r
1639IsHighLightMenuOption (\r
1640 IN UI_MENU_OPTION *MenuOption\r
1641 )\r
1642{\r
1643 if (gHighligthMenuInfo.HLTQuestionId != 0) {\r
1644 if (GetQuestionIdInfo(MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.HLTQuestionId) {\r
2e097165 1645 return (BOOLEAN) (MenuOption->Sequence == gHighligthMenuInfo.HLTSequence);\r
42645c3d
ED
1646 }\r
1647 } else {\r
1648 if(CompareMem (gHighligthMenuInfo.HLTOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.HLTOpCode->Length) == 0) {\r
1649 if (gHighligthMenuInfo.HLTIndex == 0 || gHighligthMenuInfo.HLTIndex == GetIndexInfoForOpcode(MenuOption->ThisTag->OpCode)) {\r
2e097165 1650 return (BOOLEAN) (MenuOption->Sequence == gHighligthMenuInfo.HLTSequence);\r
42645c3d
ED
1651 } else {\r
1652 return FALSE;\r
1653 }\r
1654 }\r
1655 }\r
1656\r
1657 return FALSE;\r
1658}\r
1659\r
1660/**\r
1661 Find the highlight menu.\r
1662\r
1663 If the input is NULL, base on the record highlight info in\r
1664 gHighligthMenuInfo to find the last highlight menu.\r
1665\r
1666 @param HighLightedStatement The input highlight statement.\r
1667\r
1668 @retval The highlight menu index.\r
1669\r
1670**/\r
1671LIST_ENTRY *\r
1672FindHighLightMenuOption (\r
1673 IN FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement\r
1674 )\r
1675{\r
1676 LIST_ENTRY *NewPos;\r
1677 UI_MENU_OPTION *MenuOption;\r
1678\r
1679 NewPos = gMenuOption.ForwardLink;\r
1680 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1681\r
1682 if (HighLightedStatement != NULL) {\r
1683 while (MenuOption->ThisTag != HighLightedStatement) {\r
1684 NewPos = NewPos->ForwardLink;\r
1685 if (NewPos == &gMenuOption) {\r
1686 //\r
1687 // Not Found it, break\r
1688 //\r
1689 break;\r
1690 }\r
1691 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1692 }\r
1693\r
1694 //\r
1695 // Must find the highlight statement.\r
1696 //\r
1697 ASSERT (NewPos != &gMenuOption);\r
1698\r
1699 } else {\r
1700 while (!IsHighLightMenuOption (MenuOption)) {\r
1701 NewPos = NewPos->ForwardLink;\r
1702 if (NewPos == &gMenuOption) {\r
1703 //\r
1704 // Not Found it, break\r
1705 //\r
1706 break;\r
1707 }\r
1708 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1709 }\r
1710\r
1711 //\r
1712 // Highlight statement has disappear (suppressed/disableed)\r
1713 //\r
1714 if (NewPos == &gMenuOption) {\r
1715 NewPos = NULL;\r
1716 }\r
1717 }\r
1718\r
1719 return NewPos;\r
1720}\r
1721\r
1722/**\r
1723 Is this the Top of screen menu.\r
1724\r
1725 @param MenuOption The input Menu option.\r
1726\r
1727 @retval TRUE This is the Top of screen menu option.\r
1728 @retval FALSE This is not the Top of screen menu option.\r
1729\r
1730**/\r
1731BOOLEAN\r
1732IsTopOfScreeMenuOption (\r
1733 IN UI_MENU_OPTION *MenuOption\r
1734 )\r
1735{\r
1736 if (gHighligthMenuInfo.TOSQuestionId != 0) {\r
2e097165 1737 return (BOOLEAN) (GetQuestionIdInfo(MenuOption->ThisTag->OpCode) == gHighligthMenuInfo.TOSQuestionId);\r
d1102dba 1738 }\r
42645c3d
ED
1739\r
1740 if(CompareMem (gHighligthMenuInfo.TOSOpCode, MenuOption->ThisTag->OpCode, gHighligthMenuInfo.TOSOpCode->Length) == 0) {\r
1741 if (gHighligthMenuInfo.TOSIndex == 0 || gHighligthMenuInfo.TOSIndex == GetIndexInfoForOpcode(MenuOption->ThisTag->OpCode)) {\r
1742 return TRUE;\r
1743 } else {\r
1744 return FALSE;\r
1745 }\r
1746 }\r
1747\r
1748 return FALSE;\r
1749}\r
1750\r
1751/**\r
ef3d1df7 1752 Calculate the distance between two menus and include the skip value of StartMenu.\r
42645c3d 1753\r
ef3d1df7
DB
1754 @param StartMenu The link_entry pointer to start menu.\r
1755 @param EndMenu The link_entry pointer to end menu.\r
42645c3d 1756\r
ef3d1df7
DB
1757**/\r
1758UINTN\r
1759GetDistanceBetweenMenus(\r
1760 IN LIST_ENTRY *StartMenu,\r
1761 IN LIST_ENTRY *EndMenu\r
1762)\r
1763{\r
1764 LIST_ENTRY *Link;\r
1765 UI_MENU_OPTION *MenuOption;\r
1766 UINTN Distance;\r
42645c3d 1767\r
ef3d1df7
DB
1768 Distance = 0;\r
1769\r
1770 Link = StartMenu;\r
1771 while (Link != EndMenu) {\r
1772 MenuOption = MENU_OPTION_FROM_LINK (Link);\r
1773 if (MenuOption->Row == 0) {\r
1774 UpdateOptionSkipLines (MenuOption);\r
1775 }\r
1776 Distance += MenuOption->Skip;\r
1777 Link = Link->BackLink;\r
1778 }\r
1779 return Distance;\r
1780}\r
1781\r
1782/**\r
1783 Find the top of screen menu base on the previous record menu info.\r
1784\r
1785 @param HighLightMenu The link_entry pointer to highlight menu.\r
1786\r
1787 @retval Return the the link_entry pointer top of screen menu.\r
42645c3d
ED
1788\r
1789**/\r
1790LIST_ENTRY *\r
1791FindTopOfScreenMenuOption (\r
ef3d1df7
DB
1792 IN LIST_ENTRY *HighLightMenu\r
1793 )\r
42645c3d
ED
1794{\r
1795 LIST_ENTRY *NewPos;\r
1796 UI_MENU_OPTION *MenuOption;\r
ef3d1df7
DB
1797 UINTN TopRow;\r
1798 UINTN BottomRow;\r
1799\r
1800 TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
1801 BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
42645c3d
ED
1802\r
1803 NewPos = gMenuOption.ForwardLink;\r
1804 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1805\r
1806 while (!IsTopOfScreeMenuOption(MenuOption)) {\r
1807 NewPos = NewPos->ForwardLink;\r
1808 if (NewPos == &gMenuOption) {\r
1809 //\r
1810 // Not Found it, break\r
1811 //\r
1812 break;\r
1813 }\r
1814 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1815 }\r
1816\r
1817 //\r
1818 // Last time top of screen menu has disappeared.\r
1819 //\r
1820 if (NewPos == &gMenuOption) {\r
ef3d1df7
DB
1821 return NULL;\r
1822 }\r
1823 //\r
1824 // Check whether highlight menu and top of screen menu can be shown within one page,\r
1825 // if can't, return NULL to re-calcaulate the top of scrren menu. Because some new menus\r
1826 // may be dynamically inserted between highlightmenu and previous top of screen menu,\r
1827 // So previous record top of screen menu is not appropriate for current display.\r
1828 //\r
1829 if (GetDistanceBetweenMenus (HighLightMenu, NewPos) + 1 > BottomRow - TopRow) {\r
1830 return NULL;\r
42645c3d
ED
1831 }\r
1832\r
1833 return NewPos;\r
1834}\r
1835\r
7c6c064c
ED
1836/**\r
1837 Find the first menu which will be show at the top.\r
1838\r
1839 @param FormData The data info for this form.\r
1840 @param TopOfScreen The link_entry pointer to top menu.\r
1841 @param HighlightMenu The menu which will be highlight.\r
1842 @param SkipValue The skip value for the top menu.\r
1843\r
1844**/\r
1845VOID\r
1846FindTopMenu (\r
1847 IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
1848 OUT LIST_ENTRY **TopOfScreen,\r
1849 OUT LIST_ENTRY **HighlightMenu,\r
ab369468 1850 OUT UINTN *SkipValue\r
7c6c064c
ED
1851 )\r
1852{\r
7c6c064c
ED
1853 UINTN TopRow;\r
1854 UINTN BottomRow;\r
42645c3d 1855 UI_MENU_OPTION *MenuOption;\r
ab369468 1856 UINTN TmpValue;\r
7c6c064c
ED
1857\r
1858 TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
1859 BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
b2f35637
DB
1860 //\r
1861 // When option mismatch happens,there exist two cases,one is reenter the form, just like the if case below,\r
1862 // and the other is exit current form and enter last form, it can be covered by the else case.\r
1863 //\r
1864 if (gMisMatch && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle && gFormData->FormId == gHighligthMenuInfo.FormId) {\r
42645c3d 1865 //\r
d1102dba 1866 // Reenter caused by option mismatch or auto exit caused by refresh form(refresh interval/guid),\r
42645c3d
ED
1867 // base on the record highlight info to find the highlight menu.\r
1868 //\r
7c6c064c 1869\r
42645c3d
ED
1870 *HighlightMenu = FindHighLightMenuOption(NULL);\r
1871 if (*HighlightMenu != NULL) {\r
7c6c064c 1872 //\r
42645c3d 1873 // Update skip info for this highlight menu.\r
7c6c064c 1874 //\r
42645c3d
ED
1875 MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
1876 UpdateOptionSkipLines (MenuOption);\r
7c6c064c 1877\r
42645c3d
ED
1878 //\r
1879 // Found the last time highlight menu.\r
1880 //\r
ef3d1df7 1881 *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu);\r
42645c3d
ED
1882 if (*TopOfScreen != NULL) {\r
1883 //\r
1884 // Found the last time selectable top of screen menu.\r
1885 //\r
1886 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
1887 MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);\r
1888 UpdateOptionSkipLines (MenuOption);\r
7c6c064c 1889\r
42645c3d
ED
1890 *SkipValue = gHighligthMenuInfo.SkipValue;\r
1891 } else {\r
336c8e11 1892 //\r
42645c3d
ED
1893 // Not found last time top of screen menu, so base on current highlight menu\r
1894 // to find the new top of screen menu.\r
1895 // Make the current highlight menu at the bottom of the form to calculate the\r
1896 // top of screen menu.\r
336c8e11 1897 //\r
42645c3d
ED
1898 if (MenuOption->Skip >= BottomRow - TopRow) {\r
1899 *TopOfScreen = *HighlightMenu;\r
1900 TmpValue = 0;\r
1901 } else {\r
1902 *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
1903 }\r
1904\r
1905 *SkipValue = TmpValue;\r
336c8e11 1906 }\r
42645c3d
ED
1907 } else {\r
1908 //\r
0a18956d 1909 // Last time highlight menu has disappear, find the first highlightable menu as the default one.\r
42645c3d
ED
1910 //\r
1911 *HighlightMenu = gMenuOption.ForwardLink;\r
1912 if (!IsListEmpty (&gMenuOption)) {\r
1913 MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
1914 }\r
1915 *TopOfScreen = gMenuOption.ForwardLink;\r
1916 *SkipValue = 0;\r
1917 }\r
1918\r
42645c3d
ED
1919 } else if (FormData->HighLightedStatement != NULL) {\r
1920 if (IsSavedHighlightStatement (FormData->HighLightedStatement)) {\r
1921 //\r
1922 // Input highlight menu is same as last time highlight menu.\r
1923 // Base on last time highlight menu to set the top of screen menu and highlight menu.\r
1924 //\r
1925 *HighlightMenu = FindHighLightMenuOption(NULL);\r
1926 ASSERT (*HighlightMenu != NULL);\r
1927\r
1928 //\r
1929 // Update skip info for this highlight menu.\r
1930 //\r
1931 MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
1932 UpdateOptionSkipLines (MenuOption);\r
d1102dba 1933\r
ef3d1df7 1934 *TopOfScreen = FindTopOfScreenMenuOption(*HighlightMenu);\r
42645c3d 1935 if (*TopOfScreen == NULL) {\r
336c8e11 1936 //\r
42645c3d
ED
1937 // Not found last time top of screen menu, so base on current highlight menu\r
1938 // to find the new top of screen menu.\r
1939 // Make the current highlight menu at the bottom of the form to calculate the\r
1940 // top of screen menu.\r
336c8e11 1941 //\r
42645c3d
ED
1942 if (MenuOption->Skip >= BottomRow - TopRow) {\r
1943 *TopOfScreen = *HighlightMenu;\r
1944 TmpValue = 0;\r
1945 } else {\r
1946 *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
1947 }\r
1948\r
1949 *SkipValue = TmpValue;\r
1950 } else {\r
1951 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
1952 MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);\r
1953 UpdateOptionSkipLines (MenuOption);\r
1954\r
1955 *SkipValue = gHighligthMenuInfo.SkipValue;\r
336c8e11 1956 }\r
42645c3d
ED
1957 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
1958 } else {\r
1959 //\r
1960 // Input highlight menu is not save as last time highlight menu.\r
1961 //\r
1962 *HighlightMenu = FindHighLightMenuOption(FormData->HighLightedStatement);\r
1963 MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
1964 UpdateOptionSkipLines (MenuOption);\r
7c6c064c 1965\r
42645c3d
ED
1966 //\r
1967 // Make the current highlight menu at the bottom of the form to calculate the\r
1968 // top of screen menu.\r
1969 //\r
1970 if (MenuOption->Skip >= BottomRow - TopRow) {\r
1971 *TopOfScreen = *HighlightMenu;\r
1972 TmpValue = 0;\r
1973 } else {\r
1974 *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
1975 }\r
1976\r
1977 *SkipValue = TmpValue;\r
1978 }\r
1979 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
7c6c064c 1980 } else {\r
42645c3d
ED
1981 //\r
1982 // If not has input highlight statement, just return the first one in this form.\r
1983 //\r
1984 *TopOfScreen = gMenuOption.ForwardLink;\r
1985 *HighlightMenu = gMenuOption.ForwardLink;\r
1986 if (!IsListEmpty (&gMenuOption)) {\r
1987 MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
1988 }\r
1989 *SkipValue = 0;\r
7c6c064c 1990 }\r
ab2cf8ea 1991\r
b2f35637
DB
1992 gMisMatch = FALSE;\r
1993\r
ab2cf8ea
ED
1994 //\r
1995 // First enter to show the menu, update highlight info.\r
1996 //\r
1997 UpdateHighlightMenuInfo (*HighlightMenu, *TopOfScreen, *SkipValue);\r
7c6c064c
ED
1998}\r
1999\r
af047db7 2000/**\r
42645c3d 2001 Record the highlight menu and top of screen menu info.\r
af047db7 2002\r
42645c3d
ED
2003 @param Highlight The menu opton which is highlight.\r
2004 @param TopOfScreen The menu opton which is at the top of the form.\r
2005 @param SkipValue The skip line info for the top of screen menu.\r
af047db7
ED
2006\r
2007**/\r
2008VOID\r
2009UpdateHighlightMenuInfo (\r
42645c3d
ED
2010 IN LIST_ENTRY *Highlight,\r
2011 IN LIST_ENTRY *TopOfScreen,\r
2012 IN UINTN SkipValue\r
af047db7
ED
2013 )\r
2014{\r
42645c3d 2015 UI_MENU_OPTION *MenuOption;\r
af047db7
ED
2016 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
2017\r
42645c3d
ED
2018 gHighligthMenuInfo.HiiHandle = gFormData->HiiHandle;\r
2019 gHighligthMenuInfo.FormId = gFormData->FormId;\r
2020 gHighligthMenuInfo.SkipValue = (UINT16)SkipValue;\r
af047db7 2021\r
42645c3d
ED
2022 if (!IsListEmpty (&gMenuOption)) {\r
2023 MenuOption = MENU_OPTION_FROM_LINK (Highlight);\r
2024 Statement = MenuOption->ThisTag;\r
af047db7 2025\r
42645c3d 2026 gUserInput->SelectedStatement = Statement;\r
336c8e11 2027\r
42645c3d
ED
2028 gHighligthMenuInfo.HLTSequence = MenuOption->Sequence;\r
2029 gHighligthMenuInfo.HLTQuestionId = GetQuestionIdInfo(Statement->OpCode);\r
2030 if (gHighligthMenuInfo.HLTQuestionId == 0) {\r
2031 //\r
2032 // if question id == 0, save the opcode buffer..\r
2033 //\r
2034 if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
2035 FreePool (gHighligthMenuInfo.HLTOpCode);\r
336c8e11 2036 }\r
42645c3d
ED
2037 gHighligthMenuInfo.HLTOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
2038 ASSERT (gHighligthMenuInfo.HLTOpCode != NULL);\r
2039\r
2040 gHighligthMenuInfo.HLTIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
2041 }\r
2042\r
2043 MenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
2044 Statement = MenuOption->ThisTag;\r
2045\r
2046 gHighligthMenuInfo.TOSQuestionId = GetQuestionIdInfo(Statement->OpCode);\r
2047 if (gHighligthMenuInfo.TOSQuestionId == 0) {\r
2048 //\r
2049 // if question id == 0, save the opcode buffer..\r
2050 //\r
2051 if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
2052 FreePool (gHighligthMenuInfo.TOSOpCode);\r
2053 }\r
2054 gHighligthMenuInfo.TOSOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
2055 ASSERT (gHighligthMenuInfo.TOSOpCode != NULL);\r
2056\r
2057 gHighligthMenuInfo.TOSIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
336c8e11 2058 }\r
af047db7 2059 } else {\r
42645c3d
ED
2060 gUserInput->SelectedStatement = NULL;\r
2061\r
2062 gHighligthMenuInfo.HLTSequence = 0;\r
2063 gHighligthMenuInfo.HLTQuestionId = 0;\r
2064 if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
2065 FreePool (gHighligthMenuInfo.HLTOpCode);\r
336c8e11 2066 }\r
42645c3d
ED
2067 gHighligthMenuInfo.HLTOpCode = NULL;\r
2068 gHighligthMenuInfo.HLTIndex = 0;\r
af047db7 2069\r
42645c3d
ED
2070 gHighligthMenuInfo.TOSQuestionId = 0;\r
2071 if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
2072 FreePool (gHighligthMenuInfo.TOSOpCode);\r
2073 }\r
2074 gHighligthMenuInfo.TOSOpCode = NULL;\r
2075 gHighligthMenuInfo.TOSIndex = 0;\r
2076 }\r
af047db7
ED
2077}\r
2078\r
2079/**\r
2080 Update attribut for this menu.\r
2081\r
2082 @param MenuOption The menu opton which this attribut used to.\r
2083 @param Highlight Whether this menu will be highlight.\r
2084\r
2085**/\r
2086VOID\r
2087SetDisplayAttribute (\r
2088 IN UI_MENU_OPTION *MenuOption,\r
2089 IN BOOLEAN Highlight\r
2090 )\r
2091{\r
2092 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
d1102dba 2093\r
af047db7
ED
2094 Statement = MenuOption->ThisTag;\r
2095\r
2096 if (Highlight) {\r
2097 gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
2098 return;\r
2099 }\r
2100\r
2101 if (MenuOption->GrayOut) {\r
2102 gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
2103 } else {\r
2104 if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
2105 gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
2106 } else {\r
2107 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
2108 }\r
2109 }\r
2110}\r
2111\r
2112/**\r
2113 Print string for this menu option.\r
2114\r
2115 @param MenuOption The menu opton which this attribut used to.\r
2116 @param Col The column that this string will be print at.\r
2117 @param Row The row that this string will be print at.\r
2118 @param String The string which need to print.\r
2119 @param Width The width need to print, if string is less than the\r
2120 width, the block space will be used.\r
2121 @param Highlight Whether this menu will be highlight.\r
2122\r
2123**/\r
2124VOID\r
2125DisplayMenuString (\r
2126 IN UI_MENU_OPTION *MenuOption,\r
2127 IN UINTN Col,\r
2128 IN UINTN Row,\r
2129 IN CHAR16 *String,\r
2130 IN UINTN Width,\r
2131 IN BOOLEAN Highlight\r
2132 )\r
2133{\r
2134 UINTN Length;\r
2135\r
2136 //\r
2137 // Print string with normal color.\r
2138 //\r
2139 if (!Highlight) {\r
2140 PrintStringAtWithWidth (Col, Row, String, Width);\r
2141 return;\r
2142 }\r
d1102dba 2143\r
af047db7
ED
2144 //\r
2145 // Print the highlight menu string.\r
2146 // First print the highlight string.\r
d1102dba 2147 //\r
af047db7
ED
2148 SetDisplayAttribute(MenuOption, TRUE);\r
2149 Length = PrintStringAt (Col, Row, String);\r
2150\r
2151 //\r
2152 // Second, clean the empty after the string.\r
2153 //\r
2154 SetDisplayAttribute(MenuOption, FALSE);\r
2155 PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);\r
2156}\r
2157\r
28401a65
ED
2158/**\r
2159 Check whether this menu can has option string.\r
2160\r
2161 @param MenuOption The menu opton which this attribut used to.\r
2162\r
2163 @retval TRUE This menu option can have option string.\r
2164 @retval FALSE This menu option can't have option string.\r
2165\r
2166**/\r
d1102dba 2167BOOLEAN\r
28401a65
ED
2168HasOptionString (\r
2169 IN UI_MENU_OPTION *MenuOption\r
2170 )\r
2171{\r
2172 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
2173 CHAR16 *String;\r
2174 UINTN Size;\r
2175 EFI_IFR_TEXT *TestOp;\r
2176\r
2177 Size = 0;\r
2178 Statement = MenuOption->ThisTag;\r
2179\r
2180 //\r
2181 // See if the second text parameter is really NULL\r
2182 //\r
2183 if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
2184 TestOp = (EFI_IFR_TEXT *) Statement->OpCode;\r
2185 if (TestOp->TextTwo != 0) {\r
2186 String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);\r
2187 Size = StrLen (String);\r
2188 FreePool (String);\r
2189 }\r
2190 }\r
2191\r
2192 if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
2193 (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||\r
2194 (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||\r
2195 (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||\r
2196 (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||\r
2197 //\r
2198 // Allow a wide display if text op-code and no secondary text op-code\r
2199 //\r
2200 ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))\r
2201 ) {\r
2202\r
2203 return FALSE;\r
2204 }\r
2205\r
2206 return TRUE;\r
2207}\r
2208\r
23c7d425
ED
2209/**\r
2210 Double confirm with user about the action.\r
2211\r
2212 @param Action The user input action.\r
2213\r
2214 @retval TRUE User confirm with the input or not need user confirm.\r
2215 @retval FALSE User want ignore this input.\r
2216\r
2217**/\r
2218BOOLEAN\r
2219FxConfirmPopup (\r
2220 IN UINT32 Action\r
2221 )\r
2222{\r
2223 EFI_INPUT_KEY Key;\r
2224 CHAR16 *CfmStr;\r
2225 UINTN CfmStrLen;\r
2226 UINT32 CheckFlags;\r
2227 BOOLEAN RetVal;\r
2228 UINTN CatLen;\r
5ad66ec6 2229 UINTN MaxLen;\r
23c7d425
ED
2230\r
2231 CfmStrLen = 0;\r
2232 CatLen = StrLen (gConfirmMsgConnect);\r
2233\r
2234 //\r
2235 // Below action need extra popup dialog to confirm.\r
d1102dba
LG
2236 //\r
2237 CheckFlags = BROWSER_ACTION_DISCARD |\r
23c7d425
ED
2238 BROWSER_ACTION_DEFAULT |\r
2239 BROWSER_ACTION_SUBMIT |\r
2240 BROWSER_ACTION_RESET |\r
2241 BROWSER_ACTION_EXIT;\r
2242\r
2243 //\r
2244 // Not need to confirm with user, just return TRUE.\r
2245 //\r
2246 if ((Action & CheckFlags) == 0) {\r
2247 return TRUE;\r
2248 }\r
2249\r
2250 if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
2251 CfmStrLen += StrLen (gConfirmDiscardMsg);\r
d1102dba 2252 }\r
23c7d425
ED
2253\r
2254 if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
2255 if (CfmStrLen != 0) {\r
2256 CfmStrLen += CatLen;\r
d1102dba 2257 }\r
23c7d425
ED
2258\r
2259 CfmStrLen += StrLen (gConfirmDefaultMsg);\r
2260 }\r
2261\r
2262 if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
2263 if (CfmStrLen != 0) {\r
2264 CfmStrLen += CatLen;\r
d1102dba 2265 }\r
23c7d425
ED
2266\r
2267 CfmStrLen += StrLen (gConfirmSubmitMsg);\r
2268 }\r
2269\r
2270 if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
2271 if (CfmStrLen != 0) {\r
2272 CfmStrLen += CatLen;\r
d1102dba 2273 }\r
23c7d425
ED
2274\r
2275 CfmStrLen += StrLen (gConfirmResetMsg);\r
2276 }\r
2277\r
2278 if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
2279 if (CfmStrLen != 0) {\r
2280 CfmStrLen += CatLen;\r
d1102dba 2281 }\r
23c7d425
ED
2282\r
2283 CfmStrLen += StrLen (gConfirmExitMsg);\r
2284 }\r
2285\r
2286 //\r
2287 // Allocate buffer to save the string.\r
2288 // String + "?" + "\0"\r
2289 //\r
5ad66ec6
DB
2290 MaxLen = CfmStrLen + 1 + 1;\r
2291 CfmStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
23c7d425
ED
2292 ASSERT (CfmStr != NULL);\r
2293\r
2294 if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
5ad66ec6 2295 StrCpyS (CfmStr, MaxLen, gConfirmDiscardMsg);\r
23c7d425
ED
2296 }\r
2297\r
2298 if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
2299 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2300 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2301 StrCatS (CfmStr, MaxLen, gConfirmDefaultMsg2nd);\r
23c7d425 2302 } else {\r
5ad66ec6 2303 StrCpyS (CfmStr, MaxLen, gConfirmDefaultMsg);\r
23c7d425
ED
2304 }\r
2305 }\r
2306\r
2307 if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
2308 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2309 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2310 StrCatS (CfmStr, MaxLen, gConfirmSubmitMsg2nd);\r
23c7d425 2311 } else {\r
5ad66ec6 2312 StrCpyS (CfmStr, MaxLen, gConfirmSubmitMsg);\r
23c7d425
ED
2313 }\r
2314 }\r
2315\r
2316 if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
2317 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2318 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2319 StrCatS (CfmStr, MaxLen, gConfirmResetMsg2nd);\r
23c7d425 2320 } else {\r
5ad66ec6 2321 StrCpyS (CfmStr, MaxLen, gConfirmResetMsg);\r
23c7d425
ED
2322 }\r
2323 }\r
2324\r
2325 if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
2326 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2327 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2328 StrCatS (CfmStr, MaxLen, gConfirmExitMsg2nd);\r
23c7d425 2329 } else {\r
5ad66ec6 2330 StrCpyS (CfmStr, MaxLen, gConfirmExitMsg);\r
23c7d425
ED
2331 }\r
2332 }\r
2333\r
5ad66ec6 2334 StrCatS (CfmStr, MaxLen, gConfirmMsgEnd);\r
23c7d425
ED
2335\r
2336 do {\r
2337 CreateDialog (&Key, gEmptyString, CfmStr, gConfirmOpt, gEmptyString, NULL);\r
2338 } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
299c3aec
DB
2339 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptNo[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
2340 (Key.ScanCode != SCAN_ESC));\r
23c7d425
ED
2341\r
2342 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) {\r
2343 RetVal = TRUE;\r
2344 } else {\r
2345 RetVal = FALSE;\r
2346 }\r
2347\r
2348 FreePool (CfmStr);\r
2349\r
2350 return RetVal;\r
2351}\r
28401a65 2352\r
af047db7
ED
2353/**\r
2354 Print string for this menu option.\r
2355\r
2356 @param MenuOption The menu opton which this attribut used to.\r
2357 @param SkipWidth The skip width between the left to the start of the prompt.\r
2358 @param BeginCol The begin column for one menu.\r
d1102dba 2359 @param SkipLine The skip line for this menu.\r
af047db7
ED
2360 @param BottomRow The bottom row for this form.\r
2361 @param Highlight Whether this menu will be highlight.\r
f0c5095b 2362 @param UpdateCol Whether need to update the column info for Date/Time.\r
af047db7
ED
2363\r
2364 @retval EFI_SUCESSS Process the user selection success.\r
2365\r
2366**/\r
2367EFI_STATUS\r
2368DisplayOneMenu (\r
2369 IN UI_MENU_OPTION *MenuOption,\r
2370 IN UINTN SkipWidth,\r
2371 IN UINTN BeginCol,\r
2372 IN UINTN SkipLine,\r
2373 IN UINTN BottomRow,\r
f0c5095b
ED
2374 IN BOOLEAN Highlight,\r
2375 IN BOOLEAN UpdateCol\r
af047db7
ED
2376 )\r
2377{\r
2378 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
2379 UINTN Index;\r
2380 UINT16 Width;\r
2381 UINT16 PromptWidth;\r
2382 CHAR16 *StringPtr;\r
2383 CHAR16 *OptionString;\r
2384 CHAR16 *OutputString;\r
af047db7
ED
2385 UINT16 GlyphWidth;\r
2386 UINTN Temp;\r
2387 UINTN Temp2;\r
2388 UINTN Temp3;\r
2389 EFI_STATUS Status;\r
2390 UINTN Row;\r
8c9c60b6 2391 BOOLEAN IsProcessingFirstRow;\r
af047db7
ED
2392 UINTN Col;\r
2393 UINTN PromptLineNum;\r
28401a65 2394 UINTN OptionLineNum;\r
af047db7 2395 CHAR16 AdjustValue;\r
28401a65 2396 UINTN MaxRow;\r
af047db7
ED
2397\r
2398 Statement = MenuOption->ThisTag;\r
af047db7
ED
2399 Temp = SkipLine;\r
2400 Temp2 = SkipLine;\r
2401 Temp3 = SkipLine;\r
28401a65
ED
2402 AdjustValue = 0;\r
2403 PromptLineNum = 0;\r
2404 OptionLineNum = 0;\r
2405 MaxRow = 0;\r
8c9c60b6 2406 IsProcessingFirstRow = TRUE;\r
af047db7
ED
2407\r
2408 //\r
2409 // Set default color.\r
2410 //\r
2411 SetDisplayAttribute (MenuOption, FALSE);\r
2412\r
2413 //\r
2414 // 1. Paint the option string.\r
2415 //\r
2416 Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);\r
2417 if (EFI_ERROR (Status)) {\r
2418 return Status;\r
2419 }\r
2420\r
2421 if (OptionString != NULL) {\r
2422 if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
2423 //\r
2424 // Adjust option string for date/time opcode.\r
2425 //\r
f0c5095b 2426 ProcessStringForDateTime(MenuOption, OptionString, UpdateCol);\r
af047db7 2427 }\r
d1102dba 2428\r
af047db7 2429 Width = (UINT16) gOptionBlockWidth - 1;\r
28401a65 2430 Row = MenuOption->Row;\r
af047db7 2431 GlyphWidth = 1;\r
28401a65 2432 OptionLineNum = 0;\r
d1102dba 2433\r
af047db7
ED
2434 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
2435 if (((Temp2 == 0)) && (Row <= BottomRow)) {\r
2436 if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
2437 //\r
2438 // For date/time question, it has three menu options for this qustion.\r
2439 // The first/second menu options with the skip value is 0. the last one\r
2440 // with skip value is 1.\r
2441 //\r
2442 if (MenuOption->Skip != 0) {\r
2443 //\r
2444 // For date/ time, print the last past (year for date and second for time)\r
2445 // - 7 means skip [##/##/ for date and [##:##: for time.\r
2446 //\r
2447 DisplayMenuString (MenuOption,MenuOption->OptCol, Row, OutputString, Width + 1 - 7, Highlight);\r
2448 } else {\r
2449 //\r
2450 // For date/ time, print the first and second past (year for date and second for time)\r
d1102dba 2451 // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string,\r
f0c5095b
ED
2452 // so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it.\r
2453 DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString) - 1, Highlight);\r
af047db7
ED
2454 }\r
2455 } else {\r
2456 DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
2457 }\r
28401a65 2458 OptionLineNum++;\r
af047db7 2459 }\r
d1102dba 2460\r
af047db7
ED
2461 //\r
2462 // If there is more string to process print on the next row and increment the Skip value\r
2463 //\r
2464 if (StrLen (&OptionString[Index]) != 0) {\r
2465 if (Temp2 == 0) {\r
2466 Row++;\r
2467 //\r
2468 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
2469 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
2470 // some testing to ensure we are keeping this in-sync.\r
2471 //\r
2472 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
2473 //\r
28401a65 2474 if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
af047db7
ED
2475 MenuOption->Skip++;\r
2476 }\r
2477 }\r
2478 }\r
d1102dba 2479\r
af047db7
ED
2480 FreePool (OutputString);\r
2481 if (Temp2 != 0) {\r
2482 Temp2--;\r
2483 }\r
2484 }\r
d1102dba 2485\r
af047db7
ED
2486 Highlight = FALSE;\r
2487\r
2488 FreePool (OptionString);\r
2489 }\r
af047db7
ED
2490\r
2491 //\r
28401a65 2492 // 2. Paint the description.\r
af047db7 2493 //\r
6f05c023 2494 PromptWidth = GetWidth (MenuOption, &AdjustValue);\r
28401a65 2495 Row = MenuOption->Row;\r
af047db7
ED
2496 GlyphWidth = 1;\r
2497 PromptLineNum = 0;\r
2498\r
2499 if (MenuOption->Description == NULL || MenuOption->Description[0] == '\0') {\r
28401a65
ED
2500 PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);\r
2501 PromptLineNum++;\r
af047db7 2502 } else {\r
d1102dba
LG
2503 for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
2504 if ((Temp == 0) && (Row <= BottomRow)) {\r
af047db7 2505 //\r
d1102dba 2506 // 1.Clean the start LEFT_SKIPPED_COLUMNS\r
af047db7
ED
2507 //\r
2508 PrintStringAtWithWidth (BeginCol, Row, L"", SkipWidth);\r
d1102dba 2509\r
8c9c60b6 2510 if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2 && IsProcessingFirstRow) {\r
af047db7
ED
2511 //\r
2512 // Print Arrow for Goto button.\r
2513 //\r
2514 PrintCharAt (\r
2515 MenuOption->Col - 2,\r
2516 Row,\r
2517 GEOMETRICSHAPE_RIGHT_TRIANGLE\r
2518 );\r
8c9c60b6 2519 IsProcessingFirstRow = FALSE;\r
af047db7
ED
2520 }\r
2521 DisplayMenuString (MenuOption, MenuOption->Col, Row, OutputString, PromptWidth + AdjustValue, Highlight);\r
2522 PromptLineNum ++;\r
2523 }\r
2524 //\r
2525 // If there is more string to process print on the next row and increment the Skip value\r
2526 //\r
2527 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
2528 if (Temp == 0) {\r
2529 Row++;\r
2530 }\r
2531 }\r
2532\r
2533 FreePool (OutputString);\r
2534 if (Temp != 0) {\r
2535 Temp--;\r
2536 }\r
2537 }\r
2538\r
2539 Highlight = FALSE;\r
af047db7 2540 }\r
af047db7
ED
2541\r
2542\r
2543 //\r
28401a65 2544 // 3. If this is a text op with secondary text information\r
af047db7
ED
2545 //\r
2546 if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
2547 StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
d1102dba 2548\r
af047db7 2549 Width = (UINT16) gOptionBlockWidth - 1;\r
28401a65 2550 Row = MenuOption->Row;\r
af047db7 2551 GlyphWidth = 1;\r
28401a65 2552 OptionLineNum = 0;\r
af047db7 2553\r
d1102dba 2554 for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
af047db7
ED
2555 if ((Temp3 == 0) && (Row <= BottomRow)) {\r
2556 DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
28401a65 2557 OptionLineNum++;\r
af047db7
ED
2558 }\r
2559 //\r
2560 // If there is more string to process print on the next row and increment the Skip value\r
2561 //\r
2562 if (StrLen (&StringPtr[Index]) != 0) {\r
2563 if (Temp3 == 0) {\r
2564 Row++;\r
a6a2a956
ED
2565 //\r
2566 // If the rows for text two is greater than or equal to the skip value, increase the skip value\r
2567 //\r
2568 if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
2569 MenuOption->Skip++;\r
2570 }\r
af047db7
ED
2571 }\r
2572 }\r
d1102dba 2573\r
af047db7
ED
2574 FreePool (OutputString);\r
2575 if (Temp3 != 0) {\r
2576 Temp3--;\r
2577 }\r
2578 }\r
28401a65 2579\r
af047db7
ED
2580 FreePool (StringPtr);\r
2581 }\r
2582\r
28401a65
ED
2583 //\r
2584 // 4.Line number for Option string and prompt string are not equal.\r
2585 // Clean the column whose line number is less.\r
2586 //\r
2587 if (HasOptionString(MenuOption) && (OptionLineNum != PromptLineNum)) {\r
2588 Col = OptionLineNum < PromptLineNum ? MenuOption->OptCol : BeginCol;\r
2589 Row = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row;\r
2590 Width = (UINT16) (OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth);\r
2591 MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1;\r
d1102dba 2592\r
28401a65
ED
2593 while (Row <= MaxRow) {\r
2594 DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE);\r
2595 }\r
2596 }\r
2597\r
af047db7
ED
2598 return EFI_SUCCESS;\r
2599}\r
2600\r
7c6c064c
ED
2601/**\r
2602 Display menu and wait for user to select one menu option, then return it.\r
2603 If AutoBoot is enabled, then if user doesn't select any option,\r
2604 after period of time, it will automatically return the first menu option.\r
2605\r
2606 @param FormData The current form data info.\r
2607\r
2608 @retval EFI_SUCESSS Process the user selection success.\r
2609 @retval EFI_NOT_FOUND Process option string for orderedlist/Oneof fail.\r
2610\r
2611**/\r
2612EFI_STATUS\r
2613UiDisplayMenu (\r
2614 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
2615 )\r
2616{\r
ab369468 2617 UINTN SkipValue;\r
7c6c064c
ED
2618 INTN Difference;\r
2619 UINTN DistanceValue;\r
2620 UINTN Row;\r
2621 UINTN Col;\r
7c6c064c
ED
2622 UINTN Temp;\r
2623 UINTN Temp2;\r
7c6c064c
ED
2624 UINTN TopRow;\r
2625 UINTN BottomRow;\r
7c6c064c 2626 UINTN Index;\r
7c6c064c 2627 CHAR16 *StringPtr;\r
cc63add8
DB
2628 CHAR16 *StringRightPtr;\r
2629 CHAR16 *StringErrorPtr;\r
7c6c064c 2630 CHAR16 *OptionString;\r
7c6c064c
ED
2631 CHAR16 *HelpString;\r
2632 CHAR16 *HelpHeaderString;\r
2633 CHAR16 *HelpBottomString;\r
2634 BOOLEAN NewLine;\r
2635 BOOLEAN Repaint;\r
2636 BOOLEAN UpArrow;\r
2637 BOOLEAN DownArrow;\r
2638 EFI_STATUS Status;\r
2639 EFI_INPUT_KEY Key;\r
2640 LIST_ENTRY *Link;\r
2641 LIST_ENTRY *NewPos;\r
2642 LIST_ENTRY *TopOfScreen;\r
2643 LIST_ENTRY *SavedListEntry;\r
2644 UI_MENU_OPTION *MenuOption;\r
2645 UI_MENU_OPTION *NextMenuOption;\r
2646 UI_MENU_OPTION *SavedMenuOption;\r
7c6c064c
ED
2647 UI_CONTROL_FLAG ControlFlag;\r
2648 UI_SCREEN_OPERATION ScreenOperation;\r
7c6c064c 2649 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
7c6c064c
ED
2650 BROWSER_HOT_KEY *HotKey;\r
2651 UINTN HelpPageIndex;\r
2652 UINTN HelpPageCount;\r
2653 UINTN RowCount;\r
2654 UINTN HelpLine;\r
2655 UINTN HelpHeaderLine;\r
2656 UINTN HelpBottomLine;\r
2657 BOOLEAN MultiHelpPage;\r
7c6c064c
ED
2658 UINT16 EachLineWidth;\r
2659 UINT16 HeaderLineWidth;\r
2660 UINT16 BottomLineWidth;\r
2661 EFI_STRING_ID HelpInfo;\r
2662 UI_EVENT_TYPE EventType;\r
af047db7 2663 BOOLEAN SkipHighLight;\r
cc63add8 2664 EFI_HII_VALUE *StatementValue;\r
7c6c064c
ED
2665\r
2666 EventType = UIEventNone;\r
2667 Status = EFI_SUCCESS;\r
2668 HelpString = NULL;\r
2669 HelpHeaderString = NULL;\r
2670 HelpBottomString = NULL;\r
2671 OptionString = NULL;\r
2672 ScreenOperation = UiNoOperation;\r
2673 NewLine = TRUE;\r
7c6c064c
ED
2674 HelpPageCount = 0;\r
2675 HelpLine = 0;\r
2676 RowCount = 0;\r
2677 HelpBottomLine = 0;\r
2678 HelpHeaderLine = 0;\r
2679 HelpPageIndex = 0;\r
2680 MultiHelpPage = FALSE;\r
2681 EachLineWidth = 0;\r
2682 HeaderLineWidth = 0;\r
2683 BottomLineWidth = 0;\r
7c6c064c
ED
2684 UpArrow = FALSE;\r
2685 DownArrow = FALSE;\r
2686 SkipValue = 0;\r
af047db7 2687 SkipHighLight = FALSE;\r
7c6c064c
ED
2688\r
2689 NextMenuOption = NULL;\r
7c6c064c
ED
2690 SavedMenuOption = NULL;\r
2691 HotKey = NULL;\r
2692 Repaint = TRUE;\r
2693 MenuOption = NULL;\r
af047db7 2694 gModalSkipColumn = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6;\r
7c6c064c
ED
2695\r
2696 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
2697\r
7c6c064c
ED
2698 TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
2699 BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;\r
2700\r
2701 Row = TopRow;\r
2702 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
af047db7 2703 Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gModalSkipColumn;\r
7c6c064c
ED
2704 } else {\r
2705 Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS;\r
2706 }\r
2707\r
2708 FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue);\r
42645c3d
ED
2709 if (!IsListEmpty (&gMenuOption)) {\r
2710 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2711 gUserInput->SelectedStatement = NextMenuOption->ThisTag;\r
2712 }\r
7c6c064c
ED
2713\r
2714 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
2715\r
2716 ControlFlag = CfInitialization;\r
2717 while (TRUE) {\r
2718 switch (ControlFlag) {\r
2719 case CfInitialization:\r
d1102dba 2720 if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) ||\r
af047db7
ED
2721 (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))) {\r
2722 //\r
2723 // Clear Statement range if different formset is painted.\r
2724 //\r
2725 ClearLines (\r
2726 gStatementDimensions.LeftColumn,\r
2727 gStatementDimensions.RightColumn,\r
2728 TopRow - SCROLL_ARROW_HEIGHT,\r
2729 BottomRow + SCROLL_ARROW_HEIGHT,\r
2730 GetFieldTextColor ()\r
2731 );\r
7c6c064c 2732\r
7c6c064c 2733 }\r
af047db7 2734 ControlFlag = CfRepaint;\r
7c6c064c
ED
2735 break;\r
2736\r
2737 case CfRepaint:\r
2738 ControlFlag = CfRefreshHighLight;\r
2739\r
2740 if (Repaint) {\r
2741 //\r
2742 // Display menu\r
2743 //\r
2744 DownArrow = FALSE;\r
2745 UpArrow = FALSE;\r
2746 Row = TopRow;\r
2747\r
af047db7 2748 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
d1102dba 2749\r
7c6c064c 2750 //\r
af047db7 2751 // 1. Check whether need to print the arrow up.\r
7c6c064c 2752 //\r
af047db7
ED
2753 if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
2754 UpArrow = TRUE;\r
2755 }\r
af047db7 2756\r
ae4f5746
ED
2757 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
2758 PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);\r
2759 } else {\r
2760 PrintStringAtWithWidth(gStatementDimensions.LeftColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
2761 }\r
af047db7
ED
2762 if (UpArrow) {\r
2763 gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
2764 PrintCharAt (\r
2765 gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
7c6c064c 2766 TopRow - SCROLL_ARROW_HEIGHT,\r
af047db7 2767 ARROW_UP\r
7c6c064c 2768 );\r
af047db7 2769 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
7c6c064c
ED
2770 }\r
2771\r
2772 //\r
2773 // 2.Paint the menu.\r
2774 //\r
2775 for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {\r
2776 MenuOption = MENU_OPTION_FROM_LINK (Link);\r
2777 MenuOption->Row = Row;\r
2778 MenuOption->Col = Col;\r
2779 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
af047db7 2780 MenuOption->OptCol = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth + gModalSkipColumn;\r
7c6c064c 2781 } else {\r
af047db7 2782 MenuOption->OptCol = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth;\r
7c6c064c
ED
2783 }\r
2784\r
7c6c064c
ED
2785 if (MenuOption->NestInStatement) {\r
2786 MenuOption->Col += SUBTITLE_INDENT;\r
2787 }\r
2788\r
7c6c064c 2789 //\r
af047db7 2790 // Save the highlight menu, will be used in CfRefreshHighLight case.\r
7c6c064c 2791 //\r
af047db7
ED
2792 if (Link == NewPos) {\r
2793 SavedMenuOption = MenuOption;\r
2794 SkipHighLight = TRUE;\r
7c6c064c 2795 }\r
ae4f5746
ED
2796\r
2797 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
d1102dba 2798 Status = DisplayOneMenu (MenuOption,\r
6f05c023 2799 MenuOption->Col - gStatementDimensions.LeftColumn,\r
d1102dba
LG
2800 gStatementDimensions.LeftColumn + gModalSkipColumn,\r
2801 Link == TopOfScreen ? SkipValue : 0,\r
ae4f5746 2802 BottomRow,\r
f0c5095b
ED
2803 (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
2804 TRUE\r
ae4f5746
ED
2805 );\r
2806 } else {\r
d1102dba 2807 Status = DisplayOneMenu (MenuOption,\r
6f05c023 2808 MenuOption->Col - gStatementDimensions.LeftColumn,\r
d1102dba
LG
2809 gStatementDimensions.LeftColumn,\r
2810 Link == TopOfScreen ? SkipValue : 0,\r
ae4f5746 2811 BottomRow,\r
f0c5095b
ED
2812 (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
2813 TRUE\r
2814 );\r
ae4f5746 2815 }\r
7c6c064c 2816\r
72f2eca2 2817 if (EFI_ERROR (Status)) {\r
42645c3d
ED
2818 if (gMisMatch) {\r
2819 return EFI_SUCCESS;\r
2820 } else {\r
2821 return Status;\r
2822 }\r
72f2eca2 2823 }\r
7c6c064c
ED
2824 //\r
2825 // 3. Update the row info which will be used by next menu.\r
2826 //\r
2827 if (Link == TopOfScreen) {\r
2828 Row += MenuOption->Skip - SkipValue;\r
2829 } else {\r
2830 Row += MenuOption->Skip;\r
2831 }\r
2832\r
2833 if (Row > BottomRow) {\r
2834 if (!ValueIsScroll (FALSE, Link)) {\r
2835 DownArrow = TRUE;\r
2836 }\r
2837\r
2838 Row = BottomRow + 1;\r
2839 break;\r
2840 }\r
2841 }\r
2842\r
af047db7
ED
2843 //\r
2844 // 3. Menus in this form may not cover all form, clean the remain field.\r
2845 //\r
2846 while (Row <= BottomRow) {\r
2847 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
ae4f5746 2848 PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, Row++, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);\r
af047db7
ED
2849 } else {\r
2850 PrintStringAtWithWidth(gStatementDimensions.LeftColumn, Row++, L"", gStatementDimensions.RightColumn - gHelpBlockWidth - gStatementDimensions.LeftColumn);\r
2851 }\r
7c6c064c
ED
2852 }\r
2853\r
af047db7
ED
2854 //\r
2855 // 4. Print the down arrow row.\r
2856 //\r
ae4f5746
ED
2857 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
2858 PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * + gModalSkipColumn);\r
2859 } else {\r
2860 PrintStringAtWithWidth(gStatementDimensions.LeftColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
2861 }\r
7c6c064c
ED
2862 if (DownArrow) {\r
2863 gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
2864 PrintCharAt (\r
2865 gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
2866 BottomRow + SCROLL_ARROW_HEIGHT,\r
2867 ARROW_DOWN\r
2868 );\r
2869 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
2870 }\r
2871\r
2872 MenuOption = NULL;\r
2873 }\r
2874 break;\r
2875\r
2876 case CfRefreshHighLight:\r
2877\r
2878 //\r
2879 // MenuOption: Last menu option that need to remove hilight\r
2880 // MenuOption is set to NULL in Repaint\r
2881 // NewPos: Current menu option that need to hilight\r
2882 //\r
2883 ControlFlag = CfUpdateHelpString;\r
2884\r
42645c3d
ED
2885 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
2886\r
af047db7 2887 if (SkipHighLight) {\r
af047db7 2888 SkipHighLight = FALSE;\r
42645c3d
ED
2889 MenuOption = SavedMenuOption;\r
2890 RefreshKeyHelp(gFormData, SavedMenuOption->ThisTag, FALSE);\r
af047db7
ED
2891 break;\r
2892 }\r
2893\r
8924aecd
ED
2894 if (IsListEmpty (&gMenuOption)) {\r
2895 //\r
2896 // No menu option, just update the hotkey filed.\r
2897 //\r
2898 RefreshKeyHelp(gFormData, NULL, FALSE);\r
2899 break;\r
2900 }\r
2901\r
7c6c064c
ED
2902 if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) {\r
2903 Temp = SkipValue;\r
2904 } else {\r
2905 Temp = 0;\r
2906 }\r
2907 if (NewPos == TopOfScreen) {\r
2908 Temp2 = SkipValue;\r
2909 } else {\r
2910 Temp2 = 0;\r
2911 }\r
2912\r
2913 if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
2914 if (MenuOption != NULL) {\r
2915 //\r
ab369468 2916 // Remove the old highlight menu.\r
7c6c064c 2917 //\r
d1102dba 2918 Status = DisplayOneMenu (MenuOption,\r
ab369468 2919 MenuOption->Col - gStatementDimensions.LeftColumn,\r
d1102dba
LG
2920 gStatementDimensions.LeftColumn,\r
2921 Temp,\r
ab369468 2922 BottomRow,\r
f0c5095b 2923 FALSE,\r
ab369468
ED
2924 FALSE\r
2925 );\r
7c6c064c
ED
2926 }\r
2927\r
2928 //\r
2929 // This is the current selected statement\r
2930 //\r
2931 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
42645c3d 2932 RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE);\r
7c6c064c
ED
2933\r
2934 if (!IsSelectable (MenuOption)) {\r
7c6c064c
ED
2935 break;\r
2936 }\r
2937\r
d1102dba 2938 Status = DisplayOneMenu (MenuOption,\r
ab369468 2939 MenuOption->Col - gStatementDimensions.LeftColumn,\r
d1102dba
LG
2940 gStatementDimensions.LeftColumn,\r
2941 Temp2,\r
ab369468 2942 BottomRow,\r
f0c5095b
ED
2943 TRUE,\r
2944 FALSE\r
ab369468 2945 );\r
7c6c064c
ED
2946 }\r
2947 break;\r
2948\r
2949 case CfUpdateHelpString:\r
2950 ControlFlag = CfPrepareToReadKey;\r
2951 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
2952 break;\r
2953 }\r
2954\r
ab369468
ED
2955 //\r
2956 // NewLine means only update highlight menu (remove old highlight and highlith\r
2957 // the new one), not need to full repain the form.\r
2958 //\r
7c6c064c 2959 if (Repaint || NewLine) {\r
8924aecd
ED
2960 if (IsListEmpty (&gMenuOption)) {\r
2961 //\r
2962 // Don't print anything if no mwnu option.\r
2963 //\r
7c6c064c
ED
2964 StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2965 } else {\r
8924aecd
ED
2966 //\r
2967 // Don't print anything if it is a NULL help token\r
2968 //\r
2969 ASSERT(MenuOption != NULL);\r
2970 HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
cc63add8
DB
2971 Statement = MenuOption->ThisTag;\r
2972 StatementValue = &Statement->CurrentValue;\r
8924aecd 2973 if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
cc63add8
DB
2974 if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP && StatementValue->Value.date.Month== 0xff)||(Statement->OpCode->OpCode == EFI_IFR_TIME_OP && StatementValue->Value.time.Hour == 0xff)){\r
2975 StringPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);\r
2976 } else {\r
2977 StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2978 }\r
8924aecd 2979 } else {\r
cc63add8
DB
2980 if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP && StatementValue->Value.date.Month== 0xff)||(Statement->OpCode->OpCode == EFI_IFR_TIME_OP && StatementValue->Value.time.Hour == 0xff)){\r
2981 StringRightPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
2982 StringErrorPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);\r
2983 StringPtr = AllocateZeroPool ((StrLen (StringRightPtr) + StrLen (StringErrorPtr)+ 1 ) * sizeof (CHAR16));\r
2984 StrCpyS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringRightPtr);\r
2985 StrCatS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringErrorPtr);\r
2986 FreePool (StringRightPtr);\r
2987 FreePool (StringErrorPtr);\r
2988 } else {\r
2989 StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
2990 }\r
8924aecd 2991 }\r
7c6c064c
ED
2992 }\r
2993\r
2994 RowCount = BottomRow - TopRow + 1;\r
2995 HelpPageIndex = 0;\r
2996 //\r
2997 // 1.Calculate how many line the help string need to print.\r
2998 //\r
2999 if (HelpString != NULL) {\r
3000 FreePool (HelpString);\r
3001 HelpString = NULL;\r
3002 }\r
3003 HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
3004 FreePool (StringPtr);\r
3005\r
3006 if (HelpLine > RowCount) {\r
3007 MultiHelpPage = TRUE;\r
3008 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
3009 if (HelpHeaderString != NULL) {\r
3010 FreePool (HelpHeaderString);\r
3011 HelpHeaderString = NULL;\r
3012 }\r
3013 HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, 0);\r
3014 FreePool (StringPtr);\r
3015 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
3016 if (HelpBottomString != NULL) {\r
3017 FreePool (HelpBottomString);\r
3018 HelpBottomString = NULL;\r
3019 }\r
3020 HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, 0);\r
3021 FreePool (StringPtr);\r
3022 //\r
3023 // Calculate the help page count.\r
3024 //\r
3025 if (HelpLine > 2 * RowCount - 2) {\r
3026 HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
92f62cfe 3027 if ((HelpLine - RowCount + 1) % (RowCount - 2) != 0) {\r
7c6c064c
ED
3028 HelpPageCount += 1;\r
3029 }\r
3030 } else {\r
3031 HelpPageCount = 2;\r
3032 }\r
3033 } else {\r
3034 MultiHelpPage = FALSE;\r
3035 }\r
3036 }\r
3037\r
3038 //\r
3039 // Check whether need to show the 'More(U/u)' at the begin.\r
3040 // Base on current direct info, here shows aligned to the right side of the column.\r
d1102dba 3041 // If the direction is multi line and aligned to right side may have problem, so\r
7c6c064c
ED
3042 // add ASSERT code here.\r
3043 //\r
3044 if (HelpPageIndex > 0) {\r
3045 gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
3046 for (Index = 0; Index < HelpHeaderLine; Index++) {\r
3047 ASSERT (HelpHeaderLine == 1);\r
16f69227 3048 ASSERT (GetStringWidth (HelpHeaderString) / 2 < ((UINT32) gHelpBlockWidth - 1));\r
7c6c064c
ED
3049 PrintStringAtWithWidth (\r
3050 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3051 Index + TopRow,\r
3052 gEmptyString,\r
3053 gHelpBlockWidth\r
3054 );\r
3055 PrintStringAt (\r
3056 gStatementDimensions.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
3057 Index + TopRow,\r
3058 &HelpHeaderString[Index * HeaderLineWidth]\r
3059 );\r
3060 }\r
3061 }\r
3062\r
3063 gST->ConOut->SetAttribute (gST->ConOut, GetHelpTextColor ());\r
3064 //\r
3065 // Print the help string info.\r
3066 //\r
3067 if (!MultiHelpPage) {\r
3068 for (Index = 0; Index < HelpLine; Index++) {\r
3069 PrintStringAtWithWidth (\r
3070 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3071 Index + TopRow,\r
3072 &HelpString[Index * EachLineWidth],\r
3073 gHelpBlockWidth\r
3074 );\r
3075 }\r
3076 for (; Index < RowCount; Index ++) {\r
3077 PrintStringAtWithWidth (\r
3078 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3079 Index + TopRow,\r
3080 gEmptyString,\r
3081 gHelpBlockWidth\r
3082 );\r
3083 }\r
3084 gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);\r
3085 } else {\r
3086 if (HelpPageIndex == 0) {\r
3087 for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
3088 PrintStringAtWithWidth (\r
3089 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3090 Index + TopRow,\r
3091 &HelpString[Index * EachLineWidth],\r
3092 gHelpBlockWidth\r
3093 );\r
3094 }\r
3095 } else {\r
d1102dba 3096 for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) &&\r
7c6c064c
ED
3097 (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
3098 PrintStringAtWithWidth (\r
3099 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3100 Index + TopRow + HelpHeaderLine,\r
3101 &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth],\r
3102 gHelpBlockWidth\r
3103 );\r
3104 }\r
3105 if (HelpPageIndex == HelpPageCount - 1) {\r
3106 for (; Index < RowCount - HelpHeaderLine; Index ++) {\r
3107 PrintStringAtWithWidth (\r
3108 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3109 Index + TopRow + HelpHeaderLine,\r
3110 gEmptyString,\r
3111 gHelpBlockWidth\r
3112 );\r
3113 }\r
3114 gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);\r
3115 }\r
d1102dba 3116 }\r
7c6c064c
ED
3117 }\r
3118\r
3119 //\r
3120 // Check whether need to print the 'More(D/d)' at the bottom.\r
3121 // Base on current direct info, here shows aligned to the right side of the column.\r
d1102dba 3122 // If the direction is multi line and aligned to right side may have problem, so\r
7c6c064c
ED
3123 // add ASSERT code here.\r
3124 //\r
3125 if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
3126 gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
3127 for (Index = 0; Index < HelpBottomLine; Index++) {\r
3128 ASSERT (HelpBottomLine == 1);\r
16f69227 3129 ASSERT (GetStringWidth (HelpBottomString) / 2 < ((UINT32) gHelpBlockWidth - 1));\r
7c6c064c
ED
3130 PrintStringAtWithWidth (\r
3131 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3132 BottomRow + Index - HelpBottomLine + 1,\r
3133 gEmptyString,\r
3134 gHelpBlockWidth\r
3135 );\r
3136 PrintStringAt (\r
3137 gStatementDimensions.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
3138 BottomRow + Index - HelpBottomLine + 1,\r
3139 &HelpBottomString[Index * BottomLineWidth]\r
3140 );\r
3141 }\r
3142 }\r
3143 //\r
3144 // Reset this flag every time we finish using it.\r
3145 //\r
3146 Repaint = FALSE;\r
3147 NewLine = FALSE;\r
3148 break;\r
3149\r
3150 case CfPrepareToReadKey:\r
3151 ControlFlag = CfReadKey;\r
3152 ScreenOperation = UiNoOperation;\r
3153 break;\r
3154\r
3155 case CfReadKey:\r
3156 ControlFlag = CfScreenOperation;\r
3157\r
3158 //\r
3159 // Wait for user's selection\r
3160 //\r
3161 while (TRUE) {\r
3162 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3163 if (!EFI_ERROR (Status)) {\r
3164 EventType = UIEventKey;\r
3165 break;\r
3166 }\r
3167\r
3168 //\r
3169 // If we encounter error, continue to read another key in.\r
3170 //\r
3171 if (Status != EFI_NOT_READY) {\r
3172 continue;\r
3173 }\r
d1102dba 3174\r
7c6c064c
ED
3175 EventType = UiWaitForEvent(gST->ConIn->WaitForKey);\r
3176 if (EventType == UIEventKey) {\r
3177 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3178 }\r
3179 break;\r
3180 }\r
3181\r
3182 if (EventType == UIEventDriver) {\r
42645c3d 3183 gMisMatch = TRUE;\r
7c6c064c
ED
3184 gUserInput->Action = BROWSER_ACTION_NONE;\r
3185 ControlFlag = CfExit;\r
3186 break;\r
3187 }\r
d1102dba 3188\r
7c6c064c
ED
3189 if (EventType == UIEventTimeOut) {\r
3190 gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
3191 ControlFlag = CfExit;\r
3192 break;\r
3193 }\r
3194\r
3195 switch (Key.UnicodeChar) {\r
3196 case CHAR_CARRIAGE_RETURN:\r
3197 if(MenuOption == NULL || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
3198 ControlFlag = CfReadKey;\r
3199 break;\r
3200 }\r
3201\r
3202 ScreenOperation = UiSelect;\r
3203 gDirection = 0;\r
3204 break;\r
3205\r
3206 //\r
3207 // We will push the adjustment of these numeric values directly to the input handler\r
3208 // NOTE: we won't handle manual input numeric\r
3209 //\r
3210 case '+':\r
3211 case '-':\r
3212 //\r
3213 // If the screen has no menu items, and the user didn't select UiReset\r
3214 // ignore the selection and go back to reading keys.\r
3215 //\r
05de47ef 3216 ASSERT(MenuOption != NULL);\r
7c6c064c
ED
3217 if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
3218 ControlFlag = CfReadKey;\r
3219 break;\r
3220 }\r
3221\r
7c6c064c
ED
3222 Statement = MenuOption->ThisTag;\r
3223 if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)\r
3224 || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)\r
3225 || ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (GetFieldFromNum(Statement->OpCode) != 0))\r
3226 ){\r
3227 if (Key.UnicodeChar == '+') {\r
3228 gDirection = SCAN_RIGHT;\r
3229 } else {\r
3230 gDirection = SCAN_LEFT;\r
3231 }\r
d1102dba 3232\r
7c6c064c
ED
3233 Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
3234 if (OptionString != NULL) {\r
3235 FreePool (OptionString);\r
3236 }\r
3237 if (EFI_ERROR (Status)) {\r
3238 //\r
3239 // Repaint to clear possible error prompt pop-up\r
3240 //\r
3241 Repaint = TRUE;\r
3242 NewLine = TRUE;\r
3243 } else {\r
3244 ControlFlag = CfExit;\r
3245 }\r
3246 }\r
3247 break;\r
3248\r
3249 case '^':\r
3250 ScreenOperation = UiUp;\r
3251 break;\r
3252\r
3253 case 'V':\r
3254 case 'v':\r
3255 ScreenOperation = UiDown;\r
3256 break;\r
3257\r
3258 case ' ':\r
3259 if(IsListEmpty (&gMenuOption)) {\r
3260 ControlFlag = CfReadKey;\r
3261 break;\r
3262 }\r
d1102dba 3263\r
7c6c064c
ED
3264 ASSERT(MenuOption != NULL);\r
3265 if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {\r
3266 ScreenOperation = UiSelect;\r
3267 }\r
3268 break;\r
3269\r
3270 case 'D':\r
3271 case 'd':\r
3272 if (!MultiHelpPage) {\r
3273 ControlFlag = CfReadKey;\r
3274 break;\r
3275 }\r
3276 ControlFlag = CfUpdateHelpString;\r
3277 HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;\r
3278 break;\r
3279\r
3280 case 'U':\r
3281 case 'u':\r
3282 if (!MultiHelpPage) {\r
3283 ControlFlag = CfReadKey;\r
3284 break;\r
3285 }\r
3286 ControlFlag = CfUpdateHelpString;\r
3287 HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;\r
3288 break;\r
3289\r
3290 case CHAR_NULL:\r
3291 for (Index = 0; Index < mScanCodeNumber; Index++) {\r
3292 if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
3293 ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
3294 break;\r
3295 }\r
3296 }\r
d1102dba 3297\r
7c6c064c
ED
3298 if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {\r
3299 //\r
3300 // ModalForm has no ESC key and Hot Key.\r
3301 //\r
3302 ControlFlag = CfReadKey;\r
3303 } else if (Index == mScanCodeNumber) {\r
3304 //\r
3305 // Check whether Key matches the registered hot key.\r
3306 //\r
3307 HotKey = NULL;\r
3308 HotKey = GetHotKeyFromRegisterList (&Key);\r
3309 if (HotKey != NULL) {\r
3310 ScreenOperation = UiHotKey;\r
3311 }\r
3312 }\r
3313 break;\r
3314 }\r
3315 break;\r
3316\r
3317 case CfScreenOperation:\r
8924aecd 3318 if ((ScreenOperation != UiReset) && (ScreenOperation != UiHotKey)) {\r
7c6c064c 3319 //\r
8924aecd 3320 // If the screen has no menu items, and the user didn't select UiReset or UiHotKey\r
7c6c064c
ED
3321 // ignore the selection and go back to reading keys.\r
3322 //\r
3323 if (IsListEmpty (&gMenuOption)) {\r
3324 ControlFlag = CfReadKey;\r
3325 break;\r
3326 }\r
3327 }\r
3328\r
3329 for (Index = 0;\r
bce1d8a8 3330 Index < ARRAY_SIZE (gScreenOperationToControlFlag);\r
7c6c064c
ED
3331 Index++\r
3332 ) {\r
3333 if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
3334 ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
3335 break;\r
3336 }\r
3337 }\r
3338 break;\r
3339\r
3340 case CfUiSelect:\r
3341 ControlFlag = CfRepaint;\r
3342\r
3343 ASSERT(MenuOption != NULL);\r
3344 Statement = MenuOption->ThisTag;\r
3345 if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
3346 break;\r
3347 }\r
3348\r
3349 switch (Statement->OpCode->OpCode) {\r
3350 case EFI_IFR_REF_OP:\r
3351 case EFI_IFR_ACTION_OP:\r
3352 case EFI_IFR_RESET_BUTTON_OP:\r
3353 ControlFlag = CfExit;\r
3354 break;\r
3355\r
3356 default:\r
3357 //\r
3358 // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
3359 //\r
3360 RefreshKeyHelp (gFormData, Statement, TRUE);\r
3361 Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
d1102dba 3362\r
7c6c064c
ED
3363 if (OptionString != NULL) {\r
3364 FreePool (OptionString);\r
3365 }\r
d1102dba 3366\r
7c6c064c
ED
3367 if (EFI_ERROR (Status)) {\r
3368 Repaint = TRUE;\r
3369 NewLine = TRUE;\r
3370 RefreshKeyHelp (gFormData, Statement, FALSE);\r
3371 break;\r
3372 } else {\r
3373 ControlFlag = CfExit;\r
3374 break;\r
3375 }\r
3376 }\r
3377 break;\r
3378\r
3379 case CfUiReset:\r
3380 //\r
3381 // We come here when someone press ESC\r
3382 // If the policy is not exit front page when user press ESC, process here.\r
3383 //\r
3384 if (!FormExitPolicy()) {\r
3385 Repaint = TRUE;\r
3386 NewLine = TRUE;\r
3387 ControlFlag = CfRepaint;\r
3388 break;\r
3389 }\r
3390\r
7c6c064c
ED
3391 gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
3392 ControlFlag = CfExit;\r
3393 break;\r
3394\r
3395 case CfUiHotKey:\r
3396 ControlFlag = CfRepaint;\r
05de47ef
ED
3397\r
3398 ASSERT (HotKey != NULL);\r
23c7d425
ED
3399\r
3400 if (FxConfirmPopup(HotKey->Action)) {\r
3401 gUserInput->Action = HotKey->Action;\r
a687a1d2
ED
3402 if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
3403 gUserInput->DefaultId = HotKey->DefaultId;\r
3404 }\r
23c7d425
ED
3405 ControlFlag = CfExit;\r
3406 } else {\r
3407 Repaint = TRUE;\r
3408 NewLine = TRUE;\r
3409 ControlFlag = CfRepaint;\r
3410 }\r
3411\r
7c6c064c
ED
3412 break;\r
3413\r
3414 case CfUiLeft:\r
3415 ControlFlag = CfRepaint;\r
3416 ASSERT(MenuOption != NULL);\r
3417 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
3418 if (MenuOption->Sequence != 0) {\r
3419 //\r
3420 // In the middle or tail of the Date/Time op-code set, go left.\r
3421 //\r
3422 ASSERT(NewPos != NULL);\r
3423 NewPos = NewPos->BackLink;\r
3424 }\r
3425 }\r
3426 break;\r
3427\r
3428 case CfUiRight:\r
3429 ControlFlag = CfRepaint;\r
3430 ASSERT(MenuOption != NULL);\r
3431 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
3432 if (MenuOption->Sequence != 2) {\r
3433 //\r
3434 // In the middle or tail of the Date/Time op-code set, go left.\r
3435 //\r
3436 ASSERT(NewPos != NULL);\r
3437 NewPos = NewPos->ForwardLink;\r
3438 }\r
3439 }\r
3440 break;\r
3441\r
3442 case CfUiUp:\r
3443 ControlFlag = CfRepaint;\r
ab369468 3444 NewLine = TRUE;\r
7c6c064c
ED
3445\r
3446 SavedListEntry = NewPos;\r
7c6c064c 3447 ASSERT(NewPos != NULL);\r
f0c5095b
ED
3448\r
3449 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3450 ASSERT (MenuOption != NULL);\r
3451\r
7c6c064c
ED
3452 //\r
3453 // Adjust Date/Time position before we advance forward.\r
3454 //\r
3455 AdjustDateAndTimePosition (TRUE, &NewPos);\r
7c6c064c 3456\r
ab369468
ED
3457 NewPos = NewPos->BackLink;\r
3458 //\r
3459 // Find next selectable menu or the first menu beyond current form.\r
3460 //\r
3461 Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow, FALSE);\r
3462 if (Difference < 0) {\r
3463 //\r
3464 // We hit the begining MenuOption that can be focused\r
3465 // so we simply scroll to the top.\r
3466 //\r
3467 Repaint = TRUE;\r
3468 if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
3469 TopOfScreen = gMenuOption.ForwardLink;\r
3470 NewPos = SavedListEntry;\r
3471 SkipValue = 0;\r
3472 } else {\r
7c6c064c 3473 //\r
ab369468 3474 // Scroll up to the last page when we have arrived at top page.\r
7c6c064c 3475 //\r
ab369468
ED
3476 TopOfScreen = FindTopOfScreenMenu (gMenuOption.BackLink, BottomRow - TopRow, &SkipValue);\r
3477 NewPos = gMenuOption.BackLink;\r
3478 MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow, TRUE);\r
3479 }\r
3480 } else {\r
3481 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3482\r
3483 if (MenuOption->Row < TopRow + Difference + NextMenuOption->Skip) {\r
7c6c064c
ED
3484 //\r
3485 // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
3486 //\r
3487 TopOfScreen = NewPos;\r
3488 Repaint = TRUE;\r
ab369468 3489 SkipValue = 0;\r
7c6c064c
ED
3490 }\r
3491\r
3492 //\r
ab369468 3493 // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
7c6c064c 3494 //\r
ab369468 3495 // BottomRow - TopRow + 1 means the total rows current forms supported.\r
d1102dba
LG
3496 // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu\r
3497 // and new top menu. New top menu will all shows in next form, but last highlight menu\r
3498 // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the\r
ab369468 3499 // last highlight menu.\r
d1102dba
LG
3500 //\r
3501 if (!IsSelectable(NextMenuOption) && IsSelectable(MenuOption) &&\r
ab369468
ED
3502 (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
3503 NewPos = SavedListEntry;\r
6f05c023 3504 }\r
7c6c064c 3505 }\r
7c6c064c 3506\r
ab369468 3507 UpdateStatusBar (INPUT_ERROR, FALSE);\r
7c6c064c 3508\r
7c6c064c 3509 //\r
ab369468 3510 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
7c6c064c 3511 //\r
ab369468
ED
3512 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3513 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3514\r
3515 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
ab369468 3516 break;\r
7c6c064c 3517\r
ab369468 3518 case CfUiPageUp:\r
7c6c064c 3519 //\r
ab369468 3520 // SkipValue means lines is skipped when show the top menu option.\r
7c6c064c 3521 //\r
ab369468
ED
3522 ControlFlag = CfRepaint;\r
3523 NewLine = TRUE;\r
3524 Repaint = TRUE;\r
7c6c064c
ED
3525\r
3526 Link = TopOfScreen;\r
3527 //\r
3528 // First minus the menu of the top screen, it's value is SkipValue.\r
3529 //\r
2e7183ba 3530 if (SkipValue >= BottomRow - TopRow + 1) {\r
7c6c064c 3531 //\r
ab369468
ED
3532 // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
3533 // form of options to be show, so just update the SkipValue to show the next\r
3534 // parts of options.\r
7c6c064c 3535 //\r
ab369468
ED
3536 SkipValue -= BottomRow - TopRow + 1;\r
3537 NewPos = TopOfScreen;\r
3538 break;\r
3539 } else {\r
3540 Index = (BottomRow + 1) - SkipValue - TopRow;\r
7c6c064c 3541 }\r
d1102dba 3542\r
ab369468
ED
3543 TopOfScreen = FindTopOfScreenMenu(TopOfScreen, Index, &SkipValue);\r
3544 NewPos = TopOfScreen;\r
3545 MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE);\r
d1102dba 3546\r
ab369468 3547 UpdateStatusBar (INPUT_ERROR, FALSE);\r
7c6c064c
ED
3548\r
3549 //\r
3550 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3551 // Don't do this when we are already in the first page.\r
3552 //\r
3553 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3554 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3555\r
3556 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
7c6c064c
ED
3557 break;\r
3558\r
3559 case CfUiPageDown:\r
3560 //\r
3561 // SkipValue means lines is skipped when show the top menu option.\r
3562 //\r
ab369468
ED
3563 ControlFlag = CfRepaint;\r
3564 NewLine = TRUE;\r
3565 Repaint = TRUE;\r
7c6c064c 3566\r
7c6c064c
ED
3567 Link = TopOfScreen;\r
3568 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3569 Index = TopRow + NextMenuOption->Skip - SkipValue;\r
3570 //\r
3571 // Count to the menu option which will show at the top of the next form.\r
3572 //\r
3573 while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {\r
3574 Link = Link->ForwardLink;\r
3575 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3576 Index = Index + NextMenuOption->Skip;\r
3577 }\r
3578\r
3579 if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {\r
3580 //\r
ab369468 3581 // Highlight on the last menu which can be highlight.\r
7c6c064c
ED
3582 //\r
3583 Repaint = FALSE;\r
ab369468 3584 MoveToNextStatement (TRUE, &Link, Index - TopRow, TRUE);\r
7c6c064c
ED
3585 } else {\r
3586 //\r
3587 // Calculate the skip line for top of screen menu.\r
3588 //\r
3589 if (Link == TopOfScreen) {\r
3590 //\r
3591 // The top of screen menu option occupies the entire form.\r
3592 //\r
3593 SkipValue += BottomRow - TopRow + 1;\r
3594 } else {\r
3595 SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));\r
3596 }\r
7c6c064c
ED
3597 TopOfScreen = Link;\r
3598 MenuOption = NULL;\r
3599 //\r
3600 // Move to the Next selectable menu.\r
3601 //\r
ab369468 3602 MoveToNextStatement (FALSE, &Link, BottomRow - TopRow, TRUE);\r
7c6c064c
ED
3603 }\r
3604\r
3605 //\r
3606 // Save the menu as the next highlight menu.\r
3607 //\r
3608 NewPos = Link;\r
3609\r
ab369468
ED
3610 UpdateStatusBar (INPUT_ERROR, FALSE);\r
3611\r
7c6c064c
ED
3612 //\r
3613 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3614 // Don't do this when we are already in the last page.\r
3615 //\r
3616 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3617 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3618\r
3619 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
7c6c064c
ED
3620 break;\r
3621\r
3622 case CfUiDown:\r
3623 //\r
3624 // SkipValue means lines is skipped when show the top menu option.\r
3625 // NewPos points to the menu which is highlighted now.\r
3626 //\r
3627 ControlFlag = CfRepaint;\r
ab369468 3628 NewLine = TRUE;\r
7c6c064c 3629\r
ab369468
ED
3630 if (NewPos == TopOfScreen) {\r
3631 Temp2 = SkipValue;\r
3632 } else {\r
3633 Temp2 = 0;\r
3634 }\r
3635\r
3636 SavedListEntry = NewPos;\r
7c6c064c
ED
3637 //\r
3638 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
3639 // to be one that progresses to the next set of op-codes, we need to advance to the last\r
3640 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
3641 // checking can be done. The only other logic we need to introduce is that if a Date/Time\r
3642 // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
3643 // the Date/Time op-code.\r
3644 //\r
7c6c064c
ED
3645 AdjustDateAndTimePosition (FALSE, &NewPos);\r
3646\r
ab369468
ED
3647 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3648 NewPos = NewPos->ForwardLink;\r
3649 //\r
3650 // Find the next selectable menu.\r
3651 //\r
3652 if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) {\r
3653 if (gMenuOption.ForwardLink == NewPos || &gMenuOption == NewPos) {\r
3654 Difference = -1;\r
3655 } else {\r
3656 Difference = 0;\r
3657 }\r
3658 } else {\r
3659 Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE);\r
3660 }\r
3661 if (Difference < 0) {\r
3662 //\r
3663 // Scroll to the first page.\r
3664 //\r
d1102dba 3665 if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
ab369468
ED
3666 TopOfScreen = gMenuOption.ForwardLink;\r
3667 Repaint = TRUE;\r
3668 MenuOption = NULL;\r
6f05c023 3669 } else {\r
ab369468 3670 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
6f05c023 3671 }\r
ab369468
ED
3672 NewPos = gMenuOption.ForwardLink;\r
3673 MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, TRUE);\r
6f05c023 3674\r
ab369468
ED
3675 SkipValue = 0;\r
3676 //\r
3677 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3678 //\r
3679 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3680 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3681\r
3682 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
ab369468 3683 break;\r
d1102dba 3684 }\r
7c6c064c 3685\r
ab369468
ED
3686 //\r
3687 // Get next selected menu info.\r
3688 //\r
3689 AdjustDateAndTimePosition (FALSE, &NewPos);\r
3690 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3691 if (NextMenuOption->Row == 0) {\r
3692 UpdateOptionSkipLines (NextMenuOption);\r
3693 }\r
3694\r
3695 //\r
3696 // Calculate new highlight menu end row.\r
3697 //\r
3698 Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1;\r
3699 if (Temp > BottomRow) {\r
7c6c064c 3700 //\r
ab369468 3701 // Get the top screen menu info.\r
7c6c064c 3702 //\r
ab369468
ED
3703 AdjustDateAndTimePosition (FALSE, &TopOfScreen);\r
3704 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
3705\r
3706 //\r
3707 // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows.\r
3708 // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows.\r
3709 //\r
3710 if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
7c6c064c 3711 //\r
ab369468 3712 // Skip the top op-code\r
7c6c064c 3713 //\r
ab369468
ED
3714 TopOfScreen = TopOfScreen->ForwardLink;\r
3715 DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
7c6c064c 3716\r
ab369468 3717 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
7c6c064c 3718\r
ab369468
ED
3719 //\r
3720 // If we have a remainder, skip that many more op-codes until we drain the remainder\r
3721 // Special case is the selected highlight menu has more than one form of menus.\r
3722 //\r
3723 while (DistanceValue >= SavedMenuOption->Skip && TopOfScreen != NewPos) {\r
7c6c064c 3724 //\r
ab369468 3725 // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
7c6c064c 3726 //\r
ab369468
ED
3727 DistanceValue = DistanceValue - (INTN) SavedMenuOption->Skip;\r
3728 TopOfScreen = TopOfScreen->ForwardLink;\r
7c6c064c 3729 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
ab369468 3730 }\r
7c6c064c 3731 //\r
ab369468
ED
3732 // Since we will act on this op-code in the next routine, and increment the\r
3733 // SkipValue, set the skips to one less than what is required.\r
7c6c064c 3734 //\r
ab369468
ED
3735 if (TopOfScreen != NewPos) {\r
3736 SkipValue = DistanceValue;\r
3737 } else {\r
3738 SkipValue = 0;\r
3739 }\r
7c6c064c
ED
3740 } else {\r
3741 //\r
ab369468
ED
3742 // Since we will act on this op-code in the next routine, and increment the\r
3743 // SkipValue, set the skips to one less than what is required.\r
7c6c064c 3744 //\r
ab369468 3745 SkipValue += Temp - BottomRow;\r
7c6c064c 3746 }\r
ab369468
ED
3747 Repaint = TRUE;\r
3748 } else if (!IsSelectable (NextMenuOption)) {\r
7c6c064c 3749 //\r
ab369468 3750 // Continue to go down until scroll to next page or the selectable option is found.\r
7c6c064c 3751 //\r
ab369468
ED
3752 ScreenOperation = UiDown;\r
3753 ControlFlag = CfScreenOperation;\r
3754 break;\r
3755 }\r
3756\r
3757 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3758\r
3759 //\r
3760 // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
3761 //\r
3762 // BottomRow - TopRow + 1 means the total rows current forms supported.\r
d1102dba
LG
3763 // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu\r
3764 // and new top menu. New top menu will all shows in next form, but last highlight menu\r
3765 // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the\r
ab369468 3766 // last highlight menu.\r
d1102dba
LG
3767 //\r
3768 if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) &&\r
ab369468
ED
3769 (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
3770 NewPos = SavedListEntry;\r
7c6c064c
ED
3771 }\r
3772\r
ab369468
ED
3773 UpdateStatusBar (INPUT_ERROR, FALSE);\r
3774\r
7c6c064c
ED
3775 //\r
3776 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3777 //\r
3778 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3779 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3780\r
3781 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
7c6c064c
ED
3782 break;\r
3783\r
3784 case CfUiNoOperation:\r
3785 ControlFlag = CfRepaint;\r
3786 break;\r
3787\r
3788 case CfExit:\r
5a9f73bf 3789 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
7c6c064c
ED
3790 if (HelpString != NULL) {\r
3791 FreePool (HelpString);\r
3792 }\r
3793 if (HelpHeaderString != NULL) {\r
3794 FreePool (HelpHeaderString);\r
3795 }\r
3796 if (HelpBottomString != NULL) {\r
3797 FreePool (HelpBottomString);\r
3798 }\r
3799 return EFI_SUCCESS;\r
3800\r
3801 default:\r
3802 break;\r
3803 }\r
3804 }\r
3805}\r
3806\r
0196c24a
DB
3807/**\r
3808 Free the UI Menu Option structure data.\r
3809\r
3810 @param MenuOptionList Point to the menu option list which need to be free.\r
3811\r
3812**/\r
0196c24a
DB
3813VOID\r
3814FreeMenuOptionData(\r
3815 LIST_ENTRY *MenuOptionList\r
3816 )\r
3817{\r
3818 LIST_ENTRY *Link;\r
3819 UI_MENU_OPTION *Option;\r
3820\r
3821 //\r
3822 // Free menu option list\r
3823 //\r
3824 while (!IsListEmpty (MenuOptionList)) {\r
3825 Link = GetFirstNode (MenuOptionList);\r
3826 Option = MENU_OPTION_FROM_LINK (Link);\r
3827 if (Option->Description != NULL){\r
3828 FreePool(Option->Description);\r
3829 }\r
3830 RemoveEntryList (&Option->Link);\r
3831 FreePool (Option);\r
3832 }\r
3833}\r
3834\r
7c6c064c
ED
3835/**\r
3836\r
3837 Base on the browser status info to show an pop up message.\r
3838\r
3839**/\r
3840VOID\r
3841BrowserStatusProcess (\r
3842 VOID\r
3843 )\r
3844{\r
bfae1330
ED
3845 CHAR16 *ErrorInfo;\r
3846 EFI_INPUT_KEY Key;\r
3847 EFI_EVENT WaitList[2];\r
3848 EFI_EVENT RefreshIntervalEvent;\r
3849 EFI_EVENT TimeOutEvent;\r
3850 UINT8 TimeOut;\r
3851 EFI_STATUS Status;\r
3852 UINTN Index;\r
3853 WARNING_IF_CONTEXT EventContext;\r
3854 EFI_IFR_OP_HEADER *OpCodeBuf;\r
3855 EFI_STRING_ID StringToken;\r
4d4deaac
ED
3856 CHAR16 DiscardChange;\r
3857 CHAR16 JumpToFormSet;\r
3858 CHAR16 *PrintString;\r
7c6c064c
ED
3859\r
3860 if (gFormData->BrowserStatus == BROWSER_SUCCESS) {\r
3861 return;\r
3862 }\r
3863\r
bfae1330
ED
3864 StringToken = 0;\r
3865 TimeOutEvent = NULL;\r
3866 RefreshIntervalEvent = NULL;\r
3867 OpCodeBuf = NULL;\r
3868 if (gFormData->HighLightedStatement != NULL) {\r
3869 OpCodeBuf = gFormData->HighLightedStatement->OpCode;\r
3870 }\r
3871\r
3872 if (gFormData->BrowserStatus == (BROWSER_WARNING_IF)) {\r
3873 ASSERT (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_WARNING_IF_OP);\r
3874\r
3875 TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->TimeOut;\r
3876 StringToken = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->Warning;\r
3877 } else {\r
3878 TimeOut = 0;\r
3879 if ((gFormData->BrowserStatus == (BROWSER_NO_SUBMIT_IF)) &&\r
3880 (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_NO_SUBMIT_IF_OP)) {\r
3881 StringToken = ((EFI_IFR_NO_SUBMIT_IF *) OpCodeBuf)->Error;\r
3882 } else if ((gFormData->BrowserStatus == (BROWSER_INCONSISTENT_IF)) &&\r
3883 (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_INCONSISTENT_IF_OP)) {\r
3884 StringToken = ((EFI_IFR_INCONSISTENT_IF *) OpCodeBuf)->Error;\r
3885 }\r
3886 }\r
3887\r
3888 if (StringToken != 0) {\r
3889 ErrorInfo = GetToken (StringToken, gFormData->HiiHandle);\r
3890 } else if (gFormData->ErrorString != NULL) {\r
3891 //\r
3892 // Only used to compatible with old setup browser.\r
3893 // Not use this field in new browser core.\r
3894 //\r
7c6c064c
ED
3895 ErrorInfo = gFormData->ErrorString;\r
3896 } else {\r
3897 switch (gFormData->BrowserStatus) {\r
3898 case BROWSER_SUBMIT_FAIL:\r
3899 ErrorInfo = gSaveFailed;\r
3900 break;\r
3901\r
7c6c064c
ED
3902 case BROWSER_FORM_NOT_FOUND:\r
3903 ErrorInfo = gFormNotFound;\r
3904 break;\r
3905\r
3906 case BROWSER_FORM_SUPPRESS:\r
3907 ErrorInfo = gFormSuppress;\r
3908 break;\r
3909\r
3910 case BROWSER_PROTOCOL_NOT_FOUND:\r
3911 ErrorInfo = gProtocolNotFound;\r
3912 break;\r
3913\r
4d4deaac
ED
3914 case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
3915 ErrorInfo = gNoSubmitIfFailed;\r
3916 break;\r
3917\r
f2e7732e
ED
3918 case BROWSER_RECONNECT_FAIL:\r
3919 ErrorInfo = gReconnectFail;\r
3920 break;\r
3921\r
3922 case BROWSER_RECONNECT_SAVE_CHANGES:\r
3923 ErrorInfo = gReconnectConfirmChanges;\r
3924 break;\r
3925\r
3926 case BROWSER_RECONNECT_REQUIRED:\r
3927 ErrorInfo = gReconnectRequired;\r
3928 break;\r
3929\r
7c6c064c 3930 default:\r
f2e7732e 3931 ErrorInfo = gBrowserError;\r
7c6c064c
ED
3932 break;\r
3933 }\r
3934 }\r
3935\r
4d4deaac
ED
3936 switch (gFormData->BrowserStatus) {\r
3937 case BROWSER_SUBMIT_FAIL:\r
3938 case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
f2e7732e 3939 case BROWSER_RECONNECT_SAVE_CHANGES:\r
4d4deaac
ED
3940 ASSERT (gUserInput != NULL);\r
3941 if (gFormData->BrowserStatus == (BROWSER_SUBMIT_FAIL)) {\r
3942 PrintString = gSaveProcess;\r
3943 JumpToFormSet = gJumpToFormSet[0];\r
f2e7732e
ED
3944 DiscardChange = gDiscardChange[0];\r
3945 } else if (gFormData->BrowserStatus == (BROWSER_RECONNECT_SAVE_CHANGES)){\r
3946 PrintString = gChangesOpt;\r
3947 JumpToFormSet = gConfirmOptYes[0];\r
3948 DiscardChange = gConfirmOptNo[0];\r
4d4deaac
ED
3949 } else {\r
3950 PrintString = gSaveNoSubmitProcess;\r
3951 JumpToFormSet = gCheckError[0];\r
f2e7732e 3952 DiscardChange = gDiscardChange[0];\r
4d4deaac 3953 }\r
4d4deaac 3954\r
bfae1330 3955 do {\r
4d4deaac
ED
3956 CreateDialog (&Key, gEmptyString, ErrorInfo, PrintString, gEmptyString, NULL);\r
3957 } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (DiscardChange | UPPER_LOWER_CASE_OFFSET)) &&\r
3958 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (JumpToFormSet | UPPER_LOWER_CASE_OFFSET)));\r
bfae1330 3959\r
4d4deaac
ED
3960 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (DiscardChange | UPPER_LOWER_CASE_OFFSET)) {\r
3961 gUserInput->Action = BROWSER_ACTION_DISCARD;\r
3962 } else {\r
3963 gUserInput->Action = BROWSER_ACTION_GOTO;\r
3964 }\r
3965 break;\r
bfae1330 3966\r
4d4deaac
ED
3967 default:\r
3968 if (TimeOut == 0) {\r
3969 do {\r
3970 CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
3971 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3972 } else {\r
3973 Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent);\r
3974 ASSERT_EFI_ERROR (Status);\r
bfae1330 3975\r
4d4deaac
ED
3976 EventContext.SyncEvent = TimeOutEvent;\r
3977 EventContext.TimeOut = &TimeOut;\r
3978 EventContext.ErrorInfo = ErrorInfo;\r
bfae1330 3979\r
4d4deaac
ED
3980 Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent);\r
3981 ASSERT_EFI_ERROR (Status);\r
bfae1330 3982\r
4d4deaac
ED
3983 //\r
3984 // Show the dialog first to avoid long time not reaction.\r
3985 //\r
3986 gBS->SignalEvent (RefreshIntervalEvent);\r
d1102dba 3987\r
4d4deaac
ED
3988 Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND);\r
3989 ASSERT_EFI_ERROR (Status);\r
bfae1330 3990\r
4d4deaac
ED
3991 while (TRUE) {\r
3992 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3993 if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
3994 break;\r
3995 }\r
bfae1330 3996\r
4d4deaac
ED
3997 if (Status != EFI_NOT_READY) {\r
3998 continue;\r
3999 }\r
bfae1330 4000\r
4d4deaac
ED
4001 WaitList[0] = TimeOutEvent;\r
4002 WaitList[1] = gST->ConIn->WaitForKey;\r
bfae1330 4003\r
4d4deaac
ED
4004 Status = gBS->WaitForEvent (2, WaitList, &Index);\r
4005 ASSERT_EFI_ERROR (Status);\r
4006\r
4007 if (Index == 0) {\r
4008 //\r
4009 // Timeout occur, close the hoot time out event.\r
4010 //\r
4011 break;\r
4012 }\r
bfae1330 4013 }\r
4d4deaac
ED
4014\r
4015 gBS->CloseEvent (TimeOutEvent);\r
4016 gBS->CloseEvent (RefreshIntervalEvent);\r
bfae1330 4017 }\r
4d4deaac 4018 break;\r
bfae1330
ED
4019 }\r
4020\r
bfae1330
ED
4021 if (StringToken != 0) {\r
4022 FreePool (ErrorInfo);\r
4023 }\r
7c6c064c
ED
4024}\r
4025\r
4026/**\r
4027 Display one form, and return user input.\r
d1102dba 4028\r
7c6c064c
ED
4029 @param FormData Form Data to be shown.\r
4030 @param UserInputData User input data.\r
d1102dba 4031\r
7c6c064c
ED
4032 @retval EFI_SUCCESS 1.Form Data is shown, and user input is got.\r
4033 2.Error info has show and return.\r
4034 @retval EFI_INVALID_PARAMETER The input screen dimension is not valid\r
4035 @retval EFI_NOT_FOUND New form data has some error.\r
4036**/\r
4037EFI_STATUS\r
d1102dba 4038EFIAPI\r
7c6c064c
ED
4039FormDisplay (\r
4040 IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
4041 OUT USER_INPUT *UserInputData\r
4042 )\r
4043{\r
4044 EFI_STATUS Status;\r
4045\r
4046 ASSERT (FormData != NULL);\r
4047 if (FormData == NULL) {\r
4048 return EFI_INVALID_PARAMETER;\r
4049 }\r
4050\r
4051 gUserInput = UserInputData;\r
4052 gFormData = FormData;\r
4053\r
4054 //\r
4055 // Process the status info first.\r
4056 //\r
4057 BrowserStatusProcess();\r
4d4deaac 4058 if (gFormData->BrowserStatus != BROWSER_SUCCESS) {\r
7c6c064c 4059 //\r
4d4deaac 4060 // gFormData->BrowserStatus != BROWSER_SUCCESS, means only need to print the error info, return here.\r
7c6c064c
ED
4061 //\r
4062 return EFI_SUCCESS;\r
4063 }\r
4064\r
7c6c064c
ED
4065 Status = DisplayPageFrame (FormData, &gStatementDimensions);\r
4066 if (EFI_ERROR (Status)) {\r
4067 return Status;\r
4068 }\r
4069\r
c4866c77
SEHM
4070 //\r
4071 // Global Widths should be initialized before any MenuOption creation\r
4072 // or the GetWidth() used in UiAddMenuOption() will return incorrect value.\r
4073 //\r
4074 //\r
4075 // Left right\r
4076 // |<-.->|<-.........->|<- .........->|<-...........->|\r
d1102dba 4077 // Skip Prompt Option Help\r
c4866c77
SEHM
4078 //\r
4079 gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3) + 1;\r
4080 gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - 1 - LEFT_SKIPPED_COLUMNS);\r
4081 gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gOptionBlockWidth - 1) - 1);\r
4082\r
4083 ConvertStatementToMenu();\r
4084\r
5a9f73bf
ED
4085 //\r
4086 // Check whether layout is changed.\r
4087 //\r
d1102dba 4088 if (mIsFirstForm\r
5a9f73bf
ED
4089 || (gOldFormEntry.HiiHandle != FormData->HiiHandle)\r
4090 || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))\r
4091 || (gOldFormEntry.FormId != FormData->FormId)) {\r
7c6c064c 4092 mStatementLayoutIsChanged = TRUE;\r
5a9f73bf
ED
4093 } else {\r
4094 mStatementLayoutIsChanged = FALSE;\r
7c6c064c
ED
4095 }\r
4096\r
4097 Status = UiDisplayMenu(FormData);\r
d1102dba 4098\r
5a9f73bf
ED
4099 //\r
4100 // Backup last form info.\r
4101 //\r
4102 mIsFirstForm = FALSE;\r
4103 gOldFormEntry.HiiHandle = FormData->HiiHandle;\r
4104 CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid);\r
4105 gOldFormEntry.FormId = FormData->FormId;\r
7c6c064c 4106\r
0196c24a
DB
4107 //\r
4108 //Free the Ui menu option list.\r
4109 //\r
4110 FreeMenuOptionData(&gMenuOption);\r
4111\r
7c6c064c
ED
4112 return Status;\r
4113}\r
4114\r
5a9f73bf
ED
4115/**\r
4116 Clear Screen to the initial state.\r
4117**/\r
4118VOID\r
d1102dba 4119EFIAPI\r
5a9f73bf
ED
4120DriverClearDisplayPage (\r
4121 VOID\r
4122 )\r
4123{\r
4124 ClearDisplayPage ();\r
4125 mIsFirstForm = TRUE;\r
4126}\r
4127\r
4128/**\r
4129 Set Buffer to Value for Size bytes.\r
4130\r
4131 @param Buffer Memory to set.\r
4132 @param Size Number of bytes to set\r
4133 @param Value Value of the set operation.\r
4134\r
4135**/\r
4136VOID\r
4137SetUnicodeMem (\r
4138 IN VOID *Buffer,\r
4139 IN UINTN Size,\r
4140 IN CHAR16 Value\r
4141 )\r
4142{\r
4143 CHAR16 *Ptr;\r
4144\r
4145 Ptr = Buffer;\r
4146 while ((Size--) != 0) {\r
4147 *(Ptr++) = Value;\r
4148 }\r
4149}\r
4150\r
7c6c064c
ED
4151/**\r
4152 Initialize Setup Browser driver.\r
4153\r
4154 @param ImageHandle The image handle.\r
4155 @param SystemTable The system table.\r
4156\r
4157 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
4158 @return Other value if failed to initialize the Setup Browser module.\r
4159\r
4160**/\r
4161EFI_STATUS\r
4162EFIAPI\r
4163InitializeDisplayEngine (\r
4164 IN EFI_HANDLE ImageHandle,\r
4165 IN EFI_SYSTEM_TABLE *SystemTable\r
4166 )\r
4167{\r
4168 EFI_STATUS Status;\r
4169 EFI_INPUT_KEY HotKey;\r
4170 EFI_STRING NewString;\r
4171 EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;\r
4172\r
4173 //\r
4174 // Publish our HII data\r
4175 //\r
4176 gHiiHandle = HiiAddPackages (\r
4177 &gDisplayEngineGuid,\r
4178 ImageHandle,\r
4179 DisplayEngineStrings,\r
4180 NULL\r
4181 );\r
4182 ASSERT (gHiiHandle != NULL);\r
4183\r
4184 //\r
4185 // Install Form Display protocol\r
4186 //\r
4187 Status = gBS->InstallProtocolInterface (\r
4188 &mPrivateData.Handle,\r
4189 &gEdkiiFormDisplayEngineProtocolGuid,\r
4190 EFI_NATIVE_INTERFACE,\r
4191 &mPrivateData.FromDisplayProt\r
4192 );\r
4193 ASSERT_EFI_ERROR (Status);\r
4194\r
06aad9a2
DB
4195 //\r
4196 // Install HII Popup Protocol.\r
4197 //\r
4198 Status = gBS->InstallProtocolInterface (\r
4199 &mPrivateData.Handle,\r
4200 &gEfiHiiPopupProtocolGuid,\r
4201 EFI_NATIVE_INTERFACE,\r
4202 &mPrivateData.HiiPopup\r
4203 );\r
4204 ASSERT_EFI_ERROR (Status);\r
4205\r
7c6c064c 4206 InitializeDisplayStrings();\r
d1102dba 4207\r
5a9f73bf
ED
4208 ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));\r
4209 ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));\r
7c6c064c
ED
4210\r
4211 //\r
4212 // Use BrowserEx2 protocol to register HotKey.\r
d1102dba 4213 //\r
7c6c064c
ED
4214 Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);\r
4215 if (!EFI_ERROR (Status)) {\r
4216 //\r
4217 // Register the default HotKey F9 and F10 again.\r
4218 //\r
4219 HotKey.UnicodeChar = CHAR_NULL;\r
4220 HotKey.ScanCode = SCAN_F10;\r
4221 NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);\r
4222 ASSERT (NewString != NULL);\r
4223 FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);\r
4224\r
4225 HotKey.ScanCode = SCAN_F9;\r
4226 NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);\r
4227 ASSERT (NewString != NULL);\r
4228 FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);\r
4229 }\r
4230\r
4231 return EFI_SUCCESS;\r
4232}\r
4233\r
4234/**\r
4235 This is the default unload handle for display core drivers.\r
4236\r
4237 @param[in] ImageHandle The drivers' driver image.\r
4238\r
4239 @retval EFI_SUCCESS The image is unloaded.\r
4240 @retval Others Failed to unload the image.\r
4241\r
4242**/\r
4243EFI_STATUS\r
4244EFIAPI\r
4245UnloadDisplayEngine (\r
4246 IN EFI_HANDLE ImageHandle\r
4247 )\r
4248{\r
4249 HiiRemovePackages(gHiiHandle);\r
4250\r
4251 FreeDisplayStrings ();\r
4252\r
42645c3d
ED
4253 if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
4254 FreePool (gHighligthMenuInfo.HLTOpCode);\r
4255 }\r
4256\r
4257 if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
4258 FreePool (gHighligthMenuInfo.TOSOpCode);\r
336c8e11
ED
4259 }\r
4260\r
7c6c064c
ED
4261 return EFI_SUCCESS;\r
4262}\r