BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / ex / ex_vops2.c
index 23554f3..55eb719 100644 (file)
@@ -1,4 +1,13 @@
-/* Copyright (c) 1979 Regents of the University of California */
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char *sccsid = "@(#)ex_vops2.c  6.10 (Berkeley) 1/2/88";
+#endif not lint
+
 #include "ex.h"
 #include "ex_tty.h"
 #include "ex_vis.h"
 #include "ex.h"
 #include "ex_tty.h"
 #include "ex_vis.h"
@@ -8,8 +17,8 @@
  * and mostly, insert mode (and a subroutine
  * to read an input line, including in the echo area.)
  */
  * and mostly, insert mode (and a subroutine
  * to read an input line, including in the echo area.)
  */
-char   *vUA1, *vUA2;
-char   *vUD1, *vUD2;
+extern char    *vUA1, *vUA2;           /* mjm: extern; also in ex_vops.c */
+extern char    *vUD1, *vUD2;           /* mjm: extern; also in ex_vops.c */
 
 /*
  * Obleeperate characters in hardcopy
 
 /*
  * Obleeperate characters in hardcopy
@@ -22,7 +31,7 @@ bleep(i, cp)
 
        i -= column(cp);
        do
 
        i -= column(cp);
        do
-               putchar('\\' | QUOTE);
+               ex_putchar('\\' | QUOTE);
        while (--i >= 0);
        rubble = 1;
 }
        while (--i >= 0);
        rubble = 1;
 }
@@ -37,7 +46,8 @@ vdcMID()
 
        squish();
        setLAST();
 
        squish();
        setLAST();
-       vundkind = VCHNG, CP(vutmp, linebuf);
+       if (FIXUNDO)
+               vundkind = VCHNG, CP(vutmp, linebuf);
        if (wcursor < cursor)
                cp = wcursor, wcursor = cursor, cursor = cp;
        vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor;
        if (wcursor < cursor)
                cp = wcursor, wcursor = cursor, cursor = cp;
        vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor;
@@ -65,7 +75,7 @@ takeout(BUF)
                wcursor = cursor;
                cursor = cp;
        }
                wcursor = cursor;
                cursor = cp;
        }
-       setBUF(BUF);
+       ex_setBUF(BUF);
        if ((BUF[0] & (QUOTE|TRIM)) == OVERBUF)
                beep();
 }
        if ((BUF[0] & (QUOTE|TRIM)) == OVERBUF)
                beep();
 }
@@ -102,14 +112,17 @@ bool      gobbled;
 char   *ogcursor;
 
 vappend(ch, cnt, indent)
 char   *ogcursor;
 
 vappend(ch, cnt, indent)
-       char ch;
+       int ch;         /* mjm: char --> int */
        int cnt, indent;
 {
        register int i;
        register char *gcursor;
        bool escape;
        int cnt, indent;
 {
        register int i;
        register char *gcursor;
        bool escape;
-       int repcnt;
+       int repcnt, savedoomed;
        short oldhold = hold;
        short oldhold = hold;
+#ifdef SIGWINCH
+       int oldmask;
+#endif
 
        /*
         * Before a move in hardopen when the line is dirty
 
        /*
         * Before a move in hardopen when the line is dirty
@@ -199,6 +212,9 @@ vappend(ch, cnt, indent)
         */
        gobblebl = 0;
 
         */
        gobblebl = 0;
 
+#ifdef SIGWINCH
+       oldmask = sigblock(sigmask(SIGWINCH));
+#endif
        /*
         * Text gathering loop.
         * New text goes into genbuf starting at gcursor.
        /*
         * Text gathering loop.
         * New text goes into genbuf starting at gcursor.
@@ -210,7 +226,7 @@ vappend(ch, cnt, indent)
                if (ch == 'r' && repcnt == 0)
                        escape = 0;
                else {
                if (ch == 'r' && repcnt == 0)
                        escape = 0;
                else {
-                       gcursor = vgetline(repcnt, gcursor, &escape);
+                       gcursor = vgetline(repcnt, gcursor, &escape, ch);
 
                        /*
                         * After an append, stick information
 
                        /*
                         * After an append, stick information
@@ -258,7 +274,7 @@ vappend(ch, cnt, indent)
 
                                Outchar = vinschar;
                                hold |= HOLDQIK;
 
                                Outchar = vinschar;
                                hold |= HOLDQIK;
-                               printf("%s", genbuf);
+                               ex_printf("%s", genbuf);
                                hold = oldhold;
                                Outchar = vputchar;
                        }
                                hold = oldhold;
                                Outchar = vputchar;
                        }
@@ -275,6 +291,7 @@ vappend(ch, cnt, indent)
                 */
                if (state != HARDOPEN) {
                        DEPTH(vcline) = 0;
                 */
                if (state != HARDOPEN) {
                        DEPTH(vcline) = 0;
+                       savedoomed = doomed;
                        if (doomed > 0) {
                                register int cind = cindent();
 
                        if (doomed > 0) {
                                register int cind = cindent();
 
@@ -282,6 +299,12 @@ vappend(ch, cnt, indent)
                                doomed = 0;
                        }
                        i = vreopen(LINE(vcline), lineDOT(), vcline);
                                doomed = 0;
                        }
                        i = vreopen(LINE(vcline), lineDOT(), vcline);
+#ifdef TRACE
+                       if (trace)
+                               fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed);
+#endif
+                       if (ch == 'R')
+                               doomed = savedoomed;
                }
 
                /*
                }
 
                /*
@@ -326,7 +349,7 @@ vappend(ch, cnt, indent)
                 * out dot before it changes so that undo will work
                 * correctly later.
                 */
                 * out dot before it changes so that undo will work
                 * correctly later.
                 */
-               if (vundkind == VCHNG) {
+               if (FIXUNDO && vundkind == VCHNG) {
                        vremote(1, yank, 0);
                        undap1--;
                }
                        vremote(1, yank, 0);
                        undap1--;
                }
@@ -369,6 +392,9 @@ vappend(ch, cnt, indent)
        doomed = 0;
        wcursor = cursor;
        vmove();
        doomed = 0;
        wcursor = cursor;
        vmove();
+#ifdef SIGWINCH
+       (void)sigsetmask(oldmask);
+#endif
 }
 
 /*
 }
 
 /*
@@ -394,18 +420,21 @@ back1()
  * are careful about the way we do this so that it is
  * repeatable.  (I.e. so that your kill doesn't happen,
  * when you repeat an insert if it was escaped with \ the
  * are careful about the way we do this so that it is
  * repeatable.  (I.e. so that your kill doesn't happen,
  * when you repeat an insert if it was escaped with \ the
- * first time you did it.
+ * first time you did it.  commch is the command character
+ * involved, including the prompt for readline.
  */
 char *
  */
 char *
-vgetline(cnt, gcursor, aescaped)
+vgetline(cnt, gcursor, aescaped, commch)
        int cnt;
        register char *gcursor;
        bool *aescaped;
        int cnt;
        register char *gcursor;
        bool *aescaped;
+       char commch;
 {
        register int c, ch;
        register char *cp;
 {
        register int c, ch;
        register char *cp;
-       int x, y, iwhite;
+       int x, y, iwhite, backsl=0;
        char *iglobp;
        char *iglobp;
+       char cstr[2];
        int (*OO)() = Outchar;
 
        /*
        int (*OO)() = Outchar;
 
        /*
@@ -434,6 +463,7 @@ vgetline(cnt, gcursor, aescaped)
                vprepins();
        }
        for (;;) {
                vprepins();
        }
        for (;;) {
+               backsl = 0;
                if (gobblebl)
                        gobblebl--;
                if (cnt != 0) {
                if (gobblebl)
                        gobblebl--;
                if (cnt != 0) {
@@ -441,10 +471,19 @@ vgetline(cnt, gcursor, aescaped)
                        if (cnt == 0)
                                goto vadone;
                }
                        if (cnt == 0)
                                goto vadone;
                }
-               ch = c = getkey() & (QUOTE|TRIM);
-               if (value(MAPINPUT))
-                       while ((ch = map(c, arrows)) != c)
+               c = getkey();
+               if (c != ATTN)
+                       c &= (QUOTE|TRIM);
+               ch = c;
+               maphopcnt = 0;
+               if (vglobp == 0 && Peek_key == 0 && commch != 'r')
+                       while ((ch = map(c, immacs)) != c) {
                                c = ch;
                                c = ch;
+                               if (!value(REMAP))
+                                       break;
+                               if (++maphopcnt > 256)
+                                       error("Infinite macro loop");
+                       }
                if (!iglobp) {
 
                        /*
                if (!iglobp) {
 
                        /*
@@ -453,10 +492,17 @@ vgetline(cnt, gcursor, aescaped)
                         * from untyped input when we started.
                         * Map users erase to ^H, kill to -1 for switch.
                         */
                         * from untyped input when we started.
                         * Map users erase to ^H, kill to -1 for switch.
                         */
+#ifndef USG3TTY
                        if (c == tty.sg_erase)
                        if (c == tty.sg_erase)
-                               c = CTRL(h);
+                               c = CTRL('h');
                        else if (c == tty.sg_kill)
                                c = -1;
                        else if (c == tty.sg_kill)
                                c = -1;
+#else
+                       if (c == tty.c_cc[VERASE])
+                               c = CTRL('h');
+                       else if (c == tty.c_cc[VKILL])
+                               c = -1;
+#endif
                        switch (c) {
 
                        /*
                        switch (c) {
 
                        /*
@@ -481,7 +527,7 @@ vgetline(cnt, gcursor, aescaped)
                         *              This is hard because stuff has
                         *              already been saved for repeat.
                         */
                         *              This is hard because stuff has
                         *              already been saved for repeat.
                         */
-                       case CTRL(h):
+                       case CTRL('h'):
 bakchar:
                                cp = gcursor - 1;
                                if (cp < ogcursor) {
 bakchar:
                                cp = gcursor - 1;
                                if (cp < ogcursor) {
@@ -502,7 +548,7 @@ bakchar:
                        /*
                         * ^W           Back up a white/non-white word.
                         */
                        /*
                         * ^W           Back up a white/non-white word.
                         */
-                       case CTRL(w):
+                       case CTRL('w'):
                                wdkind = 1;
                                for (cp = gcursor; cp > ogcursor && isspace(cp[-1]); cp--)
                                        continue;
                                wdkind = 1;
                                for (cp = gcursor; cp > ogcursor && isspace(cp[-1]); cp--)
                                        continue;
@@ -537,17 +583,24 @@ vbackup:
                         */
                        case '\\':
                                x = destcol, y = destline;
                         */
                        case '\\':
                                x = destcol, y = destline;
-                               putchar('\\');
+                               ex_putchar('\\');
                                vcsync();
                                c = getkey();
                                vcsync();
                                c = getkey();
-                               if (c == tty.sg_erase || c == tty.sg_kill) {
+#ifndef USG3TTY
+                               if (c == tty.sg_erase || c == tty.sg_kill)
+#else
+                               if (c == tty.c_cc[VERASE]
+                                   || c == tty.c_cc[VKILL])
+#endif
+                               {
                                        vgoto(y, x);
                                        if (doomed >= 0)
                                                doomed++;
                                        goto def;
                                }
                                ungetkey(c), c = '\\';
                                        vgoto(y, x);
                                        if (doomed >= 0)
                                                doomed++;
                                        goto def;
                                }
                                ungetkey(c), c = '\\';
-                               goto noput;
+                               backsl = 1;
+                               break;
 
                        /*
                         * ^Q           Super quote following character
 
                        /*
                         * ^Q           Super quote following character
@@ -557,10 +610,10 @@ vbackup:
                         *
                         * ^V           Synonym for ^Q
                         */
                         *
                         * ^V           Synonym for ^Q
                         */
-                       case CTRL(q):
-                       case CTRL(v):
+                       case CTRL('q'):
+                       case CTRL('v'):
                                x = destcol, y = destline;
                                x = destcol, y = destline;
-                               putchar('^');
+                               ex_putchar('^');
                                vgoto(y, x);
                                c = getkey();
 #ifdef TIOCSETC
                                vgoto(y, x);
                                c = getkey();
 #ifdef TIOCSETC
@@ -580,16 +633,89 @@ vbackup:
                 * If we get a blank not in the echo area
                 * consider splitting the window in the wrapmargin.
                 */
                 * If we get a blank not in the echo area
                 * consider splitting the window in the wrapmargin.
                 */
-               if (c == ' ' && !splitw) {
-                       if (gobblebl) {
+               if (c != NL && !splitw) {
+                       if (c == ' ' && gobblebl) {
                                gobbled = 1;
                                continue;
                        }
                                gobbled = 1;
                                continue;
                        }
-                       if (value(WRAPMARGIN) && outcol >= OCOLUMNS - value(WRAPMARGIN)) {
-                               c = NL;
-                               gobblebl = 2;
+                       if (value(WRAPMARGIN) &&
+                               (outcol >= OCOLUMNS - value(WRAPMARGIN) ||
+                                backsl && outcol==0) &&
+                               commch != 'r') {
+                               /*
+                                * At end of word and hit wrapmargin.
+                                * Move the word to next line and keep going.
+                                */
+                               wdkind = 1;
+                               *gcursor++ = c;
+                               if (backsl)
+                                       *gcursor++ = getkey();
+                               *gcursor = 0;
+                               /*
+                                * Find end of previous word if we are past it.
+                                */
+                               for (cp=gcursor; cp>ogcursor && isspace(cp[-1]); cp--)
+                                       ;
+                               if (outcol+(backsl?OCOLUMNS:0) - (gcursor-cp) >= OCOLUMNS - value(WRAPMARGIN)) {
+                                       /*
+                                        * Find beginning of previous word.
+                                        */
+                                       for (; cp>ogcursor && !isspace(cp[-1]); cp--)
+                                               ;
+                                       if (cp <= ogcursor) {
+                                               /*
+                                                * There is a single word that
+                                                * is too long to fit.  Just
+                                                * let it pass, but beep for
+                                                * each new letter to warn
+                                                * the luser.
+                                                */
+                                               c = *--gcursor;
+                                               *gcursor = 0;
+                                               beep();
+                                               goto dontbreak;
+                                       }
+                                       /*
+                                        * Save it for next line.
+                                        */
+                                       macpush(cp, 0);
+                                       cp--;
+                               }
+                               macpush("\n", 0);
+                               /*
+                                * Erase white space before the word.
+                                */
+                               while (cp > ogcursor && isspace(cp[-1]))
+                                       cp--;   /* skip blank */
+                               gobblebl = 3;
+                               goto vbackup;
+                       }
+               dontbreak:;
+               }
+
+               /*
+                * Word abbreviation mode.
+                */
+               cstr[0] = c;
+               if (anyabbrs && gcursor > ogcursor && !wordch(cstr) && wordch(gcursor-1)) {
+                       int wdtype, abno;
+
+                       cstr[1] = 0;
+                       wdkind = 1;
+                       cp = gcursor - 1;
+                       for (wdtype = wordch(cp - 1);
+                           cp > ogcursor && wordof(wdtype, cp - 1); cp--)
+                               ;
+                       *gcursor = 0;
+                       for (abno=0; abbrevs[abno].mapto; abno++) {
+                               if (eq(cp, abbrevs[abno].cap)) {
+                                       macpush(cstr, 0);
+                                       macpush(abbrevs[abno].mapto, 1);
+                                       goto vbackup;
+                               }
                        }
                }
                        }
                }
+
                switch (c) {
 
                /*
                switch (c) {
 
                /*
@@ -623,8 +749,8 @@ vbackup:
                 *              Unless in repeat where this means these
                 *              were superquoted in.
                 */
                 *              Unless in repeat where this means these
                 *              were superquoted in.
                 */
-               case CTRL(d):
-               case CTRL(t):
+               case CTRL('d'):
+               case CTRL('t'):
                        if (vglobp)
                                goto def;
                        /* fall into ... */
                        if (vglobp)
                                goto def;
                        /* fall into ... */
@@ -632,11 +758,11 @@ vbackup:
                /*
                 * ^D|QUOTE     Is a backtab (in a repeated command).
                 */
                /*
                 * ^D|QUOTE     Is a backtab (in a repeated command).
                 */
-               case CTRL(d) | QUOTE:
+               case CTRL('d') | QUOTE:
                        *gcursor = 0;
                        cp = vpastwh(genbuf);
                        c = whitecnt(genbuf);
                        *gcursor = 0;
                        cp = vpastwh(genbuf);
                        c = whitecnt(genbuf);
-                       if (ch == CTRL(t)) {
+                       if (ch == CTRL('t')) {
                                /*
                                 * ^t just generates new indent replacing
                                 * current white space rounded up to soft
                                /*
                                 * ^t just generates new indent replacing
                                 * current white space rounded up to soft
@@ -679,7 +805,7 @@ vbackup:
                                        CDCNT = 1;
                                        endim();
                                        back1();
                                        CDCNT = 1;
                                        endim();
                                        back1();
-                                       vputc(' ');
+                                       vputchar(' ');
                                        goto vbackup;
                                }
                        if (vglobp && vglobp - iglobp >= 2 &&
                                        goto vbackup;
                                }
                        if (vglobp && vglobp - iglobp >= 2 &&
@@ -697,23 +823,24 @@ vbackup:
                                continue;
                        }
 def:
                                continue;
                        }
 def:
-                       putchar(c);
-noput:
+                       if (!backsl) {
+                               ex_putchar(c);
+                               flush();
+                       }
                        if (gcursor > &genbuf[LBSIZE - 2])
                                error("Line too long");
                        *gcursor++ = c & TRIM;
                        vcsync();
                        if (gcursor > &genbuf[LBSIZE - 2])
                                error("Line too long");
                        *gcursor++ = c & TRIM;
                        vcsync();
-#ifdef LISPCODE
                        if (value(SHOWMATCH) && !iglobp)
                                if (c == ')' || c == '}')
                                        lsmatch(gcursor);
                        if (value(SHOWMATCH) && !iglobp)
                                if (c == ')' || c == '}')
                                        lsmatch(gcursor);
-#endif
                        continue;
                }
        }
 vadone:
        *gcursor = 0;
                        continue;
                }
        }
 vadone:
        *gcursor = 0;
-       Outchar = OO;
+       if (Outchar != termchar)
+               Outchar = OO;
        endim();
        return (gcursor);
 }
        endim();
        return (gcursor);
 }
@@ -752,7 +879,7 @@ vgetsplit()
 /*
  * Vmaxrep determines the maximum repetitition factor
  * allowed that will yield total line length less than
 /*
  * Vmaxrep determines the maximum repetitition factor
  * allowed that will yield total line length less than
- * 512 characters and also does hacks for the R command.
+ * LBSIZE characters and also does hacks for the R command.
  */
 vmaxrep(ch, cnt)
        char ch;
  */
 vmaxrep(ch, cnt)
        char ch;