/** @file Initialization and display related functions for question panel. ;****************************************************************************** ;* Copyright (c) 2015 - 2021, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include "LTDEPanels.h" #include "LTDEQuestions.h" #include "LTDEPrint.h" #include "LTDESupport.h" #include "LTDEMisc.h" #define DIALOG_MIN_WIDTH 10 #define DIALOG_SEPARATION_WIDTH 1 #define PANEL_COLOR_ATTRIBUTE_QUESTION (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE) #define PANEL_COLOR_ATTRIBUTE_QUESTION_BODY_INPUT (EFI_BLUE | EFI_BACKGROUND_LIGHTGRAY) /** Check if two fields are adjacent. @param[in] Field1 Pointer to first field @param[in] Field2 Pointer to second field @retval TRUE Two fields are adjacent @retval FALSE Two fields are not adjacent **/ STATIC BOOLEAN IsFieldAdjacent ( IN RECT *Field1, IN RECT *Field2 ) { if (((Field1->top == Field2->top && Field1->bottom == Field2->bottom) && (Field1->right == Field2->left || Field1->left == Field2->right)) || ((Field1->left == Field2->left && Field1->right == Field2->right ) && (Field1->top == Field2->bottom || Field1->bottom == Field2->top ))) { return TRUE; } return FALSE; } /** Get the number of control which is specific control ID in panel item. @param[in] PanelItem A Pointer to panel item instance @param[in] ControlId Request control ID @retval The number of control which is specific control ID in panel item. **/ STATIC UINT32 GetControlCountById ( IN H2O_LTDE_PANEL_ITEM *PanelItem, IN UINT32 ControlId ) { UINT32 Index; UINT32 Count; if (PanelItem == NULL || PanelItem->ControlList == NULL) { return 0; } for (Index = 0, Count = 0; Index < PanelItem->ControlCount; Index++) { if (PanelItem->ControlList[Index].ControlId == ControlId) { Count++; } } return Count; } /** Get pseudo class by dialog type. @param[in] DialogType Dialog type @retval The pseudo class value. **/ STATIC UINT32 GetPseudoClass ( IN UINT32 DialogType ) { if ((DialogType & H2O_FORM_BROWSER_D_TYPE_SHOW_HELP ) != 0 || (DialogType & H2O_FORM_BROWSER_D_TYPE_SHOW_CONFIRM_PAGE) != 0) { return H2O_STYLE_PSEUDO_CLASS_HELP; } return H2O_STYLE_PSEUDO_CLASS_NORMAL; } /** Get default dialog field. @param[out] DefaultDialogField A pointer to default dialog field @retval EFI_SUCCESS Get default dialog field successful. @retval EFI_INVALID_PARAMETER DefaultDialogField is NULL. **/ STATIC EFI_STATUS GetDefaultDialogField ( OUT RECT *DefaultDialogField ) { H2O_LTDE_PANEL *SetupPagePanel; H2O_LTDE_PANEL *HelpTextPanel; INT32 ScreenX; INT32 ScreenY; if (DefaultDialogField == NULL) { return EFI_INVALID_PARAMETER; } SetupPagePanel = GetPanel (SETUP_PAGE_PANEL_ID); if (SetupPagePanel != NULL && SetupPagePanel->Visible) { CopyRect (DefaultDialogField, &SetupPagePanel->PanelField); HelpTextPanel = GetPanel (HELP_TEXT_PANEL_ID); if (HelpTextPanel != NULL && HelpTextPanel->Visible && IsFieldAdjacent (&SetupPagePanel->PanelField, &HelpTextPanel->PanelField)) { UnionRect (DefaultDialogField, DefaultDialogField, &HelpTextPanel->PanelField); } } else { DEConOutQueryModeWithoutModeNumer ((UINT32 *) &ScreenX, (UINT32 *) &ScreenY); SetRect (DefaultDialogField, 0, 0, ScreenX - 1, ScreenY - 1); } return EFI_SUCCESS; } /** Get next selectable control in question panel. @param[in] QuestionPanel A Pointer to question panel instance @param[in] CurrentControl A Pointer to current control in question panel @param[in] IsLoop TRUE if get next selectable control in loop @return The pointer of next selectable control or NULL if not found or QuestionPanel is NULL. **/ STATIC H2O_LTDE_CONTROL * GetNextSelectableControlInQuestionPanel ( IN H2O_LTDE_PANEL *QuestionPanel, IN H2O_LTDE_CONTROL *CurrentControl, IN BOOLEAN IsLoop ) { H2O_LTDE_CONTROL *NextControl; H2O_LTDE_PANEL_ITEM *CurrentPanelItem; H2O_LTDE_PANEL_ITEM *PanelItem; if (QuestionPanel == NULL) { return NULL; } NextControl = NULL; CurrentPanelItem = GetPanelItemByControl (QuestionPanel, CurrentControl); // // Get next selectable control in current panel item if control ID of current control is not dialog body. // if (CurrentPanelItem != NULL && CurrentControl != NULL && CurrentControl->ControlId != LTDE_CONTROL_ID_DIALOG_BODY) { NextControl = GetNextSelectableControl (CurrentPanelItem, CurrentControl, FALSE); if (NextControl != NULL) { return NextControl; } } // // Get next selectable control from next panel item. // PanelItem = CurrentPanelItem; while (TRUE) { PanelItem = GetNextSelectablePanelItem (QuestionPanel, PanelItem, IsLoop); if (PanelItem == NULL) { break; } NextControl = GetNextSelectableControl (PanelItem, NULL, FALSE); if (NextControl != NULL) { break; } } if (NextControl == NULL && IsLoop && CurrentControl != NULL && CurrentControl->ControlId != LTDE_CONTROL_ID_DIALOG_BODY) { // // Get first selectable control in current panel item. // NextControl = GetNextSelectableControl (CurrentPanelItem, NULL, FALSE); } if (NextControl == NULL || NextControl == CurrentControl) { return NULL; } return NextControl; } /** Get required display width of input numeric value. @param[in] Value Numeric value @param[in] IsHex TRUE if numeric value is display in hex @return The required display width of input numeric value. **/ STATIC UINT32 GetRequiredWidthOfNumericValue ( IN UINT64 Value, IN BOOLEAN IsHex ) { UINT32 Base; UINT32 RequiredWidth; UINT64 LastValue; Base = IsHex ? 16 : 10; RequiredWidth = 0; LastValue = Value; while (Value > 0) { RequiredWidth++; LastValue = Value; Value = DivU64x32 (Value, Base); } if (ModU64x32(LastValue, Base) == 0) { RequiredWidth++; } if (IsHex) { RequiredWidth += (sizeof (HEX_NUMBER_PREFIX_STRING) / sizeof (CHAR16) - 1); } return RequiredWidth; } /** Get required display size of title item by calculating all controls in title item. @param[in] TitleItem A pointer to title item @param[in] LineWidth Diaplay line width @param[out] Width A pointer to required width @param[out] Height A pointer to required height @retval EFI_SUCCESS Get required display size of title item successful. @retval EFI_INVALID_PARAMETER Input parameter is NULL. **/ STATIC EFI_STATUS GetRequiredSizeOfTitleItem ( IN H2O_LTDE_PANEL_ITEM *TitleItem, IN UINT32 LineWidth, OUT UINT32 *Width, OUT UINT32 *Height ) { UINT32 Index; UINT32 RequiedWidth; UINT32 RequiedHeight; UINT32 ControlWidth; UINT32 ControlHeight; EFI_STATUS Status; if (TitleItem == NULL || Width == NULL || Height == NULL) { return EFI_INVALID_PARAMETER; } RequiedWidth = 0; RequiedHeight = 0; for (Index = 0; Index < TitleItem->ControlCount; Index++) { Status = CalculateRequireSize (TitleItem->ControlList[Index].Text.String, LineWidth, &ControlWidth, &ControlHeight); if (EFI_ERROR (Status)) { continue; } RequiedWidth = MAX(RequiedWidth, ControlWidth); RequiedHeight += ControlHeight; } *Width = RequiedWidth; *Height = RequiedHeight; return EFI_SUCCESS; } /** Get required display size of content item by calculating all controls in content item. @param[in] ContentItem A pointer to content item @param[in] LineWidth Diaplay line width @param[out] Width A pointer to required item width @param[out] Height A pointer to required item height @param[out] BodyControlWidth A pointer to required body control width @param[out] BodyInputControlWidth A pointer to required body input control width @retval EFI_SUCCESS Get required display size of content item successful. @retval EFI_INVALID_PARAMETER Input parameter is NULL. **/ STATIC EFI_STATUS GetRequiredSizeOfContentItem ( IN H2O_LTDE_PANEL_ITEM *ContentItem, IN UINT32 LineWidth, OUT UINT32 *Width, OUT UINT32 *Height, OUT UINT32 *BodyControlWidth, OUT UINT32 *BodyInputControlWidth ) { H2O_LTDE_CONTROL *Control; UINT32 Index; UINT32 Count; UINT32 BodyWidth; UINT32 BodyHeight; UINT32 BodyInputWidth; UINT32 BodyInputHeight; UINT32 MaxBodyWidth; UINT32 MaxBodyInputWidth; UINT32 RequiredHeight; UINT32 RequiredWidth; if (ContentItem == NULL || Width == NULL || Height == NULL || BodyControlWidth == NULL || BodyInputControlWidth == NULL) { return EFI_INVALID_PARAMETER; } // // Assume controls in dialog body and controls in dialog body input are vertically arranged // Assume body and body input of dialog are horizontally arranged in panel content item // MaxBodyWidth = 0; MaxBodyInputWidth = 0; RequiredHeight = 0; Count = GetControlCountById (ContentItem, LTDE_CONTROL_ID_DIALOG_BODY); Count = MAX (Count, GetControlCountById (ContentItem, LTDE_CONTROL_ID_DIALOG_BODY_INPUT)); for (Index = 0; Index < Count; Index++) { Control = FindControlByControlId (ContentItem->ControlList, ContentItem->ControlCount, LTDE_CONTROL_ID_DIALOG_BODY, Index); if (Control != NULL) { CalculateRequireSize (Control->Text.String, LineWidth, &BodyWidth, &BodyHeight); MaxBodyWidth = MAX (MaxBodyWidth, BodyWidth); } else { BodyHeight = 0; } Control = FindControlByControlId (ContentItem->ControlList, ContentItem->ControlCount, LTDE_CONTROL_ID_DIALOG_BODY_INPUT, Index); if (Control != NULL) { if (Control->Operand == EFI_IFR_NUMERIC_OP) { RequiredWidth = GetRequiredWidthOfNumericValue (Control->Maximum, IS_DISPLAYED_IN_HEX (Control)); } else { RequiredWidth = (UINT32) Control->Maximum; } if (RequiredWidth == 0) { BodyInputWidth = 0; BodyInputHeight = 0; } else { BodyInputWidth = (RequiredWidth <= LineWidth) ? RequiredWidth : LineWidth; BodyInputHeight = RequiredWidth / BodyInputWidth; BodyInputHeight += (RequiredWidth % BodyInputWidth != 0) ? 1 : 0; } MaxBodyInputWidth = MAX (MaxBodyInputWidth, BodyInputWidth); } else { BodyInputHeight = 0; } RequiredHeight += MAX (BodyHeight, BodyInputHeight); } *Height = RequiredHeight; *Width = MaxBodyWidth + MaxBodyInputWidth + ((MaxBodyWidth != 0 && MaxBodyInputWidth != 0) ? DIALOG_SEPARATION_WIDTH : 0); *BodyControlWidth = MaxBodyWidth; *BodyInputControlWidth = MaxBodyInputWidth; return EFI_SUCCESS; } /** Get required display size of button item by calculating all controls in content item. @param[in] ButtonItem A pointer to button item @param[out] Width A pointer to required item width @param[out] Height A pointer to required item height @retval EFI_SUCCESS Get required display size of button item successful. @retval EFI_INVALID_PARAMETER Input parameter is NULL. **/ STATIC EFI_STATUS GetRequiredSizeOfButtonItem ( IN H2O_LTDE_PANEL_ITEM *ButtonItem, OUT UINT32 *Width, OUT UINT32 *Height ) { UINT32 Index; UINTN DialogButtonWidth; if (ButtonItem == NULL || Width == NULL || Height == NULL) { return EFI_INVALID_PARAMETER; } // // Assume controls of dialog buttons are horizontally arranged in panel button item // DialogButtonWidth = 0; for (Index = 0; Index < ButtonItem->ControlCount; Index++) { DialogButtonWidth += GetStringDisplayWidth (ButtonItem->ControlList[Index].Text.String); } if (ButtonItem->ControlCount > 1) { DialogButtonWidth += ((ButtonItem->ControlCount - 1) * DIALOG_SEPARATION_WIDTH); } *Width = (UINT32) DialogButtonWidth; *Height = 1; return EFI_SUCCESS; } /** Set field of title item and fields of all controls in title item. @param[in] TitleItem A pointer to title item @param[in] Left Left value of title item @param[in] Top Top value of title item @param[in] Right Right value of title item @param[in] Bottom Bottom value of title item @retval EFI_SUCCESS Set field successful. @retval EFI_INVALID_PARAMETER TitleItem is NULL. **/ EFI_STATUS SetFieldOfTitleItem ( IN H2O_LTDE_PANEL_ITEM *TitleItem, IN INT32 Left, IN INT32 Top, IN INT32 Right, IN INT32 Bottom ) { UINT32 Index; INT32 StartX; INT32 StartY; INT32 EndX; UINT32 Height; UINT32 TitleItemWidth; H2O_LTDE_CONTROL *Control; if (TitleItem == NULL) { return EFI_INVALID_PARAMETER; } SetRect (&TitleItem->ItemField, Left, Top, Right, Bottom); // // Update field of all controls in title item. // TitleItemWidth = H2O_LTDE_FIELD_WIDTH(&TitleItem->ItemField); StartY = 0; StartX = 0; EndX = StartX + TitleItemWidth - 1; for (Index = 0; Index < TitleItem->ControlCount; Index++) { Control = &TitleItem->ControlList[Index]; Height = GetStringHeight (Control->Text.String, TitleItemWidth); SetRect (&Control->ControlField, StartX, StartY, EndX, StartY + Height - 1); StartY += Height; } TitleItem->MaxPos = StartY - 1; return EFI_SUCCESS; } /** Set field of content item and fields of all controls in content item. @param[in] ContentItem A pointer to content item @param[in] Left Left value of content item @param[in] Top Top value of content item @param[in] Right Right value of content item @param[in] Bottom Bottom value of content item @param[in] BodyControlWidth Body control Width of content item @param[in] BodyInputControlWidth Body input control Width of content item @retval EFI_SUCCESS Set field successful. @retval EFI_INVALID_PARAMETER ContentItem is NULL. **/ EFI_STATUS SetFieldOfContentItem ( IN H2O_LTDE_PANEL_ITEM *ContentItem, IN INT32 Left, IN INT32 Top, IN INT32 Right, IN INT32 Bottom, IN UINT32 BodyControlWidth, IN UINT32 BodyInputControlWidth ) { UINT32 Index; UINT32 Count; UINT32 BodyCount; UINT32 BodyWidth; UINT32 BodyHeight; UINT32 BodyInputCount; UINT32 BodyInputWidth; UINT32 BodyInputHeight; UINT32 AvailableWidth; INT32 BodyX; INT32 BodyInputX; INT32 StartY; UINT32 Width; UINT32 Height; H2O_LTDE_CONTROL *BodyControl; H2O_LTDE_CONTROL *BodyInputControl; if (ContentItem == NULL) { return EFI_INVALID_PARAMETER; } SetRect (&ContentItem->ItemField, Left, Top, Right, Bottom); if (ContentItem->ControlList == NULL || ContentItem->ControlCount == 0) { return EFI_SUCCESS; } // // Determine width of body and body input controls // BodyCount = GetControlCountById (ContentItem, LTDE_CONTROL_ID_DIALOG_BODY); BodyInputCount = GetControlCountById (ContentItem, LTDE_CONTROL_ID_DIALOG_BODY_INPUT); BodyWidth = BodyControlWidth; BodyInputWidth = BodyInputControlWidth; if (BodyCount != 0 && BodyInputCount != 0) { AvailableWidth = H2O_LTDE_FIELD_WIDTH(&ContentItem->ItemField) - DIALOG_SEPARATION_WIDTH; if (BodyWidth + BodyInputWidth > AvailableWidth) { if (BodyWidth > AvailableWidth / 2 && BodyInputWidth > AvailableWidth / 2) { BodyWidth = AvailableWidth / 2; BodyInputWidth = AvailableWidth / 2; } else if (BodyWidth > AvailableWidth / 2) { BodyWidth = AvailableWidth - BodyInputWidth; } else { BodyInputWidth = AvailableWidth - BodyWidth; } } else if (BodyWidth + BodyInputWidth < AvailableWidth) { BodyInputWidth = AvailableWidth - BodyWidth; } } else if (BodyCount != 0) { BodyWidth = H2O_LTDE_FIELD_WIDTH(&ContentItem->ItemField); } else if (BodyInputCount != 0) { BodyInputWidth = H2O_LTDE_FIELD_WIDTH(&ContentItem->ItemField); } else { return EFI_ABORTED; } // // Set field of body and body input controls // BodyX = 0; BodyInputX = (BodyCount == 0) ? 0 : BodyX + BodyWidth + DIALOG_SEPARATION_WIDTH; StartY = 0; Count = MAX (BodyCount, BodyInputCount); for (Index = 0; Index < Count; Index++) { BodyInputHeight = 0; BodyControl = FindControlByControlId (ContentItem->ControlList, ContentItem->ControlCount, LTDE_CONTROL_ID_DIALOG_BODY, Index); if (BodyControl != NULL) { BodyHeight = GetStringHeight (BodyControl->Text.String, BodyWidth); } else { BodyHeight = 0; } BodyInputControl = FindControlByControlId (ContentItem->ControlList, ContentItem->ControlCount, LTDE_CONTROL_ID_DIALOG_BODY_INPUT, Index); if (BodyInputControl != NULL) { if (BodyInputControl->Operand == EFI_IFR_NUMERIC_OP) { Width = GetRequiredWidthOfNumericValue (BodyInputControl->Maximum, IS_DISPLAYED_IN_HEX (BodyInputControl)); } else { Width = (UINT32) BodyInputControl->Maximum; } BodyInputHeight = Width / BodyInputWidth; BodyInputHeight += (Width % BodyInputWidth != 0) ? 1 : 0; } Height = MAX (BodyHeight, BodyInputHeight); if (Height == 0) { continue; } if (BodyControl != NULL) { SetRect (&BodyControl->ControlField, BodyX, StartY, BodyX + BodyWidth - 1, StartY + Height - 1); } if (BodyInputControl != NULL) { SetRect (&BodyInputControl->ControlField, BodyInputX, StartY, BodyInputX + BodyInputWidth - 1, StartY + Height - 1); } StartY += ((INT32) Height); } ContentItem->MaxPos = (StartY > 0) ? StartY - 1 : 0; return EFI_SUCCESS; } /** Set field of button item and fields of all controls in button item. @param[in] ButtonItem A pointer to button item @param[in] Left Left value of button item @param[in] Top Top value of button item @param[in] Right Right value of button item @param[in] Bottom Bottom value of button item @param[in] ButtonItemRequiredWidth Required Width of button item @retval EFI_SUCCESS Set field successful. @retval EFI_INVALID_PARAMETER ButtonItem is NULL. **/ EFI_STATUS SetFieldOfButtonItem ( IN H2O_LTDE_PANEL_ITEM *ButtonItem, IN INT32 Left, IN INT32 Top, IN INT32 Right, IN INT32 Bottom, IN UINT32 ButtonItemRequiredWidth ) { UINT32 ButtonItemWidth; UINT32 Index; UINT32 DisplayWidth; INT32 StartX; INT32 StartY; H2O_LTDE_CONTROL *Control; if (ButtonItem == NULL) { return EFI_INVALID_PARAMETER; } SetRect (&ButtonItem->ItemField, Left, Top, Right, Bottom); if (ButtonItem->ControlList == NULL || ButtonItem->ControlCount == 0) { return EFI_NOT_FOUND; } ButtonItemWidth = H2O_LTDE_FIELD_WIDTH(&ButtonItem->ItemField); StartY = 0; StartX = (ButtonItemWidth > ButtonItemRequiredWidth) ? (ButtonItemWidth - ButtonItemRequiredWidth) / 2 : 0; for (Index = 0; Index < ButtonItem->ControlCount; Index++) { Control = &ButtonItem->ControlList[Index]; DisplayWidth = (UINT32) GetStringDisplayWidth (Control->Text.String); SetRect (&Control->ControlField, StartX, StartY, StartX + DisplayWidth - 1, StartY); StartX += (DisplayWidth + DIALOG_SEPARATION_WIDTH); } ButtonItem->MaxPos = StartX - 1; return EFI_SUCCESS; } /** Update question panel field @param[in] Dialog A pointer to dialog @param[in] QuestionPanel A pointer to question panel instance @retval EFI_SUCCESS Set field successful. @retval EFI_INVALID_PARAMETER Dialog or QuestionPanel is NULL. @retval EFI_ABORTED Dialog field is empty. **/ EFI_STATUS QuestionPanelUpdateField ( IN H2O_FORM_BROWSER_D *Dialog, IN H2O_LTDE_PANEL *QuestionPanel ) { RECT DefaultDialogField; UINT32 DefaultDialogWidth; UINT32 DefaultDialogHeight; RECT DialogField; H2O_LTDE_PANEL_ITEM *TitleItem; H2O_LTDE_PANEL_ITEM *ContentItem; H2O_LTDE_PANEL_ITEM *ButtonItem; H2O_LTDE_PANEL_ITEM *PageUpItem; H2O_LTDE_PANEL_ITEM *PageDownItem; UINT32 TitleItemWidth; UINT32 TitleItemHeight; UINT32 ContentItemWidth; UINT32 ContentItemHeight; UINT32 ButtonItemWidth; UINT32 ButtonItemHeight; UINT32 BodyControlWidth; UINT32 BodyInputControlWidth; UINT32 RequiredWidth; UINT32 RequiredHeight; INT32 StartX; INT32 StartY; INT32 EndX; INT32 EndY; INT32 Offset; if (Dialog == NULL || QuestionPanel == NULL) { return EFI_INVALID_PARAMETER; } GetDefaultDialogField (&DefaultDialogField); DefaultDialogWidth = (UINT32) H2O_LTDE_FIELD_WIDTH(&DefaultDialogField); DefaultDialogHeight = (UINT32) H2O_LTDE_FIELD_HEIGHT(&DefaultDialogField); // // Get required sizes of panel controls // TitleItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_TITLE); TitleItemWidth = 0; TitleItemHeight = 0; if (TitleItem != NULL && !TitleItem->Hidden) { GetRequiredSizeOfTitleItem (TitleItem, DefaultDialogWidth, &TitleItemWidth, &TitleItemHeight); } ContentItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT); ContentItemWidth = 0; ContentItemHeight = 0; BodyControlWidth = 0; BodyInputControlWidth = 0; if (ContentItem != NULL && !ContentItem->Hidden) { GetRequiredSizeOfContentItem (ContentItem, DefaultDialogWidth, &ContentItemWidth, &ContentItemHeight, &BodyControlWidth, &BodyInputControlWidth); } ButtonItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_BUTTON); ButtonItemWidth = 0; ButtonItemHeight = 0; if (ButtonItem != NULL && !ButtonItem->Hidden) { GetRequiredSizeOfButtonItem (ButtonItem, &ButtonItemWidth, &ButtonItemHeight); } // // Calculate dialog field // Assume title, body and button controls are vertically arranged in question panel // if (GetPseudoClass (Dialog->DialogType) == H2O_STYLE_PSEUDO_CLASS_HELP) { CopyRect (&DialogField, &DefaultDialogField); } else { RequiredWidth = TitleItemWidth; RequiredWidth = MAX (RequiredWidth, ContentItemWidth); RequiredWidth = MAX (RequiredWidth, ButtonItemWidth); RequiredWidth += (QuestionPanel->BorderLineWidth * 2); if (RequiredWidth < DIALOG_MIN_WIDTH) { RequiredWidth = DIALOG_MIN_WIDTH; } RequiredHeight = TitleItemHeight; RequiredHeight += ContentItemHeight; RequiredHeight += ButtonItemHeight; RequiredHeight += (ContentItemHeight != 0 && TitleItemHeight != 0) ? 1 : 0; RequiredHeight += (ContentItemHeight != 0 && ButtonItemHeight != 0) ? 1 : 0; RequiredHeight += (ContentItemHeight == 0 && TitleItemHeight != 0 && ButtonItemHeight != 0) ? 1 : 0; RequiredHeight += (QuestionPanel->BorderLineWidth * 2); CopyRect (&DialogField, &DefaultDialogField); if (RequiredWidth < DefaultDialogWidth) { DialogField.left += ((DefaultDialogWidth - RequiredWidth) / 2); DialogField.right = DialogField.left + RequiredWidth - 1; } if (RequiredHeight < DefaultDialogHeight) { DialogField.top += ((DefaultDialogHeight - RequiredHeight) / 2); DialogField.bottom = DialogField.top + RequiredHeight - 1; } } if (IsRectEmpty (&DialogField)) { return EFI_ABORTED; } CopyRect (&QuestionPanel->PanelField, &DialogField); // // Set fields of panel controls // StartX = DialogField.left + QuestionPanel->BorderLineWidth; EndX = DialogField.right - QuestionPanel->BorderLineWidth; StartY = DialogField.top + QuestionPanel->BorderLineWidth; EndY = DialogField.bottom - QuestionPanel->BorderLineWidth; if (TitleItemHeight != 0) { SetFieldOfTitleItem (TitleItem, StartX, StartY, EndX, StartY + TitleItemHeight - 1); StartY += (TitleItemHeight + 1); // 1 for separation line } if (ButtonItemHeight != 0) { SetFieldOfButtonItem (ButtonItem, StartX, EndY - ButtonItemHeight + 1, EndX, EndY, ButtonItemWidth); EndY -= (ButtonItemHeight + 1); // 1 for separation line } if (ContentItem != NULL && ContentItemHeight != 0) { PageUpItem = GetPanelItem (QuestionPanel, ContentItem->Selectable ? LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_UP : LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP); if (PageUpItem != NULL && PageUpItem->ControlCount == 1) { RequiredWidth = (UINT32) GetStringDisplayWidth (PageUpItem->ControlList[0].Text.String); Offset = (EndX - StartX + 1 > (INT32) RequiredWidth) ? (EndX - StartX + 1 - RequiredWidth) / 2 : 0; if (StartY - 1 < DialogField.top) { StartY = DialogField.top; } else { StartY--; } SetRect (&PageUpItem->ItemField, StartX + Offset, StartY, StartX + Offset + RequiredWidth - 1, StartY); StartY++; if (ContentItem->CurrentPos > 0) { PageUpItem->Hidden = FALSE; } } SetRect (&ContentItem->ItemField, StartX, StartY, EndX, EndY); SetFieldOfContentItem (ContentItem, StartX, StartY, EndX, EndY, BodyControlWidth, BodyInputControlWidth); if (ContentItem->MaxPos > ContentItem->CurrentPos + H2O_LTDE_FIELD_HEIGHT (&ContentItem->ItemField) - 1) { PageDownItem = GetPanelItem (QuestionPanel, ContentItem->Selectable ? LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_DOWN : LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN); if (PageDownItem != NULL && PageDownItem->ControlCount == 1) { RequiredWidth = (UINT32) GetStringDisplayWidth (PageDownItem->ControlList[0].Text.String); Offset = (EndX - StartX + 1 > (INT32) RequiredWidth) ? (EndX - StartX + 1 - RequiredWidth) / 2 : 0; if (EndY + 1 > DialogField.bottom) { EndY = DialogField.bottom; SetRect (&ContentItem->ItemField, StartX, StartY, EndX, EndY - 1); SetFieldOfContentItem (ContentItem, StartX, StartY, EndX, EndY, BodyControlWidth, BodyInputControlWidth); } else { EndY++; } SetRect (&PageDownItem->ItemField, StartX + Offset, EndY, StartX + Offset + RequiredWidth - 1, EndY); EndY--; PageDownItem->Hidden = FALSE; } } } return EFI_SUCCESS; } /** Initialize title item in question panel @param[in] Dialog A pointer to dialog @param[in, out] TitleItem A pointer to title item @retval EFI_SUCCESS Initialize title item successful. @retval EFI_INVALID_PARAMETER Dialog or TitleItem is NULL. @retval EFI_OUT_OF_RESOURCES Allocate pool fail. **/ EFI_STATUS QuestionPanelInitTitleItem ( IN H2O_FORM_BROWSER_D *Dialog, IN OUT H2O_LTDE_PANEL_ITEM *TitleItem ) { H2O_LTDE_CONTROL *Control; if (Dialog == NULL || TitleItem == NULL) { return EFI_INVALID_PARAMETER; } TitleItem->ItemId = LTDE_PANEL_ITEM_ID_TITLE; TitleItem->Hidden = TRUE; if (Dialog->TitleString == NULL) { return EFI_SUCCESS; } Control = AllocateZeroPool (sizeof (H2O_LTDE_CONTROL)); if (Control == NULL) { return EFI_OUT_OF_RESOURCES; } Control->ControlId = LTDE_CONTROL_ID_DIALOG_TITLE; Control->Text.String = AllocateCopyPool (StrSize (Dialog->TitleString), Dialog->TitleString); Control->ControlStyle.PseudoClass = GetPseudoClass (Dialog->DialogType); TitleItem->Hidden = FALSE; TitleItem->Vertical = TRUE; TitleItem->ControlCount = 1; TitleItem->ControlList = Control; return EFI_SUCCESS; } /** Initialize content item in question panel @param[in] Dialog A pointer to dialog @param[in, out] ContentItem A pointer to content item @retval EFI_SUCCESS Initialize content item successful. @retval EFI_INVALID_PARAMETER Dialog or ContentItem is NULL. @retval EFI_OUT_OF_RESOURCES Allocate pool fail. **/ EFI_STATUS QuestionPanelInitContentItem ( IN H2O_FORM_BROWSER_D *Dialog, IN OUT H2O_LTDE_PANEL_ITEM *ContentItem ) { UINT32 Index; UINT32 Count; H2O_LTDE_CONTROL *ControlList; H2O_LTDE_CONTROL *Control; UINT8 Operand; UINT32 PseudoClass; if (Dialog == NULL || ContentItem == NULL) { return EFI_INVALID_PARAMETER; } ContentItem->ItemId = LTDE_PANEL_ITEM_ID_CONTENT; ContentItem->Hidden = TRUE; // // Initialize the child control array of panel body control from body and body input of dialog event // Count = Dialog->BodyStringCount + Dialog->BodyInputCount; if (Count == 0) { return EFI_SUCCESS; } ControlList = AllocateZeroPool (Count * sizeof (H2O_LTDE_CONTROL)); if (ControlList == NULL) { return EFI_OUT_OF_RESOURCES; } ContentItem->Hidden = FALSE; ContentItem->Vertical = TRUE; ContentItem->ControlCount = Count; ContentItem->ControlList = ControlList; Operand = GetOpCodeByDialogType (Dialog->DialogType); PseudoClass = GetPseudoClass (Dialog->DialogType); Count = 0; for (Index = 0; Index < Dialog->BodyStringCount; Index++) { Control = &ControlList[Count]; Control->ControlId = LTDE_CONTROL_ID_DIALOG_BODY; Control->Operand = Operand; Control->Sequence = (UINT8) Index; Control->Text.String = AllocateCopyPool (StrSize (Dialog->BodyStringArray[Index]), Dialog->BodyStringArray[Index]); Control->ControlStyle.PseudoClass = PseudoClass; if (Dialog->BodyHiiValueArray != NULL) { Control->Selectable = TRUE; CopyHiiValue (&Control->HiiValue, &Dialog->BodyHiiValueArray[Index]); ContentItem->Selectable = TRUE; } else { Control->Selectable = FALSE; } Count++; } for (Index = 0; Index < Dialog->BodyInputCount; Index++) { Control = &ControlList[Count]; Control->ControlId = LTDE_CONTROL_ID_DIALOG_BODY_INPUT; Control->Operand = Operand; Control->Sequence = (UINT8) Index; Control->Selectable = TRUE; Control->ControlStyle.PseudoClass = H2O_STYLE_PSEUDO_CLASS_DISABLED; if (Dialog->H2OStatement != NULL) { Control->Maximum = Dialog->H2OStatement->Maximum; Control->Minimum = Dialog->H2OStatement->Minimum; Control->Step = Dialog->H2OStatement->Step; Control->Flags = Dialog->H2OStatement->Flags; } switch (Operand) { case EFI_IFR_NUMERIC_OP: if ((Control->Flags & EFI_IFR_DISPLAY_UINT_HEX) != 0) { Control->Text.String = AllocateCopyPool (sizeof (HEX_NUMBER_PREFIX_STRING), HEX_NUMBER_PREFIX_STRING); } else { Control->Text.String = AllocateZeroPool (sizeof (CHAR16)); } CopyHiiValue (&Control->HiiValue, &Dialog->ConfirmHiiValue); break; case EFI_IFR_PASSWORD_OP: Control->Text.String = AllocateZeroPool (StrSize (Dialog->BodyInputStringArray[Index])); CreateValueAsString (&Control->HiiValue, Dialog->ConfirmHiiValue.BufferLen, AllocateZeroPool (Dialog->ConfirmHiiValue.BufferLen)); if (Control->Maximum == 0) { Control->Maximum = Dialog->ConfirmHiiValue.BufferLen / sizeof (CHAR16) - 1; } break; default: Control->Text.String = AllocateCopyPool (StrSize (Dialog->BodyInputStringArray[Index]), Dialog->BodyInputStringArray[Index]); CreateValueAsString (&Control->HiiValue, Dialog->ConfirmHiiValue.BufferLen, AllocateCopyPool (StrSize (Control->Text.String), Control->Text.String)); break; } ContentItem->Selectable = TRUE; Count++; } return EFI_SUCCESS; } /** Initialize hot key item of content item in question panel @param[in] Dialog A pointer to dialog @param[in] PanelItemId Hot key item ID @param[in, out] PanelItem A pointer to hot key item @retval EFI_SUCCESS Initialize hot key item successful. @retval EFI_INVALID_PARAMETER Dialog or PanelItem is NULL. @retval EFI_OUT_OF_RESOURCES Allocate pool fail. **/ EFI_STATUS QuestionPanelInitContentHotKeyItem ( IN H2O_FORM_BROWSER_D *Dialog, IN UINT32 PanelItemId, IN OUT H2O_LTDE_PANEL_ITEM *PanelItem ) { H2O_LTDE_CONTROL *Control; UINT32 ControlId; CHAR16 String[2]; if (Dialog == NULL || PanelItem == NULL) { return EFI_INVALID_PARAMETER; } switch (PanelItemId) { case LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP: String[0] = GEOMETRICSHAPE_UP_TRIANGLE; ControlId = LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_UP; break; case LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN: String[0] = GEOMETRICSHAPE_DOWN_TRIANGLE; ControlId = LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_DOWN; break; case LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_UP: String[0] = GEOMETRICSHAPE_UP_TRIANGLE; ControlId = LTDE_CONTROL_ID_DIALOG_HOT_KEY_SCROLL_UP; break; case LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_DOWN: String[0] = GEOMETRICSHAPE_DOWN_TRIANGLE; ControlId = LTDE_CONTROL_ID_DIALOG_HOT_KEY_SCROLL_DOWN; break; default: return EFI_UNSUPPORTED; } String[1] = CHAR_NULL; Control = AllocateZeroPool (sizeof (H2O_LTDE_CONTROL)); if (Control == NULL) { return EFI_OUT_OF_RESOURCES; } Control->ControlId = ControlId; Control->Operand = GetOpCodeByDialogType (Dialog->DialogType); Control->Selectable = TRUE; Control->Text.String = AllocateCopyPool (sizeof(String), String); Control->ControlStyle.PseudoClass = GetPseudoClass (Dialog->DialogType); PanelItem->ItemId = PanelItemId; PanelItem->Hidden = TRUE; PanelItem->Selectable = TRUE; PanelItem->ControlCount = 1; PanelItem->ControlList = Control; return EFI_SUCCESS; } /** Initialize button item in question panel @param[in] Dialog A pointer to dialog @param[in, out] ButtonItem A pointer to content item @retval EFI_SUCCESS Initialize hot key item successful. @retval EFI_INVALID_PARAMETER Dialog or ButtonItem is NULL. @retval EFI_OUT_OF_RESOURCES Allocate pool fail. **/ EFI_STATUS QuestionPanelInitButtonItem ( IN H2O_FORM_BROWSER_D *Dialog, IN OUT H2O_LTDE_PANEL_ITEM *ButtonItem ) { H2O_LTDE_CONTROL *ControlList; H2O_LTDE_CONTROL *Control; UINT32 Index; UINT8 Operand; UINT32 PseudoClass; if (Dialog == NULL || ButtonItem == NULL) { return EFI_INVALID_PARAMETER; } ButtonItem->ItemId = LTDE_PANEL_ITEM_ID_BUTTON; ButtonItem->Hidden = TRUE; // // Initialize the child control array of panel button control from button of dialog event // if (Dialog->ButtonCount == 0) { return EFI_SUCCESS; } ControlList = AllocateZeroPool (Dialog->ButtonCount * sizeof (H2O_LTDE_CONTROL)); if (ControlList == NULL) { return EFI_OUT_OF_RESOURCES; } ButtonItem->Hidden = FALSE; ButtonItem->Selectable = TRUE; ButtonItem->ControlCount = Dialog->ButtonCount; ButtonItem->ControlList = ControlList; ButtonItem->Vertical = FALSE; Operand = GetOpCodeByDialogType (Dialog->DialogType); PseudoClass = GetPseudoClass (Dialog->DialogType); for (Index = 0; Index < Dialog->ButtonCount; Index++) { Control = &ControlList[Index]; Control->ControlId = LTDE_CONTROL_ID_DIALOG_BUTTON; Control->Operand = Operand; Control->Sequence = (UINT8) Index; Control->Text.String = CatSPrint (NULL, L"[%s]", Dialog->ButtonStringArray[Index]); Control->Selectable = TRUE; Control->ControlStyle.PseudoClass = PseudoClass; if (Dialog->ButtonHiiValueArray != NULL) { CopyHiiValue (&Control->HiiValue, &Dialog->ButtonHiiValueArray[Index]); } else { CreateValueAsUint64 (&Control->HiiValue, (UINT64) Index); } } return EFI_SUCCESS; } /** Display content item in question panel @param[in] QuestionPanel A pointer to question panel instance @param[in, out] ContentItem A pointer to content item @retval EFI_SUCCESS Display content item successful. @retval EFI_INVALID_PARAMETER QuestionPanel or ContentItem is NULL. **/ EFI_STATUS DisplayContentItem ( IN H2O_LTDE_PANEL *QuestionPanel, IN H2O_LTDE_PANEL_ITEM *ContentItem ) { UINT32 Index; UINT32 DlgBodyCount; UINT32 DlgBodyInputCount; INT32 DisplayStartY; INT32 DisplayEndY; UINT32 FieldWidth; UINT32 FieldHeight; UINT32 LineIndex; UINT32 LineCount; INT32 Y; RECT Field; H2O_LTDE_CONTROL *DlgBodyControl; H2O_LTDE_CONTROL *DlgBodyInputControl; UINT32 StringArrayNum; CHAR16 **StringArray; CHAR16 *String; EFI_STATUS Status; if (ContentItem == NULL) { return EFI_INVALID_PARAMETER; } if (ContentItem->ControlList == NULL || ContentItem->ControlCount == 0) { ClearField (QuestionPanel->ColorAttribute, &ContentItem->ItemField); return EFI_SUCCESS; } DlgBodyCount = GetControlCountById (ContentItem, LTDE_CONTROL_ID_DIALOG_BODY); DlgBodyInputCount = GetControlCountById (ContentItem, LTDE_CONTROL_ID_DIALOG_BODY_INPUT); DisplayStartY = ContentItem->CurrentPos; DisplayEndY = DisplayStartY + H2O_LTDE_FIELD_HEIGHT(&ContentItem->ItemField) - 1; if (DlgBodyCount != 0) { for (Index = 0; Index < DlgBodyCount; Index++) { DlgBodyControl = FindControlByControlId (ContentItem->ControlList, ContentItem->ControlCount, LTDE_CONTROL_ID_DIALOG_BODY, Index); if (DlgBodyControl == NULL || !IS_OVERLAP(DlgBodyControl->ControlField.top, DlgBodyControl->ControlField.bottom, DisplayStartY, DisplayEndY)) { continue; } FieldWidth = H2O_LTDE_FIELD_WIDTH(&DlgBodyControl->ControlField); Status = GetStringArrayByWidth (DlgBodyControl->Text.String, FieldWidth, &StringArrayNum, &StringArray); if (EFI_ERROR (Status)) { continue; } FieldHeight = H2O_LTDE_FIELD_HEIGHT(&DlgBodyControl->ControlField); LineCount = MAX (FieldHeight, StringArrayNum); for (LineIndex = 0; LineIndex < LineCount; LineIndex++) { Y = DlgBodyControl->ControlField.top + LineIndex; if (!IN_RANGE (Y, DisplayStartY, DisplayEndY)) { continue; } ASSERT(Y == DisplayStartY); DisplayStartY++; String = GetAlignmentString ( (LineIndex < StringArrayNum) ? StringArray[LineIndex] : L"", (DlgBodyInputCount == 0) ? FieldWidth : FieldWidth + DIALOG_SEPARATION_WIDTH, LTDE_STRING_ALIGNMENT_ACTION_FLUSH_LEFT ); if (String == NULL) { continue; } if (DlgBodyControl == QuestionPanel->SelectedControl) { DisplayQuestionPanelControl (QuestionPanel, DlgBodyControl, TRUE); } else { DEConOutSetAttribute (QuestionPanel->ColorAttribute); DisplayString ( ContentItem->ItemField.left + DlgBodyControl->ControlField.left, ContentItem->ItemField.top + Y - ContentItem->CurrentPos, String ); } FreePool (String); } for (LineIndex = 0; LineIndex < StringArrayNum; LineIndex++) { FreePool (StringArray[LineIndex]); } FreePool (StringArray); } } if (DlgBodyInputCount != 0) { DisplayStartY = ContentItem->CurrentPos; DisplayEndY = DisplayStartY + H2O_LTDE_FIELD_HEIGHT(&ContentItem->ItemField) - 1; for (Index = 0; Index < DlgBodyInputCount; Index++) { DlgBodyInputControl = FindControlByControlId (ContentItem->ControlList, ContentItem->ControlCount, LTDE_CONTROL_ID_DIALOG_BODY_INPUT, Index); if (DlgBodyInputControl == NULL || !IS_OVERLAP(DlgBodyInputControl->ControlField.top, DlgBodyInputControl->ControlField.bottom, DisplayStartY, DisplayEndY)) { continue; } FieldWidth = H2O_LTDE_FIELD_WIDTH(&DlgBodyInputControl->ControlField); Status = GetStringArrayByWidth (DlgBodyInputControl->Text.String, FieldWidth, &StringArrayNum, &StringArray); if (EFI_ERROR (Status)) { StringArrayNum = 0; StringArray = NULL; } FieldHeight = H2O_LTDE_FIELD_HEIGHT(&DlgBodyInputControl->ControlField); LineCount = MAX (FieldHeight, StringArrayNum); for (LineIndex = 0; LineIndex < LineCount; LineIndex++) { Y = DlgBodyInputControl->ControlField.top + LineIndex; if (!IN_RANGE (Y, DisplayStartY, DisplayEndY)) { continue; } ASSERT(Y == DisplayStartY); DisplayStartY++; String = GetAlignmentString ( (LineIndex < StringArrayNum) ? StringArray[LineIndex] : L"", FieldWidth, LTDE_STRING_ALIGNMENT_ACTION_FLUSH_LEFT ); if (String == NULL) { continue; } if (DlgBodyInputControl == QuestionPanel->SelectedControl) { DisplayQuestionPanelControl (QuestionPanel, DlgBodyInputControl, TRUE); } else { DEConOutSetAttribute (PANEL_COLOR_ATTRIBUTE_QUESTION_BODY_INPUT); DisplayString ( ContentItem->ItemField.left + DlgBodyInputControl->ControlField.left, ContentItem->ItemField.top + Y - ContentItem->CurrentPos, String ); } FreePool (String); } if (StringArray != NULL) { for (LineIndex = 0; LineIndex < StringArrayNum; LineIndex++) { FreePool (StringArray[LineIndex]); } FreePool (StringArray); } } } if (DisplayStartY <= DisplayEndY) { Field.left = ContentItem->ItemField.left; Field.right = ContentItem->ItemField.right; Field.top = ContentItem->ItemField.top + DisplayStartY - ContentItem->CurrentPos; Field.bottom = ContentItem->ItemField.top + DisplayEndY - ContentItem->CurrentPos; ClearField (QuestionPanel->ColorAttribute, &Field); } return EFI_SUCCESS; } /** Display panel item in vertical directtion @param[in] Panel A pointer to panel @param[in] PanelItem A pointer to panel item @retval EFI_SUCCESS Display panel item successful. @retval EFI_INVALID_PARAMETER Panel or PanelItem is NULL. **/ STATIC EFI_STATUS DisplayPanelItemInVerticalDirection ( IN H2O_LTDE_PANEL *Panel, IN H2O_LTDE_PANEL_ITEM *PanelItem ) { UINT32 StartX; UINT32 StartY; UINT32 EndY; UINT32 Index; UINT32 StringIndex; UINT32 StringArrayNum; CHAR16 **StringArray; CHAR16 *String; EFI_STATUS Status; UINT32 ControlWidth; H2O_LTDE_CONTROL *Control; if (Panel == NULL || PanelItem == NULL) { return EFI_INVALID_PARAMETER; } if (PanelItem->ControlList == NULL || PanelItem->ControlCount == 0) { ClearField (Panel->ColorAttribute, &PanelItem->ItemField); return EFI_SUCCESS; } StartX = PanelItem->ItemField.left; StartY = PanelItem->ItemField.top; EndY = PanelItem->ItemField.bottom; for (Index = 0; Index < PanelItem->ControlCount && StartY <= EndY; Index++) { Control = &PanelItem->ControlList[Index]; ControlWidth = H2O_LTDE_FIELD_WIDTH(&Control->ControlField); Status = GetStringArrayByWidth (Control->Text.String, ControlWidth, &StringArrayNum, &StringArray); if (EFI_ERROR (Status)) { continue; } for (StringIndex = 0; StringIndex < StringArrayNum && StartY <= EndY; StringIndex++) { String = GetAlignmentString (StringArray[StringIndex], ControlWidth, LTDE_STRING_ALIGNMENT_ACTION_CENTERED); if (String == NULL) { continue; } DisplayString (StartX, StartY++, String); FreePool (String); } for (StringIndex = 0; StringIndex < StringArrayNum; StringIndex++) { SafeFreePool ((VOID **) &StringArray[StringIndex]); } SafeFreePool ((VOID **) &StringArray); } return EFI_SUCCESS; } /** Display panel item in horizontal directtion @param[in] Panel A pointer to panel @param[in] PanelItem A pointer to panel item @retval EFI_SUCCESS Display panel item successful. @retval EFI_INVALID_PARAMETER Panel or PanelItem is NULL. **/ STATIC EFI_STATUS DisplayPanelItemInHorizonalDirection ( IN H2O_LTDE_PANEL *Panel, IN H2O_LTDE_PANEL_ITEM *PanelItem ) { UINT32 PanelItemWidth; UINT32 Index; UINT32 Length; INT32 AbsoluteX; INT32 AbsoluteY; INT32 RelativeX; H2O_LTDE_CONTROL *Control; CHAR16 *SpaceString; CHAR16 *DisplayStr; UINTN DisplayStrSize; if (Panel == NULL || PanelItem == NULL) { return EFI_INVALID_PARAMETER; } PanelItemWidth = H2O_LTDE_FIELD_WIDTH(&PanelItem->ItemField); SpaceString = CreateString (PanelItemWidth, ' '); if (SpaceString == NULL) { return EFI_OUT_OF_RESOURCES; } Length = 0; for (Index = 0; Index < PanelItem->ControlCount; Index++) { Length += (UINT32) StrLen (PanelItem->ControlList[Index].Text.String); } DisplayStrSize = (PanelItemWidth + Length + 1) * sizeof(CHAR16); DisplayStr = AllocateZeroPool (DisplayStrSize); if (DisplayStr == NULL) { return EFI_OUT_OF_RESOURCES; } AbsoluteY = PanelItem->ItemField.top; AbsoluteX = PanelItem->ItemField.left; RelativeX = 0; for (Index = 0; Index < PanelItem->ControlCount; Index++) { Control = &PanelItem->ControlList[Index]; if (Control->ControlField.left > RelativeX) { Length = (UINT32) (Control->ControlField.left - RelativeX); SpaceString[Length] = CHAR_NULL; StrCatS (DisplayStr, DisplayStrSize / sizeof(CHAR16), SpaceString); SpaceString[Length] = L' '; } RelativeX = Control->ControlField.right + 1; if (Control == Panel->SelectedControl) { DEConOutSetAttribute (Panel->ColorAttribute); DisplayString (AbsoluteX, AbsoluteY, DisplayStr); ZeroMem (DisplayStr, DisplayStrSize); AbsoluteX += RelativeX; DisplayQuestionPanelControl (Panel, Control, TRUE); } else { StrCatS (DisplayStr, DisplayStrSize / sizeof(CHAR16), Control->Text.String); } } if ((UINT32) RelativeX < PanelItemWidth) { Length = PanelItemWidth - (UINT32) RelativeX; SpaceString[Length] = CHAR_NULL; StrCatS (DisplayStr, DisplayStrSize / sizeof(CHAR16), SpaceString); SpaceString[Length] = L' '; } DEConOutSetAttribute (Panel->ColorAttribute); DisplayString (AbsoluteX, AbsoluteY, DisplayStr); FreePool (DisplayStr); FreePool (SpaceString); return EFI_SUCCESS; } /** Display panel item @param[in] Panel A pointer to panel @param[in] PanelItem A pointer to panel item @retval EFI_SUCCESS Display panel item successful. @retval EFI_INVALID_PARAMETER Panel or PanelItem is NULL. **/ EFI_STATUS DisplayPanelItem ( IN H2O_LTDE_PANEL *Panel, IN H2O_LTDE_PANEL_ITEM *PanelItem ) { if (PanelItem == NULL) { return EFI_INVALID_PARAMETER; } if (PanelItem->Hidden) { return EFI_ABORTED; } if (PanelItem->ControlList == NULL || PanelItem->ControlCount == 0) { ClearField (Panel->ColorAttribute, &PanelItem->ItemField); return EFI_SUCCESS; } if (PanelItem->Vertical) { return DisplayPanelItemInVerticalDirection (Panel, PanelItem); } else { return DisplayPanelItemInHorizonalDirection (Panel, PanelItem); } } /** Display question panel control @param[in] QuestionPanel A pointer to question panel @param[in] Control A pointer to question panel control @param[in] IsHighlight TRUE if control is highlight @retval EFI_SUCCESS Display question panel control successful. @retval EFI_INVALID_PARAMETER QuestionPanel or Control is NULL. @retval EFI_OUT_OF_RESOURCES Create string fail. @retval EFI_NOT_FOUND Can not find panel item. **/ EFI_STATUS DisplayQuestionPanelControl ( IN H2O_LTDE_PANEL *QuestionPanel, IN H2O_LTDE_CONTROL *Control, IN BOOLEAN IsHighlight ) { H2O_LTDE_PANEL_ITEM *PanelItem; UINT32 Attribute; UINT32 PseudoClass; EFI_STATUS Status; UINT32 Index; UINT32 ControlFieldWidth; UINT32 FieldHeight; UINT32 StringArrayNum; CHAR16 **StringArray; INT32 AbsoluteX; INT32 RelativeY; INT32 DisplayStartY; INT32 DisplayEndY; CHAR16 *LineString; CHAR16 *String; UINT32 Action; if (QuestionPanel == NULL || Control == NULL) { return EFI_INVALID_PARAMETER; } PseudoClass = IsHighlight ? H2O_STYLE_PSEUDO_CLASS_FOCUS : Control->ControlStyle.PseudoClass; GetPanelColorAttribute (QuestionPanel->VfcfPanelInfo, NULL, H2O_IFR_STYLE_TYPE_PANEL, PseudoClass, &Attribute); DEConOutSetAttribute (Attribute); ControlFieldWidth = H2O_LTDE_FIELD_WIDTH (&Control->ControlField); LineString = CreateString (ControlFieldWidth, L' '); if (LineString == NULL) { return EFI_OUT_OF_RESOURCES; } Status = GetStringArrayByWidth (Control->Text.String, ControlFieldWidth, &StringArrayNum, &StringArray); if (EFI_ERROR (Status)) { StringArrayNum = 0; StringArray = NULL; } PanelItem = GetPanelItemByControl (QuestionPanel, Control); if (PanelItem == NULL) { return EFI_NOT_FOUND; } Action = (PanelItem->ItemId == LTDE_PANEL_ITEM_ID_CONTENT) ? LTDE_STRING_ALIGNMENT_ACTION_FLUSH_LEFT : LTDE_STRING_ALIGNMENT_ACTION_CENTERED; if (PanelItem->Vertical) { DisplayStartY = PanelItem->CurrentPos; DisplayEndY = DisplayStartY + H2O_LTDE_FIELD_HEIGHT (&PanelItem->ItemField) - 1; RelativeY = Control->ControlField.top; AbsoluteX = PanelItem->ItemField.left + Control->ControlField.left; FieldHeight = H2O_LTDE_FIELD_HEIGHT (&Control->ControlField); for (Index = 0; Index < FieldHeight; Index++, RelativeY++) { if (!IN_RANGE (RelativeY, DisplayStartY, DisplayEndY)) { continue; } if (Index < StringArrayNum) { String = GetAlignmentString (StringArray[Index], ControlFieldWidth, Action); if (String == NULL) { continue; } DisplayString (AbsoluteX, PanelItem->ItemField.top + RelativeY - DisplayStartY, String); FreePool (String); } else { DisplayString (AbsoluteX, PanelItem->ItemField.top + RelativeY - DisplayStartY, LineString); } } } else { DisplayString ( PanelItem->ItemField.left + Control->ControlField.left, PanelItem->ItemField.top + Control->ControlField.top, Control->Text.String ); } FreePool (LineString); for (Index = 0; Index < StringArrayNum; Index++) { SafeFreePool ((VOID **) &StringArray[Index]); } SafeFreePool ((VOID **) &StringArray); return EFI_SUCCESS; } /** Display question panel @param[in] QuestionPanel A pointer to question panel @retval EFI_SUCCESS Display question panel control successful. @retval EFI_INVALID_PARAMETER QuestionPanel or Control is NULL. @retval EFI_OUT_OF_RESOURCES Create string fail. **/ EFI_STATUS DisplayQuestionPanel ( IN H2O_LTDE_PANEL *QuestionPanel ) { H2O_LTDE_PANEL_ITEM *TitleItem; H2O_LTDE_PANEL_ITEM *ContentItem; H2O_LTDE_PANEL_ITEM *ButtonItem; H2O_LTDE_PANEL_ITEM *PanelItem; UINT32 SeparationStrLen; CHAR16 *SeparationStr; CHAR16 *SpaceStr; if (QuestionPanel == NULL) { return EFI_INVALID_PARAMETER; } DEConOutSetAttribute (QuestionPanel->BorderColorAttribute); if (QuestionPanel->BorderLineWidth > 0) { PrintBorderLineFunc (&QuestionPanel->PanelField, NULL); } DEConOutSetAttribute (QuestionPanel->ColorAttribute); SeparationStrLen = H2O_LTDE_FIELD_WIDTH(&QuestionPanel->PanelField); SeparationStr = CreateString (SeparationStrLen, BOXDRAW_HORIZONTAL); if (SeparationStr == NULL) { return EFI_OUT_OF_RESOURCES; } if (QuestionPanel->BorderLineWidth > 0) { SeparationStr[0] = BOXDRAW_VERTICAL_RIGHT; SeparationStr[SeparationStrLen - 1] = BOXDRAW_VERTICAL_LEFT; } TitleItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_TITLE); if (TitleItem != NULL && !TitleItem->Hidden) { DisplayPanelItem (QuestionPanel, TitleItem); } ContentItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT); if (ContentItem != NULL && !ContentItem->Hidden) { if (TitleItem != NULL && !TitleItem->Hidden) { DEConOutSetAttribute (QuestionPanel->BorderColorAttribute); DisplayString (QuestionPanel->PanelField.left, TitleItem->ItemField.bottom + 1, SeparationStr); DEConOutSetAttribute (QuestionPanel->ColorAttribute); } DisplayContentItem (QuestionPanel, ContentItem); } ButtonItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_BUTTON); if (ButtonItem != NULL && !ButtonItem->Hidden) { if (ContentItem != NULL && !ContentItem->Hidden) { if (TitleItem != NULL && !TitleItem->Hidden) { SpaceStr = SeparationStrLen > 2 ? CreateString (SeparationStrLen - 2, ' ') : NULL; if (SpaceStr != NULL) { DisplayString (QuestionPanel->PanelField.left + 1, ContentItem->ItemField.bottom + 1, SpaceStr); FreePool (SpaceStr); } } else { DEConOutSetAttribute (QuestionPanel->BorderColorAttribute); DisplayString (QuestionPanel->PanelField.left, ContentItem->ItemField.bottom + 1, SeparationStr); DEConOutSetAttribute (QuestionPanel->ColorAttribute); } } DisplayPanelItem (QuestionPanel, ButtonItem); } DEConOutSetAttribute (QuestionPanel->ColorAttribute); PanelItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP); if (PanelItem != NULL) { DisplayPanelItem (QuestionPanel, PanelItem); } PanelItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN); if (PanelItem != NULL) { DisplayPanelItem (QuestionPanel, PanelItem); } PanelItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_UP); if (PanelItem != NULL) { DisplayPanelItem (QuestionPanel, PanelItem); } PanelItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_DOWN); if (PanelItem != NULL) { DisplayPanelItem (QuestionPanel, PanelItem); } FreePool (SeparationStr); return EFI_SUCCESS; } /** Shutdown question panel @param[in] QuestionPanel A pointer to question panel @retval EFI_SUCCESS Shutdown question panel successful. **/ EFI_STATUS ShutdownQuestionPanel ( IN H2O_LTDE_PANEL *QuestionPanel ) { if (QuestionPanel != NULL) { FreePanelItemList (QuestionPanel->ItemList, QuestionPanel->ItemCount); QuestionPanel->ItemList = NULL; QuestionPanel->ItemCount = 0; H2OFreePool ((VOID **) &QuestionPanel->Data); } return EFI_SUCCESS; } /** Process page down for content item @param[in] QuestionPanel A pointer to question panel @retval EFI_SUCCESS Process page down successful. @retval EFI_INVALID_PARAMETER QuestionPanel is NULL. @retval EFI_ABORTED Can not find panel item. **/ STATIC EFI_STATUS ContentItemPageDown ( IN H2O_LTDE_PANEL *QuestionPanel ) { H2O_LTDE_PANEL_ITEM *ContentItem; H2O_LTDE_PANEL_ITEM *PageUpItem; H2O_LTDE_PANEL_ITEM *PageDownItem; H2O_LTDE_PANEL_ITEM *SelectedPanelItem; INT32 ContentItemHeight; if (QuestionPanel == NULL) { return EFI_INVALID_PARAMETER; } ContentItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT); PageUpItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP); PageDownItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN); if (ContentItem == NULL || PageUpItem == NULL || PageDownItem == NULL) { return EFI_ABORTED; } ContentItemHeight = H2O_LTDE_FIELD_HEIGHT(&ContentItem->ItemField); if (ContentItem->CurrentPos + ContentItemHeight > ContentItem->MaxPos) { return EFI_SUCCESS; } PageUpItem->Hidden = FALSE; ContentItem->CurrentPos += ContentItemHeight; if (ContentItem->CurrentPos + ContentItemHeight > ContentItem->MaxPos) { PageDownItem->Hidden = TRUE; SelectedPanelItem = GetPanelItemByControl (QuestionPanel, QuestionPanel->SelectedControl); if (QuestionPanel->SelectedControl != NULL && SelectedPanelItem != NULL && SelectedPanelItem->ItemId == LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN) { QuestionPanel->SelectedControl = GetNextSelectableControl (PageUpItem, NULL, FALSE); } } DisplayQuestionPanel (QuestionPanel); return EFI_SUCCESS; } /** Process page up for content item @param[in] QuestionPanel A pointer to question panel @retval EFI_SUCCESS Process page up successful. @retval EFI_INVALID_PARAMETER QuestionPanel is NULL. @retval EFI_ABORTED Can not find panel item. **/ EFI_STATUS ContentItemPageUp ( IN H2O_LTDE_PANEL *QuestionPanel ) { H2O_LTDE_PANEL_ITEM *ContentItem; H2O_LTDE_PANEL_ITEM *PageUpItem; H2O_LTDE_PANEL_ITEM *PageDownItem; H2O_LTDE_PANEL_ITEM *SelectedPanelItem; INT32 ContentItemHeight; if (QuestionPanel == NULL) { return EFI_INVALID_PARAMETER; } ContentItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT); PageUpItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP); PageDownItem = GetPanelItem (QuestionPanel, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN); if (ContentItem == NULL || PageUpItem == NULL || PageDownItem == NULL) { return EFI_ABORTED; } if (ContentItem->CurrentPos == 0) { return EFI_SUCCESS; } PageDownItem->Hidden = FALSE; ContentItemHeight = H2O_LTDE_FIELD_HEIGHT(&ContentItem->ItemField); if (ContentItem->CurrentPos < ContentItemHeight) { ContentItem->CurrentPos = 0; } else { ContentItem->CurrentPos -= ContentItemHeight; } if (ContentItem->CurrentPos == 0) { PageUpItem->Hidden = TRUE; SelectedPanelItem = GetPanelItemByControl (QuestionPanel, QuestionPanel->SelectedControl); if (QuestionPanel->SelectedControl != NULL && SelectedPanelItem != NULL && SelectedPanelItem->ItemId == LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP) { QuestionPanel->SelectedControl = GetNextSelectableControl (PageDownItem, NULL, FALSE); } } DisplayQuestionPanel (QuestionPanel); return EFI_SUCCESS; } /** Get default highlight control in question panel @param[in] QuestionPanel A pointer to question panel @return The default highlight control or NULL if not found ot QuestionPanel is NULL. **/ H2O_LTDE_CONTROL * QuestionPanelGetDefaultHighlight ( IN H2O_LTDE_PANEL *QuestionPanel ) { H2O_LTDE_CONTROL *HighlightControl; H2O_LTDE_CONTROL *Control; H2O_LTDE_PANEL_ITEM *PanelItem; if (QuestionPanel == NULL) { return NULL; } HighlightControl = NULL; Control = NULL; while (TRUE) { Control = GetNextSelectableControlInQuestionPanel (QuestionPanel, Control, FALSE); PanelItem = GetPanelItemByControl (QuestionPanel, Control); if (Control == NULL || PanelItem == NULL) { break; } if (HighlightControl == NULL) { HighlightControl = Control; } if (PanelItem->ItemId == LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP || PanelItem->ItemId == LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN || PanelItem->ItemId == LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_UP || PanelItem->ItemId == LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_DOWN) { continue; } HighlightControl = Control; break; } return HighlightControl; } /** Process open dialog event in question panel @param[in] Dialog A pointer to dialog data @param[in] QuestionPanel A pointer to question panel @retval EFI_SUCCESS Process open dialog event successful. @retval EFI_INVALID_PARAMETER Dialog or QuestionPanel is NULL. **/ EFI_STATUS QuestionPanelProcessOpenDEvt ( IN H2O_FORM_BROWSER_D *Dialog, IN H2O_LTDE_PANEL *QuestionPanel ) { EFI_STATUS Status; if (Dialog == NULL || QuestionPanel == NULL) { return EFI_INVALID_PARAMETER; } Status = GetPanelColorAttribute (QuestionPanel->VfcfPanelInfo, NULL, H2O_IFR_STYLE_TYPE_PANEL, GetPseudoClass (Dialog->DialogType), &QuestionPanel->ColorAttribute); if (EFI_ERROR (Status)) { QuestionPanel->ColorAttribute = PANEL_COLOR_ATTRIBUTE_QUESTION; } return EFI_SUCCESS; } /** Process user input in question panel @param[in] QuestionPanel A pointer to question panel @param[in] UserInputData A pointer to user input data @param[out] SelectedControl A pointer to user selected control @param[out] InputString A pointer to user input string @param[out] IsShutdownDialog A pointer to flag which determine to shutdown dialog @retval EFI_SUCCESS Process user input successful. @retval EFI_INVALID_PARAMETER Input parameter is NULL. @retval EFI_ABORTED Current highlight control is NULL. **/ EFI_STATUS QuestionPanelProcessUserInput ( IN H2O_LTDE_PANEL *QuestionPanel, IN H2O_DISPLAY_ENGINE_USER_INPUT_DATA *UserInputData, OUT H2O_LTDE_CONTROL **SelectedControl, OUT CHAR16 **InputString, OUT BOOLEAN *IsShutdownDialog ) { UINTN StringLength; EFI_INPUT_KEY *InputKey; H2O_LTDE_CONTROL *CurrentControl; H2O_LTDE_CONTROL *NextControl; H2O_LTDE_PANEL_ITEM *PanelItem; EFI_STATUS Status; CHAR16 *NewInputString; RECT ControlAbsField; if (UserInputData == NULL || QuestionPanel == NULL || SelectedControl == NULL || InputString == NULL || IsShutdownDialog == NULL) { return EFI_INVALID_PARAMETER; } InputKey = &UserInputData->KeyData.Key; NextControl = NULL; NewInputString = NULL; if ((InputKey->ScanCode == SCAN_ESC) || (InputKey->UnicodeChar == CHAR_CARRIAGE_RETURN && QuestionPanel->SelectedControl == NULL)) { *SelectedControl = NextControl; *InputString = NewInputString; *IsShutdownDialog = TRUE; return EFI_SUCCESS; } if (UserInputData->IsKeyboard) { CurrentControl = QuestionPanel->SelectedControl; if (CurrentControl == NULL) { return EFI_ABORTED; } switch (InputKey->UnicodeChar) { case CHAR_TAB: NextControl = CurrentControl; while (TRUE) { NextControl = GetNextSelectableControlInQuestionPanel (QuestionPanel, NextControl, TRUE); if (NextControl == NULL || NextControl == CurrentControl || (NextControl->ControlId != LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_UP && NextControl->ControlId != LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_DOWN && NextControl->ControlId != LTDE_CONTROL_ID_DIALOG_HOT_KEY_SCROLL_UP && NextControl->ControlId != LTDE_CONTROL_ID_DIALOG_HOT_KEY_SCROLL_DOWN)) { break; } } break; case CHAR_BACKSPACE: if (CurrentControl->ControlId == LTDE_CONTROL_ID_DIALOG_BODY_INPUT) { StringLength = StrLen (CurrentControl->Text.String); if (StringLength > 0) { NewInputString = AllocateZeroPool (StringLength * sizeof (CHAR16)); CopyMem (NewInputString, CurrentControl->Text.String, (StringLength - 1) * sizeof (CHAR16)); } } break; case CHAR_CARRIAGE_RETURN: switch (CurrentControl->ControlId) { case LTDE_CONTROL_ID_DIALOG_BODY_INPUT: NextControl = GetNextSelectableControlInQuestionPanel (QuestionPanel, CurrentControl, FALSE); if (NextControl == NULL) { NextControl = CurrentControl; } break; case LTDE_CONTROL_ID_DIALOG_BODY: case LTDE_CONTROL_ID_DIALOG_BUTTON: NextControl = CurrentControl; break; case LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_UP: ContentItemPageUp (QuestionPanel); break; case LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_DOWN: ContentItemPageDown (QuestionPanel); break; } break; case CHAR_NULL: switch (InputKey->ScanCode) { case SCAN_PAGE_UP: ContentItemPageUp (QuestionPanel); break; case SCAN_PAGE_DOWN: ContentItemPageDown (QuestionPanel); break; case SCAN_RIGHT: case SCAN_LEFT: PanelItem = GetPanelItemByControl (QuestionPanel, CurrentControl); if (PanelItem == NULL || PanelItem->Vertical) { return EFI_ABORTED; } if (InputKey->ScanCode == SCAN_RIGHT) { NextControl = GetNextSelectableControl (PanelItem, CurrentControl, FALSE); } else { NextControl = GetPreviousSelectableControl (PanelItem, CurrentControl, FALSE); } break; case SCAN_UP: case SCAN_DOWN: PanelItem = GetPanelItemByControl (QuestionPanel, CurrentControl); if (PanelItem == NULL || !PanelItem->Vertical || CurrentControl->ControlId == LTDE_CONTROL_ID_DIALOG_BODY_INPUT) { return EFI_ABORTED; } if (InputKey->ScanCode == SCAN_UP) { NextControl = GetPreviousSelectableControl (PanelItem, CurrentControl, FALSE); } else { NextControl = GetNextSelectableControl (PanelItem, CurrentControl, FALSE); } break; } break; default: if (CurrentControl->ControlId == LTDE_CONTROL_ID_DIALOG_BODY_INPUT) { if (IsVisibleChar (InputKey->UnicodeChar)) { NewInputString = CatSPrint (NULL, L"%s%c", CurrentControl->Text.String, InputKey->UnicodeChar); break; } } return EFI_ABORTED; } } else { // // Process mouse event // if (InputKey->UnicodeChar != CHAR_CARRIAGE_RETURN) { return EFI_NOT_FOUND; } Status = GetControlByMouse (QuestionPanel, UserInputData->CursorX, UserInputData->CursorY, &PanelItem, &NextControl); if (EFI_ERROR (Status) || !NextControl->Selectable) { return EFI_NOT_FOUND; } if (NextControl == QuestionPanel->SelectedControl) { switch (NextControl->ControlId) { case LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_UP: ContentItemPageUp (QuestionPanel); NextControl = NULL; break; case LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_DOWN: ContentItemPageDown (QuestionPanel); NextControl = NULL; break; case LTDE_CONTROL_ID_DIALOG_BODY_INPUT: CopyRect (&ControlAbsField, &NextControl->ControlField); OffsetRect (&ControlAbsField, PanelItem->ItemField.left, PanelItem->ItemField.top - PanelItem->CurrentPos); InitializeVirtualKb (&ControlAbsField); NextControl = NULL; break; } } } *SelectedControl = NextControl; *InputString = NewInputString; *IsShutdownDialog = FALSE; return EFI_SUCCESS; } /** Process open dialog event for simple dialog @param[in] Dialog A pointer to dialog data @param[in] QuestionPanel A pointer to question panel @retval EFI_SUCCESS Process open dialog event successful. @retval EFI_INVALID_PARAMETER Dialog or QuestionPanel is NULL. @retval EFI_OUT_OF_RESOURCES Allocate pool fail. **/ STATIC EFI_STATUS SimpleDialogProcessOpenDEvt ( IN H2O_FORM_BROWSER_D *Dialog, IN H2O_LTDE_PANEL *QuestionPanel ) { UINT32 ItemCount; H2O_LTDE_PANEL_ITEM *ItemList; H2O_LTDE_PANEL_ITEM *ContentItem; EFI_STATUS Status; BOOLEAN ShowTitle; if (Dialog == NULL || QuestionPanel == NULL) { return EFI_INVALID_PARAMETER; } ShowTitle = (GetPseudoClass (Dialog->DialogType) == H2O_STYLE_PSEUDO_CLASS_HELP) || ((Dialog->DialogType & H2O_FORM_BROWSER_D_TYPE_CONFIRM) != 0); ItemCount = ShowTitle ? 5 : 4; ItemList = (H2O_LTDE_PANEL_ITEM *) AllocateZeroPool (sizeof (H2O_LTDE_PANEL_ITEM) * ItemCount); if (ItemList == NULL) { return EFI_OUT_OF_RESOURCES; } ItemCount = 0; if (ShowTitle) { QuestionPanelInitTitleItem (Dialog, &ItemList[ItemCount++]); } ContentItem = &ItemList[ItemCount]; QuestionPanelInitContentItem (Dialog, &ItemList[ItemCount++]); QuestionPanelInitButtonItem (Dialog, &ItemList[ItemCount++]); if (ContentItem->Selectable) { QuestionPanelInitContentHotKeyItem (Dialog, LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_UP , &ItemList[ItemCount++]); QuestionPanelInitContentHotKeyItem (Dialog, LTDE_PANEL_ITEM_ID_CONTENT_SCROLL_DOWN, &ItemList[ItemCount++]); } else { QuestionPanelInitContentHotKeyItem (Dialog, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_UP , &ItemList[ItemCount++]); QuestionPanelInitContentHotKeyItem (Dialog, LTDE_PANEL_ITEM_ID_CONTENT_PAGE_DOWN, &ItemList[ItemCount++]); } FreePanelItemList (QuestionPanel->ItemList, QuestionPanel->ItemCount); QuestionPanel->ItemCount = ItemCount; QuestionPanel->ItemList = ItemList; Status = QuestionPanelUpdateField (Dialog, QuestionPanel); QuestionPanel->SelectedControl = QuestionPanelGetDefaultHighlight (QuestionPanel); return DisplayQuestionPanel (QuestionPanel); } /** Process event for simple dialog @param[in] Notify A pointer to notify event @param[in] UserInputData A pointer to user input data @param[in] QuestionPanel A pointer to question panel @retval EFI_SUCCESS Process open dialog event successful. @retval EFI_UNSUPPORTED Event type is not supported. @retval Other Process event fail. **/ STATIC EFI_STATUS SimpleDialogProcessEvt ( IN CONST H2O_DISPLAY_ENGINE_EVT *Notify, IN H2O_DISPLAY_ENGINE_USER_INPUT_DATA *UserInputData, IN H2O_LTDE_PANEL *QuestionPanel ) { EFI_STATUS Status; H2O_LTDE_CONTROL *SelectedControl; CHAR16 *UpdatedString; BOOLEAN IsShutdownDialog; Status = EFI_UNSUPPORTED; switch (Notify->Type) { case H2O_DISPLAY_ENGINE_EVT_TYPE_OPEN_D: return SimpleDialogProcessOpenDEvt (&((H2O_DISPLAY_ENGINE_EVT_OPEN_D *) Notify)->Dialog, QuestionPanel); case H2O_DISPLAY_ENGINE_EVT_TYPE_SHUT_D: return ShutdownQuestionPanel (QuestionPanel); case H2O_DISPLAY_ENGINE_EVT_TYPE_KEYPRESS: case H2O_DISPLAY_ENGINE_EVT_TYPE_REL_PTR_MOVE: case H2O_DISPLAY_ENGINE_EVT_TYPE_ABS_PTR_MOVE: if (UserInputData == NULL || mDEPrivate->DEStatus != DISPLAY_ENGINE_STATUS_AT_POPUP_DIALOG) { return Status; } Status = QuestionPanelProcessUserInput ( QuestionPanel, UserInputData, &SelectedControl, &UpdatedString, &IsShutdownDialog ); if (EFI_ERROR (Status)) { break; } if (SelectedControl != NULL) { if (SelectedControl == QuestionPanel->SelectedControl) { Status = SendChangeQNotify (0, 0, &QuestionPanel->SelectedControl->HiiValue); } else { switch (SelectedControl->ControlId) { case LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_UP: if (!UserInputData->IsKeyboard) { ContentItemPageUp (QuestionPanel); } break; case LTDE_CONTROL_ID_DIALOG_HOT_KEY_PAGE_DOWN: if (!UserInputData->IsKeyboard) { ContentItemPageDown (QuestionPanel); } break; default: DisplayQuestionPanelControl (QuestionPanel, QuestionPanel->SelectedControl, FALSE); QuestionPanel->SelectedControl = SelectedControl; DisplayQuestionPanelControl (QuestionPanel, QuestionPanel->SelectedControl, TRUE); break; } } } if (IsShutdownDialog) { Status = SendShutDNotify (); } break; default: break; } return Status; } /** Get dialog information @param[in] QuestionPanel A pointer to question panel @param[in] Notify A pointer to notify event @param[out] IsQuestion A pointer to flag to determine it is question dialog or not @param[out] QuestionOpCode A pointer to question opcode @retval EFI_SUCCESS Get dialog information successful. @retval EFI_INVALID_PARAMETER Input parameter is NULL. **/ STATIC EFI_STATUS GetDialogInfo ( IN H2O_LTDE_PANEL *QuestionPanel, IN CONST H2O_DISPLAY_ENGINE_EVT *Notify, OUT BOOLEAN *IsQuestion, OUT UINT8 *QuestionOpCode ) { H2O_DISPLAY_ENGINE_EVT_OPEN_D *OpenDNotify; if (QuestionPanel == NULL || Notify == NULL || IsQuestion == NULL || QuestionOpCode == NULL) { return EFI_INVALID_PARAMETER; } // // Get dialog info from OPEN_D event because ControlArray of Question Panel is not initialized. // if (Notify->Type == H2O_DISPLAY_ENGINE_EVT_TYPE_OPEN_D) { OpenDNotify = (H2O_DISPLAY_ENGINE_EVT_OPEN_D *) Notify; *IsQuestion = ((OpenDNotify->Dialog.DialogType & H2O_FORM_BROWSER_D_TYPE_QUESTIONS) == 0) ? FALSE : TRUE; *QuestionOpCode = *IsQuestion ? GetOpCodeByDialogType (OpenDNotify->Dialog.DialogType) : 0; if (QuestionPanel->Data == NULL) { QuestionPanel->Data = AllocateZeroPool (sizeof (H2O_LTDE_QUESTION_PANEL_PRIVATE_DATA)); if (QuestionPanel->Data == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (&((H2O_LTDE_QUESTION_PANEL_PRIVATE_DATA *) QuestionPanel->Data)->Dialog, &OpenDNotify->Dialog, sizeof (H2O_FORM_BROWSER_D)); } return EFI_SUCCESS; } // // Get dialog info from ControlArray of Question Panel. // if (QuestionPanel->SelectedControl != NULL) { *IsQuestion = (QuestionPanel->SelectedControl->Operand != 0) ? TRUE : FALSE; *QuestionOpCode = QuestionPanel->SelectedControl->Operand; } else { *IsQuestion = FALSE; *QuestionOpCode = 0; } return EFI_SUCCESS; } /** Process event in question function @param[in] Notify A pointer to notify event @param[in] UserInputData A pointer to user input data @retval EFI_SUCCESS Process event successful. @retval Other Process event fail. **/ EFI_STATUS ProcessEvtInQuestionFunc ( IN CONST H2O_DISPLAY_ENGINE_EVT *Notify, IN H2O_DISPLAY_ENGINE_USER_INPUT_DATA *UserInputData ) { EFI_STATUS Status; H2O_FORM_BROWSER_Q *Question; H2O_DISPLAY_ENGINE_EVT_SHUT_Q *ShutQNotify; H2O_LTDE_PANEL *QuestionPanel; H2O_LTDE_PANEL *SetupPagePanel; BOOLEAN IsQuestion; UINT8 QuestionOpCode; QuestionPanel = GetPanel (QUESTION_PANEL_ID); QuestionOpCode = 0; if (mDEPrivate->DEStatus == DISPLAY_ENGINE_STATUS_AT_POPUP_DIALOG) { Status = GetDialogInfo (QuestionPanel, Notify, &IsQuestion, &QuestionOpCode); if (EFI_ERROR (Status)) { return Status; } if (!IsQuestion) { return SimpleDialogProcessEvt (Notify, UserInputData, QuestionPanel); } } else { SetupPagePanel = GetPanel (SETUP_PAGE_PANEL_ID); if (SetupPagePanel != NULL && SetupPagePanel->SelectedControl != NULL) { QuestionOpCode = SetupPagePanel->SelectedControl->Operand; } if (Notify->Type == H2O_DISPLAY_ENGINE_EVT_TYPE_SHUT_Q) { ShutQNotify = (H2O_DISPLAY_ENGINE_EVT_SHUT_Q *) Notify; // // SHUT_Q status must get another specific question // Status = mDEPrivate->FBProtocol->GetQInfo (mDEPrivate->FBProtocol, ShutQNotify->PageId, ShutQNotify->QuestionId, &Question); if (EFI_ERROR (Status)) { return Status; } QuestionOpCode = Question->Operand; SafeFreePool ((VOID **) &Question); } } switch (QuestionOpCode) { case EFI_IFR_CHECKBOX_OP: Status = CheckboxOpCodeProcessEvt (Notify, UserInputData, QuestionPanel); break; case EFI_IFR_NUMERIC_OP: Status = NumericOpCodeProcessEvt (Notify, UserInputData, QuestionPanel); break; case EFI_IFR_ONE_OF_OP: Status = OneOfQuestionProcessEvt (Notify, UserInputData, QuestionPanel); break; case EFI_IFR_ORDERED_LIST_OP: Status = OrderListOpCodeProcessEvt (Notify, UserInputData, QuestionPanel); break; case EFI_IFR_STRING_OP: Status = StringOpCodeProcessEvt (Notify, UserInputData, QuestionPanel); break; case EFI_IFR_PASSWORD_OP: Status = PasswordOpCodeProcessEvt (Notify, UserInputData, QuestionPanel); break; case EFI_IFR_DATE_OP: case EFI_IFR_TIME_OP: Status = DateTimeOpCodeProcessEvt (Notify, UserInputData, QuestionPanel); break; case EFI_IFR_REF_OP: case EFI_IFR_ACTION_OP: case EFI_IFR_RESET_BUTTON_OP: default: Status = EFI_NOT_FOUND; break; } return Status; }