]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
ShellPkg: Fix GCC 4.4 build issues
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Edit / MainTextEditor.c
1 /** @file
2 Implements editor interface functions.
3
4 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "TextEditor.h"
16 #include "EditStatusBar.h"
17 #include "EditInputBar.h"
18
19 /**
20 Load a file from disk to editor
21
22 @retval EFI_SUCCESS The operation was successful.
23 @retval EFI_LOAD_ERROR A load error occured.
24 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
25 **/
26 EFI_STATUS
27 MainCommandOpenFile (
28 VOID
29 );
30
31 /**
32 Switch a file from ASCII to UNICODE or vise-versa.
33
34 @retval EFI_SUCCESS The switch was ok or a warning was presented.
35 **/
36 EFI_STATUS
37 MainCommandSwitchFileType (
38 VOID
39 );
40
41 /**
42 move cursor to specified lines
43
44 @retval EFI_SUCCESS The operation was successful.
45 **/
46 EFI_STATUS
47 MainCommandGotoLine (
48 VOID
49 );
50
51 /**
52 Save current file to disk, you can save to current file name or
53 save to another file name.
54
55 @retval EFI_SUCCESS The file was saved correctly.
56 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
57 @retval EFI_LOAD_ERROR A file access error occured.
58 **/
59 EFI_STATUS
60 MainCommandSaveFile (
61 VOID
62 );
63
64 /**
65 exit editor
66
67 @retval EFI_SUCCESS The operation was successful.
68 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
69 @retval EFI_LOAD_ERROR A load error occured.
70 **/
71 EFI_STATUS
72 MainCommandExit (
73 VOID
74 );
75
76 /**
77 search string in file buffer
78
79 @retval EFI_SUCCESS The operation was successful.
80 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
81 @retval EFI_LOAD_ERROR A load error occured.
82 **/
83 EFI_STATUS
84 MainCommandSearch (
85 VOID
86 );
87
88 /**
89 search string in file buffer, and replace it with another str
90
91 @retval EFI_SUCCESS The operation was successful.
92 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
93 @retval EFI_LOAD_ERROR A load error occured.
94 **/
95 EFI_STATUS
96 MainCommandSearchReplace (
97 VOID
98 );
99
100 /**
101 cut current line to clipboard
102
103 @retval EFI_SUCCESS The operation was successful.
104 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
105 @retval EFI_LOAD_ERROR A load error occured.
106 **/
107 EFI_STATUS
108 MainCommandCutLine (
109 VOID
110 );
111
112 /**
113 paste line to file buffer.
114
115 @retval EFI_SUCCESS The operation was successful.
116 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
117 @retval EFI_LOAD_ERROR A load error occured.
118 **/
119 EFI_STATUS
120 MainCommandPasteLine (
121 VOID
122 );
123
124 EDITOR_MENU_ITEM MainMenuItems[] = {
125 {
126 STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE),
127 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),
128 MainCommandGotoLine
129 },
130 {
131 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE),
132 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),
133 MainCommandSaveFile
134 },
135 {
136 STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),
137 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),
138 MainCommandExit
139 },
140
141 {
142 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH),
143 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),
144 MainCommandSearch
145 },
146 {
147 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE),
148 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),
149 MainCommandSearchReplace
150 },
151 {
152 STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE),
153 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),
154 MainCommandCutLine
155 },
156 {
157 STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE),
158 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),
159 MainCommandPasteLine
160 },
161
162 {
163 STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE),
164 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),
165 MainCommandOpenFile
166 },
167 {
168 STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE),
169 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),
170 MainCommandSwitchFileType
171 },
172
173 {
174 0,
175 0,
176 NULL
177 }
178 };
179
180
181 /**
182 Load a file from disk to editor
183
184 @retval EFI_SUCCESS The operation was successful.
185 @retval EFI_LOAD_ERROR A load error occured.
186 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
187 **/
188 EFI_STATUS
189 MainCommandOpenFile (
190 VOID
191 )
192 {
193 BOOLEAN Done;
194 EFI_STATUS Status;
195
196 //
197 // This command will open a file from current working directory.
198 // Read-only file can also be opened. But it can not be modified.
199 // Below is the scenario of Open File command:
200 // 1.IF currently opened file has not been modIFied, directly go to step .
201 // IF currently opened file has been modified,
202 // an Input Bar will be prompted as :
203 // "File Modified. Save ( Yes/No/Cancel) ?"
204 // IF user press 'y' or 'Y', currently opened file will be saved.
205 // IF user press 'n' or 'N', currently opened file will
206 // not be saved.
207 // IF user press 'c' or 'C' or ESC, Open File command ends and
208 // currently opened file is still opened.
209 //
210 // 2. An Input Bar will be prompted as : "File Name to Open: "
211 // IF user press ESC, Open File command ends and
212 // currently opened file is still opened.
213 // Any other inputs with a Return will
214 // cause currently opened file close.
215 //
216 // 3. IF user input file name is an existing file , this file will be read
217 // and opened.
218 // IF user input file name is a new file, this file will be created
219 // and opened. This file's type ( UNICODE or ASCII ) is the same
220 // with the old file.
221 // if current file is modified, so you need to choose
222 // whether to save it first.
223 //
224 if (MainEditor.FileBuffer->FileModified) {
225
226 Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
227 if (EFI_ERROR (Status)) {
228 return Status;
229 }
230 //
231 // the answer is just one character
232 //
233 Status = InputBarSetStringSize (1);
234 if (EFI_ERROR (Status)) {
235 return Status;
236 }
237 //
238 // loop for user's answer
239 // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
240 //
241 Done = FALSE;
242 while (!Done) {
243 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
244 StatusBarSetRefresh();
245
246 //
247 // ESC pressed
248 //
249 if (Status == EFI_NOT_READY) {
250 return EFI_SUCCESS;
251 }
252
253 switch (InputBarGetString()[0]) {
254 case L'y':
255 case L'Y':
256 //
257 // want to save this file first
258 //
259 Status = FileBufferSave (MainEditor.FileBuffer->FileName);
260 if (EFI_ERROR (Status)) {
261 return Status;
262 }
263
264 MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
265 FileBufferRestorePosition ();
266 Done = TRUE;
267 break;
268
269 case L'n':
270 case L'N':
271 //
272 // the file won't be saved
273 //
274 Done = TRUE;
275 break;
276
277 case L'c':
278 case L'C':
279 return EFI_SUCCESS;
280 }
281 }
282 }
283 //
284 // TO get the open file name
285 //
286 Status = InputBarSetPrompt (L"File Name to Open: ");
287 if (EFI_ERROR (Status)) {
288 FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
289 return Status;
290 }
291
292 Status = InputBarSetStringSize (100);
293 if (EFI_ERROR (Status)) {
294 FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
295 return Status;
296 }
297
298 while (1) {
299 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
300 StatusBarSetRefresh();
301
302 //
303 // ESC pressed
304 //
305 if (Status == EFI_NOT_READY) {
306 return EFI_SUCCESS;
307 }
308 //
309 // The input string length should > 0
310 //
311 if (StrLen (InputBarGetString()) > 0) {
312 //
313 // CHECK if filename is valid
314 //
315 if (!IsValidFileName (InputBarGetString())) {
316 FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
317 StatusBarSetStatusString (L"Invalid File Name");
318 return EFI_SUCCESS;
319 }
320
321 break;
322 }
323 }
324 //
325 // read from disk
326 //
327 Status = FileBufferRead (InputBarGetString(), FALSE);
328
329 if (EFI_ERROR (Status)) {
330 FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
331 return EFI_LOAD_ERROR;
332 }
333
334 return EFI_SUCCESS;
335 }
336
337 /**
338 Switch a file from ASCII to UNICODE or vise-versa.
339
340 @retval EFI_SUCCESS The switch was ok or a warning was presented.
341 **/
342 EFI_STATUS
343 MainCommandSwitchFileType (
344 VOID
345 )
346 {
347 //
348 // Below is the scenario of File Type command:
349 // After File Type is executed, file type will be changed to another type
350 // if file is read-only, can not be modified
351 //
352 if (MainEditor.FileBuffer->ReadOnly) {
353 StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
354 return EFI_SUCCESS;
355 }
356
357 if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
358 MainEditor.FileBuffer->FileType = FileTypeAscii;
359 } else {
360 MainEditor.FileBuffer->FileType = FileTypeUnicode;
361 }
362
363 MainEditor.FileBuffer->FileModified = TRUE;
364
365 return EFI_SUCCESS;
366 }
367
368 /**
369 cut current line to clipboard
370
371 @retval EFI_SUCCESS The operation was successful.
372 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
373 @retval EFI_LOAD_ERROR A load error occured.
374 **/
375 EFI_STATUS
376 MainCommandCutLine (
377 VOID
378 )
379 {
380 EFI_STATUS Status;
381 EFI_EDITOR_LINE *Line;
382
383 //
384 // This command will cut current line ( where cursor is on ) to clip board.
385 // And cursor will move to the beginning of next line.
386 // Below is the scenario of Cut Line command:
387 // 1. IF cursor is on valid line, current line will be cut to clip board.
388 // IF cursor is not on valid line, an Status String will be prompted :
389 // "Nothing to Cut".
390 //
391 Status = FileBufferCutLine (&Line);
392 if (Status == EFI_NOT_FOUND) {
393 return EFI_SUCCESS;
394 }
395
396 if (EFI_ERROR (Status)) {
397 return Status;
398 }
399
400 MainEditor.CutLine = Line;
401
402 return EFI_SUCCESS;
403 }
404
405 /**
406 paste line to file buffer.
407
408 @retval EFI_SUCCESS The operation was successful.
409 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
410 @retval EFI_LOAD_ERROR A load error occured.
411 **/
412 EFI_STATUS
413 MainCommandPasteLine (
414 VOID
415 )
416 {
417 EFI_STATUS Status;
418
419 //
420 // Below is the scenario of Paste Line command:
421 // 1. IF nothing is on clipboard, a Status String will be prompted :
422 // "No Line to Paste" and Paste Line command ends.
423 // IF something is on clipboard, insert it above current line.
424 // nothing on clipboard
425 //
426 if (MainEditor.CutLine == NULL) {
427 StatusBarSetStatusString (L"No Line to Paste");
428 return EFI_SUCCESS;
429 }
430
431 Status = FileBufferPasteLine ();
432
433 return Status;
434 }
435
436
437 /**
438 search string in file buffer
439
440 @retval EFI_SUCCESS The operation was successful.
441 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
442 @retval EFI_LOAD_ERROR A load error occured.
443 **/
444 EFI_STATUS
445 MainCommandSearch (
446 VOID
447 )
448 {
449 EFI_STATUS Status;
450 CHAR16 *Buffer;
451 BOOLEAN Done;
452 UINTN Offset;
453
454 //
455 // Below is the scenario of Search command:
456 // 1. An Input Bar will be prompted : "Enter Search String:".
457 // IF user press ESC, Search command ends.
458 // IF user just press Enter, Search command ends.
459 // IF user inputs the search string, do Step 2.
460 //
461 // 2. IF input search string is found, cursor will move to the first
462 // occurrence and do Step 3.
463 // IF input search string is not found, a Status String
464 // "Search String Not Found" will be prompted and Search command ends.
465 //
466 // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
467 // IF user press ESC, Search command ends.
468 // IF user press 'y' or 'Y', do Step 2.
469 // IF user press 'n' or 'N', Search command ends.
470 // IF user press 'c' or 'C', Search command ends.
471 //
472 Status = InputBarSetPrompt (L"Enter Search String: ");
473 if (EFI_ERROR (Status)) {
474 return Status;
475 }
476
477 Status = InputBarSetStringSize (40);
478 if (EFI_ERROR (Status)) {
479 return Status;
480 }
481
482 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
483 StatusBarSetRefresh();
484
485 //
486 // ESC
487 //
488 if (Status == EFI_NOT_READY) {
489 return EFI_SUCCESS;
490 }
491 //
492 // just enter pressed
493 //
494 if (StrLen (InputBarGetString()) == 0) {
495 return EFI_SUCCESS;
496 }
497
498 Buffer = CatSPrint (NULL, L"%s", InputBarGetString());
499 if (Buffer == NULL) {
500 return EFI_OUT_OF_RESOURCES;
501 }
502 //
503 // the first time , search from current position
504 //
505 Offset = 0;
506 do {
507 //
508 // since search may be continued to search multiple times
509 // so we need to backup editor each time
510 //
511 MainEditorBackup ();
512
513 Status = FileBufferSearch (Buffer, Offset);
514
515 if (Status == EFI_NOT_FOUND) {
516 break;
517 }
518 //
519 // Find next
520 //
521 Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
522 if (EFI_ERROR (Status)) {
523 FreePool (Buffer);
524 return Status;
525 }
526
527 Status = InputBarSetStringSize (1);
528 if (EFI_ERROR (Status)) {
529 FreePool (Buffer);
530 return Status;
531 }
532
533 Done = FALSE;
534 while (!Done) {
535 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
536 StatusBarSetRefresh();
537
538 //
539 // ESC pressed
540 //
541 if (Status == EFI_NOT_READY) {
542 FreePool (Buffer);
543 return EFI_SUCCESS;
544 }
545
546 switch (InputBarGetString()[0]) {
547 case L'y':
548 case L'Y':
549 Done = TRUE;
550 break;
551
552 case L'n':
553 case L'N':
554 FreePool (Buffer);
555 return EFI_SUCCESS;
556
557 }
558 //
559 // end of which
560 //
561 }
562 //
563 // end of while !Done
564 // for search second, third time, search from current position + strlen
565 //
566 Offset = StrLen (Buffer);
567
568 } while (1);
569 //
570 // end of do
571 //
572 FreePool (Buffer);
573 StatusBarSetStatusString (L"Search String Not Found");
574
575 return EFI_SUCCESS;
576 }
577
578 /**
579 Search string in file buffer, and replace it with another str.
580
581 @retval EFI_SUCCESS The operation was successful.
582 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
583 @retval EFI_LOAD_ERROR A load error occured.
584 **/
585 EFI_STATUS
586 MainCommandSearchReplace (
587 VOID
588 )
589 {
590 EFI_STATUS Status;
591 CHAR16 *Search;
592 CHAR16 *Replace;
593 BOOLEAN Done;
594 BOOLEAN First;
595 BOOLEAN ReplaceOption;
596 UINTN SearchLen;
597 UINTN ReplaceLen;
598 BOOLEAN ReplaceAll;
599
600 ReplaceOption = FALSE;
601
602 //
603 // Below is the scenario of Search/Replace command:
604 // 1. An Input Bar is prompted : "Enter Search String:".
605 // IF user press ESC, Search/Replace command ends.
606 // IF user just press Enter, Search/Replace command ends.
607 // IF user inputs the search string S, do Step 2.
608 //
609 // 2. An Input Bar is prompted: "Replace With:".
610 // IF user press ESC, Search/Replace command ends.
611 // IF user inputs the replace string R, do Step 3.
612 //
613 // 3. IF input search string is not found, an Status String
614 // "Search String Not Found" will be prompted
615 // and Search/Replace command ends
616 // IF input search string is found, do Step 4.
617 //
618 // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
619 // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
620 // IF user press 'n' or 'N', S will not be replaced and do Step 5.
621 // IF user press 'a' or 'A', all the S from file current position on
622 // will be replaced with R and Search/Replace command ends.
623 // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
624 //
625 // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
626 // IF user press ESC, Search/Replace command ends.
627 // IF user press 'y' or 'Y', do Step 3.
628 // IF user press 'n' or 'N', Search/Replace command ends.
629 // IF user press 'c' or 'C', Search/Replace command ends.
630 // input search string
631 //
632 Status = InputBarSetPrompt (L"Enter Search String: ");
633 if (EFI_ERROR (Status)) {
634 return Status;
635 }
636
637 Status = InputBarSetStringSize (40);
638 if (EFI_ERROR (Status)) {
639 return Status;
640 }
641
642 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
643 StatusBarSetRefresh();
644
645 //
646 // ESC
647 //
648 if (Status == EFI_NOT_READY) {
649 return EFI_SUCCESS;
650 }
651 //
652 // if just pressed enter
653 //
654 if (StrLen (InputBarGetString()) == 0) {
655 return EFI_SUCCESS;
656 }
657
658 Search = CatSPrint (NULL, L"%s", InputBarGetString());
659 if (Search == NULL) {
660 return EFI_OUT_OF_RESOURCES;
661 }
662
663 SearchLen = StrLen (Search);
664
665 //
666 // input replace string
667 //
668 Status = InputBarSetPrompt (L"Replace With: ");
669 if (EFI_ERROR (Status)) {
670 return Status;
671 }
672
673 Status = InputBarSetStringSize (40);
674 if (EFI_ERROR (Status)) {
675 return Status;
676 }
677
678 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
679 StatusBarSetRefresh();
680
681 //
682 // ESC
683 //
684 if (Status == EFI_NOT_READY) {
685 return EFI_SUCCESS;
686 }
687
688 Replace = CatSPrint (NULL, L"%s", InputBarGetString());
689 if (Replace == NULL) {
690 FreePool (Search);
691 return EFI_OUT_OF_RESOURCES;
692 }
693
694 ReplaceLen = StrLen (Replace);
695
696 First = TRUE;
697 ReplaceAll = FALSE;
698 do {
699 //
700 // since search may be continued to search multiple times
701 // so we need to backup editor each time
702 //
703 MainEditorBackup ();
704
705 if (First) {
706 Status = FileBufferSearch (Search, 0);
707 } else {
708 //
709 // if just replace, so skip this replace string
710 // if replace string is an empty string, so skip to next character
711 //
712 if (ReplaceOption) {
713 Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen);
714 } else {
715 Status = FileBufferSearch (Search, SearchLen);
716 }
717 }
718
719 if (Status == EFI_NOT_FOUND) {
720 break;
721 }
722 //
723 // replace or not?
724 //
725 Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?");
726
727 if (EFI_ERROR (Status)) {
728 FreePool (Search);
729 FreePool (Replace);
730 return Status;
731 }
732
733 Status = InputBarSetStringSize (1);
734 if (EFI_ERROR (Status)) {
735 FreePool (Search);
736 FreePool (Replace);
737 return Status;
738 }
739
740 Done = FALSE;
741 while (!Done) {
742 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
743 StatusBarSetRefresh();
744
745 //
746 // ESC pressed
747 //
748 if (Status == EFI_NOT_READY) {
749 FreePool (Search);
750 FreePool (Replace);
751 return EFI_SUCCESS;
752 }
753
754 switch (InputBarGetString()[0]) {
755 case L'y':
756 case L'Y':
757 Done = TRUE;
758 ReplaceOption = TRUE;
759 break;
760
761 case L'n':
762 case L'N':
763 Done = TRUE;
764 ReplaceOption = FALSE;
765 break;
766
767 case L'a':
768 case L'A':
769 Done = TRUE;
770 ReplaceOption = TRUE;
771 ReplaceAll = TRUE;
772 break;
773
774 case L'c':
775 case L'C':
776 FreePool (Search);
777 FreePool (Replace);
778 return EFI_SUCCESS;
779
780 }
781 //
782 // end of which
783 //
784 }
785 //
786 // end of while !Done
787 // Decide to Replace
788 //
789 if (ReplaceOption) {
790 //
791 // file is read-only
792 //
793 if (MainEditor.FileBuffer->ReadOnly) {
794 StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
795 return EFI_SUCCESS;
796 }
797 //
798 // replace all
799 //
800 if (ReplaceAll) {
801 Status = FileBufferReplaceAll (Search, Replace, 0);
802 FreePool (Search);
803 FreePool (Replace);
804 return Status;
805 }
806 //
807 // replace
808 //
809 Status = FileBufferReplace (Replace, SearchLen);
810 if (EFI_ERROR (Status)) {
811 FreePool (Search);
812 FreePool (Replace);
813 return Status;
814 }
815 }
816 //
817 // Find next
818 //
819 Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
820 if (EFI_ERROR (Status)) {
821 FreePool (Search);
822 FreePool (Replace);
823 return Status;
824 }
825
826 Status = InputBarSetStringSize (1);
827 if (EFI_ERROR (Status)) {
828 FreePool (Search);
829 FreePool (Replace);
830 return Status;
831 }
832
833 Done = FALSE;
834 while (!Done) {
835 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
836 StatusBarSetRefresh();
837
838 //
839 // ESC pressed
840 //
841 if (Status == EFI_NOT_READY) {
842 FreePool (Search);
843 FreePool (Replace);
844 return EFI_SUCCESS;
845 }
846
847 switch (InputBarGetString()[0]) {
848 case L'y':
849 case L'Y':
850 Done = TRUE;
851 break;
852
853 case L'n':
854 case L'N':
855 FreePool (Search);
856 FreePool (Replace);
857 return EFI_SUCCESS;
858
859 }
860 //
861 // end of which
862 //
863 }
864 //
865 // end of while !Done
866 //
867 First = FALSE;
868
869 } while (1);
870 //
871 // end of do
872 //
873 FreePool (Search);
874 FreePool (Replace);
875
876 StatusBarSetStatusString (L"Search String Not Found");
877
878 return EFI_SUCCESS;
879 }
880
881 /**
882 exit editor
883
884 @retval EFI_SUCCESS The operation was successful.
885 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
886 @retval EFI_LOAD_ERROR A load error occured.
887 **/
888 EFI_STATUS
889 MainCommandExit (
890 VOID
891 )
892 {
893 EFI_STATUS Status;
894
895 //
896 // Below is the scenario of Exit command:
897 // 1. IF currently opened file is not modified, exit the editor and
898 // Exit command ends.
899 // IF currently opened file is modified, do Step 2
900 //
901 // 2. An Input Bar will be prompted:
902 // "File modified. Save ( Yes/No/Cancel )?"
903 // IF user press 'y' or 'Y', currently opened file will be saved
904 // and Editor exits
905 // IF user press 'n' or 'N', currently opened file will not be saved
906 // and Editor exits.
907 // IF user press 'c' or 'C' or ESC, Exit command ends.
908 // if file has been modified, so will prompt user whether to save the changes
909 //
910 if (MainEditor.FileBuffer->FileModified) {
911
912 Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
913 if (EFI_ERROR (Status)) {
914 return Status;
915 }
916
917 Status = InputBarSetStringSize (1);
918 if (EFI_ERROR (Status)) {
919 return Status;
920 }
921
922 while (1) {
923 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
924 StatusBarSetRefresh();
925
926 //
927 // ESC pressed
928 //
929 if (Status == EFI_NOT_READY) {
930 return EFI_SUCCESS;
931 }
932
933 switch (InputBarGetString()[0]) {
934 case L'y':
935 case L'Y':
936 //
937 // write file back to disk
938 //
939 Status = FileBufferSave (MainEditor.FileBuffer->FileName);
940 if (!EFI_ERROR (Status)) {
941 EditorExit = TRUE;
942 }
943
944 return Status;
945
946 case L'n':
947 case L'N':
948 EditorExit = TRUE;
949 return EFI_SUCCESS;
950
951 case L'c':
952 case L'C':
953 return EFI_SUCCESS;
954
955 }
956 }
957 }
958
959 EditorExit = TRUE;
960 return EFI_SUCCESS;
961
962 }
963
964 /**
965 move cursor to specified lines
966
967 @retval EFI_SUCCESS The operation was successful.
968 **/
969 EFI_STATUS
970 MainCommandGotoLine (
971 VOID
972 )
973 {
974 EFI_STATUS Status;
975 UINTN Row;
976
977 //
978 // Below is the scenario of Go To Line command:
979 // 1. An Input Bar will be prompted : "Go To Line:".
980 // IF user press ESC, Go To Line command ends.
981 // IF user just press Enter, cursor remains unchanged.
982 // IF user inputs line number, do Step 2.
983 //
984 // 2. IF input line number is valid, move cursor to the beginning
985 // of specified line and Go To Line command ends.
986 // IF input line number is invalid, a Status String will be prompted:
987 // "No Such Line" and Go To Line command ends.
988 //
989 Status = InputBarSetPrompt (L"Go To Line: ");
990 if (EFI_ERROR (Status)) {
991 return Status;
992 }
993 //
994 // line number's digit <= 6
995 //
996 Status = InputBarSetStringSize (6);
997 if (EFI_ERROR (Status)) {
998 return Status;
999 }
1000
1001 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
1002 StatusBarSetRefresh();
1003
1004 //
1005 // press ESC
1006 //
1007 if (Status == EFI_NOT_READY) {
1008 return EFI_SUCCESS;
1009 }
1010 //
1011 // if JUST press enter
1012 //
1013 if (StrLen (InputBarGetString()) == 0) {
1014 return EFI_SUCCESS;
1015 }
1016
1017 Row = ShellStrToUintn (InputBarGetString());
1018
1019 //
1020 // invalid line number
1021 //
1022 if (Row > MainEditor.FileBuffer->NumLines || Row <= 0) {
1023 StatusBarSetStatusString (L"No Such Line");
1024 return EFI_SUCCESS;
1025 }
1026 //
1027 // move cursor to that line's start
1028 //
1029 FileBufferMovePosition (Row, 1);
1030
1031 return EFI_SUCCESS;
1032 }
1033
1034 /**
1035 Save current file to disk, you can save to current file name or
1036 save to another file name.
1037
1038 @retval EFI_SUCCESS The file was saved correctly.
1039 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1040 @retval EFI_LOAD_ERROR A file access error occured.
1041 **/
1042 EFI_STATUS
1043 MainCommandSaveFile (
1044 VOID
1045 )
1046 {
1047 EFI_STATUS Status;
1048 CHAR16 *FileName;
1049 BOOLEAN OldFile;
1050 CHAR16 *Str;
1051 SHELL_FILE_HANDLE FileHandle;
1052 EFI_FILE_INFO *Info;
1053
1054 //
1055 // This command will save currently opened file to disk.
1056 // You can choose save to another file name or just save to
1057 // current file name.
1058 // Below is the scenario of Save File command:
1059 // ( Suppose the old file name is A )
1060 // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
1061 // IF user press ESC, Save File command ends .
1062 // IF user press Enter, input file name will be A.
1063 // IF user inputs a new file name B, input file name will be B.
1064 //
1065 // 2. IF input file name is A, go to do Step 3.
1066 // IF input file name is B, go to do Step 4.
1067 //
1068 // 3. IF A is read only, Status Bar will show "Access Denied" and
1069 // Save File commands ends.
1070 // IF A is not read only, save file buffer to disk and remove modified
1071 // flag in Title Bar , then Save File command ends.
1072 //
1073 // 4. IF B does not exist, create this file and save file buffer to it.
1074 // Go to do Step 7.
1075 // IF B exits, do Step 5.
1076 //
1077 // 5.An Input Bar will be prompted:
1078 // "File Exists. Overwrite ( Yes/No/Cancel )?"
1079 // IF user press 'y' or 'Y', do Step 6.
1080 // IF user press 'n' or 'N', Save File commands ends.
1081 // IF user press 'c' or 'C' or ESC, Save File commands ends.
1082 //
1083 // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
1084 // Save File commands ends.
1085 // IF B can be read and write, save file buffer to B.
1086 //
1087 // 7. Update File Name field in Title Bar to B and remove the modified
1088 // flag in Title Bar.
1089 //
1090 Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName);
1091 if (Str == NULL) {
1092 return EFI_OUT_OF_RESOURCES;
1093 }
1094
1095 if (StrLen (Str) >= 50) {
1096 //
1097 // replace the long file name with "..."
1098 //
1099 Str[46] = L'.';
1100 Str[47] = L'.';
1101 Str[48] = L'.';
1102 Str[49] = L']';
1103 Str[50] = CHAR_NULL;
1104 }
1105
1106 Status = InputBarSetPrompt (Str);
1107 FreePool(Str);
1108
1109 if (EFI_ERROR (Status)) {
1110 return Status;
1111 }
1112
1113
1114 Status = InputBarSetStringSize (100);
1115 if (EFI_ERROR (Status)) {
1116 return Status;
1117 }
1118 //
1119 // get new file name
1120 //
1121 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
1122 StatusBarSetRefresh();
1123
1124 //
1125 // if user pressed ESC
1126 //
1127 if (Status == EFI_NOT_READY) {
1128 return EFI_SUCCESS;
1129 }
1130
1131 //
1132 // if just enter pressed, so think save to current file name
1133 //
1134 if (StrLen (InputBarGetString()) == 0) {
1135 FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName);
1136 } else {
1137 FileName = CatSPrint (NULL, L"%s", InputBarGetString());
1138 }
1139
1140 if (FileName == NULL) {
1141 return EFI_OUT_OF_RESOURCES;
1142 }
1143
1144 if (!IsValidFileName (FileName)) {
1145 StatusBarSetStatusString (L"Invalid File Name");
1146 FreePool (FileName);
1147 return EFI_SUCCESS;
1148 }
1149
1150 OldFile = FALSE;
1151
1152 //
1153 // save to the old file
1154 //
1155 if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) {
1156 OldFile = TRUE;
1157 }
1158
1159 if (OldFile) {
1160 //
1161 // if the file is read only, so can not write back to it.
1162 //
1163 if (MainEditor.FileBuffer->ReadOnly == TRUE) {
1164 StatusBarSetStatusString (L"Access Denied");
1165 FreePool (FileName);
1166 return EFI_SUCCESS;
1167 }
1168 } else {
1169 //
1170 // if the file exists
1171 //
1172 if (ShellFileExists(FileName) != EFI_NOT_FOUND) {
1173 //
1174 // check for read only
1175 //
1176 Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
1177 if (EFI_ERROR(Status)) {
1178 StatusBarSetStatusString (L"Open Failed");
1179 FreePool (FileName);
1180 return EFI_SUCCESS;
1181 }
1182
1183 Info = ShellGetFileInfo(FileHandle);
1184 if (Info == NULL) {
1185 StatusBarSetStatusString (L"Access Denied");
1186 FreePool (FileName);
1187 return (EFI_SUCCESS);
1188 }
1189
1190 if (Info->Attribute & EFI_FILE_READ_ONLY) {
1191 StatusBarSetStatusString (L"Access Denied - Read Only");
1192 FreePool (Info);
1193 FreePool (FileName);
1194 return (EFI_SUCCESS);
1195 }
1196 FreePool (Info);
1197
1198 //
1199 // ask user whether to overwrite this file
1200 //
1201 Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
1202 if (EFI_ERROR (Status)) {
1203 SHELL_FREE_NON_NULL (FileName);
1204 return Status;
1205 }
1206
1207 Status = InputBarSetStringSize (1);
1208 if (EFI_ERROR (Status)) {
1209 SHELL_FREE_NON_NULL (FileName);
1210 return Status;
1211 }
1212
1213 while (TRUE) {
1214 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
1215 StatusBarSetRefresh();
1216
1217 //
1218 // ESC pressed
1219 //
1220 if (Status == EFI_NOT_READY) {
1221 SHELL_FREE_NON_NULL (FileName);
1222 return EFI_SUCCESS;
1223 }
1224
1225 switch (InputBarGetString()[0]) {
1226 case L'y':
1227 case L'Y':
1228 break;
1229
1230 case L'n':
1231 case L'N':
1232 case L'c':
1233 case L'C':
1234 SHELL_FREE_NON_NULL (FileName);
1235 return EFI_SUCCESS;
1236 } // end switch
1237 } // while (!done)
1238 } // file does exist
1239 } // if old file name same
1240
1241 //
1242 // save file to disk with specified name
1243 //
1244 FileBufferSetModified();
1245 Status = FileBufferSave (FileName);
1246 SHELL_FREE_NON_NULL (FileName);
1247
1248 return Status;
1249 }
1250
1251 EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors;
1252 INTN OriginalMode;
1253
1254 //
1255 // the first time editor launch
1256 //
1257 BOOLEAN EditorFirst;
1258
1259 //
1260 // it's time editor should exit
1261 //
1262 BOOLEAN EditorExit;
1263
1264 BOOLEAN EditorMouseAction;
1265
1266 extern EFI_EDITOR_FILE_BUFFER FileBuffer;
1267
1268 extern BOOLEAN FileBufferMouseNeedRefresh;
1269
1270 extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
1271
1272 EFI_EDITOR_GLOBAL_EDITOR MainEditor;
1273
1274 //
1275 // basic initialization for MainEditor
1276 //
1277 EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {
1278 &FileBuffer,
1279 {
1280 0,
1281 0
1282 },
1283 {
1284 0,
1285 0
1286 },
1287 NULL,
1288 FALSE,
1289 NULL
1290 };
1291
1292 /**
1293 The initialization function for MainEditor.
1294
1295 @retval EFI_SUCCESS The operation was successful.
1296 @retval EFI_LOAD_ERROR A load error occured.
1297 **/
1298 EFI_STATUS
1299 EFIAPI
1300 MainEditorInit (
1301 VOID
1302 )
1303 {
1304 EFI_STATUS Status;
1305 EFI_HANDLE *HandleBuffer;
1306 UINTN HandleCount;
1307 UINTN Index;
1308
1309 //
1310 // basic initialization
1311 //
1312 CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor));
1313
1314 //
1315 // set screen attributes
1316 //
1317 MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
1318
1319 MainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);
1320 OriginalColors = MainEditor.ColorAttributes.Colors;
1321
1322 OriginalMode = gST->ConOut->Mode->Mode;
1323
1324 //
1325 // query screen size
1326 //
1327 gST->ConOut->QueryMode (
1328 gST->ConOut,
1329 gST->ConOut->Mode->Mode,
1330 &(MainEditor.ScreenSize.Column),
1331 &(MainEditor.ScreenSize.Row)
1332 );
1333
1334 //
1335 // Find mouse in System Table ConsoleInHandle
1336 //
1337 Status = gBS->HandleProtocol (
1338 gST->ConIn,
1339 &gEfiSimplePointerProtocolGuid,
1340 (VOID**)&MainEditor.MouseInterface
1341 );
1342 if (EFI_ERROR (Status)) {
1343 //
1344 // If there is no Simple Pointer Protocol on System Table
1345 //
1346 HandleBuffer = NULL;
1347 MainEditor.MouseInterface = NULL;
1348 Status = gBS->LocateHandleBuffer (
1349 ByProtocol,
1350 &gEfiSimplePointerProtocolGuid,
1351 NULL,
1352 &HandleCount,
1353 &HandleBuffer
1354 );
1355 if (!EFI_ERROR (Status) && HandleCount > 0) {
1356 //
1357 // Try to find the first available mouse device
1358 //
1359 for (Index = 0; Index < HandleCount; Index++) {
1360 Status = gBS->HandleProtocol (
1361 HandleBuffer[Index],
1362 &gEfiSimplePointerProtocolGuid,
1363 (VOID**)&MainEditor.MouseInterface
1364 );
1365 if (!EFI_ERROR (Status)) {
1366 break;
1367 }
1368 }
1369 }
1370 if (HandleBuffer != NULL) {
1371 FreePool (HandleBuffer);
1372 }
1373 }
1374
1375 if (!EFI_ERROR (Status) && MainEditor.MouseInterface != NULL) {
1376 MainEditor.MouseAccumulatorX = 0;
1377 MainEditor.MouseAccumulatorY = 0;
1378 MainEditor.MouseSupported = TRUE;
1379 }
1380
1381 //
1382 // below will call the five components' init function
1383 //
1384 Status = MainTitleBarInit (L"UEFI EDIT 2.0");
1385 if (EFI_ERROR (Status)) {
1386 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle);
1387 return EFI_LOAD_ERROR;
1388 }
1389
1390 Status = MenuBarInit (MainMenuItems);
1391 if (EFI_ERROR (Status)) {
1392 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle);
1393 return EFI_LOAD_ERROR;
1394 }
1395
1396 Status = StatusBarInit ();
1397 if (EFI_ERROR (Status)) {
1398 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle);
1399 return EFI_LOAD_ERROR;
1400 }
1401
1402 InputBarInit ();
1403
1404 Status = FileBufferInit ();
1405 if (EFI_ERROR (Status)) {
1406 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle);
1407 return EFI_LOAD_ERROR;
1408 }
1409 //
1410 // clear whole screen and enable cursor
1411 //
1412 gST->ConOut->ClearScreen (gST->ConOut);
1413 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
1414
1415 //
1416 // initialize EditorFirst and EditorExit
1417 //
1418 EditorFirst = TRUE;
1419 EditorExit = FALSE;
1420 EditorMouseAction = FALSE;
1421
1422 return EFI_SUCCESS;
1423 }
1424
1425 /**
1426 The cleanup function for MainEditor.
1427
1428 @retval EFI_SUCCESS The operation was successful.
1429 @retval EFI_LOAD_ERROR A load error occured.
1430 **/
1431 EFI_STATUS
1432 EFIAPI
1433 MainEditorCleanup (
1434 VOID
1435 )
1436 {
1437 EFI_STATUS Status;
1438
1439 //
1440 // call the five components' cleanup function
1441 // if error, do not exit
1442 // just print some warning
1443 //
1444 MainTitleBarCleanup();
1445 StatusBarCleanup();
1446 InputBarCleanup();
1447 MenuBarCleanup ();
1448
1449 Status = FileBufferCleanup ();
1450 if (EFI_ERROR (Status)) {
1451 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle);
1452 }
1453 //
1454 // restore old mode
1455 //
1456 if (OriginalMode != gST->ConOut->Mode->Mode) {
1457 gST->ConOut->SetMode (gST->ConOut, OriginalMode);
1458 }
1459 //
1460 // restore old screen color
1461 //
1462 gST->ConOut->SetAttribute (
1463 gST->ConOut,
1464 EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background)
1465 );
1466
1467 gST->ConOut->ClearScreen (gST->ConOut);
1468
1469 return EFI_SUCCESS;
1470 }
1471
1472 /**
1473 Refresh the main editor component.
1474 **/
1475 VOID
1476 EFIAPI
1477 MainEditorRefresh (
1478 VOID
1479 )
1480 {
1481 //
1482 // The Stall value is from experience. NOT from spec. avoids 'flicker'
1483 //
1484 gBS->Stall (50);
1485
1486 //
1487 // call the components refresh function
1488 //
1489 if (EditorFirst
1490 || StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0
1491 || FileBufferBackupVar.FileType != FileBuffer.FileType
1492 || FileBufferBackupVar.FileModified != FileBuffer.FileModified
1493 || FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly) {
1494
1495 MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
1496 FileBufferRestorePosition ();
1497 FileBufferRefresh ();
1498 }
1499 if (EditorFirst
1500 || FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row
1501 || FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column
1502 || FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert
1503 || StatusBarGetRefresh()) {
1504
1505 StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert);
1506 FileBufferRestorePosition ();
1507 FileBufferRefresh ();
1508 }
1509
1510 if (EditorFirst) {
1511 MenuBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
1512 FileBufferRestorePosition ();
1513 }
1514
1515 //
1516 // EditorFirst is now set to FALSE
1517 //
1518 EditorFirst = FALSE;
1519 }
1520
1521 /**
1522 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1523
1524 @param[in] GuidX The relative mouse movement.
1525
1526 @return The X location of the mouse.
1527 **/
1528 INT32
1529 EFIAPI
1530 GetTextX (
1531 IN INT32 GuidX
1532 )
1533 {
1534 INT32 Gap;
1535
1536 MainEditor.MouseAccumulatorX += GuidX;
1537 Gap = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);
1538 MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);
1539 MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32) MainEditor.ScreenSize.Column;
1540 return Gap;
1541 }
1542
1543 /**
1544 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1545
1546 @param[in] GuidY The relative mouse movement.
1547
1548 @return The Y location of the mouse.
1549 **/
1550 INT32
1551 EFIAPI
1552 GetTextY (
1553 IN INT32 GuidY
1554 )
1555 {
1556 INT32 Gap;
1557
1558 MainEditor.MouseAccumulatorY += GuidY;
1559 Gap = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);
1560 MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);
1561 MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32) MainEditor.ScreenSize.Row;
1562
1563 return Gap;
1564 }
1565
1566 /**
1567 Support mouse movement. Move the cursor.
1568
1569 @param[in] MouseState The current mouse state.
1570
1571 @retval EFI_SUCCESS The operation was successful.
1572 @retval EFI_NOT_FOUND There was no mouse support found.
1573 **/
1574 EFI_STATUS
1575 EFIAPI
1576 MainEditorHandleMouseInput (
1577 IN EFI_SIMPLE_POINTER_STATE MouseState
1578 )
1579 {
1580
1581 INT32 TextX;
1582 INT32 TextY;
1583 UINTN FRow;
1584 UINTN FCol;
1585
1586 LIST_ENTRY *Link;
1587 EFI_EDITOR_LINE *Line;
1588
1589 UINTN Index;
1590 BOOLEAN Action;
1591
1592 //
1593 // mouse action means:
1594 // mouse movement
1595 // mouse left button
1596 //
1597 Action = FALSE;
1598
1599 //
1600 // have mouse movement
1601 //
1602 if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
1603 //
1604 // handle
1605 //
1606 TextX = GetTextX (MouseState.RelativeMovementX);
1607 TextY = GetTextY (MouseState.RelativeMovementY);
1608
1609 FileBufferAdjustMousePosition (TextX, TextY);
1610
1611 Action = TRUE;
1612
1613 }
1614
1615 //
1616 // if left button pushed down
1617 //
1618 if (MouseState.LeftButton) {
1619
1620 FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1;
1621
1622 FRow = MainEditor.FileBuffer->FilePosition.Row +
1623 MainEditor.FileBuffer->MousePosition.Row -
1624 MainEditor.FileBuffer->DisplayPosition.Row;
1625
1626 //
1627 // beyond the file line length
1628 //
1629 if (MainEditor.FileBuffer->NumLines < FRow) {
1630 FRow = MainEditor.FileBuffer->NumLines;
1631 }
1632
1633 Link = MainEditor.FileBuffer->ListHead->ForwardLink;
1634 for (Index = 0; Index < FRow - 1; Index++) {
1635 Link = Link->ForwardLink;
1636 }
1637
1638 Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
1639
1640 //
1641 // beyond the line's column length
1642 //
1643 if (FCol > Line->Size + 1) {
1644 FCol = Line->Size + 1;
1645 }
1646
1647 FileBufferMovePosition (FRow, FCol);
1648
1649 MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row;
1650
1651 MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column;
1652
1653 Action = TRUE;
1654 }
1655 //
1656 // mouse has action
1657 //
1658 if (Action) {
1659 return EFI_SUCCESS;
1660 }
1661
1662 //
1663 // no mouse action
1664 //
1665 return EFI_NOT_FOUND;
1666 }
1667
1668 /**
1669 Handle user key input. This routes to other functions for the actions.
1670
1671 @retval EFI_SUCCESS The operation was successful.
1672 @retval EFI_LOAD_ERROR A load error occured.
1673 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1674 **/
1675 EFI_STATUS
1676 EFIAPI
1677 MainEditorKeyInput (
1678 VOID
1679 )
1680 {
1681 EFI_INPUT_KEY Key;
1682 EFI_STATUS Status;
1683 EFI_SIMPLE_POINTER_STATE MouseState;
1684
1685 do {
1686
1687 Status = EFI_SUCCESS;
1688 EditorMouseAction = FALSE;
1689
1690 //
1691 // backup some key elements, so that can aVOID some refresh work
1692 //
1693 MainEditorBackup ();
1694
1695 //
1696 // change priority of checking mouse/keyboard activity dynamically
1697 // so prevent starvation of keyboard.
1698 // if last time, mouse moves then this time check keyboard
1699 //
1700 if (MainEditor.MouseSupported) {
1701 Status = MainEditor.MouseInterface->GetState (
1702 MainEditor.MouseInterface,
1703 &MouseState
1704 );
1705 if (!EFI_ERROR (Status)) {
1706
1707 Status = MainEditorHandleMouseInput (MouseState);
1708
1709 if (!EFI_ERROR (Status)) {
1710 EditorMouseAction = TRUE;
1711 FileBufferMouseNeedRefresh = TRUE;
1712 } else if (Status == EFI_LOAD_ERROR) {
1713 StatusBarSetStatusString (L"Invalid Mouse Movement ");
1714 }
1715 }
1716 }
1717
1718 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
1719 if (!EFI_ERROR (Status)) {
1720 //
1721 // dispatch to different components' key handling function
1722 // so not everywhere has to set this variable
1723 //
1724 FileBufferMouseNeedRefresh = TRUE;
1725 //
1726 // clear previous status string
1727 //
1728 StatusBarSetRefresh();
1729
1730 //
1731 // dispatch to different components' key handling function
1732 //
1733 if ((Key.ScanCode == SCAN_NULL) || ((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {
1734 Status = FileBufferHandleInput (&Key);
1735 } else if ((Key.ScanCode >= SCAN_F1) && (Key.ScanCode <= SCAN_F12)) {
1736 Status = MenuBarDispatchFunctionKey (&Key);
1737 } else {
1738 StatusBarSetStatusString (L"Unknown Command");
1739 FileBufferMouseNeedRefresh = FALSE;
1740 }
1741
1742 if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
1743 //
1744 // not already has some error status
1745 //
1746 if (StatusBarGetString() != NULL && StrCmp (L"", StatusBarGetString()) == 0) {
1747 StatusBarSetStatusString (L"Disk Error. Try Again");
1748 }
1749 }
1750
1751 }
1752 //
1753 // after handling, refresh editor
1754 //
1755 MainEditorRefresh ();
1756
1757 } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);
1758
1759 return Status;
1760 }
1761
1762 /**
1763 Set clipboard
1764
1765 @param[in] Line A pointer to the line to be set to clipboard
1766
1767 @retval EFI_SUCCESS The operation was successful.
1768 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1769 **/
1770 EFI_STATUS
1771 EFIAPI
1772 MainEditorSetCutLine (
1773 EFI_EDITOR_LINE *Line
1774 )
1775 {
1776 if (Line == NULL) {
1777 return EFI_SUCCESS;
1778 }
1779
1780 if (MainEditor.CutLine != NULL) {
1781 //
1782 // free the old clipboard
1783 //
1784 LineFree (MainEditor.CutLine);
1785 }
1786 //
1787 // duplicate the line to clipboard
1788 //
1789 MainEditor.CutLine = LineDup (Line);
1790 if (MainEditor.CutLine == NULL) {
1791 return EFI_OUT_OF_RESOURCES;
1792 }
1793
1794 return EFI_SUCCESS;
1795 }
1796
1797 /**
1798 Backup function for MainEditor
1799
1800 @retval EFI_SUCCESS The operation was successful.
1801 **/
1802 EFI_STATUS
1803 EFIAPI
1804 MainEditorBackup (
1805 VOID
1806 )
1807 {
1808 FileBufferBackup ();
1809
1810 return EFI_SUCCESS;
1811 }