]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
Add missing break and add comment to non-necessary break.
[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
960\r
961 default:\r
962 //\r
963 // If it is the beginning of the string, don't worry about checking maximum limits\r
964 //\r
965 if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
966 StrnCpy (StringBuffer, &Key.UnicodeChar, 1);\r
967 StrnCpy (TempString, &Key.UnicodeChar, 1);\r
968 } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
969 KeyPad[0] = Key.UnicodeChar;\r
970 KeyPad[1] = CHAR_NULL;\r
971 StrCat (StringBuffer, KeyPad);\r
972 StrCat (TempString, KeyPad);\r
973 }\r
974 //\r
975 // If the width of the input string is now larger than the screen, we nee to\r
976 // adjust the index to start printing portions of the string\r
977 //\r
978 SetUnicodeMem (BufferedString, LargestString, L' ');\r
979\r
980 PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
981\r
982 if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {\r
983 Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;\r
984 } else {\r
985 Index = 0;\r
986 }\r
987\r
988 for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {\r
989 BufferedString[Count] = StringBuffer[Index];\r
990 }\r
991\r
992 PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
993 break;\r
994 }\r
995 } while (!SelectionComplete);\r
996 }\r
997\r
998 gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
999 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1000 return EFI_SUCCESS;\r
1001}\r
1002\r
1003/**\r
1004 Draw a pop up windows based on the dimension, number of lines and\r
1005 strings specified.\r
1006\r
1007 @param RequestedWidth The width of the pop-up.\r
1008 @param NumberOfLines The number of lines.\r
f4bcc90f 1009 @param Marker The variable argument list for the list of string to be printed.\r
7936fb6a 1010\r
1011**/\r
1012VOID\r
1013CreateSharedPopUp (\r
1014 IN UINTN RequestedWidth,\r
1015 IN UINTN NumberOfLines,\r
f4bcc90f 1016 IN VA_LIST Marker\r
7936fb6a 1017 )\r
1018{\r
1019 UINTN Index;\r
1020 UINTN Count;\r
1021 CHAR16 Character;\r
1022 UINTN Start;\r
1023 UINTN End;\r
1024 UINTN Top;\r
1025 UINTN Bottom;\r
1026 CHAR16 *String;\r
1027 UINTN DimensionsWidth;\r
1028 UINTN DimensionsHeight;\r
1029\r
1030 DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
1031 DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
1032\r
7936fb6a 1033 gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
1034\r
1035 if ((RequestedWidth + 2) > DimensionsWidth) {\r
1036 RequestedWidth = DimensionsWidth - 2;\r
1037 }\r
1038\r
1039 //\r
1040 // Subtract the PopUp width from total Columns, allow for one space extra on\r
1041 // each end plus a border.\r
1042 //\r
1043 Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
1044 End = Start + RequestedWidth + 1;\r
1045\r
1046 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
1047 Bottom = Top + NumberOfLines + 2;\r
1048\r
1049 Character = BOXDRAW_DOWN_RIGHT;\r
1050 PrintCharAt (Start, Top, Character);\r
1051 Character = BOXDRAW_HORIZONTAL;\r
1052 for (Index = Start; Index + 2 < End; Index++) {\r
1053 PrintChar (Character);\r
1054 }\r
1055\r
1056 Character = BOXDRAW_DOWN_LEFT;\r
1057 PrintChar (Character);\r
1058 Character = BOXDRAW_VERTICAL;\r
f4bcc90f 1059\r
1060 Count = 0;\r
1061 for (Index = Top; Index + 2 < Bottom; Index++, Count++) {\r
1062 String = VA_ARG (Marker, CHAR16*);\r
7936fb6a 1063\r
1064 //\r
1065 // This will clear the background of the line - we never know who might have been\r
1066 // here before us. This differs from the next clear in that it used the non-reverse\r
1067 // video for normal printing.\r
1068 //\r
1069 if (GetStringWidth (String) / 2 > 1) {\r
1070 ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
1071 }\r
1072\r
1073 //\r
1074 // Passing in a space results in the assumption that this is where typing will occur\r
1075 //\r
1076 if (String[0] == L' ') {\r
1077 ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);\r
1078 }\r
1079\r
1080 //\r
1081 // Passing in a NULL results in a blank space\r
1082 //\r
1083 if (String[0] == CHAR_NULL) {\r
1084 ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
1085 }\r
1086\r
1087 PrintStringAt (\r
1088 ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,\r
1089 Index + 1,\r
1090 String\r
1091 );\r
1092 gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
1093 PrintCharAt (Start, Index + 1, Character);\r
1094 PrintCharAt (End - 1, Index + 1, Character);\r
1095 }\r
1096\r
1097 Character = BOXDRAW_UP_RIGHT;\r
1098 PrintCharAt (Start, Bottom - 1, Character);\r
1099 Character = BOXDRAW_HORIZONTAL;\r
1100 for (Index = Start; Index + 2 < End; Index++) {\r
1101 PrintChar (Character);\r
1102 }\r
1103\r
1104 Character = BOXDRAW_UP_LEFT;\r
1105 PrintChar (Character);\r
1106}\r
1107\r
1108/**\r
1109 Draw a pop up windows based on the dimension, number of lines and\r
1110 strings specified.\r
1111\r
1112 @param RequestedWidth The width of the pop-up.\r
1113 @param NumberOfLines The number of lines.\r
7936fb6a 1114 @param ... A series of text strings that displayed in the pop-up.\r
1115\r
1116**/\r
1117VOID\r
8091267c 1118EFIAPI\r
3ebb9bdb 1119CreateMultiStringPopUp (\r
7936fb6a 1120 IN UINTN RequestedWidth,\r
1121 IN UINTN NumberOfLines,\r
7936fb6a 1122 ...\r
1123 )\r
1124{\r
f4bcc90f 1125 VA_LIST Marker;\r
1126\r
1127 VA_START (Marker, NumberOfLines);\r
d66e6c16 1128\r
f4bcc90f 1129 CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);\r
1130\r
1131 VA_END (Marker);\r
7936fb6a 1132}\r
1133\r
1134\r
1135/**\r
1136 Update status bar on the bottom of menu.\r
1137\r
b18e7050 1138 @param Selection Current Selction info.\r
7936fb6a 1139 @param MessageType The type of message to be shown.\r
1140 @param Flags The flags in Question header.\r
1141 @param State Set or clear.\r
1142\r
1143**/\r
1144VOID\r
1145UpdateStatusBar (\r
b18e7050 1146 IN UI_MENU_SELECTION *Selection,\r
7936fb6a 1147 IN UINTN MessageType,\r
1148 IN UINT8 Flags,\r
1149 IN BOOLEAN State\r
1150 )\r
1151{\r
1152 UINTN Index;\r
7936fb6a 1153 CHAR16 *NvUpdateMessage;\r
1154 CHAR16 *InputErrorMessage;\r
48a9d5f7
LG
1155 LIST_ENTRY *Link;\r
1156 FORM_BROWSER_FORMSET *LocalFormSet;\r
1157 FORM_BROWSER_STATEMENT *Question;\r
1158 \r
7936fb6a 1159 NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);\r
1160 InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);\r
1161\r
1162 switch (MessageType) {\r
1163 case INPUT_ERROR:\r
1164 if (State) {\r
1165 gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);\r
1166 PrintStringAt (\r
1167 gScreenDimensions.LeftColumn + gPromptBlockWidth,\r
1168 gScreenDimensions.BottomRow - 1,\r
1169 InputErrorMessage\r
1170 );\r
19b15d63 1171 mInputError = TRUE;\r
7936fb6a 1172 } else {\r
f0a1bf11 1173 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
7936fb6a 1174 for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {\r
1175 PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");\r
1176 }\r
1177\r
19b15d63 1178 mInputError = FALSE;\r
7936fb6a 1179 }\r
1180 break;\r
1181\r
1182 case NV_UPDATE_REQUIRED:\r
48a9d5f7
LG
1183 //\r
1184 // Global setting support. Show configuration change on every form.\r
1185 //\r
1186 if (State) {\r
1187 gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));\r
1188\r
1189 if (Selection != NULL && Selection->Statement != NULL) {\r
1190 Question = Selection->Statement;\r
1191 if (Question->Storage != NULL || Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
1192 //\r
1193 // Update only for Question value that need to be saved into Storage.\r
1194 //\r
1195 Selection->Form->NvUpdateRequired = TRUE;\r
1196 }\r
1197 }\r
1198 \r
1199 if (Selection == NULL || IsNvUpdateRequired (Selection->FormSet)) {\r
7936fb6a 1200 gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);\r
1201 PrintStringAt (\r
1202 gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,\r
1203 gScreenDimensions.BottomRow - 1,\r
1204 NvUpdateMessage\r
1205 );\r
48a9d5f7
LG
1206 }\r
1207 } else {\r
1208 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
1209 for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {\r
1210 PrintAt (\r
1211 (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),\r
1212 gScreenDimensions.BottomRow - 1,\r
1213 L" "\r
1214 );\r
7936fb6a 1215 }\r
1216 }\r
1217 break;\r
1218\r
1219 case REFRESH_STATUS_BAR:\r
19b15d63 1220 if (mInputError) {\r
b18e7050 1221 UpdateStatusBar (Selection, INPUT_ERROR, Flags, TRUE);\r
7936fb6a 1222 }\r
1223\r
48a9d5f7
LG
1224 switch (gBrowserSettingScope) {\r
1225 case SystemLevel:\r
1226 //\r
1227 // Check the maintain list to see whether there is any change.\r
1228 //\r
1229 Link = GetFirstNode (&gBrowserFormSetList);\r
1230 while (!IsNull (&gBrowserFormSetList, Link)) {\r
1231 LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
1232 if (IsNvUpdateRequired(LocalFormSet)) {\r
1233 UpdateStatusBar (NULL, NV_UPDATE_REQUIRED, Flags, TRUE);\r
1234 break;\r
1235 }\r
1236 Link = GetNextNode (&gBrowserFormSetList, Link);\r
1237 }\r
1238 break;\r
1239 case FormSetLevel:\r
1240 case FormLevel:\r
1241 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Flags, TRUE);\r
1242 default:\r
1243 break;\r
7936fb6a 1244 }\r
48a9d5f7 1245\r
7936fb6a 1246 break;\r
1247\r
1248 default:\r
1249 break;\r
1250 }\r
1251\r
f4113e1f 1252 FreePool (InputErrorMessage);\r
1253 FreePool (NvUpdateMessage);\r
7936fb6a 1254 return ;\r
1255}\r
1256\r
1257\r
1258/**\r
1259 Get the supported width for a particular op-code\r
1260\r
1261 @param Statement The FORM_BROWSER_STATEMENT structure passed in.\r
1262 @param Handle The handle in the HII database being used\r
1263\r
1264 @return Returns the number of CHAR16 characters that is support.\r
1265\r
1266**/\r
1267UINT16\r
1268GetWidth (\r
1269 IN FORM_BROWSER_STATEMENT *Statement,\r
1270 IN EFI_HII_HANDLE Handle\r
1271 )\r
1272{\r
1273 CHAR16 *String;\r
1274 UINTN Size;\r
1275 UINT16 Width;\r
1276\r
1277 Size = 0;\r
1278\r
1279 //\r
1280 // See if the second text parameter is really NULL\r
1281 //\r
1282 if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
1283 String = GetToken (Statement->TextTwo, Handle);\r
1284 Size = StrLen (String);\r
f4113e1f 1285 FreePool (String);\r
7936fb6a 1286 }\r
1287\r
1288 if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||\r
1289 (Statement->Operand == EFI_IFR_REF_OP) ||\r
1290 (Statement->Operand == EFI_IFR_PASSWORD_OP) ||\r
1291 (Statement->Operand == EFI_IFR_ACTION_OP) ||\r
1292 (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
1293 //\r
1294 // Allow a wide display if text op-code and no secondary text op-code\r
1295 //\r
1296 ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))\r
1297 ) {\r
1298 Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);\r
1299 } else {\r
1300 Width = (UINT16) gPromptBlockWidth;\r
1301 }\r
1302\r
1303 if (Statement->InSubtitle) {\r
1304 Width -= SUBTITLE_INDENT;\r
1305 }\r
1306\r
f7a14a9b 1307 return (UINT16) (Width - LEFT_SKIPPED_COLUMNS);\r
7936fb6a 1308}\r
1309\r
7936fb6a 1310/**\r
1311 Will copy LineWidth amount of a string in the OutputString buffer and return the\r
1312 number of CHAR16 characters that were copied into the OutputString buffer.\r
6c310dfb
ED
1313 The output string format is:\r
1314 Glyph Info + String info + '\0'.\r
1315\r
5ea466a5 1316 In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
7936fb6a 1317\r
1318 @param InputString String description for this option.\r
1319 @param LineWidth Width of the desired string to extract in CHAR16\r
1320 characters\r
6c310dfb 1321 @param GlyphWidth The glyph width of the begin of the char in the string.\r
7936fb6a 1322 @param Index Where in InputString to start the copy process\r
1323 @param OutputString Buffer to copy the string into\r
1324\r
6c310dfb
ED
1325 @return Returns the number of CHAR16 characters that were copied into the OutputString \r
1326 buffer, include extra glyph info and '\0' info.\r
7936fb6a 1327\r
1328**/\r
1329UINT16\r
1330GetLineByWidth (\r
1331 IN CHAR16 *InputString,\r
1332 IN UINT16 LineWidth,\r
6c310dfb 1333 IN OUT UINT16 *GlyphWidth,\r
7936fb6a 1334 IN OUT UINTN *Index,\r
1335 OUT CHAR16 **OutputString\r
1336 )\r
1337{\r
6c310dfb
ED
1338 UINT16 StrOffset;\r
1339 UINT16 GlyphOffset;\r
1340 UINT16 OriginalGlyphWidth;\r
1341 BOOLEAN ReturnFlag;\r
1342 UINT16 LastSpaceOffset;\r
1343 UINT16 LastGlyphWidth;\r
1344\r
1345 if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
1346 return 0;\r
1347 }\r
7936fb6a 1348\r
6c310dfb
ED
1349 if (LineWidth == 0 || *GlyphWidth == 0) {\r
1350 return 0;\r
7936fb6a 1351 }\r
1352\r
6c310dfb
ED
1353 //\r
1354 // Save original glyph width.\r
1355 //\r
1356 OriginalGlyphWidth = *GlyphWidth;\r
1357 LastGlyphWidth = OriginalGlyphWidth;\r
1358 ReturnFlag = FALSE;\r
1359 LastSpaceOffset = 0;\r
7936fb6a 1360\r
6c310dfb
ED
1361 //\r
1362 // 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
1363 // To avoid displaying this empty line in screen, just skip the two CHARs here.\r
1364 //\r
1365 if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
1366 *Index = *Index + 2;\r
1367 }\r
7936fb6a 1368\r
1369 //\r
6c310dfb 1370 // Fast-forward the string and see if there is a carriage-return in the string\r
7936fb6a 1371 //\r
6c310dfb
ED
1372 for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {\r
1373 switch (InputString[*Index + StrOffset]) {\r
1374 case NARROW_CHAR:\r
1375 *GlyphWidth = 1;\r
1376 break;\r
7936fb6a 1377\r
6c310dfb
ED
1378 case WIDE_CHAR:\r
1379 *GlyphWidth = 2;\r
1380 break;\r
7936fb6a 1381\r
6c310dfb
ED
1382 case CHAR_CARRIAGE_RETURN:\r
1383 case CHAR_LINEFEED:\r
1384 case CHAR_NULL:\r
1385 ReturnFlag = TRUE;\r
1386 break;\r
1387\r
1388 default:\r
1389 GlyphOffset = GlyphOffset + *GlyphWidth;\r
7936fb6a 1390\r
6c310dfb
ED
1391 //\r
1392 // Record the last space info in this line. Will be used in rewind.\r
1393 //\r
1394 if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {\r
1395 LastSpaceOffset = StrOffset;\r
1396 LastGlyphWidth = *GlyphWidth;\r
1397 }\r
1398 break;\r
1399 }\r
1400\r
1401 if (ReturnFlag) {\r
1402 break;\r
1403 }\r
1404 } \r
1405\r
1406 //\r
1407 // Rewind the string from the maximum size until we see a space to break the line\r
1408 //\r
1409 if (GlyphOffset > LineWidth) {\r
7936fb6a 1410 //\r
6c310dfb 1411 // Rewind the string to last space char in this line.\r
7936fb6a 1412 //\r
6c310dfb
ED
1413 if (LastSpaceOffset != 0) {\r
1414 StrOffset = LastSpaceOffset;\r
1415 *GlyphWidth = LastGlyphWidth;\r
1416 } else {\r
7936fb6a 1417 //\r
6c310dfb 1418 // Roll back to last char in the line width.\r
7936fb6a 1419 //\r
6c310dfb 1420 StrOffset--;\r
7936fb6a 1421 }\r
6c310dfb
ED
1422 }\r
1423\r
1424 //\r
1425 // The CHAR_NULL has process last time, this time just return 0 to stand for the end.\r
1426 //\r
1427 if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
1428 return 0;\r
1429 }\r
1430\r
1431 //\r
1432 // Need extra glyph info and '\0' info, so +2.\r
1433 //\r
1434 *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
1435 if (*OutputString == NULL) {\r
1436 return 0;\r
1437 }\r
1438\r
1439 //\r
1440 // Save the glyph info at the begin of the string, will used by Print function.\r
1441 //\r
1442 if (OriginalGlyphWidth == 1) {\r
1443 *(*OutputString) = NARROW_CHAR;\r
1444 } else {\r
1445 *(*OutputString) = WIDE_CHAR;\r
1446 }\r
7936fb6a 1447\r
6c310dfb 1448 CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
7936fb6a 1449\r
6c310dfb 1450 if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
7936fb6a 1451 //\r
6c310dfb
ED
1452 // Skip the space info at the begin of next line.\r
1453 // \r
1454 *Index = (UINT16) (*Index + StrOffset + 1);\r
1455 } else if ((InputString[*Index + StrOffset] == CHAR_LINEFEED)) {\r
7936fb6a 1456 //\r
6c310dfb
ED
1457 // Skip the /n or /n/r info.\r
1458 //\r
1459 if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
1460 *Index = (UINT16) (*Index + StrOffset + 2);\r
1461 } else {\r
1462 *Index = (UINT16) (*Index + StrOffset + 1);\r
1463 }\r
1464 } else if ((InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN)) {\r
1465 //\r
1466 // Skip the /r or /r/n info.\r
1467 // \r
1468 if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
1469 *Index = (UINT16) (*Index + StrOffset + 2);\r
1470 } else {\r
1471 *Index = (UINT16) (*Index + StrOffset + 1);\r
1472 }\r
7936fb6a 1473 } else {\r
6c310dfb 1474 *Index = (UINT16) (*Index + StrOffset);\r
7936fb6a 1475 }\r
6c310dfb
ED
1476\r
1477 //\r
1478 // Include extra glyph info and '\0' info, so +2.\r
1479 //\r
1480 return StrOffset + 2;\r
7936fb6a 1481}\r
1482\r
1483\r
1484/**\r
1485 Update display lines for a Menu Option.\r
1486\r
1487 @param Selection The user's selection.\r
1488 @param MenuOption The MenuOption to be checked.\r
7936fb6a 1489\r
7936fb6a 1490**/\r
1491VOID\r
1492UpdateOptionSkipLines (\r
1493 IN UI_MENU_SELECTION *Selection,\r
5f4ef94a 1494 IN UI_MENU_OPTION *MenuOption\r
7936fb6a 1495 )\r
1496{\r
1497 UINTN Index;\r
1498 UINT16 Width;\r
1499 UINTN Row;\r
1500 UINTN OriginalRow;\r
1501 CHAR16 *OutputString;\r
1502 CHAR16 *OptionString;\r
6c310dfb 1503 UINT16 GlyphWidth;\r
7936fb6a 1504\r
1505 Row = 0;\r
5f4ef94a 1506 OptionString = NULL;\r
7936fb6a 1507 ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
1508\r
1509 if (OptionString != NULL) {\r
1510 Width = (UINT16) gOptionBlockWidth;\r
1511\r
1512 OriginalRow = Row;\r
6c310dfb 1513 GlyphWidth = 1;\r
7936fb6a 1514\r
6c310dfb 1515 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 1516 //\r
1517 // If there is more string to process print on the next row and increment the Skip value\r
1518 //\r
d1a54e2c 1519 if (StrLen (&OptionString[Index]) != 0) {\r
5f4ef94a
ED
1520 Row++;\r
1521 //\r
1522 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
1523 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
1524 // some testing to ensure we are keeping this in-sync.\r
1525 //\r
1526 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
1527 //\r
1528 if ((Row - OriginalRow) >= MenuOption->Skip) {\r
1529 MenuOption->Skip++;\r
7936fb6a 1530 }\r
1531 }\r
1532\r
f4113e1f 1533 FreePool (OutputString);\r
7936fb6a 1534 }\r
1535\r
1536 Row = OriginalRow;\r
1537 }\r
1538\r
5f4ef94a
ED
1539 if (OptionString != NULL) {\r
1540 FreePool (OptionString);\r
1541 }\r
7936fb6a 1542}\r
1543\r
1544\r
1545/**\r
1546 Check whether this Menu Option could be highlighted.\r
1547\r
1548 This is an internal function.\r
1549\r
1550 @param MenuOption The MenuOption to be checked.\r
1551\r
1552 @retval TRUE This Menu Option is selectable.\r
1553 @retval FALSE This Menu Option could not be selected.\r
1554\r
1555**/\r
1556BOOLEAN\r
1557IsSelectable (\r
1558 UI_MENU_OPTION *MenuOption\r
1559 )\r
1560{\r
1561 if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||\r
1562 MenuOption->GrayOut || MenuOption->ReadOnly) {\r
1563 return FALSE;\r
1564 } else {\r
1565 return TRUE;\r
1566 }\r
1567}\r
1568\r
1569\r
1570/**\r
1571 Determine if the menu is the last menu that can be selected.\r
1572\r
1573 This is an internal function.\r
d66e6c16 1574\r
7936fb6a 1575 @param Direction The scroll direction. False is down. True is up.\r
1576 @param CurrentPos The current focus.\r
1577\r
1578 @return FALSE -- the menu isn't the last menu that can be selected.\r
1579 @return TRUE -- the menu is the last menu that can be selected.\r
1580\r
1581**/\r
1582BOOLEAN\r
1583ValueIsScroll (\r
1584 IN BOOLEAN Direction,\r
1585 IN LIST_ENTRY *CurrentPos\r
1586 )\r
1587{\r
1588 LIST_ENTRY *Temp;\r
7936fb6a 1589\r
1590 Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
1591\r
ce6d12cc 1592 if (Temp == &gMenuOption) {\r
7936fb6a 1593 return TRUE;\r
1594 }\r
1595\r
11232773 1596 return FALSE;\r
7936fb6a 1597}\r
1598\r
1599\r
1600/**\r
1601 Move to next selectable statement.\r
d66e6c16 1602\r
7936fb6a 1603 This is an internal function.\r
d66e6c16 1604\r
5f4ef94a 1605 @param Selection Menu selection.\r
7936fb6a 1606 @param GoUp The navigation direction. TRUE: up, FALSE: down.\r
1607 @param CurrentPosition Current position.\r
11232773 1608 @param GapToTop Gap position to top or bottom.\r
7936fb6a 1609\r
1610 @return The row distance from current MenuOption to next selectable MenuOption.\r
1611\r
1612**/\r
1613INTN\r
1614MoveToNextStatement (\r
5f4ef94a 1615 IN UI_MENU_SELECTION *Selection,\r
7936fb6a 1616 IN BOOLEAN GoUp,\r
11232773
LG
1617 IN OUT LIST_ENTRY **CurrentPosition,\r
1618 IN UINTN GapToTop\r
7936fb6a 1619 )\r
1620{\r
1621 INTN Distance;\r
1622 LIST_ENTRY *Pos;\r
7936fb6a 1623 UI_MENU_OPTION *NextMenuOption;\r
11232773 1624 UI_MENU_OPTION *PreMenuOption;\r
7936fb6a 1625\r
11232773
LG
1626 Distance = 0;\r
1627 Pos = *CurrentPosition;\r
1628 PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
7936fb6a 1629\r
1630 while (TRUE) {\r
1631 NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
5f4ef94a
ED
1632 if (NextMenuOption->Row == 0) {\r
1633 UpdateOptionSkipLines (Selection, NextMenuOption);\r
1634 }\r
1635 \r
11232773
LG
1636 if (GoUp && (PreMenuOption != NextMenuOption)) {\r
1637 //\r
1638 // Current Position doesn't need to be caculated when go up.\r
1639 // Caculate distanct at first when go up\r
1640 //\r
1641 if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
1642 NextMenuOption = PreMenuOption;\r
1643 break;\r
1644 }\r
1645 Distance += NextMenuOption->Skip;\r
1646 }\r
7936fb6a 1647 if (IsSelectable (NextMenuOption)) {\r
1648 break;\r
1649 }\r
ce6d12cc 1650 if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
11232773
LG
1651 //\r
1652 // Arrive at top.\r
1653 //\r
1654 Distance = -1;\r
7936fb6a 1655 break;\r
1656 }\r
11232773
LG
1657 if (!GoUp) {\r
1658 //\r
1659 // Caculate distanct at later when go down\r
1660 //\r
1661 if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
1662 NextMenuOption = PreMenuOption;\r
7936fb6a 1663 break;\r
1664 }\r
11232773 1665 Distance += NextMenuOption->Skip;\r
7936fb6a 1666 }\r
11232773
LG
1667 PreMenuOption = NextMenuOption;\r
1668 Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
7936fb6a 1669 }\r
1670\r
1671 *CurrentPosition = &NextMenuOption->Link;\r
1672 return Distance;\r
1673}\r
1674\r
1675\r
1676/**\r
1677 Adjust Data and Time position accordingly.\r
1678 Data format : [01/02/2004] [11:22:33]\r
1679 Line number : 0 0 1 0 0 1\r
d66e6c16 1680\r
7936fb6a 1681 This is an internal function.\r
1682\r
1683 @param DirectionUp the up or down direction. False is down. True is\r
1684 up.\r
1685 @param CurrentPosition Current position. On return: Point to the last\r
1686 Option (Year or Second) if up; Point to the first\r
1687 Option (Month or Hour) if down.\r
1688\r
1689 @return Return line number to pad. It is possible that we stand on a zero-advance\r
1690 @return data or time opcode, so pad one line when we judge if we are going to scroll outside.\r
1691\r
1692**/\r
1693UINTN\r
1694AdjustDateAndTimePosition (\r
1695 IN BOOLEAN DirectionUp,\r
1696 IN OUT LIST_ENTRY **CurrentPosition\r
1697 )\r
1698{\r
1699 UINTN Count;\r
1700 LIST_ENTRY *NewPosition;\r
1701 UI_MENU_OPTION *MenuOption;\r
1702 UINTN PadLineNumber;\r
1703\r
1704 PadLineNumber = 0;\r
1705 NewPosition = *CurrentPosition;\r
1706 MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
1707\r
1708 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
1709 (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
1710 //\r
1711 // Calculate the distance from current position to the last Date/Time MenuOption\r
1712 //\r
1713 Count = 0;\r
1714 while (MenuOption->Skip == 0) {\r
1715 Count++;\r
1716 NewPosition = NewPosition->ForwardLink;\r
1717 MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
1718 PadLineNumber = 1;\r
1719 }\r
1720\r
1721 NewPosition = *CurrentPosition;\r
1722 if (DirectionUp) {\r
1723 //\r
1724 // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended\r
1725 // to be one that back to the previous set of MenuOptions, we need to advance to the first\r
1726 // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate\r
1727 // checking can be done.\r
1728 //\r
1729 while (Count++ < 2) {\r
1730 NewPosition = NewPosition->BackLink;\r
1731 }\r
1732 } else {\r
1733 //\r
1734 // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended\r
1735 // to be one that progresses to the next set of MenuOptions, we need to advance to the last\r
1736 // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate\r
1737 // checking can be done.\r
1738 //\r
1739 while (Count-- > 0) {\r
1740 NewPosition = NewPosition->ForwardLink;\r
1741 }\r
1742 }\r
1743\r
1744 *CurrentPosition = NewPosition;\r
1745 }\r
1746\r
1747 return PadLineNumber;\r
1748}\r
1749\r
cb7d01c0 1750/**\r
1751 Find HII Handle in the HII database associated with given Device Path.\r
1752\r
1753 If DevicePath is NULL, then ASSERT.\r
1754\r
1755 @param DevicePath Device Path associated with the HII package list\r
1756 handle.\r
1757\r
1758 @retval Handle HII package list Handle associated with the Device\r
1759 Path.\r
1760 @retval NULL Hii Package list handle is not found.\r
1761\r
1762**/\r
1763EFI_HII_HANDLE\r
1764EFIAPI\r
1765DevicePathToHiiHandle (\r
1766 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1767 )\r
1768{\r
1769 EFI_STATUS Status;\r
1770 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
1771 UINTN BufferSize;\r
1772 UINTN HandleCount;\r
1773 UINTN Index;\r
1774 EFI_HANDLE Handle;\r
1775 EFI_HANDLE DriverHandle;\r
1776 EFI_HII_HANDLE *HiiHandles;\r
1777 EFI_HII_HANDLE HiiHandle;\r
1778\r
1779 ASSERT (DevicePath != NULL);\r
1780\r
1781 TmpDevicePath = DevicePath;\r
1782 //\r
1783 // Locate Device Path Protocol handle buffer\r
1784 //\r
1785 Status = gBS->LocateDevicePath (\r
1786 &gEfiDevicePathProtocolGuid,\r
1787 &TmpDevicePath,\r
1788 &DriverHandle\r
1789 );\r
1790 if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
1791 return NULL;\r
1792 }\r
1793\r
1794 //\r
1795 // Retrieve all HII Handles from HII database\r
1796 //\r
1797 BufferSize = 0x1000;\r
1798 HiiHandles = AllocatePool (BufferSize);\r
1799 ASSERT (HiiHandles != NULL);\r
1800 Status = mHiiDatabase->ListPackageLists (\r
1801 mHiiDatabase,\r
1802 EFI_HII_PACKAGE_TYPE_ALL,\r
1803 NULL,\r
1804 &BufferSize,\r
1805 HiiHandles\r
1806 );\r
1807 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1808 FreePool (HiiHandles);\r
1809 HiiHandles = AllocatePool (BufferSize);\r
1810 ASSERT (HiiHandles != NULL);\r
1811\r
1812 Status = mHiiDatabase->ListPackageLists (\r
1813 mHiiDatabase,\r
1814 EFI_HII_PACKAGE_TYPE_ALL,\r
1815 NULL,\r
1816 &BufferSize,\r
1817 HiiHandles\r
1818 );\r
1819 }\r
1820\r
1821 if (EFI_ERROR (Status)) {\r
1822 FreePool (HiiHandles);\r
1823 return NULL;\r
1824 }\r
1825\r
1826 //\r
1827 // Search Hii Handle by Driver Handle\r
1828 //\r
1829 HiiHandle = NULL;\r
1830 HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
1831 for (Index = 0; Index < HandleCount; Index++) {\r
1832 Status = mHiiDatabase->GetPackageListHandle (\r
1833 mHiiDatabase,\r
1834 HiiHandles[Index],\r
1835 &Handle\r
1836 );\r
1837 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
1838 HiiHandle = HiiHandles[Index];\r
1839 break;\r
1840 }\r
1841 }\r
1842\r
1843 FreePool (HiiHandles);\r
1844 return HiiHandle;\r
1845}\r
7936fb6a 1846\r
b2e444aa
ED
1847/**\r
1848 Find HII Handle in the HII database associated with given form set guid.\r
1849\r
1850 If FormSetGuid is NULL, then ASSERT.\r
1851\r
1852 @param ComparingGuid FormSet Guid associated with the HII package list\r
1853 handle.\r
1854\r
1855 @retval Handle HII package list Handle associated with the Device\r
1856 Path.\r
1857 @retval NULL Hii Package list handle is not found.\r
1858\r
1859**/\r
1860EFI_HII_HANDLE\r
1861FormSetGuidToHiiHandle (\r
1862 EFI_GUID *ComparingGuid\r
1863 )\r
1864{\r
1865 EFI_HII_HANDLE *HiiHandles;\r
1866 UINTN Index;\r
1867 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
1868 UINTN BufferSize;\r
1869 UINT32 Offset;\r
1870 UINT32 Offset2;\r
1871 UINT32 PackageListLength;\r
1872 EFI_HII_PACKAGE_HEADER PackageHeader;\r
1873 UINT8 *Package;\r
1874 UINT8 *OpCodeData;\r
1875 EFI_STATUS Status;\r
1876 EFI_HII_HANDLE HiiHandle;\r
1877\r
1878 ASSERT (ComparingGuid != NULL);\r
1879\r
1880 HiiHandle = NULL;\r
1881 //\r
1882 // Get all the Hii handles\r
1883 //\r
1884 HiiHandles = HiiGetHiiHandles (NULL);\r
1885 ASSERT (HiiHandles != NULL);\r
1886\r
1887 //\r
1888 // Search for formset of each class type\r
1889 //\r
1890 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
1891 BufferSize = 0;\r
1892 HiiPackageList = NULL;\r
1893 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
1894 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1895 HiiPackageList = AllocatePool (BufferSize);\r
1896 ASSERT (HiiPackageList != NULL);\r
1897\r
1898 Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
1899 }\r
1900 if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
1901 return NULL;\r
1902 }\r
1903\r
1904 //\r
1905 // Get Form package from this HII package List\r
1906 //\r
1907 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1908 Offset2 = 0;\r
1909 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); \r
1910\r
1911 while (Offset < PackageListLength) {\r
1912 Package = ((UINT8 *) HiiPackageList) + Offset;\r
1913 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
1914\r
1915 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
1916 //\r
1917 // Search FormSet in this Form Package\r
1918 //\r
1919 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
1920 while (Offset2 < PackageHeader.Length) {\r
1921 OpCodeData = Package + Offset2;\r
1922\r
1923 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
1924 //\r
1925 // Try to compare against formset GUID\r
1926 //\r
1927 if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
1928 HiiHandle = HiiHandles[Index];\r
1929 break;\r
1930 }\r
1931 }\r
1932\r
1933 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
1934 }\r
1935 }\r
1936 if (HiiHandle != NULL) {\r
1937 break;\r
1938 }\r
1939 Offset += PackageHeader.Length;\r
1940 }\r
1941 \r
1942 FreePool (HiiPackageList);\r
1943 if (HiiHandle != NULL) {\r
1944 break;\r
1945 }\r
1946 }\r
1947\r
1948 FreePool (HiiHandles);\r
1949\r
1950 return HiiHandle;\r
1951}\r
1952\r
33efdf51
ED
1953/**\r
1954 Transfer the device path string to binary format.\r
1955\r
1956 @param StringPtr The device path string info.\r
1957\r
1958 @retval Device path binary info.\r
1959\r
1960**/\r
1961EFI_DEVICE_PATH_PROTOCOL *\r
1962ConvertDevicePathFromText (\r
1963 IN CHAR16 *StringPtr\r
1964 )\r
1965{\r
1966 UINTN BufferSize;\r
1967 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1968 CHAR16 TemStr[2];\r
1969 UINT8 *DevicePathBuffer;\r
1970 UINTN Index;\r
1971 UINT8 DigitUint8;\r
1972\r
1973 ASSERT (StringPtr != NULL);\r
1974\r
1975 BufferSize = StrLen (StringPtr) / 2;\r
1976 DevicePath = AllocatePool (BufferSize);\r
1977 ASSERT (DevicePath != NULL);\r
1978 \r
1979 //\r
1980 // Convert from Device Path String to DevicePath Buffer in the reverse order.\r
1981 //\r
1982 DevicePathBuffer = (UINT8 *) DevicePath;\r
1983 for (Index = 0; StringPtr[Index] != L'\0'; Index ++) {\r
1984 TemStr[0] = StringPtr[Index];\r
1985 DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
1986 if (DigitUint8 == 0 && TemStr[0] != L'0') {\r
1987 //\r
1988 // Invalid Hex Char as the tail.\r
1989 //\r
1990 break;\r
1991 }\r
1992 if ((Index & 1) == 0) {\r
1993 DevicePathBuffer [Index/2] = DigitUint8;\r
1994 } else {\r
1995 DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
1996 }\r
1997 }\r
1998\r
1999 return DevicePath;\r
2000}\r
2001\r
8ca6180f
ED
2002/**\r
2003 Process the goto op code, update the info in the selection structure.\r
2004\r
2005 @param Statement The statement belong to goto op code.\r
2006 @param Selection The selection info.\r
2007 @param Repaint Whether need to repaint the menu.\r
2008 @param NewLine Whether need to create new line.\r
2009\r
2010 @retval EFI_SUCCESS The menu process successfully.\r
2011 @return Other value if the process failed.\r
2012**/\r
2013EFI_STATUS\r
2014ProcessGotoOpCode (\r
2015 IN OUT FORM_BROWSER_STATEMENT *Statement,\r
2016 IN OUT UI_MENU_SELECTION *Selection,\r
2017 OUT BOOLEAN *Repaint,\r
2018 OUT BOOLEAN *NewLine\r
2019 )\r
2020{\r
2021 CHAR16 *StringPtr;\r
8ca6180f 2022 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
8ca6180f
ED
2023 FORM_BROWSER_FORM *RefForm;\r
2024 EFI_INPUT_KEY Key;\r
2025 EFI_STATUS Status;\r
2026 UI_MENU_LIST *MenuList;\r
b2e444aa 2027 BOOLEAN UpdateFormInfo;\r
8ca6180f
ED
2028 \r
2029 Status = EFI_SUCCESS;\r
b2e444aa 2030 UpdateFormInfo = TRUE;\r
e7fd76d1 2031 StringPtr = NULL;\r
8ca6180f 2032\r
e7fd76d1
ED
2033 //\r
2034 // Prepare the device path check, get the device path info first.\r
2035 //\r
8ca6180f 2036 if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
e7fd76d1 2037 StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
e7fd76d1
ED
2038 }\r
2039\r
2040 //\r
2041 // Check whether the device path string is a valid string.\r
2042 //\r
33efdf51 2043 if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) {\r
8ca6180f
ED
2044 if (Selection->Form->ModalForm) {\r
2045 return Status;\r
2046 }\r
2047 //\r
2048 // Goto another Hii Package list\r
2049 //\r
2050 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
33efdf51 2051 DevicePath = ConvertDevicePathFromText (StringPtr);\r
8ca6180f
ED
2052\r
2053 Selection->Handle = DevicePathToHiiHandle (DevicePath);\r
e7fd76d1 2054 FreePool (DevicePath);\r
33efdf51 2055 FreePool (StringPtr);\r
e7fd76d1 2056\r
8ca6180f
ED
2057 if (Selection->Handle == NULL) {\r
2058 //\r
2059 // If target Hii Handle not found, exit\r
2060 //\r
2061 Selection->Action = UI_ACTION_EXIT;\r
2062 Selection->Statement = NULL;\r
2063 return Status;\r
2064 }\r
2065\r
8ca6180f
ED
2066 CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
2067 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
2068 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2069 } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {\r
2070 if (Selection->Form->ModalForm) {\r
2071 return Status;\r
2072 } \r
2073 //\r
2074 // Goto another Formset, check for uncommitted data\r
2075 //\r
2076 Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
b2e444aa
ED
2077 \r
2078 Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
2079 if (Selection->Handle == NULL) {\r
2080 //\r
2081 // If target Hii Handle not found, exit\r
2082 //\r
2083 Selection->Action = UI_ACTION_EXIT;\r
2084 Selection->Statement = NULL;\r
2085 return Status;\r
2086 } \r
8ca6180f
ED
2087\r
2088 CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
2089 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
2090 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2091 } else if (Statement->HiiValue.Value.ref.FormId != 0) {\r
2092 //\r
2093 // Check whether target From is suppressed.\r
2094 //\r
2095 RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
2096\r
2097 if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
31585af4 2098 if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
8ca6180f
ED
2099 //\r
2100 // Form is suppressed. \r
2101 //\r
2102 do {\r
2103 CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);\r
2104 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2105 if (Repaint != NULL) {\r
2106 *Repaint = TRUE;\r
2107 }\r
2108 return Status;\r
2109 }\r
2110 }\r
2111\r
2112 //\r
2113 // Goto another form inside this formset,\r
2114 //\r
2115 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2116\r
8ca6180f
ED
2117 Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
2118 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2119 } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {\r
2120 //\r
2121 // Goto another Question\r
2122 //\r
2123 Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
2124\r
2125 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
2126 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2127 } else {\r
2128 if (Repaint != NULL) {\r
2129 *Repaint = TRUE;\r
2130 }\r
2131 if (NewLine != NULL) {\r
2132 *NewLine = TRUE;\r
2133 }\r
2134 }\r
b2e444aa 2135 UpdateFormInfo = FALSE;\r
8ca6180f
ED
2136 } else {\r
2137 if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
2138 Selection->Action = UI_ACTION_REFRESH_FORM;\r
2139 }\r
b2e444aa
ED
2140 UpdateFormInfo = FALSE;\r
2141 }\r
2142\r
2143 if (UpdateFormInfo) {\r
2144 //\r
2145 // Link current form so that we can always go back when someone hits the ESC\r
2146 //\r
2147 MenuList = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId);\r
2148 if (MenuList == NULL && Selection->CurrentMenu != NULL) {\r
2149 MenuList = UiAddMenuList (Selection->CurrentMenu, Selection->Handle, &Selection->FormSetGuid, Selection->FormId);\r
2150 }\r
8ca6180f
ED
2151 }\r
2152\r
2153 return Status;\r
2154}\r
2155\r
7936fb6a 2156/**\r
2157 Display menu and wait for user to select one menu option, then return it.\r
2158 If AutoBoot is enabled, then if user doesn't select any option,\r
2159 after period of time, it will automatically return the first menu option.\r
2160\r
2161 @param Selection Menu selection.\r
2162\r
2163 @retval EFI_SUCESSS This function always return successfully for now.\r
2164\r
2165**/\r
2166EFI_STATUS\r
2167UiDisplayMenu (\r
2168 IN OUT UI_MENU_SELECTION *Selection\r
2169 )\r
2170{\r
2171 INTN SkipValue;\r
2172 INTN Difference;\r
2173 INTN OldSkipValue;\r
2174 UINTN DistanceValue;\r
2175 UINTN Row;\r
2176 UINTN Col;\r
2177 UINTN Temp;\r
2178 UINTN Temp2;\r
2179 UINTN TopRow;\r
2180 UINTN BottomRow;\r
2181 UINTN OriginalRow;\r
2182 UINTN Index;\r
7936fb6a 2183 UINT16 Width;\r
2184 CHAR16 *StringPtr;\r
2185 CHAR16 *OptionString;\r
2186 CHAR16 *OutputString;\r
ba46ab94
ED
2187 CHAR16 *HelpString;\r
2188 CHAR16 *HelpHeaderString;\r
2189 CHAR16 *HelpBottomString;\r
7936fb6a 2190 BOOLEAN NewLine;\r
2191 BOOLEAN Repaint;\r
2192 BOOLEAN SavedValue;\r
ce6d12cc 2193 BOOLEAN UpArrow;\r
2194 BOOLEAN DownArrow;\r
11232773 2195 BOOLEAN InitializedFlag;\r
7936fb6a 2196 EFI_STATUS Status;\r
2197 EFI_INPUT_KEY Key;\r
2198 LIST_ENTRY *Link;\r
2199 LIST_ENTRY *NewPos;\r
2200 LIST_ENTRY *TopOfScreen;\r
2201 LIST_ENTRY *SavedListEntry;\r
2202 UI_MENU_OPTION *MenuOption;\r
2203 UI_MENU_OPTION *NextMenuOption;\r
2204 UI_MENU_OPTION *SavedMenuOption;\r
2205 UI_MENU_OPTION *PreviousMenuOption;\r
2206 UI_CONTROL_FLAG ControlFlag;\r
2207 EFI_SCREEN_DESCRIPTOR LocalScreen;\r
2208 MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
211cc6e5 2209 MENU_REFRESH_ENTRY *MenuUpdateEntry; \r
7936fb6a 2210 UI_SCREEN_OPERATION ScreenOperation;\r
2211 UINT8 MinRefreshInterval;\r
7936fb6a 2212 UINT16 DefaultId;\r
7936fb6a 2213 FORM_BROWSER_STATEMENT *Statement;\r
d66e6c16 2214 UI_MENU_LIST *CurrentMenu;\r
b00964a9 2215 UINTN ModalSkipColumn;\r
48a9d5f7 2216 BROWSER_HOT_KEY *HotKey;\r
ba46ab94
ED
2217 UINTN HelpPageIndex;\r
2218 UINTN HelpPageCount;\r
2219 UINTN RowCount;\r
2220 UINTN HelpLine;\r
2221 UINTN HelpHeaderLine;\r
2222 UINTN HelpBottomLine;\r
2223 BOOLEAN MultiHelpPage;\r
6c310dfb
ED
2224 UINT16 GlyphWidth;\r
2225 UINT16 EachLineWidth;\r
2226 UINT16 HeaderLineWidth;\r
2227 UINT16 BottomLineWidth;\r
7936fb6a 2228\r
2229 CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
2230\r
2231 Status = EFI_SUCCESS;\r
ba46ab94
ED
2232 HelpString = NULL;\r
2233 HelpHeaderString = NULL;\r
2234 HelpBottomString = NULL;\r
7936fb6a 2235 OptionString = NULL;\r
2236 ScreenOperation = UiNoOperation;\r
2237 NewLine = TRUE;\r
2238 MinRefreshInterval = 0;\r
2239 DefaultId = 0;\r
ba46ab94
ED
2240 HelpPageCount = 0;\r
2241 HelpLine = 0;\r
2242 RowCount = 0;\r
2243 HelpBottomLine = 0;\r
2244 HelpHeaderLine = 0;\r
2245 HelpPageIndex = 0;\r
2246 MultiHelpPage = FALSE;\r
6c310dfb
ED
2247 EachLineWidth = 0;\r
2248 HeaderLineWidth = 0;\r
2249 BottomLineWidth = 0;\r
7936fb6a 2250 OutputString = NULL;\r
ce6d12cc 2251 UpArrow = FALSE;\r
2252 DownArrow = FALSE;\r
7936fb6a 2253 SkipValue = 0;\r
2254 OldSkipValue = 0;\r
2255 MenuRefreshEntry = gMenuRefreshHead;\r
2256\r
2257 NextMenuOption = NULL;\r
2258 PreviousMenuOption = NULL;\r
2259 SavedMenuOption = NULL;\r
48a9d5f7 2260 HotKey = NULL;\r
b00964a9 2261 ModalSkipColumn = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 6;\r
7936fb6a 2262\r
2263 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
2264\r
40245175 2265 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE){\r
7936fb6a 2266 TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2267 Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2268 } else {\r
2269 TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2270 Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
2271 }\r
2272\r
b00964a9
ED
2273 if (Selection->Form->ModalForm) {\r
2274 Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn;\r
2275 } else {\r
2276 Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;\r
2277 }\r
2278\r
48a9d5f7 2279 BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - SCROLL_ARROW_HEIGHT - 1;\r
7936fb6a 2280\r
2281 Selection->TopRow = TopRow;\r
2282 Selection->BottomRow = BottomRow;\r
2283 Selection->PromptCol = Col;\r
2284 Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
2285 Selection->Statement = NULL;\r
2286\r
ce6d12cc 2287 TopOfScreen = gMenuOption.ForwardLink;\r
7936fb6a 2288 Repaint = TRUE;\r
2289 MenuOption = NULL;\r
2290\r
d66e6c16 2291 //\r
2292 // Find current Menu\r
2293 //\r
2294 CurrentMenu = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId);\r
2295 if (CurrentMenu == NULL) {\r
2296 //\r
2297 // Current menu not found, add it to the menu tree\r
2298 //\r
b2e444aa 2299 CurrentMenu = UiAddMenuList (NULL, Selection->Handle, &Selection->FormSetGuid, Selection->FormId);\r
d66e6c16 2300 }\r
2301 ASSERT (CurrentMenu != NULL);\r
b18e7050 2302 Selection->CurrentMenu = CurrentMenu;\r
d66e6c16 2303\r
2304 if (Selection->QuestionId == 0) {\r
2305 //\r
2306 // Highlight not specified, fetch it from cached menu\r
2307 //\r
2308 Selection->QuestionId = CurrentMenu->QuestionId;\r
d88ca2c9 2309 Selection->Sequence = CurrentMenu->Sequence;\r
d66e6c16 2310 }\r
2311\r
7936fb6a 2312 //\r
11232773 2313 // Init option as the current user's selection\r
7936fb6a 2314 //\r
11232773 2315 InitializedFlag = TRUE;\r
ce6d12cc 2316 NewPos = gMenuOption.ForwardLink;\r
7936fb6a 2317\r
2318 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
b18e7050 2319 UpdateStatusBar (Selection, REFRESH_STATUS_BAR, (UINT8) 0, TRUE);\r
7936fb6a 2320\r
2321 ControlFlag = CfInitialization;\r
2322 Selection->Action = UI_ACTION_NONE;\r
2323 while (TRUE) {\r
2324 switch (ControlFlag) {\r
2325 case CfInitialization:\r
ce6d12cc 2326 if (IsListEmpty (&gMenuOption)) {\r
7936fb6a 2327 ControlFlag = CfReadKey;\r
2328 } else {\r
2329 ControlFlag = CfCheckSelection;\r
2330 }\r
2331 break;\r
2332\r
2333 case CfCheckSelection:\r
2334 if (Selection->Action != UI_ACTION_NONE) {\r
2335 ControlFlag = CfExit;\r
2336 } else {\r
2337 ControlFlag = CfRepaint;\r
2338 }\r
2339 break;\r
2340\r
2341 case CfRepaint:\r
2342 ControlFlag = CfRefreshHighLight;\r
2343\r
2344 if (Repaint) {\r
2345 //\r
2346 // Display menu\r
2347 //\r
ce6d12cc 2348 DownArrow = FALSE;\r
2349 UpArrow = FALSE;\r
7936fb6a 2350 Row = TopRow;\r
2351\r
cd7bfc2c
ED
2352 Temp = (UINTN) SkipValue;\r
2353 Temp2 = (UINTN) SkipValue;\r
7936fb6a 2354\r
b00964a9
ED
2355 if (Selection->Form->ModalForm) {\r
2356 ClearLines (\r
2357 LocalScreen.LeftColumn + ModalSkipColumn,\r
2358 LocalScreen.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth,\r
2359 TopRow - SCROLL_ARROW_HEIGHT,\r
2360 BottomRow + SCROLL_ARROW_HEIGHT,\r
2361 PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
2362 ); \r
2363 } else {\r
2364 ClearLines (\r
2365 LocalScreen.LeftColumn,\r
2366 LocalScreen.RightColumn,\r
2367 TopRow - SCROLL_ARROW_HEIGHT,\r
2368 BottomRow + SCROLL_ARROW_HEIGHT,\r
2369 PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
2370 );\r
2371 }\r
7936fb6a 2372 UiFreeRefreshList ();\r
2373 MinRefreshInterval = 0;\r
2374\r
ce6d12cc 2375 for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {\r
7936fb6a 2376 MenuOption = MENU_OPTION_FROM_LINK (Link);\r
2377 MenuOption->Row = Row;\r
2378 MenuOption->Col = Col;\r
b00964a9
ED
2379 if (Selection->Form->ModalForm) {\r
2380 MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn + ModalSkipColumn;\r
2381 } else {\r
2382 MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
2383 }\r
7936fb6a 2384\r
2385 Statement = MenuOption->ThisTag;\r
2386 if (Statement->InSubtitle) {\r
2387 MenuOption->Col += SUBTITLE_INDENT;\r
2388 }\r
2389\r
2390 if (MenuOption->GrayOut) {\r
2391 gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
2392 } else {\r
2393 if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {\r
f0a1bf11 2394 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2395 }\r
2396 }\r
2397\r
2398 Width = GetWidth (Statement, MenuOption->Handle);\r
2399 OriginalRow = Row;\r
6c310dfb 2400 GlyphWidth = 1;\r
7936fb6a 2401\r
11232773 2402 if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
a605dfb3
LG
2403 //\r
2404 // Print Arrow for Goto button.\r
2405 //\r
2406 PrintAt (\r
b6ca1fd8 2407 MenuOption->Col - 2,\r
a605dfb3
LG
2408 Row,\r
2409 L"%c",\r
2410 GEOMETRICSHAPE_RIGHT_TRIANGLE\r
2411 );\r
2412 }\r
2413\r
6c310dfb 2414 for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2415 if ((Temp == 0) && (Row <= BottomRow)) {\r
2416 PrintStringAt (MenuOption->Col, Row, OutputString);\r
2417 }\r
2418 //\r
2419 // If there is more string to process print on the next row and increment the Skip value\r
2420 //\r
d1a54e2c 2421 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
7936fb6a 2422 if (Temp == 0) {\r
2423 Row++;\r
2424 }\r
2425 }\r
2426\r
f4113e1f 2427 FreePool (OutputString);\r
7936fb6a 2428 if (Temp != 0) {\r
2429 Temp--;\r
2430 }\r
2431 }\r
2432\r
2433 Temp = 0;\r
2434 Row = OriginalRow;\r
2435\r
8d00a0f1 2436 Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
2437 if (EFI_ERROR (Status)) {\r
2438 //\r
2439 // Repaint to clear possible error prompt pop-up\r
2440 //\r
2441 Repaint = TRUE;\r
2442 NewLine = TRUE;\r
2443 ControlFlag = CfRepaint;\r
2444 break;\r
2445 }\r
7936fb6a 2446\r
2447 if (OptionString != NULL) {\r
2448 if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
4a6876b7 2449 ProcessStringForDateTime(MenuOption, OptionString, TRUE);\r
7936fb6a 2450 }\r
2451\r
7936fb6a 2452 Width = (UINT16) gOptionBlockWidth;\r
2453 OriginalRow = Row;\r
6c310dfb 2454 GlyphWidth = 1;\r
7936fb6a 2455\r
6c310dfb 2456 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2457 if ((Temp2 == 0) && (Row <= BottomRow)) {\r
2458 PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
2459 }\r
2460 //\r
2461 // If there is more string to process print on the next row and increment the Skip value\r
2462 //\r
d1a54e2c 2463 if (StrLen (&OptionString[Index]) != 0) {\r
7936fb6a 2464 if (Temp2 == 0) {\r
2465 Row++;\r
2466 //\r
2467 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
2468 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
2469 // some testing to ensure we are keeping this in-sync.\r
2470 //\r
2471 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
2472 //\r
2473 if ((Row - OriginalRow) >= MenuOption->Skip) {\r
2474 MenuOption->Skip++;\r
2475 }\r
2476 }\r
2477 }\r
2478\r
f4113e1f 2479 FreePool (OutputString);\r
7936fb6a 2480 if (Temp2 != 0) {\r
2481 Temp2--;\r
2482 }\r
2483 }\r
2484\r
2485 Temp2 = 0;\r
2486 Row = OriginalRow;\r
2487\r
f4113e1f 2488 FreePool (OptionString);\r
7936fb6a 2489 }\r
4ffaadcc
ED
2490\r
2491 //\r
2492 // If Question has refresh guid, register the op-code.\r
2493 //\r
2494 if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
2495 if (gMenuEventGuidRefreshHead == NULL) {\r
2496 MenuUpdateEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2497 gMenuEventGuidRefreshHead = MenuUpdateEntry;\r
2498 } else {\r
2499 MenuUpdateEntry = gMenuEventGuidRefreshHead;\r
2500 while (MenuUpdateEntry->Next != NULL) {\r
2501 MenuUpdateEntry = MenuUpdateEntry->Next; \r
2502 }\r
2503 MenuUpdateEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2504 MenuUpdateEntry = MenuUpdateEntry->Next; \r
2505 }\r
2506 ASSERT (MenuUpdateEntry != NULL);\r
2507 Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RefreshQuestionNotify, MenuUpdateEntry, &Statement->RefreshGuid, &MenuUpdateEntry->Event);\r
2508 ASSERT (!EFI_ERROR (Status));\r
2509 MenuUpdateEntry->MenuOption = MenuOption;\r
2510 MenuUpdateEntry->Selection = Selection;\r
2511 MenuUpdateEntry->CurrentColumn = MenuOption->OptCol;\r
2512 MenuUpdateEntry->CurrentRow = MenuOption->Row;\r
2513 if (MenuOption->GrayOut) {\r
2514 MenuUpdateEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
2515 } else {\r
2516 MenuUpdateEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
2517 }\r
2518 }\r
2519 \r
2520 //\r
2521 // If Question request refresh, register the op-code\r
2522 //\r
2523 if (Statement->RefreshInterval != 0) {\r
2524 //\r
2525 // Menu will be refreshed at minimal interval of all Questions\r
2526 // which have refresh request\r
2527 //\r
2528 if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {\r
2529 MinRefreshInterval = Statement->RefreshInterval;\r
2530 }\r
2531 \r
2532 if (gMenuRefreshHead == NULL) {\r
2533 MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2534 gMenuRefreshHead = MenuRefreshEntry;\r
2535 } else {\r
2536 MenuRefreshEntry = gMenuRefreshHead;\r
2537 while (MenuRefreshEntry->Next != NULL) {\r
2538 MenuRefreshEntry = MenuRefreshEntry->Next; \r
2539 }\r
2540 MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
2541 MenuRefreshEntry = MenuRefreshEntry->Next;\r
2542 }\r
2543 ASSERT (MenuRefreshEntry != NULL); \r
2544 MenuRefreshEntry->MenuOption = MenuOption;\r
2545 MenuRefreshEntry->Selection = Selection;\r
2546 MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;\r
2547 MenuRefreshEntry->CurrentRow = MenuOption->Row;\r
2548 if (MenuOption->GrayOut) {\r
2549 MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
2550 } else { \r
2551 MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
2552 }\r
2553 }\r
2554 \r
7936fb6a 2555 //\r
2556 // If this is a text op with secondary text information\r
2557 //\r
2558 if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
2559 StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle);\r
2560\r
2561 Width = (UINT16) gOptionBlockWidth;\r
2562 OriginalRow = Row;\r
6c310dfb 2563 GlyphWidth = 1;\r
7936fb6a 2564\r
6c310dfb 2565 for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2566 if ((Temp == 0) && (Row <= BottomRow)) {\r
2567 PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
2568 }\r
2569 //\r
2570 // If there is more string to process print on the next row and increment the Skip value\r
2571 //\r
d1a54e2c 2572 if (StrLen (&StringPtr[Index]) != 0) {\r
7936fb6a 2573 if (Temp2 == 0) {\r
2574 Row++;\r
2575 //\r
2576 // Since the Number of lines for this menu entry may or may not be reflected accurately\r
2577 // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
2578 // some testing to ensure we are keeping this in-sync.\r
2579 //\r
2580 // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
2581 //\r
2582 if ((Row - OriginalRow) >= MenuOption->Skip) {\r
2583 MenuOption->Skip++;\r
2584 }\r
2585 }\r
2586 }\r
2587\r
f4113e1f 2588 FreePool (OutputString);\r
7936fb6a 2589 if (Temp2 != 0) {\r
2590 Temp2--;\r
2591 }\r
2592 }\r
2593\r
2594 Row = OriginalRow;\r
f4113e1f 2595 FreePool (StringPtr);\r
7936fb6a 2596 }\r
f0a1bf11 2597 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2598\r
2599 //\r
2600 // Need to handle the bottom of the display\r
2601 //\r
2602 if (MenuOption->Skip > 1) {\r
2603 Row += MenuOption->Skip - SkipValue;\r
2604 SkipValue = 0;\r
2605 } else {\r
2606 Row += MenuOption->Skip;\r
2607 }\r
2608\r
2609 if (Row > BottomRow) {\r
2610 if (!ValueIsScroll (FALSE, Link)) {\r
ce6d12cc 2611 DownArrow = TRUE;\r
7936fb6a 2612 }\r
2613\r
2614 Row = BottomRow + 1;\r
2615 break;\r
2616 }\r
2617 }\r
2618\r
2619 if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
ce6d12cc 2620 UpArrow = TRUE;\r
7936fb6a 2621 }\r
2622\r
ce6d12cc 2623 if (UpArrow) {\r
7936fb6a 2624 gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
2625 PrintAt (\r
2626 LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
2627 TopRow - SCROLL_ARROW_HEIGHT,\r
2628 L"%c",\r
2629 ARROW_UP\r
2630 );\r
f0a1bf11 2631 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2632 }\r
2633\r
ce6d12cc 2634 if (DownArrow) {\r
7936fb6a 2635 gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
2636 PrintAt (\r
2637 LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
2638 BottomRow + SCROLL_ARROW_HEIGHT,\r
2639 L"%c",\r
2640 ARROW_DOWN\r
2641 );\r
f0a1bf11 2642 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2643 }\r
2644\r
2645 MenuOption = NULL;\r
2646 }\r
2647 break;\r
2648\r
2649 case CfRefreshHighLight:\r
2650 //\r
2651 // MenuOption: Last menu option that need to remove hilight\r
2652 // MenuOption is set to NULL in Repaint\r
2653 // NewPos: Current menu option that need to hilight\r
2654 //\r
2655 ControlFlag = CfUpdateHelpString;\r
11232773
LG
2656 if (InitializedFlag) {\r
2657 InitializedFlag = FALSE;\r
5f4ef94a 2658 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773 2659 }\r
7936fb6a 2660\r
2661 //\r
2662 // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily\r
2663 // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.\r
2664 //\r
2665 SavedValue = Repaint;\r
2666 Repaint = FALSE;\r
2667\r
2668 if (Selection->QuestionId != 0) {\r
ce6d12cc 2669 NewPos = gMenuOption.ForwardLink;\r
7936fb6a 2670 SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2671\r
d88ca2c9
ED
2672 while ((SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId ||\r
2673 SavedMenuOption->Sequence != Selection->Sequence) &&\r
2674 NewPos->ForwardLink != &gMenuOption) {\r
7936fb6a 2675 NewPos = NewPos->ForwardLink;\r
2676 SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2677 }\r
2678 if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {\r
2679 //\r
2680 // Target Question found, find its MenuOption\r
2681 //\r
2682 Link = TopOfScreen;\r
2683\r
2684 for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {\r
2685 SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
2686 Index += SavedMenuOption->Skip;\r
5f4ef94a
ED
2687 if (Link == TopOfScreen) {\r
2688 Index -= OldSkipValue;\r
2689 }\r
7936fb6a 2690 Link = Link->ForwardLink;\r
2691 }\r
5f4ef94a
ED
2692 if (NewPos == Link) {\r
2693 SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
2694 }\r
7936fb6a 2695\r
08476b33
ED
2696 //\r
2697 // Not find the selected menu in current show page.\r
2698 // Have two case to enter this if:\r
2699 // 1. Not find the menu at current page.\r
2700 // 2. Find the menu in current page, but the menu shows at the bottom and not all info shows.\r
2701 // For case 2, has an exception: The menu can show more than one pages and now only this menu shows.\r
2702 //\r
2703 // Base on the selected menu will show at the bottom of the page,\r
2704 // select the menu which will show at the top of the page.\r
2705 //\r
2706 if (Link != NewPos || Index > BottomRow || \r
2707 (Link == NewPos && (SavedMenuOption->Row + SavedMenuOption->Skip - 1 > BottomRow) && (Link != TopOfScreen))) {\r
85aa96cd
ED
2708 //\r
2709 // Find the MenuOption which has the skip value for Date/Time opcode. \r
2710 //\r
2711 AdjustDateAndTimePosition(FALSE, &NewPos);\r
7936fb6a 2712 //\r
2713 // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page\r
2714 //\r
5f4ef94a
ED
2715 SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
2716 //\r
2717 // SavedMenuOption->Row == 0 means the menu not show yet.\r
2718 //\r
2719 if (SavedMenuOption->Row == 0) {\r
2720 UpdateOptionSkipLines (Selection, SavedMenuOption);\r
2721 }\r
08476b33
ED
2722\r
2723 //\r
2724 // Base on the selected menu will show at the bottome of next page, \r
2725 // select the menu show at the top of the next page. \r
2726 //\r
7936fb6a 2727 Link = NewPos;\r
5f4ef94a 2728 for (Index = TopRow + SavedMenuOption->Skip; Index <= BottomRow + 1; ) { \r
7936fb6a 2729 Link = Link->BackLink;\r
2730 SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
5f4ef94a
ED
2731 if (SavedMenuOption->Row == 0) {\r
2732 UpdateOptionSkipLines (Selection, SavedMenuOption);\r
2733 }\r
08476b33 2734 Index += SavedMenuOption->Skip;\r
7936fb6a 2735 }\r
08476b33
ED
2736\r
2737 //\r
2738 // Found the menu which will show at the top of the page.\r
2739 //\r
2740 if (Link == NewPos) {\r
2741 //\r
2742 // The menu can show more than one pages, just show the menu at the top of the page.\r
2743 //\r
2744 SkipValue = 0;\r
2745 TopOfScreen = Link;\r
2746 OldSkipValue = SkipValue;\r
5f4ef94a 2747 } else {\r
08476b33
ED
2748 //\r
2749 // Check whether need to skip some line for menu shows at the top of the page.\r
2750 //\r
2751 SkipValue = Index - BottomRow - 1;\r
2752 if (SkipValue > 0 && SkipValue < (INTN) SavedMenuOption->Skip) {\r
2753 TopOfScreen = Link;\r
2754 OldSkipValue = SkipValue;\r
2755 } else {\r
2756 SkipValue = 0;\r
2757 TopOfScreen = Link->ForwardLink;\r
2758 }\r
5f4ef94a 2759 }\r
7936fb6a 2760\r
2761 Repaint = TRUE;\r
2762 NewLine = TRUE;\r
2763 ControlFlag = CfRepaint;\r
2764 break;\r
2765 }\r
2766 } else {\r
2767 //\r
2768 // Target Question not found, highlight the default menu option\r
2769 //\r
2770 NewPos = TopOfScreen;\r
2771 }\r
2772\r
2773 Selection->QuestionId = 0;\r
2774 }\r
2775\r
2776 if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
2777 if (MenuOption != NULL) {\r
2778 //\r
2779 // Remove highlight on last Menu Option\r
2780 //\r
2781 gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
2782 ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
f0a1bf11 2783 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2784 if (OptionString != NULL) {\r
2785 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
2786 (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
2787 ) {\r
4a6876b7 2788 ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
7936fb6a 2789 }\r
2790\r
2791 Width = (UINT16) gOptionBlockWidth;\r
2792 OriginalRow = MenuOption->Row;\r
6c310dfb 2793 GlyphWidth = 1;\r
7936fb6a 2794\r
6c310dfb 2795 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2796 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2797 PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
2798 }\r
2799 //\r
2800 // If there is more string to process print on the next row and increment the Skip value\r
2801 //\r
d1a54e2c 2802 if (StrLen (&OptionString[Index]) != 0) {\r
7936fb6a 2803 MenuOption->Row++;\r
2804 }\r
2805\r
f4113e1f 2806 FreePool (OutputString);\r
7936fb6a 2807 }\r
2808\r
2809 MenuOption->Row = OriginalRow;\r
2810\r
f4113e1f 2811 FreePool (OptionString);\r
7936fb6a 2812 } else {\r
2813 if (NewLine) {\r
2814 if (MenuOption->GrayOut) {\r
2815 gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
2816 } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {\r
f0a1bf11 2817 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2818 }\r
2819\r
2820 OriginalRow = MenuOption->Row;\r
2821 Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);\r
6c310dfb 2822 GlyphWidth = 1;\r
7936fb6a 2823\r
6c310dfb 2824 for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2825 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2826 PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
2827 }\r
2828 //\r
2829 // If there is more string to process print on the next row and increment the Skip value\r
2830 //\r
d1a54e2c 2831 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
7936fb6a 2832 MenuOption->Row++;\r
2833 }\r
2834\r
f4113e1f 2835 FreePool (OutputString);\r
7936fb6a 2836 }\r
2837\r
2838 MenuOption->Row = OriginalRow;\r
f0a1bf11 2839 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2840 }\r
2841 }\r
2842 }\r
2843\r
2844 //\r
11232773 2845 // This is the current selected statement\r
7936fb6a 2846 //\r
2847 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
11232773
LG
2848 Statement = MenuOption->ThisTag;\r
2849 Selection->Statement = Statement;\r
7936fb6a 2850 if (!IsSelectable (MenuOption)) {\r
11232773
LG
2851 Repaint = SavedValue;\r
2852 UpdateKeyHelp (Selection, MenuOption, FALSE);\r
7936fb6a 2853 break;\r
2854 }\r
2855\r
d66e6c16 2856 //\r
2857 // Record highlight for current menu\r
2858 //\r
2859 CurrentMenu->QuestionId = Statement->QuestionId;\r
d88ca2c9 2860 CurrentMenu->Sequence = MenuOption->Sequence;\r
7936fb6a 2861\r
2862 //\r
2863 // Set reverse attribute\r
2864 //\r
f0a1bf11 2865 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));\r
7936fb6a 2866 gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
2867\r
2868 //\r
2869 // Assuming that we have a refresh linked-list created, lets annotate the\r
2870 // appropriate entry that we are highlighting with its new attribute. Just prior to this\r
2871 // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh\r
2872 //\r
2873 if (gMenuRefreshHead != NULL) {\r
2874 for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {\r
81da6ef9 2875 if (MenuRefreshEntry->MenuOption->GrayOut) {\r
1fcd34f8
ED
2876 MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
2877 } else { \r
2878 MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
2879 }\r
7936fb6a 2880 if (MenuRefreshEntry->MenuOption == MenuOption) {\r
f0a1bf11 2881 MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);\r
7936fb6a 2882 }\r
2883 }\r
2884 }\r
2885\r
2886 ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
2887 if (OptionString != NULL) {\r
2888 if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
4a6876b7 2889 ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
7936fb6a 2890 }\r
2891 Width = (UINT16) gOptionBlockWidth;\r
2892\r
2893 OriginalRow = MenuOption->Row;\r
6c310dfb 2894 GlyphWidth = 1;\r
7936fb6a 2895\r
6c310dfb 2896 for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2897 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2898 PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
2899 }\r
2900 //\r
2901 // If there is more string to process print on the next row and increment the Skip value\r
2902 //\r
d1a54e2c 2903 if (StrLen (&OptionString[Index]) != 0) {\r
7936fb6a 2904 MenuOption->Row++;\r
2905 }\r
2906\r
f4113e1f 2907 FreePool (OutputString);\r
7936fb6a 2908 }\r
2909\r
2910 MenuOption->Row = OriginalRow;\r
2911\r
f4113e1f 2912 FreePool (OptionString);\r
7936fb6a 2913 } else {\r
2914 if (NewLine) {\r
2915 OriginalRow = MenuOption->Row;\r
2916\r
2917 Width = GetWidth (Statement, MenuOption->Handle);\r
6c310dfb 2918 GlyphWidth = 1;\r
7936fb6a 2919\r
6c310dfb 2920 for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
7936fb6a 2921 if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
2922 PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
2923 }\r
2924 //\r
2925 // If there is more string to process print on the next row and increment the Skip value\r
2926 //\r
d1a54e2c 2927 if (StrLen (&MenuOption->Description[Index]) != 0) {\r
7936fb6a 2928 MenuOption->Row++;\r
2929 }\r
2930\r
f4113e1f 2931 FreePool (OutputString);\r
7936fb6a 2932 }\r
2933\r
2934 MenuOption->Row = OriginalRow;\r
2935\r
2936 }\r
2937 }\r
2938\r
8b0fc5c1 2939 UpdateKeyHelp (Selection, MenuOption, FALSE);\r
8d00a0f1 2940\r
7936fb6a 2941 //\r
2942 // Clear reverse attribute\r
2943 //\r
f0a1bf11 2944 gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
7936fb6a 2945 }\r
2946 //\r
2947 // Repaint flag will be used when process CfUpdateHelpString, so restore its value\r
2948 // if we didn't break halfway when process CfRefreshHighLight.\r
2949 //\r
2950 Repaint = SavedValue;\r
2951 break;\r
2952\r
2953 case CfUpdateHelpString:\r
2954 ControlFlag = CfPrepareToReadKey;\r
b00964a9
ED
2955 if (Selection->Form->ModalForm) {\r
2956 break;\r
2957 }\r
7936fb6a 2958\r
11232773 2959 if (Repaint || NewLine) {\r
7936fb6a 2960 //\r
2961 // Don't print anything if it is a NULL help token\r
2962 //\r
c9325700 2963 ASSERT(MenuOption != NULL);\r
11232773 2964 if (MenuOption->ThisTag->Help == 0 || !IsSelectable (MenuOption)) {\r
7936fb6a 2965 StringPtr = L"\0";\r
2966 } else {\r
2967 StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
2968 }\r
2969\r
ba46ab94
ED
2970 RowCount = BottomRow - TopRow;\r
2971 HelpPageIndex = 0;\r
2972 //\r
2973 // 1.Calculate how many line the help string need to print.\r
2974 //\r
6c310dfb
ED
2975 if (HelpString != NULL) {\r
2976 FreePool (HelpString);\r
2977 }\r
2978 HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
ba46ab94
ED
2979 if (HelpLine > RowCount) {\r
2980 MultiHelpPage = TRUE;\r
2981 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
6c310dfb
ED
2982 if (HelpHeaderString != NULL) {\r
2983 FreePool (HelpHeaderString);\r
2984 }\r
2985 HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount);\r
ba46ab94 2986 StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
6c310dfb
ED
2987 if (HelpBottomString != NULL) {\r
2988 FreePool (HelpBottomString);\r
2989 }\r
2990 HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);\r
7936fb6a 2991 //\r
ba46ab94 2992 // Calculate the help page count.\r
7936fb6a 2993 //\r
ba46ab94
ED
2994 if (HelpLine > 2 * RowCount - 2) {\r
2995 HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
2996 if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {\r
2997 HelpPageCount += 1;\r
2998 }\r
2999 } else {\r
3000 HelpPageCount = 2;\r
7936fb6a 3001 }\r
ba46ab94
ED
3002 } else {\r
3003 MultiHelpPage = FALSE;\r
3004 }\r
3005 }\r
3006\r
3007 //\r
3008 // Clean the help field first.\r
3009 //\r
3010 ClearLines (\r
3011 LocalScreen.RightColumn - gHelpBlockWidth,\r
3012 LocalScreen.RightColumn,\r
3013 TopRow,\r
3014 BottomRow,\r
3015 PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
3016 );\r
7936fb6a 3017\r
ba46ab94
ED
3018 //\r
3019 // Check whether need to show the 'More(U/u)' at the begin.\r
3020 // Base on current direct info, here shows aligned to the right side of the column.\r
3021 // If the direction is multi line and aligned to right side may have problem, so \r
3022 // add ASSERT code here.\r
3023 //\r
3024 if (HelpPageIndex > 0) {\r
6c310dfb 3025 gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
ba46ab94
ED
3026 for (Index = 0; Index < HelpHeaderLine; Index++) {\r
3027 ASSERT (HelpHeaderLine == 1);\r
3028 ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
3029 PrintStringAt (\r
3030 LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
3031 Index + TopRow,\r
6c310dfb 3032 &HelpHeaderString[Index * HeaderLineWidth]\r
ba46ab94
ED
3033 );\r
3034 }\r
3035 }\r
3036\r
3037 gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);\r
3038 //\r
3039 // Print the help string info.\r
3040 //\r
3041 if (!MultiHelpPage) {\r
5ea466a5 3042 for (Index = 0; Index < HelpLine; Index++) {\r
7936fb6a 3043 PrintStringAt (\r
3044 LocalScreen.RightColumn - gHelpBlockWidth,\r
3045 Index + TopRow,\r
6c310dfb 3046 &HelpString[Index * EachLineWidth]\r
ba46ab94
ED
3047 );\r
3048 }\r
6c310dfb 3049 gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
ba46ab94
ED
3050 } else {\r
3051 if (HelpPageIndex == 0) {\r
3052 for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
3053 PrintStringAt (\r
3054 LocalScreen.RightColumn - gHelpBlockWidth,\r
3055 Index + TopRow,\r
6c310dfb 3056 &HelpString[Index * EachLineWidth]\r
ba46ab94
ED
3057 );\r
3058 }\r
3059 } else {\r
3060 for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && \r
3061 (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
3062 PrintStringAt (\r
3063 LocalScreen.RightColumn - gHelpBlockWidth,\r
3064 Index + TopRow + HelpHeaderLine,\r
6c310dfb 3065 &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth]\r
ba46ab94
ED
3066 );\r
3067 }\r
6c310dfb
ED
3068 if (HelpPageIndex == HelpPageCount - 1) {\r
3069 gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
3070 }\r
ba46ab94
ED
3071 } \r
3072 }\r
3073\r
ba46ab94
ED
3074 //\r
3075 // Check whether need to print the 'More(D/d)' at the bottom.\r
3076 // Base on current direct info, here shows aligned to the right side of the column.\r
3077 // If the direction is multi line and aligned to right side may have problem, so \r
3078 // add ASSERT code here.\r
3079 //\r
3080 if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
6c310dfb 3081 gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
ba46ab94
ED
3082 for (Index = 0; Index < HelpBottomLine; Index++) {\r
3083 ASSERT (HelpBottomLine == 1);\r
3084 ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
3085 PrintStringAt (\r
3086 LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
3087 Index + BottomRow - HelpBottomLine,\r
6c310dfb 3088 &HelpBottomString[Index * BottomLineWidth]\r
7936fb6a 3089 );\r
3090 }\r
3091 }\r
3092 //\r
3093 // Reset this flag every time we finish using it.\r
3094 //\r
3095 Repaint = FALSE;\r
3096 NewLine = FALSE;\r
3097 break;\r
3098\r
3099 case CfPrepareToReadKey:\r
3100 ControlFlag = CfReadKey;\r
3101 ScreenOperation = UiNoOperation;\r
3102 break;\r
3103\r
3104 case CfReadKey:\r
3105 ControlFlag = CfScreenOperation;\r
3106\r
3107 //\r
3108 // Wait for user's selection\r
3109 //\r
3110 do {\r
3111 Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);\r
3112 } while (Status == EFI_TIMEOUT);\r
3113\r
8d00a0f1 3114 if (Selection->Action == UI_ACTION_REFRESH_FORMSET) {\r
7936fb6a 3115 //\r
8d00a0f1 3116 // IFR is updated in Callback of refresh opcode, re-parse it\r
7936fb6a 3117 //\r
48a9d5f7 3118 ControlFlag = CfCheckSelection;\r
8d00a0f1 3119 Selection->Statement = NULL;\r
48a9d5f7 3120 break;\r
8d00a0f1 3121 }\r
3122\r
3123 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
3124 //\r
d66e6c16 3125 // If we encounter error, continue to read another key in.\r
8d00a0f1 3126 //\r
3127 if (EFI_ERROR (Status)) {\r
3128 ControlFlag = CfReadKey;\r
3129 break;\r
7936fb6a 3130 }\r
3131\r
7936fb6a 3132 switch (Key.UnicodeChar) {\r
3133 case CHAR_CARRIAGE_RETURN:\r
febca2e3
ED
3134 if(MenuOption->GrayOut || MenuOption->ReadOnly) {\r
3135 ControlFlag = CfReadKey;\r
3136 break;\r
3137 }\r
3138\r
7936fb6a 3139 ScreenOperation = UiSelect;\r
3140 gDirection = 0;\r
3141 break;\r
3142\r
3143 //\r
3144 // We will push the adjustment of these numeric values directly to the input handler\r
3145 // NOTE: we won't handle manual input numeric\r
3146 //\r
3147 case '+':\r
3148 case '-':\r
c9325700
ED
3149 //\r
3150 // If the screen has no menu items, and the user didn't select UiReset\r
3151 // ignore the selection and go back to reading keys.\r
3152 //\r
febca2e3 3153 if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
c9325700
ED
3154 ControlFlag = CfReadKey;\r
3155 break;\r
3156 }\r
3157\r
3158 ASSERT(MenuOption != NULL);\r
7936fb6a 3159 Statement = MenuOption->ThisTag;\r
3160 if ((Statement->Operand == EFI_IFR_DATE_OP)\r
3161 || (Statement->Operand == EFI_IFR_TIME_OP)\r
3162 || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))\r
3163 ){\r
3164 if (Key.UnicodeChar == '+') {\r
3165 gDirection = SCAN_RIGHT;\r
3166 } else {\r
3167 gDirection = SCAN_LEFT;\r
3168 }\r
3169 Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
8d00a0f1 3170 if (EFI_ERROR (Status)) {\r
3171 //\r
3172 // Repaint to clear possible error prompt pop-up\r
3173 //\r
3174 Repaint = TRUE;\r
3175 NewLine = TRUE;\r
7b546f74
ED
3176 } else {\r
3177 Selection->Action = UI_ACTION_REFRESH_FORM;\r
8d00a0f1 3178 }\r
676df92c 3179 if (OptionString != NULL) {\r
3180 FreePool (OptionString);\r
3181 }\r
7936fb6a 3182 }\r
3183 break;\r
3184\r
3185 case '^':\r
3186 ScreenOperation = UiUp;\r
3187 break;\r
3188\r
3189 case 'V':\r
3190 case 'v':\r
3191 ScreenOperation = UiDown;\r
3192 break;\r
3193\r
3194 case ' ':\r
40245175 3195 if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
c9325700
ED
3196 //\r
3197 // If the screen has no menu items, and the user didn't select UiReset\r
3198 // ignore the selection and go back to reading keys.\r
3199 //\r
3200 if(IsListEmpty (&gMenuOption)) {\r
3201 ControlFlag = CfReadKey;\r
3202 break;\r
3203 }\r
3204 \r
3205 ASSERT(MenuOption != NULL);\r
febca2e3 3206 if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {\r
7936fb6a 3207 ScreenOperation = UiSelect;\r
3208 }\r
3209 }\r
3210 break;\r
3211\r
ba46ab94
ED
3212 case 'D':\r
3213 case 'd':\r
3214 if (!MultiHelpPage) {\r
3215 ControlFlag = CfReadKey;\r
3216 break;\r
3217 }\r
3218 ControlFlag = CfUpdateHelpString;\r
3219 HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;\r
3220 break;\r
3221\r
3222 case 'U':\r
3223 case 'u':\r
3224 if (!MultiHelpPage) {\r
3225 ControlFlag = CfReadKey;\r
3226 break;\r
3227 }\r
3228 ControlFlag = CfUpdateHelpString;\r
3229 HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;\r
3230 break;\r
3231\r
7936fb6a 3232 case CHAR_NULL:\r
48a9d5f7
LG
3233 for (Index = 0; Index < mScanCodeNumber; Index++) {\r
3234 if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
3235 ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
3236 break;\r
3237 }\r
3238 }\r
3239 \r
3240 if (Selection->Form->ModalForm && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {\r
7936fb6a 3241 //\r
48a9d5f7 3242 // ModalForm has no ESC key and Hot Key.\r
7936fb6a 3243 //\r
48a9d5f7
LG
3244 ControlFlag = CfReadKey;\r
3245 } else if (Index == mScanCodeNumber) {\r
3246 //\r
3247 // Check whether Key matches the registered hot key.\r
3248 //\r
3249 HotKey = NULL;\r
3250 if ((gBrowserSettingScope == SystemLevel) || (gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
3251 HotKey = GetHotKeyFromRegisterList (&Key);\r
3252 }\r
3253 if (HotKey != NULL) {\r
3254 ScreenOperation = UiHotKey;\r
7936fb6a 3255 }\r
3256 }\r
3257 break;\r
3258 }\r
3259 break;\r
3260\r
3261 case CfScreenOperation:\r
d66e6c16 3262 if (ScreenOperation != UiReset) {\r
7936fb6a 3263 //\r
d66e6c16 3264 // If the screen has no menu items, and the user didn't select UiReset\r
7936fb6a 3265 // ignore the selection and go back to reading keys.\r
3266 //\r
ce6d12cc 3267 if (IsListEmpty (&gMenuOption)) {\r
7936fb6a 3268 ControlFlag = CfReadKey;\r
3269 break;\r
3270 }\r
7936fb6a 3271 }\r
3272\r
3273 for (Index = 0;\r
3274 Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);\r
3275 Index++\r
3276 ) {\r
3277 if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
3278 ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
3279 break;\r
3280 }\r
3281 }\r
3282 break;\r
3283\r
7936fb6a 3284 case CfUiSelect:\r
3285 ControlFlag = CfCheckSelection;\r
3286\r
c9325700 3287 ASSERT(MenuOption != NULL);\r
7936fb6a 3288 Statement = MenuOption->ThisTag;\r
e24adb18 3289 if (Statement->Operand == EFI_IFR_TEXT_OP) {\r
7936fb6a 3290 break;\r
3291 }\r
3292\r
3293 //\r
3294 // Keep highlight on current MenuOption\r
3295 //\r
3296 Selection->QuestionId = Statement->QuestionId;\r
3297\r
3298 switch (Statement->Operand) {\r
3299 case EFI_IFR_REF_OP:\r
8ca6180f 3300 ProcessGotoOpCode(Statement, Selection, &Repaint, &NewLine);\r
7936fb6a 3301 break;\r
3302\r
3303 case EFI_IFR_ACTION_OP:\r
3304 //\r
3305 // Process the Config string <ConfigResp>\r
3306 //\r
3307 Status = ProcessQuestionConfig (Selection, Statement);\r
3308\r
3309 if (EFI_ERROR (Status)) {\r
3310 break;\r
3311 }\r
3312\r
3313 //\r
3314 // The action button may change some Question value, so refresh the form\r
3315 //\r
3316 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3317 break;\r
3318\r
3319 case EFI_IFR_RESET_BUTTON_OP:\r
3320 //\r
3321 // Reset Question to default value specified by DefaultId\r
3322 //\r
3323 ControlFlag = CfUiDefault;\r
3324 DefaultId = Statement->DefaultId;\r
3325 break;\r
3326\r
3327 default:\r
3328 //\r
3329 // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
3330 //\r
8b0fc5c1 3331 UpdateKeyHelp (Selection, MenuOption, TRUE);\r
7936fb6a 3332 Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
3333\r
3334 if (EFI_ERROR (Status)) {\r
3335 Repaint = TRUE;\r
3336 NewLine = TRUE;\r
8b0fc5c1 3337 UpdateKeyHelp (Selection, MenuOption, FALSE);\r
3338 } else {\r
3339 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3340 }\r
7936fb6a 3341\r
0c66bc76
LG
3342 if (OptionString != NULL) {\r
3343 FreePool (OptionString);\r
3344 }\r
7936fb6a 3345 break;\r
3346 }\r
3347 break;\r
3348\r
3349 case CfUiReset:\r
3350 //\r
d66e6c16 3351 // We come here when someone press ESC\r
7936fb6a 3352 //\r
3353 ControlFlag = CfCheckSelection;\r
48a9d5f7 3354 FindNextMenu (Selection, &Repaint, &NewLine);\r
b18e7050 3355 break;\r
7936fb6a 3356\r
3357 case CfUiLeft:\r
3358 ControlFlag = CfCheckSelection;\r
c9325700 3359 ASSERT(MenuOption != NULL);\r
7936fb6a 3360 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
3361 if (MenuOption->Sequence != 0) {\r
3362 //\r
3363 // In the middle or tail of the Date/Time op-code set, go left.\r
3364 //\r
c9325700 3365 ASSERT(NewPos != NULL);\r
7936fb6a 3366 NewPos = NewPos->BackLink;\r
3367 }\r
3368 }\r
3369 break;\r
3370\r
3371 case CfUiRight:\r
3372 ControlFlag = CfCheckSelection;\r
c9325700 3373 ASSERT(MenuOption != NULL);\r
7936fb6a 3374 if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
3375 if (MenuOption->Sequence != 2) {\r
3376 //\r
3377 // In the middle or tail of the Date/Time op-code set, go left.\r
3378 //\r
c9325700 3379 ASSERT(NewPos != NULL);\r
7936fb6a 3380 NewPos = NewPos->ForwardLink;\r
3381 }\r
3382 }\r
3383 break;\r
3384\r
3385 case CfUiUp:\r
3386 ControlFlag = CfCheckSelection;\r
3387\r
11232773 3388 SavedListEntry = NewPos;\r
7936fb6a 3389\r
c9325700 3390 ASSERT(NewPos != NULL);\r
11232773
LG
3391 //\r
3392 // Adjust Date/Time position before we advance forward.\r
3393 //\r
3394 AdjustDateAndTimePosition (TRUE, &NewPos);\r
ce6d12cc 3395 if (NewPos->BackLink != &gMenuOption) {\r
11232773 3396 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
715cf6dd 3397 ASSERT (MenuOption != NULL);\r
11232773
LG
3398 NewLine = TRUE;\r
3399 NewPos = NewPos->BackLink;\r
7936fb6a 3400\r
3401 PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
5f4ef94a
ED
3402 if (PreviousMenuOption->Row == 0) {\r
3403 UpdateOptionSkipLines (Selection, PreviousMenuOption);\r
3404 }\r
7936fb6a 3405 DistanceValue = PreviousMenuOption->Skip;\r
11232773
LG
3406 Difference = 0;\r
3407 if (MenuOption->Row >= DistanceValue + TopRow) {\r
5f4ef94a 3408 Difference = MoveToNextStatement (Selection, TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);\r
11232773
LG
3409 }\r
3410 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3411 \r
7936fb6a 3412 if (Difference < 0) {\r
3413 //\r
11232773
LG
3414 // We hit the begining MenuOption that can be focused\r
3415 // so we simply scroll to the top.\r
7936fb6a 3416 //\r
11232773 3417 if (TopOfScreen != gMenuOption.ForwardLink) {\r
ce6d12cc 3418 TopOfScreen = gMenuOption.ForwardLink;\r
7936fb6a 3419 Repaint = TRUE;\r
11232773
LG
3420 } else {\r
3421 //\r
3422 // Scroll up to the last page when we have arrived at top page.\r
3423 //\r
3424 NewPos = &gMenuOption;\r
3425 TopOfScreen = &gMenuOption;\r
3426 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3427 ScreenOperation = UiPageUp;\r
3428 ControlFlag = CfScreenOperation;\r
3429 break;\r
7936fb6a 3430 }\r
11232773 3431 } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {\r
1a788cdd
LG
3432 //\r
3433 // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
3434 //\r
3435 TopOfScreen = NewPos;\r
3436 Repaint = TRUE;\r
3437 SkipValue = 0;\r
3438 OldSkipValue = 0;\r
11232773
LG
3439 } else if (!IsSelectable (NextMenuOption)) {\r
3440 //\r
3441 // Continue to go up until scroll to next page or the selectable option is found.\r
3442 //\r
3443 ScreenOperation = UiUp;\r
3444 ControlFlag = CfScreenOperation;\r
7936fb6a 3445 }\r
3446\r
3447 //\r
3448 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3449 //\r
3450 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
11232773
LG
3451 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3452 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
b18e7050 3453 UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
7936fb6a 3454 } else {\r
11232773
LG
3455 //\r
3456 // Scroll up to the last page.\r
3457 //\r
3458 NewPos = &gMenuOption;\r
3459 TopOfScreen = &gMenuOption;\r
3460 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3461 ScreenOperation = UiPageUp;\r
3462 ControlFlag = CfScreenOperation;\r
7936fb6a 3463 }\r
3464 break;\r
3465\r
3466 case CfUiPageUp:\r
3467 ControlFlag = CfCheckSelection;\r
3468\r
c9325700 3469 ASSERT(NewPos != NULL);\r
ce6d12cc 3470 if (NewPos->BackLink == &gMenuOption) {\r
7936fb6a 3471 NewLine = FALSE;\r
3472 Repaint = FALSE;\r
3473 break;\r
3474 }\r
3475\r
3476 NewLine = TRUE;\r
3477 Repaint = TRUE;\r
3478 Link = TopOfScreen;\r
11232773 3479 Index = BottomRow;\r
ce6d12cc 3480 while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) {\r
7936fb6a 3481 Link = Link->BackLink;\r
3482 PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
5f4ef94a
ED
3483 if (PreviousMenuOption->Row == 0) {\r
3484 UpdateOptionSkipLines (Selection, PreviousMenuOption);\r
3485 } \r
11232773
LG
3486 if (Index < PreviousMenuOption->Skip) {\r
3487 Index = 0;\r
3488 break;\r
3489 }\r
3490 Index = Index - PreviousMenuOption->Skip;\r
7936fb6a 3491 }\r
11232773
LG
3492 \r
3493 if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
3494 if (TopOfScreen == &gMenuOption) {\r
3495 TopOfScreen = gMenuOption.ForwardLink;\r
3496 NewPos = gMenuOption.BackLink;\r
5f4ef94a 3497 MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3498 Repaint = FALSE;\r
3499 } else if (TopOfScreen != Link) {\r
3500 TopOfScreen = Link;\r
3501 NewPos = Link;\r
5f4ef94a 3502 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3503 } else {\r
3504 //\r
3505 // Finally we know that NewPos is the last MenuOption can be focused.\r
3506 //\r
3507 Repaint = FALSE;\r
3508 NewPos = Link;\r
5f4ef94a 3509 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3510 }\r
3511 } else {\r
3512 if (Index + 1 < TopRow) {\r
3513 //\r
3514 // Back up the previous option.\r
3515 //\r
3516 Link = Link->ForwardLink;\r
3517 }\r
7936fb6a 3518\r
7936fb6a 3519 //\r
11232773 3520 // Move to the option in Next page.\r
7936fb6a 3521 //\r
11232773
LG
3522 if (TopOfScreen == &gMenuOption) {\r
3523 NewPos = gMenuOption.BackLink;\r
5f4ef94a 3524 MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3525 } else {\r
3526 NewPos = Link;\r
5f4ef94a 3527 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3528 }\r
3529\r
7936fb6a 3530 //\r
11232773 3531 // There are more MenuOption needing scrolling up.\r
7936fb6a 3532 //\r
11232773
LG
3533 TopOfScreen = Link;\r
3534 MenuOption = NULL;\r
7936fb6a 3535 }\r
3536\r
3537 //\r
3538 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3539 // Don't do this when we are already in the first page.\r
3540 //\r
3541 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3542 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3543 break;\r
3544\r
3545 case CfUiPageDown:\r
3546 ControlFlag = CfCheckSelection;\r
3547\r
cd7bfc2c 3548 ASSERT (NewPos != NULL);\r
ce6d12cc 3549 if (NewPos->ForwardLink == &gMenuOption) {\r
7936fb6a 3550 NewLine = FALSE;\r
3551 Repaint = FALSE;\r
3552 break;\r
3553 }\r
3554\r
3555 NewLine = TRUE;\r
3556 Repaint = TRUE;\r
3557 Link = TopOfScreen;\r
3558 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3559 Index = TopRow;\r
ce6d12cc 3560 while ((Index <= BottomRow) && (Link->ForwardLink != &gMenuOption)) {\r
7936fb6a 3561 Index = Index + NextMenuOption->Skip;\r
3562 Link = Link->ForwardLink;\r
3563 NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
3564 }\r
3565\r
11232773
LG
3566 if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow)) {\r
3567 //\r
3568 // Finally we know that NewPos is the last MenuOption can be focused.\r
3569 //\r
3570 Repaint = FALSE;\r
5f4ef94a 3571 MoveToNextStatement (Selection, TRUE, &Link, Index - TopRow);\r
11232773
LG
3572 } else {\r
3573 if (Index - 1 > BottomRow) {\r
3574 //\r
3575 // Back up the previous option.\r
3576 //\r
3577 Link = Link->BackLink;\r
3578 }\r
7936fb6a 3579 //\r
11232773 3580 // There are more MenuOption needing scrolling down.\r
7936fb6a 3581 //\r
3582 TopOfScreen = Link;\r
3583 MenuOption = NULL;\r
7936fb6a 3584 //\r
11232773 3585 // Move to the option in Next page.\r
7936fb6a 3586 //\r
5f4ef94a 3587 MoveToNextStatement (Selection, FALSE, &Link, BottomRow - TopRow);\r
7936fb6a 3588 }\r
3589\r
3590 //\r
3591 // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
3592 // Don't do this when we are already in the last page.\r
3593 //\r
11232773 3594 NewPos = Link;\r
7936fb6a 3595 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3596 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3597 break;\r
3598\r
3599 case CfUiDown:\r
3600 ControlFlag = CfCheckSelection;\r
3601 //\r
3602 // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
3603 // to be one that progresses to the next set of op-codes, we need to advance to the last\r
3604 // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
3605 // checking can be done. The only other logic we need to introduce is that if a Date/Time\r
3606 // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
3607 // the Date/Time op-code.\r
3608 //\r
3609 SavedListEntry = NewPos;\r
11232773 3610 AdjustDateAndTimePosition (FALSE, &NewPos);\r
7936fb6a 3611\r
ce6d12cc 3612 if (NewPos->ForwardLink != &gMenuOption) {\r
7936fb6a 3613 MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3614 NewLine = TRUE;\r
3615 NewPos = NewPos->ForwardLink;\r
7936fb6a 3616\r
11232773
LG
3617 Difference = 0;\r
3618 if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
5f4ef94a 3619 Difference = MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
11232773
LG
3620 //\r
3621 // We hit the end of MenuOption that can be focused\r
3622 // so we simply scroll to the first page.\r
3623 //\r
3624 if (Difference < 0) {\r
3625 //\r
3626 // Scroll to the first page.\r
3627 //\r
3628 if (TopOfScreen != gMenuOption.ForwardLink) {\r
3629 TopOfScreen = gMenuOption.ForwardLink;\r
3630 Repaint = TRUE;\r
3631 MenuOption = NULL;\r
3632 } else {\r
3633 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3634 }\r
3635 NewPos = gMenuOption.ForwardLink;\r
5f4ef94a 3636 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
11232773
LG
3637 \r
3638 //\r
3639 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3640 //\r
3641 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3642 AdjustDateAndTimePosition (TRUE, &NewPos);\r
3643 break;\r
3644 }\r
3645 }\r
1a788cdd
LG
3646 NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
3647\r
7936fb6a 3648 //\r
3649 // An option might be multi-line, so we need to reflect that data in the overall skip value\r
3650 //\r
5f4ef94a 3651 UpdateOptionSkipLines (Selection, NextMenuOption);\r
11232773 3652 DistanceValue = Difference + NextMenuOption->Skip;\r
7936fb6a 3653\r
3654 Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
3655 if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
3656 (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||\r
3657 NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
3658 ) {\r
3659 Temp ++;\r
3660 }\r
3661\r
3662 //\r
3663 // If we are going to scroll, update TopOfScreen\r
3664 //\r
3665 if (Temp > BottomRow) {\r
3666 do {\r
3667 //\r
3668 // Is the current top of screen a zero-advance op-code?\r
3669 // If so, keep moving forward till we hit a >0 advance op-code\r
3670 //\r
3671 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
3672\r
3673 //\r
3674 // If bottom op-code is more than one line or top op-code is more than one line\r
3675 //\r
3676 if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {\r
3677 //\r
3678 // Is the bottom op-code greater than or equal in size to the top op-code?\r
3679 //\r
3680 if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {\r
3681 //\r
3682 // Skip the top op-code\r
3683 //\r
3684 TopOfScreen = TopOfScreen->ForwardLink;\r
3685 Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);\r
3686\r
3687 OldSkipValue = Difference;\r
3688\r
3689 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
3690\r
3691 //\r
3692 // If we have a remainder, skip that many more op-codes until we drain the remainder\r
3693 //\r
1a788cdd 3694 while (Difference >= (INTN) SavedMenuOption->Skip) {\r
7936fb6a 3695 //\r
3696 // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
3697 //\r
1a788cdd 3698 Difference = Difference - (INTN) SavedMenuOption->Skip;\r
7936fb6a 3699 TopOfScreen = TopOfScreen->ForwardLink;\r
3700 SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
7936fb6a 3701 }\r
3702 //\r
3703 // Since we will act on this op-code in the next routine, and increment the\r
3704 // SkipValue, set the skips to one less than what is required.\r
3705 //\r
3706 SkipValue = Difference - 1;\r
3707\r
3708 } else {\r
3709 //\r
3710 // Since we will act on this op-code in the next routine, and increment the\r
3711 // SkipValue, set the skips to one less than what is required.\r
3712 //\r
3713 SkipValue = OldSkipValue + (Temp - BottomRow) - 1;\r
3714 }\r
3715 } else {\r
3716 if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
3717 TopOfScreen = TopOfScreen->ForwardLink;\r
3718 break;\r
3719 } else {\r
3720 SkipValue = OldSkipValue;\r
3721 }\r
3722 }\r
3723 //\r
3724 // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
3725 // Let's set a skip flag to smoothly scroll the top of the screen.\r
3726 //\r
3727 if (SavedMenuOption->Skip > 1) {\r
3728 if (SavedMenuOption == NextMenuOption) {\r
3729 SkipValue = 0;\r
3730 } else {\r
3731 SkipValue++;\r
3732 }\r
1a788cdd
LG
3733 } else if (SavedMenuOption->Skip == 1) {\r
3734 SkipValue = 0;\r
7936fb6a 3735 } else {\r
3736 SkipValue = 0;\r
3737 TopOfScreen = TopOfScreen->ForwardLink;\r
3738 }\r
3739 } while (SavedMenuOption->Skip == 0);\r
3740\r
3741 Repaint = TRUE;\r
3742 OldSkipValue = SkipValue;\r
11232773
LG
3743 } else if (!IsSelectable (NextMenuOption)) {\r
3744 //\r
3745 // Continue to go down until scroll to next page or the selectable option is found.\r
3746 //\r
3747 ScreenOperation = UiDown;\r
3748 ControlFlag = CfScreenOperation;\r
7936fb6a 3749 }\r
3750\r
3751 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3752\r
b18e7050 3753 UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
7936fb6a 3754\r
3755 } else {\r
7936fb6a 3756 //\r
11232773 3757 // Scroll to the first page.\r
7936fb6a 3758 //\r
11232773
LG
3759 if (TopOfScreen != gMenuOption.ForwardLink) {\r
3760 TopOfScreen = gMenuOption.ForwardLink;\r
3761 Repaint = TRUE;\r
3762 MenuOption = NULL;\r
3763 } else {\r
3764 MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
3765 }\r
3766 NewLine = TRUE;\r
3767 NewPos = gMenuOption.ForwardLink;\r
5f4ef94a 3768 MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
7936fb6a 3769 }\r
11232773
LG
3770\r
3771 //\r
3772 // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
3773 //\r
3774 AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
3775 AdjustDateAndTimePosition (TRUE, &NewPos);\r
7936fb6a 3776 break;\r
3777\r
48a9d5f7 3778 case CfUiHotKey:\r
7936fb6a 3779 ControlFlag = CfCheckSelection;\r
48a9d5f7
LG
3780 \r
3781 Status = EFI_SUCCESS;\r
7936fb6a 3782 //\r
48a9d5f7 3783 // Discard changes. After it, no NV flag is showed.\r
7936fb6a 3784 //\r
48a9d5f7
LG
3785 if ((HotKey->Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
3786 Status = DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
3787 if (!EFI_ERROR (Status)) {\r
3788 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3789 Selection->Statement = NULL;\r
3790 gResetRequired = FALSE;\r
3791 } else {\r
3792 do {\r
3793 CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDiscardFailed, gPressEnter, gEmptyString);\r
3794 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3795 //\r
3796 // Still show current page.\r
3797 //\r
3798 Selection->Action = UI_ACTION_NONE;\r
3799 Repaint = TRUE;\r
3800 NewLine = TRUE;\r
3801 break;\r
3802 }\r
3803 }\r
7936fb6a 3804\r
48a9d5f7
LG
3805 //\r
3806 // Reterieve default setting. After it. NV flag will be showed.\r
3807 //\r
3808 if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
09cdd7d2 3809 Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL);\r
48a9d5f7
LG
3810 if (!EFI_ERROR (Status)) {\r
3811 Selection->Action = UI_ACTION_REFRESH_FORM;\r
3812 Selection->Statement = NULL;\r
3813 gResetRequired = TRUE;\r
3814 } else {\r
3815 do {\r
3816 CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDefaultFailed, gPressEnter, gEmptyString);\r
3817 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3818 //\r
3819 // Still show current page.\r
3820 //\r
3821 Selection->Action = UI_ACTION_NONE;\r
3822 Repaint = TRUE;\r
3823 NewLine = TRUE;\r
3824 break;\r
3825 }\r
3826 }\r
7936fb6a 3827\r
48a9d5f7
LG
3828 //\r
3829 // Save changes. After it, no NV flag is showed.\r
3830 //\r
3831 if ((HotKey->Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
3832 Status = SubmitForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
3833 if (!EFI_ERROR (Status)) {\r
3834 ASSERT(MenuOption != NULL);\r
3835 UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
3836 UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
3837 } else {\r
3838 do {\r
3839 CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gSaveFailed, gPressEnter, gEmptyString);\r
3840 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
3841 //\r
3842 // Still show current page.\r
3843 //\r
3844 Selection->Action = UI_ACTION_NONE;\r
3845 Repaint = TRUE;\r
3846 NewLine = TRUE;\r
3847 break;\r
3848 }\r
3849 }\r
3850 \r
3851 //\r
3852 // Set Reset required Flag\r
3853 //\r
3854 if ((HotKey->Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
3855 gResetRequired = TRUE;\r
3856 }\r
3857 \r
3858 //\r
3859 // Exit Action\r
3860 //\r
3861 if ((HotKey->Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
3862 //\r
3863 // Form Exit without saving, Similar to ESC Key.\r
3864 // FormSet Exit without saving, Exit SendForm.\r
3865 // System Exit without saving, CallExitHandler and Exit SendForm.\r
3866 //\r
3867 DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
3868 if (gBrowserSettingScope == FormLevel) {\r
3869 ControlFlag = CfUiReset;\r
3870 } else if (gBrowserSettingScope == FormSetLevel) {\r
3871 Selection->Action = UI_ACTION_EXIT;\r
3872 } else if (gBrowserSettingScope == SystemLevel) {\r
3873 if (ExitHandlerFunction != NULL) {\r
3874 ExitHandlerFunction ();\r
3875 }\r
3876 Selection->Action = UI_ACTION_EXIT;\r
3877 }\r
3878 Selection->Statement = NULL;\r
7936fb6a 3879 }\r
3880 break;\r
3881\r
3882 case CfUiDefault:\r
3883 ControlFlag = CfCheckSelection;\r
4f33c838 3884 //\r
48a9d5f7 3885 // Reset to default value for all forms in the whole system.\r
4f33c838 3886 //\r
09cdd7d2 3887 Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel, GetDefaultForAll, NULL);\r
7936fb6a 3888\r
3889 if (!EFI_ERROR (Status)) {\r
3890 Selection->Action = UI_ACTION_REFRESH_FORM;\r
ebe43565 3891 Selection->Statement = NULL;\r
15713670 3892 gResetRequired = TRUE;\r
7936fb6a 3893 }\r
3894 break;\r
3895\r
3896 case CfUiNoOperation:\r
3897 ControlFlag = CfCheckSelection;\r
3898 break;\r
3899\r
3900 case CfExit:\r
3901 UiFreeRefreshList ();\r
3902\r
3903 gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
3904 gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);\r
3905 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
3906 gST->ConOut->OutputString (gST->ConOut, L"\n");\r
6c310dfb
ED
3907 if (HelpString != NULL) {\r
3908 FreePool (HelpString);\r
3909 }\r
3910 if (HelpHeaderString != NULL) {\r
3911 FreePool (HelpHeaderString);\r
3912 }\r
3913 if (HelpBottomString != NULL) {\r
3914 FreePool (HelpBottomString);\r
3915 }\r
7936fb6a 3916\r
3917 return EFI_SUCCESS;\r
3918\r
3919 default:\r
3920 break;\r
3921 }\r
3922 }\r
3923}\r