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