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