diff options
Diffstat (limited to 'src/xdisp.c')
-rw-r--r-- | src/xdisp.c | 111 |
1 files changed, 52 insertions, 59 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 84c75bd91d9..fa4b3c4f9ab 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -899,7 +899,7 @@ static void init_to_row_start (struct it *, struct window *, static int init_to_row_end (struct it *, struct window *, struct glyph_row *); static void back_to_previous_line_start (struct it *); -static int forward_to_next_line_start (struct it *, int *); +static int forward_to_next_line_start (struct it *, int *, struct bidi_it *); static struct text_pos string_pos_nchars_ahead (struct text_pos, Lisp_Object, EMACS_INT); static struct text_pos string_pos (EMACS_INT, Lisp_Object); @@ -3134,13 +3134,10 @@ next_overlay_change (EMACS_INT pos) return endpos; } -/* Record one cached display string position found recently by - compute_display_string_pos. */ -static EMACS_INT cached_disp_pos; -static EMACS_INT cached_prev_pos = -1; -static struct buffer *cached_disp_buffer; -static int cached_disp_modiff; -static int cached_disp_overlay_modiff; +/* How many characters forward to search for a display property or + display string. Enough for a screenful of 100 lines x 50 + characters in a line. */ +#define MAX_DISP_SCAN 5000 /* Return the character position of a display string at or after position specified by POSITION. If no display string exists at or @@ -3152,57 +3149,33 @@ static int cached_disp_overlay_modiff; on a GUI frame. */ EMACS_INT compute_display_string_pos (struct text_pos *position, - struct bidi_string_data *string, int frame_window_p) + struct bidi_string_data *string, + int frame_window_p, int *disp_prop_p) { /* OBJECT = nil means current buffer. */ Lisp_Object object = (string && STRINGP (string->lstring)) ? string->lstring : Qnil; - Lisp_Object pos, spec; + Lisp_Object pos, spec, limpos; int string_p = (string && (STRINGP (string->lstring) || string->s)); EMACS_INT eob = string_p ? string->schars : ZV; EMACS_INT begb = string_p ? 0 : BEGV; EMACS_INT bufpos, charpos = CHARPOS (*position); + EMACS_INT lim = + (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob; struct text_pos tpos; struct buffer *b; + *disp_prop_p = 1; + if (charpos >= eob /* We don't support display properties whose values are strings that have display string properties. */ || string->from_disp_str /* C strings cannot have display properties. */ || (string->s && !STRINGP (object))) - return eob; - - /* Check the cached values. */ - if (!STRINGP (object)) { - if (NILP (object)) - b = current_buffer; - else - b = XBUFFER (object); - if (b == cached_disp_buffer - && BUF_MODIFF (b) == cached_disp_modiff - && BUF_OVERLAY_MODIFF (b) == cached_disp_overlay_modiff - && !b->clip_changed) - { - if (cached_prev_pos >= 0 - && cached_prev_pos < charpos && charpos <= cached_disp_pos) - return cached_disp_pos; - /* Handle overstepping either end of the known interval. */ - if (charpos > cached_disp_pos) - cached_prev_pos = cached_disp_pos; - else /* charpos <= cached_prev_pos */ - cached_prev_pos = max (charpos - 1, 0); - } - - /* Record new values in the cache. */ - if (b != cached_disp_buffer) - { - cached_disp_buffer = b; - cached_prev_pos = max (charpos - 1, 0); - } - cached_disp_modiff = BUF_MODIFF (b); - cached_disp_overlay_modiff = BUF_OVERLAY_MODIFF (b); + *disp_prop_p = 0; + return eob; } /* If the character at CHARPOS is where the display string begins, @@ -3221,22 +3194,24 @@ compute_display_string_pos (struct text_pos *position, && handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos, frame_window_p)) { - if (!STRINGP (object)) - cached_disp_pos = charpos; return charpos; } /* Look forward for the first character with a `display' property that will replace the underlying text when displayed. */ + limpos = make_number (lim); do { - pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil); + pos = Fnext_single_char_property_change (pos, Qdisplay, object, limpos); CHARPOS (tpos) = XFASTINT (pos); + if (CHARPOS (tpos) >= lim) + { + *disp_prop_p = 0; + break; + } if (STRINGP (object)) BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos)); else BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos)); - if (CHARPOS (tpos) >= eob) - break; spec = Fget_char_property (pos, Qdisplay, object); if (!STRINGP (object)) bufpos = CHARPOS (tpos); @@ -3244,8 +3219,6 @@ compute_display_string_pos (struct text_pos *position, || !handle_display_spec (NULL, spec, object, Qnil, &tpos, bufpos, frame_window_p)); - if (!STRINGP (object)) - cached_disp_pos = CHARPOS (tpos); return CHARPOS (tpos); } @@ -5494,6 +5467,9 @@ back_to_previous_line_start (struct it *it) continuously over the text). Otherwise, don't change the value of *SKIPPED_P. + If BIDI_IT_PREV is non-NULL, store into it the state of the bidi + iterator on the newline, if it was found. + Newlines may come from buffer text, overlay strings, or strings displayed via the `display' property. That's the reason we can't simply use find_next_newline_no_quit. @@ -5506,7 +5482,8 @@ back_to_previous_line_start (struct it *it) leads to wrong cursor motion. */ static int -forward_to_next_line_start (struct it *it, int *skipped_p) +forward_to_next_line_start (struct it *it, int *skipped_p, + struct bidi_it *bidi_it_prev) { EMACS_INT old_selective; int newline_found_p, n; @@ -5518,6 +5495,8 @@ forward_to_next_line_start (struct it *it, int *skipped_p) && it->c == '\n' && CHARPOS (it->position) == IT_CHARPOS (*it)) { + if (it->bidi_p && bidi_it_prev) + *bidi_it_prev = it->bidi_it; set_iterator_to_next (it, 0); it->c = 0; return 1; @@ -5539,6 +5518,8 @@ forward_to_next_line_start (struct it *it, int *skipped_p) if (!get_next_display_element (it)) return 0; newline_found_p = it->what == IT_CHARACTER && it->c == '\n'; + if (newline_found_p && it->bidi_p && bidi_it_prev) + *bidi_it_prev = it->bidi_it; set_iterator_to_next (it, 0); } @@ -5573,6 +5554,8 @@ forward_to_next_line_start (struct it *it, int *skipped_p) && !newline_found_p) { newline_found_p = ITERATOR_AT_END_OF_LINE_P (it); + if (newline_found_p && it->bidi_p && bidi_it_prev) + *bidi_it_prev = it->bidi_it; set_iterator_to_next (it, 0); } } @@ -5696,8 +5679,9 @@ static void reseat_at_next_visible_line_start (struct it *it, int on_newline_p) { int newline_found_p, skipped_p = 0; + struct bidi_it bidi_it_prev; - newline_found_p = forward_to_next_line_start (it, &skipped_p); + newline_found_p = forward_to_next_line_start (it, &skipped_p, &bidi_it_prev); /* Skip over lines that are invisible because they are indented more than the value of IT->selective. */ @@ -5708,7 +5692,8 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p) { xassert (IT_BYTEPOS (*it) == BEGV || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n'); - newline_found_p = forward_to_next_line_start (it, &skipped_p); + newline_found_p = + forward_to_next_line_start (it, &skipped_p, &bidi_it_prev); } /* Position on the newline if that's what's requested. */ @@ -5724,11 +5709,14 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p) --IT_STRING_BYTEPOS (*it); } else - /* Setting this flag will cause - bidi_move_to_visually_next not to advance, but - instead deliver the current character (newline), - which is what the ON_NEWLINE_P flag wants. */ - it->bidi_it.first_elt = 1; + { + /* We need to restore the bidi iterator to the state + it had on the newline, and resync the IT's + position with that. */ + it->bidi_it = bidi_it_prev; + IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; + IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; + } } } else if (IT_CHARPOS (*it) > BEGV) @@ -5738,9 +5726,14 @@ reseat_at_next_visible_line_start (struct it *it, int on_newline_p) --IT_CHARPOS (*it); --IT_BYTEPOS (*it); } - /* With bidi iteration, the call to `reseat' will cause - bidi_move_to_visually_next deliver the current character, - the newline, instead of advancing. */ + else + { + /* We need to restore the bidi iterator to the state it + had on the newline and resync IT with that. */ + it->bidi_it = bidi_it_prev; + IT_CHARPOS (*it) = it->bidi_it.charpos; + IT_BYTEPOS (*it) = it->bidi_it.bytepos; + } reseat (it, it->current.pos, 0); } } |