]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
Base on the type field to get the width of value field for option opcode.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Ui.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for User Interface functions.\r
3\r
31585af4 4Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
7936fb6a 15#include "Setup.h"\r
16\r
ce6d12cc 17LIST_ENTRY gMenuOption;\r
d66e6c16 18LIST_ENTRY gMenuList = INITIALIZE_LIST_HEAD_VARIABLE (gMenuList);\r
211cc6e5
ED
19MENU_REFRESH_ENTRY *gMenuRefreshHead; // Menu list used for refresh timer opcode.\r
20MENU_REFRESH_ENTRY *gMenuEventGuidRefreshHead; // Menu list used for refresh event guid opcode.\r
7936fb6a 21\r
22//\r
23// Search table for UiDisplayMenu()\r
24//\r
25SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {\r
26 {\r
27 SCAN_UP,\r
28 UiUp,\r
29 },\r
30 {\r
31 SCAN_DOWN,\r
32 UiDown,\r
33 },\r
34 {\r
35 SCAN_PAGE_UP,\r
36 UiPageUp,\r
37 },\r
38 {\r
39 SCAN_PAGE_DOWN,\r
40 UiPageDown,\r
41 },\r
42 {\r
43 SCAN_ESC,\r
44 UiReset,\r
45 },\r
7936fb6a 46 {\r
47 SCAN_LEFT,\r
48 UiLeft,\r
49 },\r
50 {\r
51 SCAN_RIGHT,\r
52 UiRight,\r
7936fb6a 53 }\r
54};\r
55\r
48a9d5f7
LG
56UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]);\r
57\r
7936fb6a 58SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {\r
59 {\r
60 UiNoOperation,\r
61 CfUiNoOperation,\r
62 },\r
7936fb6a 63 {\r
64 UiSelect,\r
65 CfUiSelect,\r
66 },\r
67 {\r
68 UiUp,\r
69 CfUiUp,\r
70 },\r
71 {\r
72 UiDown,\r
73 CfUiDown,\r
74 },\r
75 {\r
76 UiLeft,\r
77 CfUiLeft,\r
78 },\r
79 {\r
80 UiRight,\r
81 CfUiRight,\r
82 },\r
83 {\r
84 UiReset,\r
85 CfUiReset,\r
86 },\r
7936fb6a 87 {\r
88 UiPageUp,\r
89 CfUiPageUp,\r
90 },\r
91 {\r
92 UiPageDown,\r
93 CfUiPageDown\r
48a9d5f7
LG
94 }, \r
95 {\r
96 UiHotKey,\r
97 CfUiHotKey\r
7936fb6a 98 }\r
99};\r
100\r
19b15d63 101BOOLEAN mInputError;\r
aa79b0b3 102BOOLEAN GetLineByWidthFinished = FALSE;\r
19b15d63 103\r
7936fb6a 104\r
105/**\r
106 Set Buffer to Value for Size bytes.\r
107\r
108 @param Buffer Memory to set.\r
109 @param Size Number of bytes to set\r
110 @param Value Value of the set operation.\r
111\r
112**/\r
113VOID\r
114SetUnicodeMem (\r
115 IN VOID *Buffer,\r
116 IN UINTN Size,\r
117 IN CHAR16 Value\r
118 )\r
119{\r
120 CHAR16 *Ptr;\r
121\r
122 Ptr = Buffer;\r
123 while ((Size--) != 0) {\r
124 *(Ptr++) = Value;\r
125 }\r
126}\r
127\r
128\r
129/**\r
130 Initialize Menu option list.\r
131\r
132**/\r
133VOID\r
134UiInitMenu (\r
135 VOID\r
136 )\r
137{\r
ce6d12cc 138 InitializeListHead (&gMenuOption);\r
7936fb6a 139}\r
140\r
141\r
142/**\r
d66e6c16 143 Free Menu option linked list.\r
7936fb6a 144\r
145**/\r
146VOID\r
d66e6c16 147UiFreeMenu (\r
7936fb6a 148 VOID\r
149 )\r
150{\r
d66e6c16 151 UI_MENU_OPTION *MenuOption;\r
152\r
ce6d12cc 153 while (!IsListEmpty (&gMenuOption)) {\r
154 MenuOption = MENU_OPTION_FROM_LINK (gMenuOption.ForwardLink);\r
d66e6c16 155 RemoveEntryList (&MenuOption->Link);\r
156\r
157 //\r
158 // We allocated space for this description when we did a GetToken, free it here\r
159 //\r
160 if (MenuOption->Skip != 0) {\r
161 //\r
162 // For date/time, MenuOption->Description is shared by three Menu Options\r
163 // Data format : [01/02/2004] [11:22:33]\r
164 // Line number : 0 0 1 0 0 1\r
165 //\r
166 FreePool (MenuOption->Description);\r
167 }\r
168 FreePool (MenuOption);\r
169 }\r
7936fb6a 170}\r
171\r
172\r
173/**\r
d66e6c16 174 Create a menu with specified formset GUID and form ID, and add it as a child\r
175 of the given parent menu.\r
7936fb6a 176\r
d66e6c16 177 @param Parent The parent of menu to be added.\r
b2e444aa 178 @param HiiHandle Hii handle related to this formset.\r
d66e6c16 179 @param FormSetGuid The Formset Guid of menu to be added.\r
180 @param FormId The Form ID of menu to be added.\r
181\r
182 @return A pointer to the newly added menu or NULL if memory is insufficient.\r
7936fb6a 183\r
184**/\r
d66e6c16 185UI_MENU_LIST *\r
186UiAddMenuList (\r
187 IN OUT UI_MENU_LIST *Parent,\r
b2e444aa 188 IN EFI_HII_HANDLE HiiHandle,\r
d66e6c16 189 IN EFI_GUID *FormSetGuid,\r
190 IN UINT16 FormId\r
7936fb6a 191 )\r
192{\r
d66e6c16 193 UI_MENU_LIST *MenuList;\r
7936fb6a 194\r
d66e6c16 195 MenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));\r
196 if (MenuList == NULL) {\r
197 return NULL;\r
7936fb6a 198 }\r
7936fb6a 199\r
d66e6c16 200 MenuList->Signature = UI_MENU_LIST_SIGNATURE;\r
201 InitializeListHead (&MenuList->ChildListHead);\r
7936fb6a 202\r
b2e444aa 203 MenuList->HiiHandle = HiiHandle;\r
d66e6c16 204 CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
205 MenuList->FormId = FormId;\r
206 MenuList->Parent = Parent;\r
7936fb6a 207\r
d66e6c16 208 if (Parent == NULL) {\r
209 //\r
210 // If parent is not specified, it is the root Form of a Formset\r
211 //\r
212 InsertTailList (&gMenuList, &MenuList->Link);\r
213 } else {\r
214 InsertTailList (&Parent->ChildListHead, &MenuList->Link);\r
7936fb6a 215 }\r
d66e6c16 216\r
217 return MenuList;\r
7936fb6a 218}\r
219\r
220\r
221/**\r
b2e444aa 222 Search Menu with given FormId and FormSetGuid in all cached menu list.\r
7936fb6a 223\r
d66e6c16 224 @param Parent The parent of menu to search.\r
b2e444aa 225 @param FormSetGuid The Formset GUID of the menu to search. \r
d66e6c16 226 @param FormId The Form ID of menu to search.\r
227\r
228 @return A pointer to menu found or NULL if not found.\r
7936fb6a 229\r
230**/\r
d66e6c16 231UI_MENU_LIST *\r
232UiFindChildMenuList (\r
233 IN UI_MENU_LIST *Parent,\r
b2e444aa 234 IN EFI_GUID *FormSetGuid, \r
d66e6c16 235 IN UINT16 FormId\r
7936fb6a 236 )\r
237{\r
d66e6c16 238 LIST_ENTRY *Link;\r
239 UI_MENU_LIST *Child;\r
240 UI_MENU_LIST *MenuList;\r
241\r
b2e444aa
ED
242 ASSERT (Parent != NULL);\r
243\r
244 if (Parent->FormId == FormId && CompareGuid (FormSetGuid, &Parent->FormSetGuid)) {\r
d66e6c16 245 return Parent;\r
246 }\r
7936fb6a 247\r
d66e6c16 248 Link = GetFirstNode (&Parent->ChildListHead);\r
249 while (!IsNull (&Parent->ChildListHead, Link)) {\r
250 Child = UI_MENU_LIST_FROM_LINK (Link);\r
7936fb6a 251\r
b2e444aa 252 MenuList = UiFindChildMenuList (Child, FormSetGuid, FormId);\r
d66e6c16 253 if (MenuList != NULL) {\r
254 return MenuList;\r
255 }\r
7936fb6a 256\r
d66e6c16 257 Link = GetNextNode (&Parent->ChildListHead, Link);\r
258 }\r
259\r
260 return NULL;\r
7936fb6a 261}\r
262\r
263\r
264/**\r
d66e6c16 265 Search Menu with given FormSetGuid and FormId in all cached menu list.\r
266\r
267 @param FormSetGuid The Formset GUID of the menu to search.\r
268 @param FormId The Form ID of menu to search.\r
269\r
270 @return A pointer to menu found or NULL if not found.\r
7936fb6a 271\r
272**/\r
d66e6c16 273UI_MENU_LIST *\r
274UiFindMenuList (\r
275 IN EFI_GUID *FormSetGuid,\r
276 IN UINT16 FormId\r
7936fb6a 277 )\r
278{\r
d66e6c16 279 LIST_ENTRY *Link;\r
280 UI_MENU_LIST *MenuList;\r
281 UI_MENU_LIST *Child;\r
7936fb6a 282\r
d66e6c16 283 Link = GetFirstNode (&gMenuList);\r
284 while (!IsNull (&gMenuList, Link)) {\r
285 MenuList = UI_MENU_LIST_FROM_LINK (Link);\r
7936fb6a 286\r
b2e444aa
ED
287 Child = UiFindChildMenuList(MenuList, FormSetGuid, FormId);\r
288 if (Child != NULL) {\r
289 return Child;\r
7936fb6a 290 }\r
d66e6c16 291\r
292 Link = GetNextNode (&gMenuList, Link);\r
7936fb6a 293 }\r
d66e6c16 294\r
295 return NULL;\r
7936fb6a 296}\r
297\r
298\r
299/**\r
300 Free Menu option linked list.\r
301\r
302**/\r
303VOID\r
304UiFreeRefreshList (\r
305 VOID\r
306 )\r
307{\r
308 MENU_REFRESH_ENTRY *OldMenuRefreshEntry;\r
309\r
310 while (gMenuRefreshHead != NULL) {\r
311 OldMenuRefreshEntry = gMenuRefreshHead->Next;\r
f4113e1f 312 FreePool (gMenuRefreshHead);\r
7936fb6a 313 gMenuRefreshHead = OldMenuRefreshEntry;\r
314 }\r
315\r
211cc6e5
ED
316 while (gMenuEventGuidRefreshHead != NULL) {\r
317 OldMenuRefreshEntry = gMenuEventGuidRefreshHead->Next;\r
318 if (gMenuEventGuidRefreshHead != NULL) {\r
319 gBS->CloseEvent(gMenuEventGuidRefreshHead->Event);\r
320 }\r
321 FreePool (gMenuEventGuidRefreshHead);\r
322 gMenuEventGuidRefreshHead = OldMenuRefreshEntry;\r
323 }\r
7936fb6a 324}\r
325\r
326\r
4a6876b7
ED
327/**\r
328 Process option string for date/time opcode.\r
329\r
330 @param MenuOption Menu option point to date/time.\r
331 @param OptionString Option string input for process.\r
332 @param AddOptCol Whether need to update MenuOption->OptCol. \r
333\r
334**/\r
335VOID \r
336ProcessStringForDateTime (\r
337 UI_MENU_OPTION *MenuOption,\r
338 CHAR16 *OptionString,\r
339 BOOLEAN AddOptCol\r
340 )\r
341{\r
342 UINTN Index;\r
343 UINTN Count;\r
344 FORM_BROWSER_STATEMENT *Statement;\r
345\r
346 ASSERT (MenuOption != NULL && OptionString != NULL);\r
347 \r
348 Statement = MenuOption->ThisTag;\r
349 \r
350 //\r
351 // If leading spaces on OptionString - remove the spaces\r
352 //\r
353 for (Index = 0; OptionString[Index] == L' '; Index++) {\r
354 //\r
355 // Base on the blockspace to get the option column info.\r
356 //\r
357 if (AddOptCol) {\r
358 MenuOption->OptCol++;\r
359 }\r
360 }\r
361 \r
362 for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
363 OptionString[Count] = OptionString[Index];\r
364 Count++;\r
365 }\r
366 OptionString[Count] = CHAR_NULL;\r
367 \r
368 //\r
369 // Enable to suppress field in the opcode base on the flag.\r
370 //\r
371 if (Statement->Operand == EFI_IFR_DATE_OP) {\r
372 //\r
373 // OptionString format is: <**: **: ****>\r
374 // |month|day|year|\r
375 // 4 3 5\r
376 //\r
377 if ((Statement->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
378 //\r
379 // At this point, only "<**:" in the optionstring. \r
380 // Clean the day's ** field, after clean, the format is "< :"\r
381 //\r
382 SetUnicodeMem (&OptionString[1], 2, L' ');\r
383 } else if ((Statement->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
384 //\r
385 // At this point, only "**:" in the optionstring. \r
386 // Clean the month's "**" field, after clean, the format is " :"\r
387 // \r
388 SetUnicodeMem (&OptionString[0], 2, L' ');\r
389 } else if ((Statement->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
390 //\r
391 // At this point, only "****>" in the optionstring. \r
392 // Clean the year's "****" field, after clean, the format is " >"\r
393 // \r
394 SetUnicodeMem (&OptionString[0], 4, L' ');\r
395 }\r
396 } else if (Statement->Operand == EFI_IFR_TIME_OP) {\r
397 //\r
398 // OptionString format is: <**: **: **>\r
399 // |hour|minute|second|\r
400 // 4 3 3\r
401 //\r
402 if ((Statement->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
403 //\r
404 // At this point, only "<**:" in the optionstring. \r
405 // Clean the hour's ** field, after clean, the format is "< :"\r
406 //\r
407 SetUnicodeMem (&OptionString[1], 2, L' ');\r
408 } else if ((Statement->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
409 //\r
410 // At this point, only "**:" in the optionstring. \r
411 // Clean the minute's "**" field, after clean, the format is " :"\r
412 // \r
413 SetUnicodeMem (&OptionString[0], 2, L' ');\r
414 } else if ((Statement->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
415 //\r
416 // At this point, only "**>" in the optionstring. \r
417 // Clean the second's "**" field, after clean, the format is " >"\r
418 // \r
419 SetUnicodeMem (&OptionString[0], 2, L' ');\r
420 }\r
421 }\r
422}\r
7936fb6a 423\r
424/**\r
211cc6e5 425 Refresh question.\r
7936fb6a 426\r
211cc6e5 427 @param MenuRefreshEntry Menu refresh structure which has info about the refresh question.\r
7936fb6a 428**/\r
211cc6e5
ED
429EFI_STATUS \r
430RefreshQuestion (\r
431 IN MENU_REFRESH_ENTRY *MenuRefreshEntry\r
7936fb6a 432 )\r
433{\r
8d00a0f1 434 CHAR16 *OptionString;\r
8d00a0f1 435 EFI_STATUS Status;\r
436 UI_MENU_SELECTION *Selection;\r
437 FORM_BROWSER_STATEMENT *Question;\r
7936fb6a 438\r
211cc6e5
ED
439 Selection = MenuRefreshEntry->Selection;\r
440 Question = MenuRefreshEntry->MenuOption->ThisTag;\r
7936fb6a 441\r
816a7110 442 Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);\r
211cc6e5
ED
443 if (EFI_ERROR (Status)) {\r
444 return Status;\r
445 }\r
7936fb6a 446\r
211cc6e5
ED
447 OptionString = NULL;\r
448 ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);\r
449\r
450 if (OptionString != NULL) {\r
211cc6e5
ED
451 //\r
452 // If old Text is longer than new string, need to clean the old string before paint the newer.\r
453 // This option is no need for time/date opcode, because time/data opcode has fixed string length.\r
454 //\r
455 if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) &&\r
456 (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) {\r
457 ClearLines (\r
458 MenuRefreshEntry->CurrentColumn, \r
459 MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1,\r
460 MenuRefreshEntry->CurrentRow,\r
461 MenuRefreshEntry->CurrentRow,\r
462 PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
463 );\r
464 }\r
7936fb6a 465\r
211cc6e5 466 gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
4a6876b7
ED
467 ProcessStringForDateTime(MenuRefreshEntry->MenuOption, OptionString, FALSE);\r
468 PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);\r
211cc6e5
ED
469 FreePool (OptionString);\r
470 }\r
8d00a0f1 471\r
211cc6e5
ED
472 //\r
473 // Question value may be changed, need invoke its Callback()\r
474 //\r
475 Status = ProcessCallBackFunction (Selection, Question, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
8d00a0f1 476\r
211cc6e5
ED
477 return Status;\r
478}\r
8d00a0f1 479\r
211cc6e5
ED
480/**\r
481 Refresh the question which has refresh guid event attribute.\r
482 \r
483 @param Event The event which has this function related. \r
484 @param Context The input context info related to this event or the status code return to the caller.\r
485**/\r
486VOID\r
34d137f3 487EFIAPI\r
211cc6e5
ED
488RefreshQuestionNotify(\r
489 IN EFI_EVENT Event,\r
490 IN VOID *Context\r
491 )\r
492{\r
493 MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
494 UI_MENU_SELECTION *Selection;\r
487ef018 495\r
211cc6e5
ED
496 //\r
497 // Reset FormPackage update flag\r
498 //\r
499 mHiiPackageListUpdated = FALSE;\r
8d00a0f1 500\r
211cc6e5
ED
501 MenuRefreshEntry = (MENU_REFRESH_ENTRY *)Context;\r
502 ASSERT (MenuRefreshEntry != NULL);\r
503 Selection = MenuRefreshEntry->Selection;\r
504\r
505 RefreshQuestion (MenuRefreshEntry);\r
506 \r
507 if (mHiiPackageListUpdated) {\r
508 //\r
509 // Package list is updated, force to reparse IFR binary of target Formset\r
510 //\r
511 mHiiPackageListUpdated = FALSE;\r
512 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
513 } \r
514}\r
515\r
516\r
517/**\r
518 Refresh screen.\r
519\r
520**/\r
521EFI_STATUS\r
522RefreshForm (\r
523 VOID\r
524 )\r
525{\r
526 MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
527 EFI_STATUS Status;\r
528 UI_MENU_SELECTION *Selection;\r
529\r
530 if (gMenuRefreshHead != NULL) {\r
531 //\r
532 // call from refresh interval process.\r
533 //\r
534 MenuRefreshEntry = gMenuRefreshHead;\r
535 Selection = MenuRefreshEntry->Selection;\r
536 //\r
537 // Reset FormPackage update flag\r
538 //\r
539 mHiiPackageListUpdated = FALSE;\r
540\r
541 do {\r
542 Status = RefreshQuestion (MenuRefreshEntry);\r
b18e7050
ED
543 if (EFI_ERROR (Status)) {\r
544 return Status;\r
7936fb6a 545 }\r
546\r
547 MenuRefreshEntry = MenuRefreshEntry->Next;\r
548\r
549 } while (MenuRefreshEntry != NULL);\r
8d00a0f1 550\r
551 if (mHiiPackageListUpdated) {\r
552 //\r
553 // Package list is updated, force to reparse IFR binary of target Formset\r
554 //\r
555 mHiiPackageListUpdated = FALSE;\r
556 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
557 return EFI_SUCCESS;\r
558 }\r
7936fb6a 559 }\r
8d00a0f1 560\r
561 return EFI_TIMEOUT;\r
7936fb6a 562}\r
563\r
564\r
565/**\r
566 Wait for a given event to fire, or for an optional timeout to expire.\r
567\r
568 @param Event The event to wait for\r
569 @param Timeout An optional timeout value in 100 ns units.\r
570 @param RefreshInterval Menu refresh interval (in seconds).\r
571\r
572 @retval EFI_SUCCESS Event fired before Timeout expired.\r
573 @retval EFI_TIME_OUT Timout expired before Event fired.\r
574\r
575**/\r
576EFI_STATUS\r
577UiWaitForSingleEvent (\r
578 IN EFI_EVENT Event,\r
579 IN UINT64 Timeout, OPTIONAL\r
580 IN UINT8 RefreshInterval OPTIONAL\r
581 )\r
582{\r
583 EFI_STATUS Status;\r
584 UINTN Index;\r
585 EFI_EVENT TimerEvent;\r
586 EFI_EVENT WaitList[2];\r
587\r
588 if (Timeout != 0) {\r
589 //\r
590 // Create a timer event\r
591 //\r
592 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
593 if (!EFI_ERROR (Status)) {\r
594 //\r
595 // Set the timer event\r
596 //\r
597 gBS->SetTimer (\r
598 TimerEvent,\r
599 TimerRelative,\r
600 Timeout\r
601 );\r
602\r
603 //\r
604 // Wait for the original event or the timer\r
605 //\r
606 WaitList[0] = Event;\r
607 WaitList[1] = TimerEvent;\r
608 Status = gBS->WaitForEvent (2, WaitList, &Index);\r
609 gBS->CloseEvent (TimerEvent);\r
610\r
611 //\r
612 // If the timer expired, change the return to timed out\r
613 //\r
614 if (!EFI_ERROR (Status) && Index == 1) {\r
615 Status = EFI_TIMEOUT;\r
616 }\r
617 }\r
618 } else {\r
619 //\r
620 // Update screen every second\r
621 //\r
622 if (RefreshInterval == 0) {\r
623 Timeout = ONE_SECOND;\r
624 } else {\r
625 Timeout = RefreshInterval * ONE_SECOND;\r
626 }\r
627\r
628 do {\r
629 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
630\r
631 //\r
632 // Set the timer event\r
633 //\r
634 gBS->SetTimer (\r
635 TimerEvent,\r
636 TimerRelative,\r
637 Timeout\r
638 );\r
639\r
640 //\r
641 // Wait for the original event or the timer\r
642 //\r
643 WaitList[0] = Event;\r
644 WaitList[1] = TimerEvent;\r
645 Status = gBS->WaitForEvent (2, WaitList, &Index);\r
646\r
647 //\r
648 // If the timer expired, update anything that needs a refresh and keep waiting\r
649 //\r
650 if (!EFI_ERROR (Status) && Index == 1) {\r
651 Status = EFI_TIMEOUT;\r
652 if (RefreshInterval != 0) {\r
8d00a0f1 653 Status = RefreshForm ();\r
7936fb6a 654 }\r
655 }\r
656\r
657 gBS->CloseEvent (TimerEvent);\r
658 } while (Status == EFI_TIMEOUT);\r
659 }\r
660\r
661 return Status;\r
662}\r
663\r
664\r
665/**\r
666 Add one menu option by specified description and context.\r
667\r
668 @param String String description for this option.\r
669 @param Handle Hii handle for the package list.\r
f67c4382 670 @param Form The form this statement belong to.\r
7936fb6a 671 @param Statement Statement of this Menu Option.\r
672 @param NumberOfLines Display lines for this Menu Option.\r
673 @param MenuItemCount The index for this Option in the Menu.\r
674\r
8b0fc5c1 675 @retval Pointer Pointer to the added Menu Option.\r
676\r
7936fb6a 677**/\r
8b0fc5c1 678UI_MENU_OPTION *\r
7936fb6a 679UiAddMenuOption (\r
680 IN CHAR16 *String,\r
681 IN EFI_HII_HANDLE Handle,\r
f67c4382 682 IN FORM_BROWSER_FORM *Form,\r
7936fb6a 683 IN FORM_BROWSER_STATEMENT *Statement,\r
684 IN UINT16 NumberOfLines,\r
685 IN UINT16 MenuItemCount\r
686 )\r
687{\r
688 UI_MENU_OPTION *MenuOption;\r
689 UINTN Index;\r
690 UINTN Count;\r
691\r
692 Count = 1;\r
8b0fc5c1 693 MenuOption = NULL;\r
7936fb6a 694\r
695 if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
696 //\r
697 // Add three MenuOptions for Date/Time\r
698 // Data format : [01/02/2004] [11:22:33]\r
699 // Line number : 0 0 1 0 0 1\r
700 //\r
701 NumberOfLines = 0;\r
702 Count = 3;\r
703\r
704 if (Statement->Storage == NULL) {\r
705 //\r
706 // For RTC type of date/time, set default refresh interval to be 1 second\r
707 //\r
708 if (Statement->RefreshInterval == 0) {\r
709 Statement->RefreshInterval = 1;\r
710 }\r
711 }\r
712 }\r
713\r
714 for (Index = 0; Index < Count; Index++) {\r
715 MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));\r
716 ASSERT (MenuOption);\r
717\r
718 MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;\r
719 MenuOption->Description = String;\r
720 MenuOption->Handle = Handle;\r
721 MenuOption->ThisTag = Statement;\r
722 MenuOption->EntryNumber = MenuItemCount;\r
723\r
724 if (Index == 2) {\r
725 //\r
726 // Override LineNumber for the MenuOption in Date/Time sequence\r
727 //\r
728 MenuOption->Skip = 1;\r
729 } else {\r
730 MenuOption->Skip = NumberOfLines;\r
731 }\r
732 MenuOption->Sequence = Index;\r
733\r
31585af4
ED
734 if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut ) {\r
735 MenuOption->GrayOut = TRUE;\r
736 } else {\r
737 MenuOption->GrayOut = FALSE;\r
7936fb6a 738 }\r
739\r
f67c4382
ED
740 //\r
741 // If the form or the question has the lock attribute, deal same as grayout.\r
742 //\r
743 if (Form->Locked || Statement->Locked) {\r
744 MenuOption->GrayOut = TRUE;\r
745 }\r
746 \r
8b0fc5c1 747 switch (Statement->Operand) {\r
748 case EFI_IFR_ORDERED_LIST_OP:\r
749 case EFI_IFR_ONE_OF_OP:\r
750 case EFI_IFR_NUMERIC_OP:\r
751 case EFI_IFR_TIME_OP:\r
752 case EFI_IFR_DATE_OP:\r
753 case EFI_IFR_CHECKBOX_OP:\r
754 case EFI_IFR_PASSWORD_OP:\r
755 case EFI_IFR_STRING_OP:\r
756 //\r
757 // User could change the value of these items\r
758 //\r
759 MenuOption->IsQuestion = TRUE;\r
760 break;\r
761\r
11232773
LG
762 case EFI_IFR_TEXT_OP:\r
763 if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {\r
764 //\r
765 // Initializing GrayOut option as TRUE for Text setup options \r
766 // so that those options will be Gray in colour and un selectable.\r
767 //\r
768 MenuOption->GrayOut = TRUE;\r
769 }\r
bd07919c 770 //\r
771 // break skipped on purpose\r
772 //\r
8b0fc5c1 773 default:\r
774 MenuOption->IsQuestion = FALSE;\r
775 break;\r
776 }\r
777\r
7936fb6a 778 if ((Statement->ValueExpression != NULL) ||\r
779 ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {\r
780 MenuOption->ReadOnly = TRUE;\r
781 }\r
782\r
ce6d12cc 783 InsertTailList (&gMenuOption, &MenuOption->Link);\r
7936fb6a 784 }\r
8b0fc5c1 785\r
786 return MenuOption;\r
7936fb6a 787}\r
788\r
789\r
790/**\r
791 Routine used to abstract a generic dialog interface and return the selected key or string\r
792\r
793 @param NumberOfLines The number of lines for the dialog box\r
794 @param HotKey Defines whether a single character is parsed\r
795 (TRUE) and returned in KeyValue or a string is\r
796 returned in StringBuffer. Two special characters\r
797 are considered when entering a string, a SCAN_ESC\r
798 and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates\r
799 string input and returns\r
800 @param MaximumStringSize The maximum size in bytes of a typed in string\r
801 (each character is a CHAR16) and the minimum\r
802 string returned is two bytes\r
803 @param StringBuffer The passed in pointer to the buffer which will\r
804 hold the typed in string if HotKey is FALSE\r
805 @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
7936fb6a 806 @param ... A series of (quantity == NumberOfLines) text\r
807 strings which will be used to construct the dialog\r
808 box\r
809\r
810 @retval EFI_SUCCESS Displayed dialog and received user interaction\r
811 @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.\r
812 (StringBuffer == NULL) && (HotKey == FALSE))\r
813 @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine\r
814\r
815**/\r
816EFI_STATUS\r
8091267c 817EFIAPI\r
7936fb6a 818CreateDialog (\r
819 IN UINTN NumberOfLines,\r
820 IN BOOLEAN HotKey,\r
821 IN UINTN MaximumStringSize,\r
822 OUT CHAR16 *StringBuffer,\r
823 OUT EFI_INPUT_KEY *KeyValue,\r
7936fb6a 824 ...\r
825 )\r
826{\r
827 VA_LIST Marker;\r
828 UINTN Count;\r
829 EFI_INPUT_KEY Key;\r
830 UINTN LargestString;\r
831 CHAR16 *TempString;\r
832 CHAR16 *BufferedString;\r
833 CHAR16 *StackString;\r
834 CHAR16 KeyPad[2];\r
835 UINTN Start;\r
836 UINTN Top;\r
837 UINTN Index;\r
838 EFI_STATUS Status;\r
839 BOOLEAN SelectionComplete;\r
840 UINTN InputOffset;\r
841 UINTN CurrentAttribute;\r
842 UINTN DimensionsWidth;\r
843 UINTN DimensionsHeight;\r
844\r
845 DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
846 DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
847\r
848 SelectionComplete = FALSE;\r
849 InputOffset = 0;\r
850 TempString = AllocateZeroPool (MaximumStringSize * 2);\r
851 BufferedString = AllocateZeroPool (MaximumStringSize * 2);\r
852 CurrentAttribute = gST->ConOut->Mode->Attribute;\r
853\r
854 ASSERT (TempString);\r
855 ASSERT (BufferedString);\r
856\r
7936fb6a 857 //\r
858 // Zero the outgoing buffer\r
859 //\r
860 ZeroMem (StringBuffer, MaximumStringSize);\r
861\r
862 if (HotKey) {\r
863 if (KeyValue == NULL) {\r
864 return EFI_INVALID_PARAMETER;\r
865 }\r
866 } else {\r
867 if (StringBuffer == NULL) {\r
868 return EFI_INVALID_PARAMETER;\r
869 }\r
870 }\r
871 //\r
872 // Disable cursor\r
873 //\r
874 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
875\r
f4bcc90f 876 LargestString = 0;\r
7936fb6a 877\r
3bbe68a3 878 VA_START (Marker, KeyValue);\r
879\r
7936fb6a 880 //\r
881 // Determine the largest string in the dialog box\r
882 // Notice we are starting with 1 since String is the first string\r
883 //\r
f4bcc90f 884 for (Count = 0; Count < NumberOfLines; Count++) {\r
7936fb6a 885 StackString = VA_ARG (Marker, CHAR16 *);\r
886\r
887 if (StackString[0] == L' ') {\r
888 InputOffset = Count + 1;\r
889 }\r
890\r
891 if ((GetStringWidth (StackString) / 2) > LargestString) {\r
892 //\r
893 // Size of the string visually and subtract the width by one for the null-terminator\r
894 //\r
895 LargestString = (GetStringWidth (StackString) / 2);\r
896 }\r
897 }\r
1c9a7554 898 VA_END (Marker);\r
7936fb6a 899\r
900 Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
901 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
902\r
903 Count = 0;\r
904\r
905 //\r
906 // Display the Popup\r
907 //\r
1c9a7554 908 VA_START (Marker, KeyValue);\r
909 CreateSharedPopUp (LargestString, NumberOfLines, Marker);\r
910 VA_END (Marker);\r
7936fb6a 911\r
912 //\r
913 // Take the first key typed and report it back?\r
914 //\r
915 if (HotKey) {\r
916 Status = WaitForKeyStroke (&Key);\r
917 ASSERT_EFI_ERROR (Status);\r
918 CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));\r
919\r
920 } else {\r
921 do {\r
922 Status = WaitForKeyStroke (&Key);\r
923\r
924 switch (Key.UnicodeChar) {\r
925 case CHAR_NULL:\r
926 switch (Key.ScanCode) {\r
927 case SCAN_ESC:\r
f4113e1f 928 FreePool (TempString);\r
929 FreePool (BufferedString);\r
7936fb6a 930 gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
931 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
932 return EFI_DEVICE_ERROR;\r
933\r
934 default:\r
935 break;\r
936 }\r
937\r
938 break;\r
939\r
940 case CHAR_CARRIAGE_RETURN:\r
941 SelectionComplete = TRUE;\r
f4113e1f 942 FreePool (TempString);\r
943 FreePool (BufferedString);\r
7936fb6a 944 gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
945 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
946 return EFI_SUCCESS;\r
947 break;\r
948\r
949 case CHAR_BACKSPACE:\r
950 if (StringBuffer[0] != CHAR_NULL) {\r
951 for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {\r
952 TempString[Index] = StringBuffer[Index];\r
953 }\r
954 //\r
955 // Effectively truncate string by 1 character\r
956 //\r
957 TempString[Index - 1] = CHAR_NULL;\r
958 StrCpy (StringBuffer, TempString);\r
959 }\r
d6bee311
ED
960 //\r
961 // break skipped on purpose\r
962 //\r
7936fb6a 963\r
964 default:\r
965 //\r
966 // If it is the beginning of the string, don't worry about checking maximum limits\r
967 //\r
968 if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
969 StrnCpy (StringBuffer, &Key.UnicodeChar, 1);\r
970 StrnCpy (TempString, &Key.UnicodeChar, 1);\r
971 } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
972 KeyPad[0] = Key.UnicodeChar;\r
973 KeyPad[1] = CHAR_NULL;\r
974 StrCat (StringBuffer, KeyPad);\r
975 StrCat (TempString, KeyPad);\r
976 }\r
977 //\r
978 // If the width of the input string is now larger than the screen, we nee to\r
979 // adjust the index to start printing portions of the string\r
980 //\r
981 SetUnicodeMem (BufferedString, LargestString, L' ');\r
982\r
983 PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
984\r
985 if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {\r
986 Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;\r
987 } else {\r
988 Index = 0;\r
989 }\r
990\r
991 for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {\r
992 BufferedString[Count] = StringBuffer[Index];\r
993 }\r
994\r
995 PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
996 break;\r
997 }\r
998 } while (!SelectionComplete);\r
999 }\r
1000\r
1001 gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
1002 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1003 return EFI_SUCCESS;\r
1004}\r
1005\r
1006/**\r
1007 Draw a pop up windows based on the dimension, number of lines and\r
1008 strings specified.\r
1009\r
1010 @param RequestedWidth The width of the pop-up.\r
1011 @param NumberOfLines The number of lines.\r
f4bcc90f 1012 @param Marker The variable argument list for the list of string to be printed.\r
7936fb6a 1013\r
1014**/\r
1015VOID\r
1016CreateSharedPopUp (\r
1017 IN UINTN RequestedWidth,\r
1018 IN UINTN NumberOfLines,\r
f4bcc90f 1019 IN VA_LIST Marker\r
7936fb6a 1020 )\r
1021{\r
1022 UINTN Index;\r
1023 UINTN Count;\r
1024 CHAR16 Character;\r
1025 UINTN Start;\r
1026 UINTN End;\r
1027 UINTN Top;\r
1028 UINTN Bottom;\r
1029 CHAR16 *String;\r
1030 UINTN DimensionsWidth;\r
1031 UINTN DimensionsHeight;\r
1032\r
1033 DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
1034 DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
1035\r
7936fb6a 1036 gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
1037\r
1038 if ((RequestedWidth + 2) > DimensionsWidth) {\r
1039 RequestedWidth = DimensionsWidth - 2;\r
1040 }\r
1041\r
1042 //\r
1043 // Subtract the PopUp width from total Columns, allow for one space extra on\r
1044 // each end plus a border.\r
1045 //\r
1046 Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
1047 End = Start + RequestedWidth + 1;\r
1048\r
1049 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
1050 Bottom = Top + NumberOfLines + 2;\r
1051\r
1052 Character = BOXDRAW_DOWN_RIGHT;\r
1053 PrintCharAt (Start, Top, Character);\r
1054 Character = BOXDRAW_HORIZONTAL;\r
1055 for (Index = Start; Index + 2 < End; Index++) {\r
1056 PrintChar (Character);\r
1057 }\r
1058\r
1059 Character = BOXDRAW_DOWN_LEFT;\r
1060 PrintChar (Character);\r
1061 Character = BOXDRAW_VERTICAL;\r
f4bcc90f 1062\r
1063 Count = 0;\r
1064 for (Index = Top; Index + 2 < Bottom; Index++, Count++) {\r
1065 String = VA_ARG (Marker, CHAR16*);\r
7936fb6a 1066\r
1067 //\r
1068 // This will clear the background of the line - we never know who might have been\r
1069 // here before us. This differs from the next clear in that it used the non-reverse\r
1070 // video for normal printing.\r
1071 //\r
1072 if (GetStringWidth (String) / 2 > 1) {\r
1073 ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
1074 }\r
1075\r
1076 //\r
1077 // Passing in a space results in the assumption that this is where typing will occur\r
1078 //\r
1079 if (String[0] == L' ') {\r
1080 ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);\r
1081 }\r
1082\r
1083 //\r
1084 // Passing in a NULL results in a blank space\r
1085 //\r
1086 if (String[0] == CHAR_NULL) {\r
1087 ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
1088 }\r
1089\r
1090 PrintStringAt (\r
1091 ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,\r
1092 Index + 1,\r
1093 String\r
1094 );\r
1095 gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
1096 PrintCharAt (Start, Index + 1, Character);\r
1097 PrintCharAt (End - 1, Index + 1, Character);\r
1098 }\r
1099\r
1100 Character = BOXDRAW_UP_RIGHT;\r
1101 PrintCharAt (Start, Bottom - 1, Character);\r
1102 Character = BOXDRAW_HORIZONTAL;\r
1103 for (Index = Start; Index + 2 < End; Index++) {\r
1104 PrintChar (Character);\r
1105 }\r
1106\r
1107 Character = BOXDRAW_UP_LEFT;\r
1108 PrintChar (Character);\r
1109}\r
1110\r
1111/**\r
1112 Draw a pop up windows based on the dimension, number of lines and\r
1113 strings specified.\r
1114\r
1115 @param RequestedWidth The width of the pop-up.\r
1116 @param NumberOfLines The number of lines.\r
7936fb6a 1117 @param ... A series of text strings that displayed in the pop-up.\r
1118\r
1119**/\r
1120VOID\r
8091267c 1121EFIAPI\r
3ebb9bdb 1122CreateMultiStringPopUp (\r
7936fb6a 1123 IN UINTN RequestedWidth,\r
1124 IN UINTN NumberOfLines,\r
7936fb6a 1125 ...\r
1126 )\r
1127{\r
f4bcc90f 1128 VA_LIST Marker;\r
1129\r
1130 VA_START (Marker, NumberOfLines);\r
d66e6c16 1131\r
f4bcc90f 1132 CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);\r
1133\r
1134 VA_END (Marker);\r
7936fb6a 1135}\r
1136\r
1137\r
1138/**\r
1139 Update status bar on the bottom of menu.\r
1140\r
b18e7050 1141 @param Selection Current Selction info.\r
7936fb6a 1142 @param MessageType The type of message to be shown.\r
1143 @param Flags The flags in Question header.\r
1144 @param State Set or clear.\r
1145\r
1146**/\r
1147VOID\r
1148UpdateStatusBar (\r
b18e7050 1149 IN UI_MENU_SELECTION *Selection,\r
7936fb6a 1150 IN UINTN MessageType,\r
1151 IN UINT8 Flags,\r
1152 IN BOOLEAN State\r
1153 )\r
1154{\r
1155 UINTN Index;\r
7936fb6a 1156 CHAR16 *NvUpdateMessage;\r
1157 CHAR16 *InputErrorMessage;\r
48a9d5f7
LG
1158 LIST_ENTRY *Link;\r
1159 FORM_BROWSER_FORMSET *LocalFormSet;\r
1160 FORM_BROWSER_STATEMENT *Question;\r
1161 \r
7936fb6a 1162 NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);\r
1163 InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);\r
1164\r
1165 switch (MessageType) {\r
1166 case INPUT_ERROR:\r
1167 if (State) {\r
1168 gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);\r
1169 PrintStringAt (\r
1170 gScreenDimensions.LeftColumn + gPromptBlockWidth,\r
1171 gScreenDimensions.BottomRow - 1,\r
1172 InputErrorMessage\r
1173 );\r
19b15d63 1174 mInputError = TRUE;\r
7936fb6a 1175 } else {\r
f0a1bf11 1176 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
7936fb6a 1177 for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {\r
1178 PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");\r
1179 }\r
1180\r
19b15d63 1181 mInputError = FALSE;\r
7936fb6a 1182 }\r
1183 break;\r
1184\r
1185 case NV_UPDATE_REQUIRED:\r
48a9d5f7
LG
1186 //\r
1187 // Global setting support. Show configuration change on every form.\r
1188 //\r
1189 if (State) {\r
1190 gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));\r
1191\r
1192 if (Selection != NULL && Selection->Statement != NULL) {\r
1193 Question = Selection->Statement;\r
1194 if (Question->Storage != NULL || Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1195 //\r
1196 // Update only for Question value that need to be saved into Storage.\r
1197 //\r
1198 Selection->Form->NvUpdateRequired = TRUE;\r
1199 }\r
1200 }\r
1201 \r
1202 if (Selection == NULL || IsNvUpdateRequired (Selection->FormSet)) {\r
7936fb6a 1203 gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);\r
1204 PrintStringAt (\r
1205 gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,\r
1206 gScreenDimensions.BottomRow - 1,\r
1207 NvUpdateMessage\r
1208 );\r
48a9d5f7
LG
1209 }\r
1210 } else {\r
1211 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
1212 for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {\r
1213 PrintAt (\r
1214 (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),\r
1215 gScreenDimensions.BottomRow - 1,\r
1216 L" "\r
1217 );\r
7936fb6a 1218 }\r
1219 }\r
1220 break;\r
1221\r
1222 case REFRESH_STATUS_BAR:\r
19b15d63 1223 if (mInputError) {\r
b18e7050 1224 UpdateStatusBar (Selection, INPUT_ERROR, Flags, TRUE);\r
7936fb6a 1225 }\r
1226\r
48a9d5f7
LG
1227 switch (gBrowserSettingScope) {\r
1228 case SystemLevel:\r
1229 //\r
1230 // Check the maintain list to see whether there is any change.\r
1231 //\r
1232 Link = GetFirstNode (&gBrowserFormSetList);\r
1233 while (!IsNull (&gBrowserFormSetList, Link)) {\r
1234 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
1235 if (IsNvUpdateRequired(LocalFormSet)) {\r
1236 UpdateStatusBar (NULL, NV_UPDATE_REQUIRED, Flags, TRUE);\r
1237 break;\r
1238 }\r
1239 Link = GetNextNode (&gBrowserFormSetList, Link);\r
1240 }\r
1241 break;\r
1242 case FormSetLevel:\r
1243 case FormLevel:\r
1244 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Flags, TRUE);\r
1245 default:\r
1246 break;\r
7936fb6a 1247 }\r
48a9d5f7 1248\r
7936fb6a 1249 break;\r
1250\r
1251 default:\r
1252 break;\r
1253 }\r
1254\r
f4113e1f 1255 FreePool (InputErrorMessage);\r
1256 FreePool (NvUpdateMessage);\r
7936fb6a 1257 return ;\r
1258}\r
1259\r
1260\r
1261/**\r
1262 Get the supported width for a particular op-code\r
1263\r
1264 @param Statement The FORM_BROWSER_STATEMENT structure passed in.\r
1265 @param Handle The handle in the HII database being used\r
1266\r
1267 @return Returns the number of CHAR16 characters that is support.\r
1268\r
1269**/\r
1270UINT16\r
1271GetWidth (\r
1272 IN FORM_BROWSER_STATEMENT *Statement,\r
1273 IN EFI_HII_HANDLE Handle\r
1274 )\r
1275{\r
1276 CHAR16 *String;\r
1277 UINTN Size;\r
1278 UINT16 Width;\r
1279\r
1280 Size = 0;\r
1281\r
1282 //\r
1283 // See if the second text parameter is really NULL\r
1284 //\r
1285 if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
1286 String = GetToken (Statement->TextTwo, Handle);\r
1287 Size = StrLen (String);\r
f4113e1f 1288 FreePool (String);\r
7936fb6a 1289 }\r
1290\r
1291 if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||\r
1292 (Statement->Operand == EFI_IFR_REF_OP) ||\r
1293 (Statement->Operand == EFI_IFR_PASSWORD_OP) ||\r
1294 (Statement->Operand == EFI_IFR_ACTION_OP) ||\r
1295 (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
1296 //\r
1297 // Allow a wide display if text op-code and no secondary text op-code\r
1298 //\r
1299 ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))\r
1300 ) {\r
1301 Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);\r
1302 } else {\r
1303 Width = (UINT16) gPromptBlockWidth;\r
1304 }\r
1305\r
1306 if (Statement->InSubtitle) {\r
1307 Width -= SUBTITLE_INDENT;\r
1308 }\r
1309\r
f7a14a9b 1310 return (UINT16) (Width - LEFT_SKIPPED_COLUMNS);\r
7936fb6a 1311}\r
1312\r
7936fb6a 1313/**\r
1314 Will copy LineWidth amount of a string in the OutputString buffer and return the\r
1315 number of CHAR16 characters that were copied into the OutputString buffer.\r
6c310dfb
ED
1316 The output string format is:\r
1317 Glyph Info + String info + '\0'.\r
1318\r
5ea466a5 1319 In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
7936fb6a 1320\r
1321 @param InputString String description for this option.\r
1322 @param LineWidth Width of the desired string to extract in CHAR16\r
1323 characters\r
6c310dfb 1324 @param GlyphWidth The glyph width of the begin of the char in the string.\r
7936fb6a 1325 @param Index Where in InputString to start the copy process\r
1326 @param OutputString Buffer to copy the string into\r
1327\r
6c310dfb
ED
1328 @return Returns the number of CHAR16 characters that were copied into the OutputString \r
1329 buffer, include extra glyph info and '\0' info.\r
7936fb6a 1330\r
1331**/\r
1332UINT16\r
1333GetLineByWidth (\r
1334 IN CHAR16 *InputString,\r
1335 IN UINT16 LineWidth,\r
6c310dfb 1336 IN OUT UINT16 *GlyphWidth,\r
7936fb6a 1337 IN OUT UINTN *Index,\r
1338 OUT CHAR16 **OutputString\r
1339 )\r
1340{\r
6c310dfb
ED
1341 UINT16 StrOffset;\r
1342 UINT16 GlyphOffset;\r
1343 UINT16 OriginalGlyphWidth;\r
1344 BOOLEAN ReturnFlag;\r
1345 UINT16 LastSpaceOffset;\r
1346 UINT16 LastGlyphWidth;\r
1347\r
1348 if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
1349 return 0;\r
1350 }\r
7936fb6a 1351\r
6c310dfb
ED
1352 if (LineWidth == 0 || *GlyphWidth == 0) {\r
1353 return 0;\r
7936fb6a 1354 }\r
1355\r
6c310dfb
ED
1356 //\r
1357 // Save original glyph width.\r
1358 //\r
1359 OriginalGlyphWidth = *GlyphWidth;\r
1360 LastGlyphWidth = OriginalGlyphWidth;\r
1361 ReturnFlag = FALSE;\r
1362 LastSpaceOffset = 0;\r
7936fb6a 1363\r
6c310dfb
ED
1364 //\r
1365 // 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
1366 // To avoid displaying this empty line in screen, just skip the two CHARs here.\r
1367 //\r
1368 if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
1369 *Index = *Index + 2;\r
1370 }\r
7936fb6a 1371\r
1372 //\r
6c310dfb 1373 // Fast-forward the string and see if there is a carriage-return in the string\r
7936fb6a 1374 //\r
6c310dfb
ED
1375 for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {\r
1376 switch (InputString[*Index + StrOffset]) {\r
1377 case NARROW_CHAR:\r
1378 *GlyphWidth = 1;\r
1379 break;\r
7936fb6a 1380\r
6c310dfb
ED
1381 case WIDE_CHAR:\r
1382 *GlyphWidth = 2;\r
1383 break;\r
7936fb6a 1384\r
6c310dfb
ED
1385 case CHAR_CARRIAGE_RETURN:\r
1386 case CHAR_LINEFEED:\r
1387 case CHAR_NULL:\r
1388 ReturnFlag = TRUE;\r
1389 break;\r
1390\r
1391 default:\r
1392 GlyphOffset = GlyphOffset + *GlyphWidth;\r
7936fb6a 1393\r
6c310dfb
ED
1394 //\r
1395 // Record the last space info in this line. Will be used in rewind.\r
1396 //\r
1397 if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {\r
1398 LastSpaceOffset = StrOffset;\r
1399 LastGlyphWidth = *GlyphWidth;\r
1400 }\r
1401 break;\r
1402 }\r
1403\r
1404 if (ReturnFlag) {\r
1405 break;\r
1406 }\r
1407 } \r
1408\r
1409 //\r
1410 // Rewind the string from the maximum size until we see a space to break the line\r
1411 //\r
1412 if (GlyphOffset > LineWidth) {\r
7936fb6a 1413 //\r
6c310dfb 1414 // Rewind the string to last space char in this line.\r
7936fb6a 1415 //\r
6c310dfb
ED
1416 if (LastSpaceOffset != 0) {\r
1417 StrOffset = LastSpaceOffset;\r
1418 *GlyphWidth = LastGlyphWidth;\r
1419 } else {\r
7936fb6a 1420 //\r
6c310dfb 1421 // Roll back to last char in the line width.\r
7936fb6a 1422 //\r
6c310dfb 1423 StrOffset--;\r
7936fb6a 1424 }\r
6c310dfb
ED
1425 }\r
1426\r
1427 //\r
1428 // The CHAR_NULL has process last time, this time just return 0 to stand for the end.\r
1429 //\r
1430 if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
1431 return 0;\r
1432 }\r
1433\r
1434 //\r
1435 // Need extra glyph info and '\0' info, so +2.\r
1436 //\r
1437 *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
1438 if (*OutputString == NULL) {\r
1439 return 0;\r
1440 }\r
1441\r
1442 //\r
1443 // Save the glyph info at the begin of the string, will used by Print function.\r
1444 //\r
1445 if (OriginalGlyphWidth == 1) {\r
1446 *(*OutputString) = NARROW_CHAR;\r
1447 } else {\r
1448 *(*OutputString) = WIDE_CHAR;\r
1449 }\r
7936fb6a 1450\r
6c310dfb 1451 CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
7936fb6a 1452\r
6c310dfb 1453 if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
7936fb6a 1454 //\r
6c310dfb
ED
1455 // Skip the space info at the begin of next line.\r
1456 // \r
1457 *Index = (UINT16) (*Index + StrOffset + 1);\r
76d6b68d 1458 } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {\r
7936fb6a 1459 //\r
6c310dfb
ED
1460 // Skip the /n or /n/r info.\r
1461 //\r
1462 if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
1463 *Index = (UINT16) (*Index + StrOffset + 2);\r
1464 } else {\r
1465 *Index = (UINT16) (*Index + StrOffset + 1);\r
1466 }\r
76d6b68d 1467 } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {\r
6c310dfb
ED
1468 //\r
1469 // Skip the /r or /r/n info.\r
1470 // \r
1471 if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
1472 *Index = (UINT16) (*Index + StrOffset + 2);\r
1473 } else {\r
1474 *Index = (UINT16) (*Index + StrOffset + 1);\r
1475 }\r
7936fb6a 1476 } else {\r
6c310dfb 1477 *Index = (UINT16) (*Index + StrOffset);\r
7936fb6a 1478 }\r
6c310dfb
ED
1479\r
1480 //\r
1481 // Include extra glyph info and '\0' info, so +2.\r
1482 //\r
1483 return StrOffset + 2;\r
7936fb6a 1484}\r
1485\r
1486\r
1487/**\r
1488 Update display lines for a Menu Option.\r
1489\r
1490 @param Selection The user's selection.\r
1491 @param MenuOption The MenuOption to be checked.\r
7936fb6a 1492\r
7936fb6a 1493**/\r
1494VOID\r
1495UpdateOptionSkipLines (\r
1496 IN UI_MENU_SELECTION *Selection,\r
5f4ef94a 1497 IN UI_MENU_OPTION *MenuOption\r
7936fb6a 1498 )\r
1499{\r
1500 UINTN Index;\r
1501 UINT16 Width;\r
1502 UINTN Row;\r
1503 UINTN OriginalRow;\r
1504 CHAR16 *OutputString;\r
1505 CHAR16 *OptionString;\r
6c310dfb 1506 UINT16 GlyphWidth;\r
7936fb6a 1507\r
1508 Row = 0;\r
5f4ef94a 1509 OptionString = NULL;\r
7936fb6a 1510 ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
1511\r
1512 if (OptionString != NULL) {\r
1513 Width = (UINT16) gOptionBlockWidth;\r
1514\r
1515 OriginalRow = Row;\r
6c310dfb 1516 GlyphWidth = 1;\r
7936fb6a 1517\r
6c310dfb 1518 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 1519 //\r
1520 // If there is more string to process print on the next row and increment the Skip value\r
1521 //\r
d1a54e2c 1522 if (StrLen (&OptionString[Index]) != 0) {\r
5f4ef94a
ED
1523 Row++;\r
1524 //\r
1525 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
1526 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
1527 // some testing to ensure we are keeping this in-sync.\r
1528 //\r
1529 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
1530 //\r
1531 if ((Row - OriginalRow) >= MenuOption->Skip) {\r
1532 MenuOption->Skip++;\r
7936fb6a 1533 }\r
1534 }\r
1535\r
f4113e1f 1536 FreePool (OutputString);\r
7936fb6a 1537 }\r
1538\r
1539 Row = OriginalRow;\r
1540 }\r
1541\r
5f4ef94a
ED
1542 if (OptionString != NULL) {\r
1543 FreePool (OptionString);\r
1544 }\r
7936fb6a 1545}\r
1546\r
1547\r
1548/**\r
1549 Check whether this Menu Option could be highlighted.\r
1550\r
1551 This is an internal function.\r
1552\r
1553 @param MenuOption The MenuOption to be checked.\r
1554\r
1555 @retval TRUE This Menu Option is selectable.\r
1556 @retval FALSE This Menu Option could not be selected.\r
1557\r
1558**/\r
1559BOOLEAN\r
1560IsSelectable (\r
1561 UI_MENU_OPTION *MenuOption\r
1562 )\r
1563{\r
1564 if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||\r
1565 MenuOption->GrayOut || MenuOption->ReadOnly) {\r
1566 return FALSE;\r
1567 } else {\r
1568 return TRUE;\r
1569 }\r
1570}\r
1571\r
1572\r
1573/**\r
1574 Determine if the menu is the last menu that can be selected.\r
1575\r
1576 This is an internal function.\r
d66e6c16 1577\r
7936fb6a 1578 @param Direction The scroll direction. False is down. True is up.\r
1579 @param CurrentPos The current focus.\r
1580\r
1581 @return FALSE -- the menu isn't the last menu that can be selected.\r
1582 @return TRUE -- the menu is the last menu that can be selected.\r
1583\r
1584**/\r
1585BOOLEAN\r
1586ValueIsScroll (\r
1587 IN BOOLEAN Direction,\r
1588 IN LIST_ENTRY *CurrentPos\r
1589 )\r
1590{\r
1591 LIST_ENTRY *Temp;\r
7936fb6a 1592\r
1593 Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
1594\r
ce6d12cc 1595 if (Temp == &gMenuOption) {\r
7936fb6a 1596 return TRUE;\r
1597 }\r
1598\r
11232773 1599 return FALSE;\r
7936fb6a 1600}\r
1601\r
1602\r
1603/**\r
1604 Move to next selectable statement.\r
d66e6c16 1605\r
7936fb6a 1606 This is an internal function.\r
d66e6c16 1607\r
5f4ef94a 1608 @param Selection Menu selection.\r
7936fb6a 1609 @param GoUp The navigation direction. TRUE: up, FALSE: down.\r
1610 @param CurrentPosition Current position.\r
11232773 1611 @param GapToTop Gap position to top or bottom.\r
7936fb6a 1612\r
1613 @return The row distance from current MenuOption to next selectable MenuOption.\r
1614\r
1615**/\r
1616INTN\r
1617MoveToNextStatement (\r
5f4ef94a 1618 IN UI_MENU_SELECTION *Selection,\r
7936fb6a 1619 IN BOOLEAN GoUp,\r
11232773
LG
1620 IN OUT LIST_ENTRY **CurrentPosition,\r
1621 IN UINTN GapToTop\r
7936fb6a 1622 )\r
1623{\r
1624 INTN Distance;\r
1625 LIST_ENTRY *Pos;\r
7936fb6a 1626 UI_MENU_OPTION *NextMenuOption;\r
11232773 1627 UI_MENU_OPTION *PreMenuOption;\r
7936fb6a 1628\r
11232773
LG
1629 Distance = 0;\r
1630 Pos = *CurrentPosition;\r
1631 PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
7936fb6a 1632\r
1633 while (TRUE) {\r
1634 NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
5f4ef94a
ED
1635 if (NextMenuOption->Row == 0) {\r
1636 UpdateOptionSkipLines (Selection, NextMenuOption);\r
1637 }\r
1638 \r
11232773
LG
1639 if (GoUp && (PreMenuOption != NextMenuOption)) {\r
1640 //\r
1641 // Current Position doesn't need to be caculated when go up.\r
1642 // Caculate distanct at first when go up\r
1643 //\r
1644 if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
1645 NextMenuOption = PreMenuOption;\r
1646 break;\r
1647 }\r
1648 Distance += NextMenuOption->Skip;\r
1649 }\r
7936fb6a 1650 if (IsSelectable (NextMenuOption)) {\r
1651 break;\r
1652 }\r
ce6d12cc 1653 if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
11232773
LG
1654 //\r
1655 // Arrive at top.\r
1656 //\r
1657 Distance = -1;\r
7936fb6a 1658 break;\r
1659 }\r
11232773
LG
1660 if (!GoUp) {\r
1661 //\r
1662 // Caculate distanct at later when go down\r
1663 //\r
1664 if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
1665 NextMenuOption = PreMenuOption;\r
7936fb6a 1666 break;\r
1667 }\r
11232773 1668 Distance += NextMenuOption->Skip;\r
7936fb6a 1669 }\r
11232773
LG
1670 PreMenuOption = NextMenuOption;\r
1671 Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
7936fb6a 1672 }\r
1673\r
1674 *CurrentPosition = &NextMenuOption->Link;\r
1675 return Distance;\r
1676}\r
1677\r
1678\r
1679/**\r
1680 Adjust Data and Time position accordingly.\r
1681 Data format : [01/02/2004] [11:22:33]\r
1682 Line number : 0 0 1 0 0 1\r
d66e6c16 1683\r
7936fb6a 1684 This is an internal function.\r
1685\r
1686 @param DirectionUp the up or down direction. False is down. True is\r
1687 up.\r
1688 @param CurrentPosition Current position. On return: Point to the last\r
1689 Option (Year or Second) if up; Point to the first\r
1690 Option (Month or Hour) if down.\r
1691\r
1692 @return Return line number to pad. It is possible that we stand on a zero-advance\r
1693 @return data or time opcode, so pad one line when we judge if we are going to scroll outside.\r
1694\r
1695**/\r
1696UINTN\r
1697AdjustDateAndTimePosition (\r
1698 IN BOOLEAN DirectionUp,\r
1699 IN OUT LIST_ENTRY **CurrentPosition\r
1700 )\r
1701{\r
1702 UINTN Count;\r
1703 LIST_ENTRY *NewPosition;\r
1704 UI_MENU_OPTION *MenuOption;\r
1705 UINTN PadLineNumber;\r
1706\r
1707 PadLineNumber = 0;\r
1708 NewPosition = *CurrentPosition;\r
1709 MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
1710\r
1711 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
1712 (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
1713 //\r
1714 // Calculate the distance from current position to the last Date/Time MenuOption\r
1715 //\r
1716 Count = 0;\r
1717 while (MenuOption->Skip == 0) {\r
1718 Count++;\r
1719 NewPosition = NewPosition->ForwardLink;\r
1720 MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
1721 PadLineNumber = 1;\r
1722 }\r
1723\r
1724 NewPosition = *CurrentPosition;\r
1725 if (DirectionUp) {\r
1726 //\r
1727 // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended\r
1728 // to be one that back to the previous set of MenuOptions, we need to advance to the first\r
1729 // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate\r
1730 // checking can be done.\r
1731 //\r
1732 while (Count++ < 2) {\r
1733 NewPosition = NewPosition->BackLink;\r
1734 }\r
1735 } else {\r
1736 //\r
1737 // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended\r
1738 // to be one that progresses to the next set of MenuOptions, we need to advance to the last\r
1739 // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate\r
1740 // checking can be done.\r
1741 //\r
1742 while (Count-- > 0) {\r
1743 NewPosition = NewPosition->ForwardLink;\r
1744 }\r
1745 }\r
1746\r
1747 *CurrentPosition = NewPosition;\r
1748 }\r
1749\r
1750 return PadLineNumber;\r
1751}\r
1752\r
cb7d01c0 1753/**\r
1754 Find HII Handle in the HII database associated with given Device Path.\r
1755\r
1756 If DevicePath is NULL, then ASSERT.\r
1757\r
1758 @param DevicePath Device Path associated with the HII package list\r
1759 handle.\r
1760\r
1761 @retval Handle HII package list Handle associated with the Device\r
1762 Path.\r
1763 @retval NULL Hii Package list handle is not found.\r
1764\r
1765**/\r
1766EFI_HII_HANDLE\r
1767EFIAPI\r
1768DevicePathToHiiHandle (\r
1769 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1770 )\r
1771{\r
1772 EFI_STATUS Status;\r
1773 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
1774 UINTN BufferSize;\r
1775 UINTN HandleCount;\r
1776 UINTN Index;\r
1777 EFI_HANDLE Handle;\r
1778 EFI_HANDLE DriverHandle;\r
1779 EFI_HII_HANDLE *HiiHandles;\r
1780 EFI_HII_HANDLE HiiHandle;\r
1781\r
1782 ASSERT (DevicePath != NULL);\r
1783\r
1784 TmpDevicePath = DevicePath;\r
1785 //\r
1786 // Locate Device Path Protocol handle buffer\r
1787 //\r
1788 Status = gBS->LocateDevicePath (\r
1789 &gEfiDevicePathProtocolGuid,\r
1790 &TmpDevicePath,\r
1791 &DriverHandle\r
1792 );\r
1793 if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
1794 return NULL;\r
1795 }\r
1796\r
1797 //\r
1798 // Retrieve all HII Handles from HII database\r
1799 //\r
1800 BufferSize = 0x1000;\r
1801 HiiHandles = AllocatePool (BufferSize);\r
1802 ASSERT (HiiHandles != NULL);\r
1803 Status = mHiiDatabase->ListPackageLists (\r
1804 mHiiDatabase,\r
1805 EFI_HII_PACKAGE_TYPE_ALL,\r
1806 NULL,\r
1807 &BufferSize,\r
1808 HiiHandles\r
1809 );\r
1810 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1811 FreePool (HiiHandles);\r
1812 HiiHandles = AllocatePool (BufferSize);\r
1813 ASSERT (HiiHandles != NULL);\r
1814\r
1815 Status = mHiiDatabase->ListPackageLists (\r
1816 mHiiDatabase,\r
1817 EFI_HII_PACKAGE_TYPE_ALL,\r
1818 NULL,\r
1819 &BufferSize,\r
1820 HiiHandles\r
1821 );\r
1822 }\r
1823\r
1824 if (EFI_ERROR (Status)) {\r
1825 FreePool (HiiHandles);\r
1826 return NULL;\r
1827 }\r
1828\r
1829 //\r
1830 // Search Hii Handle by Driver Handle\r
1831 //\r
1832 HiiHandle = NULL;\r
1833 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
1834 for (Index = 0; Index < HandleCount; Index++) {\r
1835 Status = mHiiDatabase->GetPackageListHandle (\r
1836 mHiiDatabase,\r
1837 HiiHandles[Index],\r
1838 &Handle\r
1839 );\r
1840 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
1841 HiiHandle = HiiHandles[Index];\r
1842 break;\r
1843 }\r
1844 }\r
1845\r
1846 FreePool (HiiHandles);\r
1847 return HiiHandle;\r
1848}\r
7936fb6a 1849\r
b2e444aa
ED
1850/**\r
1851 Find HII Handle in the HII database associated with given form set guid.\r
1852\r
1853 If FormSetGuid is NULL, then ASSERT.\r
1854\r
1855 @param ComparingGuid FormSet Guid associated with the HII package list\r
1856 handle.\r
1857\r
1858 @retval Handle HII package list Handle associated with the Device\r
1859 Path.\r
1860 @retval NULL Hii Package list handle is not found.\r
1861\r
1862**/\r
1863EFI_HII_HANDLE\r
1864FormSetGuidToHiiHandle (\r
1865 EFI_GUID *ComparingGuid\r
1866 )\r
1867{\r
1868 EFI_HII_HANDLE *HiiHandles;\r
1869 UINTN Index;\r
1870 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
1871 UINTN BufferSize;\r
1872 UINT32 Offset;\r
1873 UINT32 Offset2;\r
1874 UINT32 PackageListLength;\r
1875 EFI_HII_PACKAGE_HEADER PackageHeader;\r
1876 UINT8 *Package;\r
1877 UINT8 *OpCodeData;\r
1878 EFI_STATUS Status;\r
1879 EFI_HII_HANDLE HiiHandle;\r
1880\r
1881 ASSERT (ComparingGuid != NULL);\r
1882\r
1883 HiiHandle = NULL;\r
1884 //\r
1885 // Get all the Hii handles\r
1886 //\r
1887 HiiHandles = HiiGetHiiHandles (NULL);\r
1888 ASSERT (HiiHandles != NULL);\r
1889\r
1890 //\r
1891 // Search for formset of each class type\r
1892 //\r
1893 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
1894 BufferSize = 0;\r
1895 HiiPackageList = NULL;\r
1896 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
1897 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1898 HiiPackageList = AllocatePool (BufferSize);\r
1899 ASSERT (HiiPackageList != NULL);\r
1900\r
1901 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
1902 }\r
1903 if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
1904 return NULL;\r
1905 }\r
1906\r
1907 //\r
1908 // Get Form package from this HII package List\r
1909 //\r
1910 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1911 Offset2 = 0;\r
1912 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); \r
1913\r
1914 while (Offset < PackageListLength) {\r
1915 Package = ((UINT8 *) HiiPackageList) + Offset;\r
1916 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
1917\r
1918 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1919 //\r
1920 // Search FormSet in this Form Package\r
1921 //\r
1922 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
1923 while (Offset2 < PackageHeader.Length) {\r
1924 OpCodeData = Package + Offset2;\r
1925\r
1926 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
1927 //\r
1928 // Try to compare against formset GUID\r
1929 //\r
1930 if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
1931 HiiHandle = HiiHandles[Index];\r
1932 break;\r
1933 }\r
1934 }\r
1935\r
1936 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
1937 }\r
1938 }\r
1939 if (HiiHandle != NULL) {\r
1940 break;\r
1941 }\r
1942 Offset += PackageHeader.Length;\r
1943 }\r
1944 \r
1945 FreePool (HiiPackageList);\r
1946 if (HiiHandle != NULL) {\r
1947 break;\r
1948 }\r
1949 }\r
1950\r
1951 FreePool (HiiHandles);\r
1952\r
1953 return HiiHandle;\r
1954}\r
1955\r
33efdf51
ED
1956/**\r
1957 Transfer the device path string to binary format.\r
1958\r
1959 @param StringPtr The device path string info.\r
1960\r
1961 @retval Device path binary info.\r
1962\r
1963**/\r
1964EFI_DEVICE_PATH_PROTOCOL *\r
1965ConvertDevicePathFromText (\r
1966 IN CHAR16 *StringPtr\r
1967 )\r
1968{\r
1969 UINTN BufferSize;\r
1970 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1971 CHAR16 TemStr[2];\r
1972 UINT8 *DevicePathBuffer;\r
1973 UINTN Index;\r
1974 UINT8 DigitUint8;\r
1975\r
1976 ASSERT (StringPtr != NULL);\r
1977\r
1978 BufferSize = StrLen (StringPtr) / 2;\r
1979 DevicePath = AllocatePool (BufferSize);\r
1980 ASSERT (DevicePath != NULL);\r
1981 \r
1982 //\r
1983 // Convert from Device Path String to DevicePath Buffer in the reverse order.\r
1984 //\r
1985 DevicePathBuffer = (UINT8 *) DevicePath;\r
1986 for (Index = 0; StringPtr[Index] != L'\0'; Index ++) {\r
1987 TemStr[0] = StringPtr[Index];\r
1988 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1989 if (DigitUint8 == 0 && TemStr[0] != L'0') {\r
1990 //\r
1991 // Invalid Hex Char as the tail.\r
1992 //\r
1993 break;\r
1994 }\r
1995 if ((Index & 1) == 0) {\r
1996 DevicePathBuffer [Index/2] = DigitUint8;\r
1997 } else {\r
1998 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
1999 }\r
2000 }\r
2001\r
2002 return DevicePath;\r
2003}\r
2004\r
8ca6180f
ED
2005/**\r
2006 Process the goto op code, update the info in the selection structure.\r
2007\r
2008 @param Statement The statement belong to goto op code.\r
2009 @param Selection The selection info.\r
2010 @param Repaint Whether need to repaint the menu.\r
2011 @param NewLine Whether need to create new line.\r
2012\r
2013 @retval EFI_SUCCESS The menu process successfully.\r
2014 @return Other value if the process failed.\r
2015**/\r
2016EFI_STATUS\r
2017ProcessGotoOpCode (\r
2018 IN OUT FORM_BROWSER_STATEMENT *Statement,\r
2019 IN OUT UI_MENU_SELECTION *Selection,\r
2020 OUT BOOLEAN *Repaint,\r
2021 OUT BOOLEAN *NewLine\r
2022 )\r
2023{\r
2024 CHAR16 *StringPtr;\r
8ca6180f 2025 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
8ca6180f
ED
2026 FORM_BROWSER_FORM *RefForm;\r
2027 EFI_INPUT_KEY Key;\r
2028 EFI_STATUS Status;\r
2029 UI_MENU_LIST *MenuList;\r
b2e444aa 2030 BOOLEAN UpdateFormInfo;\r
8ca6180f
ED
2031 \r
2032 Status = EFI_SUCCESS;\r
b2e444aa 2033 UpdateFormInfo = TRUE;\r
e7fd76d1 2034 StringPtr = NULL;\r
8ca6180f 2035\r
e7fd76d1
ED
2036 //\r
2037 // Prepare the device path check, get the device path info first.\r
2038 //\r
8ca6180f 2039 if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
e7fd76d1 2040 StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
e7fd76d1
ED
2041 }\r
2042\r
2043 //\r
2044 // Check whether the device path string is a valid string.\r
2045 //\r
33efdf51 2046 if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) {\r
8ca6180f
ED
2047 if (Selection->Form->ModalForm) {\r
2048 return Status;\r
2049 }\r
2050 //\r
2051 // Goto another Hii Package list\r
2052 //\r
2053 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
33efdf51 2054 DevicePath = ConvertDevicePathFromText (StringPtr);\r
8ca6180f
ED
2055\r
2056 Selection->Handle = DevicePathToHiiHandle (DevicePath);\r
e7fd76d1 2057 FreePool (DevicePath);\r
33efdf51 2058 FreePool (StringPtr);\r
e7fd76d1 2059\r
8ca6180f
ED
2060 if (Selection->Handle == NULL) {\r
2061 //\r
2062 // If target Hii Handle not found, exit\r
2063 //\r
2064 Selection->Action = UI_ACTION_EXIT;\r
2065 Selection->Statement = NULL;\r
2066 return Status;\r
2067 }\r
2068\r
8ca6180f
ED
2069 CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
2070 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
2071 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2072 } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {\r
2073 if (Selection->Form->ModalForm) {\r
2074 return Status;\r
2075 } \r
2076 //\r
2077 // Goto another Formset, check for uncommitted data\r
2078 //\r
2079 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
b2e444aa
ED
2080 \r
2081 Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
2082 if (Selection->Handle == NULL) {\r
2083 //\r
2084 // If target Hii Handle not found, exit\r
2085 //\r
2086 Selection->Action = UI_ACTION_EXIT;\r
2087 Selection->Statement = NULL;\r
2088 return Status;\r
2089 } \r
8ca6180f
ED
2090\r
2091 CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
2092 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
2093 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2094 } else if (Statement->HiiValue.Value.ref.FormId != 0) {\r
2095 //\r
2096 // Check whether target From is suppressed.\r
2097 //\r
2098 RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
2099\r
2100 if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
31585af4 2101 if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
8ca6180f
ED
2102 //\r
2103 // Form is suppressed. \r
2104 //\r
2105 do {\r
2106 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);\r
2107 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2108 if (Repaint != NULL) {\r
2109 *Repaint = TRUE;\r
2110 }\r
2111 return Status;\r
2112 }\r
2113 }\r
2114\r
2115 //\r
2116 // Goto another form inside this formset,\r
2117 //\r
2118 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2119\r
8ca6180f
ED
2120 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
2121 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2122 } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {\r
2123 //\r
2124 // Goto another Question\r
2125 //\r
2126 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2127\r
2128 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
2129 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2130 } else {\r
2131 if (Repaint != NULL) {\r
2132 *Repaint = TRUE;\r
2133 }\r
2134 if (NewLine != NULL) {\r
2135 *NewLine = TRUE;\r
2136 }\r
2137 }\r
b2e444aa 2138 UpdateFormInfo = FALSE;\r
8ca6180f
ED
2139 } else {\r
2140 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
2141 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2142 }\r
b2e444aa
ED
2143 UpdateFormInfo = FALSE;\r
2144 }\r
2145\r
2146 if (UpdateFormInfo) {\r
2147 //\r
2148 // Link current form so that we can always go back when someone hits the ESC\r
2149 //\r
2150 MenuList = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId);\r
2151 if (MenuList == NULL && Selection->CurrentMenu != NULL) {\r
2152 MenuList = UiAddMenuList (Selection->CurrentMenu, Selection->Handle, &Selection->FormSetGuid, Selection->FormId);\r
2153 }\r
8ca6180f
ED
2154 }\r
2155\r
2156 return Status;\r
2157}\r
2158\r
7936fb6a 2159/**\r
2160 Display menu and wait for user to select one menu option, then return it.\r
2161 If AutoBoot is enabled, then if user doesn't select any option,\r
2162 after period of time, it will automatically return the first menu option.\r
2163\r
2164 @param Selection Menu selection.\r
2165\r
2166 @retval EFI_SUCESSS This function always return successfully for now.\r
2167\r
2168**/\r
2169EFI_STATUS\r
2170UiDisplayMenu (\r
2171 IN OUT UI_MENU_SELECTION *Selection\r
2172 )\r
2173{\r
2174 INTN SkipValue;\r
2175 INTN Difference;\r
2176 INTN OldSkipValue;\r
2177 UINTN DistanceValue;\r
2178 UINTN Row;\r
2179 UINTN Col;\r
2180 UINTN Temp;\r
2181 UINTN Temp2;\r
2182 UINTN TopRow;\r
2183 UINTN BottomRow;\r
2184 UINTN OriginalRow;\r
2185 UINTN Index;\r
7936fb6a 2186 UINT16 Width;\r
2187 CHAR16 *StringPtr;\r
2188 CHAR16 *OptionString;\r
2189 CHAR16 *OutputString;\r
ba46ab94
ED
2190 CHAR16 *HelpString;\r
2191 CHAR16 *HelpHeaderString;\r
2192 CHAR16 *HelpBottomString;\r
7936fb6a 2193 BOOLEAN NewLine;\r
2194 BOOLEAN Repaint;\r
2195 BOOLEAN SavedValue;\r
ce6d12cc 2196 BOOLEAN UpArrow;\r
2197 BOOLEAN DownArrow;\r
11232773 2198 BOOLEAN InitializedFlag;\r
7936fb6a 2199 EFI_STATUS Status;\r
2200 EFI_INPUT_KEY Key;\r
2201 LIST_ENTRY *Link;\r
2202 LIST_ENTRY *NewPos;\r
2203 LIST_ENTRY *TopOfScreen;\r
2204 LIST_ENTRY *SavedListEntry;\r
2205 UI_MENU_OPTION *MenuOption;\r
2206 UI_MENU_OPTION *NextMenuOption;\r
2207 UI_MENU_OPTION *SavedMenuOption;\r
2208 UI_MENU_OPTION *PreviousMenuOption;\r
2209 UI_CONTROL_FLAG ControlFlag;\r
2210 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
2211 MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
211cc6e5 2212 MENU_REFRESH_ENTRY *MenuUpdateEntry; \r
7936fb6a 2213 UI_SCREEN_OPERATION ScreenOperation;\r
2214 UINT8 MinRefreshInterval;\r
7936fb6a 2215 UINT16 DefaultId;\r
7936fb6a 2216 FORM_BROWSER_STATEMENT *Statement;\r
d66e6c16 2217 UI_MENU_LIST *CurrentMenu;\r
b00964a9 2218 UINTN ModalSkipColumn;\r
48a9d5f7 2219 BROWSER_HOT_KEY *HotKey;\r
ba46ab94
ED
2220 UINTN HelpPageIndex;\r
2221 UINTN HelpPageCount;\r
2222 UINTN RowCount;\r
2223 UINTN HelpLine;\r
2224 UINTN HelpHeaderLine;\r
2225 UINTN HelpBottomLine;\r
2226 BOOLEAN MultiHelpPage;\r
6c310dfb
ED
2227 UINT16 GlyphWidth;\r
2228 UINT16 EachLineWidth;\r
2229 UINT16 HeaderLineWidth;\r
2230 UINT16 BottomLineWidth;\r
7936fb6a 2231\r
2232 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
2233\r
2234 Status = EFI_SUCCESS;\r
ba46ab94
ED
2235 HelpString = NULL;\r
2236 HelpHeaderString = NULL;\r
2237 HelpBottomString = NULL;\r
7936fb6a 2238 OptionString = NULL;\r
2239 ScreenOperation = UiNoOperation;\r
2240 NewLine = TRUE;\r
2241 MinRefreshInterval = 0;\r
2242 DefaultId = 0;\r
ba46ab94
ED
2243 HelpPageCount = 0;\r
2244 HelpLine = 0;\r
2245 RowCount = 0;\r
2246 HelpBottomLine = 0;\r
2247 HelpHeaderLine = 0;\r
2248 HelpPageIndex = 0;\r
2249 MultiHelpPage = FALSE;\r
6c310dfb
ED
2250 EachLineWidth = 0;\r
2251 HeaderLineWidth = 0;\r
2252 BottomLineWidth = 0;\r
7936fb6a 2253 OutputString = NULL;\r
ce6d12cc 2254 UpArrow = FALSE;\r
2255 DownArrow = FALSE;\r
7936fb6a 2256 SkipValue = 0;\r
2257 OldSkipValue = 0;\r
2258 MenuRefreshEntry = gMenuRefreshHead;\r
2259\r
2260 NextMenuOption = NULL;\r
2261 PreviousMenuOption = NULL;\r
2262 SavedMenuOption = NULL;\r
48a9d5f7 2263 HotKey = NULL;\r
b00964a9 2264 ModalSkipColumn = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 6;\r
7936fb6a 2265\r
2266 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
2267\r
40245175 2268 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE){\r
7936fb6a 2269 TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2270 Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2271 } else {\r
2272 TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2273 Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2274 }\r
2275\r
b00964a9
ED
2276 if (Selection->Form->ModalForm) {\r
2277 Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn;\r
2278 } else {\r
2279 Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;\r
2280 }\r
2281\r
48a9d5f7 2282 BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - SCROLL_ARROW_HEIGHT - 1;\r
7936fb6a 2283\r
2284 Selection->TopRow = TopRow;\r
2285 Selection->BottomRow = BottomRow;\r
2286 Selection->PromptCol = Col;\r
2287 Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
2288 Selection->Statement = NULL;\r
2289\r
ce6d12cc 2290 TopOfScreen = gMenuOption.ForwardLink;\r
7936fb6a 2291 Repaint = TRUE;\r
2292 MenuOption = NULL;\r
2293\r
d66e6c16 2294 //\r
2295 // Find current Menu\r
2296 //\r
2297 CurrentMenu = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId);\r
2298 if (CurrentMenu == NULL) {\r
2299 //\r
2300 // Current menu not found, add it to the menu tree\r
2301 //\r
b2e444aa 2302 CurrentMenu = UiAddMenuList (NULL, Selection->Handle, &Selection->FormSetGuid, Selection->FormId);\r
d66e6c16 2303 }\r
2304 ASSERT (CurrentMenu != NULL);\r
b18e7050 2305 Selection->CurrentMenu = CurrentMenu;\r
d66e6c16 2306\r
2307 if (Selection->QuestionId == 0) {\r
2308 //\r
2309 // Highlight not specified, fetch it from cached menu\r
2310 //\r
2311 Selection->QuestionId = CurrentMenu->QuestionId;\r
d88ca2c9 2312 Selection->Sequence = CurrentMenu->Sequence;\r
d66e6c16 2313 }\r
2314\r
7936fb6a 2315 //\r
11232773 2316 // Init option as the current user's selection\r
7936fb6a 2317 //\r
11232773 2318 InitializedFlag = TRUE;\r
ce6d12cc 2319 NewPos = gMenuOption.ForwardLink;\r
7936fb6a 2320\r
2321 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
b18e7050 2322 UpdateStatusBar (Selection, REFRESH_STATUS_BAR, (UINT8) 0, TRUE);\r
7936fb6a 2323\r
2324 ControlFlag = CfInitialization;\r
2325 Selection->Action = UI_ACTION_NONE;\r
2326 while (TRUE) {\r
2327 switch (ControlFlag) {\r
2328 case CfInitialization:\r
ce6d12cc 2329 if (IsListEmpty (&gMenuOption)) {\r
7936fb6a 2330 ControlFlag = CfReadKey;\r
2331 } else {\r
2332 ControlFlag = CfCheckSelection;\r
2333 }\r
2334 break;\r
2335\r
2336 case CfCheckSelection:\r
2337 if (Selection->Action != UI_ACTION_NONE) {\r
2338 ControlFlag = CfExit;\r
2339 } else {\r
2340 ControlFlag = CfRepaint;\r
2341 }\r
2342 break;\r
2343\r
2344 case CfRepaint:\r
2345 ControlFlag = CfRefreshHighLight;\r
2346\r
2347 if (Repaint) {\r
2348 //\r
2349 // Display menu\r
2350 //\r
ce6d12cc 2351 DownArrow = FALSE;\r
2352 UpArrow = FALSE;\r
7936fb6a 2353 Row = TopRow;\r
2354\r
cd7bfc2c
ED
2355 Temp = (UINTN) SkipValue;\r
2356 Temp2 = (UINTN) SkipValue;\r
7936fb6a 2357\r
b00964a9
ED
2358 if (Selection->Form->ModalForm) {\r
2359 ClearLines (\r
2360 LocalScreen.LeftColumn + ModalSkipColumn,\r
2361 LocalScreen.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth,\r
2362 TopRow - SCROLL_ARROW_HEIGHT,\r
2363 BottomRow + SCROLL_ARROW_HEIGHT,\r
2364 PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
2365 ); \r
2366 } else {\r
2367 ClearLines (\r
2368 LocalScreen.LeftColumn,\r
2369 LocalScreen.RightColumn,\r
2370 TopRow - SCROLL_ARROW_HEIGHT,\r
2371 BottomRow + SCROLL_ARROW_HEIGHT,\r
2372 PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
2373 );\r
2374 }\r
7936fb6a 2375 UiFreeRefreshList ();\r
2376 MinRefreshInterval = 0;\r
2377\r
ce6d12cc 2378 for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {\r
7936fb6a 2379 MenuOption = MENU_OPTION_FROM_LINK (Link);\r
2380 MenuOption->Row = Row;\r
2381 MenuOption->Col = Col;\r
b00964a9
ED
2382 if (Selection->Form->ModalForm) {\r
2383 MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn + ModalSkipColumn;\r
2384 } else {\r
2385 MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
2386 }\r
7936fb6a 2387\r
2388 Statement = MenuOption->ThisTag;\r
2389 if (Statement->InSubtitle) {\r
2390 MenuOption->Col += SUBTITLE_INDENT;\r
2391 }\r
2392\r
2393 if (MenuOption->GrayOut) {\r
2394 gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
2395 } else {\r
2396 if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {\r
f0a1bf11 2397 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2398 }\r
2399 }\r
2400\r
2401 Width = GetWidth (Statement, MenuOption->Handle);\r
2402 OriginalRow = Row;\r
6c310dfb 2403 GlyphWidth = 1;\r
7936fb6a 2404\r
11232773 2405 if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
a605dfb3
LG
2406 //\r
2407 // Print Arrow for Goto button.\r
2408 //\r
2409 PrintAt (\r
b6ca1fd8 2410 MenuOption->Col - 2,\r
a605dfb3
LG
2411 Row,\r
2412 L"%c",\r
2413 GEOMETRICSHAPE_RIGHT_TRIANGLE\r
2414 );\r
2415 }\r
2416\r
6c310dfb 2417 for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2418 if ((Temp == 0) && (Row <= BottomRow)) {\r
2419 PrintStringAt (MenuOption->Col, Row, OutputString);\r
2420 }\r
2421 //\r
2422 // If there is more string to process print on the next row and increment the Skip value\r
2423 //\r
d1a54e2c 2424 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
7936fb6a 2425 if (Temp == 0) {\r
2426 Row++;\r
2427 }\r
2428 }\r
2429\r
f4113e1f 2430 FreePool (OutputString);\r
7936fb6a 2431 if (Temp != 0) {\r
2432 Temp--;\r
2433 }\r
2434 }\r
2435\r
2436 Temp = 0;\r
2437 Row = OriginalRow;\r
2438\r
8d00a0f1 2439 Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
2440 if (EFI_ERROR (Status)) {\r
2441 //\r
2442 // Repaint to clear possible error prompt pop-up\r
2443 //\r
2444 Repaint = TRUE;\r
2445 NewLine = TRUE;\r
2446 ControlFlag = CfRepaint;\r
2447 break;\r
2448 }\r
7936fb6a 2449\r
2450 if (OptionString != NULL) {\r
2451 if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
4a6876b7 2452 ProcessStringForDateTime(MenuOption, OptionString, TRUE);\r
7936fb6a 2453 }\r
2454\r
7936fb6a 2455 Width = (UINT16) gOptionBlockWidth;\r
2456 OriginalRow = Row;\r
6c310dfb 2457 GlyphWidth = 1;\r
7936fb6a 2458\r
6c310dfb 2459 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2460 if ((Temp2 == 0) && (Row <= BottomRow)) {\r
2461 PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
2462 }\r
2463 //\r
2464 // If there is more string to process print on the next row and increment the Skip value\r
2465 //\r
d1a54e2c 2466 if (StrLen (&OptionString[Index]) != 0) {\r
7936fb6a 2467 if (Temp2 == 0) {\r
2468 Row++;\r
2469 //\r
2470 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
2471 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
2472 // some testing to ensure we are keeping this in-sync.\r
2473 //\r
2474 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
2475 //\r
2476 if ((Row - OriginalRow) >= MenuOption->Skip) {\r
2477 MenuOption->Skip++;\r
2478 }\r
2479 }\r
2480 }\r
2481\r
f4113e1f 2482 FreePool (OutputString);\r
7936fb6a 2483 if (Temp2 != 0) {\r
2484 Temp2--;\r
2485 }\r
2486 }\r
2487\r
2488 Temp2 = 0;\r
2489 Row = OriginalRow;\r
2490\r
f4113e1f 2491 FreePool (OptionString);\r
7936fb6a 2492 }\r
4ffaadcc
ED
2493\r
2494 //\r
2495 // If Question has refresh guid, register the op-code.\r
2496 //\r
2497 if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
2498 if (gMenuEventGuidRefreshHead == NULL) {\r
2499 MenuUpdateEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2500 gMenuEventGuidRefreshHead = MenuUpdateEntry;\r
2501 } else {\r
2502 MenuUpdateEntry = gMenuEventGuidRefreshHead;\r
2503 while (MenuUpdateEntry->Next != NULL) {\r
2504 MenuUpdateEntry = MenuUpdateEntry->Next; \r
2505 }\r
2506 MenuUpdateEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2507 MenuUpdateEntry = MenuUpdateEntry->Next; \r
2508 }\r
2509 ASSERT (MenuUpdateEntry != NULL);\r
2510 Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RefreshQuestionNotify, MenuUpdateEntry, &Statement->RefreshGuid, &MenuUpdateEntry->Event);\r
2511 ASSERT (!EFI_ERROR (Status));\r
2512 MenuUpdateEntry->MenuOption = MenuOption;\r
2513 MenuUpdateEntry->Selection = Selection;\r
2514 MenuUpdateEntry->CurrentColumn = MenuOption->OptCol;\r
2515 MenuUpdateEntry->CurrentRow = MenuOption->Row;\r
2516 if (MenuOption->GrayOut) {\r
2517 MenuUpdateEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
2518 } else {\r
2519 MenuUpdateEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
2520 }\r
2521 }\r
2522 \r
2523 //\r
2524 // If Question request refresh, register the op-code\r
2525 //\r
2526 if (Statement->RefreshInterval != 0) {\r
2527 //\r
2528 // Menu will be refreshed at minimal interval of all Questions\r
2529 // which have refresh request\r
2530 //\r
2531 if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {\r
2532 MinRefreshInterval = Statement->RefreshInterval;\r
2533 }\r
2534 \r
2535 if (gMenuRefreshHead == NULL) {\r
2536 MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2537 gMenuRefreshHead = MenuRefreshEntry;\r
2538 } else {\r
2539 MenuRefreshEntry = gMenuRefreshHead;\r
2540 while (MenuRefreshEntry->Next != NULL) {\r
2541 MenuRefreshEntry = MenuRefreshEntry->Next; \r
2542 }\r
2543 MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2544 MenuRefreshEntry = MenuRefreshEntry->Next;\r
2545 }\r
2546 ASSERT (MenuRefreshEntry != NULL); \r
2547 MenuRefreshEntry->MenuOption = MenuOption;\r
2548 MenuRefreshEntry->Selection = Selection;\r
2549 MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;\r
2550 MenuRefreshEntry->CurrentRow = MenuOption->Row;\r
2551 if (MenuOption->GrayOut) {\r
2552 MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
2553 } else { \r
2554 MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
2555 }\r
2556 }\r
2557 \r
7936fb6a 2558 //\r
2559 // If this is a text op with secondary text information\r
2560 //\r
2561 if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
2562 StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle);\r
2563\r
2564 Width = (UINT16) gOptionBlockWidth;\r
2565 OriginalRow = Row;\r
6c310dfb 2566 GlyphWidth = 1;\r
7936fb6a 2567\r
6c310dfb 2568 for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2569 if ((Temp == 0) && (Row <= BottomRow)) {\r
2570 PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
2571 }\r
2572 //\r
2573 // If there is more string to process print on the next row and increment the Skip value\r
2574 //\r
d1a54e2c 2575 if (StrLen (&StringPtr[Index]) != 0) {\r
7936fb6a 2576 if (Temp2 == 0) {\r
2577 Row++;\r
2578 //\r
2579 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
2580 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
2581 // some testing to ensure we are keeping this in-sync.\r
2582 //\r
2583 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
2584 //\r
2585 if ((Row - OriginalRow) >= MenuOption->Skip) {\r
2586 MenuOption->Skip++;\r
2587 }\r
2588 }\r
2589 }\r
2590\r
f4113e1f 2591 FreePool (OutputString);\r
7936fb6a 2592 if (Temp2 != 0) {\r
2593 Temp2--;\r
2594 }\r
2595 }\r
2596\r
2597 Row = OriginalRow;\r
f4113e1f 2598 FreePool (StringPtr);\r
7936fb6a 2599 }\r
f0a1bf11 2600 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2601\r
2602 //\r
2603 // Need to handle the bottom of the display\r
2604 //\r
2605 if (MenuOption->Skip > 1) {\r
2606 Row += MenuOption->Skip - SkipValue;\r
2607 SkipValue = 0;\r
2608 } else {\r
2609 Row += MenuOption->Skip;\r
2610 }\r
2611\r
2612 if (Row > BottomRow) {\r
2613 if (!ValueIsScroll (FALSE, Link)) {\r
ce6d12cc 2614 DownArrow = TRUE;\r
7936fb6a 2615 }\r
2616\r
2617 Row = BottomRow + 1;\r
2618 break;\r
2619 }\r
2620 }\r
2621\r
2622 if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
ce6d12cc 2623 UpArrow = TRUE;\r
7936fb6a 2624 }\r
2625\r
ce6d12cc 2626 if (UpArrow) {\r
7936fb6a 2627 gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
2628 PrintAt (\r
2629 LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
2630 TopRow - SCROLL_ARROW_HEIGHT,\r
2631 L"%c",\r
2632 ARROW_UP\r
2633 );\r
f0a1bf11 2634 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2635 }\r
2636\r
ce6d12cc 2637 if (DownArrow) {\r
7936fb6a 2638 gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
2639 PrintAt (\r
2640 LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
2641 BottomRow + SCROLL_ARROW_HEIGHT,\r
2642 L"%c",\r
2643 ARROW_DOWN\r
2644 );\r
f0a1bf11 2645 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2646 }\r
2647\r
2648 MenuOption = NULL;\r
2649 }\r
2650 break;\r
2651\r
2652 case CfRefreshHighLight:\r
2653 //\r
2654 // MenuOption: Last menu option that need to remove hilight\r
2655 // MenuOption is set to NULL in Repaint\r
2656 // NewPos: Current menu option that need to hilight\r
2657 //\r
2658 ControlFlag = CfUpdateHelpString;\r
11232773
LG
2659 if (InitializedFlag) {\r
2660 InitializedFlag = FALSE;\r
5f4ef94a 2661 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773 2662 }\r
7936fb6a 2663\r
2664 //\r
2665 // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily\r
2666 // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.\r
2667 //\r
2668 SavedValue = Repaint;\r
2669 Repaint = FALSE;\r
2670\r
2671 if (Selection->QuestionId != 0) {\r
ce6d12cc 2672 NewPos = gMenuOption.ForwardLink;\r
7936fb6a 2673 SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2674\r
d88ca2c9
ED
2675 while ((SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId ||\r
2676 SavedMenuOption->Sequence != Selection->Sequence) &&\r
2677 NewPos->ForwardLink != &gMenuOption) {\r
7936fb6a 2678 NewPos = NewPos->ForwardLink;\r
2679 SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2680 }\r
2681 if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {\r
2682 //\r
2683 // Target Question found, find its MenuOption\r
2684 //\r
2685 Link = TopOfScreen;\r
2686\r
2687 for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {\r
2688 SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
2689 Index += SavedMenuOption->Skip;\r
5f4ef94a
ED
2690 if (Link == TopOfScreen) {\r
2691 Index -= OldSkipValue;\r
2692 }\r
7936fb6a 2693 Link = Link->ForwardLink;\r
2694 }\r
5f4ef94a
ED
2695 if (NewPos == Link) {\r
2696 SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
2697 }\r
7936fb6a 2698\r
08476b33
ED
2699 //\r
2700 // Not find the selected menu in current show page.\r
2701 // Have two case to enter this if:\r
2702 // 1. Not find the menu at current page.\r
2703 // 2. Find the menu in current page, but the menu shows at the bottom and not all info shows.\r
2704 // For case 2, has an exception: The menu can show more than one pages and now only this menu shows.\r
2705 //\r
2706 // Base on the selected menu will show at the bottom of the page,\r
2707 // select the menu which will show at the top of the page.\r
2708 //\r
2709 if (Link != NewPos || Index > BottomRow || \r
2710 (Link == NewPos && (SavedMenuOption->Row + SavedMenuOption->Skip - 1 > BottomRow) && (Link != TopOfScreen))) {\r
85aa96cd
ED
2711 //\r
2712 // Find the MenuOption which has the skip value for Date/Time opcode. \r
2713 //\r
2714 AdjustDateAndTimePosition(FALSE, &NewPos);\r
7936fb6a 2715 //\r
2716 // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page\r
2717 //\r
5f4ef94a
ED
2718 SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2719 //\r
2720 // SavedMenuOption->Row == 0 means the menu not show yet.\r
2721 //\r
2722 if (SavedMenuOption->Row == 0) {\r
2723 UpdateOptionSkipLines (Selection, SavedMenuOption);\r
2724 }\r
08476b33
ED
2725\r
2726 //\r
2727 // Base on the selected menu will show at the bottome of next page, \r
2728 // select the menu show at the top of the next page. \r
2729 //\r
7936fb6a 2730 Link = NewPos;\r
5f4ef94a 2731 for (Index = TopRow + SavedMenuOption->Skip; Index <= BottomRow + 1; ) { \r
7936fb6a 2732 Link = Link->BackLink;\r
2733 SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
5f4ef94a
ED
2734 if (SavedMenuOption->Row == 0) {\r
2735 UpdateOptionSkipLines (Selection, SavedMenuOption);\r
2736 }\r
08476b33 2737 Index += SavedMenuOption->Skip;\r
7936fb6a 2738 }\r
08476b33
ED
2739\r
2740 //\r
2741 // Found the menu which will show at the top of the page.\r
2742 //\r
2743 if (Link == NewPos) {\r
2744 //\r
2745 // The menu can show more than one pages, just show the menu at the top of the page.\r
2746 //\r
2747 SkipValue = 0;\r
2748 TopOfScreen = Link;\r
2749 OldSkipValue = SkipValue;\r
5f4ef94a 2750 } else {\r
08476b33
ED
2751 //\r
2752 // Check whether need to skip some line for menu shows at the top of the page.\r
2753 //\r
2754 SkipValue = Index - BottomRow - 1;\r
2755 if (SkipValue > 0 && SkipValue < (INTN) SavedMenuOption->Skip) {\r
2756 TopOfScreen = Link;\r
2757 OldSkipValue = SkipValue;\r
2758 } else {\r
2759 SkipValue = 0;\r
2760 TopOfScreen = Link->ForwardLink;\r
2761 }\r
5f4ef94a 2762 }\r
7936fb6a 2763\r
2764 Repaint = TRUE;\r
2765 NewLine = TRUE;\r
2766 ControlFlag = CfRepaint;\r
2767 break;\r
2768 }\r
2769 } else {\r
2770 //\r
2771 // Target Question not found, highlight the default menu option\r
2772 //\r
2773 NewPos = TopOfScreen;\r
2774 }\r
2775\r
2776 Selection->QuestionId = 0;\r
2777 }\r
2778\r
2779 if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
2780 if (MenuOption != NULL) {\r
2781 //\r
2782 // Remove highlight on last Menu Option\r
2783 //\r
2784 gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
2785 ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
f0a1bf11 2786 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2787 if (OptionString != NULL) {\r
2788 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
2789 (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
2790 ) {\r
4a6876b7 2791 ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
7936fb6a 2792 }\r
2793\r
2794 Width = (UINT16) gOptionBlockWidth;\r
2795 OriginalRow = MenuOption->Row;\r
6c310dfb 2796 GlyphWidth = 1;\r
7936fb6a 2797\r
6c310dfb 2798 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2799 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2800 PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
2801 }\r
2802 //\r
2803 // If there is more string to process print on the next row and increment the Skip value\r
2804 //\r
d1a54e2c 2805 if (StrLen (&OptionString[Index]) != 0) {\r
7936fb6a 2806 MenuOption->Row++;\r
2807 }\r
2808\r
f4113e1f 2809 FreePool (OutputString);\r
7936fb6a 2810 }\r
2811\r
2812 MenuOption->Row = OriginalRow;\r
2813\r
f4113e1f 2814 FreePool (OptionString);\r
7936fb6a 2815 } else {\r
2816 if (NewLine) {\r
2817 if (MenuOption->GrayOut) {\r
2818 gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
2819 } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {\r
f0a1bf11 2820 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2821 }\r
2822\r
2823 OriginalRow = MenuOption->Row;\r
2824 Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);\r
6c310dfb 2825 GlyphWidth = 1;\r
7936fb6a 2826\r
6c310dfb 2827 for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2828 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2829 PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
2830 }\r
2831 //\r
2832 // If there is more string to process print on the next row and increment the Skip value\r
2833 //\r
d1a54e2c 2834 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
7936fb6a 2835 MenuOption->Row++;\r
2836 }\r
2837\r
f4113e1f 2838 FreePool (OutputString);\r
7936fb6a 2839 }\r
2840\r
2841 MenuOption->Row = OriginalRow;\r
f0a1bf11 2842 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2843 }\r
2844 }\r
2845 }\r
2846\r
2847 //\r
11232773 2848 // This is the current selected statement\r
7936fb6a 2849 //\r
2850 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
11232773
LG
2851 Statement = MenuOption->ThisTag;\r
2852 Selection->Statement = Statement;\r
7936fb6a 2853 if (!IsSelectable (MenuOption)) {\r
11232773
LG
2854 Repaint = SavedValue;\r
2855 UpdateKeyHelp (Selection, MenuOption, FALSE);\r
7936fb6a 2856 break;\r
2857 }\r
2858\r
d66e6c16 2859 //\r
2860 // Record highlight for current menu\r
2861 //\r
2862 CurrentMenu->QuestionId = Statement->QuestionId;\r
d88ca2c9 2863 CurrentMenu->Sequence = MenuOption->Sequence;\r
7936fb6a 2864\r
2865 //\r
2866 // Set reverse attribute\r
2867 //\r
f0a1bf11 2868 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));\r
7936fb6a 2869 gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
2870\r
2871 //\r
2872 // Assuming that we have a refresh linked-list created, lets annotate the\r
2873 // appropriate entry that we are highlighting with its new attribute. Just prior to this\r
2874 // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh\r
2875 //\r
2876 if (gMenuRefreshHead != NULL) {\r
2877 for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {\r
81da6ef9 2878 if (MenuRefreshEntry->MenuOption->GrayOut) {\r
1fcd34f8
ED
2879 MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
2880 } else { \r
2881 MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
2882 }\r
7936fb6a 2883 if (MenuRefreshEntry->MenuOption == MenuOption) {\r
f0a1bf11 2884 MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);\r
7936fb6a 2885 }\r
2886 }\r
2887 }\r
2888\r
2889 ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
2890 if (OptionString != NULL) {\r
2891 if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
4a6876b7 2892 ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
7936fb6a 2893 }\r
2894 Width = (UINT16) gOptionBlockWidth;\r
2895\r
2896 OriginalRow = MenuOption->Row;\r
6c310dfb 2897 GlyphWidth = 1;\r
7936fb6a 2898\r
6c310dfb 2899 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2900 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2901 PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
2902 }\r
2903 //\r
2904 // If there is more string to process print on the next row and increment the Skip value\r
2905 //\r
d1a54e2c 2906 if (StrLen (&OptionString[Index]) != 0) {\r
7936fb6a 2907 MenuOption->Row++;\r
2908 }\r
2909\r
f4113e1f 2910 FreePool (OutputString);\r
7936fb6a 2911 }\r
2912\r
2913 MenuOption->Row = OriginalRow;\r
2914\r
f4113e1f 2915 FreePool (OptionString);\r
7936fb6a 2916 } else {\r
2917 if (NewLine) {\r
2918 OriginalRow = MenuOption->Row;\r
2919\r
2920 Width = GetWidth (Statement, MenuOption->Handle);\r
6c310dfb 2921 GlyphWidth = 1;\r
7936fb6a 2922\r
6c310dfb 2923 for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2924 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2925 PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
2926 }\r
2927 //\r
2928 // If there is more string to process print on the next row and increment the Skip value\r
2929 //\r
d1a54e2c 2930 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
7936fb6a 2931 MenuOption->Row++;\r
2932 }\r
2933\r
f4113e1f 2934 FreePool (OutputString);\r
7936fb6a 2935 }\r
2936\r
2937 MenuOption->Row = OriginalRow;\r
2938\r
2939 }\r
2940 }\r
2941\r
8b0fc5c1 2942 UpdateKeyHelp (Selection, MenuOption, FALSE);\r
8d00a0f1 2943\r
7936fb6a 2944 //\r
2945 // Clear reverse attribute\r
2946 //\r
f0a1bf11 2947 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2948 }\r
2949 //\r
2950 // Repaint flag will be used when process CfUpdateHelpString, so restore its value\r
2951 // if we didn't break halfway when process CfRefreshHighLight.\r
2952 //\r
2953 Repaint = SavedValue;\r
2954 break;\r
2955\r
2956 case CfUpdateHelpString:\r
2957 ControlFlag = CfPrepareToReadKey;\r
b00964a9
ED
2958 if (Selection->Form->ModalForm) {\r
2959 break;\r
2960 }\r
7936fb6a 2961\r
11232773 2962 if (Repaint || NewLine) {\r
7936fb6a 2963 //\r
2964 // Don't print anything if it is a NULL help token\r
2965 //\r
c9325700 2966 ASSERT(MenuOption != NULL);\r
11232773 2967 if (MenuOption->ThisTag->Help == 0 || !IsSelectable (MenuOption)) {\r
7936fb6a 2968 StringPtr = L"\0";\r
2969 } else {\r
2970 StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
2971 }\r
2972\r
ba46ab94
ED
2973 RowCount = BottomRow - TopRow;\r
2974 HelpPageIndex = 0;\r
2975 //\r
2976 // 1.Calculate how many line the help string need to print.\r
2977 //\r
6c310dfb
ED
2978 if (HelpString != NULL) {\r
2979 FreePool (HelpString);\r
2980 }\r
2981 HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
ba46ab94
ED
2982 if (HelpLine > RowCount) {\r
2983 MultiHelpPage = TRUE;\r
2984 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
6c310dfb
ED
2985 if (HelpHeaderString != NULL) {\r
2986 FreePool (HelpHeaderString);\r
2987 }\r
2988 HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount);\r
ba46ab94 2989 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
6c310dfb
ED
2990 if (HelpBottomString != NULL) {\r
2991 FreePool (HelpBottomString);\r
2992 }\r
2993 HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);\r
7936fb6a 2994 //\r
ba46ab94 2995 // Calculate the help page count.\r
7936fb6a 2996 //\r
ba46ab94
ED
2997 if (HelpLine > 2 * RowCount - 2) {\r
2998 HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
2999 if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {\r
3000 HelpPageCount += 1;\r
3001 }\r
3002 } else {\r
3003 HelpPageCount = 2;\r
7936fb6a 3004 }\r
ba46ab94
ED
3005 } else {\r
3006 MultiHelpPage = FALSE;\r
3007 }\r
3008 }\r
3009\r
3010 //\r
3011 // Clean the help field first.\r
3012 //\r
3013 ClearLines (\r
3014 LocalScreen.RightColumn - gHelpBlockWidth,\r
3015 LocalScreen.RightColumn,\r
3016 TopRow,\r
3017 BottomRow,\r
3018 PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
3019 );\r
7936fb6a 3020\r
ba46ab94
ED
3021 //\r
3022 // Check whether need to show the 'More(U/u)' at the begin.\r
3023 // Base on current direct info, here shows aligned to the right side of the column.\r
3024 // If the direction is multi line and aligned to right side may have problem, so \r
3025 // add ASSERT code here.\r
3026 //\r
3027 if (HelpPageIndex > 0) {\r
6c310dfb 3028 gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
ba46ab94
ED
3029 for (Index = 0; Index < HelpHeaderLine; Index++) {\r
3030 ASSERT (HelpHeaderLine == 1);\r
3031 ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
3032 PrintStringAt (\r
3033 LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
3034 Index + TopRow,\r
6c310dfb 3035 &HelpHeaderString[Index * HeaderLineWidth]\r
ba46ab94
ED
3036 );\r
3037 }\r
3038 }\r
3039\r
3040 gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);\r
3041 //\r
3042 // Print the help string info.\r
3043 //\r
3044 if (!MultiHelpPage) {\r
5ea466a5 3045 for (Index = 0; Index < HelpLine; Index++) {\r
7936fb6a 3046 PrintStringAt (\r
3047 LocalScreen.RightColumn - gHelpBlockWidth,\r
3048 Index + TopRow,\r
6c310dfb 3049 &HelpString[Index * EachLineWidth]\r
ba46ab94
ED
3050 );\r
3051 }\r
6c310dfb 3052 gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
ba46ab94
ED
3053 } else {\r
3054 if (HelpPageIndex == 0) {\r
3055 for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
3056 PrintStringAt (\r
3057 LocalScreen.RightColumn - gHelpBlockWidth,\r
3058 Index + TopRow,\r
6c310dfb 3059 &HelpString[Index * EachLineWidth]\r
ba46ab94
ED
3060 );\r
3061 }\r
3062 } else {\r
3063 for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && \r
3064 (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
3065 PrintStringAt (\r
3066 LocalScreen.RightColumn - gHelpBlockWidth,\r
3067 Index + TopRow + HelpHeaderLine,\r
6c310dfb 3068 &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth]\r
ba46ab94
ED
3069 );\r
3070 }\r
6c310dfb
ED
3071 if (HelpPageIndex == HelpPageCount - 1) {\r
3072 gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
3073 }\r
ba46ab94
ED
3074 } \r
3075 }\r
3076\r
ba46ab94
ED
3077 //\r
3078 // Check whether need to print the 'More(D/d)' at the bottom.\r
3079 // Base on current direct info, here shows aligned to the right side of the column.\r
3080 // If the direction is multi line and aligned to right side may have problem, so \r
3081 // add ASSERT code here.\r
3082 //\r
3083 if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
6c310dfb 3084 gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
ba46ab94
ED
3085 for (Index = 0; Index < HelpBottomLine; Index++) {\r
3086 ASSERT (HelpBottomLine == 1);\r
3087 ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
3088 PrintStringAt (\r
3089 LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
3090 Index + BottomRow - HelpBottomLine,\r
6c310dfb 3091 &HelpBottomString[Index * BottomLineWidth]\r
7936fb6a 3092 );\r
3093 }\r
3094 }\r
3095 //\r
3096 // Reset this flag every time we finish using it.\r
3097 //\r
3098 Repaint = FALSE;\r
3099 NewLine = FALSE;\r
3100 break;\r
3101\r
3102 case CfPrepareToReadKey:\r
3103 ControlFlag = CfReadKey;\r
3104 ScreenOperation = UiNoOperation;\r
3105 break;\r
3106\r
3107 case CfReadKey:\r
3108 ControlFlag = CfScreenOperation;\r
3109\r
3110 //\r
3111 // Wait for user's selection\r
3112 //\r
9cdadb7c
RN
3113 while (TRUE) {\r
3114 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3115 if (!EFI_ERROR (Status)) {\r
3116 break;\r
3117 }\r
7936fb6a 3118\r
7936fb6a 3119 //\r
9cdadb7c 3120 // If we encounter error, continue to read another key in.\r
7936fb6a 3121 //\r
9cdadb7c
RN
3122 if (Status != EFI_NOT_READY) {\r
3123 continue;\r
3124 }\r
3125\r
3126 Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);\r
3127 ASSERT_EFI_ERROR (Status);\r
3128\r
3129 if (Selection->Action == UI_ACTION_REFRESH_FORMSET) {\r
3130 //\r
3131 // IFR is updated in Callback of refresh opcode, re-parse it\r
3132 //\r
3133 ControlFlag = CfCheckSelection;\r
3134 Selection->Statement = NULL;\r
3135 break;\r
3136 }\r
8d00a0f1 3137 }\r
3138\r
9cdadb7c 3139 if (ControlFlag == CfCheckSelection) {\r
8d00a0f1 3140 break;\r
7936fb6a 3141 }\r
3142\r
7936fb6a 3143 switch (Key.UnicodeChar) {\r
3144 case CHAR_CARRIAGE_RETURN:\r
febca2e3
ED
3145 if(MenuOption->GrayOut || MenuOption->ReadOnly) {\r
3146 ControlFlag = CfReadKey;\r
3147 break;\r
3148 }\r
3149\r
7936fb6a 3150 ScreenOperation = UiSelect;\r
3151 gDirection = 0;\r
3152 break;\r
3153\r
3154 //\r
3155 // We will push the adjustment of these numeric values directly to the input handler\r
3156 // NOTE: we won't handle manual input numeric\r
3157 //\r
3158 case '+':\r
3159 case '-':\r
c9325700
ED
3160 //\r
3161 // If the screen has no menu items, and the user didn't select UiReset\r
3162 // ignore the selection and go back to reading keys.\r
3163 //\r
febca2e3 3164 if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
c9325700
ED
3165 ControlFlag = CfReadKey;\r
3166 break;\r
3167 }\r
3168\r
3169 ASSERT(MenuOption != NULL);\r
7936fb6a 3170 Statement = MenuOption->ThisTag;\r
3171 if ((Statement->Operand == EFI_IFR_DATE_OP)\r
3172 || (Statement->Operand == EFI_IFR_TIME_OP)\r
3173 || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))\r
3174 ){\r
3175 if (Key.UnicodeChar == '+') {\r
3176 gDirection = SCAN_RIGHT;\r
3177 } else {\r
3178 gDirection = SCAN_LEFT;\r
3179 }\r
3180 Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
8d00a0f1 3181 if (EFI_ERROR (Status)) {\r
3182 //\r
3183 // Repaint to clear possible error prompt pop-up\r
3184 //\r
3185 Repaint = TRUE;\r
3186 NewLine = TRUE;\r
7b546f74
ED
3187 } else {\r
3188 Selection->Action = UI_ACTION_REFRESH_FORM;\r
8d00a0f1 3189 }\r
676df92c 3190 if (OptionString != NULL) {\r
3191 FreePool (OptionString);\r
3192 }\r
7936fb6a 3193 }\r
3194 break;\r
3195\r
3196 case '^':\r
3197 ScreenOperation = UiUp;\r
3198 break;\r
3199\r
3200 case 'V':\r
3201 case 'v':\r
3202 ScreenOperation = UiDown;\r
3203 break;\r
3204\r
3205 case ' ':\r
40245175 3206 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
c9325700
ED
3207 //\r
3208 // If the screen has no menu items, and the user didn't select UiReset\r
3209 // ignore the selection and go back to reading keys.\r
3210 //\r
3211 if(IsListEmpty (&gMenuOption)) {\r
3212 ControlFlag = CfReadKey;\r
3213 break;\r
3214 }\r
3215 \r
3216 ASSERT(MenuOption != NULL);\r
febca2e3 3217 if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {\r
7936fb6a 3218 ScreenOperation = UiSelect;\r
3219 }\r
3220 }\r
3221 break;\r
3222\r
ba46ab94
ED
3223 case 'D':\r
3224 case 'd':\r
3225 if (!MultiHelpPage) {\r
3226 ControlFlag = CfReadKey;\r
3227 break;\r
3228 }\r
3229 ControlFlag = CfUpdateHelpString;\r
3230 HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;\r
3231 break;\r
3232\r
3233 case 'U':\r
3234 case 'u':\r
3235 if (!MultiHelpPage) {\r
3236 ControlFlag = CfReadKey;\r
3237 break;\r
3238 }\r
3239 ControlFlag = CfUpdateHelpString;\r
3240 HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;\r
3241 break;\r
3242\r
7936fb6a 3243 case CHAR_NULL:\r
48a9d5f7
LG
3244 for (Index = 0; Index < mScanCodeNumber; Index++) {\r
3245 if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
3246 ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
3247 break;\r
3248 }\r
3249 }\r
3250 \r
3251 if (Selection->Form->ModalForm && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {\r
7936fb6a 3252 //\r
48a9d5f7 3253 // ModalForm has no ESC key and Hot Key.\r
7936fb6a 3254 //\r
48a9d5f7
LG
3255 ControlFlag = CfReadKey;\r
3256 } else if (Index == mScanCodeNumber) {\r
3257 //\r
3258 // Check whether Key matches the registered hot key.\r
3259 //\r
3260 HotKey = NULL;\r
3261 if ((gBrowserSettingScope == SystemLevel) || (gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
3262 HotKey = GetHotKeyFromRegisterList (&Key);\r
3263 }\r
3264 if (HotKey != NULL) {\r
3265 ScreenOperation = UiHotKey;\r
7936fb6a 3266 }\r
3267 }\r
3268 break;\r
3269 }\r
3270 break;\r
3271\r
3272 case CfScreenOperation:\r
d66e6c16 3273 if (ScreenOperation != UiReset) {\r
7936fb6a 3274 //\r
d66e6c16 3275 // If the screen has no menu items, and the user didn't select UiReset\r
7936fb6a 3276 // ignore the selection and go back to reading keys.\r
3277 //\r
ce6d12cc 3278 if (IsListEmpty (&gMenuOption)) {\r
7936fb6a 3279 ControlFlag = CfReadKey;\r
3280 break;\r
3281 }\r
7936fb6a 3282 }\r
3283\r
3284 for (Index = 0;\r
3285 Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);\r
3286 Index++\r
3287 ) {\r
3288 if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
3289 ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
3290 break;\r
3291 }\r
3292 }\r
3293 break;\r
3294\r
7936fb6a 3295 case CfUiSelect:\r
3296 ControlFlag = CfCheckSelection;\r
3297\r
c9325700 3298 ASSERT(MenuOption != NULL);\r
7936fb6a 3299 Statement = MenuOption->ThisTag;\r
e24adb18 3300 if (Statement->Operand == EFI_IFR_TEXT_OP) {\r
7936fb6a 3301 break;\r
3302 }\r
3303\r
3304 //\r
3305 // Keep highlight on current MenuOption\r
3306 //\r
3307 Selection->QuestionId = Statement->QuestionId;\r
3308\r
3309 switch (Statement->Operand) {\r
3310 case EFI_IFR_REF_OP:\r
8ca6180f 3311 ProcessGotoOpCode(Statement, Selection, &Repaint, &NewLine);\r
7936fb6a 3312 break;\r
3313\r
3314 case EFI_IFR_ACTION_OP:\r
3315 //\r
3316 // Process the Config string <ConfigResp>\r
3317 //\r
3318 Status = ProcessQuestionConfig (Selection, Statement);\r
3319\r
3320 if (EFI_ERROR (Status)) {\r
3321 break;\r
3322 }\r
3323\r
3324 //\r
3325 // The action button may change some Question value, so refresh the form\r
3326 //\r
3327 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3328 break;\r
3329\r
3330 case EFI_IFR_RESET_BUTTON_OP:\r
3331 //\r
3332 // Reset Question to default value specified by DefaultId\r
3333 //\r
3334 ControlFlag = CfUiDefault;\r
3335 DefaultId = Statement->DefaultId;\r
3336 break;\r
3337\r
3338 default:\r
3339 //\r
3340 // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
3341 //\r
8b0fc5c1 3342 UpdateKeyHelp (Selection, MenuOption, TRUE);\r
7936fb6a 3343 Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
3344\r
3345 if (EFI_ERROR (Status)) {\r
3346 Repaint = TRUE;\r
3347 NewLine = TRUE;\r
8b0fc5c1 3348 UpdateKeyHelp (Selection, MenuOption, FALSE);\r
3349 } else {\r
3350 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3351 }\r
7936fb6a 3352\r
0c66bc76
LG
3353 if (OptionString != NULL) {\r
3354 FreePool (OptionString);\r
3355 }\r
7936fb6a 3356 break;\r
3357 }\r
3358 break;\r
3359\r
3360 case CfUiReset:\r
3361 //\r
d66e6c16 3362 // We come here when someone press ESC\r
7936fb6a 3363 //\r
3364 ControlFlag = CfCheckSelection;\r
48a9d5f7 3365 FindNextMenu (Selection, &Repaint, &NewLine);\r
b18e7050 3366 break;\r
7936fb6a 3367\r
3368 case CfUiLeft:\r
3369 ControlFlag = CfCheckSelection;\r
c9325700 3370 ASSERT(MenuOption != NULL);\r
7936fb6a 3371 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
3372 if (MenuOption->Sequence != 0) {\r
3373 //\r
3374 // In the middle or tail of the Date/Time op-code set, go left.\r
3375 //\r
c9325700 3376 ASSERT(NewPos != NULL);\r
7936fb6a 3377 NewPos = NewPos->BackLink;\r
3378 }\r
3379 }\r
3380 break;\r
3381\r
3382 case CfUiRight:\r
3383 ControlFlag = CfCheckSelection;\r
c9325700 3384 ASSERT(MenuOption != NULL);\r
7936fb6a 3385 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
3386 if (MenuOption->Sequence != 2) {\r
3387 //\r
3388 // In the middle or tail of the Date/Time op-code set, go left.\r
3389 //\r
c9325700 3390 ASSERT(NewPos != NULL);\r
7936fb6a 3391 NewPos = NewPos->ForwardLink;\r
3392 }\r
3393 }\r
3394 break;\r
3395\r
3396 case CfUiUp:\r
3397 ControlFlag = CfCheckSelection;\r
3398\r
11232773 3399 SavedListEntry = NewPos;\r
7936fb6a 3400\r
c9325700 3401 ASSERT(NewPos != NULL);\r
11232773
LG
3402 //\r
3403 // Adjust Date/Time position before we advance forward.\r
3404 //\r
3405 AdjustDateAndTimePosition (TRUE, &NewPos);\r
ce6d12cc 3406 if (NewPos->BackLink != &gMenuOption) {\r
11232773 3407 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
715cf6dd 3408 ASSERT (MenuOption != NULL);\r
11232773
LG
3409 NewLine = TRUE;\r
3410 NewPos = NewPos->BackLink;\r
7936fb6a 3411\r
3412 PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
5f4ef94a
ED
3413 if (PreviousMenuOption->Row == 0) {\r
3414 UpdateOptionSkipLines (Selection, PreviousMenuOption);\r
3415 }\r
7936fb6a 3416 DistanceValue = PreviousMenuOption->Skip;\r
11232773
LG
3417 Difference = 0;\r
3418 if (MenuOption->Row >= DistanceValue + TopRow) {\r
5f4ef94a 3419 Difference = MoveToNextStatement (Selection, TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);\r
11232773
LG
3420 }\r
3421 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3422 \r
7936fb6a 3423 if (Difference < 0) {\r
3424 //\r
11232773
LG
3425 // We hit the begining MenuOption that can be focused\r
3426 // so we simply scroll to the top.\r
7936fb6a 3427 //\r
11232773 3428 if (TopOfScreen != gMenuOption.ForwardLink) {\r
ce6d12cc 3429 TopOfScreen = gMenuOption.ForwardLink;\r
7936fb6a 3430 Repaint = TRUE;\r
11232773
LG
3431 } else {\r
3432 //\r
3433 // Scroll up to the last page when we have arrived at top page.\r
3434 //\r
3435 NewPos = &gMenuOption;\r
3436 TopOfScreen = &gMenuOption;\r
3437 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3438 ScreenOperation = UiPageUp;\r
3439 ControlFlag = CfScreenOperation;\r
3440 break;\r
7936fb6a 3441 }\r
11232773 3442 } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {\r
1a788cdd
LG
3443 //\r
3444 // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
3445 //\r
3446 TopOfScreen = NewPos;\r
3447 Repaint = TRUE;\r
3448 SkipValue = 0;\r
3449 OldSkipValue = 0;\r
11232773
LG
3450 } else if (!IsSelectable (NextMenuOption)) {\r
3451 //\r
3452 // Continue to go up until scroll to next page or the selectable option is found.\r
3453 //\r
3454 ScreenOperation = UiUp;\r
3455 ControlFlag = CfScreenOperation;\r
7936fb6a 3456 }\r
3457\r
3458 //\r
3459 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3460 //\r
3461 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
11232773
LG
3462 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3463 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
b18e7050 3464 UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
7936fb6a 3465 } else {\r
11232773
LG
3466 //\r
3467 // Scroll up to the last page.\r
3468 //\r
3469 NewPos = &gMenuOption;\r
3470 TopOfScreen = &gMenuOption;\r
3471 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3472 ScreenOperation = UiPageUp;\r
3473 ControlFlag = CfScreenOperation;\r
7936fb6a 3474 }\r
3475 break;\r
3476\r
3477 case CfUiPageUp:\r
3478 ControlFlag = CfCheckSelection;\r
3479\r
c9325700 3480 ASSERT(NewPos != NULL);\r
ce6d12cc 3481 if (NewPos->BackLink == &gMenuOption) {\r
7936fb6a 3482 NewLine = FALSE;\r
3483 Repaint = FALSE;\r
3484 break;\r
3485 }\r
3486\r
3487 NewLine = TRUE;\r
3488 Repaint = TRUE;\r
3489 Link = TopOfScreen;\r
11232773 3490 Index = BottomRow;\r
ce6d12cc 3491 while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) {\r
7936fb6a 3492 Link = Link->BackLink;\r
3493 PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
5f4ef94a
ED
3494 if (PreviousMenuOption->Row == 0) {\r
3495 UpdateOptionSkipLines (Selection, PreviousMenuOption);\r
3496 } \r
11232773
LG
3497 if (Index < PreviousMenuOption->Skip) {\r
3498 Index = 0;\r
3499 break;\r
3500 }\r
3501 Index = Index - PreviousMenuOption->Skip;\r
7936fb6a 3502 }\r
11232773
LG
3503 \r
3504 if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
3505 if (TopOfScreen == &gMenuOption) {\r
3506 TopOfScreen = gMenuOption.ForwardLink;\r
3507 NewPos = gMenuOption.BackLink;\r
5f4ef94a 3508 MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3509 Repaint = FALSE;\r
3510 } else if (TopOfScreen != Link) {\r
3511 TopOfScreen = Link;\r
3512 NewPos = Link;\r
5f4ef94a 3513 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3514 } else {\r
3515 //\r
3516 // Finally we know that NewPos is the last MenuOption can be focused.\r
3517 //\r
3518 Repaint = FALSE;\r
3519 NewPos = Link;\r
5f4ef94a 3520 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3521 }\r
3522 } else {\r
3523 if (Index + 1 < TopRow) {\r
3524 //\r
3525 // Back up the previous option.\r
3526 //\r
3527 Link = Link->ForwardLink;\r
3528 }\r
7936fb6a 3529\r
7936fb6a 3530 //\r
11232773 3531 // Move to the option in Next page.\r
7936fb6a 3532 //\r
11232773
LG
3533 if (TopOfScreen == &gMenuOption) {\r
3534 NewPos = gMenuOption.BackLink;\r
5f4ef94a 3535 MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3536 } else {\r
3537 NewPos = Link;\r
5f4ef94a 3538 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3539 }\r
3540\r
7936fb6a 3541 //\r
11232773 3542 // There are more MenuOption needing scrolling up.\r
7936fb6a 3543 //\r
11232773
LG
3544 TopOfScreen = Link;\r
3545 MenuOption = NULL;\r
7936fb6a 3546 }\r
3547\r
3548 //\r
3549 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3550 // Don't do this when we are already in the first page.\r
3551 //\r
3552 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3553 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3554 break;\r
3555\r
3556 case CfUiPageDown:\r
3557 ControlFlag = CfCheckSelection;\r
3558\r
cd7bfc2c 3559 ASSERT (NewPos != NULL);\r
ce6d12cc 3560 if (NewPos->ForwardLink == &gMenuOption) {\r
7936fb6a 3561 NewLine = FALSE;\r
3562 Repaint = FALSE;\r
3563 break;\r
3564 }\r
3565\r
3566 NewLine = TRUE;\r
3567 Repaint = TRUE;\r
3568 Link = TopOfScreen;\r
3569 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3570 Index = TopRow;\r
ce6d12cc 3571 while ((Index <= BottomRow) && (Link->ForwardLink != &gMenuOption)) {\r
7936fb6a 3572 Index = Index + NextMenuOption->Skip;\r
3573 Link = Link->ForwardLink;\r
3574 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3575 }\r
3576\r
11232773
LG
3577 if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow)) {\r
3578 //\r
3579 // Finally we know that NewPos is the last MenuOption can be focused.\r
3580 //\r
3581 Repaint = FALSE;\r
5f4ef94a 3582 MoveToNextStatement (Selection, TRUE, &Link, Index - TopRow);\r
11232773
LG
3583 } else {\r
3584 if (Index - 1 > BottomRow) {\r
3585 //\r
3586 // Back up the previous option.\r
3587 //\r
3588 Link = Link->BackLink;\r
3589 }\r
7936fb6a 3590 //\r
11232773 3591 // There are more MenuOption needing scrolling down.\r
7936fb6a 3592 //\r
3593 TopOfScreen = Link;\r
3594 MenuOption = NULL;\r
7936fb6a 3595 //\r
11232773 3596 // Move to the option in Next page.\r
7936fb6a 3597 //\r
5f4ef94a 3598 MoveToNextStatement (Selection, FALSE, &Link, BottomRow - TopRow);\r
7936fb6a 3599 }\r
3600\r
3601 //\r
3602 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3603 // Don't do this when we are already in the last page.\r
3604 //\r
11232773 3605 NewPos = Link;\r
7936fb6a 3606 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3607 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3608 break;\r
3609\r
3610 case CfUiDown:\r
3611 ControlFlag = CfCheckSelection;\r
3612 //\r
3613 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
3614 // to be one that progresses to the next set of op-codes, we need to advance to the last\r
3615 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
3616 // checking can be done. The only other logic we need to introduce is that if a Date/Time\r
3617 // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
3618 // the Date/Time op-code.\r
3619 //\r
3620 SavedListEntry = NewPos;\r
11232773 3621 AdjustDateAndTimePosition (FALSE, &NewPos);\r
7936fb6a 3622\r
ce6d12cc 3623 if (NewPos->ForwardLink != &gMenuOption) {\r
7936fb6a 3624 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3625 NewLine = TRUE;\r
3626 NewPos = NewPos->ForwardLink;\r
7936fb6a 3627\r
11232773
LG
3628 Difference = 0;\r
3629 if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
5f4ef94a 3630 Difference = MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
11232773
LG
3631 //\r
3632 // We hit the end of MenuOption that can be focused\r
3633 // so we simply scroll to the first page.\r
3634 //\r
3635 if (Difference < 0) {\r
3636 //\r
3637 // Scroll to the first page.\r
3638 //\r
3639 if (TopOfScreen != gMenuOption.ForwardLink) {\r
3640 TopOfScreen = gMenuOption.ForwardLink;\r
3641 Repaint = TRUE;\r
3642 MenuOption = NULL;\r
3643 } else {\r
3644 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3645 }\r
3646 NewPos = gMenuOption.ForwardLink;\r
5f4ef94a 3647 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3648 \r
3649 //\r
3650 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3651 //\r
3652 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3653 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3654 break;\r
3655 }\r
3656 }\r
1a788cdd
LG
3657 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3658\r
7936fb6a 3659 //\r
3660 // An option might be multi-line, so we need to reflect that data in the overall skip value\r
3661 //\r
5f4ef94a 3662 UpdateOptionSkipLines (Selection, NextMenuOption);\r
11232773 3663 DistanceValue = Difference + NextMenuOption->Skip;\r
7936fb6a 3664\r
3665 Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
3666 if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
3667 (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||\r
3668 NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
3669 ) {\r
3670 Temp ++;\r
3671 }\r
3672\r
3673 //\r
3674 // If we are going to scroll, update TopOfScreen\r
3675 //\r
3676 if (Temp > BottomRow) {\r
3677 do {\r
3678 //\r
3679 // Is the current top of screen a zero-advance op-code?\r
3680 // If so, keep moving forward till we hit a >0 advance op-code\r
3681 //\r
3682 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
3683\r
3684 //\r
3685 // If bottom op-code is more than one line or top op-code is more than one line\r
3686 //\r
3687 if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {\r
3688 //\r
3689 // Is the bottom op-code greater than or equal in size to the top op-code?\r
3690 //\r
3691 if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {\r
3692 //\r
3693 // Skip the top op-code\r
3694 //\r
3695 TopOfScreen = TopOfScreen->ForwardLink;\r
3696 Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);\r
3697\r
3698 OldSkipValue = Difference;\r
3699\r
3700 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
3701\r
3702 //\r
3703 // If we have a remainder, skip that many more op-codes until we drain the remainder\r
3704 //\r
1a788cdd 3705 while (Difference >= (INTN) SavedMenuOption->Skip) {\r
7936fb6a 3706 //\r
3707 // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
3708 //\r
1a788cdd 3709 Difference = Difference - (INTN) SavedMenuOption->Skip;\r
7936fb6a 3710 TopOfScreen = TopOfScreen->ForwardLink;\r
3711 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
7936fb6a 3712 }\r
3713 //\r
3714 // Since we will act on this op-code in the next routine, and increment the\r
3715 // SkipValue, set the skips to one less than what is required.\r
3716 //\r
3717 SkipValue = Difference - 1;\r
3718\r
3719 } else {\r
3720 //\r
3721 // Since we will act on this op-code in the next routine, and increment the\r
3722 // SkipValue, set the skips to one less than what is required.\r
3723 //\r
3724 SkipValue = OldSkipValue + (Temp - BottomRow) - 1;\r
3725 }\r
3726 } else {\r
3727 if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
3728 TopOfScreen = TopOfScreen->ForwardLink;\r
3729 break;\r
3730 } else {\r
3731 SkipValue = OldSkipValue;\r
3732 }\r
3733 }\r
3734 //\r
3735 // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
3736 // Let's set a skip flag to smoothly scroll the top of the screen.\r
3737 //\r
3738 if (SavedMenuOption->Skip > 1) {\r
3739 if (SavedMenuOption == NextMenuOption) {\r
3740 SkipValue = 0;\r
3741 } else {\r
3742 SkipValue++;\r
3743 }\r
1a788cdd
LG
3744 } else if (SavedMenuOption->Skip == 1) {\r
3745 SkipValue = 0;\r
7936fb6a 3746 } else {\r
3747 SkipValue = 0;\r
3748 TopOfScreen = TopOfScreen->ForwardLink;\r
3749 }\r
3750 } while (SavedMenuOption->Skip == 0);\r
3751\r
3752 Repaint = TRUE;\r
3753 OldSkipValue = SkipValue;\r
11232773
LG
3754 } else if (!IsSelectable (NextMenuOption)) {\r
3755 //\r
3756 // Continue to go down until scroll to next page or the selectable option is found.\r
3757 //\r
3758 ScreenOperation = UiDown;\r
3759 ControlFlag = CfScreenOperation;\r
7936fb6a 3760 }\r
3761\r
3762 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3763\r
b18e7050 3764 UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
7936fb6a 3765\r
3766 } else {\r
7936fb6a 3767 //\r
11232773 3768 // Scroll to the first page.\r
7936fb6a 3769 //\r
11232773
LG
3770 if (TopOfScreen != gMenuOption.ForwardLink) {\r
3771 TopOfScreen = gMenuOption.ForwardLink;\r
3772 Repaint = TRUE;\r
3773 MenuOption = NULL;\r
3774 } else {\r
3775 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3776 }\r
3777 NewLine = TRUE;\r
3778 NewPos = gMenuOption.ForwardLink;\r
5f4ef94a 3779 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
7936fb6a 3780 }\r
11232773
LG
3781\r
3782 //\r
3783 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3784 //\r
3785 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3786 AdjustDateAndTimePosition (TRUE, &NewPos);\r
7936fb6a 3787 break;\r
3788\r
48a9d5f7 3789 case CfUiHotKey:\r
7936fb6a 3790 ControlFlag = CfCheckSelection;\r
48a9d5f7
LG
3791 \r
3792 Status = EFI_SUCCESS;\r
7936fb6a 3793 //\r
48a9d5f7 3794 // Discard changes. After it, no NV flag is showed.\r
7936fb6a 3795 //\r
48a9d5f7
LG
3796 if ((HotKey->Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
3797 Status = DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
3798 if (!EFI_ERROR (Status)) {\r
3799 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3800 Selection->Statement = NULL;\r
3801 gResetRequired = FALSE;\r
3802 } else {\r
3803 do {\r
3804 CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDiscardFailed, gPressEnter, gEmptyString);\r
3805 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3806 //\r
3807 // Still show current page.\r
3808 //\r
3809 Selection->Action = UI_ACTION_NONE;\r
3810 Repaint = TRUE;\r
3811 NewLine = TRUE;\r
3812 break;\r
3813 }\r
3814 }\r
7936fb6a 3815\r
48a9d5f7
LG
3816 //\r
3817 // Reterieve default setting. After it. NV flag will be showed.\r
3818 //\r
3819 if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
9776099f 3820 Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
48a9d5f7
LG
3821 if (!EFI_ERROR (Status)) {\r
3822 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3823 Selection->Statement = NULL;\r
3824 gResetRequired = TRUE;\r
3825 } else {\r
3826 do {\r
3827 CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDefaultFailed, gPressEnter, gEmptyString);\r
3828 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3829 //\r
3830 // Still show current page.\r
3831 //\r
3832 Selection->Action = UI_ACTION_NONE;\r
3833 Repaint = TRUE;\r
3834 NewLine = TRUE;\r
3835 break;\r
3836 }\r
3837 }\r
7936fb6a 3838\r
48a9d5f7
LG
3839 //\r
3840 // Save changes. After it, no NV flag is showed.\r
3841 //\r
3842 if ((HotKey->Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
3843 Status = SubmitForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
3844 if (!EFI_ERROR (Status)) {\r
3845 ASSERT(MenuOption != NULL);\r
3846 UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
3847 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
3848 } else {\r
3849 do {\r
3850 CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gSaveFailed, gPressEnter, gEmptyString);\r
3851 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3852 //\r
3853 // Still show current page.\r
3854 //\r
3855 Selection->Action = UI_ACTION_NONE;\r
3856 Repaint = TRUE;\r
3857 NewLine = TRUE;\r
3858 break;\r
3859 }\r
3860 }\r
3861 \r
3862 //\r
3863 // Set Reset required Flag\r
3864 //\r
3865 if ((HotKey->Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
3866 gResetRequired = TRUE;\r
3867 }\r
3868 \r
3869 //\r
3870 // Exit Action\r
3871 //\r
3872 if ((HotKey->Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
3873 //\r
3874 // Form Exit without saving, Similar to ESC Key.\r
3875 // FormSet Exit without saving, Exit SendForm.\r
3876 // System Exit without saving, CallExitHandler and Exit SendForm.\r
3877 //\r
3878 DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
3879 if (gBrowserSettingScope == FormLevel) {\r
3880 ControlFlag = CfUiReset;\r
3881 } else if (gBrowserSettingScope == FormSetLevel) {\r
3882 Selection->Action = UI_ACTION_EXIT;\r
3883 } else if (gBrowserSettingScope == SystemLevel) {\r
3884 if (ExitHandlerFunction != NULL) {\r
3885 ExitHandlerFunction ();\r
3886 }\r
3887 Selection->Action = UI_ACTION_EXIT;\r
3888 }\r
3889 Selection->Statement = NULL;\r
7936fb6a 3890 }\r
3891 break;\r
3892\r
3893 case CfUiDefault:\r
3894 ControlFlag = CfCheckSelection;\r
4f33c838 3895 //\r
48a9d5f7 3896 // Reset to default value for all forms in the whole system.\r
4f33c838 3897 //\r
9776099f 3898 Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);\r
7936fb6a 3899\r
3900 if (!EFI_ERROR (Status)) {\r
3901 Selection->Action = UI_ACTION_REFRESH_FORM;\r
ebe43565 3902 Selection->Statement = NULL;\r
15713670 3903 gResetRequired = TRUE;\r
7936fb6a 3904 }\r
3905 break;\r
3906\r
3907 case CfUiNoOperation:\r
3908 ControlFlag = CfCheckSelection;\r
3909 break;\r
3910\r
3911 case CfExit:\r
3912 UiFreeRefreshList ();\r
3913\r
3914 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
3915 gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);\r
3916 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
3917 gST->ConOut->OutputString (gST->ConOut, L"\n");\r
6c310dfb
ED
3918 if (HelpString != NULL) {\r
3919 FreePool (HelpString);\r
3920 }\r
3921 if (HelpHeaderString != NULL) {\r
3922 FreePool (HelpHeaderString);\r
3923 }\r
3924 if (HelpBottomString != NULL) {\r
3925 FreePool (HelpBottomString);\r
3926 }\r
7936fb6a 3927\r
3928 return EFI_SUCCESS;\r
3929\r
3930 default:\r
3931 break;\r
3932 }\r
3933 }\r
3934}\r