added sccs, Bill put in more buffers
[unix-history] / usr / src / usr.bin / ex / ex_vmain.c
index e894dee..3ee9828 100644 (file)
@@ -20,9 +20,12 @@ vmain()
        char *oglobp;
        char d;
        line *addr;
        char *oglobp;
        char d;
        line *addr;
-       int ind;
+       int ind, nlput;
+       int shouldpo = 0;
        int onumber, olist, (*OPline)(), (*OPutchar)();
 
        int onumber, olist, (*OPline)(), (*OPutchar)();
 
+       vch_mac = VC_NOTINMAC;
+
        /*
         * If we started as a vi command (on the command line)
         * then go process initial commands (recover, next or tag).
        /*
         * If we started as a vi command (on the command line)
         * then go process initial commands (recover, next or tag).
@@ -120,6 +123,7 @@ reread:
                        fprintf(trace,"pcb=%c,",peekkey());
 #endif
                op = getkey();
                        fprintf(trace,"pcb=%c,",peekkey());
 #endif
                op = getkey();
+               maphopcnt = 0;
                do {
                        /*
                         * Keep mapping the char as long as it changes.
                do {
                        /*
                         * Keep mapping the char as long as it changes.
@@ -141,6 +145,10 @@ reread:
                                ungetkey(c);
                                goto looptop;
                        }
                                ungetkey(c);
                                goto looptop;
                        }
+                       if (!value(REMAP))
+                               break;
+                       if (++maphopcnt > 256)
+                               error("Infinite macro loop");
                } while (c != op);
 
                /*
                } while (c != op);
 
                /*
@@ -161,16 +169,23 @@ reread:
                /*
                 * ^L           Clear screen e.g. after transmission error.
                 */
                /*
                 * ^L           Clear screen e.g. after transmission error.
                 */
-               case CTRL(l):
-                       vclear();
-                       vdirty(0, vcnt);
-                       /* fall into... */
 
                /*
                 * ^R           Retype screen, getting rid of @ lines.
                 *              If in open, equivalent to ^L.
 
                /*
                 * ^R           Retype screen, getting rid of @ lines.
                 *              If in open, equivalent to ^L.
+                *              On terminals where the right arrow key sends
+                *              ^L we make ^R act like ^L, since there is no
+                *              way to get ^L.  These terminals (adm31, tvi)
+                *              are intelligent so ^R is useless.  Soroc
+                *              will probably foul this up, but nobody has
+                *              one of them.
                 */
                 */
+               case CTRL(l):
                case CTRL(r):
                case CTRL(r):
