alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2ODisplayEngineLocalTextDxe/LTDESupport.c

1009 lines
34 KiB
C

/** @file
Display related functions for H2O display engine driver.
;******************************************************************************
;* Copyright (c) 2013 - 2020, 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 "H2ODisplayEngineLocalText.h"
#include "LTDESupport.h"
#include "LTDEControl.h"
#include "LTDEPanels.h"
#include "LTDEPrint.h"
#define BORDER_LINE_CHAR_ADD_DOWN BIT0
#define BORDER_LINE_CHAR_ADD_UP BIT1
#define BORDER_LINE_CHAR_ADD_RIGHT BIT2
#define BORDER_LINE_CHAR_ADD_LEFT BIT3
UINT32 mScreenMaxY = (UINT32) -1;
UINT32 mScreenMaxX = (UINT32) -1;
/**
Create value in UINT64 type.
@param [in] TargetHiiValue HII value which set type as UINT64
@param [in] ValueUint64 Value for UINT64 type
**/
EFI_STATUS
CreateValueAsUint64 (
IN EFI_HII_VALUE *TargetHiiValue,
IN UINT64 ValueUint64
)
{
if (TargetHiiValue == NULL) {
return EFI_INVALID_PARAMETER;
}
TargetHiiValue->Type = EFI_IFR_TYPE_NUM_SIZE_64;
TargetHiiValue->Value.u64 = ValueUint64;
return EFI_SUCCESS;
}
/**
Create value in string type.
@param [in] TargetHiiValue HII value which set type as string
@param [in] Buffer String buffer
**/
EFI_STATUS
CreateValueAsString (
IN EFI_HII_VALUE *TargetHiiValue,
IN UINT16 BufferLen,
IN UINT8 *Buffer
)
{
if (TargetHiiValue == NULL) {
return EFI_INVALID_PARAMETER;
}
TargetHiiValue->Type = EFI_IFR_TYPE_STRING;
TargetHiiValue->BufferLen = BufferLen;
TargetHiiValue->Buffer = Buffer;
return EFI_SUCCESS;
}
EFI_STATUS
CompareHiiValue (
IN EFI_HII_VALUE *Value1,
IN EFI_HII_VALUE *Value2,
OUT INTN *Result
)
{
INT64 Temp64;
UINTN Len;
if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {
return EFI_UNSUPPORTED;
}
}
if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
if (Value1->Type != Value2->Type) {
//
// Both Operator should be type of String
//
return EFI_UNSUPPORTED;
}
if (Value1->Value.string == 0 || Value2->Value.string == 0) {
//
// StringId 0 is reserved
//
return EFI_INVALID_PARAMETER;
}
if (Value1->Value.string == Value2->Value.string) {
*Result = 0;
return EFI_SUCCESS;
}
*Result = 1;
return EFI_SUCCESS;
}
if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER) {
if (Value1->Type != Value2->Type) {
//
// Both Operator should be type of Buffer.
//
return EFI_UNSUPPORTED;
}
Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;
*Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);
if ((*Result == 0) && (Value1->BufferLen != Value2->BufferLen)) {
//
// In this case, means base on samll number buffer, the data is same
// So which value has more data, which value is bigger.
//
*Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;
}
return EFI_SUCCESS;
}
//
// Take remain types(integer, boolean, date/time) as integer
//
Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
if (Temp64 > 0) {
*Result = 1;
} else if (Temp64 < 0) {
*Result = -1;
} else {
*Result = 0;
}
return EFI_SUCCESS;
}
/**
Display last char on the screen by specific color which defined in panel info
@param[in] SimpleTextOut The pointer of simple text out protocol for sepcific console device
@retval EFI_SUCCESS Success to display last char on the screen or the position of last char is not
defined in any panel info
@retval EFI_INVALID_PARAMETER Input parameter is NULL
**/
STATIC
EFI_STATUS
DisplayScreenLastChar (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
H2O_LTDE_PANEL *Panel;
H2O_LTDE_PANEL *TargetPanel;
INT32 ScreenLastCharXValue;
INT32 ScreenLastCharYValue;
UINT32 PanelColorAttribute;
INT32 OrgAttribute;
INT32 OrgCursorColumn;
INT32 OrgCursorRow;
if (SimpleTextOut == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = DEConOutQueryModeWithoutModeNumer ((UINT32 *) &ScreenLastCharXValue, (UINT32 *) &ScreenLastCharYValue);
if (EFI_ERROR (Status)) {
return Status;
}
ScreenLastCharXValue--;
ScreenLastCharYValue--;
TargetPanel = NULL;
Link = GetFirstNode (&mDEPrivate->PanelListHead);
while (!IsNull (&mDEPrivate->PanelListHead, Link)) {
Panel = H2O_LTDE_PANEL_FROM_LINK (Link);
if (Panel != NULL &&
Panel->Visible &&
Panel->PanelField.right == ScreenLastCharXValue &&
Panel->PanelField.bottom == ScreenLastCharYValue) {
TargetPanel = Panel;
break;
}
Link = GetNextNode (&mDEPrivate->PanelListHead, Link);
}
if (TargetPanel == NULL) {
return EFI_SUCCESS;
}
GetPanelColorAttribute (TargetPanel->VfcfPanelInfo, NULL, H2O_IFR_STYLE_TYPE_PANEL, H2O_STYLE_PSEUDO_CLASS_NORMAL, &PanelColorAttribute);
OrgAttribute = SimpleTextOut->Mode->Attribute;
OrgCursorColumn = SimpleTextOut->Mode->CursorColumn;
OrgCursorRow = SimpleTextOut->Mode->CursorRow;
SimpleTextOut->SetCursorPosition (SimpleTextOut, ScreenLastCharXValue, ScreenLastCharYValue);
SimpleTextOut->SetAttribute (SimpleTextOut, PanelColorAttribute);
SimpleTextOut->OutputString (SimpleTextOut, L" ");
SimpleTextOut->SetAttribute (SimpleTextOut, OrgAttribute);
SimpleTextOut->SetCursorPosition (SimpleTextOut, OrgCursorColumn, OrgCursorRow);
return EFI_SUCCESS;
}
/**
Add up line on border line char
@param[in, out] BorderLineChar Pointer to border line char
**/
STATIC
VOID
BorderLineCharAddUp (
IN OUT CHAR16 *BorderLineChar
)
{
if (BorderLineChar == NULL) {
return;
}
switch (*BorderLineChar) {
case BOXDRAW_HORIZONTAL:
*BorderLineChar = BOXDRAW_UP_HORIZONTAL;
break;
case BOXDRAW_DOWN_RIGHT:
*BorderLineChar = BOXDRAW_VERTICAL_RIGHT;
break;
case BOXDRAW_DOWN_LEFT:
*BorderLineChar = BOXDRAW_VERTICAL_LEFT;
break;
case BOXDRAW_DOWN_HORIZONTAL:
*BorderLineChar = BOXDRAW_VERTICAL_HORIZONTAL;
break;
}
}
/**
Add down line on border line char
@param[in, out] BorderLineChar Pointer to border line char
**/
STATIC
VOID
BorderLineCharAddDown (
IN OUT CHAR16 *BorderLineChar
)
{
if (BorderLineChar == NULL) {
return;
}
switch (*BorderLineChar) {
case BOXDRAW_HORIZONTAL:
*BorderLineChar = BOXDRAW_DOWN_HORIZONTAL;
break;
case BOXDRAW_UP_RIGHT:
*BorderLineChar = BOXDRAW_VERTICAL_RIGHT;
break;
case BOXDRAW_UP_LEFT:
*BorderLineChar = BOXDRAW_VERTICAL_LEFT;
break;
case BOXDRAW_UP_HORIZONTAL:
*BorderLineChar = BOXDRAW_VERTICAL_HORIZONTAL;
break;
}
}
/**
Add left line on border line char
@param[in, out] BorderLineChar Pointer to border line char
**/
STATIC
VOID
BorderLineCharAddLeft (
IN OUT CHAR16 *BorderLineChar
)
{
if (BorderLineChar == NULL) {
return;
}
switch (*BorderLineChar) {
case BOXDRAW_VERTICAL:
*BorderLineChar = BOXDRAW_VERTICAL_LEFT;
break;
case BOXDRAW_UP_RIGHT:
*BorderLineChar = BOXDRAW_UP_HORIZONTAL;
break;
case BOXDRAW_DOWN_RIGHT:
*BorderLineChar = BOXDRAW_DOWN_HORIZONTAL;
break;
case BOXDRAW_VERTICAL_RIGHT:
*BorderLineChar = BOXDRAW_VERTICAL_HORIZONTAL;
break;
}
}
/**
Add right line on border line char
@param[in, out] BorderLineChar Pointer to border line char
**/
STATIC
VOID
BorderLineCharAddRight (
IN OUT CHAR16 *BorderLineChar
)
{
if (BorderLineChar == NULL) {
return;
}
switch (*BorderLineChar) {
case BOXDRAW_VERTICAL:
*BorderLineChar = BOXDRAW_VERTICAL_RIGHT;
break;
case BOXDRAW_UP_LEFT:
*BorderLineChar = BOXDRAW_UP_HORIZONTAL;
break;
case BOXDRAW_DOWN_LEFT:
*BorderLineChar = BOXDRAW_DOWN_HORIZONTAL;
break;
case BOXDRAW_VERTICAL_LEFT:
*BorderLineChar = BOXDRAW_VERTICAL_HORIZONTAL;
break;
}
}
/**
Update border line char by action
@param[in] BorderLineCharAction Add action of border line char
@param[in, out] BorderLineChar Pointer to border line char
**/
STATIC
VOID
UpdateBorderLineChar (
IN UINT32 BorderLineCharAction,
IN OUT CHAR16 *BorderLineChar
)
{
if ((BorderLineCharAction & BORDER_LINE_CHAR_ADD_DOWN) != 0) {
BorderLineCharAddDown (BorderLineChar);
}
if ((BorderLineCharAction & BORDER_LINE_CHAR_ADD_UP) != 0) {
BorderLineCharAddUp (BorderLineChar);
}
if ((BorderLineCharAction & BORDER_LINE_CHAR_ADD_RIGHT) != 0) {
BorderLineCharAddRight (BorderLineChar);
}
if ((BorderLineCharAction & BORDER_LINE_CHAR_ADD_LEFT) != 0) {
BorderLineCharAddLeft (BorderLineChar);
}
}
/**
Check if two fields are overlap.
@param[in] Field1 Pointer to first field
@param[in] Field2 Pointer to second field
@retval TRUE Two fields are overlap
@retval FALSE Two fields are not overlap
**/
STATIC
BOOLEAN
IsFieldOverlap (
IN RECT *Field1,
IN RECT *Field2
)
{
if (((Field1->right == Field2->left ) && (IS_OVERLAP (Field1->top , Field1->bottom, Field2->top , Field2->bottom))) ||
((Field1->left == Field2->right ) && (IS_OVERLAP (Field1->top , Field1->bottom, Field2->top , Field2->bottom))) ||
((Field1->bottom == Field2->top ) && (IS_OVERLAP (Field1->left, Field1->right , Field2->left, Field2->right ))) ||
((Field1->top == Field2->bottom) && (IS_OVERLAP (Field1->left, Field1->right , Field2->left, Field2->right )))) {
return TRUE;
}
return FALSE;
}
/**
Update border line strings
@param[in] CurrentPanelField Current panel field
@param[in] AdjacentPanelField Adjacent panel field
@param[in] HorizonalLineWidth Horizonal line width
@param[in, out] TopHorizonalLine Top horizonal border line string
@param[in, out] BorderLineChar Bottom horizonal border line string
@param[in, out] BorderLineChar Left vertical border line string
@param[in, out] BorderLineChar Right vertical border line string
**/
STATIC
EFI_STATUS
UpdateBorderLineStr (
IN RECT *CurrentPanelField,
IN RECT *AdjacentPanelField,
IN UINT32 HorizonalLineWidth,
IN OUT CHAR16 *TopHorizonalLine,
IN OUT CHAR16 *BottomHorizonalLine,
IN OUT CHAR16 *LeftVerticalLine,
IN OUT CHAR16 *RightVerticalLine
)
{
if (CurrentPanelField->right == AdjacentPanelField->left) {
if (IN_RANGE (CurrentPanelField->top, AdjacentPanelField->top, AdjacentPanelField->bottom)) {
if (CurrentPanelField->top == AdjacentPanelField->top) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_DOWN | BORDER_LINE_CHAR_ADD_RIGHT, &TopHorizonalLine[HorizonalLineWidth - 1]);
} else if (CurrentPanelField->top == AdjacentPanelField->bottom) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_RIGHT, &TopHorizonalLine[HorizonalLineWidth - 1]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_DOWN, &TopHorizonalLine[HorizonalLineWidth - 1]);
}
} else {
if (CurrentPanelField->bottom > AdjacentPanelField->top) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT, &RightVerticalLine[AdjacentPanelField->top - CurrentPanelField->top - 1]);
}
}
if (IN_RANGE (CurrentPanelField->bottom, AdjacentPanelField->top, AdjacentPanelField->bottom)) {
if (CurrentPanelField->bottom == AdjacentPanelField->top) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_DOWN | BORDER_LINE_CHAR_ADD_RIGHT, &BottomHorizonalLine[HorizonalLineWidth - 1]);
} else if (CurrentPanelField->bottom == AdjacentPanelField->bottom) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_RIGHT, &BottomHorizonalLine[HorizonalLineWidth - 1]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[HorizonalLineWidth - 1]);
}
} else {
if (CurrentPanelField->top < AdjacentPanelField->bottom) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT, &RightVerticalLine[AdjacentPanelField->bottom - CurrentPanelField->top - 1]);
}
}
return EFI_SUCCESS;
}
if (CurrentPanelField->left == AdjacentPanelField->right) {
if (IN_RANGE (CurrentPanelField->top, AdjacentPanelField->top, AdjacentPanelField->bottom)) {
if (CurrentPanelField->top == AdjacentPanelField->top) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_DOWN | BORDER_LINE_CHAR_ADD_LEFT, &TopHorizonalLine[0]);
} else if (CurrentPanelField->top == AdjacentPanelField->bottom) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_LEFT, &TopHorizonalLine[0]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_DOWN, &TopHorizonalLine[0]);
}
} else {
if (CurrentPanelField->bottom > AdjacentPanelField->top) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_LEFT, &LeftVerticalLine[AdjacentPanelField->top - CurrentPanelField->top - 1]);
}
}
if (IN_RANGE (CurrentPanelField->bottom, AdjacentPanelField->top, AdjacentPanelField->bottom)) {
if (CurrentPanelField->bottom == AdjacentPanelField->top) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_DOWN | BORDER_LINE_CHAR_ADD_LEFT, &BottomHorizonalLine[0]);
} else if (CurrentPanelField->bottom == AdjacentPanelField->bottom) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_LEFT, &BottomHorizonalLine[0]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP | BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[0]);
}
} else {
if (CurrentPanelField->top < AdjacentPanelField->bottom) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_LEFT, &LeftVerticalLine[AdjacentPanelField->bottom - CurrentPanelField->top - 1]);
}
}
return EFI_SUCCESS;
}
if (CurrentPanelField->bottom == AdjacentPanelField->top) {
if (IN_RANGE (CurrentPanelField->left, AdjacentPanelField->left, AdjacentPanelField->right)) {
if (CurrentPanelField->left == AdjacentPanelField->left) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[0]);
} else if (CurrentPanelField->left == AdjacentPanelField->right) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_LEFT | BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[0]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_LEFT, &BottomHorizonalLine[0]);
}
} else {
if (CurrentPanelField->right > AdjacentPanelField->left) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[AdjacentPanelField->left - CurrentPanelField->left]);
}
}
if (IN_RANGE (CurrentPanelField->right, AdjacentPanelField->left, AdjacentPanelField->right)) {
if (CurrentPanelField->right == AdjacentPanelField->left) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[HorizonalLineWidth - 1]);
} else if (CurrentPanelField->right == AdjacentPanelField->right) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_LEFT | BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[HorizonalLineWidth - 1]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_LEFT, &BottomHorizonalLine[HorizonalLineWidth - 1]);
}
} else {
if (CurrentPanelField->left < AdjacentPanelField->right) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_DOWN, &BottomHorizonalLine[AdjacentPanelField->right - CurrentPanelField->left]);
}
}
return EFI_SUCCESS;
}
if (CurrentPanelField->top == AdjacentPanelField->bottom) {
if (IN_RANGE (CurrentPanelField->left, AdjacentPanelField->left, AdjacentPanelField->right)) {
if (CurrentPanelField->left == AdjacentPanelField->left) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_UP, &TopHorizonalLine[0]);
} else if (CurrentPanelField->left == AdjacentPanelField->right) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_LEFT | BORDER_LINE_CHAR_ADD_UP, &TopHorizonalLine[0]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_LEFT, &TopHorizonalLine[0]);
}
} else {
if (CurrentPanelField->right > AdjacentPanelField->left) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP, &TopHorizonalLine[AdjacentPanelField->left - CurrentPanelField->left]);
}
}
if (IN_RANGE (CurrentPanelField->right, AdjacentPanelField->left, AdjacentPanelField->right)) {
if (CurrentPanelField->right == AdjacentPanelField->left) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_UP, &TopHorizonalLine[HorizonalLineWidth - 1]);
} else if (CurrentPanelField->right == AdjacentPanelField->right) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_LEFT | BORDER_LINE_CHAR_ADD_UP, &TopHorizonalLine[HorizonalLineWidth - 1]);
} else {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_RIGHT | BORDER_LINE_CHAR_ADD_LEFT, &TopHorizonalLine[HorizonalLineWidth - 1]);
}
} else {
if (CurrentPanelField->left < AdjacentPanelField->right) {
UpdateBorderLineChar (BORDER_LINE_CHAR_ADD_UP, &TopHorizonalLine[AdjacentPanelField->right - CurrentPanelField->left]);
}
}
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;;
}
EFI_STATUS
GetAllBorderLineField (
OUT RECT **BorderLineFieldList,
OUT UINT32 *BorderLineFieldCount
)
{
LIST_ENTRY *Link;
H2O_LTDE_PANEL *Panel;
UINT32 FieldCount;
RECT *FieldList;
if (BorderLineFieldList == NULL || BorderLineFieldCount == NULL) {
return EFI_INVALID_PARAMETER;
}
FieldCount = 0;
Link = GetFirstNode (&mDEPrivate->PanelListHead);
while (!IsNull (&mDEPrivate->PanelListHead, Link)) {
Panel = H2O_LTDE_PANEL_FROM_LINK (Link);
Link = GetNextNode (&mDEPrivate->PanelListHead, Link);
if (Panel == NULL || Panel->BorderLineWidth == 0 || !Panel->Visible) {
continue;
}
FieldCount++;
}
if (FieldCount == 0) {
return EFI_NOT_FOUND;
}
FieldList = AllocateZeroPool (FieldCount * sizeof (RECT));
if (FieldList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
FieldCount = 0;
Link = GetFirstNode (&mDEPrivate->PanelListHead);
while (!IsNull (&mDEPrivate->PanelListHead, Link)) {
Panel = H2O_LTDE_PANEL_FROM_LINK (Link);
Link = GetNextNode (&mDEPrivate->PanelListHead, Link);
if (Panel == NULL || Panel->BorderLineWidth == 0 || !Panel->Visible) {
continue;
}
CopyRect (&FieldList[FieldCount], &Panel->PanelField);
FieldCount++;
}
*BorderLineFieldList = FieldList;
*BorderLineFieldCount = FieldCount;
return EFI_SUCCESS;
}
/**
Print border line for current panel field.
It will also deal with the border line char which is overlapped with previous panel field.
@param[in] CurrentPanelField Current panel field
@param[in] PreviousPanelField Previous panel field list
@param[in] PreviousPanelFieldCount Previous panel field list count
**/
EFI_STATUS
GetBorderLineInfo (
IN RECT *CurrentPanelField,
IN RECT *BorderLineFieldList,
IN UINT32 BorderLineFieldCount,
OUT LTDE_PANEL_BORDER_LINE_INFO *BorderLineInfo
)
{
UINT32 Index;
UINT32 HorizonalLineWidth;
UINT32 VerticalLineHeight;
CHAR16 *TopHorizonalLine;
CHAR16 *BottomHorizonalLine;
CHAR16 *LeftVerticalLine;
CHAR16 *RightVerticalLine;
EFI_STATUS Status;
if (CurrentPanelField == NULL || BorderLineInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Initialize horizonal and vetical border line data for current field
//
HorizonalLineWidth = (UINT32) (CurrentPanelField->right - CurrentPanelField->left + 1);
VerticalLineHeight = (UINT32) (CurrentPanelField->bottom - CurrentPanelField->top + 1) - 2;
TopHorizonalLine = AllocatePool ((HorizonalLineWidth + 1) * sizeof (CHAR16));
BottomHorizonalLine = AllocatePool ((HorizonalLineWidth + 1) * sizeof (CHAR16));
LeftVerticalLine = AllocatePool (VerticalLineHeight * sizeof (CHAR16));
RightVerticalLine = AllocatePool (VerticalLineHeight * sizeof (CHAR16));
if (TopHorizonalLine == NULL || BottomHorizonalLine == NULL || LeftVerticalLine == NULL || RightVerticalLine == NULL) {
return EFI_OUT_OF_RESOURCES;
}
TopHorizonalLine[0] = BOXDRAW_DOWN_RIGHT;
TopHorizonalLine[HorizonalLineWidth - 1] = BOXDRAW_DOWN_LEFT;
BottomHorizonalLine[0] = BOXDRAW_UP_RIGHT;
BottomHorizonalLine[HorizonalLineWidth - 1] = BOXDRAW_UP_LEFT;
for (Index = 1; Index < HorizonalLineWidth - 1; Index++) {
TopHorizonalLine[Index] = BOXDRAW_HORIZONTAL;
BottomHorizonalLine[Index] = BOXDRAW_HORIZONTAL;
}
TopHorizonalLine[HorizonalLineWidth] = CHAR_NULL;
BottomHorizonalLine[HorizonalLineWidth] = CHAR_NULL;
for (Index = 0; Index < VerticalLineHeight; Index++) {
LeftVerticalLine[Index] = BOXDRAW_VERTICAL;
RightVerticalLine[Index] = BOXDRAW_VERTICAL;
}
//
// Update line data when current field cover to previous fields
//
if (BorderLineFieldList != NULL) {
for (Index = 0; Index < BorderLineFieldCount; Index++) {
if (!IsFieldOverlap (CurrentPanelField, &BorderLineFieldList[Index]) ||
EqualRect(CurrentPanelField, &BorderLineFieldList[Index])) {
continue;
}
Status = UpdateBorderLineStr (
CurrentPanelField,
&BorderLineFieldList[Index],
HorizonalLineWidth,
TopHorizonalLine,
BottomHorizonalLine,
LeftVerticalLine,
RightVerticalLine
);
ASSERT (Status == EFI_SUCCESS);
}
}
BorderLineInfo->HorizonalLineWidth = HorizonalLineWidth;
BorderLineInfo->VerticalLineHeight = VerticalLineHeight;
BorderLineInfo->TopHorizonalLine = TopHorizonalLine;
BorderLineInfo->BottomHorizonalLine = BottomHorizonalLine;
BorderLineInfo->LeftVerticalLine = LeftVerticalLine;
BorderLineInfo->RightVerticalLine = RightVerticalLine;
return EFI_SUCCESS;
}
VOID
FreeBorderLineInfo (
IN LTDE_PANEL_BORDER_LINE_INFO *BorderLineInfo
)
{
if (BorderLineInfo != NULL) {
SafeFreePool ((VOID **) &BorderLineInfo->TopHorizonalLine);
SafeFreePool ((VOID **) &BorderLineInfo->BottomHorizonalLine);
SafeFreePool ((VOID **) &BorderLineInfo->LeftVerticalLine);
SafeFreePool ((VOID **) &BorderLineInfo->RightVerticalLine);
}
}
/**
Print border line for current panel field.
It will also deal with the border line char which is overlapped with previous panel field.
@param[in] CurrentPanelField Current panel field
@param[in] PreviousPanelField Previous panel field list
@param[in] PreviousPanelFieldCount Previous panel field list count
**/
EFI_STATUS
PrintBorderLineFunc (
IN RECT *CurrentPanelField,
IN LTDE_PANEL_BORDER_LINE_INFO *BorderLineInfo OPTIONAL
)
{
EFI_STATUS Status;
LTDE_PANEL_BORDER_LINE_INFO *BorderLineInfoPtr;
LTDE_PANEL_BORDER_LINE_INFO BorderLineInfoInstance;
UINT32 Index;
CHAR16 Character[2];
if (CurrentPanelField == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BorderLineInfo == NULL) {
Status = GetBorderLineInfo (CurrentPanelField, NULL, 0, &BorderLineInfoInstance);
if (EFI_ERROR (Status)) {
return Status;
}
BorderLineInfoPtr = &BorderLineInfoInstance;
} else {
BorderLineInfoPtr = BorderLineInfo;
}
//
// Print border line of current field
//
DisplayString (CurrentPanelField->left, CurrentPanelField->bottom, BorderLineInfoPtr->BottomHorizonalLine);
DisplayString (CurrentPanelField->left, CurrentPanelField->top , BorderLineInfoPtr->TopHorizonalLine);
Character[1] = CHAR_NULL;
for (Index = 0; Index < BorderLineInfoPtr->VerticalLineHeight; Index++) {
Character[0] = BorderLineInfoPtr->LeftVerticalLine[Index];
DisplayString (CurrentPanelField->left , CurrentPanelField->top + 1 + Index, Character);
Character[0] = BorderLineInfoPtr->RightVerticalLine[Index];
DisplayString (CurrentPanelField->right, CurrentPanelField->top + 1 + Index, Character);
}
if (BorderLineInfoPtr != BorderLineInfo) {
FreeBorderLineInfo (BorderLineInfoPtr);
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
ConDevInit (
IN H2O_FORM_BROWSER_CONSOLE_DEV_NODE *ConDevNode
)
{
H2O_LTDE_PANEL *ScreenPanel;
H2O_LTDE_PANEL *SetupPagePanel;
UINT32 Attribute;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
UINTN DeltaX;
UINTN DeltaY;
UINT32 Interval;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
UINTN Column;
UINTN Row;
SetupPagePanel = GetPanel (SETUP_PAGE_PANEL_ID);
if (SetupPagePanel == NULL) {
return EFI_NOT_FOUND;
}
GetPanelColorAttribute (SetupPagePanel->VfcfPanelInfo, NULL, H2O_IFR_STYLE_TYPE_PANEL, H2O_STYLE_PSEUDO_CLASS_NORMAL, &Attribute);
ConDevNode->SimpleTextOut->SetAttribute (ConDevNode->SimpleTextOut, Attribute);
ConDevNode->SimpleTextOut->ClearScreen (ConDevNode->SimpleTextOut);
if (ConDevNode->GraphicsOut != NULL) {
ScreenPanel = GetPanel (SCREEN_PANEL_ID);
ConDevNode->SimpleTextOut->QueryMode (ConDevNode->SimpleTextOut, ConDevNode->SimpleTextOut->Mode->Mode, &Column, &Row);
HorizontalResolution = ConDevNode->GraphicsOut->Mode->Info->HorizontalResolution;
VerticalResolution = ConDevNode->GraphicsOut->Mode->Info->VerticalResolution;
DeltaX = (HorizontalResolution - Column * EFI_GLYPH_WIDTH) / 2;
DeltaY = (VerticalResolution - Row * EFI_GLYPH_HEIGHT) / 2;
ZeroMem (&Background, sizeof(Background));
if (DeltaX != 0 || ScreenPanel->PanelField.left != 0) {
Interval = ScreenPanel->PanelField.left * EFI_GLYPH_WIDTH;
ConDevNode->GraphicsOut->Blt (
ConDevNode->GraphicsOut,
&Background,
EfiBltVideoFill,
0,
0,
0,
0,
DeltaX + Interval,
VerticalResolution,
0
);
}
if (DeltaX != 0 || ScreenPanel->PanelField.right < (INT32) Column - 1) {
Interval = (UINT32) ((INT32) Column - 1 - ScreenPanel->PanelField.right) * EFI_GLYPH_WIDTH;
ConDevNode->GraphicsOut->Blt (
ConDevNode->GraphicsOut,
&Background,
EfiBltVideoFill,
0,
0,
HorizontalResolution - DeltaX - Interval,
0,
DeltaX + Interval,
VerticalResolution,
0
);
}
if (DeltaY != 0 || ScreenPanel->PanelField.top != 0) {
Interval = ScreenPanel->PanelField.top * EFI_GLYPH_HEIGHT;
ConDevNode->GraphicsOut->Blt (
ConDevNode->GraphicsOut,
&Background,
EfiBltVideoFill,
0,
0,
0,
0,
HorizontalResolution,
DeltaY + Interval,
0
);
}
if (DeltaY != 0 || ScreenPanel->PanelField.bottom < (INT32) Row - 1) {
Interval = (UINT32) ((INT32) Row - 1 - ScreenPanel->PanelField.bottom) * EFI_GLYPH_HEIGHT;
ConDevNode->GraphicsOut->Blt (
ConDevNode->GraphicsOut,
&Background,
EfiBltVideoFill,
0,
0,
0,
VerticalResolution - DeltaY - Interval,
HorizontalResolution,
DeltaY + Interval,
0
);
}
}
DisplayScreenLastChar (ConDevNode->SimpleTextOut);
return EFI_SUCCESS;
}
/**
Display layout which includes screen last character and the border line for each panel.
@retval EFI_SUCCESS Display layout successfully
@retval EFI_OUT_OF_RESOURCES Allocate pool fail
**/
EFI_STATUS
DisplayLayout (
VOID
)
{
LIST_ENTRY *Link;
H2O_LTDE_PANEL *Panel;
RECT *BorderLineFieldList;
UINT32 BorderLineFieldCount;
H2O_FORM_BROWSER_CONSOLE_DEV_NODE *ConDevNode;
EFI_STATUS Status;
LTDE_PANEL_BORDER_LINE_INFO BorderLineInfo;
//
// Display screen last character when console device is in initial status.
//
Link = GetFirstNode (&mDEPrivate->ConsoleDevListHead);
while (!IsNull (&mDEPrivate->ConsoleDevListHead, Link)) {
ConDevNode = H2O_FORM_BROWSER_CONSOLE_DEV_NODE_FROM_LINK (Link);
if (ConDevNode != NULL && ConDevNode->ConDevStatus == CONSOLE_DEVICE_STATUS_INIT) {
ConDevInit (ConDevNode);
ConDevNode->ConDevStatus = CONSOLE_DEVICE_STATUS_READY;
}
Link = GetNextNode (&mDEPrivate->ConsoleDevListHead, Link);
}
//
// Display border line for each panel
//
Status = GetAllBorderLineField (&BorderLineFieldList, &BorderLineFieldCount);
if (EFI_ERROR (Status)) {
return Status;
}
Link = GetFirstNode (&mDEPrivate->PanelListHead);
while (!IsNull (&mDEPrivate->PanelListHead, Link)) {
Panel = H2O_LTDE_PANEL_FROM_LINK (Link);
Link = GetNextNode (&mDEPrivate->PanelListHead, Link);
if (Panel == NULL || Panel->BorderLineWidth == 0 || !Panel->Visible) {
continue;
}
DEConOutSetAttribute (Panel->BorderColorAttribute);
Status = GetBorderLineInfo (&Panel->PanelField, BorderLineFieldList, BorderLineFieldCount, &BorderLineInfo);
if (!EFI_ERROR (Status)) {
PrintBorderLineFunc (&Panel->PanelField, &BorderLineInfo);
FreeBorderLineInfo (&BorderLineInfo);
}
}
FreePool ((VOID *) BorderLineFieldList);
return EFI_SUCCESS;
}
/**
Display string
@param [in] StartX Target x-axis of string
@param [in] StartY Target y-axis of string
@param [in] Fmt Format string
@retval EFI_SUCCESS Display string successfully
@retval Other Output dstring fail
**/
EFI_STATUS
DisplayString (
IN UINT32 StartX,
IN UINT32 StartY,
IN CHAR16 *String
)
{
CHAR16 *ModifiedStr;
UINTN ModifiedStrLen;
if (StartX > mScreenMaxX ||
StartY > mScreenMaxY) {
return EFI_INVALID_PARAMETER;
}
DEConOutSetCursorPosition (StartX, StartY);
//
// Prevent display string on screen right bottom character.
//
if (StartY == mScreenMaxY) {
if (StartX == mScreenMaxX) {
return EFI_SUCCESS;
} else if (StartX + GetStringDisplayWidth (String) >= mScreenMaxX) {
ModifiedStrLen = StrLen (String);
ModifiedStr = AllocateCopyPool ((ModifiedStrLen + 1) * sizeof (CHAR16), String);
if (ModifiedStr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
while (ModifiedStrLen > 0) {
ModifiedStrLen--;
ModifiedStr[ModifiedStrLen] = CHAR_NULL;
if (StartX + GetStringDisplayWidth (ModifiedStr) < mScreenMaxX) {
DEConOutOutputString (ModifiedStr);
break;
}
}
FreePool (ModifiedStr);
return EFI_SUCCESS;
}
}
return DEConOutOutputString (String);
}