windows-nt/Source/XPSP1/NT/base/efiutil/sdk/shell/hexedit/libfilebuffer.c
2020-09-26 16:20:57 +08:00

761 lines
16 KiB
C

/*++
Copyright (c) 1999 Intel Corporation
Module Name:
libFileBuffer.c
--*/
#ifndef _LIB_FILE_BUFFER
#define _LIB_FILE_BUFFER
#include "libMisc.h"
#define ABSOLUTE_MAX_COLUMNS 132
STATIC CHAR16 BlankLine[ABSOLUTE_MAX_COLUMNS];
STATIC EFI_STATUS FileBufferScrollUp (VOID);
STATIC EFI_STATUS FileBufferScrollDown (VOID);
STATIC EFI_STATUS FileBufferScrollLeft (VOID);
STATIC EFI_STATUS FileBufferScrollRight (VOID);
STATIC EFI_STATUS FileBufferPageUp (VOID);
STATIC EFI_STATUS FileBufferPageDown (VOID);
STATIC EFI_STATUS FileBufferHome (VOID);
STATIC EFI_STATUS FileBufferEnd (VOID);
STATIC EFI_STATUS FileBufferDoDelete (VOID);
STATIC EFI_STATUS FileBufferDoBackspace (VOID);
STATIC EFI_STATUS FileBufferDoHexInput (CHAR16);
STATIC EFI_STATUS FileBufferRefreshCurrentLine(VOID);
STATIC EFI_STATUS FileBufferRefreshDown (VOID);
STATIC EFI_STATUS FileBufferInit (VOID);
STATIC EFI_STATUS FileBufferCleanup (VOID);
STATIC EFI_STATUS FileBufferRefresh (VOID);
STATIC EFI_STATUS FileBufferHide (VOID);
STATIC EFI_STATUS FileBufferHandleInput (EFI_INPUT_KEY*);
STATIC EFI_STATUS FileBufferClearLine (UINTN);
STATIC EFI_STATUS FileBufferSetPosition (UINTN,UINTN);
STATIC EFI_STATUS FileBufferRestorePosition (VOID);
STATIC UINTN DisplayPosition();
EE_FILE_BUFFER FileBuffer = {
{0,0},
0x00,
0x00,
0x00,
0x00,
NULL,
FileBufferInit,
FileBufferCleanup,
FileBufferRefresh,
FileBufferHide,
FileBufferHandleInput,
FileBufferClearLine,
FileBufferSetPosition,
FileBufferRestorePosition,
};
STATIC
EFI_STATUS
FileBufferInit (
VOID
)
{
UINTN i;
FileBuffer.DisplayPosition.Row = TEXT_START_ROW;
FileBuffer.DisplayPosition.Column = HEX_POSITION;
FileBuffer.MaxVisibleBytes = MAX_TEXT_ROWS * 0x10;
for (i = 0; i < ABSOLUTE_MAX_COLUMNS; i++) {
BlankLine[i] = ' ';
}
LineCreateNode(MainEditor.BufferImage->ListHead);
FileBuffer.CurrentLine = MainEditor.BufferImage->ListHead->Flink;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferCleanup (
VOID
)
{
return EFI_SUCCESS;
}
STATIC
VOID
RefreshOffset (
VOID
)
{
PrintAt(0,FileBuffer.DisplayPosition.Row,L"%X",FileBuffer.Offset&0xfffffff0);
FileBufferRestorePosition();
}
STATIC
EFI_STATUS
FileBufferRefresh (
VOID
)
{
UINTN i;
UINTN Limit;
LIST_ENTRY *Item;
UINTN Offset = 0x00;
UINTN Row;
Item = MainEditor.BufferImage->ListHead->Flink;
FileBuffer.HighVisibleOffset = FileBuffer.MaxVisibleBytes;
Row = FileBuffer.LowVisibleOffset / 0x10;
for (i = 0; i < Row && Item != MainEditor.BufferImage->ListHead; i++) {
Item = Item->Flink;
FileBuffer.HighVisibleOffset += 0x10;
Offset += 0x10;
}
Limit = FileBuffer.MaxVisibleBytes / 0x10;
i = TEXT_START_ROW;
for (i = TEXT_START_ROW; i <= Limit; i++) {
if (Item->Flink != MainEditor.BufferImage->ListHead) {
LinePrint (Item,Offset,i);
Offset += 0x10;
Item = Item->Flink;
} else {
FileBufferClearLine(i);
}
}
RefreshOffset();
FileBufferRestorePosition();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferRefreshDown (
VOID
)
{
UINTN Limit;
LIST_ENTRY *Link;
UINTN i;
UINTN Offset;
Limit = FileBuffer.MaxVisibleBytes / 0x10;
Offset = FileBuffer.Offset & 0xfffffff0;
Link = FileBuffer.CurrentLine;
/* while (Link != MainEditor.BufferImage->ListHead) { */
for (i = FileBuffer.DisplayPosition.Row; i < TEXT_END_ROW; i++) {
if (Link->Flink != MainEditor.BufferImage->ListHead) {
LinePrint (Link,Offset,i);
Link = Link->Flink;
Offset += 0x10;
} else {
FileBufferClearLine(i);
}
}
FileBufferRestorePosition();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferHandleInput (
IN EFI_INPUT_KEY* Key
)
{
switch (Key->ScanCode) {
case SCAN_CODE_NULL:
FileBufferDoHexInput (Key->UnicodeChar);
break;
case SCAN_CODE_UP:
FileBufferScrollUp();
break;
case SCAN_CODE_DOWN:
FileBufferScrollDown();
break;
case SCAN_CODE_RIGHT:
FileBufferScrollRight();
break;
case SCAN_CODE_LEFT:
FileBufferScrollLeft();
break;
case SCAN_CODE_PGUP:
FileBufferPageUp();
break;
case SCAN_CODE_PGDN:
FileBufferPageDown();
break;
case SCAN_CODE_DEL:
FileBufferDoDelete();
break;
case SCAN_CODE_HOME:
FileBufferHome();
break;
case SCAN_CODE_END:
FileBufferEnd();
break;
default:
break;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferHide (
VOID
)
{
UINTN i;
UINTN NumLines;
NumLines = FileBuffer.MaxVisibleBytes / 0x10;
for (i = TEXT_START_ROW; i <= NumLines; i++) {
FileBufferClearLine(i);
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferRefreshCurrentLine (
VOID
)
{
UINTN Where;
Where = FileBuffer.DisplayPosition.Row;
LinePrint(FileBuffer.CurrentLine,(FileBuffer.Offset & 0xfffffff0),Where);
FileBufferRestorePosition();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferRefreshCurrentDigit (
VOID
)
{
UINTN Row;
UINTN Pos;
Row = FileBuffer.DisplayPosition.Row;
Pos = FileBuffer.Offset % 0x10;
DigitPrint(FileBuffer.CurrentLine,Pos,Row);
FileBufferRestorePosition();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferClearLine (
UINTN Line
)
{
BlankLine[MAX_TEXT_COLUMNS-1] = 0;
PrintAt(0,Line,BlankLine);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferSetPosition (
IN UINTN Row,
IN UINTN Column
)
{
FileBuffer.DisplayPosition.Row = Row;
FileBuffer.DisplayPosition.Column = Column;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferRestorePosition (
VOID
)
{
Out->SetCursorPosition (Out,FileBuffer.DisplayPosition.Column,FileBuffer.DisplayPosition.Row);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferScrollDown (
VOID
)
{
UINTN MaxBytes;
UINTN HighOffset;
UINTN CurrentRow;
UINTN CurrentOffset;
UINTN MaxRows;
UINTN HighRow;
UINTN NumBytes;
UINTN NumLines;
UINTN DisplayOffset;
EE_LINE *Line;
CurrentRow = FileBuffer.DisplayPosition.Row;
Line = LineCurrent();
MaxBytes = FileBuffer.MaxVisibleBytes;
HighOffset = FileBuffer.HighVisibleOffset;
MaxRows = TEXT_END_ROW;
HighRow = HighOffset/0x10;
NumBytes = MainEditor.BufferImage->NumBytes;
NumLines = NumBytes / 0x10;
if (Line->Link.Flink == MainEditor.BufferImage->ListHead->Blink) {
return EFI_SUCCESS;
}
CurrentOffset = FileBuffer.Offset + 0x10;
FileBuffer.Offset = CurrentOffset;
if (CurrentRow == (MaxRows - 1)) {
FileBuffer.LowVisibleOffset += 0x10;
FileBuffer.HighVisibleOffset += 0x10;
CurrentRow = MaxRows - 1;
FileBuffer.Refresh();
} else if (CurrentRow == HighRow) {
return EFI_SUCCESS;
} else {
++CurrentRow;
}
Line = LineNext ();
if ((CurrentOffset % 0x10) < Line->Size) {
DisplayOffset = FileBuffer.DisplayPosition.Column;
} else {
CurrentOffset = NumBytes;
DisplayOffset = (Line->Size*3) + HEX_POSITION;
if (Line->Size > 0x07) {
++DisplayOffset;
}
}
FileBuffer.SetPosition(CurrentRow,DisplayOffset);
MainEditor.StatusBar->SetOffset(CurrentOffset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferScrollUp (
VOID
)
{
UINTN CurrentRow;
UINTN MaxRows;
UINTN LowRow;
UINTN MaxBytes;
UINTN LowOffset;
UINTN CurrentOffset;
CurrentOffset = FileBuffer.Offset;
if ( CurrentOffset < 0x10 ) {
return EFI_SUCCESS;
}
MaxBytes = FileBuffer.MaxVisibleBytes;
MaxRows = MaxBytes / 0x10;
LowOffset = FileBuffer.LowVisibleOffset;
LowRow = LowOffset / 0x10;
CurrentRow = FileBuffer.DisplayPosition.Row;
CurrentOffset -= 0x10;
FileBuffer.Offset -= 0x10;
if (CurrentRow == 1) {
FileBuffer.HighVisibleOffset -= 0x10;
FileBuffer.LowVisibleOffset -= 0x10;
CurrentRow = 1;
FileBuffer.Refresh();
} else {
CurrentRow--;
}
LinePrevious ();
FileBuffer.SetPosition(CurrentRow,FileBuffer.DisplayPosition.Column);
MainEditor.StatusBar->SetOffset(CurrentOffset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferPageUp (
VOID
)
{
UINTN MaxBytes;
UINTN LowOffset;
UINTN CurrentOffset;
BOOLEAN Refresh = FALSE;
CurrentOffset = FileBuffer.Offset;
MaxBytes = FileBuffer.MaxVisibleBytes;
LowOffset = FileBuffer.LowVisibleOffset;
if (LowOffset <= MaxBytes) {
FileBuffer.HighVisibleOffset = MaxBytes - 0x10;
FileBuffer.LowVisibleOffset = 0x00;
if (LowOffset > 0x00) {
if (CurrentOffset < MaxBytes) {
FileBuffer.Offset = 0x00;
} else {
FileBuffer.Offset -= (MaxBytes - 0x10);
}
} else {
FileBuffer.Offset = 0x00;
}
Refresh = TRUE;
FileBuffer.DisplayPosition.Row = FileBuffer.Offset/0x10 + TEXT_START_ROW;
} else {
FileBuffer.HighVisibleOffset = LowOffset - 0x10;
FileBuffer.LowVisibleOffset -= (MaxBytes - 0x10);
FileBuffer.Offset -= (MaxBytes - 0x10);
Refresh = TRUE;
}
CurrentOffset -= FileBuffer.Offset;
CurrentOffset /= 0x10;
LineRetreat(CurrentOffset);
if (Refresh) {
FileBufferRefresh();
}
FileBuffer.DisplayPosition.Column = DisplayPosition();
MainEditor.StatusBar->SetOffset(FileBuffer.Offset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferPageDown (
VOID
)
{
UINTN NumBytes;
UINTN MaxBytes;
UINTN HighOffset;
UINTN CurrentOffset;
NumBytes = MainEditor.BufferImage->NumBytes;
MaxBytes = FileBuffer.MaxVisibleBytes;
HighOffset = FileBuffer.HighVisibleOffset;
CurrentOffset = FileBuffer.Offset;
FileBuffer.Offset = min(NumBytes,CurrentOffset+MaxBytes-0x10);
if (HighOffset < NumBytes) {
FileBuffer.LowVisibleOffset = HighOffset-0x10;
FileBuffer.HighVisibleOffset += (MaxBytes - 0x10);
FileBuffer.Refresh();
LineAdvance((FileBuffer.Offset-CurrentOffset)/0x10);
} else if (FileBuffer.Offset >= NumBytes-1) {
FileBuffer.Offset &= 0xfffffff0;
FileBuffer.Offset |= ((NumBytes-1) & 0x00000001f);
FileBuffer.CurrentLine = LineLast()->Link.Blink;
}
FileBuffer.DisplayPosition.Column = DisplayPosition();
FileBuffer.DisplayPosition.Row = (FileBuffer.Offset-FileBuffer.LowVisibleOffset)/0x10 + TEXT_START_ROW;
MainEditor.StatusBar->SetOffset (FileBuffer.Offset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferScrollLeft (
VOID
)
{
UINTN LineOffset;
LineOffset = FileBuffer.Offset % 0x10;
if (FileBuffer.Offset == 0x00) {
return EFI_SUCCESS;
}
if (LineOffset == 0x00) {
FileBufferScrollUp ();
FileBuffer.Offset += 0x10;
LineOffset = 0x0f;
} else {
--LineOffset;
}
FileBuffer.DisplayPosition.Column = HEX_POSITION + (LineOffset*3);
if (LineOffset > 0x07) {
++FileBuffer.DisplayPosition.Column;
}
--FileBuffer.Offset;
MainEditor.StatusBar->SetOffset(FileBuffer.Offset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferScrollRight (
VOID
)
{
UINTN CurrentOffset;
UINTN LineOffset;
EE_LINE *Line;
Line = LineCurrent();
CurrentOffset = FileBuffer.Offset;
LineOffset = CurrentOffset % 0x10;
if (CurrentOffset >= MainEditor.BufferImage->NumBytes){
return EFI_SUCCESS;
}
if (LineOffset > Line->Size) {
return EFI_SUCCESS;
}
if (LineOffset == 0x0f) {
FileBufferScrollDown();
FileBuffer.Offset &= 0xfffffff0;
FileBuffer.DisplayPosition.Column = HEX_POSITION;
RefreshOffset();
} else {
++LineOffset;
FileBuffer.DisplayPosition.Column = HEX_POSITION + (LineOffset*3);
if (LineOffset > 0x07) {
++FileBuffer.DisplayPosition.Column;
}
++FileBuffer.Offset;
}
MainEditor.StatusBar->SetOffset(FileBuffer.Offset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferHome (
VOID
)
{
FileBuffer.DisplayPosition.Column = HEX_POSITION;
FileBuffer.Offset &= 0xfffffff0;
MainEditor.StatusBar->SetOffset(FileBuffer.Offset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferEnd (
VOID
)
{
EE_LINE *Line;
Line = LineCurrent();
FileBuffer.Offset &= 0xfffffff0;
if (Line->Size > 0) {
FileBuffer.Offset |= ((Line->Size-1) & 0x0000000f);
}
FileBuffer.DisplayPosition.Column = DisplayPosition();
MainEditor.StatusBar->SetOffset(FileBuffer.Offset);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferDoHexInput (
IN CHAR16 Char
)
{
EE_LINE *Line;
UINTN LineOffset;
UINTN Pos;
UINTN Num;
if (Char == CHAR_BS) {
FileBufferDoBackspace();
return EFI_SUCCESS;
}
if (Char >= 'A' && Char <= 'F') {
Num = Char - 'A' + 0xa;
} else if (Char >= 'a' && Char <= 'f') {
Num = Char - 'a' + 0xa;
} else if (Char >= '0' && Char <= '9') {
Num = Char - '0';
} else {
return EFI_SUCCESS;
}
LineOffset = FileBuffer.Offset % 0x10;
Pos = FileBuffer.DisplayPosition.Column - HEX_POSITION;
if (LineOffset > 0x07) {
Pos -= (0x07*3)+1;
}
if (FileBuffer.CurrentLine == MainEditor.BufferImage->ListHead->Blink) {
Line = LineCreateNode(MainEditor.BufferImage->ListHead);
FileBuffer.CurrentLine = Line->Link.Blink;
}
Line = LineCurrent();
Line->Buffer[LineOffset] <<= 4;
Line->Buffer[LineOffset] |= Num;
if (FileBuffer.Offset == MainEditor.BufferImage->NumBytes) {
++Line->Size;
++MainEditor.BufferImage->NumBytes;
} else if (FileBuffer.Offset == (MainEditor.BufferImage->NumBytes - 1)) {
if ((Pos%3) != 0 && Line->Size == 0x10) {
Line = LineCreateNode(MainEditor.BufferImage->ListHead);
}
}
FileBufferRefreshCurrentDigit();
if ((Pos % 3) != 0) {
FileBufferScrollRight();
} else {
++FileBuffer.DisplayPosition.Column;
}
FileBufferRestorePosition();
FileModification();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferDoBackspace (
VOID
)
{
UINTN LinePos;
if (FileBuffer.Offset == 0x00) {
return EFI_SUCCESS;
}
FileBufferScrollLeft();
LinePos = FileBuffer.Offset % 0x10;
LineDeleteAt(FileBuffer.CurrentLine,LinePos,1);
FileBufferRefreshDown();
FileModification();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileBufferDoDelete (
VOID
)
{
LIST_ENTRY *Link;
UINTN LinePos;
if (FileBuffer.Offset == MainEditor.BufferImage->NumBytes) {
return EFI_SUCCESS;
}
LinePos = FileBuffer.Offset % 0x10;
Link = FileBuffer.CurrentLine;
LineDeleteAt(Link,LinePos,1);
if (FileBuffer.Offset == MainEditor.BufferImage->NumBytes) {
FileBufferScrollLeft();
}
FileBufferRefreshDown();
FileModification();
return EFI_SUCCESS;
}
STATIC
UINTN
DisplayPosition (
VOID
)
{
EE_LINE *Line;
UINTN Pos = 0;
Line = LineCurrent();
Pos = FileBuffer.Offset & 0x0000000f;
Pos = Pos * 3 + HEX_POSITION;
if (Line->Size > 0x07) {
Pos++;
}
return Pos;
}
#endif /* _LIB_FILE_BUFFER */