changeset 111102:9fbc584102c2

Support R2L rows. Continued lines still don't work correctly. xdisp.c (mouse_face_from_buffer_pos): Fix code using bug#1220 as test case. Implement highlight for R2L rows.
author Eli Zaretskii <eliz@gnu.org>
date Sat, 28 Aug 2010 14:09:02 +0300
parents f4fc1590d904
children 6af5749f5c94
files src/ChangeLog src/xdisp.c
diffstat 2 files changed, 117 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sat Aug 28 12:32:44 2010 +0300
+++ b/src/ChangeLog	Sat Aug 28 14:09:02 2010 +0300
@@ -1,7 +1,7 @@
 2010-08-28  Eli Zaretskii  <eliz@gnu.org>
 
 	* xdisp.c (mouse_face_from_buffer_pos): Fix code using bug#1220 as
-	test case.
+	test case.  Implement  highlight for R2L rows.
 
 2010-08-21  Eli Zaretskii  <eliz@gnu.org>
 
--- a/src/xdisp.c	Sat Aug 28 12:32:44 2010 +0300
+++ b/src/xdisp.c	Sat Aug 28 14:09:02 2010 +0300
@@ -23916,9 +23916,10 @@
 		 ++glyph)
 	      x += glyph->pixel_width;
 
-      /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
-	 or DISPLAY_STRING, and the first glyph whose position is
-	 between START_CHARPOS and END_CHARPOS.  */
+	  /* Scan the glyph row, looking for BEFORE_STRING,
+	     AFTER_STRING, or DISPLAY_STRING, and the first glyph from
+	     buffer whose position is between START_CHARPOS and
+	     END_CHARPOS.  */
 	  for (; glyph < end
 		 && !INTEGERP (glyph->object)
 		 && !EQ (glyph->object, display_string)
@@ -23953,7 +23954,64 @@
 	}
       else
 	{
-	  /* FIXME! */
+	  /* This row is in a right to left paragraph.  Scan it right
+	     to left.  */
+	  struct glyph *g;
+
+	  end = row->glyphs[TEXT_AREA] - 1;
+	  glyph = end + row->used[TEXT_AREA];
+
+	  /* Skip truncation glyphs at the start of the glyph row.  */
+	  if (row->displays_text_p)
+	    for (; glyph > end
+		   && INTEGERP (glyph->object)
+		   && glyph->charpos < 0;
+		 --glyph)
+	      ;
+
+	  /* Scan the glyph row, looking for BEFORE_STRING,
+	     AFTER_STRING, or DISPLAY_STRING, and the first glyph from
+	     buffer whose position is between START_CHARPOS and
+	     END_CHARPOS.  */
+	  for (; glyph > end
+		 && !INTEGERP (glyph->object)
+		 && !EQ (glyph->object, display_string)
+		 && !(BUFFERP (glyph->object)
+		      && (glyph->charpos >= start_charpos
+			  && glyph->charpos < end_charpos));
+	       --glyph)
+	    {
+	      /* BEFORE_STRING or AFTER_STRING are only relevant if
+		 they are present at buffer positions between
+		 START_CHARPOS and END_CHARPOS, or if they come from
+		 an overlay.  */
+	      if (EQ (glyph->object, before_string))
+		{
+		  pos = string_buffer_position (w, before_string,
+						start_charpos);
+		  /* If pos == 0, it means before_string came from an
+		     overlay, not from a buffer position.  */
+		  if (!pos || pos >= start_charpos && pos < end_charpos)
+		    break;
+		}
+	      else if (EQ (glyph->object, after_string))
+		{
+		  pos = string_buffer_position (w, after_string, end_charpos);
+		  if (!pos || pos >= start_charpos && pos < end_charpos)
+		    break;
+		}
+	    }
+
+	  /* Mouse highlight uses the screen geometry, which is left
+	     to right even in R2L paragraphs.  Therefore, for R2L
+	     paragraphs, the "first" highlighted glyph actually
+	     determines the _end_ column and x of the highlighted
+	     area.  */
+	  glyph++;	/* first glyph beyond the highlighted area */
+	  for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
+	    x += g->pixel_width;
+	  dpyinfo->mouse_face_end_x = x;
+	  dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA];
 	}
     }
 
@@ -24023,14 +24081,60 @@
       /* Find the X coordinate of the last glyph to be highlighted.  */
       for (; glyph <= end; ++glyph)
 	x += glyph->pixel_width;
-    }
-  else
-    {
-      /* FIXME! */
-    }
-
-  dpyinfo->mouse_face_end_x = x;
-  dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA];
+
+      dpyinfo->mouse_face_end_x = x;
+      dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA];
+    }
+  else
+    {
+      /* Skip truncation and continuation glyphs near the end of the
+	 row, and also blanks and stretch glyphs inserted by
+	 extend_face_to_end_of_line.  */
+      x = row->x;
+      end++;
+      while (end < glyph
+	     && INTEGERP (end->object)
+	     && end->charpos <= 0)
+	{
+	  x += end->pixel_width;
+	  ++end;
+	}
+      /* Scan the rest of the glyph row from the end, looking for the
+	 first glyph that comes from BEFORE_STRING, AFTER_STRING, or
+	 DISPLAY_STRING, or whose position is between START_CHARPOS
+	 and END_CHARPOS */
+      for ( ;
+	     end < glyph
+	     && !INTEGERP (end->object)
+	     && !EQ (end->object, display_string)
+	     && !(BUFFERP (end->object)
+		  && (end->charpos >= start_charpos
+		      && end->charpos < end_charpos));
+	   ++end)
+	{
+	  /* BEFORE_STRING or AFTER_STRING are only relevant if they
+	     are present at buffer positions between START_CHARPOS and
+	     END_CHARPOS, or if they come from an overlay.  */
+	  if (EQ (end->object, before_string))
+	    {
+	      pos = string_buffer_position (w, before_string, start_charpos);
+	      if (!pos || pos >= start_charpos && pos < end_charpos)
+		break;
+	    }
+	  else if (EQ (end->object, after_string))
+	    {
+	      pos = string_buffer_position (w, after_string, end_charpos);
+	      if (!pos || pos >= start_charpos && pos < end_charpos)
+		break;
+	    }
+	  x += end->pixel_width;
+	}
+      /* In the left-to-right screen geometry, END is actually the
+	 _beginning_ of the highlighted area for R2L paragraphs.  */
+      dpyinfo->mouse_face_beg_x = x;
+      dpyinfo->mouse_face_beg_col = end - row->glyphs[TEXT_AREA];
+    }
+
   dpyinfo->mouse_face_window = window;
   dpyinfo->mouse_face_face_id
     = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore,