From d1410150345acdf2d7693fe00b8169312fe40d14 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 6 Aug 2011 13:59:36 +0300 Subject: [PATCH] Fix bug #9254 with crash and cursor positioning under longlines-mode. src/xdisp.c (set_cursor_from_row): Fix cursor positioning when a display property strides EOL and includes a newline, as in longlines-mode. src/bidi.c (bidi_unshelve_cache): Don't reset the cache if JUST_FREE is non-zero, even if the data buffer is NULL. Fixes a crash in vertical-motion with longlines-mode. --- src/ChangeLog | 10 ++++++++++ src/bidi.c | 17 ++++++++++++----- src/xdisp.c | 28 ++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 60c835cb100..efe542e37d0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2011-08-06 Eli Zaretskii + + * xdisp.c (set_cursor_from_row): Fix cursor positioning when a + display property strides EOL and includes a newline, as in + longlines-mode. (Bug#9254) + + * bidi.c (bidi_unshelve_cache): Don't reset the cache if JUST_FREE + is non-zero, even if the data buffer is NULL. Fixes a crash in + vertical-motion with longlines-mode. (Bug#9254) + 2011-08-05 Eli Zaretskii * bidi.c : Now static. diff --git a/src/bidi.c b/src/bidi.c index 0db144bea6c..2879198ce31 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -666,7 +666,11 @@ bidi_shelve_cache (void) return databuf; } -/* Restore the cache state from a copy stashed away by bidi_shelve_cache. */ +/* Restore the cache state from a copy stashed away by + bidi_shelve_cache, and free the buffer used to stash that copy. + JUST_FREE non-zero means free the buffer, but don't restore the + cache; used when the corresponding iterator is discarded instead of + being restored. */ void bidi_unshelve_cache (void *databuf, int just_free) { @@ -674,10 +678,13 @@ bidi_unshelve_cache (void *databuf, int just_free) if (!p) { - /* A NULL pointer means an empty cache. */ - bidi_cache_start = 0; - bidi_cache_sp = 0; - bidi_cache_reset (); + if (!just_free) + { + /* A NULL pointer means an empty cache. */ + bidi_cache_start = 0; + bidi_cache_sp = 0; + bidi_cache_reset (); + } } else { diff --git a/src/xdisp.c b/src/xdisp.c index 69baea95b9c..9c281c6736b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -13285,6 +13285,9 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, /* Last buffer position covered by an overlay string with an integer `cursor' property. */ EMACS_INT bpos_covered = 0; + /* Non-zero means the display string on which to display the cursor + comes from a text property, not from an overlay. */ + int string_from_text_prop = 0; /* Skip over glyphs not having an object at the start and the end of the row. These are special glyphs like truncation marks on @@ -13603,9 +13606,14 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, { Lisp_Object str; EMACS_INT tem; + /* If the display property covers the newline, we + need to search for it one position farther. */ + EMACS_INT lim = pos_after + + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta); + string_from_text_prop = 0; str = glyph->object; - tem = string_buffer_position_lim (str, pos, pos_after, 0); + tem = string_buffer_position_lim (str, pos, lim, 0); if (tem == 0 /* from overlay */ || pos <= tem) { @@ -13629,7 +13637,10 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, EMACS_INT strpos = glyph->charpos; if (tem) - cursor = glyph; + { + cursor = glyph; + string_from_text_prop = 1; + } for ( ; (row->reversed_p ? glyph > stop : glyph < stop) && EQ (glyph->object, str); @@ -13730,8 +13741,17 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, /* previous candidate is a glyph from a string that has a non-nil `cursor' property */ || (STRINGP (g1->object) - && !NILP (Fget_char_property (make_number (g1->charpos), - Qcursor, g1->object))))) + && (!NILP (Fget_char_property (make_number (g1->charpos), + Qcursor, g1->object)) + /* pevious candidate is from the same display + string as this one, and the display string + came from a text property */ + || (EQ (g1->object, glyph->object) + && string_from_text_prop) + /* this candidate is from newline and its + position is not an exact match */ + || (INTEGERP (glyph->object) + && glyph->charpos != pt_old))))) return 0; /* If this candidate gives an exact match, use that. */ if (!(BUFFERP (glyph->object) && glyph->charpos == pt_old) -- 2.39.2