aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2016-05-21 12:35:08 +0300
committerEli Zaretskii2016-05-21 12:35:08 +0300
commit99848b37d2c3e14c0af45fc6da437a806aa58a80 (patch)
tree36e1a4603d96c4bc380b2bcc1fe9203787bc684e /src
parentedb4af7a1d1e8e0ab67b2dedad0ca0380e6866d4 (diff)
downloademacs-99848b37d2c3e14c0af45fc6da437a806aa58a80.tar.gz
emacs-99848b37d2c3e14c0af45fc6da437a806aa58a80.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)
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c64
1 files changed, 52 insertions, 12 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 10a0cf24b4a..e78d3d6f5b6 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -8810,6 +8810,8 @@ move_it_in_display_line_to (struct it *it,
8810 ? WINDOW_LEFT_FRINGE_WIDTH (it->w) 8810 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
8811 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) 8811 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
8812 { 8812 {
8813 bool moved_forward = false;
8814
8813 if (/* IT->hpos == 0 means the very first glyph 8815 if (/* IT->hpos == 0 means the very first glyph
8814 doesn't fit on the line, e.g. a wide image. */ 8816 doesn't fit on the line, e.g. a wide image. */
8815 it->hpos == 0 8817 it->hpos == 0
@@ -8828,16 +8830,37 @@ move_it_in_display_line_to (struct it *it,
8828 now that we know it fits in this row. */ 8830 now that we know it fits in this row. */
8829 if (BUFFER_POS_REACHED_P ()) 8831 if (BUFFER_POS_REACHED_P ())
8830 { 8832 {
8833 bool can_wrap = true;
8834
8835 /* If we are at a whitespace character
8836 that barely fits on this screen line,
8837 but the next character is also
8838 whitespace, we cannot wrap here. */
8839 if (it->line_wrap == WORD_WRAP
8840 && wrap_it.sp >= 0
8841 && may_wrap
8842 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
8843 {
8844 struct it tem_it;
8845 void *tem_data = NULL;
8846
8847 SAVE_IT (tem_it, *it, tem_data);
8848 set_iterator_to_next (it, true);
8849 if (get_next_display_element (it)
8850 && IT_DISPLAYING_WHITESPACE (it))
8851 can_wrap = false;
8852 RESTORE_IT (it, &tem_it, tem_data);
8853 }
8831 if (it->line_wrap != WORD_WRAP 8854 if (it->line_wrap != WORD_WRAP
8832 || wrap_it.sp < 0 8855 || wrap_it.sp < 0
8833 /* If we've just found whitespace to 8856 /* If we've just found whitespace
8834 wrap, effectively ignore the 8857 where we can wrap, effectively
8835 previous wrap point -- it is no 8858 ignore the previous wrap point --
8836 longer relevant, but we won't 8859 it is no longer relevant, but we
8837 have an opportunity to update it, 8860 won't have an opportunity to
8838 since we've reached the edge of 8861 update it, since we've reached
8839 this screen line. */ 8862 the edge of this screen line. */
8840 || (may_wrap 8863 || (may_wrap && can_wrap
8841 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))) 8864 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
8842 { 8865 {
8843 it->hpos = hpos_before_this_char; 8866 it->hpos = hpos_before_this_char;
@@ -8880,6 +8903,7 @@ move_it_in_display_line_to (struct it *it,
8880 result = MOVE_POS_MATCH_OR_ZV; 8903 result = MOVE_POS_MATCH_OR_ZV;
8881 break; 8904 break;
8882 } 8905 }
8906 moved_forward = true;
8883 if (BUFFER_POS_REACHED_P ()) 8907 if (BUFFER_POS_REACHED_P ())
8884 { 8908 {
8885 if (ITERATOR_AT_END_OF_LINE_P (it)) 8909 if (ITERATOR_AT_END_OF_LINE_P (it))
@@ -8907,7 +8931,14 @@ move_it_in_display_line_to (struct it *it,
8907 longer relevant, but we won't have an opportunity 8931 longer relevant, but we won't have an opportunity
8908 to update it, since we are done with this screen 8932 to update it, since we are done with this screen
8909 line. */ 8933 line. */
8910 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) 8934 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
8935 /* If the character after the one which set the
8936 may_wrap flag is also whitespace, we can't
8937 wrap here, since the screen line cannot be
8938 wrapped in the middle of whitespace.
8939 Therefore, wrap_it _is_ relevant in that
8940 case. */
8941 && !(moved_forward && IT_DISPLAYING_WHITESPACE (it)))
8911 { 8942 {
8912 /* If we've found TO_X, go back there, as we now 8943 /* If we've found TO_X, go back there, as we now
8913 know the last word fits on this screen line. */ 8944 know the last word fits on this screen line. */
@@ -9088,9 +9119,18 @@ move_it_in_display_line_to (struct it *it,
9088 9119
9089#undef BUFFER_POS_REACHED_P 9120#undef BUFFER_POS_REACHED_P
9090 9121
9091 /* If we scanned beyond to_pos and didn't find a point to wrap at, 9122 /* If we scanned beyond TO_POS, restore the saved iterator either to
9092 restore the saved iterator. */ 9123 the wrap point (if found), or to atpos/atx location. We decide which
9093 if (atpos_it.sp >= 0) 9124 data to use to restore the saved iterator state by their X coordinates,
9125 since buffer positions might increase non-monotonically with screen
9126 coordinates due to bidi reordering. */
9127 if (result == MOVE_LINE_CONTINUED
9128 && it->line_wrap == WORD_WRAP
9129 && wrap_it.sp >= 0
9130 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
9131 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
9132 RESTORE_IT (it, &wrap_it, wrap_data);
9133 else if (atpos_it.sp >= 0)
9094 RESTORE_IT (it, &atpos_it, atpos_data); 9134 RESTORE_IT (it, &atpos_it, atpos_data);
9095 else if (atx_it.sp >= 0) 9135 else if (atx_it.sp >= 0)
9096 RESTORE_IT (it, &atx_it, atx_data); 9136 RESTORE_IT (it, &atx_it, atx_data);