changeset 6791:7036e4fd549f

(dumpglyphs): Clear any extra pixel rows below the text. (x_display_box_cursor): Explicitly clear full height of line. (dumpglyphs): New arg just_foreground. Callers changed. (x_set_window_size): Call XSync. (note_mouse_highlight): Do nothing if buffer has changed.
author Richard M. Stallman <rms@gnu.org>
date Sun, 10 Apr 1994 06:06:51 +0000
parents ee8090b47ea6
children 385261457584
files src/xterm.c
diffstat 1 files changed, 228 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/xterm.c	Sun Apr 10 06:04:33 1994 +0000
+++ b/src/xterm.c	Sun Apr 10 06:06:51 1994 +0000
@@ -347,6 +347,7 @@
 
 static void flashback ();
 static void redraw_previous_char ();
+static void redraw_following_char ();
 static unsigned int x_x_to_emacs_modifiers ();
 
 static void note_mouse_highlight ();
@@ -541,6 +542,8 @@
    WINDOW is the x-window to output to.  LEFT and TOP are starting coords.
    HL is 1 if this text is highlighted, 2 if the cursor is on it,
    3 if should appear in its mouse-face.
+   JUST_FOREGROUND if 1 means draw only the foreground;
+   don't alter the background.
 
    FONT is the default font to use (for glyphs whose font-code is 0).
 
@@ -555,12 +558,13 @@
 /* This is the multi-face code.  */
 
 static void
-dumpglyphs (f, left, top, gp, n, hl)
+dumpglyphs (f, left, top, gp, n, hl, just_foreground)
      struct frame *f;
      int left, top;
      register GLYPH *gp; /* Points to first GLYPH. */
      register int n;  /* Number of glyphs to display. */
      int hl;
+     int just_foreground;
 {
   /* Holds characters to be displayed. */
   char *buf = (char *) alloca (f->width * sizeof (*buf));
@@ -568,6 +572,7 @@
   register int tlen = GLYPH_TABLE_LENGTH;
   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
   Window window = FRAME_X_WINDOW (f);
+  int orig_left = left;
 
   while (n > 0)
     {
@@ -691,8 +696,36 @@
 	if ((int) font == FACE_DEFAULT)
 	  font = f->display.x->font;
 
-	XDrawImageString (x_current_display, window, gc,
-			  left, top + FONT_BASE (font), buf, len);
+	if (just_foreground)
+	  XDrawString (x_current_display, window, gc,
+		       left, top + FONT_BASE (font), buf, len);
+	else
+	  {
+	    XDrawImageString (x_current_display, window, gc,
+			      left, top + FONT_BASE (font), buf, len);
+	    /* Clear the rest of the line's height.  */
+	    if (f->display.x->line_height != FONT_HEIGHT (font))
+	      XClearArea (x_current_display, window, left,
+			  top + FONT_HEIGHT (font),
+			  FONT_WIDTH (font) * len,
+			  /* This is how many pixels of height
+			     we have to clear.  */
+			  f->display.x->line_height - FONT_HEIGHT (font),
+			  False);
+	  }
+
+#if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
+	 which often is not up to date yet.  */
+	if (!just_foreground)
+	  {
+	    if (left == orig_left)
+	      redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
+				    PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+	    if (n == 0)
+	      redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
+				     PIXEL_TO_CHAR_ROW (f, top), hl == 1);
+	  }
+#endif
 
 	if (gc_temporary)
 	  XFreeGC (x_current_display, gc);
@@ -783,7 +816,7 @@
   dumpglyphs (f,
 	      CHAR_TO_PIXEL_COL (f, curs_x),
 	      CHAR_TO_PIXEL_ROW (f, curs_y),
-	      start, len, highlight);
+	      start, len, highlight, 0);
 
   /* If we drew on top of the cursor, note that it is turned off.  */
   if (curs_y == f->phys_cursor_y
@@ -841,7 +874,7 @@
 	      FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
 	      f->display.x->line_height, False);
 #if 0
-  redraw_previous_char (f, curs_x, curs_y);
+  redraw_previous_char (f, curs_x, curs_y, highlight);
 #endif
 #else /* ! defined (HAVE_X11) */
   XPixSet (FRAME_X_WINDOW (f),
@@ -855,39 +888,6 @@
   UNBLOCK_INPUT;
 }
 
