Ejemplo n.º 1
0
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 ();
}
Ejemplo n.º 2
0
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);
    }
}
Ejemplo n.º 3
0
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;
      }
}