diff options
| author | Eli Zaretskii | 2016-05-21 12:35:08 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2016-09-23 16:59:17 +0300 |
| commit | df4f8125342bafe1d70130f84acfa67cc0c4a7f4 (patch) | |
| tree | 6f2fa9895170462543b5c9d019ddb9e99b1f4b2d /src | |
| parent | 9135bd7af7bdf9f805b185a77fe4e6d33dec4009 (diff) | |
| download | emacs-df4f8125342bafe1d70130f84acfa67cc0c4a7f4.tar.gz emacs-df4f8125342bafe1d70130f84acfa67cc0c4a7f4.zip | |
Fix 'vertical-motion' and 'posn-at-point' under 'visual-line-mode'
* src/xdisp.c (move_it_in_display_line_to): Don't assume we can
wrap on a whitespace character if it's followed by another
whitespace character. When returning under WORD_WRAP for a screen
line that is continued, restore to wrap point when atpos/atx
position would be displayed on the next screen line due to
line-wrap. (Bug#23570)
This is backported from master
(cherry picked from commit 99848b37d2c3e14c0af45fc6da437a806aa58a80)
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 24daa0c3b71..adbb6e5088b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -8805,6 +8805,8 @@ move_it_in_display_line_to (struct it *it, | |||
| 8805 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) | 8805 | ? WINDOW_LEFT_FRINGE_WIDTH (it->w) |
| 8806 | : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) | 8806 | : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) |
| 8807 | { | 8807 | { |
| 8808 | bool moved_forward = false; | ||
| 8809 | |||
| 8808 | if (/* IT->hpos == 0 means the very first glyph | 8810 | if (/* IT->hpos == 0 means the very first glyph |
| 8809 | doesn't fit on the line, e.g. a wide image. */ | 8811 | doesn't fit on the line, e.g. a wide image. */ |
| 8810 | it->hpos == 0 | 8812 | it->hpos == 0 |
| @@ -8823,16 +8825,37 @@ move_it_in_display_line_to (struct it *it, | |||
| 8823 | now that we know it fits in this row. */ | 8825 | now that we know it fits in this row. */ |
| 8824 | if (BUFFER_POS_REACHED_P ()) | 8826 | if (BUFFER_POS_REACHED_P ()) |
| 8825 | { | 8827 | { |
| 8828 | bool can_wrap = true; | ||
| 8829 | |||
| 8830 | /* If we are at a whitespace character | ||
| 8831 | that barely fits on this screen line, | ||
| 8832 | but the next character is also | ||
| 8833 | whitespace, we cannot wrap here. */ | ||
| 8834 | if (it->line_wrap == WORD_WRAP | ||
| 8835 | && wrap_it.sp >= 0 | ||
| 8836 | && may_wrap | ||
| 8837 | && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) | ||
| 8838 | { | ||
| 8839 | struct it tem_it; | ||
| 8840 | void *tem_data = NULL; | ||
| 8841 | |||
| 8842 | SAVE_IT (tem_it, *it, tem_data); | ||
| 8843 | set_iterator_to_next (it, true); | ||
| 8844 | if (get_next_display_element (it) | ||
| 8845 | && IT_DISPLAYING_WHITESPACE (it)) | ||
| 8846 | can_wrap = false; | ||
| 8847 | RESTORE_IT (it, &tem_it, tem_data); | ||
| 8848 | } | ||
| 8826 | if (it->line_wrap != WORD_WRAP | 8849 | if (it->line_wrap != WORD_WRAP |
| 8827 | || wrap_it.sp < 0 | 8850 | || wrap_it.sp < 0 |
| 8828 | /* If we've just found whitespace to | 8851 | /* If we've just found whitespace |
| 8829 | wrap, effectively ignore the | 8852 | where we can wrap, effectively |
| 8830 | previous wrap point -- it is no | 8853 | ignore the previous wrap point -- |
| 8831 | longer relevant, but we won't | 8854 | it is no longer relevant, but we |
| 8832 | have an opportunity to update it, | 8855 | won't have an opportunity to |
| 8833 | since we've reached the edge of | 8856 | update it, since we've reached |
| 8834 | this screen line. */ | 8857 | the edge of this screen line. */ |
| 8835 | || (may_wrap | 8858 | || (may_wrap && can_wrap |
| 8836 | && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))) | 8859 | && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))) |
| 8837 | { | 8860 | { |
| 8838 | it->hpos = hpos_before_this_char; | 8861 | it->hpos = hpos_before_this_char; |
| @@ -8875,6 +8898,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 8875 | result = MOVE_POS_MATCH_OR_ZV; | 8898 | result = MOVE_POS_MATCH_OR_ZV; |
| 8876 | break; | 8899 | break; |
| 8877 | } | 8900 | } |
| 8901 | moved_forward = true; | ||
| 8878 | if (BUFFER_POS_REACHED_P ()) | 8902 | if (BUFFER_POS_REACHED_P ()) |
| 8879 | { | 8903 | { |
| 8880 | if (ITERATOR_AT_END_OF_LINE_P (it)) | 8904 | if (ITERATOR_AT_END_OF_LINE_P (it)) |
| @@ -8902,7 +8926,14 @@ move_it_in_display_line_to (struct it *it, | |||
| 8902 | longer relevant, but we won't have an opportunity | 8926 | longer relevant, but we won't have an opportunity |
| 8903 | to update it, since we are done with this screen | 8927 | to update it, since we are done with this screen |
| 8904 | line. */ | 8928 | line. */ |
| 8905 | if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) | 8929 | if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it) |
| 8930 | /* If the character after the one which set the | ||
| 8931 | may_wrap flag is also whitespace, we can't | ||
| 8932 | wrap here, since the screen line cannot be | ||
| 8933 | wrapped in the middle of whitespace. | ||
| 8934 | Therefore, wrap_it _is_ relevant in that | ||
| 8935 | case. */ | ||
| 8936 | && !(moved_forward && IT_DISPLAYING_WHITESPACE (it))) | ||
| 8906 | { | 8937 | { |
| 8907 | /* If we've found TO_X, go back there, as we now | 8938 | /* If we've found TO_X, go back there, as we now |
| 8908 | know the last word fits on this screen line. */ | 8939 | know the last word fits on this screen line. */ |
| @@ -9083,9 +9114,18 @@ move_it_in_display_line_to (struct it *it, | |||
| 9083 | 9114 | ||
| 9084 | #undef BUFFER_POS_REACHED_P | 9115 | #undef BUFFER_POS_REACHED_P |
| 9085 | 9116 | ||
| 9086 | /* If we scanned beyond to_pos and didn't find a point to wrap at, | 9117 | /* If we scanned beyond TO_POS, restore the saved iterator either to |
| 9087 | restore the saved iterator. */ | 9118 | the wrap point (if found), or to atpos/atx location. We decide which |
| 9088 | if (atpos_it.sp >= 0) | 9119 | data to use to restore the saved iterator state by their X coordinates, |
| 9120 | since buffer positions might increase non-monotonically with screen | ||
| 9121 | coordinates due to bidi reordering. */ | ||
| 9122 | if (result == MOVE_LINE_CONTINUED | ||
| 9123 | && it->line_wrap == WORD_WRAP | ||
| 9124 | && wrap_it.sp >= 0 | ||
| 9125 | && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x) | ||
| 9126 | || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x))) | ||
| 9127 | RESTORE_IT (it, &wrap_it, wrap_data); | ||
| 9128 | else if (atpos_it.sp >= 0) | ||
| 9089 | RESTORE_IT (it, &atpos_it, atpos_data); | 9129 | RESTORE_IT (it, &atpos_it, atpos_data); |
| 9090 | else if (atx_it.sp >= 0) | 9130 | else if (atx_it.sp >= 0) |
| 9091 | RESTORE_IT (it, &atx_it, atx_data); | 9131 | RESTORE_IT (it, &atx_it, atx_data); |