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
HBufferImageInit(VOID)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
HBufferImageBackup(VOID)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
HBufferImageFreeLines(VOID)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
HBufferImageCleanup(VOID)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
HBufferImagePrintLine(IN HEFI_EDITOR_LINE * Line,IN UINTN Row,IN UINTN FRow,IN HEFI_EDITOR_COLOR_UNION Orig,IN HEFI_EDITOR_COLOR_UNION New)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
HBufferImageIsAtHighBits(IN UINTN Column,OUT UINTN * FCol)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
HBufferImageIsInSelectedArea(IN UINTN MouseRow,IN UINTN MouseCol)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
HBufferImageRestoreMousePosition(VOID)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
HBufferImageRestorePosition(VOID)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
HBufferImageRefresh(VOID)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
HBufferImageRead(IN CONST CHAR16 * FileName,IN CONST CHAR16 * DiskName,IN UINTN DiskOffset,IN UINTN DiskSize,IN UINTN MemOffset,IN UINTN MemSize,IN EDIT_FILE_TYPE BufferType,IN BOOLEAN Recover)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
HBufferImageSave(IN CHAR16 * FileName,IN CHAR16 * DiskName,IN UINTN DiskOffset,IN UINTN DiskSize,IN UINTN MemOffset,IN UINTN MemSize,IN EDIT_FILE_TYPE BufferType)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 *
HBufferImageCreateLine(VOID)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
HBufferImageFree(VOID)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
HBufferImageCharToHex(IN CHAR16 Char)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
HBufferImageAddChar(IN CHAR16 Char)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
HBufferImageDoBackspace(VOID)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
HBufferImageDoCharInput(IN CHAR16 Char)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
HAboveCurrentScreen(IN UINTN FileRow)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
HUnderCurrentScreen(IN UINTN FileRow)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
HBufferImageMovePosition(IN UINTN NewFilePosRow,IN UINTN NewFilePosCol,IN BOOLEAN HighBits)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
HBufferImageScrollRight(VOID)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
HBufferImageScrollLeft(VOID)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
HBufferImageScrollDown(VOID)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
HBufferImageScrollUp(VOID)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
HBufferImagePageDown(VOID)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
HBufferImagePageUp(VOID)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
HBufferImageHome(VOID)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
HBufferImageEnd(VOID)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
HBufferImageGetTotalSize(VOID)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
HBufferImageDeleteCharacterFromBuffer(IN UINTN Pos,IN UINTN Count,OUT UINT8 * DeleteBuffer)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
HBufferImageAddCharacterToBuffer(IN UINTN Pos,IN UINTN Count,IN UINT8 * AddBuffer)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
HBufferImageDoDelete(VOID)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
HBufferImageBufferToList(IN VOID * Buffer,IN UINTN Bytes)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
HBufferImageListToBuffer(IN VOID * Buffer,IN UINTN Bytes)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
HBufferImageAdjustMousePosition(IN INT32 TextX,IN INT32 TextY)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
HBufferImageHandleInput(IN EFI_INPUT_KEY * Key)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