X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FSetupBrowserDxe%2FUi.c;h=137115196c6f526972cc569aeafb87b40ef890bc;hb=3347d410cc16429118a39f354f985bf2ac009007;hp=01909e46491897bb5318b3b9cd3bacae72092ea7;hpb=08476b334d91596a4eb96504f0d5304354196ba7;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c index 01909e4649..137115196c 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c @@ -1,7 +1,7 @@ /** @file Utility functions for User Interface functions. -Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -731,8 +731,10 @@ UiAddMenuOption ( } MenuOption->Sequence = Index; - if (Statement->GrayOutExpression != NULL) { - MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b; + if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut ) { + MenuOption->GrayOut = TRUE; + } else { + MenuOption->GrayOut = FALSE; } // @@ -850,8 +852,6 @@ CreateDialog ( ASSERT (TempString); ASSERT (BufferedString); - VA_START (Marker, KeyValue); - // // Zero the outgoing buffer // @@ -873,6 +873,8 @@ CreateDialog ( LargestString = 0; + VA_START (Marker, KeyValue); + // // Determine the largest string in the dialog box // Notice we are starting with 1 since String is the first string @@ -1306,101 +1308,174 @@ GetWidth ( /** Will copy LineWidth amount of a string in the OutputString buffer and return the number of CHAR16 characters that were copied into the OutputString buffer. + The output string format is: + Glyph Info + String info + '\0'. + + In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g. @param InputString String description for this option. @param LineWidth Width of the desired string to extract in CHAR16 characters + @param GlyphWidth The glyph width of the begin of the char in the string. @param Index Where in InputString to start the copy process @param OutputString Buffer to copy the string into - @return Returns the number of CHAR16 characters that were copied into the OutputString buffer. + @return Returns the number of CHAR16 characters that were copied into the OutputString + buffer, include extra glyph info and '\0' info. **/ UINT16 GetLineByWidth ( IN CHAR16 *InputString, IN UINT16 LineWidth, + IN OUT UINT16 *GlyphWidth, IN OUT UINTN *Index, OUT CHAR16 **OutputString ) { - UINT16 Count; - UINT16 Count2; + UINT16 StrOffset; + UINT16 GlyphOffset; + UINT16 OriginalGlyphWidth; + BOOLEAN ReturnFlag; + UINT16 LastSpaceOffset; + UINT16 LastGlyphWidth; + + if (InputString == NULL || Index == NULL || OutputString == NULL) { + return 0; + } - if (GetLineByWidthFinished) { - GetLineByWidthFinished = FALSE; - return (UINT16) 0; + if (LineWidth == 0 || *GlyphWidth == 0) { + return 0; } - Count = LineWidth; - Count2 = 0; + // + // Save original glyph width. + // + OriginalGlyphWidth = *GlyphWidth; + LastGlyphWidth = OriginalGlyphWidth; + ReturnFlag = FALSE; + LastSpaceOffset = 0; - *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2)); + // + // 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. + // To avoid displaying this empty line in screen, just skip the two CHARs here. + // + if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) { + *Index = *Index + 2; + } // - // Ensure we have got a valid buffer + // Fast-forward the string and see if there is a carriage-return in the string // - if (*OutputString != NULL) { + for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) { + switch (InputString[*Index + StrOffset]) { + case NARROW_CHAR: + *GlyphWidth = 1; + break; - // - //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. - //To avoid displaying this empty line in screen, just skip the two CHARs here. - // - if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) { - *Index = *Index + 2; - } + case WIDE_CHAR: + *GlyphWidth = 2; + break; - // - // Fast-forward the string and see if there is a carriage-return in the string - // - for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++) - ; + case CHAR_CARRIAGE_RETURN: + case CHAR_LINEFEED: + case CHAR_NULL: + ReturnFlag = TRUE; + break; + + default: + GlyphOffset = GlyphOffset + *GlyphWidth; + // + // Record the last space info in this line. Will be used in rewind. + // + if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) { + LastSpaceOffset = StrOffset; + LastGlyphWidth = *GlyphWidth; + } + break; + } + + if (ReturnFlag) { + break; + } + } + + // + // Rewind the string from the maximum size until we see a space to break the line + // + if (GlyphOffset > LineWidth) { // - // Copy the desired LineWidth of data to the output buffer. - // Also make sure that we don't copy more than the string. - // Also make sure that if there are linefeeds, we account for them. + // Rewind the string to last space char in this line. // - if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) && - (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2)) - ) { + if (LastSpaceOffset != 0) { + StrOffset = LastSpaceOffset; + *GlyphWidth = LastGlyphWidth; + } else { // - // Convert to CHAR16 value and show that we are done with this operation + // Roll back to last char in the line width. // - LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2); - if (LineWidth != 0) { - GetLineByWidthFinished = TRUE; - } - } else { - if (Count2 == LineWidth) { - // - // Rewind the string from the maximum size until we see a space to break the line - // - for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--) - ; - if (LineWidth == 0) { - LineWidth = Count; - } - } else { - LineWidth = Count2; - } + StrOffset--; } + } - CopyMem (*OutputString, &InputString[*Index], LineWidth * 2); + // + // The CHAR_NULL has process last time, this time just return 0 to stand for the end. + // + if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) { + return 0; + } + // + // Need extra glyph info and '\0' info, so +2. + // + *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16))); + if (*OutputString == NULL) { + return 0; + } + + // + // Save the glyph info at the begin of the string, will used by Print function. + // + if (OriginalGlyphWidth == 1) { + *(*OutputString) = NARROW_CHAR; + } else { + *(*OutputString) = WIDE_CHAR; + } + + CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16)); + + if (InputString[*Index + StrOffset] == CHAR_SPACE) { + // + // Skip the space info at the begin of next line. + // + *Index = (UINT16) (*Index + StrOffset + 1); + } else if ((InputString[*Index + StrOffset] == CHAR_LINEFEED)) { // - // If currently pointing to a space, increment the index to the first non-space character + // Skip the /n or /n/r info. // - for (; - (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN); - (*Index)++ - ) - ; - *Index = (UINT16) (*Index + LineWidth); - return LineWidth; + if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) { + *Index = (UINT16) (*Index + StrOffset + 2); + } else { + *Index = (UINT16) (*Index + StrOffset + 1); + } + } else if ((InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN)) { + // + // Skip the /r or /r/n info. + // + if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) { + *Index = (UINT16) (*Index + StrOffset + 2); + } else { + *Index = (UINT16) (*Index + StrOffset + 1); + } } else { - return (UINT16) 0; + *Index = (UINT16) (*Index + StrOffset); } + + // + // Include extra glyph info and '\0' info, so +2. + // + return StrOffset + 2; } @@ -1423,6 +1498,7 @@ UpdateOptionSkipLines ( UINTN OriginalRow; CHAR16 *OutputString; CHAR16 *OptionString; + UINT16 GlyphWidth; Row = 0; OptionString = NULL; @@ -1432,8 +1508,9 @@ UpdateOptionSkipLines ( Width = (UINT16) gOptionBlockWidth; OriginalRow = Row; + GlyphWidth = 1; - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { // // If there is more string to process print on the next row and increment the Skip value // @@ -1999,12 +2076,7 @@ ProcessGotoOpCode ( RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId); if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) { - Status = EvaluateExpression (Selection->FormSet, RefForm, RefForm->SuppressExpression); - if (EFI_ERROR (Status)) { - return Status; - } - - if (RefForm->SuppressExpression->Result.Value.b) { + if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) { // // Form is suppressed. // @@ -2093,7 +2165,9 @@ UiDisplayMenu ( CHAR16 *StringPtr; CHAR16 *OptionString; CHAR16 *OutputString; - CHAR16 *FormattedString; + CHAR16 *HelpString; + CHAR16 *HelpHeaderString; + CHAR16 *HelpBottomString; BOOLEAN NewLine; BOOLEAN Repaint; BOOLEAN SavedValue; @@ -2121,17 +2195,39 @@ UiDisplayMenu ( UI_MENU_LIST *CurrentMenu; UINTN ModalSkipColumn; BROWSER_HOT_KEY *HotKey; + UINTN HelpPageIndex; + UINTN HelpPageCount; + UINTN RowCount; + UINTN HelpLine; + UINTN HelpHeaderLine; + UINTN HelpBottomLine; + BOOLEAN MultiHelpPage; + UINT16 GlyphWidth; + UINT16 EachLineWidth; + UINT16 HeaderLineWidth; + UINT16 BottomLineWidth; CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); Status = EFI_SUCCESS; - FormattedString = NULL; + HelpString = NULL; + HelpHeaderString = NULL; + HelpBottomString = NULL; OptionString = NULL; ScreenOperation = UiNoOperation; NewLine = TRUE; MinRefreshInterval = 0; DefaultId = 0; - + HelpPageCount = 0; + HelpLine = 0; + RowCount = 0; + HelpBottomLine = 0; + HelpHeaderLine = 0; + HelpPageIndex = 0; + MultiHelpPage = FALSE; + EachLineWidth = 0; + HeaderLineWidth = 0; + BottomLineWidth = 0; OutputString = NULL; UpArrow = FALSE; DownArrow = FALSE; @@ -2282,6 +2378,7 @@ UiDisplayMenu ( Width = GetWidth (Statement, MenuOption->Handle); OriginalRow = Row; + GlyphWidth = 1; if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) { // @@ -2295,7 +2392,7 @@ UiDisplayMenu ( ); } - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if ((Temp == 0) && (Row <= BottomRow)) { PrintStringAt (MenuOption->Col, Row, OutputString); } @@ -2335,8 +2432,9 @@ UiDisplayMenu ( Width = (UINT16) gOptionBlockWidth; OriginalRow = Row; + GlyphWidth = 1; - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if ((Temp2 == 0) && (Row <= BottomRow)) { PrintStringAt (MenuOption->OptCol, Row, OutputString); } @@ -2443,8 +2541,9 @@ UiDisplayMenu ( Width = (UINT16) gOptionBlockWidth; OriginalRow = Row; + GlyphWidth = 1; - for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if ((Temp == 0) && (Row <= BottomRow)) { PrintStringAt (MenuOption->OptCol, Row, OutputString); } @@ -2672,8 +2771,9 @@ UiDisplayMenu ( Width = (UINT16) gOptionBlockWidth; OriginalRow = MenuOption->Row; + GlyphWidth = 1; - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); } @@ -2700,8 +2800,9 @@ UiDisplayMenu ( OriginalRow = MenuOption->Row; Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); + GlyphWidth = 1; - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); } @@ -2771,8 +2872,9 @@ UiDisplayMenu ( Width = (UINT16) gOptionBlockWidth; OriginalRow = MenuOption->Row; + GlyphWidth = 1; - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); } @@ -2794,8 +2896,9 @@ UiDisplayMenu ( OriginalRow = MenuOption->Row; Width = GetWidth (Statement, MenuOption->Handle); + GlyphWidth = 1; - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); } @@ -2845,22 +2948,125 @@ UiDisplayMenu ( StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle); } - ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow); - - gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND); - - for (Index = 0; Index < BottomRow - TopRow; Index++) { + RowCount = BottomRow - TopRow; + HelpPageIndex = 0; + // + // 1.Calculate how many line the help string need to print. + // + if (HelpString != NULL) { + FreePool (HelpString); + } + HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount); + if (HelpLine > RowCount) { + MultiHelpPage = TRUE; + StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle); + if (HelpHeaderString != NULL) { + FreePool (HelpHeaderString); + } + HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount); + StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle); + if (HelpBottomString != NULL) { + FreePool (HelpBottomString); + } + HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount); // - // Pad String with spaces to simulate a clearing of the previous line + // Calculate the help page count. // - for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) { - StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" "); + if (HelpLine > 2 * RowCount - 2) { + HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1; + if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) { + HelpPageCount += 1; + } + } else { + HelpPageCount = 2; } + } else { + MultiHelpPage = FALSE; + } + } + + // + // Clean the help field first. + // + ClearLines ( + LocalScreen.RightColumn - gHelpBlockWidth, + LocalScreen.RightColumn, + TopRow, + BottomRow, + PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND + ); + + // + // Check whether need to show the 'More(U/u)' at the begin. + // Base on current direct info, here shows aligned to the right side of the column. + // If the direction is multi line and aligned to right side may have problem, so + // add ASSERT code here. + // + if (HelpPageIndex > 0) { + gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND); + for (Index = 0; Index < HelpHeaderLine; Index++) { + ASSERT (HelpHeaderLine == 1); + ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1)); + PrintStringAt ( + LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1, + Index + TopRow, + &HelpHeaderString[Index * HeaderLineWidth] + ); + } + } + gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND); + // + // Print the help string info. + // + if (!MultiHelpPage) { + for (Index = 0; Index < HelpLine; Index++) { PrintStringAt ( LocalScreen.RightColumn - gHelpBlockWidth, Index + TopRow, - &FormattedString[Index * gHelpBlockWidth * 2] + &HelpString[Index * EachLineWidth] + ); + } + gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow); + } else { + if (HelpPageIndex == 0) { + for (Index = 0; Index < RowCount - HelpBottomLine; Index++) { + PrintStringAt ( + LocalScreen.RightColumn - gHelpBlockWidth, + Index + TopRow, + &HelpString[Index * EachLineWidth] + ); + } + } else { + for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && + (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) { + PrintStringAt ( + LocalScreen.RightColumn - gHelpBlockWidth, + Index + TopRow + HelpHeaderLine, + &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth] + ); + } + if (HelpPageIndex == HelpPageCount - 1) { + gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow); + } + } + } + + // + // Check whether need to print the 'More(D/d)' at the bottom. + // Base on current direct info, here shows aligned to the right side of the column. + // If the direction is multi line and aligned to right side may have problem, so + // add ASSERT code here. + // + if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) { + gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND); + for (Index = 0; Index < HelpBottomLine; Index++) { + ASSERT (HelpBottomLine == 1); + ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); + PrintStringAt ( + LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1, + Index + BottomRow - HelpBottomLine, + &HelpBottomString[Index * BottomLineWidth] ); } } @@ -2984,6 +3190,26 @@ UiDisplayMenu ( } break; + case 'D': + case 'd': + if (!MultiHelpPage) { + ControlFlag = CfReadKey; + break; + } + ControlFlag = CfUpdateHelpString; + HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1; + break; + + case 'U': + case 'u': + if (!MultiHelpPage) { + ControlFlag = CfReadKey; + break; + } + ControlFlag = CfUpdateHelpString; + HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0; + break; + case CHAR_NULL: for (Index = 0; Index < mScanCodeNumber; Index++) { if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) { @@ -3561,7 +3787,7 @@ UiDisplayMenu ( // Reterieve default setting. After it. NV flag will be showed. // if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { - Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope); + Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope, NULL); if (!EFI_ERROR (Status)) { Selection->Action = UI_ACTION_REFRESH_FORM; Selection->Statement = NULL; @@ -3639,7 +3865,7 @@ UiDisplayMenu ( // // Reset to default value for all forms in the whole system. // - Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel); + Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel, NULL); if (!EFI_ERROR (Status)) { Selection->Action = UI_ACTION_REFRESH_FORM; @@ -3659,6 +3885,15 @@ UiDisplayMenu ( gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4); gST->ConOut->EnableCursor (gST->ConOut, TRUE); gST->ConOut->OutputString (gST->ConOut, L"\n"); + if (HelpString != NULL) { + FreePool (HelpString); + } + if (HelpHeaderString != NULL) { + FreePool (HelpHeaderString); + } + if (HelpBottomString != NULL) { + FreePool (HelpBottomString); + } return EFI_SUCCESS;