]> code.delx.au - gnu-emacs/blobdiff - src/dispnew.c
(update_frame_line): If writing whole line,
[gnu-emacs] / src / dispnew.c
index 1f5eb937c7a9c14f8f0b41917b8ca6fdc55607fe..9906022b00e53ecc6ce1c5084e5f79b1ae8296e8 100644 (file)
@@ -109,6 +109,8 @@ struct dim
 \f
 /* 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 @@ void scroll_glyph_matrix_range P_ ((struct glyph_matrix *, int, int,
 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 @@ blank_row (w, row, y)
   
   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 @@ row_equal_p (w, a, b)
          || 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 @@ void
 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 @@ adjust_glyphs (f)
       FOR_EACH_FRAME (tail, lisp_frame)
        adjust_frame_glyphs (XFRAME (lisp_frame));
     }
+
+  UNBLOCK_INPUT;
 }
 
 
@@ -2456,6 +2467,10 @@ build_frame_matrix_from_leaf_window (frame_matrix, w)
 
          /* If rows are in sync, we don't have to copy glyphs because
             frame and window share glyphs.  */
+         
+#if GLYPH_DEBUG
+         strcpy (w->current_matrix->method, w->desired_matrix->method);
+#endif
        }
 
       /* Set number of used glyphs in the frame matrix.  Since we fill
@@ -2617,8 +2632,11 @@ mirror_make_current (w, frame_row)
                = MATRIX_ROW (w->current_matrix, row);
              struct glyph_row *desired_row
                = MATRIX_ROW (w->desired_matrix, row);
-             
-             assign_row (current_row, desired_row);
+
+             if (desired_row->enabled_p)
+               assign_row (current_row, desired_row);
+             else
+               swap_glyph_pointers (desired_row, current_row);
              current_row->enabled_p = 1;
            }
        }
@@ -3025,9 +3043,15 @@ direct_output_for_insert (g)
       || 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)))
@@ -3047,7 +3071,7 @@ direct_output_for_insert (g)
   /* Give up if highlighting trailing whitespace and we have trailing
      whitespace in glyph_row.  We would have to remove the trailing
      whitespace face in that case.  */
-  if (it.show_trailing_whitespace_p
+  if (!NILP (Vshow_trailing_whitespace)
       && glyph_row->used[TEXT_AREA])
     {
       struct glyph *last;
@@ -3088,6 +3112,8 @@ direct_output_for_insert (g)
         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;
 
@@ -3159,7 +3185,7 @@ direct_output_for_insert (g)
   glyph_row->contains_overlapping_glyphs_p
     |= it.glyph_row->contains_overlapping_glyphs_p;
 
-  if (it.show_trailing_whitespace_p)
+  if (!NILP (Vshow_trailing_whitespace))
     highlight_trailing_whitespace (it.f, glyph_row);
 
   /* Write glyphs.  If at end of row, we can simply call write_glyphs.
@@ -3257,6 +3283,10 @@ direct_output_forward_char (n)
   if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
     return 0;
 
+  /* Can't use direct output if highlighting trailing whitespace.  */
+  if (!NILP (Vshow_trailing_whitespace))
+    return 0;
+
   row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
 
   if (PT <= MATRIX_ROW_START_BYTEPOS (row)
@@ -3450,6 +3480,104 @@ update_single_window (w, force_p)
 }
 
 
+/* 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 +3610,7 @@ update_window (w, force_p)
       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 +3629,7 @@ update_window (w, force_p)
          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 +3650,7 @@ update_window (w, force_p)
            }
          else if (rc > 0)
            force_p = 1;
+         changed_p = 1;
        }
 
       /* Update the top mode line after scrolling because a new top
@@ -3530,6 +3660,7 @@ update_window (w, force_p)
        {
          top_line_row->y = 0;
          update_window_line (w, 0);
+         changed_p = 1;
        }
 
       /* Update the rest of the lines.  */
@@ -3550,7 +3681,7 @@ update_window (w, force_p)
            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 +3702,16 @@ update_window (w, force_p)
       
     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 +3729,16 @@ update_window (w, force_p)
       /* 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 +3767,17 @@ update_marginal_area (w, area, vpos)
 }
 
 
-/* Update the display of the text area of row VPOS in window W.  */
+/* Update the display of the text area of row VPOS in window W.
+   Value is non-zero if display has changed.  */
 
-static void
+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 +3788,10 @@ update_text_area (w, vpos)
   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 +3802,7 @@ update_text_area (w, vpos)
       
       /* Clear to end of window.  */
       rif->clear_end_of_line (-1);
+      changed_p = 1;
     }
   else
     {
@@ -3736,6 +3885,7 @@ update_text_area (w, vpos)
              
              rif->cursor_to (vpos, start_hpos, desired_row->y, start_x);
              rif->write_glyphs (start, i - start_hpos);
+             changed_p = 1;
            }
        }
       
