From c1734fbd6fa365e362c600b7b94c40b13401c255 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 23 Jul 2011 13:42:24 +0300 Subject: [PATCH] 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. --- src/ChangeLog | 8 +++++++ src/xdisp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++---- 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 + + * 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 * 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. */ -- 2.39.2