xref: /onnv-gate/usr/src/cmd/vi/port/ex_cmds2.c (revision 802:73b56fb6544b)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*802Scf46844 /*
23*802Scf46844  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*802Scf46844  * Use is subject to license terms.
25*802Scf46844  */
26*802Scf46844 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include "ex.h"
360Sstevel@tonic-gate #include "ex_argv.h"
370Sstevel@tonic-gate #include "ex_temp.h"
380Sstevel@tonic-gate #include "ex_tty.h"
390Sstevel@tonic-gate #include "ex_vis.h"
40*802Scf46844 #include <unistd.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate extern bool	pflag, nflag;		/* extern; also in ex_cmds.c */
430Sstevel@tonic-gate extern int	poffset;		/* extern; also in ex_cmds.c */
440Sstevel@tonic-gate extern short	slevel;			/* extern; has level of source() */
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * Subroutines for major command loop.
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * Is there a single letter indicating a named buffer next?
520Sstevel@tonic-gate  */
53*802Scf46844 int
54*802Scf46844 cmdreg(void)
550Sstevel@tonic-gate {
56*802Scf46844 	int c = 0;
57*802Scf46844 	int wh = skipwh();
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #ifdef XPG4
600Sstevel@tonic-gate 	if (wh && isalpha(c = peekchar()) && isascii(c) && !isdigit(c))
610Sstevel@tonic-gate #else /* XPG4 */
620Sstevel@tonic-gate 	if (wh && isalpha(c = peekchar()) && isascii(c))
630Sstevel@tonic-gate #endif /* XPG4 */
640Sstevel@tonic-gate 		c = getchar();
650Sstevel@tonic-gate 
660Sstevel@tonic-gate #ifdef XPG4
670Sstevel@tonic-gate 	if (isdigit(c)) {
680Sstevel@tonic-gate 		c = 0;
690Sstevel@tonic-gate 	}
700Sstevel@tonic-gate #endif /* XPG4 */
710Sstevel@tonic-gate 	return (c);
720Sstevel@tonic-gate }
730Sstevel@tonic-gate 
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate  * Tell whether the character ends a command
760Sstevel@tonic-gate  */
77*802Scf46844 int
78*802Scf46844 endcmd(int ch)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate 	switch (ch) {
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	case '\n':
830Sstevel@tonic-gate 	case EOF:
840Sstevel@tonic-gate 		endline = 1;
850Sstevel@tonic-gate 		return (1);
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	case '|':
880Sstevel@tonic-gate 	case '"':
890Sstevel@tonic-gate 		endline = 0;
900Sstevel@tonic-gate 		return (1);
910Sstevel@tonic-gate 	}
920Sstevel@tonic-gate 	return (0);
930Sstevel@tonic-gate }
940Sstevel@tonic-gate 
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate  * Insist on the end of the command.
970Sstevel@tonic-gate  */
98*802Scf46844 void
99*802Scf46844 eol(void)
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	if (!skipend())
1030Sstevel@tonic-gate 		error(value(vi_TERSE) ? gettext("Extra chars") :
1040Sstevel@tonic-gate 			gettext("Extra characters at end of command"));
1050Sstevel@tonic-gate 	ignnEOF();
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate #ifdef XPG4
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate  * Print out the message in the error message file at str,
1110Sstevel@tonic-gate  * with i an integer argument to printf.
1120Sstevel@tonic-gate  */
1130Sstevel@tonic-gate /*VARARGS2*/
114*802Scf46844 void
1150Sstevel@tonic-gate error(str, i)
116*802Scf46844 	unsigned char *str;
1170Sstevel@tonic-gate 	int i;
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	errcnt++;
1210Sstevel@tonic-gate 	noerror(str, i);
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate /*
1250Sstevel@tonic-gate  * noerror(): like error(), but doesn't inc errcnt.
1260Sstevel@tonic-gate  * the reason why we created this routine, instead of fixing up errcnt
1270Sstevel@tonic-gate  * after error() is called, is because we will do a longjmp, and
1280Sstevel@tonic-gate  * not a return. it does other things closing file i/o, reset, etc;
1290Sstevel@tonic-gate  * so we follow those procedures.
1300Sstevel@tonic-gate  */
1310Sstevel@tonic-gate /*VARARGS2*/
132*802Scf46844 void
1330Sstevel@tonic-gate noerror(str, i)
134*802Scf46844 	unsigned char *str;
1350Sstevel@tonic-gate 	int i;
1360Sstevel@tonic-gate {
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	error0();
1390Sstevel@tonic-gate 	merror(str, i);
1400Sstevel@tonic-gate 	if (writing) {
141*802Scf46844 		serror((unsigned char *)
142*802Scf46844 		    gettext(" [Warning - %s is incomplete]"), file);
1430Sstevel@tonic-gate 		writing = 0;
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 	error1(str);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate #else /* !XPG4 */
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate  * Print out the message in the error message file at str,
1510Sstevel@tonic-gate  * with i an integer argument to printf.
1520Sstevel@tonic-gate  */
1530Sstevel@tonic-gate /*VARARGS2*/
154*802Scf46844 void
1550Sstevel@tonic-gate error(str, i)
156*802Scf46844 	unsigned char *str;
1570Sstevel@tonic-gate 	int i;
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	errcnt++;
1610Sstevel@tonic-gate 	error0();
1620Sstevel@tonic-gate 	merror(str, i);
1630Sstevel@tonic-gate 	if (writing) {
164*802Scf46844 		serror((unsigned char *)
165*802Scf46844 		    gettext(" [Warning - %s is incomplete]"), file);
1660Sstevel@tonic-gate 		writing = 0;
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 	error1(str);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate #endif /* XPG4 */
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  * Rewind the argument list.
1740Sstevel@tonic-gate  */
175*802Scf46844 void
176*802Scf46844 erewind(void)
1770Sstevel@tonic-gate {
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	argc = argc0;
1800Sstevel@tonic-gate 	argv = argv0;
1810Sstevel@tonic-gate 	args = args0;
1820Sstevel@tonic-gate 	if (argc > 1 && !hush && cur_term) {
183*802Scf46844 		viprintf(mesg(value(vi_TERSE) ? gettext("%d files") :
1840Sstevel@tonic-gate 			gettext("%d files to edit")), argc);
1850Sstevel@tonic-gate 		if (inopen)
1860Sstevel@tonic-gate 			putchar(' ');
1870Sstevel@tonic-gate 		else
1880Sstevel@tonic-gate 			putNFL();
1890Sstevel@tonic-gate 	}
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate  * Guts of the pre-printing error processing.
1940Sstevel@tonic-gate  * If in visual and catching errors, then we don't mung up the internals,
1950Sstevel@tonic-gate  * just fixing up the echo area for the print.
1960Sstevel@tonic-gate  * Otherwise we reset a number of externals, and discard unused input.
1970Sstevel@tonic-gate  */
198*802Scf46844 void
199*802Scf46844 error0(void)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if (laste) {
2030Sstevel@tonic-gate #ifdef VMUNIX
2040Sstevel@tonic-gate 		tlaste();
2050Sstevel@tonic-gate #endif
2060Sstevel@tonic-gate 		laste = 0;
2070Sstevel@tonic-gate 		sync();
2080Sstevel@tonic-gate 	}
2090Sstevel@tonic-gate 	if (vcatch) {
2100Sstevel@tonic-gate 		if (splitw == 0)
2110Sstevel@tonic-gate 			fixech();
2120Sstevel@tonic-gate 		if (!enter_standout_mode || !exit_bold)
2130Sstevel@tonic-gate 			dingdong();
2140Sstevel@tonic-gate 		return;
2150Sstevel@tonic-gate 	}
2160Sstevel@tonic-gate 	if (input) {
2170Sstevel@tonic-gate 		input = strend(input) - 1;
2180Sstevel@tonic-gate 		if (*input == '\n')
2190Sstevel@tonic-gate 			setlastchar('\n');
2200Sstevel@tonic-gate 		input = 0;
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 	setoutt();
2230Sstevel@tonic-gate 	flush();
2240Sstevel@tonic-gate 	resetflav();
2250Sstevel@tonic-gate 	if (!enter_standout_mode || !exit_bold)
2260Sstevel@tonic-gate 		dingdong();
2270Sstevel@tonic-gate 	if (inopen) {
2280Sstevel@tonic-gate 		/*
2290Sstevel@tonic-gate 		 * We are coming out of open/visual ungracefully.
2300Sstevel@tonic-gate 		 * Restore columns, undo, and fix tty mode.
2310Sstevel@tonic-gate 		 */
2320Sstevel@tonic-gate 		columns = OCOLUMNS;
2330Sstevel@tonic-gate 		undvis();
2340Sstevel@tonic-gate 		ostop(normf);
2350Sstevel@tonic-gate 		/* ostop should be doing this
2360Sstevel@tonic-gate 		putpad(cursor_normal);
2370Sstevel@tonic-gate 		putpad(key_eol);
2380Sstevel@tonic-gate 		*/
2390Sstevel@tonic-gate 		putnl();
2400Sstevel@tonic-gate 	}
2410Sstevel@tonic-gate 	inopen = 0;
2420Sstevel@tonic-gate 	holdcm = 0;
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate /*
2460Sstevel@tonic-gate  * Post error printing processing.
2470Sstevel@tonic-gate  * Close the i/o file if left open.
2480Sstevel@tonic-gate  * If catching in visual then throw to the visual catch,
2490Sstevel@tonic-gate  * else if a child after a fork, then exit.
2500Sstevel@tonic-gate  * Otherwise, in the normal command mode error case,
2510Sstevel@tonic-gate  * finish state reset, and throw to top.
2520Sstevel@tonic-gate  */
253*802Scf46844 void
254*802Scf46844 error1(unsigned char *str)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate 	bool die;
2570Sstevel@tonic-gate 	extern short ttyindes;
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	if ((io > 0) && (io != ttyindes)) {
2600Sstevel@tonic-gate 		close(io);
2610Sstevel@tonic-gate 		io = -1;
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	die = (getpid() != ppid);	/* Only children die */
2650Sstevel@tonic-gate 	inappend = inglobal = 0;
2660Sstevel@tonic-gate 	globp = vglobp = vmacp = 0;
2670Sstevel@tonic-gate 	if (vcatch && !die) {
2680Sstevel@tonic-gate 		inopen = 1;
2690Sstevel@tonic-gate 		vcatch = 0;
2700Sstevel@tonic-gate 		if (str)
2710Sstevel@tonic-gate 			noonl();
2720Sstevel@tonic-gate 		fixol();
2730Sstevel@tonic-gate 		if (slevel > 0)
2740Sstevel@tonic-gate 			reset();
2750Sstevel@tonic-gate 		longjmp(vreslab,1);
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 	if (str && !vcatch)
2780Sstevel@tonic-gate 		putNFL();
2790Sstevel@tonic-gate 	if (die)
2800Sstevel@tonic-gate 		exit(++errcnt);
2810Sstevel@tonic-gate 	lseek(0, 0L, 2);
2820Sstevel@tonic-gate 	if (inglobal)
2830Sstevel@tonic-gate 		setlastchar('\n');
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (inexrc) {
2860Sstevel@tonic-gate 	  lprintf(gettext("Error detected in .exrc.[Hit return to continue] "), 0);
2870Sstevel@tonic-gate 	  putNFL();
2880Sstevel@tonic-gate 	  getkey();
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	while ((lastchar() != '\n') && (lastchar() != EOF))
2920Sstevel@tonic-gate 		ignchar();
2930Sstevel@tonic-gate 	ungetchar(0);
2940Sstevel@tonic-gate 	endline = 1;
2950Sstevel@tonic-gate 	reset();
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
298*802Scf46844 void
299*802Scf46844 fixol(void)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate 	if (Outchar != vputchar) {
3020Sstevel@tonic-gate 		flush();
3030Sstevel@tonic-gate 		if (state == ONEOPEN || state == HARDOPEN)
3040Sstevel@tonic-gate 			outline = destline = 0;
3050Sstevel@tonic-gate 		Outchar = vputchar;
3060Sstevel@tonic-gate 		vcontin(1);
3070Sstevel@tonic-gate 		/*
3080Sstevel@tonic-gate 		 * Outchar could be set to termchar() through vcontin().
3090Sstevel@tonic-gate 		 * So reset it again.
3100Sstevel@tonic-gate 		 */
3110Sstevel@tonic-gate 		Outchar = vputchar;
3120Sstevel@tonic-gate 	} else {
3130Sstevel@tonic-gate 		if (destcol)
3140Sstevel@tonic-gate 			vclreol();
3150Sstevel@tonic-gate 		vclean();
3160Sstevel@tonic-gate 	}
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate /*
3200Sstevel@tonic-gate  * Does an ! character follow in the command stream?
3210Sstevel@tonic-gate  */
322*802Scf46844 int
323*802Scf46844 exclam(void)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	if (peekchar() == '!') {
3270Sstevel@tonic-gate 		ignchar();
3280Sstevel@tonic-gate 		return (1);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 	return (0);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate /*
3340Sstevel@tonic-gate  * Make an argument list for e.g. next.
3350Sstevel@tonic-gate  */
336*802Scf46844 void
337*802Scf46844 makargs(void)
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	glob(&frob);
3410Sstevel@tonic-gate 	argc0 = frob.argc0;
3420Sstevel@tonic-gate 	argv0 = frob.argv;
3430Sstevel@tonic-gate 	args0 = argv0[0];
3440Sstevel@tonic-gate 	erewind();
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate /*
3480Sstevel@tonic-gate  * Advance to next file in argument list.
3490Sstevel@tonic-gate  */
350*802Scf46844 void
351*802Scf46844 next(void)
3520Sstevel@tonic-gate {
3530Sstevel@tonic-gate 	extern short isalt;	/* defined in ex_io.c */
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	if (argc == 0)
356*802Scf46844 		error(value(vi_TERSE) ?
357*802Scf46844 			(unsigned char *)gettext("No more files") :
358*802Scf46844 			(unsigned char *)gettext("No more files to edit"));
3590Sstevel@tonic-gate 	morargc = argc;
3600Sstevel@tonic-gate 	isalt = (strcmp(altfile, args)==0) + 1;
3610Sstevel@tonic-gate 	if (savedfile[0])
3620Sstevel@tonic-gate 		CP(altfile, savedfile);
3630Sstevel@tonic-gate 	(void) strlcpy(savedfile, args, sizeof (savedfile));
3640Sstevel@tonic-gate 	argc--;
3650Sstevel@tonic-gate 	args = argv ? *++argv : strend(args) + 1;
3660Sstevel@tonic-gate #if i386 || i286
3670Sstevel@tonic-gate 	destcol = 0;
3680Sstevel@tonic-gate #endif
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate  * Eat trailing flags and offsets after a command,
3730Sstevel@tonic-gate  * saving for possible later post-command prints.
3740Sstevel@tonic-gate  */
375*802Scf46844 void
376*802Scf46844 donewline(void)
3770Sstevel@tonic-gate {
378*802Scf46844 	int c;
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	resetflav();
3810Sstevel@tonic-gate 	for (;;) {
3820Sstevel@tonic-gate 		c = getchar();
3830Sstevel@tonic-gate 		switch (c) {
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 		case '^':
3860Sstevel@tonic-gate 		case '-':
3870Sstevel@tonic-gate 			poffset--;
3880Sstevel@tonic-gate 			break;
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 		case '+':
3910Sstevel@tonic-gate 			poffset++;
3920Sstevel@tonic-gate 			break;
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 		case 'l':
3950Sstevel@tonic-gate 			listf++;
3960Sstevel@tonic-gate 			break;
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 		case '#':
3990Sstevel@tonic-gate 			nflag++;
4000Sstevel@tonic-gate 			break;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 		case 'p':
4030Sstevel@tonic-gate 			listf = 0;
4040Sstevel@tonic-gate 			break;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 		case ' ':
4070Sstevel@tonic-gate 		case '\t':
4080Sstevel@tonic-gate 			continue;
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 		case '"':
4110Sstevel@tonic-gate 			comment();
4120Sstevel@tonic-gate 			setflav();
4130Sstevel@tonic-gate 			return;
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 		default:
4160Sstevel@tonic-gate 			if (!endcmd(c))
417*802Scf46844 			    serror(value(vi_TERSE) ?
418*802Scf46844 				(unsigned char *)gettext("Extra chars") :
419*802Scf46844 				(unsigned char *)gettext(
420*802Scf46844 				"Extra characters at end of \"%s\" command"),
421*802Scf46844 				    Command);
4220Sstevel@tonic-gate 			if (c == EOF)
4230Sstevel@tonic-gate 				ungetchar(c);
4240Sstevel@tonic-gate 			setflav();
4250Sstevel@tonic-gate 			return;
4260Sstevel@tonic-gate 		}
4270Sstevel@tonic-gate 		pflag++;
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate /*
4320Sstevel@tonic-gate  * Before quit or respec of arg list, check that there are
4330Sstevel@tonic-gate  * no more files in the arg list.
4340Sstevel@tonic-gate  */
435*802Scf46844 int
436*802Scf46844 nomore(void)
4370Sstevel@tonic-gate {
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	if (argc == 0 || morargc == argc)
4400Sstevel@tonic-gate 		return(0);
4410Sstevel@tonic-gate 	morargc = argc;
4420Sstevel@tonic-gate 	if (argc == 1) {
4430Sstevel@tonic-gate 		merror(value(vi_TERSE) ? gettext("1 more file") :
4440Sstevel@tonic-gate 		       gettext("1 more file to edit"), argc);
4450Sstevel@tonic-gate 	} else {
4460Sstevel@tonic-gate 		merror(value(vi_TERSE) ? gettext("%d more files") :
4470Sstevel@tonic-gate 			gettext("%d more files to edit"), argc);
4480Sstevel@tonic-gate 	}
4490Sstevel@tonic-gate 	return(1);
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate /*
4530Sstevel@tonic-gate  * Before edit of new file check that either an ! follows
4540Sstevel@tonic-gate  * or the file has not been changed.
4550Sstevel@tonic-gate  */
456*802Scf46844 int
457*802Scf46844 quickly(void)
4580Sstevel@tonic-gate {
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	if (exclam())
4610Sstevel@tonic-gate 		return (1);
4620Sstevel@tonic-gate 	if (chng && dol > zero) {
4630Sstevel@tonic-gate /*
4640Sstevel@tonic-gate 		chng = 0;
4650Sstevel@tonic-gate */
4660Sstevel@tonic-gate 		xchng = 0;
467*802Scf46844 		error(value(vi_TERSE) ? (unsigned char *)gettext("No write") :
468*802Scf46844 		    (unsigned char *)
469*802Scf46844 		    gettext("No write since last change (:%s! overrides)"),
470*802Scf46844 		    Command);
4710Sstevel@tonic-gate 	}
4720Sstevel@tonic-gate 	return (0);
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate /*
4760Sstevel@tonic-gate  * Reset the flavor of the output to print mode with no numbering.
4770Sstevel@tonic-gate  */
478*802Scf46844 void
479*802Scf46844 resetflav(void)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	if (inopen)
4830Sstevel@tonic-gate 		return;
4840Sstevel@tonic-gate 	listf = 0;
4850Sstevel@tonic-gate 	nflag = 0;
4860Sstevel@tonic-gate 	pflag = 0;
4870Sstevel@tonic-gate 	poffset = 0;
4880Sstevel@tonic-gate 	setflav();
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate /*
4920Sstevel@tonic-gate  * Print an error message with a %s type argument to printf.
4930Sstevel@tonic-gate  * Message text comes from error message file.
4940Sstevel@tonic-gate  */
495*802Scf46844 void
496*802Scf46844 serror(unsigned char *str, unsigned char *cp)
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	error0();
5000Sstevel@tonic-gate 	smerror(str, cp);
5010Sstevel@tonic-gate 	error1(str);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate /*
5050Sstevel@tonic-gate  * Set the flavor of the output based on the flags given
5060Sstevel@tonic-gate  * and the number and list options to either number or not number lines
5070Sstevel@tonic-gate  * and either use normally decoded (ARPAnet standard) characters or list mode,
5080Sstevel@tonic-gate  * where end of lines are marked and tabs print as ^I.
5090Sstevel@tonic-gate  */
510*802Scf46844 void
511*802Scf46844 setflav(void)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	if (inopen)
5150Sstevel@tonic-gate 		return;
5160Sstevel@tonic-gate 	setnumb(nflag || value(vi_NUMBER));
5170Sstevel@tonic-gate 	setlist(listf || value(vi_LIST));
5180Sstevel@tonic-gate 	if (!inopen)
5190Sstevel@tonic-gate 		setoutt();
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate /*
5230Sstevel@tonic-gate  * Skip white space and tell whether command ends then.
5240Sstevel@tonic-gate  */
525*802Scf46844 int
526*802Scf46844 skipend(void)
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	pastwh();
5300Sstevel@tonic-gate 	return (endcmd(peekchar()) && peekchar() != '"');
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*
5340Sstevel@tonic-gate  * Set the command name for non-word commands.
5350Sstevel@tonic-gate  */
536*802Scf46844 void
537*802Scf46844 tailspec(int c)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate 	static unsigned char foocmd[2];
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	foocmd[0] = c;
5420Sstevel@tonic-gate 	Command = foocmd;
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate  * Try to read off the rest of the command word.
5470Sstevel@tonic-gate  * If alphabetics follow, then this is not the command we seek.
5480Sstevel@tonic-gate  */
549*802Scf46844 void
550*802Scf46844 tail(unsigned char *comm)
5510Sstevel@tonic-gate {
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	tailprim(comm, 1, 0);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate 
556*802Scf46844 void
557*802Scf46844 tail2of(unsigned char *comm)
5580Sstevel@tonic-gate {
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	tailprim(comm, 2, 0);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate unsigned char	tcommand[20];
5640Sstevel@tonic-gate 
565*802Scf46844 void
566*802Scf46844 tailprim(unsigned char *comm, int i, bool notinvis)
5670Sstevel@tonic-gate {
568*802Scf46844 	unsigned char *cp;
569*802Scf46844 	int c;
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 	Command = comm;
5720Sstevel@tonic-gate 	for (cp = tcommand; i > 0; i--)
5730Sstevel@tonic-gate 		*cp++ = *comm++;
5740Sstevel@tonic-gate 	while (*comm && peekchar() == *comm)
5750Sstevel@tonic-gate 		*cp++ = getchar(), comm++;
5760Sstevel@tonic-gate 	c = peekchar();
5770Sstevel@tonic-gate 	if (notinvis || (isalpha(c) && isascii(c))) {
5780Sstevel@tonic-gate 		/*
5790Sstevel@tonic-gate 		 * Of the trailing lp funny business, only dl and dp
5800Sstevel@tonic-gate 		 * survive the move from ed to ex.
5810Sstevel@tonic-gate 		 */
5820Sstevel@tonic-gate 		if (tcommand[0] == 'd' && any(c, "lp"))
5830Sstevel@tonic-gate 			goto ret;
5840Sstevel@tonic-gate 		if (tcommand[0] == 's' && any(c, "gcr"))
5850Sstevel@tonic-gate 			goto ret;
5860Sstevel@tonic-gate 		while (cp < &tcommand[19] && isalpha(c = peekchar()) && isascii(c))
5870Sstevel@tonic-gate 			*cp++ = getchar();
5880Sstevel@tonic-gate 		*cp = 0;
5890Sstevel@tonic-gate 		if (notinvis)
590*802Scf46844 			serror(value(vi_TERSE) ?
591*802Scf46844 			    (unsigned char *)gettext("What?") :
592*802Scf46844 			    (unsigned char *)gettext(
593*802Scf46844 			    "%s: No such command from open/visual"), tcommand);
5940Sstevel@tonic-gate 		else
595*802Scf46844 			serror(value(vi_TERSE) ?
596*802Scf46844 			    (unsigned char *)gettext("What?") :
597*802Scf46844 			    (unsigned char *)gettext(
598*802Scf46844 			    "%s: Not an editor command"), tcommand);
5990Sstevel@tonic-gate 	}
6000Sstevel@tonic-gate ret:
6010Sstevel@tonic-gate 	*cp = 0;
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate /*
6050Sstevel@tonic-gate  * Continue after a : command from open/visual.
6060Sstevel@tonic-gate  */
607*802Scf46844 void
608*802Scf46844 vcontin(bool ask)
6090Sstevel@tonic-gate {
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	if (vcnt > 0)
6120Sstevel@tonic-gate 		vcnt = -vcnt;
6130Sstevel@tonic-gate 	if (inopen) {
6140Sstevel@tonic-gate 		if (state != VISUAL) {
6150Sstevel@tonic-gate 			/*
6160Sstevel@tonic-gate 			 * We don't know what a shell command may have left on
6170Sstevel@tonic-gate 			 * the screen, so we move the cursor to the right place
6180Sstevel@tonic-gate 			 * and then put out a newline.  But this makes an extra
6190Sstevel@tonic-gate 			 * blank line most of the time so we only do it for :sh
6200Sstevel@tonic-gate 			 * since the prompt gets left on the screen.
6210Sstevel@tonic-gate 			 *
6220Sstevel@tonic-gate 			 * BUG: :!echo longer than current line \\c
6230Sstevel@tonic-gate 			 * will mess it up.
6240Sstevel@tonic-gate 			 */
6250Sstevel@tonic-gate 			if (state == CRTOPEN) {
6260Sstevel@tonic-gate 				termreset();
6270Sstevel@tonic-gate 				vgoto(WECHO, 0);
6280Sstevel@tonic-gate 			}
6290Sstevel@tonic-gate 			if (!ask) {
630*802Scf46844 				(void) putch('\r');
631*802Scf46844 				(void) putch('\n');
6320Sstevel@tonic-gate 			}
6330Sstevel@tonic-gate 			return;
6340Sstevel@tonic-gate 		}
6350Sstevel@tonic-gate 		if (ask) {
6360Sstevel@tonic-gate 			merror(gettext("[Hit return to continue] "));
6370Sstevel@tonic-gate 			flush();
6380Sstevel@tonic-gate 		}
6390Sstevel@tonic-gate #ifndef CBREAK
6400Sstevel@tonic-gate 		vraw();
6410Sstevel@tonic-gate #endif
6420Sstevel@tonic-gate 		if (ask) {
6430Sstevel@tonic-gate #ifdef notdef
6440Sstevel@tonic-gate 			/*
6450Sstevel@tonic-gate 			 * Gobble ^Q/^S since the tty driver should be eating
6460Sstevel@tonic-gate 			 * them (as far as the user can see)
6470Sstevel@tonic-gate 			 */
6480Sstevel@tonic-gate 			while (peekkey() == CTRL('Q') || peekkey() == CTRL('S'))
6490Sstevel@tonic-gate 				ignore(getkey());
6500Sstevel@tonic-gate #endif
6510Sstevel@tonic-gate 			if(getkey() == ':') {
6520Sstevel@tonic-gate 				/* Extra newlines, but no other way */
653*802Scf46844 				(void) putch('\n');
6540Sstevel@tonic-gate 				outline = WECHO;
6550Sstevel@tonic-gate 				ungetkey(':');
6560Sstevel@tonic-gate 			}
6570Sstevel@tonic-gate 		}
6580Sstevel@tonic-gate 		vclrech(1);
6590Sstevel@tonic-gate 		if (Peekkey != ':') {
6600Sstevel@tonic-gate 			fixterm();
661*802Scf46844 			putpad((unsigned char *)enter_ca_mode);
6620Sstevel@tonic-gate 			tostart();
6630Sstevel@tonic-gate 		}
6640Sstevel@tonic-gate 	}
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate /*
6680Sstevel@tonic-gate  * Put out a newline (before a shell escape)
6690Sstevel@tonic-gate  * if in open/visual.
6700Sstevel@tonic-gate  */
671*802Scf46844 void
672*802Scf46844 vnfl(void)
6730Sstevel@tonic-gate {
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 	if (inopen) {
6760Sstevel@tonic-gate 		if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
6770Sstevel@tonic-gate 			vclean();
6780Sstevel@tonic-gate 		else
6790Sstevel@tonic-gate 			vmoveitup(1, 0);
6800Sstevel@tonic-gate 		vgoto(WECHO, 0);
6810Sstevel@tonic-gate 		vclrbyte(vtube[WECHO], WCOLS);
6820Sstevel@tonic-gate 		tostop();
6830Sstevel@tonic-gate 		/* replaced by the ostop above
6840Sstevel@tonic-gate 		putpad(cursor_normal);
6850Sstevel@tonic-gate 		putpad(key_eol);
6860Sstevel@tonic-gate 		*/
6870Sstevel@tonic-gate 	}
6880Sstevel@tonic-gate 	flush();
6890Sstevel@tonic-gate }
690