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