summaryrefslogtreecommitdiff
path: root/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit
diff options
context:
space:
mode:
Diffstat (limited to 'ShellPkg/Library/UefiShellDebug1CommandsLib/Edit')
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c322
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c6718
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h480
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c3980
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h132
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c150
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h74
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni138
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h52
-rw-r--r--ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h192
10 files changed, 6119 insertions, 6119 deletions
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c
index f5edc1bdbb..7a50057d9d 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c
@@ -1,161 +1,161 @@
-/** @file
- Main file for Edit shell Debug1 function.
-
- (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
- Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "UefiShellDebug1CommandsLib.h"
-#include "TextEditor.h"
-
-/**
- Function for 'edit' command.
-
- @param[in] ImageHandle Handle to the Image (NULL if Internal).
- @param[in] SystemTable Pointer to the System Table (NULL if Internal).
-**/
-SHELL_STATUS
-EFIAPI
-ShellCommandRunEdit (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- CHAR16 *Buffer;
- CHAR16 *ProblemParam;
- SHELL_STATUS ShellStatus;
- LIST_ENTRY *Package;
- CONST CHAR16 *Cwd;
- CHAR16 *Nfs;
- CHAR16 *Spot;
- CONST CHAR16 *TempParam;
-
- // SHELL_FILE_HANDLE TempHandle;
-
- Buffer = NULL;
- ShellStatus = SHELL_SUCCESS;
- Nfs = NULL;
-
- //
- // initialize the shell lib (we must be in non-auto-init...)
- //
- Status = ShellInitialize ();
- ASSERT_EFI_ERROR (Status);
-
- Status = CommandInit ();
- ASSERT_EFI_ERROR (Status);
-
- //
- // parse the command line
- //
- Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
- if (EFI_ERROR (Status)) {
- if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"edit", ProblemParam);
- FreePool (ProblemParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- ASSERT (FALSE);
- }
- } else {
- if (ShellCommandLineGetCount (Package) > 2) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"edit");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Cwd = gEfiShellProtocol->GetCurDir (NULL);
- if (Cwd == NULL) {
- Cwd = ShellGetEnvironmentVariable (L"path");
- if (Cwd != NULL) {
- Nfs = StrnCatGrow (&Nfs, NULL, Cwd+3, 0);
- if (Nfs != NULL) {
- Spot = StrStr (Nfs, L";");
- if (Spot != NULL) {
- *Spot = CHAR_NULL;
- }
-
- Spot = StrStr (Nfs, L"\\");
- if (Spot != NULL) {
- Spot[1] = CHAR_NULL;
- }
-
- gEfiShellProtocol->SetCurDir (NULL, Nfs);
- FreePool (Nfs);
- }
- }
- }
-
- Status = MainEditorInit ();
-
- if (EFI_ERROR (Status)) {
- gST->ConOut->ClearScreen (gST->ConOut);
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_INIT_FAILED), gShellDebug1HiiHandle);
- } else {
- MainEditorBackup ();
-
- //
- // if editor launched with file named
- //
- if (ShellCommandLineGetCount (Package) == 2) {
- TempParam = ShellCommandLineGetRawValue (Package, 1);
- ASSERT (TempParam != NULL);
- FileBufferSetFileName (TempParam);
- // if (EFI_ERROR(ShellFileExists(MainEditor.FileBuffer->FileName))) {
- // Status = ShellOpenFileByName(MainEditor.FileBuffer->FileName, &TempHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
- // if (!EFI_ERROR(Status)) {
- // ShellCloseFile(&TempHandle);
- // }
- // }
- }
-
- Status = FileBufferRead (MainEditor.FileBuffer->FileName, FALSE);
- if (!EFI_ERROR (Status)) {
- MainEditorRefresh ();
-
- Status = MainEditorKeyInput ();
- }
-
- if (Status != EFI_OUT_OF_RESOURCES) {
- //
- // back up the status string
- //
- Buffer = CatSPrint (NULL, L"%s", StatusBarGetString ());
- }
-
- MainEditorCleanup ();
-
- //
- // print editor exit code on screen
- //
- if (Status == EFI_SUCCESS) {
- } else if (Status == EFI_OUT_OF_RESOURCES) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"edit");
- } else {
- if (Buffer != NULL) {
- if (StrCmp (Buffer, L"") != 0) {
- //
- // print out the status string
- //
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_BUFFER), gShellDebug1HiiHandle, Buffer);
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
- }
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
- }
- }
-
- if (Status != EFI_OUT_OF_RESOURCES) {
- SHELL_FREE_NON_NULL (Buffer);
- }
- }
- }
-
- ShellCommandLineFreeVarList (Package);
- }
-
- return ShellStatus;
-}
+/** @file
+ Main file for Edit shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "TextEditor.h"
+
+/**
+ Function for 'edit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEdit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *Cwd;
+ CHAR16 *Nfs;
+ CHAR16 *Spot;
+ CONST CHAR16 *TempParam;
+
+ // SHELL_FILE_HANDLE TempHandle;
+
+ Buffer = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Nfs = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize ();
+ ASSERT_EFI_ERROR (Status);
+
+ Status = CommandInit ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"edit", ProblemParam);
+ FreePool (ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT (FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount (Package) > 2) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"edit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Cwd = gEfiShellProtocol->GetCurDir (NULL);
+ if (Cwd == NULL) {
+ Cwd = ShellGetEnvironmentVariable (L"path");
+ if (Cwd != NULL) {
+ Nfs = StrnCatGrow (&Nfs, NULL, Cwd+3, 0);
+ if (Nfs != NULL) {
+ Spot = StrStr (Nfs, L";");
+ if (Spot != NULL) {
+ *Spot = CHAR_NULL;
+ }
+
+ Spot = StrStr (Nfs, L"\\");
+ if (Spot != NULL) {
+ Spot[1] = CHAR_NULL;
+ }
+
+ gEfiShellProtocol->SetCurDir (NULL, Nfs);
+ FreePool (Nfs);
+ }
+ }
+ }
+
+ Status = MainEditorInit ();
+
+ if (EFI_ERROR (Status)) {
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_INIT_FAILED), gShellDebug1HiiHandle);
+ } else {
+ MainEditorBackup ();
+
+ //
+ // if editor launched with file named
+ //
+ if (ShellCommandLineGetCount (Package) == 2) {
+ TempParam = ShellCommandLineGetRawValue (Package, 1);
+ ASSERT (TempParam != NULL);
+ FileBufferSetFileName (TempParam);
+ // if (EFI_ERROR(ShellFileExists(MainEditor.FileBuffer->FileName))) {
+ // Status = ShellOpenFileByName(MainEditor.FileBuffer->FileName, &TempHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+ // if (!EFI_ERROR(Status)) {
+ // ShellCloseFile(&TempHandle);
+ // }
+ // }
+ }
+
+ Status = FileBufferRead (MainEditor.FileBuffer->FileName, FALSE);
+ if (!EFI_ERROR (Status)) {
+ MainEditorRefresh ();
+
+ Status = MainEditorKeyInput ();
+ }
+
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // back up the status string
+ //
+ Buffer = CatSPrint (NULL, L"%s", StatusBarGetString ());
+ }
+
+ MainEditorCleanup ();
+
+ //
+ // print editor exit code on screen
+ //
+ if (Status == EFI_SUCCESS) {
+ } else if (Status == EFI_OUT_OF_RESOURCES) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"edit");
+ } else {
+ if (Buffer != NULL) {
+ if (StrCmp (Buffer, L"") != 0) {
+ //
+ // print out the status string
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_BUFFER), gShellDebug1HiiHandle, Buffer);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
+ }
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
+ }
+ }
+
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ SHELL_FREE_NON_NULL (Buffer);
+ }
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return ShellStatus;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
index 088030d29f..1fb33dbb79 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
@@ -1,3359 +1,3359 @@
-/** @file
- Implements filebuffer interface functions.
-
- Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "TextEditor.h"
-#include <Guid/FileSystemInfo.h>
-#include <Library/FileHandleLib.h>
-
-EFI_EDITOR_FILE_BUFFER FileBuffer;
-EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
-
-//
-// for basic initialization of FileBuffer
-//
-EFI_EDITOR_FILE_BUFFER FileBufferConst = {
- NULL,
- FileTypeUnicode,
- NULL,
- NULL,
- 0,
- {
- 0,
- 0
- },
- {
- 0,
- 0
- },
- {
- 0,
- 0
- },
- {
- 0,
- 0
- },
- FALSE,
- TRUE,
- FALSE,
- NULL
-};
-
-//
-// the whole edit area needs to be refreshed
-//
-BOOLEAN FileBufferNeedRefresh;
-
-//
-// only the current line in edit area needs to be refresh
-//
-BOOLEAN FileBufferOnlyLineNeedRefresh;
-
-BOOLEAN FileBufferMouseNeedRefresh;
-
-extern BOOLEAN EditorMouseAction;
-
-/**
- Initialization function for FileBuffer.
-
- @param EFI_SUCCESS The initialization was successful.
- @param EFI_LOAD_ERROR A default name could not be created.
- @param EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferInit (
- VOID
- )
-{
- //
- // basically initialize the FileBuffer
- //
- CopyMem (&FileBuffer, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
- CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
-
- //
- // set default FileName
- //
- FileBuffer.FileName = EditGetDefaultFileName (L"txt");
- if (FileBuffer.FileName == NULL) {
- return EFI_LOAD_ERROR;
- }
-
- FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
- if (FileBuffer.ListHead == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- InitializeListHead (FileBuffer.ListHead);
-
- FileBuffer.DisplayPosition.Row = 2;
- FileBuffer.DisplayPosition.Column = 1;
- FileBuffer.LowVisibleRange.Row = 2;
- FileBuffer.LowVisibleRange.Column = 1;
-
- FileBufferNeedRefresh = FALSE;
- FileBufferMouseNeedRefresh = FALSE;
- FileBufferOnlyLineNeedRefresh = FALSE;
-
- return EFI_SUCCESS;
-}
-
-/**
- Backup function for FileBuffer. Only backup the following items:
- Mouse/Cursor position
- File Name, Type, ReadOnly, Modified
- Insert Mode
-
- This is for making the file buffer refresh as few as possible.
-
- @retval EFI_SUCCESS The backup operation was successful.
-**/
-EFI_STATUS
-FileBufferBackup (
- VOID
- )
-{
- FileBufferBackupVar.MousePosition = FileBuffer.MousePosition;
-
- SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
- FileBufferBackupVar.FileName = NULL;
- FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0);
-
- FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert;
- FileBufferBackupVar.FileType = FileBuffer.FileType;
-
- FileBufferBackupVar.FilePosition = FileBuffer.FilePosition;
- FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange;
-
- FileBufferBackupVar.FileModified = FileBuffer.FileModified;
- FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly;
-
- return EFI_SUCCESS;
-}
-
-/**
- Advance to the next Count lines
-
- @param[in] Count The line number to advance by.
- @param[in] CurrentLine The pointer to the current line structure.
- @param[in] LineList The pointer to the linked list of lines.
-
- @retval NULL There was an error.
- @return The line structure after the advance.
-**/
-EFI_EDITOR_LINE *
-InternalEditorMiscLineAdvance (
- IN CONST UINTN Count,
- IN CONST EFI_EDITOR_LINE *CurrentLine,
- IN CONST LIST_ENTRY *LineList
- )
-
-{
- UINTN Index;
- CONST EFI_EDITOR_LINE *Line;
-
- if ((CurrentLine == NULL) || (LineList == NULL)) {
- return NULL;
- }
-
- for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
- //
- // if already last line
- //
- if (Line->Link.ForwardLink == LineList) {
- return NULL;
- }
-
- Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- }
-
- return ((EFI_EDITOR_LINE *)Line);
-}
-
-/**
- Retreat to the previous Count lines.
-
- @param[in] Count The line number to retreat by.
- @param[in] CurrentLine The pointer to the current line structure.
- @param[in] LineList The pointer to the linked list of lines.
-
- @retval NULL There was an error.
- @return The line structure after the retreat.
-**/
-EFI_EDITOR_LINE *
-InternalEditorMiscLineRetreat (
- IN CONST UINTN Count,
- IN CONST EFI_EDITOR_LINE *CurrentLine,
- IN CONST LIST_ENTRY *LineList
- )
-
-{
- UINTN Index;
- CONST EFI_EDITOR_LINE *Line;
-
- if ((CurrentLine == NULL) || (LineList == NULL)) {
- return NULL;
- }
-
- for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
- //
- // already the first line
- //
- if (Line->Link.BackLink == LineList) {
- return NULL;
- }
-
- Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- }
-
- return ((EFI_EDITOR_LINE *)Line);
-}
-
-/**
- Advance/Retreat lines
-
- @param[in] Count line number to advance/retreat
- >0 : advance
- <0 : retreat
-
- @retval NULL An error occurred.
- @return The line after advance/retreat.
-**/
-EFI_EDITOR_LINE *
-MoveLine (
- IN CONST INTN Count
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN AbsCount;
-
- //
- // if < 0, then retreat
- // if > 0, the advance
- //
- if (Count <= 0) {
- AbsCount = (UINTN)ABS (Count);
- Line = InternalEditorMiscLineRetreat (AbsCount, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
- } else {
- Line = InternalEditorMiscLineAdvance ((UINTN)Count, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
- }
-
- return Line;
-}
-
-/**
- Function to update the 'screen' to display the mouse position.
-
- @retval EFI_SUCCESS The backup operation was successful.
-**/
-EFI_STATUS
-FileBufferRestoreMousePosition (
- VOID
- )
-{
- EFI_EDITOR_COLOR_UNION Orig;
- EFI_EDITOR_COLOR_UNION New;
- UINTN FRow;
- UINTN FColumn;
- BOOLEAN HasCharacter;
- EFI_EDITOR_LINE *CurrentLine;
- EFI_EDITOR_LINE *Line;
- CHAR16 Value;
-
- //
- // variable initialization
- //
- Line = NULL;
-
- if (MainEditor.MouseSupported) {
- if (FileBufferMouseNeedRefresh) {
- FileBufferMouseNeedRefresh = FALSE;
-
- //
- // if mouse position not moved and only mouse action
- // so do not need to refresh mouse position
- //
- if ( ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row) &&
- (FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column))
- && EditorMouseAction)
- {
- return EFI_SUCCESS;
- }
-
- //
- // backup the old screen attributes
- //
- Orig = MainEditor.ColorAttributes;
- New.Data = 0;
- New.Colors.Foreground = Orig.Colors.Background & 0xF;
- New.Colors.Background = Orig.Colors.Foreground & 0x7;
-
- //
- // clear the old mouse position
- //
- FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2;
-
- FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1;
-
- HasCharacter = TRUE;
- if (FRow > FileBuffer.NumLines) {
- HasCharacter = FALSE;
- } else {
- CurrentLine = FileBuffer.CurrentLine;
- Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
-
- if ((Line == NULL) || (FColumn > Line->Size)) {
- HasCharacter = FALSE;
- }
-
- FileBuffer.CurrentLine = CurrentLine;
- }
-
- ShellPrintEx (
- (INT32)FileBufferBackupVar.MousePosition.Column - 1,
- (INT32)FileBufferBackupVar.MousePosition.Row - 1,
- L" "
- );
-
- if (HasCharacter) {
- Value = (Line->Buffer[FColumn - 1]);
- ShellPrintEx (
- (INT32)FileBufferBackupVar.MousePosition.Column - 1,
- (INT32)FileBufferBackupVar.MousePosition.Row - 1,
- L"%c",
- Value
- );
- }
-
- //
- // set the new mouse position
- //
- gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
-
- //
- // clear the old mouse position
- //
- FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2;
- FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1;
-
- HasCharacter = TRUE;
- if (FRow > FileBuffer.NumLines) {
- HasCharacter = FALSE;
- } else {
- CurrentLine = FileBuffer.CurrentLine;
- Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
-
- if ((Line == NULL) || (FColumn > Line->Size)) {
- HasCharacter = FALSE;
- }
-
- FileBuffer.CurrentLine = CurrentLine;
- }
-
- ShellPrintEx (
- (INT32)FileBuffer.MousePosition.Column - 1,
- (INT32)FileBuffer.MousePosition.Row - 1,
- L" "
- );
-
- if (HasCharacter) {
- Value = Line->Buffer[FColumn - 1];
- ShellPrintEx (
- (INT32)FileBuffer.MousePosition.Column - 1,
- (INT32)FileBuffer.MousePosition.Row - 1,
- L"%c",
- Value
- );
- }
-
- //
- // end of HasCharacter
- //
- gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
- }
-
- //
- // end of MouseNeedRefresh
- //
- }
-
- //
- // end of MouseSupported
- //
- return EFI_SUCCESS;
-}
-
-/**
- Free all the lines in FileBuffer
- Fields affected:
- Lines
- CurrentLine
- NumLines
- ListHead
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferFreeLines (
- VOID
- )
-{
- LIST_ENTRY *Link;
- EFI_EDITOR_LINE *Line;
-
- //
- // free all the lines
- //
- if (FileBuffer.Lines != NULL) {
- Line = FileBuffer.Lines;
- Link = &(Line->Link);
- do {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- Link = Link->ForwardLink;
-
- //
- // free line's buffer and line itself
- //
- LineFree (Line);
- } while (Link != FileBuffer.ListHead);
- }
-
- //
- // clean the line list related structure
- //
- FileBuffer.Lines = NULL;
- FileBuffer.CurrentLine = NULL;
- FileBuffer.NumLines = 0;
-
- FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead;
- FileBuffer.ListHead->BackLink = FileBuffer.ListHead;
-
- return EFI_SUCCESS;
-}
-
-/**
- Cleanup function for FileBuffer.
-
- @retval EFI_SUCCESS The cleanup was successful.
-**/
-EFI_STATUS
-FileBufferCleanup (
- VOID
- )
-{
- EFI_STATUS Status;
-
- SHELL_FREE_NON_NULL (FileBuffer.FileName);
-
- //
- // free all the lines
- //
- Status = FileBufferFreeLines ();
-
- SHELL_FREE_NON_NULL (FileBuffer.ListHead);
- FileBuffer.ListHead = NULL;
-
- SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
- return Status;
-}
-
-/**
- Print a line specified by Line on a row specified by Row of the screen.
-
- @param[in] Line The line to print.
- @param[in] Row The row on the screen to print onto (begin from 1).
-
- @retval EFI_SUCCESS The printing was successful.
-**/
-EFI_STATUS
-FileBufferPrintLine (
- IN CONST EFI_EDITOR_LINE *Line,
- IN CONST UINTN Row
- )
-{
- CHAR16 *Buffer;
- UINTN Limit;
- CHAR16 *PrintLine;
- CHAR16 *PrintLine2;
- UINTN BufLen;
-
- //
- // print start from correct character
- //
- Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1;
-
- Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1;
- if (Limit > Line->Size) {
- Limit = 0;
- }
-
- BufLen = (MainEditor.ScreenSize.Column + 1) * sizeof (CHAR16);
- PrintLine = AllocatePool (BufLen);
- if (PrintLine != NULL) {
- StrnCpyS (PrintLine, BufLen/sizeof (CHAR16), Buffer, MIN (Limit, MainEditor.ScreenSize.Column));
- for (Limit = StrLen (PrintLine); Limit < MainEditor.ScreenSize.Column; Limit++) {
- PrintLine[Limit] = L' ';
- }
-
- PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL;
-
- PrintLine2 = AllocatePool (BufLen * 2);
- if (PrintLine2 != NULL) {
- ShellCopySearchAndReplace (PrintLine, PrintLine2, BufLen * 2, L"%", L"^%", FALSE, FALSE);
-
- ShellPrintEx (
- 0,
- (INT32)Row - 1,
- L"%s",
- PrintLine2
- );
- FreePool (PrintLine2);
- }
-
- FreePool (PrintLine);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Set the cursor position according to FileBuffer.DisplayPosition.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferRestorePosition (
- VOID
- )
-{
- //
- // set cursor position
- //
- return (gST->ConOut->SetCursorPosition (
- gST->ConOut,
- FileBuffer.DisplayPosition.Column - 1,
- FileBuffer.DisplayPosition.Row - 1
- ));
-}
-
-/**
- Refresh the screen with whats in the buffer.
-
- @retval EFI_SUCCESS The refresh was successful.
- @retval EFI_LOAD_ERROR There was an error finding what to write.
-**/
-EFI_STATUS
-FileBufferRefresh (
- VOID
- )
-{
- LIST_ENTRY *Link;
- EFI_EDITOR_LINE *Line;
- UINTN Row;
-
- //
- // if it's the first time after editor launch, so should refresh
- //
- if (!EditorFirst) {
- //
- // no definite required refresh
- // and file position displayed on screen has not been changed
- //
- if (!FileBufferNeedRefresh &&
- !FileBufferOnlyLineNeedRefresh &&
- (FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row) &&
- (FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column)
- )
- {
- FileBufferRestoreMousePosition ();
- FileBufferRestorePosition ();
-
- return EFI_SUCCESS;
- }
- }
-
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);
-
- //
- // only need to refresh current line
- //
- if (FileBufferOnlyLineNeedRefresh &&
- (FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row) &&
- (FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column)
- )
- {
- EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
- FileBufferPrintLine (
- FileBuffer.CurrentLine,
- FileBuffer.DisplayPosition.Row
- );
- } else {
- //
- // the whole edit area need refresh
- //
-
- //
- // no line
- //
- if (FileBuffer.Lines == NULL) {
- FileBufferRestoreMousePosition ();
- FileBufferRestorePosition ();
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-
- return EFI_SUCCESS;
- }
-
- //
- // get the first line that will be displayed
- //
- Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row);
- if (Line == NULL) {
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-
- return EFI_LOAD_ERROR;
- }
-
- Link = &(Line->Link);
- Row = 2;
- do {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- //
- // print line at row
- //
- FileBufferPrintLine (Line, Row);
-
- Link = Link->ForwardLink;
- Row++;
- } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 1));
-
- //
- // while not file end and not screen full
- //
- while (Row <= (MainEditor.ScreenSize.Row - 1)) {
- EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
- Row++;
- }
- }
-
- FileBufferRestoreMousePosition ();
- FileBufferRestorePosition ();
-
- FileBufferNeedRefresh = FALSE;
- FileBufferOnlyLineNeedRefresh = FALSE;
-
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- return EFI_SUCCESS;
-}
-
-/**
- Create a new line and append it to the line list.
- Fields affected:
- NumLines
- Lines
-
- @retval NULL The create line failed.
- @return The line created.
-**/
-EFI_EDITOR_LINE *
-FileBufferCreateLine (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
-
- //
- // allocate a line structure
- //
- Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
- if (Line == NULL) {
- return NULL;
- }
-
- //
- // initialize the structure
- //
- Line->Signature = LINE_LIST_SIGNATURE;
- Line->Size = 0;
- Line->TotalSize = 0;
- Line->Type = NewLineTypeDefault;
-
- //
- // initial buffer of the line is "\0"
- //
- ASSERT (CHAR_NULL == CHAR_NULL);
- Line->Buffer = CatSPrint (NULL, L"\0");
- if (Line->Buffer == NULL) {
- return NULL;
- }
-
- FileBuffer.NumLines++;
-
- //
- // insert the line into line list
- //
- InsertTailList (FileBuffer.ListHead, &Line->Link);
-
- if (FileBuffer.Lines == NULL) {
- FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- }
-
- return Line;
-}
-
-/**
- Set FileName field in FileBuffer.
-
- @param Str The file name to set.
-
- @retval EFI_SUCCESS The filename was successfully set.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_INVALID_PARAMETER Str is not a valid filename.
-**/
-EFI_STATUS
-FileBufferSetFileName (
- IN CONST CHAR16 *Str
- )
-{
- //
- // Verify the parameters
- //
- if (!IsValidFileName (Str)) {
- return (EFI_INVALID_PARAMETER);
- }
-
- //
- // free the old file name
- //
- SHELL_FREE_NON_NULL (FileBuffer.FileName);
-
- //
- // Allocate and set the new name
- //
- FileBuffer.FileName = CatSPrint (NULL, L"%s", Str);
- if (FileBuffer.FileName == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Free the existing file lines and reset the modified flag.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferFree (
- VOID
- )
-{
- //
- // free all the lines
- //
- FileBufferFreeLines ();
- FileBuffer.FileModified = FALSE;
-
- return EFI_SUCCESS;
-}
-
-/**
- Read a file from disk into the FileBuffer.
-
- @param[in] FileName The filename to read.
- @param[in] Recover TRUE if is for recover mode, no information printouts.
-
- @retval EFI_SUCCESS The load was successful.
- @retval EFI_LOAD_ERROR The load failed.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_INVALID_PARAMETER FileName is a directory.
-**/
-EFI_STATUS
-FileBufferRead (
- IN CONST CHAR16 *FileName,
- IN CONST BOOLEAN Recover
- )
-{
- EFI_EDITOR_LINE *Line;
- EE_NEWLINE_TYPE Type;
- UINTN LoopVar1;
- UINTN LoopVar2;
- UINTN LineSize;
- VOID *Buffer;
- CHAR16 *UnicodeBuffer;
- UINT8 *AsciiBuffer;
- UINTN FileSize;
- SHELL_FILE_HANDLE FileHandle;
- BOOLEAN CreateFile;
- EFI_STATUS Status;
- UINTN LineSizeBackup;
- EFI_FILE_INFO *Info;
-
- Line = NULL;
- LoopVar1 = 0;
- FileSize = 0;
- UnicodeBuffer = NULL;
- Type = NewLineTypeDefault;
- FileHandle = NULL;
- CreateFile = FALSE;
-
- //
- // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
- // you should set status string via StatusBarSetStatusString(L"blah")
- // since this function maybe called before the editorhandleinput loop
- // so any error will cause editor return
- // so if you want to print the error status
- // you should set the status string
- //
-
- //
- // try to open the file
- //
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
-
- if (!EFI_ERROR (Status)) {
- CreateFile = FALSE;
- if (FileHandle == NULL) {
- StatusBarSetStatusString (L"Disk Error");
- return EFI_LOAD_ERROR;
- }
-
- Info = ShellGetFileInfo (FileHandle);
-
- if (Info->Attribute & EFI_FILE_DIRECTORY) {
- StatusBarSetStatusString (L"Directory Can Not Be Edited");
- FreePool (Info);
- return EFI_INVALID_PARAMETER;
- }
-
- if (Info->Attribute & EFI_FILE_READ_ONLY) {
- FileBuffer.ReadOnly = TRUE;
- } else {
- FileBuffer.ReadOnly = FALSE;
- }
-
- //
- // get file size
- //
- FileSize = (UINTN)Info->FileSize;
-
- FreePool (Info);
- } else if (Status == EFI_NOT_FOUND) {
- //
- // file not exists. add create and try again
- //
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
- if (EFI_ERROR (Status)) {
- if ((Status == EFI_WRITE_PROTECTED) ||
- (Status == EFI_ACCESS_DENIED) ||
- (Status == EFI_NO_MEDIA) ||
- (Status == EFI_MEDIA_CHANGED)
- )
- {
- StatusBarSetStatusString (L"Access Denied");
- } else if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_VOLUME_CORRUPTED) || (Status == EFI_VOLUME_FULL)) {
- StatusBarSetStatusString (L"Disk Error");
- } else {
- StatusBarSetStatusString (L"Invalid File Name or Current-working-directory");
- }
-
- return Status;
- } else {
- //
- // it worked. now delete it and move on with the name (now validated)
- //
- Status = ShellDeleteFile (&FileHandle);
- if (Status == EFI_WARN_DELETE_FAILURE) {
- Status = EFI_ACCESS_DENIED;
- }
-
- FileHandle = NULL;
- if (EFI_ERROR (Status)) {
- StatusBarSetStatusString (L"Access Denied");
- return Status;
- }
- }
-
- //
- // file doesn't exist, so set CreateFile to TRUE
- //
- CreateFile = TRUE;
- FileBuffer.ReadOnly = FALSE;
-
- //
- // all the check ends
- // so now begin to set file name, free lines
- //
- if (StrCmp (FileName, FileBuffer.FileName) != 0) {
- FileBufferSetFileName (FileName);
- }
-
- //
- // free the old lines
- //
- FileBufferFree ();
- }
-
- //
- // the file exists
- //
- if (!CreateFile) {
- //
- // allocate buffer to read file
- //
- Buffer = AllocateZeroPool (FileSize);
- if (Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // read file into Buffer
- //
- Status = ShellReadFile (FileHandle, &FileSize, Buffer);
- ShellCloseFile (&FileHandle);
- FileHandle = NULL;
- if (EFI_ERROR (Status)) {
- StatusBarSetStatusString (L"Read File Failed");
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_LOAD_ERROR;
- }
-
- //
- // nothing in this file
- //
- if (FileSize == 0) {
- SHELL_FREE_NON_NULL (Buffer);
- //
- // since has no head, so only can be an ASCII file
- //
- FileBuffer.FileType = FileTypeAscii;
-
- goto Done;
- }
-
- AsciiBuffer = Buffer;
-
- if (FileSize < 2) {
- //
- // size < Unicode file header, so only can be ASCII file
- //
- FileBuffer.FileType = FileTypeAscii;
- } else {
- //
- // Unicode file
- //
- if (*(UINT16 *)Buffer == EFI_UNICODE_BYTE_ORDER_MARK) {
- //
- // Unicode file's size should be even
- //
- if ((FileSize % 2) != 0) {
- StatusBarSetStatusString (L"File Format Wrong");
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_LOAD_ERROR;
- }
-
- FileSize /= 2;
-
- FileBuffer.FileType = FileTypeUnicode;
- UnicodeBuffer = Buffer;
-
- //
- // pass this 0xff and 0xfe
- //
- UnicodeBuffer++;
- FileSize--;
- } else {
- FileBuffer.FileType = FileTypeAscii;
- }
-
- //
- // end of AsciiBuffer ==
- //
- }
-
- //
- // end of FileSize < 2
- // all the check ends
- // so now begin to set file name, free lines
- //
- if (StrCmp (FileName, FileBuffer.FileName) != 0) {
- FileBufferSetFileName (FileName);
- }
-
- //
- // free the old lines
- //
- FileBufferFree ();
-
- //
- // parse file content line by line
- //
- for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) {
- Type = NewLineTypeUnknown;
-
- for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) {
- if (FileBuffer.FileType == FileTypeAscii) {
- if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeCarriageReturn;
-
- //
- // has LF following
- //
- if (LineSize < FileSize - 1) {
- if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) {
- Type = NewLineTypeCarriageReturnLineFeed;
- }
- }
-
- break;
- } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) {
- Type = NewLineTypeLineFeed;
-
- //
- // has CR following
- //
- if (LineSize < FileSize - 1) {
- if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeLineFeedCarriageReturn;
- }
- }
-
- break;
- }
- } else {
- if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeCarriageReturn;
-
- //
- // has LF following
- //
- if (LineSize < FileSize - 1) {
- if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) {
- Type = NewLineTypeCarriageReturnLineFeed;
- }
- }
-
- break;
- } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) {
- Type = NewLineTypeLineFeed;
-
- //
- // has CR following
- //
- if (LineSize < FileSize - 1) {
- if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeLineFeedCarriageReturn;
- }
- }
-
- break;
- }
- }
-
- //
- // endif == ASCII
- //
- }
-
- //
- // end of for LineSize
- //
- // if the type is wrong, then exit
- //
- if (Type == NewLineTypeUnknown) {
- //
- // Now if Type is NewLineTypeUnknown, it should be file end
- //
- Type = NewLineTypeDefault;
- }
-
- LineSizeBackup = LineSize;
-
- //
- // create a new line
- //
- Line = FileBufferCreateLine ();
- if (Line == NULL) {
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // calculate file length
- //
- LineSize -= LoopVar1;
-
- //
- // Unicode and one CHAR_NULL
- //
- SHELL_FREE_NON_NULL (Line->Buffer);
- Line->Buffer = AllocateZeroPool (LineSize * 2 + 2);
-
- if (Line->Buffer == NULL) {
- RemoveEntryList (&Line->Link);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // copy this line to Line->Buffer
- //
- for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) {
- if (FileBuffer.FileType == FileTypeAscii) {
- Line->Buffer[LoopVar2] = (CHAR16)AsciiBuffer[LoopVar1];
- } else {
- Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1];
- }
-
- LoopVar1++;
- }
-
- //
- // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
- //
- Line->Buffer[LineSize] = 0;
-
- Line->Size = LineSize;
- Line->TotalSize = LineSize;
- Line->Type = Type;
-
- if ((Type == NewLineTypeCarriageReturnLineFeed) || (Type == NewLineTypeLineFeedCarriageReturn)) {
- LoopVar1++;
- }
-
- //
- // last character is a return, SO create a new line
- //
- if ((((Type == NewLineTypeCarriageReturnLineFeed) || (Type == NewLineTypeLineFeedCarriageReturn)) && (LineSizeBackup == FileSize - 2)) ||
- (((Type == NewLineTypeLineFeed) || (Type == NewLineTypeCarriageReturn)) && (LineSizeBackup == FileSize - 1))
- )
- {
- Line = FileBufferCreateLine ();
- if (Line == NULL) {
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_OUT_OF_RESOURCES;
- }
- }
-
- //
- // end of if
- //
- }
-
- //
- // end of LoopVar1
- //
- SHELL_FREE_NON_NULL (Buffer);
- }
-
- //
- // end of if CreateFile
- //
-Done:
-
- FileBuffer.DisplayPosition.Row = 2;
- FileBuffer.DisplayPosition.Column = 1;
- FileBuffer.LowVisibleRange.Row = 1;
- FileBuffer.LowVisibleRange.Column = 1;
- FileBuffer.FilePosition.Row = 1;
- FileBuffer.FilePosition.Column = 1;
- FileBuffer.MousePosition.Row = 2;
- FileBuffer.MousePosition.Column = 1;
-
- if (!Recover) {
- UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines);
- if (UnicodeBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- StatusBarSetStatusString (UnicodeBuffer);
- FreePool (UnicodeBuffer);
- }
-
- /*
- //
- // check whether we have fs?: in filename
- //
- LoopVar1 = 0;
- FSMappingPtr = NULL;
- while (FileName[LoopVar1] != 0) {
- if (FileName[LoopVar1] == L':') {
- FSMappingPtr = &FileName[LoopVar1];
- break;
- }
-
- LoopVar1++;
- }
-
- if (FSMappingPtr == NULL) {
- CurDir = ShellGetCurrentDir (NULL);
- } else {
- LoopVar1 = 0;
- LoopVar2 = 0;
- while (FileName[LoopVar1] != 0) {
- if (FileName[LoopVar1] == L':') {
- break;
- }
-
- FSMapping[LoopVar2++] = FileName[LoopVar1];
-
- LoopVar1++;
- }
-
- FSMapping[LoopVar2] = 0;
- CurDir = ShellGetCurrentDir (FSMapping);
- }
-
- if (CurDir != NULL) {
- for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
-
- CurDir[LoopVar1] = 0;
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
- FreePool (CurDir);
- } else {
- return EFI_LOAD_ERROR;
- }
-
- Status = LibDevicePathToInterface (
- &gEfiSimpleFileSystemProtocolGuid,
- DevicePath,
- (VOID **) &Vol
- );
- if (EFI_ERROR (Status)) {
- return EFI_LOAD_ERROR;
- }
-
- Status = Vol->OpenVolume (Vol, &RootFs);
- if (EFI_ERROR (Status)) {
- return EFI_LOAD_ERROR;
- }
- //
- // Get volume information of file system
- //
- Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
- VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
- Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
- if (EFI_ERROR (Status)) {
- RootFs->Close (RootFs);
- return EFI_LOAD_ERROR;
- }
-
- if (VolumeInfo->ReadOnly) {
- StatusBarSetStatusString (L"WARNING: Volume Read Only");
- }
-
- FreePool (VolumeInfo);
- RootFs->Close (RootFs);
- }
- //
- */
- //
- // has line
- //
- if (FileBuffer.Lines != 0) {
- FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- } else {
- //
- // create a dummy line
- //
- Line = FileBufferCreateLine ();
- if (Line == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- FileBuffer.CurrentLine = Line;
- }
-
- FileBuffer.FileModified = FALSE;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- FileBufferMouseNeedRefresh = TRUE;
-
- return EFI_SUCCESS;
-}
-
-/**
- According to FileBuffer.NewLineType & FileBuffer.FileType,
- get the return buffer and size.
-
- @param[in] Type The type of line.
- @param[out] Buffer The buffer to fill.
- @param[out] Size The amount of the buffer used on return.
-**/
-VOID
-GetNewLine (
- IN CONST EE_NEWLINE_TYPE Type,
- OUT CHAR8 *Buffer,
- OUT UINT8 *Size
- )
-{
- UINT8 NewLineSize;
-
- //
- // give new line buffer,
- // and will judge unicode or ascii
- //
- NewLineSize = 0;
-
- //
- // not legal new line type
- //
- if ((Type != NewLineTypeLineFeed) && (Type != NewLineTypeCarriageReturn) && (Type != NewLineTypeCarriageReturnLineFeed) && (Type != NewLineTypeLineFeedCarriageReturn)) {
- *Size = 0;
- return;
- }
-
- //
- // use_cr: give 0x0d
- //
- if (Type == NewLineTypeCarriageReturn) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0d;
- Buffer[1] = 0;
- NewLineSize = 2;
- } else {
- Buffer[0] = 0x0d;
- NewLineSize = 1;
- }
-
- *Size = NewLineSize;
- return;
- }
-
- //
- // use_lf: give 0x0a
- //
- if (Type == NewLineTypeLineFeed) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0a;
- Buffer[1] = 0;
- NewLineSize = 2;
- } else {
- Buffer[0] = 0x0a;
- NewLineSize = 1;
- }
-
- *Size = NewLineSize;
- return;
- }
-
- //
- // use_crlf: give 0x0d 0x0a
- //
- if (Type == NewLineTypeCarriageReturnLineFeed) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0d;
- Buffer[1] = 0;
- Buffer[2] = 0x0a;
- Buffer[3] = 0;
-
- NewLineSize = 4;
- } else {
- Buffer[0] = 0x0d;
- Buffer[1] = 0x0a;
- NewLineSize = 2;
- }
-
- *Size = NewLineSize;
- return;
- }
-
- //
- // use_lfcr: give 0x0a 0x0d
- //
- if (Type == NewLineTypeLineFeedCarriageReturn) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0a;
- Buffer[1] = 0;
- Buffer[2] = 0x0d;
- Buffer[3] = 0;
-
- NewLineSize = 4;
- } else {
- Buffer[0] = 0x0a;
- Buffer[1] = 0x0d;
- NewLineSize = 2;
- }
-
- *Size = NewLineSize;
- return;
- }
-}
-
-/**
- Change a Unicode string to an ASCII string.
-
- @param[in] UStr The Unicode string.
- @param[in] Length The maximum size of AStr.
- @param[out] AStr ASCII string to pass out.
-
- @return The actuall length.
-**/
-UINTN
-UnicodeToAscii (
- IN CONST CHAR16 *UStr,
- IN CONST UINTN Length,
- OUT CHAR8 *AStr
- )
-{
- UINTN Index;
-
- //
- // just buffer copy, not character copy
- //
- for (Index = 0; Index < Length; Index++) {
- *AStr++ = (CHAR8)*UStr++;
- }
-
- return Index;
-}
-
-/**
- Save lines in FileBuffer to disk
-
- @param[in] FileName The file name for writing.
-
- @retval EFI_SUCCESS Data was written.
- @retval EFI_LOAD_ERROR
- @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
-**/
-EFI_STATUS
-FileBufferSave (
- IN CONST CHAR16 *FileName
- )
-{
- SHELL_FILE_HANDLE FileHandle;
- LIST_ENTRY *Link;
- EFI_EDITOR_LINE *Line;
- CHAR16 *Str;
-
- EFI_STATUS Status;
- UINTN Length;
- UINTN NumLines;
- CHAR8 NewLineBuffer[4];
- UINT8 NewLineSize;
-
- EFI_FILE_INFO *Info;
-
- UINT64 Attribute;
-
- EE_NEWLINE_TYPE Type;
-
- UINTN TotalSize;
- //
- // 2M
- //
- CHAR8 *Cache;
- UINTN LeftSize;
- UINTN Size;
- CHAR8 *Ptr;
-
- Length = 0;
- //
- // 2M
- //
- TotalSize = 0x200000;
-
- Attribute = 0;
-
- //
- // if is the old file
- //
- if ((FileBuffer.FileName != NULL) && (StrCmp (FileName, FileBuffer.FileName) == 0)) {
- //
- // file has not been modified
- //
- if (!FileBuffer.FileModified) {
- return EFI_SUCCESS;
- }
-
- //
- // if file is read-only, set error
- //
- if (FileBuffer.ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
- return EFI_SUCCESS;
- }
- }
-
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
-
- if (!EFI_ERROR (Status)) {
- Info = ShellGetFileInfo (FileHandle);
-
- if ((Info != NULL) && Info->Attribute & EFI_FILE_DIRECTORY) {
- StatusBarSetStatusString (L"Directory Can Not Be Saved");
- ShellCloseFile (&FileHandle);
- FreePool (Info);
- return EFI_LOAD_ERROR;
- }
-
- if (Info != NULL) {
- Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY;
- FreePool (Info);
- }
-
- //
- // if file exits, so delete it
- //
- Status = ShellDeleteFile (&FileHandle);
- if (EFI_ERROR (Status) || (Status == EFI_WARN_DELETE_FAILURE)) {
- StatusBarSetStatusString (L"Write File Failed");
- return EFI_LOAD_ERROR;
- }
- }
-
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute);
-
- if (EFI_ERROR (Status)) {
- StatusBarSetStatusString (L"Create File Failed");
- return EFI_LOAD_ERROR;
- }
-
- //
- // if file is Unicode file, write Unicode header to it.
- //
- if (FileBuffer.FileType == FileTypeUnicode) {
- Length = 2;
- Status = ShellWriteFile (FileHandle, &Length, (VOID *)&gUnicodeFileTag);
- if (EFI_ERROR (Status)) {
- ShellDeleteFile (&FileHandle);
- return EFI_LOAD_ERROR;
- }
- }
-
- Cache = AllocateZeroPool (TotalSize);
- if (Cache == NULL) {
- ShellDeleteFile (&FileHandle);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // write all the lines back to disk
- //
- NumLines = 0;
- Type = NewLineTypeCarriageReturnLineFeed;
-
- Ptr = Cache;
- LeftSize = TotalSize;
-
- for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- if (Line->Type != NewLineTypeDefault) {
- Type = Line->Type;
- }
-
- //
- // newline character is at most 4 bytes ( two Unicode characters )
- //
- Length = 4;
- if ((Line->Buffer != NULL) && (Line->Size != 0)) {
- if (FileBuffer.FileType == FileTypeAscii) {
- Length += Line->Size;
- } else {
- Length += (Line->Size * 2);
- }
-
- //
- // end if FileTypeAscii
- //
- }
-
- //
- // no cache room left, so write cache to disk
- //
- if (LeftSize < Length) {
- Size = TotalSize - LeftSize;
- Status = ShellWriteFile (FileHandle, &Size, Cache);
- if (EFI_ERROR (Status)) {
- ShellDeleteFile (&FileHandle);
- FreePool (Cache);
- return EFI_LOAD_ERROR;
- }
-
- Ptr = Cache;
- LeftSize = TotalSize;
- }
-
- if ((Line->Buffer != NULL) && (Line->Size != 0)) {
- if (FileBuffer.FileType == FileTypeAscii) {
- UnicodeToAscii (Line->Buffer, Line->Size, Ptr);
- Length = Line->Size;
- } else {
- Length = (Line->Size * 2);
- CopyMem (Ptr, (CHAR8 *)Line->Buffer, Length);
- }
-
- //
- // end if FileTypeAscii
- //
- Ptr += Length;
- LeftSize -= Length;
- }
-
- //
- // end of if Line -> Buffer != NULL && Line -> Size != 0
- //
- // if not the last line , write return buffer to disk
- //
- if (Link->ForwardLink != FileBuffer.ListHead) {
- GetNewLine (Type, NewLineBuffer, &NewLineSize);
- CopyMem (Ptr, (CHAR8 *)NewLineBuffer, NewLineSize);
-
- Ptr += NewLineSize;
- LeftSize -= NewLineSize;
- }
-
- NumLines++;
- }
-
- if (TotalSize != LeftSize) {
- Size = TotalSize - LeftSize;
- Status = ShellWriteFile (FileHandle, &Size, Cache);
- if (EFI_ERROR (Status)) {
- ShellDeleteFile (&FileHandle);
- FreePool (Cache);
- return EFI_LOAD_ERROR;
- }
- }
-
- FreePool (Cache);
-
- ShellCloseFile (&FileHandle);
-
- FileBuffer.FileModified = FALSE;
-
- //
- // set status string
- //
- Str = CatSPrint (NULL, L"%d Lines Written", NumLines);
- if (Str == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- StatusBarSetStatusString (Str);
- SHELL_FREE_NON_NULL (Str);
-
- //
- // now everything is ready , you can set the new file name to filebuffer
- //
- if ((FileName != NULL) && (FileBuffer.FileName != NULL) && (StrCmp (FileName, FileBuffer.FileName) != 0)) {
- //
- // not the same
- //
- FileBufferSetFileName (FileName);
- if (FileBuffer.FileName == NULL) {
- ShellDeleteFile (&FileHandle);
- return EFI_OUT_OF_RESOURCES;
- }
- }
-
- FileBuffer.ReadOnly = FALSE;
- return EFI_SUCCESS;
-}
-
-/**
- Scroll cursor to left 1 character position.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferScrollLeft (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
-
- Line = FileBuffer.CurrentLine;
-
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.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 != FileBuffer.ListHead) {
- FRow--;
- Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- FCol = Line->Size + 1;
- } else {
- return EFI_SUCCESS;
- }
- } else {
- //
- // if not at start of this line, just move to previous column
- //
- FCol--;
- }
-
- FileBufferMovePosition (FRow, FCol);
-
- return EFI_SUCCESS;
-}
-
-/**
- Delete a char in line
-
- @param[in, out] Line The line to delete in.
- @param[in] Pos Position to delete the char at ( start from 0 ).
-**/
-VOID
-LineDeleteAt (
- IN OUT EFI_EDITOR_LINE *Line,
- IN UINTN Pos
- )
-{
- UINTN Index;
-
- //
- // move the latter characters front
- //
- for (Index = Pos - 1; Index < Line->Size; Index++) {
- Line->Buffer[Index] = Line->Buffer[Index + 1];
- }
-
- Line->Size--;
-}
-
-/**
- Concatenate Src into Dest.
-
- @param[in, out] Dest Destination string
- @param[in] Src Src String.
-**/
-VOID
-LineCat (
- IN OUT EFI_EDITOR_LINE *Dest,
- IN EFI_EDITOR_LINE *Src
- )
-{
- CHAR16 *Str;
- UINTN Size;
-
- Size = Dest->Size;
-
- Dest->Buffer[Size] = 0;
-
- //
- // concatenate the two strings
- //
- Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer);
- if (Str == NULL) {
- Dest->Buffer = NULL;
- return;
- }
-
- Dest->Size = Size + Src->Size;
- Dest->TotalSize = Dest->Size;
-
- FreePool (Dest->Buffer);
- FreePool (Src->Buffer);
-
- //
- // put str to dest->buffer
- //
- Dest->Buffer = Str;
-}
-
-/**
- Delete the previous character.
-
- @retval EFI_SUCCESS The delete was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferDoBackspace (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *End;
- LIST_ENTRY *Link;
- UINTN FileColumn;
-
- FileColumn = FileBuffer.FilePosition.Column;
-
- Line = FileBuffer.CurrentLine;
-
- //
- // the first column
- //
- if (FileColumn == 1) {
- //
- // the first row
- //
- if (FileBuffer.FilePosition.Row == 1) {
- return EFI_SUCCESS;
- }
-
- FileBufferScrollLeft ();
-
- Line = FileBuffer.CurrentLine;
- Link = Line->Link.ForwardLink;
- End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- //
- // concatenate this line with previous line
- //
- LineCat (Line, End);
- if (Line->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // remove End from line list
- //
- RemoveEntryList (&End->Link);
- FreePool (End);
-
- FileBuffer.NumLines--;
-
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- } else {
- //
- // just delete the previous character
- //
- LineDeleteAt (Line, FileColumn - 1);
- FileBufferScrollLeft ();
- FileBufferOnlyLineNeedRefresh = TRUE;
- }
-
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Add a return into line at current position.
-
- @retval EFI_SUCCESS The insetrion of the character was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferDoReturn (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *NewLine;
- UINTN FileColumn;
- UINTN Index;
- CHAR16 *Buffer;
- UINTN Row;
- UINTN Col;
-
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
-
- Line = FileBuffer.CurrentLine;
-
- FileColumn = FileBuffer.FilePosition.Column;
-
- NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
- if (NewLine == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- NewLine->Signature = LINE_LIST_SIGNATURE;
- NewLine->Size = Line->Size - FileColumn + 1;
- NewLine->TotalSize = NewLine->Size;
- NewLine->Buffer = CatSPrint (NULL, L"\0");
- if (NewLine->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- NewLine->Type = NewLineTypeDefault;
-
- if (NewLine->Size > 0) {
- //
- // UNICODE + CHAR_NULL
- //
- Buffer = AllocateZeroPool (2 * (NewLine->Size + 1));
- if (Buffer == NULL) {
- FreePool (NewLine->Buffer);
- FreePool (NewLine);
- return EFI_OUT_OF_RESOURCES;
- }
-
- FreePool (NewLine->Buffer);
-
- NewLine->Buffer = Buffer;
-
- for (Index = 0; Index < NewLine->Size; Index++) {
- NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1];
- }
-
- NewLine->Buffer[NewLine->Size] = CHAR_NULL;
-
- Line->Buffer[FileColumn - 1] = CHAR_NULL;
- Line->Size = FileColumn - 1;
- }
-
- //
- // increase NumLines
- //
- FileBuffer.NumLines++;
-
- //
- // insert it into the correct position of line list
- //
- NewLine->Link.BackLink = &(Line->Link);
- NewLine->Link.ForwardLink = Line->Link.ForwardLink;
- Line->Link.ForwardLink->BackLink = &(NewLine->Link);
- Line->Link.ForwardLink = &(NewLine->Link);
-
- //
- // move cursor to the start of next line
- //
- Row = FileBuffer.FilePosition.Row + 1;
- Col = 1;
-
- FileBufferMovePosition (Row, Col);
-
- //
- // set file is modified
- //
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Delete current character from current line. This is the effect caused
- by the 'del' key.
-
- @retval EFI_SUCCESS
-**/
-EFI_STATUS
-FileBufferDoDelete (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *Next;
- LIST_ENTRY *Link;
- UINTN FileColumn;
-
- Line = FileBuffer.CurrentLine;
- FileColumn = FileBuffer.FilePosition.Column;
-
- //
- // the last column
- //
- if (FileColumn >= Line->Size + 1) {
- //
- // the last line
- //
- if (Line->Link.ForwardLink == FileBuffer.ListHead) {
- return EFI_SUCCESS;
- }
-
- //
- // since last character,
- // so will add the next line to this line
- //
- Link = Line->Link.ForwardLink;
- Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- LineCat (Line, Next);
- if (Line->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- RemoveEntryList (&Next->Link);
- FreePool (Next);
-
- FileBuffer.NumLines--;
-
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- } else {
- //
- // just delete current character
- //
- LineDeleteAt (Line, FileColumn);
- FileBufferOnlyLineNeedRefresh = TRUE;
- }
-
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Scroll cursor to right 1 character.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferScrollRight (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
-
- Line = FileBuffer.CurrentLine;
- if (Line->Buffer == NULL) {
- return EFI_SUCCESS;
- }
-
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
-
- //
- // if already at end of this line, scroll it to the start of next line
- //
- if (FCol > Line->Size) {
- //
- // has next line
- //
- if (Line->Link.ForwardLink != FileBuffer.ListHead) {
- FRow++;
- FCol = 1;
- } else {
- return EFI_SUCCESS;
- }
- } else {
- //
- // if not at end of this line, just move to next column
- //
- FCol++;
- }
-
- FileBufferMovePosition (FRow, FCol);
-
- return EFI_SUCCESS;
-}
-
-/**
- Insert a char into line
-
-
- @param[in] Line The line to insert into.
- @param[in] Char The char to insert.
- @param[in] Pos The position to insert the char at ( start from 0 ).
- @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
-
- @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
-**/
-UINTN
-LineStrInsert (
- IN EFI_EDITOR_LINE *Line,
- IN CHAR16 Char,
- IN UINTN Pos,
- IN UINTN StrSize
- )
-{
- UINTN Index;
- CHAR16 *TempStringPtr;
- CHAR16 *Str;
-
- Index = (StrSize) * 2;
-
- Str = Line->Buffer;
-
- //
- // do not have free space
- //
- if (Line->TotalSize <= Line->Size) {
- Str = ReallocatePool (Index, Index + 16, Str);
- if (Str == NULL) {
- return 0;
- }
-
- Line->TotalSize += 8;
- }
-
- //
- // move the later part of the string one character right
- //
- TempStringPtr = Str;
- for (Index = StrSize; Index > Pos; Index--) {
- TempStringPtr[Index] = TempStringPtr[Index - 1];
- }
-
- //
- // insert char into it.
- //
- TempStringPtr[Index] = Char;
-
- Line->Buffer = Str;
- Line->Size++;
-
- return StrSize + 1;
-}
-
-/**
- Add a character to the current line.
-
- @param[in] Char The Character to input.
-
- @retval EFI_SUCCESS The input was succesful.
-**/
-EFI_STATUS
-FileBufferAddChar (
- IN CHAR16 Char
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FilePos;
-
- Line = FileBuffer.CurrentLine;
-
- //
- // only needs to refresh current line
- //
- FileBufferOnlyLineNeedRefresh = TRUE;
-
- //
- // when is insert mode, or cursor is at end of this line,
- // so insert this character
- // or replace the character.
- //
- FilePos = FileBuffer.FilePosition.Column - 1;
- if (FileBuffer.ModeInsert || (FilePos + 1 > Line->Size)) {
- LineStrInsert (Line, Char, FilePos, Line->Size + 1);
- } else {
- Line->Buffer[FilePos] = Char;
- }
-
- //
- // move cursor to right
- //
- FileBufferScrollRight ();
-
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Handles inputs from characters (ASCII key + Backspace + return)
-
- @param[in] Char The input character.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR There was an error.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferDoCharInput (
- IN CONST CHAR16 Char
- )
-{
- EFI_STATUS Status;
-
- Status = EFI_SUCCESS;
-
- switch (Char) {
- case CHAR_NULL:
- break;
-
- case CHAR_BACKSPACE:
- Status = FileBufferDoBackspace ();
- break;
-
- case CHAR_TAB:
- //
- // Tabs are ignored
- //
- break;
-
- case CHAR_LINEFEED:
- case CHAR_CARRIAGE_RETURN:
- Status = FileBufferDoReturn ();
- break;
-
- default:
- //
- // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
- //
- if ((Char > 127) || (Char < 32)) {
- Status = StatusBarSetStatusString (L"Unknown Command");
- } else {
- Status = FileBufferAddChar (Char);
- }
-
- break;
- }
-
- return Status;
-}
-
-/**
- Scroll cursor to the next line.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferScrollDown (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
-
- Line = FileBuffer.CurrentLine;
- if (Line->Buffer == NULL) {
- return EFI_SUCCESS;
- }
-
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
-
- //
- // has next line
- //
- if (Line->Link.ForwardLink != FileBuffer.ListHead) {
- FRow++;
- Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- //
- // if the next line is not that long, so move to end of next line
- //
- if (FCol > Line->Size) {
- FCol = Line->Size + 1;
- }
- } else {
- return EFI_SUCCESS;
- }
-
- FileBufferMovePosition (FRow, FCol);
-
- return EFI_SUCCESS;
-}
-
-/**
- Scroll the cursor to previous line.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferScrollUp (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
-
- Line = FileBuffer.CurrentLine;
-
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
-
- //
- // has previous line
- //
- if (Line->Link.BackLink != FileBuffer.ListHead) {
- FRow--;
- Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- //
- // if previous line is not that long, so move to the end of previous line
- //
- if (FCol > Line->Size) {
- FCol = Line->Size + 1;
- }
- } else {
- return EFI_SUCCESS;
- }
-
- FileBufferMovePosition (FRow, FCol);
-
- return EFI_SUCCESS;
-}
-
-/**
- Scroll cursor to next page.
-
- @retval EFI_SUCCESS The operation wa successful.
-**/
-EFI_STATUS
-FileBufferPageDown (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- UINTN Gap;
-
- Line = FileBuffer.CurrentLine;
-
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
-
- //
- // has next page
- //
- if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 2)) {
- Gap = (MainEditor.ScreenSize.Row - 2);
- } else {
- //
- // MOVE CURSOR TO LAST LINE
- //
- Gap = FileBuffer.NumLines - FRow;
- }
-
- //
- // get correct line
- //
- Line = MoveLine (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;
- }
-
- FRow += Gap;
-
- FileBufferMovePosition (FRow, FCol);
-
- return EFI_SUCCESS;
-}
-
-/**
- Scroll cursor to previous screen.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferPageUp (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- UINTN Gap;
- INTN Retreat;
-
- Line = FileBuffer.CurrentLine;
-
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
-
- //
- // has previous page
- //
- if (FRow > (MainEditor.ScreenSize.Row - 2)) {
- Gap = (MainEditor.ScreenSize.Row - 2);
- } else {
- //
- // the first line of file will displayed on the first line of screen
- //
- Gap = FRow - 1;
- }
-
- Retreat = Gap;
- Retreat = -Retreat;
-
- //
- // get correct line
- //
- Line = MoveLine (Retreat);
-
- //
- // 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;
- }
-
- FRow -= Gap;
-
- FileBufferMovePosition (FRow, FCol);
-
- return EFI_SUCCESS;
-}
-
-/**
- Scroll cursor to end of the current line.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferEnd (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
-
- Line = FileBuffer.CurrentLine;
-
- FRow = FileBuffer.FilePosition.Row;
-
- //
- // goto the last column of the line
- //
- FCol = Line->Size + 1;
-
- FileBufferMovePosition (FRow, FCol);
-
- return EFI_SUCCESS;
-}
-
-/**
- Dispatch input to different handler
- @param[in] Key The input key. One of:
- ASCII KEY
- Backspace/Delete
- Return
- Direction key: up/down/left/right/pgup/pgdn
- Home/End
- INS
-
- @retval EFI_SUCCESS The dispatch was done successfully.
- @retval EFI_LOAD_ERROR The dispatch was not successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferHandleInput (
- IN CONST EFI_INPUT_KEY *Key
- )
-{
- EFI_STATUS Status;
-
- Status = EFI_SUCCESS;
-
- switch (Key->ScanCode) {
- //
- // ordinary key input
- //
- case SCAN_NULL:
- if (!FileBuffer.ReadOnly) {
- Status = FileBufferDoCharInput (Key->UnicodeChar);
- } else {
- Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- }
-
- break;
-
- //
- // up arrow
- //
- case SCAN_UP:
- Status = FileBufferScrollUp ();
- break;
-
- //
- // down arrow
- //
- case SCAN_DOWN:
- Status = FileBufferScrollDown ();
- break;
-
- //
- // right arrow
- //
- case SCAN_RIGHT:
- Status = FileBufferScrollRight ();
- break;
-
- //
- // left arrow
- //
- case SCAN_LEFT:
- Status = FileBufferScrollLeft ();
- break;
-
- //
- // page up
- //
- case SCAN_PAGE_UP:
- Status = FileBufferPageUp ();
- break;
-
- //
- // page down
- //
- case SCAN_PAGE_DOWN:
- Status = FileBufferPageDown ();
- break;
-
- //
- // delete
- //
- case SCAN_DELETE:
- if (!FileBuffer.ReadOnly) {
- Status = FileBufferDoDelete ();
- } else {
- Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- }
-
- break;
-
- //
- // home
- //
- case SCAN_HOME:
- FileBufferMovePosition (FileBuffer.FilePosition.Row, 1);
- Status = EFI_SUCCESS;
- break;
-
- //
- // end
- //
- case SCAN_END:
- Status = FileBufferEnd ();
- break;
-
- //
- // insert
- //
- case SCAN_INSERT:
- FileBuffer.ModeInsert = (BOOLEAN) !FileBuffer.ModeInsert;
- Status = EFI_SUCCESS;
- break;
-
- default:
- Status = StatusBarSetStatusString (L"Unknown Command");
- break;
- }
-
- return Status;
-}
-
-/**
- Check user specified FileRow is above current screen.
-
- @param[in] FileRow The 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
-AboveCurrentScreen (
- IN UINTN FileRow
- )
-{
- //
- // if is to the above of the screen
- //
- if (FileRow < FileBuffer.LowVisibleRange.Row) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Check user specified FileRow is under current screen.
-
- @param[in] FileRow The 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
-UnderCurrentScreen (
- IN UINTN FileRow
- )
-{
- //
- // if is to the under of the screen
- //
- if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 2) - 1) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Check user specified FileCol is left to current screen.
-
- @param[in] FileCol The column of file position ( start from 1 ).
-
- @retval TRUE It is to the left.
- @retval FALSE It is not to the left.
-**/
-BOOLEAN
-LeftCurrentScreen (
- IN UINTN FileCol
- )
-{
- //
- // if is to the left of the screen
- //
- if (FileCol < FileBuffer.LowVisibleRange.Column) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Check user specified FileCol is right to current screen.
-
- @param[in] FileCol The column of file position ( start from 1 ).
-
- @retval TRUE It is to the right.
- @retval FALSE It is not to the right.
-**/
-BOOLEAN
-RightCurrentScreen (
- IN UINTN FileCol
- )
-{
- //
- // if is to the right of the screen
- //
- if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Advance/Retreat lines and set CurrentLine in FileBuffer to it
-
- @param[in] Count The line number to advance/retreat
- >0 : advance
- <0: retreat
-
- @retval NULL An error occurred.
- @return The line after advance/retreat.
-**/
-EFI_EDITOR_LINE *
-MoveCurrentLine (
- IN INTN Count
- )
-{
- EFI_EDITOR_LINE *Line;
- UINTN AbsCount;
-
- if (Count <= 0) {
- AbsCount = (UINTN)ABS (Count);
- Line = InternalEditorMiscLineRetreat (AbsCount, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
- } else {
- Line = InternalEditorMiscLineAdvance ((UINTN)Count, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
- }
-
- if (Line == NULL) {
- return NULL;
- }
-
- MainEditor.FileBuffer->CurrentLine = Line;
-
- return Line;
-}
-
-/**
- According to cursor's file position, adjust screen display
-
- @param[in] NewFilePosRow The row of file position ( start from 1 ).
- @param[in] NewFilePosCol The column of file position ( start from 1 ).
-**/
-VOID
-FileBufferMovePosition (
- IN CONST UINTN NewFilePosRow,
- IN CONST UINTN NewFilePosCol
- )
-{
- INTN RowGap;
- INTN ColGap;
- UINTN Abs;
- BOOLEAN Above;
- BOOLEAN Under;
- BOOLEAN Right;
- BOOLEAN Left;
-
- //
- // CALCULATE gap between current file position and new file position
- //
- RowGap = NewFilePosRow - FileBuffer.FilePosition.Row;
- ColGap = NewFilePosCol - FileBuffer.FilePosition.Column;
-
- Under = UnderCurrentScreen (NewFilePosRow);
- Above = AboveCurrentScreen (NewFilePosRow);
- //
- // if is below current screen
- //
- if (Under) {
- //
- // display row will be unchanged
- //
- FileBuffer.FilePosition.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 < (FileBuffer.DisplayPosition.Row - 1)) {
- FileBuffer.DisplayPosition.Row = NewFilePosRow + 1;
- }
-
- FileBuffer.FilePosition.Row = NewFilePosRow;
- } else {
- //
- // in current screen
- //
- FileBuffer.FilePosition.Row = NewFilePosRow;
- if (RowGap < 0) {
- Abs = (UINTN)ABS (RowGap);
- FileBuffer.DisplayPosition.Row -= Abs;
- } else {
- FileBuffer.DisplayPosition.Row += RowGap;
- }
- }
- }
-
- FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2);
-
- Right = RightCurrentScreen (NewFilePosCol);
- Left = LeftCurrentScreen (NewFilePosCol);
-
- //
- // if right to current screen
- //
- if (Right) {
- //
- // display column will be changed to end
- //
- FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column;
- FileBuffer.FilePosition.Column = NewFilePosCol;
- } else {
- if (Left) {
- //
- // has enough left characters , so display row unchanged
- // not has enough left characters,
- // so the first character is at the first display column
- //
- if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) {
- FileBuffer.DisplayPosition.Column = NewFilePosCol;
- }
-
- FileBuffer.FilePosition.Column = NewFilePosCol;
- } else {
- //
- // in current screen
- //
- FileBuffer.FilePosition.Column = NewFilePosCol;
- if (ColGap < 0) {
- Abs = (UINTN)(-ColGap);
- FileBuffer.DisplayPosition.Column -= Abs;
- } else {
- FileBuffer.DisplayPosition.Column += ColGap;
- }
- }
- }
-
- FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1);
-
- //
- // let CurrentLine point to correct line;
- //
- FileBuffer.CurrentLine = MoveCurrentLine (RowGap);
-}
-
-/**
- Cut current line out and return a pointer to it.
-
- @param[out] CutLine Upon a successful return pointer to the pointer to
- the allocated cut line.
-
- @retval EFI_SUCCESS The cut was successful.
- @retval EFI_NOT_FOUND There was no selection to cut.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferCutLine (
- OUT EFI_EDITOR_LINE **CutLine
- )
-{
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *NewLine;
- UINTN Row;
- UINTN Col;
-
- *CutLine = NULL;
-
- if (FileBuffer.ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- return EFI_SUCCESS;
- }
-
- Line = FileBuffer.CurrentLine;
-
- //
- // if is the last dummy line, SO CAN not cut
- //
- if ((StrCmp (Line->Buffer, L"\0") == 0) && (Line->Link.ForwardLink == FileBuffer.ListHead)
- //
- // last line
- //
- )
- {
- //
- // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
- //
- StatusBarSetStatusString (L"Nothing to Cut");
- return EFI_NOT_FOUND;
- }
-
- //
- // if is the last line, so create a dummy line
- //
- if (Line->Link.ForwardLink == FileBuffer.ListHead) {
- //
- // last line
- // create a new line
- //
- NewLine = FileBufferCreateLine ();
- if (NewLine == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
-
- FileBuffer.NumLines--;
- Row = FileBuffer.FilePosition.Row;
- Col = 1;
- //
- // move home
- //
- FileBuffer.CurrentLine = CR (
- FileBuffer.CurrentLine->Link.ForwardLink,
- EFI_EDITOR_LINE,
- Link,
- LINE_LIST_SIGNATURE
- );
-
- RemoveEntryList (&Line->Link);
-
- FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- FileBufferMovePosition (Row, Col);
-
- FileBuffer.FileModified = TRUE;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
-
- *CutLine = Line;
-
- return EFI_SUCCESS;
-}
-
-/**
- Paste a line into line list.
-
- @retval EFI_SUCCESS The paste was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferPasteLine (
- VOID
- )
-{
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *NewLine;
- UINTN Row;
- UINTN Col;
-
- //
- // if nothing is on clip board
- // then do nothing
- //
- if (MainEditor.CutLine == NULL) {
- return EFI_SUCCESS;
- }
-
- //
- // read only file can not be pasted on
- //
- if (FileBuffer.ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- return EFI_SUCCESS;
- }
-
- NewLine = LineDup (MainEditor.CutLine);
- if (NewLine == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // insert it above current line
- //
- Line = FileBuffer.CurrentLine;
- NewLine->Link.BackLink = Line->Link.BackLink;
- NewLine->Link.ForwardLink = &Line->Link;
-
- Line->Link.BackLink->ForwardLink = &NewLine->Link;
- Line->Link.BackLink = &NewLine->Link;
-
- FileBuffer.NumLines++;
- FileBuffer.CurrentLine = NewLine;
-
- FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- Col = 1;
- //
- // move home
- //
- Row = FileBuffer.FilePosition.Row;
-
- FileBufferMovePosition (Row, Col);
-
- //
- // after paste, set some value so that refresh knows to do something
- //
- FileBuffer.FileModified = TRUE;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
-
- return EFI_SUCCESS;
-}
-
-/**
- Search string from current position on in file
-
- @param[in] Str The search string.
- @param[in] Offset The offset from current position.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_NOT_FOUND The string Str was not found.
-**/
-EFI_STATUS
-FileBufferSearch (
- IN CONST CHAR16 *Str,
- IN CONST UINTN Offset
- )
-{
- CHAR16 *Current;
- UINTN Position;
- UINTN Row;
- UINTN Column;
- EFI_EDITOR_LINE *Line;
- CHAR16 *CharPos;
- LIST_ENTRY *Link;
- BOOLEAN Found;
-
- Column = 0;
- Position = 0;
-
- //
- // search if in current line
- //
- Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset;
-
- if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) {
- //
- // the end
- //
- Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size;
- }
-
- Found = FALSE;
-
- CharPos = StrStr (Current, Str);
- if (CharPos != NULL) {
- Position = CharPos - Current + 1;
- Found = TRUE;
- }
-
- //
- // found
- //
- if (Found) {
- Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset;
- Row = FileBuffer.FilePosition.Row;
- } else {
- //
- // not found so find through next lines
- //
- Link = FileBuffer.CurrentLine->Link.ForwardLink;
-
- Row = FileBuffer.FilePosition.Row + 1;
- while (Link != FileBuffer.ListHead) {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- // Position = StrStr (Line->Buffer, Str);
- CharPos = StrStr (Line->Buffer, Str);
- if (CharPos != NULL) {
- Position = CharPos - Line->Buffer + 1;
- Found = TRUE;
- }
-
- if (Found) {
- //
- // found
- //
- Column = Position;
- break;
- }
-
- Row++;
- Link = Link->ForwardLink;
- }
-
- if (Link == FileBuffer.ListHead) {
- Found = FALSE;
- } else {
- Found = TRUE;
- }
- }
-
- if (!Found) {
- return EFI_NOT_FOUND;
- }
-
- FileBufferMovePosition (Row, Column);
-
- //
- // call refresh to fresh edit area,
- // because the outer may loop to find multiply occurrence of this string
- //
- FileBufferRefresh ();
-
- return EFI_SUCCESS;
-}
-
-/**
- Replace SearchLen characters from current position on with Replace.
-
- This will modify the current buffer at the current position.
-
- @param[in] Replace The string to replace.
- @param[in] SearchLen Search string's length.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferReplace (
- IN CONST CHAR16 *Replace,
- IN CONST UINTN SearchLen
- )
-{
- UINTN ReplaceLen;
- UINTN Index;
- CHAR16 *Buffer;
- UINTN NewSize;
- UINTN OldSize;
- UINTN Gap;
-
- ReplaceLen = StrLen (Replace);
-
- OldSize = FileBuffer.CurrentLine->Size + 1;
- //
- // include CHAR_NULL
- //
- NewSize = OldSize + (ReplaceLen - SearchLen);
-
- if (ReplaceLen > SearchLen) {
- //
- // do not have the enough space
- //
- if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) {
- FileBuffer.CurrentLine->Buffer = ReallocatePool (
- 2 * OldSize,
- 2 * NewSize,
- FileBuffer.CurrentLine->Buffer
- );
- FileBuffer.CurrentLine->TotalSize = NewSize - 1;
- }
-
- if (FileBuffer.CurrentLine->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // the end CHAR_NULL character;
- //
- Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1);
- Gap = ReplaceLen - SearchLen;
-
- //
- // keep the latter part
- //
- for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) {
- *Buffer = *(Buffer - Gap);
- Buffer--;
- }
-
- //
- // set replace into it
- //
- Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = Replace[Index];
- }
- }
-
- if (ReplaceLen < SearchLen) {
- Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
-
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = Replace[Index];
- }
-
- Buffer += ReplaceLen;
- Gap = SearchLen - ReplaceLen;
-
- //
- // set replace into it
- //
- for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) {
- *Buffer = *(Buffer + Gap);
- Buffer++;
- }
- }
-
- if (ReplaceLen == SearchLen) {
- Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = Replace[Index];
- }
- }
-
- FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen);
-
- FileBufferOnlyLineNeedRefresh = TRUE;
-
- FileBuffer.FileModified = TRUE;
-
- MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
- FileBufferRestorePosition ();
- FileBufferRefresh ();
-
- return EFI_SUCCESS;
-}
-
-/**
- Move the mouse cursor position.
-
- @param[in] TextX The new x-coordinate.
- @param[in] TextY The new y-coordinate.
-**/
-VOID
-FileBufferAdjustMousePosition (
- IN CONST INT32 TextX,
- IN CONST INT32 TextY
- )
-{
- UINTN CoordinateX;
- UINTN CoordinateY;
- UINTN AbsX;
- UINTN AbsY;
-
- //
- // TextX and TextY is mouse movement data returned by mouse driver
- // This function will change it to MousePosition
- //
- //
- // get absolute value
- //
-
- AbsX = ABS (TextX);
- AbsY = ABS (TextY);
-
- CoordinateX = FileBuffer.MousePosition.Column;
- CoordinateY = FileBuffer.MousePosition.Row;
-
- if (TextX >= 0) {
- CoordinateX += TextX;
- } else {
- if (CoordinateX >= AbsX) {
- CoordinateX -= AbsX;
- } else {
- CoordinateX = 0;
- }
- }
-
- if (TextY >= 0) {
- CoordinateY += TextY;
- } else {
- if (CoordinateY >= AbsY) {
- CoordinateY -= AbsY;
- } else {
- CoordinateY = 0;
- }
- }
-
- //
- // check whether new mouse column position is beyond screen
- // if not, adjust it
- //
- if ((CoordinateX >= 1) && (CoordinateX <= MainEditor.ScreenSize.Column)) {
- FileBuffer.MousePosition.Column = CoordinateX;
- } else if (CoordinateX < 1) {
- FileBuffer.MousePosition.Column = 1;
- } else if (CoordinateX > MainEditor.ScreenSize.Column) {
- FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column;
- }
-
- //
- // check whether new mouse row position is beyond screen
- // if not, adjust it
- //
- if ((CoordinateY >= 2) && (CoordinateY <= (MainEditor.ScreenSize.Row - 1))) {
- FileBuffer.MousePosition.Row = CoordinateY;
- } else if (CoordinateY < 2) {
- FileBuffer.MousePosition.Row = 2;
- } else if (CoordinateY > (MainEditor.ScreenSize.Row - 1)) {
- FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 1);
- }
-}
-
-/**
- Search and replace operation.
-
- @param[in] SearchStr The string to search for.
- @param[in] ReplaceStr The string to replace with.
- @param[in] Offset The column to start at.
-**/
-EFI_STATUS
-FileBufferReplaceAll (
- IN CHAR16 *SearchStr,
- IN CHAR16 *ReplaceStr,
- IN UINTN Offset
- )
-{
- CHAR16 *Buffer;
- UINTN Position;
- UINTN Column;
- UINTN ReplaceLen;
- UINTN SearchLen;
- UINTN Index;
- UINTN NewSize;
- UINTN OldSize;
- UINTN Gap;
- EFI_EDITOR_LINE *Line;
- LIST_ENTRY *Link;
- CHAR16 *CharPos;
-
- SearchLen = StrLen (SearchStr);
- ReplaceLen = StrLen (ReplaceStr);
-
- Column = FileBuffer.FilePosition.Column + Offset - 1;
-
- if (Column > FileBuffer.CurrentLine->Size) {
- Column = FileBuffer.CurrentLine->Size;
- }
-
- Link = &(FileBuffer.CurrentLine->Link);
-
- while (Link != FileBuffer.ListHead) {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- CharPos = StrStr (Line->Buffer + Column, SearchStr);
- if (CharPos != NULL) {
- Position = CharPos - Line->Buffer;// + Column;
- //
- // found
- //
- if (ReplaceLen > SearchLen) {
- OldSize = Line->Size + 1;
- //
- // include CHAR_NULL
- //
- NewSize = OldSize + (ReplaceLen - SearchLen);
-
- //
- // do not have the enough space
- //
- if (Line->TotalSize + 1 <= NewSize) {
- Line->Buffer = ReallocatePool (
- 2 * OldSize,
- 2 * NewSize,
- Line->Buffer
- );
- Line->TotalSize = NewSize - 1;
- }
-
- if (Line->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // the end CHAR_NULL character;
- //
- Buffer = Line->Buffer + (NewSize - 1);
- Gap = ReplaceLen - SearchLen;
-
- //
- // keep the latter part
- //
- for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) {
- *Buffer = *(Buffer - Gap);
- Buffer--;
- }
- } else if (ReplaceLen < SearchLen) {
- Buffer = Line->Buffer + Position + ReplaceLen;
- Gap = SearchLen - ReplaceLen;
-
- for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) {
- *Buffer = *(Buffer + Gap);
- Buffer++;
- }
- } else {
- ASSERT (ReplaceLen == SearchLen);
- }
-
- //
- // set replace into it
- //
- Buffer = Line->Buffer + Position;
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = ReplaceStr[Index];
- }
-
- Line->Size += (ReplaceLen - SearchLen);
- Column += ReplaceLen;
- } else {
- //
- // not found
- //
- Column = 0;
- Link = Link->ForwardLink;
- }
- }
-
- //
- // call refresh to fresh edit area
- //
- FileBuffer.FileModified = TRUE;
- FileBufferNeedRefresh = TRUE;
- FileBufferRefresh ();
-
- return EFI_SUCCESS;
-}
-
-/**
- Set the modified state to TRUE.
-**/
-VOID
-FileBufferSetModified (
- VOID
- )
-{
- FileBuffer.FileModified = TRUE;
-}
+/** @file
+ Implements filebuffer interface functions.
+
+ Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TextEditor.h"
+#include <Guid/FileSystemInfo.h>
+#include <Library/FileHandleLib.h>
+
+EFI_EDITOR_FILE_BUFFER FileBuffer;
+EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
+
+//
+// for basic initialization of FileBuffer
+//
+EFI_EDITOR_FILE_BUFFER FileBufferConst = {
+ NULL,
+ FileTypeUnicode,
+ NULL,
+ NULL,
+ 0,
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ FALSE,
+ TRUE,
+ FALSE,
+ NULL
+};
+
+//
+// the whole edit area needs to be refreshed
+//
+BOOLEAN FileBufferNeedRefresh;
+
+//
+// only the current line in edit area needs to be refresh
+//
+BOOLEAN FileBufferOnlyLineNeedRefresh;
+
+BOOLEAN FileBufferMouseNeedRefresh;
+
+extern BOOLEAN EditorMouseAction;
+
+/**
+ Initialization function for FileBuffer.
+
+ @param EFI_SUCCESS The initialization was successful.
+ @param EFI_LOAD_ERROR A default name could not be created.
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferInit (
+ VOID
+ )
+{
+ //
+ // basically initialize the FileBuffer
+ //
+ CopyMem (&FileBuffer, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
+ CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
+
+ //
+ // set default FileName
+ //
+ FileBuffer.FileName = EditGetDefaultFileName (L"txt");
+ if (FileBuffer.FileName == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
+ if (FileBuffer.ListHead == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeListHead (FileBuffer.ListHead);
+
+ FileBuffer.DisplayPosition.Row = 2;
+ FileBuffer.DisplayPosition.Column = 1;
+ FileBuffer.LowVisibleRange.Row = 2;
+ FileBuffer.LowVisibleRange.Column = 1;
+
+ FileBufferNeedRefresh = FALSE;
+ FileBufferMouseNeedRefresh = FALSE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for FileBuffer. Only backup the following items:
+ Mouse/Cursor position
+ File Name, Type, ReadOnly, Modified
+ Insert Mode
+
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+FileBufferBackup (
+ VOID
+ )
+{
+ FileBufferBackupVar.MousePosition = FileBuffer.MousePosition;
+
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
+ FileBufferBackupVar.FileName = NULL;
+ FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0);
+
+ FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert;
+ FileBufferBackupVar.FileType = FileBuffer.FileType;
+
+ FileBufferBackupVar.FilePosition = FileBuffer.FilePosition;
+ FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange;
+
+ FileBufferBackupVar.FileModified = FileBuffer.FileModified;
+ FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Advance to the next Count lines
+
+ @param[in] Count The line number to advance by.
+ @param[in] CurrentLine The pointer to the current line structure.
+ @param[in] LineList The pointer to the linked list of lines.
+
+ @retval NULL There was an error.
+ @return The line structure after the advance.
+**/
+EFI_EDITOR_LINE *
+InternalEditorMiscLineAdvance (
+ IN CONST UINTN Count,
+ IN CONST EFI_EDITOR_LINE *CurrentLine,
+ IN CONST LIST_ENTRY *LineList
+ )
+
+{
+ UINTN Index;
+ CONST EFI_EDITOR_LINE *Line;
+
+ if ((CurrentLine == NULL) || (LineList == NULL)) {
+ return NULL;
+ }
+
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
+ //
+ // if already last line
+ //
+ if (Line->Link.ForwardLink == LineList) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return ((EFI_EDITOR_LINE *)Line);
+}
+
+/**
+ Retreat to the previous Count lines.
+
+ @param[in] Count The line number to retreat by.
+ @param[in] CurrentLine The pointer to the current line structure.
+ @param[in] LineList The pointer to the linked list of lines.
+
+ @retval NULL There was an error.
+ @return The line structure after the retreat.
+**/
+EFI_EDITOR_LINE *
+InternalEditorMiscLineRetreat (
+ IN CONST UINTN Count,
+ IN CONST EFI_EDITOR_LINE *CurrentLine,
+ IN CONST LIST_ENTRY *LineList
+ )
+
+{
+ UINTN Index;
+ CONST EFI_EDITOR_LINE *Line;
+
+ if ((CurrentLine == NULL) || (LineList == NULL)) {
+ return NULL;
+ }
+
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
+ //
+ // already the first line
+ //
+ if (Line->Link.BackLink == LineList) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return ((EFI_EDITOR_LINE *)Line);
+}
+
+/**
+ Advance/Retreat lines
+
+ @param[in] Count line number to advance/retreat
+ >0 : advance
+ <0 : retreat
+
+ @retval NULL An error occurred.
+ @return The line after advance/retreat.
+**/
+EFI_EDITOR_LINE *
+MoveLine (
+ IN CONST INTN Count
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ //
+ // if < 0, then retreat
+ // if > 0, the advance
+ //
+ if (Count <= 0) {
+ AbsCount = (UINTN)ABS (Count);
+ Line = InternalEditorMiscLineRetreat (AbsCount, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
+ } else {
+ Line = InternalEditorMiscLineAdvance ((UINTN)Count, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
+ }
+
+ return Line;
+}
+
+/**
+ Function to update the 'screen' to display the mouse position.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+FileBufferRestoreMousePosition (
+ VOID
+ )
+{
+ EFI_EDITOR_COLOR_UNION Orig;
+ EFI_EDITOR_COLOR_UNION New;
+ UINTN FRow;
+ UINTN FColumn;
+ BOOLEAN HasCharacter;
+ EFI_EDITOR_LINE *CurrentLine;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 Value;
+
+ //
+ // variable initialization
+ //
+ Line = NULL;
+
+ if (MainEditor.MouseSupported) {
+ if (FileBufferMouseNeedRefresh) {
+ FileBufferMouseNeedRefresh = FALSE;
+
+ //
+ // if mouse position not moved and only mouse action
+ // so do not need to refresh mouse position
+ //
+ if ( ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row) &&
+ (FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column))
+ && EditorMouseAction)
+ {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // backup the old screen attributes
+ //
+ Orig = MainEditor.ColorAttributes;
+ New.Data = 0;
+ New.Colors.Foreground = Orig.Colors.Background & 0xF;
+ New.Colors.Background = Orig.Colors.Foreground & 0x7;
+
+ //
+ // clear the old mouse position
+ //
+ FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2;
+
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1;
+
+ HasCharacter = TRUE;
+ if (FRow > FileBuffer.NumLines) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = FileBuffer.CurrentLine;
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
+
+ if ((Line == NULL) || (FColumn > Line->Size)) {
+ HasCharacter = FALSE;
+ }
+
+ FileBuffer.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ Value = (Line->Buffer[FColumn - 1]);
+ ShellPrintEx (
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,
+ L"%c",
+ Value
+ );
+ }
+
+ //
+ // set the new mouse position
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+
+ //
+ // clear the old mouse position
+ //
+ FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2;
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1;
+
+ HasCharacter = TRUE;
+ if (FRow > FileBuffer.NumLines) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = FileBuffer.CurrentLine;
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
+
+ if ((Line == NULL) || (FColumn > Line->Size)) {
+ HasCharacter = FALSE;
+ }
+
+ FileBuffer.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)FileBuffer.MousePosition.Column - 1,
+ (INT32)FileBuffer.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ Value = Line->Buffer[FColumn - 1];
+ ShellPrintEx (
+ (INT32)FileBuffer.MousePosition.Column - 1,
+ (INT32)FileBuffer.MousePosition.Row - 1,
+ L"%c",
+ Value
+ );
+ }
+
+ //
+ // end of HasCharacter
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+
+ //
+ // end of MouseNeedRefresh
+ //
+ }
+
+ //
+ // end of MouseSupported
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Free all the lines in FileBuffer
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferFreeLines (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // free all the lines
+ //
+ if (FileBuffer.Lines != NULL) {
+ Line = FileBuffer.Lines;
+ Link = &(Line->Link);
+ do {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ Link = Link->ForwardLink;
+
+ //
+ // free line's buffer and line itself
+ //
+ LineFree (Line);
+ } while (Link != FileBuffer.ListHead);
+ }
+
+ //
+ // clean the line list related structure
+ //
+ FileBuffer.Lines = NULL;
+ FileBuffer.CurrentLine = NULL;
+ FileBuffer.NumLines = 0;
+
+ FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead;
+ FileBuffer.ListHead->BackLink = FileBuffer.ListHead;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup function for FileBuffer.
+
+ @retval EFI_SUCCESS The cleanup was successful.
+**/
+EFI_STATUS
+FileBufferCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);
+
+ //
+ // free all the lines
+ //
+ Status = FileBufferFreeLines ();
+
+ SHELL_FREE_NON_NULL (FileBuffer.ListHead);
+ FileBuffer.ListHead = NULL;
+
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
+ return Status;
+}
+
+/**
+ Print a line specified by Line on a row specified by Row of the screen.
+
+ @param[in] Line The line to print.
+ @param[in] Row The row on the screen to print onto (begin from 1).
+
+ @retval EFI_SUCCESS The printing was successful.
+**/
+EFI_STATUS
+FileBufferPrintLine (
+ IN CONST EFI_EDITOR_LINE *Line,
+ IN CONST UINTN Row
+ )
+{
+ CHAR16 *Buffer;
+ UINTN Limit;
+ CHAR16 *PrintLine;
+ CHAR16 *PrintLine2;
+ UINTN BufLen;
+
+ //
+ // print start from correct character
+ //
+ Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1;
+
+ Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1;
+ if (Limit > Line->Size) {
+ Limit = 0;
+ }
+
+ BufLen = (MainEditor.ScreenSize.Column + 1) * sizeof (CHAR16);
+ PrintLine = AllocatePool (BufLen);
+ if (PrintLine != NULL) {
+ StrnCpyS (PrintLine, BufLen/sizeof (CHAR16), Buffer, MIN (Limit, MainEditor.ScreenSize.Column));
+ for (Limit = StrLen (PrintLine); Limit < MainEditor.ScreenSize.Column; Limit++) {
+ PrintLine[Limit] = L' ';
+ }
+
+ PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL;
+
+ PrintLine2 = AllocatePool (BufLen * 2);
+ if (PrintLine2 != NULL) {
+ ShellCopySearchAndReplace (PrintLine, PrintLine2, BufLen * 2, L"%", L"^%", FALSE, FALSE);
+
+ ShellPrintEx (
+ 0,
+ (INT32)Row - 1,
+ L"%s",
+ PrintLine2
+ );
+ FreePool (PrintLine2);
+ }
+
+ FreePool (PrintLine);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the cursor position according to FileBuffer.DisplayPosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferRestorePosition (
+ VOID
+ )
+{
+ //
+ // set cursor position
+ //
+ return (gST->ConOut->SetCursorPosition (
+ gST->ConOut,
+ FileBuffer.DisplayPosition.Column - 1,
+ FileBuffer.DisplayPosition.Row - 1
+ ));
+}
+
+/**
+ Refresh the screen with whats in the buffer.
+
+ @retval EFI_SUCCESS The refresh was successful.
+ @retval EFI_LOAD_ERROR There was an error finding what to write.
+**/
+EFI_STATUS
+FileBufferRefresh (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+ UINTN Row;
+
+ //
+ // if it's the first time after editor launch, so should refresh
+ //
+ if (!EditorFirst) {
+ //
+ // no definite required refresh
+ // and file position displayed on screen has not been changed
+ //
+ if (!FileBufferNeedRefresh &&
+ !FileBufferOnlyLineNeedRefresh &&
+ (FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row) &&
+ (FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column)
+ )
+ {
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ //
+ // only need to refresh current line
+ //
+ if (FileBufferOnlyLineNeedRefresh &&
+ (FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row) &&
+ (FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column)
+ )
+ {
+ EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ FileBufferPrintLine (
+ FileBuffer.CurrentLine,
+ FileBuffer.DisplayPosition.Row
+ );
+ } else {
+ //
+ // the whole edit area need refresh
+ //
+
+ //
+ // no line
+ //
+ if (FileBuffer.Lines == NULL) {
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // get the first line that will be displayed
+ //
+ Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row);
+ if (Line == NULL) {
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_LOAD_ERROR;
+ }
+
+ Link = &(Line->Link);
+ Row = 2;
+ do {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // print line at row
+ //
+ FileBufferPrintLine (Line, Row);
+
+ Link = Link->ForwardLink;
+ Row++;
+ } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 1));
+
+ //
+ // while not file end and not screen full
+ //
+ while (Row <= (MainEditor.ScreenSize.Row - 1)) {
+ EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ Row++;
+ }
+ }
+
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+
+ FileBufferNeedRefresh = FALSE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+}
+
+/**
+ Create a new line and append it to the line list.
+ Fields affected:
+ NumLines
+ Lines
+
+ @retval NULL The create line failed.
+ @return The line created.
+**/
+EFI_EDITOR_LINE *
+FileBufferCreateLine (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // allocate a line structure
+ //
+ Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ //
+ // initialize the structure
+ //
+ Line->Signature = LINE_LIST_SIGNATURE;
+ Line->Size = 0;
+ Line->TotalSize = 0;
+ Line->Type = NewLineTypeDefault;
+
+ //
+ // initial buffer of the line is "\0"
+ //
+ ASSERT (CHAR_NULL == CHAR_NULL);
+ Line->Buffer = CatSPrint (NULL, L"\0");
+ if (Line->Buffer == NULL) {
+ return NULL;
+ }
+
+ FileBuffer.NumLines++;
+
+ //
+ // insert the line into line list
+ //
+ InsertTailList (FileBuffer.ListHead, &Line->Link);
+
+ if (FileBuffer.Lines == NULL) {
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return Line;
+}
+
+/**
+ Set FileName field in FileBuffer.
+
+ @param Str The file name to set.
+
+ @retval EFI_SUCCESS The filename was successfully set.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.
+**/
+EFI_STATUS
+FileBufferSetFileName (
+ IN CONST CHAR16 *Str
+ )
+{
+ //
+ // Verify the parameters
+ //
+ if (!IsValidFileName (Str)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // free the old file name
+ //
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);
+
+ //
+ // Allocate and set the new name
+ //
+ FileBuffer.FileName = CatSPrint (NULL, L"%s", Str);
+ if (FileBuffer.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Free the existing file lines and reset the modified flag.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferFree (
+ VOID
+ )
+{
+ //
+ // free all the lines
+ //
+ FileBufferFreeLines ();
+ FileBuffer.FileModified = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read a file from disk into the FileBuffer.
+
+ @param[in] FileName The filename to read.
+ @param[in] Recover TRUE if is for recover mode, no information printouts.
+
+ @retval EFI_SUCCESS The load was successful.
+ @retval EFI_LOAD_ERROR The load failed.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER FileName is a directory.
+**/
+EFI_STATUS
+FileBufferRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Recover
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EE_NEWLINE_TYPE Type;
+ UINTN LoopVar1;
+ UINTN LoopVar2;
+ UINTN LineSize;
+ VOID *Buffer;
+ CHAR16 *UnicodeBuffer;
+ UINT8 *AsciiBuffer;
+ UINTN FileSize;
+ SHELL_FILE_HANDLE FileHandle;
+ BOOLEAN CreateFile;
+ EFI_STATUS Status;
+ UINTN LineSizeBackup;
+ EFI_FILE_INFO *Info;
+
+ Line = NULL;
+ LoopVar1 = 0;
+ FileSize = 0;
+ UnicodeBuffer = NULL;
+ Type = NewLineTypeDefault;
+ FileHandle = NULL;
+ CreateFile = FALSE;
+
+ //
+ // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
+ // you should set status string via StatusBarSetStatusString(L"blah")
+ // since this function maybe called before the editorhandleinput loop
+ // so any error will cause editor return
+ // so if you want to print the error status
+ // you should set the status string
+ //
+
+ //
+ // try to open the file
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+
+ if (!EFI_ERROR (Status)) {
+ CreateFile = FALSE;
+ if (FileHandle == NULL) {
+ StatusBarSetStatusString (L"Disk Error");
+ return EFI_LOAD_ERROR;
+ }
+
+ Info = ShellGetFileInfo (FileHandle);
+
+ if (Info->Attribute & EFI_FILE_DIRECTORY) {
+ StatusBarSetStatusString (L"Directory Can Not Be Edited");
+ FreePool (Info);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ FileBuffer.ReadOnly = TRUE;
+ } else {
+ FileBuffer.ReadOnly = FALSE;
+ }
+
+ //
+ // get file size
+ //
+ FileSize = (UINTN)Info->FileSize;
+
+ FreePool (Info);
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // file not exists. add create and try again
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_WRITE_PROTECTED) ||
+ (Status == EFI_ACCESS_DENIED) ||
+ (Status == EFI_NO_MEDIA) ||
+ (Status == EFI_MEDIA_CHANGED)
+ )
+ {
+ StatusBarSetStatusString (L"Access Denied");
+ } else if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_VOLUME_CORRUPTED) || (Status == EFI_VOLUME_FULL)) {
+ StatusBarSetStatusString (L"Disk Error");
+ } else {
+ StatusBarSetStatusString (L"Invalid File Name or Current-working-directory");
+ }
+
+ return Status;
+ } else {
+ //
+ // it worked. now delete it and move on with the name (now validated)
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (Status == EFI_WARN_DELETE_FAILURE) {
+ Status = EFI_ACCESS_DENIED;
+ }
+
+ FileHandle = NULL;
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Access Denied");
+ return Status;
+ }
+ }
+
+ //
+ // file doesn't exist, so set CreateFile to TRUE
+ //
+ CreateFile = TRUE;
+ FileBuffer.ReadOnly = FALSE;
+
+ //
+ // all the check ends
+ // so now begin to set file name, free lines
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {
+ FileBufferSetFileName (FileName);
+ }
+
+ //
+ // free the old lines
+ //
+ FileBufferFree ();
+ }
+
+ //
+ // the file exists
+ //
+ if (!CreateFile) {
+ //
+ // allocate buffer to read file
+ //
+ Buffer = AllocateZeroPool (FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // read file into Buffer
+ //
+ Status = ShellReadFile (FileHandle, &FileSize, Buffer);
+ ShellCloseFile (&FileHandle);
+ FileHandle = NULL;
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read File Failed");
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // nothing in this file
+ //
+ if (FileSize == 0) {
+ SHELL_FREE_NON_NULL (Buffer);
+ //
+ // since has no head, so only can be an ASCII file
+ //
+ FileBuffer.FileType = FileTypeAscii;
+
+ goto Done;
+ }
+
+ AsciiBuffer = Buffer;
+
+ if (FileSize < 2) {
+ //
+ // size < Unicode file header, so only can be ASCII file
+ //
+ FileBuffer.FileType = FileTypeAscii;
+ } else {
+ //
+ // Unicode file
+ //
+ if (*(UINT16 *)Buffer == EFI_UNICODE_BYTE_ORDER_MARK) {
+ //
+ // Unicode file's size should be even
+ //
+ if ((FileSize % 2) != 0) {
+ StatusBarSetStatusString (L"File Format Wrong");
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_LOAD_ERROR;
+ }
+
+ FileSize /= 2;
+
+ FileBuffer.FileType = FileTypeUnicode;
+ UnicodeBuffer = Buffer;
+
+ //
+ // pass this 0xff and 0xfe
+ //
+ UnicodeBuffer++;
+ FileSize--;
+ } else {
+ FileBuffer.FileType = FileTypeAscii;
+ }
+
+ //
+ // end of AsciiBuffer ==
+ //
+ }
+
+ //
+ // end of FileSize < 2
+ // all the check ends
+ // so now begin to set file name, free lines
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {
+ FileBufferSetFileName (FileName);
+ }
+
+ //
+ // free the old lines
+ //
+ FileBufferFree ();
+
+ //
+ // parse file content line by line
+ //
+ for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) {
+ Type = NewLineTypeUnknown;
+
+ for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeCarriageReturn;
+
+ //
+ // has LF following
+ //
+ if (LineSize < FileSize - 1) {
+ if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) {
+ Type = NewLineTypeCarriageReturnLineFeed;
+ }
+ }
+
+ break;
+ } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) {
+ Type = NewLineTypeLineFeed;
+
+ //
+ // has CR following
+ //
+ if (LineSize < FileSize - 1) {
+ if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeLineFeedCarriageReturn;
+ }
+ }
+
+ break;
+ }
+ } else {
+ if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeCarriageReturn;
+
+ //
+ // has LF following
+ //
+ if (LineSize < FileSize - 1) {
+ if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) {
+ Type = NewLineTypeCarriageReturnLineFeed;
+ }
+ }
+
+ break;
+ } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) {
+ Type = NewLineTypeLineFeed;
+
+ //
+ // has CR following
+ //
+ if (LineSize < FileSize - 1) {
+ if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeLineFeedCarriageReturn;
+ }
+ }
+
+ break;
+ }
+ }
+
+ //
+ // endif == ASCII
+ //
+ }
+
+ //
+ // end of for LineSize
+ //
+ // if the type is wrong, then exit
+ //
+ if (Type == NewLineTypeUnknown) {
+ //
+ // Now if Type is NewLineTypeUnknown, it should be file end
+ //
+ Type = NewLineTypeDefault;
+ }
+
+ LineSizeBackup = LineSize;
+
+ //
+ // create a new line
+ //
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // calculate file length
+ //
+ LineSize -= LoopVar1;
+
+ //
+ // Unicode and one CHAR_NULL
+ //
+ SHELL_FREE_NON_NULL (Line->Buffer);
+ Line->Buffer = AllocateZeroPool (LineSize * 2 + 2);
+
+ if (Line->Buffer == NULL) {
+ RemoveEntryList (&Line->Link);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // copy this line to Line->Buffer
+ //
+ for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ Line->Buffer[LoopVar2] = (CHAR16)AsciiBuffer[LoopVar1];
+ } else {
+ Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1];
+ }
+
+ LoopVar1++;
+ }
+
+ //
+ // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
+ //
+ Line->Buffer[LineSize] = 0;
+
+ Line->Size = LineSize;
+ Line->TotalSize = LineSize;
+ Line->Type = Type;
+
+ if ((Type == NewLineTypeCarriageReturnLineFeed) || (Type == NewLineTypeLineFeedCarriageReturn)) {
+ LoopVar1++;
+ }
+
+ //
+ // last character is a return, SO create a new line
+ //
+ if ((((Type == NewLineTypeCarriageReturnLineFeed) || (Type == NewLineTypeLineFeedCarriageReturn)) && (LineSizeBackup == FileSize - 2)) ||
+ (((Type == NewLineTypeLineFeed) || (Type == NewLineTypeCarriageReturn)) && (LineSizeBackup == FileSize - 1))
+ )
+ {
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // end of if
+ //
+ }
+
+ //
+ // end of LoopVar1
+ //
+ SHELL_FREE_NON_NULL (Buffer);
+ }
+
+ //
+ // end of if CreateFile
+ //
+Done:
+
+ FileBuffer.DisplayPosition.Row = 2;
+ FileBuffer.DisplayPosition.Column = 1;
+ FileBuffer.LowVisibleRange.Row = 1;
+ FileBuffer.LowVisibleRange.Column = 1;
+ FileBuffer.FilePosition.Row = 1;
+ FileBuffer.FilePosition.Column = 1;
+ FileBuffer.MousePosition.Row = 2;
+ FileBuffer.MousePosition.Column = 1;
+
+ if (!Recover) {
+ UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines);
+ if (UnicodeBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (UnicodeBuffer);
+ FreePool (UnicodeBuffer);
+ }
+
+ /*
+ //
+ // check whether we have fs?: in filename
+ //
+ LoopVar1 = 0;
+ FSMappingPtr = NULL;
+ while (FileName[LoopVar1] != 0) {
+ if (FileName[LoopVar1] == L':') {
+ FSMappingPtr = &FileName[LoopVar1];
+ break;
+ }
+
+ LoopVar1++;
+ }
+
+ if (FSMappingPtr == NULL) {
+ CurDir = ShellGetCurrentDir (NULL);
+ } else {
+ LoopVar1 = 0;
+ LoopVar2 = 0;
+ while (FileName[LoopVar1] != 0) {
+ if (FileName[LoopVar1] == L':') {
+ break;
+ }
+
+ FSMapping[LoopVar2++] = FileName[LoopVar1];
+
+ LoopVar1++;
+ }
+
+ FSMapping[LoopVar2] = 0;
+ CurDir = ShellGetCurrentDir (FSMapping);
+ }
+
+ if (CurDir != NULL) {
+ for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
+
+ CurDir[LoopVar1] = 0;
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
+ FreePool (CurDir);
+ } else {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = LibDevicePathToInterface (
+ &gEfiSimpleFileSystemProtocolGuid,
+ DevicePath,
+ (VOID **) &Vol
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = Vol->OpenVolume (Vol, &RootFs);
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // Get volume information of file system
+ //
+ Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
+ VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
+ Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
+ if (EFI_ERROR (Status)) {
+ RootFs->Close (RootFs);
+ return EFI_LOAD_ERROR;
+ }
+
+ if (VolumeInfo->ReadOnly) {
+ StatusBarSetStatusString (L"WARNING: Volume Read Only");
+ }
+
+ FreePool (VolumeInfo);
+ RootFs->Close (RootFs);
+ }
+ //
+ */
+ //
+ // has line
+ //
+ if (FileBuffer.Lines != 0) {
+ FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileBuffer.CurrentLine = Line;
+ }
+
+ FileBuffer.FileModified = FALSE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+ FileBufferMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ According to FileBuffer.NewLineType & FileBuffer.FileType,
+ get the return buffer and size.
+
+ @param[in] Type The type of line.
+ @param[out] Buffer The buffer to fill.
+ @param[out] Size The amount of the buffer used on return.
+**/
+VOID
+GetNewLine (
+ IN CONST EE_NEWLINE_TYPE Type,
+ OUT CHAR8 *Buffer,
+ OUT UINT8 *Size
+ )
+{
+ UINT8 NewLineSize;
+
+ //
+ // give new line buffer,
+ // and will judge unicode or ascii
+ //
+ NewLineSize = 0;
+
+ //
+ // not legal new line type
+ //
+ if ((Type != NewLineTypeLineFeed) && (Type != NewLineTypeCarriageReturn) && (Type != NewLineTypeCarriageReturnLineFeed) && (Type != NewLineTypeLineFeedCarriageReturn)) {
+ *Size = 0;
+ return;
+ }
+
+ //
+ // use_cr: give 0x0d
+ //
+ if (Type == NewLineTypeCarriageReturn) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0;
+ NewLineSize = 2;
+ } else {
+ Buffer[0] = 0x0d;
+ NewLineSize = 1;
+ }
+
+ *Size = NewLineSize;
+ return;
+ }
+
+ //
+ // use_lf: give 0x0a
+ //
+ if (Type == NewLineTypeLineFeed) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0;
+ NewLineSize = 2;
+ } else {
+ Buffer[0] = 0x0a;
+ NewLineSize = 1;
+ }
+
+ *Size = NewLineSize;
+ return;
+ }
+
+ //
+ // use_crlf: give 0x0d 0x0a
+ //
+ if (Type == NewLineTypeCarriageReturnLineFeed) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0;
+ Buffer[2] = 0x0a;
+ Buffer[3] = 0;
+
+ NewLineSize = 4;
+ } else {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0x0a;
+ NewLineSize = 2;
+ }
+
+ *Size = NewLineSize;
+ return;
+ }
+
+ //
+ // use_lfcr: give 0x0a 0x0d
+ //
+ if (Type == NewLineTypeLineFeedCarriageReturn) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0;
+ Buffer[2] = 0x0d;
+ Buffer[3] = 0;
+
+ NewLineSize = 4;
+ } else {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0x0d;
+ NewLineSize = 2;
+ }
+
+ *Size = NewLineSize;
+ return;
+ }
+}
+
+/**
+ Change a Unicode string to an ASCII string.
+
+ @param[in] UStr The Unicode string.
+ @param[in] Length The maximum size of AStr.
+ @param[out] AStr ASCII string to pass out.
+
+ @return The actuall length.
+**/
+UINTN
+UnicodeToAscii (
+ IN CONST CHAR16 *UStr,
+ IN CONST UINTN Length,
+ OUT CHAR8 *AStr
+ )
+{
+ UINTN Index;
+
+ //
+ // just buffer copy, not character copy
+ //
+ for (Index = 0; Index < Length; Index++) {
+ *AStr++ = (CHAR8)*UStr++;
+ }
+
+ return Index;
+}
+
+/**
+ Save lines in FileBuffer to disk
+
+ @param[in] FileName The file name for writing.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_LOAD_ERROR
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
+**/
+EFI_STATUS
+FileBufferSave (
+ IN CONST CHAR16 *FileName
+ )
+{
+ SHELL_FILE_HANDLE FileHandle;
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 *Str;
+
+ EFI_STATUS Status;
+ UINTN Length;
+ UINTN NumLines;
+ CHAR8 NewLineBuffer[4];
+ UINT8 NewLineSize;
+
+ EFI_FILE_INFO *Info;
+
+ UINT64 Attribute;
+
+ EE_NEWLINE_TYPE Type;
+
+ UINTN TotalSize;
+ //
+ // 2M
+ //
+ CHAR8 *Cache;
+ UINTN LeftSize;
+ UINTN Size;
+ CHAR8 *Ptr;
+
+ Length = 0;
+ //
+ // 2M
+ //
+ TotalSize = 0x200000;
+
+ Attribute = 0;
+
+ //
+ // if is the old file
+ //
+ if ((FileBuffer.FileName != NULL) && (StrCmp (FileName, FileBuffer.FileName) == 0)) {
+ //
+ // file has not been modified
+ //
+ if (!FileBuffer.FileModified) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if file is read-only, set error
+ //
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+
+ if (!EFI_ERROR (Status)) {
+ Info = ShellGetFileInfo (FileHandle);
+
+ if ((Info != NULL) && Info->Attribute & EFI_FILE_DIRECTORY) {
+ StatusBarSetStatusString (L"Directory Can Not Be Saved");
+ ShellCloseFile (&FileHandle);
+ FreePool (Info);
+ return EFI_LOAD_ERROR;
+ }
+
+ if (Info != NULL) {
+ Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY;
+ FreePool (Info);
+ }
+
+ //
+ // if file exits, so delete it
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (EFI_ERROR (Status) || (Status == EFI_WARN_DELETE_FAILURE)) {
+ StatusBarSetStatusString (L"Write File Failed");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Create File Failed");
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // if file is Unicode file, write Unicode header to it.
+ //
+ if (FileBuffer.FileType == FileTypeUnicode) {
+ Length = 2;
+ Status = ShellWriteFile (FileHandle, &Length, (VOID *)&gUnicodeFileTag);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Cache = AllocateZeroPool (TotalSize);
+ if (Cache == NULL) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // write all the lines back to disk
+ //
+ NumLines = 0;
+ Type = NewLineTypeCarriageReturnLineFeed;
+
+ Ptr = Cache;
+ LeftSize = TotalSize;
+
+ for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ if (Line->Type != NewLineTypeDefault) {
+ Type = Line->Type;
+ }
+
+ //
+ // newline character is at most 4 bytes ( two Unicode characters )
+ //
+ Length = 4;
+ if ((Line->Buffer != NULL) && (Line->Size != 0)) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ Length += Line->Size;
+ } else {
+ Length += (Line->Size * 2);
+ }
+
+ //
+ // end if FileTypeAscii
+ //
+ }
+
+ //
+ // no cache room left, so write cache to disk
+ //
+ if (LeftSize < Length) {
+ Size = TotalSize - LeftSize;
+ Status = ShellWriteFile (FileHandle, &Size, Cache);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ FreePool (Cache);
+ return EFI_LOAD_ERROR;
+ }
+
+ Ptr = Cache;
+ LeftSize = TotalSize;
+ }
+
+ if ((Line->Buffer != NULL) && (Line->Size != 0)) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ UnicodeToAscii (Line->Buffer, Line->Size, Ptr);
+ Length = Line->Size;
+ } else {
+ Length = (Line->Size * 2);
+ CopyMem (Ptr, (CHAR8 *)Line->Buffer, Length);
+ }
+
+ //
+ // end if FileTypeAscii
+ //
+ Ptr += Length;
+ LeftSize -= Length;
+ }
+
+ //
+ // end of if Line -> Buffer != NULL && Line -> Size != 0
+ //
+ // if not the last line , write return buffer to disk
+ //
+ if (Link->ForwardLink != FileBuffer.ListHead) {
+ GetNewLine (Type, NewLineBuffer, &NewLineSize);
+ CopyMem (Ptr, (CHAR8 *)NewLineBuffer, NewLineSize);
+
+ Ptr += NewLineSize;
+ LeftSize -= NewLineSize;
+ }
+
+ NumLines++;
+ }
+
+ if (TotalSize != LeftSize) {
+ Size = TotalSize - LeftSize;
+ Status = ShellWriteFile (FileHandle, &Size, Cache);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ FreePool (Cache);
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ FreePool (Cache);
+
+ ShellCloseFile (&FileHandle);
+
+ FileBuffer.FileModified = FALSE;
+
+ //
+ // set status string
+ //
+ Str = CatSPrint (NULL, L"%d Lines Written", NumLines);
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (Str);
+ SHELL_FREE_NON_NULL (Str);
+
+ //
+ // now everything is ready , you can set the new file name to filebuffer
+ //
+ if ((FileName != NULL) && (FileBuffer.FileName != NULL) && (StrCmp (FileName, FileBuffer.FileName) != 0)) {
+ //
+ // not the same
+ //
+ FileBufferSetFileName (FileName);
+ if (FileBuffer.FileName == NULL) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ FileBuffer.ReadOnly = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to left 1 character position.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferScrollLeft (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.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 != FileBuffer.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ FCol = Line->Size + 1;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at start of this line, just move to previous column
+ //
+ FCol--;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete a char in line
+
+ @param[in, out] Line The line to delete in.
+ @param[in] Pos Position to delete the char at ( start from 0 ).
+**/
+VOID
+LineDeleteAt (
+ IN OUT EFI_EDITOR_LINE *Line,
+ IN UINTN Pos
+ )
+{
+ UINTN Index;
+
+ //
+ // move the latter characters front
+ //
+ for (Index = Pos - 1; Index < Line->Size; Index++) {
+ Line->Buffer[Index] = Line->Buffer[Index + 1];
+ }
+
+ Line->Size--;
+}
+
+/**
+ Concatenate Src into Dest.
+
+ @param[in, out] Dest Destination string
+ @param[in] Src Src String.
+**/
+VOID
+LineCat (
+ IN OUT EFI_EDITOR_LINE *Dest,
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ CHAR16 *Str;
+ UINTN Size;
+
+ Size = Dest->Size;
+
+ Dest->Buffer[Size] = 0;
+
+ //
+ // concatenate the two strings
+ //
+ Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer);
+ if (Str == NULL) {
+ Dest->Buffer = NULL;
+ return;
+ }
+
+ Dest->Size = Size + Src->Size;
+ Dest->TotalSize = Dest->Size;
+
+ FreePool (Dest->Buffer);
+ FreePool (Src->Buffer);
+
+ //
+ // put str to dest->buffer
+ //
+ Dest->Buffer = Str;
+}
+
+/**
+ Delete the previous character.
+
+ @retval EFI_SUCCESS The delete was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferDoBackspace (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *End;
+ LIST_ENTRY *Link;
+ UINTN FileColumn;
+
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // the first column
+ //
+ if (FileColumn == 1) {
+ //
+ // the first row
+ //
+ if (FileBuffer.FilePosition.Row == 1) {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferScrollLeft ();
+
+ Line = FileBuffer.CurrentLine;
+ Link = Line->Link.ForwardLink;
+ End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // concatenate this line with previous line
+ //
+ LineCat (Line, End);
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // remove End from line list
+ //
+ RemoveEntryList (&End->Link);
+ FreePool (End);
+
+ FileBuffer.NumLines--;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+ } else {
+ //
+ // just delete the previous character
+ //
+ LineDeleteAt (Line, FileColumn - 1);
+ FileBufferScrollLeft ();
+ FileBufferOnlyLineNeedRefresh = TRUE;
+ }
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add a return into line at current position.
+
+ @retval EFI_SUCCESS The insetrion of the character was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferDoReturn (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN FileColumn;
+ UINTN Index;
+ CHAR16 *Buffer;
+ UINTN Row;
+ UINTN Col;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ Line = FileBuffer.CurrentLine;
+
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLine->Signature = LINE_LIST_SIGNATURE;
+ NewLine->Size = Line->Size - FileColumn + 1;
+ NewLine->TotalSize = NewLine->Size;
+ NewLine->Buffer = CatSPrint (NULL, L"\0");
+ if (NewLine->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLine->Type = NewLineTypeDefault;
+
+ if (NewLine->Size > 0) {
+ //
+ // UNICODE + CHAR_NULL
+ //
+ Buffer = AllocateZeroPool (2 * (NewLine->Size + 1));
+ if (Buffer == NULL) {
+ FreePool (NewLine->Buffer);
+ FreePool (NewLine);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FreePool (NewLine->Buffer);
+
+ NewLine->Buffer = Buffer;
+
+ for (Index = 0; Index < NewLine->Size; Index++) {
+ NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1];
+ }
+
+ NewLine->Buffer[NewLine->Size] = CHAR_NULL;
+
+ Line->Buffer[FileColumn - 1] = CHAR_NULL;
+ Line->Size = FileColumn - 1;
+ }
+
+ //
+ // increase NumLines
+ //
+ FileBuffer.NumLines++;
+
+ //
+ // insert it into the correct position of line list
+ //
+ NewLine->Link.BackLink = &(Line->Link);
+ NewLine->Link.ForwardLink = Line->Link.ForwardLink;
+ Line->Link.ForwardLink->BackLink = &(NewLine->Link);
+ Line->Link.ForwardLink = &(NewLine->Link);
+
+ //
+ // move cursor to the start of next line
+ //
+ Row = FileBuffer.FilePosition.Row + 1;
+ Col = 1;
+
+ FileBufferMovePosition (Row, Col);
+
+ //
+ // set file is modified
+ //
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete current character from current line. This is the effect caused
+ by the 'del' key.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+FileBufferDoDelete (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *Next;
+ LIST_ENTRY *Link;
+ UINTN FileColumn;
+
+ Line = FileBuffer.CurrentLine;
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ //
+ // the last column
+ //
+ if (FileColumn >= Line->Size + 1) {
+ //
+ // the last line
+ //
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // since last character,
+ // so will add the next line to this line
+ //
+ Link = Line->Link.ForwardLink;
+ Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ LineCat (Line, Next);
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RemoveEntryList (&Next->Link);
+ FreePool (Next);
+
+ FileBuffer.NumLines--;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+ } else {
+ //
+ // just delete current character
+ //
+ LineDeleteAt (Line, FileColumn);
+ FileBufferOnlyLineNeedRefresh = TRUE;
+ }
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to right 1 character.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferScrollRight (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+ if (Line->Buffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // if already at end of this line, scroll it to the start of next line
+ //
+ if (FCol > Line->Size) {
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {
+ FRow++;
+ FCol = 1;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at end of this line, just move to next column
+ //
+ FCol++;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Insert a char into line
+
+
+ @param[in] Line The line to insert into.
+ @param[in] Char The char to insert.
+ @param[in] Pos The position to insert the char at ( start from 0 ).
+ @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
+
+ @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
+**/
+UINTN
+LineStrInsert (
+ IN EFI_EDITOR_LINE *Line,
+ IN CHAR16 Char,
+ IN UINTN Pos,
+ IN UINTN StrSize
+ )
+{
+ UINTN Index;
+ CHAR16 *TempStringPtr;
+ CHAR16 *Str;
+
+ Index = (StrSize) * 2;
+
+ Str = Line->Buffer;
+
+ //
+ // do not have free space
+ //
+ if (Line->TotalSize <= Line->Size) {
+ Str = ReallocatePool (Index, Index + 16, Str);
+ if (Str == NULL) {
+ return 0;
+ }
+
+ Line->TotalSize += 8;
+ }
+
+ //
+ // move the later part of the string one character right
+ //
+ TempStringPtr = Str;
+ for (Index = StrSize; Index > Pos; Index--) {
+ TempStringPtr[Index] = TempStringPtr[Index - 1];
+ }
+
+ //
+ // insert char into it.
+ //
+ TempStringPtr[Index] = Char;
+
+ Line->Buffer = Str;
+ Line->Size++;
+
+ return StrSize + 1;
+}
+
+/**
+ Add a character to the current line.
+
+ @param[in] Char The Character to input.
+
+ @retval EFI_SUCCESS The input was succesful.
+**/
+EFI_STATUS
+FileBufferAddChar (
+ IN CHAR16 Char
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FilePos;
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // only needs to refresh current line
+ //
+ FileBufferOnlyLineNeedRefresh = TRUE;
+
+ //
+ // when is insert mode, or cursor is at end of this line,
+ // so insert this character
+ // or replace the character.
+ //
+ FilePos = FileBuffer.FilePosition.Column - 1;
+ if (FileBuffer.ModeInsert || (FilePos + 1 > Line->Size)) {
+ LineStrInsert (Line, Char, FilePos, Line->Size + 1);
+ } else {
+ Line->Buffer[FilePos] = Char;
+ }
+
+ //
+ // move cursor to right
+ //
+ FileBufferScrollRight ();
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Handles inputs from characters (ASCII key + Backspace + return)
+
+ @param[in] Char The input character.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR There was an error.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferDoCharInput (
+ IN CONST CHAR16 Char
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Char) {
+ case CHAR_NULL:
+ break;
+
+ case CHAR_BACKSPACE:
+ Status = FileBufferDoBackspace ();
+ break;
+
+ case CHAR_TAB:
+ //
+ // Tabs are ignored
+ //
+ break;
+
+ case CHAR_LINEFEED:
+ case CHAR_CARRIAGE_RETURN:
+ Status = FileBufferDoReturn ();
+ break;
+
+ default:
+ //
+ // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
+ //
+ if ((Char > 127) || (Char < 32)) {
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ } else {
+ Status = FileBufferAddChar (Char);
+ }
+
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Scroll cursor to the next line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferScrollDown (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+ if (Line->Buffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {
+ FRow++;
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // if the next line is not that long, so move to end of next line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll the cursor to previous line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferScrollUp (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != FileBuffer.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // if previous line is not that long, so move to the end of previous line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to next page.
+
+ @retval EFI_SUCCESS The operation wa successful.
+**/
+EFI_STATUS
+FileBufferPageDown (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has next page
+ //
+ if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 2)) {
+ Gap = (MainEditor.ScreenSize.Row - 2);
+ } else {
+ //
+ // MOVE CURSOR TO LAST LINE
+ //
+ Gap = FileBuffer.NumLines - FRow;
+ }
+
+ //
+ // get correct line
+ //
+ Line = MoveLine (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;
+ }
+
+ FRow += Gap;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to previous screen.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferPageUp (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+ INTN Retreat;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has previous page
+ //
+ if (FRow > (MainEditor.ScreenSize.Row - 2)) {
+ Gap = (MainEditor.ScreenSize.Row - 2);
+ } else {
+ //
+ // the first line of file will displayed on the first line of screen
+ //
+ Gap = FRow - 1;
+ }
+
+ Retreat = Gap;
+ Retreat = -Retreat;
+
+ //
+ // get correct line
+ //
+ Line = MoveLine (Retreat);
+
+ //
+ // 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;
+ }
+
+ FRow -= Gap;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to end of the current line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferEnd (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+
+ //
+ // goto the last column of the line
+ //
+ FCol = Line->Size + 1;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Dispatch input to different handler
+ @param[in] Key The input key. One of:
+ ASCII KEY
+ Backspace/Delete
+ Return
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The dispatch was done successfully.
+ @retval EFI_LOAD_ERROR The dispatch was not successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferHandleInput (
+ IN CONST EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Key->ScanCode) {
+ //
+ // ordinary key input
+ //
+ case SCAN_NULL:
+ if (!FileBuffer.ReadOnly) {
+ Status = FileBufferDoCharInput (Key->UnicodeChar);
+ } else {
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ }
+
+ break;
+
+ //
+ // up arrow
+ //
+ case SCAN_UP:
+ Status = FileBufferScrollUp ();
+ break;
+
+ //
+ // down arrow
+ //
+ case SCAN_DOWN:
+ Status = FileBufferScrollDown ();
+ break;
+
+ //
+ // right arrow
+ //
+ case SCAN_RIGHT:
+ Status = FileBufferScrollRight ();
+ break;
+
+ //
+ // left arrow
+ //
+ case SCAN_LEFT:
+ Status = FileBufferScrollLeft ();
+ break;
+
+ //
+ // page up
+ //
+ case SCAN_PAGE_UP:
+ Status = FileBufferPageUp ();
+ break;
+
+ //
+ // page down
+ //
+ case SCAN_PAGE_DOWN:
+ Status = FileBufferPageDown ();
+ break;
+
+ //
+ // delete
+ //
+ case SCAN_DELETE:
+ if (!FileBuffer.ReadOnly) {
+ Status = FileBufferDoDelete ();
+ } else {
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ }
+
+ break;
+
+ //
+ // home
+ //
+ case SCAN_HOME:
+ FileBufferMovePosition (FileBuffer.FilePosition.Row, 1);
+ Status = EFI_SUCCESS;
+ break;
+
+ //
+ // end
+ //
+ case SCAN_END:
+ Status = FileBufferEnd ();
+ break;
+
+ //
+ // insert
+ //
+ case SCAN_INSERT:
+ FileBuffer.ModeInsert = (BOOLEAN) !FileBuffer.ModeInsert;
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Check user specified FileRow is above current screen.
+
+ @param[in] FileRow The 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
+AboveCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ //
+ // if is to the above of the screen
+ //
+ if (FileRow < FileBuffer.LowVisibleRange.Row) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileRow is under current screen.
+
+ @param[in] FileRow The 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
+UnderCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ //
+ // if is to the under of the screen
+ //
+ if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 2) - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileCol is left to current screen.
+
+ @param[in] FileCol The column of file position ( start from 1 ).
+
+ @retval TRUE It is to the left.
+ @retval FALSE It is not to the left.
+**/
+BOOLEAN
+LeftCurrentScreen (
+ IN UINTN FileCol
+ )
+{
+ //
+ // if is to the left of the screen
+ //
+ if (FileCol < FileBuffer.LowVisibleRange.Column) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileCol is right to current screen.
+
+ @param[in] FileCol The column of file position ( start from 1 ).
+
+ @retval TRUE It is to the right.
+ @retval FALSE It is not to the right.
+**/
+BOOLEAN
+RightCurrentScreen (
+ IN UINTN FileCol
+ )
+{
+ //
+ // if is to the right of the screen
+ //
+ if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Advance/Retreat lines and set CurrentLine in FileBuffer to it
+
+ @param[in] Count The line number to advance/retreat
+ >0 : advance
+ <0: retreat
+
+ @retval NULL An error occurred.
+ @return The line after advance/retreat.
+**/
+EFI_EDITOR_LINE *
+MoveCurrentLine (
+ IN INTN Count
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ if (Count <= 0) {
+ AbsCount = (UINTN)ABS (Count);
+ Line = InternalEditorMiscLineRetreat (AbsCount, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
+ } else {
+ Line = InternalEditorMiscLineAdvance ((UINTN)Count, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
+ }
+
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ MainEditor.FileBuffer->CurrentLine = Line;
+
+ return Line;
+}
+
+/**
+ According to cursor's file position, adjust screen display
+
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).
+**/
+VOID
+FileBufferMovePosition (
+ IN CONST UINTN NewFilePosRow,
+ IN CONST UINTN NewFilePosCol
+ )
+{
+ INTN RowGap;
+ INTN ColGap;
+ UINTN Abs;
+ BOOLEAN Above;
+ BOOLEAN Under;
+ BOOLEAN Right;
+ BOOLEAN Left;
+
+ //
+ // CALCULATE gap between current file position and new file position
+ //
+ RowGap = NewFilePosRow - FileBuffer.FilePosition.Row;
+ ColGap = NewFilePosCol - FileBuffer.FilePosition.Column;
+
+ Under = UnderCurrentScreen (NewFilePosRow);
+ Above = AboveCurrentScreen (NewFilePosRow);
+ //
+ // if is below current screen
+ //
+ if (Under) {
+ //
+ // display row will be unchanged
+ //
+ FileBuffer.FilePosition.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 < (FileBuffer.DisplayPosition.Row - 1)) {
+ FileBuffer.DisplayPosition.Row = NewFilePosRow + 1;
+ }
+
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ } else {
+ //
+ // in current screen
+ //
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ if (RowGap < 0) {
+ Abs = (UINTN)ABS (RowGap);
+ FileBuffer.DisplayPosition.Row -= Abs;
+ } else {
+ FileBuffer.DisplayPosition.Row += RowGap;
+ }
+ }
+ }
+
+ FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2);
+
+ Right = RightCurrentScreen (NewFilePosCol);
+ Left = LeftCurrentScreen (NewFilePosCol);
+
+ //
+ // if right to current screen
+ //
+ if (Right) {
+ //
+ // display column will be changed to end
+ //
+ FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column;
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ } else {
+ if (Left) {
+ //
+ // has enough left characters , so display row unchanged
+ // not has enough left characters,
+ // so the first character is at the first display column
+ //
+ if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) {
+ FileBuffer.DisplayPosition.Column = NewFilePosCol;
+ }
+
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ } else {
+ //
+ // in current screen
+ //
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ if (ColGap < 0) {
+ Abs = (UINTN)(-ColGap);
+ FileBuffer.DisplayPosition.Column -= Abs;
+ } else {
+ FileBuffer.DisplayPosition.Column += ColGap;
+ }
+ }
+ }
+
+ FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1);
+
+ //
+ // let CurrentLine point to correct line;
+ //
+ FileBuffer.CurrentLine = MoveCurrentLine (RowGap);
+}
+
+/**
+ Cut current line out and return a pointer to it.
+
+ @param[out] CutLine Upon a successful return pointer to the pointer to
+ the allocated cut line.
+
+ @retval EFI_SUCCESS The cut was successful.
+ @retval EFI_NOT_FOUND There was no selection to cut.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferCutLine (
+ OUT EFI_EDITOR_LINE **CutLine
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN Row;
+ UINTN Col;
+
+ *CutLine = NULL;
+
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // if is the last dummy line, SO CAN not cut
+ //
+ if ((StrCmp (Line->Buffer, L"\0") == 0) && (Line->Link.ForwardLink == FileBuffer.ListHead)
+ //
+ // last line
+ //
+ )
+ {
+ //
+ // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
+ //
+ StatusBarSetStatusString (L"Nothing to Cut");
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // if is the last line, so create a dummy line
+ //
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {
+ //
+ // last line
+ // create a new line
+ //
+ NewLine = FileBufferCreateLine ();
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ FileBuffer.NumLines--;
+ Row = FileBuffer.FilePosition.Row;
+ Col = 1;
+ //
+ // move home
+ //
+ FileBuffer.CurrentLine = CR (
+ FileBuffer.CurrentLine->Link.ForwardLink,
+ EFI_EDITOR_LINE,
+ Link,
+ LINE_LIST_SIGNATURE
+ );
+
+ RemoveEntryList (&Line->Link);
+
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ FileBufferMovePosition (Row, Col);
+
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ *CutLine = Line;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Paste a line into line list.
+
+ @retval EFI_SUCCESS The paste was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferPasteLine (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN Row;
+ UINTN Col;
+
+ //
+ // if nothing is on clip board
+ // then do nothing
+ //
+ if (MainEditor.CutLine == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // read only file can not be pasted on
+ //
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ NewLine = LineDup (MainEditor.CutLine);
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // insert it above current line
+ //
+ Line = FileBuffer.CurrentLine;
+ NewLine->Link.BackLink = Line->Link.BackLink;
+ NewLine->Link.ForwardLink = &Line->Link;
+
+ Line->Link.BackLink->ForwardLink = &NewLine->Link;
+ Line->Link.BackLink = &NewLine->Link;
+
+ FileBuffer.NumLines++;
+ FileBuffer.CurrentLine = NewLine;
+
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ Col = 1;
+ //
+ // move home
+ //
+ Row = FileBuffer.FilePosition.Row;
+
+ FileBufferMovePosition (Row, Col);
+
+ //
+ // after paste, set some value so that refresh knows to do something
+ //
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search string from current position on in file
+
+ @param[in] Str The search string.
+ @param[in] Offset The offset from current position.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND The string Str was not found.
+**/
+EFI_STATUS
+FileBufferSearch (
+ IN CONST CHAR16 *Str,
+ IN CONST UINTN Offset
+ )
+{
+ CHAR16 *Current;
+ UINTN Position;
+ UINTN Row;
+ UINTN Column;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 *CharPos;
+ LIST_ENTRY *Link;
+ BOOLEAN Found;
+
+ Column = 0;
+ Position = 0;
+
+ //
+ // search if in current line
+ //
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset;
+
+ if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) {
+ //
+ // the end
+ //
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size;
+ }
+
+ Found = FALSE;
+
+ CharPos = StrStr (Current, Str);
+ if (CharPos != NULL) {
+ Position = CharPos - Current + 1;
+ Found = TRUE;
+ }
+
+ //
+ // found
+ //
+ if (Found) {
+ Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset;
+ Row = FileBuffer.FilePosition.Row;
+ } else {
+ //
+ // not found so find through next lines
+ //
+ Link = FileBuffer.CurrentLine->Link.ForwardLink;
+
+ Row = FileBuffer.FilePosition.Row + 1;
+ while (Link != FileBuffer.ListHead) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ // Position = StrStr (Line->Buffer, Str);
+ CharPos = StrStr (Line->Buffer, Str);
+ if (CharPos != NULL) {
+ Position = CharPos - Line->Buffer + 1;
+ Found = TRUE;
+ }
+
+ if (Found) {
+ //
+ // found
+ //
+ Column = Position;
+ break;
+ }
+
+ Row++;
+ Link = Link->ForwardLink;
+ }
+
+ if (Link == FileBuffer.ListHead) {
+ Found = FALSE;
+ } else {
+ Found = TRUE;
+ }
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ FileBufferMovePosition (Row, Column);
+
+ //
+ // call refresh to fresh edit area,
+ // because the outer may loop to find multiply occurrence of this string
+ //
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Replace SearchLen characters from current position on with Replace.
+
+ This will modify the current buffer at the current position.
+
+ @param[in] Replace The string to replace.
+ @param[in] SearchLen Search string's length.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferReplace (
+ IN CONST CHAR16 *Replace,
+ IN CONST UINTN SearchLen
+ )
+{
+ UINTN ReplaceLen;
+ UINTN Index;
+ CHAR16 *Buffer;
+ UINTN NewSize;
+ UINTN OldSize;
+ UINTN Gap;
+
+ ReplaceLen = StrLen (Replace);
+
+ OldSize = FileBuffer.CurrentLine->Size + 1;
+ //
+ // include CHAR_NULL
+ //
+ NewSize = OldSize + (ReplaceLen - SearchLen);
+
+ if (ReplaceLen > SearchLen) {
+ //
+ // do not have the enough space
+ //
+ if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) {
+ FileBuffer.CurrentLine->Buffer = ReallocatePool (
+ 2 * OldSize,
+ 2 * NewSize,
+ FileBuffer.CurrentLine->Buffer
+ );
+ FileBuffer.CurrentLine->TotalSize = NewSize - 1;
+ }
+
+ if (FileBuffer.CurrentLine->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // the end CHAR_NULL character;
+ //
+ Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1);
+ Gap = ReplaceLen - SearchLen;
+
+ //
+ // keep the latter part
+ //
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) {
+ *Buffer = *(Buffer - Gap);
+ Buffer--;
+ }
+
+ //
+ // set replace into it
+ //
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+ }
+
+ if (ReplaceLen < SearchLen) {
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
+
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+
+ Buffer += ReplaceLen;
+ Gap = SearchLen - ReplaceLen;
+
+ //
+ // set replace into it
+ //
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) {
+ *Buffer = *(Buffer + Gap);
+ Buffer++;
+ }
+ }
+
+ if (ReplaceLen == SearchLen) {
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+ }
+
+ FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen);
+
+ FileBufferOnlyLineNeedRefresh = TRUE;
+
+ FileBuffer.FileModified = TRUE;
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
+ FileBufferRestorePosition ();
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Move the mouse cursor position.
+
+ @param[in] TextX The new x-coordinate.
+ @param[in] TextY The new y-coordinate.
+**/
+VOID
+FileBufferAdjustMousePosition (
+ IN CONST INT32 TextX,
+ IN CONST INT32 TextY
+ )
+{
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ UINTN AbsX;
+ UINTN AbsY;
+
+ //
+ // TextX and TextY is mouse movement data returned by mouse driver
+ // This function will change it to MousePosition
+ //
+ //
+ // get absolute value
+ //
+
+ AbsX = ABS (TextX);
+ AbsY = ABS (TextY);
+
+ CoordinateX = FileBuffer.MousePosition.Column;
+ CoordinateY = FileBuffer.MousePosition.Row;
+
+ if (TextX >= 0) {
+ CoordinateX += TextX;
+ } else {
+ if (CoordinateX >= AbsX) {
+ CoordinateX -= AbsX;
+ } else {
+ CoordinateX = 0;
+ }
+ }
+
+ if (TextY >= 0) {
+ CoordinateY += TextY;
+ } else {
+ if (CoordinateY >= AbsY) {
+ CoordinateY -= AbsY;
+ } else {
+ CoordinateY = 0;
+ }
+ }
+
+ //
+ // check whether new mouse column position is beyond screen
+ // if not, adjust it
+ //
+ if ((CoordinateX >= 1) && (CoordinateX <= MainEditor.ScreenSize.Column)) {
+ FileBuffer.MousePosition.Column = CoordinateX;
+ } else if (CoordinateX < 1) {
+ FileBuffer.MousePosition.Column = 1;
+ } else if (CoordinateX > MainEditor.ScreenSize.Column) {
+ FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column;
+ }
+
+ //
+ // check whether new mouse row position is beyond screen
+ // if not, adjust it
+ //
+ if ((CoordinateY >= 2) && (CoordinateY <= (MainEditor.ScreenSize.Row - 1))) {
+ FileBuffer.MousePosition.Row = CoordinateY;
+ } else if (CoordinateY < 2) {
+ FileBuffer.MousePosition.Row = 2;
+ } else if (CoordinateY > (MainEditor.ScreenSize.Row - 1)) {
+ FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 1);
+ }
+}
+
+/**
+ Search and replace operation.
+
+ @param[in] SearchStr The string to search for.
+ @param[in] ReplaceStr The string to replace with.
+ @param[in] Offset The column to start at.
+**/
+EFI_STATUS
+FileBufferReplaceAll (
+ IN CHAR16 *SearchStr,
+ IN CHAR16 *ReplaceStr,
+ IN UINTN Offset
+ )
+{
+ CHAR16 *Buffer;
+ UINTN Position;
+ UINTN Column;
+ UINTN ReplaceLen;
+ UINTN SearchLen;
+ UINTN Index;
+ UINTN NewSize;
+ UINTN OldSize;
+ UINTN Gap;
+ EFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+ CHAR16 *CharPos;
+
+ SearchLen = StrLen (SearchStr);
+ ReplaceLen = StrLen (ReplaceStr);
+
+ Column = FileBuffer.FilePosition.Column + Offset - 1;
+
+ if (Column > FileBuffer.CurrentLine->Size) {
+ Column = FileBuffer.CurrentLine->Size;
+ }
+
+ Link = &(FileBuffer.CurrentLine->Link);
+
+ while (Link != FileBuffer.ListHead) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ CharPos = StrStr (Line->Buffer + Column, SearchStr);
+ if (CharPos != NULL) {
+ Position = CharPos - Line->Buffer;// + Column;
+ //
+ // found
+ //
+ if (ReplaceLen > SearchLen) {
+ OldSize = Line->Size + 1;
+ //
+ // include CHAR_NULL
+ //
+ NewSize = OldSize + (ReplaceLen - SearchLen);
+
+ //
+ // do not have the enough space
+ //
+ if (Line->TotalSize + 1 <= NewSize) {
+ Line->Buffer = ReallocatePool (
+ 2 * OldSize,
+ 2 * NewSize,
+ Line->Buffer
+ );
+ Line->TotalSize = NewSize - 1;
+ }
+
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // the end CHAR_NULL character;
+ //
+ Buffer = Line->Buffer + (NewSize - 1);
+ Gap = ReplaceLen - SearchLen;
+
+ //
+ // keep the latter part
+ //
+ for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) {
+ *Buffer = *(Buffer - Gap);
+ Buffer--;
+ }
+ } else if (ReplaceLen < SearchLen) {
+ Buffer = Line->Buffer + Position + ReplaceLen;
+ Gap = SearchLen - ReplaceLen;
+
+ for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) {
+ *Buffer = *(Buffer + Gap);
+ Buffer++;
+ }
+ } else {
+ ASSERT (ReplaceLen == SearchLen);
+ }
+
+ //
+ // set replace into it
+ //
+ Buffer = Line->Buffer + Position;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = ReplaceStr[Index];
+ }
+
+ Line->Size += (ReplaceLen - SearchLen);
+ Column += ReplaceLen;
+ } else {
+ //
+ // not found
+ //
+ Column = 0;
+ Link = Link->ForwardLink;
+ }
+ }
+
+ //
+ // call refresh to fresh edit area
+ //
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the modified state to TRUE.
+**/
+VOID
+FileBufferSetModified (
+ VOID
+ )
+{
+ FileBuffer.FileModified = TRUE;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h
index 7a33269eee..f398b94029 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h
@@ -1,240 +1,240 @@
-/** @file
- Declares filebuffer interface functions.
-
- Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _LIB_FILE_BUFFER_H_
-#define _LIB_FILE_BUFFER_H_
-
-#include "TextEditorTypes.h"
-
-/**
- Initialization function for FileBuffer.
-
- @param EFI_SUCCESS The initialization was successful.
- @param EFI_LOAD_ERROR A default name could not be created.
- @param EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferInit (
- VOID
- );
-
-/**
- Cleanup function for FileBuffer.
-
- @retval EFI_SUCCESS The cleanup was successful.
-**/
-EFI_STATUS
-FileBufferCleanup (
- VOID
- );
-
-/**
- Refresh the screen with whats in the buffer.
-
- @retval EFI_SUCCESS The refresh was successful.
- @retval EFI_LOAD_ERROR There was an error finding what to write.
-**/
-EFI_STATUS
-FileBufferRefresh (
- VOID
- );
-
-/**
- Dispatch input to different handler
- @param[in] Key The input key. One of:
- ASCII KEY
- Backspace/Delete
- Return
- Direction key: up/down/left/right/pgup/pgdn
- Home/End
- INS
-
- @retval EFI_SUCCESS The dispatch was done successfully.
- @retval EFI_LOAD_ERROR The dispatch was not successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferHandleInput (
- IN CONST EFI_INPUT_KEY *Key
- );
-
-/**
- Backup function for FileBuffer. Only backup the following items:
- Mouse/Cursor position
- File Name, Type, ReadOnly, Modified
- Insert Mode
-
- This is for making the file buffer refresh as few as possible.
-
- @retval EFI_SUCCESS The backup operation was successful.
-**/
-EFI_STATUS
-FileBufferBackup (
- VOID
- );
-
-/**
- Set the cursor position according to FileBuffer.DisplayPosition.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-FileBufferRestorePosition (
- VOID
- );
-
-/**
- Set FileName field in FileBuffer.
-
- @param Str The file name to set.
-
- @retval EFI_SUCCESS The filename was successfully set.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_INVALID_PARAMETER Str is not a valid filename.
-**/
-EFI_STATUS
-FileBufferSetFileName (
- IN CONST CHAR16 *Str
- );
-
-/**
- Read a file from disk into the FileBuffer.
-
- @param[in] FileName The filename to read.
- @param[in] Recover TRUE if is for recover mode, no information printouts.
-
- @retval EFI_SUCCESS The load was successful.
- @retval EFI_LOAD_ERROR The load failed.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_INVALID_PARAMETER FileName is a directory.
-**/
-EFI_STATUS
-FileBufferRead (
- IN CONST CHAR16 *FileName,
- IN CONST BOOLEAN Recover
- );
-
-/**
- Save lines in FileBuffer to disk
-
- @param[in] FileName The file name for writing.
-
- @retval EFI_SUCCESS Data was written.
- @retval EFI_LOAD_ERROR
- @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
-**/
-EFI_STATUS
-FileBufferSave (
- CONST CHAR16 *FileName
- );
-
-/**
- According to cursor's file position, adjust screen display
-
- @param[in] NewFilePosRow The row of file position ( start from 1 ).
- @param[in] NewFilePosCol The column of file position ( start from 1 ).
-**/
-VOID
-FileBufferMovePosition (
- IN CONST UINTN NewFilePosRow,
- IN CONST UINTN NewFilePosCol
- );
-
-/**
- Cut current line out and return a pointer to it.
-
- @param[out] CutLine Upon a successful return pointer to the pointer to
- the allocated cut line.
-
- @retval EFI_SUCCESS The cut was successful.
- @retval EFI_NOT_FOUND There was no selection to cut.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferCutLine (
- OUT EFI_EDITOR_LINE **CutLine
- );
-
-/**
- Paste a line into line list.
-
- @retval EFI_SUCCESS The paste was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferPasteLine (
- VOID
- );
-
-/**
- Search string from current position on in file
-
- @param[in] Str The search string.
- @param[in] Offset The offset from current position.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_NOT_FOUND The string Str was not found.
-**/
-EFI_STATUS
-FileBufferSearch (
- IN CONST CHAR16 *Str,
- IN CONST UINTN Offset
- );
-
-/**
- Replace SearchLen characters from current position on with Replace.
-
- This will modify the current buffer at the current position.
-
- @param[in] Replace The string to replace.
- @param[in] SearchLen Search string's length.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-FileBufferReplace (
- IN CONST CHAR16 *Replace,
- IN CONST UINTN SearchLen
- );
-
-/**
- Search and replace operation.
-
- @param[in] SearchStr The string to search for.
- @param[in] ReplaceStr The string to replace with.
- @param[in] Offset The column to start at.
-**/
-EFI_STATUS
-FileBufferReplaceAll (
- IN CHAR16 *SearchStr,
- IN CHAR16 *ReplaceStr,
- IN UINTN Offset
- );
-
-/**
- Move the mouse cursor position.
-
- @param[in] TextX The new x-coordinate.
- @param[in] TextY The new y-coordinate.
-**/
-VOID
-FileBufferAdjustMousePosition (
- IN CONST INT32 TextX,
- IN CONST INT32 TextY
- );
-
-/**
- Set the modified state to TRUE.
-**/
-VOID
-FileBufferSetModified (
- VOID
- );
-
-#endif
+/** @file
+ Declares filebuffer interface functions.
+
+ Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LIB_FILE_BUFFER_H_
+#define _LIB_FILE_BUFFER_H_
+
+#include "TextEditorTypes.h"
+
+/**
+ Initialization function for FileBuffer.
+
+ @param EFI_SUCCESS The initialization was successful.
+ @param EFI_LOAD_ERROR A default name could not be created.
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferInit (
+ VOID
+ );
+
+/**
+ Cleanup function for FileBuffer.
+
+ @retval EFI_SUCCESS The cleanup was successful.
+**/
+EFI_STATUS
+FileBufferCleanup (
+ VOID
+ );
+
+/**
+ Refresh the screen with whats in the buffer.
+
+ @retval EFI_SUCCESS The refresh was successful.
+ @retval EFI_LOAD_ERROR There was an error finding what to write.
+**/
+EFI_STATUS
+FileBufferRefresh (
+ VOID
+ );
+
+/**
+ Dispatch input to different handler
+ @param[in] Key The input key. One of:
+ ASCII KEY
+ Backspace/Delete
+ Return
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The dispatch was done successfully.
+ @retval EFI_LOAD_ERROR The dispatch was not successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferHandleInput (
+ IN CONST EFI_INPUT_KEY *Key
+ );
+
+/**
+ Backup function for FileBuffer. Only backup the following items:
+ Mouse/Cursor position
+ File Name, Type, ReadOnly, Modified
+ Insert Mode
+
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+FileBufferBackup (
+ VOID
+ );
+
+/**
+ Set the cursor position according to FileBuffer.DisplayPosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+FileBufferRestorePosition (
+ VOID
+ );
+
+/**
+ Set FileName field in FileBuffer.
+
+ @param Str The file name to set.
+
+ @retval EFI_SUCCESS The filename was successfully set.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.
+**/
+EFI_STATUS
+FileBufferSetFileName (
+ IN CONST CHAR16 *Str
+ );
+
+/**
+ Read a file from disk into the FileBuffer.
+
+ @param[in] FileName The filename to read.
+ @param[in] Recover TRUE if is for recover mode, no information printouts.
+
+ @retval EFI_SUCCESS The load was successful.
+ @retval EFI_LOAD_ERROR The load failed.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER FileName is a directory.
+**/
+EFI_STATUS
+FileBufferRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Recover
+ );
+
+/**
+ Save lines in FileBuffer to disk
+
+ @param[in] FileName The file name for writing.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_LOAD_ERROR
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
+**/
+EFI_STATUS
+FileBufferSave (
+ CONST CHAR16 *FileName
+ );
+
+/**
+ According to cursor's file position, adjust screen display
+
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).
+**/
+VOID
+FileBufferMovePosition (
+ IN CONST UINTN NewFilePosRow,
+ IN CONST UINTN NewFilePosCol
+ );
+
+/**
+ Cut current line out and return a pointer to it.
+
+ @param[out] CutLine Upon a successful return pointer to the pointer to
+ the allocated cut line.
+
+ @retval EFI_SUCCESS The cut was successful.
+ @retval EFI_NOT_FOUND There was no selection to cut.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferCutLine (
+ OUT EFI_EDITOR_LINE **CutLine
+ );
+
+/**
+ Paste a line into line list.
+
+ @retval EFI_SUCCESS The paste was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferPasteLine (
+ VOID
+ );
+
+/**
+ Search string from current position on in file
+
+ @param[in] Str The search string.
+ @param[in] Offset The offset from current position.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND The string Str was not found.
+**/
+EFI_STATUS
+FileBufferSearch (
+ IN CONST CHAR16 *Str,
+ IN CONST UINTN Offset
+ );
+
+/**
+ Replace SearchLen characters from current position on with Replace.
+
+ This will modify the current buffer at the current position.
+
+ @param[in] Replace The string to replace.
+ @param[in] SearchLen Search string's length.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+FileBufferReplace (
+ IN CONST CHAR16 *Replace,
+ IN CONST UINTN SearchLen
+ );
+
+/**
+ Search and replace operation.
+
+ @param[in] SearchStr The string to search for.
+ @param[in] ReplaceStr The string to replace with.
+ @param[in] Offset The column to start at.
+**/
+EFI_STATUS
+FileBufferReplaceAll (
+ IN CHAR16 *SearchStr,
+ IN CHAR16 *ReplaceStr,
+ IN UINTN Offset
+ );
+
+/**
+ Move the mouse cursor position.
+
+ @param[in] TextX The new x-coordinate.
+ @param[in] TextY The new y-coordinate.
+**/
+VOID
+FileBufferAdjustMousePosition (
+ IN CONST INT32 TextX,
+ IN CONST INT32 TextY
+ );
+
+/**
+ Set the modified state to TRUE.
+**/
+VOID
+FileBufferSetModified (
+ VOID
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
index 58beaaf9c5..6f0fda15de 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
@@ -1,1990 +1,1990 @@
-/** @file
- Implements editor interface functions.
-
- Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "TextEditor.h"
-#include "EditStatusBar.h"
-#include "EditInputBar.h"
-#include "EditMenuBar.h"
-
-//
-// the first time editor launch
-//
-BOOLEAN EditorFirst;
-
-//
-// it's time editor should exit
-//
-BOOLEAN EditorExit;
-
-BOOLEAN EditorMouseAction;
-
-extern EFI_EDITOR_FILE_BUFFER FileBuffer;
-
-extern BOOLEAN FileBufferNeedRefresh;
-
-extern BOOLEAN FileBufferOnlyLineNeedRefresh;
-
-extern BOOLEAN FileBufferMouseNeedRefresh;
-
-extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
-
-EFI_EDITOR_GLOBAL_EDITOR MainEditor;
-
-/**
- Load a file from disk to editor
-
- @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
-MainCommandOpenFile (
- VOID
- );
-
-/**
- Switch a file from ASCII to UNICODE or vise-versa.
-
- @retval EFI_SUCCESS The switch was ok or a warning was presented.
-**/
-EFI_STATUS
-MainCommandSwitchFileType (
- VOID
- );
-
-/**
- move cursor to specified lines
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-MainCommandGotoLine (
- VOID
- );
-
-/**
- Save current file to disk, you can save to current file name or
- save to another file name.
-
- @retval EFI_SUCCESS The file was saved correctly.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A file access error occurred.
-**/
-EFI_STATUS
-MainCommandSaveFile (
- VOID
- );
-
-/**
- Show help information for the editor.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-MainCommandDisplayHelp (
- VOID
- );
-
-/**
- exit editor
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandExit (
- VOID
- );
-
-/**
- search string in file buffer
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandSearch (
- VOID
- );
-
-/**
- search string in file buffer, and replace it with another str
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandSearchReplace (
- VOID
- );
-
-/**
- cut current line to clipboard
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandCutLine (
- VOID
- );
-
-/**
- paste line to file buffer.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandPasteLine (
- VOID
- );
-
-/**
- Help info that will be displayed.
-**/
-EFI_STRING_ID MainMenuHelpInfo[] = {
- STRING_TOKEN (STR_EDIT_HELP_TITLE),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_LIST_TITLE),
- STRING_TOKEN (STR_EDIT_HELP_DIV),
- STRING_TOKEN (STR_EDIT_HELP_GO_TO_LINE),
- STRING_TOKEN (STR_EDIT_HELP_SAVE_FILE),
- STRING_TOKEN (STR_EDIT_HELP_EXIT),
- STRING_TOKEN (STR_EDIT_HELP_SEARCH),
- STRING_TOKEN (STR_EDIT_HELP_SEARCH_REPLACE),
- STRING_TOKEN (STR_EDIT_HELP_CUT_LINE),
- STRING_TOKEN (STR_EDIT_HELP_PASTE_LINE),
- STRING_TOKEN (STR_EDIT_HELP_OPEN_FILE),
- STRING_TOKEN (STR_EDIT_HELP_FILE_TYPE),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_EXIT_HELP),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_BLANK),
- STRING_TOKEN (STR_EDIT_HELP_DIV),
- 0
-};
-
-MENU_ITEM_FUNCTION MainControlBasedMenuFunctions[] = {
- NULL,
- NULL, /* Ctrl - A */
- NULL, /* Ctrl - B */
- NULL, /* Ctrl - C */
- NULL, /* Ctrl - D */
- MainCommandDisplayHelp, /* Ctrl - E */
- MainCommandSearch, /* Ctrl - F */
- MainCommandGotoLine, /* Ctrl - G */
- NULL, /* Ctrl - H */
- NULL, /* Ctrl - I */
- NULL, /* Ctrl - J */
- MainCommandCutLine, /* Ctrl - K */
- NULL, /* Ctrl - L */
- NULL, /* Ctrl - M */
- NULL, /* Ctrl - N */
- MainCommandOpenFile, /* Ctrl - O */
- NULL, /* Ctrl - P */
- MainCommandExit, /* Ctrl - Q */
- MainCommandSearchReplace, /* Ctrl - R */
- MainCommandSaveFile, /* Ctrl - S */
- MainCommandSwitchFileType, /* Ctrl - T */
- MainCommandPasteLine, /* Ctrl - U */
- NULL, /* Ctrl - V */
- NULL, /* Ctrl - W */
- NULL, /* Ctrl - X */
- NULL, /* Ctrl - Y */
- NULL, /* Ctrl - Z */
-};
-
-EDITOR_MENU_ITEM MainMenuItems[] = {
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_GO_TO_LINE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F1),
- MainCommandGotoLine
- },
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_SAVE_FILE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F2),
- MainCommandSaveFile
- },
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_EXIT),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F3),
- MainCommandExit
- },
-
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_SEARCH),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F4),
- MainCommandSearch
- },
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_SEARCH_REPLACE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F5),
- MainCommandSearchReplace
- },
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_CUT_LINE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F6),
- MainCommandCutLine
- },
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_PASTE_LINE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F7),
- MainCommandPasteLine
- },
-
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_OPEN_FILE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F8),
- MainCommandOpenFile
- },
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_FILE_TYPE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F9),
- MainCommandSwitchFileType
- },
- {
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_FILE_TYPE),
- STRING_TOKEN (STR_EDIT_LIBMENUBAR_F11),
- MainCommandSwitchFileType
- },
-
- {
- 0,
- 0,
- NULL
- }
-};
-
-/**
- Load a file from disk to editor
-
- @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
-MainCommandOpenFile (
- VOID
- )
-{
- BOOLEAN Done;
- EFI_STATUS Status;
-
- //
- // This command will open a file from current working directory.
- // Read-only file can also be opened. But it can not be modified.
- // Below is the scenario of Open File command:
- // 1.IF currently opened file has not been modIFied, directly go to step .
- // IF currently opened file has been modified,
- // an Input Bar will be prompted as :
- // "File Modified. Save ( Yes/No/Cancel) ?"
- // IF user press 'y' or 'Y', currently opened file will be saved.
- // IF user press 'n' or 'N', currently opened file will
- // not be saved.
- // IF user press 'c' or 'C' or ESC, Open File command ends and
- // currently opened file is still opened.
- //
- // 2. An Input Bar will be prompted as : "File Name to Open: "
- // IF user press ESC, Open File command ends and
- // currently opened file is still opened.
- // Any other inputs with a Return will
- // cause currently opened file close.
- //
- // 3. IF user input file name is an existing file , this file will be read
- // and opened.
- // IF user input file name is a new file, this file will be created
- // and opened. This file's type ( UNICODE or ASCII ) is the same
- // with the old file.
- // if current file is modified, so you need to choose
- // whether to save it first.
- //
- if (MainEditor.FileBuffer->FileModified) {
- Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // the answer is just one character
- //
- Status = InputBarSetStringSize (1);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // loop for user's answer
- // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
- //
- Done = FALSE;
- while (!Done) {
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC pressed
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- switch (InputBarGetString ()[0]) {
- case L'y':
- case L'Y':
- //
- // want to save this file first
- //
- Status = FileBufferSave (MainEditor.FileBuffer->FileName);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
- FileBufferRestorePosition ();
- Done = TRUE;
- break;
-
- case L'n':
- case L'N':
- //
- // the file won't be saved
- //
- Done = TRUE;
- break;
-
- case L'c':
- case L'C':
- return EFI_SUCCESS;
- }
- }
- }
-
- //
- // TO get the open file name
- //
- Status = InputBarSetPrompt (L"File Name to Open: ");
- if (EFI_ERROR (Status)) {
- FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
- return Status;
- }
-
- Status = InputBarSetStringSize (100);
- if (EFI_ERROR (Status)) {
- FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
- return Status;
- }
-
- while (1) {
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC pressed
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- //
- // The input string length should > 0
- //
- if (StrLen (InputBarGetString ()) > 0) {
- //
- // CHECK if filename is valid
- //
- if (!IsValidFileName (InputBarGetString ())) {
- FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
- StatusBarSetStatusString (L"Invalid File Name");
- return EFI_SUCCESS;
- }
-
- break;
- }
- }
-
- //
- // read from disk
- //
- Status = FileBufferRead (InputBarGetString (), FALSE);
-
- if (EFI_ERROR (Status)) {
- FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
- return EFI_LOAD_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Switch a file from ASCII to UNICODE or vise-versa.
-
- @retval EFI_SUCCESS The switch was ok or a warning was presented.
-**/
-EFI_STATUS
-MainCommandSwitchFileType (
- VOID
- )
-{
- //
- // Below is the scenario of File Type command:
- // After File Type is executed, file type will be changed to another type
- // if file is read-only, can not be modified
- //
- if (MainEditor.FileBuffer->ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- return EFI_SUCCESS;
- }
-
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- MainEditor.FileBuffer->FileType = FileTypeAscii;
- } else {
- MainEditor.FileBuffer->FileType = FileTypeUnicode;
- }
-
- MainEditor.FileBuffer->FileModified = TRUE;
-
- return EFI_SUCCESS;
-}
-
-/**
- cut current line to clipboard
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandCutLine (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_EDITOR_LINE *Line;
-
- //
- // This command will cut current line ( where cursor is on ) to clip board.
- // And cursor will move to the beginning of next line.
- // Below is the scenario of Cut Line command:
- // 1. IF cursor is on valid line, current line will be cut to clip board.
- // IF cursor is not on valid line, an Status String will be prompted :
- // "Nothing to Cut".
- //
- Line = NULL;
- Status = FileBufferCutLine (&Line);
- if (Status == EFI_NOT_FOUND) {
- return EFI_SUCCESS;
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- MainEditor.CutLine = Line;
-
- return EFI_SUCCESS;
-}
-
-/**
- paste line to file buffer.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandPasteLine (
- VOID
- )
-{
- EFI_STATUS Status;
-
- //
- // Below is the scenario of Paste Line command:
- // 1. IF nothing is on clipboard, a Status String will be prompted :
- // "No Line to Paste" and Paste Line command ends.
- // IF something is on clipboard, insert it above current line.
- // nothing on clipboard
- //
- if (MainEditor.CutLine == NULL) {
- StatusBarSetStatusString (L"No Line to Paste");
- return EFI_SUCCESS;
- }
-
- Status = FileBufferPasteLine ();
-
- return Status;
-}
-
-/**
- search string in file buffer
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandSearch (
- VOID
- )
-{
- EFI_STATUS Status;
- CHAR16 *Buffer;
- BOOLEAN Done;
- UINTN Offset;
-
- //
- // Below is the scenario of Search command:
- // 1. An Input Bar will be prompted : "Enter Search String:".
- // IF user press ESC, Search command ends.
- // IF user just press Enter, Search command ends.
- // IF user inputs the search string, do Step 2.
- //
- // 2. IF input search string is found, cursor will move to the first
- // occurrence and do Step 3.
- // IF input search string is not found, a Status String
- // "Search String Not Found" will be prompted and Search command ends.
- //
- // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
- // IF user press ESC, Search command ends.
- // IF user press 'y' or 'Y', do Step 2.
- // IF user press 'n' or 'N', Search command ends.
- // IF user press 'c' or 'C', Search command ends.
- //
- Status = InputBarSetPrompt (L"Enter Search String: ");
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarSetStringSize (40);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- //
- // just enter pressed
- //
- if (StrLen (InputBarGetString ()) == 0) {
- return EFI_SUCCESS;
- }
-
- Buffer = CatSPrint (NULL, L"%s", InputBarGetString ());
- if (Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // the first time , search from current position
- //
- Offset = 0;
- do {
- //
- // since search may be continued to search multiple times
- // so we need to backup editor each time
- //
- MainEditorBackup ();
-
- Status = FileBufferSearch (Buffer, Offset);
-
- if (Status == EFI_NOT_FOUND) {
- break;
- }
-
- //
- // Find next
- //
- Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return Status;
- }
-
- Status = InputBarSetStringSize (1);
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return Status;
- }
-
- Done = FALSE;
- while (!Done) {
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC pressed
- //
- if (Status == EFI_NOT_READY) {
- FreePool (Buffer);
- return EFI_SUCCESS;
- }
-
- switch (InputBarGetString ()[0]) {
- case L'y':
- case L'Y':
- Done = TRUE;
- break;
-
- case L'n':
- case L'N':
- FreePool (Buffer);
- return EFI_SUCCESS;
- }
-
- //
- // end of which
- //
- }
-
- //
- // end of while !Done
- // for search second, third time, search from current position + strlen
- //
- Offset = StrLen (Buffer);
- } while (1);
-
- //
- // end of do
- //
- FreePool (Buffer);
- StatusBarSetStatusString (L"Search String Not Found");
-
- return EFI_SUCCESS;
-}
-
-/**
- Search string in file buffer, and replace it with another str.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandSearchReplace (
- VOID
- )
-{
- EFI_STATUS Status;
- CHAR16 *Search;
- CHAR16 *Replace;
- BOOLEAN Done;
- BOOLEAN First;
- BOOLEAN ReplaceOption;
- UINTN SearchLen;
- UINTN ReplaceLen;
- BOOLEAN ReplaceAll;
-
- ReplaceOption = FALSE;
-
- //
- // Below is the scenario of Search/Replace command:
- // 1. An Input Bar is prompted : "Enter Search String:".
- // IF user press ESC, Search/Replace command ends.
- // IF user just press Enter, Search/Replace command ends.
- // IF user inputs the search string S, do Step 2.
- //
- // 2. An Input Bar is prompted: "Replace With:".
- // IF user press ESC, Search/Replace command ends.
- // IF user inputs the replace string R, do Step 3.
- //
- // 3. IF input search string is not found, an Status String
- // "Search String Not Found" will be prompted
- // and Search/Replace command ends
- // IF input search string is found, do Step 4.
- //
- // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
- // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
- // IF user press 'n' or 'N', S will not be replaced and do Step 5.
- // IF user press 'a' or 'A', all the S from file current position on
- // will be replaced with R and Search/Replace command ends.
- // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
- //
- // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
- // IF user press ESC, Search/Replace command ends.
- // IF user press 'y' or 'Y', do Step 3.
- // IF user press 'n' or 'N', Search/Replace command ends.
- // IF user press 'c' or 'C', Search/Replace command ends.
- // input search string
- //
- Status = InputBarSetPrompt (L"Enter Search String: ");
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarSetStringSize (40);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- //
- // if just pressed enter
- //
- if (StrLen (InputBarGetString ()) == 0) {
- return EFI_SUCCESS;
- }
-
- Search = CatSPrint (NULL, L"%s", InputBarGetString ());
- if (Search == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- SearchLen = StrLen (Search);
-
- //
- // input replace string
- //
- Status = InputBarSetPrompt (L"Replace With: ");
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarSetStringSize (40);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- Replace = CatSPrint (NULL, L"%s", InputBarGetString ());
- if (Replace == NULL) {
- FreePool (Search);
- return EFI_OUT_OF_RESOURCES;
- }
-
- ReplaceLen = StrLen (Replace);
-
- First = TRUE;
- ReplaceAll = FALSE;
- do {
- //
- // since search may be continued to search multiple times
- // so we need to backup editor each time
- //
- MainEditorBackup ();
-
- if (First) {
- Status = FileBufferSearch (Search, 0);
- } else {
- //
- // if just replace, so skip this replace string
- // if replace string is an empty string, so skip to next character
- //
- if (ReplaceOption) {
- Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen);
- } else {
- Status = FileBufferSearch (Search, SearchLen);
- }
- }
-
- if (Status == EFI_NOT_FOUND) {
- break;
- }
-
- //
- // replace or not?
- //
- Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?");
-
- if (EFI_ERROR (Status)) {
- FreePool (Search);
- FreePool (Replace);
- return Status;
- }
-
- Status = InputBarSetStringSize (1);
- if (EFI_ERROR (Status)) {
- FreePool (Search);
- FreePool (Replace);
- return Status;
- }
-
- Done = FALSE;
- while (!Done) {
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC pressed
- //
- if (Status == EFI_NOT_READY) {
- FreePool (Search);
- FreePool (Replace);
- return EFI_SUCCESS;
- }
-
- switch (InputBarGetString ()[0]) {
- case L'y':
- case L'Y':
- Done = TRUE;
- ReplaceOption = TRUE;
- break;
-
- case L'n':
- case L'N':
- Done = TRUE;
- ReplaceOption = FALSE;
- break;
-
- case L'a':
- case L'A':
- Done = TRUE;
- ReplaceOption = TRUE;
- ReplaceAll = TRUE;
- break;
-
- case L'c':
- case L'C':
- FreePool (Search);
- FreePool (Replace);
- return EFI_SUCCESS;
- }
-
- //
- // end of which
- //
- }
-
- //
- // end of while !Done
- // Decide to Replace
- //
- if (ReplaceOption) {
- //
- // file is read-only
- //
- if (MainEditor.FileBuffer->ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- return EFI_SUCCESS;
- }
-
- //
- // replace all
- //
- if (ReplaceAll) {
- Status = FileBufferReplaceAll (Search, Replace, 0);
- FreePool (Search);
- FreePool (Replace);
- return Status;
- }
-
- //
- // replace
- //
- Status = FileBufferReplace (Replace, SearchLen);
- if (EFI_ERROR (Status)) {
- FreePool (Search);
- FreePool (Replace);
- return Status;
- }
- }
-
- //
- // Find next
- //
- Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
- if (EFI_ERROR (Status)) {
- FreePool (Search);
- FreePool (Replace);
- return Status;
- }
-
- Status = InputBarSetStringSize (1);
- if (EFI_ERROR (Status)) {
- FreePool (Search);
- FreePool (Replace);
- return Status;
- }
-
- Done = FALSE;
- while (!Done) {
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC pressed
- //
- if (Status == EFI_NOT_READY) {
- FreePool (Search);
- FreePool (Replace);
- return EFI_SUCCESS;
- }
-
- switch (InputBarGetString ()[0]) {
- case L'y':
- case L'Y':
- Done = TRUE;
- break;
-
- case L'n':
- case L'N':
- FreePool (Search);
- FreePool (Replace);
- return EFI_SUCCESS;
- }
-
- //
- // end of which
- //
- }
-
- //
- // end of while !Done
- //
- First = FALSE;
- } while (1);
-
- //
- // end of do
- //
- FreePool (Search);
- FreePool (Replace);
-
- StatusBarSetStatusString (L"Search String Not Found");
-
- return EFI_SUCCESS;
-}
-
-/**
- exit editor
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainCommandExit (
- VOID
- )
-{
- EFI_STATUS Status;
-
- //
- // Below is the scenario of Exit command:
- // 1. IF currently opened file is not modified, exit the editor and
- // Exit command ends.
- // IF currently opened file is modified, do Step 2
- //
- // 2. An Input Bar will be prompted:
- // "File modified. Save ( Yes/No/Cancel )?"
- // IF user press 'y' or 'Y', currently opened file will be saved
- // and Editor exits
- // IF user press 'n' or 'N', currently opened file will not be saved
- // and Editor exits.
- // IF user press 'c' or 'C' or ESC, Exit command ends.
- // if file has been modified, so will prompt user whether to save the changes
- //
- if (MainEditor.FileBuffer->FileModified) {
- Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarSetStringSize (1);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- while (1) {
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC pressed
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- switch (InputBarGetString ()[0]) {
- case L'y':
- case L'Y':
- //
- // write file back to disk
- //
- Status = FileBufferSave (MainEditor.FileBuffer->FileName);
- if (!EFI_ERROR (Status)) {
- EditorExit = TRUE;
- }
-
- return Status;
-
- case L'n':
- case L'N':
- EditorExit = TRUE;
- return EFI_SUCCESS;
-
- case L'c':
- case L'C':
- return EFI_SUCCESS;
- }
- }
- }
-
- EditorExit = TRUE;
- return EFI_SUCCESS;
-}
-
-/**
- move cursor to specified lines
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-MainCommandGotoLine (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN Row;
-
- //
- // Below is the scenario of Go To Line command:
- // 1. An Input Bar will be prompted : "Go To Line:".
- // IF user press ESC, Go To Line command ends.
- // IF user just press Enter, cursor remains unchanged.
- // IF user inputs line number, do Step 2.
- //
- // 2. IF input line number is valid, move cursor to the beginning
- // of specified line and Go To Line command ends.
- // IF input line number is invalid, a Status String will be prompted:
- // "No Such Line" and Go To Line command ends.
- //
- Status = InputBarSetPrompt (L"Go To Line: ");
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // line number's digit <= 6
- //
- Status = InputBarSetStringSize (6);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // press ESC
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- //
- // if JUST press enter
- //
- if (StrLen (InputBarGetString ()) == 0) {
- return EFI_SUCCESS;
- }
-
- Row = ShellStrToUintn (InputBarGetString ());
-
- //
- // invalid line number
- //
- if ((Row > MainEditor.FileBuffer->NumLines) || (Row <= 0)) {
- StatusBarSetStatusString (L"No Such Line");
- return EFI_SUCCESS;
- }
-
- //
- // move cursor to that line's start
- //
- FileBufferMovePosition (Row, 1);
-
- return EFI_SUCCESS;
-}
-
-/**
- Save current file to disk, you can save to current file name or
- save to another file name.
-
- @retval EFI_SUCCESS The file was saved correctly.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A file access error occurred.
-**/
-EFI_STATUS
-MainCommandSaveFile (
- VOID
- )
-{
- EFI_STATUS Status;
- CHAR16 *FileName;
- BOOLEAN OldFile;
- CHAR16 *Str;
- SHELL_FILE_HANDLE FileHandle;
- EFI_FILE_INFO *Info;
-
- //
- // This command will save currently opened file to disk.
- // You can choose save to another file name or just save to
- // current file name.
- // Below is the scenario of Save File command:
- // ( Suppose the old file name is A )
- // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
- // IF user press ESC, Save File command ends .
- // IF user press Enter, input file name will be A.
- // IF user inputs a new file name B, input file name will be B.
- //
- // 2. IF input file name is A, go to do Step 3.
- // IF input file name is B, go to do Step 4.
- //
- // 3. IF A is read only, Status Bar will show "Access Denied" and
- // Save File commands ends.
- // IF A is not read only, save file buffer to disk and remove modified
- // flag in Title Bar , then Save File command ends.
- //
- // 4. IF B does not exist, create this file and save file buffer to it.
- // Go to do Step 7.
- // IF B exits, do Step 5.
- //
- // 5.An Input Bar will be prompted:
- // "File Exists. Overwrite ( Yes/No/Cancel )?"
- // IF user press 'y' or 'Y', do Step 6.
- // IF user press 'n' or 'N', Save File commands ends.
- // IF user press 'c' or 'C' or ESC, Save File commands ends.
- //
- // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
- // Save File commands ends.
- // IF B can be read and write, save file buffer to B.
- //
- // 7. Update File Name field in Title Bar to B and remove the modified
- // flag in Title Bar.
- //
- Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName);
- if (Str == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (StrLen (Str) >= 50) {
- //
- // replace the long file name with "..."
- //
- Str[46] = L'.';
- Str[47] = L'.';
- Str[48] = L'.';
- Str[49] = L']';
- Str[50] = CHAR_NULL;
- }
-
- Status = InputBarSetPrompt (Str);
- FreePool (Str);
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = InputBarSetStringSize (100);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // get new file name
- //
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // if user pressed ESC
- //
- if (Status == EFI_NOT_READY) {
- return EFI_SUCCESS;
- }
-
- //
- // if just enter pressed, so think save to current file name
- //
- if (StrLen (InputBarGetString ()) == 0) {
- FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName);
- } else {
- FileName = CatSPrint (NULL, L"%s", InputBarGetString ());
- }
-
- if (FileName == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (!IsValidFileName (FileName)) {
- StatusBarSetStatusString (L"Invalid File Name");
- FreePool (FileName);
- return EFI_SUCCESS;
- }
-
- OldFile = FALSE;
-
- //
- // save to the old file
- //
- if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) {
- OldFile = TRUE;
- }
-
- if (OldFile) {
- //
- // if the file is read only, so can not write back to it.
- //
- if (MainEditor.FileBuffer->ReadOnly == TRUE) {
- StatusBarSetStatusString (L"Access Denied");
- FreePool (FileName);
- return EFI_SUCCESS;
- }
- } else {
- //
- // if the file exists
- //
- if (ShellFileExists (FileName) != EFI_NOT_FOUND) {
- //
- // check for read only
- //
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
- if (EFI_ERROR (Status)) {
- StatusBarSetStatusString (L"Open Failed");
- FreePool (FileName);
- return EFI_SUCCESS;
- }
-
- Info = ShellGetFileInfo (FileHandle);
- if (Info == NULL) {
- StatusBarSetStatusString (L"Access Denied");
- FreePool (FileName);
- return (EFI_SUCCESS);
- }
-
- if (Info->Attribute & EFI_FILE_READ_ONLY) {
- StatusBarSetStatusString (L"Access Denied - Read Only");
- FreePool (Info);
- FreePool (FileName);
- return (EFI_SUCCESS);
- }
-
- FreePool (Info);
-
- //
- // ask user whether to overwrite this file
- //
- Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
- if (EFI_ERROR (Status)) {
- SHELL_FREE_NON_NULL (FileName);
- return Status;
- }
-
- Status = InputBarSetStringSize (1);
- if (EFI_ERROR (Status)) {
- SHELL_FREE_NON_NULL (FileName);
- return Status;
- }
-
- while (TRUE) {
- Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
- StatusBarSetRefresh ();
-
- //
- // ESC pressed
- //
- if (Status == EFI_NOT_READY) {
- SHELL_FREE_NON_NULL (FileName);
- return EFI_SUCCESS;
- }
-
- switch (InputBarGetString ()[0]) {
- case L'y':
- case L'Y':
- break;
-
- case L'n':
- case L'N':
- case L'c':
- case L'C':
- SHELL_FREE_NON_NULL (FileName);
- return EFI_SUCCESS;
- } // end switch
- } // while (!done)
- } // file does exist
- } // if old file name same
-
- //
- // save file to disk with specified name
- //
- FileBufferSetModified ();
- Status = FileBufferSave (FileName);
- SHELL_FREE_NON_NULL (FileName);
-
- return Status;
-}
-
-/**
- Show help information for the editor.
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-MainCommandDisplayHelp (
- VOID
- )
-{
- INT32 CurrentLine;
- CHAR16 *InfoString;
- EFI_KEY_DATA KeyData;
- EFI_STATUS Status;
- UINTN EventIndex;
-
- //
- // print helpInfo
- //
- for (CurrentLine = 0; 0 != MainMenuHelpInfo[CurrentLine]; CurrentLine++) {
- InfoString = HiiGetString (gShellDebug1HiiHandle, MainMenuHelpInfo[CurrentLine], NULL);
- ShellPrintEx (0, CurrentLine+1, L"%E%s%N", InfoString);
- }
-
- //
- // scan for ctrl+w
- //
- while (TRUE) {
- Status = gBS->WaitForEvent (1, &MainEditor.TextInputEx->WaitForKeyEx, &EventIndex);
- if (EFI_ERROR (Status) || (EventIndex != 0)) {
- continue;
- }
-
- Status = MainEditor.TextInputEx->ReadKeyStrokeEx (MainEditor.TextInputEx, &KeyData);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) ||
- (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID))
- {
- //
- // For consoles that don't support/report shift state,
- // CTRL+W is translated to L'W' - L'A' + 1.
- //
- if (KeyData.Key.UnicodeChar == L'W' - L'A' + 1) {
- break;
- }
- } else if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) &&
- ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) &&
- ((KeyData.KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) == 0))
- {
- //
- // For consoles that supports/reports shift state,
- // make sure that only CONTROL shift key is pressed.
- //
- if ((KeyData.Key.UnicodeChar == 'w') || (KeyData.Key.UnicodeChar == 'W')) {
- break;
- }
- }
- }
-
- //
- // update screen with file buffer's info
- //
- FileBufferRestorePosition ();
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- FileBufferRefresh ();
-
- return EFI_SUCCESS;
-}
-
-EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors;
-INTN OriginalMode;
-
-//
-// basic initialization for MainEditor
-//
-EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {
- &FileBuffer,
- {
- { 0, 0}
- },
- {
- 0,
- 0
- },
- NULL,
- NULL,
- FALSE,
- NULL
-};
-
-/**
- The initialization function for MainEditor.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainEditorInit (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
-
- //
- // basic initialization
- //
- CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor));
-
- //
- // set screen attributes
- //
- MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
-
- MainEditor.ColorAttributes.Colors.Background = (UINT8)(gST->ConOut->Mode->Attribute >> 4);
- OriginalColors = MainEditor.ColorAttributes.Colors;
-
- OriginalMode = gST->ConOut->Mode->Mode;
-
- //
- // query screen size
- //
- gST->ConOut->QueryMode (
- gST->ConOut,
- gST->ConOut->Mode->Mode,
- &(MainEditor.ScreenSize.Column),
- &(MainEditor.ScreenSize.Row)
- );
-
- //
- // Find TextInEx in System Table ConsoleInHandle
- // Per UEFI Spec, TextInEx is required for a console capable platform.
- //
- Status = gBS->HandleProtocol (
- gST->ConsoleInHandle,
- &gEfiSimpleTextInputExProtocolGuid,
- (VOID **)&MainEditor.TextInputEx
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Find mouse in System Table ConsoleInHandle
- //
- Status = gBS->HandleProtocol (
- gST->ConsoleInHandle,
- &gEfiSimplePointerProtocolGuid,
- (VOID **)&MainEditor.MouseInterface
- );
- if (EFI_ERROR (Status)) {
- //
- // If there is no Simple Pointer Protocol on System Table
- //
- HandleBuffer = NULL;
- MainEditor.MouseInterface = NULL;
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiSimplePointerProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (!EFI_ERROR (Status) && (HandleCount > 0)) {
- //
- // Try to find the first available mouse device
- //
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiSimplePointerProtocolGuid,
- (VOID **)&MainEditor.MouseInterface
- );
- if (!EFI_ERROR (Status)) {
- break;
- }
- }
- }
-
- if (HandleBuffer != NULL) {
- FreePool (HandleBuffer);
- }
- }
-
- if (!EFI_ERROR (Status) && (MainEditor.MouseInterface != NULL)) {
- MainEditor.MouseAccumulatorX = 0;
- MainEditor.MouseAccumulatorY = 0;
- MainEditor.MouseSupported = TRUE;
- }
-
- //
- // below will call the five components' init function
- //
- Status = MainTitleBarInit (L"UEFI EDIT");
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle);
- return EFI_LOAD_ERROR;
- }
-
- Status = ControlHotKeyInit (MainControlBasedMenuFunctions);
- Status = MenuBarInit (MainMenuItems);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle);
- return EFI_LOAD_ERROR;
- }
-
- Status = StatusBarInit ();
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle);
- return EFI_LOAD_ERROR;
- }
-
- InputBarInit (MainEditor.TextInputEx);
-
- Status = FileBufferInit ();
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle);
- return EFI_LOAD_ERROR;
- }
-
- //
- // clear whole screen and enable cursor
- //
- gST->ConOut->ClearScreen (gST->ConOut);
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-
- //
- // initialize EditorFirst and EditorExit
- //
- EditorFirst = TRUE;
- EditorExit = FALSE;
- EditorMouseAction = FALSE;
-
- return EFI_SUCCESS;
-}
-
-/**
- The cleanup function for MainEditor.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainEditorCleanup (
- VOID
- )
-{
- EFI_STATUS Status;
-
- //
- // call the five components' cleanup function
- // if error, do not exit
- // just print some warning
- //
- MainTitleBarCleanup ();
- StatusBarCleanup ();
- InputBarCleanup ();
- MenuBarCleanup ();
-
- Status = FileBufferCleanup ();
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle);
- }
-
- //
- // restore old mode
- //
- if (OriginalMode != gST->ConOut->Mode->Mode) {
- gST->ConOut->SetMode (gST->ConOut, OriginalMode);
- }
-
- //
- // restore old screen color
- //
- gST->ConOut->SetAttribute (
- gST->ConOut,
- EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background)
- );
-
- gST->ConOut->ClearScreen (gST->ConOut);
-
- return EFI_SUCCESS;
-}
-
-/**
- Refresh the main editor component.
-**/
-VOID
-MainEditorRefresh (
- VOID
- )
-{
- //
- // The Stall value is from experience. NOT from spec. avoids 'flicker'
- //
- gBS->Stall (50);
-
- //
- // call the components refresh function
- //
- if ( EditorFirst
- || (StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0)
- || (FileBufferBackupVar.FileType != FileBuffer.FileType)
- || (FileBufferBackupVar.FileModified != FileBuffer.FileModified)
- || (FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly))
- {
- MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
- FileBufferRestorePosition ();
- }
-
- if ( EditorFirst
- || (FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row)
- || (FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column)
- || (FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert)
- || StatusBarGetRefresh ())
- {
- StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert);
- FileBufferRestorePosition ();
- }
-
- if (EditorFirst) {
- FileBufferRestorePosition ();
- }
-
- FileBufferRefresh ();
-
- //
- // EditorFirst is now set to FALSE
- //
- EditorFirst = FALSE;
-}
-
-/**
- Get's the resultant location of the cursor based on the relative movement of the Mouse.
-
- @param[in] GuidX The relative mouse movement.
-
- @return The X location of the mouse.
-**/
-INT32
-GetTextX (
- IN INT32 GuidX
- )
-{
- INT32 Gap;
-
- MainEditor.MouseAccumulatorX += GuidX;
- Gap = (MainEditor.MouseAccumulatorX * (INT32)MainEditor.ScreenSize.Column) / (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionX);
- MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32)MainEditor.ScreenSize.Column) % (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionX);
- MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32)MainEditor.ScreenSize.Column;
- return Gap;
-}
-
-/**
- Get's the resultant location of the cursor based on the relative movement of the Mouse.
-
- @param[in] GuidY The relative mouse movement.
-
- @return The Y location of the mouse.
-**/
-INT32
-GetTextY (
- IN INT32 GuidY
- )
-{
- INT32 Gap;
-
- MainEditor.MouseAccumulatorY += GuidY;
- Gap = (MainEditor.MouseAccumulatorY * (INT32)MainEditor.ScreenSize.Row) / (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionY);
- MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32)MainEditor.ScreenSize.Row) % (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionY);
- MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32)MainEditor.ScreenSize.Row;
-
- return Gap;
-}
-
-/**
- Support mouse movement. Move the cursor.
-
- @param[in] MouseState The current mouse state.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_NOT_FOUND There was no mouse support found.
-**/
-EFI_STATUS
-MainEditorHandleMouseInput (
- IN EFI_SIMPLE_POINTER_STATE MouseState
- )
-{
- INT32 TextX;
- INT32 TextY;
- UINTN FRow;
- UINTN FCol;
-
- LIST_ENTRY *Link;
- EFI_EDITOR_LINE *Line;
-
- UINTN Index;
- BOOLEAN Action;
-
- //
- // mouse action means:
- // mouse movement
- // mouse left button
- //
- Action = FALSE;
-
- //
- // have mouse movement
- //
- if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
- //
- // handle
- //
- TextX = GetTextX (MouseState.RelativeMovementX);
- TextY = GetTextY (MouseState.RelativeMovementY);
-
- FileBufferAdjustMousePosition (TextX, TextY);
-
- Action = TRUE;
- }
-
- //
- // if left button pushed down
- //
- if (MouseState.LeftButton) {
- FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1;
-
- FRow = MainEditor.FileBuffer->FilePosition.Row +
- MainEditor.FileBuffer->MousePosition.Row -
- MainEditor.FileBuffer->DisplayPosition.Row;
-
- //
- // beyond the file line length
- //
- if (MainEditor.FileBuffer->NumLines < FRow) {
- FRow = MainEditor.FileBuffer->NumLines;
- }
-
- Link = MainEditor.FileBuffer->ListHead->ForwardLink;
- for (Index = 0; Index < FRow - 1; Index++) {
- Link = Link->ForwardLink;
- }
-
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
-
- //
- // beyond the line's column length
- //
- if (FCol > Line->Size + 1) {
- FCol = Line->Size + 1;
- }
-
- FileBufferMovePosition (FRow, FCol);
-
- MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row;
-
- MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column;
-
- Action = TRUE;
- }
-
- //
- // mouse has action
- //
- if (Action) {
- return EFI_SUCCESS;
- }
-
- //
- // no mouse action
- //
- return EFI_NOT_FOUND;
-}
-
-/**
- Handle user key input. This routes to other functions for the actions.
-
- @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
-MainEditorKeyInput (
- VOID
- )
-{
- EFI_KEY_DATA KeyData;
- EFI_STATUS Status;
- EFI_SIMPLE_POINTER_STATE MouseState;
- BOOLEAN NoShiftState;
-
- do {
- Status = EFI_SUCCESS;
- EditorMouseAction = FALSE;
-
- //
- // backup some key elements, so that can aVOID some refresh work
- //
- MainEditorBackup ();
-
- //
- // change priority of checking mouse/keyboard activity dynamically
- // so prevent starvation of keyboard.
- // if last time, mouse moves then this time check keyboard
- //
- if (MainEditor.MouseSupported) {
- Status = MainEditor.MouseInterface->GetState (
- MainEditor.MouseInterface,
- &MouseState
- );
- if (!EFI_ERROR (Status)) {
- Status = MainEditorHandleMouseInput (MouseState);
-
- if (!EFI_ERROR (Status)) {
- EditorMouseAction = TRUE;
- FileBufferMouseNeedRefresh = TRUE;
- } else if (Status == EFI_LOAD_ERROR) {
- StatusBarSetStatusString (L"Invalid Mouse Movement ");
- }
- }
- }
-
- //
- // CheckEvent() returns Success when non-partial key is pressed.
- //
- Status = gBS->CheckEvent (MainEditor.TextInputEx->WaitForKeyEx);
- if (!EFI_ERROR (Status)) {
- Status = MainEditor.TextInputEx->ReadKeyStrokeEx (MainEditor.TextInputEx, &KeyData);
- if (!EFI_ERROR (Status)) {
- //
- // dispatch to different components' key handling function
- // so not everywhere has to set this variable
- //
- FileBufferMouseNeedRefresh = TRUE;
- //
- // clear previous status string
- //
- StatusBarSetRefresh ();
- //
- // NoShiftState: TRUE when no shift key is pressed.
- //
- NoShiftState = ((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID);
- //
- // dispatch to different components' key handling function
- //
- if (EFI_NOT_FOUND != MenuBarDispatchControlHotKey (&KeyData)) {
- Status = EFI_SUCCESS;
- } else if (NoShiftState && ((KeyData.Key.ScanCode == SCAN_NULL) || ((KeyData.Key.ScanCode >= SCAN_UP) && (KeyData.Key.ScanCode <= SCAN_PAGE_DOWN)))) {
- Status = FileBufferHandleInput (&KeyData.Key);
- } else if (NoShiftState && (KeyData.Key.ScanCode >= SCAN_F1) && (KeyData.Key.ScanCode <= SCAN_F12)) {
- Status = MenuBarDispatchFunctionKey (&KeyData.Key);
- } else {
- StatusBarSetStatusString (L"Unknown Command");
- FileBufferMouseNeedRefresh = FALSE;
- }
-
- if ((Status != EFI_SUCCESS) && (Status != EFI_OUT_OF_RESOURCES)) {
- //
- // not already has some error status
- //
- if ((StatusBarGetString () != NULL) && (StrCmp (L"", StatusBarGetString ()) == 0)) {
- StatusBarSetStatusString (L"Disk Error. Try Again");
- }
- }
- }
- }
-
- //
- // after handling, refresh editor
- //
- MainEditorRefresh ();
- } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);
-
- return Status;
-}
-
-/**
- Set clipboard
-
- @param[in] Line A pointer to the line to be set to clipboard
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
-**/
-EFI_STATUS
-MainEditorSetCutLine (
- EFI_EDITOR_LINE *Line
- )
-{
- if (Line == NULL) {
- return EFI_SUCCESS;
- }
-
- if (MainEditor.CutLine != NULL) {
- //
- // free the old clipboard
- //
- LineFree (MainEditor.CutLine);
- }
-
- //
- // duplicate the line to clipboard
- //
- MainEditor.CutLine = LineDup (Line);
- if (MainEditor.CutLine == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Backup function for MainEditor
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-MainEditorBackup (
- VOID
- )
-{
- FileBufferBackup ();
-
- return EFI_SUCCESS;
-}
+/** @file
+ Implements editor interface functions.
+
+ Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TextEditor.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+#include "EditMenuBar.h"
+
+//
+// the first time editor launch
+//
+BOOLEAN EditorFirst;
+
+//
+// it's time editor should exit
+//
+BOOLEAN EditorExit;
+
+BOOLEAN EditorMouseAction;
+
+extern EFI_EDITOR_FILE_BUFFER FileBuffer;
+
+extern BOOLEAN FileBufferNeedRefresh;
+
+extern BOOLEAN FileBufferOnlyLineNeedRefresh;
+
+extern BOOLEAN FileBufferMouseNeedRefresh;
+
+extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
+
+EFI_EDITOR_GLOBAL_EDITOR MainEditor;
+
+/**
+ Load a file from disk to editor
+
+ @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
+MainCommandOpenFile (
+ VOID
+ );
+
+/**
+ Switch a file from ASCII to UNICODE or vise-versa.
+
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.
+**/
+EFI_STATUS
+MainCommandSwitchFileType (
+ VOID
+ );
+
+/**
+ move cursor to specified lines
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandGotoLine (
+ VOID
+ );
+
+/**
+ Save current file to disk, you can save to current file name or
+ save to another file name.
+
+ @retval EFI_SUCCESS The file was saved correctly.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A file access error occurred.
+**/
+EFI_STATUS
+MainCommandSaveFile (
+ VOID
+ );
+
+/**
+ Show help information for the editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandDisplayHelp (
+ VOID
+ );
+
+/**
+ exit editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandExit (
+ VOID
+ );
+
+/**
+ search string in file buffer
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandSearch (
+ VOID
+ );
+
+/**
+ search string in file buffer, and replace it with another str
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandSearchReplace (
+ VOID
+ );
+
+/**
+ cut current line to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandCutLine (
+ VOID
+ );
+
+/**
+ paste line to file buffer.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandPasteLine (
+ VOID
+ );
+
+/**
+ Help info that will be displayed.
+**/
+EFI_STRING_ID MainMenuHelpInfo[] = {
+ STRING_TOKEN (STR_EDIT_HELP_TITLE),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_LIST_TITLE),
+ STRING_TOKEN (STR_EDIT_HELP_DIV),
+ STRING_TOKEN (STR_EDIT_HELP_GO_TO_LINE),
+ STRING_TOKEN (STR_EDIT_HELP_SAVE_FILE),
+ STRING_TOKEN (STR_EDIT_HELP_EXIT),
+ STRING_TOKEN (STR_EDIT_HELP_SEARCH),
+ STRING_TOKEN (STR_EDIT_HELP_SEARCH_REPLACE),
+ STRING_TOKEN (STR_EDIT_HELP_CUT_LINE),
+ STRING_TOKEN (STR_EDIT_HELP_PASTE_LINE),
+ STRING_TOKEN (STR_EDIT_HELP_OPEN_FILE),
+ STRING_TOKEN (STR_EDIT_HELP_FILE_TYPE),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_EXIT_HELP),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_BLANK),
+ STRING_TOKEN (STR_EDIT_HELP_DIV),
+ 0
+};
+
+MENU_ITEM_FUNCTION MainControlBasedMenuFunctions[] = {
+ NULL,
+ NULL, /* Ctrl - A */
+ NULL, /* Ctrl - B */
+ NULL, /* Ctrl - C */
+ NULL, /* Ctrl - D */
+ MainCommandDisplayHelp, /* Ctrl - E */
+ MainCommandSearch, /* Ctrl - F */
+ MainCommandGotoLine, /* Ctrl - G */
+ NULL, /* Ctrl - H */
+ NULL, /* Ctrl - I */
+ NULL, /* Ctrl - J */
+ MainCommandCutLine, /* Ctrl - K */
+ NULL, /* Ctrl - L */
+ NULL, /* Ctrl - M */
+ NULL, /* Ctrl - N */
+ MainCommandOpenFile, /* Ctrl - O */
+ NULL, /* Ctrl - P */
+ MainCommandExit, /* Ctrl - Q */
+ MainCommandSearchReplace, /* Ctrl - R */
+ MainCommandSaveFile, /* Ctrl - S */
+ MainCommandSwitchFileType, /* Ctrl - T */
+ MainCommandPasteLine, /* Ctrl - U */
+ NULL, /* Ctrl - V */
+ NULL, /* Ctrl - W */
+ NULL, /* Ctrl - X */
+ NULL, /* Ctrl - Y */
+ NULL, /* Ctrl - Z */
+};
+
+EDITOR_MENU_ITEM MainMenuItems[] = {
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_GO_TO_LINE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F1),
+ MainCommandGotoLine
+ },
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_SAVE_FILE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F2),
+ MainCommandSaveFile
+ },
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_EXIT),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F3),
+ MainCommandExit
+ },
+
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_SEARCH),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F4),
+ MainCommandSearch
+ },
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_SEARCH_REPLACE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F5),
+ MainCommandSearchReplace
+ },
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_CUT_LINE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F6),
+ MainCommandCutLine
+ },
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_PASTE_LINE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F7),
+ MainCommandPasteLine
+ },
+
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_OPEN_FILE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F8),
+ MainCommandOpenFile
+ },
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_FILE_TYPE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F9),
+ MainCommandSwitchFileType
+ },
+ {
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_FILE_TYPE),
+ STRING_TOKEN (STR_EDIT_LIBMENUBAR_F11),
+ MainCommandSwitchFileType
+ },
+
+ {
+ 0,
+ 0,
+ NULL
+ }
+};
+
+/**
+ Load a file from disk to editor
+
+ @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
+MainCommandOpenFile (
+ VOID
+ )
+{
+ BOOLEAN Done;
+ EFI_STATUS Status;
+
+ //
+ // This command will open a file from current working directory.
+ // Read-only file can also be opened. But it can not be modified.
+ // Below is the scenario of Open File command:
+ // 1.IF currently opened file has not been modIFied, directly go to step .
+ // IF currently opened file has been modified,
+ // an Input Bar will be prompted as :
+ // "File Modified. Save ( Yes/No/Cancel) ?"
+ // IF user press 'y' or 'Y', currently opened file will be saved.
+ // IF user press 'n' or 'N', currently opened file will
+ // not be saved.
+ // IF user press 'c' or 'C' or ESC, Open File command ends and
+ // currently opened file is still opened.
+ //
+ // 2. An Input Bar will be prompted as : "File Name to Open: "
+ // IF user press ESC, Open File command ends and
+ // currently opened file is still opened.
+ // Any other inputs with a Return will
+ // cause currently opened file close.
+ //
+ // 3. IF user input file name is an existing file , this file will be read
+ // and opened.
+ // IF user input file name is a new file, this file will be created
+ // and opened. This file's type ( UNICODE or ASCII ) is the same
+ // with the old file.
+ // if current file is modified, so you need to choose
+ // whether to save it first.
+ //
+ if (MainEditor.FileBuffer->FileModified) {
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString ()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this file first
+ //
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
+ FileBufferRestorePosition ();
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // TO get the open file name
+ //
+ Status = InputBarSetPrompt (L"File Name to Open: ");
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // The input string length should > 0
+ //
+ if (StrLen (InputBarGetString ()) > 0) {
+ //
+ // CHECK if filename is valid
+ //
+ if (!IsValidFileName (InputBarGetString ())) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ StatusBarSetStatusString (L"Invalid File Name");
+ return EFI_SUCCESS;
+ }
+
+ break;
+ }
+ }
+
+ //
+ // read from disk
+ //
+ Status = FileBufferRead (InputBarGetString (), FALSE);
+
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Switch a file from ASCII to UNICODE or vise-versa.
+
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.
+**/
+EFI_STATUS
+MainCommandSwitchFileType (
+ VOID
+ )
+{
+ //
+ // Below is the scenario of File Type command:
+ // After File Type is executed, file type will be changed to another type
+ // if file is read-only, can not be modified
+ //
+ if (MainEditor.FileBuffer->ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ MainEditor.FileBuffer->FileType = FileTypeAscii;
+ } else {
+ MainEditor.FileBuffer->FileType = FileTypeUnicode;
+ }
+
+ MainEditor.FileBuffer->FileModified = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ cut current line to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandCutLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // This command will cut current line ( where cursor is on ) to clip board.
+ // And cursor will move to the beginning of next line.
+ // Below is the scenario of Cut Line command:
+ // 1. IF cursor is on valid line, current line will be cut to clip board.
+ // IF cursor is not on valid line, an Status String will be prompted :
+ // "Nothing to Cut".
+ //
+ Line = NULL;
+ Status = FileBufferCutLine (&Line);
+ if (Status == EFI_NOT_FOUND) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainEditor.CutLine = Line;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ paste line to file buffer.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandPasteLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Paste Line command:
+ // 1. IF nothing is on clipboard, a Status String will be prompted :
+ // "No Line to Paste" and Paste Line command ends.
+ // IF something is on clipboard, insert it above current line.
+ // nothing on clipboard
+ //
+ if (MainEditor.CutLine == NULL) {
+ StatusBarSetStatusString (L"No Line to Paste");
+ return EFI_SUCCESS;
+ }
+
+ Status = FileBufferPasteLine ();
+
+ return Status;
+}
+
+/**
+ search string in file buffer
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandSearch (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ BOOLEAN Done;
+ UINTN Offset;
+
+ //
+ // Below is the scenario of Search command:
+ // 1. An Input Bar will be prompted : "Enter Search String:".
+ // IF user press ESC, Search command ends.
+ // IF user just press Enter, Search command ends.
+ // IF user inputs the search string, do Step 2.
+ //
+ // 2. IF input search string is found, cursor will move to the first
+ // occurrence and do Step 3.
+ // IF input search string is not found, a Status String
+ // "Search String Not Found" will be prompted and Search command ends.
+ //
+ // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
+ // IF user press ESC, Search command ends.
+ // IF user press 'y' or 'Y', do Step 2.
+ // IF user press 'n' or 'N', Search command ends.
+ // IF user press 'c' or 'C', Search command ends.
+ //
+ Status = InputBarSetPrompt (L"Enter Search String: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // just enter pressed
+ //
+ if (StrLen (InputBarGetString ()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Buffer = CatSPrint (NULL, L"%s", InputBarGetString ());
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // the first time , search from current position
+ //
+ Offset = 0;
+ do {
+ //
+ // since search may be continued to search multiple times
+ // so we need to backup editor each time
+ //
+ MainEditorBackup ();
+
+ Status = FileBufferSearch (Buffer, Offset);
+
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ //
+ // Find next
+ //
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Buffer);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString ()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ FreePool (Buffer);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // end of which
+ //
+ }
+
+ //
+ // end of while !Done
+ // for search second, third time, search from current position + strlen
+ //
+ Offset = StrLen (Buffer);
+ } while (1);
+
+ //
+ // end of do
+ //
+ FreePool (Buffer);
+ StatusBarSetStatusString (L"Search String Not Found");
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search string in file buffer, and replace it with another str.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandSearchReplace (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Search;
+ CHAR16 *Replace;
+ BOOLEAN Done;
+ BOOLEAN First;
+ BOOLEAN ReplaceOption;
+ UINTN SearchLen;
+ UINTN ReplaceLen;
+ BOOLEAN ReplaceAll;
+
+ ReplaceOption = FALSE;
+
+ //
+ // Below is the scenario of Search/Replace command:
+ // 1. An Input Bar is prompted : "Enter Search String:".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user just press Enter, Search/Replace command ends.
+ // IF user inputs the search string S, do Step 2.
+ //
+ // 2. An Input Bar is prompted: "Replace With:".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user inputs the replace string R, do Step 3.
+ //
+ // 3. IF input search string is not found, an Status String
+ // "Search String Not Found" will be prompted
+ // and Search/Replace command ends
+ // IF input search string is found, do Step 4.
+ //
+ // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
+ // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
+ // IF user press 'n' or 'N', S will not be replaced and do Step 5.
+ // IF user press 'a' or 'A', all the S from file current position on
+ // will be replaced with R and Search/Replace command ends.
+ // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
+ //
+ // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user press 'y' or 'Y', do Step 3.
+ // IF user press 'n' or 'N', Search/Replace command ends.
+ // IF user press 'c' or 'C', Search/Replace command ends.
+ // input search string
+ //
+ Status = InputBarSetPrompt (L"Enter Search String: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if just pressed enter
+ //
+ if (StrLen (InputBarGetString ()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Search = CatSPrint (NULL, L"%s", InputBarGetString ());
+ if (Search == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SearchLen = StrLen (Search);
+
+ //
+ // input replace string
+ //
+ Status = InputBarSetPrompt (L"Replace With: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ Replace = CatSPrint (NULL, L"%s", InputBarGetString ());
+ if (Replace == NULL) {
+ FreePool (Search);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ReplaceLen = StrLen (Replace);
+
+ First = TRUE;
+ ReplaceAll = FALSE;
+ do {
+ //
+ // since search may be continued to search multiple times
+ // so we need to backup editor each time
+ //
+ MainEditorBackup ();
+
+ if (First) {
+ Status = FileBufferSearch (Search, 0);
+ } else {
+ //
+ // if just replace, so skip this replace string
+ // if replace string is an empty string, so skip to next character
+ //
+ if (ReplaceOption) {
+ Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen);
+ } else {
+ Status = FileBufferSearch (Search, SearchLen);
+ }
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ //
+ // replace or not?
+ //
+ Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?");
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString ()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ ReplaceOption = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ Done = TRUE;
+ ReplaceOption = FALSE;
+ break;
+
+ case L'a':
+ case L'A':
+ Done = TRUE;
+ ReplaceOption = TRUE;
+ ReplaceAll = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // end of which
+ //
+ }
+
+ //
+ // end of while !Done
+ // Decide to Replace
+ //
+ if (ReplaceOption) {
+ //
+ // file is read-only
+ //
+ if (MainEditor.FileBuffer->ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ //
+ // replace all
+ //
+ if (ReplaceAll) {
+ Status = FileBufferReplaceAll (Search, Replace, 0);
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ //
+ // replace
+ //
+ Status = FileBufferReplace (Replace, SearchLen);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+ }
+
+ //
+ // Find next
+ //
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString ()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // end of which
+ //
+ }
+
+ //
+ // end of while !Done
+ //
+ First = FALSE;
+ } while (1);
+
+ //
+ // end of do
+ //
+ FreePool (Search);
+ FreePool (Replace);
+
+ StatusBarSetStatusString (L"Search String Not Found");
+
+ return EFI_SUCCESS;
+}
+
+/**
+ exit editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainCommandExit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Exit command:
+ // 1. IF currently opened file is not modified, exit the editor and
+ // Exit command ends.
+ // IF currently opened file is modified, do Step 2
+ //
+ // 2. An Input Bar will be prompted:
+ // "File modified. Save ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', currently opened file will be saved
+ // and Editor exits
+ // IF user press 'n' or 'N', currently opened file will not be saved
+ // and Editor exits.
+ // IF user press 'c' or 'C' or ESC, Exit command ends.
+ // if file has been modified, so will prompt user whether to save the changes
+ //
+ if (MainEditor.FileBuffer->FileModified) {
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString ()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // write file back to disk
+ //
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);
+ if (!EFI_ERROR (Status)) {
+ EditorExit = TRUE;
+ }
+
+ return Status;
+
+ case L'n':
+ case L'N':
+ EditorExit = TRUE;
+ return EFI_SUCCESS;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ EditorExit = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ move cursor to specified lines
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandGotoLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Row;
+
+ //
+ // Below is the scenario of Go To Line command:
+ // 1. An Input Bar will be prompted : "Go To Line:".
+ // IF user press ESC, Go To Line command ends.
+ // IF user just press Enter, cursor remains unchanged.
+ // IF user inputs line number, do Step 2.
+ //
+ // 2. IF input line number is valid, move cursor to the beginning
+ // of specified line and Go To Line command ends.
+ // IF input line number is invalid, a Status String will be prompted:
+ // "No Such Line" and Go To Line command ends.
+ //
+ Status = InputBarSetPrompt (L"Go To Line: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // line number's digit <= 6
+ //
+ Status = InputBarSetStringSize (6);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // press ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if JUST press enter
+ //
+ if (StrLen (InputBarGetString ()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Row = ShellStrToUintn (InputBarGetString ());
+
+ //
+ // invalid line number
+ //
+ if ((Row > MainEditor.FileBuffer->NumLines) || (Row <= 0)) {
+ StatusBarSetStatusString (L"No Such Line");
+ return EFI_SUCCESS;
+ }
+
+ //
+ // move cursor to that line's start
+ //
+ FileBufferMovePosition (Row, 1);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save current file to disk, you can save to current file name or
+ save to another file name.
+
+ @retval EFI_SUCCESS The file was saved correctly.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A file access error occurred.
+**/
+EFI_STATUS
+MainCommandSaveFile (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *FileName;
+ BOOLEAN OldFile;
+ CHAR16 *Str;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_FILE_INFO *Info;
+
+ //
+ // This command will save currently opened file to disk.
+ // You can choose save to another file name or just save to
+ // current file name.
+ // Below is the scenario of Save File command:
+ // ( Suppose the old file name is A )
+ // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
+ // IF user press ESC, Save File command ends .
+ // IF user press Enter, input file name will be A.
+ // IF user inputs a new file name B, input file name will be B.
+ //
+ // 2. IF input file name is A, go to do Step 3.
+ // IF input file name is B, go to do Step 4.
+ //
+ // 3. IF A is read only, Status Bar will show "Access Denied" and
+ // Save File commands ends.
+ // IF A is not read only, save file buffer to disk and remove modified
+ // flag in Title Bar , then Save File command ends.
+ //
+ // 4. IF B does not exist, create this file and save file buffer to it.
+ // Go to do Step 7.
+ // IF B exits, do Step 5.
+ //
+ // 5.An Input Bar will be prompted:
+ // "File Exists. Overwrite ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', do Step 6.
+ // IF user press 'n' or 'N', Save File commands ends.
+ // IF user press 'c' or 'C' or ESC, Save File commands ends.
+ //
+ // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
+ // Save File commands ends.
+ // IF B can be read and write, save file buffer to B.
+ //
+ // 7. Update File Name field in Title Bar to B and remove the modified
+ // flag in Title Bar.
+ //
+ Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName);
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (StrLen (Str) >= 50) {
+ //
+ // replace the long file name with "..."
+ //
+ Str[46] = L'.';
+ Str[47] = L'.';
+ Str[48] = L'.';
+ Str[49] = L']';
+ Str[50] = CHAR_NULL;
+ }
+
+ Status = InputBarSetPrompt (Str);
+ FreePool (Str);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // get new file name
+ //
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // if user pressed ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if just enter pressed, so think save to current file name
+ //
+ if (StrLen (InputBarGetString ()) == 0) {
+ FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName);
+ } else {
+ FileName = CatSPrint (NULL, L"%s", InputBarGetString ());
+ }
+
+ if (FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (!IsValidFileName (FileName)) {
+ StatusBarSetStatusString (L"Invalid File Name");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+
+ OldFile = FALSE;
+
+ //
+ // save to the old file
+ //
+ if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) {
+ OldFile = TRUE;
+ }
+
+ if (OldFile) {
+ //
+ // if the file is read only, so can not write back to it.
+ //
+ if (MainEditor.FileBuffer->ReadOnly == TRUE) {
+ StatusBarSetStatusString (L"Access Denied");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if the file exists
+ //
+ if (ShellFileExists (FileName) != EFI_NOT_FOUND) {
+ //
+ // check for read only
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Open Failed");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+
+ Info = ShellGetFileInfo (FileHandle);
+ if (Info == NULL) {
+ StatusBarSetStatusString (L"Access Denied");
+ FreePool (FileName);
+ return (EFI_SUCCESS);
+ }
+
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ StatusBarSetStatusString (L"Access Denied - Read Only");
+ FreePool (Info);
+ FreePool (FileName);
+ return (EFI_SUCCESS);
+ }
+
+ FreePool (Info);
+
+ //
+ // ask user whether to overwrite this file
+ //
+ Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ while (TRUE) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh ();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString ()[0]) {
+ case L'y':
+ case L'Y':
+ break;
+
+ case L'n':
+ case L'N':
+ case L'c':
+ case L'C':
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ } // end switch
+ } // while (!done)
+ } // file does exist
+ } // if old file name same
+
+ //
+ // save file to disk with specified name
+ //
+ FileBufferSetModified ();
+ Status = FileBufferSave (FileName);
+ SHELL_FREE_NON_NULL (FileName);
+
+ return Status;
+}
+
+/**
+ Show help information for the editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandDisplayHelp (
+ VOID
+ )
+{
+ INT32 CurrentLine;
+ CHAR16 *InfoString;
+ EFI_KEY_DATA KeyData;
+ EFI_STATUS Status;
+ UINTN EventIndex;
+
+ //
+ // print helpInfo
+ //
+ for (CurrentLine = 0; 0 != MainMenuHelpInfo[CurrentLine]; CurrentLine++) {
+ InfoString = HiiGetString (gShellDebug1HiiHandle, MainMenuHelpInfo[CurrentLine], NULL);
+ ShellPrintEx (0, CurrentLine+1, L"%E%s%N", InfoString);
+ }
+
+ //
+ // scan for ctrl+w
+ //
+ while (TRUE) {
+ Status = gBS->WaitForEvent (1, &MainEditor.TextInputEx->WaitForKeyEx, &EventIndex);
+ if (EFI_ERROR (Status) || (EventIndex != 0)) {
+ continue;
+ }
+
+ Status = MainEditor.TextInputEx->ReadKeyStrokeEx (MainEditor.TextInputEx, &KeyData);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) ||
+ (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID))
+ {
+ //
+ // For consoles that don't support/report shift state,
+ // CTRL+W is translated to L'W' - L'A' + 1.
+ //
+ if (KeyData.Key.UnicodeChar == L'W' - L'A' + 1) {
+ break;
+ }
+ } else if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) &&
+ ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) &&
+ ((KeyData.KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) == 0))
+ {
+ //
+ // For consoles that supports/reports shift state,
+ // make sure that only CONTROL shift key is pressed.
+ //
+ if ((KeyData.Key.UnicodeChar == 'w') || (KeyData.Key.UnicodeChar == 'W')) {
+ break;
+ }
+ }
+ }
+
+ //
+ // update screen with file buffer's info
+ //
+ FileBufferRestorePosition ();
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors;
+INTN OriginalMode;
+
+//
+// basic initialization for MainEditor
+//
+EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {
+ &FileBuffer,
+ {
+ { 0, 0}
+ },
+ {
+ 0,
+ 0
+ },
+ NULL,
+ NULL,
+ FALSE,
+ NULL
+};
+
+/**
+ The initialization function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainEditorInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // basic initialization
+ //
+ CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor));
+
+ //
+ // set screen attributes
+ //
+ MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
+
+ MainEditor.ColorAttributes.Colors.Background = (UINT8)(gST->ConOut->Mode->Attribute >> 4);
+ OriginalColors = MainEditor.ColorAttributes.Colors;
+
+ OriginalMode = gST->ConOut->Mode->Mode;
+
+ //
+ // query screen size
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &(MainEditor.ScreenSize.Column),
+ &(MainEditor.ScreenSize.Row)
+ );
+
+ //
+ // Find TextInEx in System Table ConsoleInHandle
+ // Per UEFI Spec, TextInEx is required for a console capable platform.
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConsoleInHandle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID **)&MainEditor.TextInputEx
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Find mouse in System Table ConsoleInHandle
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConsoleInHandle,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID **)&MainEditor.MouseInterface
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is no Simple Pointer Protocol on System Table
+ //
+ HandleBuffer = NULL;
+ MainEditor.MouseInterface = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimplePointerProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status) && (HandleCount > 0)) {
+ //
+ // Try to find the first available mouse device
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSimplePointerProtocolGuid,
+ (VOID **)&MainEditor.MouseInterface
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ }
+
+ if (!EFI_ERROR (Status) && (MainEditor.MouseInterface != NULL)) {
+ MainEditor.MouseAccumulatorX = 0;
+ MainEditor.MouseAccumulatorY = 0;
+ MainEditor.MouseSupported = TRUE;
+ }
+
+ //
+ // below will call the five components' init function
+ //
+ Status = MainTitleBarInit (L"UEFI EDIT");
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = ControlHotKeyInit (MainControlBasedMenuFunctions);
+ Status = MenuBarInit (MainMenuItems);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = StatusBarInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ InputBarInit (MainEditor.TextInputEx);
+
+ Status = FileBufferInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // clear whole screen and enable cursor
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ //
+ // initialize EditorFirst and EditorExit
+ //
+ EditorFirst = TRUE;
+ EditorExit = FALSE;
+ EditorMouseAction = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainEditorCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // call the five components' cleanup function
+ // if error, do not exit
+ // just print some warning
+ //
+ MainTitleBarCleanup ();
+ StatusBarCleanup ();
+ InputBarCleanup ();
+ MenuBarCleanup ();
+
+ Status = FileBufferCleanup ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle);
+ }
+
+ //
+ // restore old mode
+ //
+ if (OriginalMode != gST->ConOut->Mode->Mode) {
+ gST->ConOut->SetMode (gST->ConOut, OriginalMode);
+ }
+
+ //
+ // restore old screen color
+ //
+ gST->ConOut->SetAttribute (
+ gST->ConOut,
+ EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background)
+ );
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Refresh the main editor component.
+**/
+VOID
+MainEditorRefresh (
+ VOID
+ )
+{
+ //
+ // The Stall value is from experience. NOT from spec. avoids 'flicker'
+ //
+ gBS->Stall (50);
+
+ //
+ // call the components refresh function
+ //
+ if ( EditorFirst
+ || (StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0)
+ || (FileBufferBackupVar.FileType != FileBuffer.FileType)
+ || (FileBufferBackupVar.FileModified != FileBuffer.FileModified)
+ || (FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly))
+ {
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
+ FileBufferRestorePosition ();
+ }
+
+ if ( EditorFirst
+ || (FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row)
+ || (FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column)
+ || (FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert)
+ || StatusBarGetRefresh ())
+ {
+ StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert);
+ FileBufferRestorePosition ();
+ }
+
+ if (EditorFirst) {
+ FileBufferRestorePosition ();
+ }
+
+ FileBufferRefresh ();
+
+ //
+ // EditorFirst is now set to FALSE
+ //
+ EditorFirst = FALSE;
+}
+
+/**
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.
+
+ @param[in] GuidX The relative mouse movement.
+
+ @return The X location of the mouse.
+**/
+INT32
+GetTextX (
+ IN INT32 GuidX
+ )
+{
+ INT32 Gap;
+
+ MainEditor.MouseAccumulatorX += GuidX;
+ Gap = (MainEditor.MouseAccumulatorX * (INT32)MainEditor.ScreenSize.Column) / (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionX);
+ MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32)MainEditor.ScreenSize.Column) % (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionX);
+ MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32)MainEditor.ScreenSize.Column;
+ return Gap;
+}
+
+/**
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.
+
+ @param[in] GuidY The relative mouse movement.
+
+ @return The Y location of the mouse.
+**/
+INT32
+GetTextY (
+ IN INT32 GuidY
+ )
+{
+ INT32 Gap;
+
+ MainEditor.MouseAccumulatorY += GuidY;
+ Gap = (MainEditor.MouseAccumulatorY * (INT32)MainEditor.ScreenSize.Row) / (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionY);
+ MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32)MainEditor.ScreenSize.Row) % (INT32)(50 * (INT32)MainEditor.MouseInterface->Mode->ResolutionY);
+ MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32)MainEditor.ScreenSize.Row;
+
+ return Gap;
+}
+
+/**
+ Support mouse movement. Move the cursor.
+
+ @param[in] MouseState The current mouse state.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND There was no mouse support found.
+**/
+EFI_STATUS
+MainEditorHandleMouseInput (
+ IN EFI_SIMPLE_POINTER_STATE MouseState
+ )
+{
+ INT32 TextX;
+ INT32 TextY;
+ UINTN FRow;
+ UINTN FCol;
+
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+
+ UINTN Index;
+ BOOLEAN Action;
+
+ //
+ // mouse action means:
+ // mouse movement
+ // mouse left button
+ //
+ Action = FALSE;
+
+ //
+ // have mouse movement
+ //
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
+ //
+ // handle
+ //
+ TextX = GetTextX (MouseState.RelativeMovementX);
+ TextY = GetTextY (MouseState.RelativeMovementY);
+
+ FileBufferAdjustMousePosition (TextX, TextY);
+
+ Action = TRUE;
+ }
+
+ //
+ // if left button pushed down
+ //
+ if (MouseState.LeftButton) {
+ FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1;
+
+ FRow = MainEditor.FileBuffer->FilePosition.Row +
+ MainEditor.FileBuffer->MousePosition.Row -
+ MainEditor.FileBuffer->DisplayPosition.Row;
+
+ //
+ // beyond the file line length
+ //
+ if (MainEditor.FileBuffer->NumLines < FRow) {
+ FRow = MainEditor.FileBuffer->NumLines;
+ }
+
+ Link = MainEditor.FileBuffer->ListHead->ForwardLink;
+ for (Index = 0; Index < FRow - 1; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // beyond the line's column length
+ //
+ if (FCol > Line->Size + 1) {
+ FCol = Line->Size + 1;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row;
+
+ MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column;
+
+ Action = TRUE;
+ }
+
+ //
+ // mouse has action
+ //
+ if (Action) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // no mouse action
+ //
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Handle user key input. This routes to other functions for the actions.
+
+ @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
+MainEditorKeyInput (
+ VOID
+ )
+{
+ EFI_KEY_DATA KeyData;
+ EFI_STATUS Status;
+ EFI_SIMPLE_POINTER_STATE MouseState;
+ BOOLEAN NoShiftState;
+
+ do {
+ Status = EFI_SUCCESS;
+ EditorMouseAction = FALSE;
+
+ //
+ // backup some key elements, so that can aVOID some refresh work
+ //
+ MainEditorBackup ();
+
+ //
+ // change priority of checking mouse/keyboard activity dynamically
+ // so prevent starvation of keyboard.
+ // if last time, mouse moves then this time check keyboard
+ //
+ if (MainEditor.MouseSupported) {
+ Status = MainEditor.MouseInterface->GetState (
+ MainEditor.MouseInterface,
+ &MouseState
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = MainEditorHandleMouseInput (MouseState);
+
+ if (!EFI_ERROR (Status)) {
+ EditorMouseAction = TRUE;
+ FileBufferMouseNeedRefresh = TRUE;
+ } else if (Status == EFI_LOAD_ERROR) {
+ StatusBarSetStatusString (L"Invalid Mouse Movement ");
+ }
+ }
+ }
+
+ //
+ // CheckEvent() returns Success when non-partial key is pressed.
+ //
+ Status = gBS->CheckEvent (MainEditor.TextInputEx->WaitForKeyEx);
+ if (!EFI_ERROR (Status)) {
+ Status = MainEditor.TextInputEx->ReadKeyStrokeEx (MainEditor.TextInputEx, &KeyData);
+ if (!EFI_ERROR (Status)) {
+ //
+ // dispatch to different components' key handling function
+ // so not everywhere has to set this variable
+ //
+ FileBufferMouseNeedRefresh = TRUE;
+ //
+ // clear previous status string
+ //
+ StatusBarSetRefresh ();
+ //
+ // NoShiftState: TRUE when no shift key is pressed.
+ //
+ NoShiftState = ((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID);
+ //
+ // dispatch to different components' key handling function
+ //
+ if (EFI_NOT_FOUND != MenuBarDispatchControlHotKey (&KeyData)) {
+ Status = EFI_SUCCESS;
+ } else if (NoShiftState && ((KeyData.Key.ScanCode == SCAN_NULL) || ((KeyData.Key.ScanCode >= SCAN_UP) && (KeyData.Key.ScanCode <= SCAN_PAGE_DOWN)))) {
+ Status = FileBufferHandleInput (&KeyData.Key);
+ } else if (NoShiftState && (KeyData.Key.ScanCode >= SCAN_F1) && (KeyData.Key.ScanCode <= SCAN_F12)) {
+ Status = MenuBarDispatchFunctionKey (&KeyData.Key);
+ } else {
+ StatusBarSetStatusString (L"Unknown Command");
+ FileBufferMouseNeedRefresh = FALSE;
+ }
+
+ if ((Status != EFI_SUCCESS) && (Status != EFI_OUT_OF_RESOURCES)) {
+ //
+ // not already has some error status
+ //
+ if ((StatusBarGetString () != NULL) && (StrCmp (L"", StatusBarGetString ()) == 0)) {
+ StatusBarSetStatusString (L"Disk Error. Try Again");
+ }
+ }
+ }
+ }
+
+ //
+ // after handling, refresh editor
+ //
+ MainEditorRefresh ();
+ } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);
+
+ return Status;
+}
+
+/**
+ Set clipboard
+
+ @param[in] Line A pointer to the line to be set to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+MainEditorSetCutLine (
+ EFI_EDITOR_LINE *Line
+ )
+{
+ if (Line == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if (MainEditor.CutLine != NULL) {
+ //
+ // free the old clipboard
+ //
+ LineFree (MainEditor.CutLine);
+ }
+
+ //
+ // duplicate the line to clipboard
+ //
+ MainEditor.CutLine = LineDup (Line);
+ if (MainEditor.CutLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainEditorBackup (
+ VOID
+ )
+{
+ FileBufferBackup ();
+
+ return EFI_SUCCESS;
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
index b22b6587bf..8ee024c8bf 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
@@ -1,66 +1,66 @@
-/** @file
- Declares editor interface functions.
-
- Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _LIB_EDITOR_H_
-#define _LIB_EDITOR_H_
-
-#include "TextEditorTypes.h"
-
-/**
- The initialization function for MainEditor.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainEditorInit (
- VOID
- );
-
-/**
- The cleanup function for MainEditor.
-
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occurred.
-**/
-EFI_STATUS
-MainEditorCleanup (
- VOID
- );
-
-/**
- Refresh the main editor component.
-**/
-VOID
-MainEditorRefresh (
- VOID
- );
-
-/**
- Handle user key input. This routes to other functions for the actions.
-
- @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
-MainEditorKeyInput (
- VOID
- );
-
-/**
- Backup function for MainEditor
-
- @retval EFI_SUCCESS The operation was successful.
-**/
-EFI_STATUS
-MainEditorBackup (
- VOID
- );
-
-#endif
+/** @file
+ Declares editor interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LIB_EDITOR_H_
+#define _LIB_EDITOR_H_
+
+#include "TextEditorTypes.h"
+
+/**
+ The initialization function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainEditorInit (
+ VOID
+ );
+
+/**
+ The cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occurred.
+**/
+EFI_STATUS
+MainEditorCleanup (
+ VOID
+ );
+
+/**
+ Refresh the main editor component.
+**/
+VOID
+MainEditorRefresh (
+ VOID
+ );
+
+/**
+ Handle user key input. This routes to other functions for the actions.
+
+ @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
+MainEditorKeyInput (
+ VOID
+ );
+
+/**
+ Backup function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainEditorBackup (
+ VOID
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c
index fc77fe4068..d7f72903d5 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c
@@ -1,75 +1,75 @@
-/** @file
- Implementation of various string and line routines.
-
- Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "TextEditor.h"
-#include "Misc.h"
-
-/**
- Duplicate a EFI_EDITOR_LINE structure.
-
- @param Src The line structure to copy from.
-
- @retval NULL A memory allocation failed.
- @return a pointer to the newly allcoated line.
-**/
-EFI_EDITOR_LINE *
-LineDup (
- IN EFI_EDITOR_LINE *Src
- )
-{
- EFI_EDITOR_LINE *Dest;
-
- //
- // allocate for the line structure
- //
- Dest = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
- if (Dest == NULL) {
- return NULL;
- }
-
- //
- // allocate and set the line buffer
- //
- Dest->Buffer = CatSPrint (NULL, L"%s", Src->Buffer);
- if (Dest->Buffer == NULL) {
- FreePool (Dest);
- return NULL;
- }
-
- //
- // set the other structure members
- //
- Dest->Signature = LINE_LIST_SIGNATURE;
- Dest->Size = Src->Size;
- Dest->TotalSize = Dest->Size;
- Dest->Type = Src->Type;
- Dest->Link = Src->Link;
-
- return Dest;
-}
-
-/**
- Free a EFI_EDITOR_LINE structure.
-
- @param Src The line structure to free.
-**/
-VOID
-LineFree (
- IN EFI_EDITOR_LINE *Src
- )
-{
- if (Src == NULL) {
- return;
- }
-
- //
- // free the line buffer and then the line structure itself
- //
- SHELL_FREE_NON_NULL (Src->Buffer);
- SHELL_FREE_NON_NULL (Src);
-}
+/** @file
+ Implementation of various string and line routines.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TextEditor.h"
+#include "Misc.h"
+
+/**
+ Duplicate a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to copy from.
+
+ @retval NULL A memory allocation failed.
+ @return a pointer to the newly allcoated line.
+**/
+EFI_EDITOR_LINE *
+LineDup (
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ EFI_EDITOR_LINE *Dest;
+
+ //
+ // allocate for the line structure
+ //
+ Dest = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (Dest == NULL) {
+ return NULL;
+ }
+
+ //
+ // allocate and set the line buffer
+ //
+ Dest->Buffer = CatSPrint (NULL, L"%s", Src->Buffer);
+ if (Dest->Buffer == NULL) {
+ FreePool (Dest);
+ return NULL;
+ }
+
+ //
+ // set the other structure members
+ //
+ Dest->Signature = LINE_LIST_SIGNATURE;
+ Dest->Size = Src->Size;
+ Dest->TotalSize = Dest->Size;
+ Dest->Type = Src->Type;
+ Dest->Link = Src->Link;
+
+ return Dest;
+}
+
+/**
+ Free a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to free.
+**/
+VOID
+LineFree (
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ if (Src == NULL) {
+ return;
+ }
+
+ //
+ // free the line buffer and then the line structure itself
+ //
+ SHELL_FREE_NON_NULL (Src->Buffer);
+ SHELL_FREE_NON_NULL (Src);
+}
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h
index c3abb47576..31c60d7a9f 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h
@@ -1,37 +1,37 @@
-/** @file
- Declares generic editor helper functions.
-
- Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _LIB_MISC_H_
-#define _LIB_MISC_H_
-
-#include "TextEditorTypes.h"
-
-/**
- Free a EFI_EDITOR_LINE structure.
-
- @param Src The line structure to free.
-**/
-VOID
-LineFree (
- IN EFI_EDITOR_LINE *Src
- );
-
-/**
- Duplicate a EFI_EDITOR_LINE structure.
-
- @param Src The line structure to copy from.
-
- @retval NULL A memory allocation failed.
- @return a pointer to the newly allcoated line.
-**/
-EFI_EDITOR_LINE *
-LineDup (
- IN EFI_EDITOR_LINE *Src
- );
-
-#endif
+/** @file
+ Declares generic editor helper functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LIB_MISC_H_
+#define _LIB_MISC_H_
+
+#include "TextEditorTypes.h"
+
+/**
+ Free a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to free.
+**/
+VOID
+LineFree (
+ IN EFI_EDITOR_LINE *Src
+ );
+
+/**
+ Duplicate a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to copy from.
+
+ @retval NULL A memory allocation failed.
+ @return a pointer to the newly allcoated line.
+**/
+EFI_EDITOR_LINE *
+LineDup (
+ IN EFI_EDITOR_LINE *Src
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni
index f38221dfeb..cca4cafb9c 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni
@@ -1,69 +1,69 @@
-// /**
-//
-// Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// Abstract:
-//
-// Additional string definitions for UEFI Shell 2.0 Debug1 profile Edit command
-//
-//
-// **/
-
-/=#
-
-#langdef en-US "english"
-
-#string STR_EDIT_LIBEDITOR_TITLEBAR #language en-US "%EMainEditor init failed on TitleBar init\r\n%N"
-#string STR_EDIT_LIBEDITOR_MAINMENU #language en-US "%EMainEditor init was not successful on MainMenu init\r\n%N"
-#string STR_EDIT_LIBEDITOR_STATUSBAR #language en-US "%EMainEditor init was not successful on StatusBar init\r\n%N"
-#string STR_EDIT_LIBEDITOR_INPUTBAR #language en-US "%EMainEditor init was not successful on InputBar init\r\n%N"
-#string STR_EDIT_LIBEDITOR_FILEBUFFER #language en-US "%EMainEditor init was not successful on FileBuffer init\r\n%N"
-#string STR_EDIT_LIBEDITOR_TITLEBAR_CLEANUP #language en-US "TitleBar cleanup was not successful\r\n"
-#string STR_EDIT_LIBEDITOR_MENUBAR_CLEANUP #language en-US "MenuBar cleanup was not successful\r\n"
-#string STR_EDIT_LIBEDITOR_STATUSBAR_CLEANUP #language en-US "StatusBar cleanup was not successful\r\n"
-#string STR_EDIT_LIBEDITOR_INPUTBAR_CLEANUP #language en-US "InputBar cleanup was not successful\r\n"
-#string STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP #language en-US "FileBuffer cleanup was not successful\r\n"
-#string STR_EDIT_LIBEDITOR_MAINEDITOR_INIT #language en-US "%EMainEditor init was not succesful on TitleBar init\r\n%N"
-#string STR_EDIT_LIBINPUTBAR_MAININPUTBAR #language en-US "%s"
-#string STR_EDIT_LIBMENUBAR_OPEN_FILE #language en-US "Open File"
-#string STR_EDIT_LIBMENUBAR_SAVE_FILE #language en-US "Save File"
-#string STR_EDIT_LIBMENUBAR_EXIT #language en-US "Exit"
-#string STR_EDIT_LIBMENUBAR_CUT_LINE #language en-US "Cut Line"
-#string STR_EDIT_LIBMENUBAR_PASTE_LINE #language en-US "Paste Line"
-#string STR_EDIT_LIBMENUBAR_GO_TO_LINE #language en-US "Go To Line"
-#string STR_EDIT_LIBMENUBAR_SEARCH #language en-US "Search"
-#string STR_EDIT_LIBMENUBAR_SEARCH_REPLACE #language en-US "Search/Replace"
-#string STR_EDIT_LIBMENUBAR_FILE_TYPE #language en-US "File Type"
-#string STR_EDIT_LIBMENUBAR_F1 #language en-US "F1"
-#string STR_EDIT_LIBMENUBAR_F2 #language en-US "F2"
-#string STR_EDIT_LIBMENUBAR_F3 #language en-US "F3"
-#string STR_EDIT_LIBMENUBAR_F4 #language en-US "F4"
-#string STR_EDIT_LIBMENUBAR_F5 #language en-US "F5"
-#string STR_EDIT_LIBMENUBAR_F6 #language en-US "F6"
-#string STR_EDIT_LIBMENUBAR_F7 #language en-US "F7"
-#string STR_EDIT_LIBMENUBAR_F8 #language en-US "F8"
-#string STR_EDIT_LIBMENUBAR_F9 #language en-US "F9"
-#string STR_EDIT_LIBMENUBAR_F10 #language en-US "F10"
-#string STR_EDIT_LIBMENUBAR_F11 #language en-US "F11"
-#string STR_EDIT_LIBMENUBAR_F12 #language en-US "F12"
-#string STR_EDIT_LIBMENUBAR_CTRL_E #language en-US "Ctrl+E"
-#string STR_EDIT_LIBMENUBAR_CTRL_W #language en-US "Ctrl+W"
-#string STR_EDIT_HELP_TITLE #language en-US "Help \n"
-#string STR_EDIT_HELP_BLANK #language en-US " \n"
-#string STR_EDIT_HELP_LIST_TITLE #language en-US "Control Key Function Key Command \n"
-#string STR_EDIT_HELP_DIV #language en-US "----------- ------------ ----------------- \n"
-#string STR_EDIT_HELP_GO_TO_LINE #language en-US "Ctrl-G F1 Go To Line \n"
-#string STR_EDIT_HELP_SAVE_FILE #language en-US "Ctrl-S F2 Save File \n"
-#string STR_EDIT_HELP_EXIT #language en-US "Ctrl-Q F3 Exit \n"
-#string STR_EDIT_HELP_SEARCH #language en-US "Ctrl-F F4 Search \n"
-#string STR_EDIT_HELP_SEARCH_REPLACE #language en-US "Ctrl-R F5 Search/Replace \n"
-#string STR_EDIT_HELP_CUT_LINE #language en-US "Ctrl-K F6 Cut Line \n"
-#string STR_EDIT_HELP_PASTE_LINE #language en-US "Ctrl-U F7 Paste Line \n"
-#string STR_EDIT_HELP_OPEN_FILE #language en-US "Ctrl-O F8 Open File \n"
-#string STR_EDIT_HELP_FILE_TYPE #language en-US "Ctrl-T F9 File Type \n"
-#string STR_EDIT_HELP_EXIT_HELP #language en-US "Use Ctrl-W to exit this help \n"
-#string STR_EDIT_MAIN_INVALID_FILE_NAME #language en-US "%Hedit%N: Invalid File Name\r\n"
-#string STR_EDIT_MAIN_INIT_FAILED #language en-US "%Hedit%N: Initialization was not successful\r\n"
-#string STR_EDIT_MAIN_BUFFER #language en-US "%Hedit%N: %s\r\n"
-#string STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR #language en-US "%Hedit%N: Unknown Editor Error\r\n"
+// /**
+//
+// Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Abstract:
+//
+// Additional string definitions for UEFI Shell 2.0 Debug1 profile Edit command
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_EDIT_LIBEDITOR_TITLEBAR #language en-US "%EMainEditor init failed on TitleBar init\r\n%N"
+#string STR_EDIT_LIBEDITOR_MAINMENU #language en-US "%EMainEditor init was not successful on MainMenu init\r\n%N"
+#string STR_EDIT_LIBEDITOR_STATUSBAR #language en-US "%EMainEditor init was not successful on StatusBar init\r\n%N"
+#string STR_EDIT_LIBEDITOR_INPUTBAR #language en-US "%EMainEditor init was not successful on InputBar init\r\n%N"
+#string STR_EDIT_LIBEDITOR_FILEBUFFER #language en-US "%EMainEditor init was not successful on FileBuffer init\r\n%N"
+#string STR_EDIT_LIBEDITOR_TITLEBAR_CLEANUP #language en-US "TitleBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_MENUBAR_CLEANUP #language en-US "MenuBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_STATUSBAR_CLEANUP #language en-US "StatusBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_INPUTBAR_CLEANUP #language en-US "InputBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP #language en-US "FileBuffer cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_MAINEDITOR_INIT #language en-US "%EMainEditor init was not succesful on TitleBar init\r\n%N"
+#string STR_EDIT_LIBINPUTBAR_MAININPUTBAR #language en-US "%s"
+#string STR_EDIT_LIBMENUBAR_OPEN_FILE #language en-US "Open File"
+#string STR_EDIT_LIBMENUBAR_SAVE_FILE #language en-US "Save File"
+#string STR_EDIT_LIBMENUBAR_EXIT #language en-US "Exit"
+#string STR_EDIT_LIBMENUBAR_CUT_LINE #language en-US "Cut Line"
+#string STR_EDIT_LIBMENUBAR_PASTE_LINE #language en-US "Paste Line"
+#string STR_EDIT_LIBMENUBAR_GO_TO_LINE #language en-US "Go To Line"
+#string STR_EDIT_LIBMENUBAR_SEARCH #language en-US "Search"
+#string STR_EDIT_LIBMENUBAR_SEARCH_REPLACE #language en-US "Search/Replace"
+#string STR_EDIT_LIBMENUBAR_FILE_TYPE #language en-US "File Type"
+#string STR_EDIT_LIBMENUBAR_F1 #language en-US "F1"
+#string STR_EDIT_LIBMENUBAR_F2 #language en-US "F2"
+#string STR_EDIT_LIBMENUBAR_F3 #language en-US "F3"
+#string STR_EDIT_LIBMENUBAR_F4 #language en-US "F4"
+#string STR_EDIT_LIBMENUBAR_F5 #language en-US "F5"
+#string STR_EDIT_LIBMENUBAR_F6 #language en-US "F6"
+#string STR_EDIT_LIBMENUBAR_F7 #language en-US "F7"
+#string STR_EDIT_LIBMENUBAR_F8 #language en-US "F8"
+#string STR_EDIT_LIBMENUBAR_F9 #language en-US "F9"
+#string STR_EDIT_LIBMENUBAR_F10 #language en-US "F10"
+#string STR_EDIT_LIBMENUBAR_F11 #language en-US "F11"
+#string STR_EDIT_LIBMENUBAR_F12 #language en-US "F12"
+#string STR_EDIT_LIBMENUBAR_CTRL_E #language en-US "Ctrl+E"
+#string STR_EDIT_LIBMENUBAR_CTRL_W #language en-US "Ctrl+W"
+#string STR_EDIT_HELP_TITLE #language en-US "Help \n"
+#string STR_EDIT_HELP_BLANK #language en-US " \n"
+#string STR_EDIT_HELP_LIST_TITLE #language en-US "Control Key Function Key Command \n"
+#string STR_EDIT_HELP_DIV #language en-US "----------- ------------ ----------------- \n"
+#string STR_EDIT_HELP_GO_TO_LINE #language en-US "Ctrl-G F1 Go To Line \n"
+#string STR_EDIT_HELP_SAVE_FILE #language en-US "Ctrl-S F2 Save File \n"
+#string STR_EDIT_HELP_EXIT #language en-US "Ctrl-Q F3 Exit \n"
+#string STR_EDIT_HELP_SEARCH #language en-US "Ctrl-F F4 Search \n"
+#string STR_EDIT_HELP_SEARCH_REPLACE #language en-US "Ctrl-R F5 Search/Replace \n"
+#string STR_EDIT_HELP_CUT_LINE #language en-US "Ctrl-K F6 Cut Line \n"
+#string STR_EDIT_HELP_PASTE_LINE #language en-US "Ctrl-U F7 Paste Line \n"
+#string STR_EDIT_HELP_OPEN_FILE #language en-US "Ctrl-O F8 Open File \n"
+#string STR_EDIT_HELP_FILE_TYPE #language en-US "Ctrl-T F9 File Type \n"
+#string STR_EDIT_HELP_EXIT_HELP #language en-US "Use Ctrl-W to exit this help \n"
+#string STR_EDIT_MAIN_INVALID_FILE_NAME #language en-US "%Hedit%N: Invalid File Name\r\n"
+#string STR_EDIT_MAIN_INIT_FAILED #language en-US "%Hedit%N: Initialization was not successful\r\n"
+#string STR_EDIT_MAIN_BUFFER #language en-US "%Hedit%N: %s\r\n"
+#string STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR #language en-US "%Hedit%N: Unknown Editor Error\r\n"
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h
index 4ffc6faad3..b087950bf8 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h
@@ -1,26 +1,26 @@
-/** @file
- Main include file for Edit shell Debug1 function.
-
- Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _EFI_EDIT_H_
-#define _EFI_EDIT_H_
-
-#include "TextEditorTypes.h"
-
-#include "MainTextEditor.h"
-#include "FileBuffer.h"
-#include "EditTitleBar.h"
-#include "EditStatusBar.h"
-#include "EditInputBar.h"
-#include "EditMenuBar.h"
-#include "Misc.h"
-
-extern EFI_EDITOR_GLOBAL_EDITOR MainEditor;
-extern BOOLEAN EditorFirst;
-extern BOOLEAN EditorExit;
-
-#endif // _EFI_EDIT_H_
+/** @file
+ Main include file for Edit shell Debug1 function.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_EDIT_H_
+#define _EFI_EDIT_H_
+
+#include "TextEditorTypes.h"
+
+#include "MainTextEditor.h"
+#include "FileBuffer.h"
+#include "EditTitleBar.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+#include "EditMenuBar.h"
+#include "Misc.h"
+
+extern EFI_EDITOR_GLOBAL_EDITOR MainEditor;
+extern BOOLEAN EditorFirst;
+extern BOOLEAN EditorExit;
+
+#endif // _EFI_EDIT_H_
diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
index a4dd09a7ce..28051e2ffb 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
@@ -1,96 +1,96 @@
-/** @file
- Declares editor types.
-
- Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _EDITOR_TYPE_H_
-#define _EDITOR_TYPE_H_
-
-#include "UefiShellDebug1CommandsLib.h"
-#include "EditTitleBar.h"
-#include "EditMenuBar.h"
-
-#define MIN_POOL_SIZE 125
-#define MAX_STRING_LENGTH 127
-
-typedef struct {
- UINTN Row;
- UINTN Column;
-} EFI_EDITOR_POSITION;
-
-typedef
-EFI_STATUS
-(*EFI_MENU_ITEM_FUNCTION) (
- VOID
- );
-
-typedef enum {
- NewLineTypeDefault,
- NewLineTypeLineFeed,
- NewLineTypeCarriageReturn,
- NewLineTypeCarriageReturnLineFeed,
- NewLineTypeLineFeedCarriageReturn,
- NewLineTypeUnknown
-} EE_NEWLINE_TYPE;
-
-#define LINE_LIST_SIGNATURE SIGNATURE_32 ('e', 'e', 'l', 'l')
-typedef struct _EFI_EDITOR_LINE {
- UINTN Signature;
- CHAR16 *Buffer;
- UINTN Size; // unit is Unicode
- UINTN TotalSize; // unit is Unicode, exclude CHAR_NULL
- EE_NEWLINE_TYPE Type;
- LIST_ENTRY Link;
-} EFI_EDITOR_LINE;
-
-typedef struct {
- UINT32 Foreground : 4;
- UINT32 Background : 4;
-} EFI_EDITOR_COLOR_ATTRIBUTES;
-
-typedef union {
- EFI_EDITOR_COLOR_ATTRIBUTES Colors;
- UINTN Data;
-} EFI_EDITOR_COLOR_UNION;
-
-typedef struct {
- UINTN Columns;
- UINTN Rows;
-} EFI_EDITOR_TEXT_MODE;
-
-typedef struct {
- CHAR16 *FileName; // file name current edited in editor
- EDIT_FILE_TYPE FileType; // Unicode file or ASCII file
- LIST_ENTRY *ListHead; // list head of lines
- EFI_EDITOR_LINE *Lines; // lines of current file
- UINTN NumLines; // total line numbers
- EFI_EDITOR_POSITION DisplayPosition; // cursor position in screen
- EFI_EDITOR_POSITION FilePosition; // cursor position in file
- EFI_EDITOR_POSITION MousePosition; // mouse position in screen
- // file position of first byte displayed on screen
- //
- EFI_EDITOR_POSITION LowVisibleRange;
-
- BOOLEAN FileModified; // file is modified or not
- BOOLEAN ModeInsert; // input mode INS or OVR
- BOOLEAN ReadOnly; // file is read-only or not
- EFI_EDITOR_LINE *CurrentLine; // current line cursor is at
-} EFI_EDITOR_FILE_BUFFER;
-
-typedef struct {
- EFI_EDITOR_FILE_BUFFER *FileBuffer;
-
- EFI_EDITOR_COLOR_UNION ColorAttributes;
- EFI_EDITOR_POSITION ScreenSize; // row number and column number
- EFI_EDITOR_LINE *CutLine; // clip board
- EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
- BOOLEAN MouseSupported;
- EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
- INT32 MouseAccumulatorX;
- INT32 MouseAccumulatorY;
-} EFI_EDITOR_GLOBAL_EDITOR;
-
-#endif
+/** @file
+ Declares editor types.
+
+ Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EDITOR_TYPE_H_
+#define _EDITOR_TYPE_H_
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "EditTitleBar.h"
+#include "EditMenuBar.h"
+
+#define MIN_POOL_SIZE 125
+#define MAX_STRING_LENGTH 127
+
+typedef struct {
+ UINTN Row;
+ UINTN Column;
+} EFI_EDITOR_POSITION;
+
+typedef
+EFI_STATUS
+(*EFI_MENU_ITEM_FUNCTION) (
+ VOID
+ );
+
+typedef enum {
+ NewLineTypeDefault,
+ NewLineTypeLineFeed,
+ NewLineTypeCarriageReturn,
+ NewLineTypeCarriageReturnLineFeed,
+ NewLineTypeLineFeedCarriageReturn,
+ NewLineTypeUnknown
+} EE_NEWLINE_TYPE;
+
+#define LINE_LIST_SIGNATURE SIGNATURE_32 ('e', 'e', 'l', 'l')
+typedef struct _EFI_EDITOR_LINE {
+ UINTN Signature;
+ CHAR16 *Buffer;
+ UINTN Size; // unit is Unicode
+ UINTN TotalSize; // unit is Unicode, exclude CHAR_NULL
+ EE_NEWLINE_TYPE Type;
+ LIST_ENTRY Link;
+} EFI_EDITOR_LINE;
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 4;
+} EFI_EDITOR_COLOR_ATTRIBUTES;
+
+typedef union {
+ EFI_EDITOR_COLOR_ATTRIBUTES Colors;
+ UINTN Data;
+} EFI_EDITOR_COLOR_UNION;
+
+typedef struct {
+ UINTN Columns;
+ UINTN Rows;
+} EFI_EDITOR_TEXT_MODE;
+
+typedef struct {
+ CHAR16 *FileName; // file name current edited in editor
+ EDIT_FILE_TYPE FileType; // Unicode file or ASCII file
+ LIST_ENTRY *ListHead; // list head of lines
+ EFI_EDITOR_LINE *Lines; // lines of current file
+ UINTN NumLines; // total line numbers
+ EFI_EDITOR_POSITION DisplayPosition; // cursor position in screen
+ EFI_EDITOR_POSITION FilePosition; // cursor position in file
+ EFI_EDITOR_POSITION MousePosition; // mouse position in screen
+ // file position of first byte displayed on screen
+ //
+ EFI_EDITOR_POSITION LowVisibleRange;
+
+ BOOLEAN FileModified; // file is modified or not
+ BOOLEAN ModeInsert; // input mode INS or OVR
+ BOOLEAN ReadOnly; // file is read-only or not
+ EFI_EDITOR_LINE *CurrentLine; // current line cursor is at
+} EFI_EDITOR_FILE_BUFFER;
+
+typedef struct {
+ EFI_EDITOR_FILE_BUFFER *FileBuffer;
+
+ EFI_EDITOR_COLOR_UNION ColorAttributes;
+ EFI_EDITOR_POSITION ScreenSize; // row number and column number
+ EFI_EDITOR_LINE *CutLine; // clip board
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
+ BOOLEAN MouseSupported;
+ EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
+ INT32 MouseAccumulatorX;
+ INT32 MouseAccumulatorY;
+} EFI_EDITOR_GLOBAL_EDITOR;
+
+#endif