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