+                       if (c == CTRL(l) || (KR && *KR==CTRL(l))) {
+                               vclear();
+                               vdirty(0, vcnt);
+                       }
                        if (state != VISUAL) {
                                /*
                                 * Get a clean line, throw away the
                        if (state != VISUAL) {
                                /*
                                 * Get a clean line, throw away the
@@ -209,7 +224,9 @@ reread:
                 *              in vmacbuf, point vglobp there and punt.
                 */
                 case '@':
                 *              in vmacbuf, point vglobp there and punt.
                 */
                 case '@':
-                       c = getkey();
+                       c = getesc();
+                       if (c == 0)
+                               continue;
                        if (c == '@')
                                c = lastmac;
                        if (isupper(c))
                        if (c == '@')
                                c = lastmac;
                        if (isupper(c))
@@ -221,7 +238,7 @@ reread:
                                char tmpbuf[BUFSIZ];
 
                                regbuf(c,tmpbuf,sizeof(vmacbuf));
                                char tmpbuf[BUFSIZ];
 
                                regbuf(c,tmpbuf,sizeof(vmacbuf));
-                               macpush(tmpbuf);
+                               macpush(tmpbuf, 1);
                        ONERR
                                lastmac = 0;
                                splitw = 0;
                        ONERR
                                lastmac = 0;
                                splitw = 0;
@@ -366,14 +383,12 @@ reread:
 
                /*
                 * ^F           Window forwards, with 2 lines of continuity.
 
                /*
                 * ^F           Window forwards, with 2 lines of continuity.
-                *              Count gives new screen size.
+                *              Count repeats.
                 */
                case CTRL(f):
                        vsave();
                 */
                case CTRL(f):
                        vsave();
-                       if (hadcnt)
-                               vsetsiz(cnt);
                        if (vcnt > 2) {
                        if (vcnt > 2) {
-                               dot += (vcnt - vcline) - 2;
+                               dot += (vcnt - vcline) - 2 + (cnt-1)*basWLINES;
                                vcnt = vcline = 0;
                        }
                        vzop(0, 0, '+');
                                vcnt = vcline = 0;
                        }
                        vzop(0, 0, '+');
@@ -385,10 +400,8 @@ reread:
                 */
                case CTRL(b):
                        vsave();
                 */
                case CTRL(b):
                        vsave();
-                       if (hadcnt)
-                               vsetsiz(cnt);
                        if (one + vcline != dot && vcnt > 2) {
                        if (one + vcline != dot && vcnt > 2) {
-                               dot -= vcline - 2;
+                               dot -= vcline - 2 + (cnt-1)*basWLINES;
                                vcnt = vcline = 0;
                        }
                        vzop(0, 0, '^');
                                vcnt = vcline = 0;
                        }
                        vzop(0, 0, '^');
@@ -441,6 +454,7 @@ reread:
                        if (cnt > (i = dol - dot + 1))
                                cnt = i;
                        vsave();
                        if (cnt > (i = dol - dot + 1))
                                cnt = i;
                        vsave();
+                       vmacchng(1);
                        setLAST();
                        cursor = strend(linebuf);
                        vremote(cnt, join, 0);
                        setLAST();
                        cursor = strend(linebuf);
                        vremote(cnt, join, 0);
@@ -476,6 +490,7 @@ reread:
                case 'O':
                case 'o':
                        voOpen(c, cnt);
                case 'O':
                case 'o':
                        voOpen(c, cnt);
+                       vmacchng(1);
                        continue;
 
                /*
                        continue;
 
                /*
@@ -494,13 +509,14 @@ reread:
                case '~':
                        {
                                char mbuf[4];
                case '~':
                        {
                                char mbuf[4];
+                               setLAST();
                                mbuf[0] = 'r';
                                mbuf[1] = *cursor;
                                mbuf[2] = cursor[1]==0 ? 0 : ' ';
                                mbuf[3] = 0;
                                if (isalpha(mbuf[1]))
                                        mbuf[1] ^= ' '; /* toggle the case */
                                mbuf[0] = 'r';
                                mbuf[1] = *cursor;
                                mbuf[2] = cursor[1]==0 ? 0 : ' ';
                                mbuf[3] = 0;
                                if (isalpha(mbuf[1]))
                                        mbuf[1] ^= ' '; /* toggle the case */
-                               macpush(mbuf);
+                               macpush(mbuf, 1);
                        }
                        continue;
 
                        }
                        continue;
 
@@ -562,12 +578,15 @@ insrt:
                         * is doomed, unless R when all is, and save the
                         * current line in a the undo temporary buffer.
                         */
                         * is doomed, unless R when all is, and save the
                         * current line in a the undo temporary buffer.
                         */
+                       vmacchng(1);
                        setLAST();
                        vcursat(cursor);
                        prepapp();
                        vnoapp();
                        doomed = c == 'R' ? 10000 : 0;
                        setLAST();
                        vcursat(cursor);
                        prepapp();
                        vnoapp();
                        doomed = c == 'R' ? 10000 : 0;
-                       vundkind = VCHNG;
+                       if(FIXUNDO)
+                               vundkind = VCHNG;
+                       vmoving = 0;
                        CP(vutmp, linebuf);
 
                        /*
                        CP(vutmp, linebuf);
 
                        /*
@@ -605,6 +624,7 @@ insrt:
                                onintr();
                        /* fall into... */
 
                                onintr();
                        /* fall into... */
 
+#ifdef notdef
                /*
                 * q            Quit back to command mode, unless called as
                 *              vi on command line in which case dont do it
                /*
                 * q            Quit back to command mode, unless called as
                 *              vi on command line in which case dont do it
@@ -620,6 +640,7 @@ insrt:
                                vrepaint(cursor);
                                continue;
                        }
                                vrepaint(cursor);
                                continue;
                        }
+#endif
                        /* fall into... */
 
                /*
                        /* fall into... */
 
                /*
@@ -628,8 +649,30 @@ insrt:
                 */
                case 'Q':
                        vsave();
                 */
                case 'Q':
                        vsave();
+                       /*
+                        * If we are in the middle of a macro, throw away
+                        * the rest and fix up undo.
+                        * This code copied from getbr().
+                        */
+                       if (vmacp) {
+                               vmacp = 0;
+                               if (inopen == -1)       /* don't screw up undo for esc esc */
+                                       vundkind = VMANY;
+                               inopen = 1;     /* restore old setting now that macro done */
+                       }
                        return;
 
                        return;
 
+
+               /*
+                * ZZ           Like :x
+                */
+                case 'Z':
+                       forbid(getkey() != 'Z');
+                       oglobp = globp;
+                       globp = "x";
+                       vclrech(0);
+                       goto gogo;
+                       
                /*
                 * P            Put back text before cursor or before current
                 *              line.  If text was whole lines goes back
                /*
                 * P            Put back text before cursor or before current
                 *              line.  If text was whole lines goes back
@@ -644,7 +687,9 @@ insrt:
                case 'P':
                case 'p':
                        vmoving = 0;
                case 'P':
                case 'p':
                        vmoving = 0;
-                       forbid (inopen < 0);
+#ifdef notdef
+                       forbid (!vreg && value(UNDOMACRO) && inopen < 0);
+#endif
                        /*
                         * If previous delete was partial line, use an
                         * append or insert to put it back so as to
                        /*
                         * If previous delete was partial line, use an
                         * append or insert to put it back so as to
@@ -662,7 +707,13 @@ insrt:
                         * sure there is something to put back.
                         */
                        forbid (!vreg && unddol == dol);
                         * sure there is something to put back.
                         */
                        forbid (!vreg && unddol == dol);
+                       /*
+                        * If we just did a macro the whole buffer is in
+                        * the undo save area.  We don't want to put THAT.
+                        */
+                       forbid (vundkind == VMANY && undkind==UNDALL);
                        vsave();
                        vsave();
+                       vmacchng(1);
                        setLAST();
                        i = 0;
                        if (vreg && partreg(vreg) || !vreg && pkill[0]) {
                        setLAST();
                        i = 0;
                        if (vreg && partreg(vreg) || !vreg && pkill[0]) {
@@ -696,6 +747,7 @@ insrt:
                         * We thus put a catch in here.  If we didn't and
                         * there was an error we would end up in command mode.
                         */
                         * We thus put a catch in here.  If we didn't and
                         * there was an error we would end up in command mode.
                         */
+                       addr = dol;     /* old dol */
                        CATCH
                                vremote(1, vreg ? putreg : put, vreg);
                        ONERR
                        CATCH
                                vremote(1, vreg ? putreg : put, vreg);
                        ONERR
@@ -707,24 +759,31 @@ insrt:
                                }
                        ENDCATCH
                        splitw = 0;
                                }
                        ENDCATCH
                        splitw = 0;
+                       nlput = dol - addr + 1;
                        if (!i) {
                                /*
                                 * Increment undap1, undap2 to make up
                                 * for their incorrect initialization in the
                                 * routine vremote before calling put/putreg.
                                 */
                        if (!i) {
                                /*
                                 * Increment undap1, undap2 to make up
                                 * for their incorrect initialization in the
                                 * routine vremote before calling put/putreg.
                                 */
-                               undap1++, undap2++;
+                               if (FIXUNDO)
+                                       undap1++, undap2++;
                                vcline++;
                                vcline++;
-                       }
+                               nlput--;
 
 
-                       /*
-                        * After a put want current line first line,
-                        * and dot was made the last line put in code run
-                        * so far.  This is why we increment vcline above,
-                        * and decrease (usually) dot here.
-                        */
-                       dot = undap1;
-                       vreplace(vcline, i, undap2 - undap1);
+                               /*
+                                * After a put want current line first line,
+                                * and dot was made the last line put in code
+                                * run so far.  This is why we increment vcline
+                                * above and decrease dot here.
+                                */
+                               dot -= nlput - 1;
+                       }
+#ifdef TRACE
+                       if (trace)
+                               fprintf(trace, "vreplace(%d, %d, %d), undap1=%d, undap2=%d, dot=%d\n", vcline, i, nlput, lineno(undap1), lineno(undap2), lineno(dot));
+#endif
+                       vreplace(vcline, i, nlput);
                        if (state != VISUAL) {
                                /*
                                 * Special case in open mode.
                        if (state != VISUAL) {
                                /*
                                 * Special case in open mode.
@@ -801,6 +860,19 @@ gogo:
                        vsave();
                        goto doinit;
 
                        vsave();
                        goto doinit;
 
+#ifdef TIOCLGET
+               /*
+                * ^Z:  suspend editor session and temporarily return
+                *      to shell.  Only works on Berkeley tty driver.
+                */
+               case CTRL(z):
+                       forbid(dosusp == 0 || !ldisc);
+                       vsave();
+                       oglobp = globp;
+                       globp = "stop";
+                       goto gogo;
+#endif
+
                /*
                 * :            Read a command from the echo area and
                 *              execute it in command mode.
                /*
                 * :            Read a command from the echo area and
                 *              execute it in command mode.
@@ -815,6 +887,7 @@ gogo:
                                esave[0] = 0;
                                goto fixup;
                        }
                                esave[0] = 0;
                                goto fixup;
                        }
+                       getDOT();
                        /*
                         * Use the visual undo buffer to store the global
                         * string for command mode, since it is idle right now.
                        /*
                         * Use the visual undo buffer to store the global
                         * string for command mode, since it is idle right now.
@@ -830,6 +903,14 @@ doinit:
                         * command mode).  This is clumsy.
                         */
                        d = peekc; ungetchar(0);
                         * command mode).  This is clumsy.
                         */
                        d = peekc; ungetchar(0);
