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