blob: be77e31a40b70c9b276f2b77eaf4bdd13f32d3b2 [file] [log] [blame]
/** @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 - 2018, Intel Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#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 occurred.
**/
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 occurred.
**/
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 occurred.
@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 occurred.
@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;
}