@@ -3744,6 +3894,7 @@ update_text_area (w, vpos)
        {
          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 +3913,7 @@ update_text_area (w, vpos)
            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 +3939,25 @@ update_text_area (w, vpos)
          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.  */
+/* Update row VPOS in window W.  Value is non-zero if display has been
+   changed.  */
 
-static void
+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 +3968,21 @@ update_window_line (w, vpos)
   /* 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 +4002,7 @@ update_window_line (w, vpos)
   /* Update current_row from desired_row.  */
   make_current (w->desired_matrix, w->current_matrix, vpos);
   updated_row = NULL;
+  return changed_p;
 }
 
 
@@ -3875,28 +4039,37 @@ set_window_cursor_after_update (w)
             line that has any text on it.  Note: either all lines
             are enabled or none.  Otherwise we wouldn't be able to
             determine Y.  */
-         struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
-         int vpos, last_row_vpos;
-         struct glyph_row *last_row = NULL;
+         struct glyph_row *row, *last_row;
+         struct glyph *glyph;
+         int yb = window_text_bottom_y (w);
 
-         vpos = 0;
-         while (vpos < w->current_matrix->nrows)
+         last_row = NULL;
+         for (row = MATRIX_ROW (w->current_matrix, 0);; ++row)
            {
-             if (row->enabled_p && row->used[TEXT_AREA])
-               {
-                 last_row = row;
-                 last_row_vpos = vpos;
-               }
-             ++row;
-             ++vpos;
-           }
+             if (row->used[TEXT_AREA]
+                 && row->glyphs[TEXT_AREA][0].charpos >= 0)
+               last_row = row;
 
+             if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
+               break;
+           }
+         
          if (last_row)
            {
-             cx = last_row->pixel_width;
-             hpos = last_row->used[TEXT_AREA];
+             struct glyph *start = row->glyphs[TEXT_AREA];
+             struct glyph *last = start + row->used[TEXT_AREA];
+
+             while (last > start && (last - 1)->charpos < 0)
+               --last;
+             
+             for (glyph = start; glyph < last; ++glyph)
+               {
+                 cx += glyph->pixel_width;
+                 ++hpos;
+               }
+
              cy = last_row->y;
-             vpos = last_row_vpos;
+             vpos = MATRIX_ROW_VPOS (last_row, w->current_matrix);
            }
        }
     }
@@ -4207,10 +4380,14 @@ scrolling_window (w, top_line_p)
        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;
          }
       }
 
@@ -4659,10 +4836,18 @@ update_frame_line (frame, vpos)
   /* If display line has unknown contents, write the whole line.  */
   if (must_write_whole_line_p)
     {
-      cursor_to (vpos, 0);
-      write_glyphs (nbody, nlen);
+      if (!must_write_spaces)
+       while (nlen > 0 && CHAR_GLYPH_SPACE_P (nbody[nlen - 1]))
+         --nlen;
+
+      if (nlen)
+       {
+         cursor_to (vpos, 0);
+         write_glyphs (nbody, nlen);
+       }
+      
       cursor_to (vpos, nlen);
-      clear_end_of_line (-1);
+      clear_end_of_line (olen);
       make_current (desired_matrix, current_matrix, vpos);
       return;
     }
@@ -5693,6 +5878,13 @@ For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
   /* Set up faces of the initial terminal frame of a dumped Emacs.  */
   if (initialized
       && !noninteractive
+#ifdef MSDOS
+      /* The MSDOS terminal turns on its ``window system'' relatively
+        late into the startup, so we cannot do the frame faces'
+        initialization just yet.  It will be done later by pc-win.el
+        and internal_terminal_init.  */
+      && (strcmp (terminal_type, "internal") != 0 || inhibit_window_system)
+#endif
       && NILP (Vwindow_system))
     call0 (intern ("tty-set-up-initial-frame-faces"));
 }