2 Implements editor interface functions.
4 Copyright (c) 2005 - 2012, 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
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.
15 #include "TextEditor.h"
16 #include "EditStatusBar.h"
17 #include "EditInputBar.h"
18 #include "EditMenuBar.h"
21 // the first time editor launch
26 // it's time editor should exit
30 BOOLEAN EditorMouseAction
;
32 extern EFI_EDITOR_FILE_BUFFER FileBuffer
;
34 extern BOOLEAN FileBufferNeedRefresh
;
36 extern BOOLEAN FileBufferOnlyLineNeedRefresh
;
38 extern BOOLEAN FileBufferMouseNeedRefresh
;
40 extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
42 EFI_EDITOR_GLOBAL_EDITOR MainEditor
;
46 Load a file from disk to editor
48 @retval EFI_SUCCESS The operation was successful.
49 @retval EFI_LOAD_ERROR A load error occured.
50 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
58 Switch a file from ASCII to UNICODE or vise-versa.
60 @retval EFI_SUCCESS The switch was ok or a warning was presented.
63 MainCommandSwitchFileType (
68 move cursor to specified lines
70 @retval EFI_SUCCESS The operation was successful.
78 Save current file to disk, you can save to current file name or
79 save to another file name.
81 @retval EFI_SUCCESS The file was saved correctly.
82 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
83 @retval EFI_LOAD_ERROR A file access error occured.
91 Show help information for the editor.
93 @retval EFI_SUCCESS The operation was successful.
96 MainCommandDisplayHelp (
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.
113 search string in file buffer
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.
125 search string in file buffer, and replace it with another str
127 @retval EFI_SUCCESS The operation was successful.
128 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
129 @retval EFI_LOAD_ERROR A load error occured.
132 MainCommandSearchReplace (
137 cut current line to clipboard
139 @retval EFI_SUCCESS The operation was successful.
140 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
141 @retval EFI_LOAD_ERROR A load error occured.
149 paste line to file buffer.
151 @retval EFI_SUCCESS The operation was successful.
152 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
153 @retval EFI_LOAD_ERROR A load error occured.
156 MainCommandPasteLine (
161 Help info that will be displayed.
163 EFI_STRING_ID MainMenuHelpInfo
[] = {
164 STRING_TOKEN(STR_EDIT_HELP_TITLE
),
165 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
166 STRING_TOKEN(STR_EDIT_HELP_LIST_TITLE
),
167 STRING_TOKEN(STR_EDIT_HELP_DIV
),
168 STRING_TOKEN(STR_EDIT_HELP_GO_TO_LINE
),
169 STRING_TOKEN(STR_EDIT_HELP_SAVE_FILE
),
170 STRING_TOKEN(STR_EDIT_HELP_EXIT
),
171 STRING_TOKEN(STR_EDIT_HELP_SEARCH
),
172 STRING_TOKEN(STR_EDIT_HELP_SEARCH_REPLACE
),
173 STRING_TOKEN(STR_EDIT_HELP_CUT_LINE
),
174 STRING_TOKEN(STR_EDIT_HELP_PASTE_LINE
),
175 STRING_TOKEN(STR_EDIT_HELP_OPEN_FILE
),
176 STRING_TOKEN(STR_EDIT_HELP_FILE_TYPE
),
177 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
178 STRING_TOKEN(STR_EDIT_HELP_EXIT_HELP
),
179 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
180 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
181 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
182 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
183 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
184 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
185 STRING_TOKEN(STR_EDIT_HELP_BLANK
),
186 STRING_TOKEN(STR_EDIT_HELP_DIV
),
190 MENU_ITEM_FUNCTION MainControlBasedMenuFunctions
[] = {
196 MainCommandDisplayHelp
, /* Ctrl - E */
197 MainCommandSearch
, /* Ctrl - F */
198 MainCommandGotoLine
, /* Ctrl - G */
202 MainCommandCutLine
, /* Ctrl - K */
206 MainCommandOpenFile
, /* Ctrl - O */
208 MainCommandExit
, /* Ctrl - Q */
209 MainCommandSearchReplace
, /* Ctrl - R */
210 MainCommandSaveFile
, /* Ctrl - S */
211 MainCommandSwitchFileType
, /* Ctrl - T */
212 MainCommandPasteLine
, /* Ctrl - U */
220 EDITOR_MENU_ITEM MainMenuItems
[] = {
222 STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE
),
223 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1
),
227 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE
),
228 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2
),
232 STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT
),
233 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3
),
238 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH
),
239 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4
),
243 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE
),
244 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5
),
245 MainCommandSearchReplace
248 STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE
),
249 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6
),
253 STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE
),
254 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7
),
259 STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE
),
260 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8
),
264 STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE
),
265 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9
),
266 MainCommandSwitchFileType
269 STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE
),
270 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F11
),
271 MainCommandSwitchFileType
283 Load a file from disk to editor
285 @retval EFI_SUCCESS The operation was successful.
286 @retval EFI_LOAD_ERROR A load error occured.
287 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
290 MainCommandOpenFile (
298 // This command will open a file from current working directory.
299 // Read-only file can also be opened. But it can not be modified.
300 // Below is the scenario of Open File command:
301 // 1.IF currently opened file has not been modIFied, directly go to step .
302 // IF currently opened file has been modified,
303 // an Input Bar will be prompted as :
304 // "File Modified. Save ( Yes/No/Cancel) ?"
305 // IF user press 'y' or 'Y', currently opened file will be saved.
306 // IF user press 'n' or 'N', currently opened file will
308 // IF user press 'c' or 'C' or ESC, Open File command ends and
309 // currently opened file is still opened.
311 // 2. An Input Bar will be prompted as : "File Name to Open: "
312 // IF user press ESC, Open File command ends and
313 // currently opened file is still opened.
314 // Any other inputs with a Return will
315 // cause currently opened file close.
317 // 3. IF user input file name is an existing file , this file will be read
319 // IF user input file name is a new file, this file will be created
320 // and opened. This file's type ( UNICODE or ASCII ) is the same
321 // with the old file.
322 // if current file is modified, so you need to choose
323 // whether to save it first.
325 if (MainEditor
.FileBuffer
->FileModified
) {
327 Status
= InputBarSetPrompt (L
"File modified. Save (Yes/No/Cancel) ? ");
328 if (EFI_ERROR (Status
)) {
332 // the answer is just one character
334 Status
= InputBarSetStringSize (1);
335 if (EFI_ERROR (Status
)) {
339 // loop for user's answer
340 // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
344 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
345 StatusBarSetRefresh();
350 if (Status
== EFI_NOT_READY
) {
354 switch (InputBarGetString()[0]) {
358 // want to save this file first
360 Status
= FileBufferSave (MainEditor
.FileBuffer
->FileName
);
361 if (EFI_ERROR (Status
)) {
365 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
366 FileBufferRestorePosition ();
373 // the file won't be saved
385 // TO get the open file name
387 Status
= InputBarSetPrompt (L
"File Name to Open: ");
388 if (EFI_ERROR (Status
)) {
389 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
393 Status
= InputBarSetStringSize (100);
394 if (EFI_ERROR (Status
)) {
395 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
400 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
401 StatusBarSetRefresh();
406 if (Status
== EFI_NOT_READY
) {
410 // The input string length should > 0
412 if (StrLen (InputBarGetString()) > 0) {
414 // CHECK if filename is valid
416 if (!IsValidFileName (InputBarGetString())) {
417 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
418 StatusBarSetStatusString (L
"Invalid File Name");
428 Status
= FileBufferRead (InputBarGetString(), FALSE
);
430 if (EFI_ERROR (Status
)) {
431 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
432 return EFI_LOAD_ERROR
;
439 Switch a file from ASCII to UNICODE or vise-versa.
441 @retval EFI_SUCCESS The switch was ok or a warning was presented.
444 MainCommandSwitchFileType (
449 // Below is the scenario of File Type command:
450 // After File Type is executed, file type will be changed to another type
451 // if file is read-only, can not be modified
453 if (MainEditor
.FileBuffer
->ReadOnly
) {
454 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
458 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
459 MainEditor
.FileBuffer
->FileType
= FileTypeAscii
;
461 MainEditor
.FileBuffer
->FileType
= FileTypeUnicode
;
464 MainEditor
.FileBuffer
->FileModified
= TRUE
;
470 cut current line to clipboard
472 @retval EFI_SUCCESS The operation was successful.
473 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
474 @retval EFI_LOAD_ERROR A load error occured.
482 EFI_EDITOR_LINE
*Line
;
485 // This command will cut current line ( where cursor is on ) to clip board.
486 // And cursor will move to the beginning of next line.
487 // Below is the scenario of Cut Line command:
488 // 1. IF cursor is on valid line, current line will be cut to clip board.
489 // IF cursor is not on valid line, an Status String will be prompted :
492 Status
= FileBufferCutLine (&Line
);
493 if (Status
== EFI_NOT_FOUND
) {
497 if (EFI_ERROR (Status
)) {
501 MainEditor
.CutLine
= Line
;
507 paste line to file buffer.
509 @retval EFI_SUCCESS The operation was successful.
510 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
511 @retval EFI_LOAD_ERROR A load error occured.
514 MainCommandPasteLine (
521 // Below is the scenario of Paste Line command:
522 // 1. IF nothing is on clipboard, a Status String will be prompted :
523 // "No Line to Paste" and Paste Line command ends.
524 // IF something is on clipboard, insert it above current line.
525 // nothing on clipboard
527 if (MainEditor
.CutLine
== NULL
) {
528 StatusBarSetStatusString (L
"No Line to Paste");
532 Status
= FileBufferPasteLine ();
539 search string in file buffer
541 @retval EFI_SUCCESS The operation was successful.
542 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
543 @retval EFI_LOAD_ERROR A load error occured.
556 // Below is the scenario of Search command:
557 // 1. An Input Bar will be prompted : "Enter Search String:".
558 // IF user press ESC, Search command ends.
559 // IF user just press Enter, Search command ends.
560 // IF user inputs the search string, do Step 2.
562 // 2. IF input search string is found, cursor will move to the first
563 // occurrence and do Step 3.
564 // IF input search string is not found, a Status String
565 // "Search String Not Found" will be prompted and Search command ends.
567 // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
568 // IF user press ESC, Search command ends.
569 // IF user press 'y' or 'Y', do Step 2.
570 // IF user press 'n' or 'N', Search command ends.
571 // IF user press 'c' or 'C', Search command ends.
573 Status
= InputBarSetPrompt (L
"Enter Search String: ");
574 if (EFI_ERROR (Status
)) {
578 Status
= InputBarSetStringSize (40);
579 if (EFI_ERROR (Status
)) {
583 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
584 StatusBarSetRefresh();
589 if (Status
== EFI_NOT_READY
) {
593 // just enter pressed
595 if (StrLen (InputBarGetString()) == 0) {
599 Buffer
= CatSPrint (NULL
, L
"%s", InputBarGetString());
600 if (Buffer
== NULL
) {
601 return EFI_OUT_OF_RESOURCES
;
604 // the first time , search from current position
609 // since search may be continued to search multiple times
610 // so we need to backup editor each time
614 Status
= FileBufferSearch (Buffer
, Offset
);
616 if (Status
== EFI_NOT_FOUND
) {
622 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
623 if (EFI_ERROR (Status
)) {
628 Status
= InputBarSetStringSize (1);
629 if (EFI_ERROR (Status
)) {
636 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
637 StatusBarSetRefresh();
642 if (Status
== EFI_NOT_READY
) {
647 switch (InputBarGetString()[0]) {
664 // end of while !Done
665 // for search second, third time, search from current position + strlen
667 Offset
= StrLen (Buffer
);
674 StatusBarSetStatusString (L
"Search String Not Found");
680 Search string in file buffer, and replace it with another str.
682 @retval EFI_SUCCESS The operation was successful.
683 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
684 @retval EFI_LOAD_ERROR A load error occured.
687 MainCommandSearchReplace (
696 BOOLEAN ReplaceOption
;
701 ReplaceOption
= FALSE
;
704 // Below is the scenario of Search/Replace command:
705 // 1. An Input Bar is prompted : "Enter Search String:".
706 // IF user press ESC, Search/Replace command ends.
707 // IF user just press Enter, Search/Replace command ends.
708 // IF user inputs the search string S, do Step 2.
710 // 2. An Input Bar is prompted: "Replace With:".
711 // IF user press ESC, Search/Replace command ends.
712 // IF user inputs the replace string R, do Step 3.
714 // 3. IF input search string is not found, an Status String
715 // "Search String Not Found" will be prompted
716 // and Search/Replace command ends
717 // IF input search string is found, do Step 4.
719 // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
720 // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
721 // IF user press 'n' or 'N', S will not be replaced and do Step 5.
722 // IF user press 'a' or 'A', all the S from file current position on
723 // will be replaced with R and Search/Replace command ends.
724 // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
726 // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
727 // IF user press ESC, Search/Replace command ends.
728 // IF user press 'y' or 'Y', do Step 3.
729 // IF user press 'n' or 'N', Search/Replace command ends.
730 // IF user press 'c' or 'C', Search/Replace command ends.
731 // input search string
733 Status
= InputBarSetPrompt (L
"Enter Search String: ");
734 if (EFI_ERROR (Status
)) {
738 Status
= InputBarSetStringSize (40);
739 if (EFI_ERROR (Status
)) {
743 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
744 StatusBarSetRefresh();
749 if (Status
== EFI_NOT_READY
) {
753 // if just pressed enter
755 if (StrLen (InputBarGetString()) == 0) {
759 Search
= CatSPrint (NULL
, L
"%s", InputBarGetString());
760 if (Search
== NULL
) {
761 return EFI_OUT_OF_RESOURCES
;
764 SearchLen
= StrLen (Search
);
767 // input replace string
769 Status
= InputBarSetPrompt (L
"Replace With: ");
770 if (EFI_ERROR (Status
)) {
774 Status
= InputBarSetStringSize (40);
775 if (EFI_ERROR (Status
)) {
779 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
780 StatusBarSetRefresh();
785 if (Status
== EFI_NOT_READY
) {
789 Replace
= CatSPrint (NULL
, L
"%s", InputBarGetString());
790 if (Replace
== NULL
) {
792 return EFI_OUT_OF_RESOURCES
;
795 ReplaceLen
= StrLen (Replace
);
801 // since search may be continued to search multiple times
802 // so we need to backup editor each time
807 Status
= FileBufferSearch (Search
, 0);
810 // if just replace, so skip this replace string
811 // if replace string is an empty string, so skip to next character
814 Status
= FileBufferSearch (Search
, (ReplaceLen
== 0) ? 1 : ReplaceLen
);
816 Status
= FileBufferSearch (Search
, SearchLen
);
820 if (Status
== EFI_NOT_FOUND
) {
826 Status
= InputBarSetPrompt (L
"Replace (Yes/No/All/Cancel) ?");
828 if (EFI_ERROR (Status
)) {
834 Status
= InputBarSetStringSize (1);
835 if (EFI_ERROR (Status
)) {
843 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
844 StatusBarSetRefresh();
849 if (Status
== EFI_NOT_READY
) {
855 switch (InputBarGetString()[0]) {
859 ReplaceOption
= TRUE
;
865 ReplaceOption
= FALSE
;
871 ReplaceOption
= TRUE
;
887 // end of while !Done
894 if (MainEditor
.FileBuffer
->ReadOnly
) {
895 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
902 Status
= FileBufferReplaceAll (Search
, Replace
, 0);
910 Status
= FileBufferReplace (Replace
, SearchLen
);
911 if (EFI_ERROR (Status
)) {
920 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
921 if (EFI_ERROR (Status
)) {
927 Status
= InputBarSetStringSize (1);
928 if (EFI_ERROR (Status
)) {
936 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
937 StatusBarSetRefresh();
942 if (Status
== EFI_NOT_READY
) {
948 switch (InputBarGetString()[0]) {
966 // end of while !Done
977 StatusBarSetStatusString (L
"Search String Not Found");
985 @retval EFI_SUCCESS The operation was successful.
986 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
987 @retval EFI_LOAD_ERROR A load error occured.
997 // Below is the scenario of Exit command:
998 // 1. IF currently opened file is not modified, exit the editor and
999 // Exit command ends.
1000 // IF currently opened file is modified, do Step 2
1002 // 2. An Input Bar will be prompted:
1003 // "File modified. Save ( Yes/No/Cancel )?"
1004 // IF user press 'y' or 'Y', currently opened file will be saved
1006 // IF user press 'n' or 'N', currently opened file will not be saved
1007 // and Editor exits.
1008 // IF user press 'c' or 'C' or ESC, Exit command ends.
1009 // if file has been modified, so will prompt user whether to save the changes
1011 if (MainEditor
.FileBuffer
->FileModified
) {
1013 Status
= InputBarSetPrompt (L
"File modified. Save (Yes/No/Cancel) ? ");
1014 if (EFI_ERROR (Status
)) {
1018 Status
= InputBarSetStringSize (1);
1019 if (EFI_ERROR (Status
)) {
1024 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1025 StatusBarSetRefresh();
1030 if (Status
== EFI_NOT_READY
) {
1034 switch (InputBarGetString()[0]) {
1038 // write file back to disk
1040 Status
= FileBufferSave (MainEditor
.FileBuffer
->FileName
);
1041 if (!EFI_ERROR (Status
)) {
1066 move cursor to specified lines
1068 @retval EFI_SUCCESS The operation was successful.
1071 MainCommandGotoLine (
1079 // Below is the scenario of Go To Line command:
1080 // 1. An Input Bar will be prompted : "Go To Line:".
1081 // IF user press ESC, Go To Line command ends.
1082 // IF user just press Enter, cursor remains unchanged.
1083 // IF user inputs line number, do Step 2.
1085 // 2. IF input line number is valid, move cursor to the beginning
1086 // of specified line and Go To Line command ends.
1087 // IF input line number is invalid, a Status String will be prompted:
1088 // "No Such Line" and Go To Line command ends.
1090 Status
= InputBarSetPrompt (L
"Go To Line: ");
1091 if (EFI_ERROR (Status
)) {
1095 // line number's digit <= 6
1097 Status
= InputBarSetStringSize (6);
1098 if (EFI_ERROR (Status
)) {
1102 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1103 StatusBarSetRefresh();
1108 if (Status
== EFI_NOT_READY
) {
1112 // if JUST press enter
1114 if (StrLen (InputBarGetString()) == 0) {
1118 Row
= ShellStrToUintn (InputBarGetString());
1121 // invalid line number
1123 if (Row
> MainEditor
.FileBuffer
->NumLines
|| Row
<= 0) {
1124 StatusBarSetStatusString (L
"No Such Line");
1128 // move cursor to that line's start
1130 FileBufferMovePosition (Row
, 1);
1136 Save current file to disk, you can save to current file name or
1137 save to another file name.
1139 @retval EFI_SUCCESS The file was saved correctly.
1140 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1141 @retval EFI_LOAD_ERROR A file access error occured.
1144 MainCommandSaveFile (
1152 SHELL_FILE_HANDLE FileHandle
;
1153 EFI_FILE_INFO
*Info
;
1156 // This command will save currently opened file to disk.
1157 // You can choose save to another file name or just save to
1158 // current file name.
1159 // Below is the scenario of Save File command:
1160 // ( Suppose the old file name is A )
1161 // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
1162 // IF user press ESC, Save File command ends .
1163 // IF user press Enter, input file name will be A.
1164 // IF user inputs a new file name B, input file name will be B.
1166 // 2. IF input file name is A, go to do Step 3.
1167 // IF input file name is B, go to do Step 4.
1169 // 3. IF A is read only, Status Bar will show "Access Denied" and
1170 // Save File commands ends.
1171 // IF A is not read only, save file buffer to disk and remove modified
1172 // flag in Title Bar , then Save File command ends.
1174 // 4. IF B does not exist, create this file and save file buffer to it.
1176 // IF B exits, do Step 5.
1178 // 5.An Input Bar will be prompted:
1179 // "File Exists. Overwrite ( Yes/No/Cancel )?"
1180 // IF user press 'y' or 'Y', do Step 6.
1181 // IF user press 'n' or 'N', Save File commands ends.
1182 // IF user press 'c' or 'C' or ESC, Save File commands ends.
1184 // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
1185 // Save File commands ends.
1186 // IF B can be read and write, save file buffer to B.
1188 // 7. Update File Name field in Title Bar to B and remove the modified
1189 // flag in Title Bar.
1191 Str
= CatSPrint (NULL
, L
"File to Save: [%s]", MainEditor
.FileBuffer
->FileName
);
1193 return EFI_OUT_OF_RESOURCES
;
1196 if (StrLen (Str
) >= 50) {
1198 // replace the long file name with "..."
1204 Str
[50] = CHAR_NULL
;
1207 Status
= InputBarSetPrompt (Str
);
1210 if (EFI_ERROR (Status
)) {
1215 Status
= InputBarSetStringSize (100);
1216 if (EFI_ERROR (Status
)) {
1220 // get new file name
1222 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1223 StatusBarSetRefresh();
1226 // if user pressed ESC
1228 if (Status
== EFI_NOT_READY
) {
1233 // if just enter pressed, so think save to current file name
1235 if (StrLen (InputBarGetString()) == 0) {
1236 FileName
= CatSPrint (NULL
, L
"%s", MainEditor
.FileBuffer
->FileName
);
1238 FileName
= CatSPrint (NULL
, L
"%s", InputBarGetString());
1241 if (FileName
== NULL
) {
1242 return EFI_OUT_OF_RESOURCES
;
1245 if (!IsValidFileName (FileName
)) {
1246 StatusBarSetStatusString (L
"Invalid File Name");
1247 FreePool (FileName
);
1254 // save to the old file
1256 if (StringNoCaseCompare (&FileName
, &MainEditor
.FileBuffer
->FileName
) == 0) {
1262 // if the file is read only, so can not write back to it.
1264 if (MainEditor
.FileBuffer
->ReadOnly
== TRUE
) {
1265 StatusBarSetStatusString (L
"Access Denied");
1266 FreePool (FileName
);
1271 // if the file exists
1273 if (ShellFileExists(FileName
) != EFI_NOT_FOUND
) {
1275 // check for read only
1277 Status
= ShellOpenFileByName(FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
1278 if (EFI_ERROR(Status
)) {
1279 StatusBarSetStatusString (L
"Open Failed");
1280 FreePool (FileName
);
1284 Info
= ShellGetFileInfo(FileHandle
);
1286 StatusBarSetStatusString (L
"Access Denied");
1287 FreePool (FileName
);
1288 return (EFI_SUCCESS
);
1291 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
1292 StatusBarSetStatusString (L
"Access Denied - Read Only");
1294 FreePool (FileName
);
1295 return (EFI_SUCCESS
);
1300 // ask user whether to overwrite this file
1302 Status
= InputBarSetPrompt (L
"File exists. Overwrite (Yes/No/Cancel) ? ");
1303 if (EFI_ERROR (Status
)) {
1304 SHELL_FREE_NON_NULL (FileName
);
1308 Status
= InputBarSetStringSize (1);
1309 if (EFI_ERROR (Status
)) {
1310 SHELL_FREE_NON_NULL (FileName
);
1315 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1316 StatusBarSetRefresh();
1321 if (Status
== EFI_NOT_READY
) {
1322 SHELL_FREE_NON_NULL (FileName
);
1326 switch (InputBarGetString()[0]) {
1335 SHELL_FREE_NON_NULL (FileName
);
1339 } // file does exist
1340 } // if old file name same
1343 // save file to disk with specified name
1345 FileBufferSetModified();
1346 Status
= FileBufferSave (FileName
);
1347 SHELL_FREE_NON_NULL (FileName
);
1353 Show help information for the editor.
1355 @retval EFI_SUCCESS The operation was successful.
1358 MainCommandDisplayHelp (
1369 for (CurrentLine
= 0; 0 != MainMenuHelpInfo
[CurrentLine
]; CurrentLine
++) {
1370 InfoString
= HiiGetString(gShellDebug1HiiHandle
, MainMenuHelpInfo
[CurrentLine
], NULL
);
1371 ShellPrintEx (0, CurrentLine
+1, L
"%E%s%N", InfoString
);
1378 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1379 } while(SCAN_CONTROL_W
!= Key
.UnicodeChar
);
1382 // update screen with file buffer's info
1384 FileBufferRestorePosition ();
1385 FileBufferNeedRefresh
= TRUE
;
1386 FileBufferOnlyLineNeedRefresh
= FALSE
;
1387 FileBufferRefresh ();
1392 EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors
;
1397 // basic initialization for MainEditor
1399 EFI_EDITOR_GLOBAL_EDITOR MainEditorConst
= {
1414 The initialization function for MainEditor.
1416 @retval EFI_SUCCESS The operation was successful.
1417 @retval EFI_LOAD_ERROR A load error occured.
1426 EFI_HANDLE
*HandleBuffer
;
1431 // basic initialization
1433 CopyMem (&MainEditor
, &MainEditorConst
, sizeof (MainEditor
));
1436 // set screen attributes
1438 MainEditor
.ColorAttributes
.Colors
.Foreground
= gST
->ConOut
->Mode
->Attribute
& 0x000000ff;
1440 MainEditor
.ColorAttributes
.Colors
.Background
= (UINT8
) (gST
->ConOut
->Mode
->Attribute
>> 4);
1441 OriginalColors
= MainEditor
.ColorAttributes
.Colors
;
1443 OriginalMode
= gST
->ConOut
->Mode
->Mode
;
1446 // query screen size
1448 gST
->ConOut
->QueryMode (
1450 gST
->ConOut
->Mode
->Mode
,
1451 &(MainEditor
.ScreenSize
.Column
),
1452 &(MainEditor
.ScreenSize
.Row
)
1456 // Find mouse in System Table ConsoleInHandle
1458 Status
= gBS
->HandleProtocol (
1460 &gEfiSimplePointerProtocolGuid
,
1461 (VOID
**)&MainEditor
.MouseInterface
1463 if (EFI_ERROR (Status
)) {
1465 // If there is no Simple Pointer Protocol on System Table
1467 HandleBuffer
= NULL
;
1468 MainEditor
.MouseInterface
= NULL
;
1469 Status
= gBS
->LocateHandleBuffer (
1471 &gEfiSimplePointerProtocolGuid
,
1476 if (!EFI_ERROR (Status
) && HandleCount
> 0) {
1478 // Try to find the first available mouse device
1480 for (Index
= 0; Index
< HandleCount
; Index
++) {
1481 Status
= gBS
->HandleProtocol (
1482 HandleBuffer
[Index
],
1483 &gEfiSimplePointerProtocolGuid
,
1484 (VOID
**)&MainEditor
.MouseInterface
1486 if (!EFI_ERROR (Status
)) {
1491 if (HandleBuffer
!= NULL
) {
1492 FreePool (HandleBuffer
);
1496 if (!EFI_ERROR (Status
) && MainEditor
.MouseInterface
!= NULL
) {
1497 MainEditor
.MouseAccumulatorX
= 0;
1498 MainEditor
.MouseAccumulatorY
= 0;
1499 MainEditor
.MouseSupported
= TRUE
;
1503 // below will call the five components' init function
1505 Status
= MainTitleBarInit (L
"UEFI EDIT 2.0");
1506 if (EFI_ERROR (Status
)) {
1507 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR
), gShellDebug1HiiHandle
);
1508 return EFI_LOAD_ERROR
;
1511 Status
= ControlHotKeyInit (MainControlBasedMenuFunctions
);
1512 Status
= MenuBarInit (MainMenuItems
);
1513 if (EFI_ERROR (Status
)) {
1514 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU
), gShellDebug1HiiHandle
);
1515 return EFI_LOAD_ERROR
;
1518 Status
= StatusBarInit ();
1519 if (EFI_ERROR (Status
)) {
1520 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR
), gShellDebug1HiiHandle
);
1521 return EFI_LOAD_ERROR
;
1526 Status
= FileBufferInit ();
1527 if (EFI_ERROR (Status
)) {
1528 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER
), gShellDebug1HiiHandle
);
1529 return EFI_LOAD_ERROR
;
1532 // clear whole screen and enable cursor
1534 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1535 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
1538 // initialize EditorFirst and EditorExit
1542 EditorMouseAction
= FALSE
;
1548 The cleanup function for MainEditor.
1550 @retval EFI_SUCCESS The operation was successful.
1551 @retval EFI_LOAD_ERROR A load error occured.
1562 // call the five components' cleanup function
1563 // if error, do not exit
1564 // just print some warning
1566 MainTitleBarCleanup();
1571 Status
= FileBufferCleanup ();
1572 if (EFI_ERROR (Status
)) {
1573 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP
), gShellDebug1HiiHandle
);
1578 if (OriginalMode
!= gST
->ConOut
->Mode
->Mode
) {
1579 gST
->ConOut
->SetMode (gST
->ConOut
, OriginalMode
);
1582 // restore old screen color
1584 gST
->ConOut
->SetAttribute (
1586 EFI_TEXT_ATTR (OriginalColors
.Foreground
, OriginalColors
.Background
)
1589 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1595 Refresh the main editor component.
1604 // The Stall value is from experience. NOT from spec. avoids 'flicker'
1609 // call the components refresh function
1612 || StrCmp (FileBufferBackupVar
.FileName
, FileBuffer
.FileName
) != 0
1613 || FileBufferBackupVar
.FileType
!= FileBuffer
.FileType
1614 || FileBufferBackupVar
.FileModified
!= FileBuffer
.FileModified
1615 || FileBufferBackupVar
.ReadOnly
!= FileBuffer
.ReadOnly
) {
1617 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
1618 FileBufferRestorePosition ();
1619 FileBufferRefresh ();
1622 || FileBufferBackupVar
.FilePosition
.Row
!= FileBuffer
.FilePosition
.Row
1623 || FileBufferBackupVar
.FilePosition
.Column
!= FileBuffer
.FilePosition
.Column
1624 || FileBufferBackupVar
.ModeInsert
!= FileBuffer
.ModeInsert
1625 || StatusBarGetRefresh()) {
1627 StatusBarRefresh (EditorFirst
, MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.FileBuffer
->FilePosition
.Row
, MainEditor
.FileBuffer
->FilePosition
.Column
, MainEditor
.FileBuffer
->ModeInsert
);
1628 FileBufferRestorePosition ();
1629 FileBufferRefresh ();
1633 FileBufferRestorePosition ();
1637 // EditorFirst is now set to FALSE
1639 EditorFirst
= FALSE
;
1643 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1645 @param[in] GuidX The relative mouse movement.
1647 @return The X location of the mouse.
1657 MainEditor
.MouseAccumulatorX
+= GuidX
;
1658 Gap
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1659 MainEditor
.MouseAccumulatorX
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1660 MainEditor
.MouseAccumulatorX
= MainEditor
.MouseAccumulatorX
/ (INT32
) MainEditor
.ScreenSize
.Column
;
1665 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1667 @param[in] GuidY The relative mouse movement.
1669 @return The Y location of the mouse.
1679 MainEditor
.MouseAccumulatorY
+= GuidY
;
1680 Gap
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1681 MainEditor
.MouseAccumulatorY
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1682 MainEditor
.MouseAccumulatorY
= MainEditor
.MouseAccumulatorY
/ (INT32
) MainEditor
.ScreenSize
.Row
;
1688 Support mouse movement. Move the cursor.
1690 @param[in] MouseState The current mouse state.
1692 @retval EFI_SUCCESS The operation was successful.
1693 @retval EFI_NOT_FOUND There was no mouse support found.
1697 MainEditorHandleMouseInput (
1698 IN EFI_SIMPLE_POINTER_STATE MouseState
1708 EFI_EDITOR_LINE
*Line
;
1714 // mouse action means:
1716 // mouse left button
1721 // have mouse movement
1723 if (MouseState
.RelativeMovementX
|| MouseState
.RelativeMovementY
) {
1727 TextX
= GetTextX (MouseState
.RelativeMovementX
);
1728 TextY
= GetTextY (MouseState
.RelativeMovementY
);
1730 FileBufferAdjustMousePosition (TextX
, TextY
);
1737 // if left button pushed down
1739 if (MouseState
.LeftButton
) {
1741 FCol
= MainEditor
.FileBuffer
->MousePosition
.Column
- 1 + 1;
1743 FRow
= MainEditor
.FileBuffer
->FilePosition
.Row
+
1744 MainEditor
.FileBuffer
->MousePosition
.Row
-
1745 MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1748 // beyond the file line length
1750 if (MainEditor
.FileBuffer
->NumLines
< FRow
) {
1751 FRow
= MainEditor
.FileBuffer
->NumLines
;
1754 Link
= MainEditor
.FileBuffer
->ListHead
->ForwardLink
;
1755 for (Index
= 0; Index
< FRow
- 1; Index
++) {
1756 Link
= Link
->ForwardLink
;
1759 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1762 // beyond the line's column length
1764 if (FCol
> Line
->Size
+ 1) {
1765 FCol
= Line
->Size
+ 1;
1768 FileBufferMovePosition (FRow
, FCol
);
1770 MainEditor
.FileBuffer
->MousePosition
.Row
= MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1772 MainEditor
.FileBuffer
->MousePosition
.Column
= MainEditor
.FileBuffer
->DisplayPosition
.Column
;
1786 return EFI_NOT_FOUND
;
1790 Handle user key input. This routes to other functions for the actions.
1792 @retval EFI_SUCCESS The operation was successful.
1793 @retval EFI_LOAD_ERROR A load error occured.
1794 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1798 MainEditorKeyInput (
1804 EFI_SIMPLE_POINTER_STATE MouseState
;
1808 Status
= EFI_SUCCESS
;
1809 EditorMouseAction
= FALSE
;
1812 // backup some key elements, so that can aVOID some refresh work
1814 MainEditorBackup ();
1817 // change priority of checking mouse/keyboard activity dynamically
1818 // so prevent starvation of keyboard.
1819 // if last time, mouse moves then this time check keyboard
1821 if (MainEditor
.MouseSupported
) {
1822 Status
= MainEditor
.MouseInterface
->GetState (
1823 MainEditor
.MouseInterface
,
1826 if (!EFI_ERROR (Status
)) {
1828 Status
= MainEditorHandleMouseInput (MouseState
);
1830 if (!EFI_ERROR (Status
)) {
1831 EditorMouseAction
= TRUE
;
1832 FileBufferMouseNeedRefresh
= TRUE
;
1833 } else if (Status
== EFI_LOAD_ERROR
) {
1834 StatusBarSetStatusString (L
"Invalid Mouse Movement ");
1839 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1840 if (!EFI_ERROR (Status
)) {
1842 // dispatch to different components' key handling function
1843 // so not everywhere has to set this variable
1845 FileBufferMouseNeedRefresh
= TRUE
;
1847 // clear previous status string
1849 StatusBarSetRefresh();
1852 // dispatch to different components' key handling function
1854 if (EFI_NOT_FOUND
!= MenuBarDispatchControlHotKey(&Key
)) {
1855 Status
= EFI_SUCCESS
;
1856 } else if ((Key
.ScanCode
== SCAN_NULL
) || ((Key
.ScanCode
>= SCAN_UP
) && (Key
.ScanCode
<= SCAN_PAGE_DOWN
))) {
1857 Status
= FileBufferHandleInput (&Key
);
1858 } else if ((Key
.ScanCode
>= SCAN_F1
) && (Key
.ScanCode
<= SCAN_F12
)) {
1859 Status
= MenuBarDispatchFunctionKey (&Key
);
1861 StatusBarSetStatusString (L
"Unknown Command");
1862 FileBufferMouseNeedRefresh
= FALSE
;
1865 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_OUT_OF_RESOURCES
) {
1867 // not already has some error status
1869 if (StatusBarGetString() != NULL
&& StrCmp (L
"", StatusBarGetString()) == 0) {
1870 StatusBarSetStatusString (L
"Disk Error. Try Again");
1876 // after handling, refresh editor
1878 MainEditorRefresh ();
1880 } while (Status
!= EFI_OUT_OF_RESOURCES
&& !EditorExit
);
1888 @param[in] Line A pointer to the line to be set to clipboard
1890 @retval EFI_SUCCESS The operation was successful.
1891 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1895 MainEditorSetCutLine (
1896 EFI_EDITOR_LINE
*Line
1903 if (MainEditor
.CutLine
!= NULL
) {
1905 // free the old clipboard
1907 LineFree (MainEditor
.CutLine
);
1910 // duplicate the line to clipboard
1912 MainEditor
.CutLine
= LineDup (Line
);
1913 if (MainEditor
.CutLine
== NULL
) {
1914 return EFI_OUT_OF_RESOURCES
;
1921 Backup function for MainEditor
1923 @retval EFI_SUCCESS The operation was successful.
1931 FileBufferBackup ();