-/* Erase the character (if any) at the position just before X, Y in frame F,
-   then redraw it and the character before it.
-   This is necessary when we erase starting at X,
-   in case the character after X overlaps into the one before X.
-   Call this function with input blocked.  */
-
-static void
-redraw_previous_char (f, x, y)
-     FRAME_PTR f;
-     int x, y;
-{
-  /* Erase the character before the new ones, in case
-     what was here before overlaps it.
-     Reoutput that character, and the previous character
-     (in case the previous character overlaps it).  */
-  if (x > 0)
-    {
-      int start_x = x - 2;
-      if (start_x < 0)
-	start_x = 0;
-      XClearArea (x_current_display, FRAME_X_WINDOW (f),
-		  CHAR_TO_PIXEL_COL (f, x - 1),
-		  CHAR_TO_PIXEL_ROW (f, y),
-		  FONT_WIDTH (f->display.x->font),
-		  f->display.x->line_height, False);
-
-      dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
-		  CHAR_TO_PIXEL_ROW (f, y),
-		  &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
-		  x - start_x, highlight);
-    }
-}
-
 static
 XTclear_frame ()
 {
@@ -917,6 +917,179 @@
   UNBLOCK_INPUT;
 }
 
+#if 0
+/* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
+   always contain the right glyphs to use.
+
+   It also needs to be changed to look at the details of the font and
+   see whether there is really overlap, and do nothing when there is
+   not.  This can use font_char_overlap_left and font_char_overlap_right,
+   but just how to use them is not clear.  */
+
+/* Erase the character (if any) at the position just before X, Y in frame F,
+   then redraw it and the character before it.
+   This is necessary when we erase starting at X,
+   in case the character after X overlaps into the one before X.
+   Call this function with input blocked.  */
+
+static void
+redraw_previous_char (f, x, y, highlight_flag)
+     FRAME_PTR f;
+     int x, y;
+     int highlight_flag;
+{
+  /* Erase the character before the new ones, in case
+     what was here before overlaps it.
+     Reoutput that character, and the previous character
+     (in case the previous character overlaps it).  */
+  if (x > 0)
+    {
+      int start_x = x - 2;
+      if (start_x < 0)
+	start_x = 0;
+      XClearArea (x_current_display, FRAME_X_WINDOW (f),
+		  CHAR_TO_PIXEL_COL (f, x - 1),
+		  CHAR_TO_PIXEL_ROW (f, y),
+		  FONT_WIDTH (f->display.x->font),
+		  f->display.x->line_height, False);
+
+      dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
+		  CHAR_TO_PIXEL_ROW (f, y),
+		  &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
+		  x - start_x, highlight_flag, 1);
+    }
+}
+
+/* Erase the character (if any) at the position X, Y in frame F,
+   then redraw it and the character after it.
+   This is necessary when we erase endng at X,
+   in case the character after X overlaps into the one before X.
+   Call this function with input blocked.  */
+
+static void
+redraw_following_char (f, x, y, highlight_flag)
+     FRAME_PTR f;
+     int x, y;
+     int highlight_flag;
+{
+  int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
+  /* Erase the character after the new ones, in case
+     what was here before overlaps it.
+     Reoutput that character, and the following character
+     (in case the following character overlaps it).  */
+  if (x < limit
+      && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
+    {
+      int end_x = x + 2;
+      if (end_x > limit)
+	end_x = limit;
+      XClearArea (x_current_display, FRAME_X_WINDOW (f),
+		  CHAR_TO_PIXEL_COL (f, x),
+		  CHAR_TO_PIXEL_ROW (f, y),
+		  FONT_WIDTH (f->display.x->font),
+		  f->display.x->line_height, False);
+
+      dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
+		  CHAR_TO_PIXEL_ROW (f, y),
+		  &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
+		  end_x - x, highlight_flag, 1);
+    }
+}
+#endif /* 0 */
+
+#if 0 /* Not in use yet */
+
+/* Return 1 if character C in font F extends past its left edge.  */
+
+static int
+font_char_overlap_left (font, c)
+     XFontStruct *font;
+     int c;
+{
+  XCharStruct *s;
+
+  /* Find the bounding-box info for C.  */
+  if (font->per_char == 0)
+    s = &font->max_bounds;
+  else
+    {
+      int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+      int row, within;
+	
+      /* Decode char into row number (byte 1) and code within row (byte 2).  */
+      row = c >> 8;
+      within = c & 0177;
+      if (!(within >= font->min_char_or_byte2
+	    && within <= font->max_char_or_byte2
+	    && row >= font->min_byte1
+	    && row <= font->max_byte1))
+	{
+	  /* If char is out of range, try the font's default char instead.  */
+	  c = font->default_char;
+	  row = c >> (INTBITS - 8);
+	  within = c & 0177;
+	}
+      if (!(within >= font->min_char_or_byte2
+	    && within <= font->max_char_or_byte2
+	    && row >= font->min_byte1
+	    && row <= font->max_byte1))
+	/* Still out of range means this char does not overlap.  */
+	return 0;
+      else
+	/* We found the info for this char.  */
+	s = (font->per_char + (within - font->min_char_or_byte2)
+	     + row * rowlen);
+    }
+
+  return (s && s->lbearing < 0);
+}
+
+/* Return 1 if character C in font F extends past its right edge.  */
+
+static int
+font_char_overlap_right (font, c)
+     XFontStruct *font;
+     int c;
+{
+  XCharStruct *s;
+
+  /* Find the bounding-box info for C.  */
+  if (font->per_char == 0)
+    s = &font->max_bounds;
+  else
+    {
+      int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
+      int row, within;
+	
+      /* Decode char into row number (byte 1) and code within row (byte 2).  */
+      row = c >> 8;
+      within = c & 0177;
+      if (!(within >= font->min_char_or_byte2
+	    && within <= font->max_char_or_byte2
+	    && row >= font->min_byte1
+	    && row <= font->max_byte1))
+	{
+	  /* If char is out of range, try the font's default char instead.  */
+	  c = font->default_char;
+	  row = c >> (INTBITS - 8);
+	  within = c & 0177;
+	}
+      if (!(within >= font->min_char_or_byte2
+	    && within <= font->max_char_or_byte2
+	    && row >= font->min_byte1
+	    && row <= font->max_byte1))
+	/* Still out of range means this char does not overlap.  */
+	return 0;
+      else
+	/* We found the info for this char.  */
+	s = (font->per_char + (within - font->min_char_or_byte2)
+	     + row * rowlen);
+    }
+
+  return (s && s->rbearing >= s->width);
+}
+#endif /* 0 */
+
 /* Invert the middle quarter of the frame for .15 sec.  */
 
 /* We use the select system call to do the waiting, so we have to make sure
@@ -1336,7 +1509,7 @@
 		  CHAR_TO_PIXEL_COL (f, left),
 		  CHAR_TO_PIXEL_ROW (f, y),
 		  line, min (cols, active_frame->used[y] - left),
-		  active_frame->highlight[y]);
+		  active_frame->highlight[y], 0);
     }
 
   /* Turn the cursor on if we turned it off.  */
