/** @file Defines the Main Editor data type - - Global variables - Instances of the other objects of the editor - Main Interfaces Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #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 }, NULL, 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_KEY_DATA KeyData; EFI_STATUS Status; UINTN EventIndex; // // 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 // while (TRUE) { Status = gBS->WaitForEvent (1, &HMainEditor.TextInputEx->WaitForKeyEx, &EventIndex); if (EFI_ERROR (Status) || (EventIndex != 0)) { continue; } Status = HMainEditor.TextInputEx->ReadKeyStrokeEx (HMainEditor.TextInputEx, &KeyData); if (EFI_ERROR (Status)) { continue; } if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID)) { // // For consoles that don't support/report shift state, // CTRL+W is translated to L'W' - L'A' + 1. // if (KeyData.Key.UnicodeChar == L'W' - L'A' + 1) { break; } } else if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) && ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) && ((KeyData.KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) == 0)) { // // For consoles that supports/reports shift state, // make sure that only CONTROL shift key is pressed. // if ((KeyData.Key.UnicodeChar == 'w') || (KeyData.Key.UnicodeChar == 'W')) { break; } } } // update screen with 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. @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 occurred. @retval EFI_LOAD_ERROR A load error occurred. @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 occurred. **/ 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 TextInEx in System Table ConsoleInHandle // Per UEFI Spec, TextInEx is required for a console capable platform. // Status = gBS->HandleProtocol ( gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID**)&HMainEditor.TextInputEx ); if (EFI_ERROR (Status)) { return Status; } // // Find mouse in System Table ConsoleInHandle // Status = gBS->HandleProtocol ( gST->ConsoleInHandle, &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 (HMainEditor.TextInputEx); 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 occurred. **/ 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 occurred. @retval EFI_LOAD_ERROR A load error occurred. @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 occurred. @retval EFI_LOAD_ERROR A load error occurred. **/ EFI_STATUS HMainEditorKeyInput ( VOID ) { EFI_KEY_DATA KeyData; EFI_STATUS Status; EFI_SIMPLE_POINTER_STATE MouseState; BOOLEAN NoShiftState; 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 "); } } } // // CheckEvent() returns Success when non-partial key is pressed. // Status = gBS->CheckEvent (HMainEditor.TextInputEx->WaitForKeyEx); if (!EFI_ERROR (Status)) { Status = HMainEditor.TextInputEx->ReadKeyStrokeEx (HMainEditor.TextInputEx, &KeyData); 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(); // // NoShiftState: TRUE when no shift key is pressed. // NoShiftState = ((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID); // // dispatch to different components' key handling function // if (EFI_SUCCESS == MenuBarDispatchControlHotKey(&KeyData)) { Status = EFI_SUCCESS; } else if (NoShiftState && KeyData.Key.ScanCode == SCAN_NULL) { Status = HBufferImageHandleInput (&KeyData.Key); } else if (NoShiftState && ((KeyData.Key.ScanCode >= SCAN_UP) && (KeyData.Key.ScanCode <= SCAN_PAGE_DOWN))) { Status = HBufferImageHandleInput (&KeyData.Key); } else if (NoShiftState && ((KeyData.Key.ScanCode >= SCAN_F1) && KeyData.Key.ScanCode <= SCAN_F12)) { Status = MenuBarDispatchFunctionKey (&KeyData.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 (); }