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