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