From 887e3e0d88fb221edf5e9f2ed55c81a4e216c88e Mon Sep 17 00:00:00 2001 From: Mark Horton Date: Fri, 1 Aug 1980 06:46:44 -0800 Subject: [PATCH] release 3.3, Feb 2, 1980 SCCS-vsn: usr.bin/ex/ex.c 3.1 SCCS-vsn: usr.bin/ex/ex.h 3.1 SCCS-vsn: usr.bin/ex/ex_addr.c 3.1 SCCS-vsn: usr.bin/ex/ex_argv.h 3.1 SCCS-vsn: usr.bin/ex/ex_cmds.c 3.1 SCCS-vsn: usr.bin/ex/ex_cmds2.c 3.1 SCCS-vsn: usr.bin/ex/ex_cmdsub.c 3.1 SCCS-vsn: usr.bin/ex/ex_data.c 3.1 SCCS-vsn: usr.bin/ex/ex_get.c 3.1 SCCS-vsn: usr.bin/ex/ex_io.c 3.1 SCCS-vsn: usr.bin/ex/ex_put.c 3.1 SCCS-vsn: usr.bin/ex/ex_re.c 3.1 SCCS-vsn: usr.bin/ex/ex_re.h 3.1 SCCS-vsn: usr.bin/ex/ex_set.c 3.1 SCCS-vsn: usr.bin/ex/ex_subr.c 3.1 SCCS-vsn: usr.bin/ex/ex_temp.c 3.1 SCCS-vsn: usr.bin/ex/ex_temp.h 3.1 SCCS-vsn: usr.bin/ex/ex_tty.c 3.1 SCCS-vsn: usr.bin/ex/ex_tty.h 3.1 SCCS-vsn: usr.bin/ex/ex_tune.h 3.1 SCCS-vsn: usr.bin/ex/ex_v.c 3.1 SCCS-vsn: usr.bin/ex/ex_vadj.c 3.1 SCCS-vsn: usr.bin/ex/ex_vars.h 3.1 SCCS-vsn: usr.bin/ex/ex_vget.c 3.1 SCCS-vsn: usr.bin/ex/ex_vis.h 3.1 SCCS-vsn: usr.bin/ex/ex_vmain.c 3.1 SCCS-vsn: usr.bin/ex/ex_voper.c 3.1 SCCS-vsn: usr.bin/ex/ex_vops.c 3.1 SCCS-vsn: usr.bin/ex/ex_vops2.c 3.1 SCCS-vsn: usr.bin/ex/ex_vops3.c 3.1 SCCS-vsn: usr.bin/ex/ex_vput.c 3.1 SCCS-vsn: usr.bin/ex/ex_vwind.c 3.1 SCCS-vsn: usr.bin/ex/ex3.7preserve/ex3.7preserve.c 3.1 SCCS-vsn: usr.bin/ex/ex3.7recover/ex3.7recover.c 3.1 SCCS-vsn: usr.bin/ex/Makefile 3.1 SCCS-vsn: usr.bin/ex/OTHER/makefile.70 3.1 SCCS-vsn: usr.bin/ex/makeoptions 3.1 SCCS-vsn: usr.bin/ex/printf.c 3.1 --- usr/src/usr.bin/ex/Makefile | 2 +- usr/src/usr.bin/ex/OTHER/makefile.70 | 2 +- usr/src/usr.bin/ex/ex.c | 4 + usr/src/usr.bin/ex/ex.h | 17 +- usr/src/usr.bin/ex/ex_cmds.c | 27 ++- usr/src/usr.bin/ex/ex_cmds2.c | 48 +++-- usr/src/usr.bin/ex/ex_cmdsub.c | 263 +++++++++++++++++++-------- usr/src/usr.bin/ex/ex_data.c | 30 ++- usr/src/usr.bin/ex/ex_get.c | 10 +- usr/src/usr.bin/ex/ex_io.c | 16 +- usr/src/usr.bin/ex/ex_put.c | 27 ++- usr/src/usr.bin/ex/ex_re.c | 10 +- usr/src/usr.bin/ex/ex_set.c | 25 ++- usr/src/usr.bin/ex/ex_subr.c | 16 +- usr/src/usr.bin/ex/ex_temp.c | 11 +- usr/src/usr.bin/ex/ex_tty.c | 8 +- usr/src/usr.bin/ex/ex_tty.h | 10 +- usr/src/usr.bin/ex/ex_tune.h | 9 +- usr/src/usr.bin/ex/ex_v.c | 4 +- usr/src/usr.bin/ex/ex_vars.h | 33 ++-- usr/src/usr.bin/ex/ex_vget.c | 60 ++++-- usr/src/usr.bin/ex/ex_vmain.c | 98 +++++++--- usr/src/usr.bin/ex/ex_voper.c | 38 +++- usr/src/usr.bin/ex/ex_vops.c | 28 ++- usr/src/usr.bin/ex/ex_vops2.c | 14 +- usr/src/usr.bin/ex/ex_vput.c | 13 +- 26 files changed, 579 insertions(+), 244 deletions(-) diff --git a/usr/src/usr.bin/ex/Makefile b/usr/src/usr.bin/ex/Makefile index c62b9d799b..77f5700299 100644 --- a/usr/src/usr.bin/ex/Makefile +++ b/usr/src/usr.bin/ex/Makefile @@ -1,4 +1,4 @@ -VERSION=3.2 +VERSION=3.3 # # Ex skeletal makefile for version 7 # diff --git a/usr/src/usr.bin/ex/OTHER/makefile.70 b/usr/src/usr.bin/ex/OTHER/makefile.70 index c62b9d799b..77f5700299 100644 --- a/usr/src/usr.bin/ex/OTHER/makefile.70 +++ b/usr/src/usr.bin/ex/OTHER/makefile.70 @@ -1,4 +1,4 @@ -VERSION=3.2 +VERSION=3.3 # # Ex skeletal makefile for version 7 # diff --git a/usr/src/usr.bin/ex/ex.c b/usr/src/usr.bin/ex/ex.c index e74b5c046c..fbb4c3aa73 100644 --- a/usr/src/usr.bin/ex/ex.c +++ b/usr/src/usr.bin/ex/ex.c @@ -442,6 +442,10 @@ exit(i) int i; { +# ifdef TRACE + if (trace) + fclose(trace); +# endif _exit(i); } #endif diff --git a/usr/src/usr.bin/ex/ex.h b/usr/src/usr.bin/ex/ex.h index 9493541ce1..e7a8d3d3c5 100644 --- a/usr/src/usr.bin/ex/ex.h +++ b/usr/src/usr.bin/ex/ex.h @@ -108,11 +108,11 @@ struct option options[NOPTS + 1]; # undef putchar # undef getchar #else -#ifdef VMUNIX +# ifdef VMUNIX # define BUFSIZ 1024 -#else +# else # define BUFSIZ 512 -#endif +# endif # define NULL 0 # define EOF -1 #endif @@ -195,6 +195,11 @@ int xchng; /* Suppresses multiple "No writes" in !cmd */ * Macros */ #define CP(a, b) (ignore(strcpy(a, b))) + /* + * FIXUNDO: do we want to mung undo vars? + * Usually yes unless in a macro or global. + */ +#define FIXUNDO (inopen >= 0 && (inopen || !inglobal)) #define ckaw() {if (chng && value(AUTOWRITE)) wop(0);} #define copy(a,b,c) Copy((char *) a, (char *) b, c) #define eq(a, b) ((a) && (b) && strcmp(a, b) == 0) @@ -217,9 +222,9 @@ int xchng; /* Suppresses multiple "No writes" in !cmd */ * Environment like memory */ char altfile[FNSIZE]; /* Alternate file name */ -char direct[32]; /* Temp file goes here */ -char shell[32]; /* Copied to be settable */ -char ttytype[16]; /* A long and pretty name */ +char direct[ONMSZ]; /* Temp file goes here */ +char shell[ONMSZ]; /* Copied to be settable */ +char ttytype[ONMSZ]; /* A long and pretty name */ char uxb[UXBSIZE + 2]; /* Last !command for !! */ /* diff --git a/usr/src/usr.bin/ex/ex_cmds.c b/usr/src/usr.bin/ex/ex_cmds.c index d577f8976c..a85b1b2886 100644 --- a/usr/src/usr.bin/ex/ex_cmds.c +++ b/usr/src/usr.bin/ex/ex_cmds.c @@ -526,7 +526,6 @@ quit: flush(); unixwt(1, unixex("-i", (char *) 0, 0, 0)); vcontin(0); - putpad(TI); continue; /* source */ @@ -598,7 +597,7 @@ quit: tail("version"); setNAEOL(); /* should use SCCS subst here */ - printf("Version 3.2, January 4, 1980"); + printf("Version 3.3, February 2, 1980"); noonl(); continue; @@ -620,7 +619,9 @@ quit: case 'w': c = peekchar(); tail(c == 'q' ? "wq" : "write"); +wq: if (skipwh() && peekchar() == '!') { + pofix(); ignchar(); setall(); unix0(0); @@ -634,6 +635,14 @@ quit: goto quit; continue; +/* xit */ + case 'x': + tail("xit"); + if (!chng) + goto quit; + c = 'q'; + goto wq; + /* yank */ case 'y': tail("yank"); @@ -681,14 +690,15 @@ quit: caseline: notempty(); if (addr2 == 0) { - if (dot == dol) - error("At EOF|At end-of-file"); if (UP != NOSTR && c == '\n' && !inglobal) c = CTRL(k); if (inglobal) addr1 = addr2 = dot; - else + else { + if (dot == dol) + error("At EOF|At end-of-file"); addr1 = addr2 = dot + 1; + } } setdot(); nonzero(); @@ -716,6 +726,8 @@ numberit: case '=': newline(); setall(); + if (inglobal == 2) + pofix(); printf("%d", lineno(addr2)); noonl(); continue; @@ -728,12 +740,11 @@ numberit: filter(2); } else { unix0(1); - vnfl(); + pofix(); putpad(TE); flush(); unixwt(1, unixex("-c", uxb, 0, 0)); - vcontin(1); - putpad(TI); + vcontin(0); nochng(); } continue; diff --git a/usr/src/usr.bin/ex/ex_cmds2.c b/usr/src/usr.bin/ex/ex_cmds2.c index 95deb537d4..fd1d68fbe0 100644 --- a/usr/src/usr.bin/ex/ex_cmds2.c +++ b/usr/src/usr.bin/ex/ex_cmds2.c @@ -158,11 +158,13 @@ error1(str) io = -1; } die = (getpid() != ppid); /* Only children die */ + inglobal = 0; + globp = vglobp = vmacp = 0; if (vcatch && !die) { - inglobal = 0; - vglobp = vmacp = 0; inopen = 1; vcatch = 0; + if (str) + noonl(); fixol(); longjmp(vreslab,1); } @@ -173,8 +175,6 @@ error1(str) lseek(0, 0L, 2); if (inglobal) setlastchar('\n'); - inglobal = 0; - globp = 0; while (lastchar() != '\n' && lastchar() != EOF) ignchar(); ungetchar(0); @@ -449,7 +449,7 @@ ret: } /* - * Continue after a shell escape from open/visual. + * Continue after a : command from open/visual. */ vcontin(ask) bool ask; @@ -459,10 +459,24 @@ vcontin(ask) vcnt = -vcnt; if (inopen) { if (state != VISUAL) { -/* - vtube[WECHO][0] = '*'; - vnfl(); -*/ + /* + * We don't know what a shell command may have left on + * the screen, so we move the cursor to the right place + * and then put out a newline. But this makes an extra + * blank line most of the time so we only do it for :sh + * since the prompt gets left on the screen. + * + * BUG: :!echo longer than current line \\c + * will screw it up, but be reasonable! + */ + if (state == CRTOPEN) { + termreset(); + vgoto(WECHO, 0); + } + if (!ask) { + putch('\r'); + putch('\n'); + } return; } if (ask) { @@ -473,17 +487,27 @@ vcontin(ask) vraw(); #endif if (ask) { +#ifdef EATQS /* * Gobble ^Q/^S since the tty driver should be eating * them (as far as the user can see) */ while (peekkey() == CTRL(Q) || peekkey() == CTRL(S)) ignore(getkey()); - if(getkey() == ':') +#endif + if(getkey() == ':') { + /* Ugh. Extra newlines, but no other way */ + putch('\n'); + outline = WECHO; ungetkey(':'); + } + } + vclrech(1); + if (ask && Peekkey != ':') { + putpad(TI); + putpad(VS); + putpad(KS); } - putpad(VS); - putpad(KS); } } diff --git a/usr/src/usr.bin/ex/ex_cmdsub.c b/usr/src/usr.bin/ex/ex_cmdsub.c index 09c01d9d2f..8bd125a2e0 100644 --- a/usr/src/usr.bin/ex/ex_cmdsub.c +++ b/usr/src/usr.bin/ex/ex_cmdsub.c @@ -27,21 +27,14 @@ append(f, a) nline = 0; dot = a; - /* - * This is probably a bug, since it's different than the other tests - * in appendnone, delete, and deletenone. It is known to fail for - * the command :g/foo/r xxx (where there is one foo and the file - * xxx exists) and you try to undo it. I'm leaving it in for now - * because I'm afraid if I change it I'll break something. - */ - if (!inglobal && !inopen && f != getsub) { + if(FIXUNDO && !inopen && f!=getsub) { undap1 = undap2 = dot + 1; undkind = UNDCHANGE; } while ((*f)() == 0) { if (truedol >= endcore) { if (morelines() < 0) { - if (!inglobal && f == getsub) { + if (FIXUNDO && f == getsub) { undap1 = addr1; undap2 = addr2 + 1; } @@ -71,7 +64,7 @@ append(f, a) appendnone() { - if (inopen >= 0 && (inopen || !inglobal)) { + if(FIXUNDO) { undkind = UNDCHANGE; undap1 = undap2 = addr1; } @@ -108,7 +101,7 @@ delete(hush) register line *a1, *a2; nonzero(); - if (inopen >= 0 && (inopen || !inglobal)) { + if(FIXUNDO) { register int (*dsavint)(); change(); @@ -157,7 +150,7 @@ delete(hush) deletenone() { - if (inopen >= 0 && (inopen || !inglobal)) { + if(FIXUNDO) { undkind = UNDCHANGE; squish(); unddel = addr1; @@ -172,14 +165,16 @@ squish() { register line *a1 = dol + 1, *a2 = unddol + 1, *a3 = truedol + 1; - if (inopen == -1) - return; - if (a1 < a2 && a2 < a3) - do - *a1++ = *a2++; - while (a2 < a3); - truedol -= unddol - dol; - unddol = dol; + if(FIXUNDO) { + if (inopen == -1) + return; + if (a1 < a2 && a2 < a3) + do + *a1++ = *a2++; + while (a2 < a3); + truedol -= unddol - dol; + unddol = dol; + } } /* @@ -294,16 +289,18 @@ move1(cflag, addrt) error("Move to a moved line"); change(); if (!inglobal) - if (cflag) { - undap1 = addrt + 1; - undap2 = undap1 + lines; - deletenone(); - } else { - undkind = UNDMOVE; - undap1 = addr1; - undap2 = addr2; - unddel = addrt; - squish(); + if(FIXUNDO) { + if (cflag) { + undap1 = addrt + 1; + undap2 = undap1 + lines; + deletenone(); + } else { + undkind = UNDMOVE; + undap1 = addr1; + undap2 = addr2; + unddel = addrt; + squish(); + } } } @@ -333,6 +330,8 @@ put() { register int cnt; + if (!FIXUNDO) + error("Cannot put inside global/macro"); cnt = unddol - dol; if (cnt && inopen && pkill[0] && pkill[1]) { pragged(1); @@ -397,7 +396,7 @@ shift(c, cnt) char *dp; register int i; - if (!inglobal) + if(FIXUNDO) save12(), undkind = UNDCHANGE; cnt *= value(SHIFTWIDTH); for (addr = addr1; addr <= addr2; addr++) { @@ -449,11 +448,27 @@ tagfind(quick) { char cmdbuf[BUFSIZ]; char filebuf[FNSIZE]; + char tagfbuf[128]; register int c, d; bool samef = 1; - bool notagsfile = 0; - short master = -1; - short omagic; + int tfcount = 0; + int omagic; + char *fn, *fne; +#ifdef VMUNIX + /* + * We have lots of room so we bring in stdio and do + * a binary search on the tags file. + */ +# undef EOF +# include +# undef getchar +# undef putchar + FILE *iof; + char iofbuf[BUFSIZ]; + long mid; /* assumed byte offset */ + long top, bot; /* length of tag file */ + struct stat sbuf; +#endif omagic = value(MAGIC); if (!skipend()) { @@ -476,20 +491,76 @@ badtag: if (c == EOF) ungetchar(c); clrstats(); - do { - io = open(master ? "tags" : MASTERTAGS, 0); - if (master && io < 0) - notagsfile = 1; + + /* + * Loop once for each file in tags "path". + */ + CP(tagfbuf, svalue(TAGS)); + fne = tagfbuf - 1; + while (fne) { + fn = ++fne; + while (*fne && *fne != ' ') + fne++; + if (*fne == 0) + fne = 0; /* done, quit after this time */ + else + *fne = 0; /* null terminate filename */ +#ifdef VMUNIX + iof = fopen(fn, "r"); + if (iof == NULL) + continue; + tfcount++; + setbuf(iof, iofbuf); + fstat(fileno(iof), &sbuf); + top = sbuf.st_size; + if (top == 0L || iof == NULL) + top = -1L; + bot = 0L; + while (top >= bot) { +#else + /* + * Avoid stdio and scan tag file linearly. + */ + io = open(fn, 0); + if (io<0) + continue; while (getfile() == 0) { +#endif + /* loop for each tags file entry */ register char *cp = linebuf; register char *lp = lasttag; char *oglobp; +#ifdef VMUNIX + mid = (top + bot) / 2; + fseek(iof, mid, 0); + if (mid > 0) /* to get first tag in file to work */ + fgets(linebuf, sizeof linebuf, iof); /* scan to next \n */ + fgets(linebuf, sizeof linebuf, iof); /* get a line */ + linebuf[strlen(linebuf)-1] = 0; /* was '\n' */ +#endif while (*cp && *lp == *cp) cp++, lp++; - if (*lp || !iswhite(*cp)) + if (*lp || !iswhite(*cp)) { +#ifdef VMUNIX + if (*lp > *cp) + bot = mid + 1; + else + top = mid - 1; +#endif + /* Not this tag. Try the next */ continue; + } + + /* + * We found the tag. Decode the line in the file. + */ +#ifdef VMUNIX + fclose(iof); +#else close(io); +#endif + /* name of file */ while (*cp && iswhite(*cp)) cp++; if (!*cp) @@ -502,6 +573,7 @@ badtags: cp++; } *lp++ = 0; + if (*cp == 0) goto badtags; if (dol != zero) { @@ -520,6 +592,7 @@ badtags: if (strcmp(filebuf, savedfile) || !edited) { char cmdbuf2[sizeof filebuf + 10]; + /* Different file. Do autowrite & get it. */ if (!quick) { ckaw(); if (chng && dol > zero) @@ -530,33 +603,46 @@ badtags: strcat(cmdbuf2, filebuf); globp = cmdbuf2; d = peekc; ungetchar(0); - /* - * BUG: if it isn't found (user edited header - * line) we get left in nomagic mode. - */ - value(MAGIC) = 0; commands(1, 1); peekc = d; globp = oglobp; value(MAGIC) = omagic; samef = 0; } + + /* + * Look for pattern in the current file. + */ oglobp = globp; globp = cmdbuf; d = peekc; ungetchar(0); if (samef) markpr(dot); + /* + * BUG: if it isn't found (user edited header + * line) we get left in nomagic mode. + */ value(MAGIC) = 0; commands(1, 1); peekc = d; globp = oglobp; value(MAGIC) = omagic; return; - } - } while (++master == 0); - if (notagsfile) + } /* end of "for each tag in file" */ + + /* + * No such tag in this file. Close it and try the next. + */ +#ifdef VMUNIX + fclose(iof); +#else + close(io); +#endif + } /* end of "for each file in path" */ + if (tfcount <= 0) error("No tags file"); - serror("%s: No such tag@in tags file", lasttag); + else + serror("%s: No such tag@in tags file", lasttag); } /* @@ -566,6 +652,8 @@ badtags: yank() { + if (!FIXUNDO) + error("Can't yank inside global/macro"); save12(); undkind = UNDNONE; killcnt(addr2 - addr1 + 1); @@ -787,6 +875,10 @@ undo(c) register line *jp, *kp; line *dolp1, *newdol, *newadot; +#ifdef TRACE + if (trace) + vudump("before undo"); +#endif if (inglobal && inopen <= 0) error("Can't undo in global@commands"); if (!c) @@ -890,11 +982,15 @@ undo(c) if (undkind == UNDALL) { dot = undadot; undadot = newadot; - } - undkind = UNDCHANGE; + } else + undkind = UNDCHANGE; } if (dot == zero && dot != dol) dot = one; +#ifdef TRACE + if (trace) + vudump("after undo"); +#endif } /* @@ -945,7 +1041,9 @@ mapcmd(un) register char *p; register char c; char *dname; + struct maps *mp; /* the map structure we are working on */ + mp = exclam() ? immacs : arrows; if (skipend()) { int i; @@ -954,13 +1052,13 @@ mapcmd(un) ignchar(); if (inopen) pofix(); - for (i=0; arrows[i].mapto; i++) - if (arrows[i].cap) { - lprintf("%s", arrows[i].descr); + for (i=0; mp[i].mapto; i++) + if (mp[i].cap) { + lprintf("%s", mp[i].descr); putchar('\t'); - lprintf("%s", arrows[i].cap); + lprintf("%s", mp[i].cap); putchar('\t'); - lprintf("%s", arrows[i].mapto); + lprintf("%s", mp[i].mapto); putNFL(); } return; @@ -980,7 +1078,7 @@ mapcmd(un) ungetchar(c); if (un) { newline(); - addmac(lhs, NOSTR, NOSTR); + addmac(lhs, NOSTR, NOSTR, mp); return; } else error("Missing rhs"); @@ -1020,27 +1118,29 @@ mapcmd(un) } else { dname = lhs; } - addmac(lhs,rhs,dname); + addmac(lhs,rhs,dname,mp); } /* * Add a macro definition to those that already exist. The sequence of * chars "src" is mapped into "dest". If src is already mapped into something * this overrides the mapping. There is no recursion. Unmap is done by - * using NOSTR for dest. + * using NOSTR for dest. Dname is what to show in listings. mp is + * the structure to affect (arrows, etc). */ -addmac(src,dest,dname) +addmac(src,dest,dname,mp) register char *src, *dest, *dname; + register struct maps *mp; { register int slot, zer; - if (dest) { + if (dest && mp==arrows) { /* Make sure user doesn't screw himself */ /* * Prevent tail recursion. We really should be * checking to see if src is a suffix of dest - * but we are too lazy here, so we don't bother unless - * src is only 1 char long. + * but this makes mapping involving escapes that + * is reasonable mess up. */ if (src[1] == 0 && src[0] == dest[strlen(dest)-1]) error("No tail recursion"); @@ -1053,19 +1153,24 @@ addmac(src,dest,dname) */ if (isalpha(src[0]) && src[1] || any(src[0],":")) error("Too dangerous to map that"); - /* - * If the src were null it would cause the dest to - * be mapped always forever. This is not good. - */ - if (src[0] == 0) - error("Null lhs"); } + else if (dest) { + /* check for tail recursion in input mode: fussier */ + if (eq(src, dest+strlen(dest)-strlen(src))) + error("No tail recursion"); + } + /* + * If the src were null it would cause the dest to + * be mapped always forever. This is not good. + */ + if (src == NOSTR || src[0] == 0) + error("Missing lhs"); /* see if we already have a def for src */ zer = -1; - for (slot=0; arrows[slot].mapto; slot++) { - if (arrows[slot].cap) { - if (eq(src, arrows[slot].cap)) + for (slot=0; mp[slot].mapto; slot++) { + if (mp[slot].cap) { + if (eq(src, mp[slot].cap)) break; /* if so, reuse slot */ } else { zer = slot; /* remember an empty slot */ @@ -1074,9 +1179,9 @@ addmac(src,dest,dname) if (dest == NOSTR) { /* unmap */ - if (arrows[slot].cap) { - arrows[slot].cap = NOSTR; - arrows[slot].descr = NOSTR; + if (mp[slot].cap) { + mp[slot].cap = NOSTR; + mp[slot].descr = NOSTR; } else { error("Not mapped|That macro wasn't mapped"); } @@ -1084,7 +1189,7 @@ addmac(src,dest,dname) } /* reuse empty slot, if we found one and src isn't already defined */ - if (zer >= 0 && arrows[slot].mapto == 0) + if (zer >= 0 && mp[slot].mapto == 0) slot = zer; /* if not, append to end */ @@ -1096,18 +1201,18 @@ addmac(src,dest,dname) if (msnext - mapspace + strlen(dest) + strlen(src) + strlen(dname) + 3 > MAXCHARMACS) error("Too much macro text"); CP(msnext, src); - arrows[slot].cap = msnext; + mp[slot].cap = msnext; msnext += strlen(src) + 1; /* plus 1 for null on the end */ CP(msnext, dest); - arrows[slot].mapto = msnext; + mp[slot].mapto = msnext; msnext += strlen(dest) + 1; if (dname) { CP(msnext, dname); - arrows[slot].descr = msnext; + mp[slot].descr = msnext; msnext += strlen(dname) + 1; } else { /* default descr to string user enters */ - arrows[slot].descr = src; + mp[slot].descr = src; } } diff --git a/usr/src/usr.bin/ex/ex_data.c b/usr/src/usr.bin/ex/ex_data.c index 402d208b28..dd2953514d 100644 --- a/usr/src/usr.bin/ex/ex_data.c +++ b/usr/src/usr.bin/ex/ex_data.c @@ -6,21 +6,28 @@ * Initialization of option values. * The option #defines in ex_vars.h are made * from this file by the script makeoptions. + * + * These initializations are done char by char instead of as strings + * to confuse xstr so it will leave them alone. */ -char direct[32] = +char direct[ONMSZ] = { '/', 't', 'm', 'p' }; -char sections[32] = { - 'N', 'H', 'S', 'H', /* -ms macros */ - 'H', ' ', 'H', 'U' /* -mm macros */ -}; -char paragraphs[32] = { +char paragraphs[ONMSZ] = { 'I', 'P', 'L', 'P', 'P', 'P', 'Q', 'P', /* -ms macros */ 'P', ' ', 'L', 'I', /* -mm macros */ 'b', 'p' /* bare nroff */ }; -char shell[32] = +char sections[ONMSZ] = { + 'N', 'H', 'S', 'H', /* -ms macros */ + 'H', ' ', 'H', 'U' /* -mm macros */ +}; +char shell[ONMSZ] = { '/', 'b', 'i', 'n', '/', 's', 'h' }; -char ttytype[16] = +char tags[ONMSZ] = { + 't', 'a', 'g', 's', ' ', + '/', 'u', 's', 'r', '/', 'l', 'i', 'b', '/', 't', 'a', 'g', 's' +}; +char ttytype[ONMSZ] = { 'd', 'u', 'm', 'b' }; short COLUMNS = 80; @@ -39,13 +46,13 @@ struct option options[NOPTS + 1] = { "lisp", 0, ONOFF, 0, 0, 0, "list", 0, ONOFF, 0, 0, 0, "magic", 0, ONOFF, 1, 1, 0, - "mapinput", "mi", ONOFF, 0, 0, 0, "number", "nu", ONOFF, 0, 0, 0, "open", 0, ONOFF, 1, 1, 0, "optimize", "opt", ONOFF, 0, 0, 0, "paragraphs", "para", STRING, 0, 0, paragraphs, "prompt", 0, ONOFF, 1, 1, 0, "redraw", 0, ONOFF, 0, 0, 0, + "remap", 0, ONOFF, 1, 1, 0, "report", 0, NUMERIC, 5, 5, 0, "scroll", "scr", NUMERIC, 12, 12, 0, "sections", "sect", STRING, 0, 0, sections, @@ -53,10 +60,13 @@ struct option options[NOPTS + 1] = { "shiftwidth", "sw", NUMERIC, TABS, TABS, 0, "showmatch", "sm", ONOFF, 0, 0, 0, "slowopen", "slow", ONOFF, 0, 0, 0, + "tags", "tag", STRING, 0, 0, tags, "tabstop", "ts", NUMERIC, TABS, TABS, 0, - "ttytype", "tty", OTERM, 0, 0, ttytype, "term", 0, OTERM, 0, 0, ttytype, "terse", 0, ONOFF, 0, 0, 0, + "timeout", "to", ONOFF, 1, 1, 0, + "ttytype", "tty", OTERM, 0, 0, ttytype, + "undomacro", "um", ONOFF, 1, 1, 0, "warn", 0, ONOFF, 1, 1, 0, "window", "wi", NUMERIC, 23, 23, 0, "wrapscan", "ws", ONOFF, 1, 1, 0, diff --git a/usr/src/usr.bin/ex/ex_get.c b/usr/src/usr.bin/ex/ex_get.c index 4d19535174..873a511d1c 100644 --- a/usr/src/usr.bin/ex/ex_get.c +++ b/usr/src/usr.bin/ex/ex_get.c @@ -12,11 +12,7 @@ short lastc = '\n'; ignchar() { - register int c; - - do - c = getcd(); - while (c == CTRL(d)); + ignore(getchar()); } getchar() @@ -25,7 +21,7 @@ getchar() do c = getcd(); - while (c == CTRL(d)); + while (!globp && c == CTRL(d)); return (c); } @@ -39,7 +35,7 @@ again: return (c); c &= TRIM; if (!inopen) - if (c == CTRL(d)) + if (!globp && c == CTRL(d)) setlastchar('\n'); else if (junk(c)) { checkjunk(c); diff --git a/usr/src/usr.bin/ex/ex_io.c b/usr/src/usr.bin/ex/ex_io.c index d22f82ef87..3f0a227cce 100644 --- a/usr/src/usr.bin/ex/ex_io.c +++ b/usr/src/usr.bin/ex/ex_io.c @@ -218,6 +218,8 @@ glob(gp) close(1); dup(pvec[1]); close(pvec[0]); + close(2); /* so errors don't mess up the screen */ + open("/dev/null", 1); execl(svalue(SHELL), "sh", "-c", genbuf, 0); oerrno = errno; close(1); dup(2); errno = oerrno; filioerr(svalue(SHELL)); @@ -248,7 +250,7 @@ glob(gp) } while (c >= 0); waitfor(); if (gp->argc0 == 0) - error(NOSTR); + error("No match"); } /* @@ -346,7 +348,7 @@ rop(c) setdot(); else setall(); - if (inopen && c == 'r') + if (FIXUNDO && inopen && c == 'r') undap1 = undap2 = dot + 1; rop2(); rop3(c); @@ -389,7 +391,8 @@ other: dot = one; markpr(one); } - undkind = UNDNONE; + if(FIXUNDO) + undkind = UNDNONE; if (inopen) { vcline = 0; vreplace(0, LINES, lineDOL()); @@ -442,6 +445,8 @@ bool dofname; /* if 1 call filename, else use savedfile */ error("Write forms are 'w' and 'w>>'"); filename('w'); } else { + if (savedfile[0] == 0) + error("No file|No current filename"); saddr1=addr1; saddr2=addr2; addr1=one; @@ -632,7 +637,7 @@ uexp: vnfl(); if (hush == 0) lprintf("!%s", uxb); - if (inopen) { + if (inopen && Outchar != termchar) { vclreol(); vgoto(WECHO, 0); } else @@ -779,7 +784,8 @@ filter(mode) addr2 = addr1 - 1; } if (mode & 1) { - undap1 = undap2 = addr2+1; + if(FIXUNDO) + undap1 = undap2 = addr2+1; ignore(append(getfile, addr2)); } close(io); diff --git a/usr/src/usr.bin/ex/ex_put.c b/usr/src/usr.bin/ex/ex_put.c index c184d883e5..033c05bfea 100644 --- a/usr/src/usr.bin/ex/ex_put.c +++ b/usr/src/usr.bin/ex/ex_put.c @@ -554,10 +554,25 @@ dontcr: } } while (outcol < destcol) { - if (inopen && ND) + /* + * move one char to the right. We don't use ND space + * because it's better to just print the char we are + * moving over. There are various exceptions, however. + * If !inopen, vtube contains garbage. If the char is + * a null or a tab we want to print a space. Other random + * chars we use space for instead, too. + */ +#ifdef TRACE + if (trace) + fprintf(trace, "ND: inopen=%d, i=%d, outline=%d, outcol=%d\n", inopen, i, outline, outcol); +#endif + if (!inopen || vtube[outline]==NULL || + (i=vtube[outline][outcol]) < ' ') + i = ' '; + if (insmode && ND) tputs(ND, 0, plodput); else - plodput(' '); + plodput(i); outcol++; if (plodcnt < 0) goto out; @@ -768,7 +783,7 @@ ostart() #else tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) | RAW; #endif -#ifdef TIOCGETC +#ifdef EATQS nttyc.t_quitc = nttyc.t_startc = nttyc.t_stopc = '\377'; #endif sTTY(1); @@ -835,7 +850,7 @@ setty(f) { register int ot = tty.sg_flags; -#ifdef TIOCGETC +#ifdef EATQS if (f == normf) nttyc = ottyc; else @@ -851,7 +866,7 @@ gTTY(i) { ignore(gtty(i, &tty)); -#ifdef TIOCGETC +#ifdef EATQS ioctl(i, TIOCGETC, &ottyc); nttyc = ottyc; #endif @@ -873,7 +888,7 @@ sTTY(i) #else stty(i, &tty); #endif -#ifdef TIOCSETC +#ifdef EATQS ioctl(i, TIOCSETC, &nttyc); #endif } diff --git a/usr/src/usr.bin/ex/ex_re.c b/usr/src/usr.bin/ex/ex_re.c index 93abfaa00b..cf0692977b 100644 --- a/usr/src/usr.bin/ex/ex_re.c +++ b/usr/src/usr.bin/ex/ex_re.c @@ -73,6 +73,7 @@ out: newline(); *gp++ = c; *gp++ = 0; + saveall(); inglobal = 2; for (a1 = one; a1 <= dol; a1++) { *a1 &= ~01; @@ -80,7 +81,6 @@ out: *a1 |= 01; } /* should use gdelete from ed to avoid n**2 here on g/.../d */ - saveall(); if (inopen) inopen = -1; for (a1 = one; a1 <= dol; a1++) { @@ -115,7 +115,7 @@ substitute(c) int gsubf; gsubf = compsub(c); - if (!inglobal) + if(FIXUNDO) save12(), undkind = UNDCHANGE; stotal = 0; slines = 0; @@ -257,8 +257,10 @@ magic: case '\n': case EOF: - ungetchar(c); - goto endrhs; + if (!(globp && globp[0])) { + ungetchar(c); + goto endrhs; + } case '~': case '&': diff --git a/usr/src/usr.bin/ex/ex_set.c b/usr/src/usr.bin/ex/ex_set.c index 721836c551..bb7f2d8636 100644 --- a/usr/src/usr.bin/ex/ex_set.c +++ b/usr/src/usr.bin/ex/ex_set.c @@ -13,6 +13,7 @@ set() register struct option *op; register int c; bool no; + extern short ospeed; setnoaddr(); if (skipend()) { @@ -26,7 +27,7 @@ set() do { if (cp < &optname[ONMSZ - 2]) *cp++ = getchar(); - } while (isalpha(peekchar())); + } while (isalnum(peekchar())); *cp = 0; cp = optname; if (eq("all", cp)) { @@ -40,6 +41,24 @@ set() cp += 2; no++; } + /* Implement w300, w1200, and w9600 specially */ + if (eq(cp, "w300")) { + if (ospeed >= B1200) { +dontset: + ignore(getchar()); /* = */ + ignore(getnum()); /* value */ + continue; + } + cp = "window"; + } else if (eq(cp, "w1200")) { + if (ospeed < B1200 || ospeed >= B2400) + goto dontset; + cp = "window"; + } else if (eq(cp, "w9600")) { + if (ospeed < B2400) + goto dontset; + cp = "window"; + } for (op = options; op < &options[NOPTS]; op++) if (eq(op->oname, cp) || op->oabbrev && eq(op->oabbrev, cp)) break; @@ -67,10 +86,12 @@ printone: case NUMERIC: if (!isdigit(peekchar())) -error("Digits required@after = when assigning numeric option"); + error("Digits required@after ="); op->ovalue = getnum(); if (value(TABSTOP) <= 0) value(TABSTOP) = TABS; + if (op == &options[WINDOW]) + vsetsiz(value(WINDOW)); break; case STRING: diff --git a/usr/src/usr.bin/ex/ex_subr.c b/usr/src/usr.bin/ex/ex_subr.c index 1e17f4cb29..babd23393b 100644 --- a/usr/src/usr.bin/ex/ex_subr.c +++ b/usr/src/usr.bin/ex/ex_subr.c @@ -510,6 +510,12 @@ save(a1, a2) { register int more; + if (!FIXUNDO) + return; +#ifdef TRACE + if (trace) + vudump("before save"); +#endif undkind = UNDNONE; undadot = dot; more = (a2 - a1 + 1) - (unddol - dol); @@ -526,6 +532,10 @@ save(a1, a2) unddel = a1 - 1; undap1 = a1; undap2 = a2 + 1; +#ifdef TRACE + if (trace) + vudump("after save"); +#endif } save12() @@ -596,11 +606,11 @@ smerror(seekpt, cp) #ifdef lint char *std_errlist[] = { #else -#ifdef VMUNIX +# ifdef VMUNIX char *std_errlist[] = { -#else +# else short std_errlist[] = { -#endif +# endif #endif error("Error 0"), error("Not super-user"), diff --git a/usr/src/usr.bin/ex/ex_temp.c b/usr/src/usr.bin/ex/ex_temp.c index e8f87804f3..3f4bc5aebf 100644 --- a/usr/src/usr.bin/ex/ex_temp.c +++ b/usr/src/usr.bin/ex/ex_temp.c @@ -275,7 +275,11 @@ struct rbuf { short rb_next; char rb_text[BUFSIZ - 2 * sizeof (short)]; } *rbuf; +#ifdef VMUNIX +short rused[256]; +#else short rused[32]; +#endif short rnleft; short rblock; short rnext; @@ -396,17 +400,20 @@ putreg(c) error("Nothing in register %c", c); } if (inopen && partreg(c)) { + if (!FIXUNDO) { + splitw++; vclean(); vgoto(WECHO, 0); vreg = -1; + error("Can't put partial line inside macro"); + } squish(); addr1 = addr2 = dol; } - ignore(append(getREG, addr2)); + cnt = append(getREG, addr2); if (inopen && partreg(c)) { unddol = dol; dol = odol; dot = odot; pragged(0); } - cnt = undap2 - undap1; killcnt(cnt); notecnt = cnt; } diff --git a/usr/src/usr.bin/ex/ex_tty.c b/usr/src/usr.bin/ex/ex_tty.c index 62763af561..60853482ba 100644 --- a/usr/src/usr.bin/ex/ex_tty.c +++ b/usr/src/usr.bin/ex/ex_tty.c @@ -50,7 +50,7 @@ setterm(type) putpad(TE); if (tgetent(ltcbuf, type) != 1) { unknown++; - CP(genbuf, "xx|dumb:"); + CP(ltcbuf, "xx|dumb:"); } i = LINES = tgetnum("li"); if (LINES <= 5) @@ -59,9 +59,9 @@ setterm(type) LINES = 48; l = LINES; if (ospeed < B1200) - l /= 2; + l = 9; /* including the message line at the bottom */ else if (ospeed < B2400) - l = (l * 2) / 3; + l = 17; aoftspace = tspace; zap(); /* @@ -85,7 +85,7 @@ setterm(type) CA = 1, costCM = strlen(tgoto(CM, 8, 10)); PC = xPC ? xPC[0] : 0; aoftspace = tspace; - CP(ttytype, longname(genbuf, type)); + CP(ttytype, longname(ltcbuf, type)); if (i <= 0) LINES = 2; /* proper strings to change tty type */ diff --git a/usr/src/usr.bin/ex/ex_tty.h b/usr/src/usr.bin/ex/ex_tty.h index 0dc41fd0be..a4c69624f6 100644 --- a/usr/src/usr.bin/ex/ex_tty.h +++ b/usr/src/usr.bin/ex/ex_tty.h @@ -114,13 +114,19 @@ short WECHO; short costCM; -#define MAXNOMACS 32 /* max number of macros */ -#define MAXCHARMACS 512 /* max # of chars total in macros */ +#ifdef VMUNIX +# define MAXNOMACS 128 /* max number of macros of each kind */ +# define MAXCHARMACS 2048 /* max # of chars total in macros */ +#else +# define MAXNOMACS 32 /* max number of macros of each kind */ +# define MAXCHARMACS 512 /* max # of chars total in macros */ +#endif struct maps { char *cap; /* pressing button that sends this.. */ char *mapto; /* .. maps to this string */ char *descr; /* legible description of key */ }; struct maps arrows[MAXNOMACS]; /* macro defs - 1st 5 built in */ +struct maps immacs[MAXNOMACS]; /* for while in insert mode */ char mapspace[MAXCHARMACS]; char *msnext; /* next free location in mapspace */ diff --git a/usr/src/usr.bin/ex/ex_tune.h b/usr/src/usr.bin/ex/ex_tune.h index 192e9b8fe7..ddb0869e01 100644 --- a/usr/src/usr.bin/ex/ex_tune.h +++ b/usr/src/usr.bin/ex/ex_tune.h @@ -10,12 +10,11 @@ * "/usr/lib/..." here, "/lib" will be tried only for strings. */ #include "local/uparm.h" -#define EXRECOVER libpath(ex3.2recover) -#define EXPRESERVE libpath(ex3.2preserve) +#define EXRECOVER libpath(ex3.3recover) +#define EXPRESERVE libpath(ex3.3preserve) #ifndef VMUNIX -#define EXSTRINGS libpath(ex3.2strings) +#define EXSTRINGS libpath(ex3.3strings) #endif -#define MASTERTAGS libpath(tags) /* * If your system believes that tabs expand to a width other than @@ -43,7 +42,7 @@ #define RHSSIZE 256 /* Size of rhs of substitute */ #define NBRA 9 /* Number of re \( \) pairs */ #define TAGSIZE 32 /* Tag length */ -#define ONMSZ 32 /* Option name size */ +#define ONMSZ 64 /* Option name size */ #define GBSIZE 256 /* Buffer size */ #define UXBSIZE 128 /* Unix command buffer size */ #define VBSIZE 128 /* Partial line max size in visual */ diff --git a/usr/src/usr.bin/ex/ex_v.c b/usr/src/usr.bin/ex/ex_v.c index c42808b9f2..0f8afc4e81 100644 --- a/usr/src/usr.bin/ex/ex_v.c +++ b/usr/src/usr.bin/ex/ex_v.c @@ -318,11 +318,11 @@ vok(atube) vtube0 = atube; vclrbyte(atube, WCOLS * (WECHO - ZERO + 1)); for (i = 0; i < ZERO; i++) - vtube[i] = (char *) -20000; + vtube[i] = (char *) 0; for (; i <= WECHO; i++) vtube[i] = atube, atube += WCOLS; for (; i < TUBELINES; i++) - vtube[i] = (char *) -20000; + vtube[i] = (char *) 0; vutmp = atube; vundkind = VNONE; vUNDdot = 0; diff --git a/usr/src/usr.bin/ex/ex_vars.h b/usr/src/usr.bin/ex/ex_vars.h index c3bd859427..af2ea9f328 100644 --- a/usr/src/usr.bin/ex/ex_vars.h +++ b/usr/src/usr.bin/ex/ex_vars.h @@ -10,13 +10,13 @@ #define LISP 9 #define LIST 10 #define MAGIC 11 -#define MAPINPUT 12 -#define NUMBER 13 -#define OPEN 14 -#define OPTIMIZE 15 -#define PARAGRAPHS 16 -#define PROMPT 17 -#define REDRAW 18 +#define NUMBER 12 +#define OPEN 13 +#define OPTIMIZE 14 +#define PARAGRAPHS 15 +#define PROMPT 16 +#define REDRAW 17 +#define REMAP 18 #define REPORT 19 #define SCROLL 20 #define SECTIONS 21 @@ -24,14 +24,17 @@ #define SHIFTWIDTH 23 #define SHOWMATCH 24 #define SLOWOPEN 25 -#define TABSTOP 26 -#define TTYTYPE 27 +#define TAGS 26 +#define TABSTOP 27 #define TERM 28 #define TERSE 29 -#define WARN 30 -#define WINDOW 31 -#define WRAPSCAN 32 -#define WRAPMARGIN 33 -#define WRITEANY 34 +#define TIMEOUT 30 +#define TTYTYPE 31 +#define UNDOMACRO 32 +#define WARN 33 +#define WINDOW 34 +#define WRAPSCAN 35 +#define WRAPMARGIN 36 +#define WRITEANY 37 -#define NOPTS 35 +#define NOPTS 38 diff --git a/usr/src/usr.bin/ex/ex_vget.c b/usr/src/usr.bin/ex/ex_vget.c index a4645a03e4..4135d991f8 100644 --- a/usr/src/usr.bin/ex/ex_vget.c +++ b/usr/src/usr.bin/ex/ex_vget.c @@ -85,10 +85,6 @@ getATTN: vundkind = VMANY; inopen = 1; /* restore old setting now that macro done */ } -#ifdef TRACE - if (trace) - fflush(trace); -#endif flusho(); again: if (read(0, &ch, 1) != 1) { @@ -167,6 +163,11 @@ getesc() c = getkey(); switch (c) { + case CTRL(v): + case CTRL(q): + c = getkey(); + return (c); + case ATTN: case QUIT: ungetkey(c); @@ -408,10 +409,16 @@ map(c,maps) */ if ((c=='#' ? peekkey() : fastpeekkey()) == 0) { #ifdef MDEBUG - if (trace) - fprintf(trace,"fpk=0: return %c",c); + if (trace) + fprintf(trace,"fpk=0: return %c",c); #endif - macpush(&b[1],1); + /* + * We want to be able to undo + * commands, but it's nonsense + * to undo part of an insertion + * so if in input mode don't. + */ + macpush(&b[1],maps == arrows); return(c); } *q = getkey(); @@ -455,15 +462,18 @@ int canundo; if (st==0 || *st==0) return; + if (!value(UNDOMACRO)) + canundo = 0; #ifdef TRACE if (trace) - fprintf(trace, "macpush(%s)",st); + fprintf(trace, "macpush(%s), canundo=%d",st,canundo); #endif - if (strlen(vmacp) + strlen(st) > BUFSIZ) + if ((vmacp ? strlen(vmacp) : 0) + strlen(st) > BUFSIZ) error("Macro too long@ - maybe recursive?"); if (vmacp) { strcpy(tmpbuf, vmacp); - canundo = 0; /* can't undo inside a macro anyway */ + if (!FIXUNDO) + canundo = 0; /* can't undo inside a macro anyway */ } strcpy(vmacbuf, st); if (vmacp) @@ -471,17 +481,22 @@ int canundo; vmacp = vmacbuf; /* arrange to be able to undo the whole macro */ if (canundo) { - inopen = -1; /* no need to save since it had to be 1 or -1 before */ otchng = tchng; vsave(); saveall(); + inopen = -1; /* no need to save since it had to be 1 or -1 before */ vundkind = VMANY; } +} + #ifdef TRACE +vudump(s) +char *s; +{ if (trace) - fprintf(trace, "saveall for macro: undkind=%d, unddel=%d, undap1=%d, undap2=%d, dol=%d, unddol=%d, truedol=%d\n", undkind, lineno(unddel), lineno(undap1), lineno(undap2), lineno(dol), lineno(unddol), lineno(truedol)); -#endif + fprintf(trace, "%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n", s, undkind, vundkind, lineno(unddel), lineno(undap1), lineno(undap2), lineno(dot), lineno(dol), lineno(unddol), lineno(truedol)); } +#endif /* * Get a count from the keyed input stream. @@ -515,10 +530,21 @@ fastpeekkey() int trapalarm(); register int c; - if (inopen == -1) /* don't work inside macros! */ - return (0); - signal(SIGALRM, trapalarm); - alarm(1); + /* + * If the user has set notimeout, we wait forever for a key. + * If we are in a macro we do too, but since it's already + * buffered internally it will return immediately. + * In other cases we force this to die in 1 second. + * This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs, + * but UNIX truncates it to 0 - 1 secs) but due to system delays + * there are times when arrow keys or very fast typing get counted + * as separate. notimeout is provided for people who dislike such + * nondeterminism. + */ + if (value(TIMEOUT) && inopen >= 0) { + signal(SIGALRM, trapalarm); + alarm(1); + } CATCH c = peekkey(); #ifdef MDEBUG diff --git a/usr/src/usr.bin/ex/ex_vmain.c b/usr/src/usr.bin/ex/ex_vmain.c index e894dee246..cc763b349d 100644 --- a/usr/src/usr.bin/ex/ex_vmain.c +++ b/usr/src/usr.bin/ex/ex_vmain.c @@ -20,7 +20,8 @@ vmain() char *oglobp; char d; line *addr; - int ind; + int ind, nlput; + int shouldpo = 0; int onumber, olist, (*OPline)(), (*OPutchar)(); /* @@ -141,6 +142,8 @@ reread: ungetkey(c); goto looptop; } + if (!value(REMAP)) + break; } while (c != op); /* @@ -161,16 +164,23 @@ reread: /* * ^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. + * 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): + if (c == CTRL(l) || (KR && *KR==CTRL(l))) { + vclear(); + vdirty(0, vcnt); + } if (state != VISUAL) { /* * Get a clean line, throw away the @@ -209,7 +219,9 @@ reread: * in vmacbuf, point vglobp there and punt. */ case '@': - c = getkey(); + c = getesc(); + if (c == 0) + continue; if (c == '@') c = lastmac; if (isupper(c)) @@ -221,7 +233,7 @@ reread: char tmpbuf[BUFSIZ]; regbuf(c,tmpbuf,sizeof(vmacbuf)); - macpush(tmpbuf); + macpush(tmpbuf, 1); ONERR lastmac = 0; splitw = 0; @@ -500,7 +512,7 @@ reread: mbuf[3] = 0; if (isalpha(mbuf[1])) mbuf[1] ^= ' '; /* toggle the case */ - macpush(mbuf); + macpush(mbuf, 1); } continue; @@ -567,7 +579,9 @@ insrt: prepapp(); vnoapp(); doomed = c == 'R' ? 10000 : 0; - vundkind = VCHNG; + if(FIXUNDO) + vundkind = VCHNG; + vmoving = 0; CP(vutmp, linebuf); /* @@ -605,6 +619,7 @@ insrt: onintr(); /* fall into... */ +#ifdef notdef /* * q Quit back to command mode, unless called as * vi on command line in which case dont do it @@ -620,6 +635,7 @@ insrt: vrepaint(cursor); continue; } +#endif /* fall into... */ /* @@ -630,6 +646,17 @@ insrt: vsave(); 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 @@ -644,7 +671,7 @@ insrt: case 'P': case 'p': vmoving = 0; - forbid (inopen < 0); + forbid (!vreg && value(UNDOMACRO) && inopen < 0); /* * If previous delete was partial line, use an * append or insert to put it back so as to @@ -696,6 +723,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. */ + addr = dol; /* old dol */ CATCH vremote(1, vreg ? putreg : put, vreg); ONERR @@ -707,24 +735,31 @@ insrt: } 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. */ - undap1++, undap2++; + if (FIXUNDO) + undap1++, undap2++; 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. @@ -830,6 +865,14 @@ doinit: * 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 @@ -892,7 +935,7 @@ fixup: * a write command there, but its not * worth worrying about. */ - if (tchng && tchng != i) + if (FIXUNDO && tchng && tchng != i) vundkind = VMANY, cursor = 0; /* @@ -901,8 +944,10 @@ fixup: */ if (vcnt < 0 && Peekkey == ':') { getDOT(); + shouldpo = 1; continue; } + shouldpo = 0; /* * In the case where the file being edited is @@ -950,8 +995,9 @@ fixup: vcnt = -vcnt; if (state == VISUAL) vclear(); - else if (state == CRTOPEN) + else if (state == CRTOPEN) { vcnt = 0; + } } /* @@ -1059,12 +1105,12 @@ vremote(cnt, f, arg) addr1 = dot; addr2 = dot + cnt - 1; - if (inopen > 0) - undap1 = undap2 = dot; inglobal = 0; + if (FIXUNDO) + undap1 = undap2 = dot; (*f)(arg); inglobal = oing; - if (inopen > 0) + if (FIXUNDO) vundkind = VMANY; vmcurs = 0; } @@ -1077,7 +1123,7 @@ vsave() 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 diff --git a/usr/src/usr.bin/ex/ex_voper.c b/usr/src/usr.bin/ex/ex_voper.c index f65d7b2825..42812bf3fc 100644 --- a/usr/src/usr.bin/ex/ex_voper.c +++ b/usr/src/usr.bin/ex/ex_voper.c @@ -27,6 +27,7 @@ operate(c, cnt) bool subop = 0; char *oglobp, *ocurs; register line *addr; + line *odot; static char lastFKND, lastFCHR; char d; @@ -259,7 +260,7 @@ ein: case ',': forbid (lastFKND == 0); c = isupper(lastFKND) ? tolower(lastFKND) : toupper(lastFKND); - ungetkey(lastFCHR); + i = lastFCHR; if (vglobp == 0) vglobp = ""; subop++; @@ -279,7 +280,7 @@ ein: case ';': forbid (lastFKND == 0); c = lastFKND; - ungetkey(lastFCHR); + i = lastFCHR; subop++; goto nocount; @@ -298,11 +299,12 @@ ein: */ case 'f': /* find */ case 't': - i = getesc(); - if (i == 0) - return; - if (!subop) + if (!subop) { + i = getesc(); + if (i == 0) + return; *lastcp++ = i; + } if (vglobp == 0) lastFKND = c, lastFCHR = i; for (; cnt > 0; cnt--) @@ -597,13 +599,17 @@ errlab: vsetsiz(Xcnt); vsave(); ocurs = cursor; + odot = dot; wcursor = 0; if (readecho(c)) return; if (!vglobp) vscandir[0] = genbuf[0]; oglobp = globp; CP(vutmp, genbuf); globp = vutmp; - d = peekc; ungetchar(0); fixech(); + d = peekc; +fromsemi: + ungetchar(0); + fixech(); CATCH #ifndef CBREAK /* @@ -619,7 +625,10 @@ errlab: #ifndef CBREAK vraw(); #endif +slerr: globp = oglobp; + dot = odot; + cursor = ocurs; ungetchar(d); splitw = 0; vclean(); @@ -630,6 +639,14 @@ errlab: globp = ""; else if (peekc) --globp; + if (*globp == ';') { + /* /foo/;/bar/ */ + globp++; + dot = addr; + cursor = loc1; + goto fromsemi; + } + dot = odot; ungetchar(d); c = 0; if (*globp == 'z') @@ -639,8 +656,13 @@ errlab: i = 0; while (isdigit(*globp)) i = i * 10 + *globp++ - '0'; - if (*globp) + if (any(*globp, "^+-.")) c = *globp++; + if (*globp) { + /* random junk after the pattern */ + beep(); + goto slerr; + } globp = oglobp; splitw = 0; vmoving = 0; diff --git a/usr/src/usr.bin/ex/ex_vops.c b/usr/src/usr.bin/ex/ex_vops.c index 92a5f6829a..cb433c331c 100644 --- a/usr/src/usr.bin/ex/ex_vops.c +++ b/usr/src/usr.bin/ex/ex_vops.c @@ -81,7 +81,7 @@ vundo() notecnt = 1; if (undkind == UNDPUT && undap1 == undap2) { beep(); - return; + break; } /* * Undo() call below basically replaces undap1 to undap2-1 @@ -98,14 +98,14 @@ vundo() cnt = dot - addr; if (cnt < 0 || cnt > vcnt || state != VISUAL) { vjumpto(dot, NOSTR, '.'); - return; + break; } if (!savenote) notecnt = 0; vcline = cnt; vrepaint(vmcurs); vmcurs = 0; - return; + break; case VCHNG: case VCAPU: @@ -122,7 +122,7 @@ vundo() vsave(); vopen(dot, WBOT); vnline(cursor); - return; + break; } /* * Pseudo insert command. @@ -142,11 +142,11 @@ vundo() if (cursor > linebuf && cursor >= strend(linebuf)) cursor--; vfixcurs(); - return; + break; case VNONE: beep(); - return; + break; } } @@ -544,7 +544,8 @@ voOpen(c, cnt) } killU(); prepapp(); - vundkind = VMANY; + if (FIXUNDO) + vundkind = VMANY; if (state != VISUAL) c = WBOT + 1; else { @@ -641,6 +642,13 @@ vfilter() 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) { @@ -757,7 +765,8 @@ vrep(cnt) ungetkey(c); } CP(vutmp, linebuf); - vundkind = VCHNG; + if (FIXUNDO) + vundkind = VCHNG; wcursor = cursor + cnt; vUD1 = cursor; vUD2 = wcursor; CP(cursor, wcursor); @@ -783,7 +792,8 @@ vyankit() 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)) diff --git a/usr/src/usr.bin/ex/ex_vops2.c b/usr/src/usr.bin/ex/ex_vops2.c index 86334bc437..83041796f3 100644 --- a/usr/src/usr.bin/ex/ex_vops2.c +++ b/usr/src/usr.bin/ex/ex_vops2.c @@ -37,7 +37,8 @@ vdcMID() 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; @@ -326,7 +327,7 @@ vappend(ch, cnt, indent) * out dot before it changes so that undo will work * correctly later. */ - if (vundkind == VCHNG) { + if (FIXUNDO && vundkind == VCHNG) { vremote(1, yank, 0); undap1--; } @@ -442,9 +443,12 @@ vgetline(cnt, gcursor, aescaped) goto vadone; } ch = c = getkey() & (QUOTE|TRIM); - if (value(MAPINPUT)) - while ((ch = map(c, arrows)) != c) + if (vglobp == 0 && Peekkey == 0) + while ((ch = map(c, immacs)) != c) { c = ch; + if (!value(REMAP)) + break; + } if (!iglobp) { /* @@ -679,7 +683,7 @@ vbackup: CDCNT = 1; endim(); back1(); - vputc(' '); + vputchar(' '); goto vbackup; } if (vglobp && vglobp - iglobp >= 2 && diff --git a/usr/src/usr.bin/ex/ex_vput.c b/usr/src/usr.bin/ex/ex_vput.c index cadd33ab3c..36434a3d0b 100644 --- a/usr/src/usr.bin/ex/ex_vput.c +++ b/usr/src/usr.bin/ex/ex_vput.c @@ -767,9 +767,12 @@ vishft() goim(); up = tp + j * WCOLS - shft; i = shft; - do - vputchar(*up++); - while (--i); + do { + if (*up) + vputchar(*up++); + else + break; + } while (--i); } vigotoCL(tabstart); i = shft - (inssiz - doomed); @@ -1029,9 +1032,9 @@ vputchar(c) if (trace) tracec(c); #endif - /* Patch to fix problem of >79 chars on echo line: don't echo extras */ + /* Fix problem of >79 chars on echo line. */ if (destcol >= WCOLS-1 && splitw && destline == WECHO) - return; + pofix(); if (destcol >= WCOLS) { destline += destcol / WCOLS; destcol %= WCOLS; -- 2.20.1