diff options
author | Eli Zaretskii <eliz@gnu.org> | 2014-02-20 19:40:56 +0200 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2014-02-20 19:40:56 +0200 |
commit | 679f7827555eebb588131aebfcb9fdb959199904 (patch) | |
tree | 194994cd6ca960faa0cb9767c31211fbd93aefd0 /src/xdisp.c | |
parent | dba8296c00f035fcf7e200e846a890445606f307 (diff) | |
download | emacs-679f7827555eebb588131aebfcb9fdb959199904.tar.gz |
Fix excessive calls to bidi_shelve_cache reported in bug #15555.
src/xdisp.c (move_it_in_display_line_to): Save the iterator state in ppos_it
only once per call. Reimplement the method used to return to the
best candidate position if all the positions found in display line
are beyond TO_CHARPOS. This cuts down the number of calls to
bidi_shelve_cache, which moves a lot of stuff when lines are long
and include bidirectional text.
Diffstat (limited to 'src/xdisp.c')
-rw-r--r-- | src/xdisp.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 94dd65c5d0b..840ff1288e5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -8313,7 +8313,7 @@ move_it_in_display_line_to (struct it *it, void *ppos_data = NULL; int may_wrap = 0; enum it_method prev_method = it->method; - ptrdiff_t prev_pos = IT_CHARPOS (*it); + ptrdiff_t closest_pos, prev_pos = IT_CHARPOS (*it); int saw_smaller_pos = prev_pos < to_charpos; /* Don't produce glyphs in produce_glyphs. */ @@ -8330,16 +8330,21 @@ move_it_in_display_line_to (struct it *it, 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. */ + initial position. We restore that position in IT when we have + scanned the entire display line without finding a match for + TO_CHARPOS and all the character positions are greater than + TO_CHARPOS. We then restart the scan from the initial position, + and stop at CLOSEST_POS, which is a position > TO_CHARPOS that is + the closest to TO_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); + { + SAVE_IT (ppos_it, *it, ppos_data); + closest_pos = IT_CHARPOS (*it); + } + else + closest_pos = ZV; } #define BUFFER_POS_REACHED_P() \ @@ -8483,8 +8488,8 @@ move_it_in_display_line_to (struct it *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); + && IT_CHARPOS (*it) < closest_pos) + closest_pos = IT_CHARPOS (*it); continue; } @@ -8706,9 +8711,11 @@ move_it_in_display_line_to (struct it *it, { if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos) { - if (IT_CHARPOS (ppos_it) < ZV) + if (closest_pos < ZV) { RESTORE_IT (it, &ppos_it, ppos_data); + move_it_in_display_line_to (it, closest_pos, -1, + MOVE_TO_POS); result = MOVE_POS_MATCH_OR_ZV; } else @@ -8738,8 +8745,8 @@ move_it_in_display_line_to (struct it *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); + && IT_CHARPOS (*it) < closest_pos) + closest_pos = IT_CHARPOS (*it); /* Stop if lines are truncated and IT's current x-position is past the right edge of the window now. */ @@ -8765,8 +8772,13 @@ move_it_in_display_line_to (struct it *it, && IT_CHARPOS (*it) > to_charpos)) { if (it->bidi_p - && !at_eob_p && IT_CHARPOS (ppos_it) < ZV) - RESTORE_IT (it, &ppos_it, ppos_data); + && !BUFFER_POS_REACHED_P () + && !at_eob_p && closest_pos < ZV) + { + RESTORE_IT (it, &ppos_it, ppos_data); + move_it_in_display_line_to (it, closest_pos, -1, + MOVE_TO_POS); + } result = MOVE_POS_MATCH_OR_ZV; break; } @@ -8780,8 +8792,11 @@ move_it_in_display_line_to (struct it *it, && !saw_smaller_pos && IT_CHARPOS (*it) > to_charpos) { - if (IT_CHARPOS (ppos_it) < ZV) - RESTORE_IT (it, &ppos_it, ppos_data); + if (closest_pos < ZV) + { + RESTORE_IT (it, &ppos_it, ppos_data); + move_it_in_display_line_to (it, closest_pos, -1, MOVE_TO_POS); + } result = MOVE_POS_MATCH_OR_ZV; break; } |