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