Patch from Mike Castle to cleanup some modutils issues, in
[oweals/busybox.git] / editors / vi.c
index 8e9ecc92597a08f43740def8e501a3ac3b66661e..b1d7034d4aead72328adc2bd07ddf5e6eb8bee41 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 static const char vi_Version[] =
-       "$Id: vi.c,v 1.26 2002/12/02 21:18:08 bug1 Exp $";
+       "$Id: vi.c,v 1.37 2004/07/20 06:44:46 andersen Exp $";
 
 /*
  * To compile for standalone use:
@@ -45,7 +45,7 @@ static const char vi_Version[] =
  *     An "ex" line oriented mode- maybe using "cmdedit"
  */
 
-//----  Feature --------------  Bytes to immplement
+//----  Feature --------------  Bytes to implement
 #ifdef STANDALONE
 #define vi_main                        main
 #define CONFIG_FEATURE_VI_COLON        // 4288
@@ -197,9 +197,6 @@ static jmp_buf restart;             // catch_sig()
 #if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME)
 static int my_pid;
 #endif
-#ifdef CONFIG_FEATURE_VI_WIN_RESIZE
-static struct winsize winsize; // remember the window size
-#endif                                                 /* CONFIG_FEATURE_VI_WIN_RESIZE */
 #ifdef CONFIG_FEATURE_VI_DOT_CMD
 static int adding2q;           // are we currently adding user input to q
 static Byte *last_modifying_cmd;       // last modifying cmd for "."
@@ -378,6 +375,7 @@ extern int vi_main(int argc, char **argv)
 #ifdef CONFIG_FEATURE_VI_READONLY
                case 'R':               // Read-only flag
                        readonly = TRUE;
+                       vi_readonly = TRUE;
                        break;
 #endif                                                 /* CONFIG_FEATURE_VI_READONLY */
                        //case 'r':     // recover flag-  ignore- we don't use tmp file
@@ -403,7 +401,7 @@ extern int vi_main(int argc, char **argv)
                for (; optind < argc; optind++) {
                        editing = 1;    // 0=exit, 1=one file, 2+ =many files
                        free(cfn);
-                       cfn = (Byte *) xstrdup(argv[optind]);
+                       cfn = (Byte *) bb_xstrdup(argv[optind]);
                        edit_file(cfn);
                }
        }
@@ -412,6 +410,14 @@ extern int vi_main(int argc, char **argv)
        return (0);
 }
 
+#ifdef CONFIG_FEATURE_VI_WIN_RESIZE
+//----- See what the window size currently is --------------------
+static inline void window_size_get(int fd)
+{
+       get_terminal_width_height(fd, &columns, &rows);
+}
+#endif                                                 /* CONFIG_FEATURE_VI_WIN_RESIZE */
+
 static void edit_file(Byte * fn)
 {
        Byte c;
@@ -597,7 +603,7 @@ static Byte *get_one_address(Byte * p, int *addr)   // get colon addr, if present
                        *q++ = *p;
                        *q = '\0';
                }
-               pat = (Byte *) xstrdup((char *) buf);   // save copy of pattern
+               pat = (Byte *) bb_xstrdup((char *) buf);        // save copy of pattern
                if (*p == '/')
                        p++;
                q = char_search(dot, pat, FORWARD, FULL);
@@ -635,7 +641,7 @@ static Byte *get_address(Byte *p, int *b, int *e)   // get two colon addrs, if pre
        p = get_one_address(p, b);
        while (isblnk(*p))
                p++;
