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 HBufferImageRead (
    910   IN CONST CHAR16                   *FileName,
    911   IN CONST CHAR16                   *DiskName,
    912   IN UINTN                          DiskOffset,
    913   IN UINTN                          DiskSize,
    914   IN UINTN                          MemOffset,
    915   IN UINTN                          MemSize,
    916   IN EDIT_FILE_TYPE                 BufferType,
    917   IN BOOLEAN                        Recover
    918   )
    919 {
    920   EFI_STATUS                      Status;
    921   EDIT_FILE_TYPE                  BufferTypeBackup;
    922 
    923   //
    924   // variable initialization
    925   //
    926   Status = EFI_SUCCESS;
    927   HBufferImage.BufferType = BufferType;
    928 
    929   //
    930   // three types of buffer supported
    931   //   file buffer
    932   //   disk buffer
    933   //   memory buffer
    934   //
    935   BufferTypeBackup = HBufferImage.BufferType;
    936 
    937   switch (BufferType) {
    938   case FileTypeFileBuffer:
    939     Status = HFileImageRead (FileName, Recover);
    940     break;
    941 
    942   case FileTypeDiskBuffer:
    943     Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);
    944     break;
    945 
    946   case FileTypeMemBuffer:
    947     Status = HMemImageRead (MemOffset, MemSize, Recover);
    948     break;
    949 
    950   default:
    951     Status = EFI_NOT_FOUND;
    952     break;
    953   }
    954 
    955   if (EFI_ERROR (Status)) {
    956     HBufferImage.BufferType = BufferTypeBackup;
    957   }
    958 
    959   return Status;
    960 }
    961 
    962 /**
    963   Save the current image.
    964 
    965   @param[in] FileName     Pointer to the file name.  OPTIONAL and ignored if not FileTypeFileBuffer.
    966   @param[in] DiskName     Pointer to the disk name.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    967   @param[in] DiskOffset   Offset into the disk.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    968   @param[in] DiskSize     Size of the disk buffer.  OPTIONAL and ignored if not FileTypeDiskBuffer.
    969   @param[in] MemOffset    Offset into the Memory.  OPTIONAL and ignored if not FileTypeMemBuffer.
    970   @param[in] MemSize      Size of the Memory buffer.  OPTIONAL and ignored if not FileTypeMemBuffer.
    971   @param[in] BufferType   The type of buffer to save.  IGNORED.
    972 
    973   @return EFI_SUCCESS     The operation was successful.
    974 **/
    975 EFI_STATUS
    976 HBufferImageSave (
    977   IN CHAR16                         *FileName,
    978   IN CHAR16                         *DiskName,
    979   IN UINTN                          DiskOffset,
    980   IN UINTN                          DiskSize,
    981   IN UINTN                          MemOffset,
    982   IN UINTN                          MemSize,
    983   IN EDIT_FILE_TYPE                 BufferType
    984   )
    985 {
    986   EFI_STATUS                      Status;
    987   EDIT_FILE_TYPE                  BufferTypeBackup;
    988 
    989   //
    990   // variable initialization
    991   //
    992   Status            = EFI_SUCCESS;
    993   BufferTypeBackup  = HBufferImage.BufferType;
    994 
    995   switch (HBufferImage.BufferType) {
    996   //
    997   // file buffer
    998   //
    999   case FileTypeFileBuffer:
   1000     Status = HFileImageSave (FileName);
   1001     break;
   1002 
   1003   //
   1004   // disk buffer
   1005   //
   1006   case FileTypeDiskBuffer:
   1007     Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);
   1008     break;
   1009 
   1010   //
   1011   // memory buffer
   1012   //
   1013   case FileTypeMemBuffer:
   1014     Status = HMemImageSave (MemOffset, MemSize);
   1015     break;
   1016 
   1017   default:
   1018     Status = EFI_NOT_FOUND;
   1019     break;
   1020   }
   1021 
   1022   if (EFI_ERROR (Status)) {
   1023     HBufferImage.BufferType = BufferTypeBackup;
   1024   }
   1025 
   1026   return Status;
   1027 }
   1028 
   1029 /**
   1030   Create a new line and append it to the line list.
   1031     Fields affected:
   1032     NumLines
   1033     Lines
   1034 
   1035   @retval NULL    create line failed.
   1036   @return         the line created.
   1037 
   1038 **/
   1039 HEFI_EDITOR_LINE *
   1040 HBufferImageCreateLine (
   1041   VOID
   1042   )
   1043 {
   1044   HEFI_EDITOR_LINE  *Line;
   1045 
   1046   //
   1047   // allocate for line structure
   1048   //
   1049   Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));
   1050   if (Line == NULL) {
   1051     return NULL;
   1052   }
   1053 
   1054   Line->Signature = EFI_EDITOR_LINE_LIST;
   1055   Line->Size      = 0;
   1056 
   1057   HBufferImage.NumLines++;
   1058 
   1059   //
   1060   // insert to line list
   1061   //
   1062   InsertTailList (HBufferImage.ListHead, &Line->Link);
   1063 
   1064   if (HBufferImage.Lines == NULL) {
   1065     HBufferImage.Lines = CR (
   1066                           HBufferImage.ListHead->ForwardLink,
   1067                           HEFI_EDITOR_LINE,
   1068                           Link,
   1069                           EFI_EDITOR_LINE_LIST
   1070                           );
   1071   }
   1072 
   1073   return Line;
   1074 }
   1075 
   1076 /**
   1077   Free the current image.
   1078 
   1079   @retval EFI_SUCCESS   The operation was successful.
   1080 **/
   1081 EFI_STATUS
   1082 HBufferImageFree (
   1083   VOID
   1084   )
   1085 {
   1086   //
   1087   // free all lines
   1088   //
   1089   HBufferImageFreeLines ();
   1090 
   1091   return EFI_SUCCESS;
   1092 }
   1093 
   1094 /**
   1095   change char to int value based on Hex.
   1096 
   1097   @param[in] Char     The input char.
   1098 
   1099   @return The character's index value.
   1100   @retval -1  The operation failed.
   1101 **/
   1102 INTN
   1103 HBufferImageCharToHex (
   1104   IN CHAR16 Char
   1105   )
   1106 {
   1107   //
   1108   // change the character to hex
   1109   //
   1110   if (Char >= L'0' && Char <= L'9') {
   1111     return (INTN) (Char - L'0');
   1112   }
   1113 
   1114   if (Char >= L'a' && Char <= L'f') {
   1115     return (INTN) (Char - L'a' + 10);
   1116   }
   1117 
   1118   if (Char >= L'A' && Char <= L'F') {
   1119     return (INTN) (Char - L'A' + 10);
   1120   }
   1121 
   1122   return -1;
   1123 }
   1124 
   1125 /**
   1126   Add character.
   1127 
   1128   @param[in] Char -- input char.
   1129 
   1130   @retval EFI_SUCCESS             The operation was successful.
   1131   @retval EFI_OUT_OF_RESOURCES    A memory allocation failed.
   1132 **/
   1133 EFI_STATUS
   1134 HBufferImageAddChar (
   1135   IN  CHAR16  Char
   1136   )
   1137 {
   1138   HEFI_EDITOR_LINE  *Line;
   1139   HEFI_EDITOR_LINE  *NewLine;
   1140   INTN              Value;
   1141   UINT8             Old;
   1142   UINTN             FRow;
   1143   UINTN             FCol;
   1144   BOOLEAN           High;
   1145 
   1146   Value = HBufferImageCharToHex (Char);
   1147 
   1148   //
   1149   // invalid input
   1150   //
   1151   if (Value == -1) {
   1152     return EFI_SUCCESS;
   1153   }
   1154 
   1155   Line  = HBufferImage.CurrentLine;
   1156   FRow  = HBufferImage.BufferPosition.Row;
   1157   FCol  = HBufferImage.BufferPosition.Column;
   1158   High  = HBufferImage.HighBits;
   1159 
   1160   //
   1161   // only needs to refresh current line
   1162   //
   1163   HBufferImageOnlyLineNeedRefresh = TRUE;
   1164 
   1165   //
   1166   // not a full line and beyond the last character
   1167   //
   1168   if (FCol > Line->Size) {
   1169     //
   1170     // cursor always at high 4 bits
   1171     // and always put input to the low 4 bits
   1172     //
   1173     Line->Buffer[Line->Size] = (UINT8) Value;
   1174     Line->Size++;
   1175     High = FALSE;
   1176   } else {
   1177 
   1178     Old = Line->Buffer[FCol - 1];
   1179 
   1180     //
   1181     // always put the input to the low 4 bits
   1182     //
   1183     Old                     = (UINT8) (Old & 0x0f);
   1184     Old                     = (UINT8) (Old << 4);
   1185     Old                     = (UINT8) (Value + Old);
   1186     Line->Buffer[FCol - 1]  = Old;
   1187 
   1188     //
   1189     // at the low 4 bits of the last character of a full line
   1190     // so if no next line, need to create a new line
   1191     //
   1192     if (!High && FCol == 0x10) {
   1193 
   1194       HBufferImageOnlyLineNeedRefresh = FALSE;
   1195       HBufferImageNeedRefresh         = TRUE;
   1196 
   1197       if (Line->Link.ForwardLink == HBufferImage.ListHead) {
   1198         //
   1199         // last line
   1200         //
   1201         // create a new line
   1202         //
   1203         NewLine = HBufferImageCreateLine ();
   1204         if (NewLine == NULL) {
   1205           return EFI_OUT_OF_RESOURCES;
   1206         }
   1207         //
   1208         // end of NULL
   1209         //
   1210       }
   1211       //
   1212       // end of == ListHead
   1213       //
   1214     }
   1215     //
   1216     // end of == 0x10
   1217     //
   1218     // if already at end of this line, scroll it to the start of next line
   1219     //
   1220     if (FCol == 0x10 && !High) {
   1221       //
   1222       // definitely has next line
   1223       //
   1224       FRow++;
   1225       FCol  = 1;
   1226       High  = TRUE;
   1227     } else {
   1228       //
   1229       // if not at end of this line, just move to next column
   1230       //
   1231       if (!High) {
   1232         FCol++;
   1233       }
   1234 
   1235       if (High) {
   1236         High = FALSE;
   1237       } else {
   1238         High = TRUE;
   1239       }
   1240 
   1241     }
   1242     //
   1243     // end of ==FALSE
   1244     //
   1245   }
   1246   //
   1247   // move cursor to right
   1248   //
   1249   HBufferImageMovePosition (FRow, FCol, High);
   1250 
   1251   if (!HBufferImage.Modified) {
   1252     HBufferImage.Modified = TRUE;
   1253   }
   1254 
   1255   return EFI_SUCCESS;
   1256 }
   1257 
   1258 /**
   1259   Delete the previous character.
   1260 
   1261   @retval EFI_SUCCESS   The operationw as successful.
   1262 **/
   1263 EFI_STATUS
   1264 HBufferImageDoBackspace (
   1265   VOID
   1266   )
   1267 {
   1268   HEFI_EDITOR_LINE  *Line;
   1269 
   1270   UINTN             FileColumn;
   1271   UINTN             FPos;
   1272   BOOLEAN           LastLine;
   1273 
   1274   //
   1275   // variable initialization
   1276   //
   1277   LastLine = FALSE;
   1278 
   1279   //
   1280   // already the first character
   1281   //
   1282   if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) {
   1283     return EFI_SUCCESS;
   1284   }
   1285 
   1286   FPos        = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
   1287 
   1288   FileColumn  = HBufferImage.BufferPosition.Column;
   1289 
   1290   Line        = HBufferImage.CurrentLine;
   1291   LastLine    = FALSE;
   1292   if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) {
   1293     LastLine = TRUE;
   1294   }
   1295 
   1296   HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);
   1297 
   1298   //
   1299   // if is the last line
   1300   // then only this line need to be refreshed
   1301   //
   1302   if (LastLine) {
   1303     HBufferImageNeedRefresh         = FALSE;
   1304     HBufferImageOnlyLineNeedRefresh = TRUE;
   1305   } else {
   1306     HBufferImageNeedRefresh         = TRUE;
   1307     HBufferImageOnlyLineNeedRefresh = FALSE;
   1308   }
   1309 
   1310   if (!HBufferImage.Modified) {
   1311     HBufferImage.Modified = TRUE;
   1312   }
   1313 
   1314   return EFI_SUCCESS;
   1315 }
   1316 
   1317 /**
   1318   ASCII key + Backspace + return.
   1319 
   1320   @param[in] Char               The input char.
   1321 
   1322   @retval EFI_SUCCESS           The operation was successful.
   1323   @retval EFI_LOAD_ERROR        A load error occured.
   1324   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
   1325 **/
   1326 EFI_STATUS
   1327 HBufferImageDoCharInput (
   1328   IN  CHAR16  Char
   1329   )
   1330 {
   1331   EFI_STATUS  Status;
   1332 
   1333   Status = EFI_SUCCESS;
   1334 
   1335   switch (Char) {
   1336   case 0:
   1337     break;
   1338 
   1339   case 0x08:
   1340     Status = HBufferImageDoBackspace ();
   1341     break;
   1342 
   1343   case 0x09:
   1344   case 0x0a:
   1345   case 0x0d:
   1346     //
   1347     // Tabs, Returns are thought as nothing
   1348     //
   1349     break;
   1350 
   1351   default:
   1352     //
   1353     // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
   1354     //
   1355     if (Char > 127 || Char < 32) {
   1356       Status = StatusBarSetStatusString (L"Unknown Command");
   1357     } else {
   1358       Status = HBufferImageAddChar (Char);
   1359     }
   1360 
   1361     break;
   1362   }
   1363 
   1364   return Status;
   1365 }
   1366 
   1367 /**
   1368   Check user specified FileRow is above current screen.
   1369 
   1370   @param[in] FileRow  Row of file position ( start from 1 ).
   1371 
   1372   @retval TRUE   It is above the current screen.
   1373   @retval FALSE  It is not above the current screen.
   1374 
   1375 **/
   1376 BOOLEAN
   1377 HAboveCurrentScreen (
   1378   IN  UINTN FileRow
   1379   )
   1380 {
   1381   if (FileRow < HBufferImage.LowVisibleRow) {
   1382     return TRUE;
   1383   }
   1384 
   1385   return FALSE;
   1386 }
   1387 
   1388 /**
   1389   Check user specified FileRow is under current screen.
   1390 
   1391   @param[in] FileRow    Row of file position ( start from 1 ).
   1392 
   1393   @retval TRUE      It is under the current screen.
   1394   @retval FALSE     It is not under the current screen.
   1395 
   1396 **/
   1397 BOOLEAN
   1398 HUnderCurrentScreen (
   1399   IN  UINTN FileRow
   1400   )
   1401 {
   1402   if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) {
   1403     return TRUE;
   1404   }
   1405 
   1406   return FALSE;
   1407 }
   1408 
   1409 /**
   1410   According to cursor's file position, adjust screen display.
   1411 
   1412   @param[in] NewFilePosRow    Row of file position ( start from 1 ).
   1413   @param[in] NewFilePosCol    Column of file position ( start from 1 ).
   1414   @param[in] HighBits         Cursor will on high4 bits or low4 bits.
   1415 **/
   1416 VOID
   1417 HBufferImageMovePosition (
   1418   IN UINTN    NewFilePosRow,
   1419   IN UINTN    NewFilePosCol,
   1420   IN BOOLEAN  HighBits
   1421   )
   1422 {
   1423   INTN    RowGap;
   1424   UINTN   Abs;
   1425   BOOLEAN Above;
   1426   BOOLEAN Under;
   1427   UINTN   NewDisplayCol;
   1428 
   1429   //
   1430   // CALCULATE gap between current file position and new file position
   1431   //
   1432   RowGap                = NewFilePosRow - HBufferImage.BufferPosition.Row;
   1433 
   1434   Under                 = HUnderCurrentScreen (NewFilePosRow);
   1435   Above                 = HAboveCurrentScreen (NewFilePosRow);
   1436 
   1437   HBufferImage.HighBits = HighBits;
   1438 
   1439   //
   1440   // if is below current screen
   1441   //
   1442   if (Under) {
   1443     //
   1444     // display row will be unchanged
   1445     //
   1446     HBufferImage.BufferPosition.Row = NewFilePosRow;
   1447   } else {
   1448     if (Above) {
   1449       //
   1450       // has enough above line, so display row unchanged
   1451       // not has enough above lines, so the first line is
   1452       // at the first display line
   1453       //
   1454       if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {
   1455         HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;
   1456       }
   1457 
   1458       HBufferImage.BufferPosition.Row = NewFilePosRow;
   1459     } else {
   1460       //
   1461       // in current screen
   1462       //
   1463       HBufferImage.BufferPosition.Row = NewFilePosRow;
   1464       if (RowGap <= 0) {
   1465         Abs = (UINTN)ABS(RowGap);
   1466         HBufferImage.DisplayPosition.Row -= Abs;
   1467       } else {
   1468         HBufferImage.DisplayPosition.Row += RowGap;
   1469       }
   1470 
   1471     }
   1472   }
   1473 
   1474   HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);
   1475 
   1476   //
   1477   // always in current screen
   1478   //
   1479   HBufferImage.BufferPosition.Column  = NewFilePosCol;
   1480 
   1481   NewDisplayCol                       = 10 + (NewFilePosCol - 1) * 3;
   1482   if (NewFilePosCol > 0x8) {
   1483     NewDisplayCol++;
   1484   }
   1485 
   1486   if (!HighBits) {
   1487     NewDisplayCol++;
   1488   }
   1489 
   1490   HBufferImage.DisplayPosition.Column = NewDisplayCol;
   1491 
   1492   //
   1493   // let CurrentLine point to correct line;
   1494   //
   1495   HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);
   1496 
   1497 }
   1498 
   1499 /**
   1500   Scroll cursor to right.
   1501 
   1502   @retval EFI_SUCCESS   The operation was successful.
   1503 **/
   1504 EFI_STATUS
   1505 HBufferImageScrollRight (
   1506   VOID
   1507   )
   1508 {
   1509   HEFI_EDITOR_LINE  *Line;
   1510   UINTN             FRow;
   1511   UINTN             FCol;
   1512 
   1513   //
   1514   // scroll right will always move to the high4 bits of the next character
   1515   //
   1516   HBufferImageNeedRefresh         = FALSE;
   1517   HBufferImageOnlyLineNeedRefresh = FALSE;
   1518 
   1519   Line = HBufferImage.CurrentLine;
   1520 
   1521   FRow = HBufferImage.BufferPosition.Row;
   1522   FCol = HBufferImage.BufferPosition.Column;
   1523 
   1524   //
   1525   // this line is not full and no next line
   1526   //
   1527   if (FCol > Line->Size) {
   1528     return EFI_SUCCESS;
   1529   }
   1530   //
   1531   // if already at end of this line, scroll it to the start of next line
   1532   //
   1533   if (FCol == 0x10) {
   1534     //
   1535     // has next line
   1536     //
   1537     if (Line->Link.ForwardLink != HBufferImage.ListHead) {
   1538       FRow++;
   1539       FCol = 1;
   1540 
   1541     } else {
   1542       return EFI_SUCCESS;
   1543     }
   1544   } else {
   1545     //
   1546     // if not at end of this line, just move to next column
   1547     //
   1548     FCol++;
   1549 
   1550   }
   1551 
   1552   HBufferImageMovePosition (FRow, FCol, TRUE);
   1553 
   1554   return EFI_SUCCESS;
   1555 }
   1556 
   1557 /**
   1558   Scroll cursor to left.
   1559 
   1560   @retval EFI_SUCCESS   The operation was successful.
   1561 **/
   1562 EFI_STATUS
   1563 HBufferImageScrollLeft (
   1564   VOID
   1565   )
   1566 {
   1567 
   1568   HEFI_EDITOR_LINE  *Line;
   1569   UINTN             FRow;
   1570   UINTN             FCol;
   1571 
   1572   HBufferImageNeedRefresh         = FALSE;
   1573   HBufferImageOnlyLineNeedRefresh = FALSE;
   1574 
   1575   Line = HBufferImage.CurrentLine;
   1576 
   1577   FRow = HBufferImage.BufferPosition.Row;
   1578   FCol = HBufferImage.BufferPosition.Column;
   1579 
   1580   //
   1581   // if already at start of this line, so move to the end of previous line
   1582   //
   1583   if (FCol <= 1) {
   1584     //
   1585     // has previous line
   1586     //
   1587     if (Line->Link.BackLink != HBufferImage.ListHead) {
   1588       FRow--;
   1589       Line  = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   1590       FCol  = Line->Size;
   1591     } else {
   1592       return EFI_SUCCESS;
   1593     }
   1594   } else {
   1595     //
   1596     // if not at start of this line, just move to previous column
   1597     //
   1598     FCol--;
   1599   }
   1600 
   1601   HBufferImageMovePosition (FRow, FCol, TRUE);
   1602 
   1603   return EFI_SUCCESS;
   1604 }
   1605 
   1606 /**
   1607   Scroll cursor to the next line
   1608 
   1609   @retval EFI_SUCCESS   The operation was successful.
   1610 **/
   1611 EFI_STATUS
   1612 HBufferImageScrollDown (
   1613   VOID
   1614   )
   1615 {
   1616   HEFI_EDITOR_LINE  *Line;
   1617   UINTN             FRow;
   1618   UINTN             FCol;
   1619   BOOLEAN           HighBits;
   1620 
   1621   Line      = HBufferImage.CurrentLine;
   1622 
   1623   FRow      = HBufferImage.BufferPosition.Row;
   1624   FCol      = HBufferImage.BufferPosition.Column;
   1625   HighBits  = HBufferImage.HighBits;
   1626 
   1627   //
   1628   // has next line
   1629   //
   1630   if (Line->Link.ForwardLink != HBufferImage.ListHead) {
   1631     FRow++;
   1632     Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   1633 
   1634     //
   1635     // if the next line is not that long, so move to end of next line
   1636     //
   1637     if (FCol > Line->Size) {
   1638       FCol      = Line->Size + 1;
   1639       HighBits  = TRUE;
   1640     }
   1641 
   1642   } else {
   1643     return EFI_SUCCESS;
   1644   }
   1645 
   1646   HBufferImageMovePosition (FRow, FCol, HighBits);
   1647 
   1648   return EFI_SUCCESS;
   1649 }
   1650 
   1651 /**
   1652   Scroll cursor to previous line
   1653 
   1654   @retval EFI_SUCCESS   The operation was successful.
   1655 **/
   1656 EFI_STATUS
   1657 HBufferImageScrollUp (
   1658   VOID
   1659   )
   1660 {
   1661   HEFI_EDITOR_LINE  *Line;
   1662   UINTN             FRow;
   1663   UINTN             FCol;
   1664 
   1665   Line  = HBufferImage.CurrentLine;
   1666 
   1667   FRow  = HBufferImage.BufferPosition.Row;
   1668   FCol  = HBufferImage.BufferPosition.Column;
   1669 
   1670   //
   1671   // has previous line
   1672   //
   1673   if (Line->Link.BackLink != HBufferImage.ListHead) {
   1674     FRow--;
   1675 
   1676   } else {
   1677     return EFI_SUCCESS;
   1678   }
   1679 
   1680   HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
   1681 
   1682   return EFI_SUCCESS;
   1683 }
   1684 
   1685 /**
   1686   Scroll cursor to next page
   1687 
   1688   @retval EFI_SUCCESS   The operation was successful.
   1689 **/
   1690 EFI_STATUS
   1691 HBufferImagePageDown (
   1692   VOID
   1693   )
   1694 {
   1695   HEFI_EDITOR_LINE  *Line;
   1696   UINTN             FRow;
   1697   UINTN             FCol;
   1698   UINTN             Gap;
   1699   BOOLEAN           HighBits;
   1700 
   1701   Line      = HBufferImage.CurrentLine;
   1702 
   1703   FRow      = HBufferImage.BufferPosition.Row;
   1704   FCol      = HBufferImage.BufferPosition.Column;
   1705   HighBits  = HBufferImage.HighBits;
   1706 
   1707   //
   1708   // has next page
   1709   //
   1710   if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) {
   1711     Gap = (HMainEditor.ScreenSize.Row - 2);
   1712   } else {
   1713     //
   1714     // MOVE CURSOR TO LAST LINE
   1715     //
   1716     Gap = HBufferImage.NumLines - FRow;
   1717   }
   1718   //
   1719   // get correct line
   1720   //
   1721   Line = HMoveLine (Gap);
   1722 
   1723   //
   1724   // if that line, is not that long, so move to the end of that line
   1725   //
   1726   if (Line != NULL && FCol > Line->Size) {
   1727     FCol      = Line->Size + 1;
   1728     HighBits  = TRUE;
   1729   }
   1730 
   1731   FRow += Gap;
   1732 
   1733   HBufferImageMovePosition (FRow, FCol, HighBits);
   1734 
   1735   return EFI_SUCCESS;
   1736 }
   1737 
   1738 /**
   1739   Scroll cursor to previous page
   1740 
   1741   @retval EFI_SUCCESS   The operation was successful.
   1742 **/
   1743 EFI_STATUS
   1744 HBufferImagePageUp (
   1745   VOID
   1746   )
   1747 {
   1748   UINTN             FRow;
   1749   UINTN             FCol;
   1750   UINTN             Gap;
   1751   INTN              Retreat;
   1752 
   1753   FRow  = HBufferImage.BufferPosition.Row;
   1754   FCol  = HBufferImage.BufferPosition.Column;
   1755 
   1756   //
   1757   // has previous page
   1758   //
   1759   if (FRow > (HMainEditor.ScreenSize.Row - 2)) {
   1760     Gap = (HMainEditor.ScreenSize.Row - 2);
   1761   } else {
   1762     //
   1763     // the first line of file will displayed on the first line of screen
   1764     //
   1765     Gap = FRow - 1;
   1766   }
   1767 
   1768   Retreat = Gap;
   1769   Retreat = -Retreat;
   1770 
   1771   FRow -= Gap;
   1772 
   1773   HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
   1774 
   1775   return EFI_SUCCESS;
   1776 }
   1777 
   1778 /**
   1779   Scroll cursor to start of line
   1780 
   1781   @retval EFI_SUCCESS  The operation was successful.
   1782 **/
   1783 EFI_STATUS
   1784 HBufferImageHome (
   1785   VOID
   1786   )
   1787 {
   1788   UINTN             FRow;
   1789   UINTN             FCol;
   1790   BOOLEAN           HighBits;
   1791 
   1792   //
   1793   // curosr will at the high bit
   1794   //
   1795   FRow      = HBufferImage.BufferPosition.Row;
   1796   FCol      = 1;
   1797   HighBits  = TRUE;
   1798 
   1799   //
   1800   // move cursor position
   1801   //
   1802   HBufferImageMovePosition (FRow, FCol, HighBits);
   1803 
   1804   return EFI_SUCCESS;
   1805 }
   1806 
   1807 /**
   1808   Scroll cursor to end of line.
   1809 
   1810   @retval EFI_SUCCESS  Teh operation was successful.
   1811 **/
   1812 EFI_STATUS
   1813 HBufferImageEnd (
   1814   VOID
   1815   )
   1816 {
   1817   HEFI_EDITOR_LINE  *Line;
   1818   UINTN             FRow;
   1819   UINTN             FCol;
   1820   BOOLEAN           HighBits;
   1821 
   1822   //
   1823   // need refresh mouse
   1824   //
   1825   HBufferImageMouseNeedRefresh  = TRUE;
   1826 
   1827   Line                          = HBufferImage.CurrentLine;
   1828 
   1829   FRow                          = HBufferImage.BufferPosition.Row;
   1830 
   1831   if (Line->Size == 0x10) {
   1832     FCol      = Line->Size;
   1833     HighBits  = FALSE;
   1834   } else {
   1835     FCol      = Line->Size + 1;
   1836     HighBits  = TRUE;
   1837   }
   1838   //
   1839   // move cursor position
   1840   //
   1841   HBufferImageMovePosition (FRow, FCol, HighBits);
   1842 
   1843   return EFI_SUCCESS;
   1844 }
   1845 
   1846 /**
   1847   Get the size of the open buffer.
   1848 
   1849   @retval The size in bytes.
   1850 **/
   1851 UINTN
   1852 HBufferImageGetTotalSize (
   1853   VOID
   1854   )
   1855 {
   1856   UINTN             Size;
   1857 
   1858   HEFI_EDITOR_LINE  *Line;
   1859 
   1860   //
   1861   // calculate the total size of whole line list's buffer
   1862   //
   1863   if (HBufferImage.Lines == NULL) {
   1864     return 0;
   1865   }
   1866 
   1867   Line = CR (
   1868           HBufferImage.ListHead->BackLink,
   1869           HEFI_EDITOR_LINE,
   1870           Link,
   1871           EFI_EDITOR_LINE_LIST
   1872           );
   1873   //
   1874   // one line at most 0x10
   1875   //
   1876   Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;
   1877 
   1878   return Size;
   1879 }
   1880 
   1881 /**
   1882   Delete character from buffer.
   1883 
   1884   @param[in] Pos      Position, Pos starting from 0.
   1885   @param[in] Count    The Count of characters to delete.
   1886   @param[out] DeleteBuffer    The DeleteBuffer.
   1887 
   1888   @retval EFI_SUCCESS Success
   1889 **/
   1890 EFI_STATUS
   1891 HBufferImageDeleteCharacterFromBuffer (
   1892   IN  UINTN         Pos,
   1893   IN  UINTN         Count,
   1894   OUT UINT8         *DeleteBuffer
   1895   )
   1896 {
   1897   UINTN             Index;
   1898 
   1899   VOID              *Buffer;
   1900   UINT8             *BufferPtr;
   1901   UINTN             Size;
   1902 
   1903   HEFI_EDITOR_LINE  *Line;
   1904   LIST_ENTRY    *Link;
   1905 
   1906   UINTN             OldFCol;
   1907   UINTN             OldFRow;
   1908   UINTN             OldPos;
   1909 
   1910   UINTN             NewPos;
   1911 
   1912   EFI_STATUS        Status;
   1913 
   1914   Size      = HBufferImageGetTotalSize ();
   1915 
   1916   if (Size < Count) {
   1917     return EFI_LOAD_ERROR;
   1918   }
   1919 
   1920   if (Size == 0) {
   1921     return EFI_SUCCESS;
   1922   }
   1923 
   1924   //
   1925   // relocate all the HBufferImage fields
   1926   //
   1927   OldFRow = HBufferImage.BufferPosition.Row;
   1928   OldFCol = HBufferImage.BufferPosition.Column;
   1929   OldPos  = (OldFRow - 1) * 0x10 + OldFCol - 1;
   1930 
   1931   if (Pos > 0) {
   1932     //
   1933     // has character before it,
   1934     // so locate according to block's previous character
   1935     //
   1936     NewPos = Pos - 1;
   1937 
   1938   } else {
   1939     //
   1940     // has no character before it,
   1941     // so locate according to block's next character
   1942     //
   1943     NewPos = 0;
   1944   }
   1945 
   1946   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   1947 
   1948   Buffer = AllocateZeroPool (Size);
   1949   if (Buffer == NULL) {
   1950     return EFI_OUT_OF_RESOURCES;
   1951   }
   1952 
   1953   HBufferImageListToBuffer (Buffer, Size);
   1954 
   1955   BufferPtr = (UINT8 *) Buffer;
   1956 
   1957   //
   1958   // pass deleted buffer out
   1959   //
   1960   if (DeleteBuffer != NULL) {
   1961     for (Index = 0; Index < Count; Index++) {
   1962       DeleteBuffer[Index] = BufferPtr[Pos + Index];
   1963     }
   1964   }
   1965   //
   1966   // delete the part from Pos
   1967   //
   1968   for (Index = Pos; Index < Size - Count; Index++) {
   1969     BufferPtr[Index] = BufferPtr[Index + Count];
   1970   }
   1971 
   1972   Size -= Count;
   1973 
   1974   HBufferImageFreeLines ();
   1975 
   1976   Status = HBufferImageBufferToList (Buffer, Size);
   1977   FreePool (Buffer);
   1978 
   1979   if (EFI_ERROR (Status)) {
   1980     return Status;
   1981   }
   1982 
   1983   Link = HMainEditor.BufferImage->ListHead->ForwardLink;
   1984   for (Index = 0; Index < NewPos / 0x10; Index++) {
   1985     Link = Link->ForwardLink;
   1986   }
   1987 
   1988   Line                      = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   1989   HBufferImage.CurrentLine  = Line;
   1990 
   1991   //
   1992   // if current cursor position if inside select area
   1993   // then move it to the block's NEXT character
   1994   //
   1995   if (OldPos >= Pos && OldPos < (Pos + Count)) {
   1996     NewPos = Pos;
   1997   } else {
   1998     if (OldPos < Pos) {
   1999       NewPos = OldPos;
   2000     } else {
   2001       NewPos = OldPos - Count;
   2002     }
   2003   }
   2004 
   2005   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   2006 
   2007   return EFI_SUCCESS;
   2008 }
   2009 
   2010 /**
   2011   Add character to buffer, add before pos.
   2012 
   2013   @param[in] Pos        Position, Pos starting from 0.
   2014   @param[in] Count      Count of characters to add.
   2015   @param[in] AddBuffer  Add buffer.
   2016 
   2017   @retval EFI_SUCCESS   Success.
   2018 **/
   2019 EFI_STATUS
   2020 HBufferImageAddCharacterToBuffer (
   2021   IN  UINTN          Pos,
   2022   IN  UINTN          Count,
   2023   IN  UINT8          *AddBuffer
   2024   )
   2025 {
   2026   INTN              Index;
   2027 
   2028   VOID              *Buffer;
   2029   UINT8             *BufferPtr;
   2030   UINTN             Size;
   2031 
   2032   HEFI_EDITOR_LINE  *Line;
   2033 
   2034   LIST_ENTRY    *Link;
   2035 
   2036   UINTN             OldFCol;
   2037   UINTN             OldFRow;
   2038   UINTN             OldPos;
   2039 
   2040   UINTN             NewPos;
   2041 
   2042   Size      = HBufferImageGetTotalSize ();
   2043 
   2044   //
   2045   // relocate all the HBufferImage fields
   2046   //
   2047   OldFRow = HBufferImage.BufferPosition.Row;
   2048   OldFCol = HBufferImage.BufferPosition.Column;
   2049   OldPos  = (OldFRow - 1) * 0x10 + OldFCol - 1;
   2050 
   2051   //
   2052   // move cursor before Pos
   2053   //
   2054   if (Pos > 0) {
   2055     NewPos = Pos - 1;
   2056   } else {
   2057     NewPos = 0;
   2058   }
   2059 
   2060   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   2061 
   2062   Buffer = AllocateZeroPool (Size + Count);
   2063   if (Buffer == NULL) {
   2064     return EFI_OUT_OF_RESOURCES;
   2065   }
   2066 
   2067   HBufferImageListToBuffer (Buffer, Size);
   2068 
   2069   BufferPtr = (UINT8 *) Buffer;
   2070 
   2071   //
   2072   // get a place to add
   2073   //
   2074   for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) {
   2075     BufferPtr[Index] = BufferPtr[Index - Count];
   2076   }
   2077   //
   2078   // add the buffer
   2079   //
   2080   for (Index = (INTN) 0; Index < (INTN) Count; Index++) {
   2081     BufferPtr[Index + Pos] = AddBuffer[Index];
   2082   }
   2083 
   2084   Size += Count;
   2085 
   2086   HBufferImageFreeLines ();
   2087 
   2088   HBufferImageBufferToList (Buffer, Size);
   2089 
   2090   FreePool (Buffer);
   2091 
   2092   Link = HMainEditor.BufferImage->ListHead->ForwardLink;
   2093   for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) {
   2094     Link = Link->ForwardLink;
   2095   }
   2096 
   2097   Line                      = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   2098   HBufferImage.CurrentLine  = Line;
   2099 
   2100   if (OldPos >= Pos) {
   2101     NewPos = OldPos + Count;
   2102   } else {
   2103     NewPos = OldPos;
   2104   }
   2105 
   2106   HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
   2107 
   2108   return EFI_SUCCESS;
   2109 }
   2110 
   2111 /**
   2112   Delete current character from line.
   2113 
   2114   @retval EFI_SUCCESS   The operationw as successful.
   2115 **/
   2116 EFI_STATUS
   2117 HBufferImageDoDelete (
   2118   VOID
   2119   )
   2120 {
   2121 
   2122   HEFI_EDITOR_LINE  *Line;
   2123 
   2124   BOOLEAN           LastLine;
   2125   UINTN             FileColumn;
   2126   UINTN             FPos;
   2127 
   2128   FPos        = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
   2129 
   2130   FileColumn  = HBufferImage.BufferPosition.Column;
   2131 
   2132   Line        = HBufferImage.CurrentLine;
   2133 
   2134   //
   2135   // if beyond the last character
   2136   //
   2137   if (FileColumn > Line->Size) {
   2138     return EFI_SUCCESS;
   2139   }
   2140 
   2141   LastLine = FALSE;
   2142   if (Line->Link.ForwardLink == HBufferImage.ListHead) {
   2143     LastLine = TRUE;
   2144   }
   2145 
   2146   HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);
   2147 
   2148   //
   2149   // if is the last line
   2150   // then only this line need to be refreshed
   2151   //
   2152   if (LastLine) {
   2153     HBufferImageNeedRefresh         = FALSE;
   2154     HBufferImageOnlyLineNeedRefresh = TRUE;
   2155   } else {
   2156     HBufferImageNeedRefresh         = TRUE;
   2157     HBufferImageOnlyLineNeedRefresh = FALSE;
   2158   }
   2159 
   2160   if (!HBufferImage.Modified) {
   2161     HBufferImage.Modified = TRUE;
   2162   }
   2163 
   2164   return EFI_SUCCESS;
   2165 }
   2166 
   2167 /**
   2168   Change the raw buffer to a list of lines for the UI.
   2169 
   2170   @param[in] Buffer   The pointer to the buffer to fill.
   2171   @param[in] Bytes    The size of the buffer in bytes.
   2172 
   2173   @retval EFI_SUCCESS           The operation was successful.
   2174   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
   2175 **/
   2176 EFI_STATUS
   2177 HBufferImageBufferToList (
   2178   IN VOID   *Buffer,
   2179   IN UINTN  Bytes
   2180   )
   2181 {
   2182   UINTN             TempI;
   2183   UINTN             TempJ;
   2184   UINTN             Left;
   2185   HEFI_EDITOR_LINE  *Line;
   2186   UINT8             *BufferPtr;
   2187 
   2188   TempI         = 0;
   2189   Left      = 0;
   2190   BufferPtr = (UINT8 *) Buffer;
   2191 
   2192   //
   2193   // parse file content line by line
   2194   //
   2195   while (TempI < Bytes) {
   2196     if (Bytes - TempI >= 0x10) {
   2197       Left = 0x10;
   2198     } else {
   2199       Left = Bytes - TempI;
   2200     }
   2201 
   2202     //
   2203     // allocate a new line
   2204     //
   2205     Line = HBufferImageCreateLine ();
   2206     if (Line == NULL) {
   2207       return EFI_OUT_OF_RESOURCES;
   2208     }
   2209 
   2210     Line->Size = Left;
   2211 
   2212     for (TempJ = 0; TempJ < Left; TempJ++) {
   2213       Line->Buffer[TempJ] = BufferPtr[TempI];
   2214       TempI++;
   2215     }
   2216 
   2217   }
   2218 
   2219   //
   2220   // last line is a full line, SO create a new line
   2221   //
   2222   if (Left == 0x10 || Bytes == 0) {
   2223     Line = HBufferImageCreateLine ();
   2224     if (Line == NULL) {
   2225       return EFI_OUT_OF_RESOURCES;
   2226     }
   2227   }
   2228 
   2229   return EFI_SUCCESS;
   2230 }
   2231 
   2232 /**
   2233   Change the list of lines from the UI to a raw buffer.
   2234 
   2235   @param[in] Buffer   The pointer to the buffer to fill.
   2236   @param[in] Bytes    The size of the buffer in bytes.
   2237 
   2238   @retval EFI_SUCCESS   The operation was successful.
   2239 **/
   2240 EFI_STATUS
   2241 HBufferImageListToBuffer (
   2242   IN VOID   *Buffer,
   2243   IN UINTN  Bytes
   2244   )
   2245 {
   2246   UINTN             Count;
   2247   UINTN             Index;
   2248   HEFI_EDITOR_LINE  *Line;
   2249   LIST_ENTRY    *Link;
   2250   UINT8             *BufferPtr;
   2251 
   2252   //
   2253   // change the line list to a large buffer
   2254   //
   2255   if (HBufferImage.Lines == NULL) {
   2256     return EFI_SUCCESS;
   2257   }
   2258 
   2259   Link      = &HBufferImage.Lines->Link;
   2260   Count     = 0;
   2261   BufferPtr = (UINT8 *) Buffer;
   2262 
   2263   //
   2264   // deal line by line
   2265   //
   2266   while (Link != HBufferImage.ListHead) {
   2267 
   2268     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
   2269 
   2270     //@todo shouldn't this be an error???
   2271     if (Count + Line->Size > Bytes) {
   2272       return EFI_SUCCESS;
   2273     }
   2274 
   2275     for (Index = 0; Index < Line->Size; Index++) {
   2276       BufferPtr[Index] = Line->Buffer[Index];
   2277     }
   2278 
   2279     Count += Line->Size;
   2280     BufferPtr += Line->Size;
   2281 
   2282     Link = Link->ForwardLink;
   2283   }
   2284 
   2285   return EFI_SUCCESS;
   2286 }
   2287 
   2288 /**
   2289   Move the mouse in the image buffer.
   2290 
   2291   @param[in] TextX    The x-coordinate.
   2292   @param[in] TextY    The y-coordinate.
   2293 **/
   2294 VOID
   2295 HBufferImageAdjustMousePosition (
   2296   IN INT32 TextX,
   2297   IN INT32 TextY
   2298   )
   2299 {
   2300   UINTN TempX;
   2301   UINTN TempY;
   2302   UINTN AbsX;
   2303   UINTN AbsY;
   2304 
   2305   //
   2306   // TextX and TextY is mouse movement data returned by mouse driver
   2307   // This function will change it to MousePosition
   2308   //
   2309   //
   2310   // get absolute TempX value
   2311   //
   2312   if (TextX >= 0) {
   2313     AbsX = TextX;
   2314   } else {
   2315     AbsX = -TextX;
   2316   }
   2317   //
   2318   // get absolute TempY value
   2319   //
   2320   if (TextY >= 0) {
   2321     AbsY = TextY;
   2322   } else {
   2323     AbsY = -TextY;
   2324   }
   2325 
   2326   TempX = HBufferImage.MousePosition.Column;
   2327   TempY = HBufferImage.MousePosition.Row;
   2328 
   2329   if (TextX >= 0) {
   2330     TempX += TextX;
   2331   } else {
   2332     if (TempX >= AbsX) {
   2333       TempX -= AbsX;
   2334     } else {
   2335       TempX = 0;
   2336     }
   2337   }
   2338 
   2339   if (TextY >= 0) {
   2340     TempY += TextY;
   2341   } else {
   2342     if (TempY >= AbsY) {
   2343       TempY -= AbsY;
   2344     } else {
   2345       TempY = 0;
   2346     }
   2347   }
   2348   //
   2349   // check whether new mouse column position is beyond screen
   2350   // if not, adjust it
   2351   //
   2352   if (TempX >= 10 && TempX <= (10 + 0x10 * 3 - 1)) {
   2353     HBufferImage.MousePosition.Column = TempX;
   2354   } else if (TempX < 10) {
   2355     HBufferImage.MousePosition.Column = 10;
   2356   } else if (TempX > (10 + 0x10 * 3 - 1)) {
   2357     HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;
   2358   }
   2359   //
   2360   // check whether new mouse row position is beyond screen
   2361   // if not, adjust it
   2362   //
   2363   if (TempY >= 2 && TempY <= (HMainEditor.ScreenSize.Row - 1)) {
   2364     HBufferImage.MousePosition.Row = TempY;
   2365   } else if (TempY < 2) {
   2366     HBufferImage.MousePosition.Row = 2;
   2367   } else if (TempY > (HMainEditor.ScreenSize.Row - 1)) {
   2368     HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1);
   2369   }
   2370 
   2371 }
   2372 
   2373 /**
   2374   Dispatch input to different handler
   2375 
   2376   @param[in] Key    The input key:
   2377                      the keys can be:
   2378                        ASCII KEY
   2379                         Backspace/Delete
   2380                         Direction key: up/down/left/right/pgup/pgdn
   2381                         Home/End
   2382                         INS
   2383 
   2384   @retval EFI_SUCCESS           The operation was successful.
   2385   @retval EFI_LOAD_ERROR        A load error occured.
   2386   @retval EFI_OUT_OF_RESOURCES  A Memory allocation failed.
   2387 **/
   2388 EFI_STATUS
   2389 HBufferImageHandleInput (
   2390   IN  EFI_INPUT_KEY *Key
   2391   )
   2392 {
   2393   EFI_STATUS  Status;
   2394 
   2395   Status = EFI_SUCCESS;
   2396 
   2397   switch (Key->ScanCode) {
   2398   //
   2399   // ordinary key
   2400   //
   2401   case SCAN_NULL:
   2402     Status = HBufferImageDoCharInput (Key->UnicodeChar);
   2403     break;
   2404 
   2405   //
   2406   // up arrow
   2407   //
   2408   case SCAN_UP:
   2409     Status = HBufferImageScrollUp ();
   2410     break;
   2411 
   2412   //
   2413   // down arrow
   2414   //
   2415   case SCAN_DOWN:
   2416     Status = HBufferImageScrollDown ();
   2417     break;
   2418 
   2419   //
   2420   // right arrow
   2421   //
   2422   case SCAN_RIGHT:
   2423     Status = HBufferImageScrollRight ();
   2424     break;
   2425 
   2426   //
   2427   // left arrow
   2428   //
   2429   case SCAN_LEFT:
   2430     Status = HBufferImageScrollLeft ();
   2431     break;
   2432 
   2433   //
   2434   // page up
   2435   //
   2436   case SCAN_PAGE_UP:
   2437     Status = HBufferImagePageUp ();
   2438     break;
   2439 
   2440   //
   2441   // page down
   2442   //
   2443   case SCAN_PAGE_DOWN:
   2444     Status = HBufferImagePageDown ();
   2445     break;
   2446 
   2447   //
   2448   // delete
   2449   //
   2450   case SCAN_DELETE:
   2451     Status = HBufferImageDoDelete ();
   2452     break;
   2453 
   2454   //
   2455   // home
   2456   //
   2457   case SCAN_HOME:
   2458     Status = HBufferImageHome ();
   2459     break;
   2460 
   2461   //
   2462   // end
   2463   //
   2464   case SCAN_END:
   2465     Status = HBufferImageEnd ();
   2466     break;
   2467 
   2468   default:
   2469     Status = StatusBarSetStatusString (L"Unknown Command");
   2470     break;
   2471   }
   2472 
   2473   return Status;
   2474 }
   2475 
   2476