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