Implementation for handling the User Interface option processing.\r
\r
\r
-Copyright (c) 2004 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
\r
**/\r
\r
-#include "Ui.h"\r
#include "Setup.h"\r
\r
\r
{\r
LIST_ENTRY *Link;\r
QUESTION_OPTION *Option;\r
+ INTN Result;\r
\r
Link = GetFirstNode (&Question->OptionListHead);\r
while (!IsNull (&Question->OptionListHead, Link)) {\r
Option = QUESTION_OPTION_FROM_LINK (Link);\r
\r
- if (CompareHiiValue (&Option->Value, OptionValue, NULL) == 0) {\r
- return Option;\r
+ if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ //\r
+ // Check the suppressif condition, only a valid option can be return.\r
+ //\r
+ if ((Option->SuppressExpression == NULL) ||\r
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
+ return Option;\r
+ }\r
}\r
\r
Link = GetNextNode (&Question->OptionListHead, Link);\r
}\r
\r
\r
+/**\r
+ Return data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+\r
+ @retval Value The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index\r
+ )\r
+{\r
+ UINT64 Data;\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ Data = 0;\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Data = (UINT64) *(((UINT8 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Data = (UINT64) *(((UINT16 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Data = (UINT64) *(((UINT32 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ Data = (UINT64) *(((UINT64 *) Array) + Index);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Data;\r
+}\r
+\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+ @param Value The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether this value already in the array, if yes, return the index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Value The value to be find.\r
+ @param Index The index in the array which has same value with Value.\r
+ \r
+ @retval TRUE Found the value in the array.\r
+ @retval FALSE Not found the value.\r
+\r
+**/\r
+BOOLEAN \r
+FindArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINT64 Value,\r
+ OUT UINTN *Index OPTIONAL\r
+ )\r
+{\r
+ UINTN Count;\r
+ UINT64 TmpValue;\r
+ \r
+ ASSERT (Array != NULL);\r
+\r
+ Count = 0;\r
+ TmpValue = 0;\r
+\r
+ while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {\r
+ if (Value == TmpValue) {\r
+ if (Index != NULL) {\r
+ *Index = Count;\r
+ }\r
+ return TRUE;\r
+ }\r
+\r
+ Count ++;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
/**\r
Print Question Value according to it's storage width and display attributes.\r
\r
EFI_STATUS Status;\r
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
- EFI_HII_VALUE *QuestionValue;\r
+ EFI_IFR_TYPE_VALUE IfrTypeValue;\r
\r
- QuestionValue = &MenuOption->ThisTag->HiiValue;\r
ConfigAccess = Selection->FormSet->ConfigAccess;\r
if (ConfigAccess == NULL) {\r
return EFI_UNSUPPORTED;\r
// Prepare password string in HII database\r
//\r
if (String != NULL) {\r
- QuestionValue->Value.string = NewString (String, Selection->FormSet->HiiHandle);\r
+ IfrTypeValue.string = NewString (String, Selection->FormSet->HiiHandle);\r
} else {\r
- QuestionValue->Value.string = 0;\r
+ IfrTypeValue.string = 0;\r
}\r
\r
//\r
ConfigAccess,\r
EFI_BROWSER_ACTION_CHANGING,\r
MenuOption->ThisTag->QuestionId,\r
- QuestionValue->Type,\r
- &QuestionValue->Value,\r
+ MenuOption->ThisTag->HiiValue.Type,\r
+ &IfrTypeValue,\r
&ActionRequest\r
);\r
\r
// Remove password string from HII database\r
//\r
if (String != NULL) {\r
- DeleteString (QuestionValue->Value.string, Selection->FormSet->HiiHandle);\r
+ DeleteString (IfrTypeValue.string, Selection->FormSet->HiiHandle);\r
}\r
\r
return Status;\r
LIST_ENTRY *Link;\r
EFI_HII_VALUE HiiValue;\r
EFI_HII_VALUE *QuestionValue;\r
- BOOLEAN Suppress;\r
UINT16 Maximum;\r
QUESTION_OPTION *Option;\r
UINTN Index2;\r
+ UINT8 *ValueArray;\r
+ UINT8 ValueType;\r
+ EFI_STRING_ID StringId;\r
\r
Status = EFI_SUCCESS;\r
\r
StringPtr = NULL;\r
Character[1] = L'\0';\r
*OptionString = NULL;\r
+ StringId = 0;\r
\r
ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow;\r
QuestionValue = &Question->HiiValue;\r
Maximum = (UINT16) Question->Maximum;\r
\r
+ ValueArray = Question->BufferValue;\r
+ ValueType = Question->ValueType;\r
+\r
switch (Question->Operand) {\r
case EFI_IFR_ORDERED_LIST_OP:\r
+ //\r
+ // Check whether there are Options of this OrderedList\r
+ //\r
+ if (IsListEmpty (&Question->OptionListHead)) {\r
+ break;\r
+ }\r
//\r
// Initialize Option value array\r
//\r
-\r
- if (Question->BufferValue[0] == 0) {\r
+ if (GetArrayData (ValueArray, ValueType, 0) == 0) {\r
GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0);\r
}\r
\r
*OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize);\r
ASSERT (*OptionString);\r
\r
- HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ HiiValue.Type = ValueType;\r
HiiValue.Value.u64 = 0;\r
for (Index = 0; Index < Question->MaxContainers; Index++) {\r
- HiiValue.Value.u8 = Question->BufferValue[Index];\r
- if (HiiValue.Value.u8 == 0) {\r
+ HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
+ if (HiiValue.Value.u64 == 0) {\r
//\r
// Values for the options in ordered lists should never be a 0\r
//\r
Index2 = 0;\r
while (!IsNull (&Question->OptionListHead, Link) && Index2 < Question->MaxContainers) {\r
Option = QUESTION_OPTION_FROM_LINK (Link);\r
- Question->BufferValue[Index2++] = Option->Value.Value.u8;\r
Link = GetNextNode (&Question->OptionListHead, Link);\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
+ continue;\r
+ }\r
+ SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64);\r
+ Index2++;\r
}\r
- Question->BufferValue[Index2] = 0;\r
+ SetArrayData (ValueArray, ValueType, Index2, 0);\r
\r
- Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
- UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+ Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
+ UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
\r
FreePool (*OptionString);\r
*OptionString = NULL;\r
return EFI_NOT_FOUND;\r
}\r
\r
- Suppress = FALSE;\r
+ Character[0] = LEFT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
+ ASSERT (StringPtr != NULL);\r
+ NewStrCat (OptionString[0], StringPtr);\r
+ Character[0] = RIGHT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ Character[0] = CHAR_CARRIAGE_RETURN;\r
+ NewStrCat (OptionString[0], Character);\r
+ FreePool (StringPtr);\r
+ }\r
+\r
+ //\r
+ // Search the other options, try to find the one not in the container.\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
if ((OneOfOption->SuppressExpression != NULL) &&\r
- (OneOfOption->SuppressExpression->Result.Value.b)) {\r
- //\r
- // This option is suppressed\r
- //\r
- Suppress = TRUE;\r
+ ((EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
+ continue;\r
}\r
\r
- if (!Suppress) {\r
- Character[0] = LEFT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
- NewStrCat (OptionString[0], StringPtr);\r
- Character[0] = RIGHT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- Character[0] = CHAR_CARRIAGE_RETURN;\r
- NewStrCat (OptionString[0], Character);\r
-\r
- FreePool (StringPtr);\r
+ if (FindArrayData (ValueArray, ValueType, OneOfOption->Value.Value.u64, NULL)) {\r
+ continue;\r
}\r
+\r
+ SetArrayData (ValueArray, ValueType, Index++, OneOfOption->Value.Value.u64);\r
+\r
+ Character[0] = LEFT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
+ ASSERT (StringPtr != NULL);\r
+ NewStrCat (OptionString[0], StringPtr);\r
+ Character[0] = RIGHT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ Character[0] = CHAR_CARRIAGE_RETURN;\r
+ NewStrCat (OptionString[0], Character);\r
+ FreePool (StringPtr);\r
}\r
}\r
break;\r
\r
case EFI_IFR_ONE_OF_OP:\r
+ //\r
+ // Check whether there are Options of this OneOf\r
+ //\r
+ if (IsListEmpty (&Question->OptionListHead)) {\r
+ break;\r
+ }\r
if (Selected) {\r
//\r
// Go ask for input\r
Option = QUESTION_OPTION_FROM_LINK (Link);\r
\r
if ((Option->SuppressExpression == NULL) ||\r
- !Option->SuppressExpression->Result.Value.b) {\r
+ (EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)) {\r
CopyMem (QuestionValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
- UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
+ UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
break;\r
}\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
- if ((OneOfOption->SuppressExpression != NULL) &&\r
- (OneOfOption->SuppressExpression->Result.Value.b)) {\r
- //\r
- // This option is suppressed\r
- //\r
- Suppress = TRUE;\r
- } else {\r
- Suppress = FALSE;\r
- }\r
-\r
- if (Suppress) {\r
- //\r
- // Current selected option happen to be suppressed,\r
- // enforce to select on a non-suppressed option\r
- //\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
-\r
- if ((OneOfOption->SuppressExpression == NULL) ||\r
- !OneOfOption->SuppressExpression->Result.Value.b) {\r
- Suppress = FALSE;\r
- CopyMem (QuestionValue, &OneOfOption->Value, sizeof (EFI_HII_VALUE));\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
- UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
- break;\r
- }\r
-\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- }\r
- }\r
+ Character[0] = LEFT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
+ ASSERT (StringPtr != NULL);\r
+ NewStrCat (OptionString[0], StringPtr);\r
+ Character[0] = RIGHT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
\r
- if (!Suppress) {\r
- Character[0] = LEFT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
- NewStrCat (OptionString[0], StringPtr);\r
- Character[0] = RIGHT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
-\r
- FreePool (StringPtr);\r
- }\r
+ FreePool (StringPtr);\r
}\r
break;\r
\r
//\r
// Save Question value\r
//\r
- Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
- UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+ Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
+ UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
}\r
\r
if (QuestionValue->Value.b) {\r
\r
case 2:\r
SetUnicodeMem (OptionString[0], 7, L' ');\r
- UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%4d", QuestionValue->Value.date.Year);\r
+ UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);\r
*(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;\r
break;\r
}\r
if (Selected) {\r
StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
ASSERT (StringPtr);\r
+ CopyMem(StringPtr, Question->BufferValue, Maximum * sizeof (CHAR16));\r
\r
Status = ReadString (MenuOption, gPromptForData, StringPtr);\r
if (!EFI_ERROR (Status)) {\r
- CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
+ HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
+ Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+ if (EFI_ERROR (Status)) {\r
+ HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
+ } else {\r
+ CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
\r
- UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+ UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+ }\r
}\r
\r
FreePool (StringPtr);\r
//\r
*StringPtr = 0;\r
Status = PasswordCallback (Selection, MenuOption, StringPtr);\r
- if (Status == EFI_NOT_AVAILABLE_YET) {\r
+ if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {\r
//\r
+ // Callback is not supported, or\r
// Callback request to terminate password input\r
//\r
FreePool (StringPtr);\r
\r
TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue);\r
ASSERT (TempString != NULL);\r
- \r
+\r
TempString[Maximum] = L'\0';\r
\r
if (StrCmp (StringPtr, TempString) != 0) {\r
//\r
if (StrCmp (StringPtr, TempString) == 0) {\r
//\r
- // Two password match, send it to Configuration Driver\r
+ // Prepare the Question->HiiValue.Value.string for ValidateQuestion use.\r
//\r
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- PasswordCallback (Selection, MenuOption, StringPtr);\r
+ if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+ StringId = Question->HiiValue.Value.string;\r
+ Question->HiiValue.Value.string = NewString (StringPtr, Selection->FormSet->HiiHandle);\r
} else {\r
- CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);\r
+ HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
+ }\r
+ \r
+ Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+\r
+ //\r
+ // Researve the Question->HiiValue.Value.string.\r
+ //\r
+ if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+ DeleteString(Question->HiiValue.Value.string, Selection->FormSet->HiiHandle);\r
+ Question->HiiValue.Value.string = StringId;\r
+ } \r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Reset state machine for interactive password\r
+ //\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+ PasswordCallback (Selection, MenuOption, NULL);\r
+ } else {\r
+ //\r
+ // Researve the Question->HiiValue.Value.string.\r
+ //\r
+ HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL); \r
+ }\r
+ } else {\r
+ //\r
+ // Two password match, send it to Configuration Driver\r
+ //\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+ PasswordCallback (Selection, MenuOption, StringPtr);\r
+ } else {\r
+ CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);\r
+ }\r
}\r
} else {\r
//\r
\r
@param StringPtr The entire help string.\r
@param FormattedString The oupput formatted string.\r
+ @param EachLineWidth The max string length of each line in the formatted string.\r
@param RowCount TRUE: if Question is selected.\r
\r
**/\r
-VOID\r
+UINTN\r
ProcessHelpString (\r
IN CHAR16 *StringPtr,\r
OUT CHAR16 **FormattedString,\r
+ OUT UINT16 *EachLineWidth,\r
IN UINTN RowCount\r
)\r
{\r
- UINTN BlockWidth;\r
- UINTN AllocateSize;\r
- //\r
- // [PrevCurrIndex, CurrIndex) forms a range of a screen-line\r
- //\r
- UINTN CurrIndex;\r
- UINTN PrevCurrIndex;\r
- UINTN LineCount;\r
- UINTN VirtualLineCount;\r
- //\r
- // GlyphOffset stores glyph width of current screen-line\r
- //\r
- UINTN GlyphOffset;\r
- //\r
- // GlyphWidth equals to 2 if we meet width directive\r
- //\r
- UINTN GlyphWidth;\r
- //\r
- // during scanning, we remember the position of last space character\r
- // in case that if next word cannot put in current line, we could restore back to the position\r
- // of last space character\r
- // while we should also remmeber the glyph width of the last space character for restoring\r
- //\r
- UINTN LastSpaceIndex;\r
- UINTN LastSpaceGlyphWidth;\r
+ UINTN Index;\r
+ CHAR16 *OutputString;\r
+ UINTN TotalRowNum;\r
+ UINTN CheckedNum;\r
+ UINT16 GlyphWidth;\r
+ UINT16 LineWidth;\r
+ UINT16 MaxStringLen;\r
+ UINT16 StringLen;\r
+\r
+ TotalRowNum = 0;\r
+ CheckedNum = 0;\r
+ GlyphWidth = 1;\r
+ Index = 0;\r
+ MaxStringLen = 0;\r
+ StringLen = 0;\r
+\r
//\r
- // every time we begin to form a new screen-line, we should remember glyph width of single character\r
- // of last line\r
+ // Set default help string width.\r
//\r
- UINTN LineStartGlyphWidth;\r
- UINTN *IndexArray;\r
- UINTN *OldIndexArray;\r
+ LineWidth = (UINT16) (gHelpBlockWidth - 1);\r
\r
- BlockWidth = (UINTN) gHelpBlockWidth - 1;\r
- \r
//\r
- // every three elements of IndexArray form a screen-line of string:[ IndexArray[i*3], IndexArray[i*3+1] )\r
- // IndexArray[i*3+2] stores the initial glyph width of single character. to save this is because we want\r
- // to bring the width directive of the last line to current screen-line.\r
- // e.g.: "\wideabcde ... fghi", if "fghi" also has width directive but is splitted to the next screen-line\r
- // different from that of "\wideabcde", we should remember the width directive.\r
+ // Get row number of the String.\r
//\r
- AllocateSize = 0x20;\r
- IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);\r
- ASSERT (IndexArray != NULL);\r
-\r
- if (*FormattedString != NULL) {\r
- FreePool (*FormattedString);\r
- *FormattedString = NULL;\r
- }\r
-\r
- for (PrevCurrIndex = 0, CurrIndex = 0, LineCount = 0, LastSpaceIndex = 0,\r
- IndexArray[0] = 0, GlyphWidth = 1, GlyphOffset = 0, LastSpaceGlyphWidth = 1, LineStartGlyphWidth = 1;\r
- (StringPtr[CurrIndex] != CHAR_NULL);\r
- CurrIndex ++) {\r
-\r
- if (LineCount == AllocateSize) {\r
- AllocateSize += 0x10;\r
- OldIndexArray = IndexArray;\r
- IndexArray = AllocatePool (AllocateSize * sizeof (UINTN) * 3);\r
- CopyMem (IndexArray, OldIndexArray, LineCount * sizeof (UINTN) * 3);\r
- FreePool (OldIndexArray);\r
- }\r
- switch (StringPtr[CurrIndex]) {\r
-\r
- case NARROW_CHAR:\r
- case WIDE_CHAR:\r
- GlyphWidth = ((StringPtr[CurrIndex] == WIDE_CHAR) ? 2 : 1);\r
- if (CurrIndex == 0) {\r
- LineStartGlyphWidth = GlyphWidth;\r
- }\r
- break;\r
-\r
- //\r
- // char is '\n'\r
- // "\r\n" isn't handled here, handled by case CHAR_CARRIAGE_RETURN\r
- //\r
- case CHAR_LINEFEED:\r
- //\r
- // Store a range of string as a line\r
- //\r
- IndexArray[LineCount*3] = PrevCurrIndex;\r
- IndexArray[LineCount*3+1] = CurrIndex;\r
- IndexArray[LineCount*3+2] = LineStartGlyphWidth;\r
- LineCount ++;\r
- //\r
- // Reset offset and save begin position of line\r
- //\r
- GlyphOffset = 0;\r
- LineStartGlyphWidth = GlyphWidth;\r
- PrevCurrIndex = CurrIndex + 1;\r
- break;\r
-\r
- //\r
- // char is '\r'\r
- // "\r\n" and "\r" both are handled here\r
- //\r
- case CHAR_CARRIAGE_RETURN:\r
- if (StringPtr[CurrIndex + 1] == CHAR_LINEFEED) {\r
- //\r
- // next char is '\n'\r
- //\r
- IndexArray[LineCount*3] = PrevCurrIndex;\r
- IndexArray[LineCount*3+1] = CurrIndex;\r
- IndexArray[LineCount*3+2] = LineStartGlyphWidth;\r
- LineCount ++;\r
- CurrIndex ++;\r
- }\r
- GlyphOffset = 0;\r
- LineStartGlyphWidth = GlyphWidth;\r
- PrevCurrIndex = CurrIndex + 1;\r
- break;\r
-\r
- //\r
- // char is space or other char\r
- //\r
- default:\r
- GlyphOffset += GlyphWidth;\r
- if (GlyphOffset >= BlockWidth) {\r
- if (LastSpaceIndex > PrevCurrIndex) {\r
- //\r
- // LastSpaceIndex points to space inside current screen-line,\r
- // restore to LastSpaceIndex\r
- // (Otherwise the word is too long to fit one screen-line, just cut it)\r
- //\r
- CurrIndex = LastSpaceIndex;\r
- GlyphWidth = LastSpaceGlyphWidth;\r
- } else if (GlyphOffset > BlockWidth) {\r
- //\r
- // the word is too long to fit one screen-line and we don't get the chance\r
- // of GlyphOffset == BlockWidth because GlyphWidth = 2\r
- //\r
- CurrIndex --;\r
- }\r
-\r
- IndexArray[LineCount*3] = PrevCurrIndex;\r
- IndexArray[LineCount*3+1] = CurrIndex + 1;\r
- IndexArray[LineCount*3+2] = LineStartGlyphWidth;\r
- LineStartGlyphWidth = GlyphWidth;\r
- LineCount ++;\r
- //\r
- // Reset offset and save begin position of line\r
- //\r
- GlyphOffset = 0;\r
- PrevCurrIndex = CurrIndex + 1;\r
- }\r
-\r
- //\r
- // LastSpaceIndex: remember position of last space\r
- //\r
- if (StringPtr[CurrIndex] == CHAR_SPACE) {\r
- LastSpaceIndex = CurrIndex;\r
- LastSpaceGlyphWidth = GlyphWidth;\r
- }\r
- break;\r
+ while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
+ if (StringLen > MaxStringLen) {\r
+ MaxStringLen = StringLen;\r
}\r
- }\r
\r
- if (GlyphOffset > 0) {\r
- IndexArray[LineCount*3] = PrevCurrIndex;\r
- IndexArray[LineCount*3+1] = CurrIndex;\r
- IndexArray[LineCount*3+2] = GlyphWidth;\r
- LineCount ++;\r
+ TotalRowNum ++;\r
+ FreePool (OutputString);\r
}\r
+ *EachLineWidth = MaxStringLen;\r
\r
- if (LineCount == 0) {\r
- //\r
- // in case we meet null string\r
- //\r
- IndexArray[0] = 0;\r
- IndexArray[1] = 1;\r
- //\r
- // we assume null string's glyph width is 1\r
- //\r
- IndexArray[1] = 1;\r
- LineCount ++;\r
- }\r
-\r
- VirtualLineCount = RowCount * (LineCount / RowCount + (LineCount % RowCount > 0));\r
- *FormattedString = AllocateZeroPool (VirtualLineCount * (BlockWidth + 1) * sizeof (CHAR16) * 2);\r
+ *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));\r
ASSERT (*FormattedString != NULL);\r
\r
- for (CurrIndex = 0; CurrIndex < LineCount; CurrIndex ++) {\r
- *(*FormattedString + CurrIndex * 2 * (BlockWidth + 1)) = (CHAR16) ((IndexArray[CurrIndex*3+2] == 2) ? WIDE_CHAR : NARROW_CHAR);\r
- StrnCpy (\r
- *FormattedString + CurrIndex * 2 * (BlockWidth + 1) + 1,\r
- StringPtr + IndexArray[CurrIndex*3],\r
- IndexArray[CurrIndex*3+1]-IndexArray[CurrIndex*3]\r
- );\r
+ //\r
+ // Generate formatted help string array.\r
+ //\r
+ GlyphWidth = 1;\r
+ Index = 0;\r
+ while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
+ CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));\r
+ CheckedNum ++;\r
+ FreePool (OutputString);\r
}\r
\r
- FreePool (IndexArray);\r
+ return TotalRowNum; \r
}\r