/** @file Defines HBufferImage - the view of the file that is visible at any point, as well as the event handlers for editing the file Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "HexEditor.h" extern EFI_HANDLE HImageHandleBackup; extern HEFI_EDITOR_FILE_IMAGE HFileImage; extern HEFI_EDITOR_DISK_IMAGE HDiskImage; extern HEFI_EDITOR_MEM_IMAGE HMemImage; extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar; extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar; extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar; extern BOOLEAN HEditorMouseAction; extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar; HEFI_EDITOR_BUFFER_IMAGE HBufferImage; HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar; // // for basic initialization of HBufferImage // HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = { NULL, NULL, 0, NULL, { 0, 0 }, { 0, 0 }, { 0, 0 }, 0, TRUE, FALSE, FileTypeNone, NULL, NULL, NULL }; // // the whole edit area needs to be refreshed // BOOLEAN HBufferImageNeedRefresh; // // only the current line in edit area needs to be refresh // BOOLEAN HBufferImageOnlyLineNeedRefresh; BOOLEAN HBufferImageMouseNeedRefresh; /** Initialization function for HBufferImage @retval EFI_SUCCESS The operation was successful. @retval EFI_LOAD_ERROR A load error occurred. **/ EFI_STATUS HBufferImageInit ( VOID ) { EFI_STATUS Status; // // basically initialize the HBufferImage // CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage)); // // INIT listhead // HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY)); if (HBufferImage.ListHead == NULL) { return EFI_LOAD_ERROR; } InitializeListHead (HBufferImage.ListHead); HBufferImage.DisplayPosition.Row = 2; HBufferImage.DisplayPosition.Column = 10; HBufferImage.MousePosition.Row = 2; HBufferImage.MousePosition.Column = 10; HBufferImage.FileImage = &HFileImage; HBufferImage.DiskImage = &HDiskImage; HBufferImage.MemImage = &HMemImage; HBufferImageNeedRefresh = FALSE; HBufferImageOnlyLineNeedRefresh = FALSE; HBufferImageMouseNeedRefresh = FALSE; HBufferImageBackupVar.FileImage = &HFileImageBackupVar; HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar; HBufferImageBackupVar.MemImage = &HMemImageBackupVar; Status = HFileImageInit (); if (EFI_ERROR (Status)) { return EFI_LOAD_ERROR; } Status = HDiskImageInit (); if (EFI_ERROR (Status)) { return EFI_LOAD_ERROR; } Status = HMemImageInit (); if (EFI_ERROR (Status)) { return EFI_LOAD_ERROR; } return EFI_SUCCESS; } /** Backup function for HBufferImage. Only a few fields need to be backup. This is for making the file buffer refresh as few as possible. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageBackup ( VOID ) { HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition; HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition; HBufferImageBackupVar.Modified = HBufferImage.Modified; HBufferImageBackupVar.BufferType = HBufferImage.BufferType; HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow; HBufferImageBackupVar.HighBits = HBufferImage.HighBits; // // three kinds of buffer supported // file buffer // disk buffer // memory buffer // switch (HBufferImage.BufferType) { case FileTypeFileBuffer: HFileImageBackup (); break; case FileTypeDiskBuffer: HDiskImageBackup (); break; case FileTypeMemBuffer: HMemImageBackup (); break; default: break; } return EFI_SUCCESS; } /** Free all the lines in HBufferImage. Fields affected: Lines CurrentLine NumLines ListHead @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageFreeLines ( VOID ) { HFreeLines (HBufferImage.ListHead, HBufferImage.Lines); HBufferImage.Lines = NULL; HBufferImage.CurrentLine = NULL; HBufferImage.NumLines = 0; return EFI_SUCCESS; } /** Cleanup function for HBufferImage @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageCleanup ( VOID ) { EFI_STATUS Status; // // free all the lines // Status = HBufferImageFreeLines (); SHELL_FREE_NON_NULL (HBufferImage.ListHead); HBufferImage.ListHead = NULL; HFileImageCleanup (); HDiskImageCleanup (); return Status; } /** Print Line on Row @param[in] Line The lline to print. @param[in] Row The row on screen ( begin from 1 ). @param[in] FRow The FRow. @param[in] Orig The original color. @param[in] New The color to print with. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImagePrintLine ( IN HEFI_EDITOR_LINE *Line, IN UINTN Row, IN UINTN FRow, IN HEFI_EDITOR_COLOR_UNION Orig, IN HEFI_EDITOR_COLOR_UNION New ) { UINTN Index; UINTN Pos; BOOLEAN Selected; BOOLEAN BeNewColor; UINTN RowStart; UINTN RowEnd; UINTN ColStart; UINTN ColEnd; // // variable initialization // ColStart = 0; ColEnd = 0; Selected = FALSE; // // print the selected area in opposite color // if ((HMainEditor.SelectStart != 0) && (HMainEditor.SelectEnd != 0)) { RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1; RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1; ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1; ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1; if ((FRow >= RowStart) && (FRow <= RowEnd)) { Selected = TRUE; } if (FRow > RowStart) { ColStart = 1; } if (FRow < RowEnd) { ColEnd = 0x10; } } if (!HEditorMouseAction) { ShellPrintEx ( 0, (INT32)Row - 1, L"%8X ", ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10 ); } for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) { BeNewColor = FALSE; if (Selected) { if ((Index + 1 >= ColStart) && (Index + 1 <= ColEnd)) { BeNewColor = TRUE; } } if (BeNewColor) { gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); } else { gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); } Pos = 10 + (Index * 3); if (Line->Buffer[Index] < 0x10) { ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0"); Pos++; } if (Index < 0x07) { ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]); } else { ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]); } } gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); while (Index < 0x08) { Pos = 10 + (Index * 3); ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); Index++; } while (Index < 0x10 && Index < Line->Size) { BeNewColor = FALSE; if (Selected) { if ((Index + 1 >= ColStart) && (Index + 1 <= ColEnd)) { BeNewColor = TRUE; } } if (BeNewColor) { gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); } else { gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); } Pos = 10 + (Index * 3) + 1; if (Line->Buffer[Index] < 0x10) { ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0"); Pos++; } ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]); Index++; } gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); while (Index < 0x10) { Pos = 10 + (Index * 3) + 1; ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); Index++; } // // restore the original color // gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); // // PRINT the buffer content // if (!HEditorMouseAction) { for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) { Pos = ASCII_POSITION + Index; // // learned from shelle.h -- IsValidChar // if (Line->Buffer[Index] >= L' ') { ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16)Line->Buffer[Index]); } else { ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.'); } } while (Index < 0x10) { Pos = ASCII_POSITION + Index; ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); Index++; } } // // restore the abundant blank in hex edit area to original color // if (Selected) { if (ColEnd <= 7) { Pos = 10 + (ColEnd - 1) * 3 + 2; ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); } else if (ColEnd == 8) { Pos = 10 + (ColEnd - 1) * 3 + 2; ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); } else { Pos = 10 + (ColEnd - 1) * 3 + 3; ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); } } return EFI_SUCCESS; } /** Function to decide if a column number is stored in the high bits. @param[in] Column The column to examine. @param[out] FCol The actual column number. @retval TRUE The actual column was in high bits and is now in FCol. @retval FALSE There was not a column number in the high bits. **/ BOOLEAN HBufferImageIsAtHighBits ( IN UINTN Column, OUT UINTN *FCol ) { Column -= 10; // // NOW AFTER THE SUB, Column start from 0 // 23 AND 24 ARE BOTH BLANK // if (Column == 24) { *FCol = 0; return FALSE; } if (Column > 24) { Column--; } *FCol = (Column / 3) + 1; if (Column % 3 == 0) { return TRUE; } if ((Column % 3 == 2)) { *FCol = 0; } return FALSE; } /** Decide if a point is in the already selected area. @param[in] MouseRow The row of the point to test. @param[in] MouseCol The col of the point to test. @retval TRUE The point is in the selected area. @retval FALSE The point is not in the selected area. **/ BOOLEAN HBufferImageIsInSelectedArea ( IN UINTN MouseRow, IN UINTN MouseCol ) { UINTN FRow; UINTN RowStart; UINTN RowEnd; UINTN ColStart; UINTN ColEnd; UINTN MouseColStart; UINTN MouseColEnd; // // judge mouse position whether is in selected area // // // not select // if ((HMainEditor.SelectStart == 0) || (HMainEditor.SelectEnd == 0)) { return FALSE; } // // calculate the select area // RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1; RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1; ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1; ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1; FRow = HBufferImage.LowVisibleRow + MouseRow - 2; if ((FRow < RowStart) || (FRow > RowEnd)) { return FALSE; } if (FRow > RowStart) { ColStart = 1; } if (FRow < RowEnd) { ColEnd = 0x10; } MouseColStart = 10 + (ColStart - 1) * 3; if (ColStart > 8) { MouseColStart++; } MouseColEnd = 10 + (ColEnd - 1) * 3 + 1; if (ColEnd > 8) { MouseColEnd++; } if ((MouseCol < MouseColStart) || (MouseCol > MouseColEnd)) { return FALSE; } return TRUE; } /** Set mouse position according to HBufferImage.MousePosition. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageRestoreMousePosition ( VOID ) { HEFI_EDITOR_COLOR_UNION Orig; HEFI_EDITOR_COLOR_UNION New; UINTN FRow; UINTN FColumn; BOOLEAN HasCharacter; HEFI_EDITOR_LINE *CurrentLine; HEFI_EDITOR_LINE *Line; UINT8 Value; BOOLEAN HighBits; Line = NULL; if (HMainEditor.MouseSupported) { if (HBufferImageMouseNeedRefresh) { HBufferImageMouseNeedRefresh = FALSE; // // if mouse position not moved and only mouse action // so do not need to refresh mouse position // if (( (HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row) && (HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column) ) && HEditorMouseAction ) { return EFI_SUCCESS; } // // backup the old screen attributes // Orig = HMainEditor.ColorAttributes; New.Data = 0; New.Colors.Foreground = Orig.Colors.Background & 0xF; New.Colors.Background = Orig.Colors.Foreground & 0x7; // // if in selected area, // so do not need to refresh mouse // if (!HBufferImageIsInSelectedArea ( HBufferImageBackupVar.MousePosition.Row, HBufferImageBackupVar.MousePosition.Column )) { gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); } else { gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); } // // clear the old mouse position // FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2; HighBits = HBufferImageIsAtHighBits ( HBufferImageBackupVar.MousePosition.Column, &FColumn ); HasCharacter = TRUE; if ((FRow > HBufferImage.NumLines) || (FColumn == 0)) { HasCharacter = FALSE; } else { CurrentLine = HBufferImage.CurrentLine; Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row); if ((Line == NULL) || (FColumn > Line->Size)) { HasCharacter = FALSE; } HBufferImage.CurrentLine = CurrentLine; } ShellPrintEx ( (INT32)HBufferImageBackupVar.MousePosition.Column - 1, (INT32)HBufferImageBackupVar.MousePosition.Row - 1, L" " ); if (HasCharacter) { if (HighBits) { Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf0); Value = (UINT8)(Value >> 4); } else { Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf); } ShellPrintEx ( (INT32)HBufferImageBackupVar.MousePosition.Column - 1, (INT32)HBufferImageBackupVar.MousePosition.Row - 1, L"%x", Value ); } if (!HBufferImageIsInSelectedArea ( HBufferImage.MousePosition.Row, HBufferImage.MousePosition.Column )) { gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); } else { gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); } // // clear the old mouse position // FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2; HighBits = HBufferImageIsAtHighBits ( HBufferImage.MousePosition.Column, &FColumn ); HasCharacter = TRUE; if ((FRow > HBufferImage.NumLines) || (FColumn == 0)) { HasCharacter = FALSE; } else { CurrentLine = HBufferImage.CurrentLine; Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row); if ((Line == NULL) || (FColumn > Line->Size)) { HasCharacter = FALSE; } HBufferImage.CurrentLine = CurrentLine; } ShellPrintEx ( (INT32)HBufferImage.MousePosition.Column - 1, (INT32)HBufferImage.MousePosition.Row - 1, L" " ); if (HasCharacter) { if (HighBits) { Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf0); Value = (UINT8)(Value >> 4); } else { Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf); } ShellPrintEx ( (INT32)HBufferImage.MousePosition.Column - 1, (INT32)HBufferImage.MousePosition.Row - 1, L"%x", Value ); } // // end of HasCharacter // gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); } // // end of MouseNeedRefresh // } // // end of MouseSupported // return EFI_SUCCESS; } /** Set cursor position according to HBufferImage.DisplayPosition. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageRestorePosition ( VOID ) { // // set cursor position // gST->ConOut->SetCursorPosition ( gST->ConOut, HBufferImage.DisplayPosition.Column - 1, HBufferImage.DisplayPosition.Row - 1 ); return EFI_SUCCESS; } /** Refresh function for HBufferImage. @retval EFI_SUCCESS The operation was successful. @retval EFI_LOAD_ERROR A Load error occurred. **/ EFI_STATUS HBufferImageRefresh ( VOID ) { LIST_ENTRY *Link; HEFI_EDITOR_LINE *Line; UINTN Row; HEFI_EDITOR_COLOR_UNION Orig; HEFI_EDITOR_COLOR_UNION New; UINTN StartRow; UINTN EndRow; UINTN FStartRow; UINTN Tmp; Orig = HMainEditor.ColorAttributes; New.Data = 0; New.Colors.Foreground = Orig.Colors.Background; New.Colors.Background = Orig.Colors.Foreground; // // if it's the first time after editor launch, so should refresh // if (HEditorFirst == FALSE) { // // no definite required refresh // and file position displayed on screen has not been changed // if (!HBufferImageNeedRefresh && !HBufferImageOnlyLineNeedRefresh && (HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) ) { HBufferImageRestoreMousePosition (); HBufferImageRestorePosition (); return EFI_SUCCESS; } } gST->ConOut->EnableCursor (gST->ConOut, FALSE); // // only need to refresh current line // if (HBufferImageOnlyLineNeedRefresh && (HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow)) { HBufferImagePrintLine ( HBufferImage.CurrentLine, HBufferImage.DisplayPosition.Row, HBufferImage.BufferPosition.Row, Orig, New ); } else { // // the whole edit area need refresh // if (HEditorMouseAction && (HMainEditor.SelectStart != 0) && (HMainEditor.SelectEnd != 0)) { if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) { if ((HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart) && (HMainEditorBackupVar.SelectStart != 0)) { StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1; } else { StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1; } } else { StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1; } if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) { EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1; } else { EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1; } // // swap // if (StartRow > EndRow) { Tmp = StartRow; StartRow = EndRow; EndRow = Tmp; } FStartRow = StartRow; StartRow = 2 + StartRow - HBufferImage.LowVisibleRow; EndRow = 2 + EndRow - HBufferImage.LowVisibleRow; } else { // // not mouse selection actions // FStartRow = HBufferImage.LowVisibleRow; StartRow = 2; EndRow = (HMainEditor.ScreenSize.Row - 1); } // // no line // if (HBufferImage.Lines == NULL) { HBufferImageRestoreMousePosition (); HBufferImageRestorePosition (); gST->ConOut->EnableCursor (gST->ConOut, TRUE); return EFI_SUCCESS; } // // get the first line that will be displayed // Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row); if (Line == NULL) { gST->ConOut->EnableCursor (gST->ConOut, TRUE); return EFI_LOAD_ERROR; } Link = &(Line->Link); Row = StartRow; do { Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); // // print line at row // HBufferImagePrintLine ( Line, Row, HBufferImage.LowVisibleRow + Row - 2, Orig, New ); Link = Link->ForwardLink; Row++; } while (Link != HBufferImage.ListHead && Row <= EndRow); while (Row <= EndRow) { EditorClearLine (Row, HMainEditor.ScreenSize.Column, HMainEditor.ScreenSize.Row); Row++; } // // while not file end and not screen full // } HBufferImageRestoreMousePosition (); HBufferImageRestorePosition (); HBufferImageNeedRefresh = FALSE; HBufferImageOnlyLineNeedRefresh = FALSE; gST->ConOut->EnableCursor (gST->ConOut, TRUE); return EFI_SUCCESS; } /** Read an image into a buffer friom a source. @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer. @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer. @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer. @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer. @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer. @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer. @param[in] BufferType The type of buffer to save. IGNORED. @param[in] Recover TRUE for recovermode, FALSE otherwise. @return EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageRead ( IN CONST CHAR16 *FileName, IN CONST CHAR16 *DiskName, IN UINTN DiskOffset, IN UINTN DiskSize, IN UINTN MemOffset, IN UINTN MemSize, IN EDIT_FILE_TYPE BufferType, IN BOOLEAN Recover ) { EFI_STATUS Status; EDIT_FILE_TYPE BufferTypeBackup; // // variable initialization // Status = EFI_SUCCESS; HBufferImage.BufferType = BufferType; // // three types of buffer supported // file buffer // disk buffer // memory buffer // BufferTypeBackup = HBufferImage.BufferType; switch (BufferType) { case FileTypeFileBuffer: Status = HFileImageRead (FileName, Recover); break; case FileTypeDiskBuffer: Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover); break; case FileTypeMemBuffer: Status = HMemImageRead (MemOffset, MemSize, Recover); break; default: Status = EFI_NOT_FOUND; break; } if (EFI_ERROR (Status)) { HBufferImage.BufferType = BufferTypeBackup; } return Status; } /** Save the current image. @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer. @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer. @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer. @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer. @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer. @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer. @param[in] BufferType The type of buffer to save. IGNORED. @return EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageSave ( IN CHAR16 *FileName, IN CHAR16 *DiskName, IN UINTN DiskOffset, IN UINTN DiskSize, IN UINTN MemOffset, IN UINTN MemSize, IN EDIT_FILE_TYPE BufferType ) { EFI_STATUS Status; EDIT_FILE_TYPE BufferTypeBackup; // // variable initialization // Status = EFI_SUCCESS; BufferTypeBackup = HBufferImage.BufferType; switch (HBufferImage.BufferType) { // // file buffer // case FileTypeFileBuffer: Status = HFileImageSave (FileName); break; // // disk buffer // case FileTypeDiskBuffer: Status = HDiskImageSave (DiskName, DiskOffset, DiskSize); break; // // memory buffer // case FileTypeMemBuffer: Status = HMemImageSave (MemOffset, MemSize); break; default: Status = EFI_NOT_FOUND; break; } if (EFI_ERROR (Status)) { HBufferImage.BufferType = BufferTypeBackup; } return Status; } /** Create a new line and append it to the line list. Fields affected: NumLines Lines @retval NULL create line failed. @return the line created. **/ HEFI_EDITOR_LINE * HBufferImageCreateLine ( VOID ) { HEFI_EDITOR_LINE *Line; // // allocate for line structure // Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE)); if (Line == NULL) { return NULL; } Line->Signature = EFI_EDITOR_LINE_LIST; Line->Size = 0; HBufferImage.NumLines++; // // insert to line list // InsertTailList (HBufferImage.ListHead, &Line->Link); if (HBufferImage.Lines == NULL) { HBufferImage.Lines = CR ( HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST ); } return Line; } /** Free the current image. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageFree ( VOID ) { // // free all lines // HBufferImageFreeLines (); return EFI_SUCCESS; } /** change char to int value based on Hex. @param[in] Char The input char. @return The character's index value. @retval -1 The operation failed. **/ INTN HBufferImageCharToHex ( IN CHAR16 Char ) { // // change the character to hex // if ((Char >= L'0') && (Char <= L'9')) { return (Char - L'0'); } if ((Char >= L'a') && (Char <= L'f')) { return (Char - L'a' + 10); } if ((Char >= L'A') && (Char <= L'F')) { return (Char - L'A' + 10); } return -1; } /** Add character. @param[in] Char -- input char. @retval EFI_SUCCESS The operation was successful. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. **/ EFI_STATUS HBufferImageAddChar ( IN CHAR16 Char ) { HEFI_EDITOR_LINE *Line; HEFI_EDITOR_LINE *NewLine; INTN Value; UINT8 Old; UINTN FRow; UINTN FCol; BOOLEAN High; Value = HBufferImageCharToHex (Char); // // invalid input // if (Value == -1) { return EFI_SUCCESS; } Line = HBufferImage.CurrentLine; FRow = HBufferImage.BufferPosition.Row; FCol = HBufferImage.BufferPosition.Column; High = HBufferImage.HighBits; // // only needs to refresh current line // HBufferImageOnlyLineNeedRefresh = TRUE; // // not a full line and beyond the last character // if (FCol > Line->Size) { // // cursor always at high 4 bits // and always put input to the low 4 bits // Line->Buffer[Line->Size] = (UINT8)Value; Line->Size++; High = FALSE; } else { Old = Line->Buffer[FCol - 1]; // // always put the input to the low 4 bits // Old = (UINT8)(Old & 0x0f); Old = (UINT8)(Old << 4); Old = (UINT8)(Value + Old); Line->Buffer[FCol - 1] = Old; // // at the low 4 bits of the last character of a full line // so if no next line, need to create a new line // if (!High && (FCol == 0x10)) { HBufferImageOnlyLineNeedRefresh = FALSE; HBufferImageNeedRefresh = TRUE; if (Line->Link.ForwardLink == HBufferImage.ListHead) { // // last line // // create a new line // NewLine = HBufferImageCreateLine (); if (NewLine == NULL) { return EFI_OUT_OF_RESOURCES; } // // end of NULL // } // // end of == ListHead // } // // end of == 0x10 // // if already at end of this line, scroll it to the start of next line // if ((FCol == 0x10) && !High) { // // definitely has next line // FRow++; FCol = 1; High = TRUE; } else { // // if not at end of this line, just move to next column // if (!High) { FCol++; } if (High) { High = FALSE; } else { High = TRUE; } } // // end of ==FALSE // } // // move cursor to right // HBufferImageMovePosition (FRow, FCol, High); if (!HBufferImage.Modified) { HBufferImage.Modified = TRUE; } return EFI_SUCCESS; } /** Delete the previous character. @retval EFI_SUCCESS The operationw as successful. **/ EFI_STATUS HBufferImageDoBackspace ( VOID ) { HEFI_EDITOR_LINE *Line; UINTN FileColumn; UINTN FPos; BOOLEAN LastLine; // // variable initialization // LastLine = FALSE; // // already the first character // if ((HBufferImage.BufferPosition.Row == 1) && (HBufferImage.BufferPosition.Column == 1)) { return EFI_SUCCESS; } FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1; FileColumn = HBufferImage.BufferPosition.Column; Line = HBufferImage.CurrentLine; LastLine = FALSE; if ((Line->Link.ForwardLink == HBufferImage.ListHead) && (FileColumn > 1)) { LastLine = TRUE; } HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL); // // if is the last line // then only this line need to be refreshed // if (LastLine) { HBufferImageNeedRefresh = FALSE; HBufferImageOnlyLineNeedRefresh = TRUE; } else { HBufferImageNeedRefresh = TRUE; HBufferImageOnlyLineNeedRefresh = FALSE; } if (!HBufferImage.Modified) { HBufferImage.Modified = TRUE; } return EFI_SUCCESS; } /** ASCII key + Backspace + return. @param[in] Char The input char. @retval EFI_SUCCESS The operation was successful. @retval EFI_LOAD_ERROR A load error occurred. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. **/ EFI_STATUS HBufferImageDoCharInput ( IN CHAR16 Char ) { EFI_STATUS Status; Status = EFI_SUCCESS; switch (Char) { case 0: break; case 0x08: Status = HBufferImageDoBackspace (); break; case 0x09: case 0x0a: case 0x0d: // // Tabs, Returns are thought as nothing // break; default: // // DEAL WITH ASCII CHAR, filter out thing like ctrl+f // if ((Char > 127) || (Char < 32)) { Status = StatusBarSetStatusString (L"Unknown Command"); } else { Status = HBufferImageAddChar (Char); } break; } return Status; } /** Check user specified FileRow is above current screen. @param[in] FileRow Row of file position ( start from 1 ). @retval TRUE It is above the current screen. @retval FALSE It is not above the current screen. **/ BOOLEAN HAboveCurrentScreen ( IN UINTN FileRow ) { if (FileRow < HBufferImage.LowVisibleRow) { return TRUE; } return FALSE; } /** Check user specified FileRow is under current screen. @param[in] FileRow Row of file position ( start from 1 ). @retval TRUE It is under the current screen. @retval FALSE It is not under the current screen. **/ BOOLEAN HUnderCurrentScreen ( IN UINTN FileRow ) { if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) { return TRUE; } return FALSE; } /** According to cursor's file position, adjust screen display. @param[in] NewFilePosRow Row of file position ( start from 1 ). @param[in] NewFilePosCol Column of file position ( start from 1 ). @param[in] HighBits Cursor will on high4 bits or low4 bits. **/ VOID HBufferImageMovePosition ( IN UINTN NewFilePosRow, IN UINTN NewFilePosCol, IN BOOLEAN HighBits ) { INTN RowGap; UINTN Abs; BOOLEAN Above; BOOLEAN Under; UINTN NewDisplayCol; // // CALCULATE gap between current file position and new file position // RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row; Under = HUnderCurrentScreen (NewFilePosRow); Above = HAboveCurrentScreen (NewFilePosRow); HBufferImage.HighBits = HighBits; // // if is below current screen // if (Under) { // // display row will be unchanged // HBufferImage.BufferPosition.Row = NewFilePosRow; } else { if (Above) { // // has enough above line, so display row unchanged // not has enough above lines, so the first line is // at the first display line // if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) { HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1; } HBufferImage.BufferPosition.Row = NewFilePosRow; } else { // // in current screen // HBufferImage.BufferPosition.Row = NewFilePosRow; if (RowGap <= 0) { Abs = (UINTN)ABS (RowGap); HBufferImage.DisplayPosition.Row -= Abs; } else { HBufferImage.DisplayPosition.Row += RowGap; } } } HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2); // // always in current screen // HBufferImage.BufferPosition.Column = NewFilePosCol; NewDisplayCol = 10 + (NewFilePosCol - 1) * 3; if (NewFilePosCol > 0x8) { NewDisplayCol++; } if (!HighBits) { NewDisplayCol++; } HBufferImage.DisplayPosition.Column = NewDisplayCol; // // let CurrentLine point to correct line; // HBufferImage.CurrentLine = HMoveCurrentLine (RowGap); } /** Scroll cursor to right. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageScrollRight ( VOID ) { HEFI_EDITOR_LINE *Line; UINTN FRow; UINTN FCol; // // scroll right will always move to the high4 bits of the next character // HBufferImageNeedRefresh = FALSE; HBufferImageOnlyLineNeedRefresh = FALSE; Line = HBufferImage.CurrentLine; FRow = HBufferImage.BufferPosition.Row; FCol = HBufferImage.BufferPosition.Column; // // this line is not full and no next line // if (FCol > Line->Size) { return EFI_SUCCESS; } // // if already at end of this line, scroll it to the start of next line // if (FCol == 0x10) { // // has next line // if (Line->Link.ForwardLink != HBufferImage.ListHead) { FRow++; FCol = 1; } else { return EFI_SUCCESS; } } else { // // if not at end of this line, just move to next column // FCol++; } HBufferImageMovePosition (FRow, FCol, TRUE); return EFI_SUCCESS; } /** Scroll cursor to left. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageScrollLeft ( VOID ) { HEFI_EDITOR_LINE *Line; UINTN FRow; UINTN FCol; HBufferImageNeedRefresh = FALSE; HBufferImageOnlyLineNeedRefresh = FALSE; Line = HBufferImage.CurrentLine; FRow = HBufferImage.BufferPosition.Row; FCol = HBufferImage.BufferPosition.Column; // // if already at start of this line, so move to the end of previous line // if (FCol <= 1) { // // has previous line // if (Line->Link.BackLink != HBufferImage.ListHead) { FRow--; Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); FCol = Line->Size; } else { return EFI_SUCCESS; } } else { // // if not at start of this line, just move to previous column // FCol--; } HBufferImageMovePosition (FRow, FCol, TRUE); return EFI_SUCCESS; } /** Scroll cursor to the next line @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageScrollDown ( VOID ) { HEFI_EDITOR_LINE *Line; UINTN FRow; UINTN FCol; BOOLEAN HighBits; Line = HBufferImage.CurrentLine; FRow = HBufferImage.BufferPosition.Row; FCol = HBufferImage.BufferPosition.Column; HighBits = HBufferImage.HighBits; // // has next line // if (Line->Link.ForwardLink != HBufferImage.ListHead) { FRow++; Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); // // if the next line is not that long, so move to end of next line // if (FCol > Line->Size) { FCol = Line->Size + 1; HighBits = TRUE; } } else { return EFI_SUCCESS; } HBufferImageMovePosition (FRow, FCol, HighBits); return EFI_SUCCESS; } /** Scroll cursor to previous line @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageScrollUp ( VOID ) { HEFI_EDITOR_LINE *Line; UINTN FRow; UINTN FCol; Line = HBufferImage.CurrentLine; FRow = HBufferImage.BufferPosition.Row; FCol = HBufferImage.BufferPosition.Column; // // has previous line // if (Line->Link.BackLink != HBufferImage.ListHead) { FRow--; } else { return EFI_SUCCESS; } HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits); return EFI_SUCCESS; } /** Scroll cursor to next page @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImagePageDown ( VOID ) { HEFI_EDITOR_LINE *Line; UINTN FRow; UINTN FCol; UINTN Gap; BOOLEAN HighBits; Line = HBufferImage.CurrentLine; FRow = HBufferImage.BufferPosition.Row; FCol = HBufferImage.BufferPosition.Column; HighBits = HBufferImage.HighBits; // // has next page // if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) { Gap = (HMainEditor.ScreenSize.Row - 2); } else { // // MOVE CURSOR TO LAST LINE // Gap = HBufferImage.NumLines - FRow; } // // get correct line // Line = HMoveLine (Gap); // // if that line, is not that long, so move to the end of that line // if ((Line != NULL) && (FCol > Line->Size)) { FCol = Line->Size + 1; HighBits = TRUE; } FRow += Gap; HBufferImageMovePosition (FRow, FCol, HighBits); return EFI_SUCCESS; } /** Scroll cursor to previous page @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImagePageUp ( VOID ) { UINTN FRow; UINTN FCol; UINTN Gap; INTN Retreat; FRow = HBufferImage.BufferPosition.Row; FCol = HBufferImage.BufferPosition.Column; // // has previous page // if (FRow > (HMainEditor.ScreenSize.Row - 2)) { Gap = (HMainEditor.ScreenSize.Row - 2); } else { // // the first line of file will displayed on the first line of screen // Gap = FRow - 1; } Retreat = Gap; Retreat = -Retreat; FRow -= Gap; HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits); return EFI_SUCCESS; } /** Scroll cursor to start of line @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageHome ( VOID ) { UINTN FRow; UINTN FCol; BOOLEAN HighBits; // // curosr will at the high bit // FRow = HBufferImage.BufferPosition.Row; FCol = 1; HighBits = TRUE; // // move cursor position // HBufferImageMovePosition (FRow, FCol, HighBits); return EFI_SUCCESS; } /** Scroll cursor to end of line. @retval EFI_SUCCESS Teh operation was successful. **/ EFI_STATUS HBufferImageEnd ( VOID ) { HEFI_EDITOR_LINE *Line; UINTN FRow; UINTN FCol; BOOLEAN HighBits; // // need refresh mouse // HBufferImageMouseNeedRefresh = TRUE; Line = HBufferImage.CurrentLine; FRow = HBufferImage.BufferPosition.Row; if (Line->Size == 0x10) { FCol = Line->Size; HighBits = FALSE; } else { FCol = Line->Size + 1; HighBits = TRUE; } // // move cursor position // HBufferImageMovePosition (FRow, FCol, HighBits); return EFI_SUCCESS; } /** Get the size of the open buffer. @retval The size in bytes. **/ UINTN HBufferImageGetTotalSize ( VOID ) { UINTN Size; HEFI_EDITOR_LINE *Line; // // calculate the total size of whole line list's buffer // if (HBufferImage.Lines == NULL) { return 0; } Line = CR ( HBufferImage.ListHead->BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST ); // // one line at most 0x10 // Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size; return Size; } /** Delete character from buffer. @param[in] Pos Position, Pos starting from 0. @param[in] Count The Count of characters to delete. @param[out] DeleteBuffer The DeleteBuffer. @retval EFI_SUCCESS Success **/ EFI_STATUS HBufferImageDeleteCharacterFromBuffer ( IN UINTN Pos, IN UINTN Count, OUT UINT8 *DeleteBuffer ) { UINTN Index; VOID *Buffer; UINT8 *BufferPtr; UINTN Size; HEFI_EDITOR_LINE *Line; LIST_ENTRY *Link; UINTN OldFCol; UINTN OldFRow; UINTN OldPos; UINTN NewPos; EFI_STATUS Status; Size = HBufferImageGetTotalSize (); if (Size < Count) { return EFI_LOAD_ERROR; } if (Size == 0) { return EFI_SUCCESS; } // // relocate all the HBufferImage fields // OldFRow = HBufferImage.BufferPosition.Row; OldFCol = HBufferImage.BufferPosition.Column; OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1; if (Pos > 0) { // // has character before it, // so locate according to block's previous character // NewPos = Pos - 1; } else { // // has no character before it, // so locate according to block's next character // NewPos = 0; } HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); Buffer = AllocateZeroPool (Size); if (Buffer == NULL) { return EFI_OUT_OF_RESOURCES; } HBufferImageListToBuffer (Buffer, Size); BufferPtr = (UINT8 *)Buffer; // // pass deleted buffer out // if (DeleteBuffer != NULL) { for (Index = 0; Index < Count; Index++) { DeleteBuffer[Index] = BufferPtr[Pos + Index]; } } // // delete the part from Pos // for (Index = Pos; Index < Size - Count; Index++) { BufferPtr[Index] = BufferPtr[Index + Count]; } Size -= Count; HBufferImageFreeLines (); Status = HBufferImageBufferToList (Buffer, Size); FreePool (Buffer); if (EFI_ERROR (Status)) { return Status; } Link = HMainEditor.BufferImage->ListHead->ForwardLink; for (Index = 0; Index < NewPos / 0x10; Index++) { Link = Link->ForwardLink; } Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); HBufferImage.CurrentLine = Line; // // if current cursor position if inside select area // then move it to the block's NEXT character // if ((OldPos >= Pos) && (OldPos < (Pos + Count))) { NewPos = Pos; } else { if (OldPos < Pos) { NewPos = OldPos; } else { NewPos = OldPos - Count; } } HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); return EFI_SUCCESS; } /** Add character to buffer, add before pos. @param[in] Pos Position, Pos starting from 0. @param[in] Count Count of characters to add. @param[in] AddBuffer Add buffer. @retval EFI_SUCCESS Success. **/ EFI_STATUS HBufferImageAddCharacterToBuffer ( IN UINTN Pos, IN UINTN Count, IN UINT8 *AddBuffer ) { INTN Index; VOID *Buffer; UINT8 *BufferPtr; UINTN Size; HEFI_EDITOR_LINE *Line; LIST_ENTRY *Link; UINTN OldFCol; UINTN OldFRow; UINTN OldPos; UINTN NewPos; Size = HBufferImageGetTotalSize (); // // relocate all the HBufferImage fields // OldFRow = HBufferImage.BufferPosition.Row; OldFCol = HBufferImage.BufferPosition.Column; OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1; // // move cursor before Pos // if (Pos > 0) { NewPos = Pos - 1; } else { NewPos = 0; } HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); Buffer = AllocateZeroPool (Size + Count); if (Buffer == NULL) { return EFI_OUT_OF_RESOURCES; } HBufferImageListToBuffer (Buffer, Size); BufferPtr = (UINT8 *)Buffer; // // get a place to add // for (Index = (INTN)(Size + Count - 1); Index >= (INTN)Pos; Index--) { BufferPtr[Index] = BufferPtr[Index - Count]; } // // add the buffer // for (Index = (INTN)0; Index < (INTN)Count; Index++) { BufferPtr[Index + Pos] = AddBuffer[Index]; } Size += Count; HBufferImageFreeLines (); HBufferImageBufferToList (Buffer, Size); FreePool (Buffer); Link = HMainEditor.BufferImage->ListHead->ForwardLink; for (Index = 0; Index < (INTN)NewPos / 0x10; Index++) { Link = Link->ForwardLink; } Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); HBufferImage.CurrentLine = Line; if (OldPos >= Pos) { NewPos = OldPos + Count; } else { NewPos = OldPos; } HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); return EFI_SUCCESS; } /** Delete current character from line. @retval EFI_SUCCESS The operationw as successful. **/ EFI_STATUS HBufferImageDoDelete ( VOID ) { HEFI_EDITOR_LINE *Line; BOOLEAN LastLine; UINTN FileColumn; UINTN FPos; FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1; FileColumn = HBufferImage.BufferPosition.Column; Line = HBufferImage.CurrentLine; // // if beyond the last character // if (FileColumn > Line->Size) { return EFI_SUCCESS; } LastLine = FALSE; if (Line->Link.ForwardLink == HBufferImage.ListHead) { LastLine = TRUE; } HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL); // // if is the last line // then only this line need to be refreshed // if (LastLine) { HBufferImageNeedRefresh = FALSE; HBufferImageOnlyLineNeedRefresh = TRUE; } else { HBufferImageNeedRefresh = TRUE; HBufferImageOnlyLineNeedRefresh = FALSE; } if (!HBufferImage.Modified) { HBufferImage.Modified = TRUE; } return EFI_SUCCESS; } /** Change the raw buffer to a list of lines for the UI. @param[in] Buffer The pointer to the buffer to fill. @param[in] Bytes The size of the buffer in bytes. @retval EFI_SUCCESS The operation was successful. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. **/ EFI_STATUS HBufferImageBufferToList ( IN VOID *Buffer, IN UINTN Bytes ) { UINTN TempI; UINTN TempJ; UINTN Left; HEFI_EDITOR_LINE *Line; UINT8 *BufferPtr; TempI = 0; Left = 0; BufferPtr = (UINT8 *)Buffer; // // parse file content line by line // while (TempI < Bytes) { if (Bytes - TempI >= 0x10) { Left = 0x10; } else { Left = Bytes - TempI; } // // allocate a new line // Line = HBufferImageCreateLine (); if (Line == NULL) { return EFI_OUT_OF_RESOURCES; } Line->Size = Left; for (TempJ = 0; TempJ < Left; TempJ++) { Line->Buffer[TempJ] = BufferPtr[TempI]; TempI++; } } // // last line is a full line, SO create a new line // if ((Left == 0x10) || (Bytes == 0)) { Line = HBufferImageCreateLine (); if (Line == NULL) { return EFI_OUT_OF_RESOURCES; } } return EFI_SUCCESS; } /** Change the list of lines from the UI to a raw buffer. @param[in] Buffer The pointer to the buffer to fill. @param[in] Bytes The size of the buffer in bytes. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS HBufferImageListToBuffer ( IN VOID *Buffer, IN UINTN Bytes ) { UINTN Count; UINTN Index; HEFI_EDITOR_LINE *Line; LIST_ENTRY *Link; UINT8 *BufferPtr; // // change the line list to a large buffer // if (HBufferImage.Lines == NULL) { return EFI_SUCCESS; } Link = &HBufferImage.Lines->Link; Count = 0; BufferPtr = (UINT8 *)Buffer; // // deal line by line // while (Link != HBufferImage.ListHead) { Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); // @todo shouldn't this be an error??? if (Count + Line->Size > Bytes) { return EFI_SUCCESS; } for (Index = 0; Index < Line->Size; Index++) { BufferPtr[Index] = Line->Buffer[Index]; } Count += Line->Size; BufferPtr += Line->Size; Link = Link->ForwardLink; } return EFI_SUCCESS; } /** Move the mouse in the image buffer. @param[in] TextX The x-coordinate. @param[in] TextY The y-coordinate. **/ VOID HBufferImageAdjustMousePosition ( IN INT32 TextX, IN INT32 TextY ) { UINTN TempX; UINTN TempY; UINTN AbsX; UINTN AbsY; // // TextX and TextY is mouse movement data returned by mouse driver // This function will change it to MousePosition // // // get absolute TempX value // if (TextX >= 0) { AbsX = TextX; } else { AbsX = -TextX; } // // get absolute TempY value // if (TextY >= 0) { AbsY = TextY; } else { AbsY = -TextY; } TempX = HBufferImage.MousePosition.Column; TempY = HBufferImage.MousePosition.Row; if (TextX >= 0) { TempX += TextX; } else { if (TempX >= AbsX) { TempX -= AbsX; } else { TempX = 0; } } if (TextY >= 0) { TempY += TextY; } else { if (TempY >= AbsY) { TempY -= AbsY; } else { TempY = 0; } } // // check whether new mouse column position is beyond screen // if not, adjust it // if ((TempX >= 10) && (TempX <= (10 + 0x10 * 3 - 1))) { HBufferImage.MousePosition.Column = TempX; } else if (TempX < 10) { HBufferImage.MousePosition.Column = 10; } else if (TempX > (10 + 0x10 * 3 - 1)) { HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1; } // // check whether new mouse row position is beyond screen // if not, adjust it // if ((TempY >= 2) && (TempY <= (HMainEditor.ScreenSize.Row - 1))) { HBufferImage.MousePosition.Row = TempY; } else if (TempY < 2) { HBufferImage.MousePosition.Row = 2; } else if (TempY > (HMainEditor.ScreenSize.Row - 1)) { HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1); } } /** Dispatch input to different handler @param[in] Key The input key: the keys can be: ASCII KEY Backspace/Delete Direction key: up/down/left/right/pgup/pgdn Home/End INS @retval EFI_SUCCESS The operation was successful. @retval EFI_LOAD_ERROR A load error occurred. @retval EFI_OUT_OF_RESOURCES A Memory allocation failed. **/ EFI_STATUS HBufferImageHandleInput ( IN EFI_INPUT_KEY *Key ) { EFI_STATUS Status; Status = EFI_SUCCESS; switch (Key->ScanCode) { // // ordinary key // case SCAN_NULL: Status = HBufferImageDoCharInput (Key->UnicodeChar); break; // // up arrow // case SCAN_UP: Status = HBufferImageScrollUp (); break; // // down arrow // case SCAN_DOWN: Status = HBufferImageScrollDown (); break; // // right arrow // case SCAN_RIGHT: Status = HBufferImageScrollRight (); break; // // left arrow // case SCAN_LEFT: Status = HBufferImageScrollLeft (); break; // // page up // case SCAN_PAGE_UP: Status = HBufferImagePageUp (); break; // // page down // case SCAN_PAGE_DOWN: Status = HBufferImagePageDown (); break; // // delete // case SCAN_DELETE: Status = HBufferImageDoDelete (); break; // // home // case SCAN_HOME: Status = HBufferImageHome (); break; // // end // case SCAN_END: Status = HBufferImageEnd (); break; default: Status = StatusBarSetStatusString (L"Unknown Command"); break; } return Status; }