diff options
author | Ron Yorston <rmy@pobox.com> | 2022-03-03 11:35:46 +0000 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2022-03-04 22:57:05 +0100 |
commit | fc7868602ecf0d761a9a877141add4a9b6918d02 (patch) | |
tree | 48f24ea664b9ad54a4b7ae8b028522d68504c1b2 | |
parent | 55f969a006109703dd056bee1b6c1d11b0602449 (diff) | |
download | busybox-w32-fc7868602ecf0d761a9a877141add4a9b6918d02.tar.gz busybox-w32-fc7868602ecf0d761a9a877141add4a9b6918d02.tar.bz2 busybox-w32-fc7868602ecf0d761a9a877141add4a9b6918d02.zip |
vi: improved handling of backspace in replace mode
In replace mode ('R' command) the backspace character should get
special treatment:
- backspace only goes back to the start of the replacement;
- backspacing over replaced characters restores the original text.
Prior to this commit BusyBox vi deleted the characters both before
and after the cursor in replace mode.
function old new delta
undo_pop - 235 +235
char_insert 858 884 +26
indicate_error 81 84 +3
find_range 654 657 +3
static.text_yank 77 79 +2
do_cmd 4486 4243 -243
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/1 up/down: 269/-243) Total: 26 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/editors/vi.c b/editors/vi.c index d37cd48a3..4257c0fdc 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -224,6 +224,7 @@ | |||
224 | 224 | ||
225 | #endif | 225 | #endif |
226 | 226 | ||
227 | #define isbackspace(c) ((c) == term_orig.c_cc[VERASE] || (c) == 8 || (c) == 127) | ||
227 | 228 | ||
228 | enum { | 229 | enum { |
229 | MAX_TABSTOP = 32, // sanity limit | 230 | MAX_TABSTOP = 32, // sanity limit |
@@ -342,6 +343,7 @@ struct globals { | |||
342 | int last_modified_count; // = -1; | 343 | int last_modified_count; // = -1; |
343 | int cmdline_filecnt; // how many file names on cmd line | 344 | int cmdline_filecnt; // how many file names on cmd line |
344 | int cmdcnt; // repetition count | 345 | int cmdcnt; // repetition count |
346 | char *rstart; // start of text in Replace mode | ||
345 | unsigned rows, columns; // the terminal screen is this size | 347 | unsigned rows, columns; // the terminal screen is this size |
346 | #if ENABLE_FEATURE_VI_ASK_TERMINAL | 348 | #if ENABLE_FEATURE_VI_ASK_TERMINAL |
347 | int get_rowcol_error; | 349 | int get_rowcol_error; |
@@ -474,6 +476,7 @@ struct globals { | |||
474 | #define last_modified_count (G.last_modified_count) | 476 | #define last_modified_count (G.last_modified_count) |
475 | #define cmdline_filecnt (G.cmdline_filecnt ) | 477 | #define cmdline_filecnt (G.cmdline_filecnt ) |
476 | #define cmdcnt (G.cmdcnt ) | 478 | #define cmdcnt (G.cmdcnt ) |
479 | #define rstart (G.rstart ) | ||
477 | #define rows (G.rows ) | 480 | #define rows (G.rows ) |
478 | #define columns (G.columns ) | 481 | #define columns (G.columns ) |
479 | #define crow (G.crow ) | 482 | #define crow (G.crow ) |
@@ -1212,7 +1215,7 @@ static char *get_input_line(const char *prompt) | |||
1212 | c = get_one_char(); | 1215 | c = get_one_char(); |
1213 | if (c == '\n' || c == '\r' || c == 27) | 1216 | if (c == '\n' || c == '\r' || c == 27) |
1214 | break; // this is end of input | 1217 | break; // this is end of input |
1215 | if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { | 1218 | if (isbackspace(c)) { |
1216 | // user wants to erase prev char | 1219 | // user wants to erase prev char |
1217 | write1("\b \b"); // erase char on screen | 1220 | write1("\b \b"); // erase char on screen |
1218 | buf[--i] = '\0'; | 1221 | buf[--i] = '\0'; |
@@ -2174,8 +2177,16 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' | |||
2174 | p += 1 + stupid_insert(p, ' '); | 2177 | p += 1 + stupid_insert(p, ' '); |
2175 | } | 2178 | } |
2176 | #endif | 2179 | #endif |
2177 | } else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS | 2180 | } else if (isbackspace(c)) { |
2178 | if (p > text) { | 2181 | if (cmd_mode == 2) { |
2182 | // special treatment for backspace in Replace mode | ||
2183 | if (p > rstart) { | ||
2184 | p--; | ||
2185 | #if ENABLE_FEATURE_VI_UNDO | ||
2186 | undo_pop(); | ||
2187 | #endif | ||
2188 | } | ||
2189 | } else if (p > text) { | ||
2179 | p--; | 2190 | p--; |
2180 | p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char | 2191 | p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char |
2181 | } | 2192 | } |
@@ -3703,9 +3714,9 @@ static void do_cmd(int c) | |||
3703 | undo_queue_commit(); | 3714 | undo_queue_commit(); |
3704 | } else { | 3715 | } else { |
3705 | if (1 <= c || Isprint(c)) { | 3716 | if (1 <= c || Isprint(c)) { |
3706 | if (c != 27) | 3717 | if (c != 27 && !isbackspace(c)) |
3707 | dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); // delete char | 3718 | dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); |
3708 | dot = char_insert(dot, c, ALLOW_UNDO_CHAIN); // insert new char | 3719 | dot = char_insert(dot, c, ALLOW_UNDO_CHAIN); |
3709 | } | 3720 | } |
3710 | goto dc1; | 3721 | goto dc1; |
3711 | } | 3722 | } |
@@ -4264,6 +4275,7 @@ static void do_cmd(int c) | |||
4264 | dc5: | 4275 | dc5: |
4265 | cmd_mode = 2; | 4276 | cmd_mode = 2; |
4266 | undo_queue_commit(); | 4277 | undo_queue_commit(); |
4278 | rstart = dot; | ||
4267 | break; | 4279 | break; |
4268 | case KEYCODE_DELETE: | 4280 | case KEYCODE_DELETE: |
4269 | if (dot < end - 1) | 4281 | if (dot < end - 1) |