xref: /onnv-gate/usr/src/cmd/vi/port/ex_cmds.c (revision 4488:810f99638c34)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*4488Scf46844  * Common Development and Distribution License (the "License").
6*4488Scf46844  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21500Sceastha /*
22*4488Scf46844  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23500Sceastha  * Use is subject to license terms.
24500Sceastha  */
25500Sceastha 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include "ex.h"
350Sstevel@tonic-gate #include "ex_argv.h"
360Sstevel@tonic-gate #include "ex_temp.h"
370Sstevel@tonic-gate #include "ex_tty.h"
380Sstevel@tonic-gate #include "ex_vis.h"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate bool	pflag, nflag;
410Sstevel@tonic-gate int	poffset;
420Sstevel@tonic-gate 
430Sstevel@tonic-gate #define	nochng()	lchng = chng
440Sstevel@tonic-gate 
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * Main loop for command mode command decoding.
480Sstevel@tonic-gate  * A few commands are executed here, but main function
490Sstevel@tonic-gate  * is to strip command addresses, do a little address oriented
500Sstevel@tonic-gate  * processing and call command routines to do the real work.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate extern unsigned char *Version;
53802Scf46844 void
540Sstevel@tonic-gate commands(noprompt, exitoneof)
550Sstevel@tonic-gate 	bool noprompt, exitoneof;
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	line *addr;
580Sstevel@tonic-gate 	int c;
590Sstevel@tonic-gate 	int lchng;
600Sstevel@tonic-gate 	int given;
610Sstevel@tonic-gate 	int seensemi;
620Sstevel@tonic-gate 	int cnt;
630Sstevel@tonic-gate 	bool hadpr;
640Sstevel@tonic-gate 	bool gotfile;
650Sstevel@tonic-gate #ifdef XPG4
660Sstevel@tonic-gate 	int d;
670Sstevel@tonic-gate #endif /* XPG4 */
680Sstevel@tonic-gate 	unsigned char *vgetpass();
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	resetflav();
710Sstevel@tonic-gate 	nochng();
720Sstevel@tonic-gate 	for (;;) {
730Sstevel@tonic-gate 		if (!firstpat)
740Sstevel@tonic-gate 			laste = 0;
750Sstevel@tonic-gate 		/*
760Sstevel@tonic-gate 		 * If dot at last command
770Sstevel@tonic-gate 		 * ended up at zero, advance to one if there is a such.
780Sstevel@tonic-gate 		 */
790Sstevel@tonic-gate 		if (dot <= zero) {
800Sstevel@tonic-gate 			dot = zero;
810Sstevel@tonic-gate 			if (dol > zero)
820Sstevel@tonic-gate 				dot = one;
830Sstevel@tonic-gate 		}
840Sstevel@tonic-gate 		shudclob = 0;
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 		/*
870Sstevel@tonic-gate 		 * If autoprint or trailing print flags,
880Sstevel@tonic-gate 		 * print the line at the specified offset
890Sstevel@tonic-gate 		 * before the next command.
900Sstevel@tonic-gate 		 */
910Sstevel@tonic-gate 		if ((pflag || lchng != chng && value(vi_AUTOPRINT) &&
920Sstevel@tonic-gate 		    !inglobal && !inopen && endline) || poffset != 0) {
930Sstevel@tonic-gate 			pflag = 0;
940Sstevel@tonic-gate 			nochng();
950Sstevel@tonic-gate 			if (dol != zero) {
960Sstevel@tonic-gate 				addr1 = addr2 = dot + poffset;
970Sstevel@tonic-gate 				poffset = 0;
980Sstevel@tonic-gate 				if (addr1 < one || addr1 > dol)
990Sstevel@tonic-gate 					error(value(vi_TERSE) ?
1000Sstevel@tonic-gate 					    gettext("Offset out-of-bounds") :
1010Sstevel@tonic-gate 					    gettext("Offset after command "
1020Sstevel@tonic-gate 						"too large"));
1030Sstevel@tonic-gate 				dot = addr1;
1040Sstevel@tonic-gate 				setdot1();
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 				goto print;
1070Sstevel@tonic-gate 			}
1080Sstevel@tonic-gate 		}
1090Sstevel@tonic-gate 		nochng();
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 		/*
1120Sstevel@tonic-gate 		 * Print prompt if appropriate.
1130Sstevel@tonic-gate 		 * If not in global flush output first to prevent
1140Sstevel@tonic-gate 		 * going into pfast mode unreasonably.
1150Sstevel@tonic-gate 		 */
1160Sstevel@tonic-gate 		if (inglobal == 0) {
1170Sstevel@tonic-gate 			flush();
1180Sstevel@tonic-gate 			if (!hush && value(vi_PROMPT) && !globp &&
1190Sstevel@tonic-gate 			    !noprompt && endline) {
1200Sstevel@tonic-gate 				putchar(':');
1210Sstevel@tonic-gate 				hadpr = 1;
1220Sstevel@tonic-gate 			}
1230Sstevel@tonic-gate 			TSYNC();
1240Sstevel@tonic-gate 		}
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 		/*
1270Sstevel@tonic-gate 		 * Gobble up the address.
1280Sstevel@tonic-gate 		 * Degenerate addresses yield ".".
1290Sstevel@tonic-gate 		 */
1300Sstevel@tonic-gate 		addr2 = 0;
1310Sstevel@tonic-gate 		given = seensemi = 0;
1320Sstevel@tonic-gate 		do {
1330Sstevel@tonic-gate 			addr1 = addr2;
1340Sstevel@tonic-gate 			addr = address(0);
1350Sstevel@tonic-gate 			c = getcd();
1360Sstevel@tonic-gate 			if (addr == 0) {
1370Sstevel@tonic-gate 				if (c == ',' || c == ';')
1380Sstevel@tonic-gate 					addr = dot;
1390Sstevel@tonic-gate 				else if (addr1 != 0) {
1400Sstevel@tonic-gate 					addr2 = dot;
1410Sstevel@tonic-gate 					break;
1420Sstevel@tonic-gate 				} else
1430Sstevel@tonic-gate 					break;
1440Sstevel@tonic-gate 			}
1450Sstevel@tonic-gate 			addr2 = addr;
1460Sstevel@tonic-gate 			given++;
1470Sstevel@tonic-gate 			if (c == ';') {
1480Sstevel@tonic-gate 				c = ',';
1490Sstevel@tonic-gate 				dot = addr;
1500Sstevel@tonic-gate 				seensemi = 1;
1510Sstevel@tonic-gate 			}
1520Sstevel@tonic-gate 		} while (c == ',');
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 		if (c == '%') {
1550Sstevel@tonic-gate 			/* %: same as 1,$ */
1560Sstevel@tonic-gate 			addr1 = one;
1570Sstevel@tonic-gate 			addr2 = dol;
1580Sstevel@tonic-gate 			given = 2;
1590Sstevel@tonic-gate 			c = getchar();
1600Sstevel@tonic-gate 		}
1610Sstevel@tonic-gate 		if (addr1 == 0)
1620Sstevel@tonic-gate 			addr1 = addr2;
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 		/*
1650Sstevel@tonic-gate 		 * eat multiple colons
1660Sstevel@tonic-gate 		 */
1670Sstevel@tonic-gate 		while (c == ':')
1680Sstevel@tonic-gate 			c = getchar();
1690Sstevel@tonic-gate 		/*
1700Sstevel@tonic-gate 		 * Set command name for special character commands.
1710Sstevel@tonic-gate 		 */
1720Sstevel@tonic-gate 		tailspec(c);
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 		/*
1750Sstevel@tonic-gate 		 * If called via : escape from open or visual, limit
1760Sstevel@tonic-gate 		 * the set of available commands here to save work below.
1770Sstevel@tonic-gate 		 */
1780Sstevel@tonic-gate 		if (inopen) {
1790Sstevel@tonic-gate 			if (c == '\n' || c == '\r' ||
1800Sstevel@tonic-gate 			    c == CTRL('d') || c == EOF) {
1810Sstevel@tonic-gate 				if (addr2)
1820Sstevel@tonic-gate 					dot = addr2;
1830Sstevel@tonic-gate 				if (c == EOF)
1840Sstevel@tonic-gate 					return;
1850Sstevel@tonic-gate 				continue;
1860Sstevel@tonic-gate 			}
1870Sstevel@tonic-gate 			if (any(c, "o"))
1880Sstevel@tonic-gate notinvis:
1890Sstevel@tonic-gate 				tailprim(Command, 1, 1);
1900Sstevel@tonic-gate 		}
1910Sstevel@tonic-gate 		switch (c) {
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 		case 'a':
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 			switch (peekchar()) {
1960Sstevel@tonic-gate 			case 'b':
1970Sstevel@tonic-gate /* abbreviate */
1980Sstevel@tonic-gate 				tail("abbreviate");
1990Sstevel@tonic-gate 				setnoaddr();
2000Sstevel@tonic-gate 				mapcmd(0, 1);
2010Sstevel@tonic-gate 				anyabbrs = 1;
2020Sstevel@tonic-gate 				continue;
2030Sstevel@tonic-gate 			case 'r':
2040Sstevel@tonic-gate /* args */
2050Sstevel@tonic-gate 				tail("args");
2060Sstevel@tonic-gate 				setnoaddr();
2070Sstevel@tonic-gate 				eol();
2080Sstevel@tonic-gate 				pargs();
2090Sstevel@tonic-gate 				continue;
2100Sstevel@tonic-gate 			}
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate /* append */
2130Sstevel@tonic-gate 			if (inopen)
2140Sstevel@tonic-gate 				goto notinvis;
2150Sstevel@tonic-gate 			tail("append");
2160Sstevel@tonic-gate 			setdot();
2170Sstevel@tonic-gate 			aiflag = exclam();
2180Sstevel@tonic-gate 			donewline();
2190Sstevel@tonic-gate 			vmacchng(0);
2200Sstevel@tonic-gate 			deletenone();
2210Sstevel@tonic-gate 			setin(addr2);
2220Sstevel@tonic-gate 			inappend = 1;
2230Sstevel@tonic-gate 			(void) append(gettty, addr2);
2240Sstevel@tonic-gate 			inappend = 0;
2250Sstevel@tonic-gate 			nochng();
2260Sstevel@tonic-gate 			continue;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 		case 'c':
2290Sstevel@tonic-gate 			switch (peekchar()) {
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate /* copy */
2320Sstevel@tonic-gate 			case 'o':
2330Sstevel@tonic-gate 				tail("copy");
2340Sstevel@tonic-gate 				vmacchng(0);
2350Sstevel@tonic-gate 				vi_move();
2360Sstevel@tonic-gate 				continue;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate /* crypt */
2390Sstevel@tonic-gate 			case 'r':
2400Sstevel@tonic-gate 				tail("crypt");
2410Sstevel@tonic-gate 				crflag = -1;
2420Sstevel@tonic-gate 			ent_crypt:
2430Sstevel@tonic-gate 				setnoaddr();
2440Sstevel@tonic-gate 				xflag = 1;
2450Sstevel@tonic-gate 				if (permflag)
2460Sstevel@tonic-gate 					(void) crypt_close(perm);
2470Sstevel@tonic-gate 				permflag = 1;
2480Sstevel@tonic-gate 				if ((kflag = run_setkey(perm,
2490Sstevel@tonic-gate 				    (key = vgetpass(
2500Sstevel@tonic-gate 					gettext("Enter key:"))))) == -1) {
2510Sstevel@tonic-gate 					xflag = 0;
2520Sstevel@tonic-gate 					kflag = 0;
2530Sstevel@tonic-gate 					crflag = 0;
2540Sstevel@tonic-gate 					smerror(gettext("Encryption facility "
2550Sstevel@tonic-gate 						    "not available\n"));
2560Sstevel@tonic-gate 				}
2570Sstevel@tonic-gate 				if (kflag == 0)
2580Sstevel@tonic-gate 					crflag = 0;
2590Sstevel@tonic-gate 				continue;
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate /* cd */
2620Sstevel@tonic-gate 			case 'd':
2630Sstevel@tonic-gate 				tail("cd");
2640Sstevel@tonic-gate 				goto changdir;
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate /* chdir */
2670Sstevel@tonic-gate 			case 'h':
2680Sstevel@tonic-gate 				ignchar();
2690Sstevel@tonic-gate 				if (peekchar() == 'd') {
270802Scf46844 					unsigned char *p;
2710Sstevel@tonic-gate 					tail2of("chdir");
2720Sstevel@tonic-gate changdir:
2730Sstevel@tonic-gate 					if (savedfile[0] == '/' ||
2740Sstevel@tonic-gate 					    !value(vi_WARN))
2750Sstevel@tonic-gate 						(void) exclam();
2760Sstevel@tonic-gate 					else
2770Sstevel@tonic-gate 						(void) quickly();
2780Sstevel@tonic-gate 					if (skipend()) {
2790Sstevel@tonic-gate 						p = (unsigned char *)
2800Sstevel@tonic-gate 						    getenv("HOME");
2810Sstevel@tonic-gate 						if (p == NULL)
2820Sstevel@tonic-gate 							error(gettext(
2830Sstevel@tonic-gate 								"Home directory"
2840Sstevel@tonic-gate 								    /*CSTYLED*/
2850Sstevel@tonic-gate 								    " unknown"));
2860Sstevel@tonic-gate 					} else
2870Sstevel@tonic-gate 						getone(), p = file;
2880Sstevel@tonic-gate 					eol();
289802Scf46844 					if (chdir((char *)p) < 0)
2900Sstevel@tonic-gate 						filioerr(p);
2910Sstevel@tonic-gate 					if (savedfile[0] != '/')
2920Sstevel@tonic-gate 						edited = 0;
2930Sstevel@tonic-gate 					continue;
2940Sstevel@tonic-gate 				}
2950Sstevel@tonic-gate 				if (inopen)
296802Scf46844 					tailprim((unsigned char *)"change",
297802Scf46844 					    2, 1);
2980Sstevel@tonic-gate 				tail2of("change");
2990Sstevel@tonic-gate 				break;
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 			default:
3020Sstevel@tonic-gate 				if (inopen)
3030Sstevel@tonic-gate 					goto notinvis;
3040Sstevel@tonic-gate 				tail("change");
3050Sstevel@tonic-gate 				break;
3060Sstevel@tonic-gate 			}
3070Sstevel@tonic-gate /* change */
3080Sstevel@tonic-gate 			aiflag = exclam();
3090Sstevel@tonic-gate #ifdef XPG4ONLY
3100Sstevel@tonic-gate 			setcount2();
3110Sstevel@tonic-gate 			donewline();
3120Sstevel@tonic-gate #else /* XPG6 and Solaris */
3130Sstevel@tonic-gate 			setCNL();
3140Sstevel@tonic-gate #endif /* XPG4ONLY */
3150Sstevel@tonic-gate 			vmacchng(0);
3160Sstevel@tonic-gate 			setin(addr1);
317802Scf46844 			(void) delete(0);
3180Sstevel@tonic-gate 			inappend = 1;
3190Sstevel@tonic-gate 			if (append(gettty, addr1 - 1) == 0) {
3200Sstevel@tonic-gate #ifdef XPG4
3210Sstevel@tonic-gate 				/*
3220Sstevel@tonic-gate 				 * P2003.2/D9:5.10.7.2.4, p. 646,
3230Sstevel@tonic-gate 				 * assertion 214(A). If nothing changed,
3240Sstevel@tonic-gate 				 * set dot to the line preceding the lines
3250Sstevel@tonic-gate 				 * to be changed.
3260Sstevel@tonic-gate 				 */
3270Sstevel@tonic-gate 				dot = addr1 - 1;
3280Sstevel@tonic-gate #else /* XPG4 */
3290Sstevel@tonic-gate 				dot = addr1;
3300Sstevel@tonic-gate #endif /* XPG4 */
3310Sstevel@tonic-gate 				if (dot > dol)
3320Sstevel@tonic-gate 					dot = dol;
3330Sstevel@tonic-gate 			}
3340Sstevel@tonic-gate 			inappend = 0;
3350Sstevel@tonic-gate 			nochng();
3360Sstevel@tonic-gate 			continue;
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate /* delete */
3390Sstevel@tonic-gate 		case 'd':
3400Sstevel@tonic-gate 			/*
3410Sstevel@tonic-gate 			 * Caution: dp and dl have special meaning already.
3420Sstevel@tonic-gate 			 */
3430Sstevel@tonic-gate 			tail("delete");
3440Sstevel@tonic-gate 			c = cmdreg();
3450Sstevel@tonic-gate #ifdef XPG4ONLY
3460Sstevel@tonic-gate 			setcount2();
3470Sstevel@tonic-gate 			donewline();
3480Sstevel@tonic-gate #else /* XPG6 and Solaris */
3490Sstevel@tonic-gate 			setCNL();
3500Sstevel@tonic-gate #endif /* XPG4ONLY */
3510Sstevel@tonic-gate 			vmacchng(0);
3520Sstevel@tonic-gate 			if (c)
353802Scf46844 				(void) YANKreg(c);
354802Scf46844 			(void) delete(0);
3550Sstevel@tonic-gate 			appendnone();
3560Sstevel@tonic-gate 			continue;
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate /* edit */
3590Sstevel@tonic-gate /* ex */
3600Sstevel@tonic-gate 		case 'e':
3610Sstevel@tonic-gate 			if (crflag == 2 || crflag == -2)
3620Sstevel@tonic-gate 				crflag = -1;
3630Sstevel@tonic-gate 			tail(peekchar() == 'x' ? "ex" : "edit");
3640Sstevel@tonic-gate editcmd:
3650Sstevel@tonic-gate 			if (!exclam() && chng)
3660Sstevel@tonic-gate 				c = 'E';
3670Sstevel@tonic-gate 			gotfile = 0;
3680Sstevel@tonic-gate 			if (c == 'E') {
3690Sstevel@tonic-gate 				if (inopen && !value(vi_AUTOWRITE)) {
3700Sstevel@tonic-gate 					filename(c);
3710Sstevel@tonic-gate 					gotfile = 1;
3720Sstevel@tonic-gate 				}
3730Sstevel@tonic-gate 				ungetchar(lastchar());
3740Sstevel@tonic-gate 				if (!exclam()) {
3750Sstevel@tonic-gate 					ckaw();
3760Sstevel@tonic-gate 					if (chng && dol > zero) {
3770Sstevel@tonic-gate 						xchng = 0;
3780Sstevel@tonic-gate 						error(value(vi_TERSE) ?
3790Sstevel@tonic-gate 						    gettext("No write") :
3800Sstevel@tonic-gate 						    gettext("No write since "
3810Sstevel@tonic-gate 							"last change (:%s! "
3820Sstevel@tonic-gate 							"overrides)"),
3830Sstevel@tonic-gate 						    Command);
3840Sstevel@tonic-gate 					}
3850Sstevel@tonic-gate 				}
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 			}
3880Sstevel@tonic-gate 			if (gotfile == 0)
3890Sstevel@tonic-gate 				filename(c);
3900Sstevel@tonic-gate 			setnoaddr();
3910Sstevel@tonic-gate doecmd:
3920Sstevel@tonic-gate 			init();
3930Sstevel@tonic-gate 			addr2 = zero;
3940Sstevel@tonic-gate 			laste++;
3950Sstevel@tonic-gate 			sync();
3960Sstevel@tonic-gate 			rop(c);
3970Sstevel@tonic-gate 			nochng();
3980Sstevel@tonic-gate 			continue;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate /* file */
4010Sstevel@tonic-gate 		case 'f':
4020Sstevel@tonic-gate 			tail("file");
4030Sstevel@tonic-gate 			setnoaddr();
4040Sstevel@tonic-gate 			filename(c);
4050Sstevel@tonic-gate 			noonl();
4060Sstevel@tonic-gate /*
4070Sstevel@tonic-gate  *			synctmp();
4080Sstevel@tonic-gate  */
4090Sstevel@tonic-gate 			continue;
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate /* global */
4120Sstevel@tonic-gate 		case 'g':
4130Sstevel@tonic-gate 			tail("global");
4140Sstevel@tonic-gate 			global(!exclam());
4150Sstevel@tonic-gate 			nochng();
4160Sstevel@tonic-gate 			continue;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate /* insert */
4190Sstevel@tonic-gate 		case 'i':
4200Sstevel@tonic-gate 			if (inopen)
4210Sstevel@tonic-gate 				goto notinvis;
4220Sstevel@tonic-gate 			tail("insert");
4230Sstevel@tonic-gate 			setdot();
4240Sstevel@tonic-gate 			nonzero();
4250Sstevel@tonic-gate 			aiflag = exclam();
4260Sstevel@tonic-gate 			donewline();
4270Sstevel@tonic-gate 			vmacchng(0);
4280Sstevel@tonic-gate 			deletenone();
4290Sstevel@tonic-gate 			setin(addr2);
4300Sstevel@tonic-gate 			inappend = 1;
4310Sstevel@tonic-gate 			(void) append(gettty, addr2 - 1);
4320Sstevel@tonic-gate 			inappend = 0;
4330Sstevel@tonic-gate 			if (dot == zero && dol > zero)
4340Sstevel@tonic-gate 				dot = one;
4350Sstevel@tonic-gate 			nochng();
4360Sstevel@tonic-gate 			continue;
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate /* join */
4390Sstevel@tonic-gate 		case 'j':
4400Sstevel@tonic-gate 			tail("join");
4410Sstevel@tonic-gate 			c = exclam();
4420Sstevel@tonic-gate 			setcount();
4430Sstevel@tonic-gate 			nonzero();
4440Sstevel@tonic-gate 			donewline();
4450Sstevel@tonic-gate 			vmacchng(0);
4460Sstevel@tonic-gate #ifdef XPG4ONLY
4470Sstevel@tonic-gate 			/*
4480Sstevel@tonic-gate 			 * if no count was specified, addr1 == addr2. if only
4490Sstevel@tonic-gate 			 * 1 range arg was specified, inc addr2 to allow
4500Sstevel@tonic-gate 			 * joining of the next line.
4510Sstevel@tonic-gate 			 */
4520Sstevel@tonic-gate 			if (given < 2 && (addr1 == addr2) && (addr2 != dol))
4530Sstevel@tonic-gate 				addr2++;
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate #else /* XPG6 and Solaris */
4560Sstevel@tonic-gate 			if (given < 2 && addr2 != dol)
4570Sstevel@tonic-gate 				addr2++;
4580Sstevel@tonic-gate #endif /* XPG4ONLY */
459802Scf46844 			(void) join(c);
4600Sstevel@tonic-gate 			continue;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate /* k */
4630Sstevel@tonic-gate 		case 'k':
4640Sstevel@tonic-gate casek:
4650Sstevel@tonic-gate 			pastwh();
4660Sstevel@tonic-gate 			c = getchar();
4670Sstevel@tonic-gate 			if (endcmd(c))
468802Scf46844 				serror((vi_TERSE) ?
469802Scf46844 				    (unsigned char *)gettext("Mark what?") :
470802Scf46844 				    (unsigned char *)
471802Scf46844 				    gettext("%s requires following "
472802Scf46844 				    "letter"), Command);
4730Sstevel@tonic-gate 			donewline();
4740Sstevel@tonic-gate 			if (!islower(c))
4750Sstevel@tonic-gate 				error((vi_TERSE) ? gettext("Bad mark") :
4760Sstevel@tonic-gate 					gettext("Mark must specify a letter"));
4770Sstevel@tonic-gate 			setdot();
4780Sstevel@tonic-gate 			nonzero();
4790Sstevel@tonic-gate 			names[c - 'a'] = *addr2 &~ 01;
4800Sstevel@tonic-gate 			anymarks = 1;
4810Sstevel@tonic-gate 			continue;
4820Sstevel@tonic-gate 
4830Sstevel@tonic-gate /* list */
4840Sstevel@tonic-gate 		case 'l':
4850Sstevel@tonic-gate 			tail("list");
4860Sstevel@tonic-gate #ifdef XPG4ONLY
4870Sstevel@tonic-gate 			setcount2();
4880Sstevel@tonic-gate 			donewline();
4890Sstevel@tonic-gate #else /* XPG6 and Solaris */
4900Sstevel@tonic-gate 			setCNL();
4910Sstevel@tonic-gate #endif /* XPG4ONLY */
4920Sstevel@tonic-gate 			(void) setlist(1);
4930Sstevel@tonic-gate 			pflag = 0;
4940Sstevel@tonic-gate 			goto print;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 		case 'm':
4970Sstevel@tonic-gate 			if (peekchar() == 'a') {
4980Sstevel@tonic-gate 				ignchar();
4990Sstevel@tonic-gate 				if (peekchar() == 'p') {
5000Sstevel@tonic-gate /* map */
5010Sstevel@tonic-gate 					tail2of("map");
5020Sstevel@tonic-gate 					setnoaddr();
5030Sstevel@tonic-gate 					mapcmd(0, 0);
5040Sstevel@tonic-gate 					continue;
5050Sstevel@tonic-gate 				}
5060Sstevel@tonic-gate /* mark */
5070Sstevel@tonic-gate 				tail2of("mark");
5080Sstevel@tonic-gate 				goto casek;
5090Sstevel@tonic-gate 			}
5100Sstevel@tonic-gate /* move */
5110Sstevel@tonic-gate 			tail("move");
5120Sstevel@tonic-gate 			vmacchng(0);
5130Sstevel@tonic-gate 			vi_move();
5140Sstevel@tonic-gate 			continue;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 		case 'n':
5170Sstevel@tonic-gate 			if (peekchar() == 'u') {
5180Sstevel@tonic-gate 				tail("number");
5190Sstevel@tonic-gate 				goto numberit;
5200Sstevel@tonic-gate 			}
5210Sstevel@tonic-gate /* next */
5220Sstevel@tonic-gate 			tail("next");
5230Sstevel@tonic-gate 			setnoaddr();
5240Sstevel@tonic-gate 			if (!exclam()) {
5250Sstevel@tonic-gate 				ckaw();
5260Sstevel@tonic-gate 				if (chng && dol > zero) {
5270Sstevel@tonic-gate 					xchng = 0;
5280Sstevel@tonic-gate 					error(value(vi_TERSE) ?
5290Sstevel@tonic-gate 					    gettext("No write") :
5300Sstevel@tonic-gate 					    gettext("No write since last "
5310Sstevel@tonic-gate 						"change (:%s! overrides)"),
5320Sstevel@tonic-gate 					    Command);
5330Sstevel@tonic-gate 				}
5340Sstevel@tonic-gate 			}
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 			if (getargs())
5370Sstevel@tonic-gate 				makargs();
5380Sstevel@tonic-gate 			next();
5390Sstevel@tonic-gate 			c = 'e';
5400Sstevel@tonic-gate 			filename(c);
5410Sstevel@tonic-gate 			goto doecmd;
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate /* open */
5440Sstevel@tonic-gate 		case 'o':
5450Sstevel@tonic-gate 			tail("open");
5460Sstevel@tonic-gate 			oop();
5470Sstevel@tonic-gate 			pflag = 0;
5480Sstevel@tonic-gate 			nochng();
5490Sstevel@tonic-gate 			continue;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 		case 'p':
5520Sstevel@tonic-gate 		case 'P':
5530Sstevel@tonic-gate 			switch (peekchar()) {
5540Sstevel@tonic-gate #ifdef TAG_STACK
5550Sstevel@tonic-gate /* pop */
5560Sstevel@tonic-gate 			case 'o':
5570Sstevel@tonic-gate 				tail("pop");
5580Sstevel@tonic-gate 				poptag(exclam());
5590Sstevel@tonic-gate 				if (!inopen)
5600Sstevel@tonic-gate 					lchng = chng - 1;
5610Sstevel@tonic-gate 				else
5620Sstevel@tonic-gate 					nochng();
5630Sstevel@tonic-gate 				continue;
5640Sstevel@tonic-gate #endif
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate /* put */
5670Sstevel@tonic-gate 			case 'u':
5680Sstevel@tonic-gate 				tail("put");
5690Sstevel@tonic-gate 				setdot();
5700Sstevel@tonic-gate 				c = cmdreg();
5710Sstevel@tonic-gate 				eol();
5720Sstevel@tonic-gate 				vmacchng(0);
5730Sstevel@tonic-gate 				if (c)
574802Scf46844 					(void) putreg(c);
5750Sstevel@tonic-gate 				else
576802Scf46844 					(void) put();
5770Sstevel@tonic-gate 				continue;
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 			case 'r':
5800Sstevel@tonic-gate 				ignchar();
5810Sstevel@tonic-gate 				if (peekchar() == 'e') {
5820Sstevel@tonic-gate /* preserve */
5830Sstevel@tonic-gate 					tail2of("preserve");
5840Sstevel@tonic-gate 					eol();
5850Sstevel@tonic-gate 					if (preserve() == 0)
5860Sstevel@tonic-gate 						error(gettext(
5870Sstevel@tonic-gate 						    "Preserve failed!"));
5880Sstevel@tonic-gate 					else {
5890Sstevel@tonic-gate #ifdef XPG4
5900Sstevel@tonic-gate 						/*
5910Sstevel@tonic-gate 						 * error() incs errcnt. this is
5920Sstevel@tonic-gate 						 * misleading here; and a
5930Sstevel@tonic-gate 						 * violation of POSIX. so call
5940Sstevel@tonic-gate 						 * noerror() instead.
5950Sstevel@tonic-gate 						 * this is for assertion ex:222.
5960Sstevel@tonic-gate 						 */
5970Sstevel@tonic-gate 						noerror(
5980Sstevel@tonic-gate 						    gettext("File preserved."));
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate #else /* XPG4 */
6010Sstevel@tonic-gate 						error(
6020Sstevel@tonic-gate 						    gettext("File preserved."));
6030Sstevel@tonic-gate #endif /* XPG4 */
6040Sstevel@tonic-gate 					}
6050Sstevel@tonic-gate 				}
6060Sstevel@tonic-gate 				tail2of("print");
6070Sstevel@tonic-gate 				break;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 			default:
6100Sstevel@tonic-gate 				tail("print");
6110Sstevel@tonic-gate 				break;
6120Sstevel@tonic-gate 			}
6130Sstevel@tonic-gate /* print */
6140Sstevel@tonic-gate 			setCNL();
6150Sstevel@tonic-gate 			pflag = 0;
6160Sstevel@tonic-gate print:
6170Sstevel@tonic-gate 			nonzero();
6180Sstevel@tonic-gate 			if (clear_screen && span() > lines) {
6190Sstevel@tonic-gate 				flush1();
6200Sstevel@tonic-gate 				vclear();
6210Sstevel@tonic-gate 			}
6220Sstevel@tonic-gate 			/*
6230Sstevel@tonic-gate 			 * poffset is nonzero if trailing + or - flags
6240Sstevel@tonic-gate 			 * were given, and in that case we need to
6250Sstevel@tonic-gate 			 * adjust dot before printing a line.
6260Sstevel@tonic-gate 			 */
6270Sstevel@tonic-gate 			if (poffset == 0)
6280Sstevel@tonic-gate 				plines(addr1, addr2, 1);
6290Sstevel@tonic-gate 			else
6300Sstevel@tonic-gate 				dot = addr2;
6310Sstevel@tonic-gate 			continue;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate /* quit */
6340Sstevel@tonic-gate 		case 'q':
6350Sstevel@tonic-gate 			tail("quit");
6360Sstevel@tonic-gate 			setnoaddr();
6370Sstevel@tonic-gate 			c = quickly();
6380Sstevel@tonic-gate 			eol();
6390Sstevel@tonic-gate 			if (!c)
6400Sstevel@tonic-gate quit:
6410Sstevel@tonic-gate 				if (nomore())
6420Sstevel@tonic-gate 					continue;
6430Sstevel@tonic-gate 			if (inopen) {
6440Sstevel@tonic-gate 				vgoto(WECHO, 0);
6450Sstevel@tonic-gate 				if (!ateopr())
6460Sstevel@tonic-gate 					vnfl();
6470Sstevel@tonic-gate 				else {
6480Sstevel@tonic-gate 					tostop();
6490Sstevel@tonic-gate 				}
6500Sstevel@tonic-gate 				flush();
6510Sstevel@tonic-gate 				setty(normf);
6520Sstevel@tonic-gate 				ixlatctl(1);
6530Sstevel@tonic-gate 			}
6540Sstevel@tonic-gate 			cleanup(1);
6550Sstevel@tonic-gate 			exit(errcnt);
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 		case 'r':
6580Sstevel@tonic-gate 			if (peekchar() == 'e') {
6590Sstevel@tonic-gate 				ignchar();
6600Sstevel@tonic-gate 				switch (peekchar()) {
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate /* rewind */
6630Sstevel@tonic-gate 				case 'w':
6640Sstevel@tonic-gate 					tail2of("rewind");
6650Sstevel@tonic-gate 					setnoaddr();
6660Sstevel@tonic-gate 					if (!exclam()) {
6670Sstevel@tonic-gate 						ckaw();
6680Sstevel@tonic-gate 						if (chng && dol > zero)
6690Sstevel@tonic-gate 							error((vi_TERSE) ?
6700Sstevel@tonic-gate 							    /*CSTYLED*/
6710Sstevel@tonic-gate 							    gettext("No write") :
6720Sstevel@tonic-gate 							    gettext("No write "
6730Sstevel@tonic-gate 								"since last "
6740Sstevel@tonic-gate 								"change (:rewi"
6750Sstevel@tonic-gate 								/*CSTYLED*/
6760Sstevel@tonic-gate 								"nd! overrides)"));
6770Sstevel@tonic-gate 					}
6780Sstevel@tonic-gate 					eol();
6790Sstevel@tonic-gate 					erewind();
6800Sstevel@tonic-gate 					next();
6810Sstevel@tonic-gate 					c = 'e';
6820Sstevel@tonic-gate 					ungetchar(lastchar());
6830Sstevel@tonic-gate 					filename(c);
6840Sstevel@tonic-gate 					goto doecmd;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate /* recover */
6870Sstevel@tonic-gate 				case 'c':
6880Sstevel@tonic-gate 					tail2of("recover");
6890Sstevel@tonic-gate 					setnoaddr();
6900Sstevel@tonic-gate 					c = 'e';
6910Sstevel@tonic-gate 					if (!exclam() && chng)
6920Sstevel@tonic-gate 						c = 'E';
6930Sstevel@tonic-gate 					filename(c);
6940Sstevel@tonic-gate 					if (c == 'E') {
6950Sstevel@tonic-gate 						ungetchar(lastchar());
6960Sstevel@tonic-gate 						(void) quickly();
6970Sstevel@tonic-gate 					}
6980Sstevel@tonic-gate 					init();
6990Sstevel@tonic-gate 					addr2 = zero;
7000Sstevel@tonic-gate 					laste++;
7010Sstevel@tonic-gate 					sync();
7020Sstevel@tonic-gate 					recover();
7030Sstevel@tonic-gate 					rop2();
7040Sstevel@tonic-gate 					revocer();
7050Sstevel@tonic-gate 					if (status == 0)
7060Sstevel@tonic-gate 						rop3(c);
7070Sstevel@tonic-gate 					if (dol != zero)
7080Sstevel@tonic-gate 						change();
7090Sstevel@tonic-gate 					nochng();
7100Sstevel@tonic-gate 					continue;
7110Sstevel@tonic-gate 				}
7120Sstevel@tonic-gate 				tail2of("read");
7130Sstevel@tonic-gate 			} else
7140Sstevel@tonic-gate 				tail("read");
7150Sstevel@tonic-gate /* read */
7160Sstevel@tonic-gate 			if (crflag == 2 || crflag == -2)
7170Sstevel@tonic-gate 			/* restore crflag for new input text */
7180Sstevel@tonic-gate 				crflag = -1;
7190Sstevel@tonic-gate 			if (savedfile[0] == 0 && dol == zero)
7200Sstevel@tonic-gate 				c = 'e';
7210Sstevel@tonic-gate 			pastwh();
7220Sstevel@tonic-gate 			vmacchng(0);
7230Sstevel@tonic-gate 			if (peekchar() == '!') {
7240Sstevel@tonic-gate 				setdot();
7250Sstevel@tonic-gate 				ignchar();
726500Sceastha 				unix0(0, 1);
727802Scf46844 				(void) vi_filter(0);
7280Sstevel@tonic-gate 				continue;
7290Sstevel@tonic-gate 			}
7300Sstevel@tonic-gate 			filename(c);
7310Sstevel@tonic-gate 			rop(c);
7320Sstevel@tonic-gate 			nochng();
7330Sstevel@tonic-gate 			if (inopen && endline && addr1 > zero && addr1 < dol)
7340Sstevel@tonic-gate 				dot = addr1 + 1;
7350Sstevel@tonic-gate 			continue;
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 		case 's':
7380Sstevel@tonic-gate 			switch (peekchar()) {
7390Sstevel@tonic-gate 			/*
7400Sstevel@tonic-gate 			 * Caution: 2nd char cannot be c, g, or r
7410Sstevel@tonic-gate 			 * because these have meaning to substitute.
7420Sstevel@tonic-gate 			 */
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate /* set */
7450Sstevel@tonic-gate 			case 'e':
7460Sstevel@tonic-gate 				tail("set");
7470Sstevel@tonic-gate 				setnoaddr();
7480Sstevel@tonic-gate 				set();
7490Sstevel@tonic-gate 				continue;
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate /* shell */
7520Sstevel@tonic-gate 			case 'h':
7530Sstevel@tonic-gate 				tail("shell");
7540Sstevel@tonic-gate 				setNAEOL();
7550Sstevel@tonic-gate 				vnfl();
756802Scf46844 				putpad((unsigned char *)exit_ca_mode);
7570Sstevel@tonic-gate 				flush();
7580Sstevel@tonic-gate 				resetterm();
7590Sstevel@tonic-gate 				unixwt(1, unixex("-i", (char *)0, 0, 0));
7600Sstevel@tonic-gate 				vcontin(0);
7610Sstevel@tonic-gate 				continue;
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate /* source */
7640Sstevel@tonic-gate 			case 'o':
7650Sstevel@tonic-gate #ifdef notdef
7660Sstevel@tonic-gate 				if (inopen)
7670Sstevel@tonic-gate 					goto notinvis;
7680Sstevel@tonic-gate #endif
7690Sstevel@tonic-gate 				tail("source");
7700Sstevel@tonic-gate 				setnoaddr();
7710Sstevel@tonic-gate 				getone();
7720Sstevel@tonic-gate 				eol();
7730Sstevel@tonic-gate 				source(file, 0);
7740Sstevel@tonic-gate 				continue;
7750Sstevel@tonic-gate #ifdef SIGTSTP
7760Sstevel@tonic-gate /* stop, suspend */
7770Sstevel@tonic-gate 			case 't':
7780Sstevel@tonic-gate 				tail("stop");
7790Sstevel@tonic-gate 				goto suspend;
7800Sstevel@tonic-gate 			case 'u':
7810Sstevel@tonic-gate #ifdef XPG4
7820Sstevel@tonic-gate 				/*
7830Sstevel@tonic-gate 				 * for POSIX, "su" with no other distinguishing
7840Sstevel@tonic-gate 				 * characteristics, maps to "s". Re. P1003.D11,
7850Sstevel@tonic-gate 				 * 5.10.7.3.
7860Sstevel@tonic-gate 				 *
7870Sstevel@tonic-gate 				 * so, unless the "su" is followed by a "s" or
7880Sstevel@tonic-gate 				 * a "!", we assume that the user means "s".
7890Sstevel@tonic-gate 				 */
7900Sstevel@tonic-gate 				switch (d = peekchar()) {
7910Sstevel@tonic-gate 				case 's':
7920Sstevel@tonic-gate 				case '!':
7930Sstevel@tonic-gate #endif /* XPG4 */
7940Sstevel@tonic-gate 					tail("suspend");
7950Sstevel@tonic-gate suspend:
7960Sstevel@tonic-gate 					c = exclam();
7970Sstevel@tonic-gate 					eol();
7980Sstevel@tonic-gate 					if (!c)
7990Sstevel@tonic-gate 						ckaw();
8000Sstevel@tonic-gate 					onsusp(0);
8010Sstevel@tonic-gate 					continue;
8020Sstevel@tonic-gate #ifdef XPG4
8030Sstevel@tonic-gate 				}
8040Sstevel@tonic-gate #endif /* XPG4 */
8050Sstevel@tonic-gate #endif
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 			}
8080Sstevel@tonic-gate 			/* fall into ... */
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate /* & */
8110Sstevel@tonic-gate /* ~ */
8120Sstevel@tonic-gate /* substitute */
8130Sstevel@tonic-gate 		case '&':
8140Sstevel@tonic-gate 		case '~':
8150Sstevel@tonic-gate 			Command = (unsigned char *)"substitute";
8160Sstevel@tonic-gate 			if (c == 's')
8170Sstevel@tonic-gate 				tail(Command);
8180Sstevel@tonic-gate 			vmacchng(0);
8190Sstevel@tonic-gate 			if (!substitute(c))
8200Sstevel@tonic-gate 				pflag = 0;
8210Sstevel@tonic-gate 			continue;
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate /* t */
8240Sstevel@tonic-gate 		case 't':
8250Sstevel@tonic-gate 			if (peekchar() == 'a') {
826*4488Scf46844 				tagflg = 1; /* :tag command */
8270Sstevel@tonic-gate 				tail("tag");
8280Sstevel@tonic-gate 				tagfind(exclam());
829*4488Scf46844 				tagflg = 0;
8300Sstevel@tonic-gate 				if (!inopen)
8310Sstevel@tonic-gate 					lchng = chng - 1;
8320Sstevel@tonic-gate 				else
8330Sstevel@tonic-gate 					nochng();
8340Sstevel@tonic-gate 				continue;
8350Sstevel@tonic-gate 			}
8360Sstevel@tonic-gate 			tail("t");
8370Sstevel@tonic-gate 			vmacchng(0);
8380Sstevel@tonic-gate 			vi_move();
8390Sstevel@tonic-gate 			continue;
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 		case 'u':
8420Sstevel@tonic-gate 			if (peekchar() == 'n') {
8430Sstevel@tonic-gate 				ignchar();
8440Sstevel@tonic-gate 				switch (peekchar()) {
8450Sstevel@tonic-gate /* unmap */
8460Sstevel@tonic-gate 				case 'm':
8470Sstevel@tonic-gate 					tail2of("unmap");
8480Sstevel@tonic-gate 					setnoaddr();
8490Sstevel@tonic-gate 					mapcmd(1, 0);
8500Sstevel@tonic-gate 					continue;
8510Sstevel@tonic-gate /* unabbreviate */
8520Sstevel@tonic-gate 				case 'a':
8530Sstevel@tonic-gate 					tail2of("unabbreviate");
8540Sstevel@tonic-gate 					setnoaddr();
8550Sstevel@tonic-gate 					mapcmd(1, 1);
8560Sstevel@tonic-gate 					anyabbrs = 1;
8570Sstevel@tonic-gate 					continue;
8580Sstevel@tonic-gate 				}
8590Sstevel@tonic-gate /* undo */
8600Sstevel@tonic-gate 				tail2of("undo");
8610Sstevel@tonic-gate 			} else
8620Sstevel@tonic-gate 				tail("undo");
8630Sstevel@tonic-gate 			setnoaddr();
8640Sstevel@tonic-gate 			markDOT();
8650Sstevel@tonic-gate 			c = exclam();
8660Sstevel@tonic-gate 			donewline();
8670Sstevel@tonic-gate 			undo(c);
8680Sstevel@tonic-gate 			continue;
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 		case 'v':
8710Sstevel@tonic-gate 			switch (peekchar()) {
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 			case 'e':
8740Sstevel@tonic-gate /* version */
8750Sstevel@tonic-gate 				tail("version");
8760Sstevel@tonic-gate 				setNAEOL();
877802Scf46844 				viprintf("%s", Version);
8780Sstevel@tonic-gate 				noonl();
8790Sstevel@tonic-gate 				continue;
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate /* visual */
8820Sstevel@tonic-gate 			case 'i':
8830Sstevel@tonic-gate 				tail("visual");
8840Sstevel@tonic-gate 				if (inopen) {
8850Sstevel@tonic-gate 					c = 'e';
8860Sstevel@tonic-gate 					goto editcmd;
8870Sstevel@tonic-gate 				}
8880Sstevel@tonic-gate 				vop();
8890Sstevel@tonic-gate 				pflag = 0;
8900Sstevel@tonic-gate 				nochng();
8910Sstevel@tonic-gate 				continue;
8920Sstevel@tonic-gate 			}
8930Sstevel@tonic-gate /* v */
8940Sstevel@tonic-gate 			tail("v");
8950Sstevel@tonic-gate 			global(0);
8960Sstevel@tonic-gate 			nochng();
8970Sstevel@tonic-gate 			continue;
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate /* write */
9000Sstevel@tonic-gate 		case 'w':
9010Sstevel@tonic-gate 			c = peekchar();
9020Sstevel@tonic-gate 			tail(c == 'q' ? "wq" : "write");
9030Sstevel@tonic-gate wq:
9040Sstevel@tonic-gate 			if (skipwh() && peekchar() == '!') {
9050Sstevel@tonic-gate 				pofix();
9060Sstevel@tonic-gate 				ignchar();
9070Sstevel@tonic-gate 				setall();
908500Sceastha 				unix0(0, 1);
909802Scf46844 				(void) vi_filter(1);
9100Sstevel@tonic-gate 			} else {
9110Sstevel@tonic-gate 				setall();
9120Sstevel@tonic-gate 				if (c == 'q')
9130Sstevel@tonic-gate 					write_quit = 1;
9140Sstevel@tonic-gate 				else
9150Sstevel@tonic-gate 					write_quit = 0;
9160Sstevel@tonic-gate 				wop(1);
9170Sstevel@tonic-gate 				nochng();
9180Sstevel@tonic-gate 			}
9190Sstevel@tonic-gate 			if (c == 'q')
9200Sstevel@tonic-gate 				goto quit;
9210Sstevel@tonic-gate 			continue;
9220Sstevel@tonic-gate /* X: crypt */
9230Sstevel@tonic-gate 		case 'X':
9240Sstevel@tonic-gate 			crflag = -1; /* determine if file is encrypted */
9250Sstevel@tonic-gate 			goto ent_crypt;
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 		case 'C':
9280Sstevel@tonic-gate 			crflag = 1;  /* assume files read in are encrypted */
9290Sstevel@tonic-gate 			goto ent_crypt;
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate /* xit */
9320Sstevel@tonic-gate 		case 'x':
9330Sstevel@tonic-gate 			tail("xit");
9340Sstevel@tonic-gate 			if (!chng)
9350Sstevel@tonic-gate 				goto quit;
9360Sstevel@tonic-gate 			c = 'q';
9370Sstevel@tonic-gate 			goto wq;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate /* yank */
9400Sstevel@tonic-gate 		case 'y':
9410Sstevel@tonic-gate 			tail("yank");
9420Sstevel@tonic-gate 			c = cmdreg();
9430Sstevel@tonic-gate #ifdef XPG4ONLY
9440Sstevel@tonic-gate 			setcount2();
9450Sstevel@tonic-gate #else /* XPG6 and Solaris */
9460Sstevel@tonic-gate 			setcount();
9470Sstevel@tonic-gate #endif /* XPG4ONLY */
9480Sstevel@tonic-gate 			eol();
9490Sstevel@tonic-gate 			vmacchng(0);
9500Sstevel@tonic-gate 			if (c)
951802Scf46844 				(void) YANKreg(c);
9520Sstevel@tonic-gate 			else
953802Scf46844 				(void) yank();
9540Sstevel@tonic-gate 			continue;
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate /* z */
9570Sstevel@tonic-gate 		case 'z':
9580Sstevel@tonic-gate 			zop(0);
9590Sstevel@tonic-gate 			pflag = 0;
9600Sstevel@tonic-gate 			continue;
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate /* * */
9630Sstevel@tonic-gate /* @ */
9640Sstevel@tonic-gate 		case '*':
9650Sstevel@tonic-gate 		case '@':
9660Sstevel@tonic-gate 			c = getchar();
9670Sstevel@tonic-gate 			if (c == '\n' || c == '\r')
9680Sstevel@tonic-gate 				ungetchar(c);
9690Sstevel@tonic-gate 			if (any(c, "@*\n\r"))
9700Sstevel@tonic-gate 				c = lastmac;
9710Sstevel@tonic-gate 			if (isupper(c))
9720Sstevel@tonic-gate 				c = tolower(c);
9730Sstevel@tonic-gate 			if (!islower(c))
9740Sstevel@tonic-gate 				error(gettext("Bad register"));
9750Sstevel@tonic-gate 			donewline();
9760Sstevel@tonic-gate 			setdot();
9770Sstevel@tonic-gate 			cmdmac(c);
9780Sstevel@tonic-gate 			continue;
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate /* | */
9810Sstevel@tonic-gate 		case '|':
9820Sstevel@tonic-gate 			endline = 0;
9830Sstevel@tonic-gate 			goto caseline;
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate /* \n */
9860Sstevel@tonic-gate 		case '\n':
9870Sstevel@tonic-gate 			endline = 1;
9880Sstevel@tonic-gate caseline:
9890Sstevel@tonic-gate 			notempty();
9900Sstevel@tonic-gate 			if (addr2 == 0) {
9910Sstevel@tonic-gate 				if (cursor_up != NOSTR && c == '\n' &&
9920Sstevel@tonic-gate 				    !inglobal)
9930Sstevel@tonic-gate 					c = CTRL('k');
9940Sstevel@tonic-gate 				if (inglobal)
9950Sstevel@tonic-gate 					addr1 = addr2 = dot;
9960Sstevel@tonic-gate 				else {
9970Sstevel@tonic-gate 					if (dot == dol)
9980Sstevel@tonic-gate 						error((vi_TERSE) ?
9990Sstevel@tonic-gate 						    gettext("At EOF") :
10000Sstevel@tonic-gate 						    gettext("At end-of-file"));
10010Sstevel@tonic-gate 					addr1 = addr2 = dot + 1;
10020Sstevel@tonic-gate 				}
10030Sstevel@tonic-gate 			}
10040Sstevel@tonic-gate 			setdot();
10050Sstevel@tonic-gate 			nonzero();
10060Sstevel@tonic-gate 			if (seensemi)
10070Sstevel@tonic-gate 				addr1 = addr2;
10080Sstevel@tonic-gate 			getline(*addr1);
10090Sstevel@tonic-gate 			if (c == CTRL('k')) {
10100Sstevel@tonic-gate 				flush1();
10110Sstevel@tonic-gate 				destline--;
10120Sstevel@tonic-gate 				if (hadpr)
10130Sstevel@tonic-gate 					shudclob = 1;
10140Sstevel@tonic-gate 			}
10150Sstevel@tonic-gate 			plines(addr1, addr2, 1);
10160Sstevel@tonic-gate 			continue;
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate /* " */
10190Sstevel@tonic-gate 		case '"':
10200Sstevel@tonic-gate 			comment();
10210Sstevel@tonic-gate 			continue;
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate /* # */
10240Sstevel@tonic-gate 		case '#':
10250Sstevel@tonic-gate numberit:
10260Sstevel@tonic-gate 			setCNL();
10270Sstevel@tonic-gate 			(void) setnumb(1);
10280Sstevel@tonic-gate 			pflag = 0;
10290Sstevel@tonic-gate 			goto print;
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate /* = */
10320Sstevel@tonic-gate 		case '=':
10330Sstevel@tonic-gate 			donewline();
10340Sstevel@tonic-gate 			setall();
10350Sstevel@tonic-gate 			if (inglobal == 2)
10360Sstevel@tonic-gate 				pofix();
1037802Scf46844 			viprintf("%d", lineno(addr2));
10380Sstevel@tonic-gate 			noonl();
10390Sstevel@tonic-gate 			continue;
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate /* ! */
10420Sstevel@tonic-gate 		case '!':
10430Sstevel@tonic-gate 			if (addr2 != 0) {
10440Sstevel@tonic-gate 				vmacchng(0);
1045500Sceastha 				unix0(0, 1);
10460Sstevel@tonic-gate 				setdot();
1047802Scf46844 				(void) vi_filter(2);
10480Sstevel@tonic-gate 			} else {
1049500Sceastha 				unix0(1, 1);
10500Sstevel@tonic-gate 				pofix();
1051802Scf46844 				putpad((unsigned char *)exit_ca_mode);
10520Sstevel@tonic-gate 				flush();
10530Sstevel@tonic-gate 				resetterm();
1054*4488Scf46844 				if (!tagflg) {
1055*4488Scf46844 					unixwt(1, unixex("-c", uxb, 0, 0));
1056*4488Scf46844 				} else {
1057*4488Scf46844 					error(gettext("Invalid tags file:"
1058*4488Scf46844 					    " contains shell escape"));
1059*4488Scf46844 				}
10600Sstevel@tonic-gate 				vclrech(1);	/* vcontin(0); */
10610Sstevel@tonic-gate 				nochng();
10620Sstevel@tonic-gate 			}
10630Sstevel@tonic-gate 			continue;
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate /* < */
10660Sstevel@tonic-gate /* > */
10670Sstevel@tonic-gate 		case '<':
10680Sstevel@tonic-gate 		case '>':
10690Sstevel@tonic-gate 			for (cnt = 1; peekchar() == c; cnt++)
10700Sstevel@tonic-gate 				ignchar();
10710Sstevel@tonic-gate 			setCNL();
10720Sstevel@tonic-gate 			vmacchng(0);
10730Sstevel@tonic-gate 			shift(c, cnt);
10740Sstevel@tonic-gate 			continue;
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate /* ^D */
10770Sstevel@tonic-gate /* EOF */
10780Sstevel@tonic-gate 		case CTRL('d'):
10790Sstevel@tonic-gate 		case EOF:
10800Sstevel@tonic-gate 			if (exitoneof) {
10810Sstevel@tonic-gate 				if (addr2 != 0)
10820Sstevel@tonic-gate 					dot = addr2;
10830Sstevel@tonic-gate 				return;
10840Sstevel@tonic-gate 			}
10850Sstevel@tonic-gate 			if (!isatty(0)) {
10860Sstevel@tonic-gate 				if (intty)
10870Sstevel@tonic-gate 					/*
10880Sstevel@tonic-gate 					 * Chtty sys call at UCB may cause a
10890Sstevel@tonic-gate 					 * input which was a tty to suddenly be
10900Sstevel@tonic-gate 					 * turned into /dev/null.
10910Sstevel@tonic-gate 					 */
10920Sstevel@tonic-gate 					onhup(0);
10930Sstevel@tonic-gate 				return;
10940Sstevel@tonic-gate 			}
10950Sstevel@tonic-gate 			if (addr2 != 0) {
10960Sstevel@tonic-gate 				setlastchar('\n');
10970Sstevel@tonic-gate 				putnl();
10980Sstevel@tonic-gate 			}
10990Sstevel@tonic-gate 			if (dol == zero) {
11000Sstevel@tonic-gate 				if (addr2 == 0)
11010Sstevel@tonic-gate 					putnl();
11020Sstevel@tonic-gate 				notempty();
11030Sstevel@tonic-gate 			}
11040Sstevel@tonic-gate 			ungetchar(EOF);
11050Sstevel@tonic-gate 			zop(hadpr);
11060Sstevel@tonic-gate 			continue;
11070Sstevel@tonic-gate 		default:
11080Sstevel@tonic-gate 			if (!isalpha(c) || !isascii(c))
11090Sstevel@tonic-gate 				break;
11100Sstevel@tonic-gate 			ungetchar(c);
1111802Scf46844 			tailprim((unsigned char *)"", 0, 0);
11120Sstevel@tonic-gate 		}
11130Sstevel@tonic-gate 		ungetchar(c);
11140Sstevel@tonic-gate 		{
11150Sstevel@tonic-gate 			int length;
11160Sstevel@tonic-gate 			char multic[MULTI_BYTE_MAX];
11170Sstevel@tonic-gate 			wchar_t wchar;
11180Sstevel@tonic-gate 			length = _mbftowc(multic, &wchar, getchar, &peekc);
11190Sstevel@tonic-gate 			if (length < 0)
11200Sstevel@tonic-gate 				length = -length;
11210Sstevel@tonic-gate 			multic[length] = '\0';
11220Sstevel@tonic-gate 			error((vi_TERSE) ? gettext("What?") :
11230Sstevel@tonic-gate 				gettext("Unknown command character '%s'"),
11240Sstevel@tonic-gate 			    multic);
11250Sstevel@tonic-gate 		}
11260Sstevel@tonic-gate 	}
11270Sstevel@tonic-gate }
1128