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