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