ps,top: add an option to show threads. +260 bytes of code
[oweals/busybox.git] / editors / vi.c
index 93e5647569fe8a7d5c8964682bc2376148eed739..31a1edc9fa2b509cf7ad6428e47b3e6a6c061bc4 100644 (file)
@@ -151,7 +151,6 @@ struct globals {
        char erase_char;         // the users erase character
        char last_input_char;    // last char read from user
 
-       smalluint chars_to_parse;
 #if ENABLE_FEATURE_VI_DOT_CMD
        smallint adding2q;       // are we currently adding user input to q
        int lmc_len;             // length of last_modifying_cmd
@@ -235,7 +234,6 @@ struct globals {
 #define last_forward_char       (G.last_forward_char  )
 #define erase_char              (G.erase_char         )
 #define last_input_char         (G.last_input_char    )
-#define chars_to_parse          (G.chars_to_parse     )
 #if ENABLE_FEATURE_VI_READONLY
 #define readonly_mode           (G.readonly_mode      )
 #else
@@ -271,7 +269,7 @@ struct globals {
        SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
        last_file_modified = -1; \
        /* "" but has space for 2 chars: */ \
-       USE_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
+       IF_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
 } while (0)
 
 
@@ -300,13 +298,17 @@ static void dot_delete(void);     // delete the char at 'dot'
 static char *bound_dot(char *);        // make sure  text[0] <= P < "end"
 static char *new_screen(int, int);     // malloc virtual screen memory
 static char *char_insert(char *, char);        // insert the char c at 'p'
-static char *stupid_insert(char *, char);      // stupidly insert the char c at 'p'
+// might reallocate text[]! use p += stupid_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t stupid_insert(char *, char);  // stupidly insert the char c at 'p'
 static int find_range(char **, char **, char); // return pointers for an object
 static int st_test(char *, int, int, char *);  // helper for skip_thing()
 static char *skip_thing(char *, int, int, int);        // skip some object
 static char *find_pair(char *, char);  // find matching pair ()  []  {}
 static char *text_hole_delete(char *, char *); // at "p", delete a 'size' byte hole
-static char *text_hole_make(char *, int);      // at "p", make a 'size' byte hole
+// might reallocate text[]! use p += text_hole_make(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t text_hole_make(char *, int);  // at "p", make a 'size' byte hole
 static char *yank_delete(char *, char *, int, int);    // yank text[] into register then delete
 static void show_help(void);   // display some help info
 static void rawmode(void);     // set "raw" mode on tty
@@ -316,11 +318,11 @@ static int mysleep(int);
 static int readit(void);       // read (maybe cursor) key from stdin
 static int get_one_char(void); // read 1 char from stdin
 static int file_size(const char *);   // what is the byte size of "fn"
-#if ENABLE_FEATURE_VI_READONLY
-static int file_insert(const char *, char *, int);
-#else
-static int file_insert(const char *, char *);
+#if !ENABLE_FEATURE_VI_READONLY
+#define file_insert(fn, p, update_ro_status) file_insert(fn, p)
 #endif
+// file_insert might reallocate text[]!
+static int file_insert(const char *, char *, int);
 static int file_write(char *, char *, char *);
 #if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
 #define place_cursor(a, b, optimize) place_cursor(a, b)
@@ -370,7 +372,9 @@ static void end_cmd_q(void);        // stop saving input chars
 static void showmatching(char *);      // show the matching pair ()  []  {}
 #endif
 #if ENABLE_FEATURE_VI_YANKMARK || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) || ENABLE_FEATURE_VI_CRASHME
-static char *string_insert(char *, char *);    // insert the string at 'p'
+// might reallocate text[]! use p += string_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t string_insert(char *, const char *);  // insert the string at 'p'
 #endif
 #if ENABLE_FEATURE_VI_YANKMARK
 static char *text_yank(char *, char *, int);   // save copy of "p" into a register
@@ -420,7 +424,7 @@ int vi_main(int argc, char **argv)
                        initial_cmds[0] = xstrndup(p, MAX_INPUT_LEN);
        }
 #endif
-       while ((c = getopt(argc, argv, "hCRH" USE_FEATURE_VI_COLON("c:"))) != -1) {
+       while ((c = getopt(argc, argv, "hCRH" IF_FEATURE_VI_COLON("c:"))) != -1) {
                switch (c) {
 #if ENABLE_FEATURE_VI_CRASHME
                case 'C':
@@ -486,8 +490,7 @@ static int init_text_buffer(char *fn)
                char_insert(text, '\n');
                rc = 0;
        } else {
-               rc = file_insert(fn, text
-                       USE_FEATURE_VI_READONLY(, 1));
+               rc = file_insert(fn, text, 1);
        }
        file_modified = 0;
        last_file_modified = -1;
@@ -584,7 +587,8 @@ static void edit_file(char *fn)
                                crash_dummy();  // generate a random command
                        } else {
                                crashme = 0;
-                               dot = string_insert(text, "\n\n#####  Ran out of text to work on.  #####\n\n"); // insert the string
+                               string_insert(text, "\n\n#####  Ran out of text to work on.  #####\n\n"); // insert the string
+                               dot = text;
                                refresh(FALSE);
                        }
                }
@@ -614,7 +618,7 @@ static void edit_file(char *fn)
                // poll to see if there is input already waiting. if we are
                // not able to display output fast enough to keep up, skip
                // the display update until we catch up with input.
-               if (!chars_to_parse && mysleep(0) == 0) {
+               if (!readbuffer[0] && mysleep(0) == 0) {
                        // no input pending - so update output
                        refresh(FALSE);
                        show_status_line();
@@ -637,8 +641,8 @@ static char *get_one_address(char *p, int *addr)    // get colon addr, if present
 {
        int st;
        char *q;
-       USE_FEATURE_VI_YANKMARK(char c;)
-       USE_FEATURE_VI_SEARCH(char *pat;)
+       IF_FEATURE_VI_YANKMARK(char c;)
+       IF_FEATURE_VI_SEARCH(char *pat;)
 
        *addr = -1;                     // assume no addr
        if (*p == '.') {        // the current line
@@ -656,7 +660,7 @@ static char *get_one_address(char *p, int *addr)    // get colon addr, if present
                        c = c - 'a';
                        q = mark[(unsigned char) c];
                        if (q != NULL) {        // is mark valid
-                               *addr = count_lines(text, q);   // count lines
+                               *addr = count_lines(text, q);
                        }
                }
        }
@@ -683,7 +687,7 @@ static char *get_one_address(char *p, int *addr)    // get colon addr, if present
                sscanf(p, "%d%n", addr, &st);
                p += st;
        } else {
-               // unrecognised address - assume -1
+               // unrecognized address - assume -1
                *addr = -1;
        }
        return p;
@@ -724,6 +728,7 @@ static void setops(const char *args, const char *opname, int flg_no,
        const char *a = args + flg_no;
        int l = strlen(opname) - 1; /* opname have + ' ' */
 
+       // maybe strncmp? we had tons of erroneous strncasecmp's...
        if (strncasecmp(a, opname, l) == 0
         || strncasecmp(a, short_opname, 2) == 0
        ) {
@@ -819,7 +824,7 @@ static void colon(char *buf)
                }
        }
 #if ENABLE_FEATURE_ALLOW_EXEC
-       else if (strncmp(cmd, "!", 1) == 0) {   // run a cmd
+       else if (cmd[0] == '!') {       // run a cmd
                int retcode;
                // :!ls   run the <cmd>
                go_bottom_and_clear_to_eol();
@@ -831,19 +836,19 @@ static void colon(char *buf)
                Hit_Return();                   // let user see results
        }
 #endif
-       else if (strncmp(cmd, "=", i) == 0) {   // where is the address
+       else if (cmd[0] == '=' && !cmd[1]) {    // where is the address
                if (b < 0) {    // no addr given- use defaults
                        b = e = count_lines(text, dot);
                }
                status_line("%d", b);
-       } else if (strncasecmp(cmd, "delete", i) == 0) {        // delete lines
+       } else if (strncmp(cmd, "delete", i) == 0) {    // delete lines
                if (b < 0) {    // no addr given- use defaults
                        q = begin_line(dot);    // assume .,. for the range
                        r = end_line(dot);
                }
                dot = yank_delete(q, r, 1, YANKDEL);    // save, then delete lines
                dot_skip_over_ws();
-       } else if (strncasecmp(cmd, "edit", i) == 0) {  // Edit a file
+       } else if (strncmp(cmd, "edit", i) == 0) {      // Edit a file
                // don't edit, if the current file has been modified
                if (file_modified && !useforce) {
                        status_line_bold("No write since last change (:edit! overrides)");
@@ -877,14 +882,14 @@ static void colon(char *buf)
                // how many lines in text[]?
                li = count_lines(text, end - 1);
                status_line("\"%s\"%s"
-                       USE_FEATURE_VI_READONLY("%s")
+                       IF_FEATURE_VI_READONLY("%s")
                        " %dL, %dC", current_filename,
                        (file_size(fn) < 0 ? " [New file]" : ""),
-                       USE_FEATURE_VI_READONLY(
+                       IF_FEATURE_VI_READONLY(
                                ((readonly_mode) ? " [Readonly]" : ""),
                        )
                        li, ch);
-       } else if (strncasecmp(cmd, "file", i) == 0) {  // what File is this
+       } else if (strncmp(cmd, "file", i) == 0) {      // what File is this
                if (b != -1 || e != -1) {
                        not_implemented("No address allowed on this command");
                        goto vc1;
@@ -897,14 +902,14 @@ static void colon(char *buf)
                        // user wants file status info
                        last_status_cksum = 0;  // force status update
                }
-       } else if (strncasecmp(cmd, "features", i) == 0) {      // what features are available
+       } else if (strncmp(cmd, "features", i) == 0) {  // what features are available
                // print out values of all features
                go_bottom_and_clear_to_eol();
                cookmode();
                show_help();
                rawmode();
                Hit_Return();
-       } else if (strncasecmp(cmd, "list", i) == 0) {  // literal print line
+       } else if (strncmp(cmd, "list", i) == 0) {      // literal print line
                if (b < 0) {    // no addr given- use defaults
                        q = begin_line(dot);    // assume .,. for the range
                        r = end_line(dot);
@@ -937,8 +942,8 @@ static void colon(char *buf)
  vc2:
 #endif
                Hit_Return();
-       } else if (strncasecmp(cmd, "quit", i) == 0 // Quit
-               || strncasecmp(cmd, "next", i) == 0 // edit next file
+       } else if (strncmp(cmd, "quit", i) == 0 // Quit
+               || strncmp(cmd, "next", i) == 0 // edit next file
        ) {
                if (useforce) {
                        // force end of argv list
@@ -964,7 +969,7 @@ static void colon(char *buf)
                        goto vc1;
                }
                editing = 0;
-       } else if (strncasecmp(cmd, "read", i) == 0) {  // read file into text[]
+       } else if (strncmp(cmd, "read", i) == 0) {      // read file into text[]
                fn = args;
                if (!fn[0]) {
                        status_line_bold("No filename given");
@@ -976,23 +981,27 @@ static void colon(char *buf)
                // read after current line- unless user said ":0r foo"
                if (b != 0)
                        q = next_line(q);
-               ch = file_insert(fn, q  USE_FEATURE_VI_READONLY(, 0));
+               { // dance around potentially-reallocated text[]
+                       uintptr_t ofs = q - text;
+                       ch = file_insert(fn, q, 0);
+                       q = text + ofs;
+               }
                if (ch < 0)
                        goto vc1;       // nothing was inserted
                // how many lines in text[]?
                li = count_lines(q, q + ch - 1);
                status_line("\"%s\""
-                       USE_FEATURE_VI_READONLY("%s")
+                       IF_FEATURE_VI_READONLY("%s")
                        " %dL, %dC", fn,
-                       USE_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
+                       IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
                        li, ch);
                if (ch > 0) {
                        // if the insert is before "dot" then we need to update
                        if (q <= dot)
                                dot += ch;
-                       file_modified++;
+                       /*file_modified++; - done by file_insert */
                }
-       } else if (strncasecmp(cmd, "rewind", i) == 0) {        // rewind cmd line args
+       } else if (strncmp(cmd, "rewind", i) == 0) {    // rewind cmd line args
                if (file_modified && !useforce) {
                        status_line_bold("No write since last change (:rewind! overrides)");
                } else {
@@ -1001,7 +1010,7 @@ static void colon(char *buf)
                        editing = 0;
                }
 #if ENABLE_FEATURE_VI_SET
-       } else if (strncasecmp(cmd, "set", i) == 0) {   // set or clear features
+       } else if (strncmp(cmd, "set", i) == 0) {       // set or clear features
 #if ENABLE_FEATURE_VI_SETOPTS
                char *argp;
 #endif
@@ -1032,14 +1041,14 @@ static void colon(char *buf)
 #if ENABLE_FEATURE_VI_SETOPTS
                argp = args;
                while (*argp) {
-                       if (strncasecmp(argp, "no", 2) == 0)
+                       if (strncmp(argp, "no", 2) == 0)
                                i = 2;          // ":set noautoindent"
                        setops(argp, "autoindent ", i, "ai", VI_AUTOINDENT);
                        setops(argp, "flash ", i, "fl", VI_ERR_METHOD);
                        setops(argp, "ignorecase ", i, "ic", VI_IGNORECASE);
                        setops(argp, "showmatch ", i, "ic", VI_SHOWMATCH);
                        /* tabstopXXXX */
-                       if (strncasecmp(argp + i, "tabstop=%d ", 7) == 0) {
+                       if (strncmp(argp + i, "tabstop=%d ", 7) == 0) {
                                sscanf(strchr(argp + i, '='), "tabstop=%d" + 7, &ch);
                                if (ch > 0 && ch <= MAX_TABSTOP)
                                        tabstop = ch;
@@ -1052,7 +1061,7 @@ static void colon(char *buf)
 #endif /* FEATURE_VI_SETOPTS */
 #endif /* FEATURE_VI_SET */
 #if ENABLE_FEATURE_VI_SEARCH
-       } else if (strncasecmp(cmd, "s", 1) == 0) {     // substitute a pattern with a replacement pattern
+       } else if (cmd[0] == 's') {     // substitute a pattern with a replacement pattern
                char *ls, *F, *R;
                int gflag;
 
@@ -1063,10 +1072,12 @@ static void colon(char *buf)
                c = orig_buf[1];        // what is the delimiter
                F = orig_buf + 2;       // start of "find"
                R = strchr(F, c);       // middle delimiter
-               if (!R) goto colon_s_fail;
+               if (!R)
+                       goto colon_s_fail;
                *R++ = '\0';    // terminate "find"
                buf1 = strchr(R, c);
-               if (!buf1) goto colon_s_fail;
+               if (!buf1)
+                       goto colon_s_fail;
                *buf1++ = '\0'; // terminate "replace"
                if (*buf1 == 'g') {     // :s/foo/bar/g
                        buf1++;
@@ -1084,10 +1095,14 @@ static void colon(char *buf)
  vc4:
                        buf1 = char_search(q, F, FORWARD, LIMITED);     // search cur line only for "find"
                        if (buf1) {
+                               uintptr_t bias;
                                // we found the "find" pattern - delete it
                                text_hole_delete(buf1, buf1 + strlen(F) - 1);
                                // inset the "replace" patern
-                               string_insert(buf1, R); // insert the string
+                               bias = string_insert(buf1, R);  // insert the string
+                               buf1 += bias;
+                               ls += bias;
+                               /*q += bias; - recalculated anyway */
                                // check for "global"  :s/foo/bar/g
                                if (gflag == 1) {
                                        if ((buf1 + strlen(R)) < end_line(ls)) {
@@ -1099,12 +1114,12 @@ static void colon(char *buf)
                        q = next_line(ls);
                }
 #endif /* FEATURE_VI_SEARCH */
-       } else if (strncasecmp(cmd, "version", i) == 0) {  // show software version
+       } else if (strncmp(cmd, "version", i) == 0) {  // show software version
                status_line(BB_VER " " BB_BT);
-       } else if (strncasecmp(cmd, "write", i) == 0  // write text to file
-               || strncasecmp(cmd, "wq", i) == 0
-               || strncasecmp(cmd, "wn", i) == 0
-               || strncasecmp(cmd, "x", i) == 0
+       } else if (strncmp(cmd, "write", i) == 0  // write text to file
+               || strncmp(cmd, "wq", i) == 0
+               || strncmp(cmd, "wn", i) == 0
+               || (cmd[0] == 'x' && !cmd[1])
        ) {
                // is there a file name to write to?
                if (args[0]) {
@@ -1152,7 +1167,7 @@ static void colon(char *buf)
  vc3:;
 #endif
 #if ENABLE_FEATURE_VI_YANKMARK
-       } else if (strncasecmp(cmd, "yank", i) == 0) {  // yank lines
+       } else if (strncmp(cmd, "yank", i) == 0) {      // yank lines
                if (b < 0) {    // no addr given- use defaults
                        q = begin_line(dot);    // assume .,. for the range
                        r = end_line(dot);
@@ -1517,13 +1532,10 @@ static char *new_screen(int ro, int co)
 #if ENABLE_FEATURE_VI_SEARCH
 static int mycmp(const char *s1, const char *s2, int len)
 {
-       int i;
-
-       i = strncmp(s1, s2, len);
        if (ENABLE_FEATURE_VI_SETOPTS && ignorecase) {
-               i = strncasecmp(s1, s2, len);
+               return strncasecmp(s1, s2, len);
        }
-       return i;
+       return strncmp(s1, s2, len);
 }
 
 // search for pattern starting at p
@@ -1623,8 +1635,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
 static char *char_insert(char *p, char c) // insert the char c at 'p'
 {
        if (c == 22) {          // Is this an ctrl-V?
-               p = stupid_insert(p, '^');      // use ^ to indicate literal next
-               p--;                    // backup onto ^
+               p += stupid_insert(p, '^');     // use ^ to indicate literal next
                refresh(FALSE); // show the ^
                c = get_one_char();
                *p = c;
@@ -1651,17 +1662,23 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
                if (c == 13)
                        c = '\n';       // translate \r to \n
                sp = p;                 // remember addr of insert
-               p = stupid_insert(p, c);        // insert the char
+               p += 1 + stupid_insert(p, c);   // insert the char
 #if ENABLE_FEATURE_VI_SETOPTS
                if (showmatch && strchr(")]}", *sp) != NULL) {
                        showmatching(sp);
                }
                if (autoindent && c == '\n') {  // auto indent the new line
                        char *q;
-
-                       q = prev_line(p);       // use prev line as templet
-                       for (; isblank(*q); q++) {
-                               p = stupid_insert(p, *q);       // insert the char
+                       size_t len;
+                       q = prev_line(p);       // use prev line as template
+                       len = strspn(q, " \t"); // space or tab
+                       if (len) {
+                               uintptr_t bias;
+                               bias = text_hole_make(p, len);
+                               p += bias;
+                               q += bias;
+                               memcpy(p, q, len);
+                               p += len;
                        }
                }
 #endif
@@ -1669,12 +1686,16 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
        return p;
 }
 
-static char *stupid_insert(char *p, char c) // stupidly insert the char c at 'p'
+// might reallocate text[]! use p += stupid_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t stupid_insert(char *p, char c) // stupidly insert the char c at 'p'
 {
-       p = text_hole_make(p, 1);
+       uintptr_t bias;
+       bias = text_hole_make(p, 1);
+       p += bias;
        *p = c;
        //file_modified++; - done by text_hole_make()
-       return p + 1;
+       return bias;
 }
 
 static int find_range(char **start, char **stop, char c)
@@ -1854,26 +1875,31 @@ static void showmatching(char *p)
 }
 #endif /* FEATURE_VI_SETOPTS */
 
-//  open a hole in text[]
-static char *text_hole_make(char *p, int size) // at "p", make a 'size' byte hole
+// open a hole in text[]
+// might reallocate text[]! use p += text_hole_make(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t text_hole_make(char *p, int size)     // at "p", make a 'size' byte hole
 {
+       uintptr_t bias = 0;
+
        if (size <= 0)
-               return p;
+               return bias;
        end += size;            // adjust the new END
        if (end >= (text + text_size)) {
                char *new_text;
                text_size += end - (text + text_size) + 10240;
                new_text = xrealloc(text, text_size);
-               screenbegin = new_text + (screenbegin - text);
-               dot         = new_text + (dot         - text);
-               end         = new_text + (end         - text);
-               p           = new_text + (p           - text);
+               bias = (new_text - text);
+               screenbegin += bias;
+               dot         += bias;
+               end         += bias;
+               p           += bias;
                text = new_text;
        }
        memmove(p + size, p, end - size - p);
        memset(p, ' ', size);   // clear new hole
        file_modified++;
-       return p;
+       return bias;
 }
 
 //  close a hole in text[]
@@ -2006,42 +2032,41 @@ static void end_cmd_q(void)
 #if ENABLE_FEATURE_VI_YANKMARK \
  || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) \
  || ENABLE_FEATURE_VI_CRASHME
-static char *string_insert(char *p, char *s) // insert the string at 'p'
+// might reallocate text[]! use p += string_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t string_insert(char *p, const char *s) // insert the string at 'p'
 {
-       int cnt, i;
+       uintptr_t bias;
+       int i;
 
        i = strlen(s);
-       text_hole_make(p, i);
-       strncpy(p, s, i);
-       for (cnt = 0; *s != '\0'; s++) {
-               if (*s == '\n')
-                       cnt++;
-       }
+       bias = text_hole_make(p, i);
+       p += bias;
+       memcpy(p, s, i);
 #if ENABLE_FEATURE_VI_YANKMARK
-       status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
+       {
+               int cnt;
+               for (cnt = 0; *s != '\0'; s++) {
+                       if (*s == '\n')
+                               cnt++;
+               }
+               status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
+       }
 #endif
-       return p;
+       return bias;
 }
 #endif
 
 #if ENABLE_FEATURE_VI_YANKMARK
 static char *text_yank(char *p, char *q, int dest)     // copy text into a register
 {
-       char *t;
-       int cnt;
-
-       if (q < p) {            // they are backwards- reverse them
-               t = q;
-               q = p;
-               p = t;
+       int cnt = q - p;
+       if (cnt < 0) {          // they are backwards- reverse them
+               p = q;
+               cnt = -cnt;
        }
-       cnt = q - p + 1;
-       t = reg[dest];
-       free(t);                //  if already a yank register, free it
-       t = xmalloc(cnt + 1);   // get a new register
-       memset(t, '\0', cnt + 1);       // clear new text[]
-       strncpy(t, p, cnt);     // copy text[] into bufer
-       reg[dest] = t;
+       free(reg[dest]);        //  if already a yank register, free it
+       reg[dest] = xstrndup(p, cnt + 1);
        return p;
 }
 
@@ -2106,13 +2131,13 @@ static void rawmode(void)
        term_vi.c_cc[VMIN] = 1;
        term_vi.c_cc[VTIME] = 0;
        erase_char = term_vi.c_cc[VERASE];
-       tcsetattr(0, TCSANOW, &term_vi);
+       tcsetattr_stdin_TCSANOW(&term_vi);
 }
 
 static void cookmode(void)
 {
        fflush(stdout);
-       tcsetattr(0, TCSANOW, &term_orig);
+       tcsetattr_stdin_TCSANOW(&term_orig);
 }
 
 //----- Come here when we get a window resize signal ---------
@@ -2177,7 +2202,7 @@ static int readit(void) // read (maybe cursor) key from stdin
        int c;
 
        fflush(stdout);
-       c = read_key(STDIN_FILENO, &chars_to_parse, readbuffer);
+       c = read_key(STDIN_FILENO, readbuffer);
        if (c == -1) { // EOF/error
                go_bottom_and_clear_to_eol();
                cookmode(); // terminal to "cooked"
@@ -2273,8 +2298,8 @@ static int file_size(const char *fn) // what is the byte size of "fn"
        return cnt;
 }
 
-static int file_insert(const char *fn, char *p
-               USE_FEATURE_VI_READONLY(, int update_ro_status))
+// might reallocate text[]!
+static int file_insert(const char *fn, char *p, int update_ro_status)
 {
        int cnt = -1;
        int fd, size;
@@ -2302,7 +2327,7 @@ static int file_insert(const char *fn, char *p
                goto fi0;
        }
        size = statbuf.st_size;
-       p = text_hole_make(p, size);
+       p += text_hole_make(p, size);
        cnt = safe_read(fd, p, size);
        if (cnt < 0) {
                status_line_bold("\"%s\" %s", fn, strerror(errno));
@@ -2954,7 +2979,7 @@ static void do_cmd(int c)
                //case '`':     // `-
                //case 'u':     // u- FIXME- there is no undo
                //case 'v':     // v-
-       default:                        // unrecognised command
+       default:                        // unrecognized command
                buf[0] = c;
                buf[1] = '\0';
                if (c < ' ') {
@@ -3082,7 +3107,7 @@ static void do_cmd(int c)
        case 'P':                       // P- Put register before
        case 'p':                       // p- put register after
                p = reg[YDreg];
-               if (p == 0) {
+               if (p == NULL) {
                        status_line_bold("Nothing in register %c", what_reg());
                        break;
                }
@@ -3103,7 +3128,7 @@ static void do_cmd(int c)
                        if (c == 'p')
                                dot_right();    // move to right, can move to NL
                }
-               dot = string_insert(dot, p);    // insert the string
+               string_insert(dot, p);  // insert the string
                end_cmd_q();    // stop adding to q
                break;
        case 'U':                       // U- Undo; replace current line with original version
@@ -3111,7 +3136,7 @@ static void do_cmd(int c)
                        p = begin_line(dot);
                        q = end_line(dot);
                        p = text_hole_delete(p, q);     // delete cur line
-                       p = string_insert(p, reg[Ureg]);        // insert orig line
+                       p += string_insert(p, reg[Ureg]);       // insert orig line
                        dot = p;
                        dot_skip_over_ws();
                }
@@ -3299,18 +3324,18 @@ static void do_cmd(int c)
                cnt = strlen(p);
                if (cnt <= 0)
                        break;
-               if (strncasecmp(p, "quit", cnt) == 0
-                || strncasecmp(p, "q!", cnt) == 0   // delete lines
+               if (strncmp(p, "quit", cnt) == 0
+                || strncmp(p, "q!", cnt) == 0   // delete lines
                ) {
                        if (file_modified && p[1] != '!') {
                                status_line_bold("No write since last change (:quit! overrides)");
                        } else {
                                editing = 0;
                        }
-               } else if (strncasecmp(p, "write", cnt) == 0
-                       || strncasecmp(p, "wq", cnt) == 0
-                       || strncasecmp(p, "wn", cnt) == 0
-                       || strncasecmp(p, "x", cnt) == 0
+               } else if (strncmp(p, "write", cnt) == 0
+                       || strncmp(p, "wq", cnt) == 0
+                       || strncmp(p, "wn", cnt) == 0
+                       || (p[0] == 'x' && !p[1])
                ) {
                        cnt = file_write(current_filename, text, end - 1);
                        if (cnt < 0) {
@@ -3326,12 +3351,12 @@ static void do_cmd(int c)
                                        editing = 0;
                                }
                        }
-               } else if (strncasecmp(p, "file", cnt) == 0) {
+               } else if (strncmp(p, "file", cnt) == 0) {
                        last_status_cksum = 0;  // force status update
                } else if (sscanf(p, "%d", &j) > 0) {
                        dot = find_line(j);             // go to line # j
                        dot_skip_over_ws();
-               } else {                // unrecognised cmd
+               } else {                // unrecognized cmd
                        not_implemented(p);
                }
 #endif /* !FEATURE_VI_COLON */
@@ -3822,10 +3847,11 @@ static void crash_dummy()
        cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL";
 
        // is there already a command running?
-       if (chars_to_parse > 0)
+       if (readbuffer[0] > 0)
                goto cd1;
  cd0:
-       startrbi = rbi = 0;
+       readbuffer[0] = 'X';
+       startrbi = rbi = 1;
        sleeptime = 0;          // how long to pause between commands
        memset(readbuffer, '\0', sizeof(readbuffer));
        // generate a command by percentages
@@ -3899,7 +3925,7 @@ static void crash_dummy()
                }
                strcat(readbuffer, "\033");
        }
-       chars_to_parse = strlen(readbuffer);
+       readbuffer[0] = strlen(readbuffer + 1);
  cd1:
        totalcmds++;
        if (sleeptime > 0)