Mercurial > emacs
comparison src/scroll.c @ 10262:4face60ac721
(scrolling_1): When scroll_region_ok is set, use a
new scrolling method which scrolls groups of lines directly
to their final vertical positions.
(struct matrix_elt): New field writecount.
(calculate_direct_scrolling): New function.
(do_direct_scrolling): New function.
| author | Richard M. Stallman <rms@gnu.org> |
|---|---|
| date | Mon, 26 Dec 1994 15:38:56 +0000 |
| parents | 869e177ca872 |
| children | 5c4c0319a6e7 |
comparison
equal
deleted
inserted
replaced
| 10261:4fd304db9216 | 10262:4face60ac721 |
|---|---|
| 50 for the cost in insertcost. */ | 50 for the cost in insertcost. */ |
| 51 unsigned char insertcount; | 51 unsigned char insertcount; |
| 52 /* Number of deletes so far in this run of deletes, | 52 /* Number of deletes so far in this run of deletes, |
| 53 for the cost in deletecost. */ | 53 for the cost in deletecost. */ |
| 54 unsigned char deletecount; | 54 unsigned char deletecount; |
| 55 /* Number of writes so far since the last insert | |
| 56 or delete for the cost in writecost. */ | |
| 57 unsigned char writecount; | |
| 55 }; | 58 }; |
| 56 | 59 |
| 57 | 60 |
| 58 /* Determine, in matrix[i,j], the cost of updating the first j old lines | 61 /* Determine, in matrix[i,j], the cost of updating the first j old |
| 59 into the first i new lines. | 62 lines into the first i new lines using the general scrolling method. |
| 60 This involves using insert or delete somewhere if i != j. | 63 This involves using insert or delete somewhere if i != j. |
| 61 For each matrix elements, three kinds of costs are recorded: | 64 For each matrix elements, three kinds of costs are recorded: |
| 62 the smallest cost that ends with an insert, the smallest | 65 the smallest cost that ends with an insert, the smallest |
| 63 cost that ends with a delete, and the smallest cost that | 66 cost that ends with a delete, and the smallest cost that |
| 64 ends with neither one. These are kept separate because | 67 ends with neither one. These are kept separate because |
| 215 p->deletecost = min (cost, cost1); | 218 p->deletecost = min (cost, cost1); |
| 216 p->deletecount = (cost < cost1) ? 1 : p1->deletecount + 1; | 219 p->deletecount = (cost < cost1) ? 1 : p1->deletecount + 1; |
| 217 } | 220 } |
| 218 } | 221 } |
| 219 | 222 |
| 220 /* Perform insert-lines and delete-lines operations on FRAME | 223 /* Perform insert-lines and delete-lines operations on FRAME according |
| 221 according to the costs in MATRIX. | 224 to the costs in MATRIX, using the general scrolling method. |
| 222 Update the frame's current_glyphs info to record what was done. | 225 Update the frame's current_glyphs info to record what was done. |
| 223 | 226 |
| 224 WINDOW_SIZE is the number of lines being considered for scrolling | 227 WINDOW_SIZE is the number of lines being considered for scrolling |
| 225 and UNCHANGED_AT_TOP is the vpos of the first line being considered. | 228 and UNCHANGED_AT_TOP is the vpos of the first line being considered. |
| 226 These two arguments can specify any contiguous range of lines. | 229 These two arguments can specify any contiguous range of lines. |
| 359 | 362 |
| 360 if (window) | 363 if (window) |
| 361 set_terminal_window (0); | 364 set_terminal_window (0); |
| 362 } | 365 } |
| 363 | 366 |
| 367 /* Determine, in matrix[i,j], the cost of updating the first j | |
| 368 old lines into the first i new lines using the direct | |
| 369 scrolling method. When the old line and the new line have | |
| 370 different hash codes, the calculated cost of updating old | |
| 371 line j into new line i includes the cost of outputting new | |
| 372 line i, and if i != j, the cost of outputting the old line j | |
| 373 is also included, as a penalty for moving the line and then | |
| 374 erasing it. In addition, the cost of updating a sequence of | |
| 375 lines with constant i - j includes the cost of scrolling the | |
| 376 old lines into their new positions, unless i == j. Scrolling | |
| 377 is achieved by setting the screen window to avoid affecting | |
| 378 other lines below, and inserting or deleting lines at the top | |
| 379 of the scrolled region. The cost of scrolling a sequence of | |
| 380 lines includes the fixed cost of specifying a scroll region, | |
| 381 plus a variable cost which can depend upon the number of lines | |
| 382 involved and the distance by which they are scrolled, and an | |
| 383 extra cost to discourage long scrolls. | |
| 384 | |
| 385 As reflected in the matrix, an insert or delete does not | |
| 386 correspond directly to the insertion or deletion which is | |
| 387 used in scrolling lines. An insert means that the value of i | |
| 388 has increased without a corresponding increase in the value | |
| 389 of j. A delete means that the value of j has increased | |
| 390 without a corresponding increase in the value of i. A write | |
| 391 means that i and j are both increased by the same amount, and | |
| 392 that the old lines will be moved to their new positions. | |
| 393 | |
| 394 An insert following a delete is allowed only if i > j. | |
| 395 A delete following an insert is allowed only if i < j. | |
| 396 These restrictions ensure that the new lines in an insert | |
| 397 will always be blank as an effect of the neighboring writes. | |
| 398 Thus the calculated cost of an insert is simply the cost of | |
| 399 outputting the new line contents. The direct cost of a | |
| 400 delete is zero. Inserts and deletes indirectly affect the | |
| 401 total cost through their influence on subsequent writes. */ | |
| 402 | |
| 403 /* The vectors draw_cost, old_hash, and new_hash have the same | |
| 404 meanings here as in calculate_scrolling, and old_draw_cost | |
| 405 is the equivalent of draw_cost for the old line contents */ | |
| 406 | |
| 407 static void | |
| 408 calculate_direct_scrolling (frame, matrix, window_size, lines_below, | |
| 409 draw_cost, old_draw_cost, old_hash, new_hash, | |
| 410 free_at_end) | |
| 411 FRAME_PTR frame; | |
| 412 /* matrix is of size window_size + 1 on each side. */ | |
| 413 struct matrix_elt *matrix; | |
| 414 int window_size; | |
| 415 int *draw_cost; | |
| 416 int *old_draw_cost; | |
| 417 int *old_hash; | |
| 418 int *new_hash; | |
| 419 int free_at_end; | |
| 420 { | |
| 421 register int i, j; | |
| 422 int frame_height = FRAME_HEIGHT (frame); | |
| 423 register struct matrix_elt *p, *p1; | |
| 424 register int cost, cost1, delta; | |
| 425 | |
| 426 /* first_insert_cost[-I] is the cost of doing the first insert-line | |
| 427 at a position I lines above the bottom line in the scroll window. */ | |
| 428 int *first_insert_cost | |
| 429 = &FRAME_INSERT_COST (frame)[frame_height - 1]; | |
| 430 int *first_delete_cost | |
| 431 = &FRAME_DELETE_COST (frame)[frame_height - 1]; | |
| 432 int *next_insert_cost | |
| 433 = &FRAME_INSERTN_COST (frame)[frame_height - 1]; | |
| 434 int *next_delete_cost | |
| 435 = &FRAME_DELETEN_COST (frame)[frame_height - 1]; | |
| 436 | |
| 437 int scroll_overhead; | |
| 438 | |
| 439 /* Discourage long scrolls on fast lines. | |
| 440 Don't scroll nearly a full frame height unless it saves | |
| 441 at least 1/4 second. */ | |
| 442 int extra_cost = baud_rate / (10 * 4 * FRAME_HEIGHT (frame)); | |
| 443 | |
| 444 if (baud_rate <= 0) | |
| 445 extra_cost = 1; | |
| 446 | |
| 447 /* Overhead of setting the scroll window, plus the extra cost | |
| 448 cost of scrolling by a distance of one. The extra cost is | |
| 449 added once for consistency with the cost vectors */ | |
| 450 scroll_overhead = scroll_region_cost + extra_cost; | |
| 451 | |
| 452 /* initialize the top left corner of the matrix */ | |
| 453 matrix->writecost = 0; | |
| 454 matrix->insertcost = INFINITY; | |
| 455 matrix->deletecost = INFINITY; | |
| 456 matrix->writecount = 0; | |
| 457 matrix->insertcount = 0; | |
| 458 matrix->deletecount = 0; | |
| 459 | |
| 460 /* initialize the left edge of the matrix */ | |
| 461 cost = 0; | |
| 462 for (i = 1; i <= window_size; i++) | |
| 463 { | |
| 464 p = matrix + i * (window_size + 1); | |
| 465 cost += draw_cost[i]; | |
| 466 p->insertcost = cost; | |
| 467 p->writecost = INFINITY; | |
| 468 p->deletecost = INFINITY; | |
| 469 p->insertcount = i; | |
| 470 p->writecount = 0; | |
| 471 p->deletecount = 0; | |
| 472 } | |
| 473 | |
| 474 /* initialize the top edge of the matrix */ | |
| 475 for (j = 1; j <= window_size; j++) | |
| 476 { | |
| 477 matrix[j].deletecost = 0; | |
| 478 matrix[j].writecost = INFINITY; | |
| 479 matrix[j].insertcost = INFINITY; | |
| 480 matrix[j].deletecount = j; | |
| 481 matrix[j].writecount = 0; | |
| 482 matrix[j].insertcount = 0; | |
| 483 } | |
| 484 | |
| 485 /* `i' represents the vpos among new frame contents. | |
| 486 `j' represents the vpos among the old frame contents. */ | |
| 487 p = matrix + window_size + 2; /* matrix [1, 1] */ | |
| 488 | |
| 489 for (i = 1; i <= window_size; i++, p++) | |
| 490 for (j = 1; j <= window_size; j++, p++) | |
| 491 { | |
| 492 /* p contains the address of matrix [i, j] */ | |
| 493 | |
| 494 /* First calculate the cost assuming we do | |
| 495 not insert or delete above this line. | |
| 496 That is, if we update through line i-1 | |
| 497 based on old lines through j-1, | |
| 498 and then just change old line j to new line i. | |
| 499 | |
| 500 Depending on which choice gives the lower cost, | |
| 501 this usually involves either scrolling a single line | |
| 502 or extending a sequence of scrolled lines, but | |
| 503 when i == j, no scrolling is required. */ | |
| 504 p1 = p - window_size - 2; /* matrix [i-1, j-1] */ | |
| 505 cost = p1->insertcost; | |
| 506 if (cost > p1->deletecost) | |
| 507 cost = p1->deletecost; | |
| 508 cost1 = p1->writecost; | |
| 509 if (i == j) | |
| 510 { | |
| 511 if (cost > cost1) | |
| 512 { | |
| 513 cost = cost1; | |
| 514 p->writecount = p1->writecount + 1; | |
| 515 } | |
| 516 else | |
| 517 p->writecount = 1; | |
| 518 if (old_hash[j] != new_hash[i]) | |
| 519 { | |
| 520 cost += draw_cost[i]; | |
| 521 } | |
| 522 } | |
| 523 else | |
| 524 { | |
| 525 if (i > j) | |
| 526 { | |
| 527 delta = i - j; | |
| 528 | |
| 529 /* The cost added here for scrolling the first line by | |
| 530 a distance N includes the overhead of setting the | |
| 531 scroll window, the cost of inserting N lines at a | |
| 532 position N lines above the bottom line of the window, | |
| 533 and an extra cost which is proportional to N. */ | |
| 534 cost += scroll_overhead + first_insert_cost[-delta] + | |
| 535 (delta-1) * (next_insert_cost[-delta] + extra_cost); | |
| 536 | |
| 537 /* In the most general case, the insertion overhead and | |
| 538 the multiply factor can grow linearly as the distance | |
| 539 from the bottom of the window increases. The incremental | |
| 540 cost of scrolling an additional line depends upon the | |
| 541 rate of change of these two parameters. Each of these | |
| 542 growth rates can be determined by a simple difference. | |
| 543 To reduce the cumulative effects of rounding error, we | |
| 544 vary the position at which the difference is computed. */ | |
| 545 cost1 += first_insert_cost[-j] - first_insert_cost[1-j] + | |
| 546 (delta-1) * (next_insert_cost[-j] - next_insert_cost[1-j]); | |
| 547 } | |
| 548 else | |
| 549 { | |
| 550 delta = j - i; | |
| 551 cost += scroll_overhead + first_delete_cost[-delta] + | |
| 552 (delta-1) * (next_delete_cost[-delta] + extra_cost); | |
| 553 cost1 += first_delete_cost[-i] - first_delete_cost[1-i] + | |
| 554 (delta-1) * ( next_delete_cost[-i] - next_delete_cost[1-i]); | |
| 555 } | |
| 556 if (cost1 < cost) | |
| 557 { | |
| 558 cost = cost1; | |
| 559 p->writecount = p1->writecount + 1; | |
| 560 } | |
| 561 else | |
| 562 p->writecount = 1; | |
| 563 if (old_hash[j] != new_hash[i]) | |
| 564 { | |
| 565 cost += draw_cost[i] + old_draw_cost[j]; | |
| 566 } | |
| 567 } | |
| 568 p->writecost = cost; | |
| 569 | |
| 570 /* Calculate the cost if we do an insert-line | |
| 571 before outputting this line. | |
| 572 That is, we update through line i-1 | |
| 573 based on old lines through j, | |
| 574 do an insert-line on line i, | |
| 575 and then output line i from scratch, | |
| 576 leaving old lines starting from j for reuse below. */ | |
| 577 p1 = p - window_size - 1; /* matrix [i-1, j] */ | |
| 578 cost = p1->writecost; | |
| 579 /* If i > j, an insert is allowed after a delete. */ | |
| 580 if (i > j && p1->deletecost < cost) | |
| 581 cost = p1->deletecost; | |
| 582 if (p1->insertcost <= cost) | |
| 583 { | |
| 584 cost = p1->insertcost; | |
| 585 p->insertcount = p1->insertcount + 1; | |
| 586 } | |
| 587 else | |
| 588 p->insertcount = 1; | |
| 589 cost += draw_cost[i]; | |
| 590 p->insertcost = cost; | |
| 591 | |
| 592 /* Calculate the cost if we do a delete line after | |
| 593 outputting this line. | |
| 594 That is, we update through line i | |
| 595 based on old lines through j-1, | |
| 596 and throw away old line j. */ | |
| 597 p1 = p - 1; /* matrix [i, j-1] */ | |
| 598 cost = p1->writecost; | |
| 599 /* If i < j, a delete is allowed after an insert. */ | |
| 600 if (i < j && p1->insertcost < cost) | |
| 601 cost = p1->insertcost; | |
| 602 cost1 = p1->deletecost; | |
| 603 if (p1->deletecost <= cost) | |
| 604 { | |
| 605 cost = p1->deletecost; | |
| 606 p->deletecount = p1->deletecount + 1; | |
| 607 } | |
| 608 else | |
| 609 p->deletecount = 1; | |
| 610 p->deletecost = cost; | |
| 611 } | |
| 612 } | |
| 613 | |
| 614 /* Perform insert-lines and delete-lines operations on FRAME according | |
| 615 to the costs in MATRIX, using the direct scrolling method. | |
| 616 Update the frame's current_glyphs info to record what was done. | |
| 617 | |
| 618 WINDOW_SIZE is the number of lines being considered for scrolling | |
| 619 and UNCHANGED_AT_TOP is the vpos of the first line being considered. | |
| 620 These two arguments can specify any contiguous range of lines. | |
| 621 | |
| 622 We also shuffle the charstarts vectors for the lines | |
| 623 along with the glyphs; but the results are not quite right, | |
| 624 since we cannot offset them for changes in amount of text | |
| 625 in this line or that line. Luckily it doesn't matter, | |
| 626 since update_frame and update_line will copy in the proper | |
| 627 new charstarts vectors from the frame's desired_glyphs. | |
| 628 | |
| 629 In the direct scrolling method, a new scroll window is selected | |
| 630 before each insertion or deletion, so that groups of lines can be | |
| 631 scrolled directly to their final vertical positions. This method | |
| 632 is described in more detail in calculate_direct_scrolling, | |
| 633 where the cost matrix for this approach is constructed. */ | |
| 634 | |
| 635 static void | |
| 636 do_direct_scrolling (frame, matrix, window_size, unchanged_at_top) | |
| 637 FRAME_PTR frame; | |
| 638 struct matrix_elt *matrix; | |
| 639 int window_size; | |
| 640 int unchanged_at_top; | |
| 641 { | |
| 642 register struct matrix_elt *p; | |
| 643 register int i, j; | |
| 644 register struct frame_glyphs *current_frame; | |
| 645 /* temp_frame->enable[i] means line i has been moved to current_frame. */ | |
| 646 register struct frame_glyphs *temp_frame; | |
| 647 struct alt_queue { int count, pos, window; } *queue; | |
| 648 int offset = unchanged_at_top; | |
| 649 int qi = 0; | |
| 650 int window = 0; | |
| 651 register int tem; | |
| 652 int next; | |
| 653 | |
| 654 /* A nonzero value of write_follows indicates that a write has been | |
| 655 selected, allowing either an insert or a delete to be selected next. | |
| 656 When write_follows is zero, a delete cannot be selected unless j < i, | |
| 657 and an insert cannot be selected unless i < j. This corresponds to | |
| 658 a similar restriction (with the ordering reversed) in | |
| 659 calculate_direct_scrolling, which is intended to ensure that lines | |
| 660 marked as inserted will be blank. */ | |
| 661 int write_follows = 1; | |
| 662 | |
| 663 queue = (struct alt_queue *) alloca (FRAME_HEIGHT (frame) | |
| 664 * sizeof (struct alt_queue)); | |
| 665 | |
| 666 current_frame = FRAME_CURRENT_GLYPHS (frame); | |
| 667 temp_frame = FRAME_TEMP_GLYPHS (frame); | |
| 668 | |
| 669 bcopy (current_frame->glyphs, temp_frame->glyphs, | |
| 670 current_frame->height * sizeof (GLYPH *)); | |
| 671 bcopy (current_frame->charstarts, temp_frame->charstarts, | |
| 672 current_frame->height * sizeof (GLYPH *)); | |
| 673 bcopy (current_frame->used, temp_frame->used, | |
| 674 current_frame->height * sizeof (int)); | |
| 675 bcopy (current_frame->highlight, temp_frame->highlight, | |
| 676 current_frame->height * sizeof (char)); | |
| 677 bzero (temp_frame->enable, temp_frame->height * sizeof (char)); | |
| 678 bcopy (current_frame->bufp, temp_frame->bufp, | |
| 679 current_frame->height * sizeof (int)); | |
| 680 | |
| 681 #ifdef HAVE_X_WINDOWS | |
| 682 if (FRAME_X_P (frame)) | |
| 683 { | |
| 684 bcopy (current_frame->top_left_x, temp_frame->top_left_x, | |
| 685 current_frame->height * sizeof (short)); | |
| 686 bcopy (current_frame->top_left_y, temp_frame->top_left_y, | |
| 687 current_frame->height * sizeof (short)); | |
| 688 bcopy (current_frame->pix_width, temp_frame->pix_width, | |
| 689 current_frame->height * sizeof (short)); | |
| 690 bcopy (current_frame->pix_height, temp_frame->pix_height, | |
| 691 current_frame->height * sizeof (short)); | |
| 692 bcopy (current_frame->max_ascent, temp_frame->max_ascent, | |
| 693 current_frame->height * sizeof (short)); | |
| 694 } | |
| 695 #endif | |
| 696 | |
| 697 i = j = window_size; | |
| 698 | |
| 699 while (i > 0 || j > 0) | |
| 700 { | |
| 701 p = matrix + i * (window_size + 1) + j; | |
| 702 tem = p->insertcost; | |
| 703 if (tem < p->writecost && tem < p->deletecost | |
| 704 && (write_follows || i < j)) | |
| 705 { | |
| 706 /* Insert should be done at vpos i-1, plus maybe some before. | |
| 707 Setting count to 0 in the queue marks this as an insert. */ | |
| 708 write_follows = 0; | |
| 709 queue[qi].window = i + unchanged_at_top; | |
| 710 queue[qi].count = 0; | |
| 711 i -= p->insertcount; | |
| 712 queue[qi++].pos = i + unchanged_at_top; | |
| 713 } | |
| 714 else if (p->deletecost < p->writecost && (write_follows || i > j)) | |
| 715 { | |
| 716 /* Delete should be done at vpos j-1, plus maybe some before. */ | |
| 717 write_follows = 0; | |
| 718 j -= p->deletecount; | |
| 719 } | |
| 720 else | |
| 721 { | |
| 722 /* One or more lines should be retained. */ | |
| 723 write_follows = 1; | |
| 724 tem = p->writecount; | |
| 725 if (i > j) | |
| 726 { | |
| 727 /* Immediately scroll a group of lines downward */ | |
| 728 set_terminal_window (i + unchanged_at_top); | |
| 729 window = 1; | |
| 730 ins_del_lines (j - tem + unchanged_at_top, i - j); | |
| 731 } | |
| 732 else if (i < j) | |
| 733 { | |
| 734 /* Queue the upward scrolling of a group of lines */ | |
| 735 queue[qi].pos = i - tem + unchanged_at_top; | |
| 736 queue[qi].window = j + unchanged_at_top; | |
| 737 queue[qi++].count = i - j; | |
| 738 } | |
| 739 | |
| 740 /* Now copy the line-contents strings */ | |
| 741 while (tem > 0) | |
| 742 { | |
| 743 i--; | |
| 744 j--; | |
| 745 tem--; | |
| 746 current_frame->glyphs[i + offset] | |
| 747 = temp_frame->glyphs[j + offset]; | |
| 748 current_frame->charstarts[i + offset] | |
| 749 = temp_frame->charstarts[j + offset]; | |
| 750 current_frame->used[i + offset] | |
| 751 = temp_frame->used[j + offset]; | |
| 752 current_frame->highlight[i + offset] | |
| 753 = temp_frame->highlight[j + offset]; | |
| 754 | |
| 755 temp_frame->enable[j + offset] = 1; | |
| 756 } | |
| 757 } | |
| 758 } | |
| 759 | |
| 760 /* Now do all the upward scrolling, and copy the line-contents | |
| 761 strings for the blank lines of the recorded inserts. */ | |
| 762 | |
| 763 next = unchanged_at_top; | |
| 764 for (i = qi - 1; i >= 0; i--) | |
| 765 { | |
| 766 if (queue[i].count) | |
| 767 { | |
| 768 set_terminal_window (queue[i].window); | |
| 769 window = 1; | |
| 770 ins_del_lines (queue[i].pos, queue[i].count); | |
| 771 } | |
| 772 else | |
| 773 { | |
| 774 /* Mark the inserted lines as clear, | |
| 775 and put into them the line-contents strings | |
| 776 that were discarded during the deletions. | |
| 777 Those are the ones for which temp_frame->enable was not set. */ | |
| 778 tem = queue[i].pos; | |
| 779 for (j = queue[i].window - 1; j >= tem; j--) | |
| 780 { | |
| 781 current_frame->enable[j] = 0; | |
| 782 while (temp_frame->enable[next]) | |
| 783 next++; | |
| 784 current_frame->glyphs[j] = temp_frame->glyphs[next]; | |
| 785 current_frame->charstarts[j] = temp_frame->charstarts[next++]; | |
| 786 } | |
| 787 } | |
| 788 } | |
| 789 | |
| 790 if (window) | |
| 791 set_terminal_window (0); | |
| 792 } | |
| 793 | |
| 364 void | 794 void |
| 365 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, | 795 scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, |
| 366 draw_cost, old_hash, new_hash, free_at_end) | 796 draw_cost, old_draw_cost, old_hash, new_hash, free_at_end) |
| 367 FRAME_PTR frame; | 797 FRAME_PTR frame; |
| 368 int window_size, unchanged_at_top, unchanged_at_bottom; | 798 int window_size, unchanged_at_top, unchanged_at_bottom; |
| 369 int *draw_cost; | 799 int *draw_cost; |
| 800 int *old_draw_cost; | |
| 370 int *old_hash; | 801 int *old_hash; |
| 371 int *new_hash; | 802 int *new_hash; |
| 372 int free_at_end; | 803 int free_at_end; |
| 373 { | 804 { |
| 374 struct matrix_elt *matrix; | 805 struct matrix_elt *matrix; |
| 375 matrix = ((struct matrix_elt *) | 806 matrix = ((struct matrix_elt *) |
| 376 alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix)); | 807 alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix)); |
| 377 | 808 |
| 378 calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom, | 809 if (scroll_region_ok) |
| 379 draw_cost, old_hash, new_hash, | 810 { |
| 380 free_at_end); | 811 calculate_direct_scrolling (frame, matrix, window_size, |
| 381 do_scrolling (frame, matrix, window_size, unchanged_at_top); | 812 unchanged_at_bottom, |
| 813 draw_cost, old_draw_cost, | |
| 814 old_hash, new_hash, free_at_end); | |
| 815 do_direct_scrolling (frame, matrix, window_size, unchanged_at_top); | |
| 816 } | |
| 817 else | |
| 818 { | |
| 819 calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom, | |
| 820 draw_cost, old_hash, new_hash, | |
| 821 free_at_end); | |
| 822 do_scrolling (frame, matrix, window_size, unchanged_at_top); | |
| 823 } | |
| 382 } | 824 } |
| 383 | 825 |
| 384 /* Return number of lines in common between current and desired frame contents | 826 /* Return number of lines in common between current and desired frame contents |
| 385 described to us only as vectors of hash codes OLDHASH and NEWHASH. | 827 described to us only as vectors of hash codes OLDHASH and NEWHASH. |
| 386 Consider only vpos range START to END (not including END). | 828 Consider only vpos range START to END (not including END). |