-       if (*p == ',') {                        // is there a address seperator
+       if (*p == ',') {                        // is there a address separator
                p++;
                while (isblnk(*p))
                        p++;
@@ -687,12 +693,13 @@ static void colon(Byte * buf)
        // :s/find/replace/ // substitute pattern "find" with "replace"
        // :!<cmd>      // run <cmd> then return
        //
+       forced = useforce = FALSE;
+
        if (strlen((char *) buf) <= 0)
                goto vc1;
        if (*buf == ':')
                buf++;                  // move past the ':'
 
-       forced = useforce = FALSE;
        li = st = ch = i = 0;
        b = e = -1;
        q = text;                       // assume 1,$ for the range
@@ -811,7 +818,7 @@ static void colon(Byte * buf)
 
                // There is a read-able regular file
                // make this the current file
-               q = (Byte *) xstrdup((char *) fn);      // save the cfn
+               q = (Byte *) bb_xstrdup((char *) fn);   // save the cfn
                free(cfn);              // free the old name
                cfn = q;                        // remember new cfn
 
@@ -862,7 +869,7 @@ static void colon(Byte * buf)
                if (strlen((char *) args) > 0) {
                        // user wants a new filename
                        free(cfn);
-                       cfn = (Byte *) xstrdup((char *) args);
+                       cfn = (Byte *) bb_xstrdup((char *) args);
                } else {
                        // user wants file status info
                        edit_status();
@@ -1446,7 +1453,7 @@ static Byte *new_screen(int ro, int co)
        screen = (Byte *) xmalloc(screensize);
        // initialize the new screen. assume this will be a empty file.
        screen_erase();
-       //   non-existant text[] lines start with a tilde (~).
+       //   non-existent text[] lines start with a tilde (~).
        for (li = 1; li < ro - 1; li++) {
                screen[(li * co) + 0] = '~';
        }
@@ -1664,8 +1671,13 @@ static Byte find_range(Byte ** start, Byte ** stop, Byte c)
                q = dot;
        } else if (strchr("wW", c)) {
                do_cmd(c);              // execute movement cmd
-               if (dot > text)
-                       dot--;          // move back off of next word
+               // if we are at the next word's first char
+               // step back one char
+               // but check the possibilities when it is true
+               if (dot > text && ((isspace(dot[-1]) && !isspace(dot[0]))
+                               || (ispunct(dot[-1]) && !ispunct(dot[0]))
+                               || (isalnum(dot[-1]) && !isalnum(dot[0]))))
+                       dot--;          // move back off of next word
                if (dot > text && *dot == '\n')
                        dot--;          // stay off NL
                q = dot;
@@ -2108,10 +2120,8 @@ static void rawmode(void)
        term_vi.c_lflag &= (~ICANON & ~ECHO);   // leave ISIG ON- allow intr's
        term_vi.c_iflag &= (~IXON & ~ICRNL);
        term_vi.c_oflag &= (~ONLCR);
-#ifndef linux
        term_vi.c_cc[VMIN] = 1;
        term_vi.c_cc[VTIME] = 0;
-#endif
        erase_char = term_vi.c_cc[VERASE];
        tcsetattr(0, TCSANOW, &term_vi);
 }
@@ -2122,29 +2132,6 @@ static void cookmode(void)
        tcsetattr(0, TCSANOW, &term_orig);
 }
 
-#ifdef CONFIG_FEATURE_VI_WIN_RESIZE
-//----- See what the window size currently is --------------------
-static void window_size_get(int sig)
-{
-       int i;
-
-       i = ioctl(0, TIOCGWINSZ, &winsize);
-       if (i != 0) {
-               // force 24x80
-               winsize.ws_row = 24;
-               winsize.ws_col = 80;
-       }
-       if (winsize.ws_row <= 1) {
-               winsize.ws_row = 24;
-       }
-       if (winsize.ws_col <= 1) {
-               winsize.ws_col = 80;
-       }
-       rows = (int) winsize.ws_row;
-       columns = (int) winsize.ws_col;
-}
-#endif                                                 /* CONFIG_FEATURE_VI_WIN_RESIZE */
-
 //----- Come here when we get a window resize signal ---------
 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
 static void winch_sig(int sig)
@@ -2432,7 +2419,7 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line"
        }
        refresh(FALSE);
        free(obufp);
-       obufp = (Byte *) xstrdup((char *) buf);
+       obufp = (Byte *) bb_xstrdup((char *) buf);
        return (obufp);
 }
 
@@ -2542,7 +2529,7 @@ static int file_write(Byte * fn, Byte * first, Byte * last)
 
 //----- Terminal Drawing ---------------------------------------
 // The terminal is made up of 'rows' line of 'columns' columns.
-// classicly this would be 24 x 80.
+// classically this would be 24 x 80.
 //  screen coordinates
 //  0,0     ...     0,79
 //  1,0     ...     1,79
@@ -2563,14 +2550,14 @@ static void place_cursor(int row, int col, int opti)
        // char cm3[BUFSIZ];
        int Rrow= last_row;
 #endif                                                 /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
-       
+
        memset(cm1, '\0', BUFSIZ - 1);  // clear the buffer
 
        if (row < 0) row = 0;
        if (row >= rows) row = rows - 1;
        if (col < 0) col = 0;
        if (col >= columns) col = columns - 1;
-       
+
        //----- 1.  Try the standard terminal ESC sequence
        sprintf((char *) cm1, CMrc, row + 1, col + 1);
        cm= cm1;
@@ -2580,7 +2567,7 @@ static void place_cursor(int row, int col, int opti)
        //----- find the minimum # of chars to move cursor -------------
        //----- 2.  Try moving with discreet chars (Newline, [back]space, ...)
        memset(cm2, '\0', BUFSIZ - 1);  // clear the buffer
-       
+
        // move to the correct row
        while (row < Rrow) {
                // the cursor has to move up
@@ -2592,7 +2579,7 @@ static void place_cursor(int row, int col, int opti)
                strcat(cm2, CMdown);
                Rrow++;
        }
-       
+
        // now move to the correct column
        strcat(cm2, "\r");                      // start at col 0
        // just send out orignal source char to get to correct place
