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