BSD 4 release
[unix-history] / usr / src / cmd / ex / ex_vops.c
index 92a5f68..cc85af4 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_vops.c   6.3 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"
@@ -50,10 +51,12 @@ vUndo()
        }
        vdirty(vcline, 1);
        vsyncCL();
        }
        vdirty(vcline, 1);
        vsyncCL();
+       cursor = linebuf;
        vfixcurs();
 }
 
        vfixcurs();
 }
 
-vundo()
+vundo(show)
+bool show;     /* if true update the screen */
 {
        register int cnt;
        register line *addr;
 {
        register int cnt;
        register line *addr;
@@ -81,31 +84,38 @@ vundo()
                notecnt = 1;
                if (undkind == UNDPUT && undap1 == undap2) {
                        beep();
                notecnt = 1;
                if (undkind == UNDPUT && undap1 == undap2) {
                        beep();
-                       return;
+                       break;
                }
                /*
                 * Undo() call below basically replaces undap1 to undap2-1
                 * with dol through unddol-1.  Hack screen image to
                 * reflect this replacement.
                 */
                }
                /*
                 * Undo() call below basically replaces undap1 to undap2-1
                 * with dol through unddol-1.  Hack screen image to
                 * reflect this replacement.
                 */
-               vreplace(undap1 - addr, undap2 - undap1,
-                   undkind == UNDPUT ? 0 : unddol - dol);
+               if (show)
+                       if (undkind == UNDMOVE)
+                               vdirty(0, LINES);
+                       else
+                               vreplace(undap1 - addr, undap2 - undap1,
+                                   undkind == UNDPUT ? 0 : unddol - dol);
                savenote = notecnt;
                undo(1);
                savenote = notecnt;
                undo(1);
-               if (vundkind != VMCHNG || addr != dot)
+               if (show && (vundkind != VMCHNG || addr != dot))
                        killU();
                vundkind = VMANY;
                cnt = dot - addr;
                if (cnt < 0 || cnt > vcnt || state != VISUAL) {
                        killU();
                vundkind = VMANY;
                cnt = dot - addr;
                if (cnt < 0 || cnt > vcnt || state != VISUAL) {
-                       vjumpto(dot, NOSTR, '.');
-                       return;
+                       if (show)
+                               vjumpto(dot, NOSTR, '.');
+                       break;
                }
                if (!savenote)
                        notecnt = 0;
                }
                if (!savenote)
                        notecnt = 0;
-               vcline = cnt;
-               vrepaint(vmcurs);
+               if (show) {
+                       vcline = cnt;
+                       vrepaint(vmcurs);
+               }
                vmcurs = 0;
                vmcurs = 0;
-               return;
+               break;
 
        case VCHNG:
        case VCAPU:
 
        case VCHNG:
        case VCAPU:
@@ -116,13 +126,15 @@ vundo()
                strcLIN(temp);
                cp = vUA1; vUA1 = vUD1; vUD1 = cp;
                cp = vUA2; vUA2 = vUD2; vUD2 = cp;
                strcLIN(temp);
                cp = vUA1; vUA1 = vUD1; vUD1 = cp;
                cp = vUA2; vUA2 = vUD2; vUD2 = cp;
+               if (!show)
+                       break;
                cursor = vUD1;
                if (state == HARDOPEN) {
                        doomed = 0;
                        vsave();
                        vopen(dot, WBOT);
                        vnline(cursor);
                cursor = vUD1;
                if (state == HARDOPEN) {
                        doomed = 0;
                        vsave();
                        vopen(dot, WBOT);
                        vnline(cursor);
-                       return;
+                       break;
                }
                /*
                 * Pseudo insert command.
                }
                /*
                 * Pseudo insert command.
@@ -142,11 +154,102 @@ vundo()
                if (cursor > linebuf && cursor >= strend(linebuf))
                        cursor--;
                vfixcurs();
                if (cursor > linebuf && cursor >= strend(linebuf))
                        cursor--;
                vfixcurs();
-               return;
+               break;
 
        case VNONE:
                beep();
 
        case VNONE:
                beep();
+               break;
+       }
+}
+
+/*
+ * Routine to handle a change inside a macro.
+ * Fromvis is true if we were called from a visual command (as
+ * opposed to an ex command).  This has nothing to do with being
+ * in open/visual mode as :s/foo/bar is not fromvis.
+ */
+vmacchng(fromvis)
+bool fromvis;
+{
+       line *savedot, *savedol;
+       char *savecursor;
+       char savelb[LBSIZE];
+       int nlines, more;
+       register line *a1, *a2;
+       char ch;        /* DEBUG */
+       int copyw(), copywR();
+
+       if (!inopen)
                return;
                return;
+       if (!vmacp)
+               vch_mac = VC_NOTINMAC;
+#ifdef TRACE
+       if (trace)
+               fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot);
+#endif
+       if (vmacp && fromvis)
+               vsave();
+#ifdef TRACE
+       if (trace)
+               fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot);
+#endif
+       switch(vch_mac) {
+       case VC_NOCHANGE:
+               vch_mac = VC_ONECHANGE;
+               break;
+       case VC_ONECHANGE:
+               /* Save current state somewhere */
+#ifdef TRACE
+               vudump("before vmacchng hairy case");
+#endif
+               savedot = dot; savedol = dol; savecursor = cursor;
+               CP(savelb, linebuf);
+               nlines = dol - zero;
+               while ((line *) endcore - truedol < nlines)
+                       morelines();
+               copyw(truedol+1, zero+1, nlines);
+               truedol += nlines;
+
+#ifdef TRACE
+               visdump("before vundo");
+#endif
+               /* Restore state as it was at beginning of macro */
+               vundo(0);
+#ifdef TRACE
+               visdump("after vundo");
+               vudump("after vundo");
+#endif
+
+               /* Do the saveall we should have done then */
+               saveall();
+#ifdef TRACE
+               vudump("after saveall");
+#endif
+
+               /* Restore current state from where saved */
+               more = savedol - dol; /* amount we shift everything by */
+               if (more)
+                       (*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol);
+               unddol += more; truedol += more; undap2 += more;
+
+               truedol -= nlines;
+               copyw(zero+1, truedol+1, nlines);
+               dot = savedot; dol = savedol ; cursor = savecursor;
+               CP(linebuf, savelb);
+               vch_mac = VC_MANYCHANGE;
+
+               /* Arrange that no further undo saving happens within macro */
+               otchng = tchng; /* Copied this line blindly - bug? */
+               inopen = -1;    /* no need to save since it had to be 1 or -1 before */
+               vundkind = VMANY;
+#ifdef TRACE
+               vudump("after vmacchng");
+#endif
+               break;
+       case VC_NOTINMAC:
+       case VC_MANYCHANGE:
+               /* Nothing to do for various reasons. */
+               break;
        }
 }
 
        }
 }
 
