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

815 lines
20 KiB
C

/*++
Copyright (c) 1999 Intel Corporation
Module Name:
libMenuBar.c
Abstract:
Definition of the Menu Bar for the text editor
--*/
#ifndef _LIB_MENU_BAR
#define _LIB_MENU_BAR
#include "libMisc.h"
STATIC EFI_STATUS MenuInit (VOID);
STATIC EFI_STATUS MenuCleanup (VOID);
STATIC EFI_STATUS MenuRefresh (VOID);
STATIC EFI_STATUS MenuHandleInput (EFI_INPUT_KEY*);
STATIC EFI_STATUS MenuHide(VOID);
STATIC EFI_STATUS NewFile (VOID);
STATIC EFI_STATUS OpenFile(VOID);
STATIC EFI_STATUS CloseFile(VOID);
STATIC EFI_STATUS SaveFile(VOID);
STATIC EFI_STATUS SaveFileAs(VOID);
STATIC EFI_STATUS ExitEditor(VOID);
STATIC EFI_STATUS CutLine(VOID);
STATIC EFI_STATUS PasteLine(VOID);
STATIC EFI_STATUS SearchFind(VOID);
STATIC EFI_STATUS SearchReplace(VOID);
STATIC EFI_STATUS GotoLine(VOID);
STATIC EFI_STATUS SetupColors(VOID);
STATIC EFI_STATUS SetupScreen(VOID);
STATIC EFI_STATUS FileType(VOID);
EFI_EDITOR_MENU_ITEM MainMenuItems[] = {
{ L"Open File", L"F1", OpenFile },
{ L"Save File", L"F2", SaveFile },
{ L"Exit", L"F3", ExitEditor },
{ L"Cut Line", L"F4", CutLine },
{ L"Paste Line", L"F5", PasteLine },
{ L"Go To Line", L"F6", GotoLine },
{ L"Search", L"F7", SearchFind },
{ L"Search/Replace", L"F8", SearchReplace },
{ L"File Type", L"F9", FileType },
{ L"", L"", NULL }
};
EFI_EDITOR_MENU_BAR MainMenuBar = {
MainMenuItems,
MenuInit,
MenuCleanup,
MenuRefresh,
MenuHide,
MenuHandleInput
};
extern EFI_STATUS FileBufferRefreshDown(VOID);
extern EFI_STATUS FileBufferHome (VOID);
#define FileIsModified() \
MainEditor.FileModified
STATIC BOOLEAN EditorIsExiting;
#define IS_EDITOR_EXITING (EditorIsExiting == TRUE)
STATIC EFI_EDITOR_LINE *MenuCutLine;
STATIC
EFI_STATUS
MenuInit (
VOID
)
{
EditorIsExiting = FALSE;
MenuCutLine = NULL;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
MenuCleanup (
VOID
)
{
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
MenuRefresh (
VOID
)
{
EFI_EDITOR_MENU_ITEM *Item;
UINTN Col = 0;
UINTN Row = MENU_BAR_LOCATION;
UINTN Width;
MenuHide();
for (Item = MainMenuBar.MenuItems;Item->Function;Item++) {
Width = max((StrLen(Item->Name)+6),20);
if (((Col + Width) >= MAX_TEXT_COLUMNS)) {
Row++;
Col = 0;
}
PrintAt(Col,Row,L"%E%s%N %H%s%N ",Item->FunctionKey,Item->Name);
Col += Width;
}
MainEditor.FileBuffer->RestorePosition();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
MenuHandleInput (
EFI_INPUT_KEY *Key
)
{
EFI_EDITOR_MENU_ITEM *Item;
EFI_STATUS Status;
UINTN i = 0;
UINTN NumItems = 0;
NumItems = sizeof(MainMenuItems)/sizeof(EFI_EDITOR_MENU_ITEM) - 1;
Item = MainMenuBar.MenuItems;
i = Key->ScanCode - SCAN_CODE_F1;
if (i > (NumItems - 1)) {
return EFI_SUCCESS;
}
Item = &MainMenuBar.MenuItems[i];
Status = Item->Function();
MenuRefresh();
return (IS_EDITOR_EXITING) ? EFI_LOAD_ERROR : EFI_SUCCESS;
}
STATIC
EFI_STATUS
OpenFile (
VOID
)
{
EFI_STATUS Status = EFI_SUCCESS;
CHAR16 *Filename;
MainEditor.InputBar->SetPrompt(L"File Name to Open: ");
MainEditor.InputBar->SetStringSize (125);
Status = MainEditor.InputBar->Refresh ();
if ( EFI_ERROR(Status) ) {
return EFI_SUCCESS;
}
Filename = MainEditor.InputBar->ReturnString;
if ( Filename == NULL ) {
MainEditor.StatusBar->SetStatusString(L"Filename was NULL");
return EFI_SUCCESS;
}
Status = MainEditor.FileImage->SetFilename (Filename);
if ( EFI_ERROR(Status) ) {
EditorError(Status,L"Could Not Set Filename");
return EFI_NOT_FOUND;
}
Status = MainEditor.FileImage->OpenFile ();
if ( EFI_ERROR(Status) ) {
EditorError(Status,L"Could Not Open File");
return EFI_NOT_FOUND;
}
Status = MainEditor.FileImage->ReadFile ();
if ( EFI_ERROR(Status) ) {
EditorError(Status,L"Could Not Read File");
return EFI_NOT_FOUND;
}
Status = MainEditor.FileBuffer->Refresh();
if ( EFI_ERROR(Status) ) {
EditorError(Status,L"Could Not Refresh");
return EFI_NOT_FOUND;
}
MainEditor.FileBuffer->SetPosition(TEXT_START_ROW,TEXT_START_COLUMN);
MainEditor.TitleBar->SetTitleString(Filename);
MainEditor.Refresh();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
CloseFile (
VOID
)
{
EFI_INPUT_KEY Key;
EFI_STATUS Status;
BOOLEAN Done = FALSE;
if (FileIsModified()) {
MenuHide();
PrintAt(0,MENU_BAR_LOCATION,L"%EY%H Yes%N %EN%N %HNo%N %EQ%N %HCancel%N");
MainEditor.StatusBar->SetStatusString(L"File Modified. Save? ");
while (!Done) {
WaitForSingleEvent(In->WaitForKey,0);
Status = In->ReadKeyStroke(In,&Key);
if ( EFI_ERROR(Status) || Key.ScanCode != 0 ) {
continue;
}
switch (Key.UnicodeChar) {
case 'q':
case 'Q':
Status = EFI_NOT_READY;
Done = TRUE;
break;
case 'n':
case 'N':
Status = EFI_SUCCESS;
Done = TRUE;
break;
case 'y':
case 'Y':
Status = SaveFile();
Done = TRUE;
break;
default:
break;
}
}
MenuRefresh();
}
if (!EFI_ERROR(Status)) {
MainEditor.FileImage->CloseFile();
MainEditor.FileBuffer->Refresh ();
MainEditor.TitleBar->SetTitleString(L"");
} else {
EditorIsExiting = FALSE;
}
MainEditor.StatusBar->Refresh();
MenuRefresh();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
SaveFile (
VOID
)
{
CHAR16 *Output;
EFI_STATUS Status;
if (!MainEditor.FileModified) {
return EFI_SUCCESS;
}
Output = PoolPrint (L"File To Save: [%s]",MainEditor.FileImage->FileName);
MainEditor.InputBar->SetPrompt(Output);
MainEditor.InputBar->SetStringSize(100);
Status = MainEditor.InputBar->Refresh();
FreePool(Output);
if (!EFI_ERROR(Status)) {
if (MainEditor.InputBar->StringSize > 0) {
MainEditor.FileImage->SetFilename(MainEditor.InputBar->ReturnString);
FreePool(MainEditor.InputBar->ReturnString);
}
Status = MainEditor.FileImage->WriteFile();
}
return Status;
}
STATIC
EFI_STATUS
ExitEditor (
VOID
)
{
EditorIsExiting = TRUE;
CloseFile();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
MenuHide (
VOID
)
{
MainEditor.FileBuffer->ClearLine (MENU_BAR_LOCATION);
MainEditor.FileBuffer->ClearLine (MENU_BAR_LOCATION+1);
MainEditor.FileBuffer->ClearLine (MENU_BAR_LOCATION+2);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
CutLine (
VOID
)
{
LIST_ENTRY *Link;
LIST_ENTRY *Next;
LIST_ENTRY *Prev;
EFI_EDITOR_LINE *Line;
Link = MainEditor.FileBuffer->CurrentLine;
if (Link == MainEditor.FileImage->ListHead->Blink) {
return EFI_SUCCESS;
}
if (MenuCutLine) {
FreePool(MenuCutLine);
}
Line = CR(Link,EFI_EDITOR_LINE,Link,EFI_EDITOR_LINE_LIST);
MenuCutLine = LineDup(Line);
Next = Link->Flink;
Prev = Link->Blink;
Prev->Flink = Next;
Next->Blink = Prev;
Link->Flink = Link;
Link->Blink = Link;
MainEditor.FileImage->NumLines--;
MainEditor.FileBuffer->CurrentLine = Next;
FileBufferHome();
FileBufferRefreshDown();
FreePool(Line);
if (!FileIsModified()) {
MainEditor.FileModified = TRUE;
MainEditor.TitleBar->Refresh();
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
PasteLine (
VOID
)
{
LIST_ENTRY *Link;
EFI_EDITOR_LINE *Line;
if (!MenuCutLine) {
return EFI_SUCCESS;
}
Line = LineDup(MenuCutLine);
Link = MainEditor.FileBuffer->CurrentLine;
Line->Link.Blink = Link->Blink;
Line->Link.Flink = Link;
Link->Blink->Flink = &Line->Link;
Link->Blink = &Line->Link;
MainEditor.FileImage->NumLines++;
MainEditor.FileBuffer->CurrentLine = &Line->Link;
FileBufferHome();
FileBufferRefreshDown();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
GotoLine (
VOID
)
{
CHAR16 *Str;
UINTN Row;
UINTN Current;
UINTN RowRange;
BOOLEAN Refresh = FALSE;
MenuHide ();
Str = PoolPrint(L"Go To Line: ");
MainEditor.InputBar->SetPrompt(Str);
FreePool(Str);
MainEditor.InputBar->SetStringSize(5);
MainEditor.InputBar->Refresh();
if (MainEditor.InputBar->StringSize > 0 ) {
Row = Atoi(MainEditor.InputBar->ReturnString);
}
if ( Row > MainEditor.FileImage->NumLines ) {
return EFI_SUCCESS;
}
Current = MainEditor.FileBuffer->FilePosition.Row;
RowRange = MainEditor.FileBuffer->MaxVisibleRows;
if (Row == Current ) {
return EFI_SUCCESS;
}
if (Row < Current) {
LineRetreat(Current-Row);
if ( Row < MainEditor.FileBuffer->LowVisibleRange.Row ) {
MainEditor.FileBuffer->LowVisibleRange.Row = Row-1;
MainEditor.FileBuffer->HighVisibleRange.Row = min(Row+RowRange-1,MainEditor.FileImage->NumLines);
Refresh = TRUE;
}
} else {
LineAdvance(Row - Current);
if ( Row > MainEditor.FileBuffer->HighVisibleRange.Row ) {
MainEditor.FileBuffer->LowVisibleRange.Row = Row - 1;
MainEditor.FileBuffer->HighVisibleRange.Row = min(Row+RowRange-1,MainEditor.FileImage->NumLines);
Refresh = TRUE;
}
}
if (MainEditor.FileBuffer->LowVisibleRange.Column > TEXT_START_COLUMN ) {
MainEditor.FileBuffer->LowVisibleRange.Column = TEXT_START_COLUMN;
MainEditor.FileBuffer->HighVisibleRange.Column = MAX_TEXT_COLUMNS;
Refresh = TRUE;
}
Current = MainEditor.FileBuffer->LowVisibleRange.Row;
MainEditor.FileBuffer->FilePosition.Row = Row;
MainEditor.FileBuffer->SetPosition(Row-Current+TEXT_START_ROW,TEXT_START_COLUMN);
MainEditor.StatusBar->SetPosition(Row,TEXT_START_COLUMN+1);
if ( Refresh = TRUE ) {
MainEditor.FileBuffer->Refresh();
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
SearchFind (
VOID
)
{
CHAR16 *Str;
UINTN Pos;
EFI_EDITOR_LINE *Line;
UINTN LineNumber;
UINTN MaxRows;
UINTN NumLines;
BOOLEAN Refresh = FALSE;
BOOLEAN Found = FALSE;
Str = PoolPrint(L"Enter Search String: ");
MainEditor.InputBar->SetPrompt(Str);
FreePool(Str);
MainEditor.InputBar->SetStringSize(50);
MainEditor.InputBar->Refresh();
if (MainEditor.InputBar->StringSize == 0) {
return EFI_SUCCESS;
}
Str = PoolPrint(L"%s\0",MainEditor.InputBar->ReturnString);
Line = LineCurrent();
MaxRows = MainEditor.FileBuffer->MaxVisibleRows;
NumLines = MainEditor.FileImage->NumLines;
LineNumber = MainEditor.FileBuffer->FilePosition.Row;
while (TRUE) {
Pos = 0;
if (StrLen(Line->Buffer) != 0) {
Pos = StrStr (Line->Buffer,Str);
}
if (Pos == 0) {
if (LineNumber == MainEditor.FileImage->NumLines) {
break;
} else {
LineNumber++;
}
Line = LineNext();
continue;
}
MainEditor.FileBuffer->FilePosition.Row = LineNumber;
MainEditor.FileBuffer->FilePosition.Column = Pos;
MainEditor.StatusBar->SetPosition(LineNumber,Pos);
LineAdvance(LineNumber-MainEditor.FileBuffer->FilePosition.Row);
if (LineNumber > MainEditor.FileBuffer->HighVisibleRange.Row ||
LineNumber < MainEditor.FileBuffer->LowVisibleRange.Row) {
MainEditor.FileBuffer->LowVisibleRange.Row = LineNumber - 1;
MainEditor.FileBuffer->HighVisibleRange.Row = min(LineNumber+MaxRows-2,NumLines);
Refresh = TRUE;
}
if (Pos > MainEditor.FileBuffer->HighVisibleRange.Column ||
Pos < MainEditor.FileBuffer->LowVisibleRange.Column) {
MainEditor.FileBuffer->LowVisibleRange.Column = Pos - 1;
MainEditor.FileBuffer->HighVisibleRange.Column = Pos + MAX_TEXT_COLUMNS - 1;
Refresh = TRUE;
}
Pos = Pos - MainEditor.FileBuffer->LowVisibleRange.Column - 1;
LineNumber = LineNumber - MainEditor.FileBuffer->LowVisibleRange.Row;
MainEditor.FileBuffer->SetPosition(LineNumber+TEXT_START_ROW,Pos+TEXT_START_COLUMN);
if (Refresh) {
MainEditor.FileBuffer->Refresh();
}
Found = TRUE;
break;
}
if (!Found) {
MainEditor.StatusBar->SetStatusString(L"Search String Not Found");
}
FreePool(Str);
return EFI_SUCCESS;
}
STATIC
BOOLEAN
CheckReplace (
VOID
)
{
EFI_INPUT_KEY Key;
EFI_STATUS Status = EFI_SUCCESS;
BOOLEAN Done = FALSE;
MenuHide();
PrintAt(0,MENU_BAR_LOCATION,L"%EY%N%H Yes%N %EN%N %HNo%N %EQ%N %HCancel%N");
MainEditor.StatusBar->SetStatusString(L"Replace? ");
while (!Done) {
WaitForSingleEvent(In->WaitForKey,0);
Status = In->ReadKeyStroke(In,&Key);
if (EFI_ERROR(Status) || Key.ScanCode != 0) {
continue;
}
switch (Key.UnicodeChar) {
case 'y':
case 'Y':
Status = EFI_SUCCESS;
Done = TRUE;
break;
case 'q':
case 'Q':
Status = EFI_NOT_READY;
Done = TRUE;
break;
case 'n':
case 'N':
Status = EFI_NOT_READY;
Done = TRUE;
break;
default:
break;
}
}
MenuRefresh();
MainEditor.StatusBar->SetStatusString(L" ");
return (Status == EFI_SUCCESS);
}
STATIC
BOOLEAN
GetInputStrings (
OUT CHAR16 **Search,
OUT CHAR16 **Replace
)
{
CHAR16 *Str;
Str = PoolPrint(L"Enter Search String: ");
MainEditor.InputBar->SetPrompt(Str);
FreePool(Str);
MainEditor.InputBar->SetStringSize(50);
MainEditor.InputBar->Refresh();
if ( MainEditor.InputBar->StringSize == 0 ) {
return FALSE;
}
*Search = PoolPrint(L"%s",MainEditor.InputBar->ReturnString);
Str = PoolPrint(L"Replace With: ");
MainEditor.InputBar->SetPrompt(Str);
FreePool(Str);
MainEditor.InputBar->SetStringSize(50);
MainEditor.InputBar->Refresh();
*Replace = PoolPrint(L"%s",MainEditor.InputBar->ReturnString);
return TRUE;
}
STATIC
EFI_STATUS
SearchReplace (
VOID
)
{
CHAR16 *Search;
CHAR16 *Replacement;
UINTN SearchLength;
UINTN ReplaceLength;
UINTN LinePos;
UINTN Pos;
EFI_EDITOR_LINE *Line;
UINTN LineNumber;
UINTN MaxRows;
BOOLEAN Refresh = FALSE;
BOOLEAN Found = FALSE;
if (!GetInputStrings(&Search,&Replacement)) {
return EFI_SUCCESS;
}
Line = LineCurrent();
MaxRows = MainEditor.FileBuffer->MaxVisibleRows;
SearchLength = StrLen(Search);
ReplaceLength = StrLen(Replacement);
Pos = MainEditor.FileBuffer->FilePosition.Column - 1;
LineNumber = MainEditor.FileBuffer->FilePosition.Row - 1;
while (TRUE) {
LinePos = StrStr (Line->Buffer+Pos,Search);
if (LinePos == 0) {
if (LineNumber == MainEditor.FileImage->NumLines) {
break;
} else {
LineNumber++;
}
Line = LineNext();
Pos = 0;
continue;
}
Pos += LinePos;
LinePos = Pos + SearchLength - 1;
MainEditor.FileBuffer->FilePosition.Row = LineNumber;
MainEditor.FileBuffer->FilePosition.Column = Pos;
if (LineNumber > MainEditor.FileBuffer->HighVisibleRange.Row ||
LineNumber < MainEditor.FileBuffer->LowVisibleRange.Row) {
MainEditor.FileBuffer->LowVisibleRange.Row = LineNumber - 1;
MainEditor.FileBuffer->HighVisibleRange.Row = min(LineNumber+MaxRows-2,MainEditor.FileImage->NumLines+1);
Refresh = TRUE;
}
if (Pos > MainEditor.FileBuffer->HighVisibleRange.Column ||
Pos < MainEditor.FileBuffer->LowVisibleRange.Column) {
MainEditor.FileBuffer->LowVisibleRange.Column = Pos - 1;
MainEditor.FileBuffer->HighVisibleRange.Column = Pos + MAX_TEXT_COLUMNS - 1;
Refresh = TRUE;
}
Pos = Pos - MainEditor.FileBuffer->LowVisibleRange.Column - 1;
MainEditor.FileBuffer->SetPosition(LineNumber-MainEditor.FileBuffer->LowVisibleRange.Row+TEXT_START_ROW,Pos+TEXT_START_COLUMN);
if (Refresh) {
MainEditor.FileBuffer->Refresh();
}
Found = TRUE;
if (!CheckReplace()) {
break;
}
{
CHAR16 *Tail;
UINTN Size = Line->Size*2;
INTN Diff = ReplaceLength - SearchLength;
if (Diff > 0) {
Line->Buffer = ReallocatePool(Line->Buffer,Size,Size+2*Diff);
}
Tail = PoolPrint(L"%s%s",Replacement,Line->Buffer+LinePos);
Size = LinePos - SearchLength;
StrCpy(Line->Buffer+Size,Tail);
FreePool(Tail);
Line->Size += Diff;
Pos = LinePos + Diff;
}
if (!MainEditor.FileModified) {
MainEditor.FileModified = TRUE;
MainEditor.TitleBar->Refresh();
}
MainEditor.FileBuffer->RefreshCurrentLine();
}
if (!Found) {
MainEditor.StatusBar->SetStatusString(L"Search String Not Found");
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileType (
VOID
)
{
CHAR16 *FT;
CHAR16 *NewType;
CHAR16 *A = L"ASCII";
CHAR16 *U = L"UNICODE";
EFI_INPUT_KEY Key;
EFI_STATUS Status = EFI_SUCCESS;
BOOLEAN Done = FALSE;
BOOLEAN Choice;
Choice = MainEditor.FileImage->FileType;
if (Choice == ASCII_FILE) {
NewType = A;
} else {
NewType = U;
}
FT = PoolPrint(L"File is %s",NewType);
MainEditor.StatusBar->SetStatusString(FT);
FreePool(FT);
MenuHide();
PrintAt(0,MENU_BAR_LOCATION,L"%E U %N%H Set as UNICODE File %N %E A %N %HSet As ASCII File%N %EQ%N %HCancel%N");
while (!Done) {
WaitForSingleEvent(In->WaitForKey,0);
Status = In->ReadKeyStroke(In,&Key);
if (EFI_ERROR(Status) || Key.ScanCode != 0) {
continue;
}
switch (Key.UnicodeChar) {
case 'u':
case 'U':
Choice = UNICODE_FILE;
Done = TRUE;
break;
case 'a':
case 'A':
Choice = ASCII_FILE;
Done = TRUE;
break;
case 'q':
case 'Q':
Done = TRUE;
break;
default:
break;
}
}
MenuRefresh();
if (Choice != MainEditor.FileImage->FileType) {
MainEditor.FileImage->FileType = Choice;
NewType = (Choice == ASCII_FILE) ? A : U;
FT = PoolPrint(L"File Type Changed to %s",NewType);
MainEditor.StatusBar->SetStatusString(FT);
FreePool(FT);
}
return EFI_SUCCESS;
}
#endif /* _LIB_MENU_BAR */