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