void scrolling_1 (struct frame *frame, int window_size, int unchanged_at_top, int unchanged_at_bottom, int *draw_cost, int *old_draw_cost, unsigned *old_hash, unsigned *new_hash, int free_at_end) { USE_SAFE_ALLOCA; struct matrix_elt *matrix; SAFE_NALLOCA (matrix, window_size + 1, window_size + 1); if (FRAME_SCROLL_REGION_OK (frame)) { calculate_direct_scrolling (frame, matrix, window_size, unchanged_at_bottom, draw_cost, old_draw_cost, old_hash, new_hash, free_at_end); do_direct_scrolling (frame, frame->current_matrix, matrix, window_size, unchanged_at_top); } else { calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom, draw_cost, old_hash, new_hash, free_at_end); do_scrolling (frame, frame->current_matrix, matrix, window_size, unchanged_at_top); } SAFE_FREE (); }
void scrolling_1 (struct frame *frame, int window_size, int unchanged_at_top, int unchanged_at_bottom, int *draw_cost, int *old_draw_cost, int *old_hash, int *new_hash, int free_at_end) { struct matrix_elt *matrix = alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix); if (FRAME_SCROLL_REGION_OK (frame)) { calculate_direct_scrolling (frame, matrix, window_size, unchanged_at_bottom, draw_cost, old_draw_cost, old_hash, new_hash, free_at_end); do_direct_scrolling (frame, frame->current_matrix, matrix, window_size, unchanged_at_top); } else { calculate_scrolling (frame, matrix, window_size, unchanged_at_bottom, draw_cost, old_hash, new_hash, free_at_end); do_scrolling (frame, frame->current_matrix, matrix, window_size, unchanged_at_top); } }
static void calculate_scrolling (struct frame *frame, /* matrix is of size window_size + 1 on each side. */ struct matrix_elt *matrix, int window_size, int lines_below, int *draw_cost, unsigned *old_hash, unsigned *new_hash, int free_at_end) { int i, j; int frame_total_lines = FRAME_TOTAL_LINES (frame); struct matrix_elt *p, *p1; int cost, cost1; int lines_moved = window_size + (FRAME_SCROLL_REGION_OK (frame) ? 0 : lines_below); /* first_insert_cost[I] is the cost of doing the first insert-line at the i'th line of the lines we are considering, where I is origin 1 (as it is below). */ int *first_insert_cost = &FRAME_INSERT_COST (frame)[frame_total_lines - 1 - lines_moved]; int *first_delete_cost = &FRAME_DELETE_COST (frame)[frame_total_lines - 1 - lines_moved]; int *next_insert_cost = &FRAME_INSERTN_COST (frame)[frame_total_lines - 1 - lines_moved]; int *next_delete_cost = &FRAME_DELETEN_COST (frame)[frame_total_lines - 1 - lines_moved]; /* Discourage long scrolls on fast lines. Don't scroll nearly a full frame height unless it saves at least 1/4 second. */ int extra_cost = clip_to_bounds (1, baud_rate / (10 * 4) / frame_total_lines, INT_MAX / 2); /* initialize the top left corner of the matrix */ matrix->writecost = 0; matrix->insertcost = SCROLL_INFINITY; matrix->deletecost = SCROLL_INFINITY; matrix->insertcount = 0; matrix->deletecount = 0; /* initialize the left edge of the matrix */ cost = first_insert_cost[1] - next_insert_cost[1]; for (i = 1; i <= window_size; i++) { p = matrix + i * (window_size + 1); cost += draw_cost[i] + next_insert_cost[i] + extra_cost; p->insertcost = cost; p->writecost = SCROLL_INFINITY; p->deletecost = SCROLL_INFINITY; p->insertcount = i; p->deletecount = 0; } /* initialize the top edge of the matrix */ cost = first_delete_cost[1] - next_delete_cost[1]; for (j = 1; j <= window_size; j++) { cost += next_delete_cost[j]; matrix[j].deletecost = cost; matrix[j].writecost = SCROLL_INFINITY; matrix[j].insertcost = SCROLL_INFINITY; matrix[j].deletecount = j; matrix[j].insertcount = 0; } /* `i' represents the vpos among new frame contents. `j' represents the vpos among the old frame contents. */ p = matrix + window_size + 2; /* matrix [1, 1] */ for (i = 1; i <= window_size; i++, p++) for (j = 1; j <= window_size; j++, p++) { /* p contains the address of matrix [i, j] */ /* First calculate the cost assuming we do not insert or delete above this line. That is, if we update through line i-1 based on old lines through j-1, and then just change old line j to new line i. */ p1 = p - window_size - 2; /* matrix [i-1, j-1] */ cost = p1->writecost; if (cost > p1->insertcost) cost = p1->insertcost; if (cost > p1->deletecost) cost = p1->deletecost; if (old_hash[j] != new_hash[i]) cost += draw_cost[i]; p->writecost = cost; /* Calculate the cost if we do an insert-line before outputting this line. That is, we update through line i-1 based on old lines through j, do an insert-line on line i, and then output line i from scratch, leaving old lines starting from j for reuse below. */ p1 = p - window_size - 1; /* matrix [i-1, j] */ /* No need to think about doing a delete followed immediately by an insert. It cannot be as good as not doing either of them. */ if (free_at_end == i) { cost = p1->writecost; cost1 = p1->insertcost; } else { cost = p1->writecost + first_insert_cost[i]; if (p1->insertcount > i) emacs_abort (); cost1 = p1->insertcost + next_insert_cost[i - p1->insertcount]; } p->insertcost = min (cost, cost1) + draw_cost[i] + extra_cost; p->insertcount = (cost < cost1) ? 1 : p1->insertcount + 1; if (p->insertcount > i) emacs_abort (); /* Calculate the cost if we do a delete line after outputting this line. That is, we update through line i based on old lines through j-1, and throw away old line j. */ p1 = p - 1; /* matrix [i, j-1] */ /* No need to think about doing an insert followed immediately by a delete. */ if (free_at_end == i) { cost = p1->writecost; cost1 = p1->deletecost; } else { cost = p1->writecost + first_delete_cost[i]; cost1 = p1->deletecost + next_delete_cost[i]; } p->deletecost = min (cost, cost1); p->deletecount = (cost < cost1) ? 1 : p1->deletecount + 1; } }