diff options
author | Ron Yorston <rmy@pobox.com> | 2021-06-07 11:34:06 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-06-07 11:34:06 +0100 |
commit | abe872e2a0342357a5608342cb2892e94027b3e7 (patch) | |
tree | 297cdccf332fbb5e4eb31b1eac643180059f9b5f /editors | |
parent | 1f33f42d7bcb019b268d938df643a7a785dc19ab (diff) | |
parent | 4d983dcddeee94892d3072e84c7c9a01d4696055 (diff) | |
download | busybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.tar.gz busybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.tar.bz2 busybox-w32-abe872e2a0342357a5608342cb2892e94027b3e7.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'editors')
-rw-r--r-- | editors/vi.c | 111 |
1 files changed, 77 insertions, 34 deletions
diff --git a/editors/vi.c b/editors/vi.c index 3dcde9b24..a4d6b21b4 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -307,7 +307,6 @@ struct globals { | |||
307 | #define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash | 307 | #define err_method (vi_setops & VI_ERR_METHOD) // indicate error with beep or flash |
308 | #define ignorecase (vi_setops & VI_IGNORECASE) | 308 | #define ignorecase (vi_setops & VI_IGNORECASE) |
309 | #define showmatch (vi_setops & VI_SHOWMATCH ) | 309 | #define showmatch (vi_setops & VI_SHOWMATCH ) |
310 | #define openabove (vi_setops & VI_TABSTOP ) | ||
311 | // order of constants and strings must match | 310 | // order of constants and strings must match |
312 | #define OPTS_STR \ | 311 | #define OPTS_STR \ |
313 | "ai\0""autoindent\0" \ | 312 | "ai\0""autoindent\0" \ |
@@ -316,15 +315,10 @@ struct globals { | |||
316 | "ic\0""ignorecase\0" \ | 315 | "ic\0""ignorecase\0" \ |
317 | "sm\0""showmatch\0" \ | 316 | "sm\0""showmatch\0" \ |
318 | "ts\0""tabstop\0" | 317 | "ts\0""tabstop\0" |
319 | #define set_openabove() (vi_setops |= VI_TABSTOP) | ||
320 | #define clear_openabove() (vi_setops &= ~VI_TABSTOP) | ||
321 | #else | 318 | #else |
322 | #define autoindent (0) | 319 | #define autoindent (0) |
323 | #define expandtab (0) | 320 | #define expandtab (0) |
324 | #define err_method (0) | 321 | #define err_method (0) |
325 | #define openabove (0) | ||
326 | #define set_openabove() ((void)0) | ||
327 | #define clear_openabove() ((void)0) | ||
328 | #endif | 322 | #endif |
329 | 323 | ||
330 | #if ENABLE_FEATURE_VI_READONLY | 324 | #if ENABLE_FEATURE_VI_READONLY |
@@ -380,6 +374,9 @@ struct globals { | |||
380 | #if ENABLE_FEATURE_VI_SEARCH | 374 | #if ENABLE_FEATURE_VI_SEARCH |
381 | char *last_search_pattern; // last pattern from a '/' or '?' search | 375 | char *last_search_pattern; // last pattern from a '/' or '?' search |
382 | #endif | 376 | #endif |
377 | #if ENABLE_FEATURE_VI_SETOPTS | ||
378 | int indentcol; // column of recently autoindent, 0 or -1 | ||
379 | #endif | ||
383 | 380 | ||
384 | // former statics | 381 | // former statics |
385 | #if ENABLE_FEATURE_VI_YANKMARK | 382 | #if ENABLE_FEATURE_VI_YANKMARK |
@@ -505,6 +502,7 @@ struct globals { | |||
505 | #define ioq_start (G.ioq_start ) | 502 | #define ioq_start (G.ioq_start ) |
506 | #define dotcnt (G.dotcnt ) | 503 | #define dotcnt (G.dotcnt ) |
507 | #define last_search_pattern (G.last_search_pattern) | 504 | #define last_search_pattern (G.last_search_pattern) |
505 | #define indentcol (G.indentcol ) | ||
508 | 506 | ||
509 | #define edit_file__cur_line (G.edit_file__cur_line) | 507 | #define edit_file__cur_line (G.edit_file__cur_line) |
510 | #define refresh__old_offset (G.refresh__old_offset) | 508 | #define refresh__old_offset (G.refresh__old_offset) |
@@ -2155,15 +2153,26 @@ static uintptr_t stupid_insert(char *p, char c) // stupidly insert the char c at | |||
2155 | return bias; | 2153 | return bias; |
2156 | } | 2154 | } |
2157 | 2155 | ||
2156 | // find number of characters in indent, p must be at beginning of line | ||
2157 | static size_t indent_len(char *p) | ||
2158 | { | ||
2159 | char *r = p; | ||
2160 | |||
2161 | while (r < (end - 1) && isblank(*r)) | ||
2162 | r++; | ||
2163 | return r - p; | ||
2164 | } | ||
2165 | |||
2158 | #if !ENABLE_FEATURE_VI_UNDO | 2166 | #if !ENABLE_FEATURE_VI_UNDO |
2159 | #define char_insert(a,b,c) char_insert(a,b) | 2167 | #define char_insert(a,b,c) char_insert(a,b) |
2160 | #endif | 2168 | #endif |
2161 | static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | 2169 | static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' |
2162 | { | 2170 | { |
2163 | #if ENABLE_FEATURE_VI_SETOPTS | 2171 | #if ENABLE_FEATURE_VI_SETOPTS |
2164 | char *q; | ||
2165 | size_t len; | 2172 | size_t len; |
2173 | int col, ntab, nspc; | ||
2166 | #endif | 2174 | #endif |
2175 | char *bol = begin_line(p); | ||
2167 | 2176 | ||
2168 | if (c == 22) { // Is this an ctrl-V? | 2177 | if (c == 22) { // Is this an ctrl-V? |
2169 | p += stupid_insert(p, '^'); // use ^ to indicate literal next | 2178 | p += stupid_insert(p, '^'); // use ^ to indicate literal next |
@@ -2185,25 +2194,36 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
2185 | if ((p[-1] != '\n') && (dot > text)) { | 2194 | if ((p[-1] != '\n') && (dot > text)) { |
2186 | p--; | 2195 | p--; |
2187 | } | 2196 | } |
2188 | } else if (c == 4) { // ctrl-D reduces indentation | 2197 | #if ENABLE_FEATURE_VI_SETOPTS |
2189 | int prev; | 2198 | if (autoindent) { |
2190 | char *r, *bol; | 2199 | len = indent_len(bol); |
2191 | bol = begin_line(p); | 2200 | if (len && get_column(bol + len) == indentcol) { |
2192 | for (r = bol; r < end_line(p); ++r) { | 2201 | // remove autoindent from otherwise empty line |
2193 | if (!isblank(*r)) | 2202 | text_hole_delete(bol, bol + len - 1, undo); |
2194 | break; | 2203 | p = bol; |
2204 | } | ||
2195 | } | 2205 | } |
2196 | 2206 | #endif | |
2197 | prev = prev_tabstop(get_column(r)); | 2207 | } else if (c == 4) { // ctrl-D reduces indentation |
2208 | char *r = bol + indent_len(bol); | ||
2209 | int prev = prev_tabstop(get_column(r)); | ||
2198 | while (r > bol && get_column(r) > prev) { | 2210 | while (r > bol && get_column(r) > prev) { |
2199 | if (p > bol) | 2211 | if (p > bol) |
2200 | p--; | 2212 | p--; |
2201 | r--; | 2213 | r--; |
2202 | r = text_hole_delete(r, r, ALLOW_UNDO_QUEUED); | 2214 | r = text_hole_delete(r, r, ALLOW_UNDO_QUEUED); |
2203 | } | 2215 | } |
2216 | |||
2217 | #if ENABLE_FEATURE_VI_SETOPTS | ||
2218 | if (autoindent && indentcol && r == end_line(p)) { | ||
2219 | // record changed size of autoindent | ||
2220 | indentcol = get_column(p); | ||
2221 | return p; | ||
2222 | } | ||
2223 | #endif | ||
2204 | #if ENABLE_FEATURE_VI_SETOPTS | 2224 | #if ENABLE_FEATURE_VI_SETOPTS |
2205 | } else if (c == '\t' && expandtab) { // expand tab | 2225 | } else if (c == '\t' && expandtab) { // expand tab |
2206 | int col = get_column(p); | 2226 | col = get_column(p); |
2207 | col = next_tabstop(col) - col + 1; | 2227 | col = next_tabstop(col) - col + 1; |
2208 | while (col--) { | 2228 | while (col--) { |
2209 | # if ENABLE_FEATURE_VI_UNDO | 2229 | # if ENABLE_FEATURE_VI_UNDO |
@@ -2242,27 +2262,46 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
2242 | showmatching(p - 1); | 2262 | showmatching(p - 1); |
2243 | } | 2263 | } |
2244 | if (autoindent && c == '\n') { // auto indent the new line | 2264 | if (autoindent && c == '\n') { // auto indent the new line |
2245 | // use current/previous line as template | 2265 | // use indent of current/previous line |
2246 | q = openabove ? p : prev_line(p); | 2266 | bol = indentcol < 0 ? p : prev_line(p); |
2247 | len = strspn(q, " \t"); // space or tab | 2267 | len = indent_len(bol); |
2248 | if (openabove) { | 2268 | col = get_column(bol + len); |
2249 | p--; // this replaces dot_prev() in do_cmd() | 2269 | |
2250 | q += len; // template will be shifted by text_hole_make() | 2270 | if (len && col == indentcol) { |
2271 | // previous line was empty except for autoindent | ||
2272 | // move the indent to the current line | ||
2273 | memmove(bol + 1, bol, len); | ||
2274 | *bol = '\n'; | ||
2275 | return p; | ||
2251 | } | 2276 | } |
2277 | |||
2278 | if (indentcol < 0) | ||
2279 | p--; // open above, indent before newly inserted NL | ||
2280 | |||
2252 | if (len) { | 2281 | if (len) { |
2253 | uintptr_t bias; | 2282 | indentcol = col; |
2254 | bias = text_hole_make(p, len); | 2283 | if (expandtab) { |
2255 | p += bias; | 2284 | ntab = 0; |
2256 | q += bias; | 2285 | nspc = col; |
2286 | } else { | ||
2287 | ntab = col / tabstop; | ||
2288 | nspc = col % tabstop; | ||
2289 | } | ||
2290 | p += text_hole_make(p, ntab + nspc); | ||
2257 | # if ENABLE_FEATURE_VI_UNDO | 2291 | # if ENABLE_FEATURE_VI_UNDO |
2258 | undo_push_insert(p, len, undo); | 2292 | undo_push_insert(p, ntab + nspc, undo); |
2259 | # endif | 2293 | # endif |
2260 | memcpy(p, q, len); | 2294 | memset(p, '\t', ntab); |
2261 | p += len; | 2295 | p += ntab; |
2296 | memset(p, ' ', nspc); | ||
2297 | return p + nspc; | ||
2262 | } | 2298 | } |
2263 | } | 2299 | } |
2264 | #endif | 2300 | #endif |
2265 | } | 2301 | } |
2302 | #if ENABLE_FEATURE_VI_SETOPTS | ||
2303 | indentcol = 0; | ||
2304 | #endif | ||
2266 | return p; | 2305 | return p; |
2267 | } | 2306 | } |
2268 | 2307 | ||
@@ -2647,7 +2686,6 @@ static void setops(char *args, int flg_no) | |||
2647 | index = 1 << (index >> 1); // convert to VI_bit | 2686 | index = 1 << (index >> 1); // convert to VI_bit |
2648 | 2687 | ||
2649 | if (index & VI_TABSTOP) { | 2688 | if (index & VI_TABSTOP) { |
2650 | // don't set this bit in vi_setops, it's reused as 'openabove' | ||
2651 | int t; | 2689 | int t; |
2652 | if (!eq || flg_no) // no "=NNN" or it is "notabstop"? | 2690 | if (!eq || flg_no) // no "=NNN" or it is "notabstop"? |
2653 | goto bad; | 2691 | goto bad; |
@@ -3783,6 +3821,7 @@ static void do_cmd(int c) | |||
3783 | # endif | 3821 | # endif |
3784 | } while (--cmdcnt > 0); | 3822 | } while (--cmdcnt > 0); |
3785 | dot += cnt; | 3823 | dot += cnt; |
3824 | dot_skip_over_ws(); | ||
3786 | # if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS | 3825 | # if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS |
3787 | yank_status("Put", p, i); | 3826 | yank_status("Put", p, i); |
3788 | # endif | 3827 | # endif |
@@ -4109,17 +4148,18 @@ static void do_cmd(int c) | |||
4109 | break; | 4148 | break; |
4110 | case 'O': // O- open an empty line above | 4149 | case 'O': // O- open an empty line above |
4111 | dot_begin(); | 4150 | dot_begin(); |
4112 | set_openabove(); | 4151 | #if ENABLE_FEATURE_VI_SETOPTS |
4152 | indentcol = -1; | ||
4153 | #endif | ||
4113 | goto dc3; | 4154 | goto dc3; |
4114 | case 'o': // o- open an empty line below | 4155 | case 'o': // o- open an empty line below |
4115 | dot_end(); | 4156 | dot_end(); |
4116 | dc3: | 4157 | dc3: |
4117 | dot = char_insert(dot, '\n', ALLOW_UNDO); | 4158 | dot = char_insert(dot, '\n', ALLOW_UNDO); |
4118 | if (c == 'O' && !autoindent) { | 4159 | if (c == 'O' && !autoindent) { |
4119 | // done in char_insert() for openabove+autoindent | 4160 | // done in char_insert() for 'O'+autoindent |
4120 | dot_prev(); | 4161 | dot_prev(); |
4121 | } | 4162 | } |
4122 | clear_openabove(); | ||
4123 | goto dc_i; | 4163 | goto dc_i; |
4124 | break; | 4164 | break; |
4125 | case 'R': // R- continuous Replace char | 4165 | case 'R': // R- continuous Replace char |
@@ -4238,6 +4278,9 @@ static void do_cmd(int c) | |||
4238 | if (dot != (end-1)) { | 4278 | if (dot != (end-1)) { |
4239 | dot_prev(); | 4279 | dot_prev(); |
4240 | } | 4280 | } |
4281 | } else if (c == 'd') { | ||
4282 | dot_begin(); | ||
4283 | dot_skip_over_ws(); | ||
4241 | } else { | 4284 | } else { |
4242 | dot = save_dot; | 4285 | dot = save_dot; |
4243 | } | 4286 | } |