@@ -1981,9 +2154,11 @@
   if (! EQ (window, mouse_face_window))
     clear_mouse_face ();
 
-  /* Are we in a window whose display is up to date?  */
+  /* Are we in a window whose display is up to date?
+     And verify the buffer's text has not changed.  */
   if (WINDOWP (window) && portion == 0
-      && EQ (w->window_end_valid, w->buffer))
+      && EQ (w->window_end_valid, w->buffer)
+      && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
     {
       int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
       int i, pos;
@@ -2202,7 +2377,7 @@
 		  FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
 		  endcolumn - column,
 		  /* Highlight with mouse face if hl > 0.  */
-		  hl > 0 ? 3 : 0);
+		  hl > 0 ? 3 : 0, 0);
     }
 
   /* If we turned the cursor off, turn it back on.  */
@@ -4275,7 +4450,7 @@
   dumpglyphs (f,
 	      CHAR_TO_PIXEL_COL (f, column),
 	      CHAR_TO_PIXEL_ROW (f, row),
-	      &glyph, 1, highlight);
+	      &glyph, 1, highlight, 0);
 }
 
 static void
@@ -4383,6 +4558,14 @@
 	  || (f->display.x->current_cursor != hollow_box_cursor
 	      && (f != x_highlight_frame))))
     {
+      /* If the font is not as tall as a whole line,
+	 we must explicitly clear the line's whole height.  */
+      if (FONT_HEIGHT (f->display.x->font) != f->display.x->line_height)
+	XClearArea (x_current_display, FRAME_X_WINDOW (f),
+		    CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
+		    CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
+		    FONT_WIDTH (f->display.x->font),
+		    f->display.x->line_height, False);
       /* Erase the cursor by redrawing the character underneath it.  */
       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
 			   f->phys_cursor_glyph,
@@ -4903,7 +5086,7 @@
   else
     /* If we are setting a new frame's font for the first time,
        there are no faces yet, so this font's height is the line height.  */
-    f->display.x->line_height = FONT_HEIGHT (f);
+    f->display.x->line_height = FONT_HEIGHT (f->display.x->font);
 
   {
     Lisp_Object lispy_name;
@@ -5051,6 +5234,7 @@
 #ifdef HAVE_X11
   x_wm_set_size_hint (f, 0, change_gravity, 0, 0);
 #endif /* ! defined (HAVE_X11) */
+  XSync (x_current_display, False);
   XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
 
   /* Now, strictly speaking, we can't be sure that this is accurate,