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