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