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