/**\r
Will copy LineWidth amount of a string in the OutputString buffer and return the\r
number of CHAR16 characters that were copied into the OutputString buffer.\r
+ The output string format is:\r
+ Glyph Info + String info + '\0'.\r
+\r
In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
\r
@param InputString String description for this option.\r
@param LineWidth Width of the desired string to extract in CHAR16\r
characters\r
+ @param GlyphWidth The glyph width of the begin of the char in the string.\r
@param Index Where in InputString to start the copy process\r
@param OutputString Buffer to copy the string into\r
\r
- @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
+ @return Returns the number of CHAR16 characters that were copied into the OutputString \r
+ buffer, include extra glyph info and '\0' info.\r
\r
**/\r
UINT16\r
GetLineByWidth (\r
IN CHAR16 *InputString,\r
IN UINT16 LineWidth,\r
+ IN OUT UINT16 *GlyphWidth,\r
IN OUT UINTN *Index,\r
OUT CHAR16 **OutputString\r
)\r
{\r
- UINT16 Count;\r
- UINT16 Count2;\r
+ UINT16 StrOffset;\r
+ UINT16 GlyphOffset;\r
+ UINT16 OriginalGlyphWidth;\r
+ BOOLEAN ReturnFlag;\r
+ UINT16 LastSpaceOffset;\r
+ UINT16 LastGlyphWidth;\r
+\r
+ if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
+ return 0;\r
+ }\r
\r
- if (GetLineByWidthFinished) {\r
- GetLineByWidthFinished = FALSE;\r
- return (UINT16) 0;\r
+ if (LineWidth == 0 || *GlyphWidth == 0) {\r
+ return 0;\r
}\r
\r
- Count = LineWidth;\r
- Count2 = 0;\r
+ //\r
+ // Save original glyph width.\r
+ //\r
+ OriginalGlyphWidth = *GlyphWidth;\r
+ LastGlyphWidth = OriginalGlyphWidth;\r
+ ReturnFlag = FALSE;\r
+ LastSpaceOffset = 0;\r
\r
- *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));\r
+ //\r
+ // NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.\r
+ // To avoid displaying this empty line in screen, just skip the two CHARs here.\r
+ //\r
+ if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
+ *Index = *Index + 2;\r
+ }\r
\r
//\r
- // Ensure we have got a valid buffer\r
+ // Fast-forward the string and see if there is a carriage-return in the string\r
//\r
- if (*OutputString != NULL) {\r
+ for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {\r
+ switch (InputString[*Index + StrOffset]) {\r
+ case NARROW_CHAR:\r
+ *GlyphWidth = 1;\r
+ break;\r
\r
- //\r
- //NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.\r
- //To avoid displaying this empty line in screen, just skip the two CHARs here.\r
- //\r
- if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
- *Index = *Index + 2;\r
- }\r
+ case WIDE_CHAR:\r
+ *GlyphWidth = 2;\r
+ break;\r
\r
- //\r
- // Fast-forward the string and see if there is a carriage-return or linefeed in the string\r
- //\r
- for (; (InputString[*Index + Count2] != CHAR_LINEFEED) && (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)\r
- ;\r
+ case CHAR_CARRIAGE_RETURN:\r
+ case CHAR_LINEFEED:\r
+ case CHAR_NULL:\r
+ ReturnFlag = TRUE;\r
+ break;\r
+\r
+ default:\r
+ GlyphOffset = GlyphOffset + *GlyphWidth;\r
\r
+ //\r
+ // Record the last space info in this line. Will be used in rewind.\r
+ //\r
+ if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {\r
+ LastSpaceOffset = StrOffset;\r
+ LastGlyphWidth = *GlyphWidth;\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (ReturnFlag) {\r
+ break;\r
+ }\r
+ } \r
+\r
+ //\r
+ // Rewind the string from the maximum size until we see a space to break the line\r
+ //\r
+ if (GlyphOffset > LineWidth) {\r
//\r
- // Copy the desired LineWidth of data to the output buffer.\r
- // Also make sure that we don't copy more than the string.\r
- // Also make sure that if there are linefeeds, we account for them.\r
+ // Rewind the string to last space char in this line.\r
//\r
- if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&\r
- (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))\r
- ) {\r
+ if (LastSpaceOffset != 0) {\r
+ StrOffset = LastSpaceOffset;\r
+ *GlyphWidth = LastGlyphWidth;\r
+ } else {\r
//\r
- // Convert to CHAR16 value and show that we are done with this operation\r
+ // Roll back to last char in the line width.\r
//\r
- LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);\r
- if (LineWidth != 0) {\r
- GetLineByWidthFinished = TRUE;\r
- }\r
- } else {\r
- if (Count2 == LineWidth) {\r
- //\r
- // Rewind the string from the maximum size until we see a space to break the line\r
- //\r
- for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)\r
- ;\r
- if (LineWidth == 0) {\r
- LineWidth = Count;\r
- }\r
- } else {\r
- LineWidth = Count2;\r
- }\r
+ StrOffset--;\r
}\r
+ }\r
+\r
+ //\r
+ // The CHAR_NULL has process last time, this time just return 0 to stand for the end.\r
+ //\r
+ if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Need extra glyph info and '\0' info, so +2.\r
+ //\r
+ *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
+ if (*OutputString == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Save the glyph info at the begin of the string, will used by Print function.\r
+ //\r
+ if (OriginalGlyphWidth == 1) {\r
+ *(*OutputString) = NARROW_CHAR;\r
+ } else {\r
+ *(*OutputString) = WIDE_CHAR;\r
+ }\r
\r
- CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);\r
+ CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
\r
+ if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
//\r
- // If currently pointing to a space or carriage-return or linefeed, increment the index to the first non-space character\r
+ // Skip the space info at the begin of next line.\r
+ // \r
+ *Index = (UINT16) (*Index + StrOffset + 1);\r
+ } else if ((InputString[*Index + StrOffset] == CHAR_LINEFEED)) {\r
//\r
- for (;\r
- (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN)|| (InputString[*Index + LineWidth] == CHAR_LINEFEED);\r
- (*Index)++\r
- )\r
- ;\r
- *Index = (UINT16) (*Index + LineWidth);\r
- return LineWidth;\r
+ // Skip the /n or /n/r info.\r
+ //\r
+ if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
+ *Index = (UINT16) (*Index + StrOffset + 2);\r
+ } else {\r
+ *Index = (UINT16) (*Index + StrOffset + 1);\r
+ }\r
+ } else if ((InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN)) {\r
+ //\r
+ // Skip the /r or /r/n info.\r
+ // \r
+ if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
+ *Index = (UINT16) (*Index + StrOffset + 2);\r
+ } else {\r
+ *Index = (UINT16) (*Index + StrOffset + 1);\r
+ }\r
} else {\r
- return (UINT16) 0;\r
+ *Index = (UINT16) (*Index + StrOffset);\r
}\r
+\r
+ //\r
+ // Include extra glyph info and '\0' info, so +2.\r
+ //\r
+ return StrOffset + 2;\r
}\r
\r
\r
UINTN OriginalRow;\r
CHAR16 *OutputString;\r
CHAR16 *OptionString;\r
+ UINT16 GlyphWidth;\r
\r
Row = 0;\r
OptionString = NULL;\r
Width = (UINT16) gOptionBlockWidth;\r
\r
OriginalRow = Row;\r
+ GlyphWidth = 1;\r
\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
//\r
// If there is more string to process print on the next row and increment the Skip value\r
//\r
UINTN HelpHeaderLine;\r
UINTN HelpBottomLine;\r
BOOLEAN MultiHelpPage;\r
+ UINT16 GlyphWidth;\r
+ UINT16 EachLineWidth;\r
+ UINT16 HeaderLineWidth;\r
+ UINT16 BottomLineWidth;\r
\r
CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
\r
HelpHeaderLine = 0;\r
HelpPageIndex = 0;\r
MultiHelpPage = FALSE;\r
-\r
+ EachLineWidth = 0;\r
+ HeaderLineWidth = 0;\r
+ BottomLineWidth = 0;\r
OutputString = NULL;\r
UpArrow = FALSE;\r
DownArrow = FALSE;\r
\r
Width = GetWidth (Statement, MenuOption->Handle);\r
OriginalRow = Row;\r
+ GlyphWidth = 1;\r
\r
if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
//\r
);\r
}\r
\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if ((Temp == 0) && (Row <= BottomRow)) {\r
PrintStringAt (MenuOption->Col, Row, OutputString);\r
}\r
\r
Width = (UINT16) gOptionBlockWidth;\r
OriginalRow = Row;\r
+ GlyphWidth = 1;\r
\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if ((Temp2 == 0) && (Row <= BottomRow)) {\r
PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
}\r
\r
Width = (UINT16) gOptionBlockWidth;\r
OriginalRow = Row;\r
+ GlyphWidth = 1;\r
\r
- for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if ((Temp == 0) && (Row <= BottomRow)) {\r
PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
}\r
\r
Width = (UINT16) gOptionBlockWidth;\r
OriginalRow = MenuOption->Row;\r
+ GlyphWidth = 1;\r
\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
}\r
\r
OriginalRow = MenuOption->Row;\r
Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);\r
+ GlyphWidth = 1;\r
\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
}\r
Width = (UINT16) gOptionBlockWidth;\r
\r
OriginalRow = MenuOption->Row;\r
+ GlyphWidth = 1;\r
\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
}\r
OriginalRow = MenuOption->Row;\r
\r
Width = GetWidth (Statement, MenuOption->Handle);\r
+ GlyphWidth = 1;\r
\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
}\r
//\r
// 1.Calculate how many line the help string need to print.\r
//\r
- HelpLine = ProcessHelpString (StringPtr, &HelpString, RowCount);\r
+ if (HelpString != NULL) {\r
+ FreePool (HelpString);\r
+ }\r
+ HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
if (HelpLine > RowCount) {\r
MultiHelpPage = TRUE;\r
StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
- HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, RowCount);\r
+ if (HelpHeaderString != NULL) {\r
+ FreePool (HelpHeaderString);\r
+ }\r
+ HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount);\r
StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
- HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, RowCount);\r
+ if (HelpBottomString != NULL) {\r
+ FreePool (HelpBottomString);\r
+ }\r
+ HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);\r
//\r
// Calculate the help page count.\r
//\r
PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
);\r
\r
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
//\r
// Check whether need to show the 'More(U/u)' at the begin.\r
// Base on current direct info, here shows aligned to the right side of the column.\r
// add ASSERT code here.\r
//\r
if (HelpPageIndex > 0) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
for (Index = 0; Index < HelpHeaderLine; Index++) {\r
ASSERT (HelpHeaderLine == 1);\r
ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
PrintStringAt (\r
LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
Index + TopRow,\r
- &HelpHeaderString[Index * gHelpBlockWidth * 2]\r
+ &HelpHeaderString[Index * HeaderLineWidth]\r
);\r
}\r
}\r
PrintStringAt (\r
LocalScreen.RightColumn - gHelpBlockWidth,\r
Index + TopRow,\r
- &HelpString[Index * gHelpBlockWidth * 2]\r
+ &HelpString[Index * EachLineWidth]\r
);\r
}\r
+ gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
} else {\r
if (HelpPageIndex == 0) {\r
for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
PrintStringAt (\r
LocalScreen.RightColumn - gHelpBlockWidth,\r
Index + TopRow,\r
- &HelpString[Index * gHelpBlockWidth * 2]\r
+ &HelpString[Index * EachLineWidth]\r
);\r
}\r
} else {\r
PrintStringAt (\r
LocalScreen.RightColumn - gHelpBlockWidth,\r
Index + TopRow + HelpHeaderLine,\r
- &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* gHelpBlockWidth * 2]\r
+ &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth]\r
);\r
}\r
+ if (HelpPageIndex == HelpPageCount - 1) {\r
+ gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
+ }\r
} \r
}\r
\r
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
//\r
// Check whether need to print the 'More(D/d)' at the bottom.\r
// Base on current direct info, here shows aligned to the right side of the column.\r
// add ASSERT code here.\r
//\r
if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
for (Index = 0; Index < HelpBottomLine; Index++) {\r
ASSERT (HelpBottomLine == 1);\r
ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
PrintStringAt (\r
LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
Index + BottomRow - HelpBottomLine,\r
- &HelpBottomString[Index * gHelpBlockWidth * 2]\r
+ &HelpBottomString[Index * BottomLineWidth]\r
);\r
}\r
}\r
gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);\r
gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
gST->ConOut->OutputString (gST->ConOut, L"\n");\r
+ if (HelpString != NULL) {\r
+ FreePool (HelpString);\r
+ }\r
+ if (HelpHeaderString != NULL) {\r
+ FreePool (HelpHeaderString);\r
+ }\r
+ if (HelpBottomString != NULL) {\r
+ FreePool (HelpBottomString);\r
+ }\r
\r
return EFI_SUCCESS;\r
\r