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.
33 Switch a file from ASCII to UNICODE or vise-versa.
35 @retval EFI_SUCCESS The switch was ok or a warning was presented.
39 MainCommandSwitchFileType (
44 move cursor to specified lines
46 @retval EFI_SUCCESS The operation was successful.
55 Save current file to disk, you can save to current file name or
56 save to another file name.
58 @retval EFI_SUCCESS The file was saved correctly.
59 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
60 @retval EFI_LOAD_ERROR A file access error occured.
71 @retval EFI_SUCCESS The operation was successful.
72 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
73 @retval EFI_LOAD_ERROR A load error occured.
82 search string in file buffer
84 @retval EFI_SUCCESS The operation was successful.
85 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
86 @retval EFI_LOAD_ERROR A load error occured.
95 search string in file buffer, and replace it with another str
97 @retval EFI_SUCCESS The operation was successful.
98 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
99 @retval EFI_LOAD_ERROR A load error occured.
103 MainCommandSearchReplace (
108 cut current line to clipboard
110 @retval EFI_SUCCESS The operation was successful.
111 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
112 @retval EFI_LOAD_ERROR A load error occured.
121 paste line to file buffer.
123 @retval EFI_SUCCESS The operation was successful.
124 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
125 @retval EFI_LOAD_ERROR A load error occured.
129 MainCommandPasteLine (
133 EDITOR_MENU_ITEM MainMenuItems
[] = {
135 STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE
),
136 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1
),
140 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE
),
141 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2
),
145 STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT
),
146 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3
),
151 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH
),
152 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4
),
156 STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE
),
157 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5
),
158 MainCommandSearchReplace
161 STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE
),
162 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6
),
166 STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE
),
167 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7
),
172 STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE
),
173 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8
),
177 STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE
),
178 STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9
),
179 MainCommandSwitchFileType
191 Load a file from disk to editor
193 @retval EFI_SUCCESS The operation was successful.
194 @retval EFI_LOAD_ERROR A load error occured.
195 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
199 MainCommandOpenFile (
207 // This command will open a file from current working directory.
208 // Read-only file can also be opened. But it can not be modified.
209 // Below is the scenario of Open File command:
210 // 1.IF currently opened file has not been modIFied, directly go to step .
211 // IF currently opened file has been modified,
212 // an Input Bar will be prompted as :
213 // "File Modified. Save ( Yes/No/Cancel) ?"
214 // IF user press 'y' or 'Y', currently opened file will be saved.
215 // IF user press 'n' or 'N', currently opened file will
217 // IF user press 'c' or 'C' or ESC, Open File command ends and
218 // currently opened file is still opened.
220 // 2. An Input Bar will be prompted as : "File Name to Open: "
221 // IF user press ESC, Open File command ends and
222 // currently opened file is still opened.
223 // Any other inputs with a Return will
224 // cause currently opened file close.
226 // 3. IF user input file name is an existing file , this file will be read
228 // IF user input file name is a new file, this file will be created
229 // and opened. This file's type ( UNICODE or ASCII ) is the same
230 // with the old file.
231 // if current file is modified, so you need to choose
232 // whether to save it first.
234 if (MainEditor
.FileBuffer
->FileModified
) {
236 Status
= InputBarSetPrompt (L
"File modified. Save (Yes/No/Cancel) ? ");
237 if (EFI_ERROR (Status
)) {
241 // the answer is just one character
243 Status
= InputBarSetStringSize (1);
244 if (EFI_ERROR (Status
)) {
248 // loop for user's answer
249 // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
253 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
254 StatusBarSetRefresh();
259 if (Status
== EFI_NOT_READY
) {
263 switch (InputBarGetString()[0]) {
267 // want to save this file first
269 Status
= FileBufferSave (MainEditor
.FileBuffer
->FileName
);
270 if (EFI_ERROR (Status
)) {
274 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
275 FileBufferRestorePosition ();
282 // the file won't be saved
294 // TO get the open file name
296 Status
= InputBarSetPrompt (L
"File Name to Open: ");
297 if (EFI_ERROR (Status
)) {
298 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
302 Status
= InputBarSetStringSize (100);
303 if (EFI_ERROR (Status
)) {
304 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
309 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
310 StatusBarSetRefresh();
315 if (Status
== EFI_NOT_READY
) {
319 // The input string length should > 0
321 if (StrLen (InputBarGetString()) > 0) {
323 // CHECK if filename is valid
325 if (!IsValidFileName (InputBarGetString())) {
326 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
327 StatusBarSetStatusString (L
"Invalid File Name");
337 Status
= FileBufferRead (InputBarGetString(), FALSE
);
339 if (EFI_ERROR (Status
)) {
340 FileBufferRead (MainEditor
.FileBuffer
->FileName
, TRUE
);
341 return EFI_LOAD_ERROR
;
348 Switch a file from ASCII to UNICODE or vise-versa.
350 @retval EFI_SUCCESS The switch was ok or a warning was presented.
354 MainCommandSwitchFileType (
359 // Below is the scenario of File Type command:
360 // After File Type is executed, file type will be changed to another type
361 // if file is read-only, can not be modified
363 if (MainEditor
.FileBuffer
->ReadOnly
) {
364 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
368 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
369 MainEditor
.FileBuffer
->FileType
= FileTypeAscii
;
371 MainEditor
.FileBuffer
->FileType
= FileTypeUnicode
;
374 MainEditor
.FileBuffer
->FileModified
= TRUE
;
380 cut current line to clipboard
382 @retval EFI_SUCCESS The operation was successful.
383 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
384 @retval EFI_LOAD_ERROR A load error occured.
393 EFI_EDITOR_LINE
*Line
;
396 // This command will cut current line ( where cursor is on ) to clip board.
397 // And cursor will move to the beginning of next line.
398 // Below is the scenario of Cut Line command:
399 // 1. IF cursor is on valid line, current line will be cut to clip board.
400 // IF cursor is not on valid line, an Status String will be prompted :
403 Status
= FileBufferCutLine (&Line
);
404 if (Status
== EFI_NOT_FOUND
) {
408 if (EFI_ERROR (Status
)) {
412 MainEditor
.CutLine
= Line
;
418 paste line to file buffer.
420 @retval EFI_SUCCESS The operation was successful.
421 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
422 @retval EFI_LOAD_ERROR A load error occured.
426 MainCommandPasteLine (
433 // Below is the scenario of Paste Line command:
434 // 1. IF nothing is on clipboard, a Status String will be prompted :
435 // "No Line to Paste" and Paste Line command ends.
436 // IF something is on clipboard, insert it above current line.
437 // nothing on clipboard
439 if (MainEditor
.CutLine
== NULL
) {
440 StatusBarSetStatusString (L
"No Line to Paste");
444 Status
= FileBufferPasteLine ();
451 search string in file buffer
453 @retval EFI_SUCCESS The operation was successful.
454 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
455 @retval EFI_LOAD_ERROR A load error occured.
469 // Below is the scenario of Search command:
470 // 1. An Input Bar will be prompted : "Enter Search String:".
471 // IF user press ESC, Search command ends.
472 // IF user just press Enter, Search command ends.
473 // IF user inputs the search string, do Step 2.
475 // 2. IF input search string is found, cursor will move to the first
476 // occurrence and do Step 3.
477 // IF input search string is not found, a Status String
478 // "Search String Not Found" will be prompted and Search command ends.
480 // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
481 // IF user press ESC, Search command ends.
482 // IF user press 'y' or 'Y', do Step 2.
483 // IF user press 'n' or 'N', Search command ends.
484 // IF user press 'c' or 'C', Search command ends.
486 Status
= InputBarSetPrompt (L
"Enter Search String: ");
487 if (EFI_ERROR (Status
)) {
491 Status
= InputBarSetStringSize (40);
492 if (EFI_ERROR (Status
)) {
496 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
497 StatusBarSetRefresh();
502 if (Status
== EFI_NOT_READY
) {
506 // just enter pressed
508 if (StrLen (InputBarGetString()) == 0) {
512 Buffer
= CatSPrint (NULL
, L
"%s", InputBarGetString());
513 if (Buffer
== NULL
) {
514 return EFI_OUT_OF_RESOURCES
;
517 // the first time , search from current position
522 // since search may be continued to search multiple times
523 // so we need to backup editor each time
527 Status
= FileBufferSearch (Buffer
, Offset
);
529 if (Status
== EFI_NOT_FOUND
) {
535 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
536 if (EFI_ERROR (Status
)) {
541 Status
= InputBarSetStringSize (1);
542 if (EFI_ERROR (Status
)) {
549 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
550 StatusBarSetRefresh();
555 if (Status
== EFI_NOT_READY
) {
560 switch (InputBarGetString()[0]) {
577 // end of while !Done
578 // for search second, third time, search from current position + strlen
580 Offset
= StrLen (Buffer
);
587 StatusBarSetStatusString (L
"Search String Not Found");
593 Search string in file buffer, and replace it with another str.
595 @retval EFI_SUCCESS The operation was successful.
596 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
597 @retval EFI_LOAD_ERROR A load error occured.
601 MainCommandSearchReplace (
610 BOOLEAN ReplaceOption
;
615 ReplaceOption
= FALSE
;
618 // Below is the scenario of Search/Replace command:
619 // 1. An Input Bar is prompted : "Enter Search String:".
620 // IF user press ESC, Search/Replace command ends.
621 // IF user just press Enter, Search/Replace command ends.
622 // IF user inputs the search string S, do Step 2.
624 // 2. An Input Bar is prompted: "Replace With:".
625 // IF user press ESC, Search/Replace command ends.
626 // IF user inputs the replace string R, do Step 3.
628 // 3. IF input search string is not found, an Status String
629 // "Search String Not Found" will be prompted
630 // and Search/Replace command ends
631 // IF input search string is found, do Step 4.
633 // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
634 // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
635 // IF user press 'n' or 'N', S will not be replaced and do Step 5.
636 // IF user press 'a' or 'A', all the S from file current position on
637 // will be replaced with R and Search/Replace command ends.
638 // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
640 // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
641 // IF user press ESC, Search/Replace command ends.
642 // IF user press 'y' or 'Y', do Step 3.
643 // IF user press 'n' or 'N', Search/Replace command ends.
644 // IF user press 'c' or 'C', Search/Replace command ends.
645 // input search string
647 Status
= InputBarSetPrompt (L
"Enter Search String: ");
648 if (EFI_ERROR (Status
)) {
652 Status
= InputBarSetStringSize (40);
653 if (EFI_ERROR (Status
)) {
657 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
658 StatusBarSetRefresh();
663 if (Status
== EFI_NOT_READY
) {
667 // if just pressed enter
669 if (StrLen (InputBarGetString()) == 0) {
673 Search
= CatSPrint (NULL
, L
"%s", InputBarGetString());
674 if (Search
== NULL
) {
675 return EFI_OUT_OF_RESOURCES
;
678 SearchLen
= StrLen (Search
);
681 // input replace string
683 Status
= InputBarSetPrompt (L
"Replace With: ");
684 if (EFI_ERROR (Status
)) {
688 Status
= InputBarSetStringSize (40);
689 if (EFI_ERROR (Status
)) {
693 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
694 StatusBarSetRefresh();
699 if (Status
== EFI_NOT_READY
) {
703 Replace
= CatSPrint (NULL
, L
"%s", InputBarGetString());
704 if (Replace
== NULL
) {
706 return EFI_OUT_OF_RESOURCES
;
709 ReplaceLen
= StrLen (Replace
);
715 // since search may be continued to search multiple times
716 // so we need to backup editor each time
721 Status
= FileBufferSearch (Search
, 0);
724 // if just replace, so skip this replace string
725 // if replace string is an empty string, so skip to next character
728 Status
= FileBufferSearch (Search
, (ReplaceLen
== 0) ? 1 : ReplaceLen
);
730 Status
= FileBufferSearch (Search
, SearchLen
);
734 if (Status
== EFI_NOT_FOUND
) {
740 Status
= InputBarSetPrompt (L
"Replace (Yes/No/All/Cancel) ?");
742 if (EFI_ERROR (Status
)) {
748 Status
= InputBarSetStringSize (1);
749 if (EFI_ERROR (Status
)) {
757 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
758 StatusBarSetRefresh();
763 if (Status
== EFI_NOT_READY
) {
769 switch (InputBarGetString()[0]) {
773 ReplaceOption
= TRUE
;
779 ReplaceOption
= FALSE
;
785 ReplaceOption
= TRUE
;
801 // end of while !Done
808 if (MainEditor
.FileBuffer
->ReadOnly
) {
809 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
816 Status
= FileBufferReplaceAll (Search
, Replace
, 0);
824 Status
= FileBufferReplace (Replace
, SearchLen
);
825 if (EFI_ERROR (Status
)) {
834 Status
= InputBarSetPrompt (L
"Find Next (Yes/No) ?");
835 if (EFI_ERROR (Status
)) {
841 Status
= InputBarSetStringSize (1);
842 if (EFI_ERROR (Status
)) {
850 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
851 StatusBarSetRefresh();
856 if (Status
== EFI_NOT_READY
) {
862 switch (InputBarGetString()[0]) {
880 // end of while !Done
891 StatusBarSetStatusString (L
"Search String Not Found");
899 @retval EFI_SUCCESS The operation was successful.
900 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
901 @retval EFI_LOAD_ERROR A load error occured.
912 // Below is the scenario of Exit command:
913 // 1. IF currently opened file is not modified, exit the editor and
914 // Exit command ends.
915 // IF currently opened file is modified, do Step 2
917 // 2. An Input Bar will be prompted:
918 // "File modified. Save ( Yes/No/Cancel )?"
919 // IF user press 'y' or 'Y', currently opened file will be saved
921 // IF user press 'n' or 'N', currently opened file will not be saved
923 // IF user press 'c' or 'C' or ESC, Exit command ends.
924 // if file has been modified, so will prompt user whether to save the changes
926 if (MainEditor
.FileBuffer
->FileModified
) {
928 Status
= InputBarSetPrompt (L
"File modified. Save (Yes/No/Cancel) ? ");
929 if (EFI_ERROR (Status
)) {
933 Status
= InputBarSetStringSize (1);
934 if (EFI_ERROR (Status
)) {
939 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
940 StatusBarSetRefresh();
945 if (Status
== EFI_NOT_READY
) {
949 switch (InputBarGetString()[0]) {
953 // write file back to disk
955 Status
= FileBufferSave (MainEditor
.FileBuffer
->FileName
);
956 if (!EFI_ERROR (Status
)) {
981 move cursor to specified lines
983 @retval EFI_SUCCESS The operation was successful.
987 MainCommandGotoLine (
995 // Below is the scenario of Go To Line command:
996 // 1. An Input Bar will be prompted : "Go To Line:".
997 // IF user press ESC, Go To Line command ends.
998 // IF user just press Enter, cursor remains unchanged.
999 // IF user inputs line number, do Step 2.
1001 // 2. IF input line number is valid, move cursor to the beginning
1002 // of specified line and Go To Line command ends.
1003 // IF input line number is invalid, a Status String will be prompted:
1004 // "No Such Line" and Go To Line command ends.
1006 Status
= InputBarSetPrompt (L
"Go To Line: ");
1007 if (EFI_ERROR (Status
)) {
1011 // line number's digit <= 6
1013 Status
= InputBarSetStringSize (6);
1014 if (EFI_ERROR (Status
)) {
1018 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1019 StatusBarSetRefresh();
1024 if (Status
== EFI_NOT_READY
) {
1028 // if JUST press enter
1030 if (StrLen (InputBarGetString()) == 0) {
1034 Row
= ShellStrToUintn (InputBarGetString());
1037 // invalid line number
1039 if (Row
> MainEditor
.FileBuffer
->NumLines
|| Row
<= 0) {
1040 StatusBarSetStatusString (L
"No Such Line");
1044 // move cursor to that line's start
1046 FileBufferMovePosition (Row
, 1);
1052 Save current file to disk, you can save to current file name or
1053 save to another file name.
1055 @retval EFI_SUCCESS The file was saved correctly.
1056 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1057 @retval EFI_LOAD_ERROR A file access error occured.
1061 MainCommandSaveFile (
1069 SHELL_FILE_HANDLE FileHandle
;
1070 EFI_FILE_INFO
*Info
;
1073 // This command will save currently opened file to disk.
1074 // You can choose save to another file name or just save to
1075 // current file name.
1076 // Below is the scenario of Save File command:
1077 // ( Suppose the old file name is A )
1078 // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
1079 // IF user press ESC, Save File command ends .
1080 // IF user press Enter, input file name will be A.
1081 // IF user inputs a new file name B, input file name will be B.
1083 // 2. IF input file name is A, go to do Step 3.
1084 // IF input file name is B, go to do Step 4.
1086 // 3. IF A is read only, Status Bar will show "Access Denied" and
1087 // Save File commands ends.
1088 // IF A is not read only, save file buffer to disk and remove modified
1089 // flag in Title Bar , then Save File command ends.
1091 // 4. IF B does not exist, create this file and save file buffer to it.
1093 // IF B exits, do Step 5.
1095 // 5.An Input Bar will be prompted:
1096 // "File Exists. Overwrite ( Yes/No/Cancel )?"
1097 // IF user press 'y' or 'Y', do Step 6.
1098 // IF user press 'n' or 'N', Save File commands ends.
1099 // IF user press 'c' or 'C' or ESC, Save File commands ends.
1101 // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
1102 // Save File commands ends.
1103 // IF B can be read and write, save file buffer to B.
1105 // 7. Update File Name field in Title Bar to B and remove the modified
1106 // flag in Title Bar.
1108 Str
= CatSPrint (NULL
, L
"File to Save: [%s]", MainEditor
.FileBuffer
->FileName
);
1110 return EFI_OUT_OF_RESOURCES
;
1113 if (StrLen (Str
) >= 50) {
1115 // replace the long file name with "..."
1121 Str
[50] = CHAR_NULL
;
1124 Status
= InputBarSetPrompt (Str
);
1127 if (EFI_ERROR (Status
)) {
1132 Status
= InputBarSetStringSize (100);
1133 if (EFI_ERROR (Status
)) {
1137 // get new file name
1139 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1140 StatusBarSetRefresh();
1143 // if user pressed ESC
1145 if (Status
== EFI_NOT_READY
) {
1150 // if just enter pressed, so think save to current file name
1152 if (StrLen (InputBarGetString()) == 0) {
1153 FileName
= CatSPrint (NULL
, L
"%s", MainEditor
.FileBuffer
->FileName
);
1155 FileName
= CatSPrint (NULL
, L
"%s", InputBarGetString());
1158 if (FileName
== NULL
) {
1159 return EFI_OUT_OF_RESOURCES
;
1162 if (!IsValidFileName (FileName
)) {
1163 StatusBarSetStatusString (L
"Invalid File Name");
1164 FreePool (FileName
);
1171 // save to the old file
1173 if (StringNoCaseCompare (&FileName
, &MainEditor
.FileBuffer
->FileName
) == 0) {
1179 // if the file is read only, so can not write back to it.
1181 if (MainEditor
.FileBuffer
->ReadOnly
== TRUE
) {
1182 StatusBarSetStatusString (L
"Access Denied");
1183 FreePool (FileName
);
1188 // if the file exists
1190 if (ShellFileExists(FileName
) != EFI_NOT_FOUND
) {
1192 // check for read only
1194 Status
= ShellOpenFileByName(FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
1195 if (EFI_ERROR(Status
)) {
1196 StatusBarSetStatusString (L
"Open Failed");
1197 FreePool (FileName
);
1201 Info
= ShellGetFileInfo(FileHandle
);
1203 StatusBarSetStatusString (L
"Access Denied");
1204 FreePool (FileName
);
1205 return (EFI_SUCCESS
);
1208 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
1209 StatusBarSetStatusString (L
"Access Denied - Read Only");
1211 FreePool (FileName
);
1212 return (EFI_SUCCESS
);
1217 // ask user whether to overwrite this file
1219 Status
= InputBarSetPrompt (L
"File exists. Overwrite (Yes/No/Cancel) ? ");
1220 if (EFI_ERROR (Status
)) {
1221 SHELL_FREE_NON_NULL (FileName
);
1225 Status
= InputBarSetStringSize (1);
1226 if (EFI_ERROR (Status
)) {
1227 SHELL_FREE_NON_NULL (FileName
);
1232 Status
= InputBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1233 StatusBarSetRefresh();
1238 if (Status
== EFI_NOT_READY
) {
1239 SHELL_FREE_NON_NULL (FileName
);
1243 switch (InputBarGetString()[0]) {
1252 SHELL_FREE_NON_NULL (FileName
);
1256 } // file does exist
1257 } // if old file name same
1260 // save file to disk with specified name
1262 FileBufferSetModified();
1263 Status
= FileBufferSave (FileName
);
1264 SHELL_FREE_NON_NULL (FileName
);
1269 EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors
;
1273 // the first time editor launch
1275 BOOLEAN EditorFirst
;
1278 // it's time editor should exit
1282 BOOLEAN EditorMouseAction
;
1284 extern EFI_EDITOR_FILE_BUFFER FileBuffer
;
1286 extern BOOLEAN FileBufferMouseNeedRefresh
;
1288 extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
1290 EFI_EDITOR_GLOBAL_EDITOR MainEditor
;
1293 // basic initialization for MainEditor
1295 EFI_EDITOR_GLOBAL_EDITOR MainEditorConst
= {
1311 The initialization function for MainEditor.
1313 @retval EFI_SUCCESS The operation was successful.
1314 @retval EFI_LOAD_ERROR A load error occured.
1323 EFI_HANDLE
*HandleBuffer
;
1328 // basic initialization
1330 CopyMem (&MainEditor
, &MainEditorConst
, sizeof (MainEditor
));
1333 // set screen attributes
1335 MainEditor
.ColorAttributes
.Colors
.Foreground
= gST
->ConOut
->Mode
->Attribute
& 0x000000ff;
1337 MainEditor
.ColorAttributes
.Colors
.Background
= (UINT8
) (gST
->ConOut
->Mode
->Attribute
>> 4);
1338 OriginalColors
= MainEditor
.ColorAttributes
.Colors
;
1340 OriginalMode
= gST
->ConOut
->Mode
->Mode
;
1343 // query screen size
1345 gST
->ConOut
->QueryMode (
1347 gST
->ConOut
->Mode
->Mode
,
1348 &(MainEditor
.ScreenSize
.Column
),
1349 &(MainEditor
.ScreenSize
.Row
)
1353 // Find mouse in System Table ConsoleInHandle
1355 Status
= gBS
->HandleProtocol (
1357 &gEfiSimplePointerProtocolGuid
,
1358 (VOID
**)&MainEditor
.MouseInterface
1360 if (EFI_ERROR (Status
)) {
1362 // If there is no Simple Pointer Protocol on System Table
1364 HandleBuffer
= NULL
;
1365 MainEditor
.MouseInterface
= NULL
;
1366 Status
= gBS
->LocateHandleBuffer (
1368 &gEfiSimplePointerProtocolGuid
,
1373 if (!EFI_ERROR (Status
) && HandleCount
> 0) {
1375 // Try to find the first available mouse device
1377 for (Index
= 0; Index
< HandleCount
; Index
++) {
1378 Status
= gBS
->HandleProtocol (
1379 HandleBuffer
[Index
],
1380 &gEfiSimplePointerProtocolGuid
,
1381 (VOID
**)&MainEditor
.MouseInterface
1383 if (!EFI_ERROR (Status
)) {
1388 if (HandleBuffer
!= NULL
) {
1389 FreePool (HandleBuffer
);
1393 if (!EFI_ERROR (Status
) && MainEditor
.MouseInterface
!= NULL
) {
1394 MainEditor
.MouseAccumulatorX
= 0;
1395 MainEditor
.MouseAccumulatorY
= 0;
1396 MainEditor
.MouseSupported
= TRUE
;
1400 // below will call the five components' init function
1402 Status
= MainTitleBarInit (L
"UEFI EDIT 2.0");
1403 if (EFI_ERROR (Status
)) {
1404 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR
), gShellDebug1HiiHandle
);
1405 return EFI_LOAD_ERROR
;
1408 Status
= MenuBarInit (MainMenuItems
);
1409 if (EFI_ERROR (Status
)) {
1410 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU
), gShellDebug1HiiHandle
);
1411 return EFI_LOAD_ERROR
;
1414 Status
= StatusBarInit ();
1415 if (EFI_ERROR (Status
)) {
1416 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR
), gShellDebug1HiiHandle
);
1417 return EFI_LOAD_ERROR
;
1422 Status
= FileBufferInit ();
1423 if (EFI_ERROR (Status
)) {
1424 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER
), gShellDebug1HiiHandle
);
1425 return EFI_LOAD_ERROR
;
1428 // clear whole screen and enable cursor
1430 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1431 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
1434 // initialize EditorFirst and EditorExit
1438 EditorMouseAction
= FALSE
;
1444 The cleanup function for MainEditor.
1446 @retval EFI_SUCCESS The operation was successful.
1447 @retval EFI_LOAD_ERROR A load error occured.
1458 // call the five components' cleanup function
1459 // if error, do not exit
1460 // just print some warning
1462 MainTitleBarCleanup();
1467 Status
= FileBufferCleanup ();
1468 if (EFI_ERROR (Status
)) {
1469 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP
), gShellDebug1HiiHandle
);
1474 if (OriginalMode
!= gST
->ConOut
->Mode
->Mode
) {
1475 gST
->ConOut
->SetMode (gST
->ConOut
, OriginalMode
);
1478 // restore old screen color
1480 gST
->ConOut
->SetAttribute (
1482 EFI_TEXT_ATTR (OriginalColors
.Foreground
, OriginalColors
.Background
)
1485 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1491 Refresh the main editor component.
1500 // The Stall value is from experience. NOT from spec. avoids 'flicker'
1505 // call the components refresh function
1508 || StrCmp (FileBufferBackupVar
.FileName
, FileBuffer
.FileName
) != 0
1509 || FileBufferBackupVar
.FileType
!= FileBuffer
.FileType
1510 || FileBufferBackupVar
.FileModified
!= FileBuffer
.FileModified
1511 || FileBufferBackupVar
.ReadOnly
!= FileBuffer
.ReadOnly
) {
1513 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
1514 FileBufferRestorePosition ();
1515 FileBufferRefresh ();
1518 || FileBufferBackupVar
.FilePosition
.Row
!= FileBuffer
.FilePosition
.Row
1519 || FileBufferBackupVar
.FilePosition
.Column
!= FileBuffer
.FilePosition
.Column
1520 || FileBufferBackupVar
.ModeInsert
!= FileBuffer
.ModeInsert
1521 || StatusBarGetRefresh()) {
1523 StatusBarRefresh (EditorFirst
, MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.FileBuffer
->FilePosition
.Row
, MainEditor
.FileBuffer
->FilePosition
.Column
, MainEditor
.FileBuffer
->ModeInsert
);
1524 FileBufferRestorePosition ();
1525 FileBufferRefresh ();
1529 MenuBarRefresh (MainEditor
.ScreenSize
.Row
, MainEditor
.ScreenSize
.Column
);
1530 FileBufferRestorePosition ();
1534 // EditorFirst is now set to FALSE
1536 EditorFirst
= FALSE
;
1540 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1542 @param[in] GuidX The relative mouse movement.
1544 @return The X location of the mouse.
1554 MainEditor
.MouseAccumulatorX
+= GuidX
;
1555 Gap
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1556 MainEditor
.MouseAccumulatorX
= (MainEditor
.MouseAccumulatorX
* (INT32
) MainEditor
.ScreenSize
.Column
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionX
);
1557 MainEditor
.MouseAccumulatorX
= MainEditor
.MouseAccumulatorX
/ (INT32
) MainEditor
.ScreenSize
.Column
;
1562 Get's the resultant location of the cursor based on the relative movement of the Mouse.
1564 @param[in] GuidY The relative mouse movement.
1566 @return The Y location of the mouse.
1576 MainEditor
.MouseAccumulatorY
+= GuidY
;
1577 Gap
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) / (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1578 MainEditor
.MouseAccumulatorY
= (MainEditor
.MouseAccumulatorY
* (INT32
) MainEditor
.ScreenSize
.Row
) % (INT32
) (50 * (INT32
) MainEditor
.MouseInterface
->Mode
->ResolutionY
);
1579 MainEditor
.MouseAccumulatorY
= MainEditor
.MouseAccumulatorY
/ (INT32
) MainEditor
.ScreenSize
.Row
;
1585 Support mouse movement. Move the cursor.
1587 @param[in] MouseState The current mouse state.
1589 @retval EFI_SUCCESS The operation was successful.
1590 @retval EFI_NOT_FOUND There was no mouse support found.
1594 MainEditorHandleMouseInput (
1595 IN EFI_SIMPLE_POINTER_STATE MouseState
1605 EFI_EDITOR_LINE
*Line
;
1611 // mouse action means:
1613 // mouse left button
1618 // have mouse movement
1620 if (MouseState
.RelativeMovementX
|| MouseState
.RelativeMovementY
) {
1624 TextX
= GetTextX (MouseState
.RelativeMovementX
);
1625 TextY
= GetTextY (MouseState
.RelativeMovementY
);
1627 FileBufferAdjustMousePosition (TextX
, TextY
);
1634 // if left button pushed down
1636 if (MouseState
.LeftButton
) {
1638 FCol
= MainEditor
.FileBuffer
->MousePosition
.Column
- 1 + 1;
1640 FRow
= MainEditor
.FileBuffer
->FilePosition
.Row
+
1641 MainEditor
.FileBuffer
->MousePosition
.Row
-
1642 MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1645 // beyond the file line length
1647 if (MainEditor
.FileBuffer
->NumLines
< FRow
) {
1648 FRow
= MainEditor
.FileBuffer
->NumLines
;
1651 Link
= MainEditor
.FileBuffer
->ListHead
->ForwardLink
;
1652 for (Index
= 0; Index
< FRow
- 1; Index
++) {
1653 Link
= Link
->ForwardLink
;
1656 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1659 // beyond the line's column length
1661 if (FCol
> Line
->Size
+ 1) {
1662 FCol
= Line
->Size
+ 1;
1665 FileBufferMovePosition (FRow
, FCol
);
1667 MainEditor
.FileBuffer
->MousePosition
.Row
= MainEditor
.FileBuffer
->DisplayPosition
.Row
;
1669 MainEditor
.FileBuffer
->MousePosition
.Column
= MainEditor
.FileBuffer
->DisplayPosition
.Column
;
1683 return EFI_NOT_FOUND
;
1687 Handle user key input. This routes to other functions for the actions.
1689 @retval EFI_SUCCESS The operation was successful.
1690 @retval EFI_LOAD_ERROR A load error occured.
1691 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1695 MainEditorKeyInput (
1701 EFI_SIMPLE_POINTER_STATE MouseState
;
1705 Status
= EFI_SUCCESS
;
1706 EditorMouseAction
= FALSE
;
1709 // backup some key elements, so that can aVOID some refresh work
1711 MainEditorBackup ();
1714 // change priority of checking mouse/keyboard activity dynamically
1715 // so prevent starvation of keyboard.
1716 // if last time, mouse moves then this time check keyboard
1718 if (MainEditor
.MouseSupported
) {
1719 Status
= MainEditor
.MouseInterface
->GetState (
1720 MainEditor
.MouseInterface
,
1723 if (!EFI_ERROR (Status
)) {
1725 Status
= MainEditorHandleMouseInput (MouseState
);
1727 if (!EFI_ERROR (Status
)) {
1728 EditorMouseAction
= TRUE
;
1729 FileBufferMouseNeedRefresh
= TRUE
;
1730 } else if (Status
== EFI_LOAD_ERROR
) {
1731 StatusBarSetStatusString (L
"Invalid Mouse Movement ");
1736 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1737 if (!EFI_ERROR (Status
)) {
1739 // dispatch to different components' key handling function
1740 // so not everywhere has to set this variable
1742 FileBufferMouseNeedRefresh
= TRUE
;
1744 // clear previous status string
1746 StatusBarSetRefresh();
1749 // dispatch to different components' key handling function
1751 if ((Key
.ScanCode
== SCAN_NULL
) || ((Key
.ScanCode
>= SCAN_UP
) && (Key
.ScanCode
<= SCAN_PAGE_DOWN
))) {
1752 Status
= FileBufferHandleInput (&Key
);
1753 } else if ((Key
.ScanCode
>= SCAN_F1
) && (Key
.ScanCode
<= SCAN_F12
)) {
1754 Status
= MenuBarDispatchFunctionKey (&Key
);
1756 StatusBarSetStatusString (L
"Unknown Command");
1757 FileBufferMouseNeedRefresh
= FALSE
;
1760 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_OUT_OF_RESOURCES
) {
1762 // not already has some error status
1764 if (StatusBarGetString() != NULL
&& StrCmp (L
"", StatusBarGetString()) == 0) {
1765 StatusBarSetStatusString (L
"Disk Error. Try Again");
1771 // after handling, refresh editor
1773 MainEditorRefresh ();
1775 } while (Status
!= EFI_OUT_OF_RESOURCES
&& !EditorExit
);
1783 @param[in] Line A pointer to the line to be set to clipboard
1785 @retval EFI_SUCCESS The operation was successful.
1786 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1790 MainEditorSetCutLine (
1791 EFI_EDITOR_LINE
*Line
1798 if (MainEditor
.CutLine
!= NULL
) {
1800 // free the old clipboard
1802 LineFree (MainEditor
.CutLine
);
1805 // duplicate the line to clipboard
1807 MainEditor
.CutLine
= LineDup (Line
);
1808 if (MainEditor
.CutLine
== NULL
) {
1809 return EFI_OUT_OF_RESOURCES
;
1816 Backup function for MainEditor
1818 @retval EFI_SUCCESS The operation was successful.
1826 FileBufferBackup ();