]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / BufferImage.c
... / ...
CommitLineData
1/** @file\r
2 Defines HBufferImage - the view of the file that is visible at any point,\r
3 as well as the event handlers for editing the file\r
4\r
5 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "HexEditor.h"\r
11\r
12extern EFI_HANDLE HImageHandleBackup;\r
13\r
14extern HEFI_EDITOR_FILE_IMAGE HFileImage;\r
15extern HEFI_EDITOR_DISK_IMAGE HDiskImage;\r
16extern HEFI_EDITOR_MEM_IMAGE HMemImage;\r
17\r
18extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;\r
19extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;\r
20extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;\r
21\r
22extern BOOLEAN HEditorMouseAction;\r
23\r
24extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;\r
25extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;\r
26\r
27HEFI_EDITOR_BUFFER_IMAGE HBufferImage;\r
28HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;\r
29\r
30//\r
31// for basic initialization of HBufferImage\r
32//\r
33HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = {\r
34 NULL,\r
35 NULL,\r
36 0,\r
37 NULL,\r
38 {\r
39 0,\r
40 0\r
41 },\r
42 {\r
43 0,\r
44 0\r
45 },\r
46 {\r
47 0,\r
48 0\r
49 },\r
50 0,\r
51 TRUE,\r
52 FALSE,\r
53 FileTypeNone,\r
54 NULL,\r
55 NULL,\r
56 NULL\r
57};\r
58\r
59//\r
60// the whole edit area needs to be refreshed\r
61//\r
62BOOLEAN HBufferImageNeedRefresh;\r
63\r
64//\r
65// only the current line in edit area needs to be refresh\r
66//\r
67BOOLEAN HBufferImageOnlyLineNeedRefresh;\r
68\r
69BOOLEAN HBufferImageMouseNeedRefresh;\r
70\r
71/**\r
72 Initialization function for HBufferImage\r
73\r
74 @retval EFI_SUCCESS The operation was successful.\r
75 @retval EFI_LOAD_ERROR A load error occurred.\r
76**/\r
77EFI_STATUS\r
78HBufferImageInit (\r
79 VOID\r
80 )\r
81{\r
82 EFI_STATUS Status;\r
83\r
84 //\r
85 // basically initialize the HBufferImage\r
86 //\r
87 CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage));\r
88\r
89 //\r
90 // INIT listhead\r
91 //\r
92 HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));\r
93 if (HBufferImage.ListHead == NULL) {\r
94 return EFI_LOAD_ERROR;\r
95 }\r
96\r
97 InitializeListHead (HBufferImage.ListHead);\r
98\r
99 HBufferImage.DisplayPosition.Row = 2;\r
100 HBufferImage.DisplayPosition.Column = 10;\r
101 HBufferImage.MousePosition.Row = 2;\r
102 HBufferImage.MousePosition.Column = 10;\r
103\r
104 HBufferImage.FileImage = &HFileImage;\r
105 HBufferImage.DiskImage = &HDiskImage;\r
106 HBufferImage.MemImage = &HMemImage;\r
107\r
108 HBufferImageNeedRefresh = FALSE;\r
109 HBufferImageOnlyLineNeedRefresh = FALSE;\r
110 HBufferImageMouseNeedRefresh = FALSE;\r
111\r
112 HBufferImageBackupVar.FileImage = &HFileImageBackupVar;\r
113 HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar;\r
114 HBufferImageBackupVar.MemImage = &HMemImageBackupVar;\r
115\r
116 Status = HFileImageInit ();\r
117 if (EFI_ERROR (Status)) {\r
118 return EFI_LOAD_ERROR;\r
119 }\r
120\r
121 Status = HDiskImageInit ();\r
122 if (EFI_ERROR (Status)) {\r
123 return EFI_LOAD_ERROR;\r
124 }\r
125\r
126 Status = HMemImageInit ();\r
127 if (EFI_ERROR (Status)) {\r
128 return EFI_LOAD_ERROR;\r
129 }\r
130\r
131 return EFI_SUCCESS;\r
132}\r
133\r
134/**\r
135 Backup function for HBufferImage. Only a few fields need to be backup.\r
136 This is for making the file buffer refresh as few as possible.\r
137\r
138 @retval EFI_SUCCESS The operation was successful.\r
139**/\r
140EFI_STATUS\r
141HBufferImageBackup (\r
142 VOID\r
143 )\r
144{\r
145 HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition;\r
146\r
147 HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition;\r
148\r
149 HBufferImageBackupVar.Modified = HBufferImage.Modified;\r
150\r
151 HBufferImageBackupVar.BufferType = HBufferImage.BufferType;\r
152 HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow;\r
153 HBufferImageBackupVar.HighBits = HBufferImage.HighBits;\r
154\r
155 //\r
156 // three kinds of buffer supported\r
157 // file buffer\r
158 // disk buffer\r
159 // memory buffer\r
160 //\r
161 switch (HBufferImage.BufferType) {\r
162 case FileTypeFileBuffer:\r
163 HFileImageBackup ();\r
164 break;\r
165\r
166 case FileTypeDiskBuffer:\r
167 HDiskImageBackup ();\r
168 break;\r
169\r
170 case FileTypeMemBuffer:\r
171 HMemImageBackup ();\r
172 break;\r
173\r
174 default:\r
175 break;\r
176 }\r
177\r
178 return EFI_SUCCESS;\r
179}\r
180\r
181/**\r
182 Free all the lines in HBufferImage.\r
183 Fields affected:\r
184 Lines\r
185 CurrentLine\r
186 NumLines\r
187 ListHead\r
188\r
189 @retval EFI_SUCCESS The operation was successful.\r
190**/\r
191EFI_STATUS\r
192HBufferImageFreeLines (\r
193 VOID\r
194 )\r
195{\r
196 HFreeLines (HBufferImage.ListHead, HBufferImage.Lines);\r
197\r
198 HBufferImage.Lines = NULL;\r
199 HBufferImage.CurrentLine = NULL;\r
200 HBufferImage.NumLines = 0;\r
201\r
202 return EFI_SUCCESS;\r
203}\r
204\r
205/**\r
206 Cleanup function for HBufferImage\r
207\r
208 @retval EFI_SUCCESS The operation was successful.\r
209**/\r
210EFI_STATUS\r
211HBufferImageCleanup (\r
212 VOID\r
213 )\r
214{\r
215 EFI_STATUS Status;\r
216\r
217 //\r
218 // free all the lines\r
219 //\r
220 Status = HBufferImageFreeLines ();\r
221\r
222 SHELL_FREE_NON_NULL (HBufferImage.ListHead);\r
223 HBufferImage.ListHead = NULL;\r
224\r
225 HFileImageCleanup ();\r
226 HDiskImageCleanup ();\r
227\r
228 return Status;\r
229}\r
230\r
231/**\r
232 Print Line on Row\r
233\r
234 @param[in] Line The lline to print.\r
235 @param[in] Row The row on screen ( begin from 1 ).\r
236 @param[in] FRow The FRow.\r
237 @param[in] Orig The original color.\r
238 @param[in] New The color to print with.\r
239\r
240 @retval EFI_SUCCESS The operation was successful.\r
241**/\r
242EFI_STATUS\r
243HBufferImagePrintLine (\r
244 IN HEFI_EDITOR_LINE *Line,\r
245 IN UINTN Row,\r
246 IN UINTN FRow,\r
247 IN HEFI_EDITOR_COLOR_UNION Orig,\r
248 IN HEFI_EDITOR_COLOR_UNION New\r
249\r
250 )\r
251{\r
252 UINTN Index;\r
253 UINTN Pos;\r
254 BOOLEAN Selected;\r
255 BOOLEAN BeNewColor;\r
256 UINTN RowStart;\r
257 UINTN RowEnd;\r
258 UINTN ColStart;\r
259 UINTN ColEnd;\r
260\r
261 //\r
262 // variable initialization\r
263 //\r
264 ColStart = 0;\r
265 ColEnd = 0;\r
266 Selected = FALSE;\r
267\r
268 //\r
269 // print the selected area in opposite color\r
270 //\r
271 if ((HMainEditor.SelectStart != 0) && (HMainEditor.SelectEnd != 0)) {\r
272 RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
273 RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;\r
274\r
275 ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;\r
276 ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;\r
277\r
278 if ((FRow >= RowStart) && (FRow <= RowEnd)) {\r
279 Selected = TRUE;\r
280 }\r
281\r
282 if (FRow > RowStart) {\r
283 ColStart = 1;\r
284 }\r
285\r
286 if (FRow < RowEnd) {\r
287 ColEnd = 0x10;\r
288 }\r
289 }\r
290\r
291 if (!HEditorMouseAction) {\r
292 ShellPrintEx (\r
293 0,\r
294 (INT32)Row - 1,\r
295 L"%8X ",\r
296 ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10\r
297 );\r
298 }\r
299\r
300 for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) {\r
301 BeNewColor = FALSE;\r
302\r
303 if (Selected) {\r
304 if ((Index + 1 >= ColStart) && (Index + 1 <= ColEnd)) {\r
305 BeNewColor = TRUE;\r
306 }\r
307 }\r
308\r
309 if (BeNewColor) {\r
310 gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);\r
311 } else {\r
312 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);\r
313 }\r
314\r
315 Pos = 10 + (Index * 3);\r
316 if (Line->Buffer[Index] < 0x10) {\r
317 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");\r
318 Pos++;\r
319 }\r
320\r
321 if (Index < 0x07) {\r
322 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);\r
323 } else {\r
324 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);\r
325 }\r
326 }\r
327\r
328 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);\r
329 while (Index < 0x08) {\r
330 Pos = 10 + (Index * 3);\r
331 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
332 Index++;\r
333 }\r
334\r
335 while (Index < 0x10 && Index < Line->Size) {\r
336 BeNewColor = FALSE;\r
337\r
338 if (Selected) {\r
339 if ((Index + 1 >= ColStart) && (Index + 1 <= ColEnd)) {\r
340 BeNewColor = TRUE;\r
341 }\r
342 }\r
343\r
344 if (BeNewColor) {\r
345 gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);\r
346 } else {\r
347 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);\r
348 }\r
349\r
350 Pos = 10 + (Index * 3) + 1;\r
351 if (Line->Buffer[Index] < 0x10) {\r
352 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");\r
353 Pos++;\r
354 }\r
355\r
356 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);\r
357 Index++;\r
358 }\r
359\r
360 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);\r
361 while (Index < 0x10) {\r
362 Pos = 10 + (Index * 3) + 1;\r
363 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
364 Index++;\r
365 }\r
366\r
367 //\r
368 // restore the original color\r
369 //\r
370 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);\r
371\r
372 //\r
373 // PRINT the buffer content\r
374 //\r
375 if (!HEditorMouseAction) {\r
376 for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) {\r
377 Pos = ASCII_POSITION + Index;\r
378\r
379 //\r
380 // learned from shelle.h -- IsValidChar\r
381 //\r
382 if (Line->Buffer[Index] >= L' ') {\r
383 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16)Line->Buffer[Index]);\r
384 } else {\r
385 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.');\r
386 }\r
387 }\r
388\r
389 while (Index < 0x10) {\r
390 Pos = ASCII_POSITION + Index;\r
391 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
392 Index++;\r
393 }\r
394 }\r
395\r
396 //\r
397 // restore the abundant blank in hex edit area to original color\r
398 //\r
399 if (Selected) {\r
400 if (ColEnd <= 7) {\r
401 Pos = 10 + (ColEnd - 1) * 3 + 2;\r
402 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
403 } else if (ColEnd == 8) {\r
404 Pos = 10 + (ColEnd - 1) * 3 + 2;\r
405 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
406 } else {\r
407 Pos = 10 + (ColEnd - 1) * 3 + 3;\r
408 ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");\r
409 }\r
410 }\r
411\r
412 return EFI_SUCCESS;\r
413}\r
414\r
415/**\r
416 Function to decide if a column number is stored in the high bits.\r
417\r
418 @param[in] Column The column to examine.\r
419 @param[out] FCol The actual column number.\r
420\r
421 @retval TRUE The actual column was in high bits and is now in FCol.\r
422 @retval FALSE There was not a column number in the high bits.\r
423**/\r
424BOOLEAN\r
425HBufferImageIsAtHighBits (\r
426 IN UINTN Column,\r
427 OUT UINTN *FCol\r
428 )\r
429{\r
430 Column -= 10;\r
431\r
432 //\r
433 // NOW AFTER THE SUB, Column start from 0\r
434 // 23 AND 24 ARE BOTH BLANK\r
435 //\r
436 if (Column == 24) {\r
437 *FCol = 0;\r
438 return FALSE;\r
439 }\r
440\r
441 if (Column > 24) {\r
442 Column--;\r
443 }\r
444\r
445 *FCol = (Column / 3) + 1;\r
446\r
447 if (Column % 3 == 0) {\r
448 return TRUE;\r
449 }\r
450\r
451 if ((Column % 3 == 2)) {\r
452 *FCol = 0;\r
453 }\r
454\r
455 return FALSE;\r
456}\r
457\r
458/**\r
459 Decide if a point is in the already selected area.\r
460\r
461 @param[in] MouseRow The row of the point to test.\r
462 @param[in] MouseCol The col of the point to test.\r
463\r
464 @retval TRUE The point is in the selected area.\r
465 @retval FALSE The point is not in the selected area.\r
466**/\r
467BOOLEAN\r
468HBufferImageIsInSelectedArea (\r
469 IN UINTN MouseRow,\r
470 IN UINTN MouseCol\r
471 )\r
472{\r
473 UINTN FRow;\r
474 UINTN RowStart;\r
475 UINTN RowEnd;\r
476 UINTN ColStart;\r
477 UINTN ColEnd;\r
478 UINTN MouseColStart;\r
479 UINTN MouseColEnd;\r
480\r
481 //\r
482 // judge mouse position whether is in selected area\r
483 //\r
484 //\r
485 // not select\r
486 //\r
487 if ((HMainEditor.SelectStart == 0) || (HMainEditor.SelectEnd == 0)) {\r
488 return FALSE;\r
489 }\r
490\r
491 //\r
492 // calculate the select area\r
493 //\r
494 RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
495 RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;\r
496\r
497 ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;\r
498 ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;\r
499\r
500 FRow = HBufferImage.LowVisibleRow + MouseRow - 2;\r
501 if ((FRow < RowStart) || (FRow > RowEnd)) {\r
502 return FALSE;\r
503 }\r
504\r
505 if (FRow > RowStart) {\r
506 ColStart = 1;\r
507 }\r
508\r
509 if (FRow < RowEnd) {\r
510 ColEnd = 0x10;\r
511 }\r
512\r
513 MouseColStart = 10 + (ColStart - 1) * 3;\r
514 if (ColStart > 8) {\r
515 MouseColStart++;\r
516 }\r
517\r
518 MouseColEnd = 10 + (ColEnd - 1) * 3 + 1;\r
519 if (ColEnd > 8) {\r
520 MouseColEnd++;\r
521 }\r
522\r
523 if ((MouseCol < MouseColStart) || (MouseCol > MouseColEnd)) {\r
524 return FALSE;\r
525 }\r
526\r
527 return TRUE;\r
528}\r
529\r
530/**\r
531 Set mouse position according to HBufferImage.MousePosition.\r
532\r
533 @retval EFI_SUCCESS The operation was successful.\r
534**/\r
535EFI_STATUS\r
536HBufferImageRestoreMousePosition (\r
537 VOID\r
538 )\r
539{\r
540 HEFI_EDITOR_COLOR_UNION Orig;\r
541 HEFI_EDITOR_COLOR_UNION New;\r
542 UINTN FRow;\r
543 UINTN FColumn;\r
544 BOOLEAN HasCharacter;\r
545 HEFI_EDITOR_LINE *CurrentLine;\r
546 HEFI_EDITOR_LINE *Line;\r
547 UINT8 Value;\r
548 BOOLEAN HighBits;\r
549\r
550 Line = NULL;\r
551 if (HMainEditor.MouseSupported) {\r
552 if (HBufferImageMouseNeedRefresh) {\r
553 HBufferImageMouseNeedRefresh = FALSE;\r
554\r
555 //\r
556 // if mouse position not moved and only mouse action\r
557 // so do not need to refresh mouse position\r
558 //\r
559 if ((\r
560 (HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row) &&\r
561 (HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column)\r
562 ) &&\r
563 HEditorMouseAction\r
564 )\r
565 {\r
566 return EFI_SUCCESS;\r
567 }\r
568\r
569 //\r
570 // backup the old screen attributes\r
571 //\r
572 Orig = HMainEditor.ColorAttributes;\r
573 New.Data = 0;\r
574 New.Colors.Foreground = Orig.Colors.Background & 0xF;\r
575 New.Colors.Background = Orig.Colors.Foreground & 0x7;\r
576\r
577 //\r
578 // if in selected area,\r
579 // so do not need to refresh mouse\r
580 //\r
581 if (!HBufferImageIsInSelectedArea (\r
582 HBufferImageBackupVar.MousePosition.Row,\r
583 HBufferImageBackupVar.MousePosition.Column\r
584 ))\r
585 {\r
586 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
587 } else {\r
588 gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);\r
589 }\r
590\r
591 //\r
592 // clear the old mouse position\r
593 //\r
594 FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2;\r
595\r
596 HighBits = HBufferImageIsAtHighBits (\r
597 HBufferImageBackupVar.MousePosition.Column,\r
598 &FColumn\r
599 );\r
600\r
601 HasCharacter = TRUE;\r
602 if ((FRow > HBufferImage.NumLines) || (FColumn == 0)) {\r
603 HasCharacter = FALSE;\r
604 } else {\r
605 CurrentLine = HBufferImage.CurrentLine;\r
606 Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);\r
607\r
608 if ((Line == NULL) || (FColumn > Line->Size)) {\r
609 HasCharacter = FALSE;\r
610 }\r
611\r
612 HBufferImage.CurrentLine = CurrentLine;\r
613 }\r
614\r
615 ShellPrintEx (\r
616 (INT32)HBufferImageBackupVar.MousePosition.Column - 1,\r
617 (INT32)HBufferImageBackupVar.MousePosition.Row - 1,\r
618 L" "\r
619 );\r
620\r
621 if (HasCharacter) {\r
622 if (HighBits) {\r
623 Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf0);\r
624 Value = (UINT8)(Value >> 4);\r
625 } else {\r
626 Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf);\r
627 }\r
628\r
629 ShellPrintEx (\r
630 (INT32)HBufferImageBackupVar.MousePosition.Column - 1,\r
631 (INT32)HBufferImageBackupVar.MousePosition.Row - 1,\r
632 L"%x",\r
633 Value\r
634 );\r
635 }\r
636\r
637 if (!HBufferImageIsInSelectedArea (\r
638 HBufferImage.MousePosition.Row,\r
639 HBufferImage.MousePosition.Column\r
640 ))\r
641 {\r
642 gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);\r
643 } else {\r
644 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
645 }\r
646\r
647 //\r
648 // clear the old mouse position\r
649 //\r
650 FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2;\r
651\r
652 HighBits = HBufferImageIsAtHighBits (\r
653 HBufferImage.MousePosition.Column,\r
654 &FColumn\r
655 );\r
656\r
657 HasCharacter = TRUE;\r
658 if ((FRow > HBufferImage.NumLines) || (FColumn == 0)) {\r
659 HasCharacter = FALSE;\r
660 } else {\r
661 CurrentLine = HBufferImage.CurrentLine;\r
662 Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);\r
663\r
664 if ((Line == NULL) || (FColumn > Line->Size)) {\r
665 HasCharacter = FALSE;\r
666 }\r
667\r
668 HBufferImage.CurrentLine = CurrentLine;\r
669 }\r
670\r
671 ShellPrintEx (\r
672 (INT32)HBufferImage.MousePosition.Column - 1,\r
673 (INT32)HBufferImage.MousePosition.Row - 1,\r
674 L" "\r
675 );\r
676\r
677 if (HasCharacter) {\r
678 if (HighBits) {\r
679 Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf0);\r
680 Value = (UINT8)(Value >> 4);\r
681 } else {\r
682 Value = (UINT8)(Line->Buffer[FColumn - 1] & 0xf);\r
683 }\r
684\r
685 ShellPrintEx (\r
686 (INT32)HBufferImage.MousePosition.Column - 1,\r
687 (INT32)HBufferImage.MousePosition.Row - 1,\r
688 L"%x",\r
689 Value\r
690 );\r
691 }\r
692\r
693 //\r
694 // end of HasCharacter\r
695 //\r
696 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);\r
697 }\r
698\r
699 //\r
700 // end of MouseNeedRefresh\r
701 //\r
702 }\r
703\r
704 //\r
705 // end of MouseSupported\r
706 //\r
707 return EFI_SUCCESS;\r
708}\r
709\r
710/**\r
711 Set cursor position according to HBufferImage.DisplayPosition.\r
712\r
713 @retval EFI_SUCCESS The operation was successful.\r
714**/\r
715EFI_STATUS\r
716HBufferImageRestorePosition (\r
717 VOID\r
718 )\r
719{\r
720 //\r
721 // set cursor position\r
722 //\r
723 gST->ConOut->SetCursorPosition (\r
724 gST->ConOut,\r
725 HBufferImage.DisplayPosition.Column - 1,\r
726 HBufferImage.DisplayPosition.Row - 1\r
727 );\r
728\r
729 return EFI_SUCCESS;\r
730}\r
731\r
732/**\r
733 Refresh function for HBufferImage.\r
734\r
735 @retval EFI_SUCCESS The operation was successful.\r
736 @retval EFI_LOAD_ERROR A Load error occurred.\r
737\r
738**/\r
739EFI_STATUS\r
740HBufferImageRefresh (\r
741 VOID\r
742 )\r
743{\r
744 LIST_ENTRY *Link;\r
745 HEFI_EDITOR_LINE *Line;\r
746 UINTN Row;\r
747 HEFI_EDITOR_COLOR_UNION Orig;\r
748 HEFI_EDITOR_COLOR_UNION New;\r
749\r
750 UINTN StartRow;\r
751 UINTN EndRow;\r
752 UINTN FStartRow;\r
753 UINTN Tmp;\r
754\r
755 Orig = HMainEditor.ColorAttributes;\r
756 New.Data = 0;\r
757 New.Colors.Foreground = Orig.Colors.Background;\r
758 New.Colors.Background = Orig.Colors.Foreground;\r
759\r
760 //\r
761 // if it's the first time after editor launch, so should refresh\r
762 //\r
763 if (HEditorFirst == FALSE) {\r
764 //\r
765 // no definite required refresh\r
766 // and file position displayed on screen has not been changed\r
767 //\r
768 if (!HBufferImageNeedRefresh &&\r
769 !HBufferImageOnlyLineNeedRefresh &&\r
770 (HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow)\r
771 )\r
772 {\r
773 HBufferImageRestoreMousePosition ();\r
774 HBufferImageRestorePosition ();\r
775 return EFI_SUCCESS;\r
776 }\r
777 }\r
778\r
779 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
780\r
781 //\r
782 // only need to refresh current line\r
783 //\r
784 if (HBufferImageOnlyLineNeedRefresh && (HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow)) {\r
785 HBufferImagePrintLine (\r
786 HBufferImage.CurrentLine,\r
787 HBufferImage.DisplayPosition.Row,\r
788 HBufferImage.BufferPosition.Row,\r
789 Orig,\r
790 New\r
791 );\r
792 } else {\r
793 //\r
794 // the whole edit area need refresh\r
795 //\r
796 if (HEditorMouseAction && (HMainEditor.SelectStart != 0) && (HMainEditor.SelectEnd != 0)) {\r
797 if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) {\r
798 if ((HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart) && (HMainEditorBackupVar.SelectStart != 0)) {\r
799 StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1;\r
800 } else {\r
801 StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
802 }\r
803 } else {\r
804 StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;\r
805 }\r
806\r
807 if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) {\r
808 EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1;\r
809 } else {\r
810 EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1;\r
811 }\r
812\r
813 //\r
814 // swap\r
815 //\r
816 if (StartRow > EndRow) {\r
817 Tmp = StartRow;\r
818 StartRow = EndRow;\r
819 EndRow = Tmp;\r
820 }\r
821\r
822 FStartRow = StartRow;\r
823\r
824 StartRow = 2 + StartRow - HBufferImage.LowVisibleRow;\r
825 EndRow = 2 + EndRow - HBufferImage.LowVisibleRow;\r
826 } else {\r
827 //\r
828 // not mouse selection actions\r
829 //\r
830 FStartRow = HBufferImage.LowVisibleRow;\r
831 StartRow = 2;\r
832 EndRow = (HMainEditor.ScreenSize.Row - 1);\r
833 }\r
834\r
835 //\r
836 // no line\r
837 //\r
838 if (HBufferImage.Lines == NULL) {\r
839 HBufferImageRestoreMousePosition ();\r
840 HBufferImageRestorePosition ();\r
841 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
842 return EFI_SUCCESS;\r
843 }\r
844\r
845 //\r
846 // get the first line that will be displayed\r
847 //\r
848 Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row);\r
849 if (Line == NULL) {\r
850 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
851 return EFI_LOAD_ERROR;\r
852 }\r
853\r
854 Link = &(Line->Link);\r
855 Row = StartRow;\r
856 do {\r
857 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
858\r
859 //\r
860 // print line at row\r
861 //\r
862 HBufferImagePrintLine (\r
863 Line,\r
864 Row,\r
865 HBufferImage.LowVisibleRow + Row - 2,\r
866 Orig,\r
867 New\r
868 );\r
869\r
870 Link = Link->ForwardLink;\r
871 Row++;\r
872 } while (Link != HBufferImage.ListHead && Row <= EndRow);\r
873\r
874 while (Row <= EndRow) {\r
875 EditorClearLine (Row, HMainEditor.ScreenSize.Column, HMainEditor.ScreenSize.Row);\r
876 Row++;\r
877 }\r
878\r
879 //\r
880 // while not file end and not screen full\r
881 //\r
882 }\r
883\r
884 HBufferImageRestoreMousePosition ();\r
885 HBufferImageRestorePosition ();\r
886\r
887 HBufferImageNeedRefresh = FALSE;\r
888 HBufferImageOnlyLineNeedRefresh = FALSE;\r
889 gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
890\r
891 return EFI_SUCCESS;\r
892}\r
893\r
894/**\r
895 Read an image into a buffer friom a source.\r
896\r
897 @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.\r
898 @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.\r
899 @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.\r
900 @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.\r
901 @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.\r
902 @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.\r
903 @param[in] BufferType The type of buffer to save. IGNORED.\r
904 @param[in] Recover TRUE for recovermode, FALSE otherwise.\r
905\r
906 @return EFI_SUCCESS The operation was successful.\r
907**/\r
908EFI_STATUS\r
909HBufferImageRead (\r
910 IN CONST CHAR16 *FileName,\r
911 IN CONST CHAR16 *DiskName,\r
912 IN UINTN DiskOffset,\r
913 IN UINTN DiskSize,\r
914 IN UINTN MemOffset,\r
915 IN UINTN MemSize,\r
916 IN EDIT_FILE_TYPE BufferType,\r
917 IN BOOLEAN Recover\r
918 )\r
919{\r
920 EFI_STATUS Status;\r
921 EDIT_FILE_TYPE BufferTypeBackup;\r
922\r
923 //\r
924 // variable initialization\r
925 //\r
926 Status = EFI_SUCCESS;\r
927 HBufferImage.BufferType = BufferType;\r
928\r
929 //\r
930 // three types of buffer supported\r
931 // file buffer\r
932 // disk buffer\r
933 // memory buffer\r
934 //\r
935 BufferTypeBackup = HBufferImage.BufferType;\r
936\r
937 switch (BufferType) {\r
938 case FileTypeFileBuffer:\r
939 Status = HFileImageRead (FileName, Recover);\r
940 break;\r
941\r
942 case FileTypeDiskBuffer:\r
943 Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);\r
944 break;\r
945\r
946 case FileTypeMemBuffer:\r
947 Status = HMemImageRead (MemOffset, MemSize, Recover);\r
948 break;\r
949\r
950 default:\r
951 Status = EFI_NOT_FOUND;\r
952 break;\r
953 }\r
954\r
955 if (EFI_ERROR (Status)) {\r
956 HBufferImage.BufferType = BufferTypeBackup;\r
957 }\r
958\r
959 return Status;\r
960}\r
961\r
962/**\r
963 Save the current image.\r
964\r
965 @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.\r
966 @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.\r
967 @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.\r
968 @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.\r
969 @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.\r
970 @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.\r
971 @param[in] BufferType The type of buffer to save. IGNORED.\r
972\r
973 @return EFI_SUCCESS The operation was successful.\r
974**/\r
975EFI_STATUS\r
976HBufferImageSave (\r
977 IN CHAR16 *FileName,\r
978 IN CHAR16 *DiskName,\r
979 IN UINTN DiskOffset,\r
980 IN UINTN DiskSize,\r
981 IN UINTN MemOffset,\r
982 IN UINTN MemSize,\r
983 IN EDIT_FILE_TYPE BufferType\r
984 )\r
985{\r
986 EFI_STATUS Status;\r
987 EDIT_FILE_TYPE BufferTypeBackup;\r
988\r
989 //\r
990 // variable initialization\r
991 //\r
992 Status = EFI_SUCCESS;\r
993 BufferTypeBackup = HBufferImage.BufferType;\r
994\r
995 switch (HBufferImage.BufferType) {\r
996 //\r
997 // file buffer\r
998 //\r
999 case FileTypeFileBuffer:\r
1000 Status = HFileImageSave (FileName);\r
1001 break;\r
1002\r
1003 //\r
1004 // disk buffer\r
1005 //\r
1006 case FileTypeDiskBuffer:\r
1007 Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);\r
1008 break;\r
1009\r
1010 //\r
1011 // memory buffer\r
1012 //\r
1013 case FileTypeMemBuffer:\r
1014 Status = HMemImageSave (MemOffset, MemSize);\r
1015 break;\r
1016\r
1017 default:\r
1018 Status = EFI_NOT_FOUND;\r
1019 break;\r
1020 }\r
1021\r
1022 if (EFI_ERROR (Status)) {\r
1023 HBufferImage.BufferType = BufferTypeBackup;\r
1024 }\r
1025\r
1026 return Status;\r
1027}\r
1028\r
1029/**\r
1030 Create a new line and append it to the line list.\r
1031 Fields affected:\r
1032 NumLines\r
1033 Lines\r
1034\r
1035 @retval NULL create line failed.\r
1036 @return the line created.\r
1037\r
1038**/\r
1039HEFI_EDITOR_LINE *\r
1040HBufferImageCreateLine (\r
1041 VOID\r
1042 )\r
1043{\r
1044 HEFI_EDITOR_LINE *Line;\r
1045\r
1046 //\r
1047 // allocate for line structure\r
1048 //\r
1049 Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));\r
1050 if (Line == NULL) {\r
1051 return NULL;\r
1052 }\r
1053\r
1054 Line->Signature = EFI_EDITOR_LINE_LIST;\r
1055 Line->Size = 0;\r
1056\r
1057 HBufferImage.NumLines++;\r
1058\r
1059 //\r
1060 // insert to line list\r
1061 //\r
1062 InsertTailList (HBufferImage.ListHead, &Line->Link);\r
1063\r
1064 if (HBufferImage.Lines == NULL) {\r
1065 HBufferImage.Lines = CR (\r
1066 HBufferImage.ListHead->ForwardLink,\r
1067 HEFI_EDITOR_LINE,\r
1068 Link,\r
1069 EFI_EDITOR_LINE_LIST\r
1070 );\r
1071 }\r
1072\r
1073 return Line;\r
1074}\r
1075\r
1076/**\r
1077 Free the current image.\r
1078\r
1079 @retval EFI_SUCCESS The operation was successful.\r
1080**/\r
1081EFI_STATUS\r
1082HBufferImageFree (\r
1083 VOID\r
1084 )\r
1085{\r
1086 //\r
1087 // free all lines\r
1088 //\r
1089 HBufferImageFreeLines ();\r
1090\r
1091 return EFI_SUCCESS;\r
1092}\r
1093\r
1094/**\r
1095 change char to int value based on Hex.\r
1096\r
1097 @param[in] Char The input char.\r
1098\r
1099 @return The character's index value.\r
1100 @retval -1 The operation failed.\r
1101**/\r
1102INTN\r
1103HBufferImageCharToHex (\r
1104 IN CHAR16 Char\r
1105 )\r
1106{\r
1107 //\r
1108 // change the character to hex\r
1109 //\r
1110 if ((Char >= L'0') && (Char <= L'9')) {\r
1111 return (Char - L'0');\r
1112 }\r
1113\r
1114 if ((Char >= L'a') && (Char <= L'f')) {\r
1115 return (Char - L'a' + 10);\r
1116 }\r
1117\r
1118 if ((Char >= L'A') && (Char <= L'F')) {\r
1119 return (Char - L'A' + 10);\r
1120 }\r
1121\r
1122 return -1;\r
1123}\r
1124\r
1125/**\r
1126 Add character.\r
1127\r
1128 @param[in] Char -- input char.\r
1129\r
1130 @retval EFI_SUCCESS The operation was successful.\r
1131 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1132**/\r
1133EFI_STATUS\r
1134HBufferImageAddChar (\r
1135 IN CHAR16 Char\r
1136 )\r
1137{\r
1138 HEFI_EDITOR_LINE *Line;\r
1139 HEFI_EDITOR_LINE *NewLine;\r
1140 INTN Value;\r
1141 UINT8 Old;\r
1142 UINTN FRow;\r
1143 UINTN FCol;\r
1144 BOOLEAN High;\r
1145\r
1146 Value = HBufferImageCharToHex (Char);\r
1147\r
1148 //\r
1149 // invalid input\r
1150 //\r
1151 if (Value == -1) {\r
1152 return EFI_SUCCESS;\r
1153 }\r
1154\r
1155 Line = HBufferImage.CurrentLine;\r
1156 FRow = HBufferImage.BufferPosition.Row;\r
1157 FCol = HBufferImage.BufferPosition.Column;\r
1158 High = HBufferImage.HighBits;\r
1159\r
1160 //\r
1161 // only needs to refresh current line\r
1162 //\r
1163 HBufferImageOnlyLineNeedRefresh = TRUE;\r
1164\r
1165 //\r
1166 // not a full line and beyond the last character\r
1167 //\r
1168 if (FCol > Line->Size) {\r
1169 //\r
1170 // cursor always at high 4 bits\r
1171 // and always put input to the low 4 bits\r
1172 //\r
1173 Line->Buffer[Line->Size] = (UINT8)Value;\r
1174 Line->Size++;\r
1175 High = FALSE;\r
1176 } else {\r
1177 Old = Line->Buffer[FCol - 1];\r
1178\r
1179 //\r
1180 // always put the input to the low 4 bits\r
1181 //\r
1182 Old = (UINT8)(Old & 0x0f);\r
1183 Old = (UINT8)(Old << 4);\r
1184 Old = (UINT8)(Value + Old);\r
1185 Line->Buffer[FCol - 1] = Old;\r
1186\r
1187 //\r
1188 // at the low 4 bits of the last character of a full line\r
1189 // so if no next line, need to create a new line\r
1190 //\r
1191 if (!High && (FCol == 0x10)) {\r
1192 HBufferImageOnlyLineNeedRefresh = FALSE;\r
1193 HBufferImageNeedRefresh = TRUE;\r
1194\r
1195 if (Line->Link.ForwardLink == HBufferImage.ListHead) {\r
1196 //\r
1197 // last line\r
1198 //\r
1199 // create a new line\r
1200 //\r
1201 NewLine = HBufferImageCreateLine ();\r
1202 if (NewLine == NULL) {\r
1203 return EFI_OUT_OF_RESOURCES;\r
1204 }\r
1205\r
1206 //\r
1207 // end of NULL\r
1208 //\r
1209 }\r
1210\r
1211 //\r
1212 // end of == ListHead\r
1213 //\r
1214 }\r
1215\r
1216 //\r
1217 // end of == 0x10\r
1218 //\r
1219 // if already at end of this line, scroll it to the start of next line\r
1220 //\r
1221 if ((FCol == 0x10) && !High) {\r
1222 //\r
1223 // definitely has next line\r
1224 //\r
1225 FRow++;\r
1226 FCol = 1;\r
1227 High = TRUE;\r
1228 } else {\r
1229 //\r
1230 // if not at end of this line, just move to next column\r
1231 //\r
1232 if (!High) {\r
1233 FCol++;\r
1234 }\r
1235\r
1236 if (High) {\r
1237 High = FALSE;\r
1238 } else {\r
1239 High = TRUE;\r
1240 }\r
1241 }\r
1242\r
1243 //\r
1244 // end of ==FALSE\r
1245 //\r
1246 }\r
1247\r
1248 //\r
1249 // move cursor to right\r
1250 //\r
1251 HBufferImageMovePosition (FRow, FCol, High);\r
1252\r
1253 if (!HBufferImage.Modified) {\r
1254 HBufferImage.Modified = TRUE;\r
1255 }\r
1256\r
1257 return EFI_SUCCESS;\r
1258}\r
1259\r
1260/**\r
1261 Delete the previous character.\r
1262\r
1263 @retval EFI_SUCCESS The operationw as successful.\r
1264**/\r
1265EFI_STATUS\r
1266HBufferImageDoBackspace (\r
1267 VOID\r
1268 )\r
1269{\r
1270 HEFI_EDITOR_LINE *Line;\r
1271\r
1272 UINTN FileColumn;\r
1273 UINTN FPos;\r
1274 BOOLEAN LastLine;\r
1275\r
1276 //\r
1277 // variable initialization\r
1278 //\r
1279 LastLine = FALSE;\r
1280\r
1281 //\r
1282 // already the first character\r
1283 //\r
1284 if ((HBufferImage.BufferPosition.Row == 1) && (HBufferImage.BufferPosition.Column == 1)) {\r
1285 return EFI_SUCCESS;\r
1286 }\r
1287\r
1288 FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;\r
1289\r
1290 FileColumn = HBufferImage.BufferPosition.Column;\r
1291\r
1292 Line = HBufferImage.CurrentLine;\r
1293 LastLine = FALSE;\r
1294 if ((Line->Link.ForwardLink == HBufferImage.ListHead) && (FileColumn > 1)) {\r
1295 LastLine = TRUE;\r
1296 }\r
1297\r
1298 HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);\r
1299\r
1300 //\r
1301 // if is the last line\r
1302 // then only this line need to be refreshed\r
1303 //\r
1304 if (LastLine) {\r
1305 HBufferImageNeedRefresh = FALSE;\r
1306 HBufferImageOnlyLineNeedRefresh = TRUE;\r
1307 } else {\r
1308 HBufferImageNeedRefresh = TRUE;\r
1309 HBufferImageOnlyLineNeedRefresh = FALSE;\r
1310 }\r
1311\r
1312 if (!HBufferImage.Modified) {\r
1313 HBufferImage.Modified = TRUE;\r
1314 }\r
1315\r
1316 return EFI_SUCCESS;\r
1317}\r
1318\r
1319/**\r
1320 ASCII key + Backspace + return.\r
1321\r
1322 @param[in] Char The input char.\r
1323\r
1324 @retval EFI_SUCCESS The operation was successful.\r
1325 @retval EFI_LOAD_ERROR A load error occurred.\r
1326 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1327**/\r
1328EFI_STATUS\r
1329HBufferImageDoCharInput (\r
1330 IN CHAR16 Char\r
1331 )\r
1332{\r
1333 EFI_STATUS Status;\r
1334\r
1335 Status = EFI_SUCCESS;\r
1336\r
1337 switch (Char) {\r
1338 case 0:\r
1339 break;\r
1340\r
1341 case 0x08:\r
1342 Status = HBufferImageDoBackspace ();\r
1343 break;\r
1344\r
1345 case 0x09:\r
1346 case 0x0a:\r
1347 case 0x0d:\r
1348 //\r
1349 // Tabs, Returns are thought as nothing\r
1350 //\r
1351 break;\r
1352\r
1353 default:\r
1354 //\r
1355 // DEAL WITH ASCII CHAR, filter out thing like ctrl+f\r
1356 //\r
1357 if ((Char > 127) || (Char < 32)) {\r
1358 Status = StatusBarSetStatusString (L"Unknown Command");\r
1359 } else {\r
1360 Status = HBufferImageAddChar (Char);\r
1361 }\r
1362\r
1363 break;\r
1364 }\r
1365\r
1366 return Status;\r
1367}\r
1368\r
1369/**\r
1370 Check user specified FileRow is above current screen.\r
1371\r
1372 @param[in] FileRow Row of file position ( start from 1 ).\r
1373\r
1374 @retval TRUE It is above the current screen.\r
1375 @retval FALSE It is not above the current screen.\r
1376\r
1377**/\r
1378BOOLEAN\r
1379HAboveCurrentScreen (\r
1380 IN UINTN FileRow\r
1381 )\r
1382{\r
1383 if (FileRow < HBufferImage.LowVisibleRow) {\r
1384 return TRUE;\r
1385 }\r
1386\r
1387 return FALSE;\r
1388}\r
1389\r
1390/**\r
1391 Check user specified FileRow is under current screen.\r
1392\r
1393 @param[in] FileRow Row of file position ( start from 1 ).\r
1394\r
1395 @retval TRUE It is under the current screen.\r
1396 @retval FALSE It is not under the current screen.\r
1397\r
1398**/\r
1399BOOLEAN\r
1400HUnderCurrentScreen (\r
1401 IN UINTN FileRow\r
1402 )\r
1403{\r
1404 if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) {\r
1405 return TRUE;\r
1406 }\r
1407\r
1408 return FALSE;\r
1409}\r
1410\r
1411/**\r
1412 According to cursor's file position, adjust screen display.\r
1413\r
1414 @param[in] NewFilePosRow Row of file position ( start from 1 ).\r
1415 @param[in] NewFilePosCol Column of file position ( start from 1 ).\r
1416 @param[in] HighBits Cursor will on high4 bits or low4 bits.\r
1417**/\r
1418VOID\r
1419HBufferImageMovePosition (\r
1420 IN UINTN NewFilePosRow,\r
1421 IN UINTN NewFilePosCol,\r
1422 IN BOOLEAN HighBits\r
1423 )\r
1424{\r
1425 INTN RowGap;\r
1426 UINTN Abs;\r
1427 BOOLEAN Above;\r
1428 BOOLEAN Under;\r
1429 UINTN NewDisplayCol;\r
1430\r
1431 //\r
1432 // CALCULATE gap between current file position and new file position\r
1433 //\r
1434 RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row;\r
1435\r
1436 Under = HUnderCurrentScreen (NewFilePosRow);\r
1437 Above = HAboveCurrentScreen (NewFilePosRow);\r
1438\r
1439 HBufferImage.HighBits = HighBits;\r
1440\r
1441 //\r
1442 // if is below current screen\r
1443 //\r
1444 if (Under) {\r
1445 //\r
1446 // display row will be unchanged\r
1447 //\r
1448 HBufferImage.BufferPosition.Row = NewFilePosRow;\r
1449 } else {\r
1450 if (Above) {\r
1451 //\r
1452 // has enough above line, so display row unchanged\r
1453 // not has enough above lines, so the first line is\r
1454 // at the first display line\r
1455 //\r
1456 if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {\r
1457 HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;\r
1458 }\r
1459\r
1460 HBufferImage.BufferPosition.Row = NewFilePosRow;\r
1461 } else {\r
1462 //\r
1463 // in current screen\r
1464 //\r
1465 HBufferImage.BufferPosition.Row = NewFilePosRow;\r
1466 if (RowGap <= 0) {\r
1467 Abs = (UINTN)ABS (RowGap);\r
1468 HBufferImage.DisplayPosition.Row -= Abs;\r
1469 } else {\r
1470 HBufferImage.DisplayPosition.Row += RowGap;\r
1471 }\r
1472 }\r
1473 }\r
1474\r
1475 HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);\r
1476\r
1477 //\r
1478 // always in current screen\r
1479 //\r
1480 HBufferImage.BufferPosition.Column = NewFilePosCol;\r
1481\r
1482 NewDisplayCol = 10 + (NewFilePosCol - 1) * 3;\r
1483 if (NewFilePosCol > 0x8) {\r
1484 NewDisplayCol++;\r
1485 }\r
1486\r
1487 if (!HighBits) {\r
1488 NewDisplayCol++;\r
1489 }\r
1490\r
1491 HBufferImage.DisplayPosition.Column = NewDisplayCol;\r
1492\r
1493 //\r
1494 // let CurrentLine point to correct line;\r
1495 //\r
1496 HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);\r
1497}\r
1498\r
1499/**\r
1500 Scroll cursor to right.\r
1501\r
1502 @retval EFI_SUCCESS The operation was successful.\r
1503**/\r
1504EFI_STATUS\r
1505HBufferImageScrollRight (\r
1506 VOID\r
1507 )\r
1508{\r
1509 HEFI_EDITOR_LINE *Line;\r
1510 UINTN FRow;\r
1511 UINTN FCol;\r
1512\r
1513 //\r
1514 // scroll right will always move to the high4 bits of the next character\r
1515 //\r
1516 HBufferImageNeedRefresh = FALSE;\r
1517 HBufferImageOnlyLineNeedRefresh = FALSE;\r
1518\r
1519 Line = HBufferImage.CurrentLine;\r
1520\r
1521 FRow = HBufferImage.BufferPosition.Row;\r
1522 FCol = HBufferImage.BufferPosition.Column;\r
1523\r
1524 //\r
1525 // this line is not full and no next line\r
1526 //\r
1527 if (FCol > Line->Size) {\r
1528 return EFI_SUCCESS;\r
1529 }\r
1530\r
1531 //\r
1532 // if already at end of this line, scroll it to the start of next line\r
1533 //\r
1534 if (FCol == 0x10) {\r
1535 //\r
1536 // has next line\r
1537 //\r
1538 if (Line->Link.ForwardLink != HBufferImage.ListHead) {\r
1539 FRow++;\r
1540 FCol = 1;\r
1541 } else {\r
1542 return EFI_SUCCESS;\r
1543 }\r
1544 } else {\r
1545 //\r
1546 // if not at end of this line, just move to next column\r
1547 //\r
1548 FCol++;\r
1549 }\r
1550\r
1551 HBufferImageMovePosition (FRow, FCol, TRUE);\r
1552\r
1553 return EFI_SUCCESS;\r
1554}\r
1555\r
1556/**\r
1557 Scroll cursor to left.\r
1558\r
1559 @retval EFI_SUCCESS The operation was successful.\r
1560**/\r
1561EFI_STATUS\r
1562HBufferImageScrollLeft (\r
1563 VOID\r
1564 )\r
1565{\r
1566 HEFI_EDITOR_LINE *Line;\r
1567 UINTN FRow;\r
1568 UINTN FCol;\r
1569\r
1570 HBufferImageNeedRefresh = FALSE;\r
1571 HBufferImageOnlyLineNeedRefresh = FALSE;\r
1572\r
1573 Line = HBufferImage.CurrentLine;\r
1574\r
1575 FRow = HBufferImage.BufferPosition.Row;\r
1576 FCol = HBufferImage.BufferPosition.Column;\r
1577\r
1578 //\r
1579 // if already at start of this line, so move to the end of previous line\r
1580 //\r
1581 if (FCol <= 1) {\r
1582 //\r
1583 // has previous line\r
1584 //\r
1585 if (Line->Link.BackLink != HBufferImage.ListHead) {\r
1586 FRow--;\r
1587 Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
1588 FCol = Line->Size;\r
1589 } else {\r
1590 return EFI_SUCCESS;\r
1591 }\r
1592 } else {\r
1593 //\r
1594 // if not at start of this line, just move to previous column\r
1595 //\r
1596 FCol--;\r
1597 }\r
1598\r
1599 HBufferImageMovePosition (FRow, FCol, TRUE);\r
1600\r
1601 return EFI_SUCCESS;\r
1602}\r
1603\r
1604/**\r
1605 Scroll cursor to the next line\r
1606\r
1607 @retval EFI_SUCCESS The operation was successful.\r
1608**/\r
1609EFI_STATUS\r
1610HBufferImageScrollDown (\r
1611 VOID\r
1612 )\r
1613{\r
1614 HEFI_EDITOR_LINE *Line;\r
1615 UINTN FRow;\r
1616 UINTN FCol;\r
1617 BOOLEAN HighBits;\r
1618\r
1619 Line = HBufferImage.CurrentLine;\r
1620\r
1621 FRow = HBufferImage.BufferPosition.Row;\r
1622 FCol = HBufferImage.BufferPosition.Column;\r
1623 HighBits = HBufferImage.HighBits;\r
1624\r
1625 //\r
1626 // has next line\r
1627 //\r
1628 if (Line->Link.ForwardLink != HBufferImage.ListHead) {\r
1629 FRow++;\r
1630 Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
1631\r
1632 //\r
1633 // if the next line is not that long, so move to end of next line\r
1634 //\r
1635 if (FCol > Line->Size) {\r
1636 FCol = Line->Size + 1;\r
1637 HighBits = TRUE;\r
1638 }\r
1639 } else {\r
1640 return EFI_SUCCESS;\r
1641 }\r
1642\r
1643 HBufferImageMovePosition (FRow, FCol, HighBits);\r
1644\r
1645 return EFI_SUCCESS;\r
1646}\r
1647\r
1648/**\r
1649 Scroll cursor to previous line\r
1650\r
1651 @retval EFI_SUCCESS The operation was successful.\r
1652**/\r
1653EFI_STATUS\r
1654HBufferImageScrollUp (\r
1655 VOID\r
1656 )\r
1657{\r
1658 HEFI_EDITOR_LINE *Line;\r
1659 UINTN FRow;\r
1660 UINTN FCol;\r
1661\r
1662 Line = HBufferImage.CurrentLine;\r
1663\r
1664 FRow = HBufferImage.BufferPosition.Row;\r
1665 FCol = HBufferImage.BufferPosition.Column;\r
1666\r
1667 //\r
1668 // has previous line\r
1669 //\r
1670 if (Line->Link.BackLink != HBufferImage.ListHead) {\r
1671 FRow--;\r
1672 } else {\r
1673 return EFI_SUCCESS;\r
1674 }\r
1675\r
1676 HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);\r
1677\r
1678 return EFI_SUCCESS;\r
1679}\r
1680\r
1681/**\r
1682 Scroll cursor to next page\r
1683\r
1684 @retval EFI_SUCCESS The operation was successful.\r
1685**/\r
1686EFI_STATUS\r
1687HBufferImagePageDown (\r
1688 VOID\r
1689 )\r
1690{\r
1691 HEFI_EDITOR_LINE *Line;\r
1692 UINTN FRow;\r
1693 UINTN FCol;\r
1694 UINTN Gap;\r
1695 BOOLEAN HighBits;\r
1696\r
1697 Line = HBufferImage.CurrentLine;\r
1698\r
1699 FRow = HBufferImage.BufferPosition.Row;\r
1700 FCol = HBufferImage.BufferPosition.Column;\r
1701 HighBits = HBufferImage.HighBits;\r
1702\r
1703 //\r
1704 // has next page\r
1705 //\r
1706 if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) {\r
1707 Gap = (HMainEditor.ScreenSize.Row - 2);\r
1708 } else {\r
1709 //\r
1710 // MOVE CURSOR TO LAST LINE\r
1711 //\r
1712 Gap = HBufferImage.NumLines - FRow;\r
1713 }\r
1714\r
1715 //\r
1716 // get correct line\r
1717 //\r
1718 Line = HMoveLine (Gap);\r
1719\r
1720 //\r
1721 // if that line, is not that long, so move to the end of that line\r
1722 //\r
1723 if ((Line != NULL) && (FCol > Line->Size)) {\r
1724 FCol = Line->Size + 1;\r
1725 HighBits = TRUE;\r
1726 }\r
1727\r
1728 FRow += Gap;\r
1729\r
1730 HBufferImageMovePosition (FRow, FCol, HighBits);\r
1731\r
1732 return EFI_SUCCESS;\r
1733}\r
1734\r
1735/**\r
1736 Scroll cursor to previous page\r
1737\r
1738 @retval EFI_SUCCESS The operation was successful.\r
1739**/\r
1740EFI_STATUS\r
1741HBufferImagePageUp (\r
1742 VOID\r
1743 )\r
1744{\r
1745 UINTN FRow;\r
1746 UINTN FCol;\r
1747 UINTN Gap;\r
1748 INTN Retreat;\r
1749\r
1750 FRow = HBufferImage.BufferPosition.Row;\r
1751 FCol = HBufferImage.BufferPosition.Column;\r
1752\r
1753 //\r
1754 // has previous page\r
1755 //\r
1756 if (FRow > (HMainEditor.ScreenSize.Row - 2)) {\r
1757 Gap = (HMainEditor.ScreenSize.Row - 2);\r
1758 } else {\r
1759 //\r
1760 // the first line of file will displayed on the first line of screen\r
1761 //\r
1762 Gap = FRow - 1;\r
1763 }\r
1764\r
1765 Retreat = Gap;\r
1766 Retreat = -Retreat;\r
1767\r
1768 FRow -= Gap;\r
1769\r
1770 HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);\r
1771\r
1772 return EFI_SUCCESS;\r
1773}\r
1774\r
1775/**\r
1776 Scroll cursor to start of line\r
1777\r
1778 @retval EFI_SUCCESS The operation was successful.\r
1779**/\r
1780EFI_STATUS\r
1781HBufferImageHome (\r
1782 VOID\r
1783 )\r
1784{\r
1785 UINTN FRow;\r
1786 UINTN FCol;\r
1787 BOOLEAN HighBits;\r
1788\r
1789 //\r
1790 // curosr will at the high bit\r
1791 //\r
1792 FRow = HBufferImage.BufferPosition.Row;\r
1793 FCol = 1;\r
1794 HighBits = TRUE;\r
1795\r
1796 //\r
1797 // move cursor position\r
1798 //\r
1799 HBufferImageMovePosition (FRow, FCol, HighBits);\r
1800\r
1801 return EFI_SUCCESS;\r
1802}\r
1803\r
1804/**\r
1805 Scroll cursor to end of line.\r
1806\r
1807 @retval EFI_SUCCESS Teh operation was successful.\r
1808**/\r
1809EFI_STATUS\r
1810HBufferImageEnd (\r
1811 VOID\r
1812 )\r
1813{\r
1814 HEFI_EDITOR_LINE *Line;\r
1815 UINTN FRow;\r
1816 UINTN FCol;\r
1817 BOOLEAN HighBits;\r
1818\r
1819 //\r
1820 // need refresh mouse\r
1821 //\r
1822 HBufferImageMouseNeedRefresh = TRUE;\r
1823\r
1824 Line = HBufferImage.CurrentLine;\r
1825\r
1826 FRow = HBufferImage.BufferPosition.Row;\r
1827\r
1828 if (Line->Size == 0x10) {\r
1829 FCol = Line->Size;\r
1830 HighBits = FALSE;\r
1831 } else {\r
1832 FCol = Line->Size + 1;\r
1833 HighBits = TRUE;\r
1834 }\r
1835\r
1836 //\r
1837 // move cursor position\r
1838 //\r
1839 HBufferImageMovePosition (FRow, FCol, HighBits);\r
1840\r
1841 return EFI_SUCCESS;\r
1842}\r
1843\r
1844/**\r
1845 Get the size of the open buffer.\r
1846\r
1847 @retval The size in bytes.\r
1848**/\r
1849UINTN\r
1850HBufferImageGetTotalSize (\r
1851 VOID\r
1852 )\r
1853{\r
1854 UINTN Size;\r
1855\r
1856 HEFI_EDITOR_LINE *Line;\r
1857\r
1858 //\r
1859 // calculate the total size of whole line list's buffer\r
1860 //\r
1861 if (HBufferImage.Lines == NULL) {\r
1862 return 0;\r
1863 }\r
1864\r
1865 Line = CR (\r
1866 HBufferImage.ListHead->BackLink,\r
1867 HEFI_EDITOR_LINE,\r
1868 Link,\r
1869 EFI_EDITOR_LINE_LIST\r
1870 );\r
1871 //\r
1872 // one line at most 0x10\r
1873 //\r
1874 Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;\r
1875\r
1876 return Size;\r
1877}\r
1878\r
1879/**\r
1880 Delete character from buffer.\r
1881\r
1882 @param[in] Pos Position, Pos starting from 0.\r
1883 @param[in] Count The Count of characters to delete.\r
1884 @param[out] DeleteBuffer The DeleteBuffer.\r
1885\r
1886 @retval EFI_SUCCESS Success\r
1887**/\r
1888EFI_STATUS\r
1889HBufferImageDeleteCharacterFromBuffer (\r
1890 IN UINTN Pos,\r
1891 IN UINTN Count,\r
1892 OUT UINT8 *DeleteBuffer\r
1893 )\r
1894{\r
1895 UINTN Index;\r
1896\r
1897 VOID *Buffer;\r
1898 UINT8 *BufferPtr;\r
1899 UINTN Size;\r
1900\r
1901 HEFI_EDITOR_LINE *Line;\r
1902 LIST_ENTRY *Link;\r
1903\r
1904 UINTN OldFCol;\r
1905 UINTN OldFRow;\r
1906 UINTN OldPos;\r
1907\r
1908 UINTN NewPos;\r
1909\r
1910 EFI_STATUS Status;\r
1911\r
1912 Size = HBufferImageGetTotalSize ();\r
1913\r
1914 if (Size < Count) {\r
1915 return EFI_LOAD_ERROR;\r
1916 }\r
1917\r
1918 if (Size == 0) {\r
1919 return EFI_SUCCESS;\r
1920 }\r
1921\r
1922 //\r
1923 // relocate all the HBufferImage fields\r
1924 //\r
1925 OldFRow = HBufferImage.BufferPosition.Row;\r
1926 OldFCol = HBufferImage.BufferPosition.Column;\r
1927 OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;\r
1928\r
1929 if (Pos > 0) {\r
1930 //\r
1931 // has character before it,\r
1932 // so locate according to block's previous character\r
1933 //\r
1934 NewPos = Pos - 1;\r
1935 } else {\r
1936 //\r
1937 // has no character before it,\r
1938 // so locate according to block's next character\r
1939 //\r
1940 NewPos = 0;\r
1941 }\r
1942\r
1943 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
1944\r
1945 Buffer = AllocateZeroPool (Size);\r
1946 if (Buffer == NULL) {\r
1947 return EFI_OUT_OF_RESOURCES;\r
1948 }\r
1949\r
1950 HBufferImageListToBuffer (Buffer, Size);\r
1951\r
1952 BufferPtr = (UINT8 *)Buffer;\r
1953\r
1954 //\r
1955 // pass deleted buffer out\r
1956 //\r
1957 if (DeleteBuffer != NULL) {\r
1958 for (Index = 0; Index < Count; Index++) {\r
1959 DeleteBuffer[Index] = BufferPtr[Pos + Index];\r
1960 }\r
1961 }\r
1962\r
1963 //\r
1964 // delete the part from Pos\r
1965 //\r
1966 for (Index = Pos; Index < Size - Count; Index++) {\r
1967 BufferPtr[Index] = BufferPtr[Index + Count];\r
1968 }\r
1969\r
1970 Size -= Count;\r
1971\r
1972 HBufferImageFreeLines ();\r
1973\r
1974 Status = HBufferImageBufferToList (Buffer, Size);\r
1975 FreePool (Buffer);\r
1976\r
1977 if (EFI_ERROR (Status)) {\r
1978 return Status;\r
1979 }\r
1980\r
1981 Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
1982 for (Index = 0; Index < NewPos / 0x10; Index++) {\r
1983 Link = Link->ForwardLink;\r
1984 }\r
1985\r
1986 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
1987 HBufferImage.CurrentLine = Line;\r
1988\r
1989 //\r
1990 // if current cursor position if inside select area\r
1991 // then move it to the block's NEXT character\r
1992 //\r
1993 if ((OldPos >= Pos) && (OldPos < (Pos + Count))) {\r
1994 NewPos = Pos;\r
1995 } else {\r
1996 if (OldPos < Pos) {\r
1997 NewPos = OldPos;\r
1998 } else {\r
1999 NewPos = OldPos - Count;\r
2000 }\r
2001 }\r
2002\r
2003 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
2004\r
2005 return EFI_SUCCESS;\r
2006}\r
2007\r
2008/**\r
2009 Add character to buffer, add before pos.\r
2010\r
2011 @param[in] Pos Position, Pos starting from 0.\r
2012 @param[in] Count Count of characters to add.\r
2013 @param[in] AddBuffer Add buffer.\r
2014\r
2015 @retval EFI_SUCCESS Success.\r
2016**/\r
2017EFI_STATUS\r
2018HBufferImageAddCharacterToBuffer (\r
2019 IN UINTN Pos,\r
2020 IN UINTN Count,\r
2021 IN UINT8 *AddBuffer\r
2022 )\r
2023{\r
2024 INTN Index;\r
2025\r
2026 VOID *Buffer;\r
2027 UINT8 *BufferPtr;\r
2028 UINTN Size;\r
2029\r
2030 HEFI_EDITOR_LINE *Line;\r
2031\r
2032 LIST_ENTRY *Link;\r
2033\r
2034 UINTN OldFCol;\r
2035 UINTN OldFRow;\r
2036 UINTN OldPos;\r
2037\r
2038 UINTN NewPos;\r
2039\r
2040 Size = HBufferImageGetTotalSize ();\r
2041\r
2042 //\r
2043 // relocate all the HBufferImage fields\r
2044 //\r
2045 OldFRow = HBufferImage.BufferPosition.Row;\r
2046 OldFCol = HBufferImage.BufferPosition.Column;\r
2047 OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;\r
2048\r
2049 //\r
2050 // move cursor before Pos\r
2051 //\r
2052 if (Pos > 0) {\r
2053 NewPos = Pos - 1;\r
2054 } else {\r
2055 NewPos = 0;\r
2056 }\r
2057\r
2058 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
2059\r
2060 Buffer = AllocateZeroPool (Size + Count);\r
2061 if (Buffer == NULL) {\r
2062 return EFI_OUT_OF_RESOURCES;\r
2063 }\r
2064\r
2065 HBufferImageListToBuffer (Buffer, Size);\r
2066\r
2067 BufferPtr = (UINT8 *)Buffer;\r
2068\r
2069 //\r
2070 // get a place to add\r
2071 //\r
2072 for (Index = (INTN)(Size + Count - 1); Index >= (INTN)Pos; Index--) {\r
2073 BufferPtr[Index] = BufferPtr[Index - Count];\r
2074 }\r
2075\r
2076 //\r
2077 // add the buffer\r
2078 //\r
2079 for (Index = (INTN)0; Index < (INTN)Count; Index++) {\r
2080 BufferPtr[Index + Pos] = AddBuffer[Index];\r
2081 }\r
2082\r
2083 Size += Count;\r
2084\r
2085 HBufferImageFreeLines ();\r
2086\r
2087 HBufferImageBufferToList (Buffer, Size);\r
2088\r
2089 FreePool (Buffer);\r
2090\r
2091 Link = HMainEditor.BufferImage->ListHead->ForwardLink;\r
2092 for (Index = 0; Index < (INTN)NewPos / 0x10; Index++) {\r
2093 Link = Link->ForwardLink;\r
2094 }\r
2095\r
2096 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
2097 HBufferImage.CurrentLine = Line;\r
2098\r
2099 if (OldPos >= Pos) {\r
2100 NewPos = OldPos + Count;\r
2101 } else {\r
2102 NewPos = OldPos;\r
2103 }\r
2104\r
2105 HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);\r
2106\r
2107 return EFI_SUCCESS;\r
2108}\r
2109\r
2110/**\r
2111 Delete current character from line.\r
2112\r
2113 @retval EFI_SUCCESS The operationw as successful.\r
2114**/\r
2115EFI_STATUS\r
2116HBufferImageDoDelete (\r
2117 VOID\r
2118 )\r
2119{\r
2120 HEFI_EDITOR_LINE *Line;\r
2121\r
2122 BOOLEAN LastLine;\r
2123 UINTN FileColumn;\r
2124 UINTN FPos;\r
2125\r
2126 FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;\r
2127\r
2128 FileColumn = HBufferImage.BufferPosition.Column;\r
2129\r
2130 Line = HBufferImage.CurrentLine;\r
2131\r
2132 //\r
2133 // if beyond the last character\r
2134 //\r
2135 if (FileColumn > Line->Size) {\r
2136 return EFI_SUCCESS;\r
2137 }\r
2138\r
2139 LastLine = FALSE;\r
2140 if (Line->Link.ForwardLink == HBufferImage.ListHead) {\r
2141 LastLine = TRUE;\r
2142 }\r
2143\r
2144 HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);\r
2145\r
2146 //\r
2147 // if is the last line\r
2148 // then only this line need to be refreshed\r
2149 //\r
2150 if (LastLine) {\r
2151 HBufferImageNeedRefresh = FALSE;\r
2152 HBufferImageOnlyLineNeedRefresh = TRUE;\r
2153 } else {\r
2154 HBufferImageNeedRefresh = TRUE;\r
2155 HBufferImageOnlyLineNeedRefresh = FALSE;\r
2156 }\r
2157\r
2158 if (!HBufferImage.Modified) {\r
2159 HBufferImage.Modified = TRUE;\r
2160 }\r
2161\r
2162 return EFI_SUCCESS;\r
2163}\r
2164\r
2165/**\r
2166 Change the raw buffer to a list of lines for the UI.\r
2167\r
2168 @param[in] Buffer The pointer to the buffer to fill.\r
2169 @param[in] Bytes The size of the buffer in bytes.\r
2170\r
2171 @retval EFI_SUCCESS The operation was successful.\r
2172 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
2173**/\r
2174EFI_STATUS\r
2175HBufferImageBufferToList (\r
2176 IN VOID *Buffer,\r
2177 IN UINTN Bytes\r
2178 )\r
2179{\r
2180 UINTN TempI;\r
2181 UINTN TempJ;\r
2182 UINTN Left;\r
2183 HEFI_EDITOR_LINE *Line;\r
2184 UINT8 *BufferPtr;\r
2185\r
2186 TempI = 0;\r
2187 Left = 0;\r
2188 BufferPtr = (UINT8 *)Buffer;\r
2189\r
2190 //\r
2191 // parse file content line by line\r
2192 //\r
2193 while (TempI < Bytes) {\r
2194 if (Bytes - TempI >= 0x10) {\r
2195 Left = 0x10;\r
2196 } else {\r
2197 Left = Bytes - TempI;\r
2198 }\r
2199\r
2200 //\r
2201 // allocate a new line\r
2202 //\r
2203 Line = HBufferImageCreateLine ();\r
2204 if (Line == NULL) {\r
2205 return EFI_OUT_OF_RESOURCES;\r
2206 }\r
2207\r
2208 Line->Size = Left;\r
2209\r
2210 for (TempJ = 0; TempJ < Left; TempJ++) {\r
2211 Line->Buffer[TempJ] = BufferPtr[TempI];\r
2212 TempI++;\r
2213 }\r
2214 }\r
2215\r
2216 //\r
2217 // last line is a full line, SO create a new line\r
2218 //\r
2219 if ((Left == 0x10) || (Bytes == 0)) {\r
2220 Line = HBufferImageCreateLine ();\r
2221 if (Line == NULL) {\r
2222 return EFI_OUT_OF_RESOURCES;\r
2223 }\r
2224 }\r
2225\r
2226 return EFI_SUCCESS;\r
2227}\r
2228\r
2229/**\r
2230 Change the list of lines from the UI to a raw buffer.\r
2231\r
2232 @param[in] Buffer The pointer to the buffer to fill.\r
2233 @param[in] Bytes The size of the buffer in bytes.\r
2234\r
2235 @retval EFI_SUCCESS The operation was successful.\r
2236**/\r
2237EFI_STATUS\r
2238HBufferImageListToBuffer (\r
2239 IN VOID *Buffer,\r
2240 IN UINTN Bytes\r
2241 )\r
2242{\r
2243 UINTN Count;\r
2244 UINTN Index;\r
2245 HEFI_EDITOR_LINE *Line;\r
2246 LIST_ENTRY *Link;\r
2247 UINT8 *BufferPtr;\r
2248\r
2249 //\r
2250 // change the line list to a large buffer\r
2251 //\r
2252 if (HBufferImage.Lines == NULL) {\r
2253 return EFI_SUCCESS;\r
2254 }\r
2255\r
2256 Link = &HBufferImage.Lines->Link;\r
2257 Count = 0;\r
2258 BufferPtr = (UINT8 *)Buffer;\r
2259\r
2260 //\r
2261 // deal line by line\r
2262 //\r
2263 while (Link != HBufferImage.ListHead) {\r
2264 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);\r
2265\r
2266 // @todo shouldn't this be an error???\r
2267 if (Count + Line->Size > Bytes) {\r
2268 return EFI_SUCCESS;\r
2269 }\r
2270\r
2271 for (Index = 0; Index < Line->Size; Index++) {\r
2272 BufferPtr[Index] = Line->Buffer[Index];\r
2273 }\r
2274\r
2275 Count += Line->Size;\r
2276 BufferPtr += Line->Size;\r
2277\r
2278 Link = Link->ForwardLink;\r
2279 }\r
2280\r
2281 return EFI_SUCCESS;\r
2282}\r
2283\r
2284/**\r
2285 Move the mouse in the image buffer.\r
2286\r
2287 @param[in] TextX The x-coordinate.\r
2288 @param[in] TextY The y-coordinate.\r
2289**/\r
2290VOID\r
2291HBufferImageAdjustMousePosition (\r
2292 IN INT32 TextX,\r
2293 IN INT32 TextY\r
2294 )\r
2295{\r
2296 UINTN TempX;\r
2297 UINTN TempY;\r
2298 UINTN AbsX;\r
2299 UINTN AbsY;\r
2300\r
2301 //\r
2302 // TextX and TextY is mouse movement data returned by mouse driver\r
2303 // This function will change it to MousePosition\r
2304 //\r
2305 //\r
2306 // get absolute TempX value\r
2307 //\r
2308 if (TextX >= 0) {\r
2309 AbsX = TextX;\r
2310 } else {\r
2311 AbsX = -TextX;\r
2312 }\r
2313\r
2314 //\r
2315 // get absolute TempY value\r
2316 //\r
2317 if (TextY >= 0) {\r
2318 AbsY = TextY;\r
2319 } else {\r
2320 AbsY = -TextY;\r
2321 }\r
2322\r
2323 TempX = HBufferImage.MousePosition.Column;\r
2324 TempY = HBufferImage.MousePosition.Row;\r
2325\r
2326 if (TextX >= 0) {\r
2327 TempX += TextX;\r
2328 } else {\r
2329 if (TempX >= AbsX) {\r
2330 TempX -= AbsX;\r
2331 } else {\r
2332 TempX = 0;\r
2333 }\r
2334 }\r
2335\r
2336 if (TextY >= 0) {\r
2337 TempY += TextY;\r
2338 } else {\r
2339 if (TempY >= AbsY) {\r
2340 TempY -= AbsY;\r
2341 } else {\r
2342 TempY = 0;\r
2343 }\r
2344 }\r
2345\r
2346 //\r
2347 // check whether new mouse column position is beyond screen\r
2348 // if not, adjust it\r
2349 //\r
2350 if ((TempX >= 10) && (TempX <= (10 + 0x10 * 3 - 1))) {\r
2351 HBufferImage.MousePosition.Column = TempX;\r
2352 } else if (TempX < 10) {\r
2353 HBufferImage.MousePosition.Column = 10;\r
2354 } else if (TempX > (10 + 0x10 * 3 - 1)) {\r
2355 HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;\r
2356 }\r
2357\r
2358 //\r
2359 // check whether new mouse row position is beyond screen\r
2360 // if not, adjust it\r
2361 //\r
2362 if ((TempY >= 2) && (TempY <= (HMainEditor.ScreenSize.Row - 1))) {\r
2363 HBufferImage.MousePosition.Row = TempY;\r
2364 } else if (TempY < 2) {\r
2365 HBufferImage.MousePosition.Row = 2;\r
2366 } else if (TempY > (HMainEditor.ScreenSize.Row - 1)) {\r
2367 HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1);\r
2368 }\r
2369}\r
2370\r
2371/**\r
2372 Dispatch input to different handler\r
2373\r
2374 @param[in] Key The input key:\r
2375 the keys can be:\r
2376 ASCII KEY\r
2377 Backspace/Delete\r
2378 Direction key: up/down/left/right/pgup/pgdn\r
2379 Home/End\r
2380 INS\r
2381\r
2382 @retval EFI_SUCCESS The operation was successful.\r
2383 @retval EFI_LOAD_ERROR A load error occurred.\r
2384 @retval EFI_OUT_OF_RESOURCES A Memory allocation failed.\r
2385**/\r
2386EFI_STATUS\r
2387HBufferImageHandleInput (\r
2388 IN EFI_INPUT_KEY *Key\r
2389 )\r
2390{\r
2391 EFI_STATUS Status;\r
2392\r
2393 Status = EFI_SUCCESS;\r
2394\r
2395 switch (Key->ScanCode) {\r
2396 //\r
2397 // ordinary key\r
2398 //\r
2399 case SCAN_NULL:\r
2400 Status = HBufferImageDoCharInput (Key->UnicodeChar);\r
2401 break;\r
2402\r
2403 //\r
2404 // up arrow\r
2405 //\r
2406 case SCAN_UP:\r
2407 Status = HBufferImageScrollUp ();\r
2408 break;\r
2409\r
2410 //\r
2411 // down arrow\r
2412 //\r
2413 case SCAN_DOWN:\r
2414 Status = HBufferImageScrollDown ();\r
2415 break;\r
2416\r
2417 //\r
2418 // right arrow\r
2419 //\r
2420 case SCAN_RIGHT:\r
2421 Status = HBufferImageScrollRight ();\r
2422 break;\r
2423\r
2424 //\r
2425 // left arrow\r
2426 //\r
2427 case SCAN_LEFT:\r
2428 Status = HBufferImageScrollLeft ();\r
2429 break;\r
2430\r
2431 //\r
2432 // page up\r
2433 //\r
2434 case SCAN_PAGE_UP:\r
2435 Status = HBufferImagePageUp ();\r
2436 break;\r
2437\r
2438 //\r
2439 // page down\r
2440 //\r
2441 case SCAN_PAGE_DOWN:\r
2442 Status = HBufferImagePageDown ();\r
2443 break;\r
2444\r
2445 //\r
2446 // delete\r
2447 //\r
2448 case SCAN_DELETE:\r
2449 Status = HBufferImageDoDelete ();\r
2450 break;\r
2451\r
2452 //\r
2453 // home\r
2454 //\r
2455 case SCAN_HOME:\r
2456 Status = HBufferImageHome ();\r
2457 break;\r
2458\r
2459 //\r
2460 // end\r
2461 //\r
2462 case SCAN_END:\r
2463 Status = HBufferImageEnd ();\r
2464 break;\r
2465\r
2466 default:\r
2467 Status = StatusBarSetStatusString (L"Unknown Command");\r
2468 break;\r
2469 }\r
2470\r
2471 return Status;\r
2472}\r