]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
MdeModulePkg:Refine the function comments
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / ProcessOptions.c
CommitLineData
7c6c064c
ED
1/** @file\r
2Implementation for handling the User Interface option processing.\r
3\r
4\r
cc63add8 5Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
7c6c064c
ED
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "FormDisplay.h"\r
17\r
1c0d306f
ED
18#define MAX_TIME_OUT_LEN 0x10\r
19\r
7c6c064c
ED
20/**\r
21 Concatenate a narrow string to another string.\r
22\r
23 @param Destination The destination string.\r
01a9598e 24 @param DestMax The Max length of destination string.\r
7c6c064c
ED
25 @param Source The source string. The string to be concatenated.\r
26 to the end of Destination.\r
27\r
28**/\r
29VOID\r
30NewStrCat (\r
31 IN OUT CHAR16 *Destination,\r
5ad66ec6 32 IN UINTN DestMax,\r
7c6c064c
ED
33 IN CHAR16 *Source\r
34 )\r
35{\r
36 UINTN Length;\r
37\r
38 for (Length = 0; Destination[Length] != 0; Length++)\r
39 ;\r
40\r
41 //\r
42 // We now have the length of the original string\r
43 // We can safely assume for now that we are concatenating a narrow value to this string.\r
44 // For instance, the string is "XYZ" and cat'ing ">"\r
45 // If this assumption changes, we need to make this routine a bit more complex\r
46 //\r
47 Destination[Length] = NARROW_CHAR;\r
48 Length++;\r
49\r
5ad66ec6 50 StrCpyS (Destination + Length, DestMax - Length, Source);\r
7c6c064c
ED
51}\r
52\r
d63a9eb4
ED
53/**\r
54 Get UINT64 type value.\r
55\r
56 @param Value Input Hii value.\r
57\r
58 @retval UINT64 Return the UINT64 type value.\r
59\r
60**/\r
61UINT64\r
62HiiValueToUINT64 (\r
63 IN EFI_HII_VALUE *Value\r
64 )\r
65{\r
66 UINT64 RetVal;\r
67\r
68 RetVal = 0;\r
69\r
70 switch (Value->Type) {\r
71 case EFI_IFR_TYPE_NUM_SIZE_8:\r
72 RetVal = Value->Value.u8;\r
73 break;\r
74\r
75 case EFI_IFR_TYPE_NUM_SIZE_16:\r
76 RetVal = Value->Value.u16;\r
77 break;\r
78\r
79 case EFI_IFR_TYPE_NUM_SIZE_32:\r
80 RetVal = Value->Value.u32;\r
81 break;\r
82\r
83 case EFI_IFR_TYPE_BOOLEAN:\r
84 RetVal = Value->Value.b;\r
85 break;\r
86\r
87 case EFI_IFR_TYPE_DATE:\r
88 RetVal = *(UINT64*) &Value->Value.date;\r
89 break;\r
90\r
91 case EFI_IFR_TYPE_TIME:\r
92 RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;\r
93 break;\r
94\r
95 default:\r
96 RetVal = Value->Value.u64;\r
97 break;\r
98 }\r
99\r
100 return RetVal;\r
101}\r
102\r
40578d09
ED
103/**\r
104 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
105 \r
106 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
107 EFI_IFR_TYPE_BUFFER when do the value compare.\r
108\r
109 @param Value Expression value to compare on.\r
110\r
111 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
112 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
113\r
114**/\r
115BOOLEAN\r
116IsTypeInBuffer (\r
117 IN EFI_HII_VALUE *Value\r
118 )\r
119{\r
120 switch (Value->Type) {\r
121 case EFI_IFR_TYPE_BUFFER:\r
122 case EFI_IFR_TYPE_DATE:\r
123 case EFI_IFR_TYPE_TIME:\r
124 case EFI_IFR_TYPE_REF:\r
125 return TRUE;\r
126\r
127 default:\r
128 return FALSE;\r
129 }\r
130}\r
131\r
132/**\r
133 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
134\r
135 @param Value Expression value to compare on.\r
136\r
137 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
138 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
139\r
140**/\r
141BOOLEAN\r
142IsTypeInUINT64 (\r
143 IN EFI_HII_VALUE *Value\r
144 )\r
145{\r
146 switch (Value->Type) {\r
147 case EFI_IFR_TYPE_NUM_SIZE_8:\r
148 case EFI_IFR_TYPE_NUM_SIZE_16:\r
149 case EFI_IFR_TYPE_NUM_SIZE_32:\r
150 case EFI_IFR_TYPE_NUM_SIZE_64:\r
151 case EFI_IFR_TYPE_BOOLEAN:\r
152 return TRUE;\r
153\r
154 default:\r
155 return FALSE;\r
156 }\r
157}\r
158\r
159/**\r
160 Return the buffer length and buffer pointer for this value.\r
161 \r
162 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
163 EFI_IFR_TYPE_BUFFER when do the value compare.\r
164\r
165 @param Value Expression value to compare on.\r
166 @param Buf Return the buffer pointer.\r
167 @param BufLen Return the buffer length.\r
168\r
169**/\r
170VOID\r
171GetBufAndLenForValue (\r
172 IN EFI_HII_VALUE *Value,\r
173 OUT UINT8 **Buf,\r
174 OUT UINT16 *BufLen\r
175 )\r
176{\r
177 switch (Value->Type) {\r
178 case EFI_IFR_TYPE_BUFFER:\r
179 *Buf = Value->Buffer;\r
180 *BufLen = Value->BufferLen;\r
181 break;\r
182\r
183 case EFI_IFR_TYPE_DATE:\r
184 *Buf = (UINT8 *) (&Value->Value.date);\r
185 *BufLen = (UINT16) sizeof (EFI_HII_DATE);\r
186 break;\r
187\r
188 case EFI_IFR_TYPE_TIME:\r
189 *Buf = (UINT8 *) (&Value->Value.time);\r
190 *BufLen = (UINT16) sizeof (EFI_HII_TIME);\r
191 break;\r
192\r
193 case EFI_IFR_TYPE_REF:\r
194 *Buf = (UINT8 *) (&Value->Value.ref);\r
195 *BufLen = (UINT16) sizeof (EFI_HII_REF);\r
196 break;\r
197\r
198 default:\r
199 *Buf = NULL;\r
200 *BufLen = 0;\r
201 }\r
202}\r
203\r
7c6c064c
ED
204/**\r
205 Compare two Hii value.\r
206\r
207 @param Value1 Expression value to compare on left-hand.\r
208 @param Value2 Expression value to compare on right-hand.\r
209 @param Result Return value after compare.\r
210 retval 0 Two operators equal.\r
211 return Positive value if Value1 is greater than Value2.\r
212 retval Negative value if Value1 is less than Value2.\r
213 @param HiiHandle Only required for string compare.\r
214\r
215 @retval other Could not perform compare on two values.\r
216 @retval EFI_SUCCESS Compare the value success.\r
217\r
218**/\r
219EFI_STATUS\r
220CompareHiiValue (\r
221 IN EFI_HII_VALUE *Value1,\r
222 IN EFI_HII_VALUE *Value2,\r
223 OUT INTN *Result,\r
224 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
225 )\r
226{\r
227 INT64 Temp64;\r
228 CHAR16 *Str1;\r
229 CHAR16 *Str2;\r
230 UINTN Len;\r
40578d09
ED
231 UINT8 *Buf1;\r
232 UINT16 Buf1Len;\r
233 UINT8 *Buf2;\r
234 UINT16 Buf2Len;\r
7c6c064c 235\r
40578d09 236 if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {\r
7c6c064c
ED
237 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
238 //\r
239 // StringId 0 is reserved\r
240 //\r
241 return EFI_INVALID_PARAMETER;\r
242 }\r
243\r
244 if (Value1->Value.string == Value2->Value.string) {\r
245 *Result = 0;\r
246 return EFI_SUCCESS;\r
247 }\r
248\r
249 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
250 if (Str1 == NULL) {\r
251 //\r
252 // String not found\r
253 //\r
254 return EFI_NOT_FOUND;\r
255 }\r
256\r
257 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
258 if (Str2 == NULL) {\r
259 FreePool (Str1);\r
260 return EFI_NOT_FOUND;\r
261 }\r
262\r
263 *Result = StrCmp (Str1, Str2);\r
264\r
265 FreePool (Str1);\r
266 FreePool (Str2);\r
267\r
268 return EFI_SUCCESS;\r
269 }\r
270\r
40578d09
ED
271 //\r
272 // Take types(date, time, ref, buffer) as buffer\r
273 //\r
274 if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {\r
275 GetBufAndLenForValue(Value1, &Buf1, &Buf1Len);\r
276 GetBufAndLenForValue(Value2, &Buf2, &Buf2Len);\r
277\r
278 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
279 *Result = CompareMem (Buf1, Buf2, Len);\r
280 if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
7c6c064c
ED
281 //\r
282 // In this case, means base on samll number buffer, the data is same\r
283 // So which value has more data, which value is bigger.\r
284 //\r
40578d09 285 *Result = Buf1Len > Buf2Len ? 1 : -1;\r
7c6c064c
ED
286 }\r
287 return EFI_SUCCESS;\r
288 } \r
289\r
290 //\r
291 // Take remain types(integer, boolean, date/time) as integer\r
292 //\r
40578d09
ED
293 if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {\r
294 Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);\r
295 if (Temp64 > 0) {\r
296 *Result = 1;\r
297 } else if (Temp64 < 0) {\r
298 *Result = -1;\r
299 } else {\r
300 *Result = 0;\r
301 }\r
302 return EFI_SUCCESS;\r
7c6c064c
ED
303 }\r
304\r
40578d09 305 return EFI_UNSUPPORTED;\r
7c6c064c
ED
306}\r
307\r
308/**\r
309 Search an Option of a Question by its value.\r
310\r
311 @param Question The Question\r
312 @param OptionValue Value for Option to be searched.\r
313\r
314 @retval Pointer Pointer to the found Option.\r
315 @retval NULL Option not found.\r
316\r
317**/\r
318DISPLAY_QUESTION_OPTION *\r
319ValueToOption (\r
320 IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
321 IN EFI_HII_VALUE *OptionValue\r
322 )\r
323{\r
324 LIST_ENTRY *Link;\r
325 DISPLAY_QUESTION_OPTION *Option;\r
326 INTN Result;\r
327 EFI_HII_VALUE Value;\r
328\r
329 Link = GetFirstNode (&Question->OptionListHead);\r
330 while (!IsNull (&Question->OptionListHead, Link)) {\r
331 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
332\r
333 ZeroMem (&Value, sizeof (EFI_HII_VALUE));\r
334 Value.Type = Option->OptionOpCode->Type;\r
335 CopyMem (&Value.Value, &Option->OptionOpCode->Value, Option->OptionOpCode->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
336 \r
337 if ((CompareHiiValue (&Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
338 return Option;\r
339 }\r
340\r
341 Link = GetNextNode (&Question->OptionListHead, Link);\r
342 }\r
343\r
344 return NULL;\r
345}\r
346\r
347\r
348/**\r
349 Return data element in an Array by its Index.\r
350\r
351 @param Array The data array.\r
352 @param Type Type of the data in this array.\r
353 @param Index Zero based index for data in this array.\r
354\r
355 @retval Value The data to be returned\r
356\r
357**/\r
358UINT64\r
359GetArrayData (\r
360 IN VOID *Array,\r
361 IN UINT8 Type,\r
362 IN UINTN Index\r
363 )\r
364{\r
365 UINT64 Data;\r
366\r
367 ASSERT (Array != NULL);\r
368\r
369 Data = 0;\r
370 switch (Type) {\r
371 case EFI_IFR_TYPE_NUM_SIZE_8:\r
372 Data = (UINT64) *(((UINT8 *) Array) + Index);\r
373 break;\r
374\r
375 case EFI_IFR_TYPE_NUM_SIZE_16:\r
376 Data = (UINT64) *(((UINT16 *) Array) + Index);\r
377 break;\r
378\r
379 case EFI_IFR_TYPE_NUM_SIZE_32:\r
380 Data = (UINT64) *(((UINT32 *) Array) + Index);\r
381 break;\r
382\r
383 case EFI_IFR_TYPE_NUM_SIZE_64:\r
384 Data = (UINT64) *(((UINT64 *) Array) + Index);\r
385 break;\r
386\r
387 default:\r
388 break;\r
389 }\r
390\r
391 return Data;\r
392}\r
393\r
394\r
395/**\r
396 Set value of a data element in an Array by its Index.\r
397\r
398 @param Array The data array.\r
399 @param Type Type of the data in this array.\r
400 @param Index Zero based index for data in this array.\r
401 @param Value The value to be set.\r
402\r
403**/\r
404VOID\r
405SetArrayData (\r
406 IN VOID *Array,\r
407 IN UINT8 Type,\r
408 IN UINTN Index,\r
409 IN UINT64 Value\r
410 )\r
411{\r
412\r
413 ASSERT (Array != NULL);\r
414\r
415 switch (Type) {\r
416 case EFI_IFR_TYPE_NUM_SIZE_8:\r
417 *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
418 break;\r
419\r
420 case EFI_IFR_TYPE_NUM_SIZE_16:\r
421 *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
422 break;\r
423\r
424 case EFI_IFR_TYPE_NUM_SIZE_32:\r
425 *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
426 break;\r
427\r
428 case EFI_IFR_TYPE_NUM_SIZE_64:\r
429 *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
430 break;\r
431\r
432 default:\r
433 break;\r
434 }\r
435}\r
436\r
437/**\r
438 Check whether this value already in the array, if yes, return the index.\r
439\r
440 @param Array The data array.\r
441 @param Type Type of the data in this array.\r
442 @param Value The value to be find.\r
443 @param Index The index in the array which has same value with Value.\r
444 \r
445 @retval TRUE Found the value in the array.\r
446 @retval FALSE Not found the value.\r
447\r
448**/\r
449BOOLEAN \r
450FindArrayData (\r
451 IN VOID *Array,\r
452 IN UINT8 Type,\r
453 IN UINT64 Value,\r
454 OUT UINTN *Index OPTIONAL\r
455 )\r
456{\r
457 UINTN Count;\r
458 UINT64 TmpValue;\r
459 UINT64 ValueComp;\r
460 \r
461 ASSERT (Array != NULL);\r
462\r
463 Count = 0;\r
464 TmpValue = 0;\r
465\r
466 switch (Type) {\r
467 case EFI_IFR_TYPE_NUM_SIZE_8:\r
468 ValueComp = (UINT8) Value;\r
469 break;\r
470\r
471 case EFI_IFR_TYPE_NUM_SIZE_16:\r
472 ValueComp = (UINT16) Value;\r
473 break;\r
474\r
475 case EFI_IFR_TYPE_NUM_SIZE_32:\r
476 ValueComp = (UINT32) Value;\r
477 break;\r
478\r
479 case EFI_IFR_TYPE_NUM_SIZE_64:\r
480 ValueComp = (UINT64) Value;\r
481 break;\r
482\r
483 default:\r
484 ValueComp = 0;\r
485 break;\r
486 }\r
487\r
488 while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {\r
489 if (ValueComp == TmpValue) {\r
490 if (Index != NULL) {\r
491 *Index = Count;\r
492 }\r
493 return TRUE;\r
494 }\r
495\r
496 Count ++;\r
497 }\r
498\r
499 return FALSE;\r
500}\r
501\r
502/**\r
503 Print Question Value according to it's storage width and display attributes.\r
504\r
505 @param Question The Question to be printed.\r
506 @param FormattedNumber Buffer for output string.\r
507 @param BufferSize The FormattedNumber buffer size in bytes.\r
508\r
509 @retval EFI_SUCCESS Print success.\r
510 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
511\r
512**/\r
513EFI_STATUS\r
514PrintFormattedNumber (\r
515 IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
516 IN OUT CHAR16 *FormattedNumber,\r
517 IN UINTN BufferSize\r
518 )\r
519{\r
520 INT64 Value;\r
521 CHAR16 *Format;\r
522 EFI_HII_VALUE *QuestionValue;\r
523 EFI_IFR_NUMERIC *NumericOp;\r
524\r
525 if (BufferSize < (21 * sizeof (CHAR16))) {\r
526 return EFI_BUFFER_TOO_SMALL;\r
527 }\r
528\r
529 QuestionValue = &Question->CurrentValue;\r
530 NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;\r
531\r
532 Value = (INT64) QuestionValue->Value.u64;\r
533 switch (NumericOp->Flags & EFI_IFR_DISPLAY) {\r
534 case EFI_IFR_DISPLAY_INT_DEC:\r
535 switch (QuestionValue->Type) {\r
536 case EFI_IFR_NUMERIC_SIZE_1:\r
537 Value = (INT64) ((INT8) QuestionValue->Value.u8);\r
538 break;\r
539\r
540 case EFI_IFR_NUMERIC_SIZE_2:\r
541 Value = (INT64) ((INT16) QuestionValue->Value.u16);\r
542 break;\r
543\r
544 case EFI_IFR_NUMERIC_SIZE_4:\r
545 Value = (INT64) ((INT32) QuestionValue->Value.u32);\r
546 break;\r
547\r
548 case EFI_IFR_NUMERIC_SIZE_8:\r
549 default:\r
550 break;\r
551 }\r
552\r
553 if (Value < 0) {\r
554 Value = -Value;\r
555 Format = L"-%ld";\r
556 } else {\r
557 Format = L"%ld";\r
558 }\r
559 break;\r
560\r
561 case EFI_IFR_DISPLAY_UINT_DEC:\r
562 Format = L"%ld";\r
563 break;\r
564\r
565 case EFI_IFR_DISPLAY_UINT_HEX:\r
566 Format = L"%lx";\r
567 break;\r
568\r
569 default:\r
570 return EFI_UNSUPPORTED;\r
571 break;\r
572 }\r
573\r
574 UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);\r
575\r
576 return EFI_SUCCESS;\r
577}\r
578\r
579\r
580/**\r
581 Draw a pop up windows based on the dimension, number of lines and\r
582 strings specified.\r
583\r
584 @param RequestedWidth The width of the pop-up.\r
585 @param NumberOfLines The number of lines.\r
586 @param Marker The variable argument list for the list of string to be printed.\r
587\r
588**/\r
589VOID\r
590CreateSharedPopUp (\r
591 IN UINTN RequestedWidth,\r
592 IN UINTN NumberOfLines,\r
593 IN VA_LIST Marker\r
594 )\r
595{\r
596 UINTN Index;\r
597 UINTN Count;\r
598 CHAR16 Character;\r
599 UINTN Start;\r
600 UINTN End;\r
601 UINTN Top;\r
602 UINTN Bottom;\r
603 CHAR16 *String;\r
604 UINTN DimensionsWidth;\r
605 UINTN DimensionsHeight;\r
606\r
607 DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;\r
608 DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;\r
609\r
610 gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
611\r
612 if ((RequestedWidth + 2) > DimensionsWidth) {\r
613 RequestedWidth = DimensionsWidth - 2;\r
614 }\r
615\r
616 //\r
617 // Subtract the PopUp width from total Columns, allow for one space extra on\r
618 // each end plus a border.\r
619 //\r
620 Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gStatementDimensions.LeftColumn + 1;\r
621 End = Start + RequestedWidth + 1;\r
622\r
623 Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gStatementDimensions.TopRow - 1;\r
624 Bottom = Top + NumberOfLines + 2;\r
625\r
626 Character = BOXDRAW_DOWN_RIGHT;\r
627 PrintCharAt (Start, Top, Character);\r
628 Character = BOXDRAW_HORIZONTAL;\r
629 for (Index = Start; Index + 2 < End; Index++) {\r
630 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
631 }\r
632\r
633 Character = BOXDRAW_DOWN_LEFT;\r
634 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
635 Character = BOXDRAW_VERTICAL;\r
636\r
637 Count = 0;\r
638 for (Index = Top; Index + 2 < Bottom; Index++, Count++) {\r
639 String = VA_ARG (Marker, CHAR16*);\r
640\r
641 //\r
642 // This will clear the background of the line - we never know who might have been\r
643 // here before us. This differs from the next clear in that it used the non-reverse\r
644 // video for normal printing.\r
645 //\r
646 if (GetStringWidth (String) / 2 > 1) {\r
647 ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());\r
648 }\r
649\r
650 //\r
651 // Passing in a space results in the assumption that this is where typing will occur\r
652 //\r
653 if (String[0] == L' ') {\r
654 ClearLines (Start + 1, End - 1, Index + 1, Index + 1, GetPopupInverseColor ());\r
655 }\r
656\r
657 //\r
658 // Passing in a NULL results in a blank space\r
659 //\r
660 if (String[0] == CHAR_NULL) {\r
661 ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());\r
662 }\r
663\r
664 PrintStringAt (\r
665 ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gStatementDimensions.LeftColumn + 1,\r
666 Index + 1,\r
667 String\r
668 );\r
669 gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
670 PrintCharAt (Start, Index + 1, Character);\r
671 PrintCharAt (End - 1, Index + 1, Character);\r
672 }\r
673\r
674 Character = BOXDRAW_UP_RIGHT;\r
675 PrintCharAt (Start, Bottom - 1, Character);\r
676 Character = BOXDRAW_HORIZONTAL;\r
677 for (Index = Start; Index + 2 < End; Index++) {\r
678 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
679 }\r
680\r
681 Character = BOXDRAW_UP_LEFT;\r
682 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
683}\r
684\r
685/**\r
686 Draw a pop up windows based on the dimension, number of lines and\r
687 strings specified.\r
688\r
689 @param RequestedWidth The width of the pop-up.\r
690 @param NumberOfLines The number of lines.\r
691 @param ... A series of text strings that displayed in the pop-up.\r
692\r
693**/\r
694VOID\r
695EFIAPI\r
696CreateMultiStringPopUp (\r
697 IN UINTN RequestedWidth,\r
698 IN UINTN NumberOfLines,\r
699 ...\r
700 )\r
701{\r
702 VA_LIST Marker;\r
703\r
704 VA_START (Marker, NumberOfLines);\r
705\r
706 CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);\r
707\r
708 VA_END (Marker);\r
709}\r
710\r
1c0d306f
ED
711/**\r
712 Process nothing.\r
713\r
714 @param Event The Event need to be process\r
715 @param Context The context of the event.\r
716\r
717**/\r
718VOID\r
719EFIAPI\r
720EmptyEventProcess (\r
721 IN EFI_EVENT Event,\r
722 IN VOID *Context\r
723 )\r
724{\r
725}\r
726\r
727/**\r
728 Process for the refresh interval statement.\r
729\r
730 @param Event The Event need to be process\r
731 @param Context The context of the event.\r
732\r
733**/\r
734VOID\r
735EFIAPI\r
736RefreshTimeOutProcess (\r
737 IN EFI_EVENT Event,\r
738 IN VOID *Context\r
739 )\r
740{\r
741 WARNING_IF_CONTEXT *EventInfo;\r
742 CHAR16 TimeOutString[MAX_TIME_OUT_LEN];\r
743\r
744 EventInfo = (WARNING_IF_CONTEXT *) Context;\r
745\r
746 if (*(EventInfo->TimeOut) == 0) {\r
747 gBS->CloseEvent (Event);\r
748\r
749 gBS->SignalEvent (EventInfo->SyncEvent);\r
750 return;\r
751 }\r
752\r
753 UnicodeSPrint(TimeOutString, MAX_TIME_OUT_LEN, L"%d", *(EventInfo->TimeOut));\r
754\r
755 CreateDialog (NULL, gEmptyString, EventInfo->ErrorInfo, gPressEnter, gEmptyString, TimeOutString, NULL);\r
756\r
757 *(EventInfo->TimeOut) -= 1;\r
758}\r
759\r
7c6c064c
ED
760/**\r
761 Display error message for invalid password.\r
762\r
763**/\r
764VOID\r
765PasswordInvalid (\r
766 VOID\r
767 )\r
768{\r
769 EFI_INPUT_KEY Key;\r
770\r
771 //\r
772 // Invalid password, prompt error message\r
773 //\r
774 do {\r
775 CreateDialog (&Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString, NULL);\r
776 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
777}\r
778\r
779/**\r
780 Process password op code.\r
781\r
782 @param MenuOption The menu for current password op code.\r
783\r
784 @retval EFI_SUCCESS Question Option process success.\r
785 @retval Other Question Option process fail.\r
786\r
787**/\r
788EFI_STATUS\r
789PasswordProcess (\r
790 IN UI_MENU_OPTION *MenuOption\r
791 )\r
792{\r
793 CHAR16 *StringPtr;\r
794 CHAR16 *TempString;\r
795 UINTN Maximum;\r
796 EFI_STATUS Status;\r
797 EFI_IFR_PASSWORD *PasswordInfo;\r
798 FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
799 EFI_INPUT_KEY Key;\r
800\r
801 Question = MenuOption->ThisTag;\r
802 PasswordInfo = (EFI_IFR_PASSWORD *) Question->OpCode;\r
803 Maximum = PasswordInfo->MaxSize;\r
804 Status = EFI_SUCCESS;\r
805\r
806 StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
807 ASSERT (StringPtr);\r
808 \r
809 //\r
810 // Use a NULL password to test whether old password is required\r
811 //\r
812 *StringPtr = 0;\r
813 Status = Question->PasswordCheck (gFormData, Question, StringPtr);\r
814 if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {\r
815 //\r
816 // Password can't be set now. \r
817 //\r
818 FreePool (StringPtr);\r
819 return EFI_SUCCESS;\r
820 }\r
821\r
822 if (EFI_ERROR (Status)) {\r
823 //\r
824 // Old password exist, ask user for the old password\r
825 //\r
826 Status = ReadString (MenuOption, gPromptForPassword, StringPtr);\r
827 if (EFI_ERROR (Status)) {\r
828 FreePool (StringPtr);\r
829 return Status;\r
830 }\r
831\r
832 //\r
833 // Check user input old password\r
834 //\r
835 Status = Question->PasswordCheck (gFormData, Question, StringPtr);\r
836 if (EFI_ERROR (Status)) {\r
837 if (Status == EFI_NOT_READY) {\r
838 //\r
839 // Typed in old password incorrect\r
840 //\r
841 PasswordInvalid ();\r
842 } else {\r
843 Status = EFI_SUCCESS;\r
844 }\r
845\r
846 FreePool (StringPtr);\r
847 return Status;\r
848 }\r
849 }\r
850 \r
851 //\r
852 // Ask for new password\r
853 //\r
854 ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));\r
855 Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);\r
856 if (EFI_ERROR (Status)) {\r
857 //\r
858 // Reset state machine for password\r
859 //\r
860 Question->PasswordCheck (gFormData, Question, NULL);\r
861 FreePool (StringPtr);\r
862 return Status;\r
863 }\r
864 \r
865 //\r
866 // Confirm new password\r
867 //\r
868 TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
869 ASSERT (TempString);\r
870 Status = ReadString (MenuOption, gConfirmPassword, TempString);\r
871 if (EFI_ERROR (Status)) {\r
872 //\r
873 // Reset state machine for password\r
874 //\r
875 Question->PasswordCheck (gFormData, Question, NULL);\r
876 FreePool (StringPtr);\r
877 FreePool (TempString);\r
878 return Status;\r
879 }\r
880 \r
881 //\r
882 // Compare two typed-in new passwords\r
883 //\r
884 if (StrCmp (StringPtr, TempString) == 0) { \r
885 gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);\r
886 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
887 gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
888 gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);\r
889 FreePool (StringPtr); \r
890\r
bfae1330 891 Status = EFI_SUCCESS;\r
7c6c064c
ED
892\r
893 if (EFI_ERROR (Status)) {\r
894 //\r
895 // Reset state machine for password\r
896 //\r
897 Question->PasswordCheck (gFormData, Question, NULL);\r
898 }\r
899\r
900 return Status;\r
901 } else {\r
902 //\r
903 // Reset state machine for password\r
904 //\r
905 Question->PasswordCheck (gFormData, Question, NULL);\r
906 \r
907 //\r
908 // Two password mismatch, prompt error message\r
909 //\r
910 do {\r
911 CreateDialog (&Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString, NULL);\r
912 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
913\r
914 Status = EFI_INVALID_PARAMETER;\r
915 }\r
916 \r
917 FreePool (TempString);\r
918 FreePool (StringPtr);\r
919\r
920 return Status;\r
921}\r
922\r
923/**\r
924 Process a Question's Option (whether selected or un-selected).\r
925\r
926 @param MenuOption The MenuOption for this Question.\r
927 @param Selected TRUE: if Question is selected.\r
928 @param OptionString Pointer of the Option String to be displayed.\r
929 @param SkipErrorValue Whether need to return when value without option for it.\r
930\r
931 @retval EFI_SUCCESS Question Option process success.\r
932 @retval Other Question Option process fail.\r
933\r
934**/\r
935EFI_STATUS\r
936ProcessOptions (\r
937 IN UI_MENU_OPTION *MenuOption,\r
938 IN BOOLEAN Selected,\r
939 OUT CHAR16 **OptionString,\r
940 IN BOOLEAN SkipErrorValue\r
941 )\r
942{\r
943 EFI_STATUS Status;\r
944 CHAR16 *StringPtr;\r
945 UINTN Index;\r
946 FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
947 CHAR16 FormattedNumber[21];\r
948 UINT16 Number;\r
949 CHAR16 Character[2];\r
950 EFI_INPUT_KEY Key;\r
951 UINTN BufferSize;\r
952 DISPLAY_QUESTION_OPTION *OneOfOption;\r
953 LIST_ENTRY *Link;\r
954 EFI_HII_VALUE HiiValue;\r
955 EFI_HII_VALUE *QuestionValue;\r
956 DISPLAY_QUESTION_OPTION *Option;\r
957 UINTN Index2;\r
958 UINT8 *ValueArray;\r
959 UINT8 ValueType;\r
7c6c064c
ED
960 EFI_IFR_ORDERED_LIST *OrderList;\r
961 BOOLEAN ValueInvalid;\r
5ad66ec6 962 UINTN MaxLen;\r
7c6c064c
ED
963\r
964 Status = EFI_SUCCESS;\r
965\r
966 StringPtr = NULL;\r
967 Character[1] = L'\0';\r
968 *OptionString = NULL;\r
7c6c064c
ED
969 ValueInvalid = FALSE;\r
970\r
971 ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
972 BufferSize = (gOptionBlockWidth + 1) * 2 * gStatementDimensions.BottomRow;\r
973\r
974 Question = MenuOption->ThisTag;\r
975 QuestionValue = &Question->CurrentValue;\r
976\r
977 switch (Question->OpCode->OpCode) {\r
978 case EFI_IFR_ORDERED_LIST_OP:\r
979\r
980 //\r
981 // Check whether there are Options of this OrderedList\r
982 //\r
983 if (IsListEmpty (&Question->OptionListHead)) {\r
984 break;\r
985 }\r
986\r
987 OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;\r
988\r
989 Link = GetFirstNode (&Question->OptionListHead);\r
990 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
991\r
992 ValueType = OneOfOption->OptionOpCode->Type;\r
993 ValueArray = Question->CurrentValue.Buffer;\r
994\r
995 if (Selected) {\r
996 //\r
997 // Go ask for input\r
998 //\r
999 Status = GetSelectionInputPopUp (MenuOption);\r
1000 } else {\r
1001 //\r
1002 // We now know how many strings we will have, so we can allocate the\r
1003 // space required for the array or strings.\r
1004 //\r
5ad66ec6
DB
1005 MaxLen = OrderList->MaxContainers * BufferSize / sizeof (CHAR16);\r
1006 *OptionString = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
7c6c064c
ED
1007 ASSERT (*OptionString);\r
1008\r
1009 HiiValue.Type = ValueType;\r
1010 HiiValue.Value.u64 = 0;\r
1011 for (Index = 0; Index < OrderList->MaxContainers; Index++) {\r
1012 HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
1013 if (HiiValue.Value.u64 == 0) {\r
1014 //\r
1015 // Values for the options in ordered lists should never be a 0\r
1016 //\r
1017 break;\r
1018 }\r
1019\r
1020 OneOfOption = ValueToOption (Question, &HiiValue);\r
1021 if (OneOfOption == NULL) {\r
1022 if (SkipErrorValue) {\r
1023 //\r
1024 // Just try to get the option string, skip the value which not has option.\r
1025 //\r
1026 continue;\r
1027 }\r
1028\r
1029 //\r
1030 // Show error message\r
1031 //\r
1032 do {\r
1033 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
1034 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1035\r
1036 //\r
1037 // The initial value of the orderedlist is invalid, force to be valid value\r
1038 // Exit current DisplayForm with new value.\r
1039 //\r
1040 gUserInput->SelectedStatement = Question;\r
42645c3d 1041 gMisMatch = TRUE;\r
7c6c064c
ED
1042 ValueArray = AllocateZeroPool (Question->CurrentValue.BufferLen);\r
1043 ASSERT (ValueArray != NULL);\r
1044 gUserInput->InputValue.Buffer = ValueArray;\r
1045 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
1046 gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
1047 \r
1048 Link = GetFirstNode (&Question->OptionListHead);\r
1049 Index2 = 0;\r
1050 while (!IsNull (&Question->OptionListHead, Link) && Index2 < OrderList->MaxContainers) {\r
1051 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
1052 Link = GetNextNode (&Question->OptionListHead, Link);\r
1053 SetArrayData (ValueArray, ValueType, Index2, Option->OptionOpCode->Value.u64);\r
1054 Index2++;\r
1055 }\r
1056 SetArrayData (ValueArray, ValueType, Index2, 0);\r
1057\r
1058 FreePool (*OptionString);\r
1059 *OptionString = NULL;\r
1060 return EFI_NOT_FOUND;\r
1061 }\r
1062\r
1063 Character[0] = LEFT_ONEOF_DELIMITER;\r
5ad66ec6 1064 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1065 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
1066 ASSERT (StringPtr != NULL);\r
5ad66ec6 1067 NewStrCat (OptionString[0], MaxLen, StringPtr);\r
7c6c064c 1068 Character[0] = RIGHT_ONEOF_DELIMITER;\r
5ad66ec6 1069 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c 1070 Character[0] = CHAR_CARRIAGE_RETURN;\r
5ad66ec6 1071 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1072 FreePool (StringPtr);\r
1073 }\r
1074\r
1075 //\r
1076 // If valid option more than the max container, skip these options.\r
1077 //\r
1078 if (Index >= OrderList->MaxContainers) {\r
1079 break;\r
1080 }\r
1081\r
1082 //\r
1083 // Search the other options, try to find the one not in the container.\r
1084 //\r
1085 Link = GetFirstNode (&Question->OptionListHead);\r
1086 while (!IsNull (&Question->OptionListHead, Link)) {\r
1087 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
1088 Link = GetNextNode (&Question->OptionListHead, Link);\r
1089\r
1090 if (FindArrayData (ValueArray, ValueType, OneOfOption->OptionOpCode->Value.u64, NULL)) {\r
1091 continue;\r
1092 }\r
1093\r
1094 if (SkipErrorValue) {\r
1095 //\r
1096 // Not report error, just get the correct option string info.\r
1097 //\r
1098 Character[0] = LEFT_ONEOF_DELIMITER;\r
5ad66ec6 1099 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1100 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
1101 ASSERT (StringPtr != NULL);\r
5ad66ec6 1102 NewStrCat (OptionString[0], MaxLen, StringPtr);\r
7c6c064c 1103 Character[0] = RIGHT_ONEOF_DELIMITER;\r
5ad66ec6 1104 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c 1105 Character[0] = CHAR_CARRIAGE_RETURN;\r
5ad66ec6 1106 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1107 FreePool (StringPtr);\r
1108\r
1109 continue;\r
1110 }\r
1111\r
1112 if (!ValueInvalid) {\r
1113 ValueInvalid = TRUE;\r
1114 //\r
1115 // Show error message\r
1116 //\r
1117 do {\r
1118 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
1119 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1120\r
1121 //\r
1122 // The initial value of the orderedlist is invalid, force to be valid value\r
1123 // Exit current DisplayForm with new value.\r
1124 //\r
1125 gUserInput->SelectedStatement = Question;\r
42645c3d 1126 gMisMatch = TRUE;\r
7c6c064c
ED
1127 ValueArray = AllocateCopyPool (Question->CurrentValue.BufferLen, Question->CurrentValue.Buffer);\r
1128 ASSERT (ValueArray != NULL);\r
1129 gUserInput->InputValue.Buffer = ValueArray;\r
1130 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
1131 gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
1132 }\r
1133 \r
1134 SetArrayData (ValueArray, ValueType, Index++, OneOfOption->OptionOpCode->Value.u64);\r
1135 }\r
1136\r
1137 if (ValueInvalid) {\r
1138 FreePool (*OptionString);\r
1139 *OptionString = NULL;\r
1140 return EFI_NOT_FOUND;\r
1141 }\r
1142 }\r
1143 break;\r
1144\r
1145 case EFI_IFR_ONE_OF_OP:\r
1146 //\r
1147 // Check whether there are Options of this OneOf\r
1148 //\r
1149 if (IsListEmpty (&Question->OptionListHead)) {\r
1150 break;\r
1151 }\r
1152 if (Selected) {\r
1153 //\r
1154 // Go ask for input\r
1155 //\r
1156 Status = GetSelectionInputPopUp (MenuOption);\r
1157 } else {\r
5ad66ec6 1158 MaxLen = BufferSize / sizeof(CHAR16);\r
7c6c064c
ED
1159 *OptionString = AllocateZeroPool (BufferSize);\r
1160 ASSERT (*OptionString);\r
1161\r
1162 OneOfOption = ValueToOption (Question, QuestionValue);\r
1163 if (OneOfOption == NULL) {\r
1164 if (SkipErrorValue) {\r
1165 //\r
1166 // Not report error, just get the correct option string info.\r
1167 // \r
1168 Link = GetFirstNode (&Question->OptionListHead);\r
1169 OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
1170 } else {\r
1171 //\r
1172 // Show error message\r
1173 //\r
1174 do {\r
1175 CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
1176 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1177\r
1178 //\r
1179 // Force the Question value to be valid\r
1180 // Exit current DisplayForm with new value.\r
1181 //\r
1182 Link = GetFirstNode (&Question->OptionListHead);\r
1183 Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
1184\r
7c6c064c 1185 gUserInput->InputValue.Type = Option->OptionOpCode->Type;\r
d63a9eb4
ED
1186 switch (gUserInput->InputValue.Type) {\r
1187 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1188 gUserInput->InputValue.Value.u8 = Option->OptionOpCode->Value.u8;\r
1189 break;\r
1190 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1191 CopyMem (&gUserInput->InputValue.Value.u16, &Option->OptionOpCode->Value.u16, sizeof (UINT16));\r
1192 break;\r
1193 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1194 CopyMem (&gUserInput->InputValue.Value.u32, &Option->OptionOpCode->Value.u32, sizeof (UINT32));\r
1195 break;\r
1196 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1197 CopyMem (&gUserInput->InputValue.Value.u64, &Option->OptionOpCode->Value.u64, sizeof (UINT64));\r
1198 break;\r
1199 default:\r
1200 ASSERT (FALSE);\r
1201 break;\r
1202 }\r
7c6c064c 1203 gUserInput->SelectedStatement = Question;\r
42645c3d 1204 gMisMatch = TRUE;\r
7c6c064c
ED
1205 FreePool (*OptionString);\r
1206 *OptionString = NULL;\r
1207 return EFI_NOT_FOUND;\r
1208 }\r
1209 }\r
1210\r
1211 Character[0] = LEFT_ONEOF_DELIMITER;\r
5ad66ec6 1212 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1213 StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
1214 ASSERT (StringPtr != NULL);\r
5ad66ec6 1215 NewStrCat (OptionString[0], MaxLen, StringPtr);\r
7c6c064c 1216 Character[0] = RIGHT_ONEOF_DELIMITER;\r
5ad66ec6 1217 NewStrCat (OptionString[0], MaxLen, Character);\r
7c6c064c
ED
1218\r
1219 FreePool (StringPtr);\r
1220 }\r
1221 break;\r
1222\r
1223 case EFI_IFR_CHECKBOX_OP:\r
1224 if (Selected) {\r
1225 //\r
1226 // Since this is a BOOLEAN operation, flip it upon selection\r
1227 //\r
1228 gUserInput->InputValue.Type = QuestionValue->Type;\r
1229 gUserInput->InputValue.Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);\r
1230\r
1231 //\r
1232 // Perform inconsistent check\r
1233 //\r
bfae1330 1234 return EFI_SUCCESS;\r
7c6c064c
ED
1235 } else { \r
1236 *OptionString = AllocateZeroPool (BufferSize);\r
1237 ASSERT (*OptionString);\r
1238\r
1239 *OptionString[0] = LEFT_CHECKBOX_DELIMITER;\r
1240\r
1241 if (QuestionValue->Value.b) {\r
1242 *(OptionString[0] + 1) = CHECK_ON;\r
1243 } else {\r
1244 *(OptionString[0] + 1) = CHECK_OFF;\r
1245 }\r
1246 *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;\r
1247 }\r
1248 break;\r
1249\r
1250 case EFI_IFR_NUMERIC_OP:\r
1251 if (Selected) {\r
1252 //\r
1253 // Go ask for input\r
1254 //\r
1255 Status = GetNumericInput (MenuOption);\r
1256 } else {\r
1257 *OptionString = AllocateZeroPool (BufferSize);\r
1258 ASSERT (*OptionString);\r
1259\r
1260 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
1261\r
1262 //\r
1263 // Formatted print\r
1264 //\r
1265 PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
1266 Number = (UINT16) GetStringWidth (FormattedNumber);\r
1267 CopyMem (OptionString[0] + 1, FormattedNumber, Number);\r
1268\r
1269 *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;\r
1270 }\r
1271 break;\r
1272\r
1273 case EFI_IFR_DATE_OP:\r
1274 if (Selected) {\r
1275 //\r
1276 // This is similar to numerics\r
1277 //\r
1278 Status = GetNumericInput (MenuOption);\r
1279 } else {\r
1280 *OptionString = AllocateZeroPool (BufferSize);\r
1281 ASSERT (*OptionString);\r
1282\r
1283 switch (MenuOption->Sequence) {\r
1284 case 0:\r
1285 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
cc63add8
DB
1286 if (QuestionValue->Value.date.Month == 0xff){\r
1287 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"??");\r
1288 } else {\r
1289 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);\r
1290 }\r
7c6c064c
ED
1291 *(OptionString[0] + 3) = DATE_SEPARATOR;\r
1292 break;\r
1293\r
1294 case 1:\r
1295 SetUnicodeMem (OptionString[0], 4, L' ');\r
cc63add8
DB
1296 if (QuestionValue->Value.date.Day == 0xff){\r
1297 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"??");\r
1298 } else {\r
1299 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);\r
1300 }\r
7c6c064c
ED
1301 *(OptionString[0] + 6) = DATE_SEPARATOR;\r
1302 break;\r
1303\r
1304 case 2:\r
1305 SetUnicodeMem (OptionString[0], 7, L' ');\r
cc63add8
DB
1306 if (QuestionValue->Value.date.Year == 0xff){\r
1307 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"????");\r
1308 } else {\r
1309 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);\r
1310 }\r
7c6c064c
ED
1311 *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;\r
1312 break;\r
1313 }\r
1314 }\r
1315 break;\r
1316\r
1317 case EFI_IFR_TIME_OP:\r
1318 if (Selected) {\r
1319 //\r
1320 // This is similar to numerics\r
1321 //\r
1322 Status = GetNumericInput (MenuOption);\r
1323 } else {\r
1324 *OptionString = AllocateZeroPool (BufferSize);\r
1325 ASSERT (*OptionString);\r
1326\r
1327 switch (MenuOption->Sequence) {\r
1328 case 0:\r
1329 *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
cc63add8
DB
1330 if (QuestionValue->Value.time.Hour == 0xff){\r
1331 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"??");\r
1332 } else {\r
1333 UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);\r
1334 }\r
7c6c064c
ED
1335 *(OptionString[0] + 3) = TIME_SEPARATOR;\r
1336 break;\r
1337\r
1338 case 1:\r
1339 SetUnicodeMem (OptionString[0], 4, L' ');\r
cc63add8
DB
1340 if (QuestionValue->Value.time.Minute == 0xff){\r
1341 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"??");\r
1342 } else {\r
1343 UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);\r
1344 }\r
7c6c064c
ED
1345 *(OptionString[0] + 6) = TIME_SEPARATOR;\r
1346 break;\r
1347\r
1348 case 2:\r
1349 SetUnicodeMem (OptionString[0], 7, L' ');\r
cc63add8
DB
1350 if (QuestionValue->Value.time.Second == 0xff){\r
1351 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"??");\r
1352 } else {\r
1353 UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);\r
1354 }\r
7c6c064c
ED
1355 *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;\r
1356 break;\r
1357 }\r
1358 }\r
1359 break;\r
1360\r
1361 case EFI_IFR_STRING_OP:\r
1362 if (Selected) {\r
1363 StringPtr = AllocateZeroPool (Question->CurrentValue.BufferLen + sizeof (CHAR16));\r
1364 ASSERT (StringPtr);\r
1365 CopyMem(StringPtr, Question->CurrentValue.Buffer, Question->CurrentValue.BufferLen);\r
1366\r
1367 Status = ReadString (MenuOption, gPromptForData, StringPtr);\r
1368 if (EFI_ERROR (Status)) {\r
1369 FreePool (StringPtr);\r
1370 return Status;\r
1371 }\r
1372 \r
1373 gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);\r
1374 gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
1375 gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
1376 gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);\r
1377 FreePool (StringPtr);\r
bfae1330 1378 return EFI_SUCCESS;\r
7c6c064c
ED
1379 } else {\r
1380 *OptionString = AllocateZeroPool (BufferSize);\r
1381 ASSERT (*OptionString);\r
1382\r
1383 if (((CHAR16 *) Question->CurrentValue.Buffer)[0] == 0x0000) {\r
1384 *(OptionString[0]) = '_';\r
1385 } else {\r
1386 if (Question->CurrentValue.BufferLen < BufferSize) {\r
1387 BufferSize = Question->CurrentValue.BufferLen;\r
1388 }\r
1389 CopyMem (OptionString[0], (CHAR16 *) Question->CurrentValue.Buffer, BufferSize);\r
1390 }\r
1391 }\r
1392 break;\r
1393\r
1394 case EFI_IFR_PASSWORD_OP:\r
1395 if (Selected) {\r
1396 Status = PasswordProcess (MenuOption);\r
1397 }\r
1398 break;\r
1399\r
1400 default:\r
1401 break;\r
1402 }\r
1403\r
1404 return Status;\r
1405}\r
1406\r
1407\r
1408/**\r
1409 Process the help string: Split StringPtr to several lines of strings stored in\r
1410 FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
1411\r
1412 @param StringPtr The entire help string.\r
1413 @param FormattedString The oupput formatted string.\r
1414 @param EachLineWidth The max string length of each line in the formatted string.\r
1415 @param RowCount TRUE: if Question is selected.\r
1416\r
1417**/\r
1418UINTN\r
1419ProcessHelpString (\r
1420 IN CHAR16 *StringPtr,\r
1421 OUT CHAR16 **FormattedString,\r
1422 OUT UINT16 *EachLineWidth,\r
1423 IN UINTN RowCount\r
1424 )\r
1425{\r
1426 UINTN Index;\r
1427 CHAR16 *OutputString;\r
1428 UINTN TotalRowNum;\r
1429 UINTN CheckedNum;\r
1430 UINT16 GlyphWidth;\r
1431 UINT16 LineWidth;\r
1432 UINT16 MaxStringLen;\r
1433 UINT16 StringLen;\r
1434\r
1435 TotalRowNum = 0;\r
1436 CheckedNum = 0;\r
1437 GlyphWidth = 1;\r
1438 Index = 0;\r
1439 MaxStringLen = 0;\r
1440 StringLen = 0;\r
1441\r
1442 //\r
1443 // Set default help string width.\r
1444 //\r
1445 LineWidth = (UINT16) (gHelpBlockWidth - 1);\r
1446\r
1447 //\r
1448 // Get row number of the String.\r
1449 //\r
1450 while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
1451 if (StringLen > MaxStringLen) {\r
1452 MaxStringLen = StringLen;\r
1453 }\r
1454\r
1455 TotalRowNum ++;\r
1456 FreePool (OutputString);\r
1457 }\r
1458 *EachLineWidth = MaxStringLen;\r
1459\r
1460 *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));\r
1461 ASSERT (*FormattedString != NULL);\r
1462\r
1463 //\r
1464 // Generate formatted help string array.\r
1465 //\r
1466 GlyphWidth = 1;\r
1467 Index = 0;\r
1468 while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
1469 CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));\r
1470 CheckedNum ++;\r
1471 FreePool (OutputString);\r
1472 }\r
1473\r
1474 return TotalRowNum; \r
1475}\r