changeset 25186:d6c941334567

(redraw_overlapping_rows): Use flag overlapping_p. (direct_output_for_insert): Ditto. (direct_output_for_insert): Don't use this method if row is overlapped by others. (update_text_area): Write full line if current line is overlapped. (redraw_overlapped_rows): New. (update_window): Call it. (redraw_overlapping_rows): New. (update_window): Call it. (scrolling_window): Make sure overlapped_p flag in current rows is unchanged. (row_equal_p): Take rows overlapped_p flag into account. (adjust_glyphs): Block input while adjusting matrices. (direct_output_for_insert): Don't use this optimization for rows that overlap others. (update_window_line): Return non-zero if display has changed. (update_text_area): Ditto. (update_window): Record if display has been changed. (blank_row): Compute glyph row's physical height. (row_equal_p): Take physical row heights into account. (direct_output_for_insert): Ditto. (update_text_area): Ditto.
author Gerd Moellmann <gerd@gnu.org>
date Fri, 06 Aug 1999 13:59:32 +0000
parents d3614d7b7583
children 39feb68ed3c7
files src/dispnew.c
diffstat 1 files changed, 176 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/dispnew.c	Fri Aug 06 13:59:29 1999 +0000
+++ b/src/dispnew.c	Fri Aug 06 13:59:32 1999 +0000
@@ -109,6 +109,8 @@
 
 /* Function prototypes.  */
 
+static void redraw_overlapping_rows P_ ((struct window *, int));
+static void redraw_overlapped_rows P_ ((struct window *, int));
 static int count_blanks P_ ((struct glyph *, int));
 static int count_match P_ ((struct glyph *, struct glyph *,
 			    struct glyph *, struct glyph *));
@@ -146,9 +148,9 @@
 static void clear_window_matrices P_ ((struct window *, int));
 static void fill_up_glyph_row_area_with_spaces P_ ((struct glyph_row *, int));
 static int scrolling_window P_ ((struct window *, int));
-static void update_window_line P_ ((struct window *, int));
+static int update_window_line P_ ((struct window *, int));
 static void update_marginal_area P_ ((struct window *, int, int));
-static void update_text_area P_ ((struct window *, int));
+static int update_text_area P_ ((struct window *, int));
 static void make_current P_ ((struct glyph_matrix *, struct glyph_matrix *,
 			      int));
 static void mirror_make_current P_ ((struct window *, int));
@@ -999,8 +1001,8 @@
   
   clear_glyph_row (row);
   row->y = y;
-  row->ascent = 0;
-  row->height = CANON_Y_UNIT (XFRAME (WINDOW_FRAME (w)));
+  row->ascent = row->phys_ascent = 0;
+  row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame));
   
   if (row->y < min_y)
     row->visible_height = row->height - (min_y - row->y);
@@ -1361,12 +1363,15 @@
 	  || a->overlay_arrow_p != b->overlay_arrow_p
 	  || a->continued_p != b->continued_p
 	  || a->indicate_empty_line_p != b->indicate_empty_line_p
+	  || a->overlapped_p != b->overlapped_p
 	  || (MATRIX_ROW_CONTINUATION_LINE_P (a)
 	      != MATRIX_ROW_CONTINUATION_LINE_P (b))
 	  /* Different partially visible characters on left margin.  */
 	  || a->x != b->x
 	  /* Different height.  */
 	  || a->ascent != b->ascent
+	  || a->phys_ascent != b->phys_ascent
+	  || a->phys_height != b->phys_height
 	  || a->visible_height != b->visible_height)
 	return 0;
     }
@@ -1863,6 +1868,10 @@
 adjust_glyphs (f)
      struct frame *f;
 {
+  /* Block input so that expose events and other events that access
+     glyph matrices are not processed while we are changing them.  */
+  BLOCK_INPUT;
+
   if (f)
     adjust_frame_glyphs (f);
   else
@@ -1872,6 +1881,8 @@
       FOR_EACH_FRAME (tail, lisp_frame)
 	adjust_frame_glyphs (XFRAME (lisp_frame));
     }
+
+  UNBLOCK_INPUT;
 }
 
 
@@ -3025,9 +3036,15 @@
       || g == '\r'
       /* Give up if unable to display the cursor in the window.  */
       || w->cursor.vpos < 0
-      /* Can't do it in a continued line because continuation lines
-	 will change.  */
-      || MATRIX_ROW (w->current_matrix, w->cursor.vpos)->continued_p
+      || (glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos),
+	  /* Can't do it in a continued line because continuation
+	     lines would change.  */
+	  (glyph_row->continued_p
+	   /* Can't use this method if the line overlaps others or is
+	      overlapped by others because these other lines would
+	      have to be redisplayed.  */
+	   || glyph_row->overlapping_p
+	   || glyph_row->overlapped_p))
       /* Can't do it for partial width windows on terminal frames
 	 because we can't clear to eol in such a window.  */
       || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w)))
