From d1410150345acdf2d7693fe00b8169312fe40d14 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 6 Aug 2011 13:59:36 +0300 Subject: [PATCH 1/2] 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) From 75b771e489a32ab716b031664baee313a78caf6b Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 6 Aug 2011 14:49:35 +0300 Subject: [PATCH 2/2] Really fix bug #9224 with vertical-motion under word-wrap. src/xdisp.c (move_it_in_display_line_to): Fix vertical-motion in a buffer with word-wrap under bidirectional display. --- src/ChangeLog | 2 ++ src/xdisp.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index efe542e37d0..039c225c1f6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -3,6 +3,8 @@ * 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) + (move_it_in_display_line_to): Fix vertical-motion in a buffer with + word-wrap under bidirectional display. (Bug#9224) * 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 diff --git a/src/xdisp.c b/src/xdisp.c index 9c281c6736b..6e9474e3c10 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -8009,13 +8009,19 @@ move_it_in_display_line_to (struct it *it, positions smaller than TO_CHARPOS, return MOVE_POS_MATCH_OR_ZV, like the unidirectional display did. */ - if (it->bidi_p && (op & MOVE_TO_POS) != 0 - && !saw_smaller_pos - && IT_CHARPOS (*it) > to_charpos) + if (it->bidi_p && (op & MOVE_TO_POS) != 0) { - if (IT_CHARPOS (ppos_it) < ZV) - RESTORE_IT (it, &ppos_it, ppos_data); - goto buffer_pos_reached; + if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos) + { + if (IT_CHARPOS (ppos_it) < ZV) + RESTORE_IT (it, &ppos_it, ppos_data); + goto buffer_pos_reached; + } + else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0 + && IT_CHARPOS (*it) > to_charpos) + goto buffer_pos_reached; + else + result = MOVE_NEWLINE_OR_CR; } else result = MOVE_NEWLINE_OR_CR;