]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
CorebootModulePkg-CbParseLib: Fix bad reference in CbParseLib
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Edit / MainTextEditor.c
CommitLineData
632820d1 1/** @file\r
2 Implements editor interface functions.\r
3\r
0d807dae 4 Copyright (c) 2005 - 2014, 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
0d807dae 492 Line = NULL;\r
632820d1 493 Status = FileBufferCutLine (&Line);\r
494 if (Status == EFI_NOT_FOUND) {\r
495 return EFI_SUCCESS;\r
496 }\r
497\r
498 if (EFI_ERROR (Status)) {\r
499 return Status;\r
500 }\r
501\r
502 MainEditor.CutLine = Line;\r
503\r
504 return EFI_SUCCESS;\r
505}\r
506\r
507/**\r
508 paste line to file buffer.\r
509\r
510 @retval EFI_SUCCESS The operation was successful.\r
511 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
512 @retval EFI_LOAD_ERROR A load error occured.\r
513**/\r
514EFI_STATUS\r
632820d1 515MainCommandPasteLine (\r
516 VOID\r
517 )\r
518{\r
519 EFI_STATUS Status;\r
520\r
521 //\r
522 // Below is the scenario of Paste Line command:\r
523 // 1. IF nothing is on clipboard, a Status String will be prompted :\r
524 // "No Line to Paste" and Paste Line command ends.\r
525 // IF something is on clipboard, insert it above current line.\r
526 // nothing on clipboard\r
527 //\r
528 if (MainEditor.CutLine == NULL) {\r
529 StatusBarSetStatusString (L"No Line to Paste");\r
530 return EFI_SUCCESS;\r
531 }\r
532\r
533 Status = FileBufferPasteLine ();\r
534\r
535 return Status;\r
536}\r
537\r
538\r
539/**\r
540 search string in file buffer\r
541\r
542 @retval EFI_SUCCESS The operation was successful.\r
543 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
544 @retval EFI_LOAD_ERROR A load error occured.\r
545**/\r
546EFI_STATUS\r
632820d1 547MainCommandSearch (\r
548 VOID\r
549 )\r
550{\r
551 EFI_STATUS Status;\r
552 CHAR16 *Buffer;\r
553 BOOLEAN Done;\r
554 UINTN Offset;\r
555\r
556 //\r
557 // Below is the scenario of Search command:\r
558 // 1. An Input Bar will be prompted : "Enter Search String:".\r
559 // IF user press ESC, Search command ends.\r
560 // IF user just press Enter, Search command ends.\r
561 // IF user inputs the search string, do Step 2.\r
562 //\r
563 // 2. IF input search string is found, cursor will move to the first\r
564 // occurrence and do Step 3.\r
565 // IF input search string is not found, a Status String\r
566 // "Search String Not Found" will be prompted and Search command ends.\r
567 //\r
568 // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".\r
569 // IF user press ESC, Search command ends.\r
570 // IF user press 'y' or 'Y', do Step 2.\r
571 // IF user press 'n' or 'N', Search command ends.\r
572 // IF user press 'c' or 'C', Search command ends.\r
573 //\r
574 Status = InputBarSetPrompt (L"Enter Search String: ");\r
575 if (EFI_ERROR (Status)) {\r
576 return Status;\r
577 }\r
578\r
579 Status = InputBarSetStringSize (40);\r
580 if (EFI_ERROR (Status)) {\r
581 return Status;\r
582 }\r
583\r
584 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
585 StatusBarSetRefresh();\r
586\r
587 //\r
588 // ESC\r
589 //\r
590 if (Status == EFI_NOT_READY) {\r
591 return EFI_SUCCESS;\r
592 }\r
593 //\r
594 // just enter pressed\r
595 //\r
596 if (StrLen (InputBarGetString()) == 0) {\r
597 return EFI_SUCCESS;\r
598 }\r
599\r
600 Buffer = CatSPrint (NULL, L"%s", InputBarGetString());\r
601 if (Buffer == NULL) {\r
602 return EFI_OUT_OF_RESOURCES;\r
603 }\r
604 //\r
605 // the first time , search from current position\r
606 //\r
607 Offset = 0;\r
608 do {\r
609 //\r
610 // since search may be continued to search multiple times\r
611 // so we need to backup editor each time\r
612 //\r
613 MainEditorBackup ();\r
614\r
615 Status = FileBufferSearch (Buffer, Offset);\r
616\r
617 if (Status == EFI_NOT_FOUND) {\r
618 break;\r
619 }\r
620 //\r
621 // Find next\r
622 //\r
623 Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");\r
624 if (EFI_ERROR (Status)) {\r
625 FreePool (Buffer);\r
626 return Status;\r
627 }\r
628\r
629 Status = InputBarSetStringSize (1);\r
630 if (EFI_ERROR (Status)) {\r
631 FreePool (Buffer);\r
632 return Status;\r
633 }\r
634\r
635 Done = FALSE;\r
636 while (!Done) {\r
637 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
638 StatusBarSetRefresh();\r
639\r
640 //\r
641 // ESC pressed\r
642 //\r
643 if (Status == EFI_NOT_READY) {\r
644 FreePool (Buffer);\r
645 return EFI_SUCCESS;\r
646 }\r
647\r
648 switch (InputBarGetString()[0]) {\r
649 case L'y':\r
650 case L'Y':\r
651 Done = TRUE;\r
652 break;\r
653\r
654 case L'n':\r
655 case L'N':\r
656 FreePool (Buffer);\r
657 return EFI_SUCCESS;\r
658\r
659 }\r
660 //\r
661 // end of which\r
662 //\r
663 }\r
664 //\r
665 // end of while !Done\r
666 // for search second, third time, search from current position + strlen\r
667 //\r
668 Offset = StrLen (Buffer);\r
669\r
670 } while (1);\r
671 //\r
672 // end of do\r
673 //\r
674 FreePool (Buffer);\r
675 StatusBarSetStatusString (L"Search String Not Found");\r
676\r
677 return EFI_SUCCESS;\r
678}\r
679\r
ae724571 680/**\r
681 Search string in file buffer, and replace it with another str.\r
632820d1 682\r
683 @retval EFI_SUCCESS The operation was successful.\r
684 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
685 @retval EFI_LOAD_ERROR A load error occured.\r
686**/\r
687EFI_STATUS\r
632820d1 688MainCommandSearchReplace (\r
689 VOID\r
690 )\r
691{\r
692 EFI_STATUS Status;\r
693 CHAR16 *Search;\r
694 CHAR16 *Replace;\r
695 BOOLEAN Done;\r
696 BOOLEAN First;\r
697 BOOLEAN ReplaceOption;\r
698 UINTN SearchLen;\r
699 UINTN ReplaceLen;\r
700 BOOLEAN ReplaceAll;\r
701\r
702 ReplaceOption = FALSE;\r
703\r
704 //\r
705 // Below is the scenario of Search/Replace command:\r
706 // 1. An Input Bar is prompted : "Enter Search String:".\r
707 // IF user press ESC, Search/Replace command ends.\r
708 // IF user just press Enter, Search/Replace command ends.\r
709 // IF user inputs the search string S, do Step 2.\r
710 //\r
711 // 2. An Input Bar is prompted: "Replace With:".\r
712 // IF user press ESC, Search/Replace command ends.\r
713 // IF user inputs the replace string R, do Step 3.\r
714 //\r
715 // 3. IF input search string is not found, an Status String\r
716 // "Search String Not Found" will be prompted\r
717 // and Search/Replace command ends\r
718 // IF input search string is found, do Step 4.\r
719 //\r
720 // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"\r
721 // IF user press 'y' or 'Y', S will be replaced with R and do Step 5\r
722 // IF user press 'n' or 'N', S will not be replaced and do Step 5.\r
723 // IF user press 'a' or 'A', all the S from file current position on\r
724 // will be replaced with R and Search/Replace command ends.\r
725 // IF user press 'c' or 'C' or ESC, Search/Replace command ends.\r
726 //\r
727 // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".\r
728 // IF user press ESC, Search/Replace command ends.\r
729 // IF user press 'y' or 'Y', do Step 3.\r
730 // IF user press 'n' or 'N', Search/Replace command ends.\r
731 // IF user press 'c' or 'C', Search/Replace command ends.\r
732 // input search string\r
733 //\r
734 Status = InputBarSetPrompt (L"Enter Search String: ");\r
735 if (EFI_ERROR (Status)) {\r
736 return Status;\r
737 }\r
738\r
739 Status = InputBarSetStringSize (40);\r
740 if (EFI_ERROR (Status)) {\r
741 return Status;\r
742 }\r
743\r
744 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
745 StatusBarSetRefresh();\r
746\r
747 //\r
748 // ESC\r
749 //\r
750 if (Status == EFI_NOT_READY) {\r
751 return EFI_SUCCESS;\r
752 }\r
753 //\r
754 // if just pressed enter\r
755 //\r
756 if (StrLen (InputBarGetString()) == 0) {\r
757 return EFI_SUCCESS;\r
758 }\r
759\r
760 Search = CatSPrint (NULL, L"%s", InputBarGetString());\r
761 if (Search == NULL) {\r
762 return EFI_OUT_OF_RESOURCES;\r
763 }\r
764\r
765 SearchLen = StrLen (Search);\r
766\r
767 //\r
768 // input replace string\r
769 //\r
770 Status = InputBarSetPrompt (L"Replace With: ");\r
771 if (EFI_ERROR (Status)) {\r
772 return Status;\r
773 }\r
774\r
775 Status = InputBarSetStringSize (40);\r
776 if (EFI_ERROR (Status)) {\r
777 return Status;\r
778 }\r
779\r
780 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
781 StatusBarSetRefresh();\r
782\r
783 //\r
784 // ESC\r
785 //\r
786 if (Status == EFI_NOT_READY) {\r
787 return EFI_SUCCESS;\r
788 }\r
789\r
790 Replace = CatSPrint (NULL, L"%s", InputBarGetString());\r
791 if (Replace == NULL) {\r
792 FreePool (Search);\r
793 return EFI_OUT_OF_RESOURCES;\r
794 }\r
795\r
796 ReplaceLen = StrLen (Replace);\r
797\r
798 First = TRUE;\r
799 ReplaceAll = FALSE;\r
800 do {\r
801 //\r
802 // since search may be continued to search multiple times\r
803 // so we need to backup editor each time\r
804 //\r
805 MainEditorBackup ();\r
806\r
807 if (First) {\r
808 Status = FileBufferSearch (Search, 0);\r
809 } else {\r
810 //\r
811 // if just replace, so skip this replace string\r
812 // if replace string is an empty string, so skip to next character\r
813 //\r
814 if (ReplaceOption) {\r
815 Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen);\r
816 } else {\r
817 Status = FileBufferSearch (Search, SearchLen);\r
818 }\r
819 }\r
820\r
821 if (Status == EFI_NOT_FOUND) {\r
822 break;\r
823 }\r
824 //\r
825 // replace or not?\r
826 //\r
827 Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?");\r
828\r
829 if (EFI_ERROR (Status)) {\r
830 FreePool (Search);\r
831 FreePool (Replace);\r
832 return Status;\r
833 }\r
834\r
835 Status = InputBarSetStringSize (1);\r
836 if (EFI_ERROR (Status)) {\r
837 FreePool (Search);\r
838 FreePool (Replace);\r
839 return Status;\r
840 }\r
841\r
842 Done = FALSE;\r
843 while (!Done) {\r
844 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
845 StatusBarSetRefresh();\r
846\r
847 //\r
848 // ESC pressed\r
849 //\r
850 if (Status == EFI_NOT_READY) {\r
851 FreePool (Search);\r
852 FreePool (Replace);\r
853 return EFI_SUCCESS;\r
854 }\r
855\r
856 switch (InputBarGetString()[0]) {\r
857 case L'y':\r
858 case L'Y':\r
859 Done = TRUE;\r
860 ReplaceOption = TRUE;\r
861 break;\r
862\r
863 case L'n':\r
864 case L'N':\r
865 Done = TRUE;\r
866 ReplaceOption = FALSE;\r
867 break;\r
868\r
869 case L'a':\r
870 case L'A':\r
871 Done = TRUE;\r
872 ReplaceOption = TRUE;\r
873 ReplaceAll = TRUE;\r
874 break;\r
875\r
876 case L'c':\r
877 case L'C':\r
878 FreePool (Search);\r
879 FreePool (Replace);\r
880 return EFI_SUCCESS;\r
881\r
882 }\r
883 //\r
884 // end of which\r
885 //\r
886 }\r
887 //\r
888 // end of while !Done\r
889 // Decide to Replace\r
890 //\r
891 if (ReplaceOption) {\r
892 //\r
893 // file is read-only\r
894 //\r
895 if (MainEditor.FileBuffer->ReadOnly) {\r
896 StatusBarSetStatusString (L"Read Only File Can Not Be Modified");\r
897 return EFI_SUCCESS;\r
898 }\r
899 //\r
900 // replace all\r
901 //\r
902 if (ReplaceAll) {\r
903 Status = FileBufferReplaceAll (Search, Replace, 0);\r
904 FreePool (Search);\r
905 FreePool (Replace);\r
906 return Status;\r
907 }\r
908 //\r
909 // replace\r
910 //\r
911 Status = FileBufferReplace (Replace, SearchLen);\r
912 if (EFI_ERROR (Status)) {\r
913 FreePool (Search);\r
914 FreePool (Replace);\r
915 return Status;\r
916 }\r
917 }\r
918 //\r
919 // Find next\r
920 //\r
921 Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");\r
922 if (EFI_ERROR (Status)) {\r
923 FreePool (Search);\r
924 FreePool (Replace);\r
925 return Status;\r
926 }\r
927\r
928 Status = InputBarSetStringSize (1);\r
929 if (EFI_ERROR (Status)) {\r
930 FreePool (Search);\r
931 FreePool (Replace);\r
932 return Status;\r
933 }\r
934\r
935 Done = FALSE;\r
936 while (!Done) {\r
937 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
938 StatusBarSetRefresh();\r
939\r
940 //\r
941 // ESC pressed\r
942 //\r
943 if (Status == EFI_NOT_READY) {\r
944 FreePool (Search);\r
945 FreePool (Replace);\r
946 return EFI_SUCCESS;\r
947 }\r
948\r
949 switch (InputBarGetString()[0]) {\r
950 case L'y':\r
951 case L'Y':\r
952 Done = TRUE;\r
953 break;\r
954\r
955 case L'n':\r
956 case L'N':\r
957 FreePool (Search);\r
958 FreePool (Replace);\r
959 return EFI_SUCCESS;\r
960\r
961 }\r
962 //\r
963 // end of which\r
964 //\r
965 }\r
966 //\r
967 // end of while !Done\r
968 //\r
969 First = FALSE;\r
970\r
971 } while (1);\r
972 //\r
973 // end of do\r
974 //\r
975 FreePool (Search);\r
976 FreePool (Replace);\r
977\r
978 StatusBarSetStatusString (L"Search String Not Found");\r
979\r
980 return EFI_SUCCESS;\r
981}\r
982\r
983/**\r
984 exit editor\r
985\r
986 @retval EFI_SUCCESS The operation was successful.\r
987 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
988 @retval EFI_LOAD_ERROR A load error occured.\r
989**/\r
990EFI_STATUS\r
632820d1 991MainCommandExit (\r
992 VOID\r
993 )\r
994{\r
995 EFI_STATUS Status;\r
996\r
997 //\r
998 // Below is the scenario of Exit command:\r
999 // 1. IF currently opened file is not modified, exit the editor and\r
1000 // Exit command ends.\r
1001 // IF currently opened file is modified, do Step 2\r
1002 //\r
1003 // 2. An Input Bar will be prompted:\r
1004 // "File modified. Save ( Yes/No/Cancel )?"\r
1005 // IF user press 'y' or 'Y', currently opened file will be saved\r
1006 // and Editor exits\r
1007 // IF user press 'n' or 'N', currently opened file will not be saved\r
1008 // and Editor exits.\r
1009 // IF user press 'c' or 'C' or ESC, Exit command ends.\r
1010 // if file has been modified, so will prompt user whether to save the changes\r
1011 //\r
1012 if (MainEditor.FileBuffer->FileModified) {\r
1013\r
1014 Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");\r
1015 if (EFI_ERROR (Status)) {\r
1016 return Status;\r
1017 }\r
1018\r
1019 Status = InputBarSetStringSize (1);\r
1020 if (EFI_ERROR (Status)) {\r
1021 return Status;\r
1022 }\r
1023\r
1024 while (1) {\r
1025 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
1026 StatusBarSetRefresh();\r
1027\r
1028 //\r
1029 // ESC pressed\r
1030 //\r
1031 if (Status == EFI_NOT_READY) {\r
1032 return EFI_SUCCESS;\r
1033 }\r
1034\r
1035 switch (InputBarGetString()[0]) {\r
1036 case L'y':\r
1037 case L'Y':\r
1038 //\r
1039 // write file back to disk\r
1040 //\r
1041 Status = FileBufferSave (MainEditor.FileBuffer->FileName);\r
1042 if (!EFI_ERROR (Status)) {\r
1043 EditorExit = TRUE;\r
1044 }\r
1045\r
1046 return Status;\r
1047\r
1048 case L'n':\r
1049 case L'N':\r
1050 EditorExit = TRUE;\r
1051 return EFI_SUCCESS;\r
1052\r
1053 case L'c':\r
1054 case L'C':\r
1055 return EFI_SUCCESS;\r
1056\r
1057 }\r
1058 }\r
1059 }\r
1060\r
1061 EditorExit = TRUE;\r
1062 return EFI_SUCCESS;\r
1063\r
1064}\r
1065\r
1066/**\r
1067 move cursor to specified lines\r
1068\r
1069 @retval EFI_SUCCESS The operation was successful.\r
1070**/\r
1071EFI_STATUS\r
632820d1 1072MainCommandGotoLine (\r
1073 VOID\r
1074 )\r
1075{\r
1076 EFI_STATUS Status;\r
1077 UINTN Row;\r
1078\r
1079 //\r
1080 // Below is the scenario of Go To Line command:\r
1081 // 1. An Input Bar will be prompted : "Go To Line:".\r
1082 // IF user press ESC, Go To Line command ends.\r
1083 // IF user just press Enter, cursor remains unchanged.\r
1084 // IF user inputs line number, do Step 2.\r
1085 //\r
1086 // 2. IF input line number is valid, move cursor to the beginning\r
1087 // of specified line and Go To Line command ends.\r
1088 // IF input line number is invalid, a Status String will be prompted:\r
1089 // "No Such Line" and Go To Line command ends.\r
1090 //\r
1091 Status = InputBarSetPrompt (L"Go To Line: ");\r
1092 if (EFI_ERROR (Status)) {\r
1093 return Status;\r
1094 }\r
1095 //\r
1096 // line number's digit <= 6\r
1097 //\r
1098 Status = InputBarSetStringSize (6);\r
1099 if (EFI_ERROR (Status)) {\r
1100 return Status;\r
1101 }\r
1102\r
1103 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
1104 StatusBarSetRefresh();\r
1105\r
1106 //\r
1107 // press ESC\r
1108 //\r
1109 if (Status == EFI_NOT_READY) {\r
1110 return EFI_SUCCESS;\r
1111 }\r
1112 //\r
1113 // if JUST press enter\r
1114 //\r
1115 if (StrLen (InputBarGetString()) == 0) {\r
1116 return EFI_SUCCESS;\r
1117 }\r
1118\r
1119 Row = ShellStrToUintn (InputBarGetString());\r
1120\r
1121 //\r
1122 // invalid line number\r
1123 //\r
1124 if (Row > MainEditor.FileBuffer->NumLines || Row <= 0) {\r
1125 StatusBarSetStatusString (L"No Such Line");\r
1126 return EFI_SUCCESS;\r
1127 }\r
1128 //\r
1129 // move cursor to that line's start\r
1130 //\r
1131 FileBufferMovePosition (Row, 1);\r
1132\r
1133 return EFI_SUCCESS;\r
1134}\r
1135\r
1136/**\r
1137 Save current file to disk, you can save to current file name or\r
1138 save to another file name.\r
1139 \r
1140 @retval EFI_SUCCESS The file was saved correctly.\r
1141 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1142 @retval EFI_LOAD_ERROR A file access error occured.\r
1143**/\r
1144EFI_STATUS\r
632820d1 1145MainCommandSaveFile (\r
1146 VOID\r
1147 )\r
1148{\r
1149 EFI_STATUS Status;\r
1150 CHAR16 *FileName;\r
1151 BOOLEAN OldFile;\r
1152 CHAR16 *Str;\r
1153 SHELL_FILE_HANDLE FileHandle; \r
1154 EFI_FILE_INFO *Info;\r
1155\r
1156 //\r
1157 // This command will save currently opened file to disk.\r
1158 // You can choose save to another file name or just save to\r
1159 // current file name.\r
1160 // Below is the scenario of Save File command:\r
1161 // ( Suppose the old file name is A )\r
1162 // 1. An Input Bar will be prompted: "File To Save: [ old file name]"\r
1163 // IF user press ESC, Save File command ends .\r
1164 // IF user press Enter, input file name will be A.\r
1165 // IF user inputs a new file name B, input file name will be B.\r
1166 //\r
1167 // 2. IF input file name is A, go to do Step 3.\r
1168 // IF input file name is B, go to do Step 4.\r
1169 //\r
1170 // 3. IF A is read only, Status Bar will show "Access Denied" and\r
1171 // Save File commands ends.\r
1172 // IF A is not read only, save file buffer to disk and remove modified\r
1173 // flag in Title Bar , then Save File command ends.\r
1174 //\r
1175 // 4. IF B does not exist, create this file and save file buffer to it.\r
1176 // Go to do Step 7.\r
1177 // IF B exits, do Step 5.\r
1178 //\r
1179 // 5.An Input Bar will be prompted:\r
1180 // "File Exists. Overwrite ( Yes/No/Cancel )?"\r
1181 // IF user press 'y' or 'Y', do Step 6.\r
1182 // IF user press 'n' or 'N', Save File commands ends.\r
1183 // IF user press 'c' or 'C' or ESC, Save File commands ends.\r
1184 //\r
1185 // 6. IF B is a read-only file, Status Bar will show "Access Denied" and\r
1186 // Save File commands ends.\r
1187 // IF B can be read and write, save file buffer to B.\r
1188 //\r
1189 // 7. Update File Name field in Title Bar to B and remove the modified\r
1190 // flag in Title Bar.\r
1191 //\r
1192 Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName);\r
1193 if (Str == NULL) {\r
1194 return EFI_OUT_OF_RESOURCES;\r
1195 }\r
1196\r
1197 if (StrLen (Str) >= 50) {\r
1198 //\r
1199 // replace the long file name with "..."\r
1200 //\r
1201 Str[46] = L'.';\r
1202 Str[47] = L'.';\r
1203 Str[48] = L'.';\r
1204 Str[49] = L']';\r
1205 Str[50] = CHAR_NULL;\r
1206 }\r
1207\r
1208 Status = InputBarSetPrompt (Str);\r
1209 FreePool(Str);\r
1210\r
1211 if (EFI_ERROR (Status)) {\r
1212 return Status;\r
1213 }\r
1214\r
1215\r
1216 Status = InputBarSetStringSize (100);\r
1217 if (EFI_ERROR (Status)) {\r
1218 return Status;\r
1219 }\r
1220 //\r
1221 // get new file name\r
1222 //\r
1223 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
1224 StatusBarSetRefresh();\r
1225\r
1226 //\r
1227 // if user pressed ESC\r
1228 //\r
1229 if (Status == EFI_NOT_READY) {\r
1230 return EFI_SUCCESS;\r
1231 }\r
1232\r
1233 //\r
1234 // if just enter pressed, so think save to current file name\r
1235 //\r
1236 if (StrLen (InputBarGetString()) == 0) {\r
1237 FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName);\r
1238 } else {\r
1239 FileName = CatSPrint (NULL, L"%s", InputBarGetString());\r
1240 }\r
1241\r
1242 if (FileName == NULL) {\r
1243 return EFI_OUT_OF_RESOURCES;\r
1244 }\r
1245\r
1246 if (!IsValidFileName (FileName)) {\r
1247 StatusBarSetStatusString (L"Invalid File Name");\r
1248 FreePool (FileName);\r
1249 return EFI_SUCCESS;\r
1250 }\r
1251\r
1252 OldFile = FALSE;\r
1253\r
1254 //\r
1255 // save to the old file\r
1256 //\r
1257 if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) {\r
1258 OldFile = TRUE;\r
1259 }\r
1260\r
1261 if (OldFile) {\r
1262 //\r
1263 // if the file is read only, so can not write back to it.\r
1264 //\r
1265 if (MainEditor.FileBuffer->ReadOnly == TRUE) {\r
1266 StatusBarSetStatusString (L"Access Denied");\r
1267 FreePool (FileName);\r
1268 return EFI_SUCCESS;\r
1269 }\r
1270 } else {\r
1271 //\r
1272 // if the file exists\r
1273 //\r
1274 if (ShellFileExists(FileName) != EFI_NOT_FOUND) {\r
1275 //\r
1276 // check for read only\r
1277 //\r
1278 Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);\r
1279 if (EFI_ERROR(Status)) {\r
1280 StatusBarSetStatusString (L"Open Failed");\r
1281 FreePool (FileName);\r
1282 return EFI_SUCCESS;\r
1283 } \r
1284\r
1285 Info = ShellGetFileInfo(FileHandle);\r
1286 if (Info == NULL) {\r
1287 StatusBarSetStatusString (L"Access Denied");\r
1288 FreePool (FileName);\r
1289 return (EFI_SUCCESS);\r
1290 } \r
1291 \r
1292 if (Info->Attribute & EFI_FILE_READ_ONLY) {\r
1293 StatusBarSetStatusString (L"Access Denied - Read Only");\r
1294 FreePool (Info);\r
1295 FreePool (FileName);\r
1296 return (EFI_SUCCESS);\r
1297 }\r
1298 FreePool (Info);\r
1299\r
1300 //\r
1301 // ask user whether to overwrite this file\r
1302 //\r
1303 Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");\r
1304 if (EFI_ERROR (Status)) {\r
1305 SHELL_FREE_NON_NULL (FileName);\r
1306 return Status;\r
1307 }\r
1308\r
1309 Status = InputBarSetStringSize (1);\r
1310 if (EFI_ERROR (Status)) {\r
1311 SHELL_FREE_NON_NULL (FileName);\r
1312 return Status;\r
1313 }\r
1314\r
1315 while (TRUE) {\r
1316 Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);\r
1317 StatusBarSetRefresh();\r
1318\r
1319 //\r
1320 // ESC pressed\r
1321 //\r
1322 if (Status == EFI_NOT_READY) {\r
1323 SHELL_FREE_NON_NULL (FileName);\r
1324 return EFI_SUCCESS;\r
1325 }\r
1326\r
1327 switch (InputBarGetString()[0]) {\r
1328 case L'y':\r
1329 case L'Y':\r
1330 break;\r
1331\r
1332 case L'n':\r
1333 case L'N':\r
1334 case L'c':\r
1335 case L'C':\r
1336 SHELL_FREE_NON_NULL (FileName);\r
1337 return EFI_SUCCESS;\r
1338 } // end switch\r
1339 } // while (!done)\r
1340 } // file does exist\r
1341 } // if old file name same\r
1342\r
1343 //\r
1344 // save file to disk with specified name\r
1345 //\r
1346 FileBufferSetModified();\r
1347 Status = FileBufferSave (FileName);\r
1348 SHELL_FREE_NON_NULL (FileName);\r
1349\r
1350 return Status;\r
1351}\r
1352\r
5a2beb74 1353/**\r
feccc28a 1354 Show help information for the editor.\r
632820d1 1355\r
5a2beb74 1356 @retval EFI_SUCCESS The operation was successful.\r
1357**/\r
1358EFI_STATUS\r
1359MainCommandDisplayHelp (\r
1360 VOID\r
1361 )\r
1362{\r
feccc28a 1363 INT32 CurrentLine;\r
1364 CHAR16 *InfoString;\r
1365 EFI_INPUT_KEY Key;\r
5a2beb74 1366 \r
feccc28a 1367 //\r
5a2beb74 1368 // print helpInfo \r
feccc28a 1369 //\r
5a2beb74 1370 for (CurrentLine = 0; 0 != MainMenuHelpInfo[CurrentLine]; CurrentLine++) {\r
1371 InfoString = HiiGetString(gShellDebug1HiiHandle, MainMenuHelpInfo[CurrentLine], NULL);\r
feccc28a 1372 ShellPrintEx (0, CurrentLine+1, L"%E%s%N", InfoString); \r
5a2beb74 1373 }\r
1374 \r
feccc28a 1375 //\r
5a2beb74 1376 // scan for ctrl+w\r
feccc28a 1377 //\r
5a2beb74 1378 do {\r
1379 gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
1380 } while(SCAN_CONTROL_W != Key.UnicodeChar); \r
632820d1 1381\r
feccc28a 1382 //\r
5a2beb74 1383 // update screen with file buffer's info\r
feccc28a 1384 //\r
5a2beb74 1385 FileBufferRestorePosition ();\r
1386 FileBufferNeedRefresh = TRUE;\r
1387 FileBufferOnlyLineNeedRefresh = FALSE;\r
1388 FileBufferRefresh (); \r
632820d1 1389\r
5a2beb74 1390 return EFI_SUCCESS;\r
1391}\r
632820d1 1392\r
5a2beb74 1393EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors;\r
1394INTN OriginalMode;\r
632820d1 1395\r
632820d1 1396\r
1397//\r
1398// basic initialization for MainEditor\r
1399//\r
1400EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {\r
1401 &FileBuffer,\r
1402 {\r
ce68d3bc 1403 {0, 0}\r
632820d1 1404 },\r
1405 {\r
1406 0,\r
1407 0\r
1408 },\r
1409 NULL,\r
1410 FALSE,\r
1411 NULL\r
1412};\r
1413\r
1414/**\r
1415 The initialization function for MainEditor.\r
1416\r
1417 @retval EFI_SUCCESS The operation was successful.\r
1418 @retval EFI_LOAD_ERROR A load error occured.\r
1419**/\r
1420EFI_STATUS\r
1421EFIAPI\r
1422MainEditorInit (\r
1423 VOID\r
1424 )\r
1425{\r
1426 EFI_STATUS Status;\r
1427 EFI_HANDLE *HandleBuffer;\r
1428 UINTN HandleCount;\r
1429 UINTN Index;\r
1430\r
1431 //\r
1432 // basic initialization\r
1433 //\r
1434 CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor));\r
1435\r
1436 //\r
1437 // set screen attributes\r
1438 //\r
1439 MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;\r
1440\r
1441 MainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);\r
1442 OriginalColors = MainEditor.ColorAttributes.Colors;\r
1443\r
1444 OriginalMode = gST->ConOut->Mode->Mode;\r
1445\r
1446 //\r
1447 // query screen size\r
1448 //\r
1449 gST->ConOut->QueryMode (\r
1450 gST->ConOut,\r
1451 gST->ConOut->Mode->Mode,\r
1452 &(MainEditor.ScreenSize.Column),\r
1453 &(MainEditor.ScreenSize.Row)\r
1454 );\r
1455\r
1456 //\r
1457 // Find mouse in System Table ConsoleInHandle\r
1458 //\r
1459 Status = gBS->HandleProtocol (\r
1460 gST->ConIn,\r
1461 &gEfiSimplePointerProtocolGuid,\r
1462 (VOID**)&MainEditor.MouseInterface\r
1463 );\r
1464 if (EFI_ERROR (Status)) {\r
1465 //\r
1466 // If there is no Simple Pointer Protocol on System Table\r
1467 //\r
1468 HandleBuffer = NULL;\r
1469 MainEditor.MouseInterface = NULL;\r
1470 Status = gBS->LocateHandleBuffer (\r
1471 ByProtocol,\r
1472 &gEfiSimplePointerProtocolGuid,\r
1473 NULL,\r
1474 &HandleCount,\r
1475 &HandleBuffer\r
1476 );\r
1477 if (!EFI_ERROR (Status) && HandleCount > 0) {\r
1478 //\r
1479 // Try to find the first available mouse device\r
1480 //\r
1481 for (Index = 0; Index < HandleCount; Index++) {\r
1482 Status = gBS->HandleProtocol (\r
1483 HandleBuffer[Index],\r
1484 &gEfiSimplePointerProtocolGuid,\r
1485 (VOID**)&MainEditor.MouseInterface\r
1486 );\r
1487 if (!EFI_ERROR (Status)) {\r
1488 break;\r
1489 }\r
1490 }\r
1491 }\r
1492 if (HandleBuffer != NULL) {\r
1493 FreePool (HandleBuffer);\r
1494 }\r
1495 }\r
1496\r
1497 if (!EFI_ERROR (Status) && MainEditor.MouseInterface != NULL) {\r
1498 MainEditor.MouseAccumulatorX = 0;\r
1499 MainEditor.MouseAccumulatorY = 0;\r
1500 MainEditor.MouseSupported = TRUE;\r
1501 }\r
1502\r
1503 //\r
1504 // below will call the five components' init function\r
1505 //\r
caa6c0cc 1506 Status = MainTitleBarInit (L"UEFI EDIT");\r
632820d1 1507 if (EFI_ERROR (Status)) {\r
1508 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle);\r
1509 return EFI_LOAD_ERROR;\r
1510 }\r
1511\r
5a2beb74 1512 Status = ControlHotKeyInit (MainControlBasedMenuFunctions);\r
632820d1 1513 Status = MenuBarInit (MainMenuItems);\r
1514 if (EFI_ERROR (Status)) {\r
1515 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle);\r
1516 return EFI_LOAD_ERROR;\r
1517 }\r
1518\r
1519 Status = StatusBarInit ();\r
1520 if (EFI_ERROR (Status)) {\r
1521 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle);\r
1522 return EFI_LOAD_ERROR;\r
1523 }\r
1524\r
1525 InputBarInit ();\r
1526\r
1527 Status = FileBufferInit ();\r
1528 if (EFI_ERROR (Status)) {\r
1529 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle);\r
1530 return EFI_LOAD_ERROR;\r
1531 }\r
1532 //\r
1533 // clear whole screen and enable cursor\r
1534 //\r
1535 gST->ConOut->ClearScreen (gST->ConOut);\r
1536 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1537\r
1538 //\r
1539 // initialize EditorFirst and EditorExit\r
1540 //\r
1541 EditorFirst = TRUE;\r
1542 EditorExit = FALSE;\r
1543 EditorMouseAction = FALSE;\r
1544\r
1545 return EFI_SUCCESS;\r
1546}\r
1547\r
1548/**\r
1549 The cleanup function for MainEditor.\r
1550\r
1551 @retval EFI_SUCCESS The operation was successful.\r
1552 @retval EFI_LOAD_ERROR A load error occured.\r
1553**/\r
1554EFI_STATUS\r
1555EFIAPI\r
1556MainEditorCleanup (\r
1557 VOID\r
1558 )\r
1559{\r
1560 EFI_STATUS Status;\r
1561\r
1562 //\r
1563 // call the five components' cleanup function\r
1564 // if error, do not exit\r
1565 // just print some warning\r
1566 //\r
1567 MainTitleBarCleanup();\r
1568 StatusBarCleanup();\r
1569 InputBarCleanup();\r
1570 MenuBarCleanup ();\r
1571\r
1572 Status = FileBufferCleanup ();\r
1573 if (EFI_ERROR (Status)) {\r
1574 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle);\r
1575 }\r
1576 //\r
1577 // restore old mode\r
1578 //\r
1579 if (OriginalMode != gST->ConOut->Mode->Mode) {\r
1580 gST->ConOut->SetMode (gST->ConOut, OriginalMode);\r
1581 }\r
1582 //\r
1583 // restore old screen color\r
1584 //\r
1585 gST->ConOut->SetAttribute (\r
1586 gST->ConOut,\r
1587 EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background)\r
1588 );\r
1589\r
1590 gST->ConOut->ClearScreen (gST->ConOut);\r
1591\r
1592 return EFI_SUCCESS;\r
1593}\r
1594\r
1595/**\r
1596 Refresh the main editor component.\r
1597**/\r
1598VOID\r
1599EFIAPI\r
1600MainEditorRefresh (\r
1601 VOID\r
1602 )\r
1603{\r
1604 //\r
1605 // The Stall value is from experience. NOT from spec. avoids 'flicker'\r
1606 //\r
1607 gBS->Stall (50);\r
1608\r
1609 //\r
1610 // call the components refresh function\r
1611 //\r
1612 if (EditorFirst \r
1613 || StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0 \r
1614 || FileBufferBackupVar.FileType != FileBuffer.FileType \r
1615 || FileBufferBackupVar.FileModified != FileBuffer.FileModified \r
1616 || FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly) {\r
1617\r
980d554e 1618 MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);\r
632820d1 1619 FileBufferRestorePosition ();\r
1620 FileBufferRefresh ();\r
1621 }\r
1622 if (EditorFirst\r
1623 || FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row \r
1624 || FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column \r
1625 || FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert\r
1626 || StatusBarGetRefresh()) {\r
1627\r
1628 StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert);\r
1629 FileBufferRestorePosition ();\r
1630 FileBufferRefresh ();\r
1631 }\r
1632\r
1633 if (EditorFirst) {\r
632820d1 1634 FileBufferRestorePosition ();\r
1635 }\r
1636\r
1637 //\r
1638 // EditorFirst is now set to FALSE\r
1639 //\r
1640 EditorFirst = FALSE;\r
1641}\r
1642\r
1643/**\r
1644 Get's the resultant location of the cursor based on the relative movement of the Mouse.\r
1645\r
1646 @param[in] GuidX The relative mouse movement.\r
1647\r
1648 @return The X location of the mouse.\r
1649**/\r
1650INT32\r
1651EFIAPI\r
1652GetTextX (\r
1653 IN INT32 GuidX\r
1654 )\r
1655{\r
1656 INT32 Gap;\r
1657\r
1658 MainEditor.MouseAccumulatorX += GuidX;\r
1659 Gap = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);\r
1660 MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);\r
1661 MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32) MainEditor.ScreenSize.Column;\r
1662 return Gap;\r
1663}\r
1664\r
1665/**\r
1666 Get's the resultant location of the cursor based on the relative movement of the Mouse.\r
1667\r
1668 @param[in] GuidY The relative mouse movement.\r
1669\r
1670 @return The Y location of the mouse.\r
1671**/\r
1672INT32\r
1673EFIAPI\r
1674GetTextY (\r
1675 IN INT32 GuidY\r
1676 )\r
1677{\r
1678 INT32 Gap;\r
1679\r
1680 MainEditor.MouseAccumulatorY += GuidY;\r
1681 Gap = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);\r
1682 MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);\r
1683 MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32) MainEditor.ScreenSize.Row;\r
1684\r
1685 return Gap;\r
1686}\r
1687\r
1688/**\r
1689 Support mouse movement. Move the cursor.\r
1690\r
1691 @param[in] MouseState The current mouse state.\r
1692\r
1693 @retval EFI_SUCCESS The operation was successful.\r
1694 @retval EFI_NOT_FOUND There was no mouse support found.\r
1695**/\r
632820d1 1696EFI_STATUS\r
1697EFIAPI\r
1698MainEditorHandleMouseInput (\r
1699 IN EFI_SIMPLE_POINTER_STATE MouseState\r
1700 )\r
1701{\r
1702\r
1703 INT32 TextX;\r
1704 INT32 TextY;\r
1705 UINTN FRow;\r
1706 UINTN FCol;\r
1707\r
1708 LIST_ENTRY *Link;\r
1709 EFI_EDITOR_LINE *Line;\r
1710\r
1711 UINTN Index;\r
1712 BOOLEAN Action;\r
1713\r
1714 //\r
1715 // mouse action means:\r
1716 // mouse movement\r
1717 // mouse left button\r
1718 //\r
1719 Action = FALSE;\r
1720\r
1721 //\r
1722 // have mouse movement\r
1723 //\r
1724 if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {\r
1725 //\r
1726 // handle\r
1727 //\r
1728 TextX = GetTextX (MouseState.RelativeMovementX);\r
1729 TextY = GetTextY (MouseState.RelativeMovementY);\r
1730\r
1731 FileBufferAdjustMousePosition (TextX, TextY);\r
1732\r
1733 Action = TRUE;\r
1734\r
1735 }\r
1736\r
1737 //\r
1738 // if left button pushed down\r
1739 //\r
1740 if (MouseState.LeftButton) {\r
1741\r
1742 FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1;\r
1743\r
1744 FRow = MainEditor.FileBuffer->FilePosition.Row +\r
1745 MainEditor.FileBuffer->MousePosition.Row -\r
1746 MainEditor.FileBuffer->DisplayPosition.Row;\r
1747\r
1748 //\r
1749 // beyond the file line length\r
1750 //\r
1751 if (MainEditor.FileBuffer->NumLines < FRow) {\r
1752 FRow = MainEditor.FileBuffer->NumLines;\r
1753 }\r
1754\r
1755 Link = MainEditor.FileBuffer->ListHead->ForwardLink;\r
1756 for (Index = 0; Index < FRow - 1; Index++) {\r
1757 Link = Link->ForwardLink;\r
1758 }\r
1759\r
1760 Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);\r
1761\r
1762 //\r
1763 // beyond the line's column length\r
1764 //\r
1765 if (FCol > Line->Size + 1) {\r
1766 FCol = Line->Size + 1;\r
1767 }\r
1768\r
1769 FileBufferMovePosition (FRow, FCol);\r
1770\r
1771 MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row;\r
1772\r
1773 MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column;\r
1774\r
1775 Action = TRUE;\r
1776 }\r
1777 //\r
1778 // mouse has action\r
1779 //\r
1780 if (Action) {\r
1781 return EFI_SUCCESS;\r
1782 }\r
1783\r
1784 //\r
1785 // no mouse action\r
1786 //\r
1787 return EFI_NOT_FOUND;\r
1788}\r
1789\r
1790/**\r
1791 Handle user key input. This routes to other functions for the actions.\r
1792\r
1793 @retval EFI_SUCCESS The operation was successful.\r
1794 @retval EFI_LOAD_ERROR A load error occured.\r
1795 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1796**/\r
1797EFI_STATUS\r
1798EFIAPI\r
1799MainEditorKeyInput (\r
1800 VOID\r
1801 )\r
1802{\r
1803 EFI_INPUT_KEY Key;\r
1804 EFI_STATUS Status;\r
1805 EFI_SIMPLE_POINTER_STATE MouseState;\r
1806\r
1807 do {\r
1808\r
1809 Status = EFI_SUCCESS;\r
1810 EditorMouseAction = FALSE;\r
1811\r
1812 //\r
1813 // backup some key elements, so that can aVOID some refresh work\r
1814 //\r
1815 MainEditorBackup ();\r
1816\r
1817 //\r
1818 // change priority of checking mouse/keyboard activity dynamically\r
1819 // so prevent starvation of keyboard.\r
1820 // if last time, mouse moves then this time check keyboard\r
1821 //\r
1822 if (MainEditor.MouseSupported) {\r
1823 Status = MainEditor.MouseInterface->GetState (\r
1824 MainEditor.MouseInterface,\r
1825 &MouseState\r
1826 );\r
1827 if (!EFI_ERROR (Status)) {\r
1828\r
1829 Status = MainEditorHandleMouseInput (MouseState);\r
1830\r
1831 if (!EFI_ERROR (Status)) {\r
1832 EditorMouseAction = TRUE;\r
1833 FileBufferMouseNeedRefresh = TRUE;\r
1834 } else if (Status == EFI_LOAD_ERROR) {\r
1835 StatusBarSetStatusString (L"Invalid Mouse Movement ");\r
1836 }\r
1837 }\r
1838 }\r
1839\r
1840 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
1841 if (!EFI_ERROR (Status)) {\r
1842 //\r
1843 // dispatch to different components' key handling function\r
1844 // so not everywhere has to set this variable\r
1845 //\r
1846 FileBufferMouseNeedRefresh = TRUE;\r
1847 //\r
1848 // clear previous status string\r
1849 //\r
1850 StatusBarSetRefresh();\r
1851\r
1852 //\r
1853 // dispatch to different components' key handling function\r
1854 //\r
5a2beb74 1855 if (EFI_NOT_FOUND != MenuBarDispatchControlHotKey(&Key)) {\r
1856 Status = EFI_SUCCESS;\r
1857 } else if ((Key.ScanCode == SCAN_NULL) || ((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {\r
632820d1 1858 Status = FileBufferHandleInput (&Key);\r
1859 } else if ((Key.ScanCode >= SCAN_F1) && (Key.ScanCode <= SCAN_F12)) {\r
1860 Status = MenuBarDispatchFunctionKey (&Key);\r
1861 } else {\r
1862 StatusBarSetStatusString (L"Unknown Command");\r
5a2beb74 1863 FileBufferMouseNeedRefresh = FALSE; \r
632820d1 1864 }\r
5a2beb74 1865 \r
632820d1 1866 if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {\r
1867 //\r
1868 // not already has some error status\r
1869 //\r
1870 if (StatusBarGetString() != NULL && StrCmp (L"", StatusBarGetString()) == 0) {\r
1871 StatusBarSetStatusString (L"Disk Error. Try Again");\r
1872 }\r
1873 }\r
1874\r
1875 }\r
1876 //\r
1877 // after handling, refresh editor\r
1878 //\r
1879 MainEditorRefresh ();\r
1880\r
1881 } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);\r
1882\r
1883 return Status;\r
1884}\r
1885\r
1886/**\r
1887 Set clipboard\r
1888\r
1889 @param[in] Line A pointer to the line to be set to clipboard\r
1890\r
1891 @retval EFI_SUCCESS The operation was successful.\r
1892 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1893**/\r
1894EFI_STATUS\r
1895EFIAPI\r
1896MainEditorSetCutLine (\r
1897 EFI_EDITOR_LINE *Line\r
1898 )\r
1899{\r
1900 if (Line == NULL) {\r
1901 return EFI_SUCCESS;\r
1902 }\r
1903\r
1904 if (MainEditor.CutLine != NULL) {\r
1905 //\r
1906 // free the old clipboard\r
1907 //\r
1908 LineFree (MainEditor.CutLine);\r
1909 }\r
1910 //\r
1911 // duplicate the line to clipboard\r
1912 //\r
1913 MainEditor.CutLine = LineDup (Line);\r
1914 if (MainEditor.CutLine == NULL) {\r
1915 return EFI_OUT_OF_RESOURCES;\r
1916 }\r
1917\r
1918 return EFI_SUCCESS;\r
1919}\r
1920\r
1921/**\r
1922 Backup function for MainEditor\r
1923\r
1924 @retval EFI_SUCCESS The operation was successful.\r
1925**/\r
1926EFI_STATUS\r
1927EFIAPI\r
1928MainEditorBackup (\r
1929 VOID\r
1930 )\r
1931{\r
1932 FileBufferBackup ();\r
1933 \r
1934 return EFI_SUCCESS;\r
1935}\r