1009 lines
34 KiB
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);
|
|
}
|
|
|