diff options
| author | Eli Zaretskii | 2011-07-19 21:04:56 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-07-19 21:04:56 +0300 |
| commit | e8c17b886b93f34bcc89e2dff0510cbf63c1f179 (patch) | |
| tree | c93527f2e73a089796f2caae0755cec80795a593 /src | |
| parent | 551918c187a781636fb437e71fcf7477afda8230 (diff) | |
| download | emacs-e8c17b886b93f34bcc89e2dff0510cbf63c1f179.tar.gz emacs-e8c17b886b93f34bcc89e2dff0510cbf63c1f179.zip | |
Speed up cursor motion in large fontified buffers.
src/xdisp.c (reseat): Don't look for prev_stop, as that could mean a
very long run.
(next_element_from_buffer): When iterator oversteps prev_pos
backwards, don't search for a new prev_stop more than 1000
characters back.
(handle_stop_backwards): Don't assume that CHARPOS is necessarily
a stop_pos.
(compute_display_string_pos): Check also BUF_OVERLAY_MODIFF for a
match, when testing the cached display string position for
applicability.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 15 | ||||
| -rw-r--r-- | src/xdisp.c | 73 |
2 files changed, 61 insertions, 27 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 0114495838f..15f37f486e2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | 2011-07-19 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | Fix a significant slow-down of vertical-motion when leaning on C-n | ||
| 4 | or C-p in a fontified buffer. | ||
| 5 | * xdisp.c (reseat): Don't look for prev_stop, as that could mean a | ||
| 6 | very long run. | ||
| 7 | (next_element_from_buffer): When iterator oversteps prev_pos | ||
| 8 | backwards, don't search for a new prev_stop more than 1000 | ||
| 9 | characters back. | ||
| 10 | (handle_stop_backwards): Don't assume that CHARPOS is necessarily | ||
| 11 | a stop_pos. | ||
| 12 | (compute_display_string_pos): Check also BUF_OVERLAY_MODIFF for a | ||
| 13 | match, when testing the cached display string position for | ||
| 14 | applicability. | ||
| 15 | |||
| 1 | 2011-07-16 Eli Zaretskii <eliz@gnu.org> | 16 | 2011-07-16 Eli Zaretskii <eliz@gnu.org> |
| 2 | 17 | ||
| 3 | * xdisp.c <cached_disp_pos, cached_disp_buffer, cached_disp_modiff>: | 18 | * xdisp.c <cached_disp_pos, cached_disp_buffer, cached_disp_modiff>: |
diff --git a/src/xdisp.c b/src/xdisp.c index 1ddd78caa5d..9968fabf2a4 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -3140,8 +3140,12 @@ next_overlay_change (EMACS_INT pos) | |||
| 3140 | /* Record one cached display string position found recently by | 3140 | /* Record one cached display string position found recently by |
| 3141 | compute_display_string_pos. */ | 3141 | compute_display_string_pos. */ |
| 3142 | static EMACS_INT cached_disp_pos; | 3142 | static EMACS_INT cached_disp_pos; |
| 3143 | static EMACS_INT cached_prev_pos; | ||
| 3143 | static struct buffer *cached_disp_buffer; | 3144 | static struct buffer *cached_disp_buffer; |
| 3144 | static int cached_disp_modiff; | 3145 | static int cached_disp_modiff; |
| 3146 | static int cached_disp_overlay_modiff; | ||
| 3147 | |||
| 3148 | static int ignore_display_strings; | ||
| 3145 | 3149 | ||
| 3146 | /* Return the character position of a display string at or after | 3150 | /* Return the character position of a display string at or after |
| 3147 | position specified by POSITION. If no display string exists at or | 3151 | position specified by POSITION. If no display string exists at or |
| @@ -3171,7 +3175,8 @@ compute_display_string_pos (struct text_pos *position, | |||
| 3171 | that have display string properties. */ | 3175 | that have display string properties. */ |
| 3172 | || string->from_disp_str | 3176 | || string->from_disp_str |
| 3173 | /* C strings cannot have display properties. */ | 3177 | /* C strings cannot have display properties. */ |
| 3174 | || (string->s && !STRINGP (object))) | 3178 | || (string->s && !STRINGP (object)) |
| 3179 | || ignore_display_strings) | ||
| 3175 | return eob; | 3180 | return eob; |
| 3176 | 3181 | ||
| 3177 | /* Check the cached values. */ | 3182 | /* Check the cached values. */ |
| @@ -3183,12 +3188,22 @@ compute_display_string_pos (struct text_pos *position, | |||
| 3183 | b = XBUFFER (object); | 3188 | b = XBUFFER (object); |
| 3184 | if (b == cached_disp_buffer | 3189 | if (b == cached_disp_buffer |
| 3185 | && BUF_MODIFF (b) == cached_disp_modiff | 3190 | && BUF_MODIFF (b) == cached_disp_modiff |
| 3186 | && charpos <= cached_disp_pos) | 3191 | && BUF_OVERLAY_MODIFF (b) == cached_disp_overlay_modiff) |
| 3187 | return cached_disp_pos; | 3192 | { |
| 3193 | if (cached_prev_pos | ||
| 3194 | && cached_prev_pos < charpos && charpos <= cached_disp_pos) | ||
| 3195 | return cached_disp_pos; | ||
| 3196 | /* Handle overstepping eather end of the known interval. */ | ||
| 3197 | if (charpos > cached_disp_pos) | ||
| 3198 | cached_prev_pos = cached_disp_pos; | ||
| 3199 | else /* charpos <= cached_prev_pos */ | ||
| 3200 | cached_prev_pos = max (charpos - 1, BEGV); | ||
| 3201 | } | ||
| 3188 | 3202 | ||
| 3189 | /* Record new values in the cache. */ | 3203 | /* Record new values in the cache. */ |
| 3190 | cached_disp_buffer = b; | 3204 | cached_disp_buffer = b; |
| 3191 | cached_disp_modiff = BUF_MODIFF (b); | 3205 | cached_disp_modiff = BUF_MODIFF (b); |
| 3206 | cached_disp_overlay_modiff = BUF_OVERLAY_MODIFF (b); | ||
| 3192 | } | 3207 | } |
| 3193 | 3208 | ||
| 3194 | /* If the character at CHARPOS is where the display string begins, | 3209 | /* If the character at CHARPOS is where the display string begins, |
| @@ -5758,17 +5773,11 @@ reseat (struct it *it, struct text_pos pos, int force_p) | |||
| 5758 | { | 5773 | { |
| 5759 | /* For bidi iteration, we need to prime prev_stop and | 5774 | /* For bidi iteration, we need to prime prev_stop and |
| 5760 | base_level_stop with our best estimations. */ | 5775 | base_level_stop with our best estimations. */ |
| 5761 | if (CHARPOS (pos) < it->prev_stop) | 5776 | if (CHARPOS (pos) != it->prev_stop) |
| 5762 | { | 5777 | it->prev_stop = CHARPOS (pos); |
| 5763 | handle_stop_backwards (it, BEGV); | 5778 | if (CHARPOS (pos) < it->base_level_stop) |
| 5764 | if (CHARPOS (pos) < it->base_level_stop) | 5779 | it->base_level_stop = 0; |
| 5765 | it->base_level_stop = 0; | 5780 | handle_stop (it); |
| 5766 | } | ||
| 5767 | else if (CHARPOS (pos) > it->stop_charpos | ||
| 5768 | && it->stop_charpos >= BEGV) | ||
| 5769 | handle_stop_backwards (it, it->stop_charpos); | ||
| 5770 | else /* force_p */ | ||
| 5771 | handle_stop (it); | ||
| 5772 | } | 5781 | } |
| 5773 | else | 5782 | else |
| 5774 | { | 5783 | { |
| @@ -7022,10 +7031,10 @@ next_element_from_string (struct it *it) | |||
| 7022 | embedding level, so test for that explicitly. */ | 7031 | embedding level, so test for that explicitly. */ |
| 7023 | && !BIDI_AT_BASE_LEVEL (it->bidi_it)) | 7032 | && !BIDI_AT_BASE_LEVEL (it->bidi_it)) |
| 7024 | { | 7033 | { |
| 7025 | /* If we lost track of base_level_stop, we have no better place | 7034 | /* If we lost track of base_level_stop, we have no better |
| 7026 | for handle_stop_backwards to start from than BEGV. This | 7035 | place for handle_stop_backwards to start from than string |
| 7027 | happens, e.g., when we were reseated to the previous | 7036 | beginning. This happens, e.g., when we were reseated to |
| 7028 | screenful of text by vertical-motion. */ | 7037 | the previous screenful of text by vertical-motion. */ |
| 7029 | if (it->base_level_stop <= 0 | 7038 | if (it->base_level_stop <= 0 |
| 7030 | || IT_STRING_CHARPOS (*it) < it->base_level_stop) | 7039 | || IT_STRING_CHARPOS (*it) < it->base_level_stop) |
| 7031 | it->base_level_stop = 0; | 7040 | it->base_level_stop = 0; |
| @@ -7230,6 +7239,7 @@ handle_stop_backwards (struct it *it, EMACS_INT charpos) | |||
| 7230 | struct text_pos save_position = it->position; | 7239 | struct text_pos save_position = it->position; |
| 7231 | struct text_pos pos1; | 7240 | struct text_pos pos1; |
| 7232 | EMACS_INT next_stop; | 7241 | EMACS_INT next_stop; |
| 7242 | int found_stop = 0; | ||
| 7233 | 7243 | ||
| 7234 | /* Scan in strict logical order. */ | 7244 | /* Scan in strict logical order. */ |
| 7235 | it->bidi_p = 0; | 7245 | it->bidi_p = 0; |
| @@ -7247,17 +7257,24 @@ handle_stop_backwards (struct it *it, EMACS_INT charpos) | |||
| 7247 | /* We must advance forward, right? */ | 7257 | /* We must advance forward, right? */ |
| 7248 | if (it->stop_charpos <= it->prev_stop) | 7258 | if (it->stop_charpos <= it->prev_stop) |
| 7249 | abort (); | 7259 | abort (); |
| 7260 | /* Did we find at least one stop_pos between CHARPOS and IT's | ||
| 7261 | current position? */ | ||
| 7262 | if (it->stop_charpos <= where_we_are) | ||
| 7263 | found_stop = 1; | ||
| 7250 | charpos = it->stop_charpos; | 7264 | charpos = it->stop_charpos; |
| 7251 | } | 7265 | } |
| 7252 | while (charpos <= where_we_are); | 7266 | while (charpos <= where_we_are); |
| 7253 | 7267 | ||
| 7254 | next_stop = it->stop_charpos; | ||
| 7255 | it->stop_charpos = it->prev_stop; | ||
| 7256 | it->bidi_p = 1; | 7268 | it->bidi_p = 1; |
| 7257 | it->current = save_current; | 7269 | it->current = save_current; |
| 7258 | it->position = save_position; | 7270 | it->position = save_position; |
| 7259 | handle_stop (it); | 7271 | if (found_stop) |
| 7260 | it->stop_charpos = next_stop; | 7272 | { |
| 7273 | next_stop = it->stop_charpos; | ||
| 7274 | it->stop_charpos = it->prev_stop; | ||
| 7275 | handle_stop (it); | ||
| 7276 | it->stop_charpos = next_stop; | ||
| 7277 | } | ||
| 7261 | } | 7278 | } |
| 7262 | 7279 | ||
| 7263 | /* Load IT with the next display element from current_buffer. Value | 7280 | /* Load IT with the next display element from current_buffer. Value |
| @@ -7352,14 +7369,16 @@ next_element_from_buffer (struct it *it) | |||
| 7352 | embedding level, so test for that explicitly. */ | 7369 | embedding level, so test for that explicitly. */ |
| 7353 | && !BIDI_AT_BASE_LEVEL (it->bidi_it)) | 7370 | && !BIDI_AT_BASE_LEVEL (it->bidi_it)) |
| 7354 | { | 7371 | { |
| 7355 | /* If we lost track of base_level_stop, we have no better place | 7372 | EMACS_INT start_from; |
| 7356 | for handle_stop_backwards to start from than BEGV. This | 7373 | /* If we lost track of base_level_stop, we try looking backwards |
| 7357 | happens, e.g., when we were reseated to the previous | 7374 | for at most 1000 characters. This happens, e.g., when we |
| 7358 | screenful of text by vertical-motion. */ | 7375 | were reseated to the previous screenful of text by |
| 7376 | vertical-motion. */ | ||
| 7359 | if (it->base_level_stop <= 0 | 7377 | if (it->base_level_stop <= 0 |
| 7360 | || IT_CHARPOS (*it) < it->base_level_stop) | 7378 | || IT_CHARPOS (*it) < it->base_level_stop) |
| 7361 | it->base_level_stop = BEGV; | 7379 | it->base_level_stop = BEGV; |
| 7362 | handle_stop_backwards (it, it->base_level_stop); | 7380 | start_from = max (it->base_level_stop, IT_CHARPOS (*it) - 1000); |
| 7381 | handle_stop_backwards (it, start_from); | ||
| 7363 | return GET_NEXT_DISPLAY_ELEMENT (it); | 7382 | return GET_NEXT_DISPLAY_ELEMENT (it); |
| 7364 | } | 7383 | } |
| 7365 | else | 7384 | else |