changeset 89381:eaf61dbe44af

(SKIP_GLYPHS): New macro. (set_cursor_from_row): Pay attention to string display properties.
author Kenichi Handa <handa@m17n.org>
date Fri, 31 Jan 2003 06:11:01 +0000
parents 9320c2f4f351
children c25cbf7ce916
files src/xdisp.c
diffstat 1 files changed, 84 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/xdisp.c	Fri Jan 31 06:10:06 2003 +0000
+++ b/src/xdisp.c	Fri Jan 31 06:11:01 2003 +0000
@@ -9356,6 +9356,19 @@
   return Qnil;
 }
 
+
+/* Increment GLYPH until it reaches END or CONDITION fails while
+   adding (GLYPH)->pixel_width to X. */
+
+#define SKIP_GLYPHS(glyph, end, x, condition)	\
+  do						\
+    {						\
+      (x) += (glyph)->pixel_width;		\
+      ++(glyph);				\
+    }						\
+  while ((glyph) < (end) && (condition))
+
+
 /* Set cursor position of W.  PT is assumed to be displayed in ROW.
    DELTA is the number of bytes by which positions recorded in ROW
    differ from current buffer positions.  */
@@ -9369,6 +9382,14 @@
 {
   struct glyph *glyph = row->glyphs[TEXT_AREA];
   struct glyph *end = glyph + row->used[TEXT_AREA];
+  /* The first glyph that starts a sequence of glyphs from string.  */
+  struct glyph *string_start;
+  /* The X coordinate of string_start.  */
+  int string_start_x;
+  /* The last known character position.  */
+  int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
+  /* The last known character position before string_start.  */
+  int string_before_pos;
   int x = row->x;
   int pt_old = PT - delta;
 
@@ -9384,13 +9405,72 @@
 	++glyph;
       }
 
+  string_start = NULL;
   while (glyph < end
 	 && !INTEGERP (glyph->object)
 	 && (!BUFFERP (glyph->object)
-	     || glyph->charpos < pt_old))
-    {
-      x += glyph->pixel_width;
-      ++glyph;
+	     || (last_pos = glyph->charpos) < pt_old))
+    {
+      if (! STRINGP (glyph->object))
+	{
+	  string_start = NULL;
+	  x += glyph->pixel_width;
+	  ++glyph;
+	}
+      else
+	{
+	  string_before_pos = last_pos;
+	  string_start = glyph;
+	  string_start_x = x;
+	  /* Skip all glyphs from string.  */
+	  SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
+	}
+    }
+
+  if (string_start
+      && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
+    {
+      /* We may have skipped over point because the previous glyphs
+	 are from string.  As there's no easy way to know the
+	 character position of the current glyph, find the correct
+	 glyph on point by scanning from string_start again.  */
+      Lisp_Object limit;
+      Lisp_Object string;
+      int pos;
+
+      limit = make_number (pt_old + 1);
+      end = glyph;
+      glyph = string_start;
+      x = string_start_x;
+      string = glyph->object;
+      pos = string_buffer_position (w, string, string_before_pos);
+      /* If STRING is from overlay, LAST_POS == 0.  We skip such glyphs
+	 because we always put cursor after overlay strings.  */
+      while (pos == 0 && glyph < end)
+	{
+	  string = glyph->object;
+	  SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+	  if (glyph < end)
+	    pos = string_buffer_position (w, glyph->object, string_before_pos);
+	}
+
+      while (glyph < end)
+	{
+	  pos = XINT (Fnext_single_char_property_change
+		      (make_number (pos), Qdisplay, Qnil, limit));
+	  if (pos > pt_old)
+	    break;
+	  /* Skip glyphs from the same string.  */
+	  string = glyph->object;
+	  SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+	  /* Skip glyphs from an overlay.  */
+	  while (glyph < end
+		 && ! string_buffer_position (w, glyph->object, pos))
+	    {
+	      string = glyph->object;
+	      SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+	    }
+	}
     }
 
   w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];