@@ -544,7 +647,8 @@ voOpen(c, cnt)
        }
        killU();
        prepapp();
        }
        killU();
        prepapp();
-       vundkind = VMANY;
+       if (FIXUNDO)
+               vundkind = VMANY;
        if (state != VISUAL)
                c = WBOT + 1;
        else {
        if (state != VISUAL)
                c = WBOT + 1;
        else {
@@ -641,6 +745,13 @@ vfilter()
                dot = one;
        splitw = 0;
        notenam = "";
                dot = one;
        splitw = 0;
        notenam = "";
+       /*
+        * BUG: we shouldn't be depending on what undap2 and undap1 are,
+        * since we may be inside a macro.  What's really wanted is the
+        * number of lines we read from the filter.  However, the mistake
+        * will be an overestimate so it only results in extra work,
+        * it shouldn't cause any real screwups.
+        */
        vreplace(vcline, cnt, undap2 - undap1);
        dot = addr;
        if (dot > dol) {
        vreplace(vcline, cnt, undap2 - undap1);
        dot = addr;
        if (dot > dol) {
@@ -757,7 +868,8 @@ vrep(cnt)
                ungetkey(c);
        }
        CP(vutmp, linebuf);
                ungetkey(c);
        }
        CP(vutmp, linebuf);
-       vundkind = VCHNG;
+       if (FIXUNDO)
+               vundkind = VCHNG;
        wcursor = cursor + cnt;
        vUD1 = cursor; vUD2 = wcursor;
        CP(cursor, wcursor);
        wcursor = cursor + cnt;
        vUD1 = cursor; vUD2 = wcursor;
        CP(cursor, wcursor);
@@ -783,7 +895,8 @@ vyankit()
                vremote(cnt, yank, 0);
                setpk();
                notenam = "yank";
                vremote(cnt, yank, 0);
                setpk();
                notenam = "yank";
-               vundkind = VNONE;
+               if (FIXUNDO)
+                       vundkind = VNONE;
                DEL[0] = 0;
                wdot = NOLINE;
                if (notecnt <= vcnt - vcline && notecnt < value(REPORT))
                DEL[0] = 0;
                wdot = NOLINE;
                if (notecnt <= vcnt - vcline && notecnt < value(REPORT))