@@ -2763,7 +2750,7 @@ static void format_line(Byte *dest, Byte *src, int li)
 {
        int co;
        Byte c;
-       
+
        for (co= 0; co < MAX_SCR_COLS; co++) {
                c= ' ';         // assume blank
                if (li > 0 && co == 0) {
@@ -2914,7 +2901,7 @@ static void refresh(int full_screen)
 #else
        place_cursor(crow, ccol, FALSE);
 #endif                                                 /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
-       
+
        if (offset != old_offset)
                old_offset = offset;
 }
@@ -3012,29 +2999,29 @@ key_cmd_mode:
                //case 0x1d:    // gs
                //case 0x1e:    // rs
                //case 0x1f:    // us
-               //case '!':     // !- 
-               //case '#':     // #- 
-               //case '&':     // &- 
-               //case '(':     // (- 
-               //case ')':     // )- 
-               //case '*':     // *- 
-               //case ',':     // ,- 
-               //case '=':     // =- 
-               //case '@':     // @- 
-               //case 'F':     // F- 
-               //case 'K':     // K- 
-               //case 'Q':     // Q- 
-               //case 'S':     // S- 
-               //case 'T':     // T- 
-               //case 'V':     // V- 
-               //case '[':     // [- 
-               //case '\\':    // \- 
-               //case ']':     // ]- 
-               //case '_':     // _- 
-               //case '`':     // `- 
-               //case 'g':     // g- 
+               //case '!':     // !-
+               //case '#':     // #-
+               //case '&':     // &-
+               //case '(':     // (-
+               //case ')':     // )-
+               //case '*':     // *-
+               //case ',':     // ,-
+               //case '=':     // =-
+               //case '@':     // @-
+               //case 'F':     // F-
+               //case 'K':     // K-
+               //case 'Q':     // Q-
+               //case 'S':     // S-
+               //case 'T':     // T-
+               //case 'V':     // V-
+               //case '[':     // [-
+               //case '\\':    // \-
+               //case ']':     // ]-
+               //case '_':     // _-
+               //case '`':     // `-
+               //case 'g':     // g-
                //case 'u':     // u- FIXME- there is no undo
-               //case 'v':     // v- 
+               //case 'v':     // v-
        default:                        // unrecognised command
                buf[0] = c;
                buf[1] = '\0';
@@ -3215,7 +3202,7 @@ key_cmd_mode:
                if (cmdcnt-- > 1) {
                        do_cmd(c);
                }                               // repeat cnt
-               dot = end_line(dot + 1);
+               dot = end_line(dot);
                break;
        case '%':                       // %- find matching char of pair () [] {}
                for (q = dot; q < end && *q != '\n'; q++) {
@@ -3236,7 +3223,7 @@ key_cmd_mode:
        case 'f':                       // f- forward to a user specified char
                last_forward_char = get_one_char();     // get the search char
                //
-               // dont seperate these two commands. 'f' depends on ';'
+               // dont separate these two commands. 'f' depends on ';'
                //
                //**** fall thru to ... 'i'
        case ';':                       // ;- look at rest of line for last forward char
@@ -3263,7 +3250,7 @@ key_cmd_mode:
                // Stuff the last_modifying_cmd back into stdin
                // and let it be re-executed.
                if (last_modifying_cmd != 0) {
-                       ioq = ioq_start = (Byte *) xstrdup((char *) last_modifying_cmd);
+                       ioq = ioq_start = (Byte *) bb_xstrdup((char *) last_modifying_cmd);
                }
                break;
 #endif                                                 /* CONFIG_FEATURE_VI_DOT_CMD */
@@ -3278,7 +3265,7 @@ key_cmd_mode:
                if (strlen((char *) q) > 1) {   // new pat- save it and find
                        // there is a new pat
                        free(last_search_pattern);
-                       last_search_pattern = (Byte *) xstrdup((char *) q);
+                       last_search_pattern = (Byte *) bb_xstrdup((char *) q);
                        goto dc3;       // now find the pattern
                }
                // user changed mind and erased the "/"-  do nothing
@@ -3353,15 +3340,15 @@ key_cmd_mode:
                break;
 #endif                                                 /* CONFIG_FEATURE_VI_SEARCH */
        case '0':                       // 0- goto begining of line
-       case '1':                       // 1- 
-       case '2':                       // 2- 
-       case '3':                       // 3- 
-       case '4':                       // 4- 
-       case '5':                       // 5- 
-       case '6':                       // 6- 
-       case '7':                       // 7- 
-       case '8':                       // 8- 
-       case '9':                       // 9- 
+       case '1':                       // 1-
+       case '2':                       // 2-
+       case '3':                       // 3-
+       case '4':                       // 4-
+       case '5':                       // 5-
+       case '6':                       // 6-
+       case '7':                       // 7-
+       case '8':                       // 8-
+       case '9':                       // 9-
                if (c == '0' && cmdcnt < 1) {
                        dot_begin();    // this was a standalone zero
                } else {
@@ -3951,7 +3938,7 @@ static void crash_test()
 {
        static time_t oldtim;
        time_t tim;
-       char d[2], buf[BUFSIZ], msg[BUFSIZ];
+       char d[2], msg[BUFSIZ];
 
        msg[0] = '\0';
        if (end < text) {
@@ -3975,7 +3962,7 @@ static void crash_test()
 
        if (strlen(msg) > 0) {
                alarm(0);
-               printf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
+               printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
                        totalcmds, last_input_char, msg, SOs, SOn);
                fflush(stdout);
                while (read(0, d, 1) > 0) {