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