--- /dev/null
+/** @file\r
+ Main file for Edit shell Debug1 function.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "UefiShellDebug1CommandsLib.h"\r
+#include "TextEditor.h"\r
+\r
+/**\r
+ Function for 'edit' command.\r
+\r
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunEdit (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *Buffer;\r
+ CHAR16 *ProblemParam;\r
+ SHELL_STATUS ShellStatus;\r
+ LIST_ENTRY *Package;\r
+ CONST CHAR16 *Cwd;\r
+ CHAR16 *Nfs;\r
+ CHAR16 *Spot;\r
+// SHELL_FILE_HANDLE TempHandle;\r
+\r
+ Buffer = NULL;\r
+ ShellStatus = SHELL_SUCCESS;\r
+ Nfs = NULL;\r
+\r
+ //\r
+ // initialize the shell lib (we must be in non-auto-init...)\r
+ //\r
+ Status = ShellInitialize();\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ Status = CommandInit();\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ //\r
+ // parse the command line\r
+ //\r
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);\r
+ if (EFI_ERROR(Status)) {\r
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);\r
+ FreePool(ProblemParam);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else {\r
+ ASSERT(FALSE);\r
+ }\r
+ } else {\r
+ if (ShellCommandLineGetCount(Package) > 2) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else {\r
+ Cwd = gEfiShellProtocol->GetCurDir(NULL);\r
+ if (Cwd == NULL) {\r
+ Cwd = ShellGetEnvironmentVariable(L"path");\r
+ if (Cwd != NULL) {\r
+ Nfs = StrnCatGrow(&Nfs, NULL, Cwd+3, 0);\r
+ if (Nfs != NULL) {\r
+ Spot = StrStr(Nfs, L";");\r
+ if (Spot != NULL) {\r
+ *Spot = CHAR_NULL;\r
+ }\r
+ Spot = StrStr(Nfs, L"\\");\r
+ if (Spot != NULL) {\r
+ Spot[1] = CHAR_NULL;\r
+ }\r
+ gEfiShellProtocol->SetCurDir(NULL, Nfs);\r
+ FreePool(Nfs);\r
+ } \r
+ }\r
+ }\r
+\r
+ Status = MainEditorInit ();\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_INIT_FAILED), gShellDebug1HiiHandle);\r
+ } else {\r
+ MainEditorBackup ();\r
+\r
+ //\r
+ // if editor launched with file named\r
+ //\r
+ if (ShellCommandLineGetCount(Package) == 2) {\r
+ FileBufferSetFileName (ShellCommandLineGetRawValue(Package, 1));\r
+// if (EFI_ERROR(ShellFileExists(MainEditor.FileBuffer->FileName))) {\r
+// Status = ShellOpenFileByName(MainEditor.FileBuffer->FileName, &TempHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);\r
+// if (!EFI_ERROR(Status)) {\r
+// ShellCloseFile(&TempHandle);\r
+// }\r
+// }\r
+ }\r
+\r
+ Status = FileBufferRead (MainEditor.FileBuffer->FileName, FALSE);\r
+ if (!EFI_ERROR (Status)) {\r
+ MainEditorRefresh ();\r
+\r
+ Status = MainEditorKeyInput ();\r
+ }\r
+\r
+ if (Status != EFI_OUT_OF_RESOURCES) {\r
+ //\r
+ // back up the status string\r
+ //\r
+ Buffer = CatSPrint (NULL, L"%s", StatusBarGetString());\r
+ }\r
+\r
+ MainEditorCleanup ();\r
+\r
+ //\r
+ // print editor exit code on screen\r
+ //\r
+ if (Status == EFI_SUCCESS) {\r
+ } else if (Status == EFI_OUT_OF_RESOURCES) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_OUT_MEM), gShellDebug1HiiHandle);\r
+ } else {\r
+ if (Buffer != NULL) {\r
+ if (StrCmp (Buffer, L"") != 0) {\r
+ //\r
+ // print out the status string\r
+ //\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_BUFFER), gShellDebug1HiiHandle, Buffer);\r
+ } else {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);\r
+ }\r
+ } else {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);\r
+ }\r
+ }\r
+\r
+ if (Status != EFI_OUT_OF_RESOURCES) {\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ }\r
+ }\r
+ }\r
+ ShellCommandLineFreeVarList (Package);\r
+ }\r
+ return ShellStatus;\r
+}\r
--- /dev/null
+/** @file\r
+ Implements filebuffer interface functions.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TextEditor.h"\r
+#include <Guid/FileSystemInfo.h>\r
+#include <Library/FileHandleLib.h>\r
+\r
+EFI_EDITOR_FILE_BUFFER FileBuffer;\r
+EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;\r
+\r
+//\r
+// for basic initialization of FileBuffer\r
+//\r
+EFI_EDITOR_FILE_BUFFER FileBufferConst = {\r
+ NULL,\r
+ FileTypeUnicode,\r
+ NULL,\r
+ NULL,\r
+ 0,\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ FALSE,\r
+ TRUE,\r
+ FALSE,\r
+ NULL\r
+};\r
+\r
+//\r
+// the whole edit area needs to be refreshed\r
+//\r
+STATIC BOOLEAN FileBufferNeedRefresh;\r
+\r
+//\r
+// only the current line in edit area needs to be refresh\r
+//\r
+BOOLEAN FileBufferOnlyLineNeedRefresh;\r
+\r
+BOOLEAN FileBufferMouseNeedRefresh;\r
+\r
+extern BOOLEAN EditorMouseAction;\r
+\r
+/**\r
+ Initialization function for FileBuffer.\r
+\r
+ @param EFI_SUCCESS The initialization was successful.\r
+ @param EFI_LOAD_ERROR A default name could not be created.\r
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferInit (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // basically initialize the FileBuffer\r
+ //\r
+ CopyMem (&FileBuffer , &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));\r
+ CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));\r
+\r
+ //\r
+ // set default FileName\r
+ //\r
+ FileBuffer.FileName = EditGetDefaultFileName (L"txt");\r
+ if (FileBuffer.FileName == NULL) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));\r
+ if (FileBuffer.ListHead == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ InitializeListHead (FileBuffer.ListHead);\r
+\r
+ FileBuffer.DisplayPosition.Row = 2;\r
+ FileBuffer.DisplayPosition.Column = 1;\r
+ FileBuffer.LowVisibleRange.Row = 2;\r
+ FileBuffer.LowVisibleRange.Column = 1;\r
+\r
+ FileBufferNeedRefresh = FALSE;\r
+ FileBufferMouseNeedRefresh = FALSE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Backup function for FileBuffer. Only backup the following items:\r
+ Mouse/Cursor position\r
+ File Name, Type, ReadOnly, Modified\r
+ Insert Mode\r
+\r
+ This is for making the file buffer refresh as few as possible.\r
+\r
+ @retval EFI_SUCCESS The backup operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferBackup (\r
+ VOID\r
+ )\r
+{\r
+ FileBufferBackupVar.MousePosition = FileBuffer.MousePosition;\r
+\r
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);\r
+ FileBufferBackupVar.FileName = NULL;\r
+ FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0);\r
+\r
+ FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert;\r
+ FileBufferBackupVar.FileType = FileBuffer.FileType;\r
+\r
+ FileBufferBackupVar.FilePosition = FileBuffer.FilePosition;\r
+ FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange;\r
+\r
+ FileBufferBackupVar.FileModified = FileBuffer.FileModified;\r
+ FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Advance to the next Count lines\r
+ \r
+ @param[in] Count The line number to advance by.\r
+ @param[in] CurrentLine The pointer to the current line structure.\r
+ @param[in] LineList The pointer to the linked list of lines.\r
+\r
+ @retval NULL There was an error.\r
+ @return The line structure after the advance.\r
+**/\r
+EFI_EDITOR_LINE *\r
+EFIAPI\r
+InternalEditorMiscLineAdvance (\r
+ IN CONST UINTN Count,\r
+ IN CONST EFI_EDITOR_LINE *CurrentLine,\r
+ IN CONST LIST_ENTRY *LineList\r
+ )\r
+\r
+{\r
+ UINTN Index;\r
+ CONST EFI_EDITOR_LINE *Line;\r
+\r
+ if (CurrentLine == NULL || LineList == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {\r
+ //\r
+ // if already last line\r
+ //\r
+ if (Line->Link.ForwardLink == LineList) {\r
+ return NULL;\r
+ }\r
+\r
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ }\r
+\r
+ return ((EFI_EDITOR_LINE *)Line);\r
+}\r
+\r
+/**\r
+ Retreat to the previous Count lines.\r
+ \r
+ @param[in] Count The line number to retreat by.\r
+ @param[in] CurrentLine The pointer to the current line structure.\r
+ @param[in] LineList The pointer to the linked list of lines.\r
+\r
+ @retval NULL There was an error.\r
+ @return The line structure after the retreat.\r
+**/\r
+EFI_EDITOR_LINE *\r
+EFIAPI\r
+InternalEditorMiscLineRetreat (\r
+ IN CONST UINTN Count,\r
+ IN CONST EFI_EDITOR_LINE *CurrentLine,\r
+ IN CONST LIST_ENTRY *LineList\r
+ )\r
+\r
+{\r
+ UINTN Index;\r
+ CONST EFI_EDITOR_LINE *Line;\r
+\r
+ if (CurrentLine == NULL || LineList == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {\r
+ //\r
+ // already the first line\r
+ //\r
+ if (Line->Link.BackLink == LineList) {\r
+ return NULL;\r
+ }\r
+\r
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ }\r
+\r
+ return ((EFI_EDITOR_LINE *)Line);\r
+}\r
+\r
+/**\r
+ Advance/Retreat lines\r
+ \r
+ @param[in] Count line number to advance/retreat\r
+ >0 : advance\r
+ <0 : retreat\r
+\r
+ @retval NULL An error occured.\r
+ @return The line after advance/retreat.\r
+**/\r
+EFI_EDITOR_LINE *\r
+MoveLine (\r
+ IN CONST INTN Count\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN AbsCount;\r
+\r
+ //\r
+ // if < 0, then retreat\r
+ // if > 0, the advance\r
+ //\r
+ if (Count <= 0) {\r
+ AbsCount = -Count;\r
+ Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);\r
+ } else {\r
+ Line = InternalEditorMiscLineAdvance (Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);\r
+ }\r
+\r
+ return Line;\r
+}\r
+\r
+/**\r
+ Function to update the 'screen' to display the mouse position.\r
+\r
+ @retval EFI_SUCCESS The backup operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferRestoreMousePosition (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_COLOR_UNION Orig;\r
+ EFI_EDITOR_COLOR_UNION New;\r
+ UINTN FRow;\r
+ UINTN FColumn;\r
+ BOOLEAN HasCharacter;\r
+ EFI_EDITOR_LINE *CurrentLine;\r
+ EFI_EDITOR_LINE *Line;\r
+ CHAR16 Value;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ Line = NULL;\r
+\r
+ if (MainEditor.MouseSupported) {\r
+\r
+ if (FileBufferMouseNeedRefresh) {\r
+\r
+ FileBufferMouseNeedRefresh = FALSE;\r
+\r
+ //\r
+ // if mouse position not moved and only mouse action\r
+ // so do not need to refresh mouse position\r
+ //\r
+ if ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row &&\r
+ FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column)\r
+ && EditorMouseAction) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // backup the old screen attributes\r
+ //\r
+ Orig = MainEditor.ColorAttributes;\r
+ New.Colors.Foreground = Orig.Colors.Background;\r
+ New.Colors.Background = Orig.Colors.Foreground;\r
+\r
+ //\r
+ // clear the old mouse position\r
+ //\r
+ FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2;\r
+\r
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1;\r
+\r
+ HasCharacter = TRUE;\r
+ if (FRow > FileBuffer.NumLines) {\r
+ HasCharacter = FALSE;\r
+ } else {\r
+ CurrentLine = FileBuffer.CurrentLine;\r
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);\r
+\r
+ if (FColumn > Line->Size) {\r
+ HasCharacter = FALSE;\r
+ }\r
+\r
+ FileBuffer.CurrentLine = CurrentLine;\r
+ }\r
+\r
+ ShellPrintEx (\r
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,\r
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,\r
+ L" "\r
+ );\r
+\r
+ if (HasCharacter) {\r
+ Value = (Line->Buffer[FColumn - 1]);\r
+ ShellPrintEx (\r
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,\r
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,\r
+ L"%c",\r
+ Value\r
+ );\r
+ }\r
+ //\r
+ // set the new mouse position\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);\r
+\r
+ //\r
+ // clear the old mouse position\r
+ //\r
+ FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2;\r
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1;\r
+\r
+ HasCharacter = TRUE;\r
+ if (FRow > FileBuffer.NumLines) {\r
+ HasCharacter = FALSE;\r
+ } else {\r
+ CurrentLine = FileBuffer.CurrentLine;\r
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);\r
+\r
+ if (FColumn > Line->Size) {\r
+ HasCharacter = FALSE;\r
+ }\r
+\r
+ FileBuffer.CurrentLine = CurrentLine;\r
+ }\r
+\r
+ ShellPrintEx (\r
+ (INT32)FileBuffer.MousePosition.Column - 1,\r
+ (INT32)FileBuffer.MousePosition.Row - 1,\r
+ L" "\r
+ );\r
+\r
+ if (HasCharacter) {\r
+ Value = Line->Buffer[FColumn - 1];\r
+ ShellPrintEx (\r
+ (INT32)FileBuffer.MousePosition.Column - 1,\r
+ (INT32)FileBuffer.MousePosition.Row - 1,\r
+ L"%c",\r
+ Value\r
+ );\r
+ }\r
+ //\r
+ // end of HasCharacter\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ }\r
+ //\r
+ // end of MouseNeedRefresh\r
+ //\r
+ }\r
+ //\r
+ // end of MouseSupported\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Free all the lines in FileBuffer\r
+ Fields affected:\r
+ Lines\r
+ CurrentLine\r
+ NumLines\r
+ ListHead\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferFreeLines (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ EFI_EDITOR_LINE *Line;\r
+\r
+ //\r
+ // free all the lines\r
+ //\r
+ if (FileBuffer.Lines != NULL) {\r
+\r
+ Line = FileBuffer.Lines;\r
+ Link = &(Line->Link);\r
+ do {\r
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ Link = Link->ForwardLink;\r
+\r
+ //\r
+ // free line's buffer and line itself\r
+ //\r
+ LineFree (Line);\r
+ } while (Link != FileBuffer.ListHead);\r
+ }\r
+ //\r
+ // clean the line list related structure\r
+ //\r
+ FileBuffer.Lines = NULL;\r
+ FileBuffer.CurrentLine = NULL;\r
+ FileBuffer.NumLines = 0;\r
+\r
+ FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead;\r
+ FileBuffer.ListHead->BackLink = FileBuffer.ListHead;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Cleanup function for FileBuffer.\r
+\r
+ @retval EFI_SUCCESS The cleanup was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferCleanup (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);\r
+\r
+ //\r
+ // free all the lines\r
+ //\r
+ Status = FileBufferFreeLines ();\r
+\r
+ SHELL_FREE_NON_NULL (FileBuffer.ListHead);\r
+ FileBuffer.ListHead = NULL;\r
+\r
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);\r
+ return Status;\r
+\r
+}\r
+\r
+/**\r
+ Print a line specified by Line on a row specified by Row of the screen.\r
+\r
+ @param[in] Line The line to print.\r
+ @param[in] Row The row on the screen to print onto (begin from 1).\r
+\r
+ @retval EFI_SUCCESS The printing was successful.\r
+**/\r
+EFI_STATUS\r
+FileBufferPrintLine (\r
+ IN CONST EFI_EDITOR_LINE *Line,\r
+ IN CONST UINTN Row\r
+ )\r
+{\r
+\r
+ CHAR16 *Buffer;\r
+ UINTN Limit;\r
+ CHAR16 PrintLine[200];\r
+\r
+ //\r
+ // print start from correct character\r
+ //\r
+ Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1;\r
+\r
+ Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1;\r
+ if (Limit > Line->Size) {\r
+ Limit = 0;\r
+ }\r
+\r
+ StrnCpy (PrintLine, Buffer, Limit > MainEditor.ScreenSize.Column ? MainEditor.ScreenSize.Column : Limit);\r
+ for (; Limit < MainEditor.ScreenSize.Column; Limit++) {\r
+ PrintLine[Limit] = L' ';\r
+ }\r
+\r
+ PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL;\r
+\r
+ ShellPrintEx (\r
+ 0,\r
+ (INT32)Row - 1,\r
+ L"%s",\r
+ PrintLine\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set the cursor position according to FileBuffer.DisplayPosition.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferRestorePosition (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // set cursor position\r
+ //\r
+ return (gST->ConOut->SetCursorPosition (\r
+ gST->ConOut,\r
+ FileBuffer.DisplayPosition.Column - 1,\r
+ FileBuffer.DisplayPosition.Row - 1\r
+ ));\r
+}\r
+\r
+/**\r
+ Refresh the screen with whats in the buffer.\r
+\r
+ @retval EFI_SUCCESS The refresh was successful.\r
+ @retval EFI_LOAD_ERROR There was an error finding what to write.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferRefresh (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN Row;\r
+\r
+ //\r
+ // if it's the first time after editor launch, so should refresh\r
+ //\r
+ if (!EditorFirst) {\r
+ //\r
+ // no definite required refresh\r
+ // and file position displayed on screen has not been changed\r
+ //\r
+ if (!FileBufferNeedRefresh &&\r
+ !FileBufferOnlyLineNeedRefresh &&\r
+ FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&\r
+ FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column\r
+ ) {\r
+\r
+ FileBufferRestoreMousePosition ();\r
+ FileBufferRestorePosition ();\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+ //\r
+ // only need to refresh current line\r
+ //\r
+ if (FileBufferOnlyLineNeedRefresh &&\r
+ FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&\r
+ FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column\r
+ ) {\r
+\r
+ EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);\r
+ FileBufferPrintLine (\r
+ FileBuffer.CurrentLine,\r
+ FileBuffer.DisplayPosition.Row\r
+ );\r
+ } else {\r
+ //\r
+ // the whole edit area need refresh\r
+ //\r
+\r
+ //\r
+ // no line\r
+ //\r
+ if (FileBuffer.Lines == NULL) {\r
+ FileBufferRestoreMousePosition ();\r
+ FileBufferRestorePosition ();\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // get the first line that will be displayed\r
+ //\r
+ Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row);\r
+ if (Line == NULL) {\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Link = &(Line->Link);\r
+ Row = 2;\r
+ do {\r
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ //\r
+ // print line at row\r
+ //\r
+ FileBufferPrintLine (Line, Row);\r
+\r
+ Link = Link->ForwardLink;\r
+ Row++;\r
+ } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 4));\r
+ //\r
+ // while not file end and not screen full\r
+ //\r
+ while (Row <= (MainEditor.ScreenSize.Row - 4)) {\r
+ EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);\r
+ Row++;\r
+ }\r
+ }\r
+\r
+ FileBufferRestoreMousePosition ();\r
+ FileBufferRestorePosition ();\r
+\r
+ FileBufferNeedRefresh = FALSE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Create a new line and append it to the line list.\r
+ Fields affected:\r
+ NumLines\r
+ Lines\r
+\r
+ @retval NULL The create line failed.\r
+ @return The line created.\r
+**/\r
+EFI_EDITOR_LINE *\r
+EFIAPI\r
+FileBufferCreateLine (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+\r
+ //\r
+ // allocate a line structure\r
+ //\r
+ Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));\r
+ if (Line == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // initialize the structure\r
+ //\r
+ Line->Signature = LINE_LIST_SIGNATURE;\r
+ Line->Size = 0;\r
+ Line->TotalSize = 0;\r
+ Line->Type = NewLineTypeDefault;\r
+\r
+ //\r
+ // initial buffer of the line is "\0"\r
+ //\r
+ ASSERT(CHAR_NULL == CHAR_NULL);\r
+ Line->Buffer = CatSPrint (NULL, L"\0");\r
+ if (Line->Buffer == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ FileBuffer.NumLines++;\r
+\r
+ //\r
+ // insert the line into line list\r
+ //\r
+ InsertTailList (FileBuffer.ListHead, &Line->Link);\r
+\r
+ if (FileBuffer.Lines == NULL) {\r
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ }\r
+\r
+ return Line;\r
+}\r
+\r
+/**\r
+ Set FileName field in FileBuffer.\r
+\r
+ @param Str The file name to set.\r
+ \r
+ @retval EFI_SUCCESS The filename was successfully set.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferSetFileName (\r
+ IN CONST CHAR16 *Str\r
+ )\r
+{\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (!IsValidFileName(Str)) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ //\r
+ // free the old file name\r
+ //\r
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);\r
+\r
+ //\r
+ // Allocate and set the new name\r
+ //\r
+ FileBuffer.FileName = CatSPrint (NULL, L"%s", Str);\r
+ if (FileBuffer.FileName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+/**\r
+ Free the existing file lines and reset the modified flag.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferFree (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // free all the lines\r
+ //\r
+ FileBufferFreeLines ();\r
+ FileBuffer.FileModified = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Read a file from disk into the FileBuffer.\r
+ \r
+ @param[in] FileName The filename to read.\r
+ @param[in] Recover TRUE if is for recover mode, no information printouts.\r
+ \r
+ @retval EFI_SUCCESS The load was successful.\r
+ @retval EFI_LOAD_ERROR The load failed.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER FileName is a directory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferRead (\r
+ IN CONST CHAR16 *FileName,\r
+ IN CONST BOOLEAN Recover\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ EE_NEWLINE_TYPE Type;\r
+ UINTN LoopVar1;\r
+ UINTN LoopVar2;\r
+ UINTN LineSize;\r
+ VOID *Buffer;\r
+ CHAR16 *UnicodeBuffer;\r
+ UINT8 *AsciiBuffer;\r
+ UINTN FileSize;\r
+ SHELL_FILE_HANDLE FileHandle;\r
+ BOOLEAN CreateFile;\r
+ EFI_STATUS Status;\r
+ UINTN LineSizeBackup;\r
+ EFI_FILE_INFO *Info;\r
+\r
+ Line = NULL;\r
+ LoopVar1 = 0;\r
+ FileSize = 0;\r
+ UnicodeBuffer = NULL;\r
+ Type = NewLineTypeDefault;\r
+ FileHandle = NULL;\r
+ CreateFile = FALSE;\r
+\r
+ //\r
+ // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )\r
+ // you should set status string via StatusBarSetStatusString(L"blah")\r
+ // since this function maybe called before the editorhandleinput loop\r
+ // so any error will cause editor return\r
+ // so if you want to print the error status\r
+ // you should set the status string\r
+ //\r
+\r
+ //\r
+ // try to open the file\r
+ //\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ CreateFile = FALSE;\r
+ if (FileHandle == NULL) {\r
+ StatusBarSetStatusString (L"Disk Error");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Info = ShellGetFileInfo(FileHandle);\r
+ \r
+ if (Info->Attribute & EFI_FILE_DIRECTORY) {\r
+ StatusBarSetStatusString (L"Directory Can Not Be Edited");\r
+ FreePool (Info);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {\r
+ FileBuffer.ReadOnly = TRUE;\r
+ } else {\r
+ FileBuffer.ReadOnly = FALSE;\r
+ }\r
+ //\r
+ // get file size\r
+ //\r
+ FileSize = (UINTN) Info->FileSize;\r
+\r
+ FreePool (Info);\r
+ } else if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // file not exists. add create and try again\r
+ //\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_WRITE_PROTECTED ||\r
+ Status == EFI_ACCESS_DENIED ||\r
+ Status == EFI_NO_MEDIA ||\r
+ Status == EFI_MEDIA_CHANGED\r
+ ) {\r
+ StatusBarSetStatusString (L"Access Denied");\r
+ } else if (Status == EFI_DEVICE_ERROR || Status == EFI_VOLUME_CORRUPTED || Status == EFI_VOLUME_FULL) {\r
+ StatusBarSetStatusString (L"Disk Error");\r
+ } else {\r
+ StatusBarSetStatusString (L"Invalid File Name or Current-working-directory");\r
+ }\r
+\r
+ return Status;\r
+ } else {\r
+ //\r
+ // it worked. now delete it and move on with the name (now validated)\r
+ //\r
+ Status = ShellDeleteFile (&FileHandle);\r
+ if (Status == EFI_WARN_DELETE_FAILURE) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ }\r
+ FileHandle = NULL;\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Access Denied");\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // file doesn't exist, so set CreateFile to TRUE\r
+ //\r
+ CreateFile = TRUE;\r
+ FileBuffer.ReadOnly = FALSE;\r
+\r
+ //\r
+ // all the check ends\r
+ // so now begin to set file name, free lines\r
+ //\r
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {\r
+ FileBufferSetFileName (FileName);\r
+ }\r
+ //\r
+ // free the old lines\r
+ //\r
+ FileBufferFree ();\r
+\r
+ }\r
+ //\r
+ // the file exists\r
+ //\r
+ if (!CreateFile) {\r
+ //\r
+ // allocate buffer to read file\r
+ //\r
+ Buffer = AllocateZeroPool (FileSize);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // read file into Buffer\r
+ //\r
+ Status = ShellReadFile (FileHandle, &FileSize, Buffer);\r
+ ShellCloseFile(&FileHandle);\r
+ FileHandle = NULL;\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Read File Failed");\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ //\r
+ // nothing in this file\r
+ //\r
+ if (FileSize == 0) {\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ //\r
+ // since has no head, so only can be an ASCII file\r
+ //\r
+ FileBuffer.FileType = FileTypeAscii;\r
+\r
+ goto Done;\r
+ }\r
+\r
+ AsciiBuffer = Buffer;\r
+\r
+ if (FileSize < 2) {\r
+ //\r
+ // size < Unicode file header, so only can be ASCII file\r
+ //\r
+ FileBuffer.FileType = FileTypeAscii;\r
+ } else {\r
+ //\r
+ // Unicode file\r
+ //\r
+ if (*(UINT16 *) Buffer == EFI_UNICODE_BYTE_ORDER_MARK) {\r
+ //\r
+ // Unicode file's size should be even\r
+ //\r
+ if ((FileSize % 2) != 0) {\r
+ StatusBarSetStatusString (L"File Format Wrong");\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ FileSize /= 2;\r
+\r
+ FileBuffer.FileType = FileTypeUnicode;\r
+ UnicodeBuffer = Buffer;\r
+\r
+ //\r
+ // pass this 0xff and 0xfe\r
+ //\r
+ UnicodeBuffer++;\r
+ FileSize--;\r
+ } else {\r
+ FileBuffer.FileType = FileTypeAscii;\r
+ }\r
+ //\r
+ // end of AsciiBuffer ==\r
+ //\r
+ }\r
+ //\r
+ // end of FileSize < 2\r
+ // all the check ends\r
+ // so now begin to set file name, free lines\r
+ //\r
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {\r
+ FileBufferSetFileName (FileName);\r
+ }\r
+\r
+ //\r
+ // free the old lines\r
+ //\r
+ FileBufferFree ();\r
+\r
+ //\r
+ // parse file content line by line\r
+ //\r
+ for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) {\r
+ Type = NewLineTypeUnknown;\r
+\r
+ for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) {\r
+ if (FileBuffer.FileType == FileTypeAscii) {\r
+ if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {\r
+ Type = NewLineTypeCarriageReturn;\r
+\r
+ //\r
+ // has LF following\r
+ //\r
+ if (LineSize < FileSize - 1) {\r
+ if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) {\r
+ Type = NewLineTypeCarriageReturnLineFeed;\r
+ }\r
+ }\r
+\r
+ break;\r
+ } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) {\r
+ Type = NewLineTypeLineFeed;\r
+\r
+ //\r
+ // has CR following\r
+ //\r
+ if (LineSize < FileSize - 1) {\r
+ if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {\r
+ Type = NewLineTypeLineFeedCarriageReturn;\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+ } else {\r
+ if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {\r
+ Type = NewLineTypeCarriageReturn;\r
+\r
+ //\r
+ // has LF following\r
+ //\r
+ if (LineSize < FileSize - 1) {\r
+ if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) {\r
+ Type = NewLineTypeCarriageReturnLineFeed;\r
+ }\r
+ }\r
+\r
+ break;\r
+ } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) {\r
+ Type = NewLineTypeLineFeed;\r
+\r
+ //\r
+ // has CR following\r
+ //\r
+ if (LineSize < FileSize - 1) {\r
+ if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {\r
+ Type = NewLineTypeLineFeedCarriageReturn;\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // endif == ASCII\r
+ //\r
+ }\r
+ //\r
+ // end of for LineSize\r
+ //\r
+ // if the type is wrong, then exit\r
+ //\r
+ if (Type == NewLineTypeUnknown) {\r
+ //\r
+ // Now if Type is NewLineTypeUnknown, it should be file end\r
+ //\r
+ Type = NewLineTypeDefault;\r
+ }\r
+\r
+ LineSizeBackup = LineSize;\r
+\r
+ //\r
+ // create a new line\r
+ //\r
+ Line = FileBufferCreateLine ();\r
+ if (Line == NULL) {\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // calculate file length\r
+ //\r
+ LineSize -= LoopVar1;\r
+\r
+ //\r
+ // Unicode and one CHAR_NULL\r
+ //\r
+ SHELL_FREE_NON_NULL (Line->Buffer);\r
+ Line->Buffer = AllocateZeroPool (LineSize * 2 + 2);\r
+\r
+ if (Line->Buffer == NULL) {\r
+ RemoveEntryList (&Line->Link);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // copy this line to Line->Buffer\r
+ //\r
+ for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) {\r
+ if (FileBuffer.FileType == FileTypeAscii) {\r
+ Line->Buffer[LoopVar2] = (CHAR16) AsciiBuffer[LoopVar1];\r
+ } else {\r
+ Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1];\r
+ }\r
+\r
+ LoopVar1++;\r
+ }\r
+ //\r
+ // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;\r
+ //\r
+ Line->Buffer[LineSize] = 0;\r
+\r
+ Line->Size = LineSize;\r
+ Line->TotalSize = LineSize;\r
+ Line->Type = Type;\r
+\r
+ if (Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) {\r
+ LoopVar1++;\r
+ }\r
+\r
+ //\r
+ // last character is a return, SO create a new line\r
+ //\r
+ if (((Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) && LineSizeBackup == FileSize - 2) ||\r
+ ((Type == NewLineTypeLineFeed || Type == NewLineTypeCarriageReturn) && LineSizeBackup == FileSize - 1)\r
+ ) {\r
+ Line = FileBufferCreateLine ();\r
+ if (Line == NULL) {\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ //\r
+ // end of if\r
+ //\r
+ }\r
+ //\r
+ // end of LoopVar1\r
+ //\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+\r
+ }\r
+ //\r
+ // end of if CreateFile\r
+ //\r
+Done:\r
+\r
+ FileBuffer.DisplayPosition.Row = 2;\r
+ FileBuffer.DisplayPosition.Column = 1;\r
+ FileBuffer.LowVisibleRange.Row = 1;\r
+ FileBuffer.LowVisibleRange.Column = 1;\r
+ FileBuffer.FilePosition.Row = 1;\r
+ FileBuffer.FilePosition.Column = 1;\r
+ FileBuffer.MousePosition.Row = 2;\r
+ FileBuffer.MousePosition.Column = 1;\r
+\r
+ if (!Recover) {\r
+ UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines);\r
+ if (UnicodeBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StatusBarSetStatusString (UnicodeBuffer);\r
+ FreePool (UnicodeBuffer);\r
+ }\r
+/*\r
+ //\r
+ // check whether we have fs?: in filename\r
+ //\r
+ LoopVar1 = 0;\r
+ FSMappingPtr = NULL;\r
+ while (FileName[LoopVar1] != 0) {\r
+ if (FileName[LoopVar1] == L':') {\r
+ FSMappingPtr = &FileName[LoopVar1];\r
+ break;\r
+ }\r
+\r
+ LoopVar1++;\r
+ }\r
+\r
+ if (FSMappingPtr == NULL) {\r
+ CurDir = ShellGetCurrentDir (NULL);\r
+ } else {\r
+ LoopVar1 = 0;\r
+ LoopVar2 = 0;\r
+ while (FileName[LoopVar1] != 0) {\r
+ if (FileName[LoopVar1] == L':') {\r
+ break;\r
+ }\r
+\r
+ FSMapping[LoopVar2++] = FileName[LoopVar1];\r
+\r
+ LoopVar1++;\r
+ }\r
+\r
+ FSMapping[LoopVar2] = 0;\r
+ CurDir = ShellGetCurrentDir (FSMapping);\r
+ }\r
+\r
+ if (CurDir != NULL) {\r
+ for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);\r
+\r
+ CurDir[LoopVar1] = 0;\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);\r
+ FreePool (CurDir);\r
+ } else {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = LibDevicePathToInterface (\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ DevicePath,\r
+ (VOID **) &Vol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = Vol->OpenVolume (Vol, &RootFs);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ //\r
+ // Get volume information of file system\r
+ //\r
+ Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;\r
+ VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);\r
+ Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ RootFs->Close (RootFs);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ if (VolumeInfo->ReadOnly) {\r
+ StatusBarSetStatusString (L"WARNING: Volume Read Only");\r
+ }\r
+\r
+ FreePool (VolumeInfo);\r
+ RootFs->Close (RootFs);\r
+ }\r
+//\r
+*/\r
+ //\r
+ // has line\r
+ //\r
+ if (FileBuffer.Lines != 0) {\r
+ FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ } else {\r
+ //\r
+ // create a dummy line\r
+ //\r
+ Line = FileBufferCreateLine ();\r
+ if (Line == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FileBuffer.CurrentLine = Line;\r
+ }\r
+\r
+ FileBuffer.FileModified = FALSE;\r
+ FileBufferNeedRefresh = TRUE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+ FileBufferMouseNeedRefresh = TRUE;\r
+\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ According to FileBuffer.NewLineType & FileBuffer.FileType,\r
+ get the return buffer and size.\r
+\r
+ @param[in] Type The type of line.\r
+ @param[out] Buffer The buffer to fill.\r
+ @param[out] Size The amount of the buffer used on return.\r
+**/\r
+VOID\r
+EFIAPI\r
+GetNewLine (\r
+ IN CONST EE_NEWLINE_TYPE Type,\r
+ OUT CHAR8 *Buffer,\r
+ OUT UINT8 *Size\r
+ )\r
+{\r
+ UINT8 NewLineSize;\r
+\r
+ //\r
+ // give new line buffer,\r
+ // and will judge unicode or ascii\r
+ //\r
+ NewLineSize = 0;\r
+\r
+ //\r
+ // not legal new line type\r
+ //\r
+ if (Type != NewLineTypeLineFeed && Type != NewLineTypeCarriageReturn && Type != NewLineTypeCarriageReturnLineFeed && Type != NewLineTypeLineFeedCarriageReturn) {\r
+ *Size = 0;\r
+ return ;\r
+ }\r
+ //\r
+ // use_cr: give 0x0d\r
+ //\r
+ if (Type == NewLineTypeCarriageReturn) {\r
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {\r
+ Buffer[0] = 0x0d;\r
+ Buffer[1] = 0;\r
+ NewLineSize = 2;\r
+ } else {\r
+ Buffer[0] = 0x0d;\r
+ NewLineSize = 1;\r
+ }\r
+\r
+ *Size = NewLineSize;\r
+ return ;\r
+ }\r
+ //\r
+ // use_lf: give 0x0a\r
+ //\r
+ if (Type == NewLineTypeLineFeed) {\r
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {\r
+ Buffer[0] = 0x0a;\r
+ Buffer[1] = 0;\r
+ NewLineSize = 2;\r
+ } else {\r
+ Buffer[0] = 0x0a;\r
+ NewLineSize = 1;\r
+ }\r
+\r
+ *Size = NewLineSize;\r
+ return ;\r
+ }\r
+ //\r
+ // use_crlf: give 0x0d 0x0a\r
+ //\r
+ if (Type == NewLineTypeCarriageReturnLineFeed) {\r
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {\r
+ Buffer[0] = 0x0d;\r
+ Buffer[1] = 0;\r
+ Buffer[2] = 0x0a;\r
+ Buffer[3] = 0;\r
+\r
+ NewLineSize = 4;\r
+ } else {\r
+ Buffer[0] = 0x0d;\r
+ Buffer[1] = 0x0a;\r
+ NewLineSize = 2;\r
+ }\r
+\r
+ *Size = NewLineSize;\r
+ return ;\r
+ }\r
+ //\r
+ // use_lfcr: give 0x0a 0x0d\r
+ //\r
+ if (Type == NewLineTypeLineFeedCarriageReturn) {\r
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {\r
+ Buffer[0] = 0x0a;\r
+ Buffer[1] = 0;\r
+ Buffer[2] = 0x0d;\r
+ Buffer[3] = 0;\r
+\r
+ NewLineSize = 4;\r
+ } else {\r
+ Buffer[0] = 0x0a;\r
+ Buffer[1] = 0x0d;\r
+ NewLineSize = 2;\r
+ }\r
+\r
+ *Size = NewLineSize;\r
+ return ;\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Change a Unicode string to an ASCII string.\r
+\r
+ @param[in] UStr The Unicode string.\r
+ @param[in] Lenght The maximum size of AStr.\r
+ @param[out] AStr ASCII string to pass out.\r
+\r
+ @return The actuall length.\r
+**/\r
+UINTN\r
+EFIAPI\r
+UnicodeToAscii (\r
+ IN CONST CHAR16 *UStr,\r
+ IN CONST UINTN Length,\r
+ OUT CHAR8 *AStr\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ //\r
+ // just buffer copy, not character copy\r
+ //\r
+ for (Index = 0; Index < Length; Index++) {\r
+ *AStr++ = (CHAR8) *UStr++;\r
+ }\r
+\r
+ return Index;\r
+}\r
+\r
+/**\r
+ Save lines in FileBuffer to disk\r
+\r
+ @param[in] FileName The file name for writing.\r
+\r
+ @retval EFI_SUCCESS Data was written.\r
+ @retval EFI_LOAD_ERROR \r
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferSave (\r
+ IN CONST CHAR16 *FileName\r
+ )\r
+{\r
+ SHELL_FILE_HANDLE FileHandle;\r
+ LIST_ENTRY *Link;\r
+ EFI_EDITOR_LINE *Line;\r
+ CHAR16 *Str;\r
+\r
+ EFI_STATUS Status;\r
+ UINTN Length;\r
+ UINTN NumLines;\r
+ CHAR8 NewLineBuffer[4];\r
+ UINT8 NewLineSize;\r
+\r
+ EFI_FILE_INFO *Info;\r
+\r
+ UINT64 Attribute;\r
+\r
+ EE_NEWLINE_TYPE Type;\r
+\r
+ UINTN TotalSize;\r
+ //\r
+ // 2M\r
+ //\r
+ CHAR8 *Cache;\r
+ UINTN LeftSize;\r
+ UINTN Size;\r
+ CHAR8 *Ptr;\r
+\r
+ Length = 0;\r
+ //\r
+ // 2M\r
+ //\r
+ TotalSize = 0x200000;\r
+\r
+ Attribute = 0;\r
+\r
+\r
+\r
+ //\r
+ // if is the old file\r
+ //\r
+ if (StrCmp (FileName, FileBuffer.FileName) == 0) {\r
+ //\r
+ // file has not been modified\r
+ //\r
+ if (!FileBuffer.FileModified) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // if file is read-only, set error\r
+ //\r
+ if (FileBuffer.ReadOnly) {\r
+ StatusBarSetStatusString (L"Read Only File Can Not Be Saved");\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Info = ShellGetFileInfo(FileHandle);\r
+\r
+ if (Info != NULL && Info->Attribute & EFI_FILE_DIRECTORY) {\r
+ StatusBarSetStatusString (L"Directory Can Not Be Saved");\r
+ ShellCloseFile(FileHandle);\r
+ FreePool(Info);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ \r
+ if (Info != NULL) {\r
+ Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY;\r
+ FreePool(Info);\r
+ }\r
+\r
+ //\r
+ // if file exits, so delete it\r
+ //\r
+ Status = ShellDeleteFile (&FileHandle);\r
+ if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {\r
+ StatusBarSetStatusString (L"Write File Failed");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ }\r
+\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Create File Failed");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ //\r
+ // if file is Unicode file, write Unicode header to it.\r
+ //\r
+ if (FileBuffer.FileType == FileTypeUnicode) {\r
+ Length = 2;\r
+ Status = ShellWriteFile (FileHandle, &Length, (VOID*)&gUnicodeFileTag);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellDeleteFile (&FileHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ }\r
+\r
+ Cache = AllocateZeroPool (TotalSize);\r
+ if (Cache == NULL) {\r
+ ShellDeleteFile (&FileHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // write all the lines back to disk\r
+ //\r
+ NumLines = 0;\r
+ Type = NewLineTypeCarriageReturnLineFeed;\r
+\r
+ Ptr = Cache;\r
+ LeftSize = TotalSize;\r
+\r
+ for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) {\r
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ if (Line->Type != NewLineTypeDefault) {\r
+ Type = Line->Type;\r
+ }\r
+ //\r
+ // newline character is at most 4 bytes ( two Unicode characters )\r
+ //\r
+ Length = 4;\r
+ if (Line->Buffer != NULL && Line->Size != 0) {\r
+ if (FileBuffer.FileType == FileTypeAscii) {\r
+ Length += Line->Size;\r
+ } else {\r
+ Length += (Line->Size * 2);\r
+ }\r
+ //\r
+ // end if FileTypeAscii\r
+ //\r
+ }\r
+\r
+ //\r
+ // no cache room left, so write cache to disk\r
+ //\r
+ if (LeftSize < Length) {\r
+ Size = TotalSize - LeftSize;\r
+ Status = ShellWriteFile (FileHandle, &Size, Cache);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellDeleteFile (&FileHandle); \r
+ FreePool (Cache);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ Ptr = Cache;\r
+ LeftSize = TotalSize;\r
+ }\r
+\r
+ if (Line->Buffer != NULL && Line->Size != 0) {\r
+ if (FileBuffer.FileType == FileTypeAscii) {\r
+ UnicodeToAscii (Line->Buffer, Line->Size, Ptr);\r
+ Length = Line->Size;\r
+ } else {\r
+ Length = (Line->Size * 2);\r
+ CopyMem (Ptr, (CHAR8 *) Line->Buffer, Length);\r
+ }\r
+ //\r
+ // end if FileTypeAscii\r
+ //\r
+ Ptr += Length;\r
+ LeftSize -= Length;\r
+\r
+ }\r
+ //\r
+ // end of if Line -> Buffer != NULL && Line -> Size != 0\r
+ //\r
+ // if not the last line , write return buffer to disk\r
+ //\r
+ if (Link->ForwardLink != FileBuffer.ListHead) {\r
+ GetNewLine (Type, NewLineBuffer, &NewLineSize);\r
+ CopyMem (Ptr, (CHAR8 *) NewLineBuffer, NewLineSize);\r
+\r
+ Ptr += NewLineSize;\r
+ LeftSize -= NewLineSize;\r
+ }\r
+\r
+ NumLines++;\r
+ }\r
+\r
+ if (TotalSize != LeftSize) {\r
+ Size = TotalSize - LeftSize;\r
+ Status = ShellWriteFile (FileHandle, &Size, Cache);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellDeleteFile (&FileHandle);\r
+ FreePool (Cache);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ }\r
+\r
+ FreePool (Cache);\r
+\r
+ ShellCloseFile(&FileHandle);\r
+\r
+ FileBuffer.FileModified = FALSE;\r
+\r
+ //\r
+ // set status string\r
+ //\r
+ Str = CatSPrint (NULL, L"%d Lines Wrote", NumLines);\r
+ if (Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StatusBarSetStatusString (Str);\r
+ SHELL_FREE_NON_NULL (Str);\r
+\r
+ //\r
+ // now everything is ready , you can set the new file name to filebuffer\r
+ //\r
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {\r
+ //\r
+ // not the same\r
+ //\r
+ FileBufferSetFileName (FileName);\r
+ if (FileBuffer.FileName == NULL) {\r
+ ShellDeleteFile (&FileHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ FileBuffer.ReadOnly = FALSE;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Scroll cursor to left 1 character position.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferScrollLeft (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ FRow = FileBuffer.FilePosition.Row;\r
+ FCol = FileBuffer.FilePosition.Column;\r
+\r
+ //\r
+ // if already at start of this line, so move to the end of previous line\r
+ //\r
+ if (FCol <= 1) {\r
+ //\r
+ // has previous line\r
+ //\r
+ if (Line->Link.BackLink != FileBuffer.ListHead) {\r
+ FRow--;\r
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ FCol = Line->Size + 1;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ //\r
+ // if not at start of this line, just move to previous column\r
+ //\r
+ FCol--;\r
+ }\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Delete a char in line\r
+\r
+ @param[in,out] Line The line to delete in.\r
+ @param[in] Pos Position to delete the char at ( start from 0 ).\r
+**/\r
+VOID\r
+EFIAPI\r
+LineDeleteAt (\r
+ IN OUT EFI_EDITOR_LINE *Line,\r
+ IN UINTN Pos\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ //\r
+ // move the latter characters front\r
+ //\r
+ for (Index = Pos - 1; Index < Line->Size; Index++) {\r
+ Line->Buffer[Index] = Line->Buffer[Index + 1];\r
+ }\r
+\r
+ Line->Size--;\r
+}\r
+\r
+/**\r
+ Concatenate Src into Dest.\r
+\r
+ @param[in,out] Dest Destination string\r
+ @param[in] Src Src String.\r
+**/\r
+VOID\r
+EFIAPI\r
+LineCat (\r
+ IN OUT EFI_EDITOR_LINE *Dest,\r
+ IN EFI_EDITOR_LINE *Src\r
+ )\r
+{\r
+ CHAR16 *Str;\r
+ UINTN Size;\r
+\r
+ Size = Dest->Size;\r
+\r
+ Dest->Buffer[Size] = 0;\r
+\r
+ //\r
+ // concatenate the two strings\r
+ //\r
+ Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer);\r
+ if (Str == NULL) {\r
+ Dest->Buffer = NULL;\r
+ return ;\r
+ }\r
+\r
+ Dest->Size = Size + Src->Size;\r
+ Dest->TotalSize = Dest->Size;\r
+\r
+ FreePool (Dest->Buffer);\r
+ FreePool (Src->Buffer);\r
+\r
+ //\r
+ // put str to dest->buffer\r
+ //\r
+ Dest->Buffer = Str;\r
+}\r
+\r
+/**\r
+ Delete the previous character.\r
+\r
+ @retval EFI_SUCCESS The delete was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferDoBackspace (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ EFI_EDITOR_LINE *End;\r
+ LIST_ENTRY *Link;\r
+ UINTN FileColumn;\r
+\r
+ FileColumn = FileBuffer.FilePosition.Column;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ //\r
+ // the first column\r
+ //\r
+ if (FileColumn == 1) {\r
+ //\r
+ // the first row\r
+ //\r
+ if (FileBuffer.FilePosition.Row == 1) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FileBufferScrollLeft ();\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+ Link = Line->Link.ForwardLink;\r
+ End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ //\r
+ // concatenate this line with previous line\r
+ //\r
+ LineCat (Line, End);\r
+ if (Line->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // remove End from line list\r
+ //\r
+ RemoveEntryList (&End->Link);\r
+ FreePool (End);\r
+\r
+ FileBuffer.NumLines--;\r
+\r
+ FileBufferNeedRefresh = TRUE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+\r
+ } else {\r
+ //\r
+ // just delete the previous character\r
+ //\r
+ LineDeleteAt (Line, FileColumn - 1);\r
+ FileBufferScrollLeft ();\r
+ FileBufferOnlyLineNeedRefresh = TRUE;\r
+ }\r
+\r
+ if (!FileBuffer.FileModified) {\r
+ FileBuffer.FileModified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add a return into line at current position.\r
+\r
+ @retval EFI_SUCCESS The insetrion of the character was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferDoReturn (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ EFI_EDITOR_LINE *NewLine;\r
+ UINTN FileColumn;\r
+ UINTN Index;\r
+ CHAR16 *Buffer;\r
+ UINTN Row;\r
+ UINTN Col;\r
+\r
+ FileBufferNeedRefresh = TRUE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ FileColumn = FileBuffer.FilePosition.Column;\r
+\r
+ NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));\r
+ if (NewLine == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLine->Signature = LINE_LIST_SIGNATURE;\r
+ NewLine->Size = Line->Size - FileColumn + 1;\r
+ NewLine->TotalSize = NewLine->Size;\r
+ NewLine->Buffer = CatSPrint (NULL, L"\0");\r
+ if (NewLine->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLine->Type = NewLineTypeDefault;\r
+\r
+ if (NewLine->Size > 0) {\r
+ //\r
+ // UNICODE + CHAR_NULL\r
+ //\r
+ Buffer = AllocateZeroPool (2 * (NewLine->Size + 1));\r
+ if (Buffer == NULL) {\r
+ FreePool (NewLine->Buffer);\r
+ FreePool (NewLine);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FreePool (NewLine->Buffer);\r
+\r
+ NewLine->Buffer = Buffer;\r
+\r
+ for (Index = 0; Index < NewLine->Size; Index++) {\r
+ NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1];\r
+ }\r
+\r
+ NewLine->Buffer[NewLine->Size] = CHAR_NULL;\r
+\r
+ Line->Buffer[FileColumn - 1] = CHAR_NULL;\r
+ Line->Size = FileColumn - 1;\r
+ }\r
+ //\r
+ // increase NumLines\r
+ //\r
+ FileBuffer.NumLines++;\r
+\r
+ //\r
+ // insert it into the correct position of line list\r
+ //\r
+ NewLine->Link.BackLink = &(Line->Link);\r
+ NewLine->Link.ForwardLink = Line->Link.ForwardLink;\r
+ Line->Link.ForwardLink->BackLink = &(NewLine->Link);\r
+ Line->Link.ForwardLink = &(NewLine->Link);\r
+\r
+ //\r
+ // move cursor to the start of next line\r
+ //\r
+ Row = FileBuffer.FilePosition.Row + 1;\r
+ Col = 1;\r
+\r
+ FileBufferMovePosition (Row, Col);\r
+\r
+ //\r
+ // set file is modified\r
+ //\r
+ if (!FileBuffer.FileModified) {\r
+ FileBuffer.FileModified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Delete current character from current line. This is the effect caused \r
+ by the 'del' key.\r
+\r
+ @retval EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferDoDelete (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ EFI_EDITOR_LINE *Next;\r
+ LIST_ENTRY *Link;\r
+ UINTN FileColumn;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+ FileColumn = FileBuffer.FilePosition.Column;\r
+\r
+ //\r
+ // the last column\r
+ //\r
+ if (FileColumn >= Line->Size + 1) {\r
+ //\r
+ // the last line\r
+ //\r
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // since last character,\r
+ // so will add the next line to this line\r
+ //\r
+ Link = Line->Link.ForwardLink;\r
+ Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ LineCat (Line, Next);\r
+ if (Line->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ RemoveEntryList (&Next->Link);\r
+ FreePool (Next);\r
+\r
+ FileBuffer.NumLines--;\r
+\r
+ FileBufferNeedRefresh = TRUE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+\r
+ } else {\r
+ //\r
+ // just delete current character\r
+ //\r
+ LineDeleteAt (Line, FileColumn);\r
+ FileBufferOnlyLineNeedRefresh = TRUE;\r
+ }\r
+\r
+ if (!FileBuffer.FileModified) {\r
+ FileBuffer.FileModified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Scroll cursor to right 1 character.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferScrollRight (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+ if (Line->Buffer == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FRow = FileBuffer.FilePosition.Row;\r
+ FCol = FileBuffer.FilePosition.Column;\r
+\r
+ //\r
+ // if already at end of this line, scroll it to the start of next line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ //\r
+ // has next line\r
+ //\r
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {\r
+ FRow++;\r
+ FCol = 1;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ //\r
+ // if not at end of this line, just move to next column\r
+ //\r
+ FCol++;\r
+ }\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Insert a char into line\r
+\r
+ \r
+ @param[in] Line The line to insert into.\r
+ @param[in] Char The char to insert.\r
+ @param[in] Pos The position to insert the char at ( start from 0 ).\r
+ @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.\r
+\r
+ @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).\r
+**/\r
+UINTN\r
+EFIAPI\r
+LineStrInsert (\r
+ IN EFI_EDITOR_LINE *Line,\r
+ IN CHAR16 Char,\r
+ IN UINTN Pos,\r
+ IN UINTN StrSize\r
+ )\r
+{\r
+ UINTN Index;\r
+ CHAR16 *TempStringPtr;\r
+ CHAR16 *Str;\r
+\r
+ Index = (StrSize) * 2;\r
+\r
+ Str = Line->Buffer;\r
+\r
+ //\r
+ // do not have free space\r
+ //\r
+ if (Line->TotalSize <= Line->Size) {\r
+ Str = ReallocatePool (Index, Index + 16, Str);\r
+ if (Str == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ Line->TotalSize += 8;\r
+ }\r
+ //\r
+ // move the later part of the string one character right\r
+ //\r
+ TempStringPtr = Str;\r
+ for (Index = StrSize; Index > Pos; Index--) {\r
+ TempStringPtr[Index] = TempStringPtr[Index - 1];\r
+ }\r
+ //\r
+ // insert char into it.\r
+ //\r
+ TempStringPtr[Index] = Char;\r
+\r
+ Line->Buffer = Str;\r
+ Line->Size++;\r
+\r
+ return StrSize + 1;\r
+}\r
+\r
+/**\r
+ Add a character to the current line.\r
+\r
+ @param[in] Char The Character to input.\r
+\r
+ @retval EFI_SUCCESS The input was succesful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferAddChar (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FilePos;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ //\r
+ // only needs to refresh current line\r
+ //\r
+ FileBufferOnlyLineNeedRefresh = TRUE;\r
+\r
+ //\r
+ // when is insert mode, or cursor is at end of this line,\r
+ // so insert this character\r
+ // or replace the character.\r
+ //\r
+ FilePos = FileBuffer.FilePosition.Column - 1;\r
+ if (FileBuffer.ModeInsert || FilePos + 1 > Line->Size) {\r
+ LineStrInsert (Line, Char, FilePos, Line->Size + 1);\r
+ } else {\r
+ Line->Buffer[FilePos] = Char;\r
+ }\r
+ //\r
+ // move cursor to right\r
+ //\r
+ FileBufferScrollRight ();\r
+\r
+ if (!FileBuffer.FileModified) {\r
+ FileBuffer.FileModified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Handles inputs from characters (ASCII key + Backspace + return)\r
+\r
+ @param[in] Char The input character.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR There was an error.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferDoCharInput (\r
+ IN CONST CHAR16 Char\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (Char) {\r
+ case CHAR_NULL:\r
+ break;\r
+\r
+ case CHAR_BACKSPACE:\r
+ Status = FileBufferDoBackspace ();\r
+ break;\r
+\r
+ case CHAR_TAB:\r
+ //\r
+ // Tabs are ignored\r
+ //\r
+ break;\r
+\r
+ case CHAR_LINEFEED:\r
+ case CHAR_CARRIAGE_RETURN:\r
+ Status = FileBufferDoReturn ();\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // DEAL WITH ASCII CHAR, filter out thing like ctrl+f\r
+ //\r
+ if (Char > 127 || Char < 32) {\r
+ Status = StatusBarSetStatusString (L"Unknown Command");\r
+ } else {\r
+ Status = FileBufferAddChar (Char);\r
+ }\r
+\r
+ break;\r
+\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Scroll cursor to the next line.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferScrollDown (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+ if (Line->Buffer == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FRow = FileBuffer.FilePosition.Row;\r
+ FCol = FileBuffer.FilePosition.Column;\r
+\r
+ //\r
+ // has next line\r
+ //\r
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {\r
+ FRow++;\r
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ //\r
+ // if the next line is not that long, so move to end of next line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ FCol = Line->Size + 1;\r
+ }\r
+\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Scroll the cursor to previous line.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferScrollUp (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ FRow = FileBuffer.FilePosition.Row;\r
+ FCol = FileBuffer.FilePosition.Column;\r
+\r
+ //\r
+ // has previous line\r
+ //\r
+ if (Line->Link.BackLink != FileBuffer.ListHead) {\r
+ FRow--;\r
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ //\r
+ // if previous line is not that long, so move to the end of previous line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ FCol = Line->Size + 1;\r
+ }\r
+\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Scroll cursor to next page.\r
+\r
+ @retval EFI_SUCCESS The operation wa successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferPageDown (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ UINTN Gap;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ FRow = FileBuffer.FilePosition.Row;\r
+ FCol = FileBuffer.FilePosition.Column;\r
+\r
+ //\r
+ // has next page\r
+ //\r
+ if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 5)) {\r
+ Gap = (MainEditor.ScreenSize.Row - 5);\r
+ } else {\r
+ //\r
+ // MOVE CURSOR TO LAST LINE\r
+ //\r
+ Gap = FileBuffer.NumLines - FRow;\r
+ }\r
+ //\r
+ // get correct line\r
+ //\r
+ Line = MoveLine (Gap);\r
+\r
+ //\r
+ // if that line, is not that long, so move to the end of that line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ FCol = Line->Size + 1;\r
+ }\r
+\r
+ FRow += Gap;\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Scroll cursor to previous screen.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferPageUp (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ UINTN Gap;\r
+ INTN Retreat;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ FRow = FileBuffer.FilePosition.Row;\r
+ FCol = FileBuffer.FilePosition.Column;\r
+\r
+ //\r
+ // has previous page\r
+ //\r
+ if (FRow > (MainEditor.ScreenSize.Row - 5)) {\r
+ Gap = (MainEditor.ScreenSize.Row - 5);\r
+ } else {\r
+ //\r
+ // the first line of file will displayed on the first line of screen\r
+ //\r
+ Gap = FRow - 1;\r
+ }\r
+\r
+ Retreat = Gap;\r
+ Retreat = -Retreat;\r
+\r
+ //\r
+ // get correct line\r
+ //\r
+ Line = MoveLine (Retreat);\r
+\r
+ //\r
+ // if that line is not that long, so move to the end of that line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ FCol = Line->Size + 1;\r
+ }\r
+\r
+ FRow -= Gap;\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Scroll cursor to end of the current line.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferEnd (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ FRow = FileBuffer.FilePosition.Row;\r
+\r
+ //\r
+ // goto the last column of the line\r
+ //\r
+ FCol = Line->Size + 1;\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** \r
+ Dispatch input to different handler\r
+ @param[in] Key The input key. One of:\r
+ ASCII KEY\r
+ Backspace/Delete\r
+ Return\r
+ Direction key: up/down/left/right/pgup/pgdn\r
+ Home/End\r
+ INS\r
+\r
+ @retval EFI_SUCCESS The dispatch was done successfully.\r
+ @retval EFI_LOAD_ERROR The dispatch was not successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferHandleInput (\r
+ IN CONST EFI_INPUT_KEY *Key\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (Key->ScanCode) {\r
+ //\r
+ // ordinary key input\r
+ //\r
+ case SCAN_NULL:\r
+ if (!FileBuffer.ReadOnly) {\r
+ Status = FileBufferDoCharInput (Key->UnicodeChar);\r
+ } else {\r
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // up arrow\r
+ //\r
+ case SCAN_UP:\r
+ Status = FileBufferScrollUp ();\r
+ break;\r
+\r
+ //\r
+ // down arrow\r
+ //\r
+ case SCAN_DOWN:\r
+ Status = FileBufferScrollDown ();\r
+ break;\r
+\r
+ //\r
+ // right arrow\r
+ //\r
+ case SCAN_RIGHT:\r
+ Status = FileBufferScrollRight ();\r
+ break;\r
+\r
+ //\r
+ // left arrow\r
+ //\r
+ case SCAN_LEFT:\r
+ Status = FileBufferScrollLeft ();\r
+ break;\r
+\r
+ //\r
+ // page up\r
+ //\r
+ case SCAN_PAGE_UP:\r
+ Status = FileBufferPageUp ();\r
+ break;\r
+\r
+ //\r
+ // page down\r
+ //\r
+ case SCAN_PAGE_DOWN:\r
+ Status = FileBufferPageDown ();\r
+ break;\r
+\r
+ //\r
+ // delete\r
+ //\r
+ case SCAN_DELETE:\r
+ if (!FileBuffer.ReadOnly) {\r
+ Status = FileBufferDoDelete ();\r
+ } else {\r
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");\r
+ }\r
+\r
+ break;\r
+\r
+ //\r
+ // home\r
+ //\r
+ case SCAN_HOME:\r
+ FileBufferMovePosition (FileBuffer.FilePosition.Row, 1);\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ //\r
+ // end\r
+ //\r
+ case SCAN_END:\r
+ Status = FileBufferEnd ();\r
+ break;\r
+\r
+ //\r
+ // insert\r
+ //\r
+ case SCAN_INSERT:\r
+ FileBuffer.ModeInsert = (BOOLEAN)!FileBuffer.ModeInsert;\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+\r
+ default:\r
+ Status = StatusBarSetStatusString (L"Unknown Command");\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check user specified FileRow is above current screen.\r
+\r
+ @param[in] FileRow The row of file position ( start from 1 ).\r
+\r
+ @retval TRUE It is above the current screen.\r
+ @retval FALSE It is not above the current screen.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+AboveCurrentScreen (\r
+ IN UINTN FileRow\r
+ )\r
+{\r
+ //\r
+ // if is to the above of the screen\r
+ //\r
+ if (FileRow < FileBuffer.LowVisibleRange.Row) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Check user specified FileRow is under current screen.\r
+\r
+ @param[in] FileRow The row of file position ( start from 1 ).\r
+\r
+ @retval TRUE It is under the current screen.\r
+ @retval FALSE It is not under the current screen.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+UnderCurrentScreen (\r
+ IN UINTN FileRow\r
+ )\r
+{\r
+ //\r
+ // if is to the under of the screen\r
+ //\r
+ if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 5) - 1) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Check user specified FileCol is left to current screen.\r
+\r
+ @param[in] FileCol The column of file position ( start from 1 ).\r
+\r
+ @retval TRUE It is to the left.\r
+ @retval FALSE It is not to the left.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LeftCurrentScreen (\r
+ IN UINTN FileCol\r
+ )\r
+{\r
+ //\r
+ // if is to the left of the screen\r
+ //\r
+ if (FileCol < FileBuffer.LowVisibleRange.Column) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Check user specified FileCol is right to current screen.\r
+\r
+ @param[in] FileCol The column of file position ( start from 1 ).\r
+\r
+ @retval TRUE It is to the right.\r
+ @retval FALSE It is not to the right.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+RightCurrentScreen (\r
+ IN UINTN FileCol\r
+ )\r
+{\r
+ //\r
+ // if is to the right of the screen\r
+ //\r
+ if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Advance/Retreat lines and set CurrentLine in FileBuffer to it\r
+ \r
+ @param[in] Count The line number to advance/retreat\r
+ >0 : advance\r
+ <0: retreat\r
+\r
+ @retval NULL An error occured.\r
+ @return The line after advance/retreat.\r
+**/\r
+EFI_EDITOR_LINE *\r
+EFIAPI\r
+MoveCurrentLine (\r
+ IN INTN Count\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ UINTN AbsCount;\r
+\r
+ if (Count <= 0) {\r
+ AbsCount = -Count;\r
+ Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);\r
+ } else {\r
+ Line = InternalEditorMiscLineAdvance (Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);\r
+ }\r
+\r
+ if (Line == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ MainEditor.FileBuffer->CurrentLine = Line;\r
+\r
+ return Line;\r
+}\r
+\r
+/**\r
+ According to cursor's file position, adjust screen display\r
+\r
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).\r
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).\r
+**/\r
+VOID\r
+EFIAPI\r
+FileBufferMovePosition (\r
+ IN CONST UINTN NewFilePosRow,\r
+ IN CONST UINTN NewFilePosCol\r
+ )\r
+{\r
+ INTN RowGap;\r
+ INTN ColGap;\r
+ UINTN Abs;\r
+ BOOLEAN Above;\r
+ BOOLEAN Under;\r
+ BOOLEAN Right;\r
+ BOOLEAN Left;\r
+\r
+ //\r
+ // CALCULATE gap between current file position and new file position\r
+ //\r
+ RowGap = NewFilePosRow - FileBuffer.FilePosition.Row;\r
+ ColGap = NewFilePosCol - FileBuffer.FilePosition.Column;\r
+\r
+ Under = UnderCurrentScreen (NewFilePosRow);\r
+ Above = AboveCurrentScreen (NewFilePosRow);\r
+ //\r
+ // if is below current screen\r
+ //\r
+ if (Under) {\r
+ //\r
+ // display row will be unchanged\r
+ //\r
+ FileBuffer.FilePosition.Row = NewFilePosRow;\r
+ } else {\r
+ if (Above) {\r
+ //\r
+ // has enough above line, so display row unchanged\r
+ // not has enough above lines, so the first line is at the\r
+ // first display line\r
+ //\r
+ if (NewFilePosRow < (FileBuffer.DisplayPosition.Row - 1)) {\r
+ FileBuffer.DisplayPosition.Row = NewFilePosRow + 1;\r
+ }\r
+\r
+ FileBuffer.FilePosition.Row = NewFilePosRow;\r
+ } else {\r
+ //\r
+ // in current screen\r
+ //\r
+ FileBuffer.FilePosition.Row = NewFilePosRow;\r
+ if (RowGap < 0) {\r
+ Abs = -RowGap;\r
+ FileBuffer.DisplayPosition.Row -= Abs;\r
+ } else {\r
+ FileBuffer.DisplayPosition.Row += RowGap;\r
+ }\r
+ }\r
+ }\r
+\r
+ FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2);\r
+\r
+ Right = RightCurrentScreen (NewFilePosCol);\r
+ Left = LeftCurrentScreen (NewFilePosCol);\r
+\r
+ //\r
+ // if right to current screen\r
+ //\r
+ if (Right) {\r
+ //\r
+ // display column will be changed to end\r
+ //\r
+ FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column;\r
+ FileBuffer.FilePosition.Column = NewFilePosCol;\r
+ } else {\r
+ if (Left) {\r
+ //\r
+ // has enough left characters , so display row unchanged\r
+ // not has enough left characters,\r
+ // so the first character is at the first display column\r
+ //\r
+ if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) {\r
+ FileBuffer.DisplayPosition.Column = NewFilePosCol;\r
+ }\r
+\r
+ FileBuffer.FilePosition.Column = NewFilePosCol;\r
+ } else {\r
+ //\r
+ // in current screen\r
+ //\r
+ FileBuffer.FilePosition.Column = NewFilePosCol;\r
+ if (ColGap < 0) {\r
+ Abs = -ColGap;\r
+ FileBuffer.DisplayPosition.Column -= Abs;\r
+ } else {\r
+ FileBuffer.DisplayPosition.Column += ColGap;\r
+ }\r
+ }\r
+ }\r
+\r
+ FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1);\r
+\r
+ //\r
+ // let CurrentLine point to correct line;\r
+ //\r
+ FileBuffer.CurrentLine = MoveCurrentLine (RowGap);\r
+\r
+}\r
+\r
+/**\r
+ Cut current line out and return a pointer to it.\r
+\r
+ @param[out] CutLine Upon a successful return pointer to the pointer to \r
+ the allocated cut line.\r
+\r
+ @retval EFI_SUCCESS The cut was successful.\r
+ @retval EFI_NOT_FOUND There was no selection to cut.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferCutLine (\r
+ OUT EFI_EDITOR_LINE **CutLine\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ EFI_EDITOR_LINE *NewLine;\r
+ UINTN Row;\r
+ UINTN Col;\r
+\r
+ if (FileBuffer.ReadOnly) {\r
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Line = FileBuffer.CurrentLine;\r
+\r
+ //\r
+ // if is the last dummy line, SO CAN not cut\r
+ //\r
+ if (StrCmp (Line->Buffer, L"\0") == 0 && Line->Link.ForwardLink == FileBuffer.ListHead\r
+ //\r
+ // last line\r
+ //\r
+ ) {\r
+ //\r
+ // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING\r
+ //\r
+ StatusBarSetStatusString (L"Nothing to Cut");\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // if is the last line, so create a dummy line\r
+ //\r
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {\r
+ //\r
+ // last line\r
+ // create a new line\r
+ //\r
+ NewLine = FileBufferCreateLine ();\r
+ if (NewLine == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ FileBuffer.NumLines--;\r
+ Row = FileBuffer.FilePosition.Row;\r
+ Col = 1;\r
+ //\r
+ // move home\r
+ //\r
+ FileBuffer.CurrentLine = CR (\r
+ FileBuffer.CurrentLine->Link.ForwardLink,\r
+ EFI_EDITOR_LINE,\r
+ Link,\r
+ LINE_LIST_SIGNATURE\r
+ );\r
+\r
+ RemoveEntryList (&Line->Link);\r
+\r
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ FileBufferMovePosition (Row, Col);\r
+\r
+ FileBuffer.FileModified = TRUE;\r
+ FileBufferNeedRefresh = TRUE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+\r
+ *CutLine = Line;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Paste a line into line list.\r
+\r
+ @retval EFI_SUCCESS The paste was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferPasteLine (\r
+ VOID\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Line;\r
+ EFI_EDITOR_LINE *NewLine;\r
+ UINTN Row;\r
+ UINTN Col;\r
+\r
+ //\r
+ // if nothing is on clip board\r
+ // then do nothing\r
+ //\r
+ if (MainEditor.CutLine == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // read only file can not be pasted on\r
+ //\r
+ if (FileBuffer.ReadOnly) {\r
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NewLine = LineDup (MainEditor.CutLine);\r
+ if (NewLine == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // insert it above current line\r
+ //\r
+ Line = FileBuffer.CurrentLine;\r
+ NewLine->Link.BackLink = Line->Link.BackLink;\r
+ NewLine->Link.ForwardLink = &Line->Link;\r
+\r
+ Line->Link.BackLink->ForwardLink = &NewLine->Link;\r
+ Line->Link.BackLink = &NewLine->Link;\r
+\r
+ FileBuffer.NumLines++;\r
+ FileBuffer.CurrentLine = NewLine;\r
+\r
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ Col = 1;\r
+ //\r
+ // move home\r
+ //\r
+ Row = FileBuffer.FilePosition.Row;\r
+\r
+ FileBufferMovePosition (Row, Col);\r
+\r
+ //\r
+ // after paste, set some value so that refresh knows to do something\r
+ //\r
+ FileBuffer.FileModified = TRUE;\r
+ FileBufferNeedRefresh = TRUE;\r
+ FileBufferOnlyLineNeedRefresh = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Search string from current position on in file\r
+\r
+ @param[in] Str The search string.\r
+ @param[in] Offset The offset from current position.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_NOT_FOUND The string Str was not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferSearch (\r
+ IN CONST CHAR16 *Str,\r
+ IN CONST UINTN Offset\r
+ )\r
+{\r
+ CHAR16 *Current;\r
+ UINTN Position;\r
+ UINTN Row;\r
+ UINTN Column;\r
+ EFI_EDITOR_LINE *Line;\r
+ CHAR16 *CharPos;\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN Found;\r
+\r
+ Column = 0;\r
+\r
+ //\r
+ // search if in current line\r
+ //\r
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset;\r
+\r
+ if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) {\r
+ //\r
+ // the end\r
+ //\r
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size;\r
+ }\r
+\r
+ CharPos = StrStr (Current, Str);\r
+ if (CharPos != NULL) {\r
+ Position = CharPos - Current;\r
+ } else {\r
+ Position = 0;\r
+ }\r
+\r
+ //\r
+ // found\r
+ //\r
+ if (Position != 0) {\r
+ Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset;\r
+ Row = FileBuffer.FilePosition.Row;\r
+ Found = TRUE;\r
+ } else {\r
+ //\r
+ // not found so find through next lines\r
+ //\r
+ Link = FileBuffer.CurrentLine->Link.ForwardLink;\r
+\r
+ Row = FileBuffer.FilePosition.Row + 1;\r
+ while (Link != FileBuffer.ListHead) {\r
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+// Position = StrStr (Line->Buffer, Str);\r
+ CharPos = StrStr (Line->Buffer, Str);\r
+ if (CharPos != NULL) {\r
+ Position = CharPos - Line->Buffer;\r
+ }\r
+ if (Position != 0) {\r
+ //\r
+ // found\r
+ //\r
+ Column = Position;\r
+ break;\r
+ }\r
+\r
+ Row++;\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ if (Link == FileBuffer.ListHead) {\r
+ Found = FALSE;\r
+ } else {\r
+ Found = TRUE;\r
+ }\r
+ }\r
+\r
+ if (!Found) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ FileBufferMovePosition (Row, Column);\r
+\r
+ //\r
+ // call refresh to fresh edit area,\r
+ // because the outer may loop to find multiply occurrence of this string\r
+ //\r
+ FileBufferRefresh ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Replace SearchLen characters from current position on with Replace.\r
+\r
+ This will modify the current buffer at the current position.\r
+\r
+ @param[in] Replace The string to replace.\r
+ @param[in] SearchLen Search string's length.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferReplace (\r
+ IN CONST CHAR16 *Replace,\r
+ IN CONST UINTN SearchLen\r
+ )\r
+{\r
+ UINTN ReplaceLen;\r
+ UINTN Index;\r
+ CHAR16 *Buffer;\r
+ UINTN NewSize;\r
+ UINTN OldSize;\r
+ UINTN Gap;\r
+\r
+ ReplaceLen = StrLen (Replace);\r
+\r
+ OldSize = FileBuffer.CurrentLine->Size + 1;\r
+ //\r
+ // include CHAR_NULL\r
+ //\r
+ NewSize = OldSize + (ReplaceLen - SearchLen);\r
+\r
+ if (ReplaceLen > SearchLen) {\r
+ //\r
+ // do not have the enough space\r
+ //\r
+ if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) {\r
+ FileBuffer.CurrentLine->Buffer = ReallocatePool (\r
+ 2 * OldSize,\r
+ 2 * NewSize,\r
+ FileBuffer.CurrentLine->Buffer\r
+ );\r
+ FileBuffer.CurrentLine->TotalSize = NewSize - 1;\r
+ }\r
+\r
+ if (FileBuffer.CurrentLine->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // the end CHAR_NULL character;\r
+ //\r
+ Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1);\r
+ Gap = ReplaceLen - SearchLen;\r
+\r
+ //\r
+ // keep the latter part\r
+ //\r
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) {\r
+ *Buffer = *(Buffer - Gap);\r
+ Buffer--;\r
+ }\r
+ //\r
+ // set replace into it\r
+ //\r
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column;\r
+ for (Index = 0; Index < ReplaceLen; Index++) {\r
+ Buffer[Index] = Replace[Index];\r
+ }\r
+ }\r
+\r
+ if (ReplaceLen < SearchLen) {\r
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column;\r
+\r
+ for (Index = 0; Index < ReplaceLen; Index++) {\r
+ Buffer[Index] = Replace[Index];\r
+ }\r
+\r
+ Buffer += ReplaceLen;\r
+ Gap = SearchLen - ReplaceLen;\r
+\r
+ //\r
+ // set replace into it\r
+ //\r
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) {\r
+ *Buffer = *(Buffer + Gap);\r
+ Buffer++;\r
+ }\r
+ }\r
+\r
+ if (ReplaceLen == SearchLen) {\r
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column;\r
+ for (Index = 0; Index < ReplaceLen; Index++) {\r
+ Buffer[Index] = Replace[Index];\r
+ }\r
+ }\r
+\r
+ FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen);\r
+\r
+ FileBufferOnlyLineNeedRefresh = TRUE;\r
+\r
+ FileBuffer.FileModified = TRUE;\r
+\r
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);\r
+ FileBufferRestorePosition ();\r
+ FileBufferRefresh ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Move the mouse cursor position.\r
+\r
+ @param[in] TextX The new x-coordinate.\r
+ @param[in] TextY The new y-coordinate.\r
+**/\r
+VOID\r
+EFIAPI\r
+FileBufferAdjustMousePosition (\r
+ IN CONST INT32 TextX,\r
+ IN CONST INT32 TextY\r
+ )\r
+{\r
+ UINTN CoordinateX;\r
+ UINTN CoordinateY;\r
+ UINTN AbsX;\r
+ UINTN AbsY;\r
+\r
+ //\r
+ // TextX and TextY is mouse movement data returned by mouse driver\r
+ // This function will change it to MousePosition\r
+ //\r
+ //\r
+ // get absolute value\r
+ //\r
+\r
+ AbsX = ABS(TextX);\r
+ AbsY = ABS(TextY);\r
+\r
+ CoordinateX = FileBuffer.MousePosition.Column;\r
+ CoordinateY = FileBuffer.MousePosition.Row;\r
+\r
+ if (TextX >= 0) {\r
+ CoordinateX += TextX;\r
+ } else {\r
+ if (CoordinateX >= AbsX) {\r
+ CoordinateX -= AbsX;\r
+ } else {\r
+ CoordinateX = 0;\r
+ }\r
+ }\r
+\r
+ if (TextY >= 0) {\r
+ CoordinateY += TextY;\r
+ } else {\r
+ if (CoordinateY >= AbsY) {\r
+ CoordinateY -= AbsY;\r
+ } else {\r
+ CoordinateY = 0;\r
+ }\r
+ }\r
+ //\r
+ // check whether new mouse column position is beyond screen\r
+ // if not, adjust it\r
+ //\r
+ if (CoordinateX >= 1 && CoordinateX <= MainEditor.ScreenSize.Column) {\r
+ FileBuffer.MousePosition.Column = CoordinateX;\r
+ } else if (CoordinateX < 1) {\r
+ FileBuffer.MousePosition.Column = 1;\r
+ } else if (CoordinateX > MainEditor.ScreenSize.Column) {\r
+ FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column;\r
+ }\r
+ //\r
+ // check whether new mouse row position is beyond screen\r
+ // if not, adjust it\r
+ //\r
+ if (CoordinateY >= 2 && CoordinateY <= (MainEditor.ScreenSize.Row - 4)) {\r
+ FileBuffer.MousePosition.Row = CoordinateY;\r
+ } else if (CoordinateY < 2) {\r
+ FileBuffer.MousePosition.Row = 2;\r
+ } else if (CoordinateY > (MainEditor.ScreenSize.Row - 4)) {\r
+ FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 4);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Search and replace operation.\r
+\r
+ @param[in] SearchStr The string to search for.\r
+ @param[in] ReplaceStr The string to replace with.\r
+ @param[in] Offset The column to start at.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferReplaceAll (\r
+ IN CHAR16 *SearchStr,\r
+ IN CHAR16 *ReplaceStr,\r
+ IN UINTN Offset\r
+ )\r
+{\r
+ CHAR16 *Buffer;\r
+ UINTN Position;\r
+ UINTN Column;\r
+ UINTN ReplaceLen;\r
+ UINTN SearchLen;\r
+ UINTN Index;\r
+ UINTN NewSize;\r
+ UINTN OldSize;\r
+ UINTN Gap;\r
+ EFI_EDITOR_LINE *Line;\r
+ LIST_ENTRY *Link;\r
+ CHAR16 *CharPos;\r
+\r
+ SearchLen = StrLen (SearchStr);\r
+ ReplaceLen = StrLen (ReplaceStr);\r
+\r
+ Column = FileBuffer.FilePosition.Column + Offset - 1;\r
+\r
+ if (Column > FileBuffer.CurrentLine->Size) {\r
+ Column = FileBuffer.CurrentLine->Size;\r
+ }\r
+\r
+ Link = &(FileBuffer.CurrentLine->Link);\r
+\r
+ while (Link != FileBuffer.ListHead) {\r
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+ CharPos = StrStr (Line->Buffer + Column, SearchStr);\r
+ if (CharPos != NULL) {\r
+ Position = CharPos - Line->Buffer;// + Column;\r
+ //\r
+ // found\r
+ //\r
+ if (ReplaceLen > SearchLen) {\r
+ OldSize = Line->Size + 1;\r
+ //\r
+ // include CHAR_NULL\r
+ //\r
+ NewSize = OldSize + (ReplaceLen - SearchLen);\r
+\r
+ //\r
+ // do not have the enough space\r
+ //\r
+ if (Line->TotalSize + 1 <= NewSize) {\r
+ Line->Buffer = ReallocatePool (\r
+ 2 * OldSize,\r
+ 2 * NewSize,\r
+ Line->Buffer\r
+ );\r
+ Line->TotalSize = NewSize - 1;\r
+ }\r
+\r
+ if (Line->Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // the end CHAR_NULL character;\r
+ //\r
+ Buffer = Line->Buffer + (NewSize - 1);\r
+ Gap = ReplaceLen - SearchLen;\r
+\r
+ //\r
+ // keep the latter part\r
+ //\r
+ for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) {\r
+ *Buffer = *(Buffer - Gap);\r
+ Buffer--;\r
+ }\r
+\r
+ } else if (ReplaceLen < SearchLen){\r
+ Buffer = Line->Buffer + Position + ReplaceLen;\r
+ Gap = SearchLen - ReplaceLen;\r
+\r
+ for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) {\r
+ *Buffer = *(Buffer + Gap);\r
+ Buffer++;\r
+ }\r
+ } else {\r
+ ASSERT(ReplaceLen == SearchLen);\r
+ }\r
+ //\r
+ // set replace into it\r
+ //\r
+ Buffer = Line->Buffer + Position;\r
+ for (Index = 0; Index < ReplaceLen; Index++) {\r
+ Buffer[Index] = ReplaceStr[Index];\r
+ }\r
+\r
+ Line->Size += (ReplaceLen - SearchLen);\r
+ Column += ReplaceLen;\r
+ } else {\r
+ //\r
+ // not found\r
+ //\r
+ Column = 0;\r
+ Link = Link->ForwardLink;\r
+ }\r
+ }\r
+ //\r
+ // call refresh to fresh edit area\r
+ //\r
+ FileBuffer.FileModified = TRUE;\r
+ FileBufferNeedRefresh = TRUE;\r
+ FileBufferRefresh ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set the modified state to TRUE.\r
+**/\r
+VOID\r
+EFIAPI\r
+FileBufferSetModified (\r
+ VOID\r
+ )\r
+{\r
+ FileBuffer.FileModified = TRUE;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Declares filebuffer interface functions.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_FILE_BUFFER_H_\r
+#define _LIB_FILE_BUFFER_H_\r
+\r
+#include "TextEditorTypes.h"\r
+\r
+/**\r
+ Initialization function for FileBuffer.\r
+\r
+ @param EFI_SUCCESS The initialization was successful.\r
+ @param EFI_LOAD_ERROR A default name could not be created.\r
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferInit (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Cleanup function for FileBuffer.\r
+\r
+ @retval EFI_SUCCESS The cleanup was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferCleanup (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Refresh the screen with whats in the buffer.\r
+\r
+ @retval EFI_SUCCESS The refresh was successful.\r
+ @retval EFI_LOAD_ERROR There was an error finding what to write.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferRefresh (\r
+ VOID\r
+ );\r
+\r
+/** \r
+ Dispatch input to different handler\r
+ @param[in] Key The input key. One of:\r
+ ASCII KEY\r
+ Backspace/Delete\r
+ Return\r
+ Direction key: up/down/left/right/pgup/pgdn\r
+ Home/End\r
+ INS\r
+\r
+ @retval EFI_SUCCESS The dispatch was done successfully.\r
+ @retval EFI_LOAD_ERROR The dispatch was not successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferHandleInput (\r
+ IN CONST EFI_INPUT_KEY * Key\r
+ );\r
+\r
+/**\r
+ Backup function for FileBuffer. Only backup the following items:\r
+ Mouse/Cursor position\r
+ File Name, Type, ReadOnly, Modified\r
+ Insert Mode\r
+\r
+ This is for making the file buffer refresh as few as possible.\r
+\r
+ @retval EFI_SUCCESS The backup operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferBackup (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Set the cursor position according to FileBuffer.DisplayPosition.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferRestorePosition (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Set FileName field in FileBuffer.\r
+\r
+ @param Str The file name to set.\r
+ \r
+ @retval EFI_SUCCESS The filename was successfully set.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferSetFileName (\r
+ IN CONST CHAR16 *Str\r
+ );\r
+\r
+/**\r
+ Read a file from disk into the FileBuffer.\r
+ \r
+ @param[in] FileName The filename to read.\r
+ @param[in] Recover TRUE if is for recover mode, no information printouts.\r
+ \r
+ @retval EFI_SUCCESS The load was successful.\r
+ @retval EFI_LOAD_ERROR The load failed.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER FileName is a directory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferRead (\r
+ IN CONST CHAR16 *FileName,\r
+ IN CONST BOOLEAN Recover\r
+ );\r
+\r
+/**\r
+ Save lines in FileBuffer to disk\r
+\r
+ @param[in] FileName The file name for writing.\r
+\r
+ @retval EFI_SUCCESS Data was written.\r
+ @retval EFI_LOAD_ERROR \r
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferSave (\r
+ CONST CHAR16 *FileName\r
+ );\r
+\r
+/**\r
+ According to cursor's file position, adjust screen display\r
+\r
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).\r
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).\r
+**/\r
+VOID\r
+EFIAPI\r
+FileBufferMovePosition (\r
+ IN CONST UINTN NewFilePosRow,\r
+ IN CONST UINTN NewFilePosCol\r
+ );\r
+\r
+/**\r
+ Cut current line out and return a pointer to it.\r
+\r
+ @param[out] CutLine Upon a successful return pointer to the pointer to \r
+ the allocated cut line.\r
+\r
+ @retval EFI_SUCCESS The cut was successful.\r
+ @retval EFI_NOT_FOUND There was no selection to cut.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferCutLine (\r
+ OUT EFI_EDITOR_LINE **CutLine\r
+ );\r
+\r
+/**\r
+ Paste a line into line list.\r
+\r
+ @retval EFI_SUCCESS The paste was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferPasteLine (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Search string from current position on in file\r
+\r
+ @param[in] Str The search string.\r
+ @param[in] Offset The offset from current position.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_NOT_FOUND The string Str was not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferSearch (\r
+ IN CONST CHAR16 *Str,\r
+ IN CONST UINTN Offset\r
+ );\r
+\r
+/**\r
+ Replace SearchLen characters from current position on with Replace.\r
+\r
+ This will modify the current buffer at the current position.\r
+\r
+ @param[in] Replace The string to replace.\r
+ @param[in] SearchLen Search string's length.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferReplace (\r
+ IN CONST CHAR16 *Replace,\r
+ IN CONST UINTN SearchLen\r
+ );\r
+\r
+/**\r
+ Search and replace operation.\r
+\r
+ @param[in] SearchStr The string to search for.\r
+ @param[in] ReplaceStr The string to replace with.\r
+ @param[in] Offset The column to start at.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileBufferReplaceAll (\r
+ IN CHAR16 *SearchStr,\r
+ IN CHAR16 *ReplaceStr,\r
+ IN UINTN Offset\r
+ );\r
+\r
+/**\r
+ Move the mouse cursor position.\r
+\r
+ @param[in] TextX The new x-coordinate.\r
+ @param[in] TextY The new y-coordinate.\r
+**/\r
+VOID\r
+EFIAPI\r
+FileBufferAdjustMousePosition (\r
+ IN CONST INT32 TextX,\r
+ IN CONST INT32 TextY\r
+ );\r
+\r
+/**\r
+ Set the modified state to TRUE.\r
+**/\r
+VOID\r
+EFIAPI\r
+FileBufferSetModified (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Implements editor interface functions.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TextEditor.h"\r
+#include "EditStatusBar.h"\r
+#include "EditInputBar.h"\r
+\r
+/**\r
+ Load a file from disk to editor\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandOpenFile (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Switch a file from ASCII to UNICODE or vise-versa.\r
+\r
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSwitchFileType (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ move cursor to specified lines\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandGotoLine (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Save current file to disk, you can save to current file name or\r
+ save to another file name.\r
+ \r
+ @retval EFI_SUCCESS The file was saved correctly.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A file access error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSaveFile (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ exit editor\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandExit (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ search string in file buffer\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSearch (\r
+ VOID\r
+ );\r
+\r
+/*\r
+ search string in file buffer, and replace it with another str\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSearchReplace (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ cut current line to clipboard\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandCutLine (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ paste line to file buffer.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandPasteLine (\r
+ VOID\r
+ );\r
+\r
+EDITOR_MENU_ITEM MainMenuItems[] = {\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),\r
+ MainCommandGotoLine\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),\r
+ MainCommandSaveFile\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),\r
+ MainCommandExit\r
+ },\r
+\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),\r
+ MainCommandSearch\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),\r
+ MainCommandSearchReplace\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),\r
+ MainCommandCutLine\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),\r
+ MainCommandPasteLine\r
+ },\r
+\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),\r
+ MainCommandOpenFile\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),\r
+ MainCommandSwitchFileType\r
+ },\r
+\r
+ {\r
+ 0,\r
+ 0,\r
+ NULL\r
+ }\r
+};\r
+\r
+\r
+/**\r
+ Load a file from disk to editor\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandOpenFile (\r
+ VOID\r
+ )\r
+{\r
+ BOOLEAN Done;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // This command will open a file from current working directory.\r
+ // Read-only file can also be opened. But it can not be modified.\r
+ // Below is the scenario of Open File command:\r
+ // 1.IF currently opened file has not been modIFied, directly go to step .\r
+ // IF currently opened file has been modified,\r
+ // an Input Bar will be prompted as :\r
+ // "File Modified. Save ( Yes/No/Cancel) ?"\r
+ // IF user press 'y' or 'Y', currently opened file will be saved.\r
+ // IF user press 'n' or 'N', currently opened file will\r
+ // not be saved.\r
+ // IF user press 'c' or 'C' or ESC, Open File command ends and\r
+ // currently opened file is still opened.\r
+ //\r
+ // 2. An Input Bar will be prompted as : "File Name to Open: "\r
+ // IF user press ESC, Open File command ends and\r
+ // currently opened file is still opened.\r
+ // Any other inputs with a Return will\r
+ // cause currently opened file close.\r
+ //\r
+ // 3. IF user input file name is an existing file , this file will be read\r
+ // and opened.\r
+ // IF user input file name is a new file, this file will be created\r
+ // and opened. This file's type ( UNICODE or ASCII ) is the same\r
+ // with the old file.\r
+ // if current file is modified, so you need to choose\r
+ // whether to save it first.\r
+ //\r
+ if (MainEditor.FileBuffer->FileModified) {\r
+\r
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // the answer is just one character\r
+ //\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // loop for user's answer\r
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
+ //\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ //\r
+ // want to save this file first\r
+ //\r
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);\r
+ FileBufferRestorePosition ();\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ //\r
+ // the file won't be saved\r
+ //\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // TO get the open file name\r
+ //\r
+ Status = InputBarSetPrompt (L"File Name to Open: ");\r
+ if (EFI_ERROR (Status)) {\r
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (100);\r
+ if (EFI_ERROR (Status)) {\r
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // The input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ //\r
+ // CHECK if filename is valid\r
+ //\r
+ if (!IsValidFileName (InputBarGetString())) {\r
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);\r
+ StatusBarSetStatusString (L"Invalid File Name");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // read from disk\r
+ //\r
+ Status = FileBufferRead (InputBarGetString(), FALSE);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Switch a file from ASCII to UNICODE or vise-versa.\r
+\r
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSwitchFileType (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Below is the scenario of File Type command:\r
+ // After File Type is executed, file type will be changed to another type\r
+ // if file is read-only, can not be modified\r
+ //\r
+ if (MainEditor.FileBuffer->ReadOnly) {\r
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {\r
+ MainEditor.FileBuffer->FileType = FileTypeAscii;\r
+ } else {\r
+ MainEditor.FileBuffer->FileType = FileTypeUnicode;\r
+ }\r
+\r
+ MainEditor.FileBuffer->FileModified = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ cut current line to clipboard\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandCutLine (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EDITOR_LINE *Line;\r
+\r
+ //\r
+ // This command will cut current line ( where cursor is on ) to clip board.\r
+ // And cursor will move to the beginning of next line.\r
+ // Below is the scenario of Cut Line command:\r
+ // 1. IF cursor is on valid line, current line will be cut to clip board.\r
+ // IF cursor is not on valid line, an Status String will be prompted :\r
+ // "Nothing to Cut".\r
+ //\r
+ Status = FileBufferCutLine (&Line);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ MainEditor.CutLine = Line;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ paste line to file buffer.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandPasteLine (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Below is the scenario of Paste Line command:\r
+ // 1. IF nothing is on clipboard, a Status String will be prompted :\r
+ // "No Line to Paste" and Paste Line command ends.\r
+ // IF something is on clipboard, insert it above current line.\r
+ // nothing on clipboard\r
+ //\r
+ if (MainEditor.CutLine == NULL) {\r
+ StatusBarSetStatusString (L"No Line to Paste");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = FileBufferPasteLine ();\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ search string in file buffer\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSearch (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *Buffer;\r
+ BOOLEAN Done;\r
+ UINTN Offset;\r
+\r
+ //\r
+ // Below is the scenario of Search command:\r
+ // 1. An Input Bar will be prompted : "Enter Search String:".\r
+ // IF user press ESC, Search command ends.\r
+ // IF user just press Enter, Search command ends.\r
+ // IF user inputs the search string, do Step 2.\r
+ //\r
+ // 2. IF input search string is found, cursor will move to the first\r
+ // occurrence and do Step 3.\r
+ // IF input search string is not found, a Status String\r
+ // "Search String Not Found" will be prompted and Search command ends.\r
+ //\r
+ // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".\r
+ // IF user press ESC, Search command ends.\r
+ // IF user press 'y' or 'Y', do Step 2.\r
+ // IF user press 'n' or 'N', Search command ends.\r
+ // IF user press 'c' or 'C', Search command ends.\r
+ //\r
+ Status = InputBarSetPrompt (L"Enter Search String: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (40);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // just enter pressed\r
+ //\r
+ if (StrLen (InputBarGetString()) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Buffer = CatSPrint (NULL, L"%s", InputBarGetString());\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // the first time , search from current position\r
+ //\r
+ Offset = 0;\r
+ do {\r
+ //\r
+ // since search may be continued to search multiple times\r
+ // so we need to backup editor each time\r
+ //\r
+ MainEditorBackup ();\r
+\r
+ Status = FileBufferSearch (Buffer, Offset);\r
+\r
+ if (Status == EFI_NOT_FOUND) {\r
+ break;\r
+ }\r
+ //\r
+ // Find next\r
+ //\r
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ return Status;\r
+ }\r
+\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ FreePool (Buffer);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ FreePool (Buffer);\r
+ return EFI_SUCCESS;\r
+\r
+ }\r
+ //\r
+ // end of which\r
+ //\r
+ }\r
+ //\r
+ // end of while !Done\r
+ // for search second, third time, search from current position + strlen\r
+ //\r
+ Offset = StrLen (Buffer);\r
+\r
+ } while (1);\r
+ //\r
+ // end of do\r
+ //\r
+ FreePool (Buffer);\r
+ StatusBarSetStatusString (L"Search String Not Found");\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/*\r
+ search string in file buffer, and replace it with another str\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSearchReplace (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *Search;\r
+ CHAR16 *Replace;\r
+ BOOLEAN Done;\r
+ BOOLEAN First;\r
+ BOOLEAN ReplaceOption;\r
+ UINTN SearchLen;\r
+ UINTN ReplaceLen;\r
+ BOOLEAN ReplaceAll;\r
+\r
+ ReplaceOption = FALSE;\r
+\r
+ //\r
+ // Below is the scenario of Search/Replace command:\r
+ // 1. An Input Bar is prompted : "Enter Search String:".\r
+ // IF user press ESC, Search/Replace command ends.\r
+ // IF user just press Enter, Search/Replace command ends.\r
+ // IF user inputs the search string S, do Step 2.\r
+ //\r
+ // 2. An Input Bar is prompted: "Replace With:".\r
+ // IF user press ESC, Search/Replace command ends.\r
+ // IF user inputs the replace string R, do Step 3.\r
+ //\r
+ // 3. IF input search string is not found, an Status String\r
+ // "Search String Not Found" will be prompted\r
+ // and Search/Replace command ends\r
+ // IF input search string is found, do Step 4.\r
+ //\r
+ // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"\r
+ // IF user press 'y' or 'Y', S will be replaced with R and do Step 5\r
+ // IF user press 'n' or 'N', S will not be replaced and do Step 5.\r
+ // IF user press 'a' or 'A', all the S from file current position on\r
+ // will be replaced with R and Search/Replace command ends.\r
+ // IF user press 'c' or 'C' or ESC, Search/Replace command ends.\r
+ //\r
+ // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".\r
+ // IF user press ESC, Search/Replace command ends.\r
+ // IF user press 'y' or 'Y', do Step 3.\r
+ // IF user press 'n' or 'N', Search/Replace command ends.\r
+ // IF user press 'c' or 'C', Search/Replace command ends.\r
+ // input search string\r
+ //\r
+ Status = InputBarSetPrompt (L"Enter Search String: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (40);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // if just pressed enter\r
+ //\r
+ if (StrLen (InputBarGetString()) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Search = CatSPrint (NULL, L"%s", InputBarGetString());\r
+ if (Search == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ SearchLen = StrLen (Search);\r
+\r
+ //\r
+ // input replace string\r
+ //\r
+ Status = InputBarSetPrompt (L"Replace With: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (40);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Replace = CatSPrint (NULL, L"%s", InputBarGetString());\r
+ if (Replace == NULL) {\r
+ FreePool (Search);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ReplaceLen = StrLen (Replace);\r
+\r
+ First = TRUE;\r
+ ReplaceAll = FALSE;\r
+ do {\r
+ //\r
+ // since search may be continued to search multiple times\r
+ // so we need to backup editor each time\r
+ //\r
+ MainEditorBackup ();\r
+\r
+ if (First) {\r
+ Status = FileBufferSearch (Search, 0);\r
+ } else {\r
+ //\r
+ // if just replace, so skip this replace string\r
+ // if replace string is an empty string, so skip to next character\r
+ //\r
+ if (ReplaceOption) {\r
+ Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen);\r
+ } else {\r
+ Status = FileBufferSearch (Search, SearchLen);\r
+ }\r
+ }\r
+\r
+ if (Status == EFI_NOT_FOUND) {\r
+ break;\r
+ }\r
+ //\r
+ // replace or not?\r
+ //\r
+ Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?");\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return Status;\r
+ }\r
+\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ Done = TRUE;\r
+ ReplaceOption = TRUE;\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ Done = TRUE;\r
+ ReplaceOption = FALSE;\r
+ break;\r
+\r
+ case L'a':\r
+ case L'A':\r
+ Done = TRUE;\r
+ ReplaceOption = TRUE;\r
+ ReplaceAll = TRUE;\r
+ break;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return EFI_SUCCESS;\r
+\r
+ }\r
+ //\r
+ // end of which\r
+ //\r
+ }\r
+ //\r
+ // end of while !Done\r
+ // Decide to Replace\r
+ //\r
+ if (ReplaceOption) {\r
+ //\r
+ // file is read-only\r
+ //\r
+ if (MainEditor.FileBuffer->ReadOnly) {\r
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // replace all\r
+ //\r
+ if (ReplaceAll) {\r
+ Status = FileBufferReplaceAll (Search, Replace, 0);\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return Status;\r
+ }\r
+ //\r
+ // replace\r
+ //\r
+ Status = FileBufferReplace (Replace, SearchLen);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // Find next\r
+ //\r
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return Status;\r
+ }\r
+\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+ return EFI_SUCCESS;\r
+\r
+ }\r
+ //\r
+ // end of which\r
+ //\r
+ }\r
+ //\r
+ // end of while !Done\r
+ //\r
+ First = FALSE;\r
+\r
+ } while (1);\r
+ //\r
+ // end of do\r
+ //\r
+ FreePool (Search);\r
+ FreePool (Replace);\r
+\r
+ StatusBarSetStatusString (L"Search String Not Found");\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ exit editor\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandExit (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Below is the scenario of Exit command:\r
+ // 1. IF currently opened file is not modified, exit the editor and\r
+ // Exit command ends.\r
+ // IF currently opened file is modified, do Step 2\r
+ //\r
+ // 2. An Input Bar will be prompted:\r
+ // "File modified. Save ( Yes/No/Cancel )?"\r
+ // IF user press 'y' or 'Y', currently opened file will be saved\r
+ // and Editor exits\r
+ // IF user press 'n' or 'N', currently opened file will not be saved\r
+ // and Editor exits.\r
+ // IF user press 'c' or 'C' or ESC, Exit command ends.\r
+ // if file has been modified, so will prompt user whether to save the changes\r
+ //\r
+ if (MainEditor.FileBuffer->FileModified) {\r
+\r
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ //\r
+ // write file back to disk\r
+ //\r
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);\r
+ if (!EFI_ERROR (Status)) {\r
+ EditorExit = TRUE;\r
+ }\r
+\r
+ return Status;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ EditorExit = TRUE;\r
+ return EFI_SUCCESS;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ return EFI_SUCCESS;\r
+\r
+ }\r
+ }\r
+ }\r
+\r
+ EditorExit = TRUE;\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ move cursor to specified lines\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandGotoLine (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Row;\r
+\r
+ //\r
+ // Below is the scenario of Go To Line command:\r
+ // 1. An Input Bar will be prompted : "Go To Line:".\r
+ // IF user press ESC, Go To Line command ends.\r
+ // IF user just press Enter, cursor remains unchanged.\r
+ // IF user inputs line number, do Step 2.\r
+ //\r
+ // 2. IF input line number is valid, move cursor to the beginning\r
+ // of specified line and Go To Line command ends.\r
+ // IF input line number is invalid, a Status String will be prompted:\r
+ // "No Such Line" and Go To Line command ends.\r
+ //\r
+ Status = InputBarSetPrompt (L"Go To Line: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // line number's digit <= 6\r
+ //\r
+ Status = InputBarSetStringSize (6);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // press ESC\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // if JUST press enter\r
+ //\r
+ if (StrLen (InputBarGetString()) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Row = ShellStrToUintn (InputBarGetString());\r
+\r
+ //\r
+ // invalid line number\r
+ //\r
+ if (Row > MainEditor.FileBuffer->NumLines || Row <= 0) {\r
+ StatusBarSetStatusString (L"No Such Line");\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // move cursor to that line's start\r
+ //\r
+ FileBufferMovePosition (Row, 1);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Save current file to disk, you can save to current file name or\r
+ save to another file name.\r
+ \r
+ @retval EFI_SUCCESS The file was saved correctly.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR A file access error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainCommandSaveFile (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *FileName;\r
+ BOOLEAN OldFile;\r
+ CHAR16 *Str;\r
+ SHELL_FILE_HANDLE FileHandle; \r
+ EFI_FILE_INFO *Info;\r
+\r
+ //\r
+ // This command will save currently opened file to disk.\r
+ // You can choose save to another file name or just save to\r
+ // current file name.\r
+ // Below is the scenario of Save File command:\r
+ // ( Suppose the old file name is A )\r
+ // 1. An Input Bar will be prompted: "File To Save: [ old file name]"\r
+ // IF user press ESC, Save File command ends .\r
+ // IF user press Enter, input file name will be A.\r
+ // IF user inputs a new file name B, input file name will be B.\r
+ //\r
+ // 2. IF input file name is A, go to do Step 3.\r
+ // IF input file name is B, go to do Step 4.\r
+ //\r
+ // 3. IF A is read only, Status Bar will show "Access Denied" and\r
+ // Save File commands ends.\r
+ // IF A is not read only, save file buffer to disk and remove modified\r
+ // flag in Title Bar , then Save File command ends.\r
+ //\r
+ // 4. IF B does not exist, create this file and save file buffer to it.\r
+ // Go to do Step 7.\r
+ // IF B exits, do Step 5.\r
+ //\r
+ // 5.An Input Bar will be prompted:\r
+ // "File Exists. Overwrite ( Yes/No/Cancel )?"\r
+ // IF user press 'y' or 'Y', do Step 6.\r
+ // IF user press 'n' or 'N', Save File commands ends.\r
+ // IF user press 'c' or 'C' or ESC, Save File commands ends.\r
+ //\r
+ // 6. IF B is a read-only file, Status Bar will show "Access Denied" and\r
+ // Save File commands ends.\r
+ // IF B can be read and write, save file buffer to B.\r
+ //\r
+ // 7. Update File Name field in Title Bar to B and remove the modified\r
+ // flag in Title Bar.\r
+ //\r
+ Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName);\r
+ if (Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (StrLen (Str) >= 50) {\r
+ //\r
+ // replace the long file name with "..."\r
+ //\r
+ Str[46] = L'.';\r
+ Str[47] = L'.';\r
+ Str[48] = L'.';\r
+ Str[49] = L']';\r
+ Str[50] = CHAR_NULL;\r
+ }\r
+\r
+ Status = InputBarSetPrompt (Str);\r
+ FreePool(Str);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+\r
+ Status = InputBarSetStringSize (100);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // get new file name\r
+ //\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // if user pressed ESC\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // if just enter pressed, so think save to current file name\r
+ //\r
+ if (StrLen (InputBarGetString()) == 0) {\r
+ FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName);\r
+ } else {\r
+ FileName = CatSPrint (NULL, L"%s", InputBarGetString());\r
+ }\r
+\r
+ if (FileName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (!IsValidFileName (FileName)) {\r
+ StatusBarSetStatusString (L"Invalid File Name");\r
+ FreePool (FileName);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldFile = FALSE;\r
+\r
+ //\r
+ // save to the old file\r
+ //\r
+ if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) {\r
+ OldFile = TRUE;\r
+ }\r
+\r
+ if (OldFile) {\r
+ //\r
+ // if the file is read only, so can not write back to it.\r
+ //\r
+ if (MainEditor.FileBuffer->ReadOnly == TRUE) {\r
+ StatusBarSetStatusString (L"Access Denied");\r
+ FreePool (FileName);\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ //\r
+ // if the file exists\r
+ //\r
+ if (ShellFileExists(FileName) != EFI_NOT_FOUND) {\r
+ //\r
+ // check for read only\r
+ //\r
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+ if (EFI_ERROR(Status)) {\r
+ StatusBarSetStatusString (L"Open Failed");\r
+ FreePool (FileName);\r
+ return EFI_SUCCESS;\r
+ } \r
+\r
+ Info = ShellGetFileInfo(FileHandle);\r
+ if (Info == NULL) {\r
+ StatusBarSetStatusString (L"Access Denied");\r
+ FreePool (FileName);\r
+ return (EFI_SUCCESS);\r
+ } \r
+ \r
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {\r
+ StatusBarSetStatusString (L"Access Denied - Read Only");\r
+ FreePool (Info);\r
+ FreePool (FileName);\r
+ return (EFI_SUCCESS);\r
+ }\r
+ FreePool (Info);\r
+\r
+ //\r
+ // ask user whether to overwrite this file\r
+ //\r
+ Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return Status;\r
+ }\r
+\r
+ while (TRUE) {\r
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ case L'c':\r
+ case L'C':\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ } // end switch\r
+ } // while (!done)\r
+ } // file does exist\r
+ } // if old file name same\r
+\r
+ //\r
+ // save file to disk with specified name\r
+ //\r
+ FileBufferSetModified();\r
+ Status = FileBufferSave (FileName);\r
+ SHELL_FREE_NON_NULL (FileName);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors;\r
+INTN OriginalMode;\r
+\r
+//\r
+// the first time editor launch\r
+//\r
+BOOLEAN EditorFirst;\r
+\r
+//\r
+// it's time editor should exit\r
+//\r
+BOOLEAN EditorExit;\r
+\r
+BOOLEAN EditorMouseAction;\r
+\r
+extern EFI_EDITOR_FILE_BUFFER FileBuffer;\r
+\r
+extern BOOLEAN FileBufferMouseNeedRefresh;\r
+\r
+extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;\r
+\r
+EFI_EDITOR_GLOBAL_EDITOR MainEditor;\r
+\r
+//\r
+// basic initialization for MainEditor\r
+//\r
+EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {\r
+ &FileBuffer,\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ NULL,\r
+ FALSE,\r
+ NULL\r
+};\r
+\r
+/**\r
+ The initialization function for MainEditor.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorInit (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+\r
+ //\r
+ // basic initialization\r
+ //\r
+ CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor));\r
+\r
+ //\r
+ // set screen attributes\r
+ //\r
+ MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;\r
+\r
+ MainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);\r
+ OriginalColors = MainEditor.ColorAttributes.Colors;\r
+\r
+ OriginalMode = gST->ConOut->Mode->Mode;\r
+\r
+ //\r
+ // query screen size\r
+ //\r
+ gST->ConOut->QueryMode (\r
+ gST->ConOut,\r
+ gST->ConOut->Mode->Mode,\r
+ &(MainEditor.ScreenSize.Column),\r
+ &(MainEditor.ScreenSize.Row)\r
+ );\r
+\r
+ //\r
+ // Find mouse in System Table ConsoleInHandle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConIn,\r
+ &gEfiSimplePointerProtocolGuid,\r
+ (VOID**)&MainEditor.MouseInterface\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If there is no Simple Pointer Protocol on System Table\r
+ //\r
+ HandleBuffer = NULL;\r
+ MainEditor.MouseInterface = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimplePointerProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status) && HandleCount > 0) {\r
+ //\r
+ // Try to find the first available mouse device\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiSimplePointerProtocolGuid,\r
+ (VOID**)&MainEditor.MouseInterface\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status) && MainEditor.MouseInterface != NULL) {\r
+ MainEditor.MouseAccumulatorX = 0;\r
+ MainEditor.MouseAccumulatorY = 0;\r
+ MainEditor.MouseSupported = TRUE;\r
+ }\r
+\r
+ //\r
+ // below will call the five components' init function\r
+ //\r
+ Status = MainTitleBarInit (L"UEFI EDIT 2.0");\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = MenuBarInit (MainMenuItems);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = StatusBarInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ InputBarInit ();\r
+\r
+ Status = FileBufferInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ //\r
+ // clear whole screen and enable cursor\r
+ //\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ //\r
+ // initialize EditorFirst and EditorExit\r
+ //\r
+ EditorFirst = TRUE;\r
+ EditorExit = FALSE;\r
+ EditorMouseAction = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ The cleanup function for MainEditor.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorCleanup (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // call the five components' cleanup function\r
+ // if error, do not exit\r
+ // just print some warning\r
+ //\r
+ MainTitleBarCleanup();\r
+ StatusBarCleanup();\r
+ InputBarCleanup();\r
+ MenuBarCleanup ();\r
+\r
+ Status = FileBufferCleanup ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle);\r
+ }\r
+ //\r
+ // restore old mode\r
+ //\r
+ if (OriginalMode != gST->ConOut->Mode->Mode) {\r
+ gST->ConOut->SetMode (gST->ConOut, OriginalMode);\r
+ }\r
+ //\r
+ // restore old screen color\r
+ //\r
+ gST->ConOut->SetAttribute (\r
+ gST->ConOut,\r
+ EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background)\r
+ );\r
+\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Refresh the main editor component.\r
+**/\r
+VOID\r
+EFIAPI\r
+MainEditorRefresh (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // The Stall value is from experience. NOT from spec. avoids 'flicker'\r
+ //\r
+ gBS->Stall (50);\r
+\r
+ //\r
+ // call the components refresh function\r
+ //\r
+ if (EditorFirst \r
+ || StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0 \r
+ || FileBufferBackupVar.FileType != FileBuffer.FileType \r
+ || FileBufferBackupVar.FileModified != FileBuffer.FileModified \r
+ || FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly) {\r
+\r
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);\r
+ FileBufferRestorePosition ();\r
+ FileBufferRefresh ();\r
+ }\r
+ if (EditorFirst\r
+ || FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row \r
+ || FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column \r
+ || FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert\r
+ || StatusBarGetRefresh()) {\r
+\r
+ StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert);\r
+ FileBufferRestorePosition ();\r
+ FileBufferRefresh ();\r
+ }\r
+\r
+ if (EditorFirst) {\r
+ MenuBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
+ FileBufferRestorePosition ();\r
+ }\r
+\r
+ //\r
+ // EditorFirst is now set to FALSE\r
+ //\r
+ EditorFirst = FALSE;\r
+}\r
+\r
+/**\r
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.\r
+\r
+ @param[in] GuidX The relative mouse movement.\r
+\r
+ @return The X location of the mouse.\r
+**/\r
+INT32\r
+EFIAPI\r
+GetTextX (\r
+ IN INT32 GuidX\r
+ )\r
+{\r
+ INT32 Gap;\r
+\r
+ MainEditor.MouseAccumulatorX += GuidX;\r
+ Gap = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);\r
+ MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);\r
+ MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32) MainEditor.ScreenSize.Column;\r
+ return Gap;\r
+}\r
+\r
+/**\r
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.\r
+\r
+ @param[in] GuidY The relative mouse movement.\r
+\r
+ @return The Y location of the mouse.\r
+**/\r
+INT32\r
+EFIAPI\r
+GetTextY (\r
+ IN INT32 GuidY\r
+ )\r
+{\r
+ INT32 Gap;\r
+\r
+ MainEditor.MouseAccumulatorY += GuidY;\r
+ Gap = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);\r
+ MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);\r
+ MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32) MainEditor.ScreenSize.Row;\r
+\r
+ return Gap;\r
+}\r
+\r
+/**\r
+ Support mouse movement. Move the cursor.\r
+\r
+ @param[in] MouseState The current mouse state.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_NOT_FOUND There was no mouse support found.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorHandleMouseInput (\r
+ IN EFI_SIMPLE_POINTER_STATE MouseState\r
+ )\r
+{\r
+\r
+ INT32 TextX;\r
+ INT32 TextY;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ LIST_ENTRY *Link;\r
+ EFI_EDITOR_LINE *Line;\r
+\r
+ UINTN Index;\r
+ BOOLEAN Action;\r
+\r
+ //\r
+ // mouse action means:\r
+ // mouse movement\r
+ // mouse left button\r
+ //\r
+ Action = FALSE;\r
+\r
+ //\r
+ // have mouse movement\r
+ //\r
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {\r
+ //\r
+ // handle\r
+ //\r
+ TextX = GetTextX (MouseState.RelativeMovementX);\r
+ TextY = GetTextY (MouseState.RelativeMovementY);\r
+\r
+ FileBufferAdjustMousePosition (TextX, TextY);\r
+\r
+ Action = TRUE;\r
+\r
+ }\r
+\r
+ //\r
+ // if left button pushed down\r
+ //\r
+ if (MouseState.LeftButton) {\r
+\r
+ FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1;\r
+\r
+ FRow = MainEditor.FileBuffer->FilePosition.Row +\r
+ MainEditor.FileBuffer->MousePosition.Row -\r
+ MainEditor.FileBuffer->DisplayPosition.Row;\r
+\r
+ //\r
+ // beyond the file line length\r
+ //\r
+ if (MainEditor.FileBuffer->NumLines < FRow) {\r
+ FRow = MainEditor.FileBuffer->NumLines;\r
+ }\r
+\r
+ Link = MainEditor.FileBuffer->ListHead->ForwardLink;\r
+ for (Index = 0; Index < FRow - 1; Index++) {\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
+\r
+ //\r
+ // beyond the line's column length\r
+ //\r
+ if (FCol > Line->Size + 1) {\r
+ FCol = Line->Size + 1;\r
+ }\r
+\r
+ FileBufferMovePosition (FRow, FCol);\r
+\r
+ MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row;\r
+\r
+ MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column;\r
+\r
+ Action = TRUE;\r
+ }\r
+ //\r
+ // mouse has action\r
+ //\r
+ if (Action) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // no mouse action\r
+ //\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Handle user key input. This routes to other functions for the actions.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorKeyInput (\r
+ VOID\r
+ )\r
+{\r
+ EFI_INPUT_KEY Key;\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_POINTER_STATE MouseState;\r
+\r
+ do {\r
+\r
+ Status = EFI_SUCCESS;\r
+ EditorMouseAction = FALSE;\r
+\r
+ //\r
+ // backup some key elements, so that can aVOID some refresh work\r
+ //\r
+ MainEditorBackup ();\r
+\r
+ //\r
+ // change priority of checking mouse/keyboard activity dynamically\r
+ // so prevent starvation of keyboard.\r
+ // if last time, mouse moves then this time check keyboard\r
+ //\r
+ if (MainEditor.MouseSupported) {\r
+ Status = MainEditor.MouseInterface->GetState (\r
+ MainEditor.MouseInterface,\r
+ &MouseState\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ Status = MainEditorHandleMouseInput (MouseState);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ EditorMouseAction = TRUE;\r
+ FileBufferMouseNeedRefresh = TRUE;\r
+ } else if (Status == EFI_LOAD_ERROR) {\r
+ StatusBarSetStatusString (L"Invalid Mouse Movement ");\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // dispatch to different components' key handling function\r
+ // so not everywhere has to set this variable\r
+ //\r
+ FileBufferMouseNeedRefresh = TRUE;\r
+ //\r
+ // clear previous status string\r
+ //\r
+ StatusBarSetRefresh();\r
+\r
+ //\r
+ // dispatch to different components' key handling function\r
+ //\r
+ if ((Key.ScanCode == SCAN_NULL) || ((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {\r
+ Status = FileBufferHandleInput (&Key);\r
+ } else if ((Key.ScanCode >= SCAN_F1) && (Key.ScanCode <= SCAN_F12)) {\r
+ Status = MenuBarDispatchFunctionKey (&Key);\r
+ } else {\r
+ StatusBarSetStatusString (L"Unknown Command");\r
+ FileBufferMouseNeedRefresh = FALSE;\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {\r
+ //\r
+ // not already has some error status\r
+ //\r
+ if (StatusBarGetString() != NULL && StrCmp (L"", StatusBarGetString()) == 0) {\r
+ StatusBarSetStatusString (L"Disk Error. Try Again");\r
+ }\r
+ }\r
+\r
+ }\r
+ //\r
+ // after handling, refresh editor\r
+ //\r
+ MainEditorRefresh ();\r
+\r
+ } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set clipboard\r
+\r
+ @param[in] Line A pointer to the line to be set to clipboard\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorSetCutLine (\r
+ EFI_EDITOR_LINE *Line\r
+ )\r
+{\r
+ if (Line == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (MainEditor.CutLine != NULL) {\r
+ //\r
+ // free the old clipboard\r
+ //\r
+ LineFree (MainEditor.CutLine);\r
+ }\r
+ //\r
+ // duplicate the line to clipboard\r
+ //\r
+ MainEditor.CutLine = LineDup (Line);\r
+ if (MainEditor.CutLine == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Backup function for MainEditor\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorBackup (\r
+ VOID\r
+ )\r
+{\r
+ FileBufferBackup ();\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Declares editor interface functions.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_EDITOR_H_\r
+#define _LIB_EDITOR_H_\r
+\r
+#include "TextEditorTypes.h"\r
+\r
+/**\r
+ The initialization function for MainEditor.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorInit (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ The cleanup function for MainEditor.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorCleanup (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Refresh the main editor component.\r
+**/\r
+VOID\r
+EFIAPI\r
+MainEditorRefresh (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Handle user key input. This routes to other functions for the actions.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @retval EFI_LOAD_ERROR A load error occured.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorKeyInput (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Backup function for MainEditor\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MainEditorBackup (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Implementation of various string and line routines.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TextEditor.h"\r
+#include "Misc.h"\r
+\r
+/**\r
+ Duplicate a EFI_EDITOR_LINE structure.\r
+\r
+ @param Src The line structure to copy from.\r
+\r
+ @retval NULL A memory allocation failed.\r
+ @return a pointer to the newly allcoated line.\r
+**/\r
+EFI_EDITOR_LINE *\r
+EFIAPI\r
+LineDup (\r
+ IN EFI_EDITOR_LINE *Src\r
+ )\r
+{\r
+ EFI_EDITOR_LINE *Dest;\r
+\r
+ //\r
+ // allocate for the line structure\r
+ //\r
+ Dest = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));\r
+ if (Dest == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // allocate and set the line buffer\r
+ //\r
+ Dest->Buffer = CatSPrint (NULL, L"%s", Src->Buffer);\r
+ if (Dest->Buffer == NULL) {\r
+ FreePool (Dest);\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // set the other structure members\r
+ //\r
+ Dest->Signature = LINE_LIST_SIGNATURE;\r
+ Dest->Size = Src->Size;\r
+ Dest->TotalSize = Dest->Size;\r
+ Dest->Type = Src->Type;\r
+ Dest->Link = Src->Link;\r
+\r
+ return Dest;\r
+}\r
+\r
+/**\r
+ Free a EFI_EDITOR_LINE structure.\r
+\r
+ @param Src The line structure to free.\r
+**/\r
+VOID\r
+EFIAPI\r
+LineFree (\r
+ IN EFI_EDITOR_LINE *Src\r
+ )\r
+{\r
+ if (Src == NULL) {\r
+ return ;\r
+ }\r
+ //\r
+ // free the line buffer and then the line structure itself\r
+ //\r
+ SHELL_FREE_NON_NULL (Src->Buffer);\r
+ SHELL_FREE_NON_NULL (Src);\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
--- /dev/null
+/** @file\r
+ Declares generic editor helper functions.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_MISC_H_\r
+#define _LIB_MISC_H_\r
+\r
+#include "TextEditorTypes.h"\r
+\r
+\r
+\r
+/**\r
+ Free a EFI_EDITOR_LINE structure.\r
+\r
+ @param Src The line structure to free.\r
+**/\r
+VOID\r
+EFIAPI\r
+LineFree (\r
+ IN EFI_EDITOR_LINE *Src\r
+ );\r
+\r
+/**\r
+ Duplicate a EFI_EDITOR_LINE structure.\r
+\r
+ @param Src The line structure to copy from.\r
+\r
+ @retval NULL A memory allocation failed.\r
+ @return a pointer to the newly allcoated line.\r
+**/\r
+EFI_EDITOR_LINE *\r
+EFIAPI\r
+LineDup (\r
+ IN EFI_EDITOR_LINE *Src\r
+ );\r
+\r
+\r
+\r
+\r
+\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Main include file for Edit shell Debug1 function.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_EDIT_H_\r
+#define _EFI_EDIT_H_\r
+\r
+#include "TextEditorTypes.h"\r
+\r
+#include "MainTextEditor.h"\r
+#include "FileBuffer.h"\r
+#include "EditTitleBar.h"\r
+#include "EditStatusBar.h"\r
+#include "EditInputBar.h"\r
+#include "EditMenuBar.h"\r
+#include "Misc.h"\r
+\r
+extern EFI_EDITOR_GLOBAL_EDITOR MainEditor;\r
+extern BOOLEAN EditorFirst;\r
+extern BOOLEAN EditorExit;\r
+\r
+#endif // _EFI_EDIT_H_\r
--- /dev/null
+/** @file\r
+ Declares editor types.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EDITOR_TYPE_H_\r
+#define _EDITOR_TYPE_H_\r
+\r
+#include "UefiShellDebug1CommandsLib.h"\r
+#include "EditTitleBar.h"\r
+#include "EditMenuBar.h"\r
+\r
+#define MIN_POOL_SIZE 125\r
+#define MAX_STRING_LENGTH 127\r
+\r
+typedef struct {\r
+ UINTN Row;\r
+ UINTN Column;\r
+} EFI_EDITOR_POSITION;\r
+\r
+typedef\r
+EFI_STATUS\r
+(*EFI_MENU_ITEM_FUNCTION) (\r
+ VOID\r
+ );\r
+\r
+typedef enum {\r
+ NewLineTypeDefault,\r
+ NewLineTypeLineFeed,\r
+ NewLineTypeCarriageReturn,\r
+ NewLineTypeCarriageReturnLineFeed,\r
+ NewLineTypeLineFeedCarriageReturn,\r
+ NewLineTypeUnknown\r
+} EE_NEWLINE_TYPE;\r
+\r
+#define LINE_LIST_SIGNATURE 'eell'\r
+typedef struct _EFI_EDITOR_LINE {\r
+ UINTN Signature;\r
+ CHAR16 *Buffer;\r
+ UINTN Size; // unit is Unicode\r
+ UINTN TotalSize; // unit is Unicode, exclude CHAR_NULL\r
+ EE_NEWLINE_TYPE Type;\r
+ LIST_ENTRY Link;\r
+} EFI_EDITOR_LINE;\r
+\r
+typedef struct {\r
+ UINT32 Foreground : 4;\r
+ UINT32 Background : 4;\r
+} EFI_EDITOR_COLOR_ATTRIBUTES;\r
+\r
+typedef union {\r
+ EFI_EDITOR_COLOR_ATTRIBUTES Colors;\r
+ UINTN Data;\r
+} EFI_EDITOR_COLOR_UNION;\r
+\r
+typedef struct {\r
+ UINTN Columns;\r
+ UINTN Rows;\r
+} EFI_EDITOR_TEXT_MODE;\r
+\r
+typedef struct {\r
+ CHAR16 *FileName; // file name current edited in editor\r
+ EDIT_FILE_TYPE FileType; // Unicode file or ASCII file\r
+ LIST_ENTRY *ListHead; // list head of lines\r
+ EFI_EDITOR_LINE *Lines; // lines of current file\r
+ UINTN NumLines; // total line numbers\r
+ EFI_EDITOR_POSITION DisplayPosition; // cursor position in screen\r
+ EFI_EDITOR_POSITION FilePosition; // cursor position in file\r
+ EFI_EDITOR_POSITION MousePosition; // mouse position in screen\r
+ // file position of first byte displayed on screen\r
+ //\r
+ EFI_EDITOR_POSITION LowVisibleRange;\r
+\r
+ BOOLEAN FileModified; // file is modified or not\r
+ BOOLEAN ModeInsert; // input mode INS or OVR\r
+ BOOLEAN ReadOnly; // file is read-only or not\r
+ EFI_EDITOR_LINE *CurrentLine; // current line cursor is at\r
+} EFI_EDITOR_FILE_BUFFER;\r
+\r
+typedef struct {\r
+ EFI_EDITOR_FILE_BUFFER *FileBuffer;\r
+\r
+ EFI_EDITOR_COLOR_UNION ColorAttributes;\r
+ EFI_EDITOR_POSITION ScreenSize; // row number and column number\r
+ EFI_EDITOR_LINE *CutLine; // clip board\r
+ BOOLEAN MouseSupported;\r
+ EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;\r
+ INT32 MouseAccumulatorX;\r
+ INT32 MouseAccumulatorY;\r
+\r
+} EFI_EDITOR_GLOBAL_EDITOR;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Defines HBufferImage - the view of the file that is visible at any point,\r
+ as well as the event handlers for editing the file\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+\r
+extern EFI_HANDLE HImageHandleBackup;\r
+\r
+extern HEFI_EDITOR_FILE_IMAGE HFileImage;\r
+extern HEFI_EDITOR_DISK_IMAGE HDiskImage;\r
+extern HEFI_EDITOR_MEM_IMAGE HMemImage;\r
+\r
+extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;\r
+extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;\r
+extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;\r
+\r
+extern BOOLEAN HEditorMouseAction;\r
+\r
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;\r
+\r
+HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
+HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;\r
+\r
+//\r
+// for basic initialization of HBufferImage\r
+//\r
+HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = {\r
+ NULL,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ 0,\r
+ TRUE,\r
+ FALSE,\r
+ FileTypeNone,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+//\r
+// the whole edit area needs to be refreshed\r
+//\r
+BOOLEAN HBufferImageNeedRefresh;\r
+\r
+//\r
+// only the current line in edit area needs to be refresh\r
+//\r
+BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
+\r
+BOOLEAN HBufferImageMouseNeedRefresh;\r
+\r
+EFI_STATUS\r
+HBufferImageInit (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Initialization function for HBufferImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // basically initialize the HBufferImage\r
+ //\r
+ CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage));\r
+\r
+ //\r
+ // INIT listhead\r
+ //\r
+ HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));\r
+ if (HBufferImage.ListHead == NULL) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ InitializeListHead (HBufferImage.ListHead);\r
+\r
+ HBufferImage.DisplayPosition.Row = 2;\r
+ HBufferImage.DisplayPosition.Column = 10;\r
+ HBufferImage.MousePosition.Row = 2;\r
+ HBufferImage.MousePosition.Column = 10;\r
+\r
+ HBufferImage.FileImage = &HFileImage;\r
+ HBufferImage.DiskImage = &HDiskImage;\r
+ HBufferImage.MemImage = &HMemImage;\r
+\r
+ HBufferImageNeedRefresh = FALSE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ HBufferImageMouseNeedRefresh = FALSE;\r
+\r
+ HBufferImageBackupVar.FileImage = &HFileImageBackupVar;\r
+ HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar;\r
+ HBufferImageBackupVar.MemImage = &HMemImageBackupVar;\r
+\r
+ Status = HFileImageInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = HDiskImageInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = HMemImageInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageBackup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Backup function for HBufferImage\r
+ Only a few fields need to be backup. \r
+ This is for making the file buffer refresh \r
+ as few as possible.\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition;\r
+\r
+ HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition;\r
+\r
+ HBufferImageBackupVar.Modified = HBufferImage.Modified;\r
+\r
+ HBufferImageBackupVar.BufferType = HBufferImage.BufferType;\r
+ HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow;\r
+ HBufferImageBackupVar.HighBits = HBufferImage.HighBits;\r
+\r
+ //\r
+ // three kinds of buffer supported\r
+ // file buffer\r
+ // disk buffer\r
+ // memory buffer\r
+ //\r
+ switch (HBufferImage.BufferType) {\r
+ case FileTypeFileBuffer:\r
+ HFileImageBackup ();\r
+ break;\r
+\r
+ case FileTypeDiskBuffer:\r
+ HDiskImageBackup ();\r
+ break;\r
+\r
+ case FileTypeMemBuffer:\r
+ HMemImageBackup ();\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageFreeLines (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Free all the lines in HBufferImage\r
+ Fields affected:\r
+ Lines\r
+ CurrentLine\r
+ NumLines\r
+ ListHead \r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HFreeLines (HBufferImage.ListHead, HBufferImage.Lines);\r
+\r
+ HBufferImage.Lines = NULL;\r
+ HBufferImage.CurrentLine = NULL;\r
+ HBufferImage.NumLines = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageCleanup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Cleanup function for HBufferImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // free all the lines\r
+ //\r
+ Status = HBufferImageFreeLines ();\r
+\r
+ SHELL_FREE_NON_NULL (HBufferImage.ListHead);\r
+ HBufferImage.ListHead = NULL;\r
+\r
+ HFileImageCleanup ();\r
+ HDiskImageCleanup ();\r
+ HMemImageCleanup ();\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImagePrintLine (\r
+ IN HEFI_EDITOR_LINE *Line,\r
+ IN UINTN Row,\r
+ IN UINTN FRow,\r
+ IN HEFI_EDITOR_COLOR_UNION Orig,\r
+ IN HEFI_EDITOR_COLOR_UNION New\r
+\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Print Line on Row\r
+\r
+Arguments: \r
+\r
+ Line - Line to print\r
+ Row - Row on screen ( begin from 1 )\r
+ FRow - FRow\r
+ Orig - Orig\r
+ New - Light display\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+\r
+ UINTN Index;\r
+ UINTN Pos;\r
+ BOOLEAN Selected;\r
+ BOOLEAN BeNewColor;\r
+ UINTN RowStart;\r
+ UINTN RowEnd;\r
+ UINTN ColStart;\r
+ UINTN ColEnd;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ ColStart = 0;\r
+ ColEnd = 0;\r
+ Selected = FALSE;\r
+\r
+ //\r
+ // print the selected area in opposite color\r
+ //\r
+ if (HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {\r
+ RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
+ RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;\r
+\r
+ ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;\r
+ ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;\r
+\r
+ if (FRow >= RowStart && FRow <= RowEnd) {\r
+ Selected = TRUE;\r
+ }\r
+\r
+ if (FRow > RowStart) {\r
+ ColStart = 1;\r
+ }\r
+\r
+ if (FRow < RowEnd) {\r
+ ColEnd = 0x10;\r
+ }\r
+\r
+ }\r
+\r
+ if (HEditorMouseAction == FALSE) {\r
+ ShellPrintEx (\r
+ 0,\r
+ (INT32)Row - 1,\r
+ L"%8X ",\r
+ ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10\r
+ );\r
+\r
+ }\r
+\r
+ for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) {\r
+\r
+ BeNewColor = FALSE;\r
+\r
+ if (Selected) {\r
+ if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {\r
+ BeNewColor = TRUE;\r
+ }\r
+ }\r
+\r
+ if (BeNewColor) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ }\r
+\r
+ Pos = 10 + (Index * 3);\r
+ if (Line->Buffer[Index] < 0x10) {\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");\r
+ Pos++;\r
+ }\r
+\r
+ if (Index < 0x07) {\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);\r
+ } else {\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);\r
+ }\r
+\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ while (Index < 0x08) {\r
+ Pos = 10 + (Index * 3);\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
+ Index++;\r
+ }\r
+\r
+ while (Index < 0x10 && Index < Line->Size) {\r
+\r
+ BeNewColor = FALSE;\r
+\r
+ if (Selected) {\r
+ if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {\r
+ BeNewColor = TRUE;\r
+ }\r
+ }\r
+\r
+ if (BeNewColor) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ }\r
+\r
+ Pos = 10 + (Index * 3) + 1;\r
+ if (Line->Buffer[Index] < 0x10) {\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");\r
+ Pos++;\r
+ }\r
+\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);\r
+ Index++;\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ while (Index < 0x10) {\r
+ Pos = 10 + (Index * 3) + 1;\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
+ Index++;\r
+ }\r
+ //\r
+ // restore the original color\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+\r
+ //\r
+ // PRINT the buffer content\r
+ //\r
+ if (HEditorMouseAction == FALSE) {\r
+ for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) {\r
+ Pos = ASCII_POSITION + Index;\r
+\r
+ //\r
+ // learned from shelle.h -- IsValidChar\r
+ //\r
+ if (Line->Buffer[Index] >= L' ') {\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16) Line->Buffer[Index]);\r
+ } else {\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.');\r
+ }\r
+ }\r
+\r
+ while (Index < 0x10) {\r
+ Pos = ASCII_POSITION + Index;\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
+ Index++;\r
+ }\r
+ }\r
+ //\r
+ // restore the abundant blank in hex edit area to original color\r
+ //\r
+ if (Selected) {\r
+ if (ColEnd <= 7) {\r
+ Pos = 10 + (ColEnd - 1) * 3 + 2;\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
+ } else if (ColEnd == 8) {\r
+ Pos = 10 + (ColEnd - 1) * 3 + 2;\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
+ } else {\r
+ Pos = 10 + (ColEnd - 1) * 3 + 3;\r
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+HBufferImageIsAtHighBits (\r
+ IN UINTN Column,\r
+ OUT UINTN *FCol\r
+ )\r
+{\r
+ Column -= 10;\r
+\r
+ //\r
+ // NOW AFTER THE SUB, Column start from 0\r
+ // 23 AND 24 ARE BOTH BLANK\r
+ //\r
+ if (Column == 24) {\r
+ *FCol = 0;\r
+ return FALSE;\r
+ }\r
+\r
+ if (Column > 24) {\r
+ Column--;\r
+ }\r
+\r
+ *FCol = (Column / 3) + 1;\r
+\r
+ if (!(Column % 3)) {\r
+ return TRUE;\r
+ }\r
+\r
+ if ((Column % 3 == 2)) {\r
+ *FCol = 0;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+HBufferImageIsInSelectedArea (\r
+ IN UINTN MouseRow,\r
+ IN UINTN MouseCol\r
+ )\r
+{\r
+ UINTN FRow;\r
+ UINTN RowStart;\r
+ UINTN RowEnd;\r
+ UINTN ColStart;\r
+ UINTN ColEnd;\r
+ UINTN MouseColStart;\r
+ UINTN MouseColEnd;\r
+\r
+ //\r
+ // judge mouse position whether is in selected area\r
+ //\r
+ //\r
+ // not select\r
+ //\r
+ if (HMainEditor.SelectStart == 0 || HMainEditor.SelectEnd == 0) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // calculate the select area\r
+ //\r
+ RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
+ RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;\r
+\r
+ ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;\r
+ ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;\r
+\r
+ FRow = HBufferImage.LowVisibleRow + MouseRow - 2;\r
+ if (FRow < RowStart || FRow > RowEnd) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (FRow > RowStart) {\r
+ ColStart = 1;\r
+ }\r
+\r
+ if (FRow < RowEnd) {\r
+ ColEnd = 0x10;\r
+ }\r
+\r
+ MouseColStart = 10 + (ColStart - 1) * 3;\r
+ if (ColStart > 8) {\r
+ MouseColStart++;\r
+ }\r
+\r
+ MouseColEnd = 10 + (ColEnd - 1) * 3 + 1;\r
+ if (ColEnd > 8) {\r
+ MouseColEnd++;\r
+ }\r
+\r
+ if (MouseCol < MouseColStart || MouseCol > MouseColEnd) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageRestoreMousePosition (\r
+ VOID\r
+ )\r
+{\r
+ HEFI_EDITOR_COLOR_UNION Orig;\r
+ HEFI_EDITOR_COLOR_UNION New;\r
+ UINTN FRow;\r
+ UINTN FColumn;\r
+ BOOLEAN HasCharacter;\r
+ HEFI_EDITOR_LINE *CurrentLine;\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINT8 Value;\r
+ BOOLEAN HighBits;\r
+\r
+ Line = NULL;\r
+ if (HMainEditor.MouseSupported) {\r
+\r
+ if (HBufferImageMouseNeedRefresh) {\r
+\r
+ HBufferImageMouseNeedRefresh = FALSE;\r
+\r
+ //\r
+ // if mouse position not moved and only mouse action\r
+ // so do not need to refresh mouse position\r
+ //\r
+ if ((\r
+ HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row &&\r
+ HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column\r
+ ) &&\r
+ HEditorMouseAction\r
+ ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // backup the old screen attributes\r
+ //\r
+ Orig = HMainEditor.ColorAttributes;\r
+ New.Colors.Foreground = Orig.Colors.Background;\r
+ New.Colors.Background = Orig.Colors.Foreground;\r
+\r
+ //\r
+ // if in selected area,\r
+ // so do not need to refresh mouse\r
+ //\r
+ if (!HBufferImageIsInSelectedArea (\r
+ HBufferImageBackupVar.MousePosition.Row,\r
+ HBufferImageBackupVar.MousePosition.Column\r
+ )) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);\r
+ }\r
+ //\r
+ // clear the old mouse position\r
+ //\r
+ FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2;\r
+\r
+ HighBits = HBufferImageIsAtHighBits (\r
+ HBufferImageBackupVar.MousePosition.Column,\r
+ &FColumn\r
+ );\r
+\r
+ HasCharacter = TRUE;\r
+ if (FRow > HBufferImage.NumLines || FColumn == 0) {\r
+ HasCharacter = FALSE;\r
+ } else {\r
+ CurrentLine = HBufferImage.CurrentLine;\r
+ Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);\r
+\r
+ if (FColumn > Line->Size) {\r
+ HasCharacter = FALSE;\r
+ }\r
+\r
+ HBufferImage.CurrentLine = CurrentLine;\r
+ }\r
+\r
+ ShellPrintEx (\r
+ (INT32)HBufferImageBackupVar.MousePosition.Column - 1,\r
+ (INT32)HBufferImageBackupVar.MousePosition.Row - 1,\r
+ L" "\r
+ );\r
+\r
+ if (HasCharacter) {\r
+ if (HighBits) {\r
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);\r
+ Value = (UINT8) (Value >> 4);\r
+ } else {\r
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);\r
+ }\r
+\r
+ ShellPrintEx (\r
+ (INT32)HBufferImageBackupVar.MousePosition.Column - 1,\r
+ (INT32)HBufferImageBackupVar.MousePosition.Row - 1,\r
+ L"%x",\r
+ Value\r
+ );\r
+ }\r
+\r
+ if (!HBufferImageIsInSelectedArea (\r
+ HBufferImage.MousePosition.Row,\r
+ HBufferImage.MousePosition.Column\r
+ )) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data);\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ }\r
+ //\r
+ // clear the old mouse position\r
+ //\r
+ FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2;\r
+\r
+ HighBits = HBufferImageIsAtHighBits (\r
+ HBufferImage.MousePosition.Column,\r
+ &FColumn\r
+ );\r
+\r
+ HasCharacter = TRUE;\r
+ if (FRow > HBufferImage.NumLines || FColumn == 0) {\r
+ HasCharacter = FALSE;\r
+ } else {\r
+ CurrentLine = HBufferImage.CurrentLine;\r
+ Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);\r
+\r
+ if (FColumn > Line->Size) {\r
+ HasCharacter = FALSE;\r
+ }\r
+\r
+ HBufferImage.CurrentLine = CurrentLine;\r
+ }\r
+\r
+ ShellPrintEx (\r
+ (INT32)HBufferImage.MousePosition.Column - 1,\r
+ (INT32)HBufferImage.MousePosition.Row - 1,\r
+ L" "\r
+ );\r
+\r
+ if (HasCharacter) {\r
+ if (HighBits) {\r
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);\r
+ Value = (UINT8) (Value >> 4);\r
+ } else {\r
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);\r
+ }\r
+\r
+ ShellPrintEx (\r
+ (INT32)HBufferImage.MousePosition.Column - 1,\r
+ (INT32)HBufferImage.MousePosition.Row - 1,\r
+ L"%x",\r
+ Value\r
+ );\r
+ }\r
+ //\r
+ // end of HasCharacter\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
+ }\r
+ //\r
+ // end of MouseNeedRefresh\r
+ //\r
+ }\r
+ //\r
+ // end of MouseSupported\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageRestorePosition (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Set cursor position according to HBufferImage.DisplayPosition.\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ //\r
+ // set cursor position\r
+ //\r
+ gST->ConOut->SetCursorPosition (\r
+ gST->ConOut,\r
+ HBufferImage.DisplayPosition.Column - 1,\r
+ HBufferImage.DisplayPosition.Row - 1\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageRefresh (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Refresh function for HBufferImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR \r
+\r
+--*/\r
+{\r
+ LIST_ENTRY *Link;\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN Row;\r
+ HEFI_EDITOR_COLOR_UNION Orig;\r
+ HEFI_EDITOR_COLOR_UNION New;\r
+\r
+ UINTN StartRow;\r
+ UINTN EndRow;\r
+ UINTN FStartRow;\r
+ UINTN FEndRow;\r
+ UINTN Tmp;\r
+\r
+ Orig = HMainEditor.ColorAttributes;\r
+ New.Colors.Foreground = Orig.Colors.Background;\r
+ New.Colors.Background = Orig.Colors.Foreground;\r
+\r
+ //\r
+ // if it's the first time after editor launch, so should refresh\r
+ //\r
+ if (HEditorFirst == FALSE) {\r
+ //\r
+ // no definite required refresh\r
+ // and file position displayed on screen has not been changed\r
+ //\r
+ if (HBufferImageNeedRefresh == FALSE &&\r
+ HBufferImageOnlyLineNeedRefresh == FALSE &&\r
+ HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow\r
+ ) {\r
+ HBufferImageRestoreMousePosition ();\r
+ HBufferImageRestorePosition ();\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+ //\r
+ // only need to refresh current line\r
+ //\r
+ if (HBufferImageOnlyLineNeedRefresh == TRUE && HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) {\r
+\r
+ HBufferImagePrintLine (\r
+ HBufferImage.CurrentLine,\r
+ HBufferImage.DisplayPosition.Row,\r
+ HBufferImage.BufferPosition.Row,\r
+ Orig,\r
+ New\r
+ );\r
+ } else {\r
+ //\r
+ // the whole edit area need refresh\r
+ //\r
+ if (HEditorMouseAction && HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {\r
+ if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) {\r
+ if (HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart && HMainEditorBackupVar.SelectStart != 0) {\r
+ StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1;\r
+ } else {\r
+ StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
+ }\r
+ } else {\r
+ StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
+ }\r
+\r
+ if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) {\r
+ EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1;\r
+ } else {\r
+ EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1;\r
+ }\r
+ //\r
+ // swap\r
+ //\r
+ if (StartRow > EndRow) {\r
+ Tmp = StartRow;\r
+ StartRow = EndRow;\r
+ EndRow = Tmp;\r
+ }\r
+\r
+ FStartRow = StartRow;\r
+ FEndRow = EndRow;\r
+\r
+ StartRow = 2 + StartRow - HBufferImage.LowVisibleRow;\r
+ EndRow = 2 + EndRow - HBufferImage.LowVisibleRow;\r
+\r
+ } else {\r
+ //\r
+ // not mouse selection actions\r
+ //\r
+ FStartRow = HBufferImage.LowVisibleRow;\r
+ StartRow = 2;\r
+ EndRow = (HMainEditor.ScreenSize.Row - 4);\r
+ }\r
+ //\r
+ // no line\r
+ //\r
+ if (HBufferImage.Lines == NULL) {\r
+ HBufferImageRestoreMousePosition ();\r
+ HBufferImageRestorePosition ();\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // get the first line that will be displayed\r
+ //\r
+ Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row);\r
+ if (Line == NULL) {\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Link = &(Line->Link);\r
+ Row = StartRow;\r
+ do {\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+ //\r
+ // print line at row\r
+ //\r
+ HBufferImagePrintLine (\r
+ Line,\r
+ Row,\r
+ HBufferImage.LowVisibleRow + Row - 2,\r
+ Orig,\r
+ New\r
+ );\r
+\r
+ Link = Link->ForwardLink;\r
+ Row++;\r
+ } while (Link != HBufferImage.ListHead && Row <= EndRow);\r
+\r
+ while (Row <= EndRow) {\r
+ HEditorClearLine (Row);\r
+ Row++;\r
+ }\r
+ //\r
+ // while not file end and not screen full\r
+ //\r
+ }\r
+\r
+ HBufferImageRestoreMousePosition ();\r
+ HBufferImageRestorePosition ();\r
+\r
+ HBufferImageNeedRefresh = FALSE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageRead (\r
+ IN CONST CHAR16 *FileName,\r
+ IN CONST CHAR16 *DiskName,\r
+ IN UINTN DiskOffset,\r
+ IN UINTN DiskSize,\r
+ IN UINTN MemOffset,\r
+ IN UINTN MemSize,\r
+ IN EDIT_FILE_TYPE BufferType,\r
+ IN BOOLEAN Recover\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDIT_FILE_TYPE BufferTypeBackup;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // three types of buffer supported\r
+ // file buffer\r
+ // disk buffer\r
+ // memory buffer\r
+ //\r
+ BufferTypeBackup = HBufferImage.BufferType;\r
+\r
+ switch (BufferType) {\r
+ case FileTypeFileBuffer:\r
+ Status = HFileImageRead (FileName, Recover);\r
+ break;\r
+\r
+ case FileTypeDiskBuffer:\r
+ Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);\r
+ break;\r
+\r
+ case FileTypeMemBuffer:\r
+ Status = HMemImageRead (MemOffset, MemSize, Recover);\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ HBufferImage.BufferType = BufferTypeBackup;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageSave (\r
+ IN CHAR16 *FileName,\r
+ IN CHAR16 *DiskName,\r
+ IN UINTN DiskOffset,\r
+ IN UINTN DiskSize,\r
+ IN UINTN MemOffset,\r
+ IN UINTN MemSize,\r
+ IN EDIT_FILE_TYPE BufferType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EDIT_FILE_TYPE BufferTypeBackup;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ BufferTypeBackup = HBufferImage.BufferType;\r
+\r
+ switch (HBufferImage.BufferType) {\r
+ //\r
+ // file buffer\r
+ //\r
+ case FileTypeFileBuffer:\r
+ Status = HFileImageSave (FileName);\r
+ break;\r
+\r
+ //\r
+ // disk buffer\r
+ //\r
+ case FileTypeDiskBuffer:\r
+ Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);\r
+ break;\r
+\r
+ //\r
+ // memory buffer\r
+ //\r
+ case FileTypeMemBuffer:\r
+ Status = HMemImageSave (MemOffset, MemSize);\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ HBufferImage.BufferType = BufferTypeBackup;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+HEFI_EDITOR_LINE *\r
+HBufferImageCreateLine (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Create a new line and append it to the line list\r
+ Fields affected:\r
+ NumLines\r
+ Lines \r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ NULL -- create line failed\r
+ Not NULL -- the line created\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ //\r
+ // allocate for line structure\r
+ //\r
+ Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));\r
+ if (Line == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Line->Signature = EFI_EDITOR_LINE_LIST;\r
+ Line->Size = 0;\r
+\r
+ HBufferImage.NumLines++;\r
+\r
+ //\r
+ // insert to line list\r
+ //\r
+ InsertTailList (HBufferImage.ListHead, &Line->Link);\r
+\r
+ if (HBufferImage.Lines == NULL) {\r
+ HBufferImage.Lines = CR (\r
+ HBufferImage.ListHead->ForwardLink,\r
+ HEFI_EDITOR_LINE,\r
+ Link,\r
+ EFI_EDITOR_LINE_LIST\r
+ );\r
+ }\r
+\r
+ return Line;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageFree (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Function called when load a new file in. It will free all the old lines\r
+ and set FileModified field to FALSE\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ //\r
+ // free all lines\r
+ //\r
+ HBufferImageFreeLines ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageHandleInput (\r
+ IN EFI_INPUT_KEY *Key\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Dispatch input to different handler\r
+\r
+Arguments: \r
+\r
+ Key -- input key\r
+ the keys can be:\r
+ ASCII KEY\r
+ Backspace/Delete\r
+ Direction key: up/down/left/right/pgup/pgdn\r
+ Home/End\r
+ INS\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (Key->ScanCode) {\r
+ //\r
+ // ordinary key\r
+ //\r
+ case SCAN_NULL:\r
+ Status = HBufferImageDoCharInput (Key->UnicodeChar);\r
+ break;\r
+\r
+ //\r
+ // up arrow\r
+ //\r
+ case SCAN_UP:\r
+ Status = HBufferImageScrollUp ();\r
+ break;\r
+\r
+ //\r
+ // down arrow\r
+ //\r
+ case SCAN_DOWN:\r
+ Status = HBufferImageScrollDown ();\r
+ break;\r
+\r
+ //\r
+ // right arrow\r
+ //\r
+ case SCAN_RIGHT:\r
+ Status = HBufferImageScrollRight ();\r
+ break;\r
+\r
+ //\r
+ // left arrow\r
+ //\r
+ case SCAN_LEFT:\r
+ Status = HBufferImageScrollLeft ();\r
+ break;\r
+\r
+ //\r
+ // page up\r
+ //\r
+ case SCAN_PAGE_UP:\r
+ Status = HBufferImagePageUp ();\r
+ break;\r
+\r
+ //\r
+ // page down\r
+ //\r
+ case SCAN_PAGE_DOWN:\r
+ Status = HBufferImagePageDown ();\r
+ break;\r
+\r
+ //\r
+ // delete\r
+ //\r
+ case SCAN_DELETE:\r
+ Status = HBufferImageDoDelete ();\r
+ break;\r
+\r
+ //\r
+ // home\r
+ //\r
+ case SCAN_HOME:\r
+ Status = HBufferImageHome ();\r
+ break;\r
+\r
+ //\r
+ // end\r
+ //\r
+ case SCAN_END:\r
+ Status = HBufferImageEnd ();\r
+ break;\r
+\r
+ default:\r
+ Status = StatusBarSetStatusString (L"Unknown Command");\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageDoCharInput (\r
+ IN CHAR16 Char\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ ASCII key + Backspace + return\r
+\r
+Arguments: \r
+\r
+ Char -- input char\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (Char) {\r
+ case 0:\r
+ break;\r
+\r
+ case 0x08:\r
+ Status = HBufferImageDoBackspace ();\r
+ break;\r
+\r
+ case 0x09:\r
+ case 0x0a:\r
+ case 0x0d:\r
+ //\r
+ // Tabs, Returns are thought as nothing\r
+ //\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // DEAL WITH ASCII CHAR, filter out thing like ctrl+f\r
+ //\r
+ if (Char > 127 || Char < 32) {\r
+ Status = StatusBarSetStatusString (L"Unknown Command");\r
+ } else {\r
+ Status = HBufferImageAddChar (Char);\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+INTN\r
+HBufferImageCharToHex (\r
+ IN CHAR16 Char\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ change char to int value based on Hex\r
+\r
+Arguments: \r
+\r
+ Char -- input char\r
+\r
+Returns: \r
+\r
+ int value;\r
+\r
+\r
+--*/\r
+{\r
+ //\r
+ // change the character to hex\r
+ //\r
+ if (Char >= L'0' && Char <= L'9') {\r
+ return (INTN) (Char - L'0');\r
+ }\r
+\r
+ if (Char >= L'a' && Char <= L'f') {\r
+ return (INTN) (Char - L'a' + 10);\r
+ }\r
+\r
+ if (Char >= L'A' && Char <= L'F') {\r
+ return (INTN) (Char - L'A' + 10);\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageAddChar (\r
+ IN CHAR16 Char\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Add character\r
+\r
+Arguments: \r
+\r
+ Char -- input char\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ HEFI_EDITOR_LINE *NewLine;\r
+ INTN Value;\r
+ UINT8 Old;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ BOOLEAN High;\r
+\r
+ Value = HBufferImageCharToHex (Char);\r
+\r
+ //\r
+ // invalid input\r
+ //\r
+ if (Value == -1) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+ High = HBufferImage.HighBits;\r
+\r
+ //\r
+ // only needs to refresh current line\r
+ //\r
+ HBufferImageOnlyLineNeedRefresh = TRUE;\r
+\r
+ //\r
+ // not a full line and beyond the last character\r
+ //\r
+ if (FCol > Line->Size) {\r
+ //\r
+ // cursor always at high 4 bits\r
+ // and always put input to the low 4 bits\r
+ //\r
+ Line->Buffer[Line->Size] = (UINT8) Value;\r
+ Line->Size++;\r
+ High = FALSE;\r
+ } else {\r
+\r
+ Old = Line->Buffer[FCol - 1];\r
+\r
+ //\r
+ // always put the input to the low 4 bits\r
+ //\r
+ Old = (UINT8) (Old & 0x0f);\r
+ Old = (UINT8) (Old << 4);\r
+ Old = (UINT8) (Value + Old);\r
+ Line->Buffer[FCol - 1] = Old;\r
+\r
+ //\r
+ // at the low 4 bits of the last character of a full line\r
+ // so if no next line, need to create a new line\r
+ //\r
+ if (High == FALSE && FCol == 0x10) {\r
+\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ HBufferImageNeedRefresh = TRUE;\r
+\r
+ if (Line->Link.ForwardLink == HBufferImage.ListHead) {\r
+ //\r
+ // last line\r
+ //\r
+ // create a new line\r
+ //\r
+ NewLine = HBufferImageCreateLine ();\r
+ if (NewLine == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // end of NULL\r
+ //\r
+ }\r
+ //\r
+ // end of == ListHead\r
+ //\r
+ }\r
+ //\r
+ // end of == 0x10\r
+ //\r
+ // if already at end of this line, scroll it to the start of next line\r
+ //\r
+ if (FCol == 0x10 && High == FALSE) {\r
+ //\r
+ // definitely has next line\r
+ //\r
+ FRow++;\r
+ FCol = 1;\r
+ High = TRUE;\r
+ } else {\r
+ //\r
+ // if not at end of this line, just move to next column\r
+ //\r
+ if (!High) {\r
+ FCol++;\r
+ }\r
+\r
+ if (High) {\r
+ High = FALSE;\r
+ } else {\r
+ High = TRUE;\r
+ }\r
+\r
+ }\r
+ //\r
+ // end of ==FALSE\r
+ //\r
+ }\r
+ //\r
+ // move cursor to right\r
+ //\r
+ HBufferImageMovePosition (FRow, FCol, High);\r
+\r
+ if (!HBufferImage.Modified) {\r
+ HBufferImage.Modified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+HInCurrentScreen (\r
+ IN UINTN FileRow\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Check user specified FileRow and FileCol is in current screen\r
+\r
+Arguments: \r
+\r
+ FileRow -- Row of file position ( start from 1 )\r
+\r
+\r
+Returns: \r
+\r
+ TRUE\r
+ FALSE\r
+\r
+--*/\r
+{\r
+ if (FileRow >= HBufferImage.LowVisibleRow && FileRow <= HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 5) - 1) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+HAboveCurrentScreen (\r
+ IN UINTN FileRow\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Check user specified FileRow is above current screen\r
+\r
+Arguments: \r
+\r
+ FileRow -- Row of file position ( start from 1 )\r
+ \r
+Returns: \r
+\r
+ TRUE\r
+ FALSE\r
+\r
+--*/\r
+{\r
+ if (FileRow < HBufferImage.LowVisibleRow) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+HUnderCurrentScreen (\r
+ IN UINTN FileRow\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Check user specified FileRow is under current screen\r
+\r
+Arguments: \r
+\r
+ FileRow -- Row of file position ( start from 1 )\r
+\r
+Returns: \r
+\r
+ TRUE\r
+ FALSE\r
+\r
+--*/\r
+{\r
+ if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 5) - 1) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+VOID\r
+HBufferImageMovePosition (\r
+ IN UINTN NewFilePosRow,\r
+ IN UINTN NewFilePosCol,\r
+ IN BOOLEAN HighBits\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ According to cursor's file position, adjust screen display\r
+\r
+Arguments: \r
+\r
+ NewFilePosRow -- Row of file position ( start from 1 )\r
+ NewFilePosCol -- Column of file position ( start from 1 ) \r
+ HighBits -- cursor will on high4 bits or low4 bits\r
+\r
+Returns: \r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ INTN RowGap;\r
+ UINTN Abs;\r
+ BOOLEAN Above;\r
+ BOOLEAN Under;\r
+ UINTN NewDisplayCol;\r
+\r
+ //\r
+ // CALCULATE gap between current file position and new file position\r
+ //\r
+ RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row;\r
+\r
+ Under = HUnderCurrentScreen (NewFilePosRow);\r
+ Above = HAboveCurrentScreen (NewFilePosRow);\r
+\r
+ HBufferImage.HighBits = HighBits;\r
+\r
+ //\r
+ // if is below current screen\r
+ //\r
+ if (Under) {\r
+ //\r
+ // display row will be unchanged\r
+ //\r
+ HBufferImage.BufferPosition.Row = NewFilePosRow;\r
+ } else {\r
+ if (Above) {\r
+ //\r
+ // has enough above line, so display row unchanged\r
+ // not has enough above lines, so the first line is\r
+ // at the first display line\r
+ //\r
+ if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {\r
+ HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;\r
+ }\r
+\r
+ HBufferImage.BufferPosition.Row = NewFilePosRow;\r
+ } else {\r
+ //\r
+ // in current screen\r
+ //\r
+ HBufferImage.BufferPosition.Row = NewFilePosRow;\r
+ if (RowGap <= 0) {\r
+ Abs = -RowGap;\r
+ HBufferImage.DisplayPosition.Row -= Abs;\r
+ } else {\r
+ HBufferImage.DisplayPosition.Row += RowGap;\r
+ }\r
+\r
+ }\r
+ }\r
+\r
+ HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);\r
+\r
+ //\r
+ // always in current screen\r
+ //\r
+ HBufferImage.BufferPosition.Column = NewFilePosCol;\r
+\r
+ NewDisplayCol = 10 + (NewFilePosCol - 1) * 3;\r
+ if (NewFilePosCol > 0x8) {\r
+ NewDisplayCol++;\r
+ }\r
+\r
+ if (HighBits == FALSE) {\r
+ NewDisplayCol++;\r
+ }\r
+\r
+ HBufferImage.DisplayPosition.Column = NewDisplayCol;\r
+\r
+ //\r
+ // let CurrentLine point to correct line;\r
+ //\r
+ HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);\r
+\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageScrollRight (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to right\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ //\r
+ // scroll right will always move to the high4 bits of the next character\r
+ //\r
+ HBufferImageNeedRefresh = FALSE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+\r
+ //\r
+ // this line is not full and no next line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // if already at end of this line, scroll it to the start of next line\r
+ //\r
+ if (FCol == 0x10) {\r
+ //\r
+ // has next line\r
+ //\r
+ if (Line->Link.ForwardLink != HBufferImage.ListHead) {\r
+ FRow++;\r
+ FCol = 1;\r
+\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ //\r
+ // if not at end of this line, just move to next column\r
+ //\r
+ FCol++;\r
+\r
+ }\r
+\r
+ HBufferImageMovePosition (FRow, FCol, TRUE);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageScrollLeft (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to left\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ HBufferImageNeedRefresh = FALSE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+\r
+ //\r
+ // if already at start of this line, so move to the end of previous line\r
+ //\r
+ if (FCol <= 1) {\r
+ //\r
+ // has previous line\r
+ //\r
+ if (Line->Link.BackLink != HBufferImage.ListHead) {\r
+ FRow--;\r
+ Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ FCol = Line->Size;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ //\r
+ // if not at start of this line, just move to previous column\r
+ //\r
+ FCol--;\r
+ }\r
+\r
+ HBufferImageMovePosition (FRow, FCol, TRUE);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageScrollDown (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to the next line\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ BOOLEAN HighBits;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+ HighBits = HBufferImage.HighBits;\r
+\r
+ //\r
+ // has next line\r
+ //\r
+ if (Line->Link.ForwardLink != HBufferImage.ListHead) {\r
+ FRow++;\r
+ Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+ //\r
+ // if the next line is not that long, so move to end of next line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ FCol = Line->Size + 1;\r
+ HighBits = TRUE;\r
+ }\r
+\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ HBufferImageMovePosition (FRow, FCol, HighBits);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageScrollUp (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to previous line\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+\r
+ //\r
+ // has previous line\r
+ //\r
+ if (Line->Link.BackLink != HBufferImage.ListHead) {\r
+ FRow--;\r
+\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImagePageDown (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to next page\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ UINTN Gap;\r
+ BOOLEAN HighBits;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+ HighBits = HBufferImage.HighBits;\r
+\r
+ //\r
+ // has next page\r
+ //\r
+ if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 5)) {\r
+ Gap = (HMainEditor.ScreenSize.Row - 5);\r
+ } else {\r
+ //\r
+ // MOVE CURSOR TO LAST LINE\r
+ //\r
+ Gap = HBufferImage.NumLines - FRow;\r
+ }\r
+ //\r
+ // get correct line\r
+ //\r
+ Line = HMoveLine (Gap);\r
+\r
+ //\r
+ // if that line, is not that long, so move to the end of that line\r
+ //\r
+ if (FCol > Line->Size) {\r
+ FCol = Line->Size + 1;\r
+ HighBits = TRUE;\r
+ }\r
+\r
+ FRow += Gap;\r
+\r
+ HBufferImageMovePosition (FRow, FCol, HighBits);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImagePageUp (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to previous page\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ UINTN Gap;\r
+ INTN Retreat;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+\r
+ //\r
+ // has previous page\r
+ //\r
+ if (FRow > (HMainEditor.ScreenSize.Row - 5)) {\r
+ Gap = (HMainEditor.ScreenSize.Row - 5);\r
+ } else {\r
+ //\r
+ // the first line of file will displayed on the first line of screen\r
+ //\r
+ Gap = FRow - 1;\r
+ }\r
+\r
+ Retreat = Gap;\r
+ Retreat = -Retreat;\r
+\r
+ //\r
+ // get correct line\r
+ //\r
+ Line = HMoveLine (Retreat);\r
+\r
+ FRow -= Gap;\r
+\r
+ HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageHome (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to start of line\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ BOOLEAN HighBits;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ //\r
+ // curosr will at the high bit\r
+ //\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = 1;\r
+ HighBits = TRUE;\r
+\r
+ //\r
+ // move cursor position\r
+ //\r
+ HBufferImageMovePosition (FRow, FCol, HighBits);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageEnd (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Scroll cursor to end of line\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ BOOLEAN HighBits;\r
+\r
+ //\r
+ // need refresh mouse\r
+ //\r
+ HBufferImageMouseNeedRefresh = TRUE;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+\r
+ if (Line->Size == 0x10) {\r
+ FCol = Line->Size;\r
+ HighBits = FALSE;\r
+ } else {\r
+ FCol = Line->Size + 1;\r
+ HighBits = TRUE;\r
+ }\r
+ //\r
+ // move cursor position\r
+ //\r
+ HBufferImageMovePosition (FRow, FCol, HighBits);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINTN\r
+HBufferImageGetTotalSize (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Size;\r
+\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ //\r
+ // calculate the total size of whole line list's buffer\r
+ //\r
+ if (HBufferImage.Lines == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ Line = CR (\r
+ HBufferImage.ListHead->BackLink,\r
+ HEFI_EDITOR_LINE,\r
+ Link,\r
+ EFI_EDITOR_LINE_LIST\r
+ );\r
+ //\r
+ // one line at most 0x10\r
+ //\r
+ Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;\r
+\r
+ return Size;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageDeleteCharacterFromBuffer (\r
+ IN UINTN Pos,\r
+ IN UINTN Count,\r
+ OUT UINT8 *DeleteBuffer\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ Delete character from buffer\r
+ \r
+Arguments:\r
+\r
+ Pos - Position, Pos starting from 0\r
+ Count - Count\r
+ DeleteBuffer - DeleteBuffer\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Success\r
+ \r
+--*/\r
+{\r
+ UINTN Index;\r
+\r
+ VOID *Buffer;\r
+ UINT8 *BufferPtr;\r
+ UINTN Size;\r
+\r
+ HEFI_EDITOR_LINE *Line;\r
+ LIST_ENTRY *Link;\r
+ UINTN StartRow;\r
+\r
+ UINTN OldFCol;\r
+ UINTN OldFRow;\r
+ UINTN OldPos;\r
+\r
+ UINTN NewPos;\r
+\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // get the line that start position is at\r
+ //\r
+ StartRow = Pos / 0x10;\r
+\r
+ Size = HBufferImageGetTotalSize ();\r
+\r
+ if (Size < Count) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ if (Size == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // relocate all the HBufferImage fields\r
+ //\r
+ OldFRow = HBufferImage.BufferPosition.Row;\r
+ OldFCol = HBufferImage.BufferPosition.Column;\r
+ OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;\r
+\r
+ if (Pos > 0) {\r
+ //\r
+ // has character before it,\r
+ // so locate according to block's previous character\r
+ //\r
+ NewPos = Pos - 1;\r
+\r
+ } else {\r
+ //\r
+ // has no character before it,\r
+ // so locate according to block's next character\r
+ //\r
+ NewPos = 0;\r
+ }\r
+\r
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
+\r
+ Buffer = AllocateZeroPool (Size);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HBufferImageListToBuffer (Buffer, Size);\r
+\r
+ BufferPtr = (UINT8 *) Buffer;\r
+\r
+ //\r
+ // pass deleted buffer out\r
+ //\r
+ if (DeleteBuffer != NULL) {\r
+ for (Index = 0; Index < Count; Index++) {\r
+ DeleteBuffer[Index] = BufferPtr[Pos + Index];\r
+ }\r
+ }\r
+ //\r
+ // delete the part from Pos\r
+ //\r
+ for (Index = Pos; Index < Size - Count; Index++) {\r
+ BufferPtr[Index] = BufferPtr[Index + Count];\r
+ }\r
+\r
+ Size -= Count;\r
+\r
+ HBufferImageFreeLines ();\r
+\r
+ Status = HBufferImageBufferToList (Buffer, Size);\r
+ FreePool (Buffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
+ for (Index = 0; Index < NewPos / 0x10; Index++) {\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ HBufferImage.CurrentLine = Line;\r
+\r
+ //\r
+ // if current cursor position if inside select area\r
+ // then move it to the block's NEXT character\r
+ //\r
+ if (OldPos >= Pos && OldPos < (Pos + Count)) {\r
+ NewPos = Pos;\r
+ } else {\r
+ if (OldPos < Pos) {\r
+ NewPos = OldPos;\r
+ } else {\r
+ NewPos = OldPos - Count;\r
+ }\r
+ }\r
+\r
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageAddCharacterToBuffer (\r
+ IN UINTN Pos,\r
+ IN UINTN Count,\r
+ IN UINT8 *AddBuffer\r
+ )\r
+/*++'\r
+Routine Description:\r
+\r
+ Add character to buffer, add before pos\r
+\r
+Arguments:\r
+\r
+ Pos - Position, Pos starting from 0\r
+ Count - Count\r
+ AddBuffer - Add buffer\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Success\r
+ \r
+--*/\r
+{\r
+ INTN Index;\r
+\r
+ VOID *Buffer;\r
+ UINT8 *BufferPtr;\r
+ UINTN Size;\r
+\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ LIST_ENTRY *Link;\r
+ UINTN StartRow;\r
+\r
+ UINTN OldFCol;\r
+ UINTN OldFRow;\r
+ UINTN OldPos;\r
+\r
+ UINTN NewPos;\r
+\r
+ //\r
+ // get the line that start position is at\r
+ //\r
+ StartRow = Pos / 0x10;\r
+\r
+ Size = HBufferImageGetTotalSize ();\r
+\r
+ //\r
+ // relocate all the HBufferImage fields\r
+ //\r
+ OldFRow = HBufferImage.BufferPosition.Row;\r
+ OldFCol = HBufferImage.BufferPosition.Column;\r
+ OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;\r
+\r
+ //\r
+ // move cursor before Pos\r
+ //\r
+ if (Pos > 0) {\r
+ NewPos = Pos - 1;\r
+ } else {\r
+ NewPos = 0;\r
+ }\r
+\r
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
+\r
+ Buffer = AllocateZeroPool (Size + Count);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HBufferImageListToBuffer (Buffer, Size);\r
+\r
+ BufferPtr = (UINT8 *) Buffer;\r
+\r
+ //\r
+ // get a place to add\r
+ //\r
+ for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) {\r
+ BufferPtr[Index] = BufferPtr[Index - Count];\r
+ }\r
+ //\r
+ // add the buffer\r
+ //\r
+ for (Index = (INTN) 0; Index < (INTN) Count; Index++) {\r
+ BufferPtr[Index + Pos] = AddBuffer[Index];\r
+ }\r
+\r
+ Size += Count;\r
+\r
+ HBufferImageFreeLines ();\r
+\r
+ HBufferImageBufferToList (Buffer, Size);\r
+\r
+ FreePool (Buffer);\r
+\r
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
+ for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) {\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ HBufferImage.CurrentLine = Line;\r
+\r
+ if (OldPos >= Pos) {\r
+ NewPos = OldPos + Count;\r
+ } else {\r
+ NewPos = OldPos;\r
+ }\r
+\r
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageDoBackspace (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ delete the previous character\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ UINTN FileColumn;\r
+ UINTN FPos;\r
+ BOOLEAN LastLine;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ LastLine = FALSE;\r
+\r
+ //\r
+ // already the first character\r
+ //\r
+ if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;\r
+\r
+ FileColumn = HBufferImage.BufferPosition.Column;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+ LastLine = FALSE;\r
+ if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) {\r
+ LastLine = TRUE;\r
+ }\r
+\r
+ HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);\r
+\r
+ //\r
+ // if is the last line\r
+ // then only this line need to be refreshed\r
+ //\r
+ if (LastLine) {\r
+ HBufferImageNeedRefresh = FALSE;\r
+ HBufferImageOnlyLineNeedRefresh = TRUE;\r
+ } else {\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ }\r
+\r
+ if (!HBufferImage.Modified) {\r
+ HBufferImage.Modified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageDoDelete (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Delete current character from line\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ BOOLEAN LastLine;\r
+ UINTN FileColumn;\r
+ UINTN FPos;\r
+\r
+ FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;\r
+\r
+ FileColumn = HBufferImage.BufferPosition.Column;\r
+\r
+ Line = HBufferImage.CurrentLine;\r
+\r
+ //\r
+ // if beyond the last character\r
+ //\r
+ if (FileColumn > Line->Size) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ LastLine = FALSE;\r
+ if (Line->Link.ForwardLink == HBufferImage.ListHead) {\r
+ LastLine = TRUE;\r
+ }\r
+\r
+ HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);\r
+\r
+ //\r
+ // if is the last line\r
+ // then only this line need to be refreshed\r
+ //\r
+ if (LastLine) {\r
+ HBufferImageNeedRefresh = FALSE;\r
+ HBufferImageOnlyLineNeedRefresh = TRUE;\r
+ } else {\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ }\r
+\r
+ if (!HBufferImage.Modified) {\r
+ HBufferImage.Modified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageBufferToList (\r
+ IN VOID *Buffer,\r
+ IN UINTN Bytes\r
+ )\r
+{\r
+ UINTN i;\r
+ UINTN j;\r
+ UINTN Left;\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINT8 *BufferPtr;\r
+\r
+ i = 0;\r
+ Left = 0;\r
+ BufferPtr = (UINT8 *) Buffer;\r
+\r
+ //\r
+ // parse file content line by line\r
+ //\r
+ while (i < Bytes) {\r
+ if (Bytes - i >= 0x10) {\r
+ Left = 0x10;\r
+ } else {\r
+ Left = Bytes - i;\r
+ }\r
+\r
+ //\r
+ // allocate a new line\r
+ //\r
+ Line = HBufferImageCreateLine ();\r
+ if (Line == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Line->Size = Left;\r
+\r
+ for (j = 0; j < Left; j++) {\r
+ Line->Buffer[j] = BufferPtr[i];\r
+ i++;\r
+ }\r
+\r
+ }\r
+\r
+ //\r
+ // last line is a full line, SO create a new line\r
+ //\r
+ if (Left == 0x10 || Bytes == 0) {\r
+ Line = HBufferImageCreateLine ();\r
+ if (Line == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HBufferImageListToBuffer (\r
+ IN VOID *Buffer,\r
+ IN UINTN Bytes\r
+ )\r
+{\r
+ UINTN Count;\r
+ UINTN Index;\r
+ HEFI_EDITOR_LINE *Line;\r
+ LIST_ENTRY *Link;\r
+ UINT8 *BufferPtr;\r
+\r
+ //\r
+ // change the line list to a large buffer\r
+ //\r
+ if (HBufferImage.Lines == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = &HBufferImage.Lines->Link;\r
+ Count = 0;\r
+ BufferPtr = (UINT8 *) Buffer;\r
+\r
+ //\r
+ // deal line by line\r
+ //\r
+ while (Link != HBufferImage.ListHead) {\r
+\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+ if (Count + Line->Size > Bytes) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Index = 0; Index < Line->Size; Index++) {\r
+ BufferPtr[Index] = Line->Buffer[Index];\r
+ }\r
+\r
+ Count += Line->Size;\r
+ BufferPtr += Line->Size;\r
+\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+HBufferImageAdjustMousePosition (\r
+ IN INT32 TextX,\r
+ IN INT32 TextY\r
+ )\r
+{\r
+ UINTN X;\r
+ UINTN Y;\r
+ UINTN AbsX;\r
+ UINTN AbsY;\r
+\r
+ //\r
+ // TextX and TextY is mouse movement data returned by mouse driver\r
+ // This function will change it to MousePosition\r
+ //\r
+ //\r
+ // get absolute X value\r
+ //\r
+ if (TextX >= 0) {\r
+ AbsX = TextX;\r
+ } else {\r
+ AbsX = -TextX;\r
+ }\r
+ //\r
+ // get absolute Y value\r
+ //\r
+ if (TextY >= 0) {\r
+ AbsY = TextY;\r
+ } else {\r
+ AbsY = -TextY;\r
+ }\r
+\r
+ X = HBufferImage.MousePosition.Column;\r
+ Y = HBufferImage.MousePosition.Row;\r
+\r
+ if (TextX >= 0) {\r
+ X += TextX;\r
+ } else {\r
+ if (X >= AbsX) {\r
+ X -= AbsX;\r
+ } else {\r
+ X = 0;\r
+ }\r
+ }\r
+\r
+ if (TextY >= 0) {\r
+ Y += TextY;\r
+ } else {\r
+ if (Y >= AbsY) {\r
+ Y -= AbsY;\r
+ } else {\r
+ Y = 0;\r
+ }\r
+ }\r
+ //\r
+ // check whether new mouse column position is beyond screen\r
+ // if not, adjust it\r
+ //\r
+ if (X >= 10 && X <= (10 + 0x10 * 3 - 1)) {\r
+ HBufferImage.MousePosition.Column = X;\r
+ } else if (X < 10) {\r
+ HBufferImage.MousePosition.Column = 10;\r
+ } else if (X > (10 + 0x10 * 3 - 1)) {\r
+ HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;\r
+ }\r
+ //\r
+ // check whether new mouse row position is beyond screen\r
+ // if not, adjust it\r
+ //\r
+ if (Y >= 2 && Y <= (HMainEditor.ScreenSize.Row - 4)) {\r
+ HBufferImage.MousePosition.Row = Y;\r
+ } else if (Y < 2) {\r
+ HBufferImage.MousePosition.Row = 2;\r
+ } else if (Y > (HMainEditor.ScreenSize.Row - 4)) {\r
+ HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 4);\r
+ }\r
+\r
+}\r
--- /dev/null
+/** @file\r
+ Defines BufferImage - the view of the file that is visible at any point, \r
+ as well as the event handlers for editing the file\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_BUFFER_IMAGE_H_\r
+#define _LIB_BUFFER_IMAGE_H_\r
+\r
+#include "HexEditor.h"\r
+\r
+EFI_STATUS\r
+HBufferImageInit (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageCleanup (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageRefresh (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageHide (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageHandleInput (\r
+ EFI_INPUT_KEY *\r
+ );\r
+EFI_STATUS\r
+HBufferImageBackup (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageRead (\r
+ IN CONST CHAR16 *,\r
+ IN CONST CHAR16 *,\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN EDIT_FILE_TYPE,\r
+ IN BOOLEAN\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageSave (\r
+ IN CHAR16 *,\r
+ IN CHAR16 *,\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN EDIT_FILE_TYPE\r
+ );\r
+\r
+INTN\r
+HBufferImageCharToHex (\r
+ IN CHAR16\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageRestoreMousePosition (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageRestorePosition (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+HBufferImageMovePosition (\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN BOOLEAN\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageHandleInput (\r
+ EFI_INPUT_KEY *\r
+ );\r
+\r
+HEFI_EDITOR_LINE *\r
+HBufferImageCreateLine (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageDoCharInput (\r
+ CHAR16\r
+ );\r
+EFI_STATUS\r
+HBufferImageAddChar (\r
+ CHAR16\r
+ );\r
+\r
+BOOLEAN\r
+HInCurrentScreen (\r
+ UINTN\r
+ );\r
+BOOLEAN\r
+HAboveCurrentScreen (\r
+ UINTN\r
+ );\r
+BOOLEAN\r
+HUnderCurrentScreen (\r
+ UINTN\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageScrollRight (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageScrollLeft (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageScrollDown (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageScrollUp (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImagePageUp (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImagePageDown (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageHome (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageEnd (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageDoBackspace (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HBufferImageDoDelete (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageCutLine (\r
+ HEFI_EDITOR_LINE **\r
+ );\r
+EFI_STATUS\r
+HBufferImagePasteLine (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageGetFileInfo (\r
+ EFI_FILE_HANDLE,\r
+ CHAR16 *,\r
+ EFI_FILE_INFO **\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageSearch (\r
+ CHAR16 *,\r
+ UINTN\r
+ );\r
+EFI_STATUS\r
+HBufferImageReplace (\r
+ CHAR16 *,\r
+ UINTN\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageFree (\r
+ VOID\r
+ ) ;\r
+\r
+EFI_STATUS\r
+HBufferImageDeleteCharacterFromBuffer (\r
+ IN UINTN,\r
+ IN UINTN,\r
+ UINT8 *\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageAddCharacterToBuffer (\r
+ IN UINTN,\r
+ IN UINTN,\r
+ UINT8 *\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageBufferToList (\r
+ IN VOID *,\r
+ IN UINTN\r
+ );\r
+\r
+EFI_STATUS\r
+HBufferImageListToBuffer (\r
+ IN VOID *,\r
+ IN UINTN\r
+ );\r
+\r
+VOID\r
+HBufferImageAdjustMousePosition (\r
+ INT32,\r
+ INT32\r
+ );\r
+\r
+BOOLEAN\r
+HBufferImageIsAtHighBits (\r
+ UINTN,\r
+ UINTN *\r
+ ) ;\r
+\r
+EFI_STATUS\r
+HBufferImageCutLine (\r
+ HEFI_EDITOR_LINE **\r
+ );\r
+\r
+UINTN\r
+HBufferImageGetTotalSize (\r
+ VOID\r
+ );\r
+\r
+BOOLEAN\r
+HBufferImageIsInSelectedArea (\r
+ UINTN,\r
+ UINTN\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Functions to deal with Clip Board\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+\r
+HEFI_EDITOR_CLIPBOARD HClipBoard;\r
+\r
+//\r
+// for basic initialization of HClipBoard\r
+//\r
+HEFI_EDITOR_CLIPBOARD HClipBoardConst = {\r
+ NULL,\r
+ 0\r
+};\r
+\r
+EFI_STATUS\r
+HClipBoardInit (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Initialization function for HDiskImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ //\r
+ // basiclly initialize the HDiskImage\r
+ //\r
+ CopyMem (&HClipBoard, &HClipBoardConst, sizeof (HClipBoard));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HClipBoardCleanup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Initialization function for HDiskImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+\r
+ SHELL_FREE_NON_NULL (HClipBoard.Buffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HClipBoardSet (\r
+ IN UINT8 *Buffer,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ //\r
+ // free the old clipboard buffer\r
+ // and set new clipboard buffer\r
+ //\r
+ SHELL_FREE_NON_NULL (HClipBoard.Buffer);\r
+ HClipBoard.Buffer = Buffer;\r
+\r
+ HClipBoard.Size = Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINTN\r
+HClipBoardGet (\r
+ OUT UINT8 **Buffer\r
+ )\r
+{\r
+ //\r
+ // return the clipboard buffer\r
+ //\r
+ *Buffer = HClipBoard.Buffer;\r
+\r
+ return HClipBoard.Size;\r
+}\r
--- /dev/null
+/** @file\r
+ Defines DiskImage - the view of the file that is visible at any point, \r
+ as well as the event handlers for editing the file\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_CLIP_BOARD_H_\r
+#define _LIB_CLIP_BOARD_H_\r
+\r
+#include "HexEditor.h"\r
+\r
+EFI_STATUS\r
+HClipBoardInit (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HClipBoardCleanup (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HClipBoardSet (\r
+ UINT8 *,\r
+ UINTN\r
+ );\r
+UINTN\r
+HClipBoardGet (\r
+ UINT8 **\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Functions to deal with Disk buffer.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+#include <Protocol/BlockIo.h>\r
+\r
+extern EFI_HANDLE HImageHandleBackup;\r
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
+\r
+extern BOOLEAN HBufferImageNeedRefresh;\r
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
+extern BOOLEAN HBufferImageMouseNeedRefresh;\r
+\r
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
+\r
+HEFI_EDITOR_DISK_IMAGE HDiskImage;\r
+HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;\r
+\r
+//\r
+// for basic initialization of HDiskImage\r
+//\r
+HEFI_EDITOR_DISK_IMAGE HDiskImageConst = {\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ 0\r
+};\r
+\r
+EFI_STATUS\r
+HDiskImageInit (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Initialization function for HDiskImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ //\r
+ // basically initialize the HDiskImage\r
+ //\r
+ CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage));\r
+\r
+ CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HDiskImageBackup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Backup function for HDiskImage\r
+ Only a few fields need to be backup. \r
+ This is for making the Disk buffer refresh \r
+ as few as possible.\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - Success\r
+ EFI_OUT_OF_RESOURCES - gST->ConOut of resources\r
+\r
+--*/\r
+{\r
+ //\r
+ // backup the disk name, offset and size\r
+ //\r
+ //\r
+ SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);\r
+\r
+ HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name);\r
+ if (HDiskImageBackupVar.Name == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HDiskImageBackupVar.Offset = HDiskImage.Offset;\r
+ HDiskImageBackupVar.Size = HDiskImage.Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HDiskImageCleanup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Cleanup function for HDiskImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ SHELL_FREE_NON_NULL (HDiskImage.Name);\r
+ SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HDiskImageSetDiskNameOffsetSize (\r
+ IN CONST CHAR16 *Str,\r
+ IN UINTN Offset,\r
+ IN UINTN Size\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Set FileName field in HFileImage\r
+\r
+Arguments: \r
+\r
+ Str - File name to set\r
+ Offset - The offset\r
+ Size - The size\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ UINTN Len;\r
+ UINTN Index;\r
+\r
+ //\r
+ // free the old file name\r
+ //\r
+ SHELL_FREE_NON_NULL (HDiskImage.Name);\r
+\r
+ Len = StrLen (Str);\r
+\r
+ HDiskImage.Name = AllocateZeroPool (2 * (Len + 1));\r
+ if (HDiskImage.Name == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < Len; Index++) {\r
+ HDiskImage.Name[Index] = Str[Index];\r
+ }\r
+\r
+ HDiskImage.Name[Len] = L'\0';\r
+\r
+ HDiskImage.Offset = Offset;\r
+ HDiskImage.Size = Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HDiskImageRead (\r
+ IN CONST CHAR16 *DeviceName,\r
+ IN UINTN Offset,\r
+ IN UINTN Size,\r
+ IN BOOLEAN Recover\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Read a disk from disk into HBufferImage\r
+\r
+Arguments: \r
+\r
+ DeviceName - filename to read\r
+ Offset - The offset\r
+ Size - The size\r
+ Recover - if is for recover, no information print\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_INVALID_PARAMETER \r
+ \r
+--*/\r
+{\r
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;\r
+ EFI_HANDLE Handle;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ EFI_STATUS Status;\r
+\r
+ VOID *Buffer;\r
+ CHAR16 *Str;\r
+ UINTN Bytes;\r
+\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINT64 ByteOffset;\r
+\r
+ EDIT_FILE_TYPE BufferTypeBackup;\r
+\r
+ BufferTypeBackup = HBufferImage.BufferType;\r
+ HBufferImage.BufferType = FileTypeDiskBuffer;\r
+\r
+ DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);\r
+ if (DevicePath == NULL) {\r
+ StatusBarSetStatusString (L"Cannot Find Device");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ DupDevicePath = DuplicateDevicePath(DevicePath);\r
+ //\r
+ // get blkio interface\r
+ //\r
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);\r
+ FreePool(DupDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return Status;\r
+ }\r
+ Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return Status;\r
+ }\r
+ //\r
+ // if Offset exceeds LastBlock,\r
+ // return error\r
+ //\r
+ if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {\r
+ StatusBarSetStatusString (L"Invalid Offset + Size");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Bytes = BlkIo->Media->BlockSize * Size;\r
+ Buffer = AllocateZeroPool (Bytes);\r
+\r
+ if (Buffer == NULL) {\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);\r
+\r
+ //\r
+ // read from disk\r
+ //\r
+ Status = BlkIo->ReadBlocks (\r
+ BlkIo,\r
+ BlkIo->Media->MediaId,\r
+ Offset,\r
+ Bytes,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ HBufferImageFree ();\r
+\r
+ //\r
+ // convert buffer to line list\r
+ //\r
+ Status = HBufferImageBufferToList (Buffer, Bytes);\r
+ FreePool (Buffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return Status;\r
+ }\r
+\r
+ Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // initialize some variables\r
+ //\r
+ HDiskImage.BlockSize = BlkIo->Media->BlockSize;\r
+\r
+ HBufferImage.DisplayPosition.Row = 2;\r
+ HBufferImage.DisplayPosition.Column = 10;\r
+\r
+ HBufferImage.MousePosition.Row = 2;\r
+ HBufferImage.MousePosition.Column = 10;\r
+\r
+ HBufferImage.LowVisibleRow = 1;\r
+ HBufferImage.HighBits = TRUE;\r
+\r
+ HBufferImage.BufferPosition.Row = 1;\r
+ HBufferImage.BufferPosition.Column = 1;\r
+\r
+ if (!Recover) {\r
+ Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);\r
+ if (Str == NULL) {\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StatusBarSetStatusString (Str);\r
+ SHELL_FREE_NON_NULL (Str);\r
+\r
+ HMainEditor.SelectStart = 0;\r
+ HMainEditor.SelectEnd = 0;\r
+\r
+ }\r
+\r
+ //\r
+ // has line\r
+ //\r
+ if (HBufferImage.Lines != NULL) {\r
+ HBufferImage.CurrentLine = CR (\r
+ HBufferImage.ListHead->ForwardLink,\r
+ HEFI_EDITOR_LINE,\r
+ Link,\r
+ EFI_EDITOR_LINE_LIST\r
+ );\r
+ } else {\r
+ //\r
+ // create a dummy line\r
+ //\r
+ Line = HBufferImageCreateLine ();\r
+ if (Line == NULL) {\r
+ StatusBarSetStatusString (L"Read Disk Failed");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HBufferImage.CurrentLine = Line;\r
+ }\r
+\r
+ HBufferImage.Modified = FALSE;\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ HBufferImageMouseNeedRefresh = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HDiskImageSave (\r
+ IN CHAR16 *DeviceName,\r
+ IN UINTN Offset,\r
+ IN UINTN Size\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Save lines in HBufferImage to disk\r
+ NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!\r
+\r
+Arguments: \r
+\r
+ DeviceName - The device name\r
+ Offset - The offset\r
+ Size - The size\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_INVALID_PARAMETER\r
+\r
+--*/\r
+{\r
+\r
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ VOID *Buffer;\r
+ UINTN Bytes;\r
+\r
+ UINT64 ByteOffset;\r
+\r
+ EDIT_FILE_TYPE BufferTypeBackup;\r
+\r
+ //\r
+ // if not modified, directly return\r
+ //\r
+ if (HBufferImage.Modified == FALSE) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BufferTypeBackup = HBufferImage.BufferType;\r
+ HBufferImage.BufferType = FileTypeDiskBuffer;\r
+\r
+ DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);\r
+ if (DevicePath == NULL) {\r
+// StatusBarSetStatusString (L"Cannot Find Device");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ DupDevicePath = DuplicateDevicePath(DevicePath);\r
+\r
+ //\r
+ // get blkio interface\r
+ //\r
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);\r
+ FreePool(DupDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+// StatusBarSetStatusString (L"Read Disk Failed");\r
+ return Status;\r
+ }\r
+ Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ if (EFI_ERROR (Status)) {\r
+// StatusBarSetStatusString (L"Read Disk Failed");\r
+ return Status;\r
+ }\r
+\r
+ Bytes = BlkIo->Media->BlockSize * Size;\r
+ Buffer = AllocateZeroPool (Bytes);\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // concatenate the line list to a buffer\r
+ //\r
+ Status = HBufferImageListToBuffer (Buffer, Bytes);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ return Status;\r
+ }\r
+\r
+ ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);\r
+\r
+ //\r
+ // write the buffer to disk\r
+ //\r
+ Status = BlkIo->WriteBlocks (\r
+ BlkIo,\r
+ BlkIo->Media->MediaId,\r
+ Offset,\r
+ Bytes,\r
+ Buffer\r
+ );\r
+\r
+ FreePool (Buffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ //\r
+ // now not modified\r
+ //\r
+ HBufferImage.Modified = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Defines DiskImage - the view of the file that is visible at any point, \r
+ as well as the event handlers for editing the file\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_DISK_IMAGE_H_\r
+#define _LIB_DISK_IMAGE_H_\r
+\r
+#include "HexEditor.h"\r
+\r
+EFI_STATUS\r
+HDiskImageInit (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HDiskImageCleanup (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HDiskImageBackup (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HDiskImageRead (\r
+ IN CONST CHAR16 *,\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN BOOLEAN\r
+ );\r
+EFI_STATUS\r
+HDiskImageSave (\r
+ IN CHAR16 *,\r
+ IN UINTN,\r
+ IN UINTN\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Functions to deal with file buffer.\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+\r
+extern EFI_HANDLE HImageHandleBackup;\r
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
+\r
+extern BOOLEAN HBufferImageNeedRefresh;\r
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
+extern BOOLEAN HBufferImageMouseNeedRefresh;\r
+\r
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
+\r
+HEFI_EDITOR_FILE_IMAGE HFileImage;\r
+HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;\r
+\r
+//\r
+// for basic initialization of HFileImage\r
+//\r
+HEFI_EDITOR_BUFFER_IMAGE HFileImageConst = {\r
+ NULL,\r
+ 0,\r
+ FALSE\r
+};\r
+\r
+EFI_STATUS\r
+HFileImageInit (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Initialization function for HFileImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ //\r
+ // basically initialize the HFileImage\r
+ //\r
+ CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));\r
+\r
+ CopyMem (\r
+ &HFileImageBackupVar,\r
+ &HFileImageConst,\r
+ sizeof (HFileImageBackupVar)\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageBackup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Backup function for HFileImage\r
+ Only a few fields need to be backup. \r
+ This is for making the file buffer refresh \r
+ as few as possible.\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);\r
+ HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);\r
+ if (HFileImageBackupVar.FileName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageCleanup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Cleanup function for HFileImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+\r
+ SHELL_FREE_NON_NULL (HFileImage.FileName);\r
+ SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageSetFileName (\r
+ IN CONST CHAR16 *Str\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Set FileName field in HFileImage\r
+\r
+Arguments: \r
+\r
+ Str -- File name to set\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ UINTN Size;\r
+ UINTN Index;\r
+\r
+ //\r
+ // free the old file name\r
+ //\r
+ SHELL_FREE_NON_NULL (HFileImage.FileName);\r
+\r
+ Size = StrLen (Str);\r
+\r
+ HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));\r
+ if (HFileImage.FileName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < Size; Index++) {\r
+ HFileImage.FileName[Index] = Str[Index];\r
+ }\r
+\r
+ HFileImage.FileName[Size] = L'\0';\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageGetFileInfo (\r
+ IN EFI_FILE_HANDLE Handle,\r
+ IN CHAR16 *FileName,\r
+ OUT EFI_FILE_INFO **InfoOut\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Get this file's information\r
+\r
+Arguments: \r
+\r
+ Handle - in NT32 mode Directory handle, in other mode File Handle\r
+ FileName - The file name\r
+ InfoOut - parameter to pass file information out\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+\r
+ VOID *Info;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ Size = SIZE_OF_EFI_FILE_INFO + 1024;\r
+ Info = AllocateZeroPool (Size);\r
+ if (!Info) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // get file information\r
+ //\r
+ Status = Handle->GetInfo (Handle, &gEfiFileInfoGuid, &Size, Info);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ *InfoOut = (EFI_FILE_INFO *) Info;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageRead (\r
+ IN CONST CHAR16 *FileName,\r
+ IN BOOLEAN Recover\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Read a file from disk into HBufferImage\r
+\r
+Arguments: \r
+\r
+ FileName -- filename to read\r
+ Recover -- if is for recover, no information print\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+ \r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINT8 *Buffer;\r
+ CHAR16 *UnicodeBuffer;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ Line = NULL;\r
+\r
+ //\r
+ // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )\r
+ // you should set status string\r
+ // since this function maybe called before the editorhandleinput loop\r
+ // so any error will cause editor return\r
+ // so if you want to print the error status\r
+ // you should set the status string\r
+ //\r
+ Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);\r
+ if (EFI_ERROR(Status)) {\r
+ UnicodeBuffer = CatSPrint(NULL, L"Read error on file &s: %r", FileName, Status);\r
+ if (UnicodeBuffer == NULL) {\r
+ SHELL_FREE_NON_NULL(Buffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StatusBarSetStatusString (UnicodeBuffer);\r
+ FreePool (UnicodeBuffer);\r
+ }\r
+\r
+ HFileImageSetFileName (FileName);\r
+\r
+ //\r
+ // free the old lines\r
+ //\r
+ HBufferImageFree ();\r
+\r
+ Status = HBufferImageBufferToList (Buffer, HFileImage.Size);\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Error parsing file.");\r
+ return Status;\r
+ }\r
+\r
+ HBufferImage.DisplayPosition.Row = 2;\r
+ HBufferImage.DisplayPosition.Column = 10;\r
+ HBufferImage.MousePosition.Row = 2;\r
+ HBufferImage.MousePosition.Column = 10;\r
+ HBufferImage.LowVisibleRow = 1;\r
+ HBufferImage.HighBits = TRUE;\r
+ HBufferImage.BufferPosition.Row = 1;\r
+ HBufferImage.BufferPosition.Column = 1;\r
+\r
+ if (!Recover) {\r
+ UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);\r
+ if (UnicodeBuffer == NULL) {\r
+ SHELL_FREE_NON_NULL(Buffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StatusBarSetStatusString (UnicodeBuffer);\r
+ FreePool (UnicodeBuffer);\r
+\r
+ HMainEditor.SelectStart = 0;\r
+ HMainEditor.SelectEnd = 0;\r
+ }\r
+\r
+ //\r
+ // has line\r
+ //\r
+ if (HBufferImage.Lines != 0) {\r
+ HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ } else {\r
+ //\r
+ // create a dummy line\r
+ //\r
+ Line = HBufferImageCreateLine ();\r
+ if (Line == NULL) {\r
+ SHELL_FREE_NON_NULL(Buffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HBufferImage.CurrentLine = Line;\r
+ }\r
+\r
+ HBufferImage.Modified = FALSE;\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ HBufferImageMouseNeedRefresh = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HFileImageSave (\r
+ IN CHAR16 *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Save lines in HBufferImage to disk\r
+\r
+Arguments: \r
+\r
+ FileName - The file name\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+\r
+ LIST_ENTRY *Link;\r
+ HEFI_EDITOR_LINE *Line;\r
+ CHAR16 *Str;\r
+ EFI_STATUS Status;\r
+ UINTN NumLines;\r
+ SHELL_FILE_HANDLE FileHandle;\r
+ UINTN TotalSize;\r
+ UINT8 *Buffer;\r
+ UINT8 *Ptr;\r
+ EDIT_FILE_TYPE BufferTypeBackup;\r
+\r
+ BufferTypeBackup = HBufferImage.BufferType;\r
+ HBufferImage.BufferType = FileTypeFileBuffer;\r
+\r
+ //\r
+ // if is the old file\r
+ //\r
+ if (StrCmp (FileName, HFileImage.FileName) == 0) {\r
+ //\r
+ // check whether file exists on disk\r
+ //\r
+ if (ShellIsFile(FileName) == EFI_SUCCESS) {\r
+ //\r
+ // current file exists on disk\r
+ // so if not modified, then not save\r
+ //\r
+ if (HBufferImage.Modified == FALSE) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // if file is read-only, set error\r
+ //\r
+ if (HFileImage.ReadOnly == TRUE) {\r
+ StatusBarSetStatusString (L"Read Only File Can Not Be Saved");\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (ShellIsDirectory(FileName) == EFI_SUCCESS) {\r
+ StatusBarSetStatusString (L"Directory Can Not Be Saved");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // the file exits, delete it\r
+ //\r
+ Status = ShellDeleteFile (&FileHandle);\r
+ if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {\r
+ StatusBarSetStatusString (L"Write File Failed");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // write all the lines back to disk\r
+ //\r
+ NumLines = 0;\r
+ TotalSize = 0;\r
+ for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+ if (Line->Size != 0) {\r
+ TotalSize += Line->Size;\r
+ }\r
+ //\r
+ // end of if Line -> Size != 0\r
+ //\r
+ NumLines++;\r
+ }\r
+ //\r
+ // end of for Link\r
+ //\r
+ Buffer = AllocateZeroPool (TotalSize);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Ptr = Buffer;\r
+ for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+ if (Line->Size != 0) {\r
+ CopyMem (Ptr, Line->Buffer, Line->Size);\r
+ Ptr += Line->Size;\r
+ }\r
+ //\r
+ // end of if Line -> Size != 0\r
+ //\r
+ }\r
+\r
+\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Create File Failed");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);\r
+ FreePool (Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellDeleteFile (&FileHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ ShellCloseFile(&FileHandle);\r
+\r
+ HBufferImage.Modified = FALSE;\r
+\r
+ //\r
+ // set status string\r
+ //\r
+ Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);\r
+ StatusBarSetStatusString (Str);\r
+ FreePool (Str);\r
+\r
+ //\r
+ // now everything is ready , you can set the new file name to filebuffer\r
+ //\r
+ if (BufferTypeBackup != FileTypeFileBuffer || StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0) {\r
+ //\r
+ // not the same\r
+ //\r
+ HFileImageSetFileName (FileName);\r
+ if (HFileImage.FileName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ HFileImage.ReadOnly = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Defines FileImage - the view of the file that is visible at any point, \r
+ as well as the event handlers for editing the file\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_FILE_IMAGE_H_\r
+#define _LIB_FILE_IMAGE_H_\r
+\r
+#include "HexEditor.h"\r
+\r
+EFI_STATUS\r
+HFileImageInit (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HFileImageCleanup (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HFileImageBackup (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HFileImageSetFileName (\r
+ IN CONST CHAR16 *\r
+ );\r
+\r
+EFI_STATUS\r
+HFileImageGetFileInfo (\r
+ EFI_FILE_HANDLE,\r
+ CHAR16 *,\r
+ EFI_FILE_INFO **\r
+ );\r
+\r
+EFI_STATUS\r
+HFileImageRead (\r
+ IN CONST CHAR16 *,\r
+ IN BOOLEAN\r
+ );\r
+EFI_STATUS\r
+HFileImageSave (\r
+ IN CHAR16 *\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Main entry point of editor\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "UefiShellDebug1CommandsLib.h"\r
+#include "HexEditor.h"\r
+\r
+//\r
+// Global Variables\r
+//\r
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
+ {L"-f", TypeFlag},\r
+ {L"-d", TypeFlag},\r
+ {L"-m", TypeFlag},\r
+ {NULL, TypeMax}\r
+ };\r
+\r
+/**\r
+ Function for 'hexedit' command.\r
+\r
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunHexEdit (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *Buffer;\r
+ CHAR16 *ProblemParam;\r
+ SHELL_STATUS ShellStatus;\r
+ LIST_ENTRY *Package;\r
+ CONST CHAR16 *Cwd;\r
+ CHAR16 *NFS;\r
+ CHAR16 *Spot;\r
+ CONST CHAR16 *Name;\r
+ UINTN Offset;\r
+ UINTN Size;\r
+ UINT64 LastOffset;\r
+ EDIT_FILE_TYPE WhatToDo;\r
+\r
+ Buffer = NULL;\r
+ ShellStatus = SHELL_SUCCESS;\r
+ NFS = NULL;\r
+ Cwd = NULL;\r
+ Buffer = NULL;\r
+ Name = NULL;\r
+ Spot = NULL;\r
+ Offset = 0;\r
+ Size = 0;\r
+ LastOffset = 0;\r
+ WhatToDo = FileTypeNone;\r
+\r
+ //\r
+ // initialize the shell lib (we must be in non-auto-init...)\r
+ //\r
+ Status = ShellInitialize();\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ Status = CommandInit();\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ //\r
+ // parse the command line\r
+ //\r
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
+ if (EFI_ERROR(Status)) {\r
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);\r
+ FreePool(ProblemParam);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else {\r
+ ASSERT(FALSE);\r
+ }\r
+ } else {\r
+ //\r
+ // Check for -d\r
+ //\r
+ if (ShellCommandLineGetFlag(Package, L"-d")){\r
+ if (ShellCommandLineGetCount(Package) < 4) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else if (ShellCommandLineGetCount(Package) > 4) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else {\r
+ WhatToDo = FileTypeDiskBuffer;\r
+ Name = ShellCommandLineGetRawValue(Package, 1);\r
+ Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2));\r
+ Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 3));\r
+ }\r
+ }\r
+\r
+ //\r
+ // check for -f\r
+ //\r
+ if (ShellCommandLineGetFlag(Package, L"-f") && (WhatToDo == FileTypeNone)){\r
+ if (ShellCommandLineGetCount(Package) > 2) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else {\r
+ Name = ShellCommandLineGetRawValue(Package, 1);\r
+ if (!IsValidFileName(Name)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Name);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else {\r
+ WhatToDo = FileTypeFileBuffer;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // check for -m\r
+ //\r
+ if (ShellCommandLineGetFlag(Package, L"-m") && (WhatToDo == FileTypeNone)){\r
+ if (ShellCommandLineGetCount(Package) < 3) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else if (ShellCommandLineGetCount(Package) > 3) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ } else {\r
+ WhatToDo = FileTypeMemBuffer;\r
+ Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 1));\r
+ Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2));\r
+ }\r
+ }\r
+ ShellCommandLineFreeVarList (Package);\r
+\r
+ if (ShellStatus == SHELL_SUCCESS && WhatToDo == FileTypeNone) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
+ ShellStatus = SHELL_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ShellStatus == SHELL_SUCCESS) {\r
+ //\r
+ // Do the editor\r
+ //\r
+ Status = HMainEditorInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_INIT_FAILED), gShellDebug1HiiHandle);\r
+ } else {\r
+ HMainEditorBackup ();\r
+ switch (WhatToDo) {\r
+ case FileTypeFileBuffer:\r
+ Status = HBufferImageRead (\r
+ Name,\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ FileTypeFileBuffer,\r
+ FALSE\r
+ );\r
+ break;\r
+\r
+ case FileTypeDiskBuffer:\r
+ Status = HBufferImageRead (\r
+ NULL,\r
+ Name,\r
+ Offset,\r
+ Size,\r
+ 0,\r
+ 0,\r
+ FileTypeDiskBuffer,\r
+ FALSE\r
+ );\r
+ break;\r
+\r
+ case FileTypeMemBuffer:\r
+ Status = HBufferImageRead (\r
+ NULL,\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ (UINT32) Offset,\r
+ Size,\r
+ FileTypeMemBuffer,\r
+ FALSE\r
+ );\r
+ break;\r
+\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ HMainEditorRefresh ();\r
+ Status = HMainEditorKeyInput ();\r
+ }\r
+ if (Status != EFI_OUT_OF_RESOURCES) {\r
+ //\r
+ // back up the status string\r
+ //\r
+ Buffer = CatSPrint (NULL, L"%s", StatusBarGetString());\r
+ }\r
+ }\r
+\r
+ //\r
+ // cleanup\r
+ //\r
+ HMainEditorCleanup ();\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ if (ShellStatus == SHELL_SUCCESS) {\r
+ ShellStatus = SHELL_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // print editor exit code on screen\r
+ //\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle);\r
+ } else if (EFI_ERROR(Status)){\r
+ if (Buffer != NULL) {\r
+ if (StrCmp (Buffer, L"") != 0) {\r
+ //\r
+ // print out the status string\r
+ //\r
+ ShellPrintEx(-1, -1, L"%s", gShellDebug1HiiHandle, Buffer);\r
+ } else {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle);\r
+ }\r
+ } else {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ SHELL_FREE_NON_NULL (Buffer);\r
+ return ShellStatus;\r
+}\r
--- /dev/null
+/** @file\r
+ Main include file for hex editor\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EFI_SHELL_HEXEDIT_H_\r
+#define _EFI_SHELL_HEXEDIT_H_\r
+\r
+#include "UefiShellDebug1CommandsLib.h"\r
+#include "HexEditorTypes.h"\r
+\r
+#include "MainHexEditor.h"\r
+\r
+#include "BufferImage.h"\r
+#include "FileImage.h"\r
+#include "DiskImage.h"\r
+#include "MemImage.h"\r
+\r
+#include "EditTitleBar.h"\r
+#include "EditStatusBar.h"\r
+#include "EditInputBar.h"\r
+#include "EditMenuBar.h"\r
+\r
+#include "Misc.h"\r
+\r
+#include "Clipboard.h"\r
+\r
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
+extern BOOLEAN HEditorFirst;\r
+extern BOOLEAN HEditorExit;\r
+\r
+#endif // _HEDITOR_H\r
--- /dev/null
+/** @file\r
+ data types that are used by editor\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _HEDITOR_TYPE_H_\r
+#define _HEDITOR_TYPE_H_\r
+\r
+#include "UefiShellDebug1CommandsLib.h"\r
+#include "EditTitleBar.h"\r
+\r
+#define EFI_EDITOR_LINE_LIST 'eell'\r
+\r
+#define ASCII_POSITION ((0x10 * 3) + 12)\r
+\r
+\r
+typedef struct {\r
+ UINTN Row;\r
+ UINTN Column;\r
+} HEFI_EDITOR_POSITION;\r
+\r
+typedef\r
+EFI_STATUS\r
+(*HEFI_MENU_ITEM_FUNCTION) (\r
+ VOID\r
+ );\r
+\r
+typedef struct {\r
+ CHAR16 Name[50];\r
+ CHAR16 Key[3];\r
+ HEFI_MENU_ITEM_FUNCTION Function;\r
+} HMENU_ITEMS;\r
+\r
+typedef struct _HEFI_EDITOR_LINE {\r
+ UINTN Signature;\r
+ UINT8 Buffer[0x10];\r
+ UINTN Size; // unit is Unicode\r
+ LIST_ENTRY Link;\r
+} HEFI_EDITOR_LINE;\r
+\r
+typedef struct _HEFI_EDITOR_MENU_ITEM {\r
+ CHAR16 NameToken;\r
+ CHAR16 FunctionKeyToken;\r
+ HEFI_MENU_ITEM_FUNCTION Function;\r
+} HEFI_EDITOR_MENU_ITEM;\r
+\r
+typedef struct {\r
+ UINT32 Foreground : 4;\r
+ UINT32 Background : 4;\r
+} HEFI_EDITOR_COLOR_ATTRIBUTES;\r
+\r
+typedef union {\r
+ HEFI_EDITOR_COLOR_ATTRIBUTES Colors;\r
+ UINT8 Data;\r
+} HEFI_EDITOR_COLOR_UNION;\r
+\r
+typedef struct {\r
+ UINTN Columns;\r
+ UINTN Rows;\r
+} HEFI_EDITOR_TEXT_MODE;\r
+\r
+\r
+typedef struct {\r
+ CHAR16 *Name;\r
+\r
+ UINTN BlockSize;\r
+ UINTN Size;\r
+ UINTN Offset;\r
+} HEFI_EDITOR_DISK_IMAGE;\r
+\r
+typedef struct {\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoFncs;\r
+\r
+ UINTN Offset;\r
+ UINTN Size;\r
+} HEFI_EDITOR_MEM_IMAGE;\r
+\r
+typedef struct {\r
+ CHAR16 *FileName;\r
+ UINTN Size; // file size\r
+ BOOLEAN ReadOnly; // file is read-only or not\r
+} HEFI_EDITOR_FILE_IMAGE;\r
+\r
+typedef struct {\r
+ LIST_ENTRY *ListHead; // list head of lines\r
+ HEFI_EDITOR_LINE *Lines; // lines of current file\r
+ UINTN NumLines; // number of lines\r
+ HEFI_EDITOR_LINE *CurrentLine; // current line cursor is at\r
+ HEFI_EDITOR_POSITION DisplayPosition; // cursor position in screen\r
+ HEFI_EDITOR_POSITION MousePosition; // mouse position in screen\r
+ HEFI_EDITOR_POSITION BufferPosition; // cursor position in buffer\r
+ UINTN LowVisibleRow; // the lowest visible row of file position\r
+ BOOLEAN HighBits; // cursor is at the high4 bits or low4 bits\r
+ BOOLEAN Modified; // BUFFER is modified or not\r
+ EDIT_FILE_TYPE BufferType;\r
+\r
+ HEFI_EDITOR_FILE_IMAGE *FileImage;\r
+ HEFI_EDITOR_DISK_IMAGE *DiskImage;\r
+ HEFI_EDITOR_MEM_IMAGE *MemImage;\r
+\r
+} HEFI_EDITOR_BUFFER_IMAGE;\r
+\r
+typedef struct {\r
+ UINT8 *Buffer;\r
+ UINTN Size;\r
+} HEFI_EDITOR_CLIPBOARD;\r
+\r
+typedef struct {\r
+ HEFI_EDITOR_BUFFER_IMAGE *BufferImage;\r
+ HEFI_EDITOR_CLIPBOARD *Clipboard;\r
+\r
+ HEFI_EDITOR_COLOR_UNION ColorAttributes;\r
+ HEFI_EDITOR_POSITION ScreenSize; // row number and column number\r
+ BOOLEAN MouseSupported;\r
+ EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;\r
+ INT32 MouseAccumulatorX;\r
+ INT32 MouseAccumulatorY;\r
+\r
+ UINTN SelectStart; // starting from 1\r
+ UINTN SelectEnd; // starting from 1\r
+} HEFI_EDITOR_GLOBAL_EDITOR;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Defines the Main Editor data type - \r
+ - Global variables \r
+ - Instances of the other objects of the editor\r
+ - Main Interfaces\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+#include "EditStatusBar.h"\r
+#include "EditInputBar.h"\r
+\r
+HEFI_EDITOR_COLOR_ATTRIBUTES HOriginalColors;\r
+INTN HOriginalMode;\r
+\r
+//\r
+// the first time editor launch\r
+//\r
+BOOLEAN HEditorFirst;\r
+\r
+//\r
+// it's time editor should exit\r
+//\r
+BOOLEAN HEditorExit;\r
+\r
+BOOLEAN HEditorMouseAction;\r
+\r
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;\r
+\r
+extern HEFI_EDITOR_CLIPBOARD HClipBoard;\r
+\r
+extern BOOLEAN HBufferImageMouseNeedRefresh;\r
+extern BOOLEAN HBufferImageNeedRefresh;\r
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
+\r
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;\r
+\r
+//\r
+// basic initialization for MainEditor\r
+//\r
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditorConst = {\r
+ &HBufferImage,\r
+ &HClipBoard,\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ {\r
+ 0,\r
+ 0\r
+ },\r
+ FALSE,\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ 1,\r
+ 1\r
+};\r
+\r
+EFI_STATUS\r
+HMainCommandGoToOffset (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ move cursor to specified lines\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ UINTN Size;\r
+ UINT64 Offset;\r
+ EFI_STATUS Status;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ Size = 0;\r
+ Offset = 0;\r
+ FRow = 0;\r
+ FCol = 0;\r
+\r
+ //\r
+ // get offset\r
+ //\r
+ Status = InputBarSetPrompt (L"Go To Offset: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (8);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // THE input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Invalid Offset");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ Size = HBufferImageGetTotalSize ();\r
+ if (Offset >= Size) {\r
+ StatusBarSetStatusString (L"Invalid Offset");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ FRow = (UINTN)DivU64x32(Offset , 0x10) + 1;\r
+ FCol = (UINTN)ModU64x32(Offset , 0x10) + 1;\r
+\r
+ HBufferImageMovePosition (FRow, FCol, TRUE);\r
+\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ HBufferImageMouseNeedRefresh = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandSaveBuffer (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ save current opened buffer . \r
+ if is file buffer, you can save to current file name or \r
+ save to another file name\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Done;\r
+ CHAR16 *FileName;\r
+ BOOLEAN OldFile;\r
+ CHAR16 *Str;\r
+ EFI_FILE_INFO *Info;\r
+ SHELL_FILE_HANDLE ShellFileHandle;\r
+\r
+ if (HMainEditor.BufferImage->BufferType != FileTypeFileBuffer) {\r
+ if (HMainEditor.BufferImage->Modified == FALSE) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = InputBarSetPrompt (L"Dangerous to save disk/mem buffer. Save (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // the answer is just one character\r
+ //\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // loop for user's answer\r
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
+ //\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ //\r
+ // want to save this buffer first\r
+ //\r
+ Status = HBufferImageSave (\r
+ NULL,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ HMainEditor.BufferImage->BufferType\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"BufferSave: Problems Writing");\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ //\r
+ // the file won't be saved\r
+ //\r
+ return EFI_SUCCESS;\r
+ break;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // end of switch\r
+ //\r
+ }\r
+ //\r
+ // ENDOF WHILE\r
+ //\r
+ }\r
+ //\r
+ // ENDOF != FILEBUFFER\r
+ //\r
+ // This command will save currently opened file to disk.\r
+ // You can choose save to another file name or just save to\r
+ // current file name.\r
+ // Below is the scenario of Save File command: (\r
+ // Suppose the old file name is A )\r
+ // 1. An Input Bar will be prompted: "File To Save: [ old file name]"\r
+ // IF user press ESC, Save File command ends .\r
+ // IF user press Enter, input file name will be A.\r
+ // IF user inputs a new file name B, input file name will be B.\r
+ //\r
+ // 2. IF input file name is A, go to do Step 3.\r
+ // IF input file name is B, go to do Step 4.\r
+ //\r
+ // 3. IF A is read only, Status Bar will show "Access Denied"\r
+ // and Save File commands ends.\r
+ // IF A is not read only, save file buffer to disk\r
+ // and remove Modified flag in Title Bar , then Save File command ends.\r
+ //\r
+ // 4. IF B does not exist, create this file and save file buffer to it.\r
+ // Go to do Step 7.\r
+ // IF B exits, do Step 5.\r
+ //\r
+ // 5. An Input Bar will be prompted:\r
+ // "File Exists. Overwrite ( Yes/No/Cancel ) ?"\r
+ // IF user press 'y' or 'Y', do Step 6.\r
+ // IF user press 'n' or 'N', Save File commands ends.\r
+ // IF user press 'c' or 'C' or ESC, Save File commands ends.\r
+ //\r
+ // 6. IF B is a read-only file, Status Bar will show "Access Denied"\r
+ // and Save File commands ends.\r
+ // IF B can be read and write, save file buffer to B.\r
+ //\r
+ // 7. Update File Name field in Title Bar to B\r
+ // and remove the Modified flag in Title Bar.\r
+ //\r
+ Str = CatSPrint(NULL, \r
+ L"File to Save: [%s]",\r
+ HMainEditor.BufferImage->FileImage->FileName\r
+ );\r
+ if (Str == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (StrLen (Str) >= 50) {\r
+ //\r
+ // replace the long file name with "..."\r
+ //\r
+ Str[46] = L'.';\r
+ Str[47] = L'.';\r
+ Str[48] = L'.';\r
+ Str[49] = L']';\r
+ Str[50] = L'\0';\r
+ }\r
+\r
+ Status = InputBarSetPrompt (Str);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (100);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // get new file name\r
+ //\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // if user pressed ESC\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ SHELL_FREE_NON_NULL (Str);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ SHELL_FREE_NON_NULL (Str);\r
+\r
+ //\r
+ // if just enter pressed, so think save to current file name\r
+ //\r
+ if (StrLen (InputBarGetString()) == 0) {\r
+ FileName = CatSPrint(NULL, \r
+ L"%s",\r
+ HMainEditor.BufferImage->FileImage->FileName\r
+ );\r
+ } else {\r
+ FileName = CatSPrint(NULL, L"%s", InputBarGetString());\r
+ }\r
+\r
+ if (FileName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (!IsValidFileName (FileName)) {\r
+ StatusBarSetStatusString (L"Invalid File Name");\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldFile = FALSE;\r
+\r
+ //\r
+ // save to the old file\r
+ //\r
+ if (StringNoCaseCompare (\r
+ &FileName,\r
+ &HMainEditor.BufferImage->FileImage->FileName\r
+ ) == 0) {\r
+ OldFile = TRUE;\r
+ }\r
+\r
+ if (OldFile) {\r
+ //\r
+ // if the file is read only, so can not write back to it.\r
+ //\r
+ if (HMainEditor.BufferImage->FileImage->ReadOnly == TRUE) {\r
+ StatusBarSetStatusString (L"Access Denied");\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ Status = ShellOpenFileByName (FileName, &ShellFileHandle, EFI_FILE_MODE_READ, 0);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ Info = ShellGetFileInfo(ShellFileHandle);\r
+\r
+ ShellCloseFile(&ShellFileHandle);\r
+ //\r
+ // check if read only\r
+ //\r
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {\r
+ StatusBarSetStatusString (L"Access Denied");\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ } \r
+\r
+ SHELL_FREE_NON_NULL(Info);\r
+ //\r
+ // ask user whether to overwrite this file\r
+ //\r
+ Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return Status;\r
+ }\r
+\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ if (Status == EFI_NOT_READY) {\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ Done = TRUE;\r
+ break;\r
+ case L'n':\r
+ case L'N':\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ case L'c':\r
+ case L'C':\r
+ SHELL_FREE_NON_NULL (FileName);\r
+ return EFI_SUCCESS;\r
+ } // switch\r
+ } // while\r
+ } // if opened existing file\r
+ } // if OldFile\r
+ \r
+ //\r
+ // save file back to disk\r
+ //\r
+ Status = HBufferImageSave (\r
+ FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ FileTypeFileBuffer\r
+ );\r
+ SHELL_FREE_NON_NULL (FileName);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandSelectStart (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Load a disk buffer editor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ UINTN Start;\r
+\r
+ Start = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;\r
+\r
+ //\r
+ // last line\r
+ //\r
+ if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {\r
+ if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {\r
+ StatusBarSetStatusString (L"Invalid Block Start");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ }\r
+\r
+ if (HMainEditor.SelectEnd != 0 && Start > HMainEditor.SelectEnd) {\r
+ StatusBarSetStatusString (L"Invalid Block Start");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ HMainEditor.SelectStart = Start;\r
+\r
+ HBufferImageNeedRefresh = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandSelectEnd (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Load a disk buffer editor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ UINTN End;\r
+\r
+ End = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;\r
+\r
+ //\r
+ // last line\r
+ //\r
+ if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {\r
+ if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {\r
+ StatusBarSetStatusString (L"Invalid Block End");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ }\r
+\r
+ if (HMainEditor.SelectStart != 0 && End < HMainEditor.SelectStart) {\r
+ StatusBarSetStatusString (L"Invalid Block End");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ HMainEditor.SelectEnd = End;\r
+\r
+ HBufferImageNeedRefresh = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandCut (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ cut current line to clipboard\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ HEFI_EDITOR_LINE *Line;\r
+ LIST_ENTRY *Link;\r
+ UINT8 *Buffer;\r
+ UINTN Count;\r
+\r
+ //\r
+ // not select, so not allowed to cut\r
+ //\r
+ if (HMainEditor.SelectStart == 0) {\r
+ StatusBarSetStatusString (L"No Block is Selected");\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // not select, so not allowed to cut\r
+ //\r
+ if (HMainEditor.SelectEnd == 0) {\r
+ StatusBarSetStatusString (L"No Block is Selected");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
+ for (Index = 0; Index < (HMainEditor.SelectEnd - 1) / 0x10; Index++) {\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+ Count = HMainEditor.SelectEnd - HMainEditor.SelectStart + 1;\r
+ Buffer = AllocateZeroPool (Count);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // cut the selected area\r
+ //\r
+ HBufferImageDeleteCharacterFromBuffer (\r
+ HMainEditor.SelectStart - 1,\r
+ Count,\r
+ Buffer\r
+ );\r
+\r
+ //\r
+ // put to clipboard\r
+ //\r
+ HClipBoardSet (Buffer, Count);\r
+\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+\r
+ if (!HMainEditor.BufferImage->Modified) {\r
+ HMainEditor.BufferImage->Modified = TRUE;\r
+ }\r
+\r
+ //\r
+ // now no select area\r
+ //\r
+ HMainEditor.SelectStart = 0;\r
+ HMainEditor.SelectEnd = 0;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandPaste (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ paste line to file buffer\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_LOAD_ERROR\r
+\r
+\r
+--*/\r
+{\r
+\r
+ BOOLEAN OnlyLineRefresh;\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINT8 *Buffer;\r
+ UINTN Count;\r
+ UINTN FPos;\r
+\r
+ Count = HClipBoardGet (&Buffer);\r
+ if (Count == 0 || Buffer == NULL) {\r
+ StatusBarSetStatusString (L"Nothing to Paste");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Line = HMainEditor.BufferImage->CurrentLine;\r
+\r
+ OnlyLineRefresh = FALSE;\r
+ if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead && Line->Size + Count < 0x10) {\r
+ //\r
+ // is at last line, and after paste will not exceed\r
+ // so only this line need to be refreshed\r
+ //\r
+ // if after add, the line is 0x10, then will append a new line\r
+ // so the whole page will need be refreshed\r
+ //\r
+ OnlyLineRefresh = TRUE;\r
+\r
+ }\r
+\r
+ FPos = 0x10 * (HMainEditor.BufferImage->BufferPosition.Row - 1) + HMainEditor.BufferImage->BufferPosition.Column - 1;\r
+\r
+ HBufferImageAddCharacterToBuffer (FPos, Count, Buffer);\r
+\r
+ if (OnlyLineRefresh) {\r
+ HBufferImageNeedRefresh = FALSE;\r
+ HBufferImageOnlyLineNeedRefresh = TRUE;\r
+ } else {\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ }\r
+\r
+ if (!HMainEditor.BufferImage->Modified) {\r
+ HMainEditor.BufferImage->Modified = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandExit (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ exit editor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Below is the scenario of Exit command:\r
+ // 1. IF currently opened file is not modified, exit the editor and\r
+ // Exit command ends.\r
+ // IF currently opened file is modified, do Step 2\r
+ //\r
+ // 2. An Input Bar will be prompted:\r
+ // "File modified. Save ( Yes/No/Cancel )?"\r
+ // IF user press 'y' or 'Y', currently opened file will be saved and\r
+ // Editor exits\r
+ // IF user press 'n' or 'N', currently opened file will not be saved\r
+ // and Editor exits.\r
+ // IF user press 'c' or 'C' or ESC, Exit command ends.\r
+ //\r
+ //\r
+ // if file has been modified, so will prompt user\r
+ // whether to save the changes\r
+ //\r
+ if (HMainEditor.BufferImage->Modified) {\r
+\r
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ //\r
+ // write file back to disk\r
+ //\r
+ Status = HBufferImageSave (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ HMainEditor.BufferImage->BufferType\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ HEditorExit = TRUE;\r
+ }\r
+\r
+ return Status;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ HEditorExit = TRUE;\r
+ return EFI_SUCCESS;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ return EFI_SUCCESS;\r
+\r
+ }\r
+ }\r
+ }\r
+\r
+ HEditorExit = TRUE;\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandOpenFile (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Load a file from disk to editor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ BOOLEAN Done;\r
+ EFI_STATUS Status;\r
+ EDIT_FILE_TYPE BufferType;\r
+\r
+ BufferType = HMainEditor.BufferImage->BufferType;\r
+\r
+ //\r
+ // This command will open a file from current working directory.\r
+ // Read-only file can also be opened. But it can not be modified.\r
+ // Below is the scenario of Open File command:\r
+ // 1. IF currently opened file has not been modified, directly go to step .\r
+ // IF currently opened file has been modified, an Input Bar will be\r
+ // prompted as :\r
+ // "File Modified. Save ( Yes/No/Cancel) ?"\r
+ // IF user press 'y' or 'Y', currently opened file will be saved.\r
+ // IF user press 'n' or 'N', currently opened file will\r
+ // not be saved.\r
+ // IF user press 'c' or 'C' or ESC, Open File command ends and\r
+ // currently opened file is still opened.\r
+ //\r
+ // 2. An Input Bar will be prompted as : "File Name to Open: "\r
+ // IF user press ESC, Open File command ends and\r
+ // currently opened file is still opened.\r
+ // Any other inputs with a Return will cause\r
+ // currently opened file close.\r
+ //\r
+ // 3. IF user input file name is an existing file ,\r
+ // this file will be read and opened.\r
+ // IF user input file name is a new file, this file will be created\r
+ // and opened. This file's type ( UNICODE or ASCII ) is the same with\r
+ // the old file.\r
+ //\r
+ //\r
+ // if current file is modified, so you need to choose whether to\r
+ // save it first.\r
+ //\r
+ if (HMainEditor.BufferImage->Modified) {\r
+\r
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // the answer is just one character\r
+ //\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // loop for user's answer\r
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
+ //\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ //\r
+ // want to save this buffer first\r
+ //\r
+ Status = HBufferImageSave (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ HMainEditor.BufferImage->BufferType\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ MainTitleBarRefresh (\r
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
+ HMainEditor.BufferImage->BufferType,\r
+ HMainEditor.BufferImage->FileImage->ReadOnly,\r
+ FALSE,\r
+ HMainEditor.ScreenSize.Column,\r
+ HMainEditor.ScreenSize.Row\r
+ );\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ //\r
+ // the file won't be saved\r
+ //\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // TO get the open file name\r
+ //\r
+ Status = InputBarSetPrompt (L"File Name to Open: ");\r
+ if (EFI_ERROR (Status)) {\r
+ HBufferImageRead (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType,\r
+ TRUE\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (100);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = HBufferImageRead (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType,\r
+ TRUE\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ Status = HBufferImageRead (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType,\r
+ TRUE\r
+ );\r
+\r
+ return Status;\r
+ }\r
+ //\r
+ // THE input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ //\r
+ // CHECK if filename's valid\r
+ //\r
+ if (!IsValidFileName (InputBarGetString())) {\r
+ HBufferImageRead (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType,\r
+ TRUE\r
+ );\r
+\r
+ StatusBarSetStatusString (L"Invalid File Name");\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // read from disk\r
+ //\r
+ Status = HBufferImageRead (\r
+ InputBarGetString(),\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ FileTypeFileBuffer,\r
+ FALSE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ HBufferImageRead (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType,\r
+ TRUE\r
+ );\r
+\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandOpenDisk (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Load a disk buffer editor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_NOT_FOUND\r
+\r
+--*/\r
+{\r
+ UINT64 Size;\r
+ UINT64 Offset;\r
+ CHAR16 *DeviceName;\r
+ EFI_STATUS Status;\r
+ BOOLEAN Done;\r
+\r
+ EDIT_FILE_TYPE BufferType;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ Size = 0;\r
+ Offset = 0;\r
+ BufferType = HMainEditor.BufferImage->BufferType;\r
+\r
+ //\r
+ // if current file is modified, so you need to choose\r
+ // whether to save it first.\r
+ //\r
+ if (HMainEditor.BufferImage->Modified) {\r
+\r
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // the answer is just one character\r
+ //\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // loop for user's answer\r
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
+ //\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ //\r
+ // want to save this buffer first\r
+ //\r
+ Status = HBufferImageSave (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ MainTitleBarRefresh (\r
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
+ HMainEditor.BufferImage->BufferType,\r
+ HMainEditor.BufferImage->FileImage->ReadOnly,\r
+ FALSE,\r
+ HMainEditor.ScreenSize.Column,\r
+ HMainEditor.ScreenSize.Row\r
+ );\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ //\r
+ // the file won't be saved\r
+ //\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // get disk block device name\r
+ //\r
+ Status = InputBarSetPrompt (L"Block Device to Open: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (100);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // THE input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ DeviceName = CatSPrint(NULL, L"%s", InputBarGetString());\r
+ if (DeviceName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // get starting offset\r
+ //\r
+ Status = InputBarSetPrompt (L"First Block No.: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (16);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // THE input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // get Number of Blocks:\r
+ //\r
+ Status = InputBarSetPrompt (L"Number of Blocks: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (8);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // THE input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ if (Size == 0) {\r
+ continue;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ Status = HBufferImageRead (\r
+ NULL,\r
+ DeviceName,\r
+ (UINTN)Offset,\r
+ (UINTN)Size,\r
+ 0,\r
+ 0,\r
+ FileTypeDiskBuffer,\r
+ FALSE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+\r
+ HBufferImageRead (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType,\r
+ TRUE\r
+ );\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainCommandOpenMemory (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Load memory content to editor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+ EFI_NOT_FOUND\r
+\r
+--*/\r
+{\r
+ UINT64 Size;\r
+ UINT64 Offset;\r
+ EFI_STATUS Status;\r
+ BOOLEAN Done;\r
+ EDIT_FILE_TYPE BufferType;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ Size = 0;\r
+ Offset = 0;\r
+ BufferType = HMainEditor.BufferImage->BufferType;\r
+\r
+ //\r
+ // if current buffer is modified, so you need to choose\r
+ // whether to save it first.\r
+ //\r
+ if (HMainEditor.BufferImage->Modified) {\r
+\r
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // the answer is just one character\r
+ //\r
+ Status = InputBarSetStringSize (1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // loop for user's answer\r
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
+ //\r
+ Done = FALSE;\r
+ while (!Done) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (InputBarGetString()[0]) {\r
+ case L'y':\r
+ case L'Y':\r
+ //\r
+ // want to save this buffer first\r
+ //\r
+ Status = HBufferImageSave (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ MainTitleBarRefresh (\r
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
+ HMainEditor.BufferImage->BufferType,\r
+ HMainEditor.BufferImage->FileImage->ReadOnly,\r
+ FALSE,\r
+ HMainEditor.ScreenSize.Column,\r
+ HMainEditor.ScreenSize.Row\r
+ );\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'n':\r
+ case L'N':\r
+ //\r
+ // the file won't be saved\r
+ //\r
+ Done = TRUE;\r
+ break;\r
+\r
+ case L'c':\r
+ case L'C':\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // get starting offset\r
+ //\r
+ Status = InputBarSetPrompt (L"Starting Offset: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (8);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // THE input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // get Number of Blocks:\r
+ //\r
+ Status = InputBarSetPrompt (L"Buffer Size: ");\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = InputBarSetStringSize (8);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (1) {\r
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // ESC pressed\r
+ //\r
+ if (Status == EFI_NOT_READY) {\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // THE input string length should > 0\r
+ //\r
+ if (StrLen (InputBarGetString()) > 0) {\r
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ if (Size == 0) {\r
+ continue;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ if ((Offset + Size - 1)> 0xffffffff) {\r
+ StatusBarSetStatusString (L"Invalid parameter");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = HBufferImageRead (\r
+ NULL,\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ (UINTN)Offset,\r
+ (UINTN)Size,\r
+ FileTypeMemBuffer,\r
+ FALSE\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Read Device Error!");\r
+ HBufferImageRead (\r
+ HMainEditor.BufferImage->FileImage->FileName,\r
+ HMainEditor.BufferImage->DiskImage->Name,\r
+ HMainEditor.BufferImage->DiskImage->Offset,\r
+ HMainEditor.BufferImage->DiskImage->Size,\r
+ HMainEditor.BufferImage->MemImage->Offset,\r
+ HMainEditor.BufferImage->MemImage->Size,\r
+ BufferType,\r
+ TRUE\r
+ );\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = {\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),\r
+ HMainCommandGoToOffset\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),\r
+ HMainCommandSaveBuffer\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),\r
+ HMainCommandExit\r
+ },\r
+\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_START),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),\r
+ HMainCommandSelectStart\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_END),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),\r
+ HMainCommandSelectEnd\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_CUT),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),\r
+ HMainCommandCut\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_PASTE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),\r
+ HMainCommandPaste\r
+ },\r
+\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_FILE),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),\r
+ HMainCommandOpenFile\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_DISK),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),\r
+ HMainCommandOpenDisk\r
+ },\r
+ {\r
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY),\r
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F10),\r
+ HMainCommandOpenMemory\r
+ },\r
+\r
+ {\r
+ 0,\r
+ 0,\r
+ NULL\r
+ }\r
+};\r
+\r
+\r
+EFI_STATUS\r
+HMainEditorInit (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Init function for MainEditor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+\r
+ //\r
+ // basic initialization\r
+ //\r
+ CopyMem (&HMainEditor, &HMainEditorConst, sizeof (HMainEditor));\r
+\r
+ //\r
+ // set screen attributes\r
+ //\r
+ HMainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;\r
+\r
+ HMainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);\r
+\r
+ HOriginalColors = HMainEditor.ColorAttributes.Colors;\r
+\r
+ HOriginalMode = gST->ConOut->Mode->Mode;\r
+\r
+ //\r
+ // query screen size\r
+ //\r
+ gST->ConOut->QueryMode (\r
+ gST->ConOut,\r
+ gST->ConOut->Mode->Mode,\r
+ &(HMainEditor.ScreenSize.Column),\r
+ &(HMainEditor.ScreenSize.Row)\r
+ );\r
+\r
+ //\r
+ // Find mouse in System Table ConsoleInHandle\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConIn,\r
+ &gEfiSimplePointerProtocolGuid,\r
+ (VOID**)&HMainEditor.MouseInterface\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If there is no Simple Pointer Protocol on System Table\r
+ //\r
+ HandleBuffer = NULL;\r
+ HMainEditor.MouseInterface = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimplePointerProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status) && HandleCount > 0) {\r
+ //\r
+ // Try to find the first available mouse device\r
+ //\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiSimplePointerProtocolGuid,\r
+ (VOID**)&HMainEditor.MouseInterface\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status) && HMainEditor.MouseInterface != NULL) {\r
+ HMainEditor.MouseAccumulatorX = 0;\r
+ HMainEditor.MouseAccumulatorY = 0;\r
+ HMainEditor.MouseSupported = TRUE;\r
+ }\r
+\r
+ //\r
+ // below will call the five components' init function\r
+ //\r
+ Status = MainTitleBarInit (NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = MenuBarInit (HexEditorMenuItems);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = StatusBarInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ InputBarInit ();\r
+\r
+ Status = HBufferImageInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Status = HClipBoardInit ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD), gShellDebug1HiiHandle);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ //\r
+ // clear whole screen and enable cursor\r
+ //\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ //\r
+ // initialize EditorFirst and EditorExit\r
+ //\r
+ HEditorFirst = TRUE;\r
+ HEditorExit = FALSE;\r
+ HEditorMouseAction = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainEditorCleanup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ cleanup function for MainEditor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // call the five components' cleanup function\r
+ //\r
+ MainTitleBarCleanup ();\r
+\r
+ MenuBarCleanup ();\r
+\r
+ StatusBarCleanup ();\r
+ \r
+ InputBarCleanup ();\r
+ \r
+ Status = HBufferImageCleanup ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN), gShellDebug1HiiHandle);\r
+ }\r
+\r
+ Status = HClipBoardCleanup ();\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN), gShellDebug1HiiHandle);\r
+ }\r
+ //\r
+ // restore old mode\r
+ //\r
+ if (HOriginalMode != gST->ConOut->Mode->Mode) {\r
+ gST->ConOut->SetMode (gST->ConOut, HOriginalMode);\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (\r
+ gST->ConOut,\r
+ EFI_TEXT_ATTR (HOriginalColors.Foreground, HOriginalColors.Background)\r
+ );\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMainEditorRefresh (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Refresh function for MainEditor\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ //\r
+ // to aVOID screen flicker\r
+ // the stall value is from experience\r
+ //\r
+ gBS->Stall (50);\r
+\r
+ //\r
+ // call the four components refresh function\r
+ //\r
+ MainTitleBarRefresh (\r
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
+ HMainEditor.BufferImage->BufferType,\r
+ HMainEditor.BufferImage->FileImage->ReadOnly,\r
+ HMainEditor.BufferImage->Modified,\r
+ HMainEditor.ScreenSize.Column,\r
+ HMainEditor.ScreenSize.Row\r
+ );\r
+ HBufferImageRefresh ();\r
+ StatusBarRefresh (\r
+ HEditorFirst,\r
+ HMainEditor.ScreenSize.Row,\r
+ HMainEditor.ScreenSize.Column,\r
+ 0,\r
+ 0,\r
+ TRUE\r
+ );\r
+ MenuBarRefresh ( \r
+ HMainEditor.ScreenSize.Row,\r
+ HMainEditor.ScreenSize.Column);\r
+\r
+ //\r
+ // EditorFirst is now set to FALSE\r
+ //\r
+ HEditorFirst = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+HMainEditorHandleMouseInput (\r
+ IN EFI_SIMPLE_POINTER_STATE MouseState,\r
+ OUT BOOLEAN *BeforeLeftButtonDown\r
+ )\r
+{\r
+\r
+ INT32 TextX;\r
+ INT32 TextY;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ BOOLEAN HighBits;\r
+ LIST_ENTRY *Link;\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN Index;\r
+ BOOLEAN Action;\r
+\r
+ Action = FALSE;\r
+\r
+ //\r
+ // have mouse movement\r
+ //\r
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {\r
+ //\r
+ // handle\r
+ //\r
+ TextX = HGetTextX (MouseState.RelativeMovementX);\r
+ TextY = HGetTextY (MouseState.RelativeMovementY);\r
+\r
+ HBufferImageAdjustMousePosition (TextX, TextY);\r
+\r
+ Action = TRUE;\r
+\r
+ }\r
+\r
+ if (MouseState.LeftButton) {\r
+ HighBits = HBufferImageIsAtHighBits (\r
+ HMainEditor.BufferImage->MousePosition.Column,\r
+ &FCol\r
+ );\r
+\r
+ //\r
+ // not at an movable place\r
+ //\r
+ if (FCol == 0) {\r
+ //\r
+ // now just move mouse pointer to legal position\r
+ //\r
+ //\r
+ // move mouse position to legal position\r
+ //\r
+ HMainEditor.BufferImage->MousePosition.Column -= 10;\r
+ if (HMainEditor.BufferImage->MousePosition.Column > 24) {\r
+ HMainEditor.BufferImage->MousePosition.Column--;\r
+ FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;\r
+ } else {\r
+ if (HMainEditor.BufferImage->MousePosition.Column < 24) {\r
+ FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;\r
+ } else {\r
+ //\r
+ // == 24\r
+ //\r
+ FCol = 9;\r
+ }\r
+ }\r
+\r
+ HighBits = TRUE;\r
+\r
+ }\r
+\r
+ FRow = HMainEditor.BufferImage->BufferPosition.Row +\r
+ HMainEditor.BufferImage->MousePosition.Row -\r
+ HMainEditor.BufferImage->DisplayPosition.Row;\r
+\r
+ if (HMainEditor.BufferImage->NumLines < FRow) {\r
+ //\r
+ // dragging\r
+ //\r
+ //\r
+ // now just move mouse pointer to legal position\r
+ //\r
+ FRow = HMainEditor.BufferImage->NumLines;\r
+ HighBits = TRUE;\r
+ }\r
+\r
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
+ for (Index = 0; Index < FRow - 1; Index++) {\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+\r
+ //\r
+ // dragging\r
+ //\r
+ //\r
+ // now just move mouse pointer to legal position\r
+ //\r
+ if (FCol > Line->Size) {\r
+ if (*BeforeLeftButtonDown) {\r
+ HighBits = FALSE;\r
+\r
+ if (Line->Size == 0) {\r
+ if (FRow > 1) {\r
+ FRow--;\r
+ FCol = 16;\r
+ } else {\r
+ FRow = 1;\r
+ FCol = 1;\r
+ }\r
+\r
+ } else {\r
+ FCol = Line->Size;\r
+ }\r
+ } else {\r
+ FCol = Line->Size + 1;\r
+ HighBits = TRUE;\r
+ }\r
+ }\r
+\r
+ HBufferImageMovePosition (FRow, FCol, HighBits);\r
+\r
+ HMainEditor.BufferImage->MousePosition.Row = HMainEditor.BufferImage->DisplayPosition.Row;\r
+\r
+ HMainEditor.BufferImage->MousePosition.Column = HMainEditor.BufferImage->DisplayPosition.Column;\r
+\r
+ *BeforeLeftButtonDown = TRUE;\r
+\r
+ Action = TRUE;\r
+ } else {\r
+ //\r
+ // else of if LButton\r
+ //\r
+ // release LButton\r
+ //\r
+ if (*BeforeLeftButtonDown == TRUE) {\r
+ Action = TRUE;\r
+ }\r
+ //\r
+ // mouse up\r
+ //\r
+ *BeforeLeftButtonDown = FALSE;\r
+ }\r
+\r
+ if (Action) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+HMainEditorKeyInput (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Handle user key input. will route it to other components handle function\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+ EFI_INPUT_KEY Key;\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_POINTER_STATE MouseState;\r
+ BOOLEAN LengthChange;\r
+ UINTN Size;\r
+ UINTN OldSize;\r
+ BOOLEAN BeforeMouseIsDown;\r
+ BOOLEAN MouseIsDown;\r
+ BOOLEAN FirstDown;\r
+ BOOLEAN MouseDrag;\r
+ UINTN FRow;\r
+ UINTN FCol;\r
+ UINTN SelectStartBackup;\r
+ UINTN SelectEndBackup;\r
+\r
+ //\r
+ // variable initialization\r
+ //\r
+ OldSize = 0;\r
+ FRow = 0;\r
+ FCol = 0;\r
+ LengthChange = FALSE;\r
+\r
+ MouseIsDown = FALSE;\r
+ FirstDown = FALSE;\r
+ MouseDrag = FALSE;\r
+\r
+ do {\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ HEditorMouseAction = FALSE;\r
+\r
+ //\r
+ // backup some key elements, so that can aVOID some refresh work\r
+ //\r
+ HMainEditorBackup ();\r
+\r
+ //\r
+ // wait for user key input\r
+ //\r
+ //\r
+ // change priority of checking mouse/keyboard activity dynamically\r
+ // so prevent starvation of keyboard.\r
+ // if last time, mouse moves then this time check keyboard\r
+ //\r
+ if (HMainEditor.MouseSupported) {\r
+ Status = HMainEditor.MouseInterface->GetState (\r
+ HMainEditor.MouseInterface,\r
+ &MouseState\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ BeforeMouseIsDown = MouseIsDown;\r
+\r
+ Status = HMainEditorHandleMouseInput (MouseState, &MouseIsDown);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ if (BeforeMouseIsDown == FALSE) {\r
+ //\r
+ // mouse down\r
+ //\r
+ if (MouseIsDown == TRUE) {\r
+ FRow = HBufferImage.BufferPosition.Row;\r
+ FCol = HBufferImage.BufferPosition.Column;\r
+ SelectStartBackup = HMainEditor.SelectStart;\r
+ SelectEndBackup = HMainEditor.SelectEnd;\r
+\r
+ FirstDown = TRUE;\r
+ }\r
+ } else {\r
+\r
+ SelectStartBackup = HMainEditor.SelectStart;\r
+ SelectEndBackup = HMainEditor.SelectEnd;\r
+\r
+ //\r
+ // begin to drag\r
+ //\r
+ if (MouseIsDown == TRUE) {\r
+ if (FirstDown == TRUE) {\r
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {\r
+ HMainEditor.SelectStart = 0;\r
+ HMainEditor.SelectEnd = 0;\r
+ HMainEditor.SelectStart = (FRow - 1) * 0x10 + FCol;\r
+\r
+ MouseDrag = TRUE;\r
+ FirstDown = FALSE;\r
+ }\r
+ } else {\r
+ if ((\r
+ (HBufferImage.BufferPosition.Row - 1) *\r
+ 0x10 +\r
+ HBufferImage.BufferPosition.Column\r
+ ) >= HMainEditor.SelectStart\r
+ ) {\r
+ HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *\r
+ 0x10 +\r
+ HBufferImage.BufferPosition.Column;\r
+ } else {\r
+ HMainEditor.SelectEnd = 0;\r
+ }\r
+ }\r
+ //\r
+ // end of if RelativeX/Y\r
+ //\r
+ } else {\r
+ //\r
+ // mouse is up\r
+ //\r
+ if (MouseDrag) {\r
+ if (HBufferImageGetTotalSize () == 0) {\r
+ HMainEditor.SelectStart = 0;\r
+ HMainEditor.SelectEnd = 0;\r
+ FirstDown = FALSE;\r
+ MouseDrag = FALSE;\r
+ }\r
+\r
+ if ((\r
+ (HBufferImage.BufferPosition.Row - 1) *\r
+ 0x10 +\r
+ HBufferImage.BufferPosition.Column\r
+ ) >= HMainEditor.SelectStart\r
+ ) {\r
+ HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *\r
+ 0x10 +\r
+ HBufferImage.BufferPosition.Column;\r
+ } else {\r
+ HMainEditor.SelectEnd = 0;\r
+ }\r
+\r
+ if (HMainEditor.SelectEnd == 0) {\r
+ HMainEditor.SelectStart = 0;\r
+ }\r
+ }\r
+\r
+ FirstDown = FALSE;\r
+ MouseDrag = FALSE;\r
+ }\r
+\r
+ if (SelectStartBackup != HMainEditor.SelectStart || SelectEndBackup != HMainEditor.SelectEnd) {\r
+ if ((SelectStartBackup - 1) / 0x10 != (HMainEditor.SelectStart - 1) / 0x10) {\r
+ HBufferImageNeedRefresh = TRUE;\r
+ } else {\r
+ if ((SelectEndBackup - 1) / 0x10 != (HMainEditor.SelectEnd - 1) / 0x10) {\r
+ HBufferImageNeedRefresh = TRUE;\r
+ } else {\r
+ HBufferImageOnlyLineNeedRefresh = TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ HEditorMouseAction = TRUE;\r
+ HBufferImageMouseNeedRefresh = TRUE;\r
+\r
+ } else if (Status == EFI_LOAD_ERROR) {\r
+ StatusBarSetStatusString (L"Invalid Mouse Movement ");\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // dispatch to different components' key handling function\r
+ // so not everywhere has to set this variable\r
+ //\r
+ HBufferImageMouseNeedRefresh = TRUE;\r
+\r
+ //\r
+ // clear previous status string\r
+ //\r
+ StatusBarSetRefresh();\r
+\r
+ if (Key.ScanCode == SCAN_NULL) {\r
+ Status = HBufferImageHandleInput (&Key);\r
+ } else if (((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {\r
+ Status = HBufferImageHandleInput (&Key);\r
+ } else if (((Key.ScanCode >= SCAN_F1) && Key.ScanCode <= (SCAN_F12))) {\r
+ Status = MenuBarDispatchFunctionKey (&Key);\r
+ } else {\r
+ StatusBarSetStatusString (L"Unknown Command");\r
+\r
+ HBufferImageMouseNeedRefresh = FALSE;\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {\r
+ //\r
+ // not already has some error status\r
+ //\r
+ if (StrCmp (L"", StatusBarGetString()) == 0) {\r
+ StatusBarSetStatusString (L"Disk Error. Try Again");\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // decide if has to set length warning\r
+ //\r
+ if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) {\r
+ LengthChange = FALSE;\r
+ } else {\r
+ //\r
+ // still the old buffer\r
+ //\r
+ if (HBufferImage.BufferType != FileTypeFileBuffer) {\r
+ Size = HBufferImageGetTotalSize ();\r
+\r
+ switch (HBufferImage.BufferType) {\r
+ case FileTypeDiskBuffer:\r
+ OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage->BlockSize;\r
+ break;\r
+\r
+ case FileTypeMemBuffer:\r
+ OldSize = HBufferImage.MemImage->Size;\r
+ break;\r
+ }\r
+\r
+ if (LengthChange == FALSE) {\r
+ if (OldSize != Size) {\r
+ StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be changed");\r
+ }\r
+ }\r
+\r
+ if (OldSize != Size) {\r
+ LengthChange = TRUE;\r
+ } else {\r
+ LengthChange = FALSE;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // after handling, refresh editor\r
+ //\r
+ HMainEditorRefresh ();\r
+\r
+ } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Backup function for MainEditor.\r
+**/\r
+VOID\r
+EFIAPI\r
+HMainEditorBackup (\r
+ VOID\r
+ )\r
+{\r
+ HMainEditorBackupVar.SelectStart = HMainEditor.SelectStart;\r
+ HMainEditorBackupVar.SelectEnd = HMainEditor.SelectEnd;\r
+ HBufferImageBackup ();\r
+}\r
--- /dev/null
+/** @file\r
+ Defines the Main Editor data type - \r
+ - Global variables \r
+ - Instances of the other objects of the editor\r
+ - Main Interfaces\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_EDITOR_H_\r
+#define _LIB_EDITOR_H_\r
+\r
+#include "HexEditor.h"\r
+\r
+EFI_STATUS\r
+HMainEditorInit (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HMainEditorCleanup (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HMainEditorRefresh (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HMainEditorKeyInput (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Backup function for MainEditor.\r
+**/\r
+VOID\r
+EFIAPI\r
+HMainEditorBackup (\r
+ VOID\r
+ );\r
+#endif\r
--- /dev/null
+/** @file\r
+ Functions to deal with Mem buffer\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+\r
+extern EFI_HANDLE HImageHandleBackup;\r
+\r
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
+\r
+extern BOOLEAN HBufferImageNeedRefresh;\r
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
+extern BOOLEAN HBufferImageMouseNeedRefresh;\r
+\r
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
+\r
+HEFI_EDITOR_MEM_IMAGE HMemImage;\r
+HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;\r
+\r
+EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL DummyPciRootBridgeIo;\r
+\r
+//\r
+// for basic initialization of HDiskImage\r
+//\r
+HEFI_EDITOR_MEM_IMAGE HMemImageConst = {\r
+ NULL,\r
+ 0,\r
+ 0\r
+};\r
+\r
+EFI_STATUS\r
+DummyMemRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+DummyMemWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ );\r
+\r
+EFI_STATUS\r
+HMemImageInit (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Initialization function for HDiskImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // basically initialize the HMemImage\r
+ //\r
+ CopyMem (&HMemImage, &HMemImageConst, sizeof (HMemImage));\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiPciRootBridgeIoProtocolGuid,\r
+ NULL,\r
+ (VOID**)&HMemImage.IoFncs\r
+ );\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // For NT32, no EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL is available\r
+ // Use Dummy PciRootBridgeIo for memory access\r
+ //\r
+ ZeroMem (&DummyPciRootBridgeIo, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));\r
+ DummyPciRootBridgeIo.Mem.Read = DummyMemRead;\r
+ DummyPciRootBridgeIo.Mem.Write = DummyMemWrite;\r
+ HMemImage.IoFncs = &DummyPciRootBridgeIo;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+HMemImageBackup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Backup function for HDiskImage\r
+ Only a few fields need to be backup. \r
+ This is for making the Disk buffer refresh \r
+ as few as possible.\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ HMemImageBackupVar.Offset = HMemImage.Offset;\r
+ HMemImageBackupVar.Size = HMemImage.Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMemImageCleanup (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Cleanup function for HDiskImage\r
+\r
+Arguments: \r
+\r
+ None\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMemImageSetMemOffsetSize (\r
+ IN UINTN Offset,\r
+ IN UINTN Size\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Set FileName field in HFileImage\r
+\r
+Arguments: \r
+\r
+ Offset - The offset\r
+ Size - The size\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+\r
+ HMemImage.Offset = Offset;\r
+ HMemImage.Size = Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+HMemImageRead (\r
+ IN UINTN Offset,\r
+ IN UINTN Size,\r
+ BOOLEAN Recover\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Read a disk from disk into HBufferImage\r
+\r
+Arguments: \r
+\r
+ Offset - The offset\r
+ Size - The size\r
+ Recover - if is for recover, no information print\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+ \r
+--*/\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ void *Buffer;\r
+ CHAR16 *Str;\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ EDIT_FILE_TYPE BufferTypeBackup;\r
+\r
+ BufferTypeBackup = HBufferImage.BufferType;\r
+ HBufferImage.BufferType = FileTypeMemBuffer;\r
+\r
+ Buffer = AllocateZeroPool (Size);\r
+ if (Buffer == NULL) {\r
+ StatusBarSetStatusString (L"Read Memory Failed");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = HMemImage.IoFncs->Mem.Read (\r
+ HMemImage.IoFncs,\r
+ EfiPciWidthUint8,\r
+ Offset,\r
+ Size,\r
+ Buffer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ StatusBarSetStatusString (L"Memory Specified Not Accessible");\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ HBufferImageFree ();\r
+\r
+ Status = HBufferImageBufferToList (Buffer, Size);\r
+ FreePool (Buffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ StatusBarSetStatusString (L"Read Memory Failed");\r
+ return Status;\r
+ }\r
+\r
+ Status = HMemImageSetMemOffsetSize (Offset, Size);\r
+\r
+ HBufferImage.DisplayPosition.Row = 2;\r
+ HBufferImage.DisplayPosition.Column = 10;\r
+\r
+ HBufferImage.MousePosition.Row = 2;\r
+ HBufferImage.MousePosition.Column = 10;\r
+\r
+ HBufferImage.LowVisibleRow = 1;\r
+ HBufferImage.HighBits = TRUE;\r
+\r
+ HBufferImage.BufferPosition.Row = 1;\r
+ HBufferImage.BufferPosition.Column = 1;\r
+\r
+ if (!Recover) {\r
+ Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);\r
+ if (Str == NULL) {\r
+ StatusBarSetStatusString (L"Read Memory Failed");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StatusBarSetStatusString (Str);\r
+ SHELL_FREE_NON_NULL (Str);\r
+\r
+ HMainEditor.SelectStart = 0;\r
+ HMainEditor.SelectEnd = 0;\r
+\r
+ }\r
+\r
+ //\r
+ // has line\r
+ //\r
+ if (HBufferImage.Lines != NULL) {\r
+ HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ } else {\r
+ //\r
+ // create a dummy line\r
+ //\r
+ Line = HBufferImageCreateLine ();\r
+ if (Line == NULL) {\r
+ StatusBarSetStatusString (L"Read Memory Failed");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HBufferImage.CurrentLine = Line;\r
+ }\r
+\r
+ HBufferImage.Modified = FALSE;\r
+ HBufferImageNeedRefresh = TRUE;\r
+ HBufferImageOnlyLineNeedRefresh = FALSE;\r
+ HBufferImageMouseNeedRefresh = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+HMemImageSave (\r
+ IN UINTN Offset,\r
+ IN UINTN Size\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Save lines in HBufferImage to disk\r
+\r
+Arguments: \r
+\r
+ Offset - The offset\r
+ Size - The size\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+ EFI_LOAD_ERROR\r
+ EFI_OUT_OF_RESOURCES\r
+\r
+--*/\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ VOID *Buffer;\r
+\r
+ EDIT_FILE_TYPE BufferTypeBackup;\r
+\r
+ //\r
+ // not modified, so directly return\r
+ //\r
+ if (HBufferImage.Modified == FALSE) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ BufferTypeBackup = HBufferImage.BufferType;\r
+ HBufferImage.BufferType = FileTypeMemBuffer;\r
+\r
+ Buffer = AllocateZeroPool (Size);\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = HBufferImageListToBuffer (Buffer, Size);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Buffer);\r
+ return Status;\r
+ }\r
+ //\r
+ // write back to memory\r
+ //\r
+ Status = HMemImage.IoFncs->Mem.Write (\r
+ HMemImage.IoFncs,\r
+ EfiPciWidthUint8,\r
+ Offset,\r
+ Size,\r
+ Buffer\r
+ );\r
+\r
+ FreePool (Buffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ //\r
+ // now not modified\r
+ //\r
+ HBufferImage.Modified = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DummyMemRead (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+DummyMemWrite (\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,\r
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
+ IN UINT64 Address,\r
+ IN UINTN Count,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+ Defines MemImage - the view of the file that is visible at any point, \r
+ as well as the event handlers for editing the file\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_MEM_IMAGE_H_\r
+#define _LIB_MEM_IMAGE_H_\r
+\r
+#include "HexEditor.h"\r
+\r
+EFI_STATUS\r
+HMemImageInit (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HMemImageCleanup (\r
+ VOID\r
+ );\r
+EFI_STATUS\r
+HMemImageBackup (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+HMemImageSetMemOffsetSize (\r
+ IN UINTN,\r
+ IN UINTN\r
+ );\r
+\r
+EFI_STATUS\r
+HMemImageRead (\r
+ IN UINTN,\r
+ IN UINTN,\r
+ IN BOOLEAN\r
+ );\r
+EFI_STATUS\r
+HMemImageSave (\r
+ IN UINTN,\r
+ IN UINTN\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Implementation of various string and line routines\r
+ \r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "HexEditor.h"\r
+\r
+extern BOOLEAN HEditorMouseAction;\r
+\r
+VOID\r
+HEditorClearLine (\r
+ IN UINTN Row\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Clear line at Row\r
+\r
+Arguments: \r
+\r
+ Row -- row number to be cleared ( start from 1 )\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ CHAR16 Line[200];\r
+ UINTN Index;\r
+ UINTN Limit;\r
+ UINTN StartCol;\r
+\r
+ if (HEditorMouseAction) {\r
+ Limit = 3 * 0x10;\r
+ StartCol = 10;\r
+ } else {\r
+ Limit = HMainEditor.ScreenSize.Column;\r
+ StartCol = 1;\r
+ }\r
+ //\r
+ // prepare a blank line\r
+ //\r
+ for (Index = 0; Index < Limit; Index++) {\r
+ Line[Index] = ' ';\r
+ }\r
+\r
+ if (Row == HMainEditor.ScreenSize.Row && Limit == HMainEditor.ScreenSize.Column) {\r
+ //\r
+ // if '\0' is still at position 80, it will cause first line error\r
+ //\r
+ Line[Limit - 1] = '\0';\r
+ } else {\r
+ Line[Limit] = '\0';\r
+ }\r
+ //\r
+ // print out the blank line\r
+ //\r
+ ShellPrintEx ((INT32)StartCol - 1, (INT32)Row - 1, Line);\r
+}\r
+\r
+HEFI_EDITOR_LINE *\r
+HLineDup (\r
+ IN HEFI_EDITOR_LINE *Src\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Duplicate a line\r
+\r
+Arguments: \r
+\r
+ Src -- line to be duplicated\r
+\r
+Returns: \r
+\r
+ NULL -- wrong\r
+ Not NULL -- line created\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Dest;\r
+\r
+ //\r
+ // allocate for the line structure\r
+ //\r
+ Dest = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));\r
+ if (Dest == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Dest->Signature = EFI_EDITOR_LINE_LIST;\r
+ Dest->Size = Src->Size;\r
+\r
+ CopyMem (Dest->Buffer, Src->Buffer, 0x10);\r
+\r
+ Dest->Link = Src->Link;\r
+\r
+ return Dest;\r
+}\r
+\r
+VOID\r
+HLineFree (\r
+ IN HEFI_EDITOR_LINE *Src\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Free a line and it's internal buffer\r
+\r
+Arguments: \r
+\r
+ Src -- line to be freed\r
+\r
+Returns: \r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (Src == NULL) {\r
+ return ;\r
+ }\r
+\r
+ SHELL_FREE_NON_NULL (Src);\r
+\r
+}\r
+\r
+HEFI_EDITOR_LINE *\r
+_HLineAdvance (\r
+ IN UINTN Count\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Advance to the next Count lines\r
+\r
+Arguments: \r
+\r
+ Count -- line number to advance\r
+\r
+Returns: \r
+\r
+ NULL -- wrong\r
+ Not NULL -- line after advance\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ Line = HMainEditor.BufferImage->CurrentLine;\r
+ if (Line == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ for (Index = 0; Index < Count; Index++) {\r
+ //\r
+ // if already last line\r
+ //\r
+ if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {\r
+ return NULL;\r
+ }\r
+\r
+ Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ }\r
+\r
+ return Line;\r
+}\r
+\r
+HEFI_EDITOR_LINE *\r
+_HLineRetreat (\r
+ IN UINTN Count\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Retreat to the previous Count lines\r
+\r
+Arguments: \r
+\r
+ Count -- line number to retreat\r
+\r
+Returns: \r
+\r
+ NULL -- wrong\r
+ Not NULL -- line after retreat\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ Line = HMainEditor.BufferImage->CurrentLine;\r
+ if (Line == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ for (Index = 0; Index < Count; Index++) {\r
+ //\r
+ // already the first line\r
+ //\r
+ if (Line->Link.BackLink == HMainEditor.BufferImage->ListHead) {\r
+ return NULL;\r
+ }\r
+\r
+ Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ }\r
+\r
+ return Line;\r
+}\r
+\r
+HEFI_EDITOR_LINE *\r
+HMoveLine (\r
+ IN INTN Count\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Advance/Retreat lines\r
+\r
+Arguments: \r
+\r
+ Count -- line number to advance/retreat\r
+ >0 : advance\r
+ <0: retreat \r
+\r
+Returns: \r
+\r
+ NULL -- wrong\r
+ Not NULL -- line after advance\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN AbsCount;\r
+\r
+ //\r
+ // difference with MoveCurrentLine\r
+ // just return Line\r
+ // do not set currentline to Line\r
+ //\r
+ if (Count <= 0) {\r
+ AbsCount = -Count;\r
+ Line = _HLineRetreat (AbsCount);\r
+ } else {\r
+ Line = _HLineAdvance (Count);\r
+ }\r
+\r
+ return Line;\r
+}\r
+\r
+HEFI_EDITOR_LINE *\r
+HMoveCurrentLine (\r
+ IN INTN Count\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Advance/Retreat lines and set CurrentLine in BufferImage to it\r
+\r
+Arguments: \r
+\r
+ Count -- line number to advance/retreat\r
+ >0 : advance\r
+ <0: retreat\r
+\r
+Returns: \r
+\r
+ NULL -- wrong\r
+ Not NULL -- line after advance\r
+\r
+\r
+--*/\r
+{\r
+ HEFI_EDITOR_LINE *Line;\r
+ UINTN AbsCount;\r
+\r
+ //\r
+ // <0: retreat\r
+ // >0: advance\r
+ //\r
+ if (Count <= 0) {\r
+ AbsCount = -Count;\r
+ Line = _HLineRetreat (AbsCount);\r
+ } else {\r
+ Line = _HLineAdvance (Count);\r
+ }\r
+\r
+ if (Line == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ HMainEditor.BufferImage->CurrentLine = Line;\r
+\r
+ return Line;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+HFreeLines (\r
+ IN LIST_ENTRY *ListHead,\r
+ IN HEFI_EDITOR_LINE *Lines\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Free all the lines in HBufferImage\r
+ Fields affected:\r
+ Lines\r
+ CurrentLine\r
+ NumLines\r
+ ListHead \r
+\r
+Arguments: \r
+\r
+ ListHead - The list head\r
+ Lines - The lines\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS\r
+\r
+--*/\r
+{\r
+ LIST_ENTRY *Link;\r
+ HEFI_EDITOR_LINE *Line;\r
+\r
+ //\r
+ // release all the lines\r
+ //\r
+ if (Lines != NULL) {\r
+\r
+ Line = Lines;\r
+ Link = &(Line->Link);\r
+ do {\r
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
+ Link = Link->ForwardLink;\r
+ HLineFree (Line);\r
+ } while (Link != ListHead);\r
+ }\r
+\r
+ ListHead->ForwardLink = ListHead;\r
+ ListHead->BackLink = ListHead;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINTN\r
+HStrStr (\r
+ IN CHAR16 *Str,\r
+ IN CHAR16 *Pat\r
+ )\r
+/*++\r
+\r
+Routine Description: \r
+\r
+ Search Pat in Str\r
+\r
+Arguments: \r
+\r
+ Str -- mother string\r
+ Pat -- search pattern\r
+\r
+\r
+Returns: \r
+\r
+ 0 : not found\r
+ >= 1 : found position + 1\r
+\r
+--*/\r
+{\r
+ INTN *Failure;\r
+ INTN i;\r
+ INTN j;\r
+ INTN Lenp;\r
+ INTN Lens;\r
+\r
+ //\r
+ // this function copies from some lib\r
+ //\r
+ Lenp = StrLen (Pat);\r
+ Lens = StrLen (Str);\r
+\r
+ Failure = AllocateZeroPool (Lenp * sizeof (INTN));\r
+ Failure[0] = -1;\r
+ for (j = 1; j < Lenp; j++) {\r
+ i = Failure[j - 1];\r
+ while ((Pat[j] != Pat[i + 1]) && (i >= 0)) {\r
+ i = Failure[i];\r
+ }\r
+\r
+ if (Pat[j] == Pat[i + 1]) {\r
+ Failure[j] = i + 1;\r
+ } else {\r
+ Failure[j] = -1;\r
+ }\r
+ }\r
+\r
+ i = 0;\r
+ j = 0;\r
+ while (i < Lens && j < Lenp) {\r
+ if (Str[i] == Pat[j]) {\r
+ i++;\r
+ j++;\r
+ } else if (j == 0) {\r
+ i++;\r
+ } else {\r
+ j = Failure[j - 1] + 1;\r
+ }\r
+ }\r
+\r
+ FreePool (Failure);\r
+\r
+ //\r
+ // 0: not found\r
+ // >=1 : found position + 1\r
+ //\r
+ return ((j == Lenp) ? (i - Lenp) : -1) + 1;\r
+\r
+}\r
+\r
+INT32\r
+HGetTextX (\r
+ IN INT32 GuidX\r
+ )\r
+{\r
+ INT32 Gap;\r
+\r
+ HMainEditor.MouseAccumulatorX += GuidX;\r
+ Gap = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX);\r
+ HMainEditor.MouseAccumulatorX = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX);\r
+ HMainEditor.MouseAccumulatorX = HMainEditor.MouseAccumulatorX / (INT32) HMainEditor.ScreenSize.Column;\r
+ return Gap;\r
+}\r
+\r
+INT32\r
+HGetTextY (\r
+ IN INT32 GuidY\r
+ )\r
+{\r
+ INT32 Gap;\r
+\r
+ HMainEditor.MouseAccumulatorY += GuidY;\r
+ Gap = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY);\r
+ HMainEditor.MouseAccumulatorY = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY);\r
+ HMainEditor.MouseAccumulatorY = HMainEditor.MouseAccumulatorY / (INT32) HMainEditor.ScreenSize.Row;\r
+\r
+ return Gap;\r
+}\r
+\r
+EFI_STATUS\r
+HXtoi (\r
+ IN CHAR16 *Str,\r
+ OUT UINTN *Value\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ convert hex string to uint\r
+ \r
+Arguments:\r
+\r
+ Str - The string\r
+ Value - The value\r
+\r
+Returns:\r
+\r
+\r
+--*/\r
+{\r
+ UINT64 u;\r
+ CHAR16 c;\r
+ UINTN Size;\r
+\r
+ Size = sizeof (UINTN);\r
+\r
+ //\r
+ // skip leading white space\r
+ //\r
+ while (*Str && *Str == ' ') {\r
+ Str += 1;\r
+ }\r
+\r
+ if (StrLen (Str) > Size * 2) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ //\r
+ // convert hex digits\r
+ //\r
+ u = 0;\r
+ c = *Str;\r
+ while (c) {\r
+ c = *Str;\r
+ Str++;\r
+\r
+ if (c == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // not valid char\r
+ //\r
+ if (!((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9') || (c == '\0'))) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ if (c >= 'a' && c <= 'f') {\r
+ c -= 'a' - 'A';\r
+ }\r
+\r
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {\r
+ u = LShiftU64 (u, 4) + (c - (c >= 'A' ? 'A' - 10 : '0'));\r
+ } else {\r
+ //\r
+ // '\0'\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ *Value = (UINTN) u;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ Definitions for various line and string routines\r
+\r
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _LIB_MISC_H_\r
+#define _LIB_MISC_H_\r
+\r
+#include "HexEditor.h"\r
+\r
+VOID\r
+HEditorClearLine (\r
+ UINTN\r
+ );\r
+HEFI_EDITOR_LINE *\r
+HLineDup (\r
+ HEFI_EDITOR_LINE *\r
+ );\r
+VOID\r
+HLineFree (\r
+ HEFI_EDITOR_LINE *\r
+ );\r
+\r
+HEFI_EDITOR_LINE *\r
+HMoveLine (\r
+ INTN\r
+ );\r
+HEFI_EDITOR_LINE *\r
+HMoveCurrentLine (\r
+ INTN\r
+ );\r
+\r
+UINTN\r
+HLineStrInsert (\r
+ HEFI_EDITOR_LINE *,\r
+ CHAR16,\r
+ UINTN,\r
+ UINTN\r
+ );\r
+\r
+VOID\r
+HLineCat (\r
+ HEFI_EDITOR_LINE *,\r
+ HEFI_EDITOR_LINE *\r
+ );\r
+\r
+VOID\r
+HLineDeleteAt (\r
+ HEFI_EDITOR_LINE *,\r
+ UINTN\r
+ );\r
+\r
+UINTN\r
+HUnicodeToAscii (\r
+ CHAR16 *,\r
+ UINTN,\r
+ CHAR8 *\r
+ );\r
+\r
+UINTN\r
+HStrStr (\r
+ CHAR16 *,\r
+ CHAR16 *\r
+ );\r
+\r
+EFI_STATUS\r
+HFreeLines (\r
+ LIST_ENTRY *,\r
+ HEFI_EDITOR_LINE *\r
+ );\r
+\r
+INT32\r
+HGetTextX (\r
+ INT32\r
+ ) ;\r
+INT32\r
+HGetTextY (\r
+ INT32\r
+ ) ;\r
+\r
+EFI_STATUS\r
+HXtoi (\r
+ CHAR16 *,\r
+ UINTN *\r
+ );\r
+\r
+#endif\r