2 Implements editor interface functions.
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
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"
20 Load a file from disk to editor
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.
32 Switch a file from ASCII to UNICODE or vise-versa.
34 @retval EFI_SUCCESS The switch was ok or a warning was presented.
37 MainCommandSwitchFileType (
42 move cursor to specified lines
44 @retval EFI_SUCCESS The operation was successful.
52 Save current file to disk, you can save to current file name or
53 save to another file name.
55 @retval EFI_SUCCESS The file was saved correctly.
56 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
57 @retval EFI_LOAD_ERROR A file access error occured.
67 @retval EFI_SUCCESS The operation was successful.
68 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
69 @retval EFI_LOAD_ERROR A load error occured.
77 search string in file buffer
79 @retval EFI_SUCCESS The operation was successful.
80 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
81 @retval EFI_LOAD_ERROR A load error occured.
89 search string in file buffer, and replace it with another str
91 @retval EFI_SUCCESS The operation was successful.
92 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
93 @retval EFI_LOAD_ERROR A load error occured.
96 MainCommandSearchReplace (
101 cut current line to clipboard
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 paste line to 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.
120 MainCommandPasteLine (
124 EDITOR_MENU_ITEM MainMenuItems
[] = {
126 STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE
),
127 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1
),
131 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE
),
132 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2
),
136 STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT
),
137 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3
),
142 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH
),
143 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4
),
147 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE
),
148 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5
),
149 MainCommandSearchReplace
152 STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE
),
153 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6
),
157 STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE
),
158 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7
),
163 STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE
),
164 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8
),
168 STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE
),
169 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9
),
170 MainCommandSwitchFileType
182 Load a file from disk to editor
184 @retval EFI_SUCCESS The operation was successful.
185 @retval EFI_LOAD_ERROR A load error occured.
186 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
189 MainCommandOpenFile (
197 // This command will open a file from current working directory.
198 // Read-only file can also be opened. But it can not be modified.
199 // Below is the scenario of Open File command:
200 // 1.IF currently opened file has not been modIFied, directly go to step .
201 // IF currently opened file has been modified,
202 // an Input Bar will be prompted as :
203 // "File Modified. Save ( Yes/No/Cancel) ?"
204 // IF user press 'y' or 'Y', currently opened file will be saved.
205 // IF user press 'n' or 'N', currently opened file will
207 // IF user press 'c' or 'C' or ESC, Open File command ends and
208 // currently opened file is still opened.
210 // 2. An Input Bar will be prompted as : "File Name to Open: "
211 // IF user press ESC, Open File command ends and
212 // currently opened file is still opened.
213 // Any other inputs with a Return will
214 // cause currently opened file close.
216 // 3. IF user input file name is an existing file , this file will be read
218 // IF user input file name is a new file, this file will be created
219 // and opened. This file's type ( UNICODE or ASCII ) is the same
220 // with the old file.
221 // if current file is modified, so you need to choose
222 // whether to save it first.
224 if (MainEditor
.FileBuffer
->FileModified
) {
226 Status
= InputBarSetPrompt (L
"File modified. Save (Yes/No/Cancel) ? ");
227 if (EFI_ERROR (Status
)) {
231 // the answer is just one character
233 Status
= InputBarSetStringSize (1);
234 if (EFI_ERROR (Status
)) {
238 // loop for user's answer
239 // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
243 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
244 StatusBarSetRefresh();
249 if (Status
== EFI_NOT_READY
) {
253 switch (InputBarGetString()[0]) {
257 // want to save this file first
259 Status
= FileBufferSave (MainEditor
.FileBuffer
->FileName
);
260 if (EFI_ERROR (Status
)) {
264 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
265 FileBufferRestorePosition ();
272 // the file won't be saved
284 // TO get the open file name
286 Status
= InputBarSetPrompt (L
"File Name to Open: ");
287 if (EFI_ERROR (Status
)) {
288 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
292 Status
= InputBarSetStringSize (100);
293 if (EFI_ERROR (Status
)) {
294 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
299 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
300 StatusBarSetRefresh();
305 if (Status
== EFI_NOT_READY
) {
309 // The input string length should > 0
311 if (StrLen (InputBarGetString()) > 0) {
313 // CHECK if filename is valid
315 if (!IsValidFileName (InputBarGetString())) {
316 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
317 StatusBarSetStatusString (L
"Invalid File Name");
327 Status
= FileBufferRead (InputBarGetString(), FALSE
);
329 if (EFI_ERROR (Status
)) {
330 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
331 return EFI_LOAD_ERROR
;
338 Switch a file from ASCII to UNICODE or vise-versa.
340 @retval EFI_SUCCESS The switch was ok or a warning was presented.
343 MainCommandSwitchFileType (
348 // Below is the scenario of File Type command:
349 // After File Type is executed, file type will be changed to another type
350 // if file is read-only, can not be modified
352 if (MainEditor
.FileBuffer
->ReadOnly
) {
353 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
357 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
358 MainEditor
.FileBuffer
->FileType
= FileTypeAscii
;
360 MainEditor
.FileBuffer
->FileType
= FileTypeUnicode
;
363 MainEditor
.FileBuffer
->FileModified
= TRUE
;
369 cut current line to clipboard
371 @retval EFI_SUCCESS The operation was successful.
372 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
373 @retval EFI_LOAD_ERROR A load error occured.
381 EFI_EDITOR_LINE
*Line
;
384 // This command will cut current line ( where cursor is on ) to clip board.
385 // And cursor will move to the beginning of next line.
386 // Below is the scenario of Cut Line command:
387 // 1. IF cursor is on valid line, current line will be cut to clip board.
388 // IF cursor is not on valid line, an Status String will be prompted :
391 Status
= FileBufferCutLine (&Line
);
392 if (Status
== EFI_NOT_FOUND
) {
396 if (EFI_ERROR (Status
)) {
400 MainEditor
.CutLine
= Line
;
406 paste line to file buffer.
408 @retval EFI_SUCCESS The operation was successful.
409 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
410 @retval EFI_LOAD_ERROR A load error occured.
413 MainCommandPasteLine (
420 // Below is the scenario of Paste Line command:
421 // 1. IF nothing is on clipboard, a Status String will be prompted :
422 // "No Line to Paste" and Paste Line command ends.
423 // IF something is on clipboard, insert it above current line.
424 // nothing on clipboard
426 if (MainEditor
.CutLine
== NULL
) {
427 StatusBarSetStatusString (L
"No Line to Paste");
431 Status
= FileBufferPasteLine ();
438 search string in file buffer
440 @retval EFI_SUCCESS The operation was successful.
441 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
442 @retval EFI_LOAD_ERROR A load error occured.
455 // Below is the scenario of Search command:
456 // 1. An Input Bar will be prompted : "Enter Search String:".
457 // IF user press ESC, Search command ends.
458 // IF user just press Enter, Search command ends.
459 // IF user inputs the search string, do Step 2.
461 // 2. IF input search string is found, cursor will move to the first
462 // occurrence and do Step 3.
463 // IF input search string is not found, a Status String
464 // "Search String Not Found" will be prompted and Search command ends.
466 // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
467 // IF user press ESC, Search command ends.
468 // IF user press 'y' or 'Y', do Step 2.
469 // IF user press 'n' or 'N', Search command ends.
470 // IF user press 'c' or 'C', Search command ends.
472 Status
= InputBarSetPrompt (L
"Enter Search String: ");
473 if (EFI_ERROR (Status
)) {
477 Status
= InputBarSetStringSize (40);
478 if (EFI_ERROR (Status
)) {
482 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
483 StatusBarSetRefresh();
488 if (Status
== EFI_NOT_READY
) {
492 // just enter pressed
494 if (StrLen (InputBarGetString()) == 0) {
498 Buffer
= CatSPrint (NULL
, L
"%s", InputBarGetString());
499 if (Buffer
== NULL
) {
500 return EFI_OUT_OF_RESOURCES
;
503 // the first time , search from current position
508 // since search may be continued to search multiple times
509 // so we need to backup editor each time
513 Status
= FileBufferSearch (Buffer
, Offset
);
515 if (Status
== EFI_NOT_FOUND
) {
521 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
522 if (EFI_ERROR (Status
)) {
527 Status
= InputBarSetStringSize (1);
528 if (EFI_ERROR (Status
)) {
535 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
536 StatusBarSetRefresh();
541 if (Status
== EFI_NOT_READY
) {
546 switch (InputBarGetString()[0]) {
563 // end of while !Done
564 // for search second, third time, search from current position + strlen
566 Offset
= StrLen (Buffer
);
573 StatusBarSetStatusString (L
"Search String Not Found");
579 Search string in file buffer, and replace it with another str.
581 @retval EFI_SUCCESS The operation was successful.
582 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
583 @retval EFI_LOAD_ERROR A load error occured.
586 MainCommandSearchReplace (
595 BOOLEAN ReplaceOption
;
600 ReplaceOption
= FALSE
;
603 // Below is the scenario of Search/Replace command:
604 // 1. An Input Bar is prompted : "Enter Search String:".
605 // IF user press ESC, Search/Replace command ends.
606 // IF user just press Enter, Search/Replace command ends.
607 // IF user inputs the search string S, do Step 2.
609 // 2. An Input Bar is prompted: "Replace With:".
610 // IF user press ESC, Search/Replace command ends.
611 // IF user inputs the replace string R, do Step 3.
613 // 3. IF input search string is not found, an Status String
614 // "Search String Not Found" will be prompted
615 // and Search/Replace command ends
616 // IF input search string is found, do Step 4.
618 // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
619 // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
620 // IF user press 'n' or 'N', S will not be replaced and do Step 5.
621 // IF user press 'a' or 'A', all the S from file current position on
622 // will be replaced with R and Search/Replace command ends.
623 // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
625 // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
626 // IF user press ESC, Search/Replace command ends.
627 // IF user press 'y' or 'Y', do Step 3.
628 // IF user press 'n' or 'N', Search/Replace command ends.
629 // IF user press 'c' or 'C', Search/Replace command ends.
630 // input search string
632 Status
= InputBarSetPrompt (L
"Enter Search String: ");
633 if (EFI_ERROR (Status
)) {
637 Status
= InputBarSetStringSize (40);
638 if (EFI_ERROR (Status
)) {
642 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
643 StatusBarSetRefresh();
648 if (Status
== EFI_NOT_READY
) {
652 // if just pressed enter
654 if (StrLen (InputBarGetString()) == 0) {
658 Search
= CatSPrint (NULL
, L
"%s", InputBarGetString());
659 if (Search
== NULL
) {
660 return EFI_OUT_OF_RESOURCES
;
663 SearchLen
= StrLen (Search
);
666 // input replace string
668 Status
= InputBarSetPrompt (L
"Replace With: ");
669 if (EFI_ERROR (Status
)) {
673 Status
= InputBarSetStringSize (40);
674 if (EFI_ERROR (Status
)) {
678 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
679 StatusBarSetRefresh();
684 if (Status
== EFI_NOT_READY
) {
688 Replace
= CatSPrint (NULL
, L
"%s", InputBarGetString());
689 if (Replace
== NULL
) {
691 return EFI_OUT_OF_RESOURCES
;
694 ReplaceLen
= StrLen (Replace
);
700 // since search may be continued to search multiple times
701 // so we need to backup editor each time
706 Status
= FileBufferSearch (Search
, 0);
709 // if just replace, so skip this replace string
710 // if replace string is an empty string, so skip to next character
713 Status
= FileBufferSearch (Search
, (ReplaceLen
== 0) ? 1 : ReplaceLen
);
715 Status
= FileBufferSearch (Search
, SearchLen
);
719 if (Status
== EFI_NOT_FOUND
) {
725 Status
= InputBarSetPrompt (L
"Replace (Yes/No/All/Cancel) ?");
727 if (EFI_ERROR (Status
)) {
733 Status
= InputBarSetStringSize (1);
734 if (EFI_ERROR (Status
)) {
742 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
743 StatusBarSetRefresh();
748 if (Status
== EFI_NOT_READY
) {
754 switch (InputBarGetString()[0]) {
758 ReplaceOption
= TRUE
;
764 ReplaceOption
= FALSE
;
770 ReplaceOption
= TRUE
;
786 // end of while !Done
793 if (MainEditor
.FileBuffer
->ReadOnly
) {
794 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
801 Status
= FileBufferReplaceAll (Search
, Replace
, 0);
809 Status
= FileBufferReplace (Replace
, SearchLen
);
810 if (EFI_ERROR (Status
)) {
819 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
820 if (EFI_ERROR (Status
)) {
826 Status
= InputBarSetStringSize (1);
827 if (EFI_ERROR (Status
)) {
835 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
836 StatusBarSetRefresh();
841 if (Status
== EFI_NOT_READY
) {
847 switch (InputBarGetString()[0]) {
865 // end of while !Done
876 StatusBarSetStatusString (L
"Search String Not Found");
884 @retval EFI_SUCCESS The operation was successful.
885 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
886 @retval EFI_LOAD_ERROR A load error occured.
896 // Below is the scenario of Exit command:
897 // 1. IF currently opened file is not modified, exit the editor and
898 // Exit command ends.
899 // IF currently opened file is modified, do Step 2
901 // 2. An Input Bar will be prompted:
902 // "File modified. Save ( Yes/No/Cancel )?"
903 // IF user press 'y' or 'Y', currently opened file will be saved
905 // IF user press 'n' or 'N', currently opened file will not be saved
907 // IF user press 'c' or 'C' or ESC, Exit command ends.
908 // if file has been modified, so will prompt user whether to save the changes
910 if (MainEditor
.FileBuffer
->FileModified
) {
912 Status
= InputBarSetPrompt (L
"File modified. Save (Yes/No/Cancel) ? ");
913 if (EFI_ERROR (Status
)) {
917 Status
= InputBarSetStringSize (1);
918 if (EFI_ERROR (Status
)) {
923 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
924 StatusBarSetRefresh();
929 if (Status
== EFI_NOT_READY
) {
933 switch (InputBarGetString()[0]) {
937 // write file back to disk
939 Status
= FileBufferSave (MainEditor
.FileBuffer
->FileName
);
940 if (!EFI_ERROR (Status
)) {
965 move cursor to specified lines
967 @retval EFI_SUCCESS The operation was successful.
970 MainCommandGotoLine (
978 // Below is the scenario of Go To Line command:
979 // 1. An Input Bar will be prompted : "Go To Line:".
980 // IF user press ESC, Go To Line command ends.
981 // IF user just press Enter, cursor remains unchanged.
982 // IF user inputs line number, do Step 2.
984 // 2. IF input line number is valid, move cursor to the beginning
985 // of specified line and Go To Line command ends.
986 // IF input line number is invalid, a Status String will be prompted:
987 // "No Such Line" and Go To Line command ends.
989 Status
= InputBarSetPrompt (L
"Go To Line: ");
990 if (EFI_ERROR (Status
)) {
994 // line number's digit <= 6
996 Status
= InputBarSetStringSize (6);
997 if (EFI_ERROR (Status
)) {
1001 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1002 StatusBarSetRefresh();
1007 if (Status
== EFI_NOT_READY
) {
1011 // if JUST press enter
1013 if (StrLen (InputBarGetString()) == 0) {
1017 Row
= ShellStrToUintn (InputBarGetString());
1020 // invalid line number
1022 if (Row
> MainEditor
.FileBuffer
->NumLines
|| Row
<= 0) {
1023 StatusBarSetStatusString (L
"No Such Line");
1027 // move cursor to that line's start
1029 FileBufferMovePosition (Row
, 1);
1035 Save current file to disk, you can save to current file name or
1036 save to another file name.
1038 @retval EFI_SUCCESS The file was saved correctly.
1039 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1040 @retval EFI_LOAD_ERROR A file access error occured.
1043 MainCommandSaveFile (
1051 SHELL_FILE_HANDLE FileHandle
;
1052 EFI_FILE_INFO
*Info
;
1055 // This command will save currently opened file to disk.
1056 // You can choose save to another file name or just save to
1057 // current file name.
1058 // Below is the scenario of Save File command:
1059 // ( Suppose the old file name is A )
1060 // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
1061 // IF user press ESC, Save File command ends .
1062 // IF user press Enter, input file name will be A.
1063 // IF user inputs a new file name B, input file name will be B.
1065 // 2. IF input file name is A, go to do Step 3.
1066 // IF input file name is B, go to do Step 4.
1068 // 3. IF A is read only, Status Bar will show "Access Denied" and
1069 // Save File commands ends.
1070 // IF A is not read only, save file buffer to disk and remove modified
1071 // flag in Title Bar , then Save File command ends.
1073 // 4. IF B does not exist, create this file and save file buffer to it.
1075 // IF B exits, do Step 5.
1077 // 5.An Input Bar will be prompted:
1078 // "File Exists. Overwrite ( Yes/No/Cancel )?"
1079 // IF user press 'y' or 'Y', do Step 6.
1080 // IF user press 'n' or 'N', Save File commands ends.
1081 // IF user press 'c' or 'C' or ESC, Save File commands ends.
1083 // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
1084 // Save File commands ends.
1085 // IF B can be read and write, save file buffer to B.
1087 // 7. Update File Name field in Title Bar to B and remove the modified
1088 // flag in Title Bar.
1090 Str
= CatSPrint (NULL
, L
"File to Save: [%s]", MainEditor
.FileBuffer
->FileName
);
1092 return EFI_OUT_OF_RESOURCES
;
1095 if (StrLen (Str
) >= 50) {
1097 // replace the long file name with "..."
1103 Str
[50] = CHAR_NULL
;
1106 Status
= InputBarSetPrompt (Str
);
1109 if (EFI_ERROR (Status
)) {
1114 Status
= InputBarSetStringSize (100);
1115 if (EFI_ERROR (Status
)) {
1119 // get new file name
1121 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1122 StatusBarSetRefresh();
1125 // if user pressed ESC
1127 if (Status
== EFI_NOT_READY
) {
1132 // if just enter pressed, so think save to current file name
1134 if (StrLen (InputBarGetString()) == 0) {
1135 FileName
= CatSPrint (NULL
, L
"%s", MainEditor
.FileBuffer
->FileName
);
1137 FileName
= CatSPrint (NULL
, L
"%s", InputBarGetString());
1140 if (FileName
== NULL
) {
1141 return EFI_OUT_OF_RESOURCES
;
1144 if (!IsValidFileName (FileName
)) {
1145 StatusBarSetStatusString (L
"Invalid File Name");
1146 FreePool (FileName
);
1153 // save to the old file
1155 if (StringNoCaseCompare (&FileName
, &MainEditor
.FileBuffer
->FileName
) == 0) {
1161 // if the file is read only, so can not write back to it.
1163 if (MainEditor
.FileBuffer
->ReadOnly
== TRUE
) {
1164 StatusBarSetStatusString (L
"Access Denied");
1165 FreePool (FileName
);
1170 // if the file exists
1172 if (ShellFileExists(FileName
) != EFI_NOT_FOUND
) {
1174 // check for read only
1176 Status
= ShellOpenFileByName(FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
1177 if (EFI_ERROR(Status
)) {
1178 StatusBarSetStatusString (L
"Open Failed");
1179 FreePool (FileName
);
1183 Info
= ShellGetFileInfo(FileHandle
);
1185 StatusBarSetStatusString (L
"Access Denied");
1186 FreePool (FileName
);
1187 return (EFI_SUCCESS
);
1190 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
1191 StatusBarSetStatusString (L
"Access Denied - Read Only");
1193 FreePool (FileName
);
1194 return (EFI_SUCCESS
);
1199 // ask user whether to overwrite this file
1201 Status
= InputBarSetPrompt (L
"File exists. Overwrite (Yes/No/Cancel) ? ");
1202 if (EFI_ERROR (Status
)) {
1203 SHELL_FREE_NON_NULL (FileName
);
1207 Status
= InputBarSetStringSize (1);
1208 if (EFI_ERROR (Status
)) {
1209 SHELL_FREE_NON_NULL (FileName
);
1214 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1215 StatusBarSetRefresh();
1220 if (Status
== EFI_NOT_READY
) {
1221 SHELL_FREE_NON_NULL (FileName
);
1225 switch (InputBarGetString()[0]) {
1234 SHELL_FREE_NON_NULL (FileName
);
1238 } // file does exist
1239 } // if old file name same
1242 // save file to disk with specified name
1244 FileBufferSetModified();
1245 Status
= FileBufferSave (FileName
);
1246 SHELL_FREE_NON_NULL (FileName
);
1251 EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors
;
1255 // the first time editor launch
1257 BOOLEAN EditorFirst
;
1260 // it's time editor should exit
1264 BOOLEAN EditorMouseAction
;
1266 extern EFI_EDITOR_FILE_BUFFER FileBuffer
;
1268 extern BOOLEAN FileBufferMouseNeedRefresh
;
1270 extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
1272 EFI_EDITOR_GLOBAL_EDITOR MainEditor
;
1275 // basic initialization for MainEditor
1277 EFI_EDITOR_GLOBAL_EDITOR MainEditorConst
= {
1293 The initialization function for MainEditor.
1295 @retval EFI_SUCCESS The operation was successful.
1296 @retval EFI_LOAD_ERROR A load error occured.
1305 EFI_HANDLE
*HandleBuffer
;
1310 // basic initialization
1312 CopyMem (&MainEditor
, &MainEditorConst
, sizeof (MainEditor
));
1315 // set screen attributes
1317 MainEditor
.ColorAttributes
.Colors
.Foreground
= gST
->ConOut
->Mode
->Attribute
& 0x000000ff;
1319 MainEditor
.ColorAttributes
.Colors
.Background
= (UINT8
) (gST
->ConOut
->Mode
->Attribute
>> 4);
1320 OriginalColors
= MainEditor
.ColorAttributes
.Colors
;
1322 OriginalMode
= gST
->ConOut
->Mode
->Mode
;
1325 // query screen size
1327 gST
->ConOut
->QueryMode (
1329 gST
->ConOut
->Mode
->Mode
,
1330 &(MainEditor
.ScreenSize
.Column
),
1331 &(MainEditor
.ScreenSize
.Row
)
1335 // Find mouse in System Table ConsoleInHandle
1337 Status
= gBS
->HandleProtocol (
1339 &gEfiSimplePointerProtocolGuid
,
1340 (VOID
**)&MainEditor
.MouseInterface
1342 if (EFI_ERROR (Status
)) {
1344 // If there is no Simple Pointer Protocol on System Table
1346 HandleBuffer
= NULL
;
1347 MainEditor
.MouseInterface
= NULL
;
1348 Status
= gBS
->LocateHandleBuffer (
1350 &gEfiSimplePointerProtocolGuid
,
1355 if (!EFI_ERROR (Status
) && HandleCount
> 0) {
1357 // Try to find the first available mouse device
1359 for (Index
= 0; Index
< HandleCount
; Index
++) {
1360 Status
= gBS
->HandleProtocol (
1361 HandleBuffer
[Index
],
1362 &gEfiSimplePointerProtocolGuid
,
1363 (VOID
**)&MainEditor
.MouseInterface
1365 if (!EFI_ERROR (Status
)) {
1370 if (HandleBuffer
!= NULL
) {
1371 FreePool (HandleBuffer
);
1375 if (!EFI_ERROR (Status
) && MainEditor
.MouseInterface
!= NULL
) {
1376 MainEditor
.MouseAccumulatorX
= 0;
1377 MainEditor
.MouseAccumulatorY
= 0;
1378 MainEditor
.MouseSupported
= TRUE
;
1382 // below will call the five components' init function
1384 Status
= MainTitleBarInit (L
"UEFI EDIT 2.0");
1385 if (EFI_ERROR (Status
)) {
1386 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR
), gShellDebug1HiiHandle
);
1387 return EFI_LOAD_ERROR
;
1390 Status
= MenuBarInit (MainMenuItems
);
1391 if (EFI_ERROR (Status
)) {
1392 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU
), gShellDebug1HiiHandle
);
1393 return EFI_LOAD_ERROR
;
1396 Status
= StatusBarInit ();
1397 if (EFI_ERROR (Status
)) {
1398 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR
), gShellDebug1HiiHandle
);
1399 return EFI_LOAD_ERROR
;
1404 Status
= FileBufferInit ();
1405 if (EFI_ERROR (Status
)) {
1406 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER
), gShellDebug1HiiHandle
);
1407 return EFI_LOAD_ERROR
;
1410 // clear whole screen and enable cursor
1412 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1413 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
1416 // initialize EditorFirst and EditorExit
1420 EditorMouseAction
= FALSE
;
1426 The cleanup function for MainEditor.
1428 @retval EFI_SUCCESS The operation was successful.
1429 @retval EFI_LOAD_ERROR A load error occured.
1440 // call the five components' cleanup function
1441 // if error, do not exit
1442 // just print some warning
1444 MainTitleBarCleanup();
1449 Status
= FileBufferCleanup ();
1450 if (EFI_ERROR (Status
)) {
1451 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP
), gShellDebug1HiiHandle
);
1456 if (OriginalMode
!= gST
->ConOut
->Mode
->Mode
) {
1457 gST
->ConOut
->SetMode (gST
->ConOut
, OriginalMode
);
1460 // restore old screen color
1462 gST
->ConOut
->SetAttribute (
1464 EFI_TEXT_ATTR (OriginalColors
.Foreground
, OriginalColors
.Background
)
1467 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1473 Refresh the main editor component.
1482 // The Stall value is from experience. NOT from spec. avoids 'flicker'
1487 // call the components refresh function
1490 || StrCmp (FileBufferBackupVar
.FileName
, FileBuffer
.FileName
) != 0
1491 || FileBufferBackupVar
.FileType
!= FileBuffer
.FileType
1492 || FileBufferBackupVar
.FileModified
!= FileBuffer
.FileModified
1493 || FileBufferBackupVar
.ReadOnly
!= FileBuffer
.ReadOnly
) {
1495 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
1496 FileBufferRestorePosition ();
1497 FileBufferRefresh ();
1500 || FileBufferBackupVar
.FilePosition
.Row
!= FileBuffer
.FilePosition
.Row
1501 || FileBufferBackupVar
.FilePosition
.Column
!= FileBuffer
.FilePosition
.Column
1502 || FileBufferBackupVar
.ModeInsert
!= FileBuffer
.ModeInsert
1503 || StatusBarGetRefresh()) {
1505 StatusBarRefresh (EditorFirst
, MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.FileBuffer
->FilePosition
.Row
, MainEditor
.FileBuffer
->FilePosition
.Column
, MainEditor
.FileBuffer
->ModeInsert
);
1506 FileBufferRestorePosition ();
1507 FileBufferRefresh ();
1511 MenuBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1512 FileBufferRestorePosition ();
1516 // EditorFirst is now set to FALSE
1518 EditorFirst
= FALSE
;
1522 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1524 @param[in] GuidX The relative mouse movement.
1526 @return The X location of the mouse.
1536 MainEditor
.MouseAccumulatorX
+= GuidX
;
1537 Gap
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1538 MainEditor
.MouseAccumulatorX
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1539 MainEditor
.MouseAccumulatorX
= MainEditor
.MouseAccumulatorX
/ (INT32
) MainEditor
.ScreenSize
.Column
;
1544 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1546 @param[in] GuidY The relative mouse movement.
1548 @return The Y location of the mouse.
1558 MainEditor
.MouseAccumulatorY
+= GuidY
;
1559 Gap
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1560 MainEditor
.MouseAccumulatorY
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1561 MainEditor
.MouseAccumulatorY
= MainEditor
.MouseAccumulatorY
/ (INT32
) MainEditor
.ScreenSize
.Row
;
1567 Support mouse movement. Move the cursor.
1569 @param[in] MouseState The current mouse state.
1571 @retval EFI_SUCCESS The operation was successful.
1572 @retval EFI_NOT_FOUND There was no mouse support found.
1576 MainEditorHandleMouseInput (
1577 IN EFI_SIMPLE_POINTER_STATE MouseState
1587 EFI_EDITOR_LINE
*Line
;
1593 // mouse action means:
1595 // mouse left button
1600 // have mouse movement
1602 if (MouseState
.RelativeMovementX
|| MouseState
.RelativeMovementY
) {
1606 TextX
= GetTextX (MouseState
.RelativeMovementX
);
1607 TextY
= GetTextY (MouseState
.RelativeMovementY
);
1609 FileBufferAdjustMousePosition (TextX
, TextY
);
1616 // if left button pushed down
1618 if (MouseState
.LeftButton
) {
1620 FCol
= MainEditor
.FileBuffer
->MousePosition
.Column
- 1 + 1;
1622 FRow
= MainEditor
.FileBuffer
->FilePosition
.Row
+
1623 MainEditor
.FileBuffer
->MousePosition
.Row
-
1624 MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1627 // beyond the file line length
1629 if (MainEditor
.FileBuffer
->NumLines
< FRow
) {
1630 FRow
= MainEditor
.FileBuffer
->NumLines
;
1633 Link
= MainEditor
.FileBuffer
->ListHead
->ForwardLink
;
1634 for (Index
= 0; Index
< FRow
- 1; Index
++) {
1635 Link
= Link
->ForwardLink
;
1638 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1641 // beyond the line's column length
1643 if (FCol
> Line
->Size
+ 1) {
1644 FCol
= Line
->Size
+ 1;
1647 FileBufferMovePosition (FRow
, FCol
);
1649 MainEditor
.FileBuffer
->MousePosition
.Row
= MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1651 MainEditor
.FileBuffer
->MousePosition
.Column
= MainEditor
.FileBuffer
->DisplayPosition
.Column
;
1665 return EFI_NOT_FOUND
;
1669 Handle user key input. This routes to other functions for the actions.
1671 @retval EFI_SUCCESS The operation was successful.
1672 @retval EFI_LOAD_ERROR A load error occured.
1673 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1677 MainEditorKeyInput (
1683 EFI_SIMPLE_POINTER_STATE MouseState
;
1687 Status
= EFI_SUCCESS
;
1688 EditorMouseAction
= FALSE
;
1691 // backup some key elements, so that can aVOID some refresh work
1693 MainEditorBackup ();
1696 // change priority of checking mouse/keyboard activity dynamically
1697 // so prevent starvation of keyboard.
1698 // if last time, mouse moves then this time check keyboard
1700 if (MainEditor
.MouseSupported
) {
1701 Status
= MainEditor
.MouseInterface
->GetState (
1702 MainEditor
.MouseInterface
,
1705 if (!EFI_ERROR (Status
)) {
1707 Status
= MainEditorHandleMouseInput (MouseState
);
1709 if (!EFI_ERROR (Status
)) {
1710 EditorMouseAction
= TRUE
;
1711 FileBufferMouseNeedRefresh
= TRUE
;
1712 } else if (Status
== EFI_LOAD_ERROR
) {
1713 StatusBarSetStatusString (L
"Invalid Mouse Movement ");
1718 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1719 if (!EFI_ERROR (Status
)) {
1721 // dispatch to different components' key handling function
1722 // so not everywhere has to set this variable
1724 FileBufferMouseNeedRefresh
= TRUE
;
1726 // clear previous status string
1728 StatusBarSetRefresh();
1731 // dispatch to different components' key handling function
1733 if ((Key
.ScanCode
== SCAN_NULL
) || ((Key
.ScanCode
>= SCAN_UP
) && (Key
.ScanCode
<= SCAN_PAGE_DOWN
))) {
1734 Status
= FileBufferHandleInput (&Key
);
1735 } else if ((Key
.ScanCode
>= SCAN_F1
) && (Key
.ScanCode
<= SCAN_F12
)) {
1736 Status
= MenuBarDispatchFunctionKey (&Key
);
1738 StatusBarSetStatusString (L
"Unknown Command");
1739 FileBufferMouseNeedRefresh
= FALSE
;
1742 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_OUT_OF_RESOURCES
) {
1744 // not already has some error status
1746 if (StatusBarGetString() != NULL
&& StrCmp (L
"", StatusBarGetString()) == 0) {
1747 StatusBarSetStatusString (L
"Disk Error. Try Again");
1753 // after handling, refresh editor
1755 MainEditorRefresh ();
1757 } while (Status
!= EFI_OUT_OF_RESOURCES
&& !EditorExit
);
1765 @param[in] Line A pointer to the line to be set to clipboard
1767 @retval EFI_SUCCESS The operation was successful.
1768 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1772 MainEditorSetCutLine (
1773 EFI_EDITOR_LINE
*Line
1780 if (MainEditor
.CutLine
!= NULL
) {
1782 // free the old clipboard
1784 LineFree (MainEditor
.CutLine
);
1787 // duplicate the line to clipboard
1789 MainEditor
.CutLine
= LineDup (Line
);
1790 if (MainEditor
.CutLine
== NULL
) {
1791 return EFI_OUT_OF_RESOURCES
;
1798 Backup function for MainEditor
1800 @retval EFI_SUCCESS The operation was successful.
1808 FileBufferBackup ();