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