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