2 Implementation for handling the User Interface option processing.
5 Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "FormDisplay.h"
18 #define MAX_TIME_OUT_LEN 0x10
21 Concatenate a narrow string to another string.
23 @param Destination The destination string.
24 @param Source The source string. The string to be concatenated.
25 to the end of Destination.
30 IN OUT CHAR16
*Destination
,
36 for (Length
= 0; Destination
[Length
] != 0; Length
++)
40 // We now have the length of the original string
41 // We can safely assume for now that we are concatenating a narrow value to this string.
42 // For instance, the string is "XYZ" and cat'ing ">"
43 // If this assumption changes, we need to make this routine a bit more complex
45 Destination
[Length
] = NARROW_CHAR
;
48 StrCpy (Destination
+ Length
, Source
);
52 Get UINT64 type value.
54 @param Value Input Hii value.
56 @retval UINT64 Return the UINT64 type value.
61 IN EFI_HII_VALUE
*Value
68 switch (Value
->Type
) {
69 case EFI_IFR_TYPE_NUM_SIZE_8
:
70 RetVal
= Value
->Value
.u8
;
73 case EFI_IFR_TYPE_NUM_SIZE_16
:
74 RetVal
= Value
->Value
.u16
;
77 case EFI_IFR_TYPE_NUM_SIZE_32
:
78 RetVal
= Value
->Value
.u32
;
81 case EFI_IFR_TYPE_BOOLEAN
:
82 RetVal
= Value
->Value
.b
;
85 case EFI_IFR_TYPE_DATE
:
86 RetVal
= *(UINT64
*) &Value
->Value
.date
;
89 case EFI_IFR_TYPE_TIME
:
90 RetVal
= (*(UINT64
*) &Value
->Value
.time
) & 0xffffff;
94 RetVal
= Value
->Value
.u64
;
102 Compare two Hii value.
104 @param Value1 Expression value to compare on left-hand.
105 @param Value2 Expression value to compare on right-hand.
106 @param Result Return value after compare.
107 retval 0 Two operators equal.
108 return Positive value if Value1 is greater than Value2.
109 retval Negative value if Value1 is less than Value2.
110 @param HiiHandle Only required for string compare.
112 @retval other Could not perform compare on two values.
113 @retval EFI_SUCCESS Compare the value success.
118 IN EFI_HII_VALUE
*Value1
,
119 IN EFI_HII_VALUE
*Value2
,
121 IN EFI_HII_HANDLE HiiHandle OPTIONAL
129 if (Value1
->Type
>= EFI_IFR_TYPE_OTHER
|| Value2
->Type
>= EFI_IFR_TYPE_OTHER
) {
130 if (Value1
->Type
!= EFI_IFR_TYPE_BUFFER
&& Value2
->Type
!= EFI_IFR_TYPE_BUFFER
) {
131 return EFI_UNSUPPORTED
;
135 if (Value1
->Type
== EFI_IFR_TYPE_STRING
|| Value2
->Type
== EFI_IFR_TYPE_STRING
) {
136 if (Value1
->Type
!= Value2
->Type
) {
138 // Both Operator should be type of String
140 return EFI_UNSUPPORTED
;
143 if (Value1
->Value
.string
== 0 || Value2
->Value
.string
== 0) {
145 // StringId 0 is reserved
147 return EFI_INVALID_PARAMETER
;
150 if (Value1
->Value
.string
== Value2
->Value
.string
) {
155 Str1
= GetToken (Value1
->Value
.string
, HiiHandle
);
160 return EFI_NOT_FOUND
;
163 Str2
= GetToken (Value2
->Value
.string
, HiiHandle
);
166 return EFI_NOT_FOUND
;
169 *Result
= StrCmp (Str1
, Str2
);
177 if (Value1
->Type
== EFI_IFR_TYPE_BUFFER
|| Value2
->Type
== EFI_IFR_TYPE_BUFFER
) {
178 if (Value1
->Type
!= Value2
->Type
) {
180 // Both Operator should be type of Buffer.
182 return EFI_UNSUPPORTED
;
184 Len
= Value1
->BufferLen
> Value2
->BufferLen
? Value2
->BufferLen
: Value1
->BufferLen
;
185 *Result
= CompareMem (Value1
->Buffer
, Value2
->Buffer
, Len
);
186 if ((*Result
== 0) && (Value1
->BufferLen
!= Value2
->BufferLen
))
189 // In this case, means base on samll number buffer, the data is same
190 // So which value has more data, which value is bigger.
192 *Result
= Value1
->BufferLen
> Value2
->BufferLen
? 1 : -1;
198 // Take remain types(integer, boolean, date/time) as integer
200 Temp64
= HiiValueToUINT64(Value1
) - HiiValueToUINT64(Value2
);
203 } else if (Temp64
< 0) {
213 Search an Option of a Question by its value.
215 @param Question The Question
216 @param OptionValue Value for Option to be searched.
218 @retval Pointer Pointer to the found Option.
219 @retval NULL Option not found.
222 DISPLAY_QUESTION_OPTION
*
224 IN FORM_DISPLAY_ENGINE_STATEMENT
*Question
,
225 IN EFI_HII_VALUE
*OptionValue
229 DISPLAY_QUESTION_OPTION
*Option
;
233 Link
= GetFirstNode (&Question
->OptionListHead
);
234 while (!IsNull (&Question
->OptionListHead
, Link
)) {
235 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
237 ZeroMem (&Value
, sizeof (EFI_HII_VALUE
));
238 Value
.Type
= Option
->OptionOpCode
->Type
;
239 CopyMem (&Value
.Value
, &Option
->OptionOpCode
->Value
, Option
->OptionOpCode
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
241 if ((CompareHiiValue (&Value
, OptionValue
, &Result
, NULL
) == EFI_SUCCESS
) && (Result
== 0)) {
245 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
253 Return data element in an Array by its Index.
255 @param Array The data array.
256 @param Type Type of the data in this array.
257 @param Index Zero based index for data in this array.
259 @retval Value The data to be returned
271 ASSERT (Array
!= NULL
);
275 case EFI_IFR_TYPE_NUM_SIZE_8
:
276 Data
= (UINT64
) *(((UINT8
*) Array
) + Index
);
279 case EFI_IFR_TYPE_NUM_SIZE_16
:
280 Data
= (UINT64
) *(((UINT16
*) Array
) + Index
);
283 case EFI_IFR_TYPE_NUM_SIZE_32
:
284 Data
= (UINT64
) *(((UINT32
*) Array
) + Index
);
287 case EFI_IFR_TYPE_NUM_SIZE_64
:
288 Data
= (UINT64
) *(((UINT64
*) Array
) + Index
);
300 Set value of a data element in an Array by its Index.
302 @param Array The data array.
303 @param Type Type of the data in this array.
304 @param Index Zero based index for data in this array.
305 @param Value The value to be set.
317 ASSERT (Array
!= NULL
);
320 case EFI_IFR_TYPE_NUM_SIZE_8
:
321 *(((UINT8
*) Array
) + Index
) = (UINT8
) Value
;
324 case EFI_IFR_TYPE_NUM_SIZE_16
:
325 *(((UINT16
*) Array
) + Index
) = (UINT16
) Value
;
328 case EFI_IFR_TYPE_NUM_SIZE_32
:
329 *(((UINT32
*) Array
) + Index
) = (UINT32
) Value
;
332 case EFI_IFR_TYPE_NUM_SIZE_64
:
333 *(((UINT64
*) Array
) + Index
) = (UINT64
) Value
;
342 Check whether this value already in the array, if yes, return the index.
344 @param Array The data array.
345 @param Type Type of the data in this array.
346 @param Value The value to be find.
347 @param Index The index in the array which has same value with Value.
349 @retval TRUE Found the value in the array.
350 @retval FALSE Not found the value.
358 OUT UINTN
*Index OPTIONAL
365 ASSERT (Array
!= NULL
);
371 case EFI_IFR_TYPE_NUM_SIZE_8
:
372 ValueComp
= (UINT8
) Value
;
375 case EFI_IFR_TYPE_NUM_SIZE_16
:
376 ValueComp
= (UINT16
) Value
;
379 case EFI_IFR_TYPE_NUM_SIZE_32
:
380 ValueComp
= (UINT32
) Value
;
383 case EFI_IFR_TYPE_NUM_SIZE_64
:
384 ValueComp
= (UINT64
) Value
;
392 while ((TmpValue
= GetArrayData (Array
, Type
, Count
)) != 0) {
393 if (ValueComp
== TmpValue
) {
407 Print Question Value according to it's storage width and display attributes.
409 @param Question The Question to be printed.
410 @param FormattedNumber Buffer for output string.
411 @param BufferSize The FormattedNumber buffer size in bytes.
413 @retval EFI_SUCCESS Print success.
414 @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
418 PrintFormattedNumber (
419 IN FORM_DISPLAY_ENGINE_STATEMENT
*Question
,
420 IN OUT CHAR16
*FormattedNumber
,
426 EFI_HII_VALUE
*QuestionValue
;
427 EFI_IFR_NUMERIC
*NumericOp
;
429 if (BufferSize
< (21 * sizeof (CHAR16
))) {
430 return EFI_BUFFER_TOO_SMALL
;
433 QuestionValue
= &Question
->CurrentValue
;
434 NumericOp
= (EFI_IFR_NUMERIC
*) Question
->OpCode
;
436 Value
= (INT64
) QuestionValue
->Value
.u64
;
437 switch (NumericOp
->Flags
& EFI_IFR_DISPLAY
) {
438 case EFI_IFR_DISPLAY_INT_DEC
:
439 switch (QuestionValue
->Type
) {
440 case EFI_IFR_NUMERIC_SIZE_1
:
441 Value
= (INT64
) ((INT8
) QuestionValue
->Value
.u8
);
444 case EFI_IFR_NUMERIC_SIZE_2
:
445 Value
= (INT64
) ((INT16
) QuestionValue
->Value
.u16
);
448 case EFI_IFR_NUMERIC_SIZE_4
:
449 Value
= (INT64
) ((INT32
) QuestionValue
->Value
.u32
);
452 case EFI_IFR_NUMERIC_SIZE_8
:
465 case EFI_IFR_DISPLAY_UINT_DEC
:
469 case EFI_IFR_DISPLAY_UINT_HEX
:
474 return EFI_UNSUPPORTED
;
478 UnicodeSPrint (FormattedNumber
, BufferSize
, Format
, Value
);
485 Draw a pop up windows based on the dimension, number of lines and
488 @param RequestedWidth The width of the pop-up.
489 @param NumberOfLines The number of lines.
490 @param Marker The variable argument list for the list of string to be printed.
495 IN UINTN RequestedWidth
,
496 IN UINTN NumberOfLines
,
508 UINTN DimensionsWidth
;
509 UINTN DimensionsHeight
;
511 DimensionsWidth
= gStatementDimensions
.RightColumn
- gStatementDimensions
.LeftColumn
;
512 DimensionsHeight
= gStatementDimensions
.BottomRow
- gStatementDimensions
.TopRow
;
514 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetPopupColor ());
516 if ((RequestedWidth
+ 2) > DimensionsWidth
) {
517 RequestedWidth
= DimensionsWidth
- 2;
521 // Subtract the PopUp width from total Columns, allow for one space extra on
522 // each end plus a border.
524 Start
= (DimensionsWidth
- RequestedWidth
- 2) / 2 + gStatementDimensions
.LeftColumn
+ 1;
525 End
= Start
+ RequestedWidth
+ 1;
527 Top
= ((DimensionsHeight
- NumberOfLines
- 2) / 2) + gStatementDimensions
.TopRow
- 1;
528 Bottom
= Top
+ NumberOfLines
+ 2;
530 Character
= BOXDRAW_DOWN_RIGHT
;
531 PrintCharAt (Start
, Top
, Character
);
532 Character
= BOXDRAW_HORIZONTAL
;
533 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
534 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
537 Character
= BOXDRAW_DOWN_LEFT
;
538 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
539 Character
= BOXDRAW_VERTICAL
;
542 for (Index
= Top
; Index
+ 2 < Bottom
; Index
++, Count
++) {
543 String
= VA_ARG (Marker
, CHAR16
*);
546 // This will clear the background of the line - we never know who might have been
547 // here before us. This differs from the next clear in that it used the non-reverse
548 // video for normal printing.
550 if (GetStringWidth (String
) / 2 > 1) {
551 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, GetPopupColor ());
555 // Passing in a space results in the assumption that this is where typing will occur
557 if (String
[0] == L
' ') {
558 ClearLines (Start
+ 1, End
- 1, Index
+ 1, Index
+ 1, GetPopupInverseColor ());
562 // Passing in a NULL results in a blank space
564 if (String
[0] == CHAR_NULL
) {
565 ClearLines (Start
, End
, Index
+ 1, Index
+ 1, GetPopupColor ());
569 ((DimensionsWidth
- GetStringWidth (String
) / 2) / 2) + gStatementDimensions
.LeftColumn
+ 1,
573 gST
->ConOut
->SetAttribute (gST
->ConOut
, GetPopupColor ());
574 PrintCharAt (Start
, Index
+ 1, Character
);
575 PrintCharAt (End
- 1, Index
+ 1, Character
);
578 Character
= BOXDRAW_UP_RIGHT
;
579 PrintCharAt (Start
, Bottom
- 1, Character
);
580 Character
= BOXDRAW_HORIZONTAL
;
581 for (Index
= Start
; Index
+ 2 < End
; Index
++) {
582 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
585 Character
= BOXDRAW_UP_LEFT
;
586 PrintCharAt ((UINTN
)-1, (UINTN
)-1, Character
);
590 Draw a pop up windows based on the dimension, number of lines and
593 @param RequestedWidth The width of the pop-up.
594 @param NumberOfLines The number of lines.
595 @param ... A series of text strings that displayed in the pop-up.
600 CreateMultiStringPopUp (
601 IN UINTN RequestedWidth
,
602 IN UINTN NumberOfLines
,
608 VA_START (Marker
, NumberOfLines
);
610 CreateSharedPopUp (RequestedWidth
, NumberOfLines
, Marker
);
618 @param Event The Event need to be process
619 @param Context The context of the event.
632 Process for the refresh interval statement.
634 @param Event The Event need to be process
635 @param Context The context of the event.
640 RefreshTimeOutProcess (
645 WARNING_IF_CONTEXT
*EventInfo
;
646 CHAR16 TimeOutString
[MAX_TIME_OUT_LEN
];
648 EventInfo
= (WARNING_IF_CONTEXT
*) Context
;
650 if (*(EventInfo
->TimeOut
) == 0) {
651 gBS
->CloseEvent (Event
);
653 gBS
->SignalEvent (EventInfo
->SyncEvent
);
657 UnicodeSPrint(TimeOutString
, MAX_TIME_OUT_LEN
, L
"%d", *(EventInfo
->TimeOut
));
659 CreateDialog (NULL
, gEmptyString
, EventInfo
->ErrorInfo
, gPressEnter
, gEmptyString
, TimeOutString
, NULL
);
661 *(EventInfo
->TimeOut
) -= 1;
665 Display error message for invalid password.
676 // Invalid password, prompt error message
679 CreateDialog (&Key
, gEmptyString
, gPassowordInvalid
, gPressEnter
, gEmptyString
, NULL
);
680 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
684 Process password op code.
686 @param MenuOption The menu for current password op code.
688 @retval EFI_SUCCESS Question Option process success.
689 @retval Other Question Option process fail.
694 IN UI_MENU_OPTION
*MenuOption
701 EFI_IFR_PASSWORD
*PasswordInfo
;
702 FORM_DISPLAY_ENGINE_STATEMENT
*Question
;
705 Question
= MenuOption
->ThisTag
;
706 PasswordInfo
= (EFI_IFR_PASSWORD
*) Question
->OpCode
;
707 Maximum
= PasswordInfo
->MaxSize
;
708 Status
= EFI_SUCCESS
;
710 StringPtr
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
714 // Use a NULL password to test whether old password is required
717 Status
= Question
->PasswordCheck (gFormData
, Question
, StringPtr
);
718 if (Status
== EFI_NOT_AVAILABLE_YET
|| Status
== EFI_UNSUPPORTED
) {
720 // Password can't be set now.
722 FreePool (StringPtr
);
726 if (EFI_ERROR (Status
)) {
728 // Old password exist, ask user for the old password
730 Status
= ReadString (MenuOption
, gPromptForPassword
, StringPtr
);
731 if (EFI_ERROR (Status
)) {
732 FreePool (StringPtr
);
737 // Check user input old password
739 Status
= Question
->PasswordCheck (gFormData
, Question
, StringPtr
);
740 if (EFI_ERROR (Status
)) {
741 if (Status
== EFI_NOT_READY
) {
743 // Typed in old password incorrect
747 Status
= EFI_SUCCESS
;
750 FreePool (StringPtr
);
756 // Ask for new password
758 ZeroMem (StringPtr
, (Maximum
+ 1) * sizeof (CHAR16
));
759 Status
= ReadString (MenuOption
, gPromptForNewPassword
, StringPtr
);
760 if (EFI_ERROR (Status
)) {
762 // Reset state machine for password
764 Question
->PasswordCheck (gFormData
, Question
, NULL
);
765 FreePool (StringPtr
);
770 // Confirm new password
772 TempString
= AllocateZeroPool ((Maximum
+ 1) * sizeof (CHAR16
));
774 Status
= ReadString (MenuOption
, gConfirmPassword
, TempString
);
775 if (EFI_ERROR (Status
)) {
777 // Reset state machine for password
779 Question
->PasswordCheck (gFormData
, Question
, NULL
);
780 FreePool (StringPtr
);
781 FreePool (TempString
);
786 // Compare two typed-in new passwords
788 if (StrCmp (StringPtr
, TempString
) == 0) {
789 gUserInput
->InputValue
.Buffer
= AllocateCopyPool (Question
->CurrentValue
.BufferLen
, StringPtr
);
790 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
791 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
792 gUserInput
->InputValue
.Value
.string
= HiiSetString(gFormData
->HiiHandle
, gUserInput
->InputValue
.Value
.string
, StringPtr
, NULL
);
793 FreePool (StringPtr
);
795 Status
= EFI_SUCCESS
;
797 if (EFI_ERROR (Status
)) {
799 // Reset state machine for password
801 Question
->PasswordCheck (gFormData
, Question
, NULL
);
807 // Reset state machine for password
809 Question
->PasswordCheck (gFormData
, Question
, NULL
);
812 // Two password mismatch, prompt error message
815 CreateDialog (&Key
, gEmptyString
, gConfirmError
, gPressEnter
, gEmptyString
, NULL
);
816 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
818 Status
= EFI_INVALID_PARAMETER
;
821 FreePool (TempString
);
822 FreePool (StringPtr
);
828 Process a Question's Option (whether selected or un-selected).
830 @param MenuOption The MenuOption for this Question.
831 @param Selected TRUE: if Question is selected.
832 @param OptionString Pointer of the Option String to be displayed.
833 @param SkipErrorValue Whether need to return when value without option for it.
835 @retval EFI_SUCCESS Question Option process success.
836 @retval Other Question Option process fail.
841 IN UI_MENU_OPTION
*MenuOption
,
843 OUT CHAR16
**OptionString
,
844 IN BOOLEAN SkipErrorValue
850 FORM_DISPLAY_ENGINE_STATEMENT
*Question
;
851 CHAR16 FormattedNumber
[21];
856 DISPLAY_QUESTION_OPTION
*OneOfOption
;
858 EFI_HII_VALUE HiiValue
;
859 EFI_HII_VALUE
*QuestionValue
;
860 DISPLAY_QUESTION_OPTION
*Option
;
864 EFI_STRING_ID StringId
;
865 EFI_IFR_ORDERED_LIST
*OrderList
;
866 BOOLEAN ValueInvalid
;
868 Status
= EFI_SUCCESS
;
871 Character
[1] = L
'\0';
872 *OptionString
= NULL
;
874 ValueInvalid
= FALSE
;
876 ZeroMem (FormattedNumber
, 21 * sizeof (CHAR16
));
877 BufferSize
= (gOptionBlockWidth
+ 1) * 2 * gStatementDimensions
.BottomRow
;
879 Question
= MenuOption
->ThisTag
;
880 QuestionValue
= &Question
->CurrentValue
;
882 switch (Question
->OpCode
->OpCode
) {
883 case EFI_IFR_ORDERED_LIST_OP
:
886 // Check whether there are Options of this OrderedList
888 if (IsListEmpty (&Question
->OptionListHead
)) {
892 OrderList
= (EFI_IFR_ORDERED_LIST
*) Question
->OpCode
;
894 Link
= GetFirstNode (&Question
->OptionListHead
);
895 OneOfOption
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
897 ValueType
= OneOfOption
->OptionOpCode
->Type
;
898 ValueArray
= Question
->CurrentValue
.Buffer
;
904 Status
= GetSelectionInputPopUp (MenuOption
);
907 // We now know how many strings we will have, so we can allocate the
908 // space required for the array or strings.
910 *OptionString
= AllocateZeroPool (OrderList
->MaxContainers
* BufferSize
);
911 ASSERT (*OptionString
);
913 HiiValue
.Type
= ValueType
;
914 HiiValue
.Value
.u64
= 0;
915 for (Index
= 0; Index
< OrderList
->MaxContainers
; Index
++) {
916 HiiValue
.Value
.u64
= GetArrayData (ValueArray
, ValueType
, Index
);
917 if (HiiValue
.Value
.u64
== 0) {
919 // Values for the options in ordered lists should never be a 0
924 OneOfOption
= ValueToOption (Question
, &HiiValue
);
925 if (OneOfOption
== NULL
) {
926 if (SkipErrorValue
) {
928 // Just try to get the option string, skip the value which not has option.
934 // Show error message
937 CreateDialog (&Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
, NULL
);
938 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
941 // The initial value of the orderedlist is invalid, force to be valid value
942 // Exit current DisplayForm with new value.
944 gUserInput
->SelectedStatement
= Question
;
946 ValueArray
= AllocateZeroPool (Question
->CurrentValue
.BufferLen
);
947 ASSERT (ValueArray
!= NULL
);
948 gUserInput
->InputValue
.Buffer
= ValueArray
;
949 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
950 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
952 Link
= GetFirstNode (&Question
->OptionListHead
);
954 while (!IsNull (&Question
->OptionListHead
, Link
) && Index2
< OrderList
->MaxContainers
) {
955 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
956 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
957 SetArrayData (ValueArray
, ValueType
, Index2
, Option
->OptionOpCode
->Value
.u64
);
960 SetArrayData (ValueArray
, ValueType
, Index2
, 0);
962 FreePool (*OptionString
);
963 *OptionString
= NULL
;
964 return EFI_NOT_FOUND
;
967 Character
[0] = LEFT_ONEOF_DELIMITER
;
968 NewStrCat (OptionString
[0], Character
);
969 StringPtr
= GetToken (OneOfOption
->OptionOpCode
->Option
, gFormData
->HiiHandle
);
970 ASSERT (StringPtr
!= NULL
);
971 NewStrCat (OptionString
[0], StringPtr
);
972 Character
[0] = RIGHT_ONEOF_DELIMITER
;
973 NewStrCat (OptionString
[0], Character
);
974 Character
[0] = CHAR_CARRIAGE_RETURN
;
975 NewStrCat (OptionString
[0], Character
);
976 FreePool (StringPtr
);
980 // If valid option more than the max container, skip these options.
982 if (Index
>= OrderList
->MaxContainers
) {
987 // Search the other options, try to find the one not in the container.
989 Link
= GetFirstNode (&Question
->OptionListHead
);
990 while (!IsNull (&Question
->OptionListHead
, Link
)) {
991 OneOfOption
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
992 Link
= GetNextNode (&Question
->OptionListHead
, Link
);
994 if (FindArrayData (ValueArray
, ValueType
, OneOfOption
->OptionOpCode
->Value
.u64
, NULL
)) {
998 if (SkipErrorValue
) {
1000 // Not report error, just get the correct option string info.
1002 Character
[0] = LEFT_ONEOF_DELIMITER
;
1003 NewStrCat (OptionString
[0], Character
);
1004 StringPtr
= GetToken (OneOfOption
->OptionOpCode
->Option
, gFormData
->HiiHandle
);
1005 ASSERT (StringPtr
!= NULL
);
1006 NewStrCat (OptionString
[0], StringPtr
);
1007 Character
[0] = RIGHT_ONEOF_DELIMITER
;
1008 NewStrCat (OptionString
[0], Character
);
1009 Character
[0] = CHAR_CARRIAGE_RETURN
;
1010 NewStrCat (OptionString
[0], Character
);
1011 FreePool (StringPtr
);
1016 if (!ValueInvalid
) {
1017 ValueInvalid
= TRUE
;
1019 // Show error message
1022 CreateDialog (&Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
, NULL
);
1023 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1026 // The initial value of the orderedlist is invalid, force to be valid value
1027 // Exit current DisplayForm with new value.
1029 gUserInput
->SelectedStatement
= Question
;
1031 ValueArray
= AllocateCopyPool (Question
->CurrentValue
.BufferLen
, Question
->CurrentValue
.Buffer
);
1032 ASSERT (ValueArray
!= NULL
);
1033 gUserInput
->InputValue
.Buffer
= ValueArray
;
1034 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
1035 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
1038 SetArrayData (ValueArray
, ValueType
, Index
++, OneOfOption
->OptionOpCode
->Value
.u64
);
1042 FreePool (*OptionString
);
1043 *OptionString
= NULL
;
1044 return EFI_NOT_FOUND
;
1049 case EFI_IFR_ONE_OF_OP
:
1051 // Check whether there are Options of this OneOf
1053 if (IsListEmpty (&Question
->OptionListHead
)) {
1060 Status
= GetSelectionInputPopUp (MenuOption
);
1062 *OptionString
= AllocateZeroPool (BufferSize
);
1063 ASSERT (*OptionString
);
1065 OneOfOption
= ValueToOption (Question
, QuestionValue
);
1066 if (OneOfOption
== NULL
) {
1067 if (SkipErrorValue
) {
1069 // Not report error, just get the correct option string info.
1071 Link
= GetFirstNode (&Question
->OptionListHead
);
1072 OneOfOption
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
1075 // Show error message
1078 CreateDialog (&Key
, gEmptyString
, gOptionMismatch
, gPressEnter
, gEmptyString
, NULL
);
1079 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1082 // Force the Question value to be valid
1083 // Exit current DisplayForm with new value.
1085 Link
= GetFirstNode (&Question
->OptionListHead
);
1086 Option
= DISPLAY_QUESTION_OPTION_FROM_LINK (Link
);
1088 gUserInput
->InputValue
.Type
= Option
->OptionOpCode
->Type
;
1089 switch (gUserInput
->InputValue
.Type
) {
1090 case EFI_IFR_TYPE_NUM_SIZE_8
:
1091 gUserInput
->InputValue
.Value
.u8
= Option
->OptionOpCode
->Value
.u8
;
1093 case EFI_IFR_TYPE_NUM_SIZE_16
:
1094 CopyMem (&gUserInput
->InputValue
.Value
.u16
, &Option
->OptionOpCode
->Value
.u16
, sizeof (UINT16
));
1096 case EFI_IFR_TYPE_NUM_SIZE_32
:
1097 CopyMem (&gUserInput
->InputValue
.Value
.u32
, &Option
->OptionOpCode
->Value
.u32
, sizeof (UINT32
));
1099 case EFI_IFR_TYPE_NUM_SIZE_64
:
1100 CopyMem (&gUserInput
->InputValue
.Value
.u64
, &Option
->OptionOpCode
->Value
.u64
, sizeof (UINT64
));
1106 gUserInput
->SelectedStatement
= Question
;
1108 FreePool (*OptionString
);
1109 *OptionString
= NULL
;
1110 return EFI_NOT_FOUND
;
1114 Character
[0] = LEFT_ONEOF_DELIMITER
;
1115 NewStrCat (OptionString
[0], Character
);
1116 StringPtr
= GetToken (OneOfOption
->OptionOpCode
->Option
, gFormData
->HiiHandle
);
1117 ASSERT (StringPtr
!= NULL
);
1118 NewStrCat (OptionString
[0], StringPtr
);
1119 Character
[0] = RIGHT_ONEOF_DELIMITER
;
1120 NewStrCat (OptionString
[0], Character
);
1122 FreePool (StringPtr
);
1126 case EFI_IFR_CHECKBOX_OP
:
1129 // Since this is a BOOLEAN operation, flip it upon selection
1131 gUserInput
->InputValue
.Type
= QuestionValue
->Type
;
1132 gUserInput
->InputValue
.Value
.b
= (BOOLEAN
) (QuestionValue
->Value
.b
? FALSE
: TRUE
);
1135 // Perform inconsistent check
1139 *OptionString
= AllocateZeroPool (BufferSize
);
1140 ASSERT (*OptionString
);
1142 *OptionString
[0] = LEFT_CHECKBOX_DELIMITER
;
1144 if (QuestionValue
->Value
.b
) {
1145 *(OptionString
[0] + 1) = CHECK_ON
;
1147 *(OptionString
[0] + 1) = CHECK_OFF
;
1149 *(OptionString
[0] + 2) = RIGHT_CHECKBOX_DELIMITER
;
1153 case EFI_IFR_NUMERIC_OP
:
1158 Status
= GetNumericInput (MenuOption
);
1160 *OptionString
= AllocateZeroPool (BufferSize
);
1161 ASSERT (*OptionString
);
1163 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
1168 PrintFormattedNumber (Question
, FormattedNumber
, 21 * sizeof (CHAR16
));
1169 Number
= (UINT16
) GetStringWidth (FormattedNumber
);
1170 CopyMem (OptionString
[0] + 1, FormattedNumber
, Number
);
1172 *(OptionString
[0] + Number
/ 2) = RIGHT_NUMERIC_DELIMITER
;
1176 case EFI_IFR_DATE_OP
:
1179 // This is similar to numerics
1181 Status
= GetNumericInput (MenuOption
);
1183 *OptionString
= AllocateZeroPool (BufferSize
);
1184 ASSERT (*OptionString
);
1186 switch (MenuOption
->Sequence
) {
1188 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
1189 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Month
);
1190 *(OptionString
[0] + 3) = DATE_SEPARATOR
;
1194 SetUnicodeMem (OptionString
[0], 4, L
' ');
1195 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.date
.Day
);
1196 *(OptionString
[0] + 6) = DATE_SEPARATOR
;
1200 SetUnicodeMem (OptionString
[0], 7, L
' ');
1201 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%04d", QuestionValue
->Value
.date
.Year
);
1202 *(OptionString
[0] + 11) = RIGHT_NUMERIC_DELIMITER
;
1208 case EFI_IFR_TIME_OP
:
1211 // This is similar to numerics
1213 Status
= GetNumericInput (MenuOption
);
1215 *OptionString
= AllocateZeroPool (BufferSize
);
1216 ASSERT (*OptionString
);
1218 switch (MenuOption
->Sequence
) {
1220 *OptionString
[0] = LEFT_NUMERIC_DELIMITER
;
1221 UnicodeSPrint (OptionString
[0] + 1, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Hour
);
1222 *(OptionString
[0] + 3) = TIME_SEPARATOR
;
1226 SetUnicodeMem (OptionString
[0], 4, L
' ');
1227 UnicodeSPrint (OptionString
[0] + 4, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Minute
);
1228 *(OptionString
[0] + 6) = TIME_SEPARATOR
;
1232 SetUnicodeMem (OptionString
[0], 7, L
' ');
1233 UnicodeSPrint (OptionString
[0] + 7, 21 * sizeof (CHAR16
), L
"%02d", QuestionValue
->Value
.time
.Second
);
1234 *(OptionString
[0] + 9) = RIGHT_NUMERIC_DELIMITER
;
1240 case EFI_IFR_STRING_OP
:
1242 StringPtr
= AllocateZeroPool (Question
->CurrentValue
.BufferLen
+ sizeof (CHAR16
));
1244 CopyMem(StringPtr
, Question
->CurrentValue
.Buffer
, Question
->CurrentValue
.BufferLen
);
1246 Status
= ReadString (MenuOption
, gPromptForData
, StringPtr
);
1247 if (EFI_ERROR (Status
)) {
1248 FreePool (StringPtr
);
1252 gUserInput
->InputValue
.Buffer
= AllocateCopyPool (Question
->CurrentValue
.BufferLen
, StringPtr
);
1253 gUserInput
->InputValue
.BufferLen
= Question
->CurrentValue
.BufferLen
;
1254 gUserInput
->InputValue
.Type
= Question
->CurrentValue
.Type
;
1255 gUserInput
->InputValue
.Value
.string
= HiiSetString(gFormData
->HiiHandle
, gUserInput
->InputValue
.Value
.string
, StringPtr
, NULL
);
1256 FreePool (StringPtr
);
1259 *OptionString
= AllocateZeroPool (BufferSize
);
1260 ASSERT (*OptionString
);
1262 if (((CHAR16
*) Question
->CurrentValue
.Buffer
)[0] == 0x0000) {
1263 *(OptionString
[0]) = '_';
1265 if (Question
->CurrentValue
.BufferLen
< BufferSize
) {
1266 BufferSize
= Question
->CurrentValue
.BufferLen
;
1268 CopyMem (OptionString
[0], (CHAR16
*) Question
->CurrentValue
.Buffer
, BufferSize
);
1273 case EFI_IFR_PASSWORD_OP
:
1275 Status
= PasswordProcess (MenuOption
);
1288 Process the help string: Split StringPtr to several lines of strings stored in
1289 FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
1291 @param StringPtr The entire help string.
1292 @param FormattedString The oupput formatted string.
1293 @param EachLineWidth The max string length of each line in the formatted string.
1294 @param RowCount TRUE: if Question is selected.
1299 IN CHAR16
*StringPtr
,
1300 OUT CHAR16
**FormattedString
,
1301 OUT UINT16
*EachLineWidth
,
1306 CHAR16
*OutputString
;
1311 UINT16 MaxStringLen
;
1322 // Set default help string width.
1324 LineWidth
= (UINT16
) (gHelpBlockWidth
- 1);
1327 // Get row number of the String.
1329 while ((StringLen
= GetLineByWidth (StringPtr
, LineWidth
, &GlyphWidth
, &Index
, &OutputString
)) != 0) {
1330 if (StringLen
> MaxStringLen
) {
1331 MaxStringLen
= StringLen
;
1335 FreePool (OutputString
);
1337 *EachLineWidth
= MaxStringLen
;
1339 *FormattedString
= AllocateZeroPool (TotalRowNum
* MaxStringLen
* sizeof (CHAR16
));
1340 ASSERT (*FormattedString
!= NULL
);
1343 // Generate formatted help string array.
1347 while((StringLen
= GetLineByWidth (StringPtr
, LineWidth
, &GlyphWidth
, &Index
, &OutputString
)) != 0) {
1348 CopyMem (*FormattedString
+ CheckedNum
* MaxStringLen
, OutputString
, StringLen
* sizeof (CHAR16
));
1350 FreePool (OutputString
);