summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2011-07-23 13:42:24 +0300
committerEli Zaretskii <eliz@gnu.org>2011-07-23 13:42:24 +0300
commitc1734fbd6fa365e362c600b7b94c40b13401c255 (patch)
tree13ca21188a81d26cf89e9ddb1ac6a4f929f11fca
parentb6d5a68964e812af176a6217882add25703914b2 (diff)
downloademacs-c1734fbd6fa365e362c600b7b94c40b13401c255.tar.gz
Fix pos-visible-in-window-p under bidi redisplay when lines are truncated.
src/xdisp.c (move_it_in_display_line_to): Record the best matching position for TO_CHARPOS while scanning the line, and restore it on exit if none of the characters scanned was an exact match. Fixes vertical-motion and pos-visible-in-window-p when exact match is impossible due to invisible text, and the lines are truncated.
-rw-r--r--src/ChangeLog8
-rw-r--r--src/xdisp.c58
2 files changed, 62 insertions, 4 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c03acbcfd1c..dd5a1fba871 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2011-07-23 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (move_it_in_display_line_to): Record the best matching
+ position for TO_CHARPOS while scanning the line, and restore it on
+ exit if none of the characters scanned was an exact match. Fixes
+ vertical-motion and pos-visible-in-window-p when exact match is
+ impossible due to invisible text, and the lines are truncated.
+
2011-07-22 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (compute_stop_pos_backwards): New function.
diff --git a/src/xdisp.c b/src/xdisp.c
index 52b1f484939..a5eb2aa923a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -7620,8 +7620,9 @@ move_it_in_display_line_to (struct it *it,
{
enum move_it_result result = MOVE_UNDEFINED;
struct glyph_row *saved_glyph_row;
- struct it wrap_it, atpos_it, atx_it;
+ struct it wrap_it, atpos_it, atx_it, ppos_it;
void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
+ void *ppos_data = NULL;
int may_wrap = 0;
enum it_method prev_method = it->method;
EMACS_INT prev_pos = IT_CHARPOS (*it);
@@ -7640,6 +7641,19 @@ move_it_in_display_line_to (struct it *it,
atpos_it.sp = -1;
atx_it.sp = -1;
+ /* Use ppos_it under bidi reordering to save a copy of IT for the
+ position > CHARPOS that is the closest to CHARPOS. We restore
+ that position in IT when we have scanned the entire display line
+ without finding a match for CHARPOS and all the character
+ positions are greater than CHARPOS. */
+ if (it->bidi_p)
+ {
+ SAVE_IT (ppos_it, *it, ppos_data);
+ SET_TEXT_POS (ppos_it.current.pos, ZV, ZV_BYTE);
+ if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
+ SAVE_IT (ppos_it, *it, ppos_data);
+ }
+
#define BUFFER_POS_REACHED_P() \
((op & MOVE_TO_POS) != 0 \
&& BUFFERP (it->object) \
@@ -7765,6 +7779,11 @@ move_it_in_display_line_to (struct it *it,
if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
SET_TEXT_POS (this_line_min_pos,
IT_CHARPOS (*it), IT_BYTEPOS (*it));
+ if (it->bidi_p
+ && (op & MOVE_TO_POS)
+ && IT_CHARPOS (*it) > to_charpos
+ && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it))
+ SAVE_IT (ppos_it, *it, ppos_data);
continue;
}
@@ -7975,7 +7994,11 @@ move_it_in_display_line_to (struct it *it,
if ((op & MOVE_TO_POS) != 0
&& !saw_smaller_pos
&& IT_CHARPOS (*it) > to_charpos)
- result = MOVE_POS_MATCH_OR_ZV;
+ {
+ result = MOVE_POS_MATCH_OR_ZV;
+ if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
+ RESTORE_IT (it, &ppos_it, ppos_data);
+ }
else
result = MOVE_NEWLINE_OR_CR;
break;
@@ -7991,6 +8014,11 @@ move_it_in_display_line_to (struct it *it,
SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
if (IT_CHARPOS (*it) < to_charpos)
saw_smaller_pos = 1;
+ if (it->bidi_p
+ && (op & MOVE_TO_POS)
+ && IT_CHARPOS (*it) >= to_charpos
+ && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it))
+ SAVE_IT (ppos_it, *it, ppos_data);
/* Stop if lines are truncated and IT's current x-position is
past the right edge of the window now. */
@@ -8000,10 +8028,21 @@ move_it_in_display_line_to (struct it *it,
if (!FRAME_WINDOW_P (it->f)
|| IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
{
- if (!get_next_display_element (it)
- || BUFFER_POS_REACHED_P ())
+ int at_eob_p = 0;
+
+ if ((at_eob_p = !get_next_display_element (it))
+ || BUFFER_POS_REACHED_P ()
+ /* 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. */
+ || ((op & MOVE_TO_POS) != 0
+ && !saw_smaller_pos
+ && IT_CHARPOS (*it) > to_charpos))
{
result = MOVE_POS_MATCH_OR_ZV;
+ if (it->bidi_p && !at_eob_p && IT_CHARPOS (ppos_it) < ZV)
+ RESTORE_IT (it, &ppos_it, ppos_data);
break;
}
if (ITERATOR_AT_END_OF_LINE_P (it))
@@ -8012,6 +8051,15 @@ move_it_in_display_line_to (struct it *it,
break;
}
}
+ else if ((op & MOVE_TO_POS) != 0
+ && !saw_smaller_pos
+ && IT_CHARPOS (*it) > to_charpos)
+ {
+ result = MOVE_POS_MATCH_OR_ZV;
+ if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
+ RESTORE_IT (it, &ppos_it, ppos_data);
+ break;
+ }
result = MOVE_LINE_TRUNCATED;
break;
}
@@ -8035,6 +8083,8 @@ move_it_in_display_line_to (struct it *it,
xfree (atx_data);
if (wrap_data)
xfree (wrap_data);
+ if (ppos_data)
+ xfree (ppos_data);
/* Restore the iterator settings altered at the beginning of this
function. */