Comment's added and fixed.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / MainHexEditor.c
1 /** @file\r
2     Defines the Main Editor data type - \r
3      - Global variables \r
4      - Instances of the other objects of the editor\r
5      - Main Interfaces\r
6   \r
7   Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>\r
8   This program and the accompanying materials\r
9   are licensed and made available under the terms and conditions of the BSD License\r
10   which accompanies this distribution.  The full text of the license may be found at\r
11   http://opensource.org/licenses/bsd-license.php\r
12 \r
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15 \r
16 **/\r
17 \r
18 #include "HexEditor.h"\r
19 #include "EditStatusBar.h"\r
20 #include "EditInputBar.h"\r
21 \r
22 HEFI_EDITOR_COLOR_ATTRIBUTES    HOriginalColors;\r
23 INTN                            HOriginalMode;\r
24 \r
25 //\r
26 // the first time editor launch\r
27 //\r
28 BOOLEAN                         HEditorFirst;\r
29 \r
30 //\r
31 // it's time editor should exit\r
32 //\r
33 BOOLEAN                         HEditorExit;\r
34 \r
35 BOOLEAN                         HEditorMouseAction;\r
36 \r
37 extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
38 extern HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;\r
39 \r
40 extern HEFI_EDITOR_CLIPBOARD    HClipBoard;\r
41 \r
42 extern BOOLEAN                  HBufferImageMouseNeedRefresh;\r
43 extern BOOLEAN                  HBufferImageNeedRefresh;\r
44 extern BOOLEAN                  HBufferImageOnlyLineNeedRefresh;\r
45 \r
46 HEFI_EDITOR_GLOBAL_EDITOR       HMainEditor;\r
47 HEFI_EDITOR_GLOBAL_EDITOR       HMainEditorBackupVar;\r
48 \r
49 //\r
50 // basic initialization for MainEditor\r
51 //\r
52 HEFI_EDITOR_GLOBAL_EDITOR       HMainEditorConst = {\r
53   &HBufferImage,\r
54   &HClipBoard,\r
55   {\r
56     0,\r
57     0\r
58   },\r
59   {\r
60     0,\r
61     0\r
62   },\r
63   FALSE,\r
64   NULL,\r
65   0,\r
66   0,\r
67   1,\r
68   1\r
69 };\r
70 \r
71 EFI_STATUS\r
72 HMainCommandGoToOffset (\r
73   VOID\r
74   )\r
75 /*++\r
76 \r
77 Routine Description: \r
78 \r
79   move cursor to specified lines\r
80 \r
81 Arguments:  \r
82 \r
83   None\r
84 \r
85 Returns:  \r
86 \r
87   EFI_SUCCESS\r
88 \r
89 --*/\r
90 {\r
91   UINTN       Size;\r
92   UINT64      Offset;\r
93   EFI_STATUS  Status;\r
94   UINTN       FRow;\r
95   UINTN       FCol;\r
96 \r
97   //\r
98   // variable initialization\r
99   //\r
100   Size    = 0;\r
101   Offset  = 0;\r
102   FRow    = 0;\r
103   FCol    = 0;\r
104 \r
105   //\r
106   // get offset\r
107   //\r
108   Status = InputBarSetPrompt (L"Go To Offset: ");\r
109   if (EFI_ERROR (Status)) {\r
110     return Status;\r
111   }\r
112 \r
113   Status = InputBarSetStringSize (8);\r
114   if (EFI_ERROR (Status)) {\r
115     return Status;\r
116   }\r
117 \r
118   while (1) {\r
119     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
120 \r
121     //\r
122     // ESC pressed\r
123     //\r
124     if (Status == EFI_NOT_READY) {\r
125 \r
126       return EFI_SUCCESS;\r
127     }\r
128     //\r
129     // THE input string length should > 0\r
130     //\r
131     if (StrLen (InputBarGetString()) > 0) {\r
132       Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);\r
133       if (EFI_ERROR (Status)) {\r
134         StatusBarSetStatusString (L"Invalid Offset");\r
135         return EFI_SUCCESS;\r
136       }\r
137 \r
138       break;\r
139     }\r
140   }\r
141 \r
142   Size = HBufferImageGetTotalSize ();\r
143   if (Offset >= Size) {\r
144     StatusBarSetStatusString (L"Invalid Offset");\r
145     return EFI_SUCCESS;\r
146   }\r
147 \r
148   FRow  = (UINTN)DivU64x32(Offset , 0x10) + 1;\r
149   FCol  = (UINTN)ModU64x32(Offset , 0x10) + 1;\r
150 \r
151   HBufferImageMovePosition (FRow, FCol, TRUE);\r
152 \r
153   HBufferImageNeedRefresh         = TRUE;\r
154   HBufferImageOnlyLineNeedRefresh = FALSE;\r
155   HBufferImageMouseNeedRefresh    = TRUE;\r
156 \r
157   return EFI_SUCCESS;\r
158 }\r
159 \r
160 EFI_STATUS\r
161 HMainCommandSaveBuffer (\r
162   VOID\r
163   )\r
164 /*++\r
165 \r
166 Routine Description: \r
167 \r
168   save current opened buffer . \r
169   if is file buffer, you can save to current file name or \r
170   save to another file name\r
171 \r
172 Arguments:  \r
173 \r
174   None\r
175 \r
176 Returns:  \r
177 \r
178   EFI_SUCCESS\r
179   EFI_OUT_OF_RESOURCES\r
180   EFI_LOAD_ERROR\r
181 \r
182 --*/\r
183 {\r
184   EFI_STATUS          Status;\r
185   BOOLEAN             Done;\r
186   CHAR16              *FileName;\r
187   BOOLEAN             OldFile;\r
188   CHAR16              *Str;\r
189   EFI_FILE_INFO       *Info;\r
190   SHELL_FILE_HANDLE   ShellFileHandle;\r
191 \r
192   if (HMainEditor.BufferImage->BufferType != FileTypeFileBuffer) {\r
193     if (HMainEditor.BufferImage->Modified == FALSE) {\r
194       return EFI_SUCCESS;\r
195     }\r
196 \r
197     Status = InputBarSetPrompt (L"Dangerous to save disk/mem buffer. Save (Yes/No/Cancel) ? ");\r
198     if (EFI_ERROR (Status)) {\r
199       return Status;\r
200     }\r
201     //\r
202     // the answer is just one character\r
203     //\r
204     Status = InputBarSetStringSize (1);\r
205     if (EFI_ERROR (Status)) {\r
206       return Status;\r
207     }\r
208     //\r
209     // loop for user's answer\r
210     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
211     //\r
212     while (1) {\r
213       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
214 \r
215       //\r
216       // ESC pressed\r
217       //\r
218       if (Status == EFI_NOT_READY) {\r
219         return EFI_SUCCESS;\r
220       }\r
221 \r
222       switch (InputBarGetString()[0]) {\r
223       case L'y':\r
224       case L'Y':\r
225         //\r
226         // want to save this buffer first\r
227         //\r
228         Status = HBufferImageSave (\r
229                   NULL,\r
230                   HMainEditor.BufferImage->DiskImage->Name,\r
231                   HMainEditor.BufferImage->DiskImage->Offset,\r
232                   HMainEditor.BufferImage->DiskImage->Size,\r
233                   HMainEditor.BufferImage->MemImage->Offset,\r
234                   HMainEditor.BufferImage->MemImage->Size,\r
235                   HMainEditor.BufferImage->BufferType\r
236                   );\r
237 \r
238         if (EFI_ERROR (Status)) {\r
239           StatusBarSetStatusString (L"BufferSave: Problems Writing");\r
240           return Status;\r
241         }\r
242 \r
243         return EFI_SUCCESS;\r
244 \r
245       case L'n':\r
246       case L'N':\r
247         //\r
248         // the file won't be saved\r
249         //\r
250         return EFI_SUCCESS;\r
251         break;\r
252 \r
253       case L'c':\r
254       case L'C':\r
255         return EFI_SUCCESS;\r
256       }\r
257       //\r
258       // end of switch\r
259       //\r
260     }\r
261     //\r
262     // ENDOF WHILE\r
263     //\r
264   }\r
265   //\r
266   // ENDOF != FILEBUFFER\r
267   //\r
268   // This command will save currently opened file to disk.\r
269   // You can choose save to another file name or just save to\r
270   // current file name.\r
271   // Below is the scenario of Save File command: (\r
272   //    Suppose the old file name is A )\r
273   // 1. An Input Bar will be prompted:    "File To Save: [ old file name]"\r
274   //    IF user press ESC, Save File command ends .\r
275   //    IF user press Enter, input file name will be A.\r
276   //    IF user inputs a new file name B,  input file name will be B.\r
277   //\r
278   // 2. IF input file name is A, go to do Step 3.\r
279   //    IF input file name is B, go to do Step 4.\r
280   //\r
281   // 3. IF A is read only, Status Bar will show "Access Denied"\r
282   //       and Save File commands ends.\r
283   //    IF A is not read only, save file buffer to disk\r
284   //       and remove Modified flag in Title Bar , then Save File command ends.\r
285   //\r
286   // 4. IF B does not exist, create this file and save file buffer to it.\r
287   //       Go to do Step 7.\r
288   //    IF B exits, do Step 5.\r
289   //\r
290   // 5. An Input Bar will be prompted:\r
291   //       "File Exists. Overwrite ( Yes/No/Cancel ) ?"\r
292   //      IF user press 'y' or 'Y', do Step 6.\r
293   //      IF user press 'n' or 'N', Save File commands ends.\r
294   //      IF user press 'c' or 'C' or ESC, Save File commands ends.\r
295   //\r
296   // 6. IF B is a read-only file, Status Bar will show "Access Denied"\r
297   //       and Save File commands ends.\r
298   //    IF B can be read and write, save file buffer to B.\r
299   //\r
300   // 7. Update File Name field in Title Bar to B\r
301   //       and remove the Modified flag in Title Bar.\r
302   //\r
303   Str = CatSPrint(NULL, \r
304           L"File to Save: [%s]",\r
305           HMainEditor.BufferImage->FileImage->FileName\r
306           );\r
307   if (Str == NULL) {\r
308     return EFI_OUT_OF_RESOURCES;\r
309   }\r
310 \r
311   if (StrLen (Str) >= 50) {\r
312     //\r
313     // replace the long file name with "..."\r
314     //\r
315     Str[46] = L'.';\r
316     Str[47] = L'.';\r
317     Str[48] = L'.';\r
318     Str[49] = L']';\r
319     Str[50] = L'\0';\r
320   }\r
321 \r
322   Status = InputBarSetPrompt (Str);\r
323   if (EFI_ERROR (Status)) {\r
324     return Status;\r
325   }\r
326 \r
327   Status = InputBarSetStringSize (100);\r
328   if (EFI_ERROR (Status)) {\r
329     return Status;\r
330   }\r
331   //\r
332   // get new file name\r
333   //\r
334   Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
335 \r
336   //\r
337   // if user pressed ESC\r
338   //\r
339   if (Status == EFI_NOT_READY) {\r
340     SHELL_FREE_NON_NULL (Str);\r
341     return EFI_SUCCESS;\r
342   }\r
343 \r
344   SHELL_FREE_NON_NULL (Str);\r
345 \r
346   //\r
347   // if just enter pressed, so think save to current file name\r
348   //\r
349   if (StrLen (InputBarGetString()) == 0) {\r
350     FileName = CatSPrint(NULL, \r
351                 L"%s",\r
352                 HMainEditor.BufferImage->FileImage->FileName\r
353                 );\r
354   } else {\r
355     FileName = CatSPrint(NULL, L"%s", InputBarGetString());\r
356   }\r
357 \r
358   if (FileName == NULL) {\r
359     return EFI_OUT_OF_RESOURCES;\r
360   }\r
361 \r
362   if (!IsValidFileName (FileName)) {\r
363     StatusBarSetStatusString (L"Invalid File Name");\r
364     SHELL_FREE_NON_NULL (FileName);\r
365     return EFI_SUCCESS;\r
366   }\r
367 \r
368   OldFile = FALSE;\r
369 \r
370   //\r
371   // save to the old file\r
372   //\r
373   if (StringNoCaseCompare (\r
374         &FileName,\r
375         &HMainEditor.BufferImage->FileImage->FileName\r
376         ) == 0) {\r
377     OldFile = TRUE;\r
378   }\r
379 \r
380   if (OldFile) {\r
381     //\r
382     // if the file is read only, so can not write back to it.\r
383     //\r
384     if (HMainEditor.BufferImage->FileImage->ReadOnly == TRUE) {\r
385       StatusBarSetStatusString (L"Access Denied");\r
386       SHELL_FREE_NON_NULL (FileName);\r
387       return EFI_SUCCESS;\r
388     }\r
389   } else {\r
390     Status = ShellOpenFileByName (FileName, &ShellFileHandle, EFI_FILE_MODE_READ, 0);\r
391 \r
392     if (!EFI_ERROR (Status)) {\r
393 \r
394       Info = ShellGetFileInfo(ShellFileHandle);\r
395 \r
396       ShellCloseFile(&ShellFileHandle);\r
397       //\r
398       // check if read only\r
399       //\r
400       if (Info->Attribute & EFI_FILE_READ_ONLY) {\r
401         StatusBarSetStatusString (L"Access Denied");\r
402         SHELL_FREE_NON_NULL (FileName);\r
403         return EFI_SUCCESS;\r
404       } \r
405 \r
406       SHELL_FREE_NON_NULL(Info);\r
407       //\r
408       // ask user whether to overwrite this file\r
409       //\r
410       Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");\r
411       if (EFI_ERROR (Status)) {\r
412         SHELL_FREE_NON_NULL (FileName);\r
413         return Status;\r
414       }\r
415 \r
416       Status = InputBarSetStringSize (1);\r
417       if (EFI_ERROR (Status)) {\r
418         SHELL_FREE_NON_NULL (FileName);\r
419         return Status;\r
420       }\r
421 \r
422       Done = FALSE;\r
423       while (!Done) {\r
424         Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
425 \r
426         if (Status == EFI_NOT_READY) {\r
427           SHELL_FREE_NON_NULL (FileName);\r
428           return EFI_SUCCESS;\r
429         }\r
430 \r
431         switch (InputBarGetString()[0]) {\r
432         case L'y':\r
433         case L'Y':\r
434           Done = TRUE;\r
435           break;\r
436         case L'n':\r
437         case L'N':\r
438           SHELL_FREE_NON_NULL (FileName);\r
439           return EFI_SUCCESS;\r
440         case L'c':\r
441         case L'C':\r
442           SHELL_FREE_NON_NULL (FileName);\r
443           return EFI_SUCCESS;\r
444         } // switch\r
445       } // while\r
446     } // if opened existing file\r
447   } // if OldFile\r
448   \r
449   //\r
450   // save file back to disk\r
451   //\r
452   Status = HBufferImageSave (\r
453             FileName,\r
454             HMainEditor.BufferImage->DiskImage->Name,\r
455             HMainEditor.BufferImage->DiskImage->Offset,\r
456             HMainEditor.BufferImage->DiskImage->Size,\r
457             HMainEditor.BufferImage->MemImage->Offset,\r
458             HMainEditor.BufferImage->MemImage->Size,\r
459             FileTypeFileBuffer\r
460             );\r
461   SHELL_FREE_NON_NULL (FileName);\r
462 \r
463   if (EFI_ERROR (Status)) {\r
464     return EFI_LOAD_ERROR;\r
465   }\r
466 \r
467   return EFI_SUCCESS;\r
468 }\r
469 \r
470 EFI_STATUS\r
471 HMainCommandSelectStart (\r
472   VOID\r
473   )\r
474 /*++\r
475 \r
476 Routine Description: \r
477 \r
478   Load a disk buffer editor\r
479 \r
480 Arguments:  \r
481 \r
482   None\r
483 \r
484 Returns:  \r
485 \r
486    EFI_SUCCESS\r
487    EFI_LOAD_ERROR\r
488    EFI_OUT_OF_RESOURCES\r
489 \r
490 --*/\r
491 {\r
492   UINTN Start;\r
493 \r
494   Start = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;\r
495 \r
496   //\r
497   // last line\r
498   //\r
499   if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {\r
500     if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {\r
501       StatusBarSetStatusString (L"Invalid Block Start");\r
502       return EFI_LOAD_ERROR;\r
503     }\r
504   }\r
505 \r
506   if (HMainEditor.SelectEnd != 0 && Start > HMainEditor.SelectEnd) {\r
507     StatusBarSetStatusString (L"Invalid Block Start");\r
508     return EFI_LOAD_ERROR;\r
509   }\r
510 \r
511   HMainEditor.SelectStart = Start;\r
512 \r
513   HBufferImageNeedRefresh = TRUE;\r
514 \r
515   return EFI_SUCCESS;\r
516 }\r
517 \r
518 EFI_STATUS\r
519 HMainCommandSelectEnd (\r
520   VOID\r
521   )\r
522 /*++\r
523 \r
524 Routine Description: \r
525 \r
526   Load a disk buffer editor\r
527 \r
528 Arguments:  \r
529 \r
530   None\r
531 \r
532 Returns:  \r
533 \r
534    EFI_SUCCESS\r
535    EFI_LOAD_ERROR\r
536    EFI_OUT_OF_RESOURCES\r
537 \r
538 --*/\r
539 {\r
540   UINTN End;\r
541 \r
542   End = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;\r
543 \r
544   //\r
545   // last line\r
546   //\r
547   if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {\r
548     if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {\r
549       StatusBarSetStatusString (L"Invalid Block End");\r
550       return EFI_LOAD_ERROR;\r
551     }\r
552   }\r
553 \r
554   if (HMainEditor.SelectStart != 0 && End < HMainEditor.SelectStart) {\r
555     StatusBarSetStatusString (L"Invalid Block End");\r
556     return EFI_SUCCESS;\r
557   }\r
558 \r
559   HMainEditor.SelectEnd   = End;\r
560 \r
561   HBufferImageNeedRefresh = TRUE;\r
562 \r
563   return EFI_SUCCESS;\r
564 }\r
565 \r
566 EFI_STATUS\r
567 HMainCommandCut (\r
568   VOID\r
569   )\r
570 /*++\r
571 \r
572 Routine Description: \r
573 \r
574   cut current line to clipboard\r
575 \r
576 Arguments:  \r
577 \r
578   None\r
579 \r
580 Returns:  \r
581 \r
582   EFI_SUCCESS\r
583   EFI_OUT_OF_RESOURCES\r
584   EFI_LOAD_ERROR\r
585 \r
586 --*/\r
587 {\r
588   UINTN             Index;\r
589   HEFI_EDITOR_LINE  *Line;\r
590   LIST_ENTRY    *Link;\r
591   UINT8             *Buffer;\r
592   UINTN             Count;\r
593 \r
594   //\r
595   // not select, so not allowed to cut\r
596   //\r
597   if (HMainEditor.SelectStart == 0) {\r
598     StatusBarSetStatusString (L"No Block is Selected");\r
599     return EFI_SUCCESS;\r
600   }\r
601   //\r
602   // not select, so not allowed to cut\r
603   //\r
604   if (HMainEditor.SelectEnd == 0) {\r
605     StatusBarSetStatusString (L"No Block is Selected");\r
606     return EFI_SUCCESS;\r
607   }\r
608 \r
609   Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
610   for (Index = 0; Index < (HMainEditor.SelectEnd - 1) / 0x10; Index++) {\r
611     Link = Link->ForwardLink;\r
612   }\r
613 \r
614   Line    = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
615 \r
616   Count   = HMainEditor.SelectEnd - HMainEditor.SelectStart + 1;\r
617   Buffer  = AllocateZeroPool (Count);\r
618   if (Buffer == NULL) {\r
619     return EFI_OUT_OF_RESOURCES;\r
620   }\r
621   //\r
622   // cut the selected area\r
623   //\r
624   HBufferImageDeleteCharacterFromBuffer (\r
625     HMainEditor.SelectStart - 1,\r
626     Count,\r
627     Buffer\r
628     );\r
629 \r
630   //\r
631   // put to clipboard\r
632   //\r
633   HClipBoardSet (Buffer, Count);\r
634 \r
635   HBufferImageNeedRefresh         = TRUE;\r
636   HBufferImageOnlyLineNeedRefresh = FALSE;\r
637 \r
638   if (!HMainEditor.BufferImage->Modified) {\r
639     HMainEditor.BufferImage->Modified = TRUE;\r
640   }\r
641 \r
642   //\r
643   // now no select area\r
644   //\r
645   HMainEditor.SelectStart = 0;\r
646   HMainEditor.SelectEnd   = 0;\r
647 \r
648   return EFI_SUCCESS;\r
649 }\r
650 \r
651 EFI_STATUS\r
652 HMainCommandPaste (\r
653   VOID\r
654   )\r
655 /*++\r
656 \r
657 Routine Description: \r
658 \r
659   paste line to file buffer\r
660 \r
661 Arguments:  \r
662 \r
663   None\r
664 \r
665 Returns:  \r
666 \r
667   EFI_SUCCESS\r
668   EFI_OUT_OF_RESOURCES\r
669   EFI_LOAD_ERROR\r
670 \r
671 \r
672 --*/\r
673 {\r
674 \r
675   BOOLEAN           OnlyLineRefresh;\r
676   HEFI_EDITOR_LINE  *Line;\r
677   UINT8             *Buffer;\r
678   UINTN             Count;\r
679   UINTN             FPos;\r
680 \r
681   Count = HClipBoardGet (&Buffer);\r
682   if (Count == 0 || Buffer == NULL) {\r
683     StatusBarSetStatusString (L"Nothing to Paste");\r
684     return EFI_SUCCESS;\r
685   }\r
686 \r
687   Line            = HMainEditor.BufferImage->CurrentLine;\r
688 \r
689   OnlyLineRefresh = FALSE;\r
690   if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead && Line->Size + Count < 0x10) {\r
691     //\r
692     // is at last line, and after paste will not exceed\r
693     // so only this line need to be refreshed\r
694     //\r
695     // if after add, the line is 0x10, then will append a new line\r
696     // so the whole page will need be refreshed\r
697     //\r
698     OnlyLineRefresh = TRUE;\r
699 \r
700   }\r
701 \r
702   FPos = 0x10 * (HMainEditor.BufferImage->BufferPosition.Row - 1) + HMainEditor.BufferImage->BufferPosition.Column - 1;\r
703 \r
704   HBufferImageAddCharacterToBuffer (FPos, Count, Buffer);\r
705 \r
706   if (OnlyLineRefresh) {\r
707     HBufferImageNeedRefresh         = FALSE;\r
708     HBufferImageOnlyLineNeedRefresh = TRUE;\r
709   } else {\r
710     HBufferImageNeedRefresh         = TRUE;\r
711     HBufferImageOnlyLineNeedRefresh = FALSE;\r
712   }\r
713 \r
714   if (!HMainEditor.BufferImage->Modified) {\r
715     HMainEditor.BufferImage->Modified = TRUE;\r
716   }\r
717 \r
718   return EFI_SUCCESS;\r
719 \r
720 }\r
721 \r
722 EFI_STATUS\r
723 HMainCommandExit (\r
724   VOID\r
725   )\r
726 /*++\r
727 \r
728 Routine Description: \r
729 \r
730   exit editor\r
731 \r
732 Arguments:  \r
733 \r
734   None\r
735 \r
736 Returns:  \r
737 \r
738   EFI_SUCCESS\r
739   EFI_OUT_OF_RESOURCES\r
740   EFI_LOAD_ERROR\r
741 \r
742 --*/\r
743 {\r
744   EFI_STATUS  Status;\r
745 \r
746   //\r
747   // Below is the scenario of Exit command:\r
748   // 1. IF currently opened file is not modified, exit the editor and\r
749   //       Exit command ends.\r
750   //    IF currently opened file is modified, do Step 2\r
751   //\r
752   // 2. An Input Bar will be prompted:\r
753   //       "File modified. Save ( Yes/No/Cancel )?"\r
754   //      IF user press 'y' or 'Y', currently opened file will be saved and\r
755   //         Editor exits\r
756   //      IF user press 'n' or 'N', currently opened file will not be saved\r
757   //         and Editor exits.\r
758   //      IF user press 'c' or 'C' or ESC, Exit command ends.\r
759   //\r
760   //\r
761   // if file has been modified, so will prompt user\r
762   //       whether to save the changes\r
763   //\r
764   if (HMainEditor.BufferImage->Modified) {\r
765 \r
766     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
767     if (EFI_ERROR (Status)) {\r
768       return Status;\r
769     }\r
770 \r
771     Status = InputBarSetStringSize (1);\r
772     if (EFI_ERROR (Status)) {\r
773       return Status;\r
774     }\r
775 \r
776     while (1) {\r
777       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
778 \r
779       //\r
780       // ESC pressed\r
781       //\r
782       if (Status == EFI_NOT_READY) {\r
783         return EFI_SUCCESS;\r
784       }\r
785 \r
786       switch (InputBarGetString()[0]) {\r
787       case L'y':\r
788       case L'Y':\r
789         //\r
790         // write file back to disk\r
791         //\r
792         Status = HBufferImageSave (\r
793                   HMainEditor.BufferImage->FileImage->FileName,\r
794                   HMainEditor.BufferImage->DiskImage->Name,\r
795                   HMainEditor.BufferImage->DiskImage->Offset,\r
796                   HMainEditor.BufferImage->DiskImage->Size,\r
797                   HMainEditor.BufferImage->MemImage->Offset,\r
798                   HMainEditor.BufferImage->MemImage->Size,\r
799                   HMainEditor.BufferImage->BufferType\r
800                   );\r
801         if (!EFI_ERROR (Status)) {\r
802           HEditorExit = TRUE;\r
803         }\r
804 \r
805         return Status;\r
806 \r
807       case L'n':\r
808       case L'N':\r
809         HEditorExit = TRUE;\r
810         return EFI_SUCCESS;\r
811 \r
812       case L'c':\r
813       case L'C':\r
814         return EFI_SUCCESS;\r
815 \r
816       }\r
817     }\r
818   }\r
819 \r
820   HEditorExit = TRUE;\r
821   return EFI_SUCCESS;\r
822 \r
823 }\r
824 \r
825 EFI_STATUS\r
826 HMainCommandOpenFile (\r
827   VOID\r
828   )\r
829 /*++\r
830 \r
831 Routine Description: \r
832 \r
833   Load a file from disk to editor\r
834 \r
835 Arguments:  \r
836 \r
837   None\r
838 \r
839 Returns:  \r
840 \r
841    EFI_SUCCESS\r
842    EFI_LOAD_ERROR\r
843    EFI_OUT_OF_RESOURCES\r
844 \r
845 --*/\r
846 {\r
847   BOOLEAN                         Done;\r
848   EFI_STATUS                      Status;\r
849   EDIT_FILE_TYPE                  BufferType;\r
850 \r
851   BufferType = HMainEditor.BufferImage->BufferType;\r
852 \r
853   //\r
854   //  This command will open a file from current working directory.\r
855   //  Read-only file can also be opened. But it can not be modified.\r
856   // Below is the scenario of Open File command:\r
857   // 1. IF currently opened file has not been modified, directly go to step .\r
858   //  IF currently opened file has been modified, an Input Bar will be\r
859   //     prompted as :\r
860   //      "File Modified. Save ( Yes/No/Cancel) ?"\r
861   //          IF user press 'y' or 'Y', currently opened file will be saved.\r
862   //          IF user press 'n' or 'N', currently opened file will\r
863   //             not be saved.\r
864   //          IF user press 'c' or 'C' or ESC, Open File command ends and\r
865   //             currently opened file is still opened.\r
866   //\r
867   // 2. An Input Bar will be prompted as :  "File Name to Open: "\r
868   //      IF user press ESC, Open File command ends and\r
869   //         currently opened file is still opened.\r
870   //      Any other inputs with a Return will cause\r
871   //          currently opened file close.\r
872   //\r
873   // 3. IF user input file name is an existing file ,\r
874   //       this file will be read and opened.\r
875   //    IF user input file name is a new file, this file will be created\r
876   //       and opened. This file's type ( UNICODE or ASCII ) is the same with\r
877   //       the old file.\r
878   //\r
879   //\r
880   // if current file is modified, so you need to choose whether to\r
881   //    save it first.\r
882   //\r
883   if (HMainEditor.BufferImage->Modified) {\r
884 \r
885     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
886     if (EFI_ERROR (Status)) {\r
887       return Status;\r
888     }\r
889     //\r
890     // the answer is just one character\r
891     //\r
892     Status = InputBarSetStringSize (1);\r
893     if (EFI_ERROR (Status)) {\r
894       return Status;\r
895     }\r
896     //\r
897     // loop for user's answer\r
898     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
899     //\r
900     Done = FALSE;\r
901     while (!Done) {\r
902       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
903 \r
904       //\r
905       // ESC pressed\r
906       //\r
907       if (Status == EFI_NOT_READY) {\r
908         return EFI_SUCCESS;\r
909       }\r
910 \r
911       switch (InputBarGetString()[0]) {\r
912       case L'y':\r
913       case L'Y':\r
914         //\r
915         // want to save this buffer first\r
916         //\r
917         Status = HBufferImageSave (\r
918                   HMainEditor.BufferImage->FileImage->FileName,\r
919                   HMainEditor.BufferImage->DiskImage->Name,\r
920                   HMainEditor.BufferImage->DiskImage->Offset,\r
921                   HMainEditor.BufferImage->DiskImage->Size,\r
922                   HMainEditor.BufferImage->MemImage->Offset,\r
923                   HMainEditor.BufferImage->MemImage->Size,\r
924                   HMainEditor.BufferImage->BufferType\r
925                   );\r
926         if (EFI_ERROR (Status)) {\r
927           return Status;\r
928         }\r
929 \r
930         MainTitleBarRefresh (\r
931           HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
932           HMainEditor.BufferImage->BufferType,\r
933           HMainEditor.BufferImage->FileImage->ReadOnly,\r
934           FALSE,\r
935           HMainEditor.ScreenSize.Column,\r
936           HMainEditor.ScreenSize.Row,\r
937           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,\r
938           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size  :0\r
939           );\r
940         Done = TRUE;\r
941         break;\r
942 \r
943       case L'n':\r
944       case L'N':\r
945         //\r
946         // the file won't be saved\r
947         //\r
948         Done = TRUE;\r
949         break;\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   // TO get the open file name\r
959   //\r
960   Status = InputBarSetPrompt (L"File Name to Open: ");\r
961   if (EFI_ERROR (Status)) {\r
962     HBufferImageRead (\r
963       HMainEditor.BufferImage->FileImage->FileName,\r
964       HMainEditor.BufferImage->DiskImage->Name,\r
965       HMainEditor.BufferImage->DiskImage->Offset,\r
966       HMainEditor.BufferImage->DiskImage->Size,\r
967       HMainEditor.BufferImage->MemImage->Offset,\r
968       HMainEditor.BufferImage->MemImage->Size,\r
969       BufferType,\r
970       TRUE\r
971       );\r
972     return Status;\r
973   }\r
974 \r
975   Status = InputBarSetStringSize (100);\r
976   if (EFI_ERROR (Status)) {\r
977     Status = HBufferImageRead (\r
978               HMainEditor.BufferImage->FileImage->FileName,\r
979               HMainEditor.BufferImage->DiskImage->Name,\r
980               HMainEditor.BufferImage->DiskImage->Offset,\r
981               HMainEditor.BufferImage->DiskImage->Size,\r
982               HMainEditor.BufferImage->MemImage->Offset,\r
983               HMainEditor.BufferImage->MemImage->Size,\r
984               BufferType,\r
985               TRUE\r
986               );\r
987     return Status;\r
988   }\r
989 \r
990   while (1) {\r
991     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
992 \r
993     //\r
994     // ESC pressed\r
995     //\r
996     if (Status == EFI_NOT_READY) {\r
997       Status = HBufferImageRead (\r
998                 HMainEditor.BufferImage->FileImage->FileName,\r
999                 HMainEditor.BufferImage->DiskImage->Name,\r
1000                 HMainEditor.BufferImage->DiskImage->Offset,\r
1001                 HMainEditor.BufferImage->DiskImage->Size,\r
1002                 HMainEditor.BufferImage->MemImage->Offset,\r
1003                 HMainEditor.BufferImage->MemImage->Size,\r
1004                 BufferType,\r
1005                 TRUE\r
1006                 );\r
1007 \r
1008       return Status;\r
1009     }\r
1010     //\r
1011     // THE input string length should > 0\r
1012     //\r
1013     if (StrLen (InputBarGetString()) > 0) {\r
1014       //\r
1015       // CHECK if filename's valid\r
1016       //\r
1017       if (!IsValidFileName (InputBarGetString())) {\r
1018         HBufferImageRead (\r
1019           HMainEditor.BufferImage->FileImage->FileName,\r
1020           HMainEditor.BufferImage->DiskImage->Name,\r
1021           HMainEditor.BufferImage->DiskImage->Offset,\r
1022           HMainEditor.BufferImage->DiskImage->Size,\r
1023           HMainEditor.BufferImage->MemImage->Offset,\r
1024           HMainEditor.BufferImage->MemImage->Size,\r
1025           BufferType,\r
1026           TRUE\r
1027           );\r
1028 \r
1029         StatusBarSetStatusString (L"Invalid File Name");\r
1030         return EFI_SUCCESS;\r
1031       }\r
1032 \r
1033       break;\r
1034     }\r
1035   }\r
1036   //\r
1037   // read from disk\r
1038   //\r
1039   Status = HBufferImageRead (\r
1040             InputBarGetString(),\r
1041             HMainEditor.BufferImage->DiskImage->Name,\r
1042             HMainEditor.BufferImage->DiskImage->Offset,\r
1043             HMainEditor.BufferImage->DiskImage->Size,\r
1044             HMainEditor.BufferImage->MemImage->Offset,\r
1045             HMainEditor.BufferImage->MemImage->Size,\r
1046             FileTypeFileBuffer,\r
1047             FALSE\r
1048             );\r
1049 \r
1050   if (EFI_ERROR (Status)) {\r
1051     HBufferImageRead (\r
1052       HMainEditor.BufferImage->FileImage->FileName,\r
1053       HMainEditor.BufferImage->DiskImage->Name,\r
1054       HMainEditor.BufferImage->DiskImage->Offset,\r
1055       HMainEditor.BufferImage->DiskImage->Size,\r
1056       HMainEditor.BufferImage->MemImage->Offset,\r
1057       HMainEditor.BufferImage->MemImage->Size,\r
1058       BufferType,\r
1059       TRUE\r
1060       );\r
1061 \r
1062     return EFI_LOAD_ERROR;\r
1063   }\r
1064 \r
1065   return EFI_SUCCESS;\r
1066 }\r
1067 \r
1068 EFI_STATUS\r
1069 HMainCommandOpenDisk (\r
1070   VOID\r
1071   )\r
1072 /*++\r
1073 \r
1074 Routine Description: \r
1075 \r
1076   Load a disk buffer editor\r
1077 \r
1078 Arguments:  \r
1079 \r
1080   None\r
1081 \r
1082 Returns:  \r
1083 \r
1084    EFI_SUCCESS\r
1085    EFI_LOAD_ERROR\r
1086    EFI_OUT_OF_RESOURCES\r
1087    EFI_NOT_FOUND\r
1088 \r
1089 --*/\r
1090 {\r
1091   UINT64                          Size;\r
1092   UINT64                          Offset;\r
1093   CHAR16                          *DeviceName;\r
1094   EFI_STATUS                      Status;\r
1095   BOOLEAN                         Done;\r
1096 \r
1097   EDIT_FILE_TYPE                  BufferType;\r
1098 \r
1099   //\r
1100   // variable initialization\r
1101   //\r
1102   Size        = 0;\r
1103   Offset      = 0;\r
1104   BufferType  = HMainEditor.BufferImage->BufferType;\r
1105 \r
1106   //\r
1107   // if current file is modified, so you need to choose\r
1108   // whether to save it first.\r
1109   //\r
1110   if (HMainEditor.BufferImage->Modified) {\r
1111 \r
1112     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
1113     if (EFI_ERROR (Status)) {\r
1114       return Status;\r
1115     }\r
1116     //\r
1117     // the answer is just one character\r
1118     //\r
1119     Status = InputBarSetStringSize (1);\r
1120     if (EFI_ERROR (Status)) {\r
1121       return Status;\r
1122     }\r
1123     //\r
1124     // loop for user's answer\r
1125     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
1126     //\r
1127     Done = FALSE;\r
1128     while (!Done) {\r
1129       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
1130 \r
1131       //\r
1132       // ESC pressed\r
1133       //\r
1134       if (Status == EFI_NOT_READY) {\r
1135         return EFI_SUCCESS;\r
1136       }\r
1137 \r
1138       switch (InputBarGetString()[0]) {\r
1139       case L'y':\r
1140       case L'Y':\r
1141         //\r
1142         // want to save this buffer first\r
1143         //\r
1144         Status = HBufferImageSave (\r
1145                   HMainEditor.BufferImage->FileImage->FileName,\r
1146                   HMainEditor.BufferImage->DiskImage->Name,\r
1147                   HMainEditor.BufferImage->DiskImage->Offset,\r
1148                   HMainEditor.BufferImage->DiskImage->Size,\r
1149                   HMainEditor.BufferImage->MemImage->Offset,\r
1150                   HMainEditor.BufferImage->MemImage->Size,\r
1151                   BufferType\r
1152                   );\r
1153         if (EFI_ERROR (Status)) {\r
1154           return Status;\r
1155         }\r
1156 \r
1157         MainTitleBarRefresh (\r
1158           HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
1159           HMainEditor.BufferImage->BufferType,\r
1160           HMainEditor.BufferImage->FileImage->ReadOnly,\r
1161           FALSE,\r
1162           HMainEditor.ScreenSize.Column,\r
1163           HMainEditor.ScreenSize.Row,\r
1164           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,\r
1165           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size  :0\r
1166           );\r
1167         Done = TRUE;\r
1168         break;\r
1169 \r
1170       case L'n':\r
1171       case L'N':\r
1172         //\r
1173         // the file won't be saved\r
1174         //\r
1175         Done = TRUE;\r
1176         break;\r
1177 \r
1178       case L'c':\r
1179       case L'C':\r
1180         return EFI_SUCCESS;\r
1181       }\r
1182     }\r
1183   }\r
1184   //\r
1185   // get disk block device name\r
1186   //\r
1187   Status = InputBarSetPrompt (L"Block Device to Open: ");\r
1188   if (EFI_ERROR (Status)) {\r
1189     return Status;\r
1190   }\r
1191 \r
1192   Status = InputBarSetStringSize (100);\r
1193   if (EFI_ERROR (Status)) {\r
1194     return Status;\r
1195   }\r
1196 \r
1197   while (1) {\r
1198     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
1199 \r
1200     //\r
1201     // ESC pressed\r
1202     //\r
1203     if (Status == EFI_NOT_READY) {\r
1204 \r
1205       return EFI_SUCCESS;\r
1206     }\r
1207     //\r
1208     // THE input string length should > 0\r
1209     //\r
1210     if (StrLen (InputBarGetString()) > 0) {\r
1211       break;\r
1212     }\r
1213   }\r
1214 \r
1215   DeviceName = CatSPrint(NULL, L"%s", InputBarGetString());\r
1216   if (DeviceName == NULL) {\r
1217     return EFI_OUT_OF_RESOURCES;\r
1218   }\r
1219   //\r
1220   // get starting offset\r
1221   //\r
1222   Status = InputBarSetPrompt (L"First Block No.: ");\r
1223   if (EFI_ERROR (Status)) {\r
1224     return Status;\r
1225   }\r
1226 \r
1227   Status = InputBarSetStringSize (16);\r
1228   if (EFI_ERROR (Status)) {\r
1229     return Status;\r
1230   }\r
1231 \r
1232   while (1) {\r
1233     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
1234 \r
1235     //\r
1236     // ESC pressed\r
1237     //\r
1238     if (Status == EFI_NOT_READY) {\r
1239 \r
1240       return EFI_SUCCESS;\r
1241     }\r
1242     //\r
1243     // THE input string length should > 0\r
1244     //\r
1245     if (StrLen (InputBarGetString()) > 0) {\r
1246       Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);\r
1247       if (EFI_ERROR (Status)) {\r
1248         continue;\r
1249       }\r
1250 \r
1251       break;\r
1252     }\r
1253   }\r
1254   //\r
1255   // get Number of Blocks:\r
1256   //\r
1257   Status = InputBarSetPrompt (L"Number of Blocks: ");\r
1258   if (EFI_ERROR (Status)) {\r
1259     return Status;\r
1260   }\r
1261 \r
1262   Status = InputBarSetStringSize (8);\r
1263   if (EFI_ERROR (Status)) {\r
1264     return Status;\r
1265   }\r
1266 \r
1267   while (1) {\r
1268     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
1269 \r
1270     //\r
1271     // ESC pressed\r
1272     //\r
1273     if (Status == EFI_NOT_READY) {\r
1274 \r
1275       return EFI_SUCCESS;\r
1276     }\r
1277     //\r
1278     // THE input string length should > 0\r
1279     //\r
1280     if (StrLen (InputBarGetString()) > 0) {\r
1281       Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);\r
1282       if (EFI_ERROR (Status)) {\r
1283         continue;\r
1284       }\r
1285 \r
1286       if (Size == 0) {\r
1287         continue;\r
1288       }\r
1289 \r
1290       break;\r
1291     }\r
1292   }\r
1293 \r
1294   Status = HBufferImageRead (\r
1295             NULL,\r
1296             DeviceName,\r
1297             (UINTN)Offset,\r
1298             (UINTN)Size,\r
1299             0,\r
1300             0,\r
1301             FileTypeDiskBuffer,\r
1302             FALSE\r
1303             );\r
1304 \r
1305   if (EFI_ERROR (Status)) {\r
1306 \r
1307     HBufferImageRead (\r
1308       HMainEditor.BufferImage->FileImage->FileName,\r
1309       HMainEditor.BufferImage->DiskImage->Name,\r
1310       HMainEditor.BufferImage->DiskImage->Offset,\r
1311       HMainEditor.BufferImage->DiskImage->Size,\r
1312       HMainEditor.BufferImage->MemImage->Offset,\r
1313       HMainEditor.BufferImage->MemImage->Size,\r
1314       BufferType,\r
1315       TRUE\r
1316       );\r
1317     return EFI_NOT_FOUND;\r
1318   }\r
1319 \r
1320   return EFI_SUCCESS;\r
1321 }\r
1322 \r
1323 EFI_STATUS\r
1324 HMainCommandOpenMemory (\r
1325   VOID\r
1326   )\r
1327 /*++\r
1328 \r
1329 Routine Description: \r
1330 \r
1331   Load memory content to editor\r
1332 \r
1333 Arguments:  \r
1334 \r
1335   None\r
1336 \r
1337 Returns:  \r
1338 \r
1339    EFI_SUCCESS\r
1340    EFI_LOAD_ERROR\r
1341    EFI_OUT_OF_RESOURCES\r
1342    EFI_NOT_FOUND\r
1343 \r
1344 --*/\r
1345 {\r
1346   UINT64                          Size;\r
1347   UINT64                          Offset;\r
1348   EFI_STATUS                      Status;\r
1349   BOOLEAN                         Done;\r
1350   EDIT_FILE_TYPE                  BufferType;\r
1351 \r
1352   //\r
1353   // variable initialization\r
1354   //\r
1355   Size        = 0;\r
1356   Offset      = 0;\r
1357   BufferType  = HMainEditor.BufferImage->BufferType;\r
1358 \r
1359   //\r
1360   // if current buffer is modified, so you need to choose\r
1361   // whether to save it first.\r
1362   //\r
1363   if (HMainEditor.BufferImage->Modified) {\r
1364 \r
1365     Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");\r
1366     if (EFI_ERROR (Status)) {\r
1367       return Status;\r
1368     }\r
1369     //\r
1370     // the answer is just one character\r
1371     //\r
1372     Status = InputBarSetStringSize (1);\r
1373     if (EFI_ERROR (Status)) {\r
1374       return Status;\r
1375     }\r
1376     //\r
1377     // loop for user's answer\r
1378     // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'\r
1379     //\r
1380     Done = FALSE;\r
1381     while (!Done) {\r
1382       Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
1383 \r
1384       //\r
1385       // ESC pressed\r
1386       //\r
1387       if (Status == EFI_NOT_READY) {\r
1388         return EFI_SUCCESS;\r
1389       }\r
1390 \r
1391       switch (InputBarGetString()[0]) {\r
1392       case L'y':\r
1393       case L'Y':\r
1394         //\r
1395         // want to save this buffer first\r
1396         //\r
1397         Status = HBufferImageSave (\r
1398                   HMainEditor.BufferImage->FileImage->FileName,\r
1399                   HMainEditor.BufferImage->DiskImage->Name,\r
1400                   HMainEditor.BufferImage->DiskImage->Offset,\r
1401                   HMainEditor.BufferImage->DiskImage->Size,\r
1402                   HMainEditor.BufferImage->MemImage->Offset,\r
1403                   HMainEditor.BufferImage->MemImage->Size,\r
1404                   BufferType\r
1405                   );\r
1406         if (EFI_ERROR (Status)) {\r
1407           return Status;\r
1408         }\r
1409 \r
1410         MainTitleBarRefresh (\r
1411           HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
1412           HMainEditor.BufferImage->BufferType,\r
1413           HMainEditor.BufferImage->FileImage->ReadOnly,\r
1414           FALSE,\r
1415           HMainEditor.ScreenSize.Column,\r
1416           HMainEditor.ScreenSize.Row,\r
1417           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,\r
1418           HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size  :0\r
1419           );\r
1420         Done = TRUE;\r
1421         break;\r
1422 \r
1423       case L'n':\r
1424       case L'N':\r
1425         //\r
1426         // the file won't be saved\r
1427         //\r
1428         Done = TRUE;\r
1429         break;\r
1430 \r
1431       case L'c':\r
1432       case L'C':\r
1433         return EFI_SUCCESS;\r
1434       }\r
1435     }\r
1436   }\r
1437   //\r
1438   // get starting offset\r
1439   //\r
1440   Status = InputBarSetPrompt (L"Starting Offset: ");\r
1441   if (EFI_ERROR (Status)) {\r
1442     return Status;\r
1443   }\r
1444 \r
1445   Status = InputBarSetStringSize (8);\r
1446   if (EFI_ERROR (Status)) {\r
1447     return Status;\r
1448   }\r
1449 \r
1450   while (1) {\r
1451     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
1452 \r
1453     //\r
1454     // ESC pressed\r
1455     //\r
1456     if (Status == EFI_NOT_READY) {\r
1457 \r
1458       return EFI_SUCCESS;\r
1459     }\r
1460     //\r
1461     // THE input string length should > 0\r
1462     //\r
1463     if (StrLen (InputBarGetString()) > 0) {\r
1464       Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);\r
1465       if (EFI_ERROR (Status)) {\r
1466         continue;\r
1467       }\r
1468 \r
1469       break;\r
1470     }\r
1471   }\r
1472   //\r
1473   // get Number of Blocks:\r
1474   //\r
1475   Status = InputBarSetPrompt (L"Buffer Size: ");\r
1476   if (EFI_ERROR (Status)) {\r
1477     return Status;\r
1478   }\r
1479 \r
1480   Status = InputBarSetStringSize (8);\r
1481   if (EFI_ERROR (Status)) {\r
1482     return Status;\r
1483   }\r
1484 \r
1485   while (1) {\r
1486     Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);\r
1487 \r
1488     //\r
1489     // ESC pressed\r
1490     //\r
1491     if (Status == EFI_NOT_READY) {\r
1492 \r
1493       return EFI_SUCCESS;\r
1494     }\r
1495     //\r
1496     // THE input string length should > 0\r
1497     //\r
1498     if (StrLen (InputBarGetString()) > 0) {\r
1499       Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);\r
1500       if (EFI_ERROR (Status)) {\r
1501         continue;\r
1502       }\r
1503 \r
1504       if (Size == 0) {\r
1505         continue;\r
1506       }\r
1507 \r
1508       break;\r
1509     }\r
1510   }\r
1511 \r
1512   if ((Offset + Size - 1)> 0xffffffff) {\r
1513     StatusBarSetStatusString (L"Invalid parameter");\r
1514     return EFI_LOAD_ERROR;\r
1515   }\r
1516 \r
1517   Status = HBufferImageRead (\r
1518             NULL,\r
1519             NULL,\r
1520             0,\r
1521             0,\r
1522             (UINTN)Offset,\r
1523             (UINTN)Size,\r
1524             FileTypeMemBuffer,\r
1525             FALSE\r
1526             );\r
1527 \r
1528   if (EFI_ERROR (Status)) {\r
1529     StatusBarSetStatusString (L"Read Device Error!");\r
1530     HBufferImageRead (\r
1531       HMainEditor.BufferImage->FileImage->FileName,\r
1532       HMainEditor.BufferImage->DiskImage->Name,\r
1533       HMainEditor.BufferImage->DiskImage->Offset,\r
1534       HMainEditor.BufferImage->DiskImage->Size,\r
1535       HMainEditor.BufferImage->MemImage->Offset,\r
1536       HMainEditor.BufferImage->MemImage->Size,\r
1537       BufferType,\r
1538       TRUE\r
1539       );\r
1540     return EFI_NOT_FOUND;\r
1541   }\r
1542   return EFI_SUCCESS;\r
1543 \r
1544 }\r
1545 \r
1546 CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = {\r
1547   {\r
1548     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET),\r
1549     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),\r
1550     HMainCommandGoToOffset\r
1551   },\r
1552   {\r
1553     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER),\r
1554     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),\r
1555     HMainCommandSaveBuffer\r
1556   },\r
1557   {\r
1558     STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),\r
1559     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),\r
1560     HMainCommandExit\r
1561   },\r
1562 \r
1563   {\r
1564     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_START),\r
1565     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),\r
1566     HMainCommandSelectStart\r
1567   },\r
1568   {\r
1569     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_END),\r
1570     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),\r
1571     HMainCommandSelectEnd\r
1572   },\r
1573   {\r
1574     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_CUT),\r
1575     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),\r
1576     HMainCommandCut\r
1577   },\r
1578   {\r
1579     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_PASTE),\r
1580     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),\r
1581     HMainCommandPaste\r
1582   },\r
1583 \r
1584   {\r
1585     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_FILE),\r
1586     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),\r
1587     HMainCommandOpenFile\r
1588   },\r
1589   {\r
1590     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_DISK),\r
1591     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),\r
1592     HMainCommandOpenDisk\r
1593   },\r
1594   {\r
1595     STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY),\r
1596     STRING_TOKEN(STR_EDIT_LIBMENUBAR_F10),\r
1597     HMainCommandOpenMemory\r
1598   },\r
1599 \r
1600   {\r
1601     0,\r
1602     0,\r
1603     NULL\r
1604   }\r
1605 };\r
1606 \r
1607 \r
1608 EFI_STATUS\r
1609 HMainEditorInit (\r
1610   VOID\r
1611   )\r
1612 /*++\r
1613 \r
1614 Routine Description: \r
1615 \r
1616   Init function for MainEditor\r
1617 \r
1618 Arguments:  \r
1619 \r
1620   None\r
1621 \r
1622 Returns:  \r
1623 \r
1624   EFI_SUCCESS\r
1625   EFI_LOAD_ERROR\r
1626 \r
1627 --*/\r
1628 {\r
1629   EFI_STATUS  Status;\r
1630   EFI_HANDLE  *HandleBuffer;\r
1631   UINTN       HandleCount;\r
1632   UINTN       Index;\r
1633 \r
1634   //\r
1635   // basic initialization\r
1636   //\r
1637   CopyMem (&HMainEditor, &HMainEditorConst, sizeof (HMainEditor));\r
1638 \r
1639   //\r
1640   // set screen attributes\r
1641   //\r
1642   HMainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;\r
1643 \r
1644   HMainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);\r
1645 \r
1646   HOriginalColors = HMainEditor.ColorAttributes.Colors;\r
1647 \r
1648   HOriginalMode = gST->ConOut->Mode->Mode;\r
1649 \r
1650   //\r
1651   // query screen size\r
1652   //\r
1653   gST->ConOut->QueryMode (\r
1654         gST->ConOut,\r
1655         gST->ConOut->Mode->Mode,\r
1656         &(HMainEditor.ScreenSize.Column),\r
1657         &(HMainEditor.ScreenSize.Row)\r
1658         );\r
1659 \r
1660   //\r
1661   // Find mouse in System Table ConsoleInHandle\r
1662   //\r
1663   Status = gBS->HandleProtocol (\r
1664                 gST->ConIn,\r
1665                 &gEfiSimplePointerProtocolGuid,\r
1666                 (VOID**)&HMainEditor.MouseInterface\r
1667                 );\r
1668   if (EFI_ERROR (Status)) {\r
1669     //\r
1670     // If there is no Simple Pointer Protocol on System Table\r
1671     //\r
1672     HandleBuffer = NULL;\r
1673     HMainEditor.MouseInterface = NULL;\r
1674     Status = gBS->LocateHandleBuffer (\r
1675                   ByProtocol,\r
1676                   &gEfiSimplePointerProtocolGuid,\r
1677                   NULL,\r
1678                   &HandleCount,\r
1679                   &HandleBuffer\r
1680                   );\r
1681     if (!EFI_ERROR (Status) && HandleCount > 0) {\r
1682       //\r
1683       // Try to find the first available mouse device\r
1684       //\r
1685       for (Index = 0; Index < HandleCount; Index++) {\r
1686         Status = gBS->HandleProtocol (\r
1687                       HandleBuffer[Index],\r
1688                       &gEfiSimplePointerProtocolGuid,\r
1689                       (VOID**)&HMainEditor.MouseInterface\r
1690                       );\r
1691         if (!EFI_ERROR (Status)) {\r
1692           break;\r
1693         }\r
1694       }\r
1695     }\r
1696     if (HandleBuffer != NULL) {\r
1697       FreePool (HandleBuffer);\r
1698     }\r
1699   }\r
1700 \r
1701   if (!EFI_ERROR (Status) && HMainEditor.MouseInterface != NULL) {\r
1702     HMainEditor.MouseAccumulatorX  = 0;\r
1703     HMainEditor.MouseAccumulatorY  = 0;\r
1704     HMainEditor.MouseSupported     = TRUE;\r
1705   }\r
1706 \r
1707   //\r
1708   // below will call the five components' init function\r
1709   //\r
1710   Status = MainTitleBarInit (NULL);\r
1711   if (EFI_ERROR (Status)) {\r
1712     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE), gShellDebug1HiiHandle);\r
1713     return EFI_LOAD_ERROR;\r
1714   }\r
1715 \r
1716   Status = MenuBarInit (HexEditorMenuItems);\r
1717   if (EFI_ERROR (Status)) {\r
1718     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle);\r
1719     return EFI_LOAD_ERROR;\r
1720   }\r
1721 \r
1722   Status = StatusBarInit ();\r
1723   if (EFI_ERROR (Status)) {\r
1724     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS), gShellDebug1HiiHandle);\r
1725     return EFI_LOAD_ERROR;\r
1726   }\r
1727 \r
1728   InputBarInit ();\r
1729 \r
1730   Status = HBufferImageInit ();\r
1731   if (EFI_ERROR (Status)) {\r
1732     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE), gShellDebug1HiiHandle);\r
1733     return EFI_LOAD_ERROR;\r
1734   }\r
1735 \r
1736   Status = HClipBoardInit ();\r
1737   if (EFI_ERROR (Status)) {\r
1738     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD), gShellDebug1HiiHandle);\r
1739     return EFI_LOAD_ERROR;\r
1740   }\r
1741   //\r
1742   // clear whole screen and enable cursor\r
1743   //\r
1744   gST->ConOut->ClearScreen (gST->ConOut);\r
1745   gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
1746 \r
1747   //\r
1748   // initialize EditorFirst and EditorExit\r
1749   //\r
1750   HEditorFirst        = TRUE;\r
1751   HEditorExit         = FALSE;\r
1752   HEditorMouseAction  = FALSE;\r
1753 \r
1754   return EFI_SUCCESS;\r
1755 }\r
1756 \r
1757 EFI_STATUS\r
1758 HMainEditorCleanup (\r
1759   VOID\r
1760   )\r
1761 /*++\r
1762 \r
1763 Routine Description: \r
1764 \r
1765   cleanup function for MainEditor\r
1766 \r
1767 Arguments:  \r
1768 \r
1769   None\r
1770 \r
1771 Returns:  \r
1772 \r
1773   EFI_SUCCESS\r
1774   EFI_LOAD_ERROR\r
1775 \r
1776 --*/\r
1777 {\r
1778   EFI_STATUS  Status;\r
1779 \r
1780   //\r
1781   // call the five components' cleanup function\r
1782   //\r
1783   MainTitleBarCleanup ();\r
1784 \r
1785   MenuBarCleanup ();\r
1786 \r
1787   StatusBarCleanup ();\r
1788   \r
1789   InputBarCleanup ();\r
1790   \r
1791   Status = HBufferImageCleanup ();\r
1792   if (EFI_ERROR (Status)) {\r
1793     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN), gShellDebug1HiiHandle);\r
1794   }\r
1795 \r
1796   Status = HClipBoardCleanup ();\r
1797   if (EFI_ERROR (Status)) {\r
1798     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN), gShellDebug1HiiHandle);\r
1799   }\r
1800   //\r
1801   // restore old mode\r
1802   //\r
1803   if (HOriginalMode != gST->ConOut->Mode->Mode) {\r
1804     gST->ConOut->SetMode (gST->ConOut, HOriginalMode);\r
1805   }\r
1806 \r
1807   gST->ConOut->SetAttribute (\r
1808         gST->ConOut,\r
1809         EFI_TEXT_ATTR (HOriginalColors.Foreground, HOriginalColors.Background)\r
1810         );\r
1811   gST->ConOut->ClearScreen (gST->ConOut);\r
1812 \r
1813   return EFI_SUCCESS;\r
1814 }\r
1815 \r
1816 EFI_STATUS\r
1817 HMainEditorRefresh (\r
1818   VOID\r
1819   )\r
1820 /*++\r
1821 \r
1822 Routine Description: \r
1823 \r
1824   Refresh function for MainEditor\r
1825 \r
1826 Arguments:  \r
1827 \r
1828   None\r
1829 \r
1830 Returns:  \r
1831 \r
1832   EFI_SUCCESS\r
1833 \r
1834 --*/\r
1835 {\r
1836   BOOLEAN NameChange;\r
1837   BOOLEAN ReadChange;\r
1838 \r
1839   NameChange = FALSE;\r
1840   ReadChange = FALSE;\r
1841 \r
1842   if ( HMainEditor.BufferImage->FileImage != NULL && \r
1843        HMainEditor.BufferImage->FileImage->FileName != NULL && \r
1844        HBufferImageBackupVar.FileImage != NULL && \r
1845        HBufferImageBackupVar.FileImage->FileName != NULL && \r
1846        StrCmp (HMainEditor.BufferImage->FileImage->FileName, HBufferImageBackupVar.FileImage->FileName) != 0 ) {\r
1847     NameChange = TRUE;\r
1848   }\r
1849   if ( HMainEditor.BufferImage->FileImage != NULL && \r
1850        HBufferImageBackupVar.FileImage != NULL && \r
1851        HMainEditor.BufferImage->FileImage->ReadOnly != HBufferImageBackupVar.FileImage->ReadOnly ) {\r
1852     ReadChange = TRUE;\r
1853   }\r
1854 \r
1855   //\r
1856   // to aVOID screen flicker\r
1857   // the stall value is from experience\r
1858   //\r
1859   gBS->Stall (50);\r
1860 \r
1861   //\r
1862   // call the components refresh function\r
1863   //\r
1864   if (HEditorFirst \r
1865     || NameChange\r
1866     || HMainEditor.BufferImage->BufferType != HBufferImageBackupVar.BufferType \r
1867     || HBufferImageBackupVar.Modified != HMainEditor.BufferImage->Modified \r
1868     || ReadChange ) {\r
1869 \r
1870     MainTitleBarRefresh (\r
1871       HMainEditor.BufferImage->BufferType == FileTypeFileBuffer&&HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Name:NULL,\r
1872       HMainEditor.BufferImage->BufferType,\r
1873       (BOOLEAN)(HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->ReadOnly:FALSE),\r
1874       HMainEditor.BufferImage->Modified,\r
1875       HMainEditor.ScreenSize.Column,\r
1876       HMainEditor.ScreenSize.Row,\r
1877       HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,\r
1878       HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size  :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size  :0\r
1879       );\r
1880     HBufferImageRefresh ();\r
1881   }\r
1882   if (HEditorFirst\r
1883     || HBufferImageBackupVar.DisplayPosition.Row != HMainEditor.BufferImage->DisplayPosition.Row \r
1884     || HBufferImageBackupVar.DisplayPosition.Column != HMainEditor.BufferImage->DisplayPosition.Column \r
1885     || StatusBarGetRefresh()) {\r
1886 \r
1887     StatusBarRefresh (\r
1888       HEditorFirst,\r
1889       HMainEditor.ScreenSize.Row,\r
1890       HMainEditor.ScreenSize.Column,\r
1891       0,\r
1892       0,\r
1893       TRUE\r
1894       );\r
1895     HBufferImageRefresh ();\r
1896   }\r
1897 \r
1898   if (HEditorFirst) {\r
1899     MenuBarRefresh (    \r
1900       HMainEditor.ScreenSize.Row,\r
1901       HMainEditor.ScreenSize.Column);\r
1902     HBufferImageRefresh ();\r
1903   }\r
1904 \r
1905   //\r
1906   // EditorFirst is now set to FALSE\r
1907   //\r
1908   HEditorFirst = FALSE;\r
1909 \r
1910   return EFI_SUCCESS;\r
1911 }\r
1912 \r
1913 STATIC\r
1914 EFI_STATUS\r
1915 HMainEditorHandleMouseInput (\r
1916   IN  EFI_SIMPLE_POINTER_STATE       MouseState,\r
1917   OUT BOOLEAN                        *BeforeLeftButtonDown\r
1918   )\r
1919 {\r
1920 \r
1921   INT32             TextX;\r
1922   INT32             TextY;\r
1923   UINTN             FRow;\r
1924   UINTN             FCol;\r
1925   BOOLEAN           HighBits;\r
1926   LIST_ENTRY    *Link;\r
1927   HEFI_EDITOR_LINE  *Line;\r
1928   UINTN             Index;\r
1929   BOOLEAN           Action;\r
1930 \r
1931   Action = FALSE;\r
1932 \r
1933   //\r
1934   // have mouse movement\r
1935   //\r
1936   if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {\r
1937     //\r
1938     // handle\r
1939     //\r
1940     TextX = HGetTextX (MouseState.RelativeMovementX);\r
1941     TextY = HGetTextY (MouseState.RelativeMovementY);\r
1942 \r
1943     HBufferImageAdjustMousePosition (TextX, TextY);\r
1944 \r
1945     Action = TRUE;\r
1946 \r
1947   }\r
1948 \r
1949   if (MouseState.LeftButton) {\r
1950     HighBits = HBufferImageIsAtHighBits (\r
1951                 HMainEditor.BufferImage->MousePosition.Column,\r
1952                 &FCol\r
1953                 );\r
1954 \r
1955     //\r
1956     // not at an movable place\r
1957     //\r
1958     if (FCol == 0) {\r
1959       //\r
1960       // now just move mouse pointer to legal position\r
1961       //\r
1962       //\r
1963       // move mouse position to legal position\r
1964       //\r
1965       HMainEditor.BufferImage->MousePosition.Column -= 10;\r
1966       if (HMainEditor.BufferImage->MousePosition.Column > 24) {\r
1967         HMainEditor.BufferImage->MousePosition.Column--;\r
1968         FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;\r
1969       } else {\r
1970         if (HMainEditor.BufferImage->MousePosition.Column < 24) {\r
1971           FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;\r
1972         } else {\r
1973           //\r
1974           // == 24\r
1975           //\r
1976           FCol = 9;\r
1977         }\r
1978       }\r
1979 \r
1980       HighBits = TRUE;\r
1981 \r
1982     }\r
1983 \r
1984     FRow = HMainEditor.BufferImage->BufferPosition.Row +\r
1985       HMainEditor.BufferImage->MousePosition.Row -\r
1986       HMainEditor.BufferImage->DisplayPosition.Row;\r
1987 \r
1988     if (HMainEditor.BufferImage->NumLines < FRow) {\r
1989       //\r
1990       // dragging\r
1991       //\r
1992       //\r
1993       // now just move mouse pointer to legal position\r
1994       //\r
1995       FRow      = HMainEditor.BufferImage->NumLines;\r
1996       HighBits  = TRUE;\r
1997     }\r
1998 \r
1999     Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
2000     for (Index = 0; Index < FRow - 1; Index++) {\r
2001       Link = Link->ForwardLink;\r
2002     }\r
2003 \r
2004     Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
2005 \r
2006     //\r
2007     // dragging\r
2008     //\r
2009     //\r
2010     // now just move mouse pointer to legal position\r
2011     //\r
2012     if (FCol > Line->Size) {\r
2013       if (*BeforeLeftButtonDown) {\r
2014         HighBits = FALSE;\r
2015 \r
2016         if (Line->Size == 0) {\r
2017           if (FRow > 1) {\r
2018             FRow--;\r
2019             FCol = 16;\r
2020           } else {\r
2021             FRow  = 1;\r
2022             FCol  = 1;\r
2023           }\r
2024 \r
2025         } else {\r
2026           FCol = Line->Size;\r
2027         }\r
2028       } else {\r
2029         FCol      = Line->Size + 1;\r
2030         HighBits  = TRUE;\r
2031       }\r
2032     }\r
2033 \r
2034     HBufferImageMovePosition (FRow, FCol, HighBits);\r
2035 \r
2036     HMainEditor.BufferImage->MousePosition.Row    = HMainEditor.BufferImage->DisplayPosition.Row;\r
2037 \r
2038     HMainEditor.BufferImage->MousePosition.Column = HMainEditor.BufferImage->DisplayPosition.Column;\r
2039 \r
2040     *BeforeLeftButtonDown                         = TRUE;\r
2041 \r
2042     Action = TRUE;\r
2043   } else {\r
2044     //\r
2045     // else of if LButton\r
2046     //\r
2047     // release LButton\r
2048     //\r
2049     if (*BeforeLeftButtonDown == TRUE) {\r
2050       Action = TRUE;\r
2051     }\r
2052     //\r
2053     // mouse up\r
2054     //\r
2055     *BeforeLeftButtonDown = FALSE;\r
2056   }\r
2057 \r
2058   if (Action) {\r
2059     return EFI_SUCCESS;\r
2060   }\r
2061 \r
2062   return EFI_NOT_FOUND;\r
2063 }\r
2064 \r
2065 EFI_STATUS\r
2066 HMainEditorKeyInput (\r
2067   VOID\r
2068   )\r
2069 /*++\r
2070 \r
2071 Routine Description: \r
2072 \r
2073   Handle user key input. will route it to other components handle function\r
2074 \r
2075 Arguments:  \r
2076 \r
2077   None\r
2078 \r
2079 Returns:  \r
2080 \r
2081   EFI_SUCCESS\r
2082   EFI_LOAD_ERROR\r
2083   EFI_OUT_OF_RESOURCES\r
2084 \r
2085 --*/\r
2086 {\r
2087   EFI_INPUT_KEY             Key;\r
2088   EFI_STATUS                Status;\r
2089   EFI_SIMPLE_POINTER_STATE  MouseState;\r
2090   BOOLEAN                   LengthChange;\r
2091   UINTN                     Size;\r
2092   UINTN                     OldSize;\r
2093   BOOLEAN                   BeforeMouseIsDown;\r
2094   BOOLEAN                   MouseIsDown;\r
2095   BOOLEAN                   FirstDown;\r
2096   BOOLEAN                   MouseDrag;\r
2097   UINTN                     FRow;\r
2098   UINTN                     FCol;\r
2099   UINTN                     SelectStartBackup;\r
2100   UINTN                     SelectEndBackup;\r
2101 \r
2102   //\r
2103   // variable initialization\r
2104   //\r
2105   OldSize       = 0;\r
2106   FRow          = 0;\r
2107   FCol          = 0;\r
2108   LengthChange  = FALSE;\r
2109 \r
2110   MouseIsDown   = FALSE;\r
2111   FirstDown     = FALSE;\r
2112   MouseDrag     = FALSE;\r
2113 \r
2114   do {\r
2115 \r
2116     Status              = EFI_SUCCESS;\r
2117 \r
2118     HEditorMouseAction  = FALSE;\r
2119 \r
2120     //\r
2121     // backup some key elements, so that can aVOID some refresh work\r
2122     //\r
2123     HMainEditorBackup ();\r
2124 \r
2125     //\r
2126     // wait for user key input\r
2127     //\r
2128     //\r
2129     // change priority of checking mouse/keyboard activity dynamically\r
2130     // so prevent starvation of keyboard.\r
2131     // if last time, mouse moves then this time check keyboard\r
2132     //\r
2133     if (HMainEditor.MouseSupported) {\r
2134       Status = HMainEditor.MouseInterface->GetState (\r
2135                                             HMainEditor.MouseInterface,\r
2136                                             &MouseState\r
2137                                             );\r
2138       if (!EFI_ERROR (Status)) {\r
2139 \r
2140         BeforeMouseIsDown = MouseIsDown;\r
2141 \r
2142         Status            = HMainEditorHandleMouseInput (MouseState, &MouseIsDown);\r
2143 \r
2144         if (!EFI_ERROR (Status)) {\r
2145           if (BeforeMouseIsDown == FALSE) {\r
2146             //\r
2147             // mouse down\r
2148             //\r
2149             if (MouseIsDown == TRUE) {\r
2150               FRow              = HBufferImage.BufferPosition.Row;\r
2151               FCol              = HBufferImage.BufferPosition.Column;\r
2152               SelectStartBackup = HMainEditor.SelectStart;\r
2153               SelectEndBackup   = HMainEditor.SelectEnd;\r
2154 \r
2155               FirstDown         = TRUE;\r
2156             }\r
2157           } else {\r
2158 \r
2159             SelectStartBackup = HMainEditor.SelectStart;\r
2160             SelectEndBackup   = HMainEditor.SelectEnd;\r
2161 \r
2162             //\r
2163             // begin to drag\r
2164             //\r
2165             if (MouseIsDown == TRUE) {\r
2166               if (FirstDown == TRUE) {\r
2167                 if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {\r
2168                   HMainEditor.SelectStart = 0;\r
2169                   HMainEditor.SelectEnd   = 0;\r
2170                   HMainEditor.SelectStart = (FRow - 1) * 0x10 + FCol;\r
2171 \r
2172                   MouseDrag               = TRUE;\r
2173                   FirstDown               = FALSE;\r
2174                 }\r
2175               } else {\r
2176                 if ((\r
2177                       (HBufferImage.BufferPosition.Row - 1) *\r
2178                     0x10 +\r
2179                     HBufferImage.BufferPosition.Column\r
2180                       ) >= HMainEditor.SelectStart\r
2181                         ) {\r
2182                   HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *\r
2183                     0x10 +\r
2184                     HBufferImage.BufferPosition.Column;\r
2185                 } else {\r
2186                   HMainEditor.SelectEnd = 0;\r
2187                 }\r
2188               }\r
2189               //\r
2190               // end of if RelativeX/Y\r
2191               //\r
2192             } else {\r
2193               //\r
2194               // mouse is up\r
2195               //\r
2196               if (MouseDrag) {\r
2197                 if (HBufferImageGetTotalSize () == 0) {\r
2198                   HMainEditor.SelectStart = 0;\r
2199                   HMainEditor.SelectEnd   = 0;\r
2200                   FirstDown               = FALSE;\r
2201                   MouseDrag               = FALSE;\r
2202                 }\r
2203 \r
2204                 if ((\r
2205                       (HBufferImage.BufferPosition.Row - 1) *\r
2206                     0x10 +\r
2207                     HBufferImage.BufferPosition.Column\r
2208                       ) >= HMainEditor.SelectStart\r
2209                         ) {\r
2210                   HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *\r
2211                     0x10 +\r
2212                     HBufferImage.BufferPosition.Column;\r
2213                 } else {\r
2214                   HMainEditor.SelectEnd = 0;\r
2215                 }\r
2216 \r
2217                 if (HMainEditor.SelectEnd == 0) {\r
2218                   HMainEditor.SelectStart = 0;\r
2219                 }\r
2220               }\r
2221 \r
2222               FirstDown = FALSE;\r
2223               MouseDrag = FALSE;\r
2224             }\r
2225 \r
2226             if (SelectStartBackup != HMainEditor.SelectStart || SelectEndBackup != HMainEditor.SelectEnd) {\r
2227               if ((SelectStartBackup - 1) / 0x10 != (HMainEditor.SelectStart - 1) / 0x10) {\r
2228                 HBufferImageNeedRefresh = TRUE;\r
2229               } else {\r
2230                 if ((SelectEndBackup - 1) / 0x10 != (HMainEditor.SelectEnd - 1) / 0x10) {\r
2231                   HBufferImageNeedRefresh = TRUE;\r
2232                 } else {\r
2233                   HBufferImageOnlyLineNeedRefresh = TRUE;\r
2234                 }\r
2235               }\r
2236             }\r
2237           }\r
2238 \r
2239           HEditorMouseAction            = TRUE;\r
2240           HBufferImageMouseNeedRefresh  = TRUE;\r
2241 \r
2242         } else if (Status == EFI_LOAD_ERROR) {\r
2243           StatusBarSetStatusString (L"Invalid Mouse Movement ");\r
2244         }\r
2245       }\r
2246     }\r
2247 \r
2248     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
2249     if (!EFI_ERROR (Status)) {\r
2250       //\r
2251       // dispatch to different components' key handling function\r
2252       // so not everywhere has to set this variable\r
2253       //\r
2254       HBufferImageMouseNeedRefresh = TRUE;\r
2255 \r
2256       //\r
2257       // clear previous status string\r
2258       //\r
2259       StatusBarSetRefresh();\r
2260 \r
2261       if (Key.ScanCode == SCAN_NULL) {\r
2262         Status = HBufferImageHandleInput (&Key);\r
2263       } else if (((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {\r
2264         Status = HBufferImageHandleInput (&Key);\r
2265       } else if (((Key.ScanCode >= SCAN_F1) && Key.ScanCode <= (SCAN_F12))) {\r
2266         Status = MenuBarDispatchFunctionKey (&Key);\r
2267       } else {\r
2268         StatusBarSetStatusString (L"Unknown Command");\r
2269 \r
2270         HBufferImageMouseNeedRefresh = FALSE;\r
2271       }\r
2272 \r
2273       if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {\r
2274         //\r
2275         // not already has some error status\r
2276         //\r
2277         if (StrCmp (L"", StatusBarGetString()) == 0) {\r
2278           StatusBarSetStatusString (L"Disk Error. Try Again");\r
2279         }\r
2280       }\r
2281     }\r
2282     //\r
2283     // decide if has to set length warning\r
2284     //\r
2285     if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) {\r
2286       LengthChange = FALSE;\r
2287     } else {\r
2288       //\r
2289       // still the old buffer\r
2290       //\r
2291       if (HBufferImage.BufferType != FileTypeFileBuffer) {\r
2292         Size = HBufferImageGetTotalSize ();\r
2293 \r
2294         switch (HBufferImage.BufferType) {\r
2295         case FileTypeDiskBuffer:\r
2296           OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage->BlockSize;\r
2297           break;\r
2298 \r
2299         case FileTypeMemBuffer:\r
2300           OldSize = HBufferImage.MemImage->Size;\r
2301           break;\r
2302         }\r
2303 \r
2304         if (LengthChange == FALSE) {\r
2305           if (OldSize != Size) {\r
2306             StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be changed");\r
2307           }\r
2308         }\r
2309 \r
2310         if (OldSize != Size) {\r
2311           LengthChange = TRUE;\r
2312         } else {\r
2313           LengthChange = FALSE;\r
2314         }\r
2315       }\r
2316     }\r
2317     //\r
2318     // after handling, refresh editor\r
2319     //\r
2320     HMainEditorRefresh ();\r
2321 \r
2322   } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit);\r
2323 \r
2324   return Status;\r
2325 }\r
2326 \r
2327 /**\r
2328   Backup function for MainEditor.\r
2329 **/\r
2330 VOID\r
2331 EFIAPI\r
2332 HMainEditorBackup (\r
2333   VOID\r
2334   )\r
2335 {\r
2336   HMainEditorBackupVar.SelectStart  = HMainEditor.SelectStart;\r
2337   HMainEditorBackupVar.SelectEnd    = HMainEditor.SelectEnd;\r
2338   HBufferImageBackup ();\r
2339 }\r