aboutsummaryrefslogtreecommitdiffstats
path: root/src/scroll.c
diff options
context:
space:
mode:
authorGerd Moellmann1999-07-21 21:43:52 +0000
committerGerd Moellmann1999-07-21 21:43:52 +0000
commit8970011174264a7fcba68d789df30c9fead389ec (patch)
tree73563267e877c1d9369ae564d9f9c1e2d1b56c7a /src/scroll.c
parent7840ced19916e4443b30d00c386b6b3d8584459e (diff)
downloademacs-8970011174264a7fcba68d789df30c9fead389ec.tar.gz
emacs-8970011174264a7fcba68d789df30c9fead389ec.zip
Rewritten.
Diffstat (limited to 'src/scroll.c')
-rw-r--r--src/scroll.c537
1 files changed, 275 insertions, 262 deletions
diff --git a/src/scroll.c b/src/scroll.c
index 12c3828b33c..727d96442b5 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -20,12 +20,13 @@ Boston, MA 02111-1307, USA. */
20 20
21 21
22#include <config.h> 22#include <config.h>
23#include <stdio.h>
24#include <string.h>
23#include "termchar.h" 25#include "termchar.h"
24#include "lisp.h" 26#include "lisp.h"
25#include "dispextern.h" 27#include "dispextern.h"
26#include "frame.h" 28#include "frame.h"
27 29#include "window.h"
28extern struct display_line **ophys_lines;
29 30
30#define max(a, b) ((a) > (b) ? (a) : (b)) 31#define max(a, b) ((a) > (b) ? (a) : (b))
31#define min(a, b) ((a) < (b) ? (a) : (b)) 32#define min(a, b) ((a) < (b) ? (a) : (b))
@@ -58,6 +59,13 @@ struct matrix_elt
58 unsigned char writecount; 59 unsigned char writecount;
59 }; 60 };
60 61
62static void do_direct_scrolling P_ ((struct glyph_matrix *,
63 struct matrix_elt *,
64 int, int));
65static void do_scrolling P_ ((struct glyph_matrix *,
66 struct matrix_elt *,
67 int, int));
68
61 69
62/* Determine, in matrix[i,j], the cost of updating the first j old 70/* Determine, in matrix[i,j], the cost of updating the first j old
63 lines into the first i new lines using the general scrolling method. 71 lines into the first i new lines using the general scrolling method.
@@ -96,7 +104,7 @@ calculate_scrolling (frame, matrix, window_size, lines_below,
96 104
97 int lines_moved = window_size + (scroll_region_ok ? 0 : lines_below); 105 int lines_moved = window_size + (scroll_region_ok ? 0 : lines_below);
98 /* first_insert_cost[I] is the cost of doing the first insert-line 106 /* first_insert_cost[I] is the cost of doing the first insert-line
99 at the I'th line of the lines we are considering, 107 at the i'th line of the lines we are considering,
100 where I is origin 1 (as it is below). */ 108 where I is origin 1 (as it is below). */
101 int *first_insert_cost 109 int *first_insert_cost
102 = &FRAME_INSERT_COST (frame)[frame_height - 1 - lines_moved]; 110 = &FRAME_INSERT_COST (frame)[frame_height - 1 - lines_moved];
@@ -220,150 +228,162 @@ calculate_scrolling (frame, matrix, window_size, lines_below,
220 p->deletecount = (cost < cost1) ? 1 : p1->deletecount + 1; 228 p->deletecount = (cost < cost1) ? 1 : p1->deletecount + 1;
221 } 229 }
222} 230}
231
232
223 233
224/* Perform insert-lines and delete-lines operations on FRAME according 234/* Perform insert-lines and delete-lines operations on CURRENT_MATRIX
225 to the costs in MATRIX, using the general scrolling method. 235 according to the costs in MATRIX, using the general scrolling
226 Update the frame's current_glyphs info to record what was done. 236 method that is used if the terminal does not support the setting of
237 scroll windows (scroll_region_ok == 0).
227 238
228 WINDOW_SIZE is the number of lines being considered for scrolling 239 WINDOW_SIZE is the number of lines being considered for scrolling
229 and UNCHANGED_AT_TOP is the vpos of the first line being considered. 240 and UNCHANGED_AT_TOP is the vpos of the first line being
230 These two arguments can specify any contiguous range of lines. 241 considered. These two arguments can specify any contiguous range
242 of lines. */
231 243
232 We also shuffle the charstarts vectors for the lines
233 along with the glyphs; but the results are not quite right,
234 since we cannot offset them for changes in amount of text
235 in this line or that line. Luckily it doesn't matter,
236 since update_frame and update_line will copy in the proper
237 new charstarts vectors from the frame's desired_glyphs. */
238
239static void 244static void
240do_scrolling (frame, matrix, window_size, unchanged_at_top) 245do_scrolling (current_matrix, matrix, window_size, unchanged_at_top)
241 FRAME_PTR frame; 246 struct glyph_matrix *current_matrix;
242 struct matrix_elt *matrix; 247 struct matrix_elt *matrix;
243 int window_size; 248 int window_size;
244 int unchanged_at_top; 249 int unchanged_at_top;
245{ 250{
246 register struct matrix_elt *p; 251 struct matrix_elt *p;
247 register int i, j; 252 int i, j, k;
248 register struct frame_glyphs *current_frame; 253
249 /* temp_frame->enable[i] means line i has been moved to current_frame. */ 254 /* Set to 1 if we have set a terminal window with
250 register struct frame_glyphs *temp_frame; 255 set_terminal_window. */
251 struct queue { int count, pos; } *queue; 256 int terminal_window_p = 0;
252 int offset = unchanged_at_top; 257
253 int qi = 0; 258 /* A queue for line insertions to be done. */
254 int window = 0; 259 struct queue { int count, pos; };
255 register int tem; 260 struct queue *queue_start
256 int next; 261 = (struct queue *) alloca (current_matrix->nrows * sizeof (struct queue));
257 262 struct queue *queue = queue_start;
258 queue = (struct queue *) alloca (FRAME_HEIGHT (frame) 263
259 * sizeof (struct queue)); 264 char *retained_p = (char *) alloca (window_size * sizeof (char));
260 265 int *copy_from = (int *) alloca (window_size * sizeof (int));
261 current_frame = FRAME_CURRENT_GLYPHS (frame); 266
262 temp_frame = FRAME_TEMP_GLYPHS (frame); 267 /* Zero means line is empty. */
263 268 bzero (retained_p, window_size * sizeof (char));
264 bcopy (current_frame->glyphs, temp_frame->glyphs, 269 for (k = 0; k < window_size; ++k)
265 current_frame->height * sizeof (GLYPH *)); 270 copy_from[k] = -1;
266 bcopy (current_frame->charstarts, temp_frame->charstarts, 271
267 current_frame->height * sizeof (int *)); 272#define CHECK \
268 bcopy (current_frame->used, temp_frame->used, 273 do \
269 current_frame->height * sizeof (int)); 274 { \
270 bcopy (current_frame->highlight, temp_frame->highlight, 275 int k; \
271 current_frame->height * sizeof (char)); 276 for (k = 0; k < window_size; ++k) \
272 bzero (temp_frame->enable, temp_frame->height * sizeof (char)); 277 xassert (copy_from[k] == -1 \
273 bcopy (current_frame->bufp, temp_frame->bufp, 278 || (copy_from[k] >= 0 && copy_from[k] < window_size)); \
274 current_frame->height * sizeof (int)); 279 } \
275 280 while (0);
276#ifdef HAVE_WINDOW_SYSTEM 281
277 if (FRAME_WINDOW_P (frame)) 282 /* When j is advanced, this corresponds to deleted lines.
278 { 283 When i is advanced, this corresponds to inserted lines. */
279 bcopy (current_frame->top_left_x, temp_frame->top_left_x,
280 current_frame->height * sizeof (short));
281 bcopy (current_frame->top_left_y, temp_frame->top_left_y,
282 current_frame->height * sizeof (short));
283 bcopy (current_frame->pix_width, temp_frame->pix_width,
284 current_frame->height * sizeof (short));
285 bcopy (current_frame->pix_height, temp_frame->pix_height,
286 current_frame->height * sizeof (short));
287 bcopy (current_frame->max_ascent, temp_frame->max_ascent,
288 current_frame->height * sizeof (short));
289 }
290#endif
291
292 i = j = window_size; 284 i = j = window_size;
293
294 while (i > 0 || j > 0) 285 while (i > 0 || j > 0)
295 { 286 {
296 p = matrix + i * (window_size + 1) + j; 287 p = matrix + i * (window_size + 1) + j;
297 tem = p->insertcost; 288
298 if (tem < p->writecost && tem < p->deletecost) 289 if (p->insertcost < p->writecost && p->insertcost < p->deletecost)
299 { 290 {
300 /* Insert should be done at vpos i-1, plus maybe some before */ 291 /* Insert should be done at vpos i-1, plus maybe some before.
301 queue[qi].count = p->insertcount; 292 Queue the screen operation to be performed. */
293 queue->count = p->insertcount;
294 queue->pos = i + unchanged_at_top - p->insertcount;
295 ++queue;
296
297 /* By incrementing I, we leave room in the result rows
298 for the empty rows opened up. */
302 i -= p->insertcount; 299 i -= p->insertcount;
303 queue[qi++].pos = i + unchanged_at_top;
304 } 300 }
305 else if (p->deletecost < p->writecost) 301 else if (p->deletecost < p->writecost)
306 { 302 {
307 /* Old line at vpos j-1, and maybe some before it, 303 /* Old line at vpos j-1, and maybe some before it, should be
308 should be deleted */ 304 deleted. By decrementing J, we skip some lines in the
305 temp_rows which is equivalent to omitting these lines in
306 the result rows, thus deleting them. */
309 j -= p->deletecount; 307 j -= p->deletecount;
310 if (!window) 308
309 /* Set the terminal window, if not done already. */
310 if (! terminal_window_p)
311 { 311 {
312 set_terminal_window (window_size + unchanged_at_top); 312 set_terminal_window (window_size + unchanged_at_top);
313 window = 1; 313 terminal_window_p = 1;
314 } 314 }
315
316 /* Delete lines on the terminal. */
315 ins_del_lines (j + unchanged_at_top, - p->deletecount); 317 ins_del_lines (j + unchanged_at_top, - p->deletecount);
316 } 318 }
317 else 319 else
318 { 320 {
319 /* Best thing done here is no insert or delete */ 321 /* Best thing done here is no insert or delete, i.e. a write. */
320 /* Old line at vpos j-1 ends up at vpos i-1 */ 322 --i, --j;
321 current_frame->glyphs[i + offset - 1] 323 xassert (i >= 0 && i < window_size);
322 = temp_frame->glyphs[j + offset - 1]; 324 xassert (j >= 0 && j < window_size);
323 current_frame->charstarts[i + offset - 1] 325 copy_from[i] = j;
324 = temp_frame->charstarts[j + offset - 1]; 326 retained_p[j] = 1;
325 current_frame->used[i + offset - 1] 327
326 = temp_frame->used[j + offset - 1]; 328#if GLYPH_DEBUG
327 current_frame->highlight[i + offset - 1] 329 CHECK;
328 = temp_frame->highlight[j + offset - 1]; 330#endif
329
330 temp_frame->enable[j + offset - 1] = 1;
331 i--;
332 j--;
333 } 331 }
334 } 332 }
335 333
336 if (!window && qi) 334 /* Now do all insertions queued above. */
335 if (queue > queue_start)
337 { 336 {
338 set_terminal_window (window_size + unchanged_at_top); 337 int next = -1;
339 window = 1;
340 }
341 338
342 /* Now do all insertions */ 339 /* Set the terminal window if not yet done. */
340 if (!terminal_window_p)
341 {
342 set_terminal_window (window_size + unchanged_at_top);
343 terminal_window_p = 1;
344 }
343 345
344 next = unchanged_at_top; 346 do
345 for (i = qi - 1; i >= 0; i--)
346 {
347 ins_del_lines (queue[i].pos, queue[i].count);
348
349 /* Mark the inserted lines as clear,
350 and put into them the line-contents strings
351 that were discarded during the deletions.
352 Those are the ones for which temp_frame->enable was not set. */
353 tem = queue[i].pos;
354 for (j = tem + queue[i].count - 1; j >= tem; j--)
355 { 347 {
356 current_frame->enable[j] = 0; 348 --queue;
357 while (temp_frame->enable[next]) 349
358 next++; 350 /* Do the deletion on the terminal. */
359 current_frame->glyphs[j] = temp_frame->glyphs[next]; 351 ins_del_lines (queue->pos, queue->count);
360 current_frame->charstarts[j] = temp_frame->charstarts[next++]; 352
353 /* All lines in the range deleted become empty in the glyph
354 matrix. Assign to them glyph rows that are not retained.
355 K is the starting position of the deleted range relative
356 to the window we are working in. */
357 k = queue->pos - unchanged_at_top;
358 for (j = 0; j < queue->count; ++j)
359 {
360 /* Find the next row not retained. */
361 while (retained_p[++next])
362 ;
363
364 /* Record that this row is to be used for the empty
365 glyph row j. */
366 copy_from[k + j] = next;
367 }
361 } 368 }
369 while (queue > queue_start);
370
362 } 371 }
363 372
364 if (window) 373 for (k = 0; k < window_size; ++k)
374 xassert (copy_from[k] >= 0 && copy_from[k] < window_size);
375
376 /* Perform the row swizzling. */
377 mirrored_line_dance (current_matrix, unchanged_at_top, window_size,
378 copy_from, retained_p);
379
380 /* Some sanity checks if GLYPH_DEBUG != 0. */
381 CHECK_MATRIX (current_matrix);
382
383 if (terminal_window_p)
365 set_terminal_window (0); 384 set_terminal_window (0);
366} 385}
386
367 387
368/* Determine, in matrix[i,j], the cost of updating the first j 388/* Determine, in matrix[i,j], the cost of updating the first j
369 old lines into the first i new lines using the direct 389 old lines into the first i new lines using the direct
@@ -611,186 +631,179 @@ calculate_direct_scrolling (frame, matrix, window_size, lines_below,
611 p->deletecost = cost; 631 p->deletecost = cost;
612 } 632 }
613} 633}
634
635
614 636
615/* Perform insert-lines and delete-lines operations on FRAME according 637/* Perform insert-lines and delete-lines operations on CURRENT_MATRIX
616 to the costs in MATRIX, using the direct scrolling method. 638 according to the costs in MATRIX, using the direct scrolling method
617 Update the frame's current_glyphs info to record what was done. 639 which is used when the terminal supports setting a scroll window
640 (scroll_region_ok).
618 641
619 WINDOW_SIZE is the number of lines being considered for scrolling 642 WINDOW_SIZE is the number of lines being considered for scrolling
620 and UNCHANGED_AT_TOP is the vpos of the first line being considered. 643 and UNCHANGED_AT_TOP is the vpos of the first line being
621 These two arguments can specify any contiguous range of lines. 644 considered. These two arguments can specify any contiguous range
645 of lines.
622 646
623 We also shuffle the charstarts vectors for the lines
624 along with the glyphs; but the results are not quite right,
625 since we cannot offset them for changes in amount of text
626 in this line or that line. Luckily it doesn't matter,
627 since update_frame and update_line will copy in the proper
628 new charstarts vectors from the frame's desired_glyphs.
629
630 In the direct scrolling method, a new scroll window is selected 647 In the direct scrolling method, a new scroll window is selected
631 before each insertion or deletion, so that groups of lines can be 648 before each insertion or deletion, so that groups of lines can be
632 scrolled directly to their final vertical positions. This method 649 scrolled directly to their final vertical positions. This method
633 is described in more detail in calculate_direct_scrolling, 650 is described in more detail in calculate_direct_scrolling, where
634 where the cost matrix for this approach is constructed. */ 651 the cost matrix for this approach is constructed. */
635 652
636static void 653static void
637do_direct_scrolling (frame, matrix, window_size, unchanged_at_top) 654do_direct_scrolling (current_matrix, cost_matrix, window_size,
638 FRAME_PTR frame; 655 unchanged_at_top)
639 struct matrix_elt *matrix; 656 struct glyph_matrix *current_matrix;
657 struct matrix_elt *cost_matrix;
640 int window_size; 658 int window_size;
641 int unchanged_at_top; 659 int unchanged_at_top;
642{ 660{
643 register struct matrix_elt *p; 661 struct matrix_elt *p;
644 register int i, j; 662 int i, j;
645 register struct frame_glyphs *current_frame;
646 /* temp_frame->enable[i] means line i has been moved to current_frame. */
647 register struct frame_glyphs *temp_frame;
648 struct alt_queue { int count, pos, window; } *queue;
649 int offset = unchanged_at_top;
650 int qi = 0;
651 int window = 0;
652 register int tem;
653 int next;
654 663
655 /* A nonzero value of write_follows indicates that a write has been 664 /* A queue of deletions and insertions to be performed. */
656 selected, allowing either an insert or a delete to be selected next. 665 struct alt_queue { int count, pos, window; };
657 When write_follows is zero, a delete cannot be selected unless j < i, 666 struct alt_queue *queue_start = (struct alt_queue *)
658 and an insert cannot be selected unless i < j. This corresponds to 667 alloca (window_size * sizeof *queue_start);
659 a similar restriction (with the ordering reversed) in 668 struct alt_queue *queue = queue_start;
660 calculate_direct_scrolling, which is intended to ensure that lines
661 marked as inserted will be blank. */
662 int write_follows = 1;
663
664 queue = (struct alt_queue *) alloca (FRAME_HEIGHT (frame)
665 * sizeof (struct alt_queue));
666
667 current_frame = FRAME_CURRENT_GLYPHS (frame);
668 temp_frame = FRAME_TEMP_GLYPHS (frame);
669
670 bcopy (current_frame->glyphs, temp_frame->glyphs,
671 current_frame->height * sizeof (GLYPH *));
672 bcopy (current_frame->charstarts, temp_frame->charstarts,
673 current_frame->height * sizeof (GLYPH *));
674 bcopy (current_frame->used, temp_frame->used,
675 current_frame->height * sizeof (int));
676 bcopy (current_frame->highlight, temp_frame->highlight,
677 current_frame->height * sizeof (char));
678 bzero (temp_frame->enable, temp_frame->height * sizeof (char));
679 bcopy (current_frame->bufp, temp_frame->bufp,
680 current_frame->height * sizeof (int));
681
682#ifdef HAVE_WINDOW_SYSTEM
683 if (FRAME_WINDOW_P (frame))
684 {
685 bcopy (current_frame->top_left_x, temp_frame->top_left_x,
686 current_frame->height * sizeof (short));
687 bcopy (current_frame->top_left_y, temp_frame->top_left_y,
688 current_frame->height * sizeof (short));
689 bcopy (current_frame->pix_width, temp_frame->pix_width,
690 current_frame->height * sizeof (short));
691 bcopy (current_frame->pix_height, temp_frame->pix_height,
692 current_frame->height * sizeof (short));
693 bcopy (current_frame->max_ascent, temp_frame->max_ascent,
694 current_frame->height * sizeof (short));
695 }
696#endif
697 669
698 i = j = window_size; 670 /* Set to 1 if a terminal window has been set with
671 set_terminal_window: */
672 int terminal_window_p = 0;
699 673
674 /* A nonzero value of write_follows indicates that a write has been
675 selected, allowing either an insert or a delete to be selected
676 next. When write_follows is zero, a delete cannot be selected
677 unless j < i, and an insert cannot be selected unless i < j.
678 This corresponds to a similar restriction (with the ordering
679 reversed) in calculate_direct_scrolling, which is intended to
680 ensure that lines marked as inserted will be blank. */
681 int write_follows_p = 1;
682
683 /* For each row in the new matrix what row of the old matrix it is. */
684 int *copy_from = (int *) alloca (window_size * sizeof (int));
685
686 /* Non-zero for each row in the new matrix that is retained from the
687 old matrix. Lines not retained are empty. */
688 char *retained_p = (char *) alloca (window_size * sizeof (char));
689
690 bzero (retained_p, window_size * sizeof (char));
691
692 /* Perform some sanity checks when GLYPH_DEBUG is on. */
693 CHECK_MATRIX (current_matrix);
694
695 /* We are working on the line range UNCHANGED_AT_TOP ...
696 UNCHANGED_AT_TOP + WINDOW_SIZE (not including) in CURRENT_MATRIX.
697 We step through lines in this range from the end to the start. I
698 is an index into new lines, j an index into old lines. The cost
699 matrix determines what to do for ranges of indices.
700
701 If i is decremented without also decrementing j, this corresponds
702 to inserting empty lines in the result. If j is decremented
703 without also decrementing i, this corresponds to omitting these
704 lines in the new rows, i.e. rows are deleted. */
705 i = j = window_size;
706
700 while (i > 0 || j > 0) 707 while (i > 0 || j > 0)
701 { 708 {
702 p = matrix + i * (window_size + 1) + j; 709 p = cost_matrix + i * (window_size + 1) + j;
703 tem = p->insertcost; 710
704 if (tem < p->writecost && tem < p->deletecost 711 if (p->insertcost < p->writecost
705 && (write_follows || i < j)) 712 && p->insertcost < p->deletecost
713 && (write_follows_p || i < j))
706 { 714 {
707 /* Insert should be done at vpos i-1, plus maybe some before. 715 /* Insert is cheaper than deleting or writing lines. Leave
708 Setting count to 0 in the queue marks this as an insert. */ 716 a hole in the result display that will be filled with
709 write_follows = 0; 717 empty lines when the queue is emptied. */
710 queue[qi].window = i + unchanged_at_top; 718 queue->count = 0;
711 queue[qi].count = 0; 719 queue->window = i;
720 queue->pos = i - p->insertcount;
721 ++queue;
722
712 i -= p->insertcount; 723 i -= p->insertcount;
713 queue[qi++].pos = i + unchanged_at_top; 724 write_follows_p = 0;
714 } 725 }
715 else if (p->deletecost < p->writecost && (write_follows || i > j)) 726 else if (p->deletecost < p->writecost
727 && (write_follows_p || i > j))
716 { 728 {
717 /* Delete should be done at vpos j-1, plus maybe some before. */ 729 /* Deleting lines is cheaper. By decrementing J, omit
718 write_follows = 0; 730 deletecount lines from the original. */
731 write_follows_p = 0;
719 j -= p->deletecount; 732 j -= p->deletecount;
720 } 733 }
721 else 734 else
722 { 735 {
723 /* One or more lines should be retained. */ 736 /* One or more lines should be written. In the direct
724 write_follows = 1; 737 scrolling method we do this by scrolling the lines to the
725 tem = p->writecount; 738 place they belong. */
739 int n_to_write = p->writecount;
740 write_follows_p = 1;
741 xassert (n_to_write > 0);
742
726 if (i > j) 743 if (i > j)
727 { 744 {
728 /* Immediately scroll a group of lines downward */ 745 /* Immediately insert lines */
729 set_terminal_window (i + unchanged_at_top); 746 set_terminal_window (i + unchanged_at_top);
730 window = 1; 747 terminal_window_p = 1;
731 ins_del_lines (j - tem + unchanged_at_top, i - j); 748 ins_del_lines (j - n_to_write + unchanged_at_top, i - j);
732 } 749 }
733 else if (i < j) 750 else if (i < j)
734 { 751 {
735 /* Queue the upward scrolling of a group of lines */ 752 /* Queue the deletion of a group of lines */
736 queue[qi].pos = i - tem + unchanged_at_top; 753 queue->pos = i - n_to_write + unchanged_at_top;
737 queue[qi].window = j + unchanged_at_top; 754 queue->window = j + unchanged_at_top;
738 queue[qi++].count = i - j; 755 queue->count = i - j;
756 ++queue;
739 } 757 }
740 758
741 /* Now copy the line-contents strings */ 759 while (n_to_write > 0)
742 while (tem > 0)
743 { 760 {
744 i--; 761 --i, --j, --n_to_write;
745 j--; 762 copy_from[i] = j;
746 tem--; 763 retained_p[j] = 1;
747 current_frame->glyphs[i + offset]
748 = temp_frame->glyphs[j + offset];
749 current_frame->charstarts[i + offset]
750 = temp_frame->charstarts[j + offset];
751 current_frame->used[i + offset]
752 = temp_frame->used[j + offset];
753 current_frame->highlight[i + offset]
754 = temp_frame->highlight[j + offset];
755
756 temp_frame->enable[j + offset] = 1;
757 } 764 }
758 } 765 }
759 } 766 }
760 767
761 /* Now do all the upward scrolling, and copy the line-contents 768 /* Do queued operations. */
762 strings for the blank lines of the recorded inserts. */ 769 if (queue > queue_start)
763
764 next = unchanged_at_top;
765 for (i = qi - 1; i >= 0; i--)
766 { 770 {
767 if (queue[i].count) 771 int next = -1;
768 { 772
769 set_terminal_window (queue[i].window); 773 do
770 window = 1;
771 ins_del_lines (queue[i].pos, queue[i].count);
772 }
773 else
774 { 774 {
775 /* Mark the inserted lines as clear, 775 --queue;
776 and put into them the line-contents strings 776 if (queue->count)
777 that were discarded during the deletions. 777 {
778 Those are the ones for which temp_frame->enable was not set. */ 778 set_terminal_window (queue->window);
779 tem = queue[i].pos; 779 terminal_window_p = 1;
780 for (j = queue[i].window - 1; j >= tem; j--) 780 ins_del_lines (queue->pos, queue->count);
781 }
782 else
781 { 783 {
782 current_frame->enable[j] = 0; 784 for (j = queue->window - 1; j >= queue->pos; --j)
783 while (temp_frame->enable[next]) 785 {
784 next++; 786 while (retained_p[++next])
785 current_frame->glyphs[j] = temp_frame->glyphs[next]; 787 ;
786 current_frame->charstarts[j] = temp_frame->charstarts[next++]; 788 copy_from[j] = next;
789 }
787 } 790 }
788 } 791 }
792 while (queue > queue_start);
789 } 793 }
790 794
791 if (window) 795 /* Now, for each row I in the range of rows we are working on,
796 copy_from[i] gives the original line to copy to I, and
797 retained_p[copy_from[i]] is zero if line I in the new display is
798 empty. */
799 mirrored_line_dance (current_matrix, unchanged_at_top, window_size,
800 copy_from, retained_p);
801
802 if (terminal_window_p)
792 set_terminal_window (0); 803 set_terminal_window (0);
793} 804}
805
806
794 807
795void 808void
796scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom, 809scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
@@ -813,22 +826,26 @@ scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
813 unchanged_at_bottom, 826 unchanged_at_bottom,
814 draw_cost, old_draw_cost, 827 draw_cost, old_draw_cost,
815 old_hash, new_hash, free_at_end); 828 old_hash, new_hash, free_at_end);
816 do_direct_scrolling (frame, matrix, window_size, unchanged_at_top); 829 do_direct_scrolling (frame->current_matrix,
830 matrix, window_size, unchanged_at_top);
817 } 831 }
818 else 832 else
819 { 833 {
820 calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom, 834 calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom,
821 draw_cost, old_hash, new_hash, 835 draw_cost, old_hash, new_hash,
822 free_at_end); 836 free_at_end);
823 do_scrolling (frame, matrix, window_size, unchanged_at_top); 837 do_scrolling (frame->current_matrix, matrix, window_size,
838 unchanged_at_top);
824 } 839 }
825} 840}
841
842
826 843
827/* Return number of lines in common between current and desired frame contents 844/* Return number of lines in common between current and desired frame
828 described to us only as vectors of hash codes OLDHASH and NEWHASH. 845 contents described to us only as vectors of hash codes OLDHASH and
829 Consider only vpos range START to END (not including END). 846 NEWHASH. Consider only vpos range START to END (not including
830 Ignore short lines on the assumption that 847 END). Ignore short lines on the assumption that avoiding redrawing
831 avoiding redrawing such a line will have little weight. */ 848 such a line will have little weight. */
832 849
833int 850int
834scrolling_max_lines_saved (start, end, oldhash, newhash, cost) 851scrolling_max_lines_saved (start, end, oldhash, newhash, cost)
@@ -851,11 +868,9 @@ scrolling_max_lines_saved (start, end, oldhash, newhash, cost)
851 868
852 bzero (lines, sizeof lines); 869 bzero (lines, sizeof lines);
853 870
854 /* Put new lines' hash codes in hash table. 871 /* Put new lines' hash codes in hash table. Ignore lines shorter
855 Ignore lines shorter than the threshold. 872 than the threshold. Thus, if the lines that are in common are
856 Thus, if the lines that are in common 873 mainly the ones that are short, they won't count. */
857 are mainly the ones that are short,
858 they won't count. */
859 for (i = start; i < end; i++) 874 for (i = start; i < end; i++)
860 { 875 {
861 if (cost[i] > threshold) 876 if (cost[i] > threshold)
@@ -866,9 +881,8 @@ scrolling_max_lines_saved (start, end, oldhash, newhash, cost)
866 } 881 }
867 } 882 }
868 883
869 /* Look up old line hash codes in the hash table. 884 /* Look up old line hash codes in the hash table. Count number of
870 Count number of matches between old lines and new. */ 885 matches between old lines and new. */
871
872 for (i = start; i < end; i++) 886 for (i = start; i < end; i++)
873 { 887 {
874 h = oldhash[i] & 0777; 888 h = oldhash[i] & 0777;
@@ -883,11 +897,10 @@ scrolling_max_lines_saved (start, end, oldhash, newhash, cost)
883 return matchcount; 897 return matchcount;
884} 898}
885 899
886/* Return a measure of the cost of moving the lines 900/* Return a measure of the cost of moving the lines starting with vpos
887 starting with vpos FROM, up to but not including vpos TO, 901 FROM, up to but not including vpos TO, down by AMOUNT lines (AMOUNT
888 down by AMOUNT lines (AMOUNT may be negative). 902 may be negative). These are the same arguments that might be given
889 These are the same arguments that might be given to 903 to scroll_frame_lines to perform this scrolling. */
890 scroll_frame_lines to perform this scrolling. */
891 904
892int 905int
893scroll_cost (frame, from, to, amount) 906scroll_cost (frame, from, to, amount)