@@ -3088,6 +3105,8 @@
 	 the original row, or if it is not a character glyph.  */
       if (glyph_row->ascent != it.ascent
 	  || glyph_row->height != it.ascent + it.descent
+	  || glyph_row->phys_ascent != it.phys_ascent
+	  || glyph_row->phys_height != it.phys_ascent + it.phys_descent
 	  || it.what != IT_CHARACTER)
 	return 0;
 
@@ -3450,6 +3469,104 @@
 }
 
 
+/* Redraw lines from the current matrix of window W that are
+   overlapped by other rows.  YB is bottom-most y-position in W.  */
+
+static void
+redraw_overlapped_rows (w, yb)
+     struct window *w;
+     int yb;
+{
+  int i, bottom_y;
+  struct glyph_row *row;
+  
+  /* If rows overlapping others have been changed, the rows being
+     overlapped have to be redrawn.  This won't draw lines that have
+     already been drawn in update_window_line because overlapped_p in
+     desired rows is 0, so after row assignment overlapped_p in
+     current rows is 0.  */
+  for (i = 0; i < w->current_matrix->nrows; ++i)
+    {
+      row = w->current_matrix->rows + i;
+
+      if (!row->enabled_p)
+	break;
+      else if (row->mode_line_p)
+	continue;
+      
+      if (row->overlapped_p)
+	{
+	  enum glyph_row_area area;
+	  
+	  for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+	    {
+	      updated_row = row;
+	      updated_area = area;
+	      rif->cursor_to (i, 0, row->y, area == TEXT_AREA ? row->x : 0);
+	      if (row->used[area])
+		rif->write_glyphs (row->glyphs[area], row->used[area]);
+	      rif->clear_end_of_line (-1);
+	    }
+	  
+	  row->overlapped_p = 0;
+	}
+
+      bottom_y = MATRIX_ROW_BOTTOM_Y (row);
+      if (bottom_y >= yb)
+	break;
+    }
+}
+
+
+/* Redraw lines from the current matrix of window W that overlap
+   others.  YB is bottom-most y-position in W.  */
+
+static void
+redraw_overlapping_rows (w, yb)
+     struct window *w;
+     int yb;
+{
+  int i, bottom_y;
+  struct glyph_row *row;
+  
+  for (i = 0; i < w->current_matrix->nrows; ++i)
+    {
+      row = w->current_matrix->rows + i;
+
+      if (!row->enabled_p)
+	break;
+      else if (row->mode_line_p)
+	continue;
+      
+      bottom_y = MATRIX_ROW_BOTTOM_Y (row);
+
+      if (row->overlapping_p && i > 0 && bottom_y < yb)
+	{
+	  if (row->used[LEFT_MARGIN_AREA])
+	    rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
+  
+	  if (row->used[TEXT_AREA])
+	    rif->fix_overlapping_area (w, row, TEXT_AREA);
+  
+	  if (row->used[RIGHT_MARGIN_AREA])
+	    rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
+
+	  /* Record in neighbor rows that ROW overwrites part of their
+	     display.  */
+	  if (row->phys_ascent > row->ascent && i > 0)
+	    MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
+	  if ((row->phys_height - row->phys_ascent
+	       > row->height - row->ascent)
+	      && bottom_y < yb)
+	    MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1;
+	}
+
+      if (bottom_y >= yb)
+	break;
+    }
+}
+
+
 /* Update display of window W.  FORCE_P non-zero means that we should
    not stop when detecting pending input.  */
 
@@ -3482,7 +3599,7 @@
       struct glyph_row *row, *end;
       struct glyph_row *mode_line_row;
       struct glyph_row *top_line_row = NULL;
-      int yb;
+      int yb, changed_p = 0;
 
       rif->update_window_begin_hook (w);
       yb = window_text_bottom_y (w);
@@ -3501,6 +3618,7 @@
 	  mode_line_row->y = yb;
 	  update_window_line (w, MATRIX_ROW_VPOS (mode_line_row,
 						  desired_matrix));
+	  changed_p = 1;
 	}
 
       /* Find first enabled row.  Optimizations in redisplay_internal
@@ -3521,6 +3639,7 @@
 	    }
 	  else if (rc > 0)
 	    force_p = 1;
+	  changed_p = 1;
 	}
 
       /* Update the top mode line after scrolling because a new top
@@ -3530,6 +3649,7 @@
 	{
 	  top_line_row->y = 0;
 	  update_window_line (w, 0);
+	  changed_p = 1;
 	}
 
       /* Update the rest of the lines.  */
@@ -3550,7 +3670,7 @@
 	    if (!force_p && vpos % preempt_count == 0)
 	      detect_input_pending ();
 
