]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
MdePkg: Refine casting expression result to bigger size
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / FormDisplay.c
CommitLineData
7c6c064c
ED
1/** @file\r
2Entry and initialization module for the browser.\r
3\r
0196c24a 4Copyright (c) 2007 - 2016, 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
543 *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
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
880 Width = (UINT16) gOptionBlockWidth;\r
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
1721 Find the Top of screen menu.\r
1722\r
1723 If the input is NULL, base on the record highlight info in\r
1724 gHighligthMenuInfo to find the last highlight menu.\r
1725\r
1726 @param HighLightedStatement The input highlight statement.\r
1727\r
1728 @retval The highlight menu index.\r
1729\r
1730**/\r
1731LIST_ENTRY *\r
1732FindTopOfScreenMenuOption (\r
1733 VOID\r
1734 )\r
1735{\r
1736 LIST_ENTRY *NewPos;\r
1737 UI_MENU_OPTION *MenuOption;\r
1738\r
1739 NewPos = gMenuOption.ForwardLink;\r
1740 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1741\r
1742 while (!IsTopOfScreeMenuOption(MenuOption)) {\r
1743 NewPos = NewPos->ForwardLink;\r
1744 if (NewPos == &gMenuOption) {\r
1745 //\r
1746 // Not Found it, break\r
1747 //\r
1748 break;\r
1749 }\r
1750 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
1751 }\r
1752\r
1753 //\r
1754 // Last time top of screen menu has disappeared.\r
1755 //\r
1756 if (NewPos == &gMenuOption) {\r
1757 NewPos = NULL;\r
1758 }\r
1759\r
1760 return NewPos;\r
1761}\r
1762\r
7c6c064c
ED
1763/**\r
1764 Find the first menu which will be show at the top.\r
1765\r
1766 @param FormData The data info for this form.\r
1767 @param TopOfScreen The link_entry pointer to top menu.\r
1768 @param HighlightMenu The menu which will be highlight.\r
1769 @param SkipValue The skip value for the top menu.\r
1770\r
1771**/\r
1772VOID\r
1773FindTopMenu (\r
1774 IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
1775 OUT LIST_ENTRY **TopOfScreen,\r
1776 OUT LIST_ENTRY **HighlightMenu,\r
ab369468 1777 OUT UINTN *SkipValue\r
7c6c064c
ED
1778 )\r
1779{\r
7c6c064c
ED
1780 UINTN TopRow;\r
1781 UINTN BottomRow;\r
42645c3d 1782 UI_MENU_OPTION *MenuOption;\r
ab369468 1783 UINTN TmpValue;\r
7c6c064c
ED
1784\r
1785 TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
1786 BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
b2f35637
DB
1787 //\r
1788 // When option mismatch happens,there exist two cases,one is reenter the form, just like the if case below,\r
1789 // and the other is exit current form and enter last form, it can be covered by the else case.\r
1790 //\r
1791 if (gMisMatch && gFormData->HiiHandle == gHighligthMenuInfo.HiiHandle && gFormData->FormId == gHighligthMenuInfo.FormId) {\r
42645c3d
ED
1792 //\r
1793 // Reenter caused by option mismatch or auto exit caused by refresh form(refresh interval/guid), \r
1794 // base on the record highlight info to find the highlight menu.\r
1795 //\r
7c6c064c 1796\r
42645c3d
ED
1797 *HighlightMenu = FindHighLightMenuOption(NULL);\r
1798 if (*HighlightMenu != NULL) {\r
7c6c064c 1799 //\r
42645c3d 1800 // Update skip info for this highlight menu.\r
7c6c064c 1801 //\r
42645c3d
ED
1802 MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
1803 UpdateOptionSkipLines (MenuOption);\r
7c6c064c 1804\r
42645c3d
ED
1805 //\r
1806 // Found the last time highlight menu.\r
1807 //\r
1808 *TopOfScreen = FindTopOfScreenMenuOption();\r
1809 if (*TopOfScreen != NULL) {\r
1810 //\r
1811 // Found the last time selectable top of screen menu.\r
1812 //\r
1813 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
1814 MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);\r
1815 UpdateOptionSkipLines (MenuOption);\r
7c6c064c 1816\r
42645c3d
ED
1817 *SkipValue = gHighligthMenuInfo.SkipValue;\r
1818 } else {\r
336c8e11 1819 //\r
42645c3d
ED
1820 // Not found last time top of screen menu, so base on current highlight menu\r
1821 // to find the new top of screen menu.\r
1822 // Make the current highlight menu at the bottom of the form to calculate the\r
1823 // top of screen menu.\r
336c8e11 1824 //\r
42645c3d
ED
1825 if (MenuOption->Skip >= BottomRow - TopRow) {\r
1826 *TopOfScreen = *HighlightMenu;\r
1827 TmpValue = 0;\r
1828 } else {\r
1829 *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
1830 }\r
1831\r
1832 *SkipValue = TmpValue;\r
336c8e11 1833 }\r
42645c3d
ED
1834 } else {\r
1835 //\r
0a18956d 1836 // Last time highlight menu has disappear, find the first highlightable menu as the default one.\r
42645c3d
ED
1837 //\r
1838 *HighlightMenu = gMenuOption.ForwardLink;\r
1839 if (!IsListEmpty (&gMenuOption)) {\r
1840 MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
1841 }\r
1842 *TopOfScreen = gMenuOption.ForwardLink;\r
1843 *SkipValue = 0;\r
1844 }\r
1845\r
42645c3d
ED
1846 } else if (FormData->HighLightedStatement != NULL) {\r
1847 if (IsSavedHighlightStatement (FormData->HighLightedStatement)) {\r
1848 //\r
1849 // Input highlight menu is same as last time highlight menu.\r
1850 // Base on last time highlight menu to set the top of screen menu and highlight menu.\r
1851 //\r
1852 *HighlightMenu = FindHighLightMenuOption(NULL);\r
1853 ASSERT (*HighlightMenu != NULL);\r
1854\r
1855 //\r
1856 // Update skip info for this highlight menu.\r
1857 //\r
1858 MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
1859 UpdateOptionSkipLines (MenuOption);\r
1860 \r
1861 *TopOfScreen = FindTopOfScreenMenuOption();\r
1862 if (*TopOfScreen == NULL) {\r
336c8e11 1863 //\r
42645c3d
ED
1864 // Not found last time top of screen menu, so base on current highlight menu\r
1865 // to find the new top of screen menu.\r
1866 // Make the current highlight menu at the bottom of the form to calculate the\r
1867 // top of screen menu.\r
336c8e11 1868 //\r
42645c3d
ED
1869 if (MenuOption->Skip >= BottomRow - TopRow) {\r
1870 *TopOfScreen = *HighlightMenu;\r
1871 TmpValue = 0;\r
1872 } else {\r
1873 *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
1874 }\r
1875\r
1876 *SkipValue = TmpValue;\r
1877 } else {\r
1878 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
1879 MenuOption = MENU_OPTION_FROM_LINK (*TopOfScreen);\r
1880 UpdateOptionSkipLines (MenuOption);\r
1881\r
1882 *SkipValue = gHighligthMenuInfo.SkipValue;\r
336c8e11 1883 }\r
42645c3d
ED
1884 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
1885 } else {\r
1886 //\r
1887 // Input highlight menu is not save as last time highlight menu.\r
1888 //\r
1889 *HighlightMenu = FindHighLightMenuOption(FormData->HighLightedStatement);\r
1890 MenuOption = MENU_OPTION_FROM_LINK (*HighlightMenu);\r
1891 UpdateOptionSkipLines (MenuOption);\r
7c6c064c 1892\r
42645c3d
ED
1893 //\r
1894 // Make the current highlight menu at the bottom of the form to calculate the\r
1895 // top of screen menu.\r
1896 //\r
1897 if (MenuOption->Skip >= BottomRow - TopRow) {\r
1898 *TopOfScreen = *HighlightMenu;\r
1899 TmpValue = 0;\r
1900 } else {\r
1901 *TopOfScreen = FindTopOfScreenMenu(*HighlightMenu, BottomRow - TopRow - MenuOption->Skip, &TmpValue);\r
1902 }\r
1903\r
1904 *SkipValue = TmpValue;\r
1905 }\r
1906 AdjustDateAndTimePosition(TRUE, TopOfScreen);\r
7c6c064c 1907 } else {\r
42645c3d
ED
1908 //\r
1909 // If not has input highlight statement, just return the first one in this form.\r
1910 //\r
1911 *TopOfScreen = gMenuOption.ForwardLink;\r
1912 *HighlightMenu = gMenuOption.ForwardLink;\r
1913 if (!IsListEmpty (&gMenuOption)) {\r
1914 MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow, TRUE);\r
1915 }\r
1916 *SkipValue = 0;\r
7c6c064c 1917 }\r
ab2cf8ea 1918\r
b2f35637
DB
1919 gMisMatch = FALSE;\r
1920\r
ab2cf8ea
ED
1921 //\r
1922 // First enter to show the menu, update highlight info.\r
1923 //\r
1924 UpdateHighlightMenuInfo (*HighlightMenu, *TopOfScreen, *SkipValue);\r
7c6c064c
ED
1925}\r
1926\r
af047db7 1927/**\r
42645c3d 1928 Record the highlight menu and top of screen menu info.\r
af047db7 1929\r
42645c3d
ED
1930 @param Highlight The menu opton which is highlight.\r
1931 @param TopOfScreen The menu opton which is at the top of the form.\r
1932 @param SkipValue The skip line info for the top of screen menu.\r
af047db7
ED
1933\r
1934**/\r
1935VOID\r
1936UpdateHighlightMenuInfo (\r
42645c3d
ED
1937 IN LIST_ENTRY *Highlight,\r
1938 IN LIST_ENTRY *TopOfScreen,\r
1939 IN UINTN SkipValue\r
af047db7
ED
1940 )\r
1941{\r
42645c3d 1942 UI_MENU_OPTION *MenuOption;\r
af047db7
ED
1943 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
1944\r
42645c3d
ED
1945 gHighligthMenuInfo.HiiHandle = gFormData->HiiHandle;\r
1946 gHighligthMenuInfo.FormId = gFormData->FormId;\r
1947 gHighligthMenuInfo.SkipValue = (UINT16)SkipValue;\r
af047db7 1948\r
42645c3d
ED
1949 if (!IsListEmpty (&gMenuOption)) {\r
1950 MenuOption = MENU_OPTION_FROM_LINK (Highlight);\r
1951 Statement = MenuOption->ThisTag;\r
af047db7 1952\r
42645c3d 1953 gUserInput->SelectedStatement = Statement;\r
336c8e11 1954\r
42645c3d
ED
1955 gHighligthMenuInfo.HLTSequence = MenuOption->Sequence;\r
1956 gHighligthMenuInfo.HLTQuestionId = GetQuestionIdInfo(Statement->OpCode);\r
1957 if (gHighligthMenuInfo.HLTQuestionId == 0) {\r
1958 //\r
1959 // if question id == 0, save the opcode buffer..\r
1960 //\r
1961 if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
1962 FreePool (gHighligthMenuInfo.HLTOpCode);\r
336c8e11 1963 }\r
42645c3d
ED
1964 gHighligthMenuInfo.HLTOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
1965 ASSERT (gHighligthMenuInfo.HLTOpCode != NULL);\r
1966\r
1967 gHighligthMenuInfo.HLTIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
1968 }\r
1969\r
1970 MenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
1971 Statement = MenuOption->ThisTag;\r
1972\r
1973 gHighligthMenuInfo.TOSQuestionId = GetQuestionIdInfo(Statement->OpCode);\r
1974 if (gHighligthMenuInfo.TOSQuestionId == 0) {\r
1975 //\r
1976 // if question id == 0, save the opcode buffer..\r
1977 //\r
1978 if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
1979 FreePool (gHighligthMenuInfo.TOSOpCode);\r
1980 }\r
1981 gHighligthMenuInfo.TOSOpCode = AllocateCopyPool (Statement->OpCode->Length, Statement->OpCode);\r
1982 ASSERT (gHighligthMenuInfo.TOSOpCode != NULL);\r
1983\r
1984 gHighligthMenuInfo.TOSIndex = GetIndexInfoForOpcode(Statement->OpCode);\r
336c8e11 1985 }\r
af047db7 1986 } else {\r
42645c3d
ED
1987 gUserInput->SelectedStatement = NULL;\r
1988\r
1989 gHighligthMenuInfo.HLTSequence = 0;\r
1990 gHighligthMenuInfo.HLTQuestionId = 0;\r
1991 if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
1992 FreePool (gHighligthMenuInfo.HLTOpCode);\r
336c8e11 1993 }\r
42645c3d
ED
1994 gHighligthMenuInfo.HLTOpCode = NULL;\r
1995 gHighligthMenuInfo.HLTIndex = 0;\r
af047db7 1996\r
42645c3d
ED
1997 gHighligthMenuInfo.TOSQuestionId = 0;\r
1998 if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
1999 FreePool (gHighligthMenuInfo.TOSOpCode);\r
2000 }\r
2001 gHighligthMenuInfo.TOSOpCode = NULL;\r
2002 gHighligthMenuInfo.TOSIndex = 0;\r
2003 }\r
af047db7
ED
2004}\r
2005\r
2006/**\r
2007 Update attribut for this menu.\r
2008\r
2009 @param MenuOption The menu opton which this attribut used to.\r
2010 @param Highlight Whether this menu will be highlight.\r
2011\r
2012**/\r
2013VOID\r
2014SetDisplayAttribute (\r
2015 IN UI_MENU_OPTION *MenuOption,\r
2016 IN BOOLEAN Highlight\r
2017 )\r
2018{\r
2019 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
2020 \r
2021 Statement = MenuOption->ThisTag;\r
2022\r
2023 if (Highlight) {\r
2024 gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
2025 return;\r
2026 }\r
2027\r
2028 if (MenuOption->GrayOut) {\r
2029 gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
2030 } else {\r
2031 if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
2032 gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
2033 } else {\r
2034 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
2035 }\r
2036 }\r
2037}\r
2038\r
2039/**\r
2040 Print string for this menu option.\r
2041\r
2042 @param MenuOption The menu opton which this attribut used to.\r
2043 @param Col The column that this string will be print at.\r
2044 @param Row The row that this string will be print at.\r
2045 @param String The string which need to print.\r
2046 @param Width The width need to print, if string is less than the\r
2047 width, the block space will be used.\r
2048 @param Highlight Whether this menu will be highlight.\r
2049\r
2050**/\r
2051VOID\r
2052DisplayMenuString (\r
2053 IN UI_MENU_OPTION *MenuOption,\r
2054 IN UINTN Col,\r
2055 IN UINTN Row,\r
2056 IN CHAR16 *String,\r
2057 IN UINTN Width,\r
2058 IN BOOLEAN Highlight\r
2059 )\r
2060{\r
2061 UINTN Length;\r
2062\r
2063 //\r
2064 // Print string with normal color.\r
2065 //\r
2066 if (!Highlight) {\r
2067 PrintStringAtWithWidth (Col, Row, String, Width);\r
2068 return;\r
2069 }\r
2070 \r
2071 //\r
2072 // Print the highlight menu string.\r
2073 // First print the highlight string.\r
2074 // \r
2075 SetDisplayAttribute(MenuOption, TRUE);\r
2076 Length = PrintStringAt (Col, Row, String);\r
2077\r
2078 //\r
2079 // Second, clean the empty after the string.\r
2080 //\r
2081 SetDisplayAttribute(MenuOption, FALSE);\r
2082 PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);\r
2083}\r
2084\r
28401a65
ED
2085/**\r
2086 Check whether this menu can has option string.\r
2087\r
2088 @param MenuOption The menu opton which this attribut used to.\r
2089\r
2090 @retval TRUE This menu option can have option string.\r
2091 @retval FALSE This menu option can't have option string.\r
2092\r
2093**/\r
2094BOOLEAN \r
2095HasOptionString (\r
2096 IN UI_MENU_OPTION *MenuOption\r
2097 )\r
2098{\r
2099 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
2100 CHAR16 *String;\r
2101 UINTN Size;\r
2102 EFI_IFR_TEXT *TestOp;\r
2103\r
2104 Size = 0;\r
2105 Statement = MenuOption->ThisTag;\r
2106\r
2107 //\r
2108 // See if the second text parameter is really NULL\r
2109 //\r
2110 if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
2111 TestOp = (EFI_IFR_TEXT *) Statement->OpCode;\r
2112 if (TestOp->TextTwo != 0) {\r
2113 String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);\r
2114 Size = StrLen (String);\r
2115 FreePool (String);\r
2116 }\r
2117 }\r
2118\r
2119 if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
2120 (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||\r
2121 (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||\r
2122 (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||\r
2123 (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||\r
2124 //\r
2125 // Allow a wide display if text op-code and no secondary text op-code\r
2126 //\r
2127 ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))\r
2128 ) {\r
2129\r
2130 return FALSE;\r
2131 }\r
2132\r
2133 return TRUE;\r
2134}\r
2135\r
23c7d425
ED
2136/**\r
2137 Double confirm with user about the action.\r
2138\r
2139 @param Action The user input action.\r
2140\r
2141 @retval TRUE User confirm with the input or not need user confirm.\r
2142 @retval FALSE User want ignore this input.\r
2143\r
2144**/\r
2145BOOLEAN\r
2146FxConfirmPopup (\r
2147 IN UINT32 Action\r
2148 )\r
2149{\r
2150 EFI_INPUT_KEY Key;\r
2151 CHAR16 *CfmStr;\r
2152 UINTN CfmStrLen;\r
2153 UINT32 CheckFlags;\r
2154 BOOLEAN RetVal;\r
2155 UINTN CatLen;\r
5ad66ec6 2156 UINTN MaxLen;\r
23c7d425
ED
2157\r
2158 CfmStrLen = 0;\r
2159 CatLen = StrLen (gConfirmMsgConnect);\r
2160\r
2161 //\r
2162 // Below action need extra popup dialog to confirm.\r
2163 // \r
2164 CheckFlags = BROWSER_ACTION_DISCARD | \r
2165 BROWSER_ACTION_DEFAULT |\r
2166 BROWSER_ACTION_SUBMIT |\r
2167 BROWSER_ACTION_RESET |\r
2168 BROWSER_ACTION_EXIT;\r
2169\r
2170 //\r
2171 // Not need to confirm with user, just return TRUE.\r
2172 //\r
2173 if ((Action & CheckFlags) == 0) {\r
2174 return TRUE;\r
2175 }\r
2176\r
2177 if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
2178 CfmStrLen += StrLen (gConfirmDiscardMsg);\r
2179 } \r
2180\r
2181 if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
2182 if (CfmStrLen != 0) {\r
2183 CfmStrLen += CatLen;\r
2184 } \r
2185\r
2186 CfmStrLen += StrLen (gConfirmDefaultMsg);\r
2187 }\r
2188\r
2189 if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
2190 if (CfmStrLen != 0) {\r
2191 CfmStrLen += CatLen;\r
2192 } \r
2193\r
2194 CfmStrLen += StrLen (gConfirmSubmitMsg);\r
2195 }\r
2196\r
2197 if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
2198 if (CfmStrLen != 0) {\r
2199 CfmStrLen += CatLen;\r
2200 } \r
2201\r
2202 CfmStrLen += StrLen (gConfirmResetMsg);\r
2203 }\r
2204\r
2205 if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
2206 if (CfmStrLen != 0) {\r
2207 CfmStrLen += CatLen;\r
2208 } \r
2209\r
2210 CfmStrLen += StrLen (gConfirmExitMsg);\r
2211 }\r
2212\r
2213 //\r
2214 // Allocate buffer to save the string.\r
2215 // String + "?" + "\0"\r
2216 //\r
5ad66ec6
DB
2217 MaxLen = CfmStrLen + 1 + 1;\r
2218 CfmStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
23c7d425
ED
2219 ASSERT (CfmStr != NULL);\r
2220\r
2221 if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
5ad66ec6 2222 StrCpyS (CfmStr, MaxLen, gConfirmDiscardMsg);\r
23c7d425
ED
2223 }\r
2224\r
2225 if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
2226 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2227 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2228 StrCatS (CfmStr, MaxLen, gConfirmDefaultMsg2nd);\r
23c7d425 2229 } else {\r
5ad66ec6 2230 StrCpyS (CfmStr, MaxLen, gConfirmDefaultMsg);\r
23c7d425
ED
2231 }\r
2232 }\r
2233\r
2234 if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
2235 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2236 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2237 StrCatS (CfmStr, MaxLen, gConfirmSubmitMsg2nd);\r
23c7d425 2238 } else {\r
5ad66ec6 2239 StrCpyS (CfmStr, MaxLen, gConfirmSubmitMsg);\r
23c7d425
ED
2240 }\r
2241 }\r
2242\r
2243 if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
2244 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2245 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2246 StrCatS (CfmStr, MaxLen, gConfirmResetMsg2nd);\r
23c7d425 2247 } else {\r
5ad66ec6 2248 StrCpyS (CfmStr, MaxLen, gConfirmResetMsg);\r
23c7d425
ED
2249 }\r
2250 }\r
2251\r
2252 if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
2253 if (CfmStr[0] != 0) {\r
5ad66ec6
DB
2254 StrCatS (CfmStr, MaxLen, gConfirmMsgConnect);\r
2255 StrCatS (CfmStr, MaxLen, gConfirmExitMsg2nd);\r
23c7d425 2256 } else {\r
5ad66ec6 2257 StrCpyS (CfmStr, MaxLen, gConfirmExitMsg);\r
23c7d425
ED
2258 }\r
2259 }\r
2260\r
5ad66ec6 2261 StrCatS (CfmStr, MaxLen, gConfirmMsgEnd);\r
23c7d425
ED
2262\r
2263 do {\r
2264 CreateDialog (&Key, gEmptyString, CfmStr, gConfirmOpt, gEmptyString, NULL);\r
2265 } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
299c3aec
DB
2266 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (gConfirmOptNo[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
2267 (Key.ScanCode != SCAN_ESC));\r
23c7d425
ED
2268\r
2269 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (gConfirmOptYes[0] | UPPER_LOWER_CASE_OFFSET)) {\r
2270 RetVal = TRUE;\r
2271 } else {\r
2272 RetVal = FALSE;\r
2273 }\r
2274\r
2275 FreePool (CfmStr);\r
2276\r
2277 return RetVal;\r
2278}\r
28401a65 2279\r
af047db7
ED
2280/**\r
2281 Print string for this menu option.\r
2282\r
2283 @param MenuOption The menu opton which this attribut used to.\r
2284 @param SkipWidth The skip width between the left to the start of the prompt.\r
2285 @param BeginCol The begin column for one menu.\r
2286 @param SkipLine The skip line for this menu. \r
2287 @param BottomRow The bottom row for this form.\r
2288 @param Highlight Whether this menu will be highlight.\r
f0c5095b 2289 @param UpdateCol Whether need to update the column info for Date/Time.\r
af047db7
ED
2290\r
2291 @retval EFI_SUCESSS Process the user selection success.\r
2292\r
2293**/\r
2294EFI_STATUS\r
2295DisplayOneMenu (\r
2296 IN UI_MENU_OPTION *MenuOption,\r
2297 IN UINTN SkipWidth,\r
2298 IN UINTN BeginCol,\r
2299 IN UINTN SkipLine,\r
2300 IN UINTN BottomRow,\r
f0c5095b
ED
2301 IN BOOLEAN Highlight,\r
2302 IN BOOLEAN UpdateCol\r
af047db7
ED
2303 )\r
2304{\r
2305 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
2306 UINTN Index;\r
2307 UINT16 Width;\r
2308 UINT16 PromptWidth;\r
2309 CHAR16 *StringPtr;\r
2310 CHAR16 *OptionString;\r
2311 CHAR16 *OutputString;\r
af047db7
ED
2312 UINT16 GlyphWidth;\r
2313 UINTN Temp;\r
2314 UINTN Temp2;\r
2315 UINTN Temp3;\r
2316 EFI_STATUS Status;\r
2317 UINTN Row;\r
8c9c60b6 2318 BOOLEAN IsProcessingFirstRow;\r
af047db7
ED
2319 UINTN Col;\r
2320 UINTN PromptLineNum;\r
28401a65 2321 UINTN OptionLineNum;\r
af047db7 2322 CHAR16 AdjustValue;\r
28401a65 2323 UINTN MaxRow;\r
af047db7
ED
2324\r
2325 Statement = MenuOption->ThisTag;\r
af047db7
ED
2326 Temp = SkipLine;\r
2327 Temp2 = SkipLine;\r
2328 Temp3 = SkipLine;\r
28401a65
ED
2329 AdjustValue = 0;\r
2330 PromptLineNum = 0;\r
2331 OptionLineNum = 0;\r
2332 MaxRow = 0;\r
8c9c60b6 2333 IsProcessingFirstRow = TRUE;\r
af047db7
ED
2334\r
2335 //\r
2336 // Set default color.\r
2337 //\r
2338 SetDisplayAttribute (MenuOption, FALSE);\r
2339\r
2340 //\r
2341 // 1. Paint the option string.\r
2342 //\r
2343 Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);\r
2344 if (EFI_ERROR (Status)) {\r
2345 return Status;\r
2346 }\r
2347\r
2348 if (OptionString != NULL) {\r
2349 if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
2350 //\r
2351 // Adjust option string for date/time opcode.\r
2352 //\r
f0c5095b 2353 ProcessStringForDateTime(MenuOption, OptionString, UpdateCol);\r
af047db7
ED
2354 }\r
2355 \r
2356 Width = (UINT16) gOptionBlockWidth - 1;\r
28401a65 2357 Row = MenuOption->Row;\r
af047db7 2358 GlyphWidth = 1;\r
28401a65 2359 OptionLineNum = 0;\r
af047db7
ED
2360 \r
2361 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
2362 if (((Temp2 == 0)) && (Row <= BottomRow)) {\r
2363 if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
2364 //\r
2365 // For date/time question, it has three menu options for this qustion.\r
2366 // The first/second menu options with the skip value is 0. the last one\r
2367 // with skip value is 1.\r
2368 //\r
2369 if (MenuOption->Skip != 0) {\r
2370 //\r
2371 // For date/ time, print the last past (year for date and second for time)\r
2372 // - 7 means skip [##/##/ for date and [##:##: for time.\r
2373 //\r
2374 DisplayMenuString (MenuOption,MenuOption->OptCol, Row, OutputString, Width + 1 - 7, Highlight);\r
2375 } else {\r
2376 //\r
2377 // For date/ time, print the first and second past (year for date and second for time)\r
f0c5095b
ED
2378 // The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string, \r
2379 // so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it.\r
2380 DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, StrLen (OutputString) - 1, Highlight);\r
af047db7
ED
2381 }\r
2382 } else {\r
2383 DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
2384 }\r
28401a65 2385 OptionLineNum++;\r
af047db7
ED
2386 }\r
2387 \r
2388 //\r
2389 // If there is more string to process print on the next row and increment the Skip value\r
2390 //\r
2391 if (StrLen (&OptionString[Index]) != 0) {\r
2392 if (Temp2 == 0) {\r
2393 Row++;\r
2394 //\r
2395 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
2396 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
2397 // some testing to ensure we are keeping this in-sync.\r
2398 //\r
2399 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
2400 //\r
28401a65 2401 if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
af047db7
ED
2402 MenuOption->Skip++;\r
2403 }\r
2404 }\r
2405 }\r
2406 \r
2407 FreePool (OutputString);\r
2408 if (Temp2 != 0) {\r
2409 Temp2--;\r
2410 }\r
2411 }\r
2412 \r
af047db7
ED
2413 Highlight = FALSE;\r
2414\r
2415 FreePool (OptionString);\r
2416 }\r
af047db7
ED
2417\r
2418 //\r
28401a65 2419 // 2. Paint the description.\r
af047db7 2420 //\r
6f05c023 2421 PromptWidth = GetWidth (MenuOption, &AdjustValue);\r
28401a65 2422 Row = MenuOption->Row;\r
af047db7
ED
2423 GlyphWidth = 1;\r
2424 PromptLineNum = 0;\r
2425\r
2426 if (MenuOption->Description == NULL || MenuOption->Description[0] == '\0') {\r
28401a65
ED
2427 PrintStringAtWithWidth (BeginCol, Row, L"", PromptWidth + AdjustValue + SkipWidth);\r
2428 PromptLineNum++;\r
af047db7
ED
2429 } else {\r
2430 for (Index = 0; GetLineByWidth (MenuOption->Description, PromptWidth, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
2431 if ((Temp == 0) && (Row <= BottomRow)) { \r
2432 //\r
2433 // 1.Clean the start LEFT_SKIPPED_COLUMNS \r
2434 //\r
2435 PrintStringAtWithWidth (BeginCol, Row, L"", SkipWidth);\r
2436 \r
8c9c60b6 2437 if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2 && IsProcessingFirstRow) {\r
af047db7
ED
2438 //\r
2439 // Print Arrow for Goto button.\r
2440 //\r
2441 PrintCharAt (\r
2442 MenuOption->Col - 2,\r
2443 Row,\r
2444 GEOMETRICSHAPE_RIGHT_TRIANGLE\r
2445 );\r
8c9c60b6 2446 IsProcessingFirstRow = FALSE;\r
af047db7
ED
2447 }\r
2448 DisplayMenuString (MenuOption, MenuOption->Col, Row, OutputString, PromptWidth + AdjustValue, Highlight);\r
2449 PromptLineNum ++;\r
2450 }\r
2451 //\r
2452 // If there is more string to process print on the next row and increment the Skip value\r
2453 //\r
2454 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
2455 if (Temp == 0) {\r
2456 Row++;\r
2457 }\r
2458 }\r
2459\r
2460 FreePool (OutputString);\r
2461 if (Temp != 0) {\r
2462 Temp--;\r
2463 }\r
2464 }\r
2465\r
2466 Highlight = FALSE;\r
af047db7 2467 }\r
af047db7
ED
2468\r
2469\r
2470 //\r
28401a65 2471 // 3. If this is a text op with secondary text information\r
af047db7
ED
2472 //\r
2473 if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
2474 StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
2475 \r
2476 Width = (UINT16) gOptionBlockWidth - 1;\r
28401a65 2477 Row = MenuOption->Row;\r
af047db7 2478 GlyphWidth = 1;\r
28401a65 2479 OptionLineNum = 0;\r
af047db7
ED
2480\r
2481 for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { \r
2482 if ((Temp3 == 0) && (Row <= BottomRow)) {\r
2483 DisplayMenuString (MenuOption, MenuOption->OptCol, Row, OutputString, Width + 1, Highlight);\r
28401a65 2484 OptionLineNum++;\r
af047db7
ED
2485 }\r
2486 //\r
2487 // If there is more string to process print on the next row and increment the Skip value\r
2488 //\r
2489 if (StrLen (&StringPtr[Index]) != 0) {\r
2490 if (Temp3 == 0) {\r
2491 Row++;\r
a6a2a956
ED
2492 //\r
2493 // If the rows for text two is greater than or equal to the skip value, increase the skip value\r
2494 //\r
2495 if ((Row - MenuOption->Row) >= MenuOption->Skip) {\r
2496 MenuOption->Skip++;\r
2497 }\r
af047db7
ED
2498 }\r
2499 }\r
2500 \r
2501 FreePool (OutputString);\r
2502 if (Temp3 != 0) {\r
2503 Temp3--;\r
2504 }\r
2505 }\r
28401a65 2506\r
af047db7
ED
2507 FreePool (StringPtr);\r
2508 }\r
2509\r
28401a65
ED
2510 //\r
2511 // 4.Line number for Option string and prompt string are not equal.\r
2512 // Clean the column whose line number is less.\r
2513 //\r
2514 if (HasOptionString(MenuOption) && (OptionLineNum != PromptLineNum)) {\r
2515 Col = OptionLineNum < PromptLineNum ? MenuOption->OptCol : BeginCol;\r
2516 Row = (OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum) + MenuOption->Row;\r
2517 Width = (UINT16) (OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth);\r
2518 MaxRow = (OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum) + MenuOption->Row - 1;\r
2519 \r
2520 while (Row <= MaxRow) {\r
2521 DisplayMenuString (MenuOption, Col, Row++, L"", Width, FALSE);\r
2522 }\r
2523 }\r
2524\r
af047db7
ED
2525 return EFI_SUCCESS;\r
2526}\r
2527\r
7c6c064c
ED
2528/**\r
2529 Display menu and wait for user to select one menu option, then return it.\r
2530 If AutoBoot is enabled, then if user doesn't select any option,\r
2531 after period of time, it will automatically return the first menu option.\r
2532\r
2533 @param FormData The current form data info.\r
2534\r
2535 @retval EFI_SUCESSS Process the user selection success.\r
2536 @retval EFI_NOT_FOUND Process option string for orderedlist/Oneof fail.\r
2537\r
2538**/\r
2539EFI_STATUS\r
2540UiDisplayMenu (\r
2541 IN FORM_DISPLAY_ENGINE_FORM *FormData\r
2542 )\r
2543{\r
ab369468 2544 UINTN SkipValue;\r
7c6c064c
ED
2545 INTN Difference;\r
2546 UINTN DistanceValue;\r
2547 UINTN Row;\r
2548 UINTN Col;\r
7c6c064c
ED
2549 UINTN Temp;\r
2550 UINTN Temp2;\r
7c6c064c
ED
2551 UINTN TopRow;\r
2552 UINTN BottomRow;\r
7c6c064c 2553 UINTN Index;\r
7c6c064c 2554 CHAR16 *StringPtr;\r
cc63add8
DB
2555 CHAR16 *StringRightPtr;\r
2556 CHAR16 *StringErrorPtr;\r
7c6c064c 2557 CHAR16 *OptionString;\r
7c6c064c
ED
2558 CHAR16 *HelpString;\r
2559 CHAR16 *HelpHeaderString;\r
2560 CHAR16 *HelpBottomString;\r
2561 BOOLEAN NewLine;\r
2562 BOOLEAN Repaint;\r
2563 BOOLEAN UpArrow;\r
2564 BOOLEAN DownArrow;\r
2565 EFI_STATUS Status;\r
2566 EFI_INPUT_KEY Key;\r
2567 LIST_ENTRY *Link;\r
2568 LIST_ENTRY *NewPos;\r
2569 LIST_ENTRY *TopOfScreen;\r
2570 LIST_ENTRY *SavedListEntry;\r
2571 UI_MENU_OPTION *MenuOption;\r
2572 UI_MENU_OPTION *NextMenuOption;\r
2573 UI_MENU_OPTION *SavedMenuOption;\r
7c6c064c
ED
2574 UI_CONTROL_FLAG ControlFlag;\r
2575 UI_SCREEN_OPERATION ScreenOperation;\r
7c6c064c 2576 FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
7c6c064c
ED
2577 BROWSER_HOT_KEY *HotKey;\r
2578 UINTN HelpPageIndex;\r
2579 UINTN HelpPageCount;\r
2580 UINTN RowCount;\r
2581 UINTN HelpLine;\r
2582 UINTN HelpHeaderLine;\r
2583 UINTN HelpBottomLine;\r
2584 BOOLEAN MultiHelpPage;\r
7c6c064c
ED
2585 UINT16 EachLineWidth;\r
2586 UINT16 HeaderLineWidth;\r
2587 UINT16 BottomLineWidth;\r
2588 EFI_STRING_ID HelpInfo;\r
2589 UI_EVENT_TYPE EventType;\r
af047db7 2590 BOOLEAN SkipHighLight;\r
cc63add8 2591 EFI_HII_VALUE *StatementValue;\r
7c6c064c
ED
2592\r
2593 EventType = UIEventNone;\r
2594 Status = EFI_SUCCESS;\r
2595 HelpString = NULL;\r
2596 HelpHeaderString = NULL;\r
2597 HelpBottomString = NULL;\r
2598 OptionString = NULL;\r
2599 ScreenOperation = UiNoOperation;\r
2600 NewLine = TRUE;\r
7c6c064c
ED
2601 HelpPageCount = 0;\r
2602 HelpLine = 0;\r
2603 RowCount = 0;\r
2604 HelpBottomLine = 0;\r
2605 HelpHeaderLine = 0;\r
2606 HelpPageIndex = 0;\r
2607 MultiHelpPage = FALSE;\r
2608 EachLineWidth = 0;\r
2609 HeaderLineWidth = 0;\r
2610 BottomLineWidth = 0;\r
7c6c064c
ED
2611 UpArrow = FALSE;\r
2612 DownArrow = FALSE;\r
2613 SkipValue = 0;\r
af047db7 2614 SkipHighLight = FALSE;\r
7c6c064c
ED
2615\r
2616 NextMenuOption = NULL;\r
7c6c064c
ED
2617 SavedMenuOption = NULL;\r
2618 HotKey = NULL;\r
2619 Repaint = TRUE;\r
2620 MenuOption = NULL;\r
af047db7 2621 gModalSkipColumn = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6;\r
7c6c064c
ED
2622\r
2623 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
2624\r
7c6c064c
ED
2625 TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
2626 BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;\r
2627\r
2628 Row = TopRow;\r
2629 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
af047db7 2630 Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gModalSkipColumn;\r
7c6c064c
ED
2631 } else {\r
2632 Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS;\r
2633 }\r
2634\r
2635 FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue);\r
42645c3d
ED
2636 if (!IsListEmpty (&gMenuOption)) {\r
2637 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2638 gUserInput->SelectedStatement = NextMenuOption->ThisTag;\r
2639 }\r
7c6c064c
ED
2640\r
2641 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
2642\r
2643 ControlFlag = CfInitialization;\r
2644 while (TRUE) {\r
2645 switch (ControlFlag) {\r
2646 case CfInitialization:\r
af047db7
ED
2647 if ((gOldFormEntry.HiiHandle != FormData->HiiHandle) || \r
2648 (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))) {\r
2649 //\r
2650 // Clear Statement range if different formset is painted.\r
2651 //\r
2652 ClearLines (\r
2653 gStatementDimensions.LeftColumn,\r
2654 gStatementDimensions.RightColumn,\r
2655 TopRow - SCROLL_ARROW_HEIGHT,\r
2656 BottomRow + SCROLL_ARROW_HEIGHT,\r
2657 GetFieldTextColor ()\r
2658 );\r
7c6c064c 2659\r
7c6c064c 2660 }\r
af047db7 2661 ControlFlag = CfRepaint;\r
7c6c064c
ED
2662 break;\r
2663\r
2664 case CfRepaint:\r
2665 ControlFlag = CfRefreshHighLight;\r
2666\r
2667 if (Repaint) {\r
2668 //\r
2669 // Display menu\r
2670 //\r
2671 DownArrow = FALSE;\r
2672 UpArrow = FALSE;\r
2673 Row = TopRow;\r
2674\r
af047db7
ED
2675 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
2676 \r
7c6c064c 2677 //\r
af047db7 2678 // 1. Check whether need to print the arrow up.\r
7c6c064c 2679 //\r
af047db7
ED
2680 if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
2681 UpArrow = TRUE;\r
2682 }\r
af047db7 2683\r
ae4f5746
ED
2684 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
2685 PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);\r
2686 } else {\r
2687 PrintStringAtWithWidth(gStatementDimensions.LeftColumn, TopRow - 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
2688 }\r
af047db7
ED
2689 if (UpArrow) {\r
2690 gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
2691 PrintCharAt (\r
2692 gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
7c6c064c 2693 TopRow - SCROLL_ARROW_HEIGHT,\r
af047db7 2694 ARROW_UP\r
7c6c064c 2695 );\r
af047db7 2696 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
7c6c064c
ED
2697 }\r
2698\r
2699 //\r
2700 // 2.Paint the menu.\r
2701 //\r
2702 for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {\r
2703 MenuOption = MENU_OPTION_FROM_LINK (Link);\r
2704 MenuOption->Row = Row;\r
2705 MenuOption->Col = Col;\r
2706 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
af047db7 2707 MenuOption->OptCol = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth + gModalSkipColumn;\r
7c6c064c 2708 } else {\r
af047db7 2709 MenuOption->OptCol = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth;\r
7c6c064c
ED
2710 }\r
2711\r
7c6c064c
ED
2712 if (MenuOption->NestInStatement) {\r
2713 MenuOption->Col += SUBTITLE_INDENT;\r
2714 }\r
2715\r
7c6c064c 2716 //\r
af047db7 2717 // Save the highlight menu, will be used in CfRefreshHighLight case.\r
7c6c064c 2718 //\r
af047db7
ED
2719 if (Link == NewPos) {\r
2720 SavedMenuOption = MenuOption;\r
2721 SkipHighLight = TRUE;\r
7c6c064c 2722 }\r
ae4f5746
ED
2723\r
2724 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
72f2eca2 2725 Status = DisplayOneMenu (MenuOption, \r
6f05c023 2726 MenuOption->Col - gStatementDimensions.LeftColumn,\r
ae4f5746
ED
2727 gStatementDimensions.LeftColumn + gModalSkipColumn, \r
2728 Link == TopOfScreen ? SkipValue : 0, \r
2729 BottomRow,\r
f0c5095b
ED
2730 (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
2731 TRUE\r
ae4f5746
ED
2732 );\r
2733 } else {\r
72f2eca2 2734 Status = DisplayOneMenu (MenuOption, \r
6f05c023 2735 MenuOption->Col - gStatementDimensions.LeftColumn,\r
ae4f5746
ED
2736 gStatementDimensions.LeftColumn, \r
2737 Link == TopOfScreen ? SkipValue : 0, \r
2738 BottomRow,\r
f0c5095b
ED
2739 (BOOLEAN) ((Link == NewPos) && IsSelectable(MenuOption)),\r
2740 TRUE\r
2741 );\r
ae4f5746 2742 }\r
7c6c064c 2743\r
72f2eca2 2744 if (EFI_ERROR (Status)) {\r
42645c3d
ED
2745 if (gMisMatch) {\r
2746 return EFI_SUCCESS;\r
2747 } else {\r
2748 return Status;\r
2749 }\r
72f2eca2 2750 }\r
7c6c064c
ED
2751 //\r
2752 // 3. Update the row info which will be used by next menu.\r
2753 //\r
2754 if (Link == TopOfScreen) {\r
2755 Row += MenuOption->Skip - SkipValue;\r
2756 } else {\r
2757 Row += MenuOption->Skip;\r
2758 }\r
2759\r
2760 if (Row > BottomRow) {\r
2761 if (!ValueIsScroll (FALSE, Link)) {\r
2762 DownArrow = TRUE;\r
2763 }\r
2764\r
2765 Row = BottomRow + 1;\r
2766 break;\r
2767 }\r
2768 }\r
2769\r
af047db7
ED
2770 //\r
2771 // 3. Menus in this form may not cover all form, clean the remain field.\r
2772 //\r
2773 while (Row <= BottomRow) {\r
2774 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
ae4f5746 2775 PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, Row++, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * gModalSkipColumn);\r
af047db7
ED
2776 } else {\r
2777 PrintStringAtWithWidth(gStatementDimensions.LeftColumn, Row++, L"", gStatementDimensions.RightColumn - gHelpBlockWidth - gStatementDimensions.LeftColumn);\r
2778 }\r
7c6c064c
ED
2779 }\r
2780\r
af047db7
ED
2781 //\r
2782 // 4. Print the down arrow row.\r
2783 //\r
ae4f5746
ED
2784 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
2785 PrintStringAtWithWidth(gStatementDimensions.LeftColumn + gModalSkipColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * + gModalSkipColumn);\r
2786 } else {\r
2787 PrintStringAtWithWidth(gStatementDimensions.LeftColumn, BottomRow + 1, L"", gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn);\r
2788 }\r
7c6c064c
ED
2789 if (DownArrow) {\r
2790 gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
2791 PrintCharAt (\r
2792 gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
2793 BottomRow + SCROLL_ARROW_HEIGHT,\r
2794 ARROW_DOWN\r
2795 );\r
2796 gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
2797 }\r
2798\r
2799 MenuOption = NULL;\r
2800 }\r
2801 break;\r
2802\r
2803 case CfRefreshHighLight:\r
2804\r
2805 //\r
2806 // MenuOption: Last menu option that need to remove hilight\r
2807 // MenuOption is set to NULL in Repaint\r
2808 // NewPos: Current menu option that need to hilight\r
2809 //\r
2810 ControlFlag = CfUpdateHelpString;\r
2811\r
42645c3d
ED
2812 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
2813\r
af047db7 2814 if (SkipHighLight) {\r
af047db7 2815 SkipHighLight = FALSE;\r
42645c3d
ED
2816 MenuOption = SavedMenuOption;\r
2817 RefreshKeyHelp(gFormData, SavedMenuOption->ThisTag, FALSE);\r
af047db7
ED
2818 break;\r
2819 }\r
2820\r
8924aecd
ED
2821 if (IsListEmpty (&gMenuOption)) {\r
2822 //\r
2823 // No menu option, just update the hotkey filed.\r
2824 //\r
2825 RefreshKeyHelp(gFormData, NULL, FALSE);\r
2826 break;\r
2827 }\r
2828\r
7c6c064c
ED
2829 if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) {\r
2830 Temp = SkipValue;\r
2831 } else {\r
2832 Temp = 0;\r
2833 }\r
2834 if (NewPos == TopOfScreen) {\r
2835 Temp2 = SkipValue;\r
2836 } else {\r
2837 Temp2 = 0;\r
2838 }\r
2839\r
2840 if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
2841 if (MenuOption != NULL) {\r
2842 //\r
ab369468 2843 // Remove the old highlight menu.\r
7c6c064c 2844 //\r
ab369468
ED
2845 Status = DisplayOneMenu (MenuOption, \r
2846 MenuOption->Col - gStatementDimensions.LeftColumn,\r
2847 gStatementDimensions.LeftColumn, \r
2848 Temp, \r
2849 BottomRow,\r
f0c5095b 2850 FALSE,\r
ab369468
ED
2851 FALSE\r
2852 );\r
7c6c064c
ED
2853 }\r
2854\r
2855 //\r
2856 // This is the current selected statement\r
2857 //\r
2858 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
42645c3d 2859 RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE);\r
7c6c064c
ED
2860\r
2861 if (!IsSelectable (MenuOption)) {\r
7c6c064c
ED
2862 break;\r
2863 }\r
2864\r
ab369468
ED
2865 Status = DisplayOneMenu (MenuOption, \r
2866 MenuOption->Col - gStatementDimensions.LeftColumn,\r
2867 gStatementDimensions.LeftColumn, \r
2868 Temp2, \r
2869 BottomRow,\r
f0c5095b
ED
2870 TRUE,\r
2871 FALSE\r
ab369468 2872 );\r
7c6c064c
ED
2873 }\r
2874 break;\r
2875\r
2876 case CfUpdateHelpString:\r
2877 ControlFlag = CfPrepareToReadKey;\r
2878 if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
2879 break;\r
2880 }\r
2881\r
ab369468
ED
2882 //\r
2883 // NewLine means only update highlight menu (remove old highlight and highlith\r
2884 // the new one), not need to full repain the form.\r
2885 //\r
7c6c064c 2886 if (Repaint || NewLine) {\r
8924aecd
ED
2887 if (IsListEmpty (&gMenuOption)) {\r
2888 //\r
2889 // Don't print anything if no mwnu option.\r
2890 //\r
7c6c064c
ED
2891 StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2892 } else {\r
8924aecd
ED
2893 //\r
2894 // Don't print anything if it is a NULL help token\r
2895 //\r
2896 ASSERT(MenuOption != NULL);\r
2897 HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
cc63add8
DB
2898 Statement = MenuOption->ThisTag;\r
2899 StatementValue = &Statement->CurrentValue;\r
8924aecd 2900 if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
cc63add8
DB
2901 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
2902 StringPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);\r
2903 } else {\r
2904 StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
2905 }\r
8924aecd 2906 } else {\r
cc63add8
DB
2907 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
2908 StringRightPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
2909 StringErrorPtr = GetToken (STRING_TOKEN (GET_TIME_FAIL), gHiiHandle);\r
2910 StringPtr = AllocateZeroPool ((StrLen (StringRightPtr) + StrLen (StringErrorPtr)+ 1 ) * sizeof (CHAR16));\r
2911 StrCpyS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringRightPtr);\r
2912 StrCatS (StringPtr, StrLen (StringRightPtr) + StrLen (StringErrorPtr) + 1, StringErrorPtr);\r
2913 FreePool (StringRightPtr);\r
2914 FreePool (StringErrorPtr);\r
2915 } else {\r
2916 StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
2917 }\r
8924aecd 2918 }\r
7c6c064c
ED
2919 }\r
2920\r
2921 RowCount = BottomRow - TopRow + 1;\r
2922 HelpPageIndex = 0;\r
2923 //\r
2924 // 1.Calculate how many line the help string need to print.\r
2925 //\r
2926 if (HelpString != NULL) {\r
2927 FreePool (HelpString);\r
2928 HelpString = NULL;\r
2929 }\r
2930 HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
2931 FreePool (StringPtr);\r
2932\r
2933 if (HelpLine > RowCount) {\r
2934 MultiHelpPage = TRUE;\r
2935 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
2936 if (HelpHeaderString != NULL) {\r
2937 FreePool (HelpHeaderString);\r
2938 HelpHeaderString = NULL;\r
2939 }\r
2940 HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, 0);\r
2941 FreePool (StringPtr);\r
2942 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
2943 if (HelpBottomString != NULL) {\r
2944 FreePool (HelpBottomString);\r
2945 HelpBottomString = NULL;\r
2946 }\r
2947 HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, 0);\r
2948 FreePool (StringPtr);\r
2949 //\r
2950 // Calculate the help page count.\r
2951 //\r
2952 if (HelpLine > 2 * RowCount - 2) {\r
2953 HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
92f62cfe 2954 if ((HelpLine - RowCount + 1) % (RowCount - 2) != 0) {\r
7c6c064c
ED
2955 HelpPageCount += 1;\r
2956 }\r
2957 } else {\r
2958 HelpPageCount = 2;\r
2959 }\r
2960 } else {\r
2961 MultiHelpPage = FALSE;\r
2962 }\r
2963 }\r
2964\r
2965 //\r
2966 // Check whether need to show the 'More(U/u)' at the begin.\r
2967 // Base on current direct info, here shows aligned to the right side of the column.\r
2968 // If the direction is multi line and aligned to right side may have problem, so \r
2969 // add ASSERT code here.\r
2970 //\r
2971 if (HelpPageIndex > 0) {\r
2972 gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
2973 for (Index = 0; Index < HelpHeaderLine; Index++) {\r
2974 ASSERT (HelpHeaderLine == 1);\r
2975 ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
2976 PrintStringAtWithWidth (\r
2977 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
2978 Index + TopRow,\r
2979 gEmptyString,\r
2980 gHelpBlockWidth\r
2981 );\r
2982 PrintStringAt (\r
2983 gStatementDimensions.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
2984 Index + TopRow,\r
2985 &HelpHeaderString[Index * HeaderLineWidth]\r
2986 );\r
2987 }\r
2988 }\r
2989\r
2990 gST->ConOut->SetAttribute (gST->ConOut, GetHelpTextColor ());\r
2991 //\r
2992 // Print the help string info.\r
2993 //\r
2994 if (!MultiHelpPage) {\r
2995 for (Index = 0; Index < HelpLine; Index++) {\r
2996 PrintStringAtWithWidth (\r
2997 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
2998 Index + TopRow,\r
2999 &HelpString[Index * EachLineWidth],\r
3000 gHelpBlockWidth\r
3001 );\r
3002 }\r
3003 for (; Index < RowCount; Index ++) {\r
3004 PrintStringAtWithWidth (\r
3005 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3006 Index + TopRow,\r
3007 gEmptyString,\r
3008 gHelpBlockWidth\r
3009 );\r
3010 }\r
3011 gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);\r
3012 } else {\r
3013 if (HelpPageIndex == 0) {\r
3014 for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
3015 PrintStringAtWithWidth (\r
3016 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3017 Index + TopRow,\r
3018 &HelpString[Index * EachLineWidth],\r
3019 gHelpBlockWidth\r
3020 );\r
3021 }\r
3022 } else {\r
3023 for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && \r
3024 (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
3025 PrintStringAtWithWidth (\r
3026 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3027 Index + TopRow + HelpHeaderLine,\r
3028 &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth],\r
3029 gHelpBlockWidth\r
3030 );\r
3031 }\r
3032 if (HelpPageIndex == HelpPageCount - 1) {\r
3033 for (; Index < RowCount - HelpHeaderLine; Index ++) {\r
3034 PrintStringAtWithWidth (\r
3035 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3036 Index + TopRow + HelpHeaderLine,\r
3037 gEmptyString,\r
3038 gHelpBlockWidth\r
3039 );\r
3040 }\r
3041 gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);\r
3042 }\r
3043 } \r
3044 }\r
3045\r
3046 //\r
3047 // Check whether need to print the 'More(D/d)' at the bottom.\r
3048 // Base on current direct info, here shows aligned to the right side of the column.\r
3049 // If the direction is multi line and aligned to right side may have problem, so \r
3050 // add ASSERT code here.\r
3051 //\r
3052 if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
3053 gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
3054 for (Index = 0; Index < HelpBottomLine; Index++) {\r
3055 ASSERT (HelpBottomLine == 1);\r
3056 ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
3057 PrintStringAtWithWidth (\r
3058 gStatementDimensions.RightColumn - gHelpBlockWidth,\r
3059 BottomRow + Index - HelpBottomLine + 1,\r
3060 gEmptyString,\r
3061 gHelpBlockWidth\r
3062 );\r
3063 PrintStringAt (\r
3064 gStatementDimensions.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
3065 BottomRow + Index - HelpBottomLine + 1,\r
3066 &HelpBottomString[Index * BottomLineWidth]\r
3067 );\r
3068 }\r
3069 }\r
3070 //\r
3071 // Reset this flag every time we finish using it.\r
3072 //\r
3073 Repaint = FALSE;\r
3074 NewLine = FALSE;\r
3075 break;\r
3076\r
3077 case CfPrepareToReadKey:\r
3078 ControlFlag = CfReadKey;\r
3079 ScreenOperation = UiNoOperation;\r
3080 break;\r
3081\r
3082 case CfReadKey:\r
3083 ControlFlag = CfScreenOperation;\r
3084\r
3085 //\r
3086 // Wait for user's selection\r
3087 //\r
3088 while (TRUE) {\r
3089 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3090 if (!EFI_ERROR (Status)) {\r
3091 EventType = UIEventKey;\r
3092 break;\r
3093 }\r
3094\r
3095 //\r
3096 // If we encounter error, continue to read another key in.\r
3097 //\r
3098 if (Status != EFI_NOT_READY) {\r
3099 continue;\r
3100 }\r
3101 \r
3102 EventType = UiWaitForEvent(gST->ConIn->WaitForKey);\r
3103 if (EventType == UIEventKey) {\r
3104 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3105 }\r
3106 break;\r
3107 }\r
3108\r
3109 if (EventType == UIEventDriver) {\r
42645c3d 3110 gMisMatch = TRUE;\r
7c6c064c
ED
3111 gUserInput->Action = BROWSER_ACTION_NONE;\r
3112 ControlFlag = CfExit;\r
3113 break;\r
3114 }\r
3115 \r
3116 if (EventType == UIEventTimeOut) {\r
3117 gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
3118 ControlFlag = CfExit;\r
3119 break;\r
3120 }\r
3121\r
3122 switch (Key.UnicodeChar) {\r
3123 case CHAR_CARRIAGE_RETURN:\r
3124 if(MenuOption == NULL || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
3125 ControlFlag = CfReadKey;\r
3126 break;\r
3127 }\r
3128\r
3129 ScreenOperation = UiSelect;\r
3130 gDirection = 0;\r
3131 break;\r
3132\r
3133 //\r
3134 // We will push the adjustment of these numeric values directly to the input handler\r
3135 // NOTE: we won't handle manual input numeric\r
3136 //\r
3137 case '+':\r
3138 case '-':\r
3139 //\r
3140 // If the screen has no menu items, and the user didn't select UiReset\r
3141 // ignore the selection and go back to reading keys.\r
3142 //\r
05de47ef 3143 ASSERT(MenuOption != NULL);\r
7c6c064c
ED
3144 if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
3145 ControlFlag = CfReadKey;\r
3146 break;\r
3147 }\r
3148\r
7c6c064c
ED
3149 Statement = MenuOption->ThisTag;\r
3150 if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)\r
3151 || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)\r
3152 || ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (GetFieldFromNum(Statement->OpCode) != 0))\r
3153 ){\r
3154 if (Key.UnicodeChar == '+') {\r
3155 gDirection = SCAN_RIGHT;\r
3156 } else {\r
3157 gDirection = SCAN_LEFT;\r
3158 }\r
3159 \r
3160 Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
3161 if (OptionString != NULL) {\r
3162 FreePool (OptionString);\r
3163 }\r
3164 if (EFI_ERROR (Status)) {\r
3165 //\r
3166 // Repaint to clear possible error prompt pop-up\r
3167 //\r
3168 Repaint = TRUE;\r
3169 NewLine = TRUE;\r
3170 } else {\r
3171 ControlFlag = CfExit;\r
3172 }\r
3173 }\r
3174 break;\r
3175\r
3176 case '^':\r
3177 ScreenOperation = UiUp;\r
3178 break;\r
3179\r
3180 case 'V':\r
3181 case 'v':\r
3182 ScreenOperation = UiDown;\r
3183 break;\r
3184\r
3185 case ' ':\r
3186 if(IsListEmpty (&gMenuOption)) {\r
3187 ControlFlag = CfReadKey;\r
3188 break;\r
3189 }\r
3190 \r
3191 ASSERT(MenuOption != NULL);\r
3192 if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {\r
3193 ScreenOperation = UiSelect;\r
3194 }\r
3195 break;\r
3196\r
3197 case 'D':\r
3198 case 'd':\r
3199 if (!MultiHelpPage) {\r
3200 ControlFlag = CfReadKey;\r
3201 break;\r
3202 }\r
3203 ControlFlag = CfUpdateHelpString;\r
3204 HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;\r
3205 break;\r
3206\r
3207 case 'U':\r
3208 case 'u':\r
3209 if (!MultiHelpPage) {\r
3210 ControlFlag = CfReadKey;\r
3211 break;\r
3212 }\r
3213 ControlFlag = CfUpdateHelpString;\r
3214 HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;\r
3215 break;\r
3216\r
3217 case CHAR_NULL:\r
3218 for (Index = 0; Index < mScanCodeNumber; Index++) {\r
3219 if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
3220 ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
3221 break;\r
3222 }\r
3223 }\r
3224 \r
3225 if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {\r
3226 //\r
3227 // ModalForm has no ESC key and Hot Key.\r
3228 //\r
3229 ControlFlag = CfReadKey;\r
3230 } else if (Index == mScanCodeNumber) {\r
3231 //\r
3232 // Check whether Key matches the registered hot key.\r
3233 //\r
3234 HotKey = NULL;\r
3235 HotKey = GetHotKeyFromRegisterList (&Key);\r
3236 if (HotKey != NULL) {\r
3237 ScreenOperation = UiHotKey;\r
3238 }\r
3239 }\r
3240 break;\r
3241 }\r
3242 break;\r
3243\r
3244 case CfScreenOperation:\r
8924aecd 3245 if ((ScreenOperation != UiReset) && (ScreenOperation != UiHotKey)) {\r
7c6c064c 3246 //\r
8924aecd 3247 // If the screen has no menu items, and the user didn't select UiReset or UiHotKey\r
7c6c064c
ED
3248 // ignore the selection and go back to reading keys.\r
3249 //\r
3250 if (IsListEmpty (&gMenuOption)) {\r
3251 ControlFlag = CfReadKey;\r
3252 break;\r
3253 }\r
3254 }\r
3255\r
3256 for (Index = 0;\r
bce1d8a8 3257 Index < ARRAY_SIZE (gScreenOperationToControlFlag);\r
7c6c064c
ED
3258 Index++\r
3259 ) {\r
3260 if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
3261 ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
3262 break;\r
3263 }\r
3264 }\r
3265 break;\r
3266\r
3267 case CfUiSelect:\r
3268 ControlFlag = CfRepaint;\r
3269\r
3270 ASSERT(MenuOption != NULL);\r
3271 Statement = MenuOption->ThisTag;\r
3272 if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
3273 break;\r
3274 }\r
3275\r
3276 switch (Statement->OpCode->OpCode) {\r
3277 case EFI_IFR_REF_OP:\r
3278 case EFI_IFR_ACTION_OP:\r
3279 case EFI_IFR_RESET_BUTTON_OP:\r
3280 ControlFlag = CfExit;\r
3281 break;\r
3282\r
3283 default:\r
3284 //\r
3285 // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
3286 //\r
3287 RefreshKeyHelp (gFormData, Statement, TRUE);\r
3288 Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
3289 \r
3290 if (OptionString != NULL) {\r
3291 FreePool (OptionString);\r
3292 }\r
3293 \r
3294 if (EFI_ERROR (Status)) {\r
3295 Repaint = TRUE;\r
3296 NewLine = TRUE;\r
3297 RefreshKeyHelp (gFormData, Statement, FALSE);\r
3298 break;\r
3299 } else {\r
3300 ControlFlag = CfExit;\r
3301 break;\r
3302 }\r
3303 }\r
3304 break;\r
3305\r
3306 case CfUiReset:\r
3307 //\r
3308 // We come here when someone press ESC\r
3309 // If the policy is not exit front page when user press ESC, process here.\r
3310 //\r
3311 if (!FormExitPolicy()) {\r
3312 Repaint = TRUE;\r
3313 NewLine = TRUE;\r
3314 ControlFlag = CfRepaint;\r
3315 break;\r
3316 }\r
3317\r
7c6c064c
ED
3318 gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
3319 ControlFlag = CfExit;\r
3320 break;\r
3321\r
3322 case CfUiHotKey:\r
3323 ControlFlag = CfRepaint;\r
05de47ef
ED
3324\r
3325 ASSERT (HotKey != NULL);\r
23c7d425
ED
3326\r
3327 if (FxConfirmPopup(HotKey->Action)) {\r
3328 gUserInput->Action = HotKey->Action;\r
a687a1d2
ED
3329 if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
3330 gUserInput->DefaultId = HotKey->DefaultId;\r
3331 }\r
23c7d425
ED
3332 ControlFlag = CfExit;\r
3333 } else {\r
3334 Repaint = TRUE;\r
3335 NewLine = TRUE;\r
3336 ControlFlag = CfRepaint;\r
3337 }\r
3338\r
7c6c064c
ED
3339 break;\r
3340\r
3341 case CfUiLeft:\r
3342 ControlFlag = CfRepaint;\r
3343 ASSERT(MenuOption != NULL);\r
3344 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
3345 if (MenuOption->Sequence != 0) {\r
3346 //\r
3347 // In the middle or tail of the Date/Time op-code set, go left.\r
3348 //\r
3349 ASSERT(NewPos != NULL);\r
3350 NewPos = NewPos->BackLink;\r
3351 }\r
3352 }\r
3353 break;\r
3354\r
3355 case CfUiRight:\r
3356 ControlFlag = CfRepaint;\r
3357 ASSERT(MenuOption != NULL);\r
3358 if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
3359 if (MenuOption->Sequence != 2) {\r
3360 //\r
3361 // In the middle or tail of the Date/Time op-code set, go left.\r
3362 //\r
3363 ASSERT(NewPos != NULL);\r
3364 NewPos = NewPos->ForwardLink;\r
3365 }\r
3366 }\r
3367 break;\r
3368\r
3369 case CfUiUp:\r
3370 ControlFlag = CfRepaint;\r
ab369468 3371 NewLine = TRUE;\r
7c6c064c
ED
3372\r
3373 SavedListEntry = NewPos;\r
7c6c064c 3374 ASSERT(NewPos != NULL);\r
f0c5095b
ED
3375\r
3376 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3377 ASSERT (MenuOption != NULL);\r
3378\r
7c6c064c
ED
3379 //\r
3380 // Adjust Date/Time position before we advance forward.\r
3381 //\r
3382 AdjustDateAndTimePosition (TRUE, &NewPos);\r
7c6c064c 3383\r
ab369468
ED
3384 NewPos = NewPos->BackLink;\r
3385 //\r
3386 // Find next selectable menu or the first menu beyond current form.\r
3387 //\r
3388 Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow, FALSE);\r
3389 if (Difference < 0) {\r
3390 //\r
3391 // We hit the begining MenuOption that can be focused\r
3392 // so we simply scroll to the top.\r
3393 //\r
3394 Repaint = TRUE;\r
3395 if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) {\r
3396 TopOfScreen = gMenuOption.ForwardLink;\r
3397 NewPos = SavedListEntry;\r
3398 SkipValue = 0;\r
3399 } else {\r
7c6c064c 3400 //\r
ab369468 3401 // Scroll up to the last page when we have arrived at top page.\r
7c6c064c 3402 //\r
ab369468
ED
3403 TopOfScreen = FindTopOfScreenMenu (gMenuOption.BackLink, BottomRow - TopRow, &SkipValue);\r
3404 NewPos = gMenuOption.BackLink;\r
3405 MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow, TRUE);\r
3406 }\r
3407 } else {\r
3408 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3409\r
3410 if (MenuOption->Row < TopRow + Difference + NextMenuOption->Skip) {\r
7c6c064c
ED
3411 //\r
3412 // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
3413 //\r
3414 TopOfScreen = NewPos;\r
3415 Repaint = TRUE;\r
ab369468 3416 SkipValue = 0;\r
7c6c064c
ED
3417 }\r
3418\r
3419 //\r
ab369468 3420 // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
7c6c064c 3421 //\r
ab369468
ED
3422 // BottomRow - TopRow + 1 means the total rows current forms supported.\r
3423 // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu \r
3424 // and new top menu. New top menu will all shows in next form, but last highlight menu \r
3425 // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the \r
3426 // last highlight menu.\r
3427 // \r
3428 if (!IsSelectable(NextMenuOption) && IsSelectable(MenuOption) && \r
3429 (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
3430 NewPos = SavedListEntry;\r
6f05c023 3431 }\r
7c6c064c 3432 }\r
7c6c064c 3433\r
ab369468 3434 UpdateStatusBar (INPUT_ERROR, FALSE);\r
7c6c064c 3435\r
7c6c064c 3436 //\r
ab369468 3437 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
7c6c064c 3438 //\r
ab369468
ED
3439 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3440 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3441\r
3442 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
ab369468 3443 break;\r
7c6c064c 3444\r
ab369468 3445 case CfUiPageUp:\r
7c6c064c 3446 //\r
ab369468 3447 // SkipValue means lines is skipped when show the top menu option.\r
7c6c064c 3448 //\r
ab369468
ED
3449 ControlFlag = CfRepaint;\r
3450 NewLine = TRUE;\r
3451 Repaint = TRUE;\r
7c6c064c
ED
3452\r
3453 Link = TopOfScreen;\r
3454 //\r
3455 // First minus the menu of the top screen, it's value is SkipValue.\r
3456 //\r
2e7183ba 3457 if (SkipValue >= BottomRow - TopRow + 1) {\r
7c6c064c 3458 //\r
ab369468
ED
3459 // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
3460 // form of options to be show, so just update the SkipValue to show the next\r
3461 // parts of options.\r
7c6c064c 3462 //\r
ab369468
ED
3463 SkipValue -= BottomRow - TopRow + 1;\r
3464 NewPos = TopOfScreen;\r
3465 break;\r
3466 } else {\r
3467 Index = (BottomRow + 1) - SkipValue - TopRow;\r
7c6c064c 3468 }\r
ab369468
ED
3469 \r
3470 TopOfScreen = FindTopOfScreenMenu(TopOfScreen, Index, &SkipValue);\r
3471 NewPos = TopOfScreen;\r
3472 MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, FALSE);\r
3473 \r
3474 UpdateStatusBar (INPUT_ERROR, FALSE);\r
7c6c064c
ED
3475\r
3476 //\r
3477 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3478 // Don't do this when we are already in the first page.\r
3479 //\r
3480 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3481 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3482\r
3483 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
7c6c064c
ED
3484 break;\r
3485\r
3486 case CfUiPageDown:\r
3487 //\r
3488 // SkipValue means lines is skipped when show the top menu option.\r
3489 //\r
ab369468
ED
3490 ControlFlag = CfRepaint;\r
3491 NewLine = TRUE;\r
3492 Repaint = TRUE;\r
7c6c064c 3493\r
7c6c064c
ED
3494 Link = TopOfScreen;\r
3495 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3496 Index = TopRow + NextMenuOption->Skip - SkipValue;\r
3497 //\r
3498 // Count to the menu option which will show at the top of the next form.\r
3499 //\r
3500 while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {\r
3501 Link = Link->ForwardLink;\r
3502 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3503 Index = Index + NextMenuOption->Skip;\r
3504 }\r
3505\r
3506 if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {\r
3507 //\r
ab369468 3508 // Highlight on the last menu which can be highlight.\r
7c6c064c
ED
3509 //\r
3510 Repaint = FALSE;\r
ab369468 3511 MoveToNextStatement (TRUE, &Link, Index - TopRow, TRUE);\r
7c6c064c
ED
3512 } else {\r
3513 //\r
3514 // Calculate the skip line for top of screen menu.\r
3515 //\r
3516 if (Link == TopOfScreen) {\r
3517 //\r
3518 // The top of screen menu option occupies the entire form.\r
3519 //\r
3520 SkipValue += BottomRow - TopRow + 1;\r
3521 } else {\r
3522 SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));\r
3523 }\r
7c6c064c
ED
3524 TopOfScreen = Link;\r
3525 MenuOption = NULL;\r
3526 //\r
3527 // Move to the Next selectable menu.\r
3528 //\r
ab369468 3529 MoveToNextStatement (FALSE, &Link, BottomRow - TopRow, TRUE);\r
7c6c064c
ED
3530 }\r
3531\r
3532 //\r
3533 // Save the menu as the next highlight menu.\r
3534 //\r
3535 NewPos = Link;\r
3536\r
ab369468
ED
3537 UpdateStatusBar (INPUT_ERROR, FALSE);\r
3538\r
7c6c064c
ED
3539 //\r
3540 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3541 // Don't do this when we are already in the last page.\r
3542 //\r
3543 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3544 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3545\r
3546 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
7c6c064c
ED
3547 break;\r
3548\r
3549 case CfUiDown:\r
3550 //\r
3551 // SkipValue means lines is skipped when show the top menu option.\r
3552 // NewPos points to the menu which is highlighted now.\r
3553 //\r
3554 ControlFlag = CfRepaint;\r
ab369468 3555 NewLine = TRUE;\r
7c6c064c 3556\r
ab369468
ED
3557 if (NewPos == TopOfScreen) {\r
3558 Temp2 = SkipValue;\r
3559 } else {\r
3560 Temp2 = 0;\r
3561 }\r
3562\r
3563 SavedListEntry = NewPos;\r
7c6c064c
ED
3564 //\r
3565 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
3566 // to be one that progresses to the next set of op-codes, we need to advance to the last\r
3567 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
3568 // checking can be done. The only other logic we need to introduce is that if a Date/Time\r
3569 // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
3570 // the Date/Time op-code.\r
3571 //\r
7c6c064c
ED
3572 AdjustDateAndTimePosition (FALSE, &NewPos);\r
3573\r
ab369468
ED
3574 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3575 NewPos = NewPos->ForwardLink;\r
3576 //\r
3577 // Find the next selectable menu.\r
3578 //\r
3579 if (MenuOption->Row + MenuOption->Skip - Temp2 > BottomRow + 1) {\r
3580 if (gMenuOption.ForwardLink == NewPos || &gMenuOption == NewPos) {\r
3581 Difference = -1;\r
3582 } else {\r
3583 Difference = 0;\r
3584 }\r
3585 } else {\r
3586 Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow + 1 - (MenuOption->Row + MenuOption->Skip - Temp2), FALSE);\r
3587 }\r
3588 if (Difference < 0) {\r
3589 //\r
3590 // Scroll to the first page.\r
3591 //\r
3592 if (TopOfScreen != gMenuOption.ForwardLink || SkipValue != 0) { \r
3593 TopOfScreen = gMenuOption.ForwardLink;\r
3594 Repaint = TRUE;\r
3595 MenuOption = NULL;\r
6f05c023 3596 } else {\r
ab369468 3597 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
6f05c023 3598 }\r
ab369468
ED
3599 NewPos = gMenuOption.ForwardLink;\r
3600 MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow, TRUE);\r
6f05c023 3601\r
ab369468
ED
3602 SkipValue = 0;\r
3603 //\r
3604 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3605 //\r
3606 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3607 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3608\r
3609 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
ab369468
ED
3610 break;\r
3611 } \r
7c6c064c 3612\r
ab369468
ED
3613 //\r
3614 // Get next selected menu info.\r
3615 //\r
3616 AdjustDateAndTimePosition (FALSE, &NewPos);\r
3617 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3618 if (NextMenuOption->Row == 0) {\r
3619 UpdateOptionSkipLines (NextMenuOption);\r
3620 }\r
3621\r
3622 //\r
3623 // Calculate new highlight menu end row.\r
3624 //\r
3625 Temp = (MenuOption->Row + MenuOption->Skip - Temp2) + Difference + NextMenuOption->Skip - 1;\r
3626 if (Temp > BottomRow) {\r
7c6c064c 3627 //\r
ab369468 3628 // Get the top screen menu info.\r
7c6c064c 3629 //\r
ab369468
ED
3630 AdjustDateAndTimePosition (FALSE, &TopOfScreen);\r
3631 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
3632\r
3633 //\r
3634 // Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows.\r
3635 // Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows.\r
3636 //\r
3637 if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
7c6c064c 3638 //\r
ab369468 3639 // Skip the top op-code\r
7c6c064c 3640 //\r
ab369468
ED
3641 TopOfScreen = TopOfScreen->ForwardLink;\r
3642 DistanceValue = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
7c6c064c 3643\r
ab369468 3644 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
7c6c064c 3645\r
ab369468
ED
3646 //\r
3647 // If we have a remainder, skip that many more op-codes until we drain the remainder\r
3648 // Special case is the selected highlight menu has more than one form of menus.\r
3649 //\r
3650 while (DistanceValue >= SavedMenuOption->Skip && TopOfScreen != NewPos) {\r
7c6c064c 3651 //\r
ab369468 3652 // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
7c6c064c 3653 //\r
ab369468
ED
3654 DistanceValue = DistanceValue - (INTN) SavedMenuOption->Skip;\r
3655 TopOfScreen = TopOfScreen->ForwardLink;\r
7c6c064c 3656 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
ab369468 3657 }\r
7c6c064c 3658 //\r
ab369468
ED
3659 // Since we will act on this op-code in the next routine, and increment the\r
3660 // SkipValue, set the skips to one less than what is required.\r
7c6c064c 3661 //\r
ab369468
ED
3662 if (TopOfScreen != NewPos) {\r
3663 SkipValue = DistanceValue;\r
3664 } else {\r
3665 SkipValue = 0;\r
3666 }\r
7c6c064c
ED
3667 } else {\r
3668 //\r
ab369468
ED
3669 // Since we will act on this op-code in the next routine, and increment the\r
3670 // SkipValue, set the skips to one less than what is required.\r
7c6c064c 3671 //\r
ab369468 3672 SkipValue += Temp - BottomRow;\r
7c6c064c 3673 }\r
ab369468
ED
3674 Repaint = TRUE;\r
3675 } else if (!IsSelectable (NextMenuOption)) {\r
7c6c064c 3676 //\r
ab369468 3677 // Continue to go down until scroll to next page or the selectable option is found.\r
7c6c064c 3678 //\r
ab369468
ED
3679 ScreenOperation = UiDown;\r
3680 ControlFlag = CfScreenOperation;\r
3681 break;\r
3682 }\r
3683\r
3684 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3685\r
3686 //\r
3687 // Check whether new highlight menu is selectable, if not, keep highlight on the old one.\r
3688 //\r
3689 // BottomRow - TopRow + 1 means the total rows current forms supported.\r
3690 // Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu \r
3691 // and new top menu. New top menu will all shows in next form, but last highlight menu \r
3692 // may only shows 1 line. + 1 at right part means at least need to keep 1 line for the \r
3693 // last highlight menu.\r
3694 // \r
3695 if (!IsSelectable (NextMenuOption) && IsSelectable (MenuOption) && \r
3696 (BottomRow - TopRow + 1 >= Difference + NextMenuOption->Skip + 1)) {\r
3697 NewPos = SavedListEntry;\r
7c6c064c
ED
3698 }\r
3699\r
ab369468
ED
3700 UpdateStatusBar (INPUT_ERROR, FALSE);\r
3701\r
7c6c064c
ED
3702 //\r
3703 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3704 //\r
3705 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3706 AdjustDateAndTimePosition (TRUE, &NewPos);\r
42645c3d
ED
3707\r
3708 UpdateHighlightMenuInfo(NewPos, TopOfScreen, SkipValue);\r
7c6c064c
ED
3709 break;\r
3710\r
3711 case CfUiNoOperation:\r
3712 ControlFlag = CfRepaint;\r
3713 break;\r
3714\r
3715 case CfExit:\r
5a9f73bf 3716 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
7c6c064c
ED
3717 if (HelpString != NULL) {\r
3718 FreePool (HelpString);\r
3719 }\r
3720 if (HelpHeaderString != NULL) {\r
3721 FreePool (HelpHeaderString);\r
3722 }\r
3723 if (HelpBottomString != NULL) {\r
3724 FreePool (HelpBottomString);\r
3725 }\r
3726 return EFI_SUCCESS;\r
3727\r
3728 default:\r
3729 break;\r
3730 }\r
3731 }\r
3732}\r
3733\r
0196c24a
DB
3734/**\r
3735 Free the UI Menu Option structure data.\r
3736\r
3737 @param MenuOptionList Point to the menu option list which need to be free.\r
3738\r
3739**/\r
0196c24a
DB
3740VOID\r
3741FreeMenuOptionData(\r
3742 LIST_ENTRY *MenuOptionList\r
3743 )\r
3744{\r
3745 LIST_ENTRY *Link;\r
3746 UI_MENU_OPTION *Option;\r
3747\r
3748 //\r
3749 // Free menu option list\r
3750 //\r
3751 while (!IsListEmpty (MenuOptionList)) {\r
3752 Link = GetFirstNode (MenuOptionList);\r
3753 Option = MENU_OPTION_FROM_LINK (Link);\r
3754 if (Option->Description != NULL){\r
3755 FreePool(Option->Description);\r
3756 }\r
3757 RemoveEntryList (&Option->Link);\r
3758 FreePool (Option);\r
3759 }\r
3760}\r
3761\r
7c6c064c
ED
3762/**\r
3763\r
3764 Base on the browser status info to show an pop up message.\r
3765\r
3766**/\r
3767VOID\r
3768BrowserStatusProcess (\r
3769 VOID\r
3770 )\r
3771{\r
bfae1330
ED
3772 CHAR16 *ErrorInfo;\r
3773 EFI_INPUT_KEY Key;\r
3774 EFI_EVENT WaitList[2];\r
3775 EFI_EVENT RefreshIntervalEvent;\r
3776 EFI_EVENT TimeOutEvent;\r
3777 UINT8 TimeOut;\r
3778 EFI_STATUS Status;\r
3779 UINTN Index;\r
3780 WARNING_IF_CONTEXT EventContext;\r
3781 EFI_IFR_OP_HEADER *OpCodeBuf;\r
3782 EFI_STRING_ID StringToken;\r
4d4deaac
ED
3783 CHAR16 DiscardChange;\r
3784 CHAR16 JumpToFormSet;\r
3785 CHAR16 *PrintString;\r
7c6c064c
ED
3786\r
3787 if (gFormData->BrowserStatus == BROWSER_SUCCESS) {\r
3788 return;\r
3789 }\r
3790\r
bfae1330
ED
3791 StringToken = 0;\r
3792 TimeOutEvent = NULL;\r
3793 RefreshIntervalEvent = NULL;\r
3794 OpCodeBuf = NULL;\r
3795 if (gFormData->HighLightedStatement != NULL) {\r
3796 OpCodeBuf = gFormData->HighLightedStatement->OpCode;\r
3797 }\r
3798\r
3799 if (gFormData->BrowserStatus == (BROWSER_WARNING_IF)) {\r
3800 ASSERT (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_WARNING_IF_OP);\r
3801\r
3802 TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->TimeOut;\r
3803 StringToken = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->Warning;\r
3804 } else {\r
3805 TimeOut = 0;\r
3806 if ((gFormData->BrowserStatus == (BROWSER_NO_SUBMIT_IF)) &&\r
3807 (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_NO_SUBMIT_IF_OP)) {\r
3808 StringToken = ((EFI_IFR_NO_SUBMIT_IF *) OpCodeBuf)->Error;\r
3809 } else if ((gFormData->BrowserStatus == (BROWSER_INCONSISTENT_IF)) &&\r
3810 (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_INCONSISTENT_IF_OP)) {\r
3811 StringToken = ((EFI_IFR_INCONSISTENT_IF *) OpCodeBuf)->Error;\r
3812 }\r
3813 }\r
3814\r
3815 if (StringToken != 0) {\r
3816 ErrorInfo = GetToken (StringToken, gFormData->HiiHandle);\r
3817 } else if (gFormData->ErrorString != NULL) {\r
3818 //\r
3819 // Only used to compatible with old setup browser.\r
3820 // Not use this field in new browser core.\r
3821 //\r
7c6c064c
ED
3822 ErrorInfo = gFormData->ErrorString;\r
3823 } else {\r
3824 switch (gFormData->BrowserStatus) {\r
3825 case BROWSER_SUBMIT_FAIL:\r
3826 ErrorInfo = gSaveFailed;\r
3827 break;\r
3828\r
7c6c064c
ED
3829 case BROWSER_FORM_NOT_FOUND:\r
3830 ErrorInfo = gFormNotFound;\r
3831 break;\r
3832\r
3833 case BROWSER_FORM_SUPPRESS:\r
3834 ErrorInfo = gFormSuppress;\r
3835 break;\r
3836\r
3837 case BROWSER_PROTOCOL_NOT_FOUND:\r
3838 ErrorInfo = gProtocolNotFound;\r
3839 break;\r
3840\r
4d4deaac
ED
3841 case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
3842 ErrorInfo = gNoSubmitIfFailed;\r
3843 break;\r
3844\r
f2e7732e
ED
3845 case BROWSER_RECONNECT_FAIL:\r
3846 ErrorInfo = gReconnectFail;\r
3847 break;\r
3848\r
3849 case BROWSER_RECONNECT_SAVE_CHANGES:\r
3850 ErrorInfo = gReconnectConfirmChanges;\r
3851 break;\r
3852\r
3853 case BROWSER_RECONNECT_REQUIRED:\r
3854 ErrorInfo = gReconnectRequired;\r
3855 break;\r
3856\r
7c6c064c 3857 default:\r
f2e7732e 3858 ErrorInfo = gBrowserError;\r
7c6c064c
ED
3859 break;\r
3860 }\r
3861 }\r
3862\r
4d4deaac
ED
3863 switch (gFormData->BrowserStatus) {\r
3864 case BROWSER_SUBMIT_FAIL:\r
3865 case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF:\r
f2e7732e 3866 case BROWSER_RECONNECT_SAVE_CHANGES:\r
4d4deaac
ED
3867 ASSERT (gUserInput != NULL);\r
3868 if (gFormData->BrowserStatus == (BROWSER_SUBMIT_FAIL)) {\r
3869 PrintString = gSaveProcess;\r
3870 JumpToFormSet = gJumpToFormSet[0];\r
f2e7732e
ED
3871 DiscardChange = gDiscardChange[0];\r
3872 } else if (gFormData->BrowserStatus == (BROWSER_RECONNECT_SAVE_CHANGES)){\r
3873 PrintString = gChangesOpt;\r
3874 JumpToFormSet = gConfirmOptYes[0];\r
3875 DiscardChange = gConfirmOptNo[0];\r
4d4deaac
ED
3876 } else {\r
3877 PrintString = gSaveNoSubmitProcess;\r
3878 JumpToFormSet = gCheckError[0];\r
f2e7732e 3879 DiscardChange = gDiscardChange[0];\r
4d4deaac 3880 }\r
4d4deaac 3881\r
bfae1330 3882 do {\r
4d4deaac
ED
3883 CreateDialog (&Key, gEmptyString, ErrorInfo, PrintString, gEmptyString, NULL);\r
3884 } while (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (DiscardChange | UPPER_LOWER_CASE_OFFSET)) &&\r
3885 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (JumpToFormSet | UPPER_LOWER_CASE_OFFSET)));\r
bfae1330 3886\r
4d4deaac
ED
3887 if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (DiscardChange | UPPER_LOWER_CASE_OFFSET)) {\r
3888 gUserInput->Action = BROWSER_ACTION_DISCARD;\r
3889 } else {\r
3890 gUserInput->Action = BROWSER_ACTION_GOTO;\r
3891 }\r
3892 break;\r
bfae1330 3893\r
4d4deaac
ED
3894 default:\r
3895 if (TimeOut == 0) {\r
3896 do {\r
3897 CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
3898 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3899 } else {\r
3900 Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent);\r
3901 ASSERT_EFI_ERROR (Status);\r
bfae1330 3902\r
4d4deaac
ED
3903 EventContext.SyncEvent = TimeOutEvent;\r
3904 EventContext.TimeOut = &TimeOut;\r
3905 EventContext.ErrorInfo = ErrorInfo;\r
bfae1330 3906\r
4d4deaac
ED
3907 Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent);\r
3908 ASSERT_EFI_ERROR (Status);\r
bfae1330 3909\r
4d4deaac
ED
3910 //\r
3911 // Show the dialog first to avoid long time not reaction.\r
3912 //\r
3913 gBS->SignalEvent (RefreshIntervalEvent);\r
3914 \r
3915 Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND);\r
3916 ASSERT_EFI_ERROR (Status);\r
bfae1330 3917\r
4d4deaac
ED
3918 while (TRUE) {\r
3919 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3920 if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
3921 break;\r
3922 }\r
bfae1330 3923\r
4d4deaac
ED
3924 if (Status != EFI_NOT_READY) {\r
3925 continue;\r
3926 }\r
bfae1330 3927\r
4d4deaac
ED
3928 WaitList[0] = TimeOutEvent;\r
3929 WaitList[1] = gST->ConIn->WaitForKey;\r
bfae1330 3930\r
4d4deaac
ED
3931 Status = gBS->WaitForEvent (2, WaitList, &Index);\r
3932 ASSERT_EFI_ERROR (Status);\r
3933\r
3934 if (Index == 0) {\r
3935 //\r
3936 // Timeout occur, close the hoot time out event.\r
3937 //\r
3938 break;\r
3939 }\r
bfae1330 3940 }\r
4d4deaac
ED
3941\r
3942 gBS->CloseEvent (TimeOutEvent);\r
3943 gBS->CloseEvent (RefreshIntervalEvent);\r
bfae1330 3944 }\r
4d4deaac 3945 break;\r
bfae1330
ED
3946 }\r
3947\r
bfae1330
ED
3948 if (StringToken != 0) {\r
3949 FreePool (ErrorInfo);\r
3950 }\r
7c6c064c
ED
3951}\r
3952\r
3953/**\r
3954 Display one form, and return user input.\r
3955 \r
3956 @param FormData Form Data to be shown.\r
3957 @param UserInputData User input data.\r
3958 \r
3959 @retval EFI_SUCCESS 1.Form Data is shown, and user input is got.\r
3960 2.Error info has show and return.\r
3961 @retval EFI_INVALID_PARAMETER The input screen dimension is not valid\r
3962 @retval EFI_NOT_FOUND New form data has some error.\r
3963**/\r
3964EFI_STATUS\r
3965EFIAPI \r
3966FormDisplay (\r
3967 IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
3968 OUT USER_INPUT *UserInputData\r
3969 )\r
3970{\r
3971 EFI_STATUS Status;\r
3972\r
3973 ASSERT (FormData != NULL);\r
3974 if (FormData == NULL) {\r
3975 return EFI_INVALID_PARAMETER;\r
3976 }\r
3977\r
3978 gUserInput = UserInputData;\r
3979 gFormData = FormData;\r
3980\r
3981 //\r
3982 // Process the status info first.\r
3983 //\r
3984 BrowserStatusProcess();\r
4d4deaac 3985 if (gFormData->BrowserStatus != BROWSER_SUCCESS) {\r
7c6c064c 3986 //\r
4d4deaac 3987 // gFormData->BrowserStatus != BROWSER_SUCCESS, means only need to print the error info, return here.\r
7c6c064c
ED
3988 //\r
3989 return EFI_SUCCESS;\r
3990 }\r
3991\r
7c6c064c
ED
3992 Status = DisplayPageFrame (FormData, &gStatementDimensions);\r
3993 if (EFI_ERROR (Status)) {\r
3994 return Status;\r
3995 }\r
3996\r
c4866c77
SEHM
3997 //\r
3998 // Global Widths should be initialized before any MenuOption creation\r
3999 // or the GetWidth() used in UiAddMenuOption() will return incorrect value.\r
4000 //\r
4001 //\r
4002 // Left right\r
4003 // |<-.->|<-.........->|<- .........->|<-...........->|\r
4004 // Skip Prompt Option Help \r
4005 //\r
4006 gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3) + 1;\r
4007 gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - 1 - LEFT_SKIPPED_COLUMNS);\r
4008 gPromptBlockWidth = (CHAR16) (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn - 2 * (gOptionBlockWidth - 1) - 1);\r
4009\r
4010 ConvertStatementToMenu();\r
4011\r
5a9f73bf
ED
4012 //\r
4013 // Check whether layout is changed.\r
4014 //\r
4015 if (mIsFirstForm \r
4016 || (gOldFormEntry.HiiHandle != FormData->HiiHandle)\r
4017 || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))\r
4018 || (gOldFormEntry.FormId != FormData->FormId)) {\r
7c6c064c 4019 mStatementLayoutIsChanged = TRUE;\r
5a9f73bf
ED
4020 } else {\r
4021 mStatementLayoutIsChanged = FALSE;\r
7c6c064c
ED
4022 }\r
4023\r
4024 Status = UiDisplayMenu(FormData);\r
5a9f73bf
ED
4025 \r
4026 //\r
4027 // Backup last form info.\r
4028 //\r
4029 mIsFirstForm = FALSE;\r
4030 gOldFormEntry.HiiHandle = FormData->HiiHandle;\r
4031 CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid);\r
4032 gOldFormEntry.FormId = FormData->FormId;\r
7c6c064c 4033\r
0196c24a
DB
4034 //\r
4035 //Free the Ui menu option list.\r
4036 //\r
4037 FreeMenuOptionData(&gMenuOption);\r
4038\r
7c6c064c
ED
4039 return Status;\r
4040}\r
4041\r
5a9f73bf
ED
4042/**\r
4043 Clear Screen to the initial state.\r
4044**/\r
4045VOID\r
4046EFIAPI \r
4047DriverClearDisplayPage (\r
4048 VOID\r
4049 )\r
4050{\r
4051 ClearDisplayPage ();\r
4052 mIsFirstForm = TRUE;\r
4053}\r
4054\r
4055/**\r
4056 Set Buffer to Value for Size bytes.\r
4057\r
4058 @param Buffer Memory to set.\r
4059 @param Size Number of bytes to set\r
4060 @param Value Value of the set operation.\r
4061\r
4062**/\r
4063VOID\r
4064SetUnicodeMem (\r
4065 IN VOID *Buffer,\r
4066 IN UINTN Size,\r
4067 IN CHAR16 Value\r
4068 )\r
4069{\r
4070 CHAR16 *Ptr;\r
4071\r
4072 Ptr = Buffer;\r
4073 while ((Size--) != 0) {\r
4074 *(Ptr++) = Value;\r
4075 }\r
4076}\r
4077\r
7c6c064c
ED
4078/**\r
4079 Initialize Setup Browser driver.\r
4080\r
4081 @param ImageHandle The image handle.\r
4082 @param SystemTable The system table.\r
4083\r
4084 @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
4085 @return Other value if failed to initialize the Setup Browser module.\r
4086\r
4087**/\r
4088EFI_STATUS\r
4089EFIAPI\r
4090InitializeDisplayEngine (\r
4091 IN EFI_HANDLE ImageHandle,\r
4092 IN EFI_SYSTEM_TABLE *SystemTable\r
4093 )\r
4094{\r
4095 EFI_STATUS Status;\r
4096 EFI_INPUT_KEY HotKey;\r
4097 EFI_STRING NewString;\r
4098 EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;\r
4099\r
4100 //\r
4101 // Publish our HII data\r
4102 //\r
4103 gHiiHandle = HiiAddPackages (\r
4104 &gDisplayEngineGuid,\r
4105 ImageHandle,\r
4106 DisplayEngineStrings,\r
4107 NULL\r
4108 );\r
4109 ASSERT (gHiiHandle != NULL);\r
4110\r
4111 //\r
4112 // Install Form Display protocol\r
4113 //\r
4114 Status = gBS->InstallProtocolInterface (\r
4115 &mPrivateData.Handle,\r
4116 &gEdkiiFormDisplayEngineProtocolGuid,\r
4117 EFI_NATIVE_INTERFACE,\r
4118 &mPrivateData.FromDisplayProt\r
4119 );\r
4120 ASSERT_EFI_ERROR (Status);\r
4121\r
4122 InitializeDisplayStrings();\r
5a9f73bf
ED
4123 \r
4124 ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));\r
4125 ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));\r
7c6c064c
ED
4126\r
4127 //\r
4128 // Use BrowserEx2 protocol to register HotKey.\r
4129 // \r
4130 Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);\r
4131 if (!EFI_ERROR (Status)) {\r
4132 //\r
4133 // Register the default HotKey F9 and F10 again.\r
4134 //\r
4135 HotKey.UnicodeChar = CHAR_NULL;\r
4136 HotKey.ScanCode = SCAN_F10;\r
4137 NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);\r
4138 ASSERT (NewString != NULL);\r
4139 FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);\r
4140\r
4141 HotKey.ScanCode = SCAN_F9;\r
4142 NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);\r
4143 ASSERT (NewString != NULL);\r
4144 FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);\r
4145 }\r
4146\r
4147 return EFI_SUCCESS;\r
4148}\r
4149\r
4150/**\r
4151 This is the default unload handle for display core drivers.\r
4152\r
4153 @param[in] ImageHandle The drivers' driver image.\r
4154\r
4155 @retval EFI_SUCCESS The image is unloaded.\r
4156 @retval Others Failed to unload the image.\r
4157\r
4158**/\r
4159EFI_STATUS\r
4160EFIAPI\r
4161UnloadDisplayEngine (\r
4162 IN EFI_HANDLE ImageHandle\r
4163 )\r
4164{\r
4165 HiiRemovePackages(gHiiHandle);\r
4166\r
4167 FreeDisplayStrings ();\r
4168\r
42645c3d
ED
4169 if (gHighligthMenuInfo.HLTOpCode != NULL) {\r
4170 FreePool (gHighligthMenuInfo.HLTOpCode);\r
4171 }\r
4172\r
4173 if (gHighligthMenuInfo.TOSOpCode != NULL) {\r
4174 FreePool (gHighligthMenuInfo.TOSOpCode);\r
336c8e11
ED
4175 }\r
4176\r
7c6c064c
ED
4177 return EFI_SUCCESS;\r
4178}\r