From d266c41674825be66485f44ce1862b0486da9fb1 Mon Sep 17 00:00:00 2001 From: Mark Horton Date: Fri, 1 Aug 1980 07:21:26 -0800 Subject: [PATCH] release 3.4, June 24, 1980 SCCS-vsn: usr.bin/ex/ex.c 4.1 SCCS-vsn: usr.bin/ex/ex.h 4.1 SCCS-vsn: usr.bin/ex/ex_addr.c 4.1 SCCS-vsn: usr.bin/ex/ex_argv.h 4.1 SCCS-vsn: usr.bin/ex/ex_cmds.c 4.1 SCCS-vsn: usr.bin/ex/ex_cmds2.c 4.1 SCCS-vsn: usr.bin/ex/ex_cmdsub.c 4.1 SCCS-vsn: usr.bin/ex/ex_data.c 4.1 SCCS-vsn: usr.bin/ex/ex_get.c 4.1 SCCS-vsn: usr.bin/ex/ex_io.c 4.1 SCCS-vsn: usr.bin/ex/ex_put.c 4.1 SCCS-vsn: usr.bin/ex/ex_re.c 4.1 SCCS-vsn: usr.bin/ex/ex_re.h 4.1 SCCS-vsn: usr.bin/ex/ex_set.c 4.1 SCCS-vsn: usr.bin/ex/ex_subr.c 4.1 SCCS-vsn: usr.bin/ex/ex_temp.c 4.1 SCCS-vsn: usr.bin/ex/ex_temp.h 4.1 SCCS-vsn: usr.bin/ex/ex_tty.c 4.1 SCCS-vsn: usr.bin/ex/ex_tty.h 4.1 SCCS-vsn: usr.bin/ex/ex_tune.h 4.1 SCCS-vsn: usr.bin/ex/ex_v.c 4.1 SCCS-vsn: usr.bin/ex/ex_vadj.c 4.1 SCCS-vsn: usr.bin/ex/ex_vars.h 4.1 SCCS-vsn: usr.bin/ex/ex_vget.c 4.1 SCCS-vsn: usr.bin/ex/ex_vis.h 4.1 SCCS-vsn: usr.bin/ex/ex_vmain.c 4.1 SCCS-vsn: usr.bin/ex/ex_voper.c 4.1 SCCS-vsn: usr.bin/ex/ex_vops.c 4.1 SCCS-vsn: usr.bin/ex/ex_vops2.c 4.1 SCCS-vsn: usr.bin/ex/ex_vops3.c 4.1 SCCS-vsn: usr.bin/ex/ex_vput.c 4.1 SCCS-vsn: usr.bin/ex/ex_vwind.c 4.1 SCCS-vsn: usr.bin/ex/ex3.7preserve/ex3.7preserve.c 4.1 SCCS-vsn: usr.bin/ex/ex3.7recover/ex3.7recover.c 4.1 SCCS-vsn: usr.bin/ex/Makefile 4.1 SCCS-vsn: usr.bin/ex/OTHER/makefile.70 4.1 SCCS-vsn: usr.bin/ex/makeoptions 4.1 SCCS-vsn: usr.bin/ex/printf.c 4.1 --- usr/src/usr.bin/ex/Makefile | 9 +- usr/src/usr.bin/ex/OTHER/makefile.70 | 9 +- usr/src/usr.bin/ex/ex.c | 98 +++-- usr/src/usr.bin/ex/ex.h | 43 ++- .../usr.bin/ex/ex3.7recover/ex3.7recover.c | 5 + usr/src/usr.bin/ex/ex_addr.c | 7 +- usr/src/usr.bin/ex/ex_cmds.c | 81 +++- usr/src/usr.bin/ex/ex_cmds2.c | 30 +- usr/src/usr.bin/ex/ex_cmdsub.c | 49 ++- usr/src/usr.bin/ex/ex_data.c | 6 +- usr/src/usr.bin/ex/ex_io.c | 358 ++---------------- usr/src/usr.bin/ex/ex_put.c | 354 +++++++++++++---- usr/src/usr.bin/ex/ex_re.c | 24 +- usr/src/usr.bin/ex/ex_re.h | 2 +- usr/src/usr.bin/ex/ex_set.c | 2 + usr/src/usr.bin/ex/ex_subr.c | 41 +- usr/src/usr.bin/ex/ex_temp.c | 180 ++++++++- usr/src/usr.bin/ex/ex_tty.c | 57 ++- usr/src/usr.bin/ex/ex_tty.h | 51 ++- usr/src/usr.bin/ex/ex_tune.h | 10 +- usr/src/usr.bin/ex/ex_v.c | 13 +- usr/src/usr.bin/ex/ex_vadj.c | 10 +- usr/src/usr.bin/ex/ex_vars.h | 56 +-- usr/src/usr.bin/ex/ex_vget.c | 102 ++++- usr/src/usr.bin/ex/ex_vis.h | 16 +- usr/src/usr.bin/ex/ex_vmain.c | 54 ++- usr/src/usr.bin/ex/ex_voper.c | 3 + usr/src/usr.bin/ex/ex_vops.c | 113 +++++- usr/src/usr.bin/ex/ex_vops2.c | 106 +++++- usr/src/usr.bin/ex/ex_vops3.c | 12 +- usr/src/usr.bin/ex/ex_vput.c | 36 +- usr/src/usr.bin/ex/makeoptions | 67 ++-- 32 files changed, 1397 insertions(+), 607 deletions(-) diff --git a/usr/src/usr.bin/ex/Makefile b/usr/src/usr.bin/ex/Makefile index 77f5700299..bb182d77d7 100644 --- a/usr/src/usr.bin/ex/Makefile +++ b/usr/src/usr.bin/ex/Makefile @@ -1,4 +1,4 @@ -VERSION=3.3 +VERSION=3.4 # # Ex skeletal makefile for version 7 # @@ -41,7 +41,7 @@ CXREF= ${BINDIR}/cxref INCLUDE=/usr/include PR= pr OBJS= ex.o ex_addr.o ex_cmds.o ex_cmds2.o ex_cmdsub.o ex_data.o ex_get.o \ - ex_io.o ex_put.o ex_re.o ex_set.o ex_subr.o ex_temp.o ex_tty.o \ + ex_io.o ex_put.o ex_re.o ex_set.o ex_subr.o ex_temp.o ex_tty.o ex_unix.o \ ex_v.o ex_vadj.o ex_vget.o ex_vmain.o ex_voperate.o \ ex_vops.o ex_vops2.o ex_vops3.o ex_vput.o ex_vwind.o \ printf.o strings.o @@ -91,15 +91,17 @@ clean: -rm -f *.o x*.[cs] ninstall: a.out - -rm -f ${NBINDIR}/ex ${NBINDIR}/vi + -rm -f ${NBINDIR}/ex ${NBINDIR}/vi ${DESTDIR}${NBINDIR}/view cp a.out ${NBINDIR}/ex # -cp ex${VERSION}strings ${LIBDIR}/ex${VERSION}strings ln ${NBINDIR}/ex ${NBINDIR}/vi + ln ${DESTDIR}${NBINDIR}/ex ${DESTDIR}${NBINDIR}/view chmod 1755 ${NBINDIR}/ex install: a.out exrecover expreserve -rm -f ${DESTDIR}${BINDIR}/ex -rm -f ${DESTDIR}${BINDIR}/vi + -rm -f ${DESTDIR}${BINDIR}/view -rm -f ${DESTDIR}${BINDIR}/edit -rm -f ${DESTDIR}${BINDIR}/e -rm -f ${DESTDIR}/usr/bin/ex @@ -108,6 +110,7 @@ install: a.out exrecover expreserve ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/edit ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/e ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/vi + ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/view ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}/usr/bin/ex chmod 1755 ${DESTDIR}${BINDIR}/ex cp exrecover ${DESTDIR}${LIBDIR}/ex${VERSION}recover diff --git a/usr/src/usr.bin/ex/OTHER/makefile.70 b/usr/src/usr.bin/ex/OTHER/makefile.70 index 77f5700299..bb182d77d7 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.3 +VERSION=3.4 # # Ex skeletal makefile for version 7 # @@ -41,7 +41,7 @@ CXREF= ${BINDIR}/cxref INCLUDE=/usr/include PR= pr OBJS= ex.o ex_addr.o ex_cmds.o ex_cmds2.o ex_cmdsub.o ex_data.o ex_get.o \ - ex_io.o ex_put.o ex_re.o ex_set.o ex_subr.o ex_temp.o ex_tty.o \ + ex_io.o ex_put.o ex_re.o ex_set.o ex_subr.o ex_temp.o ex_tty.o ex_unix.o \ ex_v.o ex_vadj.o ex_vget.o ex_vmain.o ex_voperate.o \ ex_vops.o ex_vops2.o ex_vops3.o ex_vput.o ex_vwind.o \ printf.o strings.o @@ -91,15 +91,17 @@ clean: -rm -f *.o x*.[cs] ninstall: a.out - -rm -f ${NBINDIR}/ex ${NBINDIR}/vi + -rm -f ${NBINDIR}/ex ${NBINDIR}/vi ${DESTDIR}${NBINDIR}/view cp a.out ${NBINDIR}/ex # -cp ex${VERSION}strings ${LIBDIR}/ex${VERSION}strings ln ${NBINDIR}/ex ${NBINDIR}/vi + ln ${DESTDIR}${NBINDIR}/ex ${DESTDIR}${NBINDIR}/view chmod 1755 ${NBINDIR}/ex install: a.out exrecover expreserve -rm -f ${DESTDIR}${BINDIR}/ex -rm -f ${DESTDIR}${BINDIR}/vi + -rm -f ${DESTDIR}${BINDIR}/view -rm -f ${DESTDIR}${BINDIR}/edit -rm -f ${DESTDIR}${BINDIR}/e -rm -f ${DESTDIR}/usr/bin/ex @@ -108,6 +110,7 @@ install: a.out exrecover expreserve ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/edit ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/e ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/vi + ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}${BINDIR}/view ln ${DESTDIR}${BINDIR}/ex ${DESTDIR}/usr/bin/ex chmod 1755 ${DESTDIR}${BINDIR}/ex cp exrecover ${DESTDIR}${LIBDIR}/ex${VERSION}recover diff --git a/usr/src/usr.bin/ex/ex.c b/usr/src/usr.bin/ex/ex.c index fbb4c3aa73..b10ceb8779 100644 --- a/usr/src/usr.bin/ex/ex.c +++ b/usr/src/usr.bin/ex/ex.c @@ -52,6 +52,8 @@ char tttrace[] = { '/','d','e','v','/','t','t','y','x','x',0 }; * data base, grabbing of tty modes (at beginning * and after escapes). * + * ex_unix.c Routines for the ! command and its variations. + * * ex_v*.c Visual/open mode routines... see ex_v.c for a * guide to the overall organization. */ @@ -59,12 +61,11 @@ char tttrace[] = { '/','d','e','v','/','t','t','y','x','x',0 }; /* * Main procedure. Process arguments and then * transfer control to the main command processing loop - * in the routine commands. We are entered as either "ex", "edit" or "vi" - * and the distinction is made here. Actually, we are "vi" if - * there is a 'v' in our name, and "edit" if there is a 'd' in our - * name. For edit we just diddle options; for vi we actually - * force an early visual command, setting the external initev so - * the q command in visual doesn't give command mode. + * in the routine commands. We are entered as either "ex", "edit", "vi" + * or "view" and the distinction is made here. Actually, we are "vi" if + * there is a 'v' in our name, "view" is there is a 'w', and "edit" if + * there is a 'd' in our name. For edit we just diddle options; + * for vi we actually force an early visual command. */ main(ac, av) register int ac; @@ -88,33 +89,37 @@ main(ac, av) * get messed up if an interrupt comes in quickly. */ gTTY(1); +#ifndef USG3TTY normf = tty.sg_flags; +#else + normf = tty; +#endif ppid = getpid(); /* - * Defend against d's, v's, and a's in directories of + * Defend against d's, v's, w's, and a's in directories of * path leading to our true name. */ av[0] = tailpath(av[0]); - ivis = any('v', av[0]); /* - * For debugging take files out of . if name is a.out. - * If a 'd' in our name, then set options for edit. + * Figure out how we were invoked: ex, edit, vi, view. */ -#ifndef VMUNIX - if (av[0][0] == 'a') - erpath = tailpath(erpath); -#endif - if (ivis) { -#ifdef notdef - options[BEAUTIFY].odefault = value(BEAUTIFY) = 1; -#endif - } else if (any('d', av[0])) { + ivis = any('v', av[0]); /* "vi" */ + if (any('w', av[0])) /* "view" */ + value(READONLY) = 1; + if (any('d', av[0])) { /* "edit" */ value(OPEN) = 0; value(REPORT) = 1; value(MAGIC) = 0; } +#ifndef VMUNIX + /* + * For debugging take files out of . if name is a.out. + */ + if (av[0][0] == 'a') + erpath = tailpath(erpath); +#endif /* * Open the error message file. */ @@ -137,6 +142,10 @@ main(ac, av) ruptible = signal(SIGINT, SIG_IGN) == SIG_DFL; if (signal(SIGTERM, SIG_IGN) == SIG_DFL) signal(SIGTERM, onhup); +#ifdef TIOCLGET + if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) + signal(SIGTSTP, onsusp), dosusp++; +#endif /* * Initialize end of core pointers. @@ -161,6 +170,10 @@ main(ac, av) fast++; } else switch (c) { + case 'R': + value(READONLY) = 1; + break; + #ifdef TRACE case 'T': if (av[0][2] == 0) @@ -212,6 +225,11 @@ main(ac, av) defwind = 10*defwind + *cp - '0'; break; + case 'x': + /* -x: encrypted mode */ + xflag = 1; + break; + default: smerror("Unknown option %s\n", av[0]); break; @@ -223,6 +241,11 @@ main(ac, av) ac--, av++; } + if(xflag){ + key = getpass(KEYPROMPT); + kflag = crinit(key, perm); + } + /* * If we are doing a recover and no filename * was given, then execute an exrecover command with @@ -258,19 +281,24 @@ main(ac, av) setrupt(); intty = isatty(0); value(PROMPT) = intty; + if (cp = getenv("SHELL")) + CP(shell, cp); if (fast || !intty) setterm("dumb"); else { gettmode(); - if ((cp = getenv("TERM")) != 0) + if ((cp = getenv("TERM")) != 0 && *cp) setterm(cp); } } if (setexit() == 0 && !fast && intty) - if (globp = getenv("EXINIT")) + if ((globp = getenv("EXINIT")) && *globp) commands(1,1); - else if ((cp = getenv("HOME")) != 0) - source(strcat(strcpy(genbuf, cp), "/.exrc"), 1); + else { + globp = 0; + if ((cp = getenv("HOME")) != 0 && *cp) + source(strcat(strcpy(genbuf, cp), "/.exrc"), 1); + } /* * Initial processing. Handle tag, recover, and file argument @@ -342,9 +370,21 @@ init() undkind = UNDNONE; chng = 0; edited = 0; +#ifdef USG + signal (SIGHUP, SIG_IGN); +#endif +#ifdef USG3TTY +#ifndef USG + signal (SIGHUP, SIG_IGN); +#endif +#endif for (i = 0; i <= 'z'-'a'+1; i++) names[i] = 1; anymarks = 0; + if(xflag) { + xtflag = 1; + makekey(key, tperm); + } } /* @@ -360,6 +400,11 @@ init() onhup() { + /* + * USG tty driver can send multiple HUP's!! + */ + signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); if (chng == 0) { cleanup(1); exit(0); @@ -410,12 +455,17 @@ onintr() setrupt() { - if (ruptible) + if (ruptible) { #ifndef CBREAK signal(SIGINT, onintr); #else signal(SIGINT, inopen ? vintr : onintr); #endif +#ifdef TIOCLGET + if (dosusp) + signal(SIGTSTP, onsusp); +#endif + } } preserve() diff --git a/usr/src/usr.bin/ex/ex.h b/usr/src/usr.bin/ex/ex.h index e7a8d3d3c5..c9c0c76b3c 100644 --- a/usr/src/usr.bin/ex/ex.h +++ b/usr/src/usr.bin/ex/ex.h @@ -4,7 +4,7 @@ #endif /* - * Ex version 3.1 + * Ex version 3 (see exact version in ex_cmds.c, search for /Version/) * * Mark Horton, UC Berkeley * Bill Joy, UC Berkeley @@ -29,25 +29,40 @@ * * Please forward bug reports to * - * Bill Joy + * Mark Horton * Computer Science Division, EECS * EVANS HALL * U.C. Berkeley 94704 * (415) 642-4948 * (415) 642-1024 (dept. office) * - * or to wnj@mit-mc on the ARPA-net. I would particularly like to hear + * or to csvax.mark@berkeley on the ARPA-net. I would particularly like to hear * of additional terminal descriptions you add to the termcap data base. */ #include #include #include -#include #include #include #include +/* + * The following little dance copes with the new USG tty handling. + * This stuff has the advantage of considerable flexibility, and + * the disadvantage of being incompatible with anything else. + * The presence of the symbol USG3TTY will indicate the new code: + * in this case, we define CBREAK (because we can simulate it exactly), + * but we won't actually use it, so we set it to a value that will + * probably blow the compilation if we goof up. + */ +#ifdef USG3TTY +#include +#define CBREAK xxxxx +#else +#include +#endif + extern int errno; #ifndef VMUNIX @@ -142,6 +157,9 @@ int chng; /* Warn "No write" */ char *Command; short defwind; /* -w# change default window size */ int dirtcnt; /* When >= MAXDIRT, should sync temporary */ +#ifdef TIOCLGET +bool dosusp; /* Do SIGTSTP in visual when ^Z typed */ +#endif bool edited; /* Current file is [Edited] */ line *endcore; /* Last available core location */ bool endline; /* Last cmd mode command ended with \n */ @@ -154,6 +172,7 @@ char genbuf[LBSIZE]; /* Working buffer when manipulating linebuf */ bool hush; /* Command line option - was given, hush up! */ char *globp; /* (Untyped) input string to command mode */ bool holdcm; /* Don't cursor address */ +bool inappend; /* in ex command append mode */ bool inglobal; /* Inside g//... or v//... */ char *initev; /* Initial : escape for visual */ bool inopen; /* Inside open or visual */ @@ -173,6 +192,7 @@ line names['z'-'a'+2]; /* Mark registers a-z,' */ int notecnt; /* Count for notify (to visual from cmd) */ bool numberf; /* Command should run in number mode */ char obuf[BUFSIZ]; /* Buffer for tty output */ +short oprompt; /* Saved during source */ short ospeed; /* Output speed (from gtty) */ int otchng; /* Backup tchng to find changes in macros */ short peekc; /* Peek ahead character (cmd mode input) */ @@ -276,6 +296,20 @@ line *undadot; /* If we saved all lines, dot reverts here */ #define UNDNONE 3 #define UNDPUT 4 +/* + * Various miscellaneous flags and buffers needed by the encryption routines. + */ +#define KSIZE 9 /* key size for encryption */ +#define KEYPROMPT "Key: " +int xflag; /* True if we are in encryption mode */ +int xtflag; /* True if the temp file is being encrypted */ +int kflag; /* True if the key has been accepted */ +char perm[768]; +char tperm[768]; +char *key; +char crbuf[CRSIZE]; +char *getpass(); + /* * Function type definitions */ @@ -333,6 +367,7 @@ int numbline(); int (*oldquit)(); int onhup(); int onintr(); +int onsusp(); int putch(); int shift(); int termchar(); diff --git a/usr/src/usr.bin/ex/ex3.7recover/ex3.7recover.c b/usr/src/usr.bin/ex/ex3.7recover/ex3.7recover.c index 9781fb9f8d..218e65a8a3 100644 --- a/usr/src/usr.bin/ex/ex3.7recover/ex3.7recover.c +++ b/usr/src/usr.bin/ex/ex3.7recover/ex3.7recover.c @@ -175,8 +175,13 @@ error(str, inf) { fprintf(stderr, str, inf); +#ifndef USG3TTY gtty(2, &tty); if ((tty.sg_flags & RAW) == 0) +#else + ioctl(2, TCGETA, &tty); + if (tty.c_lflag & ICANON) +#endif fprintf(stderr, "\n"); exit(1); } diff --git a/usr/src/usr.bin/ex/ex_addr.c b/usr/src/usr.bin/ex/ex_addr.c index 5621e5e590..afe1b7c119 100644 --- a/usr/src/usr.bin/ex/ex_addr.c +++ b/usr/src/usr.bin/ex/ex_addr.c @@ -192,9 +192,12 @@ address(inline) addr = dot; if (inline && execute(0, dot)) { if (c == '/') { - while (loc1 <= inline) + while (loc1 <= inline) { + if (loc1 == loc2) + loc2++; if (!execute(1)) goto nope; + } break; } else if (loc1 < inline) { char *last; @@ -202,6 +205,8 @@ doques: do { last = loc1; + if (loc1 == loc2) + loc2++; if (!execute(1)) break; } while (loc1 < inline); diff --git a/usr/src/usr.bin/ex/ex_cmds.c b/usr/src/usr.bin/ex/ex_cmds.c index a85b1b2886..7e85951e1f 100644 --- a/usr/src/usr.bin/ex/ex_cmds.c +++ b/usr/src/usr.bin/ex/ex_cmds.c @@ -137,7 +137,15 @@ choice: case 'a': - if (peekchar() == 'r') { + switch(peekchar()) { + case 'b': +/* abbreviate */ + tail("abbreviate"); + setnoaddr(); + mapcmd(0, 1); + anyabbrs = 1; + continue; + case 'r': /* args */ tail("args"); setnoaddr(); @@ -153,9 +161,12 @@ choice: setdot(); aiflag = exclam(); newline(); + vmacchng(0); deletenone(); setin(addr2); + inappend = 1; ignore(append(gettty, addr2)); + inappend = 0; nochng(); continue; @@ -165,6 +176,7 @@ choice: /* copy */ case 'o': tail("copy"); + vmacchng(0); move(); continue; @@ -213,9 +225,12 @@ changdir: /* change */ aiflag = exclam(); setCNL(); + vmacchng(0); setin(addr1); delete(0); + inappend = 1; ignore(append(gettty, addr1 - 1)); + inappend = 0; nochng(); continue; @@ -227,6 +242,7 @@ changdir: tail("delete"); c = cmdreg(); setCNL(); + vmacchng(0); if (c) YANKreg(c); delete(0); @@ -237,6 +253,7 @@ changdir: /* ex */ case 'e': tail(peekchar() == 'x' ? "ex" : "edit"); +editcmd: if (!exclam() && chng) c = 'E'; filename(c); @@ -281,9 +298,12 @@ doecmd: nonzero(); aiflag = exclam(); newline(); + vmacchng(0); deletenone(); setin(addr2); + inappend = 1; ignore(append(gettty, addr2 - 1)); + inappend = 0; if (dot == zero && dol > zero) dot = one; nochng(); @@ -296,6 +316,7 @@ doecmd: setcount(); nonzero(); newline(); + vmacchng(0); if (given < 2 && addr2 != dol) addr2++; join(c); @@ -332,7 +353,7 @@ casek: /* map */ tail2of("map"); setnoaddr(); - mapcmd(0); + mapcmd(0, 0); continue; } /* mark */ @@ -341,6 +362,7 @@ casek: } /* move */ tail("move"); + vmacchng(0); move(); continue; @@ -379,6 +401,7 @@ casek: setdot(); c = cmdreg(); eol(); + vmacchng(0); if (c) putreg(c); else @@ -429,8 +452,11 @@ quit: if (!ateopr()) vnfl(); else { + tostop(); + /* replaced by tostop putpad(VE); putpad(KE); + */ } flush(); setty(normf); @@ -447,8 +473,9 @@ quit: case 'w': tail2of("rewind"); setnoaddr(); - ignore(quickly()); eol(); + ckaw(); + ignore(quickly()); erewind(); next(); c = 'e'; @@ -489,6 +516,7 @@ quit: if (savedfile[0] == 0 && dol == zero) c = 'e'; pastwh(); + vmacchng(0); if (peekchar() == '!') { setdot(); ignchar(); @@ -538,6 +566,21 @@ quit: eol(); source(file, 0); continue; +#ifdef TIOCLGET +/* stop */ + case 't': + tail("stop"); + if (!ldisc) + error("Old tty driver|Not using new tty driver/shell"); + c = exclam(); + eol(); + if (!c) + ckaw(); + eol(); + onsusp(); + continue; +#endif + } /* fall into ... */ @@ -549,6 +592,7 @@ quit: Command = "substitute"; if (c == 's') tail(Command); + vmacchng(0); if (!substitute(c)) pflag = 0; continue; @@ -565,17 +609,26 @@ quit: continue; } tail("t"); + vmacchng(0); move(); continue; case 'u': if (peekchar() == 'n') { -/* unmap */ ignchar(); - if (peekchar() == 'm') { + switch(peekchar()) { +/* unmap */ + case 'm': tail2of("unmap"); setnoaddr(); - mapcmd(1); + mapcmd(1, 0); + continue; +/* unabbreviate */ + case 'a': + tail2of("unabbreviate"); + setnoaddr(); + mapcmd(1, 1); + anyabbrs = 1; continue; } /* undo */ @@ -597,13 +650,17 @@ quit: tail("version"); setNAEOL(); /* should use SCCS subst here */ - printf("Version 3.3, February 2, 1980"); + printf("Version 3.4, June 24, 1980"); noonl(); continue; /* visual */ case 'i': tail("visual"); + if (inopen) { + c = 'e'; + goto editcmd; + } vop(); pflag = 0; nochng(); @@ -649,6 +706,7 @@ wq: c = cmdreg(); setcount(); eol(); + vmacchng(0); if (c) YANKreg(c); else @@ -714,6 +772,11 @@ caseline: plines(addr1, addr2, 1); continue; +/* " */ + case '"': + comment(); + continue; + /* # */ case '#': numberit: @@ -735,6 +798,7 @@ numberit: /* ! */ case '!': if (addr2 != 0) { + vmacchng(0); unix0(0); setdot(); filter(2); @@ -744,7 +808,7 @@ numberit: putpad(TE); flush(); unixwt(1, unixex("-c", uxb, 0, 0)); - vcontin(0); + vclrech(1); /* vcontin(0); */ nochng(); } continue; @@ -756,6 +820,7 @@ numberit: for (cnt = 1; peekchar() == c; cnt++) ignchar(); setCNL(); + vmacchng(0); shift(c, cnt); continue; diff --git a/usr/src/usr.bin/ex/ex_cmds2.c b/usr/src/usr.bin/ex/ex_cmds2.c index fd1d68fbe0..67210cc353 100644 --- a/usr/src/usr.bin/ex/ex_cmds2.c +++ b/usr/src/usr.bin/ex/ex_cmds2.c @@ -39,6 +39,7 @@ endcmd(ch) return (1); case '|': + case '"': endline = 0; return (1); } @@ -102,6 +103,10 @@ erewind() error0() { + if (laste) { + laste = 0; + sync(); + } if (vcatch) { if (splitw == 0) fixech(); @@ -118,10 +123,6 @@ error0() setoutt(); flush(); resetflav(); - if (laste) { - laste = 0; - sync(); - } if (!SO || !SE) dingdong(); if (inopen) { @@ -132,8 +133,10 @@ error0() COLUMNS = OCOLUMNS; undvis(); ostop(normf); + /* ostop should be doing this putpad(VE); putpad(KE); + */ putnl(); } inopen = 0; @@ -158,7 +161,7 @@ error1(str) io = -1; } die = (getpid() != ppid); /* Only children die */ - inglobal = 0; + inappend = inglobal = 0; globp = vglobp = vmacp = 0; if (vcatch && !die) { inopen = 1; @@ -228,10 +231,12 @@ makargs() */ next() { + extern short isalt; /* defined in ex_io.c */ if (argc == 0) error("No more files@to edit"); morargc = argc; + isalt = (strcmp(altfile, args)==0) + 1; if (savedfile[0]) CP(altfile, savedfile); CP(savedfile, args); @@ -277,6 +282,11 @@ newline() case '\t': continue; + case '"': + comment(); + setflav(); + return; + default: if (!endcmd(c)) serror("Extra chars|Extra characters at end of \"%s\" command", Command); @@ -378,7 +388,7 @@ skipend() { pastwh(); - return (endcmd(peekchar())); + return (endcmd(peekchar()) && peekchar() != '"'); } /* @@ -503,10 +513,13 @@ vcontin(ask) } } vclrech(1); - if (ask && Peekkey != ':') { + if (Peekkey != ':') { putpad(TI); + tostart(); + /* replaced by ostart. putpad(VS); putpad(KS); + */ } } } @@ -525,8 +538,11 @@ vnfl() vmoveitup(1, 0); vgoto(WECHO, 0); vclrbyte(vtube[WECHO], WCOLS); + tostop(); + /* replaced by the ostop above putpad(VE); putpad(KE); + */ } flush(); } diff --git a/usr/src/usr.bin/ex/ex_cmdsub.c b/usr/src/usr.bin/ex/ex_cmdsub.c index 8bd125a2e0..ae7b2f6f49 100644 --- a/usr/src/usr.bin/ex/ex_cmdsub.c +++ b/usr/src/usr.bin/ex/ex_cmdsub.c @@ -3,6 +3,7 @@ #include "ex_argv.h" #include "ex_temp.h" #include "ex_tty.h" +#include "ex_vis.h" /* * Command mode subroutines implementing @@ -12,6 +13,7 @@ bool endline = 1; line *tad1; +static jnoop(); /* * Append after line a lines returned by function f. @@ -213,7 +215,11 @@ join(c) strcLIN(genbuf); delete(0); jcount = 1; + if (FIXUNDO) + undap1 = undap2 = addr1; ignore(append(jnoop, --addr1)); + if (FIXUNDO) + vundkind = VMANY; } static @@ -524,6 +530,7 @@ badtag: io = open(fn, 0); if (io<0) continue; + tfcount++; while (getfile() == 0) { #endif /* loop for each tags file entry */ @@ -541,7 +548,7 @@ badtag: #endif while (*cp && *lp == *cp) cp++, lp++; - if (*lp || !iswhite(*cp)) { + if ((*lp || !iswhite(*cp)) && (value(TAGLENGTH)==0 || lp-lasttag < value(TAGLENGTH))) { #ifdef VMUNIX if (*lp > *cp) bot = mid + 1; @@ -560,6 +567,10 @@ badtag: #else close(io); #endif + /* Rest of tag if abbreviated */ + while (!iswhite(*cp)) + cp++; + /* name of file */ while (*cp && iswhite(*cp)) cp++; @@ -582,7 +593,7 @@ badtags: */ names['t'-'a'] = *dot &~ 01; if (inopen) { - extern char *ncols['z'-'a'+1]; + extern char *ncols['z'-'a'+2]; extern char *cursor; ncols['t'-'a'] = cursor; @@ -985,7 +996,11 @@ undo(c) } else undkind = UNDCHANGE; } - if (dot == zero && dot != dol) + /* + * Defensive programming - after a munged undadot. + * Also handle empty buffer case. + */ + if ((dot <= zero || dot > dol) && dot != dol) dot = one; #ifdef TRACE if (trace) @@ -1034,22 +1049,25 @@ somechange() * Map command: * map src dest */ -mapcmd(un) +mapcmd(un, ab) int un; /* true if this is unmap command */ + int ab; /* true if this is abbr command */ { - char lhs[10], rhs[100]; /* max sizes resp. */ + char lhs[100], rhs[100]; /* max sizes resp. */ register char *p; register char c; char *dname; struct maps *mp; /* the map structure we are working on */ - mp = exclam() ? immacs : arrows; + mp = ab ? abbrevs : exclam() ? immacs : arrows; if (skipend()) { int i; /* print current mapping values */ if (peekchar() != EOF) ignchar(); + if (un) + error("Missing lhs"); if (inopen) pofix(); for (i=0; mp[i].mapto; i++) @@ -1069,15 +1087,14 @@ mapcmd(un) c = getchar(); if (c == CTRL(v)) { c = getchar(); - } else if (any(c, " \t")) { - if (un) - eol(); /* will usually cause an error */ - else - break; - } else if (endcmd(c)) { + } else if (!un && any(c, " \t")) { + /* End of lhs */ + break; + } else if (endcmd(c) && c!='"') { ungetchar(c); if (un) { newline(); + *p = 0; addmac(lhs, NOSTR, NOSTR, mp); return; } else @@ -1093,7 +1110,7 @@ mapcmd(un) c = getchar(); if (c == CTRL(v)) { c = getchar(); - } else if (endcmd(c)) { + } else if (endcmd(c) && c!='"') { ungetchar(c); break; } @@ -1134,6 +1151,10 @@ addmac(src,dest,dname,mp) { register int slot, zer; +#ifdef TRACE + if (trace) + fprintf(trace, "addmac(src='%s', dest='%s', dname='%s', mp=%x\n", src, dest, dname, mp); +#endif if (dest && mp==arrows) { /* Make sure user doesn't screw himself */ /* @@ -1170,7 +1191,7 @@ addmac(src,dest,dname,mp) zer = -1; for (slot=0; mp[slot].mapto; slot++) { if (mp[slot].cap) { - if (eq(src, mp[slot].cap)) + if (eq(src, mp[slot].cap) || eq(src, mp[slot].mapto)) break; /* if so, reuse slot */ } else { zer = slot; /* remember an empty slot */ diff --git a/usr/src/usr.bin/ex/ex_data.c b/usr/src/usr.bin/ex/ex_data.c index dd2953514d..5883f163df 100644 --- a/usr/src/usr.bin/ex/ex_data.c +++ b/usr/src/usr.bin/ex/ex_data.c @@ -46,11 +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, + "mesg", 0, ONOFF, 1, 1, 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, + "readonly", "ro", ONOFF, 0, 0, 0, "redraw", 0, ONOFF, 0, 0, 0, "remap", 0, ONOFF, 1, 1, 0, "report", 0, NUMERIC, 5, 5, 0, @@ -60,13 +62,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, + "taglength", "tl", NUMERIC, 0, 0, 0, + "tags", "tag", STRING, 0, 0, tags, "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_io.c b/usr/src/usr.bin/ex/ex_io.c index 3f0a227cce..1c329dd062 100644 --- a/usr/src/usr.bin/ex/ex_io.c +++ b/usr/src/usr.bin/ex/ex_io.c @@ -6,7 +6,7 @@ #include "ex_vis.h" /* - * File input/output, unix escapes, source, filtering preserve and recover + * File input/output, source, preserve and recover */ /* @@ -16,6 +16,7 @@ int altdot; int oldadot; bool wasalt; +short isalt; long cntch; /* Count of characters on unit io */ #ifndef VMUNIX @@ -42,8 +43,11 @@ filename(comm) if (savedfile[0] == 0 && comm != 'f') error("No file|No current filename"); CP(file, savedfile); - wasalt = 0; + wasalt = (isalt > 0) ? isalt-1 : 0; + isalt = 0; oldadot = altdot; + if (c == 'e' || c == 'E') + altdot = lineDOT(); if (d == EOF) ungetchar(d); } else { @@ -84,6 +88,8 @@ filename(comm) if (file[0] != 0) { lprintf("\"%s\"", file); if (comm == 'f') { + if (value(READONLY)) + printf(" [Read only]"); if (!edited) printf(" [Not edited]"); if (tchng) @@ -138,7 +144,7 @@ getargs() switch (c) { case '\\': - if (any(peekchar(), "#%")) + if (any(peekchar(), "#%|")) c = getchar(); /* fall into... */ @@ -322,6 +328,8 @@ rop(c) error(" Directory"); case S_IFREG: + if (xflag) + break; i = read(io, (char *) &magic, sizeof(magic)); lseek(io, 0l, 0); if (i != sizeof(magic)) @@ -462,7 +470,8 @@ bool dofname; /* if 1 call filename, else use savedfile */ switch (c) { case 0: - if (!exclam && !value(WRITEANY)) switch (edfile()) { + if (!exclam && (!value(WRITEANY) || value(READONLY))) + switch (edfile()) { case NOTEDF: if (nonexist) @@ -481,7 +490,14 @@ bool dofname; /* if 1 call filename, else use savedfile */ close(io); break; + case EDF: + if (value(READONLY)) + error(" File is read only"); + break; + case PARTBUF: + if (value(READONLY)) + error(" File is read only"); error(" Use \"w!\" to write partial buffer"); } cre: @@ -539,318 +555,6 @@ edfile() return (addr1 == one && addr2 == dol ? EDF : PARTBUF); } -/* - * First part of a shell escape, - * parse the line, expanding # and % and ! and printing if implied. - */ -unix0(warn) - bool warn; -{ - register char *up, *fp; - register short c; - char printub, puxb[UXBSIZE + sizeof (int)]; - - printub = 0; - CP(puxb, uxb); - c = getchar(); - if (c == '\n' || c == EOF) - error("Incomplete shell escape command@- use 'shell' to get a shell"); - up = uxb; - do { - switch (c) { - - case '\\': - if (any(peekchar(), "%#!")) - c = getchar(); - default: - if (up >= &uxb[UXBSIZE]) { -tunix: - uxb[0] = 0; - error("Command too long"); - } - *up++ = c; - break; - - case '!': - fp = puxb; - if (*fp == 0) { - uxb[0] = 0; - error("No previous command@to substitute for !"); - } - printub++; - while (*fp) { - if (up >= &uxb[UXBSIZE]) - goto tunix; - *up++ = *fp++; - } - break; - - case '#': - fp = altfile; - if (*fp == 0) { - uxb[0] = 0; - error("No alternate filename@to substitute for #"); - } - goto uexp; - - case '%': - fp = savedfile; - if (*fp == 0) { - uxb[0] = 0; - error("No filename@to substitute for %%"); - } -uexp: - printub++; - while (*fp) { - if (up >= &uxb[UXBSIZE]) - goto tunix; - *up++ = *fp++ | QUOTE; - } - break; - } - c = getchar(); - } while (c == '|' || !endcmd(c)); - if (c == EOF) - ungetchar(c); - *up = 0; - if (!inopen) - resetflav(); - if (warn) - ckaw(); - if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) { - xchng = chng; - vnfl(); - printf(mesg("[No write]|[No write since last change]")); - noonl(); - flush(); - } else - warn = 0; - if (printub) { - if (uxb[0] == 0) - error("No previous command@to repeat"); - if (inopen) { - splitw++; - vclean(); - vgoto(WECHO, 0); - } - if (warn) - vnfl(); - if (hush == 0) - lprintf("!%s", uxb); - if (inopen && Outchar != termchar) { - vclreol(); - vgoto(WECHO, 0); - } else - putnl(); - flush(); - } -} - -/* - * Do the real work for execution of a shell escape. - * Mode is like the number passed to open system calls - * and indicates filtering. If input is implied, newstdin - * must have been setup already. - */ -unixex(opt, up, newstdin, mode) - char *opt, *up; - int newstdin, mode; -{ - int pvec[2], f; - - signal(SIGINT, SIG_IGN); - if (inopen) - f = setty(normf); - if ((mode & 1) && pipe(pvec) < 0) { - /* Newstdin should be io so it will be closed */ - if (inopen) - setty(f); - error("Can't make pipe for filter"); - } -#ifndef VFORK - pid = fork(); -#else - pid = vfork(); -#endif - if (pid < 0) { - if (mode & 1) { - close(pvec[0]); - close(pvec[1]); - } - setrupt(); - error("No more processes"); - } - if (pid == 0) { - if (mode & 2) { - close(0); - dup(newstdin); - close(newstdin); - } - if (mode & 1) { - close(pvec[0]); - close(1); - dup(pvec[1]); - if (inopen) { - close(2); - dup(1); - } - close(pvec[1]); - } - if (io) - close(io); - if (tfile) - close(tfile); -#ifndef VMUNIX - close(erfile); -#endif - signal(SIGHUP, oldhup); - signal(SIGQUIT, oldquit); - if (ruptible) - signal(SIGINT, SIG_DFL); - execl(svalue(SHELL), "sh", opt, up, (char *) 0); - printf("No %s!\n", svalue(SHELL)); - error(NOSTR); - } - if (mode & 1) { - io = pvec[0]; - close(pvec[1]); - } - if (newstdin) - close(newstdin); - return (f); -} - -/* - * Wait for the command to complete. - * F is for restoration of tty mode if from open/visual. - * C flags suppression of printing. - */ -unixwt(c, f) - bool c; - int f; -{ - - waitfor(); - if (inopen) - setty(f); - setrupt(); - if (!inopen && c && hush == 0) { - printf("!\n"); - flush(); - termreset(); - gettmode(); - } -} - -/* - * Setup a pipeline for the filtration implied by mode - * which is like a open number. If input is required to - * the filter, then a child editor is created to write it. - * If output is catch it from io which is created by unixex. - */ -filter(mode) - register int mode; -{ - static int pvec[2]; - register int f; - register int lines = lineDOL(); - - mode++; - if (mode & 2) { - signal(SIGINT, SIG_IGN); - if (pipe(pvec) < 0) - error("Can't make pipe"); - pid = fork(); - io = pvec[0]; - if (pid < 0) { - setrupt(); - close(pvec[1]); - error("No more processes"); - } - if (pid == 0) { - setrupt(); - io = pvec[1]; - close(pvec[0]); - putfile(); - exit(0); - } - close(pvec[1]); - io = pvec[0]; - setrupt(); - } - f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode); - if (mode == 3) { - delete(0); - addr2 = addr1 - 1; - } - if (mode & 1) { - if(FIXUNDO) - undap1 = undap2 = addr2+1; - ignore(append(getfile, addr2)); - } - close(io); - io = -1; - unixwt(!inopen, f); - netchHAD(lines); -} - -/* - * Set up to do a recover, getting io to be a pipe from - * the recover process. - */ -recover() -{ - static int pvec[2]; - - if (pipe(pvec) < 0) - error(" Can't make pipe for recovery"); - pid = fork(); - io = pvec[0]; - if (pid < 0) { - close(pvec[1]); - error(" Can't fork to execute recovery"); - } - if (pid == 0) { - close(2); - dup(1); - close(1); - dup(pvec[1]); - close(pvec[1]); - execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0); - close(1); - dup(2); - error(" No recovery routine"); - } - close(pvec[1]); -} - -/* - * Wait for the process (pid an external) to complete. - */ -waitfor() -{ - - do - rpid = wait(&status); - while (rpid != pid && rpid != -1); - status = (status >> 8) & 0377; -} - -/* - * The end of a recover operation. If the process - * exits non-zero, force not edited; otherwise force - * a write. - */ -revocer() -{ - - waitfor(); - if (pid == rpid && status != 0) - edited = 0; - else - change(); -} - /* * Extract the next line from the io stream. */ @@ -868,12 +572,23 @@ getfile() ninbuf = read(io, genbuf, LBSIZE) - 1; if (ninbuf < 0) { if (lp != linebuf) { + lp++; printf(" [Incomplete last line]"); break; } return (EOF); } fp = genbuf; + while(fp < &genbuf[ninbuf]) { + if (*fp++ & 0200) { + if (kflag) + crblock(perm, genbuf, ninbuf+1, +cntch); + break; + } + } + fp = genbuf; + cntch += ninbuf+1; } if (lp >= &linebuf[LBSIZE]) { error(" Line too long"); @@ -891,7 +606,6 @@ getfile() } *lp++ = c; } while (c != '\n'); - cntch += lp - linebuf; *--lp = 0; nextip = fp; cntln++; @@ -920,6 +634,8 @@ putfile() for (;;) { if (--nib < 0) { nib = fp - genbuf; + if(kflag) + crblock(perm, genbuf, nib, cntch); if (write(io, genbuf, nib) != nib) { wrerror(); } @@ -934,6 +650,8 @@ putfile() } } while (a1 <= addr2); nib = fp - genbuf; + if(kflag) + crblock(perm, genbuf, nib, cntch); if (write(io, genbuf, nib) != nib) { wrerror(); } @@ -957,7 +675,8 @@ wrerror() * Source command, handles nested sources. * Traps errors since it mungs unit 0 during the source. */ -static short slevel; +short slevel; +short ttyindes; source(fil, okfail) char *fil; @@ -965,12 +684,13 @@ source(fil, okfail) { jmp_buf osetexit; register int saveinp, ointty, oerrno; - int oprompt; signal(SIGINT, SIG_IGN); saveinp = dup(0); if (saveinp < 0) error("Too many nested sources"); + if (slevel <= 0) + ttyindes = saveinp; close(0); if (open(fil, 0) < 0) { oerrno = errno; diff --git a/usr/src/usr.bin/ex/ex_put.c b/usr/src/usr.bin/ex/ex_put.c index 033c05bfea..74fbb4210e 100644 --- a/usr/src/usr.bin/ex/ex_put.c +++ b/usr/src/usr.bin/ex/ex_put.c @@ -194,12 +194,8 @@ slobber(c) * The output buffer is initialized with a useful error * message so we don't have to keep it in data space. */ -static char linb[66] = { - 'E', 'r', 'r', 'o', 'r', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', - 'f', 'i', 'l', 'e', ' ', 'n', 'o', 't', ' ', - 'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e', '\n', 0 -}; -static char *linp = linb + 33; +static char linb[66]; +static char *linp = linb; /* * Phadnl records when we have already had a complete line ending with \n. @@ -344,8 +340,14 @@ fgoto() if (AM == 0) { while (l > 0) { if (pfast) - putch('\r'); - putch('\n'); + if (xCR) + tputs(xCR, 0, putch); + else + putch('\r'); + if (xNL) + tputs(xNL, 0, putch); + else + putch('\n'); l--; } outcol = 0; @@ -366,7 +368,28 @@ fgoto() destcol = c; } while (l > LINES - 1) { - putch('\n'); + /* + * The following linefeed (or simulation thereof) + * is supposed to scroll up the screen, since we + * are on the bottom line. We make the assumption + * that linefeed will scroll. If ns is in the + * capability list this won't work. We should + * probably have an sc capability but sf will + * generally take the place if it works. + * + * Superbee glitch: in the middle of the screen we + * have to use esc B (down) because linefeed screws up + * in "Efficient Paging" (what a joke) mode (which is + * essential in some SB's because CRLF mode puts garbage + * in at end of memory), but you must use linefeed to + * scroll since down arrow won't go past memory end. + * I turned this off after recieving Paul Eggert's + * Superbee description which wins better. + */ + if (xNL /* && !XB */ && pfast) + tputs(xNL, 0, putch); + else + putch('\n'); l--; if (pfast == 0) outcol = 0; @@ -423,40 +446,74 @@ plod(cnt) plodcnt = plodflg = cnt; soutcol = outcol; soutline = outline; + /* + * Consider homing and moving down/right from there, vs moving + * directly with local motions to the right spot. + */ if (HO) { + /* + * i is the cost to home and tab/space to the right to + * get to the proper column. This assumes ND space costs + * 1 char. So i+destcol is cost of motion with home. + */ if (GT) - i = (destcol / value(HARDTABS)) + (destcol % value(HARDTABS)); + i = (destcol / value(HARDTABS)) + (destcol % value(HARDTABS)); else i = destcol; - if (destcol >= outcol) { - j = destcol / value(HARDTABS) - outcol / value(HARDTABS); - if (GT && j) - j += destcol % value(HARDTABS); + /* + * j is cost to move locally without homing + */ + if (destcol >= outcol) { /* if motion is to the right */ + j = destcol / value(HARDTABS) - outcol / value(HARDTABS); + if (GT && j) + j += destcol % value(HARDTABS); else j = destcol - outcol; - } else + } else + /* leftward motion only works if we can backspace. */ if (outcol - destcol <= i && (BS || BC)) - i = j = outcol - destcol; + i = j = outcol - destcol; /* cheaper to backspace */ else - j = i + 1; + j = i + 1; /* impossibly expensive */ + + /* k is the absolute value of vertical distance */ k = outline - destline; if (k < 0) k = -k; j += k; - if (i + destline < j) { + + /* + * Decision. We may not have a choice if no UP. + */ + if (i + destline < j || (!UP && destline < outline)) { + /* + * Cheaper to home. Do it now and pretend it's a + * regular local motion. + */ tputs(HO, 0, plodput); outcol = outline = 0; } else if (LL) { + /* + * Quickly consider homing down and moving from there. + * Assume cost of LL is 2. + */ k = (LINES - 1) - destline; - if (i + k + 2 < j) { + if (i + k + 2 < j && (k<=0 || UP)) { tputs(LL, 0, plodput); outcol = 0; outline = LINES - 1; } } - } + } else + /* + * No home and no up means it's impossible, so we return an + * incredibly big number to make cursor motion win out. + */ + if (!UP && destline < outline) + return (500); if (GT) - i = destcol % value(HARDTABS) + destcol / value(HARDTABS); + i = destcol % value(HARDTABS) + + destcol / value(HARDTABS); else i = destcol; /* @@ -486,9 +543,19 @@ plod(cnt) * a return preliminarily. */ if (j > i + 1 || outcol > destcol && !BS && !BC) { - plodput('\r'); + /* + * BUG: this doesn't take the (possibly long) length + * of xCR into account. + */ + if (xCR) + tputs(xCR, 0, plodput); + else + plodput('\r'); if (NC) { - plodput('\n'); + if (xNL) + tputs(xNL, 0, plodput); + else + plodput('\n'); outline++; } outcol = 0; @@ -496,7 +563,10 @@ plod(cnt) dontcr: while (outline < destline) { outline++; - plodput('\n'); + if (xNL && pfast) + tputs(xNL, 0, plodput); + else + plodput('\n'); if (plodcnt < 0) goto out; if (NONL || pfast == 0) @@ -529,7 +599,7 @@ dontcr: } if (GT && !insmode && destcol - outcol > 1) { for (;;) { - i = (outcol / value(HARDTABS) + 1) * value(HARDTABS); + i = tabcol(outcol, value(HARDTABS)); if (i > destcol) break; if (TA) @@ -562,10 +632,6 @@ dontcr: * 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 = ' '; @@ -668,7 +734,7 @@ putch(c) int c; { - *obp++ = c; + *obp++ = c & 0177; if (obp >= &obuf[sizeof obuf]) flusho(); } @@ -677,16 +743,6 @@ putch(c) * Miscellaneous routines related to output. */ -/* - * Cursor motion. - */ -char * -cgoto() -{ - - return (tgoto(CM, destcol, destline)); -} - /* * Put with padding */ @@ -747,7 +803,13 @@ pstart() flusho(); pfast = 1; normtty++; +#ifndef USG3TTY tty.sg_flags = normf & ~(ECHO|XTABS|CRMOD); +#else + tty = normf; + tty.c_oflag &= ~(ONLCR|TAB3); + tty.c_lflag &= ~ECHO; +#endif sTTY(1); } @@ -769,42 +831,116 @@ pstop() /* * Prep tty for open mode. */ +ttymode ostart() { - int f; + ttymode f; if (!intty) error("Open and visual must be used interactively"); gTTY(1); normtty++; +#ifndef USG3TTY f = tty.sg_flags; -#ifdef CBREAK - tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) | CBREAK; + tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) | +# ifdef CBREAK + CBREAK; +# else + RAW; +# endif +# ifdef TIOCGETC + ttcharoff(); +# endif #else - tty.sg_flags = (normf &~ (ECHO|XTABS|CRMOD)) | RAW; -#endif -#ifdef EATQS - nttyc.t_quitc = nttyc.t_startc = nttyc.t_stopc = '\377'; + f = tty; + tty = normf; + tty.c_iflag &= ~ICRNL; + tty.c_lflag &= ~(ECHO|ICANON); + tty.c_oflag &= ~TAB3; + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 1; + ttcharoff(); #endif sTTY(1); - putpad(VS); - putpad(KS); + tostart(); pfast |= 2; return (f); } +/* actions associated with putting the terminal in open mode */ +tostart() +{ + putpad(VS); + putpad(KS); + if (!value(MESG)) + chmod(ttynbuf, 0611); /* 11 = urgent only allowed */ +} + +/* + * Turn off start/stop chars if they aren't the default ^S/^Q. + * This is so idiots who make esc their start/stop don't lose. + * We always turn off quit since datamedias send ^\ for their + * right arrow key. + */ +#ifdef TIOCGETC +ttcharoff() +{ + nttyc.t_quitc = '\377'; + if (nttyc.t_startc != CTRL(q)) + nttyc.t_startc = '\377'; + if (nttyc.t_stopc != CTRL(s)) + nttyc.t_stopc = '\377'; +# ifdef TIOCLGET + nlttyc.t_suspc = '\377'; /* ^Z */ + nlttyc.t_dsuspc = '\377'; /* ^Y */ + nlttyc.t_flushc = '\377'; /* ^O */ + nlttyc.t_lnextc = '\377'; /* ^V */ +# endif +} +#endif + +#ifdef USG3TTY +ttcharoff() +{ + tty.c_cc[VQUIT] = '\377'; +# ifdef VSTART + /* + * The following is sample code if USG ever lets people change + * their start/stop chars. As long as they can't we can't get + * into trouble so we just leave them alone. + */ + if (tty.c_cc[VSTART] != CTRL(q)) + tty.c_cc[VSTART] = '\377'; + if (tty.c_cc[VSTOP] != CTRL(s)) + tty.c_cc[VSTOP] = '\377'; +# endif +} +#endif + /* * Stop open, restoring tty modes. */ ostop(f) - int f; + ttymode f; { +#ifndef USG3TTY pfast = (f & CRMOD) == 0; +#else + pfast = (f.c_oflag & OCRNL) == 0; +#endif termreset(), fgoto(), flusho(); normal(f); + tostop(); +} + +/* Actions associated with putting the terminal in the right mode. */ +tostop() +{ putpad(VE); putpad(KE); + if (!value(MESG)) + chmod(ttynbuf, ttymesg); } #ifndef CBREAK @@ -833,7 +969,7 @@ vraw() * Restore flags to normal state f. */ normal(f) - int f; + ttymode f; { if (normtty > 0) { @@ -845,18 +981,31 @@ normal(f) /* * Straight set of flags to state f. */ +ttymode setty(f) - int f; + ttymode f; { +#ifndef USG3TTY register int ot = tty.sg_flags; +#else + ttymode ot; + ot = tty; +#endif -#ifdef EATQS - if (f == normf) +#ifndef USG3TTY + if (f == normf) { nttyc = ottyc; - else - nttyc.t_quitc = nttyc.t_startc = nttyc.t_stopc = '\377'; -#endif +# ifdef TIOCLGET + nlttyc = olttyc; +# endif + } else + ttcharoff(); tty.sg_flags = f; +#else + if (tty.c_lflag & ICANON) + ttcharoff(); + tty = f; +#endif sTTY(1); return (ot); } @@ -864,32 +1013,63 @@ setty(f) gTTY(i) int i; { + char *tn; + struct stat sbuf; +#ifndef USG3TTY ignore(gtty(i, &tty)); -#ifdef EATQS +# ifdef TIOCGETC ioctl(i, TIOCGETC, &ottyc); nttyc = ottyc; +# endif +# ifdef TIOCLGET + ioctl(i, TIOCGLTC, &olttyc); + nlttyc = olttyc; +# endif +#else + ioctl(i, TCGETA, &tty); #endif + if ((tn=ttyname(0)) == NULL && (tn=ttyname(1)) == NULL && (tn=ttyname(2)) == NULL) + tn = "/dev/tty"; + strcpy(ttynbuf, tn); + stat(ttynbuf, &sbuf); + ttymesg = sbuf.st_mode & 0777; } +/* + * sTTY: set the tty modes on file descriptor i to be what's + * currently in global "tty". (Also use nttyc if needed.) + */ sTTY(i) int i; { -/* - * Bug in USG tty driver, put out a null char as a patch. - */ -#ifdef USG - if (tty.sg_ospeed == B1200) - write(1, "", 1); -#endif -#ifdef TIOCSETN +#ifndef USG3TTY +# ifdef USG + /* Bug in USG tty driver, put out a DEL as a patch. */ + if (tty.sg_ospeed >= B1200) + write(1, "\377", 1); +# endif + +# ifdef TIOCSETN + /* Don't flush typeahead if we don't have to */ ioctl(i, TIOCSETN, &tty); -#else +# else + /* We have to. Too bad. */ stty(i, &tty); -#endif -#ifdef EATQS +# endif + +# ifdef TIOCGETC + /* Update the other random chars while we're at it. */ ioctl(i, TIOCSETC, &nttyc); +# endif +# ifdef TIOCLGET + ioctl(i, TIOCSLTC, &nlttyc); +# endif + +#else + /* USG 3 very simple: just set everything */ + ioctl(i, TCSETAW, &tty); #endif } @@ -901,3 +1081,39 @@ noonl() putchar(Outchar != termchar ? ' ' : '\n'); } + +#ifdef TIOCLGET +/* + * We have just gotten a susp. Suspend and prepare to resume. + */ +onsusp() +{ + ttymode f; + + f = setty(normf); + vnfl(); + putpad(TE); + flush(); + + signal(SIGTSTP, SIG_DFL); + kill(0, SIGTSTP); + + /* the pc stops here */ + + signal(SIGTSTP, onsusp); + vcontin(0); + setty(f); + if (!inopen) + error(0); + else { + if (vcnt < 0) { + vcnt = -vcnt; + if (state == VISUAL) + vclear(); + else if (state == CRTOPEN) + vcnt = 0; + } + vdirty(0, LINES); + vrepaint(cursor); + } +} diff --git a/usr/src/usr.bin/ex/ex_re.c b/usr/src/usr.bin/ex/ex_re.c index cf0692977b..c2b21d3355 100644 --- a/usr/src/usr.bin/ex/ex_re.c +++ b/usr/src/usr.bin/ex/ex_re.c @@ -104,7 +104,7 @@ out: } } -bool xflag; +bool cflag; int scount, slines, stotal; substitute(c) @@ -145,7 +145,7 @@ substitute(c) addr2 += n; } } - if (stotal == 0 && !inglobal && !xflag) + if (stotal == 0 && !inglobal && !cflag) error("Fail|Substitute pattern match failed"); snote(stotal, slines); return (stotal); @@ -157,7 +157,7 @@ compsub(ch) static int gsubf; if (!value(EDCOMPATIBLE)) - gsubf = xflag = 0; + gsubf = cflag = 0; uselastre = 0; switch (ch) { @@ -174,7 +174,7 @@ compsub(ch) uselastre = 1; comprhs(seof); gsubf = 0; - xflag = 0; + cflag = 0; break; case '~': @@ -184,6 +184,8 @@ compsub(ch) redo: if (re.Expbuf[0] == 0) error("No previous re|No previous regular expression"); + if (subre.Expbuf[0] == 0) + error("No previous substitute re|No previous substitute to repeat"); break; } for (;;) { @@ -195,7 +197,7 @@ compsub(ch) continue; case 'c': - xflag = !xflag; + cflag = !cflag; continue; case 'r': @@ -307,7 +309,7 @@ confirmed(a) { register int c, ch; - if (xflag == 0) + if (cflag == 0) return (1); pofix(); pline(lineno(a)); @@ -522,7 +524,7 @@ complex: if (c == eof || c == EOF) { if (bracketp != bracket) cerror("Unmatched \\(|More \\('s than \\)'s in regular expression"); - *ep++ = CEOF; + *ep++ = CEOFC; if (c == EOF) ungetchar(c); return (eof); @@ -647,7 +649,7 @@ cerror("Bad \\n|\\n in regular expression with n greater than the number of \\(' case '\n': if (oknl) { ungetchar(c); - *ep++ = CEOF; + *ep++ = CEOFC; return (eof); } cerror("Badly formed re|Missing closing delimiter for regular expression"); @@ -701,10 +703,6 @@ execute(gf, addr) if (gf) { if (circfl) return (0); -#ifdef notdef - if (loc1 == loc2) - loc2++; -#endif locs = p1 = loc2; } else { if (addr == zero) @@ -783,7 +781,7 @@ advance(lp, ep) continue; return (0); - case CEOF: + case CEOFC: loc2 = lp; return (1); diff --git a/usr/src/usr.bin/ex/ex_re.h b/usr/src/usr.bin/ex/ex_re.h index 500d5d5a96..e1bb3b4f25 100644 --- a/usr/src/usr.bin/ex/ex_re.h +++ b/usr/src/usr.bin/ex/ex_re.h @@ -59,7 +59,7 @@ char rhsbuf[RHSSIZE]; /* Rhs of last substitute */ #define CCL 8 #define NCCL 12 #define CDOL 16 -#define CEOF 17 +#define CEOFC 17 #define CKET 18 #define CCHR 20 #define CBRC 24 diff --git a/usr/src/usr.bin/ex/ex_set.c b/usr/src/usr.bin/ex/ex_set.c index bb7f2d8636..0939742375 100644 --- a/usr/src/usr.bin/ex/ex_set.c +++ b/usr/src/usr.bin/ex/ex_set.c @@ -74,6 +74,8 @@ printone: } if (op->otype == ONOFF) { op->ovalue = 1 - no; + if (op == &options[PROMPT]) + oprompt = 1 - no; goto next; } if (no) diff --git a/usr/src/usr.bin/ex/ex_subr.c b/usr/src/usr.bin/ex/ex_subr.c index babd23393b..c77e5fc2a0 100644 --- a/usr/src/usr.bin/ex/ex_subr.c +++ b/usr/src/usr.bin/ex/ex_subr.c @@ -56,6 +56,21 @@ column(cp) return (qcolumn(cp, (char *) 0)); } +/* + * Ignore a comment to the end of the line. + * This routine eats the trailing newline so don't call newline(). + */ +comment() +{ + register int c; + + do { + c = getchar(); + } while (c != '\n' && c != EOF); + if (c == EOF) + ungetchar(c); +} + Copy(to, from, size) register char *from, *to; register int size; @@ -179,6 +194,8 @@ ignnEOF() if (c == EOF) ungetchar(c); + else if (c=='"') + comment(); } iswhite(c) @@ -437,13 +454,15 @@ putmk1(addr, n) int n; { register line *markp; + register oldglobmk; + oldglobmk = *addr & 1; *addr &= ~1; for (markp = (anymarks ? names : &names['z'-'a'+1]); markp <= &names['z'-'a'+1]; markp++) if (*markp == *addr) *markp = n; - *addr = n; + *addr = n | oldglobmk; } char * @@ -684,6 +703,25 @@ syserror() error("System error %d", e); } +/* + * Return the column number that results from being in column col and + * hitting a tab, where tabs are set every ts columns. Work right for + * the case where col > COLUMNS, even if ts does not divide COLUMNS. + */ +tabcol(col, ts) +int col, ts; +{ + int offset, result; + + if (col >= COLUMNS) { + offset = COLUMNS * (col/COLUMNS); + col -= offset; + } else + offset = 0; + result = col + ts - (col % ts) + offset; + return (result); +} + char * vfindcol(i) int i; @@ -767,4 +805,3 @@ markit(addr) if (addr != dot && addr >= one && addr <= dol) markDOT(); } - diff --git a/usr/src/usr.bin/ex/ex_temp.c b/usr/src/usr.bin/ex/ex_temp.c index 3f4bc5aebf..597d8813cd 100644 --- a/usr/src/usr.bin/ex/ex_temp.c +++ b/usr/src/usr.bin/ex/ex_temp.c @@ -137,6 +137,8 @@ getblock(atl, iof) int iof; { register int bno, off; + register char *p1, *p2; + register int n; bno = (atl >> OFFBTS) & BLKMSK; off = (atl << SHFT) & LBTMSK; @@ -157,24 +159,48 @@ getblock(atl, iof) return (obuff + off); if (iof == READ) { if (hitin2 == 0) { - if (ichang2) + if (ichang2) { + if(xtflag) + crblock(tperm, ibuff2, CRSIZE, (long)0); blkio(iblock2, ibuff2, write); + } ichang2 = 0; iblock2 = bno; blkio(bno, ibuff2, read); + if(xtflag) + crblock(tperm, ibuff2, CRSIZE, (long)0); hitin2 = 1; return (ibuff2 + off); } hitin2 = 0; - if (ichanged) + if (ichanged) { + if(xtflag) + crblock(tperm, ibuff, CRSIZE, (long)0); blkio(iblock, ibuff, write); + } ichanged = 0; iblock = bno; blkio(bno, ibuff, read); + if(xtflag) + crblock(tperm, ibuff, CRSIZE, (long)0); return (ibuff + off); } - if (oblock >= 0) - blkio(oblock, obuff, write); + if (oblock >= 0) { + if(xtflag) { + /* + * Encrypt block before writing, so some devious + * person can't look at temp file while editing. + */ + p1 = obuff; + p2 = crbuf; + n = CRSIZE; + while(n--) + *p2++ = *p1++; + crblock(tperm, crbuf, CRSIZE, (long)0); + blkio(oblock, crbuf, write); + } else + blkio(oblock, obuff, write); + } oblock = bno; return (obuff + off); } @@ -217,6 +243,8 @@ synctmp() if (*bp < 0) { tline = (tline + OFFMSK) &~ OFFMSK; *bp = ((tline >> OFFBTS) & BLKMSK); + if (*bp > NMBLKS) + error(" Tmp file too large"); tline += INCRMT; oblock = *bp + 1; bp[1] = -1; @@ -573,3 +601,147 @@ int buflen; *p = '\0'; getDOT(); } + +/* + * Encryption routines. These are essentially unmodified from ed. + */ + +/* + * crblock: encrypt/decrypt a block of text. + * buf is the buffer through which the text is both input and + * output. nchar is the size of the buffer. permp is a work + * buffer, and startn is the beginning of a sequence. + */ +crblock(permp, buf, nchar, startn) +char *permp; +char *buf; +int nchar; +long startn; +{ + register char *p1; + int n1; + int n2; + register char *t1, *t2, *t3; + + t1 = permp; + t2 = &permp[256]; + t3 = &permp[512]; + + n1 = startn&0377; + n2 = (startn>>8)&0377; + p1 = buf; + while(nchar--) { + *p1 = t2[(t3[(t1[(*p1+n1)&0377]+n2)&0377]-n2)&0377]-n1; + n1++; + if(n1==256){ + n1 = 0; + n2++; + if(n2==256) n2 = 0; + } + p1++; + } +} + +/* + * makekey: initialize buffers based on user key a. + */ +makekey(a, b) +char *a, *b; +{ + register int i; + long t; + char temp[KSIZE + 1]; + + for(i = 0; i < KSIZE; i++) + temp[i] = *a++; + time(&t); + t += getpid(); + for(i = 0; i < 4; i++) + temp[i] ^= (t>>(8*i))&0377; + crinit(temp, b); +} + +/* + * crinit: besides initializing the encryption machine, this routine + * returns 0 if the key is null, and 1 if it is non-null. + */ +crinit(keyp, permp) +char *keyp, *permp; +{ + register char *t1, *t2, *t3; + register i; + int ic, k, temp; + unsigned random; + char buf[13]; + long seed; + + t1 = permp; + t2 = &permp[256]; + t3 = &permp[512]; + if(*keyp == 0) + return(0); + strncpy(buf, keyp, 8); + while (*keyp) + *keyp++ = '\0'; + + buf[8] = buf[0]; + buf[9] = buf[1]; + domakekey(buf); + + seed = 123; + for (i=0; i<13; i++) + seed = seed*buf[i] + i; + for(i=0;i<256;i++){ + t1[i] = i; + t3[i] = 0; + } + for(i=0; i<256; i++) { + seed = 5*seed + buf[i%13]; + random = seed % 65521; + k = 256-1 - i; + ic = (random&0377) % (k+1); + random >>= 8; + temp = t1[k]; + t1[k] = t1[ic]; + t1[ic] = temp; + if(t3[k]!=0) continue; + ic = (random&0377) % k; + while(t3[ic]!=0) ic = (ic+1) % k; + t3[k] = ic; + t3[ic] = k; + } + for(i=0; i<256; i++) + t2[t1[i]&0377] = i; + return(1); +} + +/* + * domakekey: the following is the major nonportable part of the encryption + * mechanism. A 10 character key is supplied in buffer. + * This string is fed to makekey (an external program) which + * responds with a 13 character result. This result is placed + * in buffer. + */ +domakekey(buffer) +char *buffer; +{ + int pf[2]; + + if (pipe(pf)<0) + pf[0] = pf[1] = -1; + if (fork()==0) { + close(0); + close(1); + dup(pf[0]); + dup(pf[1]); + execl("/usr/lib/makekey", "-", 0); + execl("/lib/makekey", "-", 0); + exit(1); + } + write(pf[1], buffer, 10); + if (wait((int *)NULL)==-1 || read(pf[0], buffer, 13)!=13) + error("crypt: cannot generate key"); + close(pf[0]); + close(pf[1]); + /* end of nonportable part */ +} diff --git a/usr/src/usr.bin/ex/ex_tty.c b/usr/src/usr.bin/ex/ex_tty.c index 60853482ba..99b14e7f16 100644 --- a/usr/src/usr.bin/ex/ex_tty.c +++ b/usr/src/usr.bin/ex/ex_tty.c @@ -12,6 +12,7 @@ short ospeed = -1; gettmode() { +#ifndef USG3TTY if (gtty(1, &tty) < 0) return; if (ospeed != tty.sg_ospeed) @@ -21,17 +22,29 @@ gettmode() UPPERCASE = (tty.sg_flags & LCASE) != 0; GT = (tty.sg_flags & XTABS) != XTABS && !XT; NONL = (tty.sg_flags & CRMOD) == 0; +#else + if (ioctl(1, TCGETA, &tty) < 0) + return; + if (ospeed != tty.c_cflag & CBAUD) + value(SLOWOPEN) = (tty.c_cflag & CBAUD) < B1200; + ospeed = tty.c_cflag & CBAUD; + normf = tty; + UPPERCASE = (tty.c_iflag & IUCLC) != 0; + GT = (tty.c_oflag & TABDLY) != TAB3 && !XT; + NONL = (tty.c_oflag & OCRNL) == 0; +#endif } char *xPC; char **sstrs[] = { - &AL, &BC, &BT, &CD, &CE, &CL, &CM, &DC, &DL, &DM, &DO, &ED, &EI, + &AL, &BC, &BT, &CD, &CE, &CL, &CM, &xCR, &DC, &DL, &DM, &DO, &ED, &EI, &F0, &F1, &F2, &F3, &F4, &F5, &F6, &F7, &F8, &F9, &HO, &IC, &IM, &IP, &KD, &KE, &KH, &KL, &KR, &KS, &KU, &LL, - &ND, &xPC, &SE, &SF, &SO, &SR, &TA, &TE, &TI, &UP, &VB, &VS, &VE + &ND, &xNL, &xPC, &SE, &SF, &SO, &SR, &TA, &TE, &TI, &UP, &VB, &VS, &VE }; bool *sflags[] = { - &AM, &BS, &DA, &DB, &EO, &HC, &HZ, &IN, &MI, &NC, &OS, &UL, &XN, &XT + &AM, &BS, &DA, &DB, &EO, &HC, &HZ, &IN, &MI, &NC, &NS, &OS, &UL, + &XB, &XN, &XT, &XX }; char **fkeys[10] = { &F0, &F1, &F2, &F3, &F4, &F5, &F6, &F7, &F8, &F9 @@ -39,7 +52,7 @@ char **fkeys[10] = { setterm(type) char *type; { - char *cgoto(); + char *tgoto(); register int unknown, i; register int l; char ltcbuf[TCBUFSIZE]; @@ -73,13 +86,36 @@ setterm(type) arrows[3].cap = KR; arrows[3].mapto = "l"; arrows[3].descr = "right"; arrows[4].cap = KH; arrows[4].mapto = "H"; arrows[4].descr = "home"; +#ifdef TIOCLGET + /* + * Now map users susp char to ^Z, being careful that the susp + * overrides any arrow key, but only for hackers (=new tty driver). + */ + { + static char sc[2]; + int i, fnd; + + ioctl(0, TIOCGETD, &ldisc); + if (ldisc == NTTYDISC) { + sc[0] = olttyc.t_suspc; + sc[1] = 0; + if (olttyc.t_suspc == CTRL(z)) { + for (i=0; i<=4; i++) + if (arrows[i].cap[0] == CTRL(z)) + addmac(sc, NULL, NULL, arrows); + } else + addmac(sc, "\32", "susp", arrows); + } + } +#endif + options[WINDOW].ovalue = options[WINDOW].odefault = l - 1; if (defwind) options[WINDOW].ovalue = defwind; options[SCROLL].ovalue = options[SCROLL].odefault = HC ? 11 : ((l-1) / 2); COLUMNS = tgetnum("co"); - if (COLUMNS <= 20) + if (COLUMNS <= 4) COLUMNS = 1000; - if (cgoto()[0] == 'O') /* OOPS */ + if (tgoto(CM, 2, 2)[0] == 'O') /* OOPS */ CA = 0, CM = 0; else CA = 1, costCM = strlen(tgoto(CM, 8, 10)); @@ -89,11 +125,6 @@ setterm(type) if (i <= 0) LINES = 2; /* proper strings to change tty type */ -#ifdef notdef - /* Taken out because we don't allow it. See ex_set.c for reasons. */ - if (inopen) - putpad(VE); -#endif termreset(); gettmode(); value(REDRAW) = AL && DL; @@ -108,13 +139,13 @@ zap() register bool **fp; register char ***sp; - namp = "ambsdadbeohchzinmincosulxnxt"; + namp = "ambsdadbeohchzinmincnsosulxbxnxtxx"; fp = sflags; do { *(*fp++) = tgetflag(namp); namp += 2; } while (*namp); - namp = "albcbtcdceclcmdcdldmdoedeik0k1k2k3k4k5k6k7k8k9hoicimipkdkekhklkrkskullndpcsesfsosrtatetiupvbvsve"; + namp = "albcbtcdceclcmcrdcdldmdoedeik0k1k2k3k4k5k6k7k8k9hoicimipkdkekhklkrkskullndnlpcsesfsosrtatetiupvbvsve"; sp = sstrs; do { *(*sp++) = tgetstr(namp, &aoftspace); diff --git a/usr/src/usr.bin/ex/ex_tty.h b/usr/src/usr.bin/ex/ex_tty.h index a4c69624f6..522421fa80 100644 --- a/usr/src/usr.bin/ex/ex_tty.h +++ b/usr/src/usr.bin/ex/ex_tty.h @@ -35,6 +35,7 @@ char *CD; /* P* Clear to end of display */ char *CE; /* P Clear to end of line */ char *CL; /* P* Clear screen */ char *CM; /* P Cursor motion */ +char *xCR; /* P Carriage return */ char *DC; /* P* Delete character */ char *DL; /* P* Delete line sequence */ char *DM; /* Delete mode (enter) */ @@ -56,6 +57,7 @@ char *KS; /* Keypad start xmitting */ char *KU; /* Keypad up arrow */ char *LL; /* Quick to last line, column 0 */ char *ND; /* Non-destructive space */ +char *xNL; /* Line feed (new line) */ char PC; /* Pad character */ char *SE; /* Standout end (may leave space) */ char *SF; /* P Scroll forwards */ @@ -80,10 +82,13 @@ bool HZ; /* Hazeltine ~ braindamage */ bool IN; /* Insert-null blessing */ bool MI; /* can move in insert mode */ bool NC; /* No Cr - \r snds \r\n then eats \n (dm2500) */ +bool NS; /* No scroll - linefeed at bottom won't scroll */ bool OS; /* Overstrike works */ bool UL; /* Underlining works even though !os */ +bool XB; /* Beehive (no escape key, simulate with f1) */ bool XN; /* A newline gets eaten after wrap (concept) */ bool XT; /* Tabs are destructive */ +bool XX; /* Tektronix 4025 insert line */ /* X? is reserved for severely nauseous glitches */ /* If there are enough of these we may need bit masks! */ @@ -102,12 +107,42 @@ short outline; short destcol; /* Where the cursor should be */ short destline; -#ifdef TIOCSETC -struct tchars ottyc, nttyc; /* For V7 character masking */ +/* + * There are several kinds of tty drivers to contend with. These include: + * (1) V6: no CBREAK, no ioctl. (Include PWB V1 here). + * (2) V7 research: has CBREAK, has ioctl, and has the tchars (TIOCSETC) + * business to change start, stop, etc. chars. + * (3) USG V2: Basically like V6 but RAW mode is like V7 RAW. + * (We treat it as V6.) + * (4) USG V3: equivalent to V7 but totally incompatible. + * (5) Berkeley: has ltchars in addition to all of V7. + * + * The following attempts to decide what we are on, and declare + * some variables in the appropriate format. The wierd looking one (ttymode) + * is the thing we pass to sTTY and family to turn "RAW" mode on or off + * when we go into or out of visual mode. In V7/V6 it's just the flags word + * to stty. In USG V3 it's the whole tty structure. + */ +#ifdef USG3TTY /* USG V3 */ + struct termio tty; /* Use this one structure to change modes */ + typedef struct termio ttymode; /* Mode to contain tty flags */ + +#else /* All others */ + struct sgttyb tty; /* Always stty/gtty using this one structure */ + typedef int ttymode; /* Mode to contain tty flags */ +# ifdef TIOCSETC /* V7 */ + struct tchars ottyc, nttyc; /* For V7 character masking */ +# endif +# ifdef TIOCLGET /* Berkeley */ + struct ltchars olttyc, nlttyc; /* More of tchars style stuff */ +# endif + #endif -struct sgttyb tty; /* Always stty/gtty using this one structure */ -bool normtty; /* Have to restor normal mode from normf */ -int normf; /* Restore tty flags to this (someday) */ + +ttymode normf; /* Restore tty flags to this (someday) */ +bool normtty; /* Have to restore normal mode from normf */ + +ttymode ostart(), setty(), unixex(); short WBOT; short WECHO; @@ -128,5 +163,11 @@ struct maps { }; struct maps arrows[MAXNOMACS]; /* macro defs - 1st 5 built in */ struct maps immacs[MAXNOMACS]; /* for while in insert mode */ +struct maps abbrevs[MAXNOMACS]; /* for word abbreviations */ +int ldisc; /* line discipline for ucb tty driver */ char mapspace[MAXCHARMACS]; char *msnext; /* next free location in mapspace */ +int maphopcnt; /* check for infinite mapping loops */ +bool anyabbrs; /* true if abbr or unabbr has been done */ +char ttynbuf[20]; /* result of ttyname() */ +int ttymesg; /* original mode of users tty */ diff --git a/usr/src/usr.bin/ex/ex_tune.h b/usr/src/usr.bin/ex/ex_tune.h index ddb0869e01..79dde460c1 100644 --- a/usr/src/usr.bin/ex/ex_tune.h +++ b/usr/src/usr.bin/ex/ex_tune.h @@ -10,10 +10,10 @@ * "/usr/lib/..." here, "/lib" will be tried only for strings. */ #include "local/uparm.h" -#define EXRECOVER libpath(ex3.3recover) -#define EXPRESERVE libpath(ex3.3preserve) +#define EXRECOVER libpath(ex3.4recover) +#define EXPRESERVE libpath(ex3.4preserve) #ifndef VMUNIX -#define EXSTRINGS libpath(ex3.3strings) +#define EXSTRINGS libpath(ex3.4strings) #endif /* @@ -35,9 +35,11 @@ #ifdef VMUNIX #define LBSIZE 1024 #define ESIZE 512 +#define CRSIZE 1024 #else #define LBSIZE 512 /* Line length */ #define ESIZE 128 /* Size of compiled re */ +#define CRSIZE 512 #endif #define RHSSIZE 256 /* Size of rhs of substitute */ #define NBRA 9 /* Number of re \( \) pairs */ @@ -106,5 +108,5 @@ * Attention is the interrupt character (normally 0177 -- delete). * Quit is the quit signal (normally FS -- control-\) and quits open/visual. */ -#define ATTN 0177 +#define ATTN (-2) #define QUIT ('\\' & 037) diff --git a/usr/src/usr.bin/ex/ex_v.c b/usr/src/usr.bin/ex/ex_v.c index 0f8afc4e81..00ef0fa85f 100644 --- a/usr/src/usr.bin/ex/ex_v.c +++ b/usr/src/usr.bin/ex/ex_v.c @@ -53,7 +53,7 @@ oop() { register char *ic; char atube[TUBESIZE + LBSIZE]; - register int f; + register ttymode f; ovbeg(); if (peekchar() == '/') { @@ -128,7 +128,7 @@ ovbeg() } ovend(f) - int f; + ttymode f; { splitw++; @@ -153,7 +153,7 @@ vop() { register int c; char atube[TUBESIZE + LBSIZE]; - register int f; + register ttymode f; if (!CA && UP == NOSTR) { if (initev) { @@ -175,6 +175,11 @@ toopen: goto toopen; error("Visual requires clear screen capability"); } + if (NS && !SF) { + if (initev) + goto toopen; + error("Visual requires scrolling"); + } ovbeg(); bastate = VISUAL; c = 0; @@ -258,6 +263,8 @@ undvis() undap1 = one; undap2 = dol + 1; undkind = UNDALL; + if (undadot <= zero || undadot > dol) + undadot = zero+1; } /* diff --git a/usr/src/usr.bin/ex/ex_vadj.c b/usr/src/usr.bin/ex/ex_vadj.c index 78373397da..b0d9e1e266 100644 --- a/usr/src/usr.bin/ex/ex_vadj.c +++ b/usr/src/usr.bin/ex/ex_vadj.c @@ -115,7 +115,15 @@ vreopen(p, lineno, l) * necessary to determine which way to go. */ vigoto(p, 0); +#ifdef TRACE + if (trace) + fprintf(trace, "before pline in vreopen\n"); +#endif pline(lineno); +#ifdef TRACE + if (trace) + fprintf(trace, "after pline in vreopen\n"); +#endif /* * When we are typing part of a line for hardcopy open, don't @@ -362,8 +370,8 @@ vrollup(dl) cnt = dl - (splitw ? WECHO : WBOT); if (splitw && (state == VISUAL || state == CRTOPEN)) holdupd = 1; - vscroll(cnt); vmoveitup(cnt, 1); + vscroll(cnt); destline = dl - cnt, destcol = dc; } diff --git a/usr/src/usr.bin/ex/ex_vars.h b/usr/src/usr.bin/ex/ex_vars.h index af2ea9f328..b4cc3d8fbf 100644 --- a/usr/src/usr.bin/ex/ex_vars.h +++ b/usr/src/usr.bin/ex/ex_vars.h @@ -10,31 +10,33 @@ #define LISP 9 #define LIST 10 #define MAGIC 11 -#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 -#define SHELL 22 -#define SHIFTWIDTH 23 -#define SHOWMATCH 24 -#define SLOWOPEN 25 -#define TAGS 26 -#define TABSTOP 27 -#define TERM 28 -#define TERSE 29 -#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 MESG 12 +#define NUMBER 13 +#define OPEN 14 +#define OPTIMIZE 15 +#define PARAGRAPHS 16 +#define PROMPT 17 +#define READONLY 18 +#define REDRAW 19 +#define REMAP 20 +#define REPORT 21 +#define SCROLL 22 +#define SECTIONS 23 +#define SHELL 24 +#define SHIFTWIDTH 25 +#define SHOWMATCH 26 +#define SLOWOPEN 27 +#define TABSTOP 28 +#define TAGLENGTH 29 +#define TAGS 30 +#define TERM 31 +#define TERSE 32 +#define TIMEOUT 33 +#define TTYTYPE 34 +#define WARN 35 +#define WINDOW 36 +#define WRAPSCAN 37 +#define WRAPMARGIN 38 +#define WRITEANY 39 -#define NOPTS 38 +#define NOPTS 40 diff --git a/usr/src/usr.bin/ex/ex_vget.c b/usr/src/usr.bin/ex/ex_vget.c index 4135d991f8..177c8541f5 100644 --- a/usr/src/usr.bin/ex/ex_vget.c +++ b/usr/src/usr.bin/ex/ex_vget.c @@ -63,6 +63,11 @@ getbr() char ch; register int c, d; register char *colp; +#define BEEHIVE +#ifdef BEEHIVE + static char Peek2key; +#endif + extern short slevel, ttyindes; getATTN: if (Peekkey) { @@ -70,6 +75,13 @@ getATTN: Peekkey = 0; return (c); } +#ifdef BEEHIVE + if (Peek2key) { + c = Peek2key; + Peek2key = 0; + return (c); + } +#endif if (vglobp) { if (*vglobp) return (lastvgk = *vglobp++); @@ -84,15 +96,36 @@ getATTN: if (inopen == -1) /* don't screw up undo for esc esc */ vundkind = VMANY; inopen = 1; /* restore old setting now that macro done */ + vch_mac = VC_NOTINMAC; } flusho(); again: - if (read(0, &ch, 1) != 1) { + if (read(slevel == 0 ? 0 : ttyindes, &ch, 1) != 1) { if (errno == EINTR) goto getATTN; error("Input read error"); } c = ch & TRIM; +#ifdef BEEHIVE + if (XB && slevel==0 && c == ESCAPE) { + if (read(0, &Peek2key, 1) != 1) + goto getATTN; + Peek2key &= TRIM; + switch (Peek2key) { + case 'C': /* SPOW mode sometimes sends \EC for space */ + c = ' '; + Peek2key = 0; + break; + case 'q': /* f2 -> ^C */ + c = CTRL(c); + Peek2key = 0; + break; + case 'p': /* f1 -> esc */ + Peek2key = 0; + break; + } + } +#endif #ifdef UCVISUAL /* @@ -218,6 +251,8 @@ readecho(c) } OP = Pline; Pline = normline; ignore(vgetline(0, genbuf + 1, &waste)); + if (Outchar == termchar) + putchar('\n'); vscrap(); Pline = OP; if (Peekkey != ATTN && Peekkey != QUIT && Peekkey != CTRL(h)) { @@ -243,7 +278,7 @@ blewit: setLAST() { - if (vglobp) + if (vglobp || vmacp) return; lastreg = vreg; lasthad = Xhadcnt; @@ -387,12 +422,19 @@ map(c,maps) if (trace) fprintf(trace,"map(%c): ",c); #endif + /* + * If c==0, the char came from getesc typing escape. Pass it through + * unchanged. 0 messes up the following code anyway. + */ + if (c==0) + return(0); + b[0] = c; b[1] = 0; for (d=0; maps[d].mapto; d++) { #ifdef MDEBUG if (trace) - fprintf(trace,"d=%d, ",d); + fprintf(trace,"\ntry '%s', ",maps[d].cap); #endif if (p = maps[d].cap) { for (q=b; *p; p++, q++) { @@ -402,6 +444,8 @@ map(c,maps) #endif if (*q==0) { /* + * Is there another char waiting? + * * This test is oversimplified, but * should work mostly. It handles the * case where we get an ESCAPE that @@ -410,9 +454,13 @@ map(c,maps) if ((c=='#' ? peekkey() : fastpeekkey()) == 0) { #ifdef MDEBUG if (trace) - fprintf(trace,"fpk=0: return %c",c); + fprintf(trace,"fpk=0: return '%c'",c); #endif /* + * Nothing waiting. Push back + * what we peeked at & return + * failure (c). + * * We want to be able to undo * commands, but it's nonsense * to undo part of an insertion @@ -427,11 +475,11 @@ map(c,maps) if (*p != *q) goto contin; } - macpush(maps[d].mapto,1); + macpush(maps[d].mapto,maps == arrows); c = getkey(); #ifdef MDEBUG - if (trace) - fprintf(trace,"Success: return %c",c); + if (trace) + fprintf(trace,"Success: push(%s), return %c",maps[d].mapto, c); #endif return(c); /* first char of map string */ contin:; @@ -439,7 +487,7 @@ map(c,maps) } #ifdef MDEBUG if (trace) - fprintf(trace,"Fail: return %c",c); /* DEBUG */ + fprintf(trace,"Fail: push(%s), return %c", &b[1], c); #endif macpush(&b[1],0); return(c); @@ -462,11 +510,13 @@ int canundo; if (st==0 || *st==0) return; +#ifdef notdef if (!value(UNDOMACRO)) canundo = 0; +#endif #ifdef TRACE if (trace) - fprintf(trace, "macpush(%s), canundo=%d",st,canundo); + fprintf(trace, "macpush(%s), canundo=%d\n",st,canundo); #endif if ((vmacp ? strlen(vmacp) : 0) + strlen(st) > BUFSIZ) error("Macro too long@ - maybe recursive?"); @@ -481,20 +531,50 @@ int canundo; vmacp = vmacbuf; /* arrange to be able to undo the whole macro */ if (canundo) { +#ifdef notdef otchng = tchng; vsave(); saveall(); inopen = -1; /* no need to save since it had to be 1 or -1 before */ vundkind = VMANY; +#endif + vch_mac = VC_NOCHANGE; } } #ifdef TRACE +visdump(s) +char *s; +{ + register int i; + + if (!trace) return; + + fprintf(trace, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n", + s, basWTOP, basWLINES, WTOP, WBOT, WLINES, WCOLS, WECHO); + fprintf(trace, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n", + vcnt, vcline, cursor-linebuf, wcursor-linebuf, wdot-zero); + for (i=0; i 256) + error("Infinite macro loop"); } while (c != op); /* @@ -378,14 +383,12 @@ reread: /* * ^F Window forwards, with 2 lines of continuity. - * Count gives new screen size. + * Count repeats. */ case CTRL(f): vsave(); - if (hadcnt) - vsetsiz(cnt); if (vcnt > 2) { - dot += (vcnt - vcline) - 2; + dot += (vcnt - vcline) - 2 + (cnt-1)*basWLINES; vcnt = vcline = 0; } vzop(0, 0, '+'); @@ -397,10 +400,8 @@ reread: */ case CTRL(b): vsave(); - if (hadcnt) - vsetsiz(cnt); if (one + vcline != dot && vcnt > 2) { - dot -= vcline - 2; + dot -= vcline - 2 + (cnt-1)*basWLINES; vcnt = vcline = 0; } vzop(0, 0, '^'); @@ -453,6 +454,7 @@ reread: if (cnt > (i = dol - dot + 1)) cnt = i; vsave(); + vmacchng(1); setLAST(); cursor = strend(linebuf); vremote(cnt, join, 0); @@ -488,6 +490,7 @@ reread: case 'O': case 'o': voOpen(c, cnt); + vmacchng(1); continue; /* @@ -506,6 +509,7 @@ reread: case '~': { char mbuf[4]; + setLAST(); mbuf[0] = 'r'; mbuf[1] = *cursor; mbuf[2] = cursor[1]==0 ? 0 : ' '; @@ -574,6 +578,7 @@ insrt: * is doomed, unless R when all is, and save the * current line in a the undo temporary buffer. */ + vmacchng(1); setLAST(); vcursat(cursor); prepapp(); @@ -644,6 +649,17 @@ insrt: */ 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; @@ -671,7 +687,9 @@ insrt: case 'P': case 'p': vmoving = 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 @@ -689,7 +707,13 @@ insrt: * 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(); + vmacchng(1); setLAST(); i = 0; if (vreg && partreg(vreg) || !vreg && pkill[0]) { @@ -836,6 +860,19 @@ gogo: 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. @@ -850,6 +887,7 @@ gogo: 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. @@ -1037,7 +1075,7 @@ fixup: * u undo the last changing command. */ case 'u': - vundo(); + vundo(1); continue; /* diff --git a/usr/src/usr.bin/ex/ex_voper.c b/usr/src/usr.bin/ex/ex_voper.c index 42812bf3fc..63bf53c527 100644 --- a/usr/src/usr.bin/ex/ex_voper.c +++ b/usr/src/usr.bin/ex/ex_voper.c @@ -106,11 +106,13 @@ operate(c, cnt) */ case 'r': vrep(cnt); + vmacchng(1); return; default: goto nocount; } + vmacchng(1); /* * Had an operator, so accept another count. * Multiply counts together. @@ -413,6 +415,7 @@ deleteit: case 'x': if (margin()) goto errlab; + vmacchng(1); while (cnt > 0 && !margin()) wcursor += dir, cnt--; opf = deleteop; diff --git a/usr/src/usr.bin/ex/ex_vops.c b/usr/src/usr.bin/ex/ex_vops.c index cb433c331c..21e83ed530 100644 --- a/usr/src/usr.bin/ex/ex_vops.c +++ b/usr/src/usr.bin/ex/ex_vops.c @@ -50,10 +50,12 @@ vUndo() } vdirty(vcline, 1); vsyncCL(); + cursor = linebuf; vfixcurs(); } -vundo() +vundo(show) +bool show; /* if true update the screen */ { register int cnt; register line *addr; @@ -88,22 +90,29 @@ vundo() * 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); - if (vundkind != VMCHNG || addr != dot) + if (show && (vundkind != VMCHNG || addr != dot)) killU(); vundkind = VMANY; cnt = dot - addr; if (cnt < 0 || cnt > vcnt || state != VISUAL) { - vjumpto(dot, NOSTR, '.'); + if (show) + vjumpto(dot, NOSTR, '.'); break; } if (!savenote) notecnt = 0; - vcline = cnt; - vrepaint(vmcurs); + if (show) { + vcline = cnt; + vrepaint(vmcurs); + } vmcurs = 0; break; @@ -116,6 +125,8 @@ vundo() strcLIN(temp); cp = vUA1; vUA1 = vUD1; vUD1 = cp; cp = vUA2; vUA2 = vUD2; vUD2 = cp; + if (!show) + break; cursor = vUD1; if (state == HARDOPEN) { doomed = 0; @@ -150,6 +161,94 @@ vundo() } } +/* + * 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; + int nlines, more; + register line *a1, *a2; + char ch; /* DEBUG */ + int copyw(), copywR(); + + if (!inopen) + 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; + 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; + + truedol -= nlines; + copyw(zero+1, truedol+1, nlines); + dot = savedot; dol = savedol ; cursor = savecursor; + 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; + } +} + /* * Initialize undo information before an append. */ diff --git a/usr/src/usr.bin/ex/ex_vops2.c b/usr/src/usr.bin/ex/ex_vops2.c index 83041796f3..cfffc8dadd 100644 --- a/usr/src/usr.bin/ex/ex_vops2.c +++ b/usr/src/usr.bin/ex/ex_vops2.c @@ -407,6 +407,7 @@ vgetline(cnt, gcursor, aescaped) register char *cp; int x, y, iwhite; char *iglobp; + char cstr[2]; int (*OO)() = Outchar; /* @@ -442,12 +443,18 @@ vgetline(cnt, gcursor, aescaped) if (cnt == 0) goto vadone; } - ch = c = getkey() & (QUOTE|TRIM); + c = getkey(); + if (c != ATTN) + c &= (QUOTE|TRIM); + ch = c; + maphopcnt = 0; if (vglobp == 0 && Peekkey == 0) while ((ch = map(c, immacs)) != c) { c = ch; if (!value(REMAP)) break; + if (++maphopcnt > 256) + error("Infinite macro loop"); } if (!iglobp) { @@ -457,10 +464,17 @@ vgetline(cnt, gcursor, aescaped) * 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; +#else + if (c == tty.c_cc[VERASE]) + c = CTRL(h); + else if (c == tty.c_cc[VKILL]) + c = -1; +#endif switch (c) { /* @@ -544,7 +558,12 @@ vbackup: putchar('\\'); vcsync(); c = getkey(); +#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++; @@ -584,16 +603,85 @@ vbackup: * 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; } - if (value(WRAPMARGIN) && outcol >= OCOLUMNS - value(WRAPMARGIN)) { - c = NL; - gobblebl = 2; + if (/* c <= ' ' && */ value(WRAPMARGIN) && + outcol >= OCOLUMNS - value(WRAPMARGIN)) { + /* + * At end of word and hit wrapmargin. + * Move the word to next line and keep going. + */ + wdkind = 1; + *gcursor++ = c; + *gcursor = 0; + /* + * Find end of previous word if we are past it. + */ + for (cp=gcursor; cp>ogcursor && isspace(cp[-1]); cp--) + ; + if (outcol - (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) { /* @@ -702,22 +790,22 @@ vbackup: } def: putchar(c); + flush(); noput: if (gcursor > &genbuf[LBSIZE - 2]) error("Line too long"); *gcursor++ = c & TRIM; vcsync(); -#ifdef LISPCODE if (value(SHOWMATCH) && !iglobp) if (c == ')' || c == '}') lsmatch(gcursor); -#endif continue; } } vadone: *gcursor = 0; - Outchar = OO; + if (Outchar != termchar) + Outchar = OO; endim(); return (gcursor); } diff --git a/usr/src/usr.bin/ex/ex_vops3.c b/usr/src/usr.bin/ex/ex_vops3.c index b0e96971e6..b1ae183f4c 100644 --- a/usr/src/usr.bin/ex/ex_vops3.c +++ b/usr/src/usr.bin/ex/ex_vops3.c @@ -322,11 +322,11 @@ lmatchp(addr) register int i; register char *parens, *cp; - for (cp = cursor; !any(*cp, "({)}");) + for (cp = cursor; !any(*cp, "({[)}]");) if (*cp++ == 0) return (0); lf = 0; - parens = any(*cp, "()") ? "()" : "{}"; + parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}"; if (*cp == parens[1]) { dir = -1; llimit = one; @@ -370,6 +370,12 @@ lsmatch(cp) if (i) goim(); } + else { + strcLIN(sp); + strcpy(scurs, genbuf); + if (!lmatchp((line *) 0)) + beep(); + } strcLIN(sp); wdot = 0; wcursor = 0; @@ -456,7 +462,7 @@ lnext() if (*wcursor) return (1); if (wdot >= llimit) { - if (wcursor > linebuf) + if (lf == vmove && wcursor > linebuf) wcursor--; return (0); } diff --git a/usr/src/usr.bin/ex/ex_vput.c b/usr/src/usr.bin/ex/ex_vput.c index 36434a3d0b..b06da78f4f 100644 --- a/usr/src/usr.bin/ex/ex_vput.c +++ b/usr/src/usr.bin/ex/ex_vput.c @@ -115,10 +115,28 @@ vclrech(didphys) * since we don't really know whats out there. * Vigoto might decide (incorrectly) to do nothing. */ - if (DB) - vgoto(WECHO, 0), vputp(CD ? CD : CE, 1); - else - vigoto(WECHO, 0), vclreol(); + if (DB) { + vgoto(WECHO, 0); + vputp(CD ? CD : CE, 1); + } else { + if (XT) { + /* + * This code basically handles the t1061 + * where positioning at (0, 0) won't work + * because the terminal won't let you put + * the cursor on it's magic cookie. + * + * Should probably be XS above, or even a + * new X? glitch, but right now t1061 is the + * only terminal with XT. + */ + vgoto(WECHO, 0); + vputp(DL, 1); + } else { + vigoto(WECHO, 0); + vclreol(); + } + } splitw = 0; didphys = 1; } @@ -399,11 +417,11 @@ vgoto(y, x) */ vgotab() { - register int i = (LINE(vcline) - destline) * WCOLS + destcol; + register int i = tabcol(destcol, value(TABSTOP)) - destcol; do (*Outchar)(QUOTE); - while (++i % value(TABSTOP)); + while (--i); } /* @@ -443,7 +461,7 @@ vmaktop(p, cp) register int i; char temp[TUBECOLS]; - if (vtube[p] == cp) + if (p < 0 || vtube[p] == cp) return; for (i = ZERO; i <= WECHO; i++) if (vtube[i] == cp) { @@ -542,7 +560,7 @@ vinschar(c) * use QUOTE here since we really need to print blanks. * QUOTE|' ' is the representation of this. */ - inssiz = value(TABSTOP) - inscol % value(TABSTOP); + inssiz = tabcol(inscol, value(TABSTOP)) - inscol; c = ' ' | QUOTE; } else inssiz = 1; @@ -618,7 +636,7 @@ vinschar(c) * line is now deeper. We then do the shift * implied by the insertion. */ - if (inssiz >= doomed + value(TABSTOP) - tabstart % value(TABSTOP)) { + if (inssiz >= doomed + tabcol(tabstart, value(TABSTOP)) - tabstart) { if (IN) vrigid(); vneedpos(value(TABSTOP)); diff --git a/usr/src/usr.bin/ex/makeoptions b/usr/src/usr.bin/ex/makeoptions index 84d2639389..dd7e02737f 100644 --- a/usr/src/usr.bin/ex/makeoptions +++ b/usr/src/usr.bin/ex/makeoptions @@ -1,40 +1,43 @@ # # remake options -- this isn't necessary unless you add/delete options # - onintr ifintr - cp ex_data.c /tmp/$$.c - ex - /tmp/$$.c <<'%' - g/^#include/d - w - q +onintr ifintr +cp ex_data.c /tmp/$$.c +ex - /tmp/$$.c <<'%' + g/^#include/d + w + q '%' - cc -E $* /tmp/$$.c >/tmp/foo.c - ex - /tmp/foo.c <<'X' - g/^# /d - set sh=/bin/csh - g/^[ ]*$/d - 1,/options/d - /}/-1,$d - 1,$s/ "// - 1,$s/".*// - 1m$ - w! ex_vars.h - !rm -f %; num ex_vars.h >% - e - $t0 - 1s/......../ 0 / - 1,$s/\(......\)\(.*\)/#define \U\2\L \1/ - 1,$s/ */ /g - g/ */s// /g - w - !rm -f ex_vars.h; expand -8,24 % >ex_vars.h - e! ex_vars.h - $i +cc -E $* /tmp/$$.c >/tmp/foo.c +ex - /tmp/foo.c <<'X' + " delete all preprocessor output (# line, etc) + g/^# /d + set sh=/bin/csh + " delete junk (all but data lines) + g/^[ ]*$/d + 1,/options/d + /}/-1,$d + " get rid of all of line but option name + 1,$s/ "// + 1,$s/".*// + 1m$ " kludge since options start at 0 but num at 1 + %!num + $t0 " unkludge + 1s/......../ 0 / " unkludge + " make #define lines + 1,$s/\(......\)\(.*\)/#define \U\2\L \1/ + " get rid of extra blanks, turning into (single) tabs. + 1,$s/ */ /g + g/ */s// /g + " filter through expand to make it line up nice + %!expand -8\,24 + " blank line and number of options. + $i . - $s/e[ ].*[ ]/e NOPTS / - w - q + $s/e[ ].*[ ]/e NOPTS / + w! ex_vars.h + q 'X' ifintr: - rm /tmp/foo.c +rm /tmp/foo.c -- 2.20.1