BSD 4 release
[unix-history] / usr / src / cmd / ex / ex_vops2.c
index 86334bc..4d1cc93 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (c) 1979 Regents of the University of California */
+/* Copyright (c) 1980 Regents of the University of California */
+static char *sccsid = "@(#)ex_vops2.c  6.2 10/23/80";
 #include "ex.h"
 #include "ex_tty.h"
 #include "ex_vis.h"
 #include "ex.h"
 #include "ex_tty.h"
 #include "ex_vis.h"
@@ -37,7 +38,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;
@@ -108,7 +110,7 @@ vappend(ch, cnt, indent)
        register int i;
        register char *gcursor;
        bool escape;
        register int i;
        register char *gcursor;
        bool escape;
-       int repcnt;
+       int repcnt, savedoomed;
        short oldhold = hold;
 
        /*
        short oldhold = hold;
 
        /*
@@ -210,7 +212,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
@@ -275,6 +277,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 +285,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 +335,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--;
                }
@@ -394,18 +403,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 +446,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 +454,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 && Peekkey == 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 +475,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)
                                c = CTRL(h);
                        else if (c == tty.sg_kill)
                                c = -1;
                        if (c == tty.sg_erase)
                                c = CTRL(h);
                        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) {
 
                        /*
@@ -540,14 +569,21 @@ vbackup:
                                putchar('\\');
                                vcsync();
                                c = getkey();
                                putchar('\\');
                                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
@@ -580,16 +616,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);
+                                               goto vbackup;
+                                       }
+                               }
                }
                }
+
                switch (c) {
 
                /*
                switch (c) {
 
                /*
@@ -679,7 +788,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 +806,24 @@ vbackup:
                                continue;
                        }
 def:
                                continue;
                        }
 def:
-                       putchar(c);
-noput:
+                       if (!backsl) {
+                               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);
 }