2 Implements editor interface functions.
4 Copyright (c) 2005 - 2016, 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 :
493 Status
= FileBufferCutLine (&Line
);
494 if (Status
== EFI_NOT_FOUND
) {
498 if (EFI_ERROR (Status
)) {
502 MainEditor
.CutLine
= Line
;
508 paste line to file buffer.
510 @retval EFI_SUCCESS The operation was successful.
511 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
512 @retval EFI_LOAD_ERROR A load error occured.
515 MainCommandPasteLine (
522 // Below is the scenario of Paste Line command:
523 // 1. IF nothing is on clipboard, a Status String will be prompted :
524 // "No Line to Paste" and Paste Line command ends.
525 // IF something is on clipboard, insert it above current line.
526 // nothing on clipboard
528 if (MainEditor
.CutLine
== NULL
) {
529 StatusBarSetStatusString (L
"No Line to Paste");
533 Status
= FileBufferPasteLine ();
540 search string in file buffer
542 @retval EFI_SUCCESS The operation was successful.
543 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
544 @retval EFI_LOAD_ERROR A load error occured.
557 // Below is the scenario of Search command:
558 // 1. An Input Bar will be prompted : "Enter Search String:".
559 // IF user press ESC, Search command ends.
560 // IF user just press Enter, Search command ends.
561 // IF user inputs the search string, do Step 2.
563 // 2. IF input search string is found, cursor will move to the first
564 // occurrence and do Step 3.
565 // IF input search string is not found, a Status String
566 // "Search String Not Found" will be prompted and Search command ends.
568 // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
569 // IF user press ESC, Search command ends.
570 // IF user press 'y' or 'Y', do Step 2.
571 // IF user press 'n' or 'N', Search command ends.
572 // IF user press 'c' or 'C', Search command ends.
574 Status
= InputBarSetPrompt (L
"Enter Search String: ");
575 if (EFI_ERROR (Status
)) {
579 Status
= InputBarSetStringSize (40);
580 if (EFI_ERROR (Status
)) {
584 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
585 StatusBarSetRefresh();
590 if (Status
== EFI_NOT_READY
) {
594 // just enter pressed
596 if (StrLen (InputBarGetString()) == 0) {
600 Buffer
= CatSPrint (NULL
, L
"%s", InputBarGetString());
601 if (Buffer
== NULL
) {
602 return EFI_OUT_OF_RESOURCES
;
605 // the first time , search from current position
610 // since search may be continued to search multiple times
611 // so we need to backup editor each time
615 Status
= FileBufferSearch (Buffer
, Offset
);
617 if (Status
== EFI_NOT_FOUND
) {
623 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
624 if (EFI_ERROR (Status
)) {
629 Status
= InputBarSetStringSize (1);
630 if (EFI_ERROR (Status
)) {
637 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
638 StatusBarSetRefresh();
643 if (Status
== EFI_NOT_READY
) {
648 switch (InputBarGetString()[0]) {
665 // end of while !Done
666 // for search second, third time, search from current position + strlen
668 Offset
= StrLen (Buffer
);
675 StatusBarSetStatusString (L
"Search String Not Found");
681 Search string in file buffer, and replace it with another str.
683 @retval EFI_SUCCESS The operation was successful.
684 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
685 @retval EFI_LOAD_ERROR A load error occured.
688 MainCommandSearchReplace (
697 BOOLEAN ReplaceOption
;
702 ReplaceOption
= FALSE
;
705 // Below is the scenario of Search/Replace command:
706 // 1. An Input Bar is prompted : "Enter Search String:".
707 // IF user press ESC, Search/Replace command ends.
708 // IF user just press Enter, Search/Replace command ends.
709 // IF user inputs the search string S, do Step 2.
711 // 2. An Input Bar is prompted: "Replace With:".
712 // IF user press ESC, Search/Replace command ends.
713 // IF user inputs the replace string R, do Step 3.
715 // 3. IF input search string is not found, an Status String
716 // "Search String Not Found" will be prompted
717 // and Search/Replace command ends
718 // IF input search string is found, do Step 4.
720 // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
721 // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
722 // IF user press 'n' or 'N', S will not be replaced and do Step 5.
723 // IF user press 'a' or 'A', all the S from file current position on
724 // will be replaced with R and Search/Replace command ends.
725 // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
727 // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
728 // IF user press ESC, Search/Replace command ends.
729 // IF user press 'y' or 'Y', do Step 3.
730 // IF user press 'n' or 'N', Search/Replace command ends.
731 // IF user press 'c' or 'C', Search/Replace command ends.
732 // input search string
734 Status
= InputBarSetPrompt (L
"Enter Search String: ");
735 if (EFI_ERROR (Status
)) {
739 Status
= InputBarSetStringSize (40);
740 if (EFI_ERROR (Status
)) {
744 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
745 StatusBarSetRefresh();
750 if (Status
== EFI_NOT_READY
) {
754 // if just pressed enter
756 if (StrLen (InputBarGetString()) == 0) {
760 Search
= CatSPrint (NULL
, L
"%s", InputBarGetString());
761 if (Search
== NULL
) {
762 return EFI_OUT_OF_RESOURCES
;
765 SearchLen
= StrLen (Search
);
768 // input replace string
770 Status
= InputBarSetPrompt (L
"Replace With: ");
771 if (EFI_ERROR (Status
)) {
775 Status
= InputBarSetStringSize (40);
776 if (EFI_ERROR (Status
)) {
780 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
781 StatusBarSetRefresh();
786 if (Status
== EFI_NOT_READY
) {
790 Replace
= CatSPrint (NULL
, L
"%s", InputBarGetString());
791 if (Replace
== NULL
) {
793 return EFI_OUT_OF_RESOURCES
;
796 ReplaceLen
= StrLen (Replace
);
802 // since search may be continued to search multiple times
803 // so we need to backup editor each time
808 Status
= FileBufferSearch (Search
, 0);
811 // if just replace, so skip this replace string
812 // if replace string is an empty string, so skip to next character
815 Status
= FileBufferSearch (Search
, (ReplaceLen
== 0) ? 1 : ReplaceLen
);
817 Status
= FileBufferSearch (Search
, SearchLen
);
821 if (Status
== EFI_NOT_FOUND
) {
827 Status
= InputBarSetPrompt (L
"Replace (Yes/No/All/Cancel) ?");
829 if (EFI_ERROR (Status
)) {
835 Status
= InputBarSetStringSize (1);
836 if (EFI_ERROR (Status
)) {
844 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
845 StatusBarSetRefresh();
850 if (Status
== EFI_NOT_READY
) {
856 switch (InputBarGetString()[0]) {
860 ReplaceOption
= TRUE
;
866 ReplaceOption
= FALSE
;
872 ReplaceOption
= TRUE
;
888 // end of while !Done
895 if (MainEditor
.FileBuffer
->ReadOnly
) {
896 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
903 Status
= FileBufferReplaceAll (Search
, Replace
, 0);
911 Status
= FileBufferReplace (Replace
, SearchLen
);
912 if (EFI_ERROR (Status
)) {
921 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
922 if (EFI_ERROR (Status
)) {
928 Status
= InputBarSetStringSize (1);
929 if (EFI_ERROR (Status
)) {
937 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
938 StatusBarSetRefresh();
943 if (Status
== EFI_NOT_READY
) {
949 switch (InputBarGetString()[0]) {
967 // end of while !Done
978 StatusBarSetStatusString (L
"Search String Not Found");
986 @retval EFI_SUCCESS The operation was successful.
987 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
988 @retval EFI_LOAD_ERROR A load error occured.
998 // Below is the scenario of Exit command:
999 // 1. IF currently opened file is not modified, exit the editor and
1000 // Exit command ends.
1001 // IF currently opened file is modified, do Step 2
1003 // 2. An Input Bar will be prompted:
1004 // "File modified. Save ( Yes/No/Cancel )?"
1005 // IF user press 'y' or 'Y', currently opened file will be saved
1007 // IF user press 'n' or 'N', currently opened file will not be saved
1008 // and Editor exits.
1009 // IF user press 'c' or 'C' or ESC, Exit command ends.
1010 // if file has been modified, so will prompt user whether to save the changes
1012 if (MainEditor
.FileBuffer
->FileModified
) {
1014 Status
= InputBarSetPrompt (L
"File modified. Save (Yes/No/Cancel) ? ");
1015 if (EFI_ERROR (Status
)) {
1019 Status
= InputBarSetStringSize (1);
1020 if (EFI_ERROR (Status
)) {
1025 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1026 StatusBarSetRefresh();
1031 if (Status
== EFI_NOT_READY
) {
1035 switch (InputBarGetString()[0]) {
1039 // write file back to disk
1041 Status
= FileBufferSave (MainEditor
.FileBuffer
->FileName
);
1042 if (!EFI_ERROR (Status
)) {
1067 move cursor to specified lines
1069 @retval EFI_SUCCESS The operation was successful.
1072 MainCommandGotoLine (
1080 // Below is the scenario of Go To Line command:
1081 // 1. An Input Bar will be prompted : "Go To Line:".
1082 // IF user press ESC, Go To Line command ends.
1083 // IF user just press Enter, cursor remains unchanged.
1084 // IF user inputs line number, do Step 2.
1086 // 2. IF input line number is valid, move cursor to the beginning
1087 // of specified line and Go To Line command ends.
1088 // IF input line number is invalid, a Status String will be prompted:
1089 // "No Such Line" and Go To Line command ends.
1091 Status
= InputBarSetPrompt (L
"Go To Line: ");
1092 if (EFI_ERROR (Status
)) {
1096 // line number's digit <= 6
1098 Status
= InputBarSetStringSize (6);
1099 if (EFI_ERROR (Status
)) {
1103 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1104 StatusBarSetRefresh();
1109 if (Status
== EFI_NOT_READY
) {
1113 // if JUST press enter
1115 if (StrLen (InputBarGetString()) == 0) {
1119 Row
= ShellStrToUintn (InputBarGetString());
1122 // invalid line number
1124 if (Row
> MainEditor
.FileBuffer
->NumLines
|| Row
<= 0) {
1125 StatusBarSetStatusString (L
"No Such Line");
1129 // move cursor to that line's start
1131 FileBufferMovePosition (Row
, 1);
1137 Save current file to disk, you can save to current file name or
1138 save to another file name.
1140 @retval EFI_SUCCESS The file was saved correctly.
1141 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1142 @retval EFI_LOAD_ERROR A file access error occured.
1145 MainCommandSaveFile (
1153 SHELL_FILE_HANDLE FileHandle
;
1154 EFI_FILE_INFO
*Info
;
1157 // This command will save currently opened file to disk.
1158 // You can choose save to another file name or just save to
1159 // current file name.
1160 // Below is the scenario of Save File command:
1161 // ( Suppose the old file name is A )
1162 // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
1163 // IF user press ESC, Save File command ends .
1164 // IF user press Enter, input file name will be A.
1165 // IF user inputs a new file name B, input file name will be B.
1167 // 2. IF input file name is A, go to do Step 3.
1168 // IF input file name is B, go to do Step 4.
1170 // 3. IF A is read only, Status Bar will show "Access Denied" and
1171 // Save File commands ends.
1172 // IF A is not read only, save file buffer to disk and remove modified
1173 // flag in Title Bar , then Save File command ends.
1175 // 4. IF B does not exist, create this file and save file buffer to it.
1177 // IF B exits, do Step 5.
1179 // 5.An Input Bar will be prompted:
1180 // "File Exists. Overwrite ( Yes/No/Cancel )?"
1181 // IF user press 'y' or 'Y', do Step 6.
1182 // IF user press 'n' or 'N', Save File commands ends.
1183 // IF user press 'c' or 'C' or ESC, Save File commands ends.
1185 // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
1186 // Save File commands ends.
1187 // IF B can be read and write, save file buffer to B.
1189 // 7. Update File Name field in Title Bar to B and remove the modified
1190 // flag in Title Bar.
1192 Str
= CatSPrint (NULL
, L
"File to Save: [%s]", MainEditor
.FileBuffer
->FileName
);
1194 return EFI_OUT_OF_RESOURCES
;
1197 if (StrLen (Str
) >= 50) {
1199 // replace the long file name with "..."
1205 Str
[50] = CHAR_NULL
;
1208 Status
= InputBarSetPrompt (Str
);
1211 if (EFI_ERROR (Status
)) {
1216 Status
= InputBarSetStringSize (100);
1217 if (EFI_ERROR (Status
)) {
1221 // get new file name
1223 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1224 StatusBarSetRefresh();
1227 // if user pressed ESC
1229 if (Status
== EFI_NOT_READY
) {
1234 // if just enter pressed, so think save to current file name
1236 if (StrLen (InputBarGetString()) == 0) {
1237 FileName
= CatSPrint (NULL
, L
"%s", MainEditor
.FileBuffer
->FileName
);
1239 FileName
= CatSPrint (NULL
, L
"%s", InputBarGetString());
1242 if (FileName
== NULL
) {
1243 return EFI_OUT_OF_RESOURCES
;
1246 if (!IsValidFileName (FileName
)) {
1247 StatusBarSetStatusString (L
"Invalid File Name");
1248 FreePool (FileName
);
1255 // save to the old file
1257 if (StringNoCaseCompare (&FileName
, &MainEditor
.FileBuffer
->FileName
) == 0) {
1263 // if the file is read only, so can not write back to it.
1265 if (MainEditor
.FileBuffer
->ReadOnly
== TRUE
) {
1266 StatusBarSetStatusString (L
"Access Denied");
1267 FreePool (FileName
);
1272 // if the file exists
1274 if (ShellFileExists(FileName
) != EFI_NOT_FOUND
) {
1276 // check for read only
1278 Status
= ShellOpenFileByName(FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
1279 if (EFI_ERROR(Status
)) {
1280 StatusBarSetStatusString (L
"Open Failed");
1281 FreePool (FileName
);
1285 Info
= ShellGetFileInfo(FileHandle
);
1287 StatusBarSetStatusString (L
"Access Denied");
1288 FreePool (FileName
);
1289 return (EFI_SUCCESS
);
1292 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
1293 StatusBarSetStatusString (L
"Access Denied - Read Only");
1295 FreePool (FileName
);
1296 return (EFI_SUCCESS
);
1301 // ask user whether to overwrite this file
1303 Status
= InputBarSetPrompt (L
"File exists. Overwrite (Yes/No/Cancel) ? ");
1304 if (EFI_ERROR (Status
)) {
1305 SHELL_FREE_NON_NULL (FileName
);
1309 Status
= InputBarSetStringSize (1);
1310 if (EFI_ERROR (Status
)) {
1311 SHELL_FREE_NON_NULL (FileName
);
1316 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1317 StatusBarSetRefresh();
1322 if (Status
== EFI_NOT_READY
) {
1323 SHELL_FREE_NON_NULL (FileName
);
1327 switch (InputBarGetString()[0]) {
1336 SHELL_FREE_NON_NULL (FileName
);
1340 } // file does exist
1341 } // if old file name same
1344 // save file to disk with specified name
1346 FileBufferSetModified();
1347 Status
= FileBufferSave (FileName
);
1348 SHELL_FREE_NON_NULL (FileName
);
1354 Show help information for the editor.
1356 @retval EFI_SUCCESS The operation was successful.
1359 MainCommandDisplayHelp (
1370 for (CurrentLine
= 0; 0 != MainMenuHelpInfo
[CurrentLine
]; CurrentLine
++) {
1371 InfoString
= HiiGetString(gShellDebug1HiiHandle
, MainMenuHelpInfo
[CurrentLine
], NULL
);
1372 ShellPrintEx (0, CurrentLine
+1, L
"%E%s%N", InfoString
);
1379 gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1380 } while(SCAN_CONTROL_W
!= Key
.UnicodeChar
);
1383 // update screen with file buffer's info
1385 FileBufferRestorePosition ();
1386 FileBufferNeedRefresh
= TRUE
;
1387 FileBufferOnlyLineNeedRefresh
= FALSE
;
1388 FileBufferRefresh ();
1393 EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors
;
1398 // basic initialization for MainEditor
1400 EFI_EDITOR_GLOBAL_EDITOR MainEditorConst
= {
1415 The initialization function for MainEditor.
1417 @retval EFI_SUCCESS The operation was successful.
1418 @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");
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.
1561 // call the five components' cleanup function
1562 // if error, do not exit
1563 // just print some warning
1565 MainTitleBarCleanup();
1570 Status
= FileBufferCleanup ();
1571 if (EFI_ERROR (Status
)) {
1572 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP
), gShellDebug1HiiHandle
);
1577 if (OriginalMode
!= gST
->ConOut
->Mode
->Mode
) {
1578 gST
->ConOut
->SetMode (gST
->ConOut
, OriginalMode
);
1581 // restore old screen color
1583 gST
->ConOut
->SetAttribute (
1585 EFI_TEXT_ATTR (OriginalColors
.Foreground
, OriginalColors
.Background
)
1588 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1594 Refresh the main editor component.
1602 // The Stall value is from experience. NOT from spec. avoids 'flicker'
1607 // call the components refresh function
1610 || StrCmp (FileBufferBackupVar
.FileName
, FileBuffer
.FileName
) != 0
1611 || FileBufferBackupVar
.FileType
!= FileBuffer
.FileType
1612 || FileBufferBackupVar
.FileModified
!= FileBuffer
.FileModified
1613 || FileBufferBackupVar
.ReadOnly
!= FileBuffer
.ReadOnly
) {
1615 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
1616 FileBufferRestorePosition ();
1620 || FileBufferBackupVar
.FilePosition
.Row
!= FileBuffer
.FilePosition
.Row
1621 || FileBufferBackupVar
.FilePosition
.Column
!= FileBuffer
.FilePosition
.Column
1622 || FileBufferBackupVar
.ModeInsert
!= FileBuffer
.ModeInsert
1623 || StatusBarGetRefresh()) {
1625 StatusBarRefresh (EditorFirst
, MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.FileBuffer
->FilePosition
.Row
, MainEditor
.FileBuffer
->FilePosition
.Column
, MainEditor
.FileBuffer
->ModeInsert
);
1626 FileBufferRestorePosition ();
1630 FileBufferRestorePosition ();
1633 FileBufferRefresh ();
1636 // EditorFirst is now set to FALSE
1638 EditorFirst
= FALSE
;
1642 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1644 @param[in] GuidX The relative mouse movement.
1646 @return The X location of the mouse.
1655 MainEditor
.MouseAccumulatorX
+= GuidX
;
1656 Gap
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1657 MainEditor
.MouseAccumulatorX
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1658 MainEditor
.MouseAccumulatorX
= MainEditor
.MouseAccumulatorX
/ (INT32
) MainEditor
.ScreenSize
.Column
;
1663 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1665 @param[in] GuidY The relative mouse movement.
1667 @return The Y location of the mouse.
1676 MainEditor
.MouseAccumulatorY
+= GuidY
;
1677 Gap
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1678 MainEditor
.MouseAccumulatorY
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1679 MainEditor
.MouseAccumulatorY
= MainEditor
.MouseAccumulatorY
/ (INT32
) MainEditor
.ScreenSize
.Row
;
1685 Support mouse movement. Move the cursor.
1687 @param[in] MouseState The current mouse state.
1689 @retval EFI_SUCCESS The operation was successful.
1690 @retval EFI_NOT_FOUND There was no mouse support found.
1693 MainEditorHandleMouseInput (
1694 IN EFI_SIMPLE_POINTER_STATE MouseState
1704 EFI_EDITOR_LINE
*Line
;
1710 // mouse action means:
1712 // mouse left button
1717 // have mouse movement
1719 if (MouseState
.RelativeMovementX
|| MouseState
.RelativeMovementY
) {
1723 TextX
= GetTextX (MouseState
.RelativeMovementX
);
1724 TextY
= GetTextY (MouseState
.RelativeMovementY
);
1726 FileBufferAdjustMousePosition (TextX
, TextY
);
1733 // if left button pushed down
1735 if (MouseState
.LeftButton
) {
1737 FCol
= MainEditor
.FileBuffer
->MousePosition
.Column
- 1 + 1;
1739 FRow
= MainEditor
.FileBuffer
->FilePosition
.Row
+
1740 MainEditor
.FileBuffer
->MousePosition
.Row
-
1741 MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1744 // beyond the file line length
1746 if (MainEditor
.FileBuffer
->NumLines
< FRow
) {
1747 FRow
= MainEditor
.FileBuffer
->NumLines
;
1750 Link
= MainEditor
.FileBuffer
->ListHead
->ForwardLink
;
1751 for (Index
= 0; Index
< FRow
- 1; Index
++) {
1752 Link
= Link
->ForwardLink
;
1755 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1758 // beyond the line's column length
1760 if (FCol
> Line
->Size
+ 1) {
1761 FCol
= Line
->Size
+ 1;
1764 FileBufferMovePosition (FRow
, FCol
);
1766 MainEditor
.FileBuffer
->MousePosition
.Row
= MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1768 MainEditor
.FileBuffer
->MousePosition
.Column
= MainEditor
.FileBuffer
->DisplayPosition
.Column
;
1782 return EFI_NOT_FOUND
;
1786 Handle user key input. This routes to other functions for the actions.
1788 @retval EFI_SUCCESS The operation was successful.
1789 @retval EFI_LOAD_ERROR A load error occured.
1790 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1793 MainEditorKeyInput (
1799 EFI_SIMPLE_POINTER_STATE MouseState
;
1803 Status
= EFI_SUCCESS
;
1804 EditorMouseAction
= FALSE
;
1807 // backup some key elements, so that can aVOID some refresh work
1809 MainEditorBackup ();
1812 // change priority of checking mouse/keyboard activity dynamically
1813 // so prevent starvation of keyboard.
1814 // if last time, mouse moves then this time check keyboard
1816 if (MainEditor
.MouseSupported
) {
1817 Status
= MainEditor
.MouseInterface
->GetState (
1818 MainEditor
.MouseInterface
,
1821 if (!EFI_ERROR (Status
)) {
1823 Status
= MainEditorHandleMouseInput (MouseState
);
1825 if (!EFI_ERROR (Status
)) {
1826 EditorMouseAction
= TRUE
;
1827 FileBufferMouseNeedRefresh
= TRUE
;
1828 } else if (Status
== EFI_LOAD_ERROR
) {
1829 StatusBarSetStatusString (L
"Invalid Mouse Movement ");
1834 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1835 if (!EFI_ERROR (Status
)) {
1837 // dispatch to different components' key handling function
1838 // so not everywhere has to set this variable
1840 FileBufferMouseNeedRefresh
= TRUE
;
1842 // clear previous status string
1844 StatusBarSetRefresh();
1847 // dispatch to different components' key handling function
1849 if (EFI_NOT_FOUND
!= MenuBarDispatchControlHotKey(&Key
)) {
1850 Status
= EFI_SUCCESS
;
1851 } else if ((Key
.ScanCode
== SCAN_NULL
) || ((Key
.ScanCode
>= SCAN_UP
) && (Key
.ScanCode
<= SCAN_PAGE_DOWN
))) {
1852 Status
= FileBufferHandleInput (&Key
);
1853 } else if ((Key
.ScanCode
>= SCAN_F1
) && (Key
.ScanCode
<= SCAN_F12
)) {
1854 Status
= MenuBarDispatchFunctionKey (&Key
);
1856 StatusBarSetStatusString (L
"Unknown Command");
1857 FileBufferMouseNeedRefresh
= FALSE
;
1860 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_OUT_OF_RESOURCES
) {
1862 // not already has some error status
1864 if (StatusBarGetString() != NULL
&& StrCmp (L
"", StatusBarGetString()) == 0) {
1865 StatusBarSetStatusString (L
"Disk Error. Try Again");
1871 // after handling, refresh editor
1873 MainEditorRefresh ();
1875 } while (Status
!= EFI_OUT_OF_RESOURCES
&& !EditorExit
);
1883 @param[in] Line A pointer to the line to be set to clipboard
1885 @retval EFI_SUCCESS The operation was successful.
1886 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1889 MainEditorSetCutLine (
1890 EFI_EDITOR_LINE
*Line
1897 if (MainEditor
.CutLine
!= NULL
) {
1899 // free the old clipboard
1901 LineFree (MainEditor
.CutLine
);
1904 // duplicate the line to clipboard
1906 MainEditor
.CutLine
= LineDup (Line
);
1907 if (MainEditor
.CutLine
== NULL
) {
1908 return EFI_OUT_OF_RESOURCES
;
1915 Backup function for MainEditor
1917 @retval EFI_SUCCESS The operation was successful.
1924 FileBufferBackup ();