diff options
| author | Eli Zaretskii | 2014-04-12 14:21:47 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2014-04-12 14:21:47 +0300 |
| commit | 180c8ce0c6a702bc21403e1f5a0b2781bb5f787c (patch) | |
| tree | 80579c3d79dd86e3580f587055eb9a4587830a7f | |
| parent | 204db02a2b8826a72d49edd1ca8d32d6d33478c8 (diff) | |
| download | emacs-180c8ce0c6a702bc21403e1f5a0b2781bb5f787c.tar.gz emacs-180c8ce0c6a702bc21403e1f5a0b2781bb5f787c.zip | |
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 @@ | |||
| 1 | 2014-04-12 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * xdisp.c (move_it_by_lines): If a large portion of buffer text is | ||
| 4 | covered by a display string that ends in a newline, and that cases | ||
| 5 | going back by DVPOS lines to hit the search limit, lift the limit | ||
| 6 | and go back until DVPOS is reached. (Bug#17244) | ||
| 7 | |||
| 8 | * indent.c (Fvertical_motion): Handle correctly the case when the | ||
| 9 | display string is preceded by an empty line. | ||
| 10 | |||
| 1 | 2014-04-11 Eli Zaretskii <eliz@gnu.org> | 11 | 2014-04-11 Eli Zaretskii <eliz@gnu.org> |
| 2 | 12 | ||
| 3 | * w32.c (sys_umask) <WRITE_USER>: Remove redundant constant, and | 13 | * 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. */) | |||
| 2051 | string, move_it_to will overshoot it, while vertical-motion | 2051 | string, move_it_to will overshoot it, while vertical-motion |
| 2052 | wants to put the cursor _before_ the display string. So in | 2052 | wants to put the cursor _before_ the display string. So in |
| 2053 | that case, we move to buffer position before the display | 2053 | that case, we move to buffer position before the display |
| 2054 | string, and avoid overshooting. */ | 2054 | string, and avoid overshooting. But if the position before |
| 2055 | move_it_to (&it, disp_string_at_start_p ? PT - 1 : PT, | 2055 | the display string is a newline, we don't do this, because |
| 2056 | otherwise we will end up in a screen line that is one too | ||
| 2057 | far back. */ | ||
| 2058 | move_it_to (&it, | ||
| 2059 | (!disp_string_at_start_p | ||
| 2060 | || FETCH_BYTE (IT_BYTEPOS (it)) == '\n') | ||
| 2061 | ? PT | ||
| 2062 | : PT - 1, | ||
| 2056 | -1, -1, -1, MOVE_TO_POS); | 2063 | -1, -1, -1, MOVE_TO_POS); |
| 2057 | 2064 | ||
| 2058 | /* IT may move too far if truncate-lines is on and PT lies | 2065 | /* 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) | |||
| 9511 | ptrdiff_t start_charpos, i; | 9511 | ptrdiff_t start_charpos, i; |
| 9512 | int nchars_per_row | 9512 | int nchars_per_row |
| 9513 | = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); | 9513 | = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); |
| 9514 | bool hit_pos_limit = false; | ||
| 9514 | ptrdiff_t pos_limit; | 9515 | ptrdiff_t pos_limit; |
| 9515 | 9516 | ||
| 9516 | /* Start at the beginning of the screen line containing IT's | 9517 | /* 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) | |||
| 9527 | pos_limit = BEGV; | 9528 | pos_limit = BEGV; |
| 9528 | else | 9529 | else |
| 9529 | pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV); | 9530 | pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV); |
| 9531 | |||
| 9530 | for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i) | 9532 | for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i) |
| 9531 | back_to_previous_visible_line_start (it); | 9533 | back_to_previous_visible_line_start (it); |
| 9534 | if (i > 0 && IT_CHARPOS (*it) <= pos_limit) | ||
| 9535 | hit_pos_limit = true; | ||
| 9532 | reseat (it, it->current.pos, 1); | 9536 | reseat (it, it->current.pos, 1); |
| 9533 | 9537 | ||
| 9534 | /* Move further back if we end up in a string or an image. */ | 9538 | /* 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) | |||
| 9572 | else | 9576 | else |
| 9573 | bidi_unshelve_cache (it2data, 1); | 9577 | bidi_unshelve_cache (it2data, 1); |
| 9574 | } | 9578 | } |
| 9579 | else if (hit_pos_limit && pos_limit > BEGV | ||
| 9580 | && dvpos < 0 && it2.vpos < -dvpos) | ||
| 9581 | { | ||
| 9582 | /* If we hit the limit, but still didn't make it far enough | ||
| 9583 | back, that means there's a display string with a newline | ||
| 9584 | covering a large chunk of text, and that caused | ||
| 9585 | back_to_previous_visible_line_start try to go too far. | ||
| 9586 | Punish those who commit such atrocities by going back | ||
| 9587 | until we've reached DVPOS, after lifting the limit, which | ||
| 9588 | could make it slow for very long lines. "If it hurts, | ||
| 9589 | don't do that!" */ | ||
| 9590 | dvpos += it2.vpos; | ||
| 9591 | RESTORE_IT (it, it, it2data); | ||
| 9592 | for (i = -dvpos; i > 0; --i) | ||
| 9593 | { | ||
| 9594 | back_to_previous_visible_line_start (it); | ||
| 9595 | it->vpos--; | ||
| 9596 | } | ||
| 9597 | } | ||
| 9575 | else | 9598 | else |
| 9576 | RESTORE_IT (it, it, it2data); | 9599 | RESTORE_IT (it, it, it2data); |
| 9577 | } | 9600 | } |