-	    update_window_line (w, vpos);
+	    changed_p |= update_window_line (w, vpos);
 
 	    /* Mark all rows below the last visible one in the current
 	       matrix as invalid.  This is necessary because of
@@ -3571,6 +3691,16 @@
       
     set_cursor:
       
+      /* Fix the appearance of overlapping(overlapped rows.  */
+      if (rif->fix_overlapping_area
+	  && !w->pseudo_window_p
+	  && changed_p
+	  && !paused_p)
+	{
+	  redraw_overlapped_rows (w, yb);
+	  redraw_overlapping_rows (w, yb);
+	}
+      
       if (!paused_p && !w->pseudo_window_p)
 	{
 	  /* Make cursor visible at cursor position of W.  */
@@ -3588,14 +3718,16 @@
       /* Remember the redisplay method used to display the matrix.  */
       strcpy (w->current_matrix->method, w->desired_matrix->method);
 #endif
-      
+
       /* End of update of window W.  */
       rif->update_window_end_hook (w, 1);
+
     }
   else
     paused_p = 1;
 
   clear_glyph_matrix (desired_matrix);
+
   return paused_p;
 }
 
@@ -3624,15 +3756,17 @@
 }
 
 
-/* Update the display of the text area of row VPOS in window W.  */
-
-static void
+/* Update the display of the text area of row VPOS in window W.
+   Value is non-zero if display has changed.  */
+
+static int
 update_text_area (w, vpos)
      struct window *w;
      int vpos;
 {
   struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+  int changed_p = 0;
 
   /* Let functions in xterm.c know what area subsequent X positions
      will be relative to.  */
@@ -3643,7 +3777,10 @@
   if (!current_row->enabled_p
       || desired_row->y != current_row->y
       || desired_row->ascent != current_row->ascent
+      || desired_row->phys_ascent != current_row->phys_ascent
+      || desired_row->phys_height != current_row->phys_height
       || desired_row->visible_height != current_row->visible_height
+      || current_row->overlapped_p
       || current_row->x != desired_row->x)
     {
       rif->cursor_to (vpos, 0, desired_row->y, desired_row->x);
@@ -3654,6 +3791,7 @@
       
       /* Clear to end of window.  */
       rif->clear_end_of_line (-1);
+      changed_p = 1;
     }
   else
     {
@@ -3736,6 +3874,7 @@
 	      
 	      rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
 	      rif->write_glyphs (start, i - start_hpos);
+	      changed_p = 1;
 	    }
 	}
       
@@ -3744,6 +3883,7 @@
 	{
 	  rif->cursor_to (vpos, i, desired_row->y, x);
 	  rif->write_glyphs (desired_glyph, desired_row->used[TEXT_AREA] - i);
+	  changed_p = 1;
 	}
       
       /* Maybe clear to end of line.  */
@@ -3762,6 +3902,7 @@
 	    rif->cursor_to (vpos, i, desired_row->y,
 			    desired_row->x + desired_row->pixel_width);
 	  rif->clear_end_of_line (-1);
+	  changed_p = 1;
 	}
       else if (desired_row->pixel_width < current_row->pixel_width)
 	{
@@ -3787,20 +3928,25 @@
 	  else
 	    x = current_row->x + current_row->pixel_width;
 	  rif->clear_end_of_line (x);
+	  changed_p = 1;
 	}
     }
+
+  return changed_p;
 }
 
 
-/* Update row VPOS in window W.  */
-
-static void
+/* Update row VPOS in window W.  Value is non-zero if display has been
+   changed.  */
+
+static int
 update_window_line (w, vpos)
      struct window *w;
      int vpos;
 {
   struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
   struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
+  int changed_p = 0;
 
   xassert (desired_row->enabled_p);
 
@@ -3811,15 +3957,21 @@
   /* Update display of the left margin area, if there is one.  */
   if (!desired_row->full_width_p
       && !NILP (w->left_margin_width))
-    update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
+    {
+      update_marginal_area (w, LEFT_MARGIN_AREA, vpos);
+      changed_p = 1;
+    }
   
   /* Update the display of the text area.  */
-  update_text_area (w, vpos);
+  changed_p |= update_text_area (w, vpos);
   
   /* Update display of the right margin area, if there is one.  */
   if (!desired_row->full_width_p
       && !NILP (w->right_margin_width))
-    update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
+    {
+      changed_p = 1;
+      update_marginal_area (w, RIGHT_MARGIN_AREA, vpos);
+    }
   
   /* Draw truncation marks etc.  */
   if (!current_row->enabled_p
@@ -3839,6 +3991,7 @@
   /* Update current_row from desired_row.  */
   make_current (w->desired_matrix, w->current_matrix, vpos);
   updated_row = NULL;
+  return changed_p;
 }
 
 
@@ -4207,10 +4360,14 @@
 	for (j = 0; j < r->nrows; ++j)
 	  {
 	    struct glyph_row *from, *to;
+	    int to_overlapped_p;
+	    
 	    to = MATRIX_ROW (current_matrix, r->desired_vpos + j);
+	    to_overlapped_p = to->overlapped_p;
 	    from = MATRIX_ROW (desired_matrix, r->desired_vpos + j);
 	    assign_row (to, from);
 	    to->enabled_p = 1, from->enabled_p = 0;
+	    to->overlapped_p = to_overlapped_p;
 	  }
       }