From: Eli Zaretskii <eliz@gnu.org>
Date: Sat, 9 Jul 2011 13:57:13 +0000 (+0300)
Subject: Fix various problems with cursor positioning around display properties.
X-Git-Tag: emacs-pretest-24.0.90~104^2~275^2~4
X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=3855635591937dc2076ff143f8ad3b8b35495231;p=emacs.git

Fix various problems with cursor positioning around display properties.

 src/xdisp.c (move_it_in_display_line_to): Record prev_method and
 prev_pos immediately before the call to set_iterator_to_next.
 Fixes cursor motion in bidi-reordered lines with stretch glyphs
 and strings displayed in margins.  (Bug#8133)  (Bug#8867)
 Return MOVE_POS_MATCH_OR_ZV only if iterator position is past
 TO_CHARPOS.
 (pos_visible_p): Support positions in bidi-reordered lines.  Save
 and restore bidi cache.
 (move_it_in_display_line_to): If iterator ended up at
 EOL, but we never saw any buffer positions smaller than
 to_charpos, return MOVE_POS_MATCH_OR_ZV.  Fixes vertical cursor
 motion in bidi-reordered lines.
---

diff --git a/src/ChangeLog b/src/ChangeLog
index 74a684df45e..7dc419ef731 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
+2011-07-09  Eli Zaretskii  <eliz@gnu.org>
+
+	* xdisp.c (move_it_in_display_line_to): Record prev_method and
+	prev_pos immediately before the call to set_iterator_to_next.
+	Fixes cursor motion in bidi-reordered lines with stretch glyphs
+	and strings displayed in margins.  (Bug#8133)  (Bug#8867)
+	Return MOVE_POS_MATCH_OR_ZV only if iterator position is past
+	TO_CHARPOS.
+	(pos_visible_p): Support positions in bidi-reordered lines.  Save
+	and restore bidi cache.
+
+2011-07-08  Eli Zaretskii  <eliz@gnu.org>
+
+	* xdisp.c (move_it_in_display_line_to): If iterator ended up at
+	EOL, but we never saw any buffer positions smaller than
+	to_charpos, return MOVE_POS_MATCH_OR_ZV.  Fixes vertical cursor
+	motion in bidi-reordered lines.
+
 2011-07-07  Eli Zaretskii  <eliz@gnu.org>
 
 	* xdisp.c (find_row_edges): If ROW->start.pos gives position
diff --git a/src/xdisp.c b/src/xdisp.c
index 1cc3e2eaadb..cef2fe6df7b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1222,6 +1222,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
 	       int *rtop, int *rbot, int *rowh, int *vpos)
 {
   struct it it;
+  void *itdata = bidi_shelve_cache ();
   struct text_pos top;
   int visible_p = 0;
   struct buffer *old_buffer = NULL;
@@ -1252,13 +1253,21 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
   move_it_to (&it, charpos, -1, it.last_visible_y-1, -1,
 	      (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
 
-  if (charpos >= 0 && IT_CHARPOS (it) >= charpos)
+  if (charpos >= 0
+      && (((!it.bidi_p || it.bidi_it.scan_dir == 1)
+	   && IT_CHARPOS (it) >= charpos)
+	  /* When scanning backwards under bidi iteration, move_it_to
+	     stops at or _before_ CHARPOS, because it stops at or to
+	     the _right_ of the character at CHARPOS. */
+	  || (it.bidi_p && it.bidi_it.scan_dir == -1
+	      && IT_CHARPOS (it) <= charpos)))
     {
       /* We have reached CHARPOS, or passed it.  How the call to
-	 move_it_to can overshoot: (i) If CHARPOS is on invisible
-	 text, move_it_to stops at the end of the invisible text,
-	 after CHARPOS.  (ii) If CHARPOS is in a display vector,
-	 move_it_to stops on its last glyph.  */
+	 move_it_to can overshoot: (i) If CHARPOS is on invisible text
+	 or covered by a display property, move_it_to stops at the end
+	 of the invisible text, to the right of CHARPOS.  (ii) If
+	 CHARPOS is in a display vector, move_it_to stops on its last
+	 glyph.  */
       int top_x = it.current_x;
       int top_y = it.current_y;
       enum it_method it_method = it.method;
@@ -1307,6 +1316,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
     }
   else
     {
+      /* We were asked to provide info about WINDOW_END.  */
       struct it it2;
       void *it2data = NULL;
 
@@ -1333,6 +1343,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
       else
 	xfree (it2data);
     }
+  bidi_unshelve_cache (itdata);
 
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
@@ -7525,6 +7536,7 @@ move_it_in_display_line_to (struct it *it,
   int may_wrap = 0;
   enum it_method prev_method = it->method;
   EMACS_INT prev_pos = IT_CHARPOS (*it);
+  int saw_smaller_pos = prev_pos < to_charpos;
 
   /* Don't produce glyphs in produce_glyphs.  */
   saved_glyph_row = it->glyph_row;
@@ -7565,15 +7577,16 @@ move_it_in_display_line_to (struct it *it,
   ((IT)->current_x = x, (IT)->max_ascent = ascent,	\
    (IT)->max_descent = descent)
 
-      /* Stop if we move beyond TO_CHARPOS (after an image or stretch
-	 glyph).  */
+      /* Stop if we move beyond TO_CHARPOS (after an image or a
+	 display string or stretch glyph).  */
       if ((op & MOVE_TO_POS) != 0
 	  && BUFFERP (it->object)
 	  && it->method == GET_FROM_BUFFER
 	  && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos)
 	      || (it->bidi_p
 		  && (prev_method == GET_FROM_IMAGE
-		      || prev_method == GET_FROM_STRETCH)
+		      || prev_method == GET_FROM_STRETCH
+		      || prev_method == GET_FROM_STRING)
 		  /* Passed TO_CHARPOS from left to right.  */
 		  && ((prev_pos < to_charpos
 		       && IT_CHARPOS (*it) > to_charpos)
@@ -7593,9 +7606,6 @@ move_it_in_display_line_to (struct it *it,
 	    SAVE_IT (atpos_it, *it, atpos_data);
 	}
 
-      prev_method = it->method;
-      if (it->method == GET_FROM_BUFFER)
-	prev_pos = IT_CHARPOS (*it);
       /* Stop when ZV reached.
          We used to stop here when TO_CHARPOS reached as well, but that is
          too soon if this glyph does not fit on this line.  So we handle it
@@ -7659,6 +7669,9 @@ move_it_in_display_line_to (struct it *it,
 
       if (it->area != TEXT_AREA)
 	{
+	  prev_method = it->method;
+	  if (it->method == GET_FROM_BUFFER)
+	    prev_pos = IT_CHARPOS (*it);
 	  set_iterator_to_next (it, 1);
 	  if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
 	    SET_TEXT_POS (this_line_min_pos,
@@ -7770,6 +7783,9 @@ move_it_in_display_line_to (struct it *it,
 				}
 			    }
 
+			  prev_method = it->method;
+			  if (it->method == GET_FROM_BUFFER)
+			    prev_pos = IT_CHARPOS (*it);
 			  set_iterator_to_next (it, 1);
 			  if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
 			    SET_TEXT_POS (this_line_min_pos,
@@ -7863,10 +7879,20 @@ move_it_in_display_line_to (struct it *it,
       /* Is this a line end?  If yes, we're done.  */
       if (ITERATOR_AT_END_OF_LINE_P (it))
 	{
-	  result = MOVE_NEWLINE_OR_CR;
+	  /* If we are past TO_CHARPOS, but never saw any character
+	     positions smaller than TO_CHARPOS, return
+	     MOVE_POS_MATCH_OR_ZV, like the unidirectional display
+	     did.  */
+	  if ((op & MOVE_TO_POS) != 0
+	      && !saw_smaller_pos
+	      && IT_CHARPOS (*it) > to_charpos)
+	    result = MOVE_POS_MATCH_OR_ZV;
+	  else
+	    result = MOVE_NEWLINE_OR_CR;
 	  break;
 	}
 
+      prev_method = it->method;
       if (it->method == GET_FROM_BUFFER)
 	prev_pos = IT_CHARPOS (*it);
       /* The current display element has been consumed.  Advance
@@ -7874,6 +7900,8 @@ move_it_in_display_line_to (struct it *it,
       set_iterator_to_next (it, 1);
       if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
 	SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
+      if (IT_CHARPOS (*it) < to_charpos)
+	saw_smaller_pos = 1;
 
       /* Stop if lines are truncated and IT's current x-position is
 	 past the right edge of the window now.  */
@@ -7967,8 +7995,8 @@ move_it_in_display_line (struct it *it,
    description of enum move_operation_enum.
 
    If TO_CHARPOS is in invisible text, e.g. a truncated part of a
-   screen line, this function will set IT to the next position >
-   TO_CHARPOS.  */
+   screen line, this function will set IT to the next position that is
+   displayed to the right of TO_CHARPOS on the screen.  */
 
 void
 move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos, int op)