There are cases that the operands of an expression are all with rank less
than UINT64/INT64 and the result of the expression is explicitly cast to
UINT64/INT64 to fit the target size.
An example will be:
UINT32 a,b;
// a and b can be any unsigned int type with rank less than UINT64, like
// UINT8, UINT16, etc.
UINT64 c;
c = (UINT64) (a + b);
Some static code checkers may warn that the expression result might
overflow within the rank of "int" (integer promotions) and the result is
then cast to a bigger size.
The commit refines codes by the following rules:
1). When the expression is possible to overflow the range of unsigned int/
int:
c = (UINT64)a + b;
2). When the expression will not overflow within the rank of "int", remove
the explicit type casts:
c = a + b;
3). When the expression will be cast to pointer of possible greater size:
UINT32 a,b;
VOID *c;
c = (VOID *)(UINTN)(a + b); --> c = (VOID *)((UINTN)a + b);
4). When one side of a comparison expression contains only operands with
rank less than UINT32:
UINT8 a;
UINT16 b;
UINTN c;
if ((UINTN)(a + b) > c) {...} --> if (((UINT32)a + b) > c) {...}
For rule 4), if we remove the 'UINTN' type cast like:
if (a + b > c) {...}
The VS compiler will complain with warning C4018 (signed/unsigned
mismatch, level 3 warning) due to promoting 'a + b' to type 'int'.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
		
	
		
			
				
	
	
		
			2476 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2476 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @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 - 2017, Intel Corporation. All rights reserved. <BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "HexEditor.h"
 | |
| 
 | |
| 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 occured.
 | |
| **/
 | |
| 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 occured.
 | |
| 
 | |
| **/
 | |
| 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 occured.
 | |
|   @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 occured.
 | |
|   @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;
 | |
| }
 | |
| 
 |