+                       if (shouldpo) {
+                               /*
+                                * So after a "Hit return..." ":", we do
+                                * another "Hit return..." the next time
+                                */
+                               pofix();
+                               shouldpo = 0;
+                       }
                        CATCH
                                /*
                                 * Save old values of options so we can
                        CATCH
                                /*
                                 * Save old values of options so we can
@@ -892,7 +973,7 @@ fixup:
                         * a write command there, but its not
                         * worth worrying about.
                         */
                         * a write command there, but its not
                         * worth worrying about.
                         */
-                       if (tchng && tchng != i)
+                       if (FIXUNDO && tchng && tchng != i)
                                vundkind = VMANY, cursor = 0;
 
                        /*
                                vundkind = VMANY, cursor = 0;
 
                        /*
@@ -901,8 +982,10 @@ fixup:
                         */
                        if (vcnt < 0 && Peekkey == ':') {
                                getDOT();
                         */
                        if (vcnt < 0 && Peekkey == ':') {
                                getDOT();
+                               shouldpo = 1;
                                continue;
                        }
                                continue;
                        }
+                       shouldpo = 0;
 
                        /*
                         * In the case where the file being edited is
 
                        /*
                         * In the case where the file being edited is
@@ -950,8 +1033,9 @@ fixup:
                                        vcnt = -vcnt;
                                        if (state == VISUAL)
                                                vclear();
                                        vcnt = -vcnt;
                                        if (state == VISUAL)
                                                vclear();
-                                       else if (state == CRTOPEN)
+                                       else if (state == CRTOPEN) {
                                                vcnt = 0;
                                                vcnt = 0;
+                                       }
                                }
 
                                /*
                                }
 
                                /*
@@ -991,7 +1075,7 @@ fixup:
                 * u            undo the last changing command.
                 */
                case 'u':
                 * u            undo the last changing command.
                 */
                case 'u':
-                       vundo();
+                       vundo(1);
                        continue;
 
                /*
                        continue;
 
                /*
@@ -1059,12 +1143,12 @@ vremote(cnt, f, arg)
 
        addr1 = dot;
        addr2 = dot + cnt - 1;
 
        addr1 = dot;
        addr2 = dot + cnt - 1;
-       if (inopen > 0)
-               undap1 = undap2 = dot;
        inglobal = 0;
        inglobal = 0;
+       if (FIXUNDO)
+               undap1 = undap2 = dot;
        (*f)(arg);
        inglobal = oing;
        (*f)(arg);
        inglobal = oing;
-       if (inopen > 0)
+       if (FIXUNDO)
                vundkind = VMANY;
        vmcurs = 0;
 }
                vundkind = VMANY;
        vmcurs = 0;
 }
@@ -1077,7 +1161,7 @@ vsave()
        char temp[LBSIZE];
 
        CP(temp, linebuf);
        char temp[LBSIZE];
 
        CP(temp, linebuf);
-       if (vundkind == VCHNG || vundkind == VCAPU) {
+       if (FIXUNDO && vundkind == VCHNG || vundkind == VCAPU) {
                /*
                 * If the undo state is saved in the temporary buffer
                 * vutmp, then we sync this into the temp file so that
                /*
                 * If the undo state is saved in the temporary buffer
                 * vutmp, then we sync this into the temp file so that