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