diff options
author | Eli Zaretskii <eliz@gnu.org> | 2014-04-12 14:21:47 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2014-04-12 14:21:47 +0300 |
commit | 180c8ce0c6a702bc21403e1f5a0b2781bb5f787c (patch) | |
tree | 80579c3d79dd86e3580f587055eb9a4587830a7f | |
parent | 204db02a2b8826a72d49edd1ca8d32d6d33478c8 (diff) | |
download | emacs-180c8ce0c6a702bc21403e1f5a0b2781bb5f787c.tar.gz |
Fix bug #17244 with line-move-visual when display string covers a lot of text.
src/xdisp.c (move_it_by_lines): If a large portion of buffer text is
covered by a display string that ends in a newline, and that cases
going back by DVPOS lines to hit the search limit, lift the limit
and go back until DVPOS is reached.
src/indent.c (Fvertical_motion): Handle correctly the case when the
display string is preceded by an empty line.
-rw-r--r-- | src/ChangeLog | 10 | ||||
-rw-r--r-- | src/indent.c | 11 | ||||
-rw-r--r-- | src/xdisp.c | 23 |
3 files changed, 42 insertions, 2 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 22f25bef6f3..cb17738d139 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2014-04-12 Eli Zaretskii <eliz@gnu.org> + + * xdisp.c (move_it_by_lines): If a large portion of buffer text is + covered by a display string that ends in a newline, and that cases + going back by DVPOS lines to hit the search limit, lift the limit + and go back until DVPOS is reached. (Bug#17244) + + * indent.c (Fvertical_motion): Handle correctly the case when the + display string is preceded by an empty line. + 2014-04-11 Eli Zaretskii <eliz@gnu.org> * w32.c (sys_umask) <WRITE_USER>: Remove redundant constant, and diff --git a/src/indent.c b/src/indent.c index 683d44841b9..dc862518924 100644 --- a/src/indent.c +++ b/src/indent.c @@ -2051,8 +2051,15 @@ whether or not it is currently displayed in some window. */) string, move_it_to will overshoot it, while vertical-motion wants to put the cursor _before_ the display string. So in that case, we move to buffer position before the display - string, and avoid overshooting. */ - move_it_to (&it, disp_string_at_start_p ? PT - 1 : PT, + string, and avoid overshooting. But if the position before + the display string is a newline, we don't do this, because + otherwise we will end up in a screen line that is one too + far back. */ + move_it_to (&it, + (!disp_string_at_start_p + || FETCH_BYTE (IT_BYTEPOS (it)) == '\n') + ? PT + : PT - 1, -1, -1, -1, MOVE_TO_POS); /* IT may move too far if truncate-lines is on and PT lies diff --git a/src/xdisp.c b/src/xdisp.c index 53bd46328f2..eb3a6df1fc5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -9511,6 +9511,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) ptrdiff_t start_charpos, i; int nchars_per_row = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); + bool hit_pos_limit = false; ptrdiff_t pos_limit; /* Start at the beginning of the screen line containing IT's @@ -9527,8 +9528,11 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) pos_limit = BEGV; else pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV); + for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i) back_to_previous_visible_line_start (it); + if (i > 0 && IT_CHARPOS (*it) <= pos_limit) + hit_pos_limit = true; reseat (it, it->current.pos, 1); /* Move further back if we end up in a string or an image. */ @@ -9572,6 +9576,25 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) else bidi_unshelve_cache (it2data, 1); } + else if (hit_pos_limit && pos_limit > BEGV + && dvpos < 0 && it2.vpos < -dvpos) + { + /* If we hit the limit, but still didn't make it far enough + back, that means there's a display string with a newline + covering a large chunk of text, and that caused + back_to_previous_visible_line_start try to go too far. + Punish those who commit such atrocities by going back + until we've reached DVPOS, after lifting the limit, which + could make it slow for very long lines. "If it hurts, + don't do that!" */ + dvpos += it2.vpos; + RESTORE_IT (it, it, it2data); + for (i = -dvpos; i > 0; --i) + { + back_to_previous_visible_line_start (it); + it->vpos--; + } + } else RESTORE_IT (it, it, it2data); } |