فهرست منبع

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>
Ron Yorston 4 سال پیش
والد
کامیت
ce2ee16543
1فایلهای تغییر یافته به همراه23 افزوده شده و 14 حذف شده
  1. 23 14
      editors/vi.c

+ 23 - 14
editors/vi.c

@@ -43,6 +43,12 @@ struct globals *ptr_to_globals;
 
 #endif
 
+#ifdef RT_USING_POSIX_TERMIOS
+#define isbackspace(c) ((c) == term_orig.c_cc[VERASE] || (c) == 8 || (c) == 127)
+#else
+#define isbackspace(c) ((c) == 8 || (c) == 127)
+#endif /* RT_USING_POSIX_TERMIOS */
+
 enum {
     MAX_TABSTOP = 32, // sanity limit
     // User input len. Need not be extra big.
@@ -159,6 +165,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;
@@ -279,6 +286,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               )
@@ -2123,12 +2131,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 (
-        #ifdef RT_USING_POSIX_TERMIOS
-            c == term_orig.c_cc[VERASE] ||
-        #endif
-            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
         }
@@ -3016,11 +3028,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 (
-            #ifdef RT_USING_POSIX_TERMIOS
-                c == term_orig.c_cc[VERASE] ||
-            #endif
-                c == 8 || c == 127) {
+        if (isbackspace(c)) {
             // user wants to erase prev char
             vi_puts("\b \b"); // erase char on screen
             buf[--i] = '\0';
@@ -3605,9 +3613,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;
         }
@@ -4159,6 +4167,7 @@ static void do_cmd(int c)
  dc5:
         cmd_mode = 2;
         undo_queue_commit();
+        rstart = dot;
         break;
     case KEYCODE_DELETE:
         if (dot < end - 1)