aboutsummaryrefslogtreecommitdiffstats
path: root/src/indent.c
diff options
context:
space:
mode:
authorEli Zaretskii2011-09-24 16:23:58 +0300
committerEli Zaretskii2011-09-24 16:23:58 +0300
commite3cbd34b8793d52fb3252c8e0406bc5d67c2db44 (patch)
treeabe74fe6623c25dea8c65abb05806b05baaf76b5 /src/indent.c
parentfac7ae53a7832a967e351c6dbfa5552bb313d4bc (diff)
downloademacs-e3cbd34b8793d52fb3252c8e0406bc5d67c2db44.tar.gz
emacs-e3cbd34b8793d52fb3252c8e0406bc5d67c2db44.zip
Fix vertical cursor motion when the newline is covered by a display string.
src/indent.c (Fvertical_motion): Compute and apply the overshoot logic when moving up, not only when moving down. Fix the confusing name and values of the it_overshoot_expected variable; logic changes accordingly. (Bug#9254) (Bug#9549) src/xdisp.c (pos_visible_p): Produce correct pixel coordinates when CHARPOS is covered by a display string which includes newlines. (move_it_vertically_backward): Avoid inflooping when START_CHARPOS is covered by a display string with embedded newlines.
Diffstat (limited to 'src/indent.c')
-rw-r--r--src/indent.c101
1 files changed, 53 insertions, 48 deletions
diff --git a/src/indent.c b/src/indent.c
index e00d2152577..e6629ef5811 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -2019,7 +2019,8 @@ whether or not it is currently displayed in some window. */)
2019 else 2019 else
2020 { 2020 {
2021 EMACS_INT it_start; 2021 EMACS_INT it_start;
2022 int first_x, it_overshoot_expected IF_LINT (= 0); 2022 int first_x, it_overshoot_count = 0;
2023 int overshoot_handled = 0;
2023 2024
2024 itdata = bidi_shelve_cache (); 2025 itdata = bidi_shelve_cache ();
2025 SET_TEXT_POS (pt, PT, PT_BYTE); 2026 SET_TEXT_POS (pt, PT, PT_BYTE);
@@ -2028,22 +2029,23 @@ whether or not it is currently displayed in some window. */)
2028 it_start = IT_CHARPOS (it); 2029 it_start = IT_CHARPOS (it);
2029 2030
2030 /* See comments below for why we calculate this. */ 2031 /* See comments below for why we calculate this. */
2031 if (XINT (lines) > 0) 2032 if (it.cmp_it.id >= 0)
2033 it_overshoot_count = 0;
2034 else if (it.method == GET_FROM_STRING)
2032 { 2035 {
2033 if (it.cmp_it.id >= 0) 2036 const char *s = SSDATA (it.string);
2034 it_overshoot_expected = 1; 2037 const char *e = s + SBYTES (it.string);
2035 else if (it.method == GET_FROM_STRING) 2038 while (s < e)
2036 { 2039 {
2037 const char *s = SSDATA (it.string); 2040 if (*s++ == '\n')
2038 const char *e = s + SBYTES (it.string); 2041 it_overshoot_count++;
2039 while (s < e && *s != '\n')
2040 ++s;
2041 it_overshoot_expected = (s == e) ? -1 : 0;
2042 } 2042 }
2043 else 2043 if (!it_overshoot_count)
2044 it_overshoot_expected = (it.method == GET_FROM_IMAGE 2044 it_overshoot_count == -1;
2045 || it.method == GET_FROM_STRETCH);
2046 } 2045 }
2046 else
2047 it_overshoot_count =
2048 !(it.method == GET_FROM_IMAGE || it.method == GET_FROM_STRETCH);
2047 2049
2048 /* Scan from the start of the line containing PT. If we don't 2050 /* Scan from the start of the line containing PT. If we don't
2049 do this, we start moving with IT->current_x == 0, while PT is 2051 do this, we start moving with IT->current_x == 0, while PT is
@@ -2057,6 +2059,25 @@ whether or not it is currently displayed in some window. */)
2057 tell, and it causes Bug#2694 . -- cyd */ 2059 tell, and it causes Bug#2694 . -- cyd */
2058 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); 2060 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
2059 2061
2062 /* IT may move too far if truncate-lines is on and PT lies
2063 beyond the right margin. IT may also move too far if the
2064 starting point is on a Lisp string that has embedded
2065 newlines. In these cases, backtrack. */
2066 if (IT_CHARPOS (it) > it_start)
2067 {
2068 /* We need to backtrack also if the Lisp string contains no
2069 newlines, but there is a newline right after it. In this
2070 case, IT overshoots if there is an after-string just
2071 before the newline. */
2072 if (it_overshoot_count < 0
2073 && it.method == GET_FROM_BUFFER
2074 && it.c == '\n')
2075 it_overshoot_count = 1;
2076 if (it_overshoot_count > 0)
2077 move_it_by_lines (&it, -it_overshoot_count);
2078
2079 overshoot_handled = 1;
2080 }
2060 if (XINT (lines) <= 0) 2081 if (XINT (lines) <= 0)
2061 { 2082 {
2062 it.vpos = 0; 2083 it.vpos = 0;
@@ -2065,47 +2086,31 @@ whether or not it is currently displayed in some window. */)
2065 if (XINT (lines) == 0 || IT_CHARPOS (it) > 0) 2086 if (XINT (lines) == 0 || IT_CHARPOS (it) > 0)
2066 move_it_by_lines (&it, max (INT_MIN, XINT (lines))); 2087 move_it_by_lines (&it, max (INT_MIN, XINT (lines)));
2067 } 2088 }
2089 else if (overshoot_handled)
2090 {
2091 it.vpos = 0;
2092 move_it_by_lines (&it, min (INT_MAX, XINT (lines)));
2093 }
2068 else 2094 else
2069 { 2095 {
2070 if (IT_CHARPOS (it) > it_start) 2096 /* Otherwise, we are at the first row occupied by PT, which
2071 { 2097 might span multiple screen lines (e.g., if it's on a
2072 /* IT may move too far if truncate-lines is on and PT 2098 multi-line display string). We want to start from the
2073 lies beyond the right margin. In that case, 2099 last line that it occupies. */
2074 backtrack unless the starting point is on an image, 2100 if (it_start < ZV)
2075 stretch glyph, composition, or Lisp string. */
2076 if (!it_overshoot_expected
2077 /* Also, backtrack if the Lisp string contains no
2078 newline, but there is a newline right after it.
2079 In this case, IT overshoots if there is an
2080 after-string just before the newline. */
2081 || (it_overshoot_expected < 0
2082 && it.method == GET_FROM_BUFFER
2083 && it.c == '\n'))
2084 move_it_by_lines (&it, -1);
2085 it.vpos = 0;
2086 move_it_by_lines (&it, min (INT_MAX, XINT (lines)));
2087 }
2088 else
2089 { 2101 {
2090 /* Otherwise, we are at the first row occupied by PT, 2102 while (IT_CHARPOS (it) <= it_start)
2091 which might span multiple screen lines (e.g., if it's
2092 on a multi-line display string). We want to start
2093 from the last line that it occupies. */
2094 if (it_start < ZV)
2095 {
2096 while (IT_CHARPOS (it) <= it_start)
2097 {
2098 it.vpos = 0;
2099 move_it_by_lines (&it, 1);
2100 }
2101 if (XINT (lines) > 1)
2102 move_it_by_lines (&it, min (INT_MAX, XINT (lines) - 1));
2103 }
2104 else
2105 { 2103 {
2106 it.vpos = 0; 2104 it.vpos = 0;
2107 move_it_by_lines (&it, min (INT_MAX, XINT (lines))); 2105 move_it_by_lines (&it, 1);
2108 } 2106 }
2107 if (XINT (lines) > 1)
2108 move_it_by_lines (&it, min (INT_MAX, XINT (lines) - 1));
2109 }
2110 else
2111 {
2112 it.vpos = 0;
2113 move_it_by_lines (&it, min (INT_MAX, XINT (lines)));
2109 } 2114 }
2110 } 2115 }
2111 2116