xref: /titanic_51/usr/src/cmd/vi/port/ex_cmds2.c (revision 68c92b9f236192fc4b1af4355a207acf7469bd59)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5f2f27852Scf46844  * Common Development and Distribution License (the "License").
6f2f27852Scf46844  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21f6db9f27Scf46844 /*
22*68c92b9fScf46844  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23f6db9f27Scf46844  * Use is subject to license terms.
24f6db9f27Scf46844  */
25f6db9f27Scf46844 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include "ex.h"
357c478bd9Sstevel@tonic-gate #include "ex_argv.h"
367c478bd9Sstevel@tonic-gate #include "ex_temp.h"
377c478bd9Sstevel@tonic-gate #include "ex_tty.h"
387c478bd9Sstevel@tonic-gate #include "ex_vis.h"
39f6db9f27Scf46844 #include <unistd.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate extern bool	pflag, nflag;		/* extern; also in ex_cmds.c */
427c478bd9Sstevel@tonic-gate extern int	poffset;		/* extern; also in ex_cmds.c */
437c478bd9Sstevel@tonic-gate extern short	slevel;			/* extern; has level of source() */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * Subroutines for major command loop.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Is there a single letter indicating a named buffer next?
517c478bd9Sstevel@tonic-gate  */
52f6db9f27Scf46844 int
53f6db9f27Scf46844 cmdreg(void)
547c478bd9Sstevel@tonic-gate {
55f6db9f27Scf46844 	int c = 0;
56f6db9f27Scf46844 	int wh = skipwh();
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #ifdef XPG4
597c478bd9Sstevel@tonic-gate 	if (wh && isalpha(c = peekchar()) && isascii(c) && !isdigit(c))
607c478bd9Sstevel@tonic-gate #else /* XPG4 */
617c478bd9Sstevel@tonic-gate 	if (wh && isalpha(c = peekchar()) && isascii(c))
627c478bd9Sstevel@tonic-gate #endif /* XPG4 */
637c478bd9Sstevel@tonic-gate 		c = getchar();
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #ifdef XPG4
667c478bd9Sstevel@tonic-gate 	if (isdigit(c)) {
677c478bd9Sstevel@tonic-gate 		c = 0;
687c478bd9Sstevel@tonic-gate 	}
697c478bd9Sstevel@tonic-gate #endif /* XPG4 */
707c478bd9Sstevel@tonic-gate 	return (c);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate  * Tell whether the character ends a command
757c478bd9Sstevel@tonic-gate  */
76f6db9f27Scf46844 int
77f6db9f27Scf46844 endcmd(int ch)
787c478bd9Sstevel@tonic-gate {
797c478bd9Sstevel@tonic-gate 	switch (ch) {
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	case '\n':
827c478bd9Sstevel@tonic-gate 	case EOF:
837c478bd9Sstevel@tonic-gate 		endline = 1;
847c478bd9Sstevel@tonic-gate 		return (1);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	case '|':
877c478bd9Sstevel@tonic-gate 	case '"':
887c478bd9Sstevel@tonic-gate 		endline = 0;
897c478bd9Sstevel@tonic-gate 		return (1);
907c478bd9Sstevel@tonic-gate 	}
917c478bd9Sstevel@tonic-gate 	return (0);
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * Insist on the end of the command.
967c478bd9Sstevel@tonic-gate  */
97f6db9f27Scf46844 void
98f6db9f27Scf46844 eol(void)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	if (!skipend())
1027c478bd9Sstevel@tonic-gate 		error(value(vi_TERSE) ? gettext("Extra chars") :
1037c478bd9Sstevel@tonic-gate 			gettext("Extra characters at end of command"));
1047c478bd9Sstevel@tonic-gate 	ignnEOF();
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #ifdef XPG4
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate  * Print out the message in the error message file at str,
1107c478bd9Sstevel@tonic-gate  * with i an integer argument to printf.
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate /*VARARGS2*/
113f6db9f27Scf46844 void
1147c478bd9Sstevel@tonic-gate error(str, i)
115f6db9f27Scf46844 	unsigned char *str;
1167c478bd9Sstevel@tonic-gate 	int i;
1177c478bd9Sstevel@tonic-gate {
118*68c92b9fScf46844 	tagflg = 0;
1197c478bd9Sstevel@tonic-gate 	errcnt++;
1207c478bd9Sstevel@tonic-gate 	noerror(str, i);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate  * noerror(): like error(), but doesn't inc errcnt.
1257c478bd9Sstevel@tonic-gate  * the reason why we created this routine, instead of fixing up errcnt
1267c478bd9Sstevel@tonic-gate  * after error() is called, is because we will do a longjmp, and
1277c478bd9Sstevel@tonic-gate  * not a return. it does other things closing file i/o, reset, etc;
1287c478bd9Sstevel@tonic-gate  * so we follow those procedures.
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate /*VARARGS2*/
131f6db9f27Scf46844 void
1327c478bd9Sstevel@tonic-gate noerror(str, i)
133f6db9f27Scf46844 	unsigned char *str;
1347c478bd9Sstevel@tonic-gate 	int i;
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	error0();
1387c478bd9Sstevel@tonic-gate 	merror(str, i);
1397c478bd9Sstevel@tonic-gate 	if (writing) {
140f6db9f27Scf46844 		serror((unsigned char *)
141f6db9f27Scf46844 		    gettext(" [Warning - %s is incomplete]"), file);
1427c478bd9Sstevel@tonic-gate 		writing = 0;
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate 	error1(str);
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate #else /* !XPG4 */
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate  * Print out the message in the error message file at str,
1507c478bd9Sstevel@tonic-gate  * with i an integer argument to printf.
1517c478bd9Sstevel@tonic-gate  */
1527c478bd9Sstevel@tonic-gate /*VARARGS2*/
153f6db9f27Scf46844 void
1547c478bd9Sstevel@tonic-gate error(str, i)
155f6db9f27Scf46844 	unsigned char *str;
1567c478bd9Sstevel@tonic-gate 	int i;
1577c478bd9Sstevel@tonic-gate {
158*68c92b9fScf46844 	tagflg = 0;
1597c478bd9Sstevel@tonic-gate 	errcnt++;
1607c478bd9Sstevel@tonic-gate 	error0();
1617c478bd9Sstevel@tonic-gate 	merror(str, i);
1627c478bd9Sstevel@tonic-gate 	if (writing) {
163f6db9f27Scf46844 		serror((unsigned char *)
164f6db9f27Scf46844 		    gettext(" [Warning - %s is incomplete]"), file);
1657c478bd9Sstevel@tonic-gate 		writing = 0;
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 	error1(str);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate #endif /* XPG4 */
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Rewind the argument list.
1737c478bd9Sstevel@tonic-gate  */
174f6db9f27Scf46844 void
175f6db9f27Scf46844 erewind(void)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	argc = argc0;
1797c478bd9Sstevel@tonic-gate 	argv = argv0;
1807c478bd9Sstevel@tonic-gate 	args = args0;
1817c478bd9Sstevel@tonic-gate 	if (argc > 1 && !hush && cur_term) {
182f6db9f27Scf46844 		viprintf(mesg(value(vi_TERSE) ? gettext("%d files") :
1837c478bd9Sstevel@tonic-gate 			gettext("%d files to edit")), argc);
1847c478bd9Sstevel@tonic-gate 		if (inopen)
1857c478bd9Sstevel@tonic-gate 			putchar(' ');
1867c478bd9Sstevel@tonic-gate 		else
1877c478bd9Sstevel@tonic-gate 			putNFL();
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * Guts of the pre-printing error processing.
1937c478bd9Sstevel@tonic-gate  * If in visual and catching errors, then we don't mung up the internals,
1947c478bd9Sstevel@tonic-gate  * just fixing up the echo area for the print.
1957c478bd9Sstevel@tonic-gate  * Otherwise we reset a number of externals, and discard unused input.
1967c478bd9Sstevel@tonic-gate  */
197f6db9f27Scf46844 void
198f6db9f27Scf46844 error0(void)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	if (laste) {
2027c478bd9Sstevel@tonic-gate #ifdef VMUNIX
2037c478bd9Sstevel@tonic-gate 		tlaste();
2047c478bd9Sstevel@tonic-gate #endif
2057c478bd9Sstevel@tonic-gate 		laste = 0;
2067c478bd9Sstevel@tonic-gate 		sync();
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 	if (vcatch) {
2097c478bd9Sstevel@tonic-gate 		if (splitw == 0)
2107c478bd9Sstevel@tonic-gate 			fixech();
2117c478bd9Sstevel@tonic-gate 		if (!enter_standout_mode || !exit_bold)
2127c478bd9Sstevel@tonic-gate 			dingdong();
2137c478bd9Sstevel@tonic-gate 		return;
2147c478bd9Sstevel@tonic-gate 	}
2157c478bd9Sstevel@tonic-gate 	if (input) {
2167c478bd9Sstevel@tonic-gate 		input = strend(input) - 1;
2177c478bd9Sstevel@tonic-gate 		if (*input == '\n')
2187c478bd9Sstevel@tonic-gate 			setlastchar('\n');
2197c478bd9Sstevel@tonic-gate 		input = 0;
2207c478bd9Sstevel@tonic-gate 	}
2217c478bd9Sstevel@tonic-gate 	setoutt();
2227c478bd9Sstevel@tonic-gate 	flush();
2237c478bd9Sstevel@tonic-gate 	resetflav();
2247c478bd9Sstevel@tonic-gate 	if (!enter_standout_mode || !exit_bold)
2257c478bd9Sstevel@tonic-gate 		dingdong();
2267c478bd9Sstevel@tonic-gate 	if (inopen) {
2277c478bd9Sstevel@tonic-gate 		/*
2287c478bd9Sstevel@tonic-gate 		 * We are coming out of open/visual ungracefully.
2297c478bd9Sstevel@tonic-gate 		 * Restore columns, undo, and fix tty mode.
2307c478bd9Sstevel@tonic-gate 		 */
2317c478bd9Sstevel@tonic-gate 		columns = OCOLUMNS;
2327c478bd9Sstevel@tonic-gate 		undvis();
2337c478bd9Sstevel@tonic-gate 		ostop(normf);
2347c478bd9Sstevel@tonic-gate 		/* ostop should be doing this
2357c478bd9Sstevel@tonic-gate 		putpad(cursor_normal);
2367c478bd9Sstevel@tonic-gate 		putpad(key_eol);
2377c478bd9Sstevel@tonic-gate 		*/
2387c478bd9Sstevel@tonic-gate 		putnl();
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 	inopen = 0;
2417c478bd9Sstevel@tonic-gate 	holdcm = 0;
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate  * Post error printing processing.
2467c478bd9Sstevel@tonic-gate  * Close the i/o file if left open.
2477c478bd9Sstevel@tonic-gate  * If catching in visual then throw to the visual catch,
2487c478bd9Sstevel@tonic-gate  * else if a child after a fork, then exit.
2497c478bd9Sstevel@tonic-gate  * Otherwise, in the normal command mode error case,
2507c478bd9Sstevel@tonic-gate  * finish state reset, and throw to top.
2517c478bd9Sstevel@tonic-gate  */
252f6db9f27Scf46844 void
253f6db9f27Scf46844 error1(unsigned char *str)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	bool die;
2567c478bd9Sstevel@tonic-gate 	extern short ttyindes;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	if ((io > 0) && (io != ttyindes)) {
2597c478bd9Sstevel@tonic-gate 		close(io);
2607c478bd9Sstevel@tonic-gate 		io = -1;
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	die = (getpid() != ppid);	/* Only children die */
2647c478bd9Sstevel@tonic-gate 	inappend = inglobal = 0;
2657c478bd9Sstevel@tonic-gate 	globp = vglobp = vmacp = 0;
2667c478bd9Sstevel@tonic-gate 	if (vcatch && !die) {
2677c478bd9Sstevel@tonic-gate 		inopen = 1;
2687c478bd9Sstevel@tonic-gate 		vcatch = 0;
2697c478bd9Sstevel@tonic-gate 		if (str)
2707c478bd9Sstevel@tonic-gate 			noonl();
2717c478bd9Sstevel@tonic-gate 		fixol();
2727c478bd9Sstevel@tonic-gate 		if (slevel > 0)
2737c478bd9Sstevel@tonic-gate 			reset();
2747c478bd9Sstevel@tonic-gate 		longjmp(vreslab,1);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 	if (str && !vcatch)
2777c478bd9Sstevel@tonic-gate 		putNFL();
2787c478bd9Sstevel@tonic-gate 	if (die)
2797c478bd9Sstevel@tonic-gate 		exit(++errcnt);
2807c478bd9Sstevel@tonic-gate 	lseek(0, 0L, 2);
2817c478bd9Sstevel@tonic-gate 	if (inglobal)
2827c478bd9Sstevel@tonic-gate 		setlastchar('\n');
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 	if (inexrc) {
285f2f27852Scf46844 		/*
286f2f27852Scf46844 		 * Set inexrc to 0 so that this error is printed only
287f2f27852Scf46844 		 * once (eg. when stdin is redirected from /dev/null and
288f2f27852Scf46844 		 * vi prints "Input read error" because it is unable to
289f2f27852Scf46844 		 * read() the <CR>).
290f2f27852Scf46844 		 */
291f2f27852Scf46844 		inexrc = 0;
292f2f27852Scf46844 		lprintf(gettext(
293f2f27852Scf46844 		    "Error detected in .exrc.[Hit return to continue] "),
294f2f27852Scf46844 		    0);
2957c478bd9Sstevel@tonic-gate 		putNFL();
2967c478bd9Sstevel@tonic-gate 		getkey();
2977c478bd9Sstevel@tonic-gate 	}
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	while ((lastchar() != '\n') && (lastchar() != EOF))
3007c478bd9Sstevel@tonic-gate 		ignchar();
3017c478bd9Sstevel@tonic-gate 	ungetchar(0);
3027c478bd9Sstevel@tonic-gate 	endline = 1;
3037c478bd9Sstevel@tonic-gate 	reset();
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
306f6db9f27Scf46844 void
307f6db9f27Scf46844 fixol(void)
3087c478bd9Sstevel@tonic-gate {
3097c478bd9Sstevel@tonic-gate 	if (Outchar != vputchar) {
3107c478bd9Sstevel@tonic-gate 		flush();
3117c478bd9Sstevel@tonic-gate 		if (state == ONEOPEN || state == HARDOPEN)
3127c478bd9Sstevel@tonic-gate 			outline = destline = 0;
3137c478bd9Sstevel@tonic-gate 		Outchar = vputchar;
3147c478bd9Sstevel@tonic-gate 		vcontin(1);
3157c478bd9Sstevel@tonic-gate 		/*
3167c478bd9Sstevel@tonic-gate 		 * Outchar could be set to termchar() through vcontin().
3177c478bd9Sstevel@tonic-gate 		 * So reset it again.
3187c478bd9Sstevel@tonic-gate 		 */
3197c478bd9Sstevel@tonic-gate 		Outchar = vputchar;
3207c478bd9Sstevel@tonic-gate 	} else {
3217c478bd9Sstevel@tonic-gate 		if (destcol)
3227c478bd9Sstevel@tonic-gate 			vclreol();
3237c478bd9Sstevel@tonic-gate 		vclean();
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate /*
3287c478bd9Sstevel@tonic-gate  * Does an ! character follow in the command stream?
3297c478bd9Sstevel@tonic-gate  */
330f6db9f27Scf46844 int
331f6db9f27Scf46844 exclam(void)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	if (peekchar() == '!') {
3357c478bd9Sstevel@tonic-gate 		ignchar();
3367c478bd9Sstevel@tonic-gate 		return (1);
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 	return (0);
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate /*
3427c478bd9Sstevel@tonic-gate  * Make an argument list for e.g. next.
3437c478bd9Sstevel@tonic-gate  */
344f6db9f27Scf46844 void
345f6db9f27Scf46844 makargs(void)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	glob(&frob);
3497c478bd9Sstevel@tonic-gate 	argc0 = frob.argc0;
3507c478bd9Sstevel@tonic-gate 	argv0 = frob.argv;
3517c478bd9Sstevel@tonic-gate 	args0 = argv0[0];
3527c478bd9Sstevel@tonic-gate 	erewind();
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate /*
3567c478bd9Sstevel@tonic-gate  * Advance to next file in argument list.
3577c478bd9Sstevel@tonic-gate  */
358f6db9f27Scf46844 void
359f6db9f27Scf46844 next(void)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate 	extern short isalt;	/* defined in ex_io.c */
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	if (argc == 0)
364f6db9f27Scf46844 		error(value(vi_TERSE) ?
365f6db9f27Scf46844 			(unsigned char *)gettext("No more files") :
366f6db9f27Scf46844 			(unsigned char *)gettext("No more files to edit"));
3677c478bd9Sstevel@tonic-gate 	morargc = argc;
3687c478bd9Sstevel@tonic-gate 	isalt = (strcmp(altfile, args)==0) + 1;
3697c478bd9Sstevel@tonic-gate 	if (savedfile[0])
3707c478bd9Sstevel@tonic-gate 		CP(altfile, savedfile);
3717c478bd9Sstevel@tonic-gate 	(void) strlcpy(savedfile, args, sizeof (savedfile));
3727c478bd9Sstevel@tonic-gate 	argc--;
3737c478bd9Sstevel@tonic-gate 	args = argv ? *++argv : strend(args) + 1;
3747c478bd9Sstevel@tonic-gate #if i386 || i286
3757c478bd9Sstevel@tonic-gate 	destcol = 0;
3767c478bd9Sstevel@tonic-gate #endif
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate /*
3807c478bd9Sstevel@tonic-gate  * Eat trailing flags and offsets after a command,
3817c478bd9Sstevel@tonic-gate  * saving for possible later post-command prints.
3827c478bd9Sstevel@tonic-gate  */
383f6db9f27Scf46844 void
384f6db9f27Scf46844 donewline(void)
3857c478bd9Sstevel@tonic-gate {
386f6db9f27Scf46844 	int c;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	resetflav();
3897c478bd9Sstevel@tonic-gate 	for (;;) {
3907c478bd9Sstevel@tonic-gate 		c = getchar();
3917c478bd9Sstevel@tonic-gate 		switch (c) {
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 		case '^':
3947c478bd9Sstevel@tonic-gate 		case '-':
3957c478bd9Sstevel@tonic-gate 			poffset--;
3967c478bd9Sstevel@tonic-gate 			break;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 		case '+':
3997c478bd9Sstevel@tonic-gate 			poffset++;
4007c478bd9Sstevel@tonic-gate 			break;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 		case 'l':
4037c478bd9Sstevel@tonic-gate 			listf++;
4047c478bd9Sstevel@tonic-gate 			break;
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 		case '#':
4077c478bd9Sstevel@tonic-gate 			nflag++;
4087c478bd9Sstevel@tonic-gate 			break;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 		case 'p':
4117c478bd9Sstevel@tonic-gate 			listf = 0;
4127c478bd9Sstevel@tonic-gate 			break;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 		case ' ':
4157c478bd9Sstevel@tonic-gate 		case '\t':
4167c478bd9Sstevel@tonic-gate 			continue;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 		case '"':
4197c478bd9Sstevel@tonic-gate 			comment();
4207c478bd9Sstevel@tonic-gate 			setflav();
4217c478bd9Sstevel@tonic-gate 			return;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 		default:
4247c478bd9Sstevel@tonic-gate 			if (!endcmd(c))
425f6db9f27Scf46844 			    serror(value(vi_TERSE) ?
426f6db9f27Scf46844 				(unsigned char *)gettext("Extra chars") :
427f6db9f27Scf46844 				(unsigned char *)gettext(
428f6db9f27Scf46844 				"Extra characters at end of \"%s\" command"),
429f6db9f27Scf46844 				    Command);
4307c478bd9Sstevel@tonic-gate 			if (c == EOF)
4317c478bd9Sstevel@tonic-gate 				ungetchar(c);
4327c478bd9Sstevel@tonic-gate 			setflav();
4337c478bd9Sstevel@tonic-gate 			return;
4347c478bd9Sstevel@tonic-gate 		}
4357c478bd9Sstevel@tonic-gate 		pflag++;
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate  * Before quit or respec of arg list, check that there are
4417c478bd9Sstevel@tonic-gate  * no more files in the arg list.
4427c478bd9Sstevel@tonic-gate  */
443f6db9f27Scf46844 int
444f6db9f27Scf46844 nomore(void)
4457c478bd9Sstevel@tonic-gate {
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	if (argc == 0 || morargc == argc)
4487c478bd9Sstevel@tonic-gate 		return(0);
4497c478bd9Sstevel@tonic-gate 	morargc = argc;
4507c478bd9Sstevel@tonic-gate 	if (argc == 1) {
4517c478bd9Sstevel@tonic-gate 		merror(value(vi_TERSE) ? gettext("1 more file") :
4527c478bd9Sstevel@tonic-gate 		       gettext("1 more file to edit"), argc);
4537c478bd9Sstevel@tonic-gate 	} else {
4547c478bd9Sstevel@tonic-gate 		merror(value(vi_TERSE) ? gettext("%d more files") :
4557c478bd9Sstevel@tonic-gate 			gettext("%d more files to edit"), argc);
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate 	return(1);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate /*
4617c478bd9Sstevel@tonic-gate  * Before edit of new file check that either an ! follows
4627c478bd9Sstevel@tonic-gate  * or the file has not been changed.
4637c478bd9Sstevel@tonic-gate  */
464f6db9f27Scf46844 int
465f6db9f27Scf46844 quickly(void)
4667c478bd9Sstevel@tonic-gate {
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	if (exclam())
4697c478bd9Sstevel@tonic-gate 		return (1);
4707c478bd9Sstevel@tonic-gate 	if (chng && dol > zero) {
4717c478bd9Sstevel@tonic-gate /*
4727c478bd9Sstevel@tonic-gate 		chng = 0;
4737c478bd9Sstevel@tonic-gate */
4747c478bd9Sstevel@tonic-gate 		xchng = 0;
475f6db9f27Scf46844 		error(value(vi_TERSE) ? (unsigned char *)gettext("No write") :
476f6db9f27Scf46844 		    (unsigned char *)
477f6db9f27Scf46844 		    gettext("No write since last change (:%s! overrides)"),
478f6db9f27Scf46844 		    Command);
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 	return (0);
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate  * Reset the flavor of the output to print mode with no numbering.
4857c478bd9Sstevel@tonic-gate  */
486f6db9f27Scf46844 void
487f6db9f27Scf46844 resetflav(void)
4887c478bd9Sstevel@tonic-gate {
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	if (inopen)
4917c478bd9Sstevel@tonic-gate 		return;
4927c478bd9Sstevel@tonic-gate 	listf = 0;
4937c478bd9Sstevel@tonic-gate 	nflag = 0;
4947c478bd9Sstevel@tonic-gate 	pflag = 0;
4957c478bd9Sstevel@tonic-gate 	poffset = 0;
4967c478bd9Sstevel@tonic-gate 	setflav();
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate /*
5007c478bd9Sstevel@tonic-gate  * Print an error message with a %s type argument to printf.
5017c478bd9Sstevel@tonic-gate  * Message text comes from error message file.
5027c478bd9Sstevel@tonic-gate  */
503f6db9f27Scf46844 void
504f6db9f27Scf46844 serror(unsigned char *str, unsigned char *cp)
5057c478bd9Sstevel@tonic-gate {
506*68c92b9fScf46844 	tagflg = 0;
5077c478bd9Sstevel@tonic-gate 	error0();
5087c478bd9Sstevel@tonic-gate 	smerror(str, cp);
5097c478bd9Sstevel@tonic-gate 	error1(str);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate /*
5137c478bd9Sstevel@tonic-gate  * Set the flavor of the output based on the flags given
5147c478bd9Sstevel@tonic-gate  * and the number and list options to either number or not number lines
5157c478bd9Sstevel@tonic-gate  * and either use normally decoded (ARPAnet standard) characters or list mode,
5167c478bd9Sstevel@tonic-gate  * where end of lines are marked and tabs print as ^I.
5177c478bd9Sstevel@tonic-gate  */
518f6db9f27Scf46844 void
519f6db9f27Scf46844 setflav(void)
5207c478bd9Sstevel@tonic-gate {
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (inopen)
5237c478bd9Sstevel@tonic-gate 		return;
5247c478bd9Sstevel@tonic-gate 	setnumb(nflag || value(vi_NUMBER));
5257c478bd9Sstevel@tonic-gate 	setlist(listf || value(vi_LIST));
5267c478bd9Sstevel@tonic-gate 	if (!inopen)
5277c478bd9Sstevel@tonic-gate 		setoutt();
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate /*
5317c478bd9Sstevel@tonic-gate  * Skip white space and tell whether command ends then.
5327c478bd9Sstevel@tonic-gate  */
533f6db9f27Scf46844 int
534f6db9f27Scf46844 skipend(void)
5357c478bd9Sstevel@tonic-gate {
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	pastwh();
5387c478bd9Sstevel@tonic-gate 	return (endcmd(peekchar()) && peekchar() != '"');
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate /*
5427c478bd9Sstevel@tonic-gate  * Set the command name for non-word commands.
5437c478bd9Sstevel@tonic-gate  */
544f6db9f27Scf46844 void
545f6db9f27Scf46844 tailspec(int c)
5467c478bd9Sstevel@tonic-gate {
5477c478bd9Sstevel@tonic-gate 	static unsigned char foocmd[2];
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	foocmd[0] = c;
5507c478bd9Sstevel@tonic-gate 	Command = foocmd;
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate /*
5547c478bd9Sstevel@tonic-gate  * Try to read off the rest of the command word.
5557c478bd9Sstevel@tonic-gate  * If alphabetics follow, then this is not the command we seek.
5567c478bd9Sstevel@tonic-gate  */
557f6db9f27Scf46844 void
558f6db9f27Scf46844 tail(unsigned char *comm)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	tailprim(comm, 1, 0);
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate 
564f6db9f27Scf46844 void
565f6db9f27Scf46844 tail2of(unsigned char *comm)
5667c478bd9Sstevel@tonic-gate {
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	tailprim(comm, 2, 0);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate unsigned char	tcommand[20];
5727c478bd9Sstevel@tonic-gate 
573f6db9f27Scf46844 void
574f6db9f27Scf46844 tailprim(unsigned char *comm, int i, bool notinvis)
5757c478bd9Sstevel@tonic-gate {
576f6db9f27Scf46844 	unsigned char *cp;
577f6db9f27Scf46844 	int c;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	Command = comm;
5807c478bd9Sstevel@tonic-gate 	for (cp = tcommand; i > 0; i--)
5817c478bd9Sstevel@tonic-gate 		*cp++ = *comm++;
5827c478bd9Sstevel@tonic-gate 	while (*comm && peekchar() == *comm)
5837c478bd9Sstevel@tonic-gate 		*cp++ = getchar(), comm++;
5847c478bd9Sstevel@tonic-gate 	c = peekchar();
5857c478bd9Sstevel@tonic-gate 	if (notinvis || (isalpha(c) && isascii(c))) {
5867c478bd9Sstevel@tonic-gate 		/*
5877c478bd9Sstevel@tonic-gate 		 * Of the trailing lp funny business, only dl and dp
5887c478bd9Sstevel@tonic-gate 		 * survive the move from ed to ex.
5897c478bd9Sstevel@tonic-gate 		 */
5907c478bd9Sstevel@tonic-gate 		if (tcommand[0] == 'd' && any(c, "lp"))
5917c478bd9Sstevel@tonic-gate 			goto ret;
5927c478bd9Sstevel@tonic-gate 		if (tcommand[0] == 's' && any(c, "gcr"))
5937c478bd9Sstevel@tonic-gate 			goto ret;
5947c478bd9Sstevel@tonic-gate 		while (cp < &tcommand[19] && isalpha(c = peekchar()) && isascii(c))
5957c478bd9Sstevel@tonic-gate 			*cp++ = getchar();
5967c478bd9Sstevel@tonic-gate 		*cp = 0;
5977c478bd9Sstevel@tonic-gate 		if (notinvis)
598f6db9f27Scf46844 			serror(value(vi_TERSE) ?
599f6db9f27Scf46844 			    (unsigned char *)gettext("What?") :
600f6db9f27Scf46844 			    (unsigned char *)gettext(
601f6db9f27Scf46844 			    "%s: No such command from open/visual"), tcommand);
6027c478bd9Sstevel@tonic-gate 		else
603f6db9f27Scf46844 			serror(value(vi_TERSE) ?
604f6db9f27Scf46844 			    (unsigned char *)gettext("What?") :
605f6db9f27Scf46844 			    (unsigned char *)gettext(
606f6db9f27Scf46844 			    "%s: Not an editor command"), tcommand);
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate ret:
6097c478bd9Sstevel@tonic-gate 	*cp = 0;
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate  * Continue after a : command from open/visual.
6147c478bd9Sstevel@tonic-gate  */
615f6db9f27Scf46844 void
616f6db9f27Scf46844 vcontin(bool ask)
6177c478bd9Sstevel@tonic-gate {
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	if (vcnt > 0)
6207c478bd9Sstevel@tonic-gate 		vcnt = -vcnt;
6217c478bd9Sstevel@tonic-gate 	if (inopen) {
6227c478bd9Sstevel@tonic-gate 		if (state != VISUAL) {
6237c478bd9Sstevel@tonic-gate 			/*
6247c478bd9Sstevel@tonic-gate 			 * We don't know what a shell command may have left on
6257c478bd9Sstevel@tonic-gate 			 * the screen, so we move the cursor to the right place
6267c478bd9Sstevel@tonic-gate 			 * and then put out a newline.  But this makes an extra
6277c478bd9Sstevel@tonic-gate 			 * blank line most of the time so we only do it for :sh
6287c478bd9Sstevel@tonic-gate 			 * since the prompt gets left on the screen.
6297c478bd9Sstevel@tonic-gate 			 *
6307c478bd9Sstevel@tonic-gate 			 * BUG: :!echo longer than current line \\c
6317c478bd9Sstevel@tonic-gate 			 * will mess it up.
6327c478bd9Sstevel@tonic-gate 			 */
6337c478bd9Sstevel@tonic-gate 			if (state == CRTOPEN) {
6347c478bd9Sstevel@tonic-gate 				termreset();
6357c478bd9Sstevel@tonic-gate 				vgoto(WECHO, 0);
6367c478bd9Sstevel@tonic-gate 			}
6377c478bd9Sstevel@tonic-gate 			if (!ask) {
638f6db9f27Scf46844 				(void) putch('\r');
639f6db9f27Scf46844 				(void) putch('\n');
6407c478bd9Sstevel@tonic-gate 			}
6417c478bd9Sstevel@tonic-gate 			return;
6427c478bd9Sstevel@tonic-gate 		}
6437c478bd9Sstevel@tonic-gate 		if (ask) {
6447c478bd9Sstevel@tonic-gate 			merror(gettext("[Hit return to continue] "));
6457c478bd9Sstevel@tonic-gate 			flush();
6467c478bd9Sstevel@tonic-gate 		}
6477c478bd9Sstevel@tonic-gate #ifndef CBREAK
6487c478bd9Sstevel@tonic-gate 		vraw();
6497c478bd9Sstevel@tonic-gate #endif
6507c478bd9Sstevel@tonic-gate 		if (ask) {
6517c478bd9Sstevel@tonic-gate #ifdef notdef
6527c478bd9Sstevel@tonic-gate 			/*
6537c478bd9Sstevel@tonic-gate 			 * Gobble ^Q/^S since the tty driver should be eating
6547c478bd9Sstevel@tonic-gate 			 * them (as far as the user can see)
6557c478bd9Sstevel@tonic-gate 			 */
6567c478bd9Sstevel@tonic-gate 			while (peekkey() == CTRL('Q') || peekkey() == CTRL('S'))
6577c478bd9Sstevel@tonic-gate 				ignore(getkey());
6587c478bd9Sstevel@tonic-gate #endif
6597c478bd9Sstevel@tonic-gate 			if(getkey() == ':') {
6607c478bd9Sstevel@tonic-gate 				/* Extra newlines, but no other way */
661f6db9f27Scf46844 				(void) putch('\n');
6627c478bd9Sstevel@tonic-gate 				outline = WECHO;
6637c478bd9Sstevel@tonic-gate 				ungetkey(':');
6647c478bd9Sstevel@tonic-gate 			}
6657c478bd9Sstevel@tonic-gate 		}
6667c478bd9Sstevel@tonic-gate 		vclrech(1);
6677c478bd9Sstevel@tonic-gate 		if (Peekkey != ':') {
6687c478bd9Sstevel@tonic-gate 			fixterm();
669f6db9f27Scf46844 			putpad((unsigned char *)enter_ca_mode);
6707c478bd9Sstevel@tonic-gate 			tostart();
6717c478bd9Sstevel@tonic-gate 		}
6727c478bd9Sstevel@tonic-gate 	}
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate /*
6767c478bd9Sstevel@tonic-gate  * Put out a newline (before a shell escape)
6777c478bd9Sstevel@tonic-gate  * if in open/visual.
6787c478bd9Sstevel@tonic-gate  */
679f6db9f27Scf46844 void
680f6db9f27Scf46844 vnfl(void)
6817c478bd9Sstevel@tonic-gate {
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	if (inopen) {
6847c478bd9Sstevel@tonic-gate 		if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
6857c478bd9Sstevel@tonic-gate 			vclean();
6867c478bd9Sstevel@tonic-gate 		else
6877c478bd9Sstevel@tonic-gate 			vmoveitup(1, 0);
6887c478bd9Sstevel@tonic-gate 		vgoto(WECHO, 0);
6897c478bd9Sstevel@tonic-gate 		vclrbyte(vtube[WECHO], WCOLS);
6907c478bd9Sstevel@tonic-gate 		tostop();
6917c478bd9Sstevel@tonic-gate 		/* replaced by the ostop above
6927c478bd9Sstevel@tonic-gate 		putpad(cursor_normal);
6937c478bd9Sstevel@tonic-gate 		putpad(key_eol);
6947c478bd9Sstevel@tonic-gate 		*/
6957c478bd9Sstevel@tonic-gate 	}
6967c478bd9Sstevel@tonic-gate 	flush();
6977c478bd9Sstevel@tonic-gate }
698