Home | History | Annotate | Download | only in HexEdit
      1 /** @file
      2   Defines HBufferImage - the view of the file that is visible at any point,
      3   as well as the event handlers for editing the file
      4 
      5   Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "HexEditor.h"
     17 
     18 extern EFI_HANDLE                 HImageHandleBackup;
     19 
     20 extern HEFI_EDITOR_FILE_IMAGE     HFileImage;
     21 extern HEFI_EDITOR_DISK_IMAGE     HDiskImage;
     22 extern HEFI_EDITOR_MEM_IMAGE      HMemImage;
     23 
     24 extern HEFI_EDITOR_FILE_IMAGE     HFileImageBackupVar;
     25 extern HEFI_EDITOR_DISK_IMAGE     HDiskImageBackupVar;
     26 extern HEFI_EDITOR_MEM_IMAGE      HMemImageBackupVar;
     27 
     28 extern BOOLEAN                    HEditorMouseAction;
     29 
     30 extern HEFI_EDITOR_GLOBAL_EDITOR  HMainEditor;
     31 extern HEFI_EDITOR_GLOBAL_EDITOR  HMainEditorBackupVar;
     32 
     33 HEFI_EDITOR_BUFFER_IMAGE          HBufferImage;
     34 HEFI_EDITOR_BUFFER_IMAGE          HBufferImageBackupVar;
     35 
     36 //
     37 // for basic initialization of HBufferImage
     38 //
     39 HEFI_EDITOR_BUFFER_IMAGE          HBufferImageConst = {
     40   NULL,
     41   NULL,
     42   0,
     43   NULL,
     44   {
     45     0,
     46     0
     47   },
     48   {
     49     0,
     50     0
     51   },
     52   {
     53     0,
     54     0
     55   },
     56   0,
     57   TRUE,
     58   FALSE,
     59   FileTypeNone,
     60   NULL,
     61   NULL,
     62   NULL
     63 };
     64 
     65 //
     66 // the whole edit area needs to be refreshed
     67 //
     68 BOOLEAN                           HBufferImageNeedRefresh;
     69 
     70 //
     71 // only the current line in edit area needs to be refresh
     72 //
     73 BOOLEAN                           HBufferImageOnlyLineNeedRefresh;
     74 
     75 BOOLEAN                           HBufferImageMouseNeedRefresh;
     76 
     77 /**
     78   Initialization function for HBufferImage
     79 
     80   @retval EFI_SUCCESS       The operation was successful.
     81   @retval EFI_LOAD_ERROR    A load error occured.
     82 **/
     83 EFI_STATUS
     84 HBufferImageInit (
     85   VOID
     86   )
     87 {
     88   EFI_STATUS  Status;
     89 
     90   //
     91   // basically initialize the HBufferImage
     92   //
     93   CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage));
     94 
     95   //
     96   // INIT listhead
     97   //
     98   HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
     99   if (HBufferImage.ListHead == NULL) {
    100     return EFI_LOAD_ERROR;
    101   }
    102 
    103   InitializeListHead (HBufferImage.ListHead);
    104 
    105   HBufferImage.DisplayPosition.Row    = 2;
    106   HBufferImage.DisplayPosition.Column = 10;
    107   HBufferImage.MousePosition.Row      = 2;
    108   HBufferImage.MousePosition.Column   = 10;
    109 
    110   HBufferImage.FileImage              = &HFileImage;
    111   HBufferImage.DiskImage              = &HDiskImage;
    112   HBufferImage.MemImage               = &HMemImage;
    113 
    114   HBufferImageNeedRefresh             = FALSE;
    115   HBufferImageOnlyLineNeedRefresh     = FALSE;
    116   HBufferImageMouseNeedRefresh        = FALSE;
    117 
    118   HBufferImageBackupVar.FileImage     = &HFileImageBackupVar;
    119   HBufferImageBackupVar.DiskImage     = &HDiskImageBackupVar;
    120   HBufferImageBackupVar.MemImage      = &HMemImageBackupVar;
    121 
    122   Status = HFileImageInit ();
    123   if (EFI_ERROR (Status)) {
    124     return EFI_LOAD_ERROR;
    125   }
    126 
    127   Status = HDiskImageInit ();
    128   if (EFI_ERROR (Status)) {
    129     return EFI_LOAD_ERROR;
    130   }
    131 
    132   Status = HMemImageInit ();
    133   if (EFI_ERROR (Status)) {
    134     return EFI_LOAD_ERROR;
    135   }
    136 
    137   return EFI_SUCCESS;
    138 }
    139 
    140 /**
    141   Backup function for HBufferImage. Only a few fields need to be backup.
    142   This is for making the file buffer refresh as few as possible.
    143 
    144   @retval EFI_SUCCESS  The operation was successful.
    145 **/
    146 EFI_STATUS
    147 HBufferImageBackup (
    148   VOID
    149   )
    150 {
    151   HBufferImageBackupVar.MousePosition   = HBufferImage.MousePosition;
    152 
    153   HBufferImageBackupVar.BufferPosition  = HBufferImage.BufferPosition;
    154 
    155   HBufferImageBackupVar.Modified        = HBufferImage.Modified;
    156 
    157   HBufferImageBackupVar.BufferType      = HBufferImage.BufferType;
    158   HBufferImageBackupVar.LowVisibleRow   = HBufferImage.LowVisibleRow;
    159   HBufferImageBackupVar.HighBits        = HBufferImage.HighBits;
    160 
    161   //
    162   // three kinds of buffer supported
    163   //   file buffer
    164   //   disk buffer
    165   //   memory buffer
    166   //
    167   switch (HBufferImage.BufferType) {
    168   case FileTypeFileBuffer:
    169     HFileImageBackup ();
    170     break;
    171 
    172   case FileTypeDiskBuffer:
    173     HDiskImageBackup ();
    174     break;
    175 
    176   case FileTypeMemBuffer:
    177     HMemImageBackup ();
    178     break;
    179 
    180   default:
    181     break;
    182   }
    183 
    184   return EFI_SUCCESS;
    185 }
    186 
    187 /**
    188   Free all the lines in HBufferImage.
    189     Fields affected:
    190     Lines
    191     CurrentLine
    192     NumLines
    193     ListHead
    194 
    195   @retval EFI_SUCCESS  The operation was successful.
    196 **/
    197 EFI_STATUS
    198 HBufferImageFreeLines (
    199   VOID
    200   )
    201 {
    202   HFreeLines (HBufferImage.ListHead, HBufferImage.Lines);
    203 
    204   HBufferImage.Lines        = NULL;
    205   HBufferImage.CurrentLine  = NULL;
    206   HBufferImage.NumLines     = 0;
    207 
    208   return EFI_SUCCESS;
    209 }
    210 
    211 /**
    212   Cleanup function for HBufferImage
    213 
    214   @retval EFI_SUCCESS  The operation was successful.
    215 **/
    216 EFI_STATUS
    217 HBufferImageCleanup (
    218   VOID
    219   )
    220 {
    221   EFI_STATUS  Status;
    222 
    223   //
    224   // free all the lines
    225   //
    226   Status = HBufferImageFreeLines ();
    227 
    228   SHELL_FREE_NON_NULL (HBufferImage.ListHead);
    229   HBufferImage.ListHead = NULL;
    230 
    231   HFileImageCleanup ();
    232   HDiskImageCleanup ();
    233 
    234   return Status;
    235 
    236 }
    237 
    238 /**
    239   Print Line on Row
    240 
    241   @param[in] Line     The lline to print.
    242   @param[in] Row      The row on screen ( begin from 1 ).
    243   @param[in] FRow     The FRow.
    244   @param[in] Orig     The original color.
    245   @param[in] New      The color to print with.
    246 
    247   @retval EFI_SUCCESS The operation was successful.
    248 **/
    249 EFI_STATUS
    250 HBufferImagePrintLine (
    251   IN HEFI_EDITOR_LINE           *Line,
    252   IN UINTN                      Row,
    253   IN UINTN                      FRow,
    254   IN HEFI_EDITOR_COLOR_UNION    Orig,
    255   IN HEFI_EDITOR_COLOR_UNION    New
    256 
    257   )
    258 {
    259 
    260   UINTN   Index;
    261   UINTN   Pos;
    262   BOOLEAN Selected;
    263   BOOLEAN BeNewColor;
    264   UINTN   RowStart;
    265   UINTN   RowEnd;
    266   UINTN   ColStart;
    267   UINTN   ColEnd;
    268 
    269   //
    270   // variable initialization
    271   //
    272   ColStart  = 0;
    273   ColEnd    = 0;
    274   Selected  = FALSE;
    275 
    276   //
    277   // print the selected area in opposite color
    278   //
    279   if (HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
    280     RowStart  = (HMainEditor.SelectStart - 1) / 0x10 + 1;
    281     RowEnd    = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
    282 
    283     ColStart  = (HMainEditor.SelectStart - 1) % 0x10 + 1;
    284     ColEnd    = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
    285 
    286     if (FRow >= RowStart && FRow <= RowEnd) {
    287       Selected = TRUE;
    288     }
    289 
    290     if (FRow > RowStart) {
    291       ColStart = 1;
    292     }
    293 
    294     if (FRow < RowEnd) {
    295       ColEnd = 0x10;
    296     }
    297 
    298   }
    299 
    300   if (!HEditorMouseAction) {
    301     ShellPrintEx (
    302       0,
    303       (INT32)Row - 1,
    304       L"%8X ",
    305       ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10
    306       );
    307 
    308   }
    309 
    310   for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) {
    311 
    312     BeNewColor = FALSE;
    313 
    314     if (Selected) {
    315       if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
    316         BeNewColor = TRUE;
    317       }
    318     }
    319 
    320     if (BeNewColor) {
    321       gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
    322     } else {
    323       gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
    324     }
    325 
    326     Pos = 10 + (Index * 3);
    327     if (Line->Buffer[Index] < 0x10) {
    328       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
    329       Pos++;
    330     }
    331 
    332     if (Index < 0x07) {
    333       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
    334     } else {
    335       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x  ", Line->Buffer[Index]);
    336     }
    337 
    338   }
    339 
    340   gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
    341   while (Index < 0x08) {
    342     Pos = 10 + (Index * 3);
    343     ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"    ");
    344     Index++;
    345   }
    346 
    347   while (Index < 0x10 && Index < Line->Size) {
    348 
    349     BeNewColor = FALSE;
    350 
    351     if (Selected) {
    352       if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
    353         BeNewColor = TRUE;
    354       }
    355     }
    356 
    357     if (BeNewColor) {
    358       gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
    359     } else {
    360       gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
    361     }
    362 
    363     Pos = 10 + (Index * 3) + 1;
    364     if (Line->Buffer[Index] < 0x10) {
    365       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
    366       Pos++;
    367     }
    368 
    369     ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
    370     Index++;
    371   }
    372 
    373   gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
    374   while (Index < 0x10) {
    375     Pos = 10 + (Index * 3) + 1;
    376     ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"   ");
    377     Index++;
    378   }
    379   //
    380   // restore the original color
    381   //
    382   gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
    383 
    384   //
    385   // PRINT the buffer content
    386   //
    387   if (!HEditorMouseAction) {
    388     for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) {
    389       Pos = ASCII_POSITION + Index;
    390 
    391       //
    392       // learned from shelle.h -- IsValidChar
    393       //
    394       if (Line->Buffer[Index] >= L' ') {
    395         ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16) Line->Buffer[Index]);
    396       } else {
    397         ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.');
    398       }
    399     }
    400 
    401     while (Index < 0x10) {
    402       Pos = ASCII_POSITION + Index;
    403       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
    404       Index++;
    405     }
    406   }
    407   //
    408   // restore the abundant blank in hex edit area to original color
    409   //
    410   if (Selected) {
    411     if (ColEnd <= 7) {
    412       Pos = 10 + (ColEnd - 1) * 3 + 2;
    413       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
    414     } else if (ColEnd == 8) {
    415       Pos = 10 + (ColEnd - 1) * 3 + 2;
    416       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"  ");
    417     } else {
    418       Pos = 10 + (ColEnd - 1) * 3 + 3;
    419       ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
    420     }
    421   }
    422 
    423   return EFI_SUCCESS;
    424 }
    425 
    426 /**
    427   Function to decide if a column number is stored in the high bits.
    428 
    429   @param[in] Column     The column to examine.
    430   @param[out] FCol      The actual column number.
    431 
    432   @retval TRUE      The actual column was in high bits and is now in FCol.
    433   @retval FALSE     There was not a column number in the high bits.
    434 **/
    435 BOOLEAN
    436 HBufferImageIsAtHighBits (
    437   IN  UINTN Column,
    438   OUT UINTN *FCol
    439   )
    440 {
    441   Column -= 10;
    442 
    443   //
    444   // NOW AFTER THE SUB, Column start from 0
    445   // 23 AND 24 ARE BOTH BLANK
    446   //
    447   if (Column == 24) {
    448     *FCol = 0;
    449     return FALSE;
    450   }
    451 
    452   if (Column > 24) {
    453     Column--;
    454   }
    455 
    456   *FCol = (Column / 3) + 1;
    457 
    458   if (Column % 3 == 0) {
    459     return TRUE;
    460   }
    461 
    462   if ((Column % 3 == 2)) {
    463     *FCol = 0;
    464   }
    465 
    466   return FALSE;
    467 }
    468 
    469 /**
    470   Decide if a point is in the already selected area.
    471 
    472   @param[in] MouseRow     The row of the point to test.
    473   @param[in] MouseCol     The col of the point to test.
    474 
    475   @retval TRUE      The point is in the selected area.
    476   @retval FALSE     The point is not in the selected area.
    477 **/
    478 BOOLEAN
    479 HBufferImageIsInSelectedArea (
    480   IN UINTN MouseRow,
    481   IN UINTN MouseCol
    482   )
    483 {
    484   UINTN FRow;
    485   UINTN RowStart;
    486   UINTN RowEnd;
    487   UINTN ColStart;
    488   UINTN ColEnd;
    489   UINTN MouseColStart;
    490   UINTN MouseColEnd;
    491 
    492   //
    493   // judge mouse position whether is in selected area
    494   //
    495   //
    496   // not select
    497   //
    498   if (HMainEditor.SelectStart == 0 || HMainEditor.SelectEnd == 0) {
    499     return FALSE;
    500   }
    501   //
    502   // calculate the select area
    503   //
    504   RowStart  = (HMainEditor.SelectStart - 1) / 0x10 + 1;
    505   RowEnd    = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
    506 
    507   ColStart  = (HMainEditor.SelectStart - 1) % 0x10 + 1;
    508   ColEnd    = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
    509 
    510   FRow      = HBufferImage.LowVisibleRow + MouseRow - 2;
    511   if (FRow < RowStart || FRow > RowEnd) {
    512     return FALSE;
    513   }
    514 
    515   if (FRow > RowStart) {
    516     ColStart = 1;
    517   }
    518 
    519   if (FRow < RowEnd) {
    520     ColEnd = 0x10;
    521   }
    522 
    523   MouseColStart = 10 + (ColStart - 1) * 3;
    524   if (ColStart > 8) {
    525     MouseColStart++;
    526   }
    527 
    528   MouseColEnd = 10 + (ColEnd - 1) * 3 + 1;
    529   if (ColEnd > 8) {
    530     MouseColEnd++;
    531   }
    532 
    533   if (MouseCol < MouseColStart || MouseCol > MouseColEnd) {
    534     return FALSE;
    535   }
    536 
    537   return TRUE;
    538 }
    539 
    540 /**
    541   Set mouse position according to HBufferImage.MousePosition.
    542 
    543   @retval EFI_SUCCESS  The operation was successful.
    544 **/
    545 EFI_STATUS
    546 HBufferImageRestoreMousePosition (
    547   VOID
    548   )
    549 {
    550   HEFI_EDITOR_COLOR_UNION Orig;
    551   HEFI_EDITOR_COLOR_UNION New;
    552   UINTN                   FRow;
    553   UINTN                   FColumn;
    554   BOOLEAN                 HasCharacter;
    555   HEFI_EDITOR_LINE        *CurrentLine;
    556   HEFI_EDITOR_LINE        *Line;
    557   UINT8                   Value;
    558   BOOLEAN                 HighBits;
    559 
    560   Line = NULL;
    561   if (HMainEditor.MouseSupported) {
    562 
    563     if (HBufferImageMouseNeedRefresh) {
    564 
    565       HBufferImageMouseNeedRefresh = FALSE;
    566 
    567       //
    568       // if mouse position not moved and only mouse action
    569       // so do not need to refresh mouse position
    570       //
    571       if ((
    572             HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row &&
    573           HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column
    574         ) &&
    575           HEditorMouseAction
    576           ) {
    577         return EFI_SUCCESS;
    578       }
    579       //
    580       // backup the old screen attributes
    581       //
    582       Orig                  = HMainEditor.ColorAttributes;
    583       New.Data              = 0;
    584       New.Colors.Foreground = Orig.Colors.Background & 0xF;
    585       New.Colors.Background = Orig.Colors.Foreground & 0x7;
    586 
    587       //
    588       // if in selected area,
    589       // so do not need to refresh mouse
    590       //
    591       if (!HBufferImageIsInSelectedArea (
    592             HBufferImageBackupVar.MousePosition.Row,
    593             HBufferImageBackupVar.MousePosition.Column
    594             )) {
    595         gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
    596       } else {
    597         gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
    598       }
    599       //
    600       // clear the old mouse position
    601       //
    602       FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2;
    603 
    604       HighBits = HBufferImageIsAtHighBits (
    605                   HBufferImageBackupVar.MousePosition.Column,
    606                   &FColumn
    607                   );
    608 
    609       HasCharacter = TRUE;
    610       if (FRow > HBufferImage.NumLines || FColumn == 0) {
    611         HasCharacter = FALSE;
    612       } else {
    613         CurrentLine = HBufferImage.CurrentLine;
    614         Line        = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
    615 
    616         if (Line == NULL || FColumn > Line->Size) {
    617           HasCharacter = FALSE;
    618         }
    619 
    620         HBufferImage.CurrentLine = CurrentLine;
    621       }
    622 
    623       ShellPrintEx (
    624         (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
    625         (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
    626         L" "
    627         );
    628 
    629       if (HasCharacter) {
    630         if (HighBits) {
    631           Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
    632           Value = (UINT8) (Value >> 4);
    633         } else {
    634           Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
    635         }
    636 
    637         ShellPrintEx (
    638           (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
    639           (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
    640           L"%x",
    641           Value
    642           );
    643       }
    644 
    645       if (!HBufferImageIsInSelectedArea (
    646             HBufferImage.MousePosition.Row,
    647             HBufferImage.MousePosition.Column
    648             )) {
    649         gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
    650       } else {
    651         gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
    652       }
    653       //
    654       // clear the old mouse position
    655       //
    656       FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2;
    657 
    658       HighBits = HBufferImageIsAtHighBits (
    659                   HBufferImage.MousePosition.Column,
    660                   &FColumn
    661                   );
    662 
    663       HasCharacter = TRUE;
    664       if (FRow > HBufferImage.NumLines || FColumn == 0) {
    665         HasCharacter = FALSE;
    666       } else {
    667         CurrentLine = HBufferImage.CurrentLine;
    668         Line        = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
    669 
    670         if (Line == NULL || FColumn > Line->Size) {
    671           HasCharacter = FALSE;
    672         }
    673 
    674         HBufferImage.CurrentLine = CurrentLine;
    675       }
    676 
    677       ShellPrintEx (
    678         (INT32)HBufferImage.MousePosition.Column - 1,
    679         (INT32)HBufferImage.MousePosition.Row - 1,
    680         L" "
    681         );
    682 
    683       if (HasCharacter) {
    684         if (HighBits) {
    685           Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
    686           Value = (UINT8) (Value >> 4);
    687         } else {
    688           Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
    689         }
    690 
    691         ShellPrintEx (
    692           (INT32)HBufferImage.MousePosition.Column - 1,
    693           (INT32)HBufferImage.MousePosition.Row - 1,
    694           L"%x",
    695           Value
    696           );
    697       }
    698       //
    699       // end of HasCharacter
    700       //
    701       gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
    702     }
    703     //
    704     // end of MouseNeedRefresh
    705     //
    706   }
    707   //
    708   // end of MouseSupported
    709   //
    710   return EFI_SUCCESS;
    711 }
    712 
    713 /**
    714   Set cursor position according to HBufferImage.DisplayPosition.
    715 
    716   @retval EFI_SUCCESS  The operation was successful.
    717 **/
    718 EFI_STATUS
    719 HBufferImageRestorePosition (
    720   VOID
    721   )
    722 {
    723   //
    724   // set cursor position
    725   //
    726   gST->ConOut->SetCursorPosition (
    727         gST->ConOut,
    728         HBufferImage.DisplayPosition.Column - 1,
    729         HBufferImage.DisplayPosition.Row - 1
    730         );
    731 
    732   return EFI_SUCCESS;
    733 }
    734 
    735 /**
    736   Refresh function for HBufferImage.
    737 
    738   @retval EFI_SUCCESS     The operation was successful.
    739   @retval EFI_LOAD_ERROR  A Load error occured.
    740 
    741 **/
    742 EFI_STATUS
    743 HBufferImageRefresh (
    744   VOID
    745   )
    746 {
    747   LIST_ENTRY          *Link;
    748   HEFI_EDITOR_LINE        *Line;
    749   UINTN                   Row;
    750   HEFI_EDITOR_COLOR_UNION Orig;
    751   HEFI_EDITOR_COLOR_UNION New;
    752 
    753   UINTN                   StartRow;
    754   UINTN                   EndRow;
    755   UINTN                   FStartRow;
    756   UINTN                   Tmp;
    757 
    758   Orig                  = HMainEditor.ColorAttributes;
    759   New.Data              = 0;
    760   New.Colors.Foreground = Orig.Colors.Background;
    761   New.Colors.Background = Orig.Colors.Foreground;
    762 
    763   //
    764   // if it's the first time after editor launch, so should refresh
    765   //
    766   if (HEditorFirst == FALSE) {
    767     //
    768     // no definite required refresh
    769     // and file position displayed on screen has not been changed
    770     //
    771     if (!HBufferImageNeedRefresh &&
    772         !HBufferImageOnlyLineNeedRefresh &&
    773         HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow
    774         ) {
    775       HBufferImageRestoreMousePosition ();
    776       HBufferImageRestorePosition ();
    777       return EFI_SUCCESS;
    778     }
    779   }
    780 
    781   gST->ConOut->EnableCursor (gST->ConOut, FALSE);
    782 
    783   //
    784   // only need to refresh current line
    785   //
    786   if (HBufferImageOnlyLineNeedRefresh && HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) {
    787 
    788     HBufferImagePrintLine (
    789       HBufferImage.CurrentLine,
    790       HBufferImage.DisplayPosition.Row,
    791       HBufferImage.BufferPosition.Row,
    792       Orig,
    793       New
    794       );
    795   } else {
    796     //
    797     // the whole edit area need refresh
    798     //
    799     if (HEditorMouseAction && HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
    800       if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) {
    801         if (HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart && HMainEditorBackupVar.SelectStart != 0) {
    802           StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1;
    803         } else {
    804           StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
    805         }
    806       } else {
    807         StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
    808       }
    809 
    810       if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) {
    811         EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1;
    812       } else {
    813         EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
    814       }
    815       //
    816       // swap
    817       //
    818       if (StartRow > EndRow) {
    819         Tmp       = StartRow;
    820         StartRow  = EndRow;
    821         EndRow    = Tmp;
    822       }
    823 
    824       FStartRow = StartRow;
    825 
    826       StartRow  = 2 + StartRow - HBufferImage.LowVisibleRow;
    827       EndRow    = 2 + EndRow - HBufferImage.LowVisibleRow;
    828 
    829     } else {
    830       //
    831       // not mouse selection actions
    832       //
    833       FStartRow = HBufferImage.LowVisibleRow;
    834       StartRow  = 2;
    835       EndRow    = (HMainEditor.ScreenSize.Row - 1);
    836     }
    837     //
    838     // no line
    839     //
    840     if (HBufferImage.Lines == NULL) {
    841       HBufferImageRestoreMousePosition ();
    842       HBufferImageRestorePosition ();
    843       gST->ConOut->EnableCursor (gST->ConOut, TRUE);
    844       return EFI_SUCCESS;
    845     }
    846     //
    847     // get the first line that will be displayed
    848     //
    849     Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row);
    850     if (Line == NULL) {
    851       gST->ConOut->EnableCursor (gST->ConOut, TRUE);
    852       return EFI_LOAD_ERROR;
    853     }
    854 
    855     Link  = &(Line->Link);
    856     Row   = StartRow;
    857     do {
    858       Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
    859 
    860       //
    861       // print line at row
    862       //
    863       HBufferImagePrintLine (
    864         Line,
    865         Row,
    866         HBufferImage.LowVisibleRow + Row - 2,
    867         Orig,
    868         New
    869         );
    870 
    871       Link = Link->ForwardLink;
    872       Row++;
    873     } while (Link != HBufferImage.ListHead && Row <= EndRow);
    874 
    875     while (Row <= EndRow) {
    876       EditorClearLine (Row, HMainEditor.ScreenSize.Column, HMainEditor.ScreenSize.Row);
    877       Row++;
    878     }
    879     //
    880     // while not file end and not screen full
    881     //
    882   }
    883 
    884   HBufferImageRestoreMousePosition ();
    885   HBufferImageRestorePosition ();
    886 
    887   HBufferImageNeedRefresh         = FALSE;
    888   HBufferImageOnlyLineNeedRefresh = FALSE;
    889   gST->ConOut->EnableCursor (gST->ConOut, TRUE);
    890 
    891   return EFI_SUCCESS;
    892 }
    893 
    894 /**
    895   Read an image into a buffer friom a source.
    896 
    897   @param[in] FileName     Pointer to the file name.  OPTIONAL and ignored if not FileTypeFileBuffer.
    898   @param[in] DiskName     Pointer to the disk name.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    899   @param[in] DiskOffset   Offset into the disk.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    900   @param[in] DiskSize     Size of the disk buffer.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    901   @param[in] MemOffset    Offset into the Memory.  OPTIONAL and ignored if not FileTypeMemBuffer.
    902   @param[in] MemSize      Size of the Memory buffer.  OPTIONAL and ignored if not FileTypeMemBuffer.
    903   @param[in] BufferType   The type of buffer to save.  IGNORED.
    904   @param[in] Recover      TRUE for recovermode, FALSE otherwise.
    905 
    906   @return EFI_SUCCESS     The operation was successful.
    907 **/
    908 EFI_STATUS
    909 EFIAPI
    910 HBufferImageRead (
    911   IN CONST CHAR16                   *FileName,
    912   IN CONST CHAR16                   *DiskName,
    913   IN UINTN                          DiskOffset,
    914   IN UINTN                          DiskSize,
    915   IN UINTN                          MemOffset,
    916   IN UINTN                          MemSize,
    917   IN EDIT_FILE_TYPE                 BufferType,
    918   IN BOOLEAN                        Recover
    919   )
    920 {
    921   EFI_STATUS                      Status;
    922   EDIT_FILE_TYPE                  BufferTypeBackup;
    923 
    924   //
    925   // variable initialization
    926   //
    927   Status = EFI_SUCCESS;
    928   HBufferImage.BufferType = BufferType;
    929 
    930   //
    931   // three types of buffer supported
    932   //   file buffer
    933   //   disk buffer
    934   //   memory buffer
    935   //
    936   BufferTypeBackup = HBufferImage.BufferType;
    937 
    938   switch (BufferType) {
    939   case FileTypeFileBuffer:
    940     Status = HFileImageRead (FileName, Recover);
    941     break;
    942 
    943   case FileTypeDiskBuffer:
    944     Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);
    945     break;
    946 
    947   case FileTypeMemBuffer:
    948     Status = HMemImageRead (MemOffset, MemSize, Recover);
    949     break;
    950 
    951   default:
    952     Status = EFI_NOT_FOUND;
    953     break;
    954   }
    955 
    956   if (EFI_ERROR (Status)) {
    957     HBufferImage.BufferType = BufferTypeBackup;
    958   }
    959 
    960   return Status;
    961 }
    962 
    963 /**
    964   Save the current image.
    965 
    966   @param[in] FileName     Pointer to the file name.  OPTIONAL and ignored if not FileTypeFileBuffer.
    967   @param[in] DiskName     Pointer to the disk name.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    968   @param[in] DiskOffset   Offset into the disk.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    969   @param[in] DiskSize     Size of the disk buffer.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    970   @param[in] MemOffset    Offset into the Memory.  OPTIONAL and ignored if not FileTypeMemBuffer.
    971   @param[in] MemSize      Size of the Memory buffer.  OPTIONAL and ignored if not FileTypeMemBuffer.
    972   @param[in] BufferType   The type of buffer to save.  IGNORED.
    973 
    974   @return EFI_SUCCESS     The operation was successful.
    975 **/
    976 EFI_STATUS
    977 HBufferImageSave (
    978   IN CHAR16                         *FileName,
    979   IN CHAR16                         *DiskName,
    980   IN UINTN                          DiskOffset,
    981   IN UINTN                          DiskSize,
    982   IN UINTN                          MemOffset,
    983   IN UINTN                          MemSize,
    984   IN EDIT_FILE_TYPE                 BufferType
    985   )
    986 {
    987   EFI_STATUS                      Status;
    988   EDIT_FILE_TYPE                  BufferTypeBackup;
    989 
    990   //
    991   // variable initialization
    992   //
    993   Status            = EFI_SUCCESS;
    994   BufferTypeBackup  = HBufferImage.BufferType;
    995 
    996   switch (HBufferImage.BufferType) {
    997   //
    998   // file buffer
    999   //
   1000   case FileTypeFileBuffer:
   1001     Status = HFileImageSave (FileName);
   1002     break;
   1003 
   1004   //
   1005   // disk buffer
   1006   //
   1007   case FileTypeDiskBuffer:
   1008     Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);
   1009     break;
   1010 
   1011   //
   1012   // memory buffer
   1013   //
   1014   case FileTypeMemBuffer:
   1015     Status = HMemImageSave (MemOffset, MemSize);
   1016     break;
   1017 
   1018   default:
   1019     Status = EFI_NOT_FOUND;
   1020     break;
   1021   }
   1022 
   1023   if (EFI_ERROR (Status)) {
   1024     HBufferImage.BufferType = BufferTypeBackup;
   1025   }
   1026 
   1027   return Status;
   1028 }
   1029 
   1030 /**
   1031   Create a new line and append it to the line list.
   1032     Fields affected:
   1033     NumLines
   1034     Lines
   1035 
   1036   @retval NULL    create line failed.
   1037   @return         the line created.
   1038 
   1039 **/
   1040 HEFI_EDITOR_LINE *
   1041 HBufferImageCreateLine (
   1042   VOID
   1043   )
   1044 {
   1045   HEFI_EDITOR_LINE  *Line;
   1046 
   1047   //
   1048   // allocate for line structure
   1049   //
   1050   Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));
   1051   if (Line == NULL) {
   1052     return NULL;
   1053   }
   1054 
   1055   Line->Signature = EFI_EDITOR_LINE_LIST;
   1056   Line->Size      = 0;
   1057 
   1058   HBufferImage.NumLines++;
   1059 
   1060   //
   1061   // insert to line list
   1062   //
   1063   InsertTailList (HBufferImage.ListHead, &Line->Link);
   1064 
   1065   if (HBufferImage.Lines == NULL) {
   1066     HBufferImage.Lines = CR (
   1067                           HBufferImage.ListHead->ForwardLink,
   1068                           HEFI_EDITOR_LINE,
   1069                           Link,
   1070                           EFI_EDITOR_LINE_LIST
   1071                           );
   1072   }
   1073 
   1074   return Line;
   1075 }
   1076 
   1077 /**
   1078   Free the current image.
   1079 
   1080   @retval EFI_SUCCESS   The operation was successful.
   1081 **/
   1082 EFI_STATUS
   1083 HBufferImageFree (
   1084   VOID
   1085   )
   1086 {
   1087   //
   1088   // free all lines
   1089   //
   1090   HBufferImageFreeLines ();
   1091 
   1092   return EFI_SUCCESS;
   1093 }
   1094 
   1095 /**
   1096   change char to int value based on Hex.
   1097 
   1098   @param[in] Char     The input char.
   1099 
   1100   @return The character's index value.
   1101   @retval -1  The operation failed.
   1102 **/
   1103 INTN
   1104 EFIAPI
   1105 HBufferImageCharToHex (
   1106   IN CHAR16 Char
   1107   )
   1108 {
   1109   //
   1110   // change the character to hex
   1111   //
   1112   if (Char >= L'0' && Char <= L'9') {
   1113     return (INTN) (Char - L'0');
   1114   }
   1115 
   1116   if (Char >= L'a' && Char <= L'f') {
   1117     return (INTN) (Char - L'a' + 10);
   1118   }
   1119 
   1120   if (Char >= L'A' && Char <= L'F') {
   1121     return (INTN) (Char - L'A' + 10);
   1122   }
   1123 
   1124   return -1;
   1125 }
   1126 
   1127 /**
   1128   Add character.
   1129 
   1130   @param[in] Char -- input char.
   1131 
   1132   @retval EFI_SUCCESS             The operation was successful.
   1133   @retval EFI_OUT_OF_RESOURCES    A memory allocation failed.
   1134 **/
   1135 EFI_STATUS
   1136 EFIAPI
   1137 HBufferImageAddChar (
   1138   IN  CHAR16  Char
   1139   )
   1140 {
   1141   HEFI_EDITOR_LINE  *Line;
   1142   HEFI_EDITOR_LINE  *NewLine;
   1143   INTN              Value;
   1144   UINT8             Old;
   1145   UINTN             FRow;
   1146   UINTN             FCol;
   1147   BOOLEAN           High;
   1148 
   1149   Value = HBufferImageCharToHex (Char);
   1150 
   1151   //
   1152   // invalid input
   1153   //
   1154   if (Value == -1) {
   1155     return EFI_SUCCESS;
   1156   }
   1157 
   1158   Line  = HBufferImage.CurrentLine;
   1159   FRow  = HBufferImage.BufferPosition.Row;
   1160   FCol  = HBufferImage.BufferPosition.Column;
   1161   High  = HBufferImage.HighBits;
   1162 
   1163   //
   1164   // only needs to refresh current line
   1165   //
   1166   HBufferImageOnlyLineNeedRefresh = TRUE;
   1167 
   1168   //
   1169   // not a full line and beyond the last character
   1170   //
   1171   if (FCol > Line->Size) {
   1172     //
   1173     // cursor always at high 4 bits
   1174     // and always put input to the low 4 bits
   1175     //
   1176     Line->Buffer[Line->Size] = (UINT8) Value;
   1177     Line->Size++;
   1178     High = FALSE;
   1179   } else {
   1180 
   1181     Old = Line->Buffer[FCol - 1];
   1182 
   1183     //
   1184     // always put the input to the low 4 bits
   1185     //
   1186     Old                     = (UINT8) (Old & 0x0f);
   1187     Old                     = (UINT8) (Old << 4);
   1188     Old                     = (UINT8) (Value + Old);
   1189     Line->Buffer[FCol - 1]  = Old;
   1190 
   1191     //
   1192     // at the low 4 bits of the last character of a full line
   1193     // so if no next line, need to create a new line
   1194     //
   1195     if (!High && FCol == 0x10) {
   1196 
   1197       HBufferImageOnlyLineNeedRefresh = FALSE;
   1198       HBufferImageNeedRefresh         = TRUE;
   1199 
   1200       if (Line->Link.ForwardLink == HBufferImage.ListHead) {
   1201         //
   1202         // last line
   1203         //
   1204         // create a new line
   1205         //
   1206         NewLine = HBufferImageCreateLine ();
   1207         if (NewLine == NULL) {
   1208           return EFI_OUT_OF_RESOURCES;
   1209         }
   1210         //
   1211         // end of NULL
   1212         //
   1213       }
   1214       //
   1215       // end of == ListHead
   1216       //
   1217     }
   1218     //
   1219     // end of == 0x10
   1220     //
   1221     // if already at end of this line, scroll it to the start of next line
   1222     //
   1223     if (FCol == 0x10 && !High) {
   1224       //
   1225       // definitely has next line
   1226       //
   1227       FRow++;
   1228       FCol  = 1;
   1229       High  = TRUE;
   1230     } else {
   1231       //
   1232       // if not at end of this line, just move to next column
   1233       //
   1234       if (!High) {
   1235         FCol++;
   1236       }
   1237 
   1238       if (High) {
   1239         High = FALSE;
   1240       } else {
   1241         High = TRUE;
   1242       }
   1243 
   1244     }
   1245     //
   1246     // end of ==FALSE
   1247     //
   1248   }
   1249   //
   1250   // move cursor to right
   1251   //
   1252   HBufferImageMovePosition (FRow, FCol, High);
   1253 
   1254   if (!HBufferImage.Modified) {
   1255     HBufferImage.Modified = TRUE;
   1256   }
   1257 
   1258   return EFI_SUCCESS;
   1259 }
   1260 
   1261 /**
   1262   Delete the previous character.
   1263 
   1264   @retval EFI_SUCCESS   The operationw as successful.
   1265 **/
   1266 EFI_STATUS
   1267 EFIAPI
   1268 HBufferImageDoBackspace (
   1269   VOID
   1270   )
   1271 {
   1272   HEFI_EDITOR_LINE  *Line;
   1273 
   1274   UINTN             FileColumn;
   1275   UINTN             FPos;
   1276   BOOLEAN           LastLine;
   1277 
   1278   //
   1279   // variable initialization
   1280   //
   1281   LastLine = FALSE;
   1282 
   1283   //
   1284   // already the first character
   1285   //
   1286   if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) {
   1287     return EFI_SUCCESS;
   1288   }
   1289 
   1290   FPos        = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
   1291 
   1292   FileColumn  = HBufferImage.BufferPosition.Column;
   1293 
   1294   Line        = HBufferImage.CurrentLine;
   1295   LastLine    = FALSE;
   1296   if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) {
   1297     LastLine = TRUE;
   1298   }
   1299 
   1300   HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);
   1301 
   1302   //
   1303   // if is the last line
   1304   // then only this line need to be refreshed
   1305   //
   1306   if (LastLine) {
   1307     HBufferImageNeedRefresh         = FALSE;
   1308     HBufferImageOnlyLineNeedRefresh = TRUE;
   1309   } else {
   1310     HBufferImageNeedRefresh         = TRUE;
   1311     HBufferImageOnlyLineNeedRefresh = FALSE;
   1312   }
   1313 
   1314   if (!HBufferImage.Modified) {
   1315     HBufferImage.Modified = TRUE;
   1316   }
   1317 
   1318   return EFI_SUCCESS;
   1319 }
   1320 
   1321 /**
   1322   ASCII key + Backspace + return.
   1323 
   1324   @param[in] Char               The input char.
   1325 
   1326   @retval EFI_SUCCESS           The operation was successful.
   1327   @retval EFI_LOAD_ERROR        A load error occured.
   1328   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
   1329 **/
   1330 EFI_STATUS
   1331 EFIAPI
   1332 HBufferImageDoCharInput (
   1333   IN  CHAR16  Char
   1334   )
   1335 {
   1336   EFI_STATUS  Status;
   1337 
   1338   Status = EFI_SUCCESS;
   1339 
   1340   switch (Char) {
   1341   case 0:
   1342     break;
   1343 
   1344   case 0x08:
   1345     Status = HBufferImageDoBackspace ();
   1346     break;
   1347 
   1348   case 0x09:
   1349   case 0x0a:
   1350   case 0x0d:
   1351     //
   1352     // Tabs, Returns are thought as nothing
   1353     //
   1354     break;
   1355 
   1356   default:
   1357     //
   1358     // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
   1359     //
   1360     if (Char > 127 || Char < 32) {
   1361       Status = StatusBarSetStatusString (L"Unknown Command");
   1362     } else {
   1363       Status = HBufferImageAddChar (Char);
   1364     }
   1365 
   1366     break;
   1367   }
   1368 
   1369   return Status;
   1370 }
   1371 
   1372 /**
   1373   Check user specified FileRow is above current screen.
   1374 
   1375   @param[in] FileRow  Row of file position ( start from 1 ).
   1376 
   1377   @retval TRUE   It is above the current screen.
   1378   @retval FALSE  It is not above the current screen.
   1379 
   1380 **/
   1381 BOOLEAN
   1382 HAboveCurrentScreen (
   1383   IN  UINTN FileRow
   1384   )
   1385 {
   1386   if (FileRow < HBufferImage.LowVisibleRow) {
   1387     return TRUE;
   1388   }
   1389 
   1390   return FALSE;
   1391 }
   1392 
   1393 /**
   1394   Check user specified FileRow is under current screen.
   1395 
   1396   @param[in] FileRow    Row of file position ( start from 1 ).
   1397 
   1398   @retval TRUE      It is under the current screen.
   1399   @retval FALSE     It is not under the current screen.
   1400 
   1401 **/
   1402 BOOLEAN
   1403 HUnderCurrentScreen (
   1404   IN  UINTN FileRow
   1405   )
   1406 {
   1407   if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) {
   1408     return TRUE;
   1409   }
   1410 
   1411   return FALSE;
   1412 }
   1413 
   1414 /**
   1415   According to cursor's file position, adjust screen display.
   1416 
   1417   @param[in] NewFilePosRow    Row of file position ( start from 1 ).
   1418   @param[in] NewFilePosCol    Column of file position ( start from 1 ).
   1419   @param[in] HighBits         Cursor will on high4 bits or low4 bits.
   1420 **/
   1421 VOID
   1422 HBufferImageMovePosition (
   1423   IN UINTN    NewFilePosRow,
   1424   IN UINTN    NewFilePosCol,
   1425   IN BOOLEAN  HighBits
   1426   )
   1427 {
   1428   INTN    RowGap;
   1429   UINTN   Abs;
   1430   BOOLEAN Above;
   1431   BOOLEAN Under;
   1432   UINTN   NewDisplayCol;
   1433 
   1434   //
   1435   // CALCULATE gap between current file position and new file position
   1436   //
   1437   RowGap                = NewFilePosRow - HBufferImage.BufferPosition.Row;
   1438 
   1439   Under                 = HUnderCurrentScreen (NewFilePosRow);
   1440   Above                 = HAboveCurrentScreen (NewFilePosRow);
   1441 
   1442   HBufferImage.HighBits = HighBits;
   1443 
   1444   //
   1445   // if is below current screen
   1446   //
   1447   if (Under) {
   1448     //
   1449     // display row will be unchanged
   1450     //
   1451     HBufferImage.BufferPosition.Row = NewFilePosRow;
   1452   } else {
   1453     if (Above) {
   1454       //
   1455       // has enough above line, so display row unchanged
   1456       // not has enough above lines, so the first line is
   1457       // at the first display line
   1458       //
   1459       if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {
   1460         HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;
   1461       }
   1462 
   1463       HBufferImage.BufferPosition.Row = NewFilePosRow;
   1464     } else {
   1465       //
   1466       // in current screen
   1467       //
   1468       HBufferImage.BufferPosition.Row = NewFilePosRow;
   1469       if (RowGap <= 0) {
   1470         Abs = (UINTN)ABS(RowGap);
   1471         HBufferImage.DisplayPosition.Row -= Abs;
   1472       } else {
   1473         HBufferImage.DisplayPosition.Row += RowGap;
   1474       }
   1475 
   1476     }
   1477   }
   1478 
   1479   HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);
   1480 
   1481   //
   1482   // always in current screen
   1483   //
   1484   HBufferImage.BufferPosition.Column  = NewFilePosCol;
   1485 
   1486   NewDisplayCol                       = 10 + (NewFilePosCol - 1) * 3;
   1487   if (NewFilePosCol > 0x8) {
   1488     NewDisplayCol++;
   1489   }
   1490 
   1491   if (!HighBits) {
   1492     NewDisplayCol++;
   1493   }
   1494 
   1495   HBufferImage.DisplayPosition.Column = NewDisplayCol;
   1496 
   1497   //
   1498   // let CurrentLine point to correct line;
   1499   //
   1500   HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);
   1501 
   1502 }
   1503 
   1504 /**
   1505   Scroll cursor to right.
   1506 
   1507   @retval EFI_SUCCESS   The operation was successful.
   1508 **/
   1509 EFI_STATUS
   1510 HBufferImageScrollRight (
   1511   VOID
   1512   )
   1513 {
   1514   HEFI_EDITOR_LINE  *Line;
   1515   UINTN             FRow;
   1516   UINTN             FCol;
   1517 
   1518   //
   1519   // scroll right will always move to the high4 bits of the next character
   1520   //
   1521   HBufferImageNeedRefresh         = FALSE;
   1522   HBufferImageOnlyLineNeedRefresh = FALSE;
   1523 
   1524   Line = HBufferImage.CurrentLine;
   1525 
   1526   FRow = HBufferImage.BufferPosition.Row;
   1527   FCol = HBufferImage.BufferPosition.Column;
   1528 
   1529   //
   1530   // this line is not full and no next line
   1531   //
   1532   if (FCol > Line->Size) {
   1533     return EFI_SUCCESS;
   1534   }
   1535   //
   1536   // if already at end of this line, scroll it to the start of next line
   1537   //
   1538   if (FCol == 0x10) {
   1539     //
   1540     // has next line
   1541     //
   1542     if (Line->Link.ForwardLink != HBufferImage.ListHead) {
   1543       FRow++;
   1544       FCol = 1;
   1545 
   1546     } else {
   1547       return EFI_SUCCESS;
   1548     }
   1549   } else {
   1550     //
   1551     // if not at end of this line, just move to next column
   1552     //
   1553     FCol++;
   1554 
   1555   }
   1556 
   1557   HBufferImageMovePosition (FRow, FCol, TRUE);
   1558 
   1559   return EFI_SUCCESS;
   1560 }
   1561 
   1562 /**
   1563   Scroll cursor to left.
   1564 
   1565   @retval EFI_SUCCESS   The operation was successful.
   1566 **/
   1567 EFI_STATUS
   1568 HBufferImageScrollLeft (
   1569   VOID
   1570   )
   1571 {
   1572 
   1573   HEFI_EDITOR_LINE  *Line;
   1574   UINTN             FRow;
   1575   UINTN             FCol;
   1576 
   1577   HBufferImageNeedRefresh         = FALSE;
   1578   HBufferImageOnlyLineNeedRefresh = FALSE;
   1579 
   1580   Line = HBufferImage.CurrentLine;
   1581 
   1582   FRow = HBufferImage.BufferPosition.Row;
   1583   FCol = HBufferImage.BufferPosition.Column;
   1584 
   1585   //
   1586   // if already at start of this line, so move to the end of previous line
   1587   //
   1588   if (FCol <= 1) {
   1589     //
   1590     // has previous line
   1591     //
   1592     if (Line->Link.BackLink != HBufferImage.ListHead) {
   1593       FRow--;
   1594       Line  = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   1595       FCol  = Line->Size;
   1596     } else {
   1597       return EFI_SUCCESS;
   1598     }
   1599   } else {
   1600     //
   1601     // if not at start of this line, just move to previous column
   1602     //
   1603     FCol--;
   1604   }
   1605 
   1606   HBufferImageMovePosition (FRow, FCol, TRUE);
   1607 
   1608   return EFI_SUCCESS;
   1609 }
   1610 
   1611 /**
   1612   Scroll cursor to the next line
   1613 
   1614   @retval EFI_SUCCESS   The operation was successful.
   1615 **/
   1616 EFI_STATUS
   1617 HBufferImageScrollDown (
   1618   VOID
   1619   )
   1620 {
   1621   HEFI_EDITOR_LINE  *Line;
   1622   UINTN             FRow;
   1623   UINTN             FCol;
   1624   BOOLEAN           HighBits;
   1625 
   1626   Line      = HBufferImage.CurrentLine;
   1627 
   1628   FRow      = HBufferImage.BufferPosition.Row;
   1629   FCol      = HBufferImage.BufferPosition.Column;
   1630   HighBits  = HBufferImage.HighBits;
   1631 
   1632   //
   1633   // has next line
   1634   //
   1635   if (Line->Link.ForwardLink != HBufferImage.ListHead) {
   1636     FRow++;
   1637     Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   1638 
   1639     //
   1640     // if the next line is not that long, so move to end of next line
   1641     //
   1642     if (FCol > Line->Size) {
   1643       FCol      = Line->Size + 1;
   1644       HighBits  = TRUE;
   1645     }
   1646 
   1647   } else {
   1648     return EFI_SUCCESS;
   1649   }
   1650 
   1651   HBufferImageMovePosition (FRow, FCol, HighBits);
   1652 
   1653   return EFI_SUCCESS;
   1654 }
   1655 
   1656 /**
   1657   Scroll cursor to previous line
   1658 
   1659   @retval EFI_SUCCESS   The operation was successful.
   1660 **/
   1661 EFI_STATUS
   1662 HBufferImageScrollUp (
   1663   VOID
   1664   )
   1665 {
   1666   HEFI_EDITOR_LINE  *Line;
   1667   UINTN             FRow;
   1668   UINTN             FCol;
   1669 
   1670   Line  = HBufferImage.CurrentLine;
   1671 
   1672   FRow  = HBufferImage.BufferPosition.Row;
   1673   FCol  = HBufferImage.BufferPosition.Column;
   1674 
   1675   //
   1676   // has previous line
   1677   //
   1678   if (Line->Link.BackLink != HBufferImage.ListHead) {
   1679     FRow--;
   1680 
   1681   } else {
   1682     return EFI_SUCCESS;
   1683   }
   1684 
   1685   HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
   1686 
   1687   return EFI_SUCCESS;
   1688 }
   1689 
   1690 /**
   1691   Scroll cursor to next page
   1692 
   1693   @retval EFI_SUCCESS   The operation was successful.
   1694 **/
   1695 EFI_STATUS
   1696 HBufferImagePageDown (
   1697   VOID
   1698   )
   1699 {
   1700   HEFI_EDITOR_LINE  *Line;
   1701   UINTN             FRow;
   1702   UINTN             FCol;
   1703   UINTN             Gap;
   1704   BOOLEAN           HighBits;
   1705 
   1706   Line      = HBufferImage.CurrentLine;
   1707 
   1708   FRow      = HBufferImage.BufferPosition.Row;
   1709   FCol      = HBufferImage.BufferPosition.Column;
   1710   HighBits  = HBufferImage.HighBits;
   1711 
   1712   //
   1713   // has next page
   1714   //
   1715   if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) {
   1716     Gap = (HMainEditor.ScreenSize.Row - 2);
   1717   } else {
   1718     //
   1719     // MOVE CURSOR TO LAST LINE
   1720     //
   1721     Gap = HBufferImage.NumLines - FRow;
   1722   }
   1723   //
   1724   // get correct line
   1725   //
   1726   Line = HMoveLine (Gap);
   1727 
   1728   //
   1729   // if that line, is not that long, so move to the end of that line
   1730   //
   1731   if (Line != NULL && FCol > Line->Size) {
   1732     FCol      = Line->Size + 1;
   1733     HighBits  = TRUE;
   1734   }
   1735 
   1736   FRow += Gap;
   1737 
   1738   HBufferImageMovePosition (FRow, FCol, HighBits);
   1739 
   1740   return EFI_SUCCESS;
   1741 }
   1742 
   1743 /**
   1744   Scroll cursor to previous page
   1745 
   1746   @retval EFI_SUCCESS   The operation was successful.
   1747 **/
   1748 EFI_STATUS
   1749 HBufferImagePageUp (
   1750   VOID
   1751   )
   1752 {
   1753   UINTN             FRow;
   1754   UINTN             FCol;
   1755   UINTN             Gap;
   1756   INTN              Retreat;
   1757 
   1758   FRow  = HBufferImage.BufferPosition.Row;
   1759   FCol  = HBufferImage.BufferPosition.Column;
   1760 
   1761   //
   1762   // has previous page
   1763   //
   1764   if (FRow > (HMainEditor.ScreenSize.Row - 2)) {
   1765     Gap = (HMainEditor.ScreenSize.Row - 2);
   1766   } else {
   1767     //
   1768     // the first line of file will displayed on the first line of screen
   1769     //
   1770     Gap = FRow - 1;
   1771   }
   1772 
   1773   Retreat = Gap;
   1774   Retreat = -Retreat;
   1775 
   1776   FRow -= Gap;
   1777 
   1778   HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
   1779 
   1780   return EFI_SUCCESS;
   1781 }
   1782 
   1783 /**
   1784   Scroll cursor to start of line
   1785 
   1786   @retval EFI_SUCCESS  The operation was successful.
   1787 **/
   1788 EFI_STATUS
   1789 HBufferImageHome (
   1790   VOID
   1791   )
   1792 {
   1793   UINTN             FRow;
   1794   UINTN             FCol;
   1795   BOOLEAN           HighBits;
   1796 
   1797   //
   1798   // curosr will at the high bit
   1799   //
   1800   FRow      = HBufferImage.BufferPosition.Row;
   1801   FCol      = 1;
   1802   HighBits  = TRUE;
   1803 
   1804   //
   1805   // move cursor position
   1806   //
   1807   HBufferImageMovePosition (FRow, FCol, HighBits);
   1808 
   1809   return EFI_SUCCESS;
   1810 }
   1811 
   1812 /**
   1813   Scroll cursor to end of line.
   1814 
   1815   @retval EFI_SUCCESS  Teh operation was successful.
   1816 **/
   1817 EFI_STATUS
   1818 HBufferImageEnd (
   1819   VOID
   1820   )
   1821 {
   1822   HEFI_EDITOR_LINE  *Line;
   1823   UINTN             FRow;
   1824   UINTN             FCol;
   1825   BOOLEAN           HighBits;
   1826 
   1827   //
   1828   // need refresh mouse
   1829   //
   1830   HBufferImageMouseNeedRefresh  = TRUE;
   1831 
   1832   Line                          = HBufferImage.CurrentLine;
   1833 
   1834   FRow                          = HBufferImage.BufferPosition.Row;
   1835 
   1836   if (Line->Size == 0x10) {
   1837     FCol      = Line->Size;
   1838     HighBits  = FALSE;
   1839   } else {
   1840     FCol      = Line->Size + 1;
   1841     HighBits  = TRUE;
   1842   }
   1843   //
   1844   // move cursor position
   1845   //
   1846   HBufferImageMovePosition (FRow, FCol, HighBits);
   1847 
   1848   return EFI_SUCCESS;
   1849 }
   1850 
   1851 /**
   1852   Get the size of the open buffer.
   1853 
   1854   @retval The size in bytes.
   1855 **/
   1856 UINTN
   1857 HBufferImageGetTotalSize (
   1858   VOID
   1859   )
   1860 {
   1861   UINTN             Size;
   1862 
   1863   HEFI_EDITOR_LINE  *Line;
   1864 
   1865   //
   1866   // calculate the total size of whole line list's buffer
   1867   //
   1868   if (HBufferImage.Lines == NULL) {
   1869     return 0;
   1870   }
   1871 
   1872   Line = CR (
   1873           HBufferImage.ListHead->BackLink,
   1874           HEFI_EDITOR_LINE,
   1875           Link,
   1876           EFI_EDITOR_LINE_LIST
   1877           );
   1878   //
   1879   // one line at most 0x10
   1880   //
   1881   Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;
   1882 
   1883   return Size;
   1884 }
   1885 
   1886 /**
   1887   Delete character from buffer.
   1888 
   1889   @param[in] Pos      Position, Pos starting from 0.
   1890   @param[in] Count    The Count of characters to delete.
   1891   @param[out] DeleteBuffer    The DeleteBuffer.
   1892 
   1893   @retval EFI_SUCCESS Success
   1894 **/
   1895 EFI_STATUS
   1896 HBufferImageDeleteCharacterFromBuffer (
   1897   IN  UINTN         Pos,
   1898   IN  UINTN         Count,
   1899   OUT UINT8         *DeleteBuffer
   1900   )
   1901 {
   1902   UINTN             Index;
   1903 
   1904   VOID              *Buffer;
   1905   UINT8             *BufferPtr;
   1906   UINTN             Size;
   1907 
   1908   HEFI_EDITOR_LINE  *Line;
   1909   LIST_ENTRY    *Link;
   1910 
   1911   UINTN             OldFCol;
   1912   UINTN             OldFRow;
   1913   UINTN             OldPos;
   1914 
   1915   UINTN             NewPos;
   1916 
   1917   EFI_STATUS        Status;
   1918 
   1919   Size      = HBufferImageGetTotalSize ();
   1920 
   1921   if (Size < Count) {
   1922     return EFI_LOAD_ERROR;
   1923   }
   1924 
   1925   if (Size == 0) {
   1926     return EFI_SUCCESS;
   1927   }
   1928 
   1929   //
   1930   // relocate all the HBufferImage fields
   1931   //
   1932   OldFRow = HBufferImage.BufferPosition.Row;
   1933   OldFCol = HBufferImage.BufferPosition.Column;
   1934   OldPos  = (OldFRow - 1) * 0x10 + OldFCol - 1;
   1935 
   1936   if (Pos > 0) {
   1937     //
   1938     // has character before it,
   1939     // so locate according to block's previous character
   1940     //
   1941     NewPos = Pos - 1;
   1942 
   1943   } else {
   1944     //
   1945     // has no character before it,
   1946     // so locate according to block's next character
   1947     //
   1948     NewPos = 0;
   1949   }
   1950 
   1951   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   1952 
   1953   Buffer = AllocateZeroPool (Size);
   1954   if (Buffer == NULL) {
   1955     return EFI_OUT_OF_RESOURCES;
   1956   }
   1957 
   1958   HBufferImageListToBuffer (Buffer, Size);
   1959 
   1960   BufferPtr = (UINT8 *) Buffer;
   1961 
   1962   //
   1963   // pass deleted buffer out
   1964   //
   1965   if (DeleteBuffer != NULL) {
   1966     for (Index = 0; Index < Count; Index++) {
   1967       DeleteBuffer[Index] = BufferPtr[Pos + Index];
   1968     }
   1969   }
   1970   //
   1971   // delete the part from Pos
   1972   //
   1973   for (Index = Pos; Index < Size - Count; Index++) {
   1974     BufferPtr[Index] = BufferPtr[Index + Count];
   1975   }
   1976 
   1977   Size -= Count;
   1978 
   1979   HBufferImageFreeLines ();
   1980 
   1981   Status = HBufferImageBufferToList (Buffer, Size);
   1982   FreePool (Buffer);
   1983 
   1984   if (EFI_ERROR (Status)) {
   1985     return Status;
   1986   }
   1987 
   1988   Link = HMainEditor.BufferImage->ListHead->ForwardLink;
   1989   for (Index = 0; Index < NewPos / 0x10; Index++) {
   1990     Link = Link->ForwardLink;
   1991   }
   1992 
   1993   Line                      = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   1994   HBufferImage.CurrentLine  = Line;
   1995 
   1996   //
   1997   // if current cursor position if inside select area
   1998   // then move it to the block's NEXT character
   1999   //
   2000   if (OldPos >= Pos && OldPos < (Pos + Count)) {
   2001     NewPos = Pos;
   2002   } else {
   2003     if (OldPos < Pos) {
   2004       NewPos = OldPos;
   2005     } else {
   2006       NewPos = OldPos - Count;
   2007     }
   2008   }
   2009 
   2010   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   2011 
   2012   return EFI_SUCCESS;
   2013 }
   2014 
   2015 /**
   2016   Add character to buffer, add before pos.
   2017 
   2018   @param[in] Pos        Position, Pos starting from 0.
   2019   @param[in] Count      Count of characters to add.
   2020   @param[in] AddBuffer  Add buffer.
   2021 
   2022   @retval EFI_SUCCESS   Success.
   2023 **/
   2024 EFI_STATUS
   2025 HBufferImageAddCharacterToBuffer (
   2026   IN  UINTN          Pos,
   2027   IN  UINTN          Count,
   2028   IN  UINT8          *AddBuffer
   2029   )
   2030 {
   2031   INTN              Index;
   2032 
   2033   VOID              *Buffer;
   2034   UINT8             *BufferPtr;
   2035   UINTN             Size;
   2036 
   2037   HEFI_EDITOR_LINE  *Line;
   2038 
   2039   LIST_ENTRY    *Link;
   2040 
   2041   UINTN             OldFCol;
   2042   UINTN             OldFRow;
   2043   UINTN             OldPos;
   2044 
   2045   UINTN             NewPos;
   2046 
   2047   Size      = HBufferImageGetTotalSize ();
   2048 
   2049   //
   2050   // relocate all the HBufferImage fields
   2051   //
   2052   OldFRow = HBufferImage.BufferPosition.Row;
   2053   OldFCol = HBufferImage.BufferPosition.Column;
   2054   OldPos  = (OldFRow - 1) * 0x10 + OldFCol - 1;
   2055 
   2056   //
   2057   // move cursor before Pos
   2058   //
   2059   if (Pos > 0) {
   2060     NewPos = Pos - 1;
   2061   } else {
   2062     NewPos = 0;
   2063   }
   2064 
   2065   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   2066 
   2067   Buffer = AllocateZeroPool (Size + Count);
   2068   if (Buffer == NULL) {
   2069     return EFI_OUT_OF_RESOURCES;
   2070   }
   2071 
   2072   HBufferImageListToBuffer (Buffer, Size);
   2073 
   2074   BufferPtr = (UINT8 *) Buffer;
   2075 
   2076   //
   2077   // get a place to add
   2078   //
   2079   for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) {
   2080     BufferPtr[Index] = BufferPtr[Index - Count];
   2081   }
   2082   //
   2083   // add the buffer
   2084   //
   2085   for (Index = (INTN) 0; Index < (INTN) Count; Index++) {
   2086     BufferPtr[Index + Pos] = AddBuffer[Index];
   2087   }
   2088 
   2089   Size += Count;
   2090 
   2091   HBufferImageFreeLines ();
   2092 
   2093   HBufferImageBufferToList (Buffer, Size);
   2094 
   2095   FreePool (Buffer);
   2096 
   2097   Link = HMainEditor.BufferImage->ListHead->ForwardLink;
   2098   for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) {
   2099     Link = Link->ForwardLink;
   2100   }
   2101 
   2102   Line                      = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   2103   HBufferImage.CurrentLine  = Line;
   2104 
   2105   if (OldPos >= Pos) {
   2106     NewPos = OldPos + Count;
   2107   } else {
   2108     NewPos = OldPos;
   2109   }
   2110 
   2111   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   2112 
   2113   return EFI_SUCCESS;
   2114 }
   2115 
   2116 /**
   2117   Delete current character from line.
   2118 
   2119   @retval EFI_SUCCESS   The operationw as successful.
   2120 **/
   2121 EFI_STATUS
   2122 EFIAPI
   2123 HBufferImageDoDelete (
   2124   VOID
   2125   )
   2126 {
   2127 
   2128   HEFI_EDITOR_LINE  *Line;
   2129 
   2130   BOOLEAN           LastLine;
   2131   UINTN             FileColumn;
   2132   UINTN             FPos;
   2133 
   2134   FPos        = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
   2135 
   2136   FileColumn  = HBufferImage.BufferPosition.Column;
   2137 
   2138   Line        = HBufferImage.CurrentLine;
   2139 
   2140   //
   2141   // if beyond the last character
   2142   //
   2143   if (FileColumn > Line->Size) {
   2144     return EFI_SUCCESS;
   2145   }
   2146 
   2147   LastLine = FALSE;
   2148   if (Line->Link.ForwardLink == HBufferImage.ListHead) {
   2149     LastLine = TRUE;
   2150   }
   2151 
   2152   HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);
   2153 
   2154   //
   2155   // if is the last line
   2156   // then only this line need to be refreshed
   2157   //
   2158   if (LastLine) {
   2159     HBufferImageNeedRefresh         = FALSE;
   2160     HBufferImageOnlyLineNeedRefresh = TRUE;
   2161   } else {
   2162     HBufferImageNeedRefresh         = TRUE;
   2163     HBufferImageOnlyLineNeedRefresh = FALSE;
   2164   }
   2165 
   2166   if (!HBufferImage.Modified) {
   2167     HBufferImage.Modified = TRUE;
   2168   }
   2169 
   2170   return EFI_SUCCESS;
   2171 }
   2172 
   2173 /**
   2174   Change the raw buffer to a list of lines for the UI.
   2175 
   2176   @param[in] Buffer   The pointer to the buffer to fill.
   2177   @param[in] Bytes    The size of the buffer in bytes.
   2178 
   2179   @retval EFI_SUCCESS           The operation was successful.
   2180   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
   2181 **/
   2182 EFI_STATUS
   2183 EFIAPI
   2184 HBufferImageBufferToList (
   2185   IN VOID   *Buffer,
   2186   IN UINTN  Bytes
   2187   )
   2188 {
   2189   UINTN             TempI;
   2190   UINTN             TempJ;
   2191   UINTN             Left;
   2192   HEFI_EDITOR_LINE  *Line;
   2193   UINT8             *BufferPtr;
   2194 
   2195   TempI         = 0;
   2196   Left      = 0;
   2197   BufferPtr = (UINT8 *) Buffer;
   2198 
   2199   //
   2200   // parse file content line by line
   2201   //
   2202   while (TempI < Bytes) {
   2203     if (Bytes - TempI >= 0x10) {
   2204       Left = 0x10;
   2205     } else {
   2206       Left = Bytes - TempI;
   2207     }
   2208 
   2209     //
   2210     // allocate a new line
   2211     //
   2212     Line = HBufferImageCreateLine ();
   2213     if (Line == NULL) {
   2214       return EFI_OUT_OF_RESOURCES;
   2215     }
   2216 
   2217     Line->Size = Left;
   2218 
   2219     for (TempJ = 0; TempJ < Left; TempJ++) {
   2220       Line->Buffer[TempJ] = BufferPtr[TempI];
   2221       TempI++;
   2222     }
   2223 
   2224   }
   2225 
   2226   //
   2227   // last line is a full line, SO create a new line
   2228   //
   2229   if (Left == 0x10 || Bytes == 0) {
   2230     Line = HBufferImageCreateLine ();
   2231     if (Line == NULL) {
   2232       return EFI_OUT_OF_RESOURCES;
   2233     }
   2234   }
   2235 
   2236   return EFI_SUCCESS;
   2237 }
   2238 
   2239 /**
   2240   Change the list of lines from the UI to a raw buffer.
   2241 
   2242   @param[in] Buffer   The pointer to the buffer to fill.
   2243   @param[in] Bytes    The size of the buffer in bytes.
   2244 
   2245   @retval EFI_SUCCESS   The operation was successful.
   2246 **/
   2247 EFI_STATUS
   2248 EFIAPI
   2249 HBufferImageListToBuffer (
   2250   IN VOID   *Buffer,
   2251   IN UINTN  Bytes
   2252   )
   2253 {
   2254   UINTN             Count;
   2255   UINTN             Index;
   2256   HEFI_EDITOR_LINE  *Line;
   2257   LIST_ENTRY    *Link;
   2258   UINT8             *BufferPtr;
   2259 
   2260   //
   2261   // change the line list to a large buffer
   2262   //
   2263   if (HBufferImage.Lines == NULL) {
   2264     return EFI_SUCCESS;
   2265   }
   2266 
   2267   Link      = &HBufferImage.Lines->Link;
   2268   Count     = 0;
   2269   BufferPtr = (UINT8 *) Buffer;
   2270 
   2271   //
   2272   // deal line by line
   2273   //
   2274   while (Link != HBufferImage.ListHead) {
   2275 
   2276     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   2277 
   2278     //@todo shouldn't this be an error???
   2279     if (Count + Line->Size > Bytes) {
   2280       return EFI_SUCCESS;
   2281     }
   2282 
   2283     for (Index = 0; Index < Line->Size; Index++) {
   2284       BufferPtr[Index] = Line->Buffer[Index];
   2285     }
   2286 
   2287     Count += Line->Size;
   2288     BufferPtr += Line->Size;
   2289 
   2290     Link = Link->ForwardLink;
   2291   }
   2292 
   2293   return EFI_SUCCESS;
   2294 }
   2295 
   2296 /**
   2297   Move the mouse in the image buffer.
   2298 
   2299   @param[in] TextX    The x-coordinate.
   2300   @param[in] TextY    The y-coordinate.
   2301 **/
   2302 VOID
   2303 EFIAPI
   2304 HBufferImageAdjustMousePosition (
   2305   IN INT32 TextX,
   2306   IN INT32 TextY
   2307   )
   2308 {
   2309   UINTN TempX;
   2310   UINTN TempY;
   2311   UINTN AbsX;
   2312   UINTN AbsY;
   2313 
   2314   //
   2315   // TextX and TextY is mouse movement data returned by mouse driver
   2316   // This function will change it to MousePosition
   2317   //
   2318   //
   2319   // get absolute TempX value
   2320   //
   2321   if (TextX >= 0) {
   2322     AbsX = TextX;
   2323   } else {
   2324     AbsX = -TextX;
   2325   }
   2326   //
   2327   // get absolute TempY value
   2328   //
   2329   if (TextY >= 0) {
   2330     AbsY = TextY;
   2331   } else {
   2332     AbsY = -TextY;
   2333   }
   2334 
   2335   TempX = HBufferImage.MousePosition.Column;
   2336   TempY = HBufferImage.MousePosition.Row;
   2337 
   2338   if (TextX >= 0) {
   2339     TempX += TextX;
   2340   } else {
   2341     if (TempX >= AbsX) {
   2342       TempX -= AbsX;
   2343     } else {
   2344       TempX = 0;
   2345     }
   2346   }
   2347 
   2348   if (TextY >= 0) {
   2349     TempY += TextY;
   2350   } else {
   2351     if (TempY >= AbsY) {
   2352       TempY -= AbsY;
   2353     } else {
   2354       TempY = 0;
   2355     }
   2356   }
   2357   //
   2358   // check whether new mouse column position is beyond screen
   2359   // if not, adjust it
   2360   //
   2361   if (TempX >= 10 && TempX <= (10 + 0x10 * 3 - 1)) {
   2362     HBufferImage.MousePosition.Column = TempX;
   2363   } else if (TempX < 10) {
   2364     HBufferImage.MousePosition.Column = 10;
   2365   } else if (TempX > (10 + 0x10 * 3 - 1)) {
   2366     HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;
   2367   }
   2368   //
   2369   // check whether new mouse row position is beyond screen
   2370   // if not, adjust it
   2371   //
   2372   if (TempY >= 2 && TempY <= (HMainEditor.ScreenSize.Row - 1)) {
   2373     HBufferImage.MousePosition.Row = TempY;
   2374   } else if (TempY < 2) {
   2375     HBufferImage.MousePosition.Row = 2;
   2376   } else if (TempY > (HMainEditor.ScreenSize.Row - 1)) {
   2377     HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1);
   2378   }
   2379 
   2380 }
   2381 
   2382 /**
   2383   Dispatch input to different handler
   2384 
   2385   @param[in] Key    The input key:
   2386                      the keys can be:
   2387                        ASCII KEY
   2388                         Backspace/Delete
   2389                         Direction key: up/down/left/right/pgup/pgdn
   2390                         Home/End
   2391                         INS
   2392 
   2393   @retval EFI_SUCCESS           The operation was successful.
   2394   @retval EFI_LOAD_ERROR        A load error occured.
   2395   @retval EFI_OUT_OF_RESOURCES  A Memory allocation failed.
   2396 **/
   2397 EFI_STATUS
   2398 HBufferImageHandleInput (
   2399   IN  EFI_INPUT_KEY *Key
   2400   )
   2401 {
   2402   EFI_STATUS  Status;
   2403 
   2404   Status = EFI_SUCCESS;
   2405 
   2406   switch (Key->ScanCode) {
   2407   //
   2408   // ordinary key
   2409   //
   2410   case SCAN_NULL:
   2411     Status = HBufferImageDoCharInput (Key->UnicodeChar);
   2412     break;
   2413 
   2414   //
   2415   // up arrow
   2416   //
   2417   case SCAN_UP:
   2418     Status = HBufferImageScrollUp ();
   2419     break;
   2420 
   2421   //
   2422   // down arrow
   2423   //
   2424   case SCAN_DOWN:
   2425     Status = HBufferImageScrollDown ();
   2426     break;
   2427 
   2428   //
   2429   // right arrow
   2430   //
   2431   case SCAN_RIGHT:
   2432     Status = HBufferImageScrollRight ();
   2433     break;
   2434 
   2435   //
   2436   // left arrow
   2437   //
   2438   case SCAN_LEFT:
   2439     Status = HBufferImageScrollLeft ();
   2440     break;
   2441 
   2442   //
   2443   // page up
   2444   //
   2445   case SCAN_PAGE_UP:
   2446     Status = HBufferImagePageUp ();
   2447     break;
   2448 
   2449   //
   2450   // page down
   2451   //
   2452   case SCAN_PAGE_DOWN:
   2453     Status = HBufferImagePageDown ();
   2454     break;
   2455 
   2456   //
   2457   // delete
   2458   //
   2459   case SCAN_DELETE:
   2460     Status = HBufferImageDoDelete ();
   2461     break;
   2462 
   2463   //
   2464   // home
   2465   //
   2466   case SCAN_HOME:
   2467     Status = HBufferImageHome ();
   2468     break;
   2469 
   2470   //
   2471   // end
   2472   //
   2473   case SCAN_END:
   2474     Status = HBufferImageEnd ();
   2475     break;
   2476 
   2477   default:
   2478     Status = StatusBarSetStatusString (L"Unknown Command");
   2479     break;
   2480   }
   2481 
   2482   return Status;
   2483 }
   2484 
   2485