| /** @file | |
| Defines the Main Editor data type - | |
| - Global variables | |
| - Instances of the other objects of the editor | |
| - Main Interfaces | |
| Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved. <BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "HexEditor.h" | |
| #include "EditStatusBar.h" | |
| #include "EditInputBar.h" | |
| HEFI_EDITOR_COLOR_ATTRIBUTES HOriginalColors; | |
| INTN HOriginalMode; | |
| // | |
| // the first time editor launch | |
| // | |
| BOOLEAN HEditorFirst; | |
| // | |
| // it's time editor should exit | |
| // | |
| BOOLEAN HEditorExit; | |
| BOOLEAN HEditorMouseAction; | |
| extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage; | |
| extern HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar; | |
| extern BOOLEAN HBufferImageMouseNeedRefresh; | |
| extern BOOLEAN HBufferImageNeedRefresh; | |
| extern BOOLEAN HBufferImageOnlyLineNeedRefresh; | |
| HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; | |
| HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar; | |
| // | |
| // basic initialization for MainEditor | |
| // | |
| HEFI_EDITOR_GLOBAL_EDITOR HMainEditorConst = { | |
| &HBufferImage, | |
| { | |
| {0, 0} | |
| }, | |
| { | |
| 0, | |
| 0 | |
| }, | |
| FALSE, | |
| NULL, | |
| 0, | |
| 0, | |
| 1, | |
| 1 | |
| }; | |
| /** | |
| Help info that will be displayed. | |
| **/ | |
| EFI_STRING_ID HexMainMenuHelpInfo[] = { | |
| STRING_TOKEN(STR_HEXEDIT_HELP_TITLE), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_LIST_TITLE), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_DIV), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_GO_TO_OFFSET), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_SAVE_BUFFER), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_EXIT), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_START), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_END), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_CUT), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_PASTE), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_FILE), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_DISK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_MEMORY), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_EXIT_HELP), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), | |
| STRING_TOKEN(STR_HEXEDIT_HELP_DIV), | |
| 0 | |
| }; | |
| /** | |
| show help menu. | |
| @retval EFI_SUCCESS The operation was successful. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandDisplayHelp ( | |
| VOID | |
| ) | |
| { | |
| INT32 CurrentLine; | |
| CHAR16 * InfoString; | |
| EFI_INPUT_KEY Key; | |
| CurrentLine = 0; | |
| // print helpInfo | |
| for (CurrentLine = 0; 0 != HexMainMenuHelpInfo[CurrentLine]; CurrentLine++) { | |
| InfoString = HiiGetString(gShellDebug1HiiHandle, HexMainMenuHelpInfo[CurrentLine] | |
| , NULL); | |
| ShellPrintEx (0,CurrentLine+1,L"%E%s%N",InfoString); | |
| } | |
| // scan for ctrl+w | |
| do { | |
| gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); | |
| } while(SCAN_CONTROL_W != Key.UnicodeChar); | |
| // update screen with buffer's info | |
| HBufferImageNeedRefresh = TRUE; | |
| HBufferImageOnlyLineNeedRefresh = FALSE; | |
| HBufferImageRefresh (); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Move cursor to specified lines. | |
| @retval EFI_SUCCESS The operation was successful. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandGoToOffset ( | |
| VOID | |
| ) | |
| { | |
| UINTN Size; | |
| UINT64 Offset; | |
| EFI_STATUS Status; | |
| UINTN FRow; | |
| UINTN FCol; | |
| // | |
| // variable initialization | |
| // | |
| Size = 0; | |
| Offset = 0; | |
| FRow = 0; | |
| FCol = 0; | |
| // | |
| // get offset | |
| // | |
| Status = InputBarSetPrompt (L"Go To Offset: "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (8); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // THE input string length should > 0 | |
| // | |
| if (StrLen (InputBarGetString()) > 0) { | |
| Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE); | |
| if (EFI_ERROR (Status)) { | |
| StatusBarSetStatusString (L"Invalid Offset"); | |
| return EFI_SUCCESS; | |
| } | |
| break; | |
| } | |
| } | |
| Size = HBufferImageGetTotalSize (); | |
| if (Offset >= Size) { | |
| StatusBarSetStatusString (L"Invalid Offset"); | |
| return EFI_SUCCESS; | |
| } | |
| FRow = (UINTN)DivU64x32(Offset , 0x10) + 1; | |
| FCol = (UINTN)ModU64x32(Offset , 0x10) + 1; | |
| HBufferImageMovePosition (FRow, FCol, TRUE); | |
| HBufferImageNeedRefresh = TRUE; | |
| HBufferImageOnlyLineNeedRefresh = FALSE; | |
| HBufferImageMouseNeedRefresh = TRUE; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Save current opened buffer. | |
| If is file buffer, you can save to current file name or | |
| save to another file name. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandSaveBuffer ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| BOOLEAN Done; | |
| CHAR16 *FileName; | |
| BOOLEAN OldFile; | |
| CHAR16 *Str; | |
| EFI_FILE_INFO *Info; | |
| SHELL_FILE_HANDLE ShellFileHandle; | |
| if (HMainEditor.BufferImage->BufferType != FileTypeFileBuffer) { | |
| if (!HMainEditor.BufferImage->Modified) { | |
| return EFI_SUCCESS; | |
| } | |
| Status = InputBarSetPrompt (L"Dangerous to save disk/mem buffer. Save (Yes/No/Cancel) ? "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // the answer is just one character | |
| // | |
| Status = InputBarSetStringSize (1); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // loop for user's answer | |
| // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' | |
| // | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| switch (InputBarGetString()[0]) { | |
| case L'y': | |
| case L'Y': | |
| // | |
| // want to save this buffer first | |
| // | |
| Status = HBufferImageSave ( | |
| NULL, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| HMainEditor.BufferImage->BufferType | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| StatusBarSetStatusString (L"BufferSave: Problems Writing"); | |
| return Status; | |
| } | |
| return EFI_SUCCESS; | |
| case L'n': | |
| case L'N': | |
| // | |
| // the file won't be saved | |
| // | |
| return EFI_SUCCESS; | |
| case L'c': | |
| case L'C': | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // end of switch | |
| // | |
| } | |
| // | |
| // ENDOF WHILE | |
| // | |
| } | |
| // | |
| // ENDOF != FILEBUFFER | |
| // | |
| // This command will save currently opened file to disk. | |
| // You can choose save to another file name or just save to | |
| // current file name. | |
| // Below is the scenario of Save File command: ( | |
| // Suppose the old file name is A ) | |
| // 1. An Input Bar will be prompted: "File To Save: [ old file name]" | |
| // IF user press ESC, Save File command ends . | |
| // IF user press Enter, input file name will be A. | |
| // IF user inputs a new file name B, input file name will be B. | |
| // | |
| // 2. IF input file name is A, go to do Step 3. | |
| // IF input file name is B, go to do Step 4. | |
| // | |
| // 3. IF A is read only, Status Bar will show "Access Denied" | |
| // and Save File commands ends. | |
| // IF A is not read only, save file buffer to disk | |
| // and remove Modified flag in Title Bar , then Save File command ends. | |
| // | |
| // 4. IF B does not exist, create this file and save file buffer to it. | |
| // Go to do Step 7. | |
| // IF B exits, do Step 5. | |
| // | |
| // 5. An Input Bar will be prompted: | |
| // "File Exists. Overwrite ( Yes/No/Cancel ) ?" | |
| // IF user press 'y' or 'Y', do Step 6. | |
| // IF user press 'n' or 'N', Save File commands ends. | |
| // IF user press 'c' or 'C' or ESC, Save File commands ends. | |
| // | |
| // 6. IF B is a read-only file, Status Bar will show "Access Denied" | |
| // and Save File commands ends. | |
| // IF B can be read and write, save file buffer to B. | |
| // | |
| // 7. Update File Name field in Title Bar to B | |
| // and remove the Modified flag in Title Bar. | |
| // | |
| Str = CatSPrint(NULL, | |
| L"File to Save: [%s]", | |
| HMainEditor.BufferImage->FileImage->FileName | |
| ); | |
| if (Str == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| if (StrLen (Str) >= 50) { | |
| // | |
| // replace the long file name with "..." | |
| // | |
| Str[46] = L'.'; | |
| Str[47] = L'.'; | |
| Str[48] = L'.'; | |
| Str[49] = L']'; | |
| Str[50] = L'\0'; | |
| } | |
| Status = InputBarSetPrompt (Str); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (100); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // get new file name | |
| // | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // if user pressed ESC | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| SHELL_FREE_NON_NULL (Str); | |
| return EFI_SUCCESS; | |
| } | |
| SHELL_FREE_NON_NULL (Str); | |
| // | |
| // if just enter pressed, so think save to current file name | |
| // | |
| if (StrLen (InputBarGetString()) == 0) { | |
| FileName = CatSPrint(NULL, | |
| L"%s", | |
| HMainEditor.BufferImage->FileImage->FileName | |
| ); | |
| } else { | |
| FileName = CatSPrint(NULL, L"%s", InputBarGetString()); | |
| } | |
| if (FileName == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| if (!IsValidFileName (FileName)) { | |
| StatusBarSetStatusString (L"Invalid File Name"); | |
| SHELL_FREE_NON_NULL (FileName); | |
| return EFI_SUCCESS; | |
| } | |
| OldFile = FALSE; | |
| // | |
| // save to the old file | |
| // | |
| if (StringNoCaseCompare ( | |
| &FileName, | |
| &HMainEditor.BufferImage->FileImage->FileName | |
| ) == 0) { | |
| OldFile = TRUE; | |
| } | |
| if (OldFile) { | |
| // | |
| // if the file is read only, so can not write back to it. | |
| // | |
| if (HMainEditor.BufferImage->FileImage->ReadOnly) { | |
| StatusBarSetStatusString (L"Access Denied"); | |
| SHELL_FREE_NON_NULL (FileName); | |
| return EFI_SUCCESS; | |
| } | |
| } else { | |
| Status = ShellOpenFileByName (FileName, &ShellFileHandle, EFI_FILE_MODE_READ, 0); | |
| if (!EFI_ERROR (Status)) { | |
| Info = ShellGetFileInfo(ShellFileHandle); | |
| ShellCloseFile(&ShellFileHandle); | |
| // | |
| // check if read only | |
| // | |
| if (Info->Attribute & EFI_FILE_READ_ONLY) { | |
| StatusBarSetStatusString (L"Access Denied"); | |
| SHELL_FREE_NON_NULL (FileName); | |
| return EFI_SUCCESS; | |
| } | |
| SHELL_FREE_NON_NULL(Info); | |
| // | |
| // ask user whether to overwrite this file | |
| // | |
| Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? "); | |
| if (EFI_ERROR (Status)) { | |
| SHELL_FREE_NON_NULL (FileName); | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (1); | |
| if (EFI_ERROR (Status)) { | |
| SHELL_FREE_NON_NULL (FileName); | |
| return Status; | |
| } | |
| Done = FALSE; | |
| while (!Done) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| if (Status == EFI_NOT_READY) { | |
| SHELL_FREE_NON_NULL (FileName); | |
| return EFI_SUCCESS; | |
| } | |
| switch (InputBarGetString()[0]) { | |
| case L'y': | |
| case L'Y': | |
| Done = TRUE; | |
| break; | |
| case L'n': | |
| case L'N': | |
| SHELL_FREE_NON_NULL (FileName); | |
| return EFI_SUCCESS; | |
| case L'c': | |
| case L'C': | |
| SHELL_FREE_NON_NULL (FileName); | |
| return EFI_SUCCESS; | |
| } // switch | |
| } // while | |
| } // if opened existing file | |
| } // if OldFile | |
| // | |
| // save file back to disk | |
| // | |
| Status = HBufferImageSave ( | |
| FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| FileTypeFileBuffer | |
| ); | |
| SHELL_FREE_NON_NULL (FileName); | |
| if (EFI_ERROR (Status)) { | |
| return EFI_LOAD_ERROR; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Load a disk buffer editor. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandSelectStart ( | |
| VOID | |
| ) | |
| { | |
| UINTN Start; | |
| Start = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column; | |
| // | |
| // last line | |
| // | |
| if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) { | |
| if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) { | |
| StatusBarSetStatusString (L"Invalid Block Start"); | |
| return EFI_LOAD_ERROR; | |
| } | |
| } | |
| if (HMainEditor.SelectEnd != 0 && Start > HMainEditor.SelectEnd) { | |
| StatusBarSetStatusString (L"Invalid Block Start"); | |
| return EFI_LOAD_ERROR; | |
| } | |
| HMainEditor.SelectStart = Start; | |
| HBufferImageNeedRefresh = TRUE; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Load a disk buffer editor. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandSelectEnd ( | |
| VOID | |
| ) | |
| { | |
| UINTN End; | |
| End = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column; | |
| // | |
| // last line | |
| // | |
| if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) { | |
| if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) { | |
| StatusBarSetStatusString (L"Invalid Block End"); | |
| return EFI_LOAD_ERROR; | |
| } | |
| } | |
| if (HMainEditor.SelectStart != 0 && End < HMainEditor.SelectStart) { | |
| StatusBarSetStatusString (L"Invalid Block End"); | |
| return EFI_SUCCESS; | |
| } | |
| HMainEditor.SelectEnd = End; | |
| HBufferImageNeedRefresh = TRUE; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Cut current line to clipboard. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandCut ( | |
| VOID | |
| ) | |
| { | |
| UINTN Index; | |
| LIST_ENTRY *Link; | |
| UINT8 *Buffer; | |
| UINTN Count; | |
| // | |
| // not select, so not allowed to cut | |
| // | |
| if (HMainEditor.SelectStart == 0) { | |
| StatusBarSetStatusString (L"No Block is Selected"); | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // not select, so not allowed to cut | |
| // | |
| if (HMainEditor.SelectEnd == 0) { | |
| StatusBarSetStatusString (L"No Block is Selected"); | |
| return EFI_SUCCESS; | |
| } | |
| Link = HMainEditor.BufferImage->ListHead->ForwardLink; | |
| for (Index = 0; Index < (HMainEditor.SelectEnd - 1) / 0x10; Index++) { | |
| Link = Link->ForwardLink; | |
| } | |
| Count = HMainEditor.SelectEnd - HMainEditor.SelectStart + 1; | |
| Buffer = AllocateZeroPool (Count); | |
| if (Buffer == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // cut the selected area | |
| // | |
| HBufferImageDeleteCharacterFromBuffer ( | |
| HMainEditor.SelectStart - 1, | |
| Count, | |
| Buffer | |
| ); | |
| // | |
| // put to clipboard | |
| // | |
| HClipBoardSet (Buffer, Count); | |
| HBufferImageNeedRefresh = TRUE; | |
| HBufferImageOnlyLineNeedRefresh = FALSE; | |
| if (!HMainEditor.BufferImage->Modified) { | |
| HMainEditor.BufferImage->Modified = TRUE; | |
| } | |
| // | |
| // now no select area | |
| // | |
| HMainEditor.SelectStart = 0; | |
| HMainEditor.SelectEnd = 0; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Paste line to file buffer. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandPaste ( | |
| VOID | |
| ) | |
| { | |
| BOOLEAN OnlyLineRefresh; | |
| HEFI_EDITOR_LINE *Line; | |
| UINT8 *Buffer; | |
| UINTN Count; | |
| UINTN FPos; | |
| Count = HClipBoardGet (&Buffer); | |
| if (Count == 0 || Buffer == NULL) { | |
| StatusBarSetStatusString (L"Nothing to Paste"); | |
| return EFI_SUCCESS; | |
| } | |
| Line = HMainEditor.BufferImage->CurrentLine; | |
| OnlyLineRefresh = FALSE; | |
| if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead && Line->Size + Count < 0x10) { | |
| // | |
| // is at last line, and after paste will not exceed | |
| // so only this line need to be refreshed | |
| // | |
| // if after add, the line is 0x10, then will append a new line | |
| // so the whole page will need be refreshed | |
| // | |
| OnlyLineRefresh = TRUE; | |
| } | |
| FPos = 0x10 * (HMainEditor.BufferImage->BufferPosition.Row - 1) + HMainEditor.BufferImage->BufferPosition.Column - 1; | |
| HBufferImageAddCharacterToBuffer (FPos, Count, Buffer); | |
| if (OnlyLineRefresh) { | |
| HBufferImageNeedRefresh = FALSE; | |
| HBufferImageOnlyLineNeedRefresh = TRUE; | |
| } else { | |
| HBufferImageNeedRefresh = TRUE; | |
| HBufferImageOnlyLineNeedRefresh = FALSE; | |
| } | |
| if (!HMainEditor.BufferImage->Modified) { | |
| HMainEditor.BufferImage->Modified = TRUE; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Exit editor. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandExit ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| // | |
| // Below is the scenario of Exit command: | |
| // 1. IF currently opened file is not modified, exit the editor and | |
| // Exit command ends. | |
| // IF currently opened file is modified, do Step 2 | |
| // | |
| // 2. An Input Bar will be prompted: | |
| // "File modified. Save ( Yes/No/Cancel )?" | |
| // IF user press 'y' or 'Y', currently opened file will be saved and | |
| // Editor exits | |
| // IF user press 'n' or 'N', currently opened file will not be saved | |
| // and Editor exits. | |
| // IF user press 'c' or 'C' or ESC, Exit command ends. | |
| // | |
| // | |
| // if file has been modified, so will prompt user | |
| // whether to save the changes | |
| // | |
| if (HMainEditor.BufferImage->Modified) { | |
| Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (1); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| switch (InputBarGetString()[0]) { | |
| case L'y': | |
| case L'Y': | |
| // | |
| // write file back to disk | |
| // | |
| Status = HBufferImageSave ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| HMainEditor.BufferImage->BufferType | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| HEditorExit = TRUE; | |
| } | |
| return Status; | |
| case L'n': | |
| case L'N': | |
| HEditorExit = TRUE; | |
| return EFI_SUCCESS; | |
| case L'c': | |
| case L'C': | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| } | |
| HEditorExit = TRUE; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Load a file from disk to editor. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandOpenFile ( | |
| VOID | |
| ) | |
| { | |
| BOOLEAN Done; | |
| EFI_STATUS Status; | |
| EDIT_FILE_TYPE BufferType; | |
| BufferType = HMainEditor.BufferImage->BufferType; | |
| // | |
| // This command will open a file from current working directory. | |
| // Read-only file can also be opened. But it can not be modified. | |
| // Below is the scenario of Open File command: | |
| // 1. IF currently opened file has not been modified, directly go to step . | |
| // IF currently opened file has been modified, an Input Bar will be | |
| // prompted as : | |
| // "File Modified. Save ( Yes/No/Cancel) ?" | |
| // IF user press 'y' or 'Y', currently opened file will be saved. | |
| // IF user press 'n' or 'N', currently opened file will | |
| // not be saved. | |
| // IF user press 'c' or 'C' or ESC, Open File command ends and | |
| // currently opened file is still opened. | |
| // | |
| // 2. An Input Bar will be prompted as : "File Name to Open: " | |
| // IF user press ESC, Open File command ends and | |
| // currently opened file is still opened. | |
| // Any other inputs with a Return will cause | |
| // currently opened file close. | |
| // | |
| // 3. IF user input file name is an existing file , | |
| // this file will be read and opened. | |
| // IF user input file name is a new file, this file will be created | |
| // and opened. This file's type ( UNICODE or ASCII ) is the same with | |
| // the old file. | |
| // | |
| // | |
| // if current file is modified, so you need to choose whether to | |
| // save it first. | |
| // | |
| if (HMainEditor.BufferImage->Modified) { | |
| Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // the answer is just one character | |
| // | |
| Status = InputBarSetStringSize (1); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // loop for user's answer | |
| // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' | |
| // | |
| Done = FALSE; | |
| while (!Done) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| switch (InputBarGetString()[0]) { | |
| case L'y': | |
| case L'Y': | |
| // | |
| // want to save this buffer first | |
| // | |
| Status = HBufferImageSave ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| HMainEditor.BufferImage->BufferType | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| MainTitleBarRefresh ( | |
| HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL, | |
| HMainEditor.BufferImage->BufferType, | |
| HMainEditor.BufferImage->FileImage->ReadOnly, | |
| FALSE, | |
| HMainEditor.ScreenSize.Column, | |
| HMainEditor.ScreenSize.Row, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0 | |
| ); | |
| Done = TRUE; | |
| break; | |
| case L'n': | |
| case L'N': | |
| // | |
| // the file won't be saved | |
| // | |
| Done = TRUE; | |
| break; | |
| case L'c': | |
| case L'C': | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| } | |
| // | |
| // TO get the open file name | |
| // | |
| Status = InputBarSetPrompt (L"File Name to Open: "); | |
| if (EFI_ERROR (Status)) { | |
| HBufferImageRead ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType, | |
| TRUE | |
| ); | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (100); | |
| if (EFI_ERROR (Status)) { | |
| Status = HBufferImageRead ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType, | |
| TRUE | |
| ); | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| Status = HBufferImageRead ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType, | |
| TRUE | |
| ); | |
| return Status; | |
| } | |
| // | |
| // THE input string length should > 0 | |
| // | |
| if (StrLen (InputBarGetString()) > 0) { | |
| // | |
| // CHECK if filename's valid | |
| // | |
| if (!IsValidFileName (InputBarGetString())) { | |
| HBufferImageRead ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType, | |
| TRUE | |
| ); | |
| StatusBarSetStatusString (L"Invalid File Name"); | |
| return EFI_SUCCESS; | |
| } | |
| break; | |
| } | |
| } | |
| // | |
| // read from disk | |
| // | |
| Status = HBufferImageRead ( | |
| InputBarGetString(), | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| FileTypeFileBuffer, | |
| FALSE | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| HBufferImageRead ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType, | |
| TRUE | |
| ); | |
| return EFI_LOAD_ERROR; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Load a disk buffer editor. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| @retval EFI_NOT_FOUND The disk was not found. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandOpenDisk ( | |
| VOID | |
| ) | |
| { | |
| UINT64 Size; | |
| UINT64 Offset; | |
| CHAR16 *DeviceName; | |
| EFI_STATUS Status; | |
| BOOLEAN Done; | |
| EDIT_FILE_TYPE BufferType; | |
| // | |
| // variable initialization | |
| // | |
| Size = 0; | |
| Offset = 0; | |
| BufferType = HMainEditor.BufferImage->BufferType; | |
| // | |
| // if current file is modified, so you need to choose | |
| // whether to save it first. | |
| // | |
| if (HMainEditor.BufferImage->Modified) { | |
| Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // the answer is just one character | |
| // | |
| Status = InputBarSetStringSize (1); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // loop for user's answer | |
| // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' | |
| // | |
| Done = FALSE; | |
| while (!Done) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| switch (InputBarGetString()[0]) { | |
| case L'y': | |
| case L'Y': | |
| // | |
| // want to save this buffer first | |
| // | |
| Status = HBufferImageSave ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| MainTitleBarRefresh ( | |
| HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL, | |
| HMainEditor.BufferImage->BufferType, | |
| HMainEditor.BufferImage->FileImage->ReadOnly, | |
| FALSE, | |
| HMainEditor.ScreenSize.Column, | |
| HMainEditor.ScreenSize.Row, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0 | |
| ); | |
| Done = TRUE; | |
| break; | |
| case L'n': | |
| case L'N': | |
| // | |
| // the file won't be saved | |
| // | |
| Done = TRUE; | |
| break; | |
| case L'c': | |
| case L'C': | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| } | |
| // | |
| // get disk block device name | |
| // | |
| Status = InputBarSetPrompt (L"Block Device to Open: "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (100); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // THE input string length should > 0 | |
| // | |
| if (StrLen (InputBarGetString()) > 0) { | |
| break; | |
| } | |
| } | |
| DeviceName = CatSPrint(NULL, L"%s", InputBarGetString()); | |
| if (DeviceName == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // get starting offset | |
| // | |
| Status = InputBarSetPrompt (L"First Block No.: "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (16); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // THE input string length should > 0 | |
| // | |
| if (StrLen (InputBarGetString()) > 0) { | |
| Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| break; | |
| } | |
| } | |
| // | |
| // get Number of Blocks: | |
| // | |
| Status = InputBarSetPrompt (L"Number of Blocks: "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (8); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // THE input string length should > 0 | |
| // | |
| if (StrLen (InputBarGetString()) > 0) { | |
| Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| if (Size == 0) { | |
| continue; | |
| } | |
| break; | |
| } | |
| } | |
| Status = HBufferImageRead ( | |
| NULL, | |
| DeviceName, | |
| (UINTN)Offset, | |
| (UINTN)Size, | |
| 0, | |
| 0, | |
| FileTypeDiskBuffer, | |
| FALSE | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| HBufferImageRead ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType, | |
| TRUE | |
| ); | |
| return EFI_NOT_FOUND; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Load memory content to editor | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| @retval EFI_NOT_FOUND The disk was not found. | |
| **/ | |
| EFI_STATUS | |
| HMainCommandOpenMemory ( | |
| VOID | |
| ) | |
| { | |
| UINT64 Size; | |
| UINT64 Offset; | |
| EFI_STATUS Status; | |
| BOOLEAN Done; | |
| EDIT_FILE_TYPE BufferType; | |
| // | |
| // variable initialization | |
| // | |
| Size = 0; | |
| Offset = 0; | |
| BufferType = HMainEditor.BufferImage->BufferType; | |
| // | |
| // if current buffer is modified, so you need to choose | |
| // whether to save it first. | |
| // | |
| if (HMainEditor.BufferImage->Modified) { | |
| Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // the answer is just one character | |
| // | |
| Status = InputBarSetStringSize (1); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // loop for user's answer | |
| // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' | |
| // | |
| Done = FALSE; | |
| while (!Done) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| switch (InputBarGetString()[0]) { | |
| case L'y': | |
| case L'Y': | |
| // | |
| // want to save this buffer first | |
| // | |
| Status = HBufferImageSave ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| MainTitleBarRefresh ( | |
| HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL, | |
| HMainEditor.BufferImage->BufferType, | |
| HMainEditor.BufferImage->FileImage->ReadOnly, | |
| FALSE, | |
| HMainEditor.ScreenSize.Column, | |
| HMainEditor.ScreenSize.Row, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0 | |
| ); | |
| Done = TRUE; | |
| break; | |
| case L'n': | |
| case L'N': | |
| // | |
| // the file won't be saved | |
| // | |
| Done = TRUE; | |
| break; | |
| case L'c': | |
| case L'C': | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| } | |
| // | |
| // get starting offset | |
| // | |
| Status = InputBarSetPrompt (L"Starting Offset: "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (8); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // THE input string length should > 0 | |
| // | |
| if (StrLen (InputBarGetString()) > 0) { | |
| Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| break; | |
| } | |
| } | |
| // | |
| // get Number of Blocks: | |
| // | |
| Status = InputBarSetPrompt (L"Buffer Size: "); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = InputBarSetStringSize (8); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| while (1) { | |
| Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); | |
| // | |
| // ESC pressed | |
| // | |
| if (Status == EFI_NOT_READY) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // THE input string length should > 0 | |
| // | |
| if (StrLen (InputBarGetString()) > 0) { | |
| Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| if (Size == 0) { | |
| continue; | |
| } | |
| break; | |
| } | |
| } | |
| if ((Offset + Size - 1)> 0xffffffff) { | |
| StatusBarSetStatusString (L"Invalid parameter"); | |
| return EFI_LOAD_ERROR; | |
| } | |
| Status = HBufferImageRead ( | |
| NULL, | |
| NULL, | |
| 0, | |
| 0, | |
| (UINTN)Offset, | |
| (UINTN)Size, | |
| FileTypeMemBuffer, | |
| FALSE | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| StatusBarSetStatusString (L"Read Device Error!"); | |
| HBufferImageRead ( | |
| HMainEditor.BufferImage->FileImage->FileName, | |
| HMainEditor.BufferImage->DiskImage->Name, | |
| HMainEditor.BufferImage->DiskImage->Offset, | |
| HMainEditor.BufferImage->DiskImage->Size, | |
| HMainEditor.BufferImage->MemImage->Offset, | |
| HMainEditor.BufferImage->MemImage->Size, | |
| BufferType, | |
| TRUE | |
| ); | |
| return EFI_NOT_FOUND; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| MENU_ITEM_FUNCTION HexMainControlBasedMenuFunctions[] = { | |
| NULL, | |
| NULL, /* Ctrl - A */ | |
| NULL, /* Ctrl - B */ | |
| NULL, /* Ctrl - C */ | |
| HMainCommandSelectEnd, /* Ctrl - D */ | |
| HMainCommandDisplayHelp, /* Ctrl - E */ | |
| NULL, /* Ctrl - F */ | |
| HMainCommandGoToOffset, /* Ctrl - G */ | |
| NULL, /* Ctrl - H */ | |
| HMainCommandOpenDisk, /* Ctrl - I */ | |
| NULL, /* Ctrl - J */ | |
| NULL, /* Ctrl - K */ | |
| NULL, /* Ctrl - L */ | |
| HMainCommandOpenMemory, /* Ctrl - M */ | |
| NULL, /* Ctrl - N */ | |
| HMainCommandOpenFile, /* Ctrl - O */ | |
| NULL, /* Ctrl - P */ | |
| HMainCommandExit, /* Ctrl - Q */ | |
| NULL, /* Ctrl - R */ | |
| HMainCommandSaveBuffer, /* Ctrl - S */ | |
| HMainCommandSelectStart, /* Ctrl - T */ | |
| NULL, /* Ctrl - U */ | |
| HMainCommandPaste, /* Ctrl - V */ | |
| NULL, /* Ctrl - W */ | |
| HMainCommandCut, /* Ctrl - X */ | |
| NULL, /* Ctrl - Y */ | |
| NULL, /* Ctrl - Z */ | |
| }; | |
| CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = { | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1), | |
| HMainCommandGoToOffset | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2), | |
| HMainCommandSaveBuffer | |
| }, | |
| { | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3), | |
| HMainCommandExit | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_START), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4), | |
| HMainCommandSelectStart | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_END), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5), | |
| HMainCommandSelectEnd | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_CUT), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6), | |
| HMainCommandCut | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_PASTE), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7), | |
| HMainCommandPaste | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_FILE), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8), | |
| HMainCommandOpenFile | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_DISK), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9), | |
| HMainCommandOpenDisk | |
| }, | |
| { | |
| STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY), | |
| STRING_TOKEN(STR_EDIT_LIBMENUBAR_F10), | |
| HMainCommandOpenMemory | |
| }, | |
| { | |
| 0, | |
| 0, | |
| NULL | |
| } | |
| }; | |
| /** | |
| Init function for MainEditor | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainEditorInit ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_HANDLE *HandleBuffer; | |
| UINTN HandleCount; | |
| UINTN Index; | |
| // | |
| // basic initialization | |
| // | |
| CopyMem (&HMainEditor, &HMainEditorConst, sizeof (HMainEditor)); | |
| // | |
| // set screen attributes | |
| // | |
| HMainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff; | |
| HMainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4); | |
| HOriginalColors = HMainEditor.ColorAttributes.Colors; | |
| HOriginalMode = gST->ConOut->Mode->Mode; | |
| // | |
| // query screen size | |
| // | |
| gST->ConOut->QueryMode ( | |
| gST->ConOut, | |
| gST->ConOut->Mode->Mode, | |
| &(HMainEditor.ScreenSize.Column), | |
| &(HMainEditor.ScreenSize.Row) | |
| ); | |
| // | |
| // Find mouse in System Table ConsoleInHandle | |
| // | |
| Status = gBS->HandleProtocol ( | |
| gST->ConIn, | |
| &gEfiSimplePointerProtocolGuid, | |
| (VOID**)&HMainEditor.MouseInterface | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // If there is no Simple Pointer Protocol on System Table | |
| // | |
| HandleBuffer = NULL; | |
| HMainEditor.MouseInterface = NULL; | |
| Status = gBS->LocateHandleBuffer ( | |
| ByProtocol, | |
| &gEfiSimplePointerProtocolGuid, | |
| NULL, | |
| &HandleCount, | |
| &HandleBuffer | |
| ); | |
| if (!EFI_ERROR (Status) && HandleCount > 0) { | |
| // | |
| // Try to find the first available mouse device | |
| // | |
| for (Index = 0; Index < HandleCount; Index++) { | |
| Status = gBS->HandleProtocol ( | |
| HandleBuffer[Index], | |
| &gEfiSimplePointerProtocolGuid, | |
| (VOID**)&HMainEditor.MouseInterface | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| break; | |
| } | |
| } | |
| } | |
| if (HandleBuffer != NULL) { | |
| FreePool (HandleBuffer); | |
| } | |
| } | |
| if (!EFI_ERROR (Status) && HMainEditor.MouseInterface != NULL) { | |
| HMainEditor.MouseAccumulatorX = 0; | |
| HMainEditor.MouseAccumulatorY = 0; | |
| HMainEditor.MouseSupported = TRUE; | |
| } | |
| // | |
| // below will call the five components' init function | |
| // | |
| Status = MainTitleBarInit (L"UEFI HEXEDIT"); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE), gShellDebug1HiiHandle); | |
| return EFI_LOAD_ERROR; | |
| } | |
| Status = ControlHotKeyInit (HexMainControlBasedMenuFunctions); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle); | |
| return EFI_LOAD_ERROR; | |
| } | |
| Status = MenuBarInit (HexEditorMenuItems); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle); | |
| return EFI_LOAD_ERROR; | |
| } | |
| Status = StatusBarInit (); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS), gShellDebug1HiiHandle); | |
| return EFI_LOAD_ERROR; | |
| } | |
| InputBarInit (); | |
| Status = HBufferImageInit (); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE), gShellDebug1HiiHandle); | |
| return EFI_LOAD_ERROR; | |
| } | |
| Status = HClipBoardInit (); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD), gShellDebug1HiiHandle); | |
| return EFI_LOAD_ERROR; | |
| } | |
| // | |
| // clear whole screen and enable cursor | |
| // | |
| gST->ConOut->ClearScreen (gST->ConOut); | |
| gST->ConOut->EnableCursor (gST->ConOut, TRUE); | |
| // | |
| // initialize EditorFirst and EditorExit | |
| // | |
| HEditorFirst = TRUE; | |
| HEditorExit = FALSE; | |
| HEditorMouseAction = FALSE; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Cleanup function for MainEditor. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainEditorCleanup ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| // | |
| // call the five components' cleanup function | |
| // | |
| MainTitleBarCleanup (); | |
| MenuBarCleanup (); | |
| StatusBarCleanup (); | |
| InputBarCleanup (); | |
| Status = HBufferImageCleanup (); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN), gShellDebug1HiiHandle); | |
| } | |
| Status = HClipBoardCleanup (); | |
| if (EFI_ERROR (Status)) { | |
| ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN), gShellDebug1HiiHandle); | |
| } | |
| // | |
| // restore old mode | |
| // | |
| if (HOriginalMode != gST->ConOut->Mode->Mode) { | |
| gST->ConOut->SetMode (gST->ConOut, HOriginalMode); | |
| } | |
| gST->ConOut->SetAttribute ( | |
| gST->ConOut, | |
| EFI_TEXT_ATTR (HOriginalColors.Foreground, HOriginalColors.Background) | |
| ); | |
| gST->ConOut->ClearScreen (gST->ConOut); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Refresh function for MainEditor. | |
| @retval EFI_SUCCESS The operation was successful. | |
| **/ | |
| EFI_STATUS | |
| HMainEditorRefresh ( | |
| VOID | |
| ) | |
| { | |
| BOOLEAN NameChange; | |
| BOOLEAN ReadChange; | |
| NameChange = FALSE; | |
| ReadChange = FALSE; | |
| if (HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer) { | |
| if (HMainEditor.BufferImage->DiskImage != NULL && | |
| HBufferImageBackupVar.DiskImage != NULL && | |
| (HMainEditor.BufferImage->DiskImage->Offset != HBufferImageBackupVar.DiskImage->Offset || | |
| HMainEditor.BufferImage->DiskImage->Size != HBufferImageBackupVar.DiskImage->Size) ){ | |
| NameChange = TRUE; | |
| } | |
| } else if (HMainEditor.BufferImage->BufferType == FileTypeMemBuffer) { | |
| if (HMainEditor.BufferImage->MemImage != NULL && | |
| HBufferImageBackupVar.MemImage != NULL && | |
| (HMainEditor.BufferImage->MemImage->Offset != HBufferImageBackupVar.MemImage->Offset || | |
| HMainEditor.BufferImage->MemImage->Size != HBufferImageBackupVar.MemImage->Size) ){ | |
| NameChange = TRUE; | |
| } | |
| } else if (HMainEditor.BufferImage->BufferType == FileTypeFileBuffer) { | |
| if ( HMainEditor.BufferImage->FileImage != NULL && | |
| HMainEditor.BufferImage->FileImage->FileName != NULL && | |
| HBufferImageBackupVar.FileImage != NULL && | |
| HBufferImageBackupVar.FileImage->FileName != NULL && | |
| StrCmp (HMainEditor.BufferImage->FileImage->FileName, HBufferImageBackupVar.FileImage->FileName) != 0 ) { | |
| NameChange = TRUE; | |
| } | |
| } | |
| if ( HMainEditor.BufferImage->FileImage != NULL && | |
| HBufferImageBackupVar.FileImage != NULL && | |
| HMainEditor.BufferImage->FileImage->ReadOnly != HBufferImageBackupVar.FileImage->ReadOnly ) { | |
| ReadChange = TRUE; | |
| } | |
| // | |
| // to aVOID screen flicker | |
| // the stall value is from experience | |
| // | |
| gBS->Stall (50); | |
| // | |
| // call the components refresh function | |
| // | |
| if (HEditorFirst | |
| || NameChange | |
| || HMainEditor.BufferImage->BufferType != HBufferImageBackupVar.BufferType | |
| || HBufferImageBackupVar.Modified != HMainEditor.BufferImage->Modified | |
| || ReadChange ) { | |
| MainTitleBarRefresh ( | |
| HMainEditor.BufferImage->BufferType == FileTypeFileBuffer&&HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Name:NULL, | |
| HMainEditor.BufferImage->BufferType, | |
| (BOOLEAN)(HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->ReadOnly:FALSE), | |
| HMainEditor.BufferImage->Modified, | |
| HMainEditor.ScreenSize.Column, | |
| HMainEditor.ScreenSize.Row, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Offset:0, | |
| HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Size :0 | |
| ); | |
| HBufferImageRefresh (); | |
| } | |
| if (HEditorFirst | |
| || HBufferImageBackupVar.DisplayPosition.Row != HMainEditor.BufferImage->DisplayPosition.Row | |
| || HBufferImageBackupVar.DisplayPosition.Column != HMainEditor.BufferImage->DisplayPosition.Column | |
| || StatusBarGetRefresh()) { | |
| StatusBarRefresh ( | |
| HEditorFirst, | |
| HMainEditor.ScreenSize.Row, | |
| HMainEditor.ScreenSize.Column, | |
| (UINTN)(-1), | |
| (UINTN)(-1), | |
| FALSE | |
| ); | |
| HBufferImageRefresh (); | |
| } | |
| if (HEditorFirst) { | |
| HBufferImageRefresh (); | |
| } | |
| // | |
| // EditorFirst is now set to FALSE | |
| // | |
| HEditorFirst = FALSE; | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Handle the mouse input. | |
| @param[in] MouseState The current mouse state. | |
| @param[out] BeforeLeftButtonDown helps with selections. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| @retval EFI_NOT_FOUND The disk was not found. | |
| **/ | |
| EFI_STATUS | |
| HMainEditorHandleMouseInput ( | |
| IN EFI_SIMPLE_POINTER_STATE MouseState, | |
| OUT BOOLEAN *BeforeLeftButtonDown | |
| ) | |
| { | |
| INT32 TextX; | |
| INT32 TextY; | |
| UINTN FRow; | |
| UINTN FCol; | |
| BOOLEAN HighBits; | |
| LIST_ENTRY *Link; | |
| HEFI_EDITOR_LINE *Line; | |
| UINTN Index; | |
| BOOLEAN Action; | |
| Action = FALSE; | |
| // | |
| // have mouse movement | |
| // | |
| if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) { | |
| // | |
| // handle | |
| // | |
| TextX = HGetTextX (MouseState.RelativeMovementX); | |
| TextY = HGetTextY (MouseState.RelativeMovementY); | |
| HBufferImageAdjustMousePosition (TextX, TextY); | |
| Action = TRUE; | |
| } | |
| if (MouseState.LeftButton) { | |
| HighBits = HBufferImageIsAtHighBits ( | |
| HMainEditor.BufferImage->MousePosition.Column, | |
| &FCol | |
| ); | |
| // | |
| // not at an movable place | |
| // | |
| if (FCol == 0) { | |
| // | |
| // now just move mouse pointer to legal position | |
| // | |
| // | |
| // move mouse position to legal position | |
| // | |
| HMainEditor.BufferImage->MousePosition.Column -= 10; | |
| if (HMainEditor.BufferImage->MousePosition.Column > 24) { | |
| HMainEditor.BufferImage->MousePosition.Column--; | |
| FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1; | |
| } else { | |
| if (HMainEditor.BufferImage->MousePosition.Column < 24) { | |
| FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1; | |
| } else { | |
| // | |
| // == 24 | |
| // | |
| FCol = 9; | |
| } | |
| } | |
| HighBits = TRUE; | |
| } | |
| FRow = HMainEditor.BufferImage->BufferPosition.Row + | |
| HMainEditor.BufferImage->MousePosition.Row - | |
| HMainEditor.BufferImage->DisplayPosition.Row; | |
| if (HMainEditor.BufferImage->NumLines < FRow) { | |
| // | |
| // dragging | |
| // | |
| // | |
| // now just move mouse pointer to legal position | |
| // | |
| FRow = HMainEditor.BufferImage->NumLines; | |
| HighBits = TRUE; | |
| } | |
| Link = HMainEditor.BufferImage->ListHead->ForwardLink; | |
| for (Index = 0; Index < FRow - 1; Index++) { | |
| Link = Link->ForwardLink; | |
| } | |
| Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); | |
| // | |
| // dragging | |
| // | |
| // | |
| // now just move mouse pointer to legal position | |
| // | |
| if (FCol > Line->Size) { | |
| if (*BeforeLeftButtonDown) { | |
| HighBits = FALSE; | |
| if (Line->Size == 0) { | |
| if (FRow > 1) { | |
| FRow--; | |
| FCol = 16; | |
| } else { | |
| FRow = 1; | |
| FCol = 1; | |
| } | |
| } else { | |
| FCol = Line->Size; | |
| } | |
| } else { | |
| FCol = Line->Size + 1; | |
| HighBits = TRUE; | |
| } | |
| } | |
| HBufferImageMovePosition (FRow, FCol, HighBits); | |
| HMainEditor.BufferImage->MousePosition.Row = HMainEditor.BufferImage->DisplayPosition.Row; | |
| HMainEditor.BufferImage->MousePosition.Column = HMainEditor.BufferImage->DisplayPosition.Column; | |
| *BeforeLeftButtonDown = TRUE; | |
| Action = TRUE; | |
| } else { | |
| // | |
| // else of if LButton | |
| // | |
| // release LButton | |
| // | |
| if (*BeforeLeftButtonDown) { | |
| Action = TRUE; | |
| } | |
| // | |
| // mouse up | |
| // | |
| *BeforeLeftButtonDown = FALSE; | |
| } | |
| if (Action) { | |
| return EFI_SUCCESS; | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| /** | |
| Handle user key input. will route it to other components handle function. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation occured. | |
| @retval EFI_LOAD_ERROR A load error occured. | |
| **/ | |
| EFI_STATUS | |
| HMainEditorKeyInput ( | |
| VOID | |
| ) | |
| { | |
| EFI_INPUT_KEY Key; | |
| EFI_STATUS Status; | |
| EFI_SIMPLE_POINTER_STATE MouseState; | |
| BOOLEAN LengthChange; | |
| UINTN Size; | |
| UINTN OldSize; | |
| BOOLEAN BeforeMouseIsDown; | |
| BOOLEAN MouseIsDown; | |
| BOOLEAN FirstDown; | |
| BOOLEAN MouseDrag; | |
| UINTN FRow; | |
| UINTN FCol; | |
| UINTN SelectStartBackup; | |
| UINTN SelectEndBackup; | |
| // | |
| // variable initialization | |
| // | |
| OldSize = 0; | |
| FRow = 0; | |
| FCol = 0; | |
| LengthChange = FALSE; | |
| MouseIsDown = FALSE; | |
| FirstDown = FALSE; | |
| MouseDrag = FALSE; | |
| do { | |
| Status = EFI_SUCCESS; | |
| HEditorMouseAction = FALSE; | |
| // | |
| // backup some key elements, so that can aVOID some refresh work | |
| // | |
| HMainEditorBackup (); | |
| // | |
| // wait for user key input | |
| // | |
| // | |
| // change priority of checking mouse/keyboard activity dynamically | |
| // so prevent starvation of keyboard. | |
| // if last time, mouse moves then this time check keyboard | |
| // | |
| if (HMainEditor.MouseSupported) { | |
| Status = HMainEditor.MouseInterface->GetState ( | |
| HMainEditor.MouseInterface, | |
| &MouseState | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| BeforeMouseIsDown = MouseIsDown; | |
| Status = HMainEditorHandleMouseInput (MouseState, &MouseIsDown); | |
| if (!EFI_ERROR (Status)) { | |
| if (!BeforeMouseIsDown) { | |
| // | |
| // mouse down | |
| // | |
| if (MouseIsDown) { | |
| FRow = HBufferImage.BufferPosition.Row; | |
| FCol = HBufferImage.BufferPosition.Column; | |
| SelectStartBackup = HMainEditor.SelectStart; | |
| SelectEndBackup = HMainEditor.SelectEnd; | |
| FirstDown = TRUE; | |
| } | |
| } else { | |
| SelectStartBackup = HMainEditor.SelectStart; | |
| SelectEndBackup = HMainEditor.SelectEnd; | |
| // | |
| // begin to drag | |
| // | |
| if (MouseIsDown) { | |
| if (FirstDown) { | |
| if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) { | |
| HMainEditor.SelectStart = 0; | |
| HMainEditor.SelectEnd = 0; | |
| HMainEditor.SelectStart = (FRow - 1) * 0x10 + FCol; | |
| MouseDrag = TRUE; | |
| FirstDown = FALSE; | |
| } | |
| } else { | |
| if (( | |
| (HBufferImage.BufferPosition.Row - 1) * | |
| 0x10 + | |
| HBufferImage.BufferPosition.Column | |
| ) >= HMainEditor.SelectStart | |
| ) { | |
| HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) * | |
| 0x10 + | |
| HBufferImage.BufferPosition.Column; | |
| } else { | |
| HMainEditor.SelectEnd = 0; | |
| } | |
| } | |
| // | |
| // end of if RelativeX/Y | |
| // | |
| } else { | |
| // | |
| // mouse is up | |
| // | |
| if (MouseDrag) { | |
| if (HBufferImageGetTotalSize () == 0) { | |
| HMainEditor.SelectStart = 0; | |
| HMainEditor.SelectEnd = 0; | |
| FirstDown = FALSE; | |
| MouseDrag = FALSE; | |
| } | |
| if (( | |
| (HBufferImage.BufferPosition.Row - 1) * | |
| 0x10 + | |
| HBufferImage.BufferPosition.Column | |
| ) >= HMainEditor.SelectStart | |
| ) { | |
| HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) * | |
| 0x10 + | |
| HBufferImage.BufferPosition.Column; | |
| } else { | |
| HMainEditor.SelectEnd = 0; | |
| } | |
| if (HMainEditor.SelectEnd == 0) { | |
| HMainEditor.SelectStart = 0; | |
| } | |
| } | |
| FirstDown = FALSE; | |
| MouseDrag = FALSE; | |
| } | |
| if (SelectStartBackup != HMainEditor.SelectStart || SelectEndBackup != HMainEditor.SelectEnd) { | |
| if ((SelectStartBackup - 1) / 0x10 != (HMainEditor.SelectStart - 1) / 0x10) { | |
| HBufferImageNeedRefresh = TRUE; | |
| } else { | |
| if ((SelectEndBackup - 1) / 0x10 != (HMainEditor.SelectEnd - 1) / 0x10) { | |
| HBufferImageNeedRefresh = TRUE; | |
| } else { | |
| HBufferImageOnlyLineNeedRefresh = TRUE; | |
| } | |
| } | |
| } | |
| } | |
| HEditorMouseAction = TRUE; | |
| HBufferImageMouseNeedRefresh = TRUE; | |
| } else if (Status == EFI_LOAD_ERROR) { | |
| StatusBarSetStatusString (L"Invalid Mouse Movement "); | |
| } | |
| } | |
| } | |
| Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); | |
| if (!EFI_ERROR (Status)) { | |
| // | |
| // dispatch to different components' key handling function | |
| // so not everywhere has to set this variable | |
| // | |
| HBufferImageMouseNeedRefresh = TRUE; | |
| // | |
| // clear previous status string | |
| // | |
| StatusBarSetRefresh(); | |
| if (EFI_SUCCESS == MenuBarDispatchControlHotKey(&Key)) { | |
| Status = EFI_SUCCESS; | |
| } else if (Key.ScanCode == SCAN_NULL) { | |
| Status = HBufferImageHandleInput (&Key); | |
| } else if (((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) { | |
| Status = HBufferImageHandleInput (&Key); | |
| } else if (((Key.ScanCode >= SCAN_F1) && Key.ScanCode <= (SCAN_F12))) { | |
| Status = MenuBarDispatchFunctionKey (&Key); | |
| } else { | |
| StatusBarSetStatusString (L"Unknown Command"); | |
| HBufferImageMouseNeedRefresh = FALSE; | |
| } | |
| if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) { | |
| // | |
| // not already has some error status | |
| // | |
| if (StrCmp (L"", StatusBarGetString()) == 0) { | |
| StatusBarSetStatusString (L"Disk Error. Try Again"); | |
| } | |
| } | |
| } | |
| // | |
| // decide if has to set length warning | |
| // | |
| if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) { | |
| LengthChange = FALSE; | |
| } else { | |
| // | |
| // still the old buffer | |
| // | |
| if (HBufferImage.BufferType != FileTypeFileBuffer) { | |
| Size = HBufferImageGetTotalSize (); | |
| switch (HBufferImage.BufferType) { | |
| case FileTypeDiskBuffer: | |
| OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage->BlockSize; | |
| break; | |
| case FileTypeMemBuffer: | |
| OldSize = HBufferImage.MemImage->Size; | |
| break; | |
| default: | |
| OldSize = 0; | |
| break; | |
| } | |
| if (!LengthChange) { | |
| if (OldSize != Size) { | |
| StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be changed"); | |
| } | |
| } | |
| if (OldSize != Size) { | |
| LengthChange = TRUE; | |
| } else { | |
| LengthChange = FALSE; | |
| } | |
| } | |
| } | |
| // | |
| // after handling, refresh editor | |
| // | |
| HMainEditorRefresh (); | |
| } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit); | |
| return Status; | |
| } | |
| /** | |
| Backup function for MainEditor. | |
| **/ | |
| VOID | |
| HMainEditorBackup ( | |
| VOID | |
| ) | |
| { | |
| HMainEditorBackupVar.SelectStart = HMainEditor.SelectStart; | |
| HMainEditorBackupVar.SelectEnd = HMainEditor.SelectEnd; | |
| HBufferImageBackup (); | |
| } |