alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2ODisplayEngineLocalTextDxe/LTDEPanels/LTDEQuestionPanel.c

2466 lines
84 KiB
C

/** @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;
}