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