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 @@ #endif +#define isbackspace(c) ((c) == term_orig.c_cc[VERASE] || (c) == 8 || (c) == 127) enum { MAX_TABSTOP = 32, // sanity limit @@ -342,6 +343,7 @@ struct globals { int last_modified_count; // = -1; int cmdline_filecnt; // how many file names on cmd line int cmdcnt; // repetition count + char *rstart; // start of text in Replace mode unsigned rows, columns; // the terminal screen is this size #if ENABLE_FEATURE_VI_ASK_TERMINAL int get_rowcol_error; @@ -474,6 +476,7 @@ struct globals { #define last_modified_count (G.last_modified_count) #define cmdline_filecnt (G.cmdline_filecnt ) #define cmdcnt (G.cmdcnt ) +#define rstart (G.rstart ) #define rows (G.rows ) #define columns (G.columns ) #define crow (G.crow ) @@ -1212,7 +1215,7 @@ static char *get_input_line(const char *prompt) c = get_one_char(); if (c == '\n' || c == '\r' || c == 27) break; // this is end of input - if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { + if (isbackspace(c)) { // user wants to erase prev char write1("\b \b"); // erase char on screen buf[--i] = '\0'; @@ -2174,8 +2177,16 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' p += 1 + stupid_insert(p, ' '); } #endif - } else if (c == term_orig.c_cc[VERASE] || c == 8 || c == 127) { // Is this a BS - if (p > text) { + } else if (isbackspace(c)) { + if (cmd_mode == 2) { + // special treatment for backspace in Replace mode + if (p > rstart) { + p--; +#if ENABLE_FEATURE_VI_UNDO + undo_pop(); +#endif + } + } else if (p > text) { p--; p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char } @@ -3703,9 +3714,9 @@ static void do_cmd(int c) undo_queue_commit(); } else { if (1 <= c || Isprint(c)) { - if (c != 27) - dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); // delete char - dot = char_insert(dot, c, ALLOW_UNDO_CHAIN); // insert new char + if (c != 27 && !isbackspace(c)) + dot = yank_delete(dot, dot, PARTIAL, YANKDEL, ALLOW_UNDO); + dot = char_insert(dot, c, ALLOW_UNDO_CHAIN); } goto dc1; } @@ -4264,6 +4275,7 @@ static void do_cmd(int c) dc5: cmd_mode = 2; undo_queue_commit(); + rstart = dot; break; case KEYCODE_DELETE: if (dot < end - 1)