mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-18 15:27:48 +01:00
2476 lines
55 KiB
C
2476 lines
55 KiB
C
|
/** @file
|
||
|
Defines HBufferImage - the view of the file that is visible at any point,
|
||
|
as well as the event handlers for editing the file
|
||
|
|
||
|
Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved. <BR>
|
||
|
This program and the accompanying materials
|
||
|
are licensed and made available under the terms and conditions of the BSD License
|
||
|
which accompanies this distribution. The full text of the license may be found at
|
||
|
http://opensource.org/licenses/bsd-license.php
|
||
|
|
||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||
|
|
||
|
**/
|
||
|
|
||
|
#include "HexEditor.h"
|
||
|
|
||
|
extern EFI_HANDLE HImageHandleBackup;
|
||
|
|
||
|
extern HEFI_EDITOR_FILE_IMAGE HFileImage;
|
||
|
extern HEFI_EDITOR_DISK_IMAGE HDiskImage;
|
||
|
extern HEFI_EDITOR_MEM_IMAGE HMemImage;
|
||
|
|
||
|
extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
|
||
|
extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;
|
||
|
extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;
|
||
|
|
||
|
extern BOOLEAN HEditorMouseAction;
|
||
|
|
||
|
extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
|
||
|
extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;
|
||
|
|
||
|
HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
|
||
|
HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;
|
||
|
|
||
|
//
|
||
|
// for basic initialization of HBufferImage
|
||
|
//
|
||
|
HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = {
|
||
|
NULL,
|
||
|
NULL,
|
||
|
0,
|
||
|
NULL,
|
||
|
{
|
||
|
0,
|
||
|
0
|
||
|
},
|
||
|
{
|
||
|
0,
|
||
|
0
|
||
|
},
|
||
|
{
|
||
|
0,
|
||
|
0
|
||
|
},
|
||
|
0,
|
||
|
TRUE,
|
||
|
FALSE,
|
||
|
FileTypeNone,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// the whole edit area needs to be refreshed
|
||
|
//
|
||
|
BOOLEAN HBufferImageNeedRefresh;
|
||
|
|
||
|
//
|
||
|
// only the current line in edit area needs to be refresh
|
||
|
//
|
||
|
BOOLEAN HBufferImageOnlyLineNeedRefresh;
|
||
|
|
||
|
BOOLEAN HBufferImageMouseNeedRefresh;
|
||
|
|
||
|
/**
|
||
|
Initialization function for HBufferImage
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@retval EFI_LOAD_ERROR A load error occured.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageInit (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
//
|
||
|
// basically initialize the HBufferImage
|
||
|
//
|
||
|
CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage));
|
||
|
|
||
|
//
|
||
|
// INIT listhead
|
||
|
//
|
||
|
HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
|
||
|
if (HBufferImage.ListHead == NULL) {
|
||
|
return EFI_LOAD_ERROR;
|
||
|
}
|
||
|
|
||
|
InitializeListHead (HBufferImage.ListHead);
|
||
|
|
||
|
HBufferImage.DisplayPosition.Row = 2;
|
||
|
HBufferImage.DisplayPosition.Column = 10;
|
||
|
HBufferImage.MousePosition.Row = 2;
|
||
|
HBufferImage.MousePosition.Column = 10;
|
||
|
|
||
|
HBufferImage.FileImage = &HFileImage;
|
||
|
HBufferImage.DiskImage = &HDiskImage;
|
||
|
HBufferImage.MemImage = &HMemImage;
|
||
|
|
||
|
HBufferImageNeedRefresh = FALSE;
|
||
|
HBufferImageOnlyLineNeedRefresh = FALSE;
|
||
|
HBufferImageMouseNeedRefresh = FALSE;
|
||
|
|
||
|
HBufferImageBackupVar.FileImage = &HFileImageBackupVar;
|
||
|
HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar;
|
||
|
HBufferImageBackupVar.MemImage = &HMemImageBackupVar;
|
||
|
|
||
|
Status = HFileImageInit ();
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return EFI_LOAD_ERROR;
|
||
|
}
|
||
|
|
||
|
Status = HDiskImageInit ();
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return EFI_LOAD_ERROR;
|
||
|
}
|
||
|
|
||
|
Status = HMemImageInit ();
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return EFI_LOAD_ERROR;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Backup function for HBufferImage. Only a few fields need to be backup.
|
||
|
This is for making the file buffer refresh as few as possible.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageBackup (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition;
|
||
|
|
||
|
HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition;
|
||
|
|
||
|
HBufferImageBackupVar.Modified = HBufferImage.Modified;
|
||
|
|
||
|
HBufferImageBackupVar.BufferType = HBufferImage.BufferType;
|
||
|
HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow;
|
||
|
HBufferImageBackupVar.HighBits = HBufferImage.HighBits;
|
||
|
|
||
|
//
|
||
|
// three kinds of buffer supported
|
||
|
// file buffer
|
||
|
// disk buffer
|
||
|
// memory buffer
|
||
|
//
|
||
|
switch (HBufferImage.BufferType) {
|
||
|
case FileTypeFileBuffer:
|
||
|
HFileImageBackup ();
|
||
|
break;
|
||
|
|
||
|
case FileTypeDiskBuffer:
|
||
|
HDiskImageBackup ();
|
||
|
break;
|
||
|
|
||
|
case FileTypeMemBuffer:
|
||
|
HMemImageBackup ();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Free all the lines in HBufferImage.
|
||
|
Fields affected:
|
||
|
Lines
|
||
|
CurrentLine
|
||
|
NumLines
|
||
|
ListHead
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageFreeLines (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HFreeLines (HBufferImage.ListHead, HBufferImage.Lines);
|
||
|
|
||
|
HBufferImage.Lines = NULL;
|
||
|
HBufferImage.CurrentLine = NULL;
|
||
|
HBufferImage.NumLines = 0;
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Cleanup function for HBufferImage
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageCleanup (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
//
|
||
|
// free all the lines
|
||
|
//
|
||
|
Status = HBufferImageFreeLines ();
|
||
|
|
||
|
SHELL_FREE_NON_NULL (HBufferImage.ListHead);
|
||
|
HBufferImage.ListHead = NULL;
|
||
|
|
||
|
HFileImageCleanup ();
|
||
|
HDiskImageCleanup ();
|
||
|
|
||
|
return Status;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Print Line on Row
|
||
|
|
||
|
@param[in] Line The lline to print.
|
||
|
@param[in] Row The row on screen ( begin from 1 ).
|
||
|
@param[in] FRow The FRow.
|
||
|
@param[in] Orig The original color.
|
||
|
@param[in] New The color to print with.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImagePrintLine (
|
||
|
IN HEFI_EDITOR_LINE *Line,
|
||
|
IN UINTN Row,
|
||
|
IN UINTN FRow,
|
||
|
IN HEFI_EDITOR_COLOR_UNION Orig,
|
||
|
IN HEFI_EDITOR_COLOR_UNION New
|
||
|
|
||
|
)
|
||
|
{
|
||
|
|
||
|
UINTN Index;
|
||
|
UINTN Pos;
|
||
|
BOOLEAN Selected;
|
||
|
BOOLEAN BeNewColor;
|
||
|
UINTN RowStart;
|
||
|
UINTN RowEnd;
|
||
|
UINTN ColStart;
|
||
|
UINTN ColEnd;
|
||
|
|
||
|
//
|
||
|
// variable initialization
|
||
|
//
|
||
|
ColStart = 0;
|
||
|
ColEnd = 0;
|
||
|
Selected = FALSE;
|
||
|
|
||
|
//
|
||
|
// print the selected area in opposite color
|
||
|
//
|
||
|
if (HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
|
||
|
RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
|
||
|
RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
|
||
|
|
||
|
ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
|
||
|
ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
|
||
|
|
||
|
if (FRow >= RowStart && FRow <= RowEnd) {
|
||
|
Selected = TRUE;
|
||
|
}
|
||
|
|
||
|
if (FRow > RowStart) {
|
||
|
ColStart = 1;
|
||
|
}
|
||
|
|
||
|
if (FRow < RowEnd) {
|
||
|
ColEnd = 0x10;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (!HEditorMouseAction) {
|
||
|
ShellPrintEx (
|
||
|
0,
|
||
|
(INT32)Row - 1,
|
||
|
L"%8X ",
|
||
|
((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) {
|
||
|
|
||
|
BeNewColor = FALSE;
|
||
|
|
||
|
if (Selected) {
|
||
|
if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
|
||
|
BeNewColor = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (BeNewColor) {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
|
||
|
} else {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
|
||
|
}
|
||
|
|
||
|
Pos = 10 + (Index * 3);
|
||
|
if (Line->Buffer[Index] < 0x10) {
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
|
||
|
Pos++;
|
||
|
}
|
||
|
|
||
|
if (Index < 0x07) {
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
|
||
|
} else {
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
|
||
|
while (Index < 0x08) {
|
||
|
Pos = 10 + (Index * 3);
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
while (Index < 0x10 && Index < Line->Size) {
|
||
|
|
||
|
BeNewColor = FALSE;
|
||
|
|
||
|
if (Selected) {
|
||
|
if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
|
||
|
BeNewColor = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (BeNewColor) {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
|
||
|
} else {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
|
||
|
}
|
||
|
|
||
|
Pos = 10 + (Index * 3) + 1;
|
||
|
if (Line->Buffer[Index] < 0x10) {
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
|
||
|
Pos++;
|
||
|
}
|
||
|
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
|
||
|
Index++;
|
||
|
}
|
||
|
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
|
||
|
while (Index < 0x10) {
|
||
|
Pos = 10 + (Index * 3) + 1;
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
|
||
|
Index++;
|
||
|
}
|
||
|
//
|
||
|
// restore the original color
|
||
|
//
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
|
||
|
|
||
|
//
|
||
|
// PRINT the buffer content
|
||
|
//
|
||
|
if (!HEditorMouseAction) {
|
||
|
for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) {
|
||
|
Pos = ASCII_POSITION + Index;
|
||
|
|
||
|
//
|
||
|
// learned from shelle.h -- IsValidChar
|
||
|
//
|
||
|
if (Line->Buffer[Index] >= L' ') {
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16) Line->Buffer[Index]);
|
||
|
} else {
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (Index < 0x10) {
|
||
|
Pos = ASCII_POSITION + Index;
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
|
||
|
Index++;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// restore the abundant blank in hex edit area to original color
|
||
|
//
|
||
|
if (Selected) {
|
||
|
if (ColEnd <= 7) {
|
||
|
Pos = 10 + (ColEnd - 1) * 3 + 2;
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
|
||
|
} else if (ColEnd == 8) {
|
||
|
Pos = 10 + (ColEnd - 1) * 3 + 2;
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
|
||
|
} else {
|
||
|
Pos = 10 + (ColEnd - 1) * 3 + 3;
|
||
|
ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Function to decide if a column number is stored in the high bits.
|
||
|
|
||
|
@param[in] Column The column to examine.
|
||
|
@param[out] FCol The actual column number.
|
||
|
|
||
|
@retval TRUE The actual column was in high bits and is now in FCol.
|
||
|
@retval FALSE There was not a column number in the high bits.
|
||
|
**/
|
||
|
BOOLEAN
|
||
|
HBufferImageIsAtHighBits (
|
||
|
IN UINTN Column,
|
||
|
OUT UINTN *FCol
|
||
|
)
|
||
|
{
|
||
|
Column -= 10;
|
||
|
|
||
|
//
|
||
|
// NOW AFTER THE SUB, Column start from 0
|
||
|
// 23 AND 24 ARE BOTH BLANK
|
||
|
//
|
||
|
if (Column == 24) {
|
||
|
*FCol = 0;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (Column > 24) {
|
||
|
Column--;
|
||
|
}
|
||
|
|
||
|
*FCol = (Column / 3) + 1;
|
||
|
|
||
|
if (Column % 3 == 0) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if ((Column % 3 == 2)) {
|
||
|
*FCol = 0;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Decide if a point is in the already selected area.
|
||
|
|
||
|
@param[in] MouseRow The row of the point to test.
|
||
|
@param[in] MouseCol The col of the point to test.
|
||
|
|
||
|
@retval TRUE The point is in the selected area.
|
||
|
@retval FALSE The point is not in the selected area.
|
||
|
**/
|
||
|
BOOLEAN
|
||
|
HBufferImageIsInSelectedArea (
|
||
|
IN UINTN MouseRow,
|
||
|
IN UINTN MouseCol
|
||
|
)
|
||
|
{
|
||
|
UINTN FRow;
|
||
|
UINTN RowStart;
|
||
|
UINTN RowEnd;
|
||
|
UINTN ColStart;
|
||
|
UINTN ColEnd;
|
||
|
UINTN MouseColStart;
|
||
|
UINTN MouseColEnd;
|
||
|
|
||
|
//
|
||
|
// judge mouse position whether is in selected area
|
||
|
//
|
||
|
//
|
||
|
// not select
|
||
|
//
|
||
|
if (HMainEditor.SelectStart == 0 || HMainEditor.SelectEnd == 0) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
//
|
||
|
// calculate the select area
|
||
|
//
|
||
|
RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
|
||
|
RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
|
||
|
|
||
|
ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
|
||
|
ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
|
||
|
|
||
|
FRow = HBufferImage.LowVisibleRow + MouseRow - 2;
|
||
|
if (FRow < RowStart || FRow > RowEnd) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (FRow > RowStart) {
|
||
|
ColStart = 1;
|
||
|
}
|
||
|
|
||
|
if (FRow < RowEnd) {
|
||
|
ColEnd = 0x10;
|
||
|
}
|
||
|
|
||
|
MouseColStart = 10 + (ColStart - 1) * 3;
|
||
|
if (ColStart > 8) {
|
||
|
MouseColStart++;
|
||
|
}
|
||
|
|
||
|
MouseColEnd = 10 + (ColEnd - 1) * 3 + 1;
|
||
|
if (ColEnd > 8) {
|
||
|
MouseColEnd++;
|
||
|
}
|
||
|
|
||
|
if (MouseCol < MouseColStart || MouseCol > MouseColEnd) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Set mouse position according to HBufferImage.MousePosition.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageRestoreMousePosition (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_COLOR_UNION Orig;
|
||
|
HEFI_EDITOR_COLOR_UNION New;
|
||
|
UINTN FRow;
|
||
|
UINTN FColumn;
|
||
|
BOOLEAN HasCharacter;
|
||
|
HEFI_EDITOR_LINE *CurrentLine;
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINT8 Value;
|
||
|
BOOLEAN HighBits;
|
||
|
|
||
|
Line = NULL;
|
||
|
if (HMainEditor.MouseSupported) {
|
||
|
|
||
|
if (HBufferImageMouseNeedRefresh) {
|
||
|
|
||
|
HBufferImageMouseNeedRefresh = FALSE;
|
||
|
|
||
|
//
|
||
|
// if mouse position not moved and only mouse action
|
||
|
// so do not need to refresh mouse position
|
||
|
//
|
||
|
if ((
|
||
|
HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row &&
|
||
|
HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column
|
||
|
) &&
|
||
|
HEditorMouseAction
|
||
|
) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
//
|
||
|
// backup the old screen attributes
|
||
|
//
|
||
|
Orig = HMainEditor.ColorAttributes;
|
||
|
New.Data = 0;
|
||
|
New.Colors.Foreground = Orig.Colors.Background & 0xF;
|
||
|
New.Colors.Background = Orig.Colors.Foreground & 0x7;
|
||
|
|
||
|
//
|
||
|
// if in selected area,
|
||
|
// so do not need to refresh mouse
|
||
|
//
|
||
|
if (!HBufferImageIsInSelectedArea (
|
||
|
HBufferImageBackupVar.MousePosition.Row,
|
||
|
HBufferImageBackupVar.MousePosition.Column
|
||
|
)) {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
|
||
|
} else {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
|
||
|
}
|
||
|
//
|
||
|
// clear the old mouse position
|
||
|
//
|
||
|
FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2;
|
||
|
|
||
|
HighBits = HBufferImageIsAtHighBits (
|
||
|
HBufferImageBackupVar.MousePosition.Column,
|
||
|
&FColumn
|
||
|
);
|
||
|
|
||
|
HasCharacter = TRUE;
|
||
|
if (FRow > HBufferImage.NumLines || FColumn == 0) {
|
||
|
HasCharacter = FALSE;
|
||
|
} else {
|
||
|
CurrentLine = HBufferImage.CurrentLine;
|
||
|
Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
|
||
|
|
||
|
if (Line == NULL || FColumn > Line->Size) {
|
||
|
HasCharacter = FALSE;
|
||
|
}
|
||
|
|
||
|
HBufferImage.CurrentLine = CurrentLine;
|
||
|
}
|
||
|
|
||
|
ShellPrintEx (
|
||
|
(INT32)HBufferImageBackupVar.MousePosition.Column - 1,
|
||
|
(INT32)HBufferImageBackupVar.MousePosition.Row - 1,
|
||
|
L" "
|
||
|
);
|
||
|
|
||
|
if (HasCharacter) {
|
||
|
if (HighBits) {
|
||
|
Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
|
||
|
Value = (UINT8) (Value >> 4);
|
||
|
} else {
|
||
|
Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
|
||
|
}
|
||
|
|
||
|
ShellPrintEx (
|
||
|
(INT32)HBufferImageBackupVar.MousePosition.Column - 1,
|
||
|
(INT32)HBufferImageBackupVar.MousePosition.Row - 1,
|
||
|
L"%x",
|
||
|
Value
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (!HBufferImageIsInSelectedArea (
|
||
|
HBufferImage.MousePosition.Row,
|
||
|
HBufferImage.MousePosition.Column
|
||
|
)) {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
|
||
|
} else {
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
|
||
|
}
|
||
|
//
|
||
|
// clear the old mouse position
|
||
|
//
|
||
|
FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2;
|
||
|
|
||
|
HighBits = HBufferImageIsAtHighBits (
|
||
|
HBufferImage.MousePosition.Column,
|
||
|
&FColumn
|
||
|
);
|
||
|
|
||
|
HasCharacter = TRUE;
|
||
|
if (FRow > HBufferImage.NumLines || FColumn == 0) {
|
||
|
HasCharacter = FALSE;
|
||
|
} else {
|
||
|
CurrentLine = HBufferImage.CurrentLine;
|
||
|
Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
|
||
|
|
||
|
if (Line == NULL || FColumn > Line->Size) {
|
||
|
HasCharacter = FALSE;
|
||
|
}
|
||
|
|
||
|
HBufferImage.CurrentLine = CurrentLine;
|
||
|
}
|
||
|
|
||
|
ShellPrintEx (
|
||
|
(INT32)HBufferImage.MousePosition.Column - 1,
|
||
|
(INT32)HBufferImage.MousePosition.Row - 1,
|
||
|
L" "
|
||
|
);
|
||
|
|
||
|
if (HasCharacter) {
|
||
|
if (HighBits) {
|
||
|
Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
|
||
|
Value = (UINT8) (Value >> 4);
|
||
|
} else {
|
||
|
Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
|
||
|
}
|
||
|
|
||
|
ShellPrintEx (
|
||
|
(INT32)HBufferImage.MousePosition.Column - 1,
|
||
|
(INT32)HBufferImage.MousePosition.Row - 1,
|
||
|
L"%x",
|
||
|
Value
|
||
|
);
|
||
|
}
|
||
|
//
|
||
|
// end of HasCharacter
|
||
|
//
|
||
|
gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
|
||
|
}
|
||
|
//
|
||
|
// end of MouseNeedRefresh
|
||
|
//
|
||
|
}
|
||
|
//
|
||
|
// end of MouseSupported
|
||
|
//
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Set cursor position according to HBufferImage.DisplayPosition.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageRestorePosition (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// set cursor position
|
||
|
//
|
||
|
gST->ConOut->SetCursorPosition (
|
||
|
gST->ConOut,
|
||
|
HBufferImage.DisplayPosition.Column - 1,
|
||
|
HBufferImage.DisplayPosition.Row - 1
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Refresh function for HBufferImage.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@retval EFI_LOAD_ERROR A Load error occured.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageRefresh (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
LIST_ENTRY *Link;
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINTN Row;
|
||
|
HEFI_EDITOR_COLOR_UNION Orig;
|
||
|
HEFI_EDITOR_COLOR_UNION New;
|
||
|
|
||
|
UINTN StartRow;
|
||
|
UINTN EndRow;
|
||
|
UINTN FStartRow;
|
||
|
UINTN Tmp;
|
||
|
|
||
|
Orig = HMainEditor.ColorAttributes;
|
||
|
New.Data = 0;
|
||
|
New.Colors.Foreground = Orig.Colors.Background;
|
||
|
New.Colors.Background = Orig.Colors.Foreground;
|
||
|
|
||
|
//
|
||
|
// if it's the first time after editor launch, so should refresh
|
||
|
//
|
||
|
if (HEditorFirst == FALSE) {
|
||
|
//
|
||
|
// no definite required refresh
|
||
|
// and file position displayed on screen has not been changed
|
||
|
//
|
||
|
if (!HBufferImageNeedRefresh &&
|
||
|
!HBufferImageOnlyLineNeedRefresh &&
|
||
|
HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow
|
||
|
) {
|
||
|
HBufferImageRestoreMousePosition ();
|
||
|
HBufferImageRestorePosition ();
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
|
||
|
|
||
|
//
|
||
|
// only need to refresh current line
|
||
|
//
|
||
|
if (HBufferImageOnlyLineNeedRefresh && HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) {
|
||
|
|
||
|
HBufferImagePrintLine (
|
||
|
HBufferImage.CurrentLine,
|
||
|
HBufferImage.DisplayPosition.Row,
|
||
|
HBufferImage.BufferPosition.Row,
|
||
|
Orig,
|
||
|
New
|
||
|
);
|
||
|
} else {
|
||
|
//
|
||
|
// the whole edit area need refresh
|
||
|
//
|
||
|
if (HEditorMouseAction && HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
|
||
|
if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) {
|
||
|
if (HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart && HMainEditorBackupVar.SelectStart != 0) {
|
||
|
StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1;
|
||
|
} else {
|
||
|
StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
|
||
|
}
|
||
|
} else {
|
||
|
StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
|
||
|
}
|
||
|
|
||
|
if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) {
|
||
|
EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1;
|
||
|
} else {
|
||
|
EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
|
||
|
}
|
||
|
//
|
||
|
// swap
|
||
|
//
|
||
|
if (StartRow > EndRow) {
|
||
|
Tmp = StartRow;
|
||
|
StartRow = EndRow;
|
||
|
EndRow = Tmp;
|
||
|
}
|
||
|
|
||
|
FStartRow = StartRow;
|
||
|
|
||
|
StartRow = 2 + StartRow - HBufferImage.LowVisibleRow;
|
||
|
EndRow = 2 + EndRow - HBufferImage.LowVisibleRow;
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// not mouse selection actions
|
||
|
//
|
||
|
FStartRow = HBufferImage.LowVisibleRow;
|
||
|
StartRow = 2;
|
||
|
EndRow = (HMainEditor.ScreenSize.Row - 1);
|
||
|
}
|
||
|
//
|
||
|
// no line
|
||
|
//
|
||
|
if (HBufferImage.Lines == NULL) {
|
||
|
HBufferImageRestoreMousePosition ();
|
||
|
HBufferImageRestorePosition ();
|
||
|
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
//
|
||
|
// get the first line that will be displayed
|
||
|
//
|
||
|
Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row);
|
||
|
if (Line == NULL) {
|
||
|
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
|
||
|
return EFI_LOAD_ERROR;
|
||
|
}
|
||
|
|
||
|
Link = &(Line->Link);
|
||
|
Row = StartRow;
|
||
|
do {
|
||
|
Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
|
||
|
|
||
|
//
|
||
|
// print line at row
|
||
|
//
|
||
|
HBufferImagePrintLine (
|
||
|
Line,
|
||
|
Row,
|
||
|
HBufferImage.LowVisibleRow + Row - 2,
|
||
|
Orig,
|
||
|
New
|
||
|
);
|
||
|
|
||
|
Link = Link->ForwardLink;
|
||
|
Row++;
|
||
|
} while (Link != HBufferImage.ListHead && Row <= EndRow);
|
||
|
|
||
|
while (Row <= EndRow) {
|
||
|
EditorClearLine (Row, HMainEditor.ScreenSize.Column, HMainEditor.ScreenSize.Row);
|
||
|
Row++;
|
||
|
}
|
||
|
//
|
||
|
// while not file end and not screen full
|
||
|
//
|
||
|
}
|
||
|
|
||
|
HBufferImageRestoreMousePosition ();
|
||
|
HBufferImageRestorePosition ();
|
||
|
|
||
|
HBufferImageNeedRefresh = FALSE;
|
||
|
HBufferImageOnlyLineNeedRefresh = FALSE;
|
||
|
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Read an image into a buffer friom a source.
|
||
|
|
||
|
@param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
|
||
|
@param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
|
||
|
@param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
|
||
|
@param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
|
||
|
@param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
|
||
|
@param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
|
||
|
@param[in] BufferType The type of buffer to save. IGNORED.
|
||
|
@param[in] Recover TRUE for recovermode, FALSE otherwise.
|
||
|
|
||
|
@return EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageRead (
|
||
|
IN CONST CHAR16 *FileName,
|
||
|
IN CONST CHAR16 *DiskName,
|
||
|
IN UINTN DiskOffset,
|
||
|
IN UINTN DiskSize,
|
||
|
IN UINTN MemOffset,
|
||
|
IN UINTN MemSize,
|
||
|
IN EDIT_FILE_TYPE BufferType,
|
||
|
IN BOOLEAN Recover
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EDIT_FILE_TYPE BufferTypeBackup;
|
||
|
|
||
|
//
|
||
|
// variable initialization
|
||
|
//
|
||
|
Status = EFI_SUCCESS;
|
||
|
HBufferImage.BufferType = BufferType;
|
||
|
|
||
|
//
|
||
|
// three types of buffer supported
|
||
|
// file buffer
|
||
|
// disk buffer
|
||
|
// memory buffer
|
||
|
//
|
||
|
BufferTypeBackup = HBufferImage.BufferType;
|
||
|
|
||
|
switch (BufferType) {
|
||
|
case FileTypeFileBuffer:
|
||
|
Status = HFileImageRead (FileName, Recover);
|
||
|
break;
|
||
|
|
||
|
case FileTypeDiskBuffer:
|
||
|
Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);
|
||
|
break;
|
||
|
|
||
|
case FileTypeMemBuffer:
|
||
|
Status = HMemImageRead (MemOffset, MemSize, Recover);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Status = EFI_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
HBufferImage.BufferType = BufferTypeBackup;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Save the current image.
|
||
|
|
||
|
@param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
|
||
|
@param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
|
||
|
@param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
|
||
|
@param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
|
||
|
@param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
|
||
|
@param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
|
||
|
@param[in] BufferType The type of buffer to save. IGNORED.
|
||
|
|
||
|
@return EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageSave (
|
||
|
IN CHAR16 *FileName,
|
||
|
IN CHAR16 *DiskName,
|
||
|
IN UINTN DiskOffset,
|
||
|
IN UINTN DiskSize,
|
||
|
IN UINTN MemOffset,
|
||
|
IN UINTN MemSize,
|
||
|
IN EDIT_FILE_TYPE BufferType
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EDIT_FILE_TYPE BufferTypeBackup;
|
||
|
|
||
|
//
|
||
|
// variable initialization
|
||
|
//
|
||
|
Status = EFI_SUCCESS;
|
||
|
BufferTypeBackup = HBufferImage.BufferType;
|
||
|
|
||
|
switch (HBufferImage.BufferType) {
|
||
|
//
|
||
|
// file buffer
|
||
|
//
|
||
|
case FileTypeFileBuffer:
|
||
|
Status = HFileImageSave (FileName);
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// disk buffer
|
||
|
//
|
||
|
case FileTypeDiskBuffer:
|
||
|
Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// memory buffer
|
||
|
//
|
||
|
case FileTypeMemBuffer:
|
||
|
Status = HMemImageSave (MemOffset, MemSize);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Status = EFI_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
HBufferImage.BufferType = BufferTypeBackup;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Create a new line and append it to the line list.
|
||
|
Fields affected:
|
||
|
NumLines
|
||
|
Lines
|
||
|
|
||
|
@retval NULL create line failed.
|
||
|
@return the line created.
|
||
|
|
||
|
**/
|
||
|
HEFI_EDITOR_LINE *
|
||
|
HBufferImageCreateLine (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
|
||
|
//
|
||
|
// allocate for line structure
|
||
|
//
|
||
|
Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));
|
||
|
if (Line == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Line->Signature = EFI_EDITOR_LINE_LIST;
|
||
|
Line->Size = 0;
|
||
|
|
||
|
HBufferImage.NumLines++;
|
||
|
|
||
|
//
|
||
|
// insert to line list
|
||
|
//
|
||
|
InsertTailList (HBufferImage.ListHead, &Line->Link);
|
||
|
|
||
|
if (HBufferImage.Lines == NULL) {
|
||
|
HBufferImage.Lines = CR (
|
||
|
HBufferImage.ListHead->ForwardLink,
|
||
|
HEFI_EDITOR_LINE,
|
||
|
Link,
|
||
|
EFI_EDITOR_LINE_LIST
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return Line;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Free the current image.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageFree (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// free all lines
|
||
|
//
|
||
|
HBufferImageFreeLines ();
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
change char to int value based on Hex.
|
||
|
|
||
|
@param[in] Char The input char.
|
||
|
|
||
|
@return The character's index value.
|
||
|
@retval -1 The operation failed.
|
||
|
**/
|
||
|
INTN
|
||
|
HBufferImageCharToHex (
|
||
|
IN CHAR16 Char
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// change the character to hex
|
||
|
//
|
||
|
if (Char >= L'0' && Char <= L'9') {
|
||
|
return (Char - L'0');
|
||
|
}
|
||
|
|
||
|
if (Char >= L'a' && Char <= L'f') {
|
||
|
return (Char - L'a' + 10);
|
||
|
}
|
||
|
|
||
|
if (Char >= L'A' && Char <= L'F') {
|
||
|
return (Char - L'A' + 10);
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Add character.
|
||
|
|
||
|
@param[in] Char -- input char.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageAddChar (
|
||
|
IN CHAR16 Char
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
HEFI_EDITOR_LINE *NewLine;
|
||
|
INTN Value;
|
||
|
UINT8 Old;
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
BOOLEAN High;
|
||
|
|
||
|
Value = HBufferImageCharToHex (Char);
|
||
|
|
||
|
//
|
||
|
// invalid input
|
||
|
//
|
||
|
if (Value == -1) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = HBufferImage.BufferPosition.Column;
|
||
|
High = HBufferImage.HighBits;
|
||
|
|
||
|
//
|
||
|
// only needs to refresh current line
|
||
|
//
|
||
|
HBufferImageOnlyLineNeedRefresh = TRUE;
|
||
|
|
||
|
//
|
||
|
// not a full line and beyond the last character
|
||
|
//
|
||
|
if (FCol > Line->Size) {
|
||
|
//
|
||
|
// cursor always at high 4 bits
|
||
|
// and always put input to the low 4 bits
|
||
|
//
|
||
|
Line->Buffer[Line->Size] = (UINT8) Value;
|
||
|
Line->Size++;
|
||
|
High = FALSE;
|
||
|
} else {
|
||
|
|
||
|
Old = Line->Buffer[FCol - 1];
|
||
|
|
||
|
//
|
||
|
// always put the input to the low 4 bits
|
||
|
//
|
||
|
Old = (UINT8) (Old & 0x0f);
|
||
|
Old = (UINT8) (Old << 4);
|
||
|
Old = (UINT8) (Value + Old);
|
||
|
Line->Buffer[FCol - 1] = Old;
|
||
|
|
||
|
//
|
||
|
// at the low 4 bits of the last character of a full line
|
||
|
// so if no next line, need to create a new line
|
||
|
//
|
||
|
if (!High && FCol == 0x10) {
|
||
|
|
||
|
HBufferImageOnlyLineNeedRefresh = FALSE;
|
||
|
HBufferImageNeedRefresh = TRUE;
|
||
|
|
||
|
if (Line->Link.ForwardLink == HBufferImage.ListHead) {
|
||
|
//
|
||
|
// last line
|
||
|
//
|
||
|
// create a new line
|
||
|
//
|
||
|
NewLine = HBufferImageCreateLine ();
|
||
|
if (NewLine == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
//
|
||
|
// end of NULL
|
||
|
//
|
||
|
}
|
||
|
//
|
||
|
// end of == ListHead
|
||
|
//
|
||
|
}
|
||
|
//
|
||
|
// end of == 0x10
|
||
|
//
|
||
|
// if already at end of this line, scroll it to the start of next line
|
||
|
//
|
||
|
if (FCol == 0x10 && !High) {
|
||
|
//
|
||
|
// definitely has next line
|
||
|
//
|
||
|
FRow++;
|
||
|
FCol = 1;
|
||
|
High = TRUE;
|
||
|
} else {
|
||
|
//
|
||
|
// if not at end of this line, just move to next column
|
||
|
//
|
||
|
if (!High) {
|
||
|
FCol++;
|
||
|
}
|
||
|
|
||
|
if (High) {
|
||
|
High = FALSE;
|
||
|
} else {
|
||
|
High = TRUE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
//
|
||
|
// end of ==FALSE
|
||
|
//
|
||
|
}
|
||
|
//
|
||
|
// move cursor to right
|
||
|
//
|
||
|
HBufferImageMovePosition (FRow, FCol, High);
|
||
|
|
||
|
if (!HBufferImage.Modified) {
|
||
|
HBufferImage.Modified = TRUE;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Delete the previous character.
|
||
|
|
||
|
@retval EFI_SUCCESS The operationw as successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageDoBackspace (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
|
||
|
UINTN FileColumn;
|
||
|
UINTN FPos;
|
||
|
BOOLEAN LastLine;
|
||
|
|
||
|
//
|
||
|
// variable initialization
|
||
|
//
|
||
|
LastLine = FALSE;
|
||
|
|
||
|
//
|
||
|
// already the first character
|
||
|
//
|
||
|
if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
|
||
|
|
||
|
FileColumn = HBufferImage.BufferPosition.Column;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
LastLine = FALSE;
|
||
|
if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) {
|
||
|
LastLine = TRUE;
|
||
|
}
|
||
|
|
||
|
HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);
|
||
|
|
||
|
//
|
||
|
// if is the last line
|
||
|
// then only this line need to be refreshed
|
||
|
//
|
||
|
if (LastLine) {
|
||
|
HBufferImageNeedRefresh = FALSE;
|
||
|
HBufferImageOnlyLineNeedRefresh = TRUE;
|
||
|
} else {
|
||
|
HBufferImageNeedRefresh = TRUE;
|
||
|
HBufferImageOnlyLineNeedRefresh = FALSE;
|
||
|
}
|
||
|
|
||
|
if (!HBufferImage.Modified) {
|
||
|
HBufferImage.Modified = TRUE;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
ASCII key + Backspace + return.
|
||
|
|
||
|
@param[in] Char The input char.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@retval EFI_LOAD_ERROR A load error occured.
|
||
|
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageDoCharInput (
|
||
|
IN CHAR16 Char
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
Status = EFI_SUCCESS;
|
||
|
|
||
|
switch (Char) {
|
||
|
case 0:
|
||
|
break;
|
||
|
|
||
|
case 0x08:
|
||
|
Status = HBufferImageDoBackspace ();
|
||
|
break;
|
||
|
|
||
|
case 0x09:
|
||
|
case 0x0a:
|
||
|
case 0x0d:
|
||
|
//
|
||
|
// Tabs, Returns are thought as nothing
|
||
|
//
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
//
|
||
|
// DEAL WITH ASCII CHAR, filter out thing like ctrl+f
|
||
|
//
|
||
|
if (Char > 127 || Char < 32) {
|
||
|
Status = StatusBarSetStatusString (L"Unknown Command");
|
||
|
} else {
|
||
|
Status = HBufferImageAddChar (Char);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Check user specified FileRow is above current screen.
|
||
|
|
||
|
@param[in] FileRow Row of file position ( start from 1 ).
|
||
|
|
||
|
@retval TRUE It is above the current screen.
|
||
|
@retval FALSE It is not above the current screen.
|
||
|
|
||
|
**/
|
||
|
BOOLEAN
|
||
|
HAboveCurrentScreen (
|
||
|
IN UINTN FileRow
|
||
|
)
|
||
|
{
|
||
|
if (FileRow < HBufferImage.LowVisibleRow) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Check user specified FileRow is under current screen.
|
||
|
|
||
|
@param[in] FileRow Row of file position ( start from 1 ).
|
||
|
|
||
|
@retval TRUE It is under the current screen.
|
||
|
@retval FALSE It is not under the current screen.
|
||
|
|
||
|
**/
|
||
|
BOOLEAN
|
||
|
HUnderCurrentScreen (
|
||
|
IN UINTN FileRow
|
||
|
)
|
||
|
{
|
||
|
if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
According to cursor's file position, adjust screen display.
|
||
|
|
||
|
@param[in] NewFilePosRow Row of file position ( start from 1 ).
|
||
|
@param[in] NewFilePosCol Column of file position ( start from 1 ).
|
||
|
@param[in] HighBits Cursor will on high4 bits or low4 bits.
|
||
|
**/
|
||
|
VOID
|
||
|
HBufferImageMovePosition (
|
||
|
IN UINTN NewFilePosRow,
|
||
|
IN UINTN NewFilePosCol,
|
||
|
IN BOOLEAN HighBits
|
||
|
)
|
||
|
{
|
||
|
INTN RowGap;
|
||
|
UINTN Abs;
|
||
|
BOOLEAN Above;
|
||
|
BOOLEAN Under;
|
||
|
UINTN NewDisplayCol;
|
||
|
|
||
|
//
|
||
|
// CALCULATE gap between current file position and new file position
|
||
|
//
|
||
|
RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row;
|
||
|
|
||
|
Under = HUnderCurrentScreen (NewFilePosRow);
|
||
|
Above = HAboveCurrentScreen (NewFilePosRow);
|
||
|
|
||
|
HBufferImage.HighBits = HighBits;
|
||
|
|
||
|
//
|
||
|
// if is below current screen
|
||
|
//
|
||
|
if (Under) {
|
||
|
//
|
||
|
// display row will be unchanged
|
||
|
//
|
||
|
HBufferImage.BufferPosition.Row = NewFilePosRow;
|
||
|
} else {
|
||
|
if (Above) {
|
||
|
//
|
||
|
// has enough above line, so display row unchanged
|
||
|
// not has enough above lines, so the first line is
|
||
|
// at the first display line
|
||
|
//
|
||
|
if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {
|
||
|
HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;
|
||
|
}
|
||
|
|
||
|
HBufferImage.BufferPosition.Row = NewFilePosRow;
|
||
|
} else {
|
||
|
//
|
||
|
// in current screen
|
||
|
//
|
||
|
HBufferImage.BufferPosition.Row = NewFilePosRow;
|
||
|
if (RowGap <= 0) {
|
||
|
Abs = (UINTN)ABS(RowGap);
|
||
|
HBufferImage.DisplayPosition.Row -= Abs;
|
||
|
} else {
|
||
|
HBufferImage.DisplayPosition.Row += RowGap;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);
|
||
|
|
||
|
//
|
||
|
// always in current screen
|
||
|
//
|
||
|
HBufferImage.BufferPosition.Column = NewFilePosCol;
|
||
|
|
||
|
NewDisplayCol = 10 + (NewFilePosCol - 1) * 3;
|
||
|
if (NewFilePosCol > 0x8) {
|
||
|
NewDisplayCol++;
|
||
|
}
|
||
|
|
||
|
if (!HighBits) {
|
||
|
NewDisplayCol++;
|
||
|
}
|
||
|
|
||
|
HBufferImage.DisplayPosition.Column = NewDisplayCol;
|
||
|
|
||
|
//
|
||
|
// let CurrentLine point to correct line;
|
||
|
//
|
||
|
HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to right.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageScrollRight (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
|
||
|
//
|
||
|
// scroll right will always move to the high4 bits of the next character
|
||
|
//
|
||
|
HBufferImageNeedRefresh = FALSE;
|
||
|
HBufferImageOnlyLineNeedRefresh = FALSE;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = HBufferImage.BufferPosition.Column;
|
||
|
|
||
|
//
|
||
|
// this line is not full and no next line
|
||
|
//
|
||
|
if (FCol > Line->Size) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
//
|
||
|
// if already at end of this line, scroll it to the start of next line
|
||
|
//
|
||
|
if (FCol == 0x10) {
|
||
|
//
|
||
|
// has next line
|
||
|
//
|
||
|
if (Line->Link.ForwardLink != HBufferImage.ListHead) {
|
||
|
FRow++;
|
||
|
FCol = 1;
|
||
|
|
||
|
} else {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// if not at end of this line, just move to next column
|
||
|
//
|
||
|
FCol++;
|
||
|
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (FRow, FCol, TRUE);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to left.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageScrollLeft (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
|
||
|
HBufferImageNeedRefresh = FALSE;
|
||
|
HBufferImageOnlyLineNeedRefresh = FALSE;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = HBufferImage.BufferPosition.Column;
|
||
|
|
||
|
//
|
||
|
// if already at start of this line, so move to the end of previous line
|
||
|
//
|
||
|
if (FCol <= 1) {
|
||
|
//
|
||
|
// has previous line
|
||
|
//
|
||
|
if (Line->Link.BackLink != HBufferImage.ListHead) {
|
||
|
FRow--;
|
||
|
Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
|
||
|
FCol = Line->Size;
|
||
|
} else {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// if not at start of this line, just move to previous column
|
||
|
//
|
||
|
FCol--;
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (FRow, FCol, TRUE);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to the next line
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageScrollDown (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
BOOLEAN HighBits;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = HBufferImage.BufferPosition.Column;
|
||
|
HighBits = HBufferImage.HighBits;
|
||
|
|
||
|
//
|
||
|
// has next line
|
||
|
//
|
||
|
if (Line->Link.ForwardLink != HBufferImage.ListHead) {
|
||
|
FRow++;
|
||
|
Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
|
||
|
|
||
|
//
|
||
|
// if the next line is not that long, so move to end of next line
|
||
|
//
|
||
|
if (FCol > Line->Size) {
|
||
|
FCol = Line->Size + 1;
|
||
|
HighBits = TRUE;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (FRow, FCol, HighBits);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to previous line
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageScrollUp (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = HBufferImage.BufferPosition.Column;
|
||
|
|
||
|
//
|
||
|
// has previous line
|
||
|
//
|
||
|
if (Line->Link.BackLink != HBufferImage.ListHead) {
|
||
|
FRow--;
|
||
|
|
||
|
} else {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to next page
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImagePageDown (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
UINTN Gap;
|
||
|
BOOLEAN HighBits;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = HBufferImage.BufferPosition.Column;
|
||
|
HighBits = HBufferImage.HighBits;
|
||
|
|
||
|
//
|
||
|
// has next page
|
||
|
//
|
||
|
if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) {
|
||
|
Gap = (HMainEditor.ScreenSize.Row - 2);
|
||
|
} else {
|
||
|
//
|
||
|
// MOVE CURSOR TO LAST LINE
|
||
|
//
|
||
|
Gap = HBufferImage.NumLines - FRow;
|
||
|
}
|
||
|
//
|
||
|
// get correct line
|
||
|
//
|
||
|
Line = HMoveLine (Gap);
|
||
|
|
||
|
//
|
||
|
// if that line, is not that long, so move to the end of that line
|
||
|
//
|
||
|
if (Line != NULL && FCol > Line->Size) {
|
||
|
FCol = Line->Size + 1;
|
||
|
HighBits = TRUE;
|
||
|
}
|
||
|
|
||
|
FRow += Gap;
|
||
|
|
||
|
HBufferImageMovePosition (FRow, FCol, HighBits);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to previous page
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImagePageUp (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
UINTN Gap;
|
||
|
INTN Retreat;
|
||
|
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = HBufferImage.BufferPosition.Column;
|
||
|
|
||
|
//
|
||
|
// has previous page
|
||
|
//
|
||
|
if (FRow > (HMainEditor.ScreenSize.Row - 2)) {
|
||
|
Gap = (HMainEditor.ScreenSize.Row - 2);
|
||
|
} else {
|
||
|
//
|
||
|
// the first line of file will displayed on the first line of screen
|
||
|
//
|
||
|
Gap = FRow - 1;
|
||
|
}
|
||
|
|
||
|
Retreat = Gap;
|
||
|
Retreat = -Retreat;
|
||
|
|
||
|
FRow -= Gap;
|
||
|
|
||
|
HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to start of line
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageHome (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
BOOLEAN HighBits;
|
||
|
|
||
|
//
|
||
|
// curosr will at the high bit
|
||
|
//
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
FCol = 1;
|
||
|
HighBits = TRUE;
|
||
|
|
||
|
//
|
||
|
// move cursor position
|
||
|
//
|
||
|
HBufferImageMovePosition (FRow, FCol, HighBits);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Scroll cursor to end of line.
|
||
|
|
||
|
@retval EFI_SUCCESS Teh operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageEnd (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINTN FRow;
|
||
|
UINTN FCol;
|
||
|
BOOLEAN HighBits;
|
||
|
|
||
|
//
|
||
|
// need refresh mouse
|
||
|
//
|
||
|
HBufferImageMouseNeedRefresh = TRUE;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
|
||
|
FRow = HBufferImage.BufferPosition.Row;
|
||
|
|
||
|
if (Line->Size == 0x10) {
|
||
|
FCol = Line->Size;
|
||
|
HighBits = FALSE;
|
||
|
} else {
|
||
|
FCol = Line->Size + 1;
|
||
|
HighBits = TRUE;
|
||
|
}
|
||
|
//
|
||
|
// move cursor position
|
||
|
//
|
||
|
HBufferImageMovePosition (FRow, FCol, HighBits);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Get the size of the open buffer.
|
||
|
|
||
|
@retval The size in bytes.
|
||
|
**/
|
||
|
UINTN
|
||
|
HBufferImageGetTotalSize (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
UINTN Size;
|
||
|
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
|
||
|
//
|
||
|
// calculate the total size of whole line list's buffer
|
||
|
//
|
||
|
if (HBufferImage.Lines == NULL) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Line = CR (
|
||
|
HBufferImage.ListHead->BackLink,
|
||
|
HEFI_EDITOR_LINE,
|
||
|
Link,
|
||
|
EFI_EDITOR_LINE_LIST
|
||
|
);
|
||
|
//
|
||
|
// one line at most 0x10
|
||
|
//
|
||
|
Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;
|
||
|
|
||
|
return Size;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Delete character from buffer.
|
||
|
|
||
|
@param[in] Pos Position, Pos starting from 0.
|
||
|
@param[in] Count The Count of characters to delete.
|
||
|
@param[out] DeleteBuffer The DeleteBuffer.
|
||
|
|
||
|
@retval EFI_SUCCESS Success
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageDeleteCharacterFromBuffer (
|
||
|
IN UINTN Pos,
|
||
|
IN UINTN Count,
|
||
|
OUT UINT8 *DeleteBuffer
|
||
|
)
|
||
|
{
|
||
|
UINTN Index;
|
||
|
|
||
|
VOID *Buffer;
|
||
|
UINT8 *BufferPtr;
|
||
|
UINTN Size;
|
||
|
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
LIST_ENTRY *Link;
|
||
|
|
||
|
UINTN OldFCol;
|
||
|
UINTN OldFRow;
|
||
|
UINTN OldPos;
|
||
|
|
||
|
UINTN NewPos;
|
||
|
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
Size = HBufferImageGetTotalSize ();
|
||
|
|
||
|
if (Size < Count) {
|
||
|
return EFI_LOAD_ERROR;
|
||
|
}
|
||
|
|
||
|
if (Size == 0) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// relocate all the HBufferImage fields
|
||
|
//
|
||
|
OldFRow = HBufferImage.BufferPosition.Row;
|
||
|
OldFCol = HBufferImage.BufferPosition.Column;
|
||
|
OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
|
||
|
|
||
|
if (Pos > 0) {
|
||
|
//
|
||
|
// has character before it,
|
||
|
// so locate according to block's previous character
|
||
|
//
|
||
|
NewPos = Pos - 1;
|
||
|
|
||
|
} else {
|
||
|
//
|
||
|
// has no character before it,
|
||
|
// so locate according to block's next character
|
||
|
//
|
||
|
NewPos = 0;
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
|
||
|
|
||
|
Buffer = AllocateZeroPool (Size);
|
||
|
if (Buffer == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
HBufferImageListToBuffer (Buffer, Size);
|
||
|
|
||
|
BufferPtr = (UINT8 *) Buffer;
|
||
|
|
||
|
//
|
||
|
// pass deleted buffer out
|
||
|
//
|
||
|
if (DeleteBuffer != NULL) {
|
||
|
for (Index = 0; Index < Count; Index++) {
|
||
|
DeleteBuffer[Index] = BufferPtr[Pos + Index];
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// delete the part from Pos
|
||
|
//
|
||
|
for (Index = Pos; Index < Size - Count; Index++) {
|
||
|
BufferPtr[Index] = BufferPtr[Index + Count];
|
||
|
}
|
||
|
|
||
|
Size -= Count;
|
||
|
|
||
|
HBufferImageFreeLines ();
|
||
|
|
||
|
Status = HBufferImageBufferToList (Buffer, Size);
|
||
|
FreePool (Buffer);
|
||
|
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
Link = HMainEditor.BufferImage->ListHead->ForwardLink;
|
||
|
for (Index = 0; Index < NewPos / 0x10; Index++) {
|
||
|
Link = Link->ForwardLink;
|
||
|
}
|
||
|
|
||
|
Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
|
||
|
HBufferImage.CurrentLine = Line;
|
||
|
|
||
|
//
|
||
|
// if current cursor position if inside select area
|
||
|
// then move it to the block's NEXT character
|
||
|
//
|
||
|
if (OldPos >= Pos && OldPos < (Pos + Count)) {
|
||
|
NewPos = Pos;
|
||
|
} else {
|
||
|
if (OldPos < Pos) {
|
||
|
NewPos = OldPos;
|
||
|
} else {
|
||
|
NewPos = OldPos - Count;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Add character to buffer, add before pos.
|
||
|
|
||
|
@param[in] Pos Position, Pos starting from 0.
|
||
|
@param[in] Count Count of characters to add.
|
||
|
@param[in] AddBuffer Add buffer.
|
||
|
|
||
|
@retval EFI_SUCCESS Success.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageAddCharacterToBuffer (
|
||
|
IN UINTN Pos,
|
||
|
IN UINTN Count,
|
||
|
IN UINT8 *AddBuffer
|
||
|
)
|
||
|
{
|
||
|
INTN Index;
|
||
|
|
||
|
VOID *Buffer;
|
||
|
UINT8 *BufferPtr;
|
||
|
UINTN Size;
|
||
|
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
|
||
|
LIST_ENTRY *Link;
|
||
|
|
||
|
UINTN OldFCol;
|
||
|
UINTN OldFRow;
|
||
|
UINTN OldPos;
|
||
|
|
||
|
UINTN NewPos;
|
||
|
|
||
|
Size = HBufferImageGetTotalSize ();
|
||
|
|
||
|
//
|
||
|
// relocate all the HBufferImage fields
|
||
|
//
|
||
|
OldFRow = HBufferImage.BufferPosition.Row;
|
||
|
OldFCol = HBufferImage.BufferPosition.Column;
|
||
|
OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
|
||
|
|
||
|
//
|
||
|
// move cursor before Pos
|
||
|
//
|
||
|
if (Pos > 0) {
|
||
|
NewPos = Pos - 1;
|
||
|
} else {
|
||
|
NewPos = 0;
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
|
||
|
|
||
|
Buffer = AllocateZeroPool (Size + Count);
|
||
|
if (Buffer == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
HBufferImageListToBuffer (Buffer, Size);
|
||
|
|
||
|
BufferPtr = (UINT8 *) Buffer;
|
||
|
|
||
|
//
|
||
|
// get a place to add
|
||
|
//
|
||
|
for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) {
|
||
|
BufferPtr[Index] = BufferPtr[Index - Count];
|
||
|
}
|
||
|
//
|
||
|
// add the buffer
|
||
|
//
|
||
|
for (Index = (INTN) 0; Index < (INTN) Count; Index++) {
|
||
|
BufferPtr[Index + Pos] = AddBuffer[Index];
|
||
|
}
|
||
|
|
||
|
Size += Count;
|
||
|
|
||
|
HBufferImageFreeLines ();
|
||
|
|
||
|
HBufferImageBufferToList (Buffer, Size);
|
||
|
|
||
|
FreePool (Buffer);
|
||
|
|
||
|
Link = HMainEditor.BufferImage->ListHead->ForwardLink;
|
||
|
for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) {
|
||
|
Link = Link->ForwardLink;
|
||
|
}
|
||
|
|
||
|
Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
|
||
|
HBufferImage.CurrentLine = Line;
|
||
|
|
||
|
if (OldPos >= Pos) {
|
||
|
NewPos = OldPos + Count;
|
||
|
} else {
|
||
|
NewPos = OldPos;
|
||
|
}
|
||
|
|
||
|
HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Delete current character from line.
|
||
|
|
||
|
@retval EFI_SUCCESS The operationw as successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageDoDelete (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
|
||
|
BOOLEAN LastLine;
|
||
|
UINTN FileColumn;
|
||
|
UINTN FPos;
|
||
|
|
||
|
FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
|
||
|
|
||
|
FileColumn = HBufferImage.BufferPosition.Column;
|
||
|
|
||
|
Line = HBufferImage.CurrentLine;
|
||
|
|
||
|
//
|
||
|
// if beyond the last character
|
||
|
//
|
||
|
if (FileColumn > Line->Size) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
LastLine = FALSE;
|
||
|
if (Line->Link.ForwardLink == HBufferImage.ListHead) {
|
||
|
LastLine = TRUE;
|
||
|
}
|
||
|
|
||
|
HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);
|
||
|
|
||
|
//
|
||
|
// if is the last line
|
||
|
// then only this line need to be refreshed
|
||
|
//
|
||
|
if (LastLine) {
|
||
|
HBufferImageNeedRefresh = FALSE;
|
||
|
HBufferImageOnlyLineNeedRefresh = TRUE;
|
||
|
} else {
|
||
|
HBufferImageNeedRefresh = TRUE;
|
||
|
HBufferImageOnlyLineNeedRefresh = FALSE;
|
||
|
}
|
||
|
|
||
|
if (!HBufferImage.Modified) {
|
||
|
HBufferImage.Modified = TRUE;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Change the raw buffer to a list of lines for the UI.
|
||
|
|
||
|
@param[in] Buffer The pointer to the buffer to fill.
|
||
|
@param[in] Bytes The size of the buffer in bytes.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageBufferToList (
|
||
|
IN VOID *Buffer,
|
||
|
IN UINTN Bytes
|
||
|
)
|
||
|
{
|
||
|
UINTN TempI;
|
||
|
UINTN TempJ;
|
||
|
UINTN Left;
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
UINT8 *BufferPtr;
|
||
|
|
||
|
TempI = 0;
|
||
|
Left = 0;
|
||
|
BufferPtr = (UINT8 *) Buffer;
|
||
|
|
||
|
//
|
||
|
// parse file content line by line
|
||
|
//
|
||
|
while (TempI < Bytes) {
|
||
|
if (Bytes - TempI >= 0x10) {
|
||
|
Left = 0x10;
|
||
|
} else {
|
||
|
Left = Bytes - TempI;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// allocate a new line
|
||
|
//
|
||
|
Line = HBufferImageCreateLine ();
|
||
|
if (Line == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
Line->Size = Left;
|
||
|
|
||
|
for (TempJ = 0; TempJ < Left; TempJ++) {
|
||
|
Line->Buffer[TempJ] = BufferPtr[TempI];
|
||
|
TempI++;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// last line is a full line, SO create a new line
|
||
|
//
|
||
|
if (Left == 0x10 || Bytes == 0) {
|
||
|
Line = HBufferImageCreateLine ();
|
||
|
if (Line == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Change the list of lines from the UI to a raw buffer.
|
||
|
|
||
|
@param[in] Buffer The pointer to the buffer to fill.
|
||
|
@param[in] Bytes The size of the buffer in bytes.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageListToBuffer (
|
||
|
IN VOID *Buffer,
|
||
|
IN UINTN Bytes
|
||
|
)
|
||
|
{
|
||
|
UINTN Count;
|
||
|
UINTN Index;
|
||
|
HEFI_EDITOR_LINE *Line;
|
||
|
LIST_ENTRY *Link;
|
||
|
UINT8 *BufferPtr;
|
||
|
|
||
|
//
|
||
|
// change the line list to a large buffer
|
||
|
//
|
||
|
if (HBufferImage.Lines == NULL) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
Link = &HBufferImage.Lines->Link;
|
||
|
Count = 0;
|
||
|
BufferPtr = (UINT8 *) Buffer;
|
||
|
|
||
|
//
|
||
|
// deal line by line
|
||
|
//
|
||
|
while (Link != HBufferImage.ListHead) {
|
||
|
|
||
|
Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
|
||
|
|
||
|
//@todo shouldn't this be an error???
|
||
|
if (Count + Line->Size > Bytes) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
for (Index = 0; Index < Line->Size; Index++) {
|
||
|
BufferPtr[Index] = Line->Buffer[Index];
|
||
|
}
|
||
|
|
||
|
Count += Line->Size;
|
||
|
BufferPtr += Line->Size;
|
||
|
|
||
|
Link = Link->ForwardLink;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Move the mouse in the image buffer.
|
||
|
|
||
|
@param[in] TextX The x-coordinate.
|
||
|
@param[in] TextY The y-coordinate.
|
||
|
**/
|
||
|
VOID
|
||
|
HBufferImageAdjustMousePosition (
|
||
|
IN INT32 TextX,
|
||
|
IN INT32 TextY
|
||
|
)
|
||
|
{
|
||
|
UINTN TempX;
|
||
|
UINTN TempY;
|
||
|
UINTN AbsX;
|
||
|
UINTN AbsY;
|
||
|
|
||
|
//
|
||
|
// TextX and TextY is mouse movement data returned by mouse driver
|
||
|
// This function will change it to MousePosition
|
||
|
//
|
||
|
//
|
||
|
// get absolute TempX value
|
||
|
//
|
||
|
if (TextX >= 0) {
|
||
|
AbsX = TextX;
|
||
|
} else {
|
||
|
AbsX = -TextX;
|
||
|
}
|
||
|
//
|
||
|
// get absolute TempY value
|
||
|
//
|
||
|
if (TextY >= 0) {
|
||
|
AbsY = TextY;
|
||
|
} else {
|
||
|
AbsY = -TextY;
|
||
|
}
|
||
|
|
||
|
TempX = HBufferImage.MousePosition.Column;
|
||
|
TempY = HBufferImage.MousePosition.Row;
|
||
|
|
||
|
if (TextX >= 0) {
|
||
|
TempX += TextX;
|
||
|
} else {
|
||
|
if (TempX >= AbsX) {
|
||
|
TempX -= AbsX;
|
||
|
} else {
|
||
|
TempX = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (TextY >= 0) {
|
||
|
TempY += TextY;
|
||
|
} else {
|
||
|
if (TempY >= AbsY) {
|
||
|
TempY -= AbsY;
|
||
|
} else {
|
||
|
TempY = 0;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// check whether new mouse column position is beyond screen
|
||
|
// if not, adjust it
|
||
|
//
|
||
|
if (TempX >= 10 && TempX <= (10 + 0x10 * 3 - 1)) {
|
||
|
HBufferImage.MousePosition.Column = TempX;
|
||
|
} else if (TempX < 10) {
|
||
|
HBufferImage.MousePosition.Column = 10;
|
||
|
} else if (TempX > (10 + 0x10 * 3 - 1)) {
|
||
|
HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;
|
||
|
}
|
||
|
//
|
||
|
// check whether new mouse row position is beyond screen
|
||
|
// if not, adjust it
|
||
|
//
|
||
|
if (TempY >= 2 && TempY <= (HMainEditor.ScreenSize.Row - 1)) {
|
||
|
HBufferImage.MousePosition.Row = TempY;
|
||
|
} else if (TempY < 2) {
|
||
|
HBufferImage.MousePosition.Row = 2;
|
||
|
} else if (TempY > (HMainEditor.ScreenSize.Row - 1)) {
|
||
|
HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Dispatch input to different handler
|
||
|
|
||
|
@param[in] Key The input key:
|
||
|
the keys can be:
|
||
|
ASCII KEY
|
||
|
Backspace/Delete
|
||
|
Direction key: up/down/left/right/pgup/pgdn
|
||
|
Home/End
|
||
|
INS
|
||
|
|
||
|
@retval EFI_SUCCESS The operation was successful.
|
||
|
@retval EFI_LOAD_ERROR A load error occured.
|
||
|
@retval EFI_OUT_OF_RESOURCES A Memory allocation failed.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
HBufferImageHandleInput (
|
||
|
IN EFI_INPUT_KEY *Key
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
Status = EFI_SUCCESS;
|
||
|
|
||
|
switch (Key->ScanCode) {
|
||
|
//
|
||
|
// ordinary key
|
||
|
//
|
||
|
case SCAN_NULL:
|
||
|
Status = HBufferImageDoCharInput (Key->UnicodeChar);
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// up arrow
|
||
|
//
|
||
|
case SCAN_UP:
|
||
|
Status = HBufferImageScrollUp ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// down arrow
|
||
|
//
|
||
|
case SCAN_DOWN:
|
||
|
Status = HBufferImageScrollDown ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// right arrow
|
||
|
//
|
||
|
case SCAN_RIGHT:
|
||
|
Status = HBufferImageScrollRight ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// left arrow
|
||
|
//
|
||
|
case SCAN_LEFT:
|
||
|
Status = HBufferImageScrollLeft ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// page up
|
||
|
//
|
||
|
case SCAN_PAGE_UP:
|
||
|
Status = HBufferImagePageUp ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// page down
|
||
|
//
|
||
|
case SCAN_PAGE_DOWN:
|
||
|
Status = HBufferImagePageDown ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// delete
|
||
|
//
|
||
|
case SCAN_DELETE:
|
||
|
Status = HBufferImageDoDelete ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// home
|
||
|
//
|
||
|
case SCAN_HOME:
|
||
|
Status = HBufferImageHome ();
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// end
|
||
|
//
|
||
|
case SCAN_END:
|
||
|
Status = HBufferImageEnd ();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Status = StatusBarSetStatusString (L"Unknown Command");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|