comparison src/indent.c @ 97781:8ff0a4ca5511

(Fvertical_motion): Revert last change. Handle the general case where we are moving forward, and PT spans multiple screen lines.
author Chong Yidong <cyd@stupidchicken.com>
date Wed, 27 Aug 2008 23:12:57 +0000
parents fd1ac489f6d6
children 36198ccea250
comparison
equal deleted inserted replaced
97780:0ad50f1c1e6b 97781:8ff0a4ca5511
2053 pos = *vmotion (PT, XINT (lines), w); 2053 pos = *vmotion (PT, XINT (lines), w);
2054 SET_PT_BOTH (pos.bufpos, pos.bytepos); 2054 SET_PT_BOTH (pos.bufpos, pos.bytepos);
2055 } 2055 }
2056 else 2056 else
2057 { 2057 {
2058 int it_start, oselective, first_x; 2058 int it_start, oselective, first_x, it_overshoot_expected;
2059 int start_string_newlines = 0;
2060 enum it_method omethod;
2061 2059
2062 SET_TEXT_POS (pt, PT, PT_BYTE); 2060 SET_TEXT_POS (pt, PT, PT_BYTE);
2063 start_display (&it, w, pt); 2061 start_display (&it, w, pt);
2064 first_x = it.first_visible_x; 2062 first_x = it.first_visible_x;
2063 it_start = IT_CHARPOS (it);
2064
2065 /* See comments below for why we calculate this. */
2066 if (XINT (lines) > 0)
2067 {
2068 if (it.method == GET_FROM_STRING)
2069 {
2070 const char *s = SDATA (it.string);
2071 const char *e = s + SBYTES (it.string);
2072 while (s < e && *s != '\n')
2073 ++s;
2074 it_overshoot_expected = (s == e) ? -1 : 0;
2075 }
2076 else
2077 it_overshoot_expected = (it.method == GET_FROM_IMAGE
2078 || it.method == GET_FROM_STRETCH
2079 || it.method == GET_FROM_COMPOSITION);
2080 }
2065 2081
2066 /* Scan from the start of the line containing PT. If we don't 2082 /* Scan from the start of the line containing PT. If we don't
2067 do this, we start moving with IT->current_x == 0, while PT is 2083 do this, we start moving with IT->current_x == 0, while PT is
2068 really at some x > 0. The effect is, in continuation lines, that 2084 really at some x > 0. */
2069 we end up with the iterator placed at where it thinks X is 0,
2070 while the end position is really at some X > 0, the same X that
2071 PT had. */
2072 it_start = IT_CHARPOS (it);
2073 omethod = it.method;
2074
2075 if (omethod == GET_FROM_STRING)
2076 {
2077 char *s = SDATA (it.string) + IT_STRING_CHARPOS (it);
2078 const char *e = s + SBYTES (it.string);
2079 for (; s < e; s++)
2080 if (*s == '\n')
2081 start_string_newlines++;
2082 }
2083
2084 reseat_at_previous_visible_line_start (&it); 2085 reseat_at_previous_visible_line_start (&it);
2085 it.current_x = it.hpos = 0; 2086 it.current_x = it.hpos = 0;
2086 /* Temporarily disable selective display so we don't move too far */ 2087 /* Temporarily disable selective display so we don't move too far */
2087 oselective = it.selective; 2088 oselective = it.selective;
2088 it.selective = 0; 2089 it.selective = 0;
2089 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); 2090 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
2090 it.selective = oselective; 2091 it.selective = oselective;
2091 2092
2092 if (XINT (lines) > 0) 2093 if (XINT (lines) <= 0)
2093 { 2094 {
2094 /* If we start on a multi-line string, move the iterator to 2095 it.vpos = 0;
2095 the last line of that string. */ 2096 /* Do this even if LINES is 0, so that we move back to the
2096 if (omethod == GET_FROM_STRING && start_string_newlines) 2097 beginning of the current line as we ought. */
2097 move_it_by_lines (&it, start_string_newlines, 0); 2098 if (XINT (lines) == 0 || IT_CHARPOS (it) > 0)
2098 2099 move_it_by_lines (&it, XINT (lines), 0);
2099 /* If we got too far, move back. This may happen if 2100 }
2100 truncate-lines is on and PT is beyond the right margin. 2101 else
2101 If the starting point is on an image, stretch glyph, 2102 {
2102 composition, or Lisp string, no need to backtrack... */ 2103 if (IT_CHARPOS (it) > PT)
2103 if (IT_CHARPOS (it) > it_start 2104 {
2104 && (omethod == GET_FROM_BUFFER 2105 /* IT may move too far if truncate-lines is on and PT
2105 || omethod == GET_FROM_DISPLAY_VECTOR 2106 lies beyond the right margin. In that case,
2106 || omethod == GET_FROM_C_STRING 2107 backtrack unless the starting point is on an image,
2107 /* ... except for one corner case: when the Lisp 2108 stretch glyph, composition, or Lisp string. */
2108 string contains a newline, or if there is a 2109 if (!it_overshoot_expected
2109 newline immediately afterwards (e.g. if there is 2110 /* Also, backtrack if the Lisp string contains no
2110 an overlay with an after-string just before the 2111 newline, but there is a newline right after it.
2111 newline). */ 2112 In this case, IT overshoots if there is an
2112 || (omethod == GET_FROM_STRING 2113 after-string just before the newline. */
2113 && (start_string_newlines 2114 || (it_overshoot_expected < 0
2114 || (it.method == GET_FROM_BUFFER 2115 && it.method == GET_FROM_BUFFER
2115 && it.c == '\n'))))) 2116 && it.c == '\n'))
2116 move_it_by_lines (&it, -1, 0); 2117 move_it_by_lines (&it, -1, 0);
2117 } 2118 it.vpos = 0;
2118 2119 move_it_by_lines (&it, XINT (lines), 0);
2119 it.vpos = 0; 2120 }
2120 /* Do this even if LINES is 0, so that we move back 2121 else
2121 to the beginning of the current line as we ought. */ 2122 {
2122 if (XINT (lines) >= 0 || IT_CHARPOS (it) > 0) 2123 /* Otherwise, we are at the first row occupied by PT,
2123 move_it_by_lines (&it, XINT (lines), 0); 2124 which might span multiple screen lines (e.g., if it's
2125 on a multi-line display string). We want to start
2126 from the last line that it occupies. */
2127 it.vpos = 0;
2128 if (PT < ZV)
2129 {
2130 while (IT_CHARPOS (it) <= PT)
2131 move_it_by_lines (&it, 1, 0);
2132 move_it_by_lines (&it, XINT (lines) - 1, 0);
2133 }
2134 else
2135 move_it_by_lines (&it, XINT (lines), 0);
2136 }
2137 }
2124 2138
2125 /* Move to the goal column, if one was specified. */ 2139 /* Move to the goal column, if one was specified. */
2126 if (!NILP (lcols)) 2140 if (!NILP (lcols))
2127 { 2141 {
2128 /* If the window was originally hscrolled, move forward by 2142 /* If the window was originally hscrolled, move forward by