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