diff options
| author | Eli Zaretskii | 2011-09-24 16:23:58 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-09-24 16:23:58 +0300 |
| commit | e3cbd34b8793d52fb3252c8e0406bc5d67c2db44 (patch) | |
| tree | abe74fe6623c25dea8c65abb05806b05baaf76b5 /src/indent.c | |
| parent | fac7ae53a7832a967e351c6dbfa5552bb313d4bc (diff) | |
| download | emacs-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.c | 101 |
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 | ||