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