alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2ODisplayEngineLocalMetroDxe/UiLib/UiFuncs.c

1059 lines
24 KiB
C

/** @file
UI Common Controls
;******************************************************************************
;* Copyright (c) 2012 - 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 "UiControls.h"
#include "UiManager.h"
#include "UiRender.h"
#include "H2ODisplayEngineLocalMetro.h"
#include "MetroUi.h"
UINT32 mDbgNo = 0;
UINT32 mSetPositionLevel = 0;
BOOLEAN mShowSetPositionDbg = FALSE;
BOOLEAN mShowUpdateRegionDbg = FALSE;
STATIC CHAR16 mPaddingChar[201] = {0};
#define MAX_PARENT 128
typedef struct {
UI_CONTROL *Parents[MAX_PARENT];
UI_CONTROL *FirstControl;
CHAR16 *ParentsName[MAX_PARENT];
UINTN Count;
UI_MANAGER *Manager;
HINSTANCE Instance;
} XML_UI_DATA;
VOID
SetUnicodeMem (
IN VOID *Buffer,
IN UINTN Size,
IN CHAR16 Value
)
/*++
Routine Description:
Set Buffer to Value for Size bytes.
Arguments:
Buffer - Memory to set.
Size - Number of bytes to set
Value - Value of the set operation.
Returns:
None
--*/
{
CHAR16 *Ptr;
Ptr = Buffer;
while (Size--) {
*(Ptr++) = Value;
}
}
VOID
ShowSetPositionDbgInfo (
UI_CONTROL *Control,
CONST RECT *Pos
)
{
if (!mShowSetPositionDbg) {
return ;
}
if (mSetPositionLevel == 1) {
SetUnicodeMem (mPaddingChar, 200, '-');
}
if (mSetPositionLevel > 50) {
ASSERT (FALSE);
}
mPaddingChar[(mSetPositionLevel << 1) + 1] = '\0';
DEBUG ((
EFI_D_INFO,
"%06d:SetPosition %4d %4d %4d %4d:%s(%s):%s:%d\n",
mDbgNo++,
Pos->left,
Pos->top,
Pos->right - Pos->left,
Pos->bottom - Pos->top,
mPaddingChar,
Control->Class->ClassName,
((Control->Name[0] != '\0') ? Control->Name : L""),
mSetPositionLevel
));
mPaddingChar[(mSetPositionLevel << 1) + 1] = '-';
}
VOID
ShowUpdateRegionDbgInfo (
UI_CONTROL *Control,
CONST RECT *Pos
)
{
if (!mShowUpdateRegionDbg) {
return;
}
DEBUG ((
EFI_D_INFO, "%06d:UpdateRegion %4d %4d %4d %4d:(%s)\n",
mDbgNo++,
Pos->left,
Pos->top,
Pos->right - Pos->left,
Pos->bottom - Pos->top,
Control->Class->ClassName
));
}
BOOLEAN
EFIAPI
UiSetAttribute (
VOID *This,
CHAR16 *Name,
CHAR16 *Value
)
{
ASSERT (This != NULL);
if (This == NULL) {
return FALSE;
}
return CONTROL_CLASS(This)->SetAttribute ((UI_CONTROL *)This, Name, Value);
}
BOOLEAN
EFIAPI
UiSetAttributeEx (
VOID *This,
CHAR16 *Name,
IN CONST CHAR16 *Format,
...
)
{
VA_LIST Marker;
CHAR16 *ValueStr;
BOOLEAN Result;
VA_START (Marker, Format);
ValueStr = CatVSPrint (NULL, Format, Marker);
VA_END (Marker);
Result = CONTROL_CLASS(This)->SetAttribute ((UI_CONTROL *)This, Name, ValueStr);
FreePool (ValueStr);
return Result;
}
UI_CONTROL *
UiFindChildByName (
VOID *This,
CHAR16 *Name
)
{
return CONTROL_CLASS(This)->FindChildByName ((UI_CONTROL *)This, Name, UI_SEARCH_TYPE_ALL);
}
VOID
EFIAPI
UiApplyAttributeList (
UI_CONTROL *Control,
CHAR16 *StrList
)
{
CHAR16 Name[256];
CHAR16 Value[1024];
UINTN Index;
CHAR16 QuoteChar;
while(*StrList != L'\0') {
Index = 0;
//
// skip space or tab
//
while ((*StrList == L' ') || (*StrList == L'\t')) {
StrList++;
}
while( *StrList != L'\0' && *StrList != L'=') {
Name[Index++] = *StrList++;
}
Name[Index] = '\0';
ASSERT(*StrList == L'=');
if(*StrList++ != L'=') {
return ;
}
ASSERT(*StrList == L'\"' || *StrList == L'\'');
if (*StrList != L'\"' && *StrList != L'\'') {
return ;
}
QuoteChar = *StrList;
StrList++;
Index = 0;
while(*StrList != L'\0' && *StrList != QuoteChar) {
if (*StrList == '\\' && *(StrList + 1) == QuoteChar) {
Value[Index++] = *StrList++;
}
Value[Index++] = *StrList++;
}
Value[Index] = '\0';
ASSERT(*StrList == L'\"' || *StrList == L'\'');
if (*StrList != L'\"' && *StrList != L'\'') {
return ;
}
UiSetAttribute (Control, Name, Value);
StrList++;
if(*StrList != L' ' && *StrList != '\t') {
return ;
}
StrList++;
}
}
UI_CONTROL *
EFIAPI
GetUiControl (
HWND Hwnd
)
{
return (UI_CONTROL *) GetWindowLongPtr (Hwnd, 0);
}
UI_CONTROL *
EFIAPI
CreateControl (
CHAR16 *ControlName,
UI_CONTROL *Parent
)
{
HWND Wnd;
UI_MANAGER *Manager;
Manager = NULL;
if (Parent != NULL) {
Manager = Parent->Manager;
ASSERT (Manager != NULL);
}
Wnd = CreateWindowEx (
WS_EX_NOACTIVATE,
ControlName,
NULL,
((Parent != NULL) ? WS_CHILD : 0) | WS_VISIBLE,
0, 0, 0, 0,
(Parent != NULL) ? Parent->Wnd : NULL,
NULL,
NULL,
Manager
);
ASSERT (Wnd != NULL);
if (Wnd == NULL) {
return NULL;
}
return GetUiControl (Wnd);
}
UI_CONTROL *
EFIAPI
CreateAddControl (
CHAR16 *ControlName,
UI_CONTROL *Parent
)
{
UI_CONTROL *CreatedControl;
CreatedControl = CreateControl (ControlName, Parent);
if (CreatedControl != NULL) {
CONTROL_CLASS(Parent)->AddChild (Parent, CreatedControl);
}
return CreatedControl;
}
INT32
UiLengthToPixelEx (
IN UI_LENGTH *Length,
IN INT32 Available,
IN INT32 FontSize,
IN BOOLEAN IncludeRemainderPixel
)
{
switch (Length->Type) {
case UI_LENGTH_TYPE_PIXEL:
return Length->Value;
case UI_LENGTH_TYPE_PERCENTAGE:
if (IncludeRemainderPixel) {
return (Length->Value * Available) / 100 + ((((Length->Value * Available) % 100) > 0) ? 1 : 0);
} else {
return (Length->Value * Available) / 100;
}
case UI_LENGTH_TYPE_EM:
return (Length->Value * FontSize);
default:
return 0;
}
}
INT32
UiLengthToPixel (
IN UI_LENGTH *Length,
IN INT32 Available,
IN INT32 FontSize
)
{
return UiLengthToPixelEx (Length, Available, FontSize, FALSE);
}
POINT
CalculateControlDisplayXY (
IN UI_CONTROL *Control,
IN SIZE *ControlSize,
IN SIZE *AvailableSize
)
{
POINT Point;
Point.x = 0;
Point.y = 0;
//
// Control display location is determined by Left, Top, Right, Bottom. Top and Left have higher priority.
//
switch (Control->Left.Type) {
case UI_LENGTH_TYPE_PIXEL:
case UI_LENGTH_TYPE_PERCENTAGE:
case UI_LENGTH_TYPE_EM:
Point.x = UiLengthToPixelEx (&Control->Left, AvailableSize->cx, GetControlFontSize (Control), FALSE);
break;
default:
switch (Control->Right.Type) {
case UI_LENGTH_TYPE_PIXEL:
case UI_LENGTH_TYPE_PERCENTAGE:
case UI_LENGTH_TYPE_EM:
Point.x = AvailableSize->cx -
ControlSize->cx -
UiLengthToPixelEx (&Control->Right, AvailableSize->cx, GetControlFontSize (Control), TRUE);
break;
}
}
switch (Control->Top.Type) {
case UI_LENGTH_TYPE_PIXEL:
case UI_LENGTH_TYPE_PERCENTAGE:
case UI_LENGTH_TYPE_EM:
Point.y = UiLengthToPixelEx (&Control->Top, AvailableSize->cy, GetControlFontSize (Control), FALSE);
break;
default:
switch (Control->Bottom.Type) {
case UI_LENGTH_TYPE_PIXEL:
case UI_LENGTH_TYPE_PERCENTAGE:
case UI_LENGTH_TYPE_EM:
Point.y = AvailableSize->cy -
ControlSize->cy -
UiLengthToPixelEx (&Control->Bottom, AvailableSize->cy, GetControlFontSize (Control), TRUE);
break;
}
}
return Point;
}
INT32
CalculateControlDisplayWidth (
IN UI_CONTROL *Control,
IN SIZE AvailableSize
)
{
INT32 Width;
//
// Control display width is determined by Width or (Left,Right). Width has higher priority.
//
switch (Control->Width.Type) {
case UI_LENGTH_TYPE_MATCH_PARENT:
Width = MATCH_PARENT;
break;
case UI_LENGTH_TYPE_WRAP_CONTENT:
Width = WRAP_CONTENT;
break;
case UI_LENGTH_TYPE_PIXEL:
case UI_LENGTH_TYPE_PERCENTAGE:
case UI_LENGTH_TYPE_EM:
Width = UiLengthToPixel (&Control->Width, AvailableSize.cx, GetControlFontSize (Control));
if (Width > 0 && Control->BoxSizing == UI_BOX_SIZING_CONTENT_BOX) {
Width += GetControlPaddingWidth (Control) + GetControlBorderWidth (Control);
}
break;
default:
if (IS_UI_LENGTH_VALUE_ASSIGNED(Control->Left ) &&
IS_UI_LENGTH_VALUE_ASSIGNED(Control->Right)) {
Width = AvailableSize.cx -
UiLengthToPixelEx (&Control->Left , AvailableSize.cx, GetControlFontSize (Control), FALSE) -
UiLengthToPixelEx (&Control->Right, AvailableSize.cx, GetControlFontSize (Control), TRUE );
Width = MAX (Width, 0);
} else {
Width = 0;
}
break;
}
return Width;
}
INT32
CalculateControlDisplayHeight (
IN UI_CONTROL *Control,
IN SIZE AvailableSize
)
{
INT32 Height;
//
// Control display height is determined by Height or (Top,Bottom). Height has higher priority.
//
switch (Control->Height.Type) {
case UI_LENGTH_TYPE_MATCH_PARENT:
Height = MATCH_PARENT;
break;
case UI_LENGTH_TYPE_WRAP_CONTENT:
Height = WRAP_CONTENT;
break;
case UI_LENGTH_TYPE_PIXEL:
case UI_LENGTH_TYPE_PERCENTAGE:
case UI_LENGTH_TYPE_EM:
Height = UiLengthToPixel (&Control->Height, AvailableSize.cy, GetControlFontSize (Control));
if (Height > 0 && Control->BoxSizing == UI_BOX_SIZING_CONTENT_BOX) {
Height += GetControlPaddingHeight (Control) + GetControlBorderHeight (Control);
}
break;
default:
if (IS_UI_LENGTH_VALUE_ASSIGNED(Control->Top ) &&
IS_UI_LENGTH_VALUE_ASSIGNED(Control->Bottom)) {
Height = AvailableSize.cy -
UiLengthToPixelEx (&Control->Top , AvailableSize.cy, GetControlFontSize (Control), FALSE) -
UiLengthToPixelEx (&Control->Bottom, AvailableSize.cy, GetControlFontSize (Control), TRUE );
Height = MAX (Height, 0);
} else {
Height = 0;
}
break;
}
return Height;
}
SIZE
CalculateControlDisplaySize (
IN UI_CONTROL *Control,
IN SIZE AvailableSize
)
{
SIZE Size;
Size.cx = CalculateControlDisplayWidth (Control, AvailableSize);
Size.cy = CalculateControlDisplayHeight (Control, AvailableSize);
return Size;
}
UINT32
GetControlBkImageStyle (
IN UI_CONTROL *Control
)
{
return ((Control->Filter & DT_GRAY) == DT_GRAY) ? (Control->BkImageStyle | DT_GRAY) : Control->BkImageStyle;
}
UINT32
GetControlFontSize (
IN UI_CONTROL *Control
)
{
if (Control->FontSize != 0) {
return Control->FontSize;
}
if (Control->Manager != NULL) {
return Control->Manager->GetDefaultFontSize (Control->Manager);
}
return 0;
}
INT32
GetControlPaddingLeft (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Padding.Left, Control->Available.cx, GetControlFontSize (Control));
}
INT32
GetControlPaddingRight (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Padding.Right, Control->Available.cx, GetControlFontSize (Control));
}
INT32
GetControlPaddingTop (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Padding.Top, Control->Available.cy, GetControlFontSize (Control));
}
INT32
GetControlPaddingBottom (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Padding.Bottom, Control->Available.cy, GetControlFontSize (Control));
}
INT32
GetControlPaddingWidth (
IN UI_CONTROL *Control
)
{
return (GetControlPaddingLeft (Control) + GetControlPaddingRight (Control));
}
INT32
GetControlPaddingHeight (
IN UI_CONTROL *Control
)
{
return (GetControlPaddingTop (Control) + GetControlPaddingBottom (Control));
}
INT32
GetControlBorderLeft (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Border.Left, Control->Available.cx, GetControlFontSize (Control));
}
INT32
GetControlBorderRight (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Border.Right, Control->Available.cx, GetControlFontSize (Control));
}
INT32
GetControlBorderTop (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Border.Top, Control->Available.cy, GetControlFontSize (Control));
}
INT32
GetControlBorderBottom (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Border.Bottom, Control->Available.cy, GetControlFontSize (Control));
}
INT32
GetControlBorderWidth (
IN UI_CONTROL *Control
)
{
return (GetControlBorderLeft (Control) + GetControlBorderRight (Control));
}
INT32
GetControlBorderHeight (
IN UI_CONTROL *Control
)
{
return (GetControlBorderTop (Control) + GetControlBorderBottom (Control));
}
INT32
GetControlMarginLeft (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Margin.Left, Control->Available.cx, GetControlFontSize (Control));
}
INT32
GetControlMarginRight (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Margin.Right, Control->Available.cx, GetControlFontSize (Control));
}
INT32
GetControlMarginTop (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Margin.Top, Control->Available.cy, GetControlFontSize (Control));
}
INT32
GetControlMarginBottom (
IN UI_CONTROL *Control
)
{
return UiLengthToPixel (&Control->Margin.Bottom, Control->Available.cy, GetControlFontSize (Control));
}
INT32
GetControlMarginWidth (
IN UI_CONTROL *Control
)
{
return (GetControlMarginLeft (Control) + GetControlMarginRight (Control));
}
INT32
GetControlMarginHeight (
IN UI_CONTROL *Control
)
{
return (GetControlMarginTop (Control) + GetControlMarginBottom (Control));
}
STATIC
COLORREF
GetMenuColor (
VOID
)
{
HSV_VALUE Hsv;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel;
if (PcdGet32(PcdH2OLmdeMultiLayout) == 1) {
return 0xFF89E52C;
}
GetCurrentMenuHsv (&Hsv);
if (Hsv.Hue == 0 && Hsv.Saturation == 0 && Hsv.Value == 0) {
//
// Use default color if current menu image doesn't exist.
//
return 0xFF834EAD;
}
HSV2RGB (&Hsv, &Pixel);
return (0xFF000000 | (Pixel.Red << 16) | (Pixel.Green << 8) | Pixel.Blue);
}
STATIC
COLORREF
GetMenuLightColor (
VOID
)
{
HSV_VALUE Hsv;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel;
if (PcdGet32(PcdH2OLmdeMultiLayout) == 1) {
return 0xFF89E52C;
}
GetCurrentMenuHsv (&Hsv);
if (Hsv.Hue == 0 && Hsv.Saturation == 0 && Hsv.Value == 0) {
//
// Use default light color if current menu image doesn't exist.
//
return 0xFF9D72C0;
}
Hsv.Hue = Hsv.Hue <= 5 ? Hsv.Hue + 360 - 5 : Hsv.Hue - 5;
Hsv.Saturation = Hsv.Saturation <= 3 ? 0 : Hsv.Saturation - 3;
Hsv.Value = Hsv.Value >= 73 ? 100 : Hsv.Value + 27;
HSV2RGB (&Hsv, &Pixel);
return (0xFF000000 | (Pixel.Red << 16) | (Pixel.Green << 8) | Pixel.Blue);
}
COLORREF
EFIAPI
GetColorValue (
CHAR16 *Value
)
{
EFI_STATUS Status;
COLORREF Color;
while (*Value > L'\0' && *Value <= L' ') Value++;
if (*Value == '#') Value++;
if (*Value == L'@') {
Value++;
if (StrCmp (Value, L"menucolor") == 0) {
return GetMenuColor ();
} else if (StrCmp (Value, L"menulightcolor") == 0) {
return GetMenuLightColor ();
}
ASSERT (FALSE);
}
Color = (COLORREF) StrToUInt (Value, 16, &Status);
return Color;
}
VOID
AdjustImageToMenuColor (
IN OUT UI_CONTROL *Control
)
{
HSV_VALUE SrcHsv;
HSV_VALUE DstHsv;
UINT32 Color;
INT16 HueDiff;
INT8 SaturationDiff;
INT8 ValueDiff;
CHAR16 Str[20];
GetCurrentMenuHsv (&SrcHsv);
Color = (UINT32)GetColorValue (L"@menucolor");
Color |= 0xFF000000;
RGB2HSV((EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)&Color, &DstHsv);
if (DstHsv.Hue == 0 && DstHsv.Saturation == 0 && DstHsv.Value == 0) {
return ;
}
HueDiff = (INT16) (DstHsv.Hue - SrcHsv.Hue);
SaturationDiff = (INT8) (DstHsv.Saturation - SrcHsv.Saturation);
ValueDiff = (INT8) (DstHsv.Value - SrcHsv.Value);
UnicodeSPrint (Str, sizeof (Str), L"%d,%d,%d", HueDiff, SaturationDiff, ValueDiff);
UiSetAttribute (Control, L"hsvadjust", Str);
}
/**
Convert to IFR numeric question flags value.
@param[in] IsHexValue Flag to determine that numeric question is hex or not
@param[in] IsSignedValue Flag to determine that numeric question is signed value or not
@param[in] ValueSize Numeric question value size in bytes
@return Numeric question flags value
**/
UINT8
ConvertToIfrNumericFlags (
IN BOOLEAN IsHexValue,
IN BOOLEAN IsSignedValue,
IN UINTN ValueSize
)
{
UINT8 IfrNumericFlags;
if (IsHexValue) {
IfrNumericFlags = EFI_IFR_DISPLAY_UINT_HEX;
} else {
IfrNumericFlags = IsSignedValue ? EFI_IFR_DISPLAY_INT_DEC : EFI_IFR_DISPLAY_UINT_DEC;
}
switch (ValueSize) {
case 1:
IfrNumericFlags |= EFI_IFR_NUMERIC_SIZE_1;
break;
case 2:
IfrNumericFlags |= EFI_IFR_NUMERIC_SIZE_2;
break;
case 4:
IfrNumericFlags |= EFI_IFR_NUMERIC_SIZE_4;
break;
case 8:
default:
IfrNumericFlags |= EFI_IFR_NUMERIC_SIZE_8;
break;
}
return IfrNumericFlags;
}
UI_CONTROL *
EFIAPI
ContainerCreateControl (
UI_CONTROL *Container,
CHAR16 *ControlName
)
{
UI_CONTROL *Control;
Control = CreateControl (ControlName, (UI_CONTROL *) Container);
CONTROL_CLASS(Container)->AddChild (Container, Control);
return Control;
}
VOID
EFIAPI
RegisterClassTable (
UI_GET_CLASS *GetClassTable
)
{
UINT8 Buf[sizeof (WNDCLASS) + sizeof (UI_CONTROL_CLASS *)];
WNDCLASS *WndClass;
UI_CONTROL_CLASS *ControlClass;
UI_GET_CLASS *GetClass;
WndClass = (WNDCLASS *) Buf;
WndClass->style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
WndClass->lpfnWndProc = (WNDPROC) NULL;
WndClass->cbClsExtra = sizeof (UI_CONTROL_CLASS *);
WndClass->cbWndExtra = sizeof (UI_CONTROL *);
WndClass->hInstance = NULL;
WndClass->hIcon = NULL;
WndClass->hCursor = 0;
WndClass->hbrBackground = GetStockObject(NULL_BRUSH);
WndClass->lpszMenuName = NULL;
WndClass->lpszClassName = NULL;
GetClass = GetClassTable;
while ((*GetClass) != NULL) {
ControlClass = (*GetClass)();
ASSERT (ControlClass != NULL);
if (ControlClass == NULL) {
continue;
}
WndClass->lpfnWndProc = ControlClass->WndProc;
WndClass->lpszClassName = ControlClass->ClassName;
*(UI_CONTROL_CLASS **)(Buf + sizeof (WNDCLASS)) = ControlClass;
RegisterClass(WndClass);
GetClass++;
}
}
CHAR16 *
StrDuplicate (
IN CONST CHAR16 *Src
)
{
return AllocateCopyPool (StrSize (Src), Src);
}
EFI_STATUS
EFIAPI
InitUiClass (
UI_CONTROL_CLASS **Class,
UINT32 ClassSize,
CHAR16 *ClassName,
UI_CONTROL_CLASS *ParentClass
)
{
ASSERT (ParentClass != NULL);
if (ParentClass == NULL) {
return EFI_INVALID_PARAMETER;
}
*Class = AllocateZeroPool (ClassSize);
ASSERT (*Class != NULL);
if (*Class == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (*Class, ParentClass, ParentClass->ClassSize);
(*Class)->Parent = ParentClass;
(*Class)->ClassSize = ClassSize;
(*Class)->ClassName = StrDuplicate (ClassName);
return EFI_SUCCESS;
}
VOID
UiNeedUpdatePos (
VOID *This
)
{
UI_CONTROL *Control;
UI_CONTROL *Parent;
Control = (UI_CONTROL *)This;
Control->NeedUpdateChildPos = TRUE;
CONTROL_CLASS (Control)->Invalidate (Control);
Parent = CONTROL_CLASS(Control)->GetParent(Control);
if (Parent != NULL) {
CONTROL_CLASS (Control)->Invalidate (Control);
}
while (Parent != NULL) {
Parent->NeedUpdateChildPos = TRUE;
Parent = CONTROL_CLASS (Parent)->GetParent(Parent);
}
}
VOID
XmlCreateControlStartCallback (
VOID *Data,
CHAR16 *ElementName,
CHAR16 **AttrNames,
CHAR16 **AttrValues
)
{
HWND ControlWnd;
UI_CONTROL *ParentControl;
UI_CONTROL *Control;
XML_UI_DATA *XmlUiData;
XmlUiData = (XML_UI_DATA *) Data;
ParentControl = XmlUiData->Parents[XmlUiData->Count - 1];
ControlWnd = CreateWindowEx (
WS_EX_NOACTIVATE,
ElementName,
L"",
WS_CHILD | WS_VISIBLE,
0,
0,
0,
0,
ParentControl->Wnd,
0,
XmlUiData->Instance,
XmlUiData->Manager
);
ASSERT (ControlWnd != NULL);
if (ControlWnd == NULL) {
return ;
}
Control = (UI_CONTROL *) GetWindowLongPtr (ControlWnd, 0);
if (XmlUiData->FirstControl == NULL) {
XmlUiData->FirstControl = Control;
}
CONTROL_CLASS(ParentControl)->AddChild (ParentControl, Control);
XmlUiData->Parents[XmlUiData->Count] = Control;
XmlUiData->ParentsName[XmlUiData->Count] = ElementName;
++XmlUiData->Count;
while (*AttrNames != NULL) {
CONTROL_CLASS(Control)->SetAttribute (Control, *AttrNames, *AttrValues);
AttrNames++;
AttrValues++;
}
}
VOID
XmlCreateControlEndCallback (
VOID *Data,
CHAR16 *ElementName
)
{
XML_UI_DATA *XmlUiData;
XmlUiData = (XML_UI_DATA *) Data;
ASSERT (XmlUiData->Count > 1);
if (XmlUiData->Count <= 1) {
return ;
}
if (StrCmp (ElementName, XmlUiData->ParentsName[XmlUiData->Count - 1]) == 0) {
XmlUiData->ParentsName[XmlUiData->Count - 1] = NULL;
--XmlUiData->Count;
}
}
UI_CONTROL *
EFIAPI
XmlCreateControl (
CHAR16 *XMLBuffer,
UI_CONTROL *Parent
)
{
XML_UI_DATA XmlUiData;
CHAR16 *Buf;
ASSERT (Parent != NULL);
ZeroMem (&XmlUiData, sizeof (XmlUiData));
XmlUiData.Count = 1;
XmlUiData.Parents[0] = Parent;
XmlUiData.Manager = Parent->Manager;
XmlUiData.Instance = Parent->Manager->Instance;
XmlUiData.FirstControl = NULL;
Buf = StrDuplicate (XMLBuffer);
if (Buf != NULL) {
SaxParser (
Buf,
XmlCreateControlStartCallback,
NULL,
XmlCreateControlEndCallback,
&XmlUiData
);
FreePool (Buf);
}
return XmlUiData.FirstControl;
}