summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2011-07-09 16:57:13 +0300
committerEli Zaretskii <eliz@gnu.org>2011-07-09 16:57:13 +0300
commit3855635591937dc2076ff143f8ad3b8b35495231 (patch)
treec50cff61f4d3341a8f4b9c8077e44245fd65e573
parentad3c1639757e8b5aefb490426ca44dad08b74130 (diff)
downloademacs-3855635591937dc2076ff143f8ad3b8b35495231.tar.gz
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.
-rw-r--r--src/ChangeLog18
-rw-r--r--src/xdisp.c56
2 files changed, 60 insertions, 14 deletions
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)