xref: /onnv-gate/usr/src/cmd/vi/port/ex_subr.c (revision 13093:48f2dbca79a2)
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*13093SRoger.Faulkner@Oracle.COM  * Common Development and Distribution License (the "License").
6*13093SRoger.Faulkner@Oracle.COM  * 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  */
21*13093SRoger.Faulkner@Oracle.COM 
220Sstevel@tonic-gate /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
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 #include <sys/stropts.h>
330Sstevel@tonic-gate #include <sys/eucioctl.h>
340Sstevel@tonic-gate #ifndef PRESUNEUC
350Sstevel@tonic-gate #include <locale.h>
360Sstevel@tonic-gate /* Undef putchar/getchar if they're defined. */
370Sstevel@tonic-gate #ifdef putchar
380Sstevel@tonic-gate #	undef putchar
390Sstevel@tonic-gate #endif
400Sstevel@tonic-gate #ifdef getchar
410Sstevel@tonic-gate #	undef getchar
420Sstevel@tonic-gate #endif
430Sstevel@tonic-gate #endif /* PRESUNEUC */
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #include "ex.h"
460Sstevel@tonic-gate #include "ex_re.h"
470Sstevel@tonic-gate #include "ex_tty.h"
480Sstevel@tonic-gate #include "ex_vis.h"
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * Random routines, in alphabetical order.
520Sstevel@tonic-gate  */
530Sstevel@tonic-gate 
54802Scf46844 int
any(int c,unsigned char * s)55802Scf46844 any(int c, unsigned char *s)
560Sstevel@tonic-gate {
57802Scf46844 	int x;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	while (x = *s++)
600Sstevel@tonic-gate 		if (x == c)
610Sstevel@tonic-gate 			return (1);
620Sstevel@tonic-gate 	return (0);
630Sstevel@tonic-gate }
640Sstevel@tonic-gate 
65802Scf46844 int
backtab(int i)66802Scf46844 backtab(int i)
670Sstevel@tonic-gate {
68802Scf46844 	int j;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	j = i % value(vi_SHIFTWIDTH);
710Sstevel@tonic-gate 	if (j == 0)
720Sstevel@tonic-gate 		j = value(vi_SHIFTWIDTH);
730Sstevel@tonic-gate 	i -= j;
740Sstevel@tonic-gate 	if (i < 0)
750Sstevel@tonic-gate 		i = 0;
760Sstevel@tonic-gate 	return (i);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate 
79802Scf46844 void
change(void)80802Scf46844 change(void)
810Sstevel@tonic-gate {
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	tchng++;
840Sstevel@tonic-gate 	chng = tchng;
850Sstevel@tonic-gate }
860Sstevel@tonic-gate 
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate  * Column returns the number of
890Sstevel@tonic-gate  * columns occupied by printing the
900Sstevel@tonic-gate  * characters through position cp of the
910Sstevel@tonic-gate  * current line.
920Sstevel@tonic-gate  */
93802Scf46844 int
column(unsigned char * cp)94802Scf46844 column(unsigned char *cp)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	if (cp == 0)
980Sstevel@tonic-gate 		cp = &linebuf[LBSIZE - 2];
99802Scf46844 	return (qcolumn(cp, (unsigned char *)0));
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate /* lcolumn is same as column except it returns number of columns
1030Sstevel@tonic-gate  * occupied by characters before position
1040Sstevel@tonic-gate  * cp of the current line
1050Sstevel@tonic-gate  */
106802Scf46844 int
lcolumn(unsigned char * cp)107802Scf46844 lcolumn(unsigned char *cp)
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	if (cp == 0)
1110Sstevel@tonic-gate 		cp = &linebuf[LBSIZE - 2];
112802Scf46844 	return (nqcolumn(lastchr(linebuf, cp), (unsigned char *)0));
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate  * Ignore a comment to the end of the line.
1170Sstevel@tonic-gate  * This routine eats the trailing newline so don't call donewline().
1180Sstevel@tonic-gate  */
119802Scf46844 void
comment(void)120802Scf46844 comment(void)
1210Sstevel@tonic-gate {
122802Scf46844 	int c;
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	do {
1250Sstevel@tonic-gate 		c = getchar();
1260Sstevel@tonic-gate 	} while (c != '\n' && c != EOF);
1270Sstevel@tonic-gate 	if (c == EOF)
1280Sstevel@tonic-gate 		ungetchar(c);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate 
131802Scf46844 void
Copy(unsigned char * to,unsigned char * from,int size)132802Scf46844 Copy(unsigned char *to, unsigned char *from, int size)
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	if (size > 0)
1360Sstevel@tonic-gate 		do
1370Sstevel@tonic-gate 			*to++ = *from++;
1380Sstevel@tonic-gate 		while (--size > 0);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate 
141802Scf46844 void
copyw(line * to,line * from,int size)142802Scf46844 copyw(line *to, line *from, int size)
1430Sstevel@tonic-gate {
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	if (size > 0)
1460Sstevel@tonic-gate 		do
1470Sstevel@tonic-gate 			*to++ = *from++;
1480Sstevel@tonic-gate 		while (--size > 0);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate 
151802Scf46844 void
copywR(line * to,line * from,int size)152802Scf46844 copywR(line *to, line *from, int size)
1530Sstevel@tonic-gate {
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	while (--size >= 0)
1560Sstevel@tonic-gate 		to[size] = from[size];
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate 
159802Scf46844 int
ctlof(int c)160802Scf46844 ctlof(int c)
1610Sstevel@tonic-gate {
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	return (c == DELETE ? '?' : c | ('A' - 1));
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate 
166802Scf46844 void
dingdong(void)167802Scf46844 dingdong(void)
1680Sstevel@tonic-gate {
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	if (flash_screen && value(vi_FLASH))
171802Scf46844 		putpad((unsigned char *)flash_screen);
1720Sstevel@tonic-gate 	else if (value(vi_ERRORBELLS))
173802Scf46844 		putpad((unsigned char *)bell);
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
176802Scf46844 int
fixindent(int indent)177802Scf46844 fixindent(int indent)
1780Sstevel@tonic-gate {
179802Scf46844 	int i;
180802Scf46844 	unsigned char *cp;
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	i = whitecnt(genbuf);
1830Sstevel@tonic-gate 	cp = vpastwh(genbuf);
1840Sstevel@tonic-gate 	if (*cp == 0 && i == indent && linebuf[0] == 0) {
1850Sstevel@tonic-gate 		genbuf[0] = 0;
1860Sstevel@tonic-gate 		return (i);
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 	CP(genindent(i), cp);
1890Sstevel@tonic-gate 	return (i);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
192802Scf46844 void
filioerr(unsigned char * cp)193802Scf46844 filioerr(unsigned char *cp)
1940Sstevel@tonic-gate {
195802Scf46844 	int oerrno = errno;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	lprintf("\"%s\"", cp);
1980Sstevel@tonic-gate 	errno = oerrno;
1990Sstevel@tonic-gate 	syserror(1);
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate unsigned char *
genindent(indent)2030Sstevel@tonic-gate genindent(indent)
204802Scf46844 	int indent;
2050Sstevel@tonic-gate {
206802Scf46844 	unsigned char *cp;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	for (cp = genbuf; indent >= value(vi_TABSTOP); indent -= value(vi_TABSTOP))
2090Sstevel@tonic-gate 		*cp++ = '\t';
2100Sstevel@tonic-gate 	for (; indent > 0; indent--)
2110Sstevel@tonic-gate 		*cp++ = ' ';
2120Sstevel@tonic-gate 	return (cp);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate 
215802Scf46844 void
getDOT(void)216802Scf46844 getDOT(void)
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate 
219*13093SRoger.Faulkner@Oracle.COM 	getaline(*dot);
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate line *
getmark(c)2230Sstevel@tonic-gate getmark(c)
224802Scf46844 	int c;
2250Sstevel@tonic-gate {
226802Scf46844 	line *addr;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	for (addr = one; addr <= dol; addr++)
2290Sstevel@tonic-gate 		if (names[c - 'a'] == (*addr &~ 01)) {
2300Sstevel@tonic-gate 			return (addr);
2310Sstevel@tonic-gate 		}
2320Sstevel@tonic-gate 	return (0);
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate 
235802Scf46844 void
ignnEOF(void)236802Scf46844 ignnEOF(void)
2370Sstevel@tonic-gate {
238802Scf46844 	int c = getchar();
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	if (c == EOF)
2410Sstevel@tonic-gate 		ungetchar(c);
2420Sstevel@tonic-gate 	else if (c=='"')
2430Sstevel@tonic-gate 		comment();
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate 
246802Scf46844 int
iswhite(int c)247802Scf46844 iswhite(int c)
2480Sstevel@tonic-gate {
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	return (c == ' ' || c == '\t');
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
253802Scf46844 int
junk(wchar_t c)254802Scf46844 junk(wchar_t c)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	if (c && !value(vi_BEAUTIFY))
2580Sstevel@tonic-gate 		return (0);
2590Sstevel@tonic-gate 	if (c >= ' ' && c != DELETE)
2600Sstevel@tonic-gate 		return (0);
2610Sstevel@tonic-gate 	switch (c) {
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	case '\t':
2640Sstevel@tonic-gate 	case '\n':
2650Sstevel@tonic-gate 	case '\f':
2660Sstevel@tonic-gate 		return (0);
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	default:
2690Sstevel@tonic-gate 		return (1);
2700Sstevel@tonic-gate 	}
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate 
273802Scf46844 void
killed(void)274802Scf46844 killed(void)
2750Sstevel@tonic-gate {
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	killcnt(addr2 - addr1 + 1);
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
280802Scf46844 void
killcnt(int cnt)281802Scf46844 killcnt(int cnt)
2820Sstevel@tonic-gate {
2830Sstevel@tonic-gate 	extern char *verbalize();
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (inopen) {
2860Sstevel@tonic-gate 		notecnt = cnt;
2870Sstevel@tonic-gate 		notenam = notesgn = (unsigned char *)"";
2880Sstevel@tonic-gate 		return;
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 	if (!notable(cnt))
2910Sstevel@tonic-gate 		return;
2920Sstevel@tonic-gate 	if (value(vi_TERSE) == 0) {
2930Sstevel@tonic-gate 		verbalize(cnt, Command, "");
2940Sstevel@tonic-gate 	} else {
2950Sstevel@tonic-gate 		if (cnt == 1) {
296802Scf46844 			viprintf(gettext("1 line"), cnt);
2970Sstevel@tonic-gate 		} else {
298802Scf46844 			viprintf(gettext("%d lines"), cnt);
2990Sstevel@tonic-gate 		}
3000Sstevel@tonic-gate 	}
3010Sstevel@tonic-gate 	putNFL();
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate 
304802Scf46844 int
lineno(line * a)305802Scf46844 lineno(line *a)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	return (a - zero);
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate 
311802Scf46844 int
lineDOL(void)312802Scf46844 lineDOL(void)
3130Sstevel@tonic-gate {
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	return (lineno(dol));
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate 
318802Scf46844 int
lineDOT(void)319802Scf46844 lineDOT(void)
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	return (lineno(dot));
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate 
325802Scf46844 void
markDOT(void)326802Scf46844 markDOT(void)
3270Sstevel@tonic-gate {
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	markpr(dot);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate 
332802Scf46844 void
markpr(line * which)333802Scf46844 markpr(line *which)
3340Sstevel@tonic-gate {
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	if ((inglobal == 0 || inopen) && which <= endcore) {
3370Sstevel@tonic-gate 		names['z'-'a'+1] = *which & ~01;
3380Sstevel@tonic-gate 		if (inopen)
3390Sstevel@tonic-gate 			ncols['z'-'a'+1] = cursor;
3400Sstevel@tonic-gate 	}
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate 
343802Scf46844 int
markreg(int c)344802Scf46844 markreg(int c)
3450Sstevel@tonic-gate {
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	if (c == '\'' || c == '`')
3480Sstevel@tonic-gate 		return ('z' + 1);
3490Sstevel@tonic-gate 	if (c >= 'a' && c <= 'z')
3500Sstevel@tonic-gate 		return (c);
3510Sstevel@tonic-gate 	return (0);
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate /*
3550Sstevel@tonic-gate  * Mesg decodes the terse/verbose strings. Thus
3560Sstevel@tonic-gate  *	'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy'
3570Sstevel@tonic-gate  *	'xxx|yyy' -> 'xxx' if terse, else 'yyy'
3580Sstevel@tonic-gate  * All others map to themselves.
3590Sstevel@tonic-gate  */
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate  * The feature described above was disabled for localizable messaging.
3620Sstevel@tonic-gate  */
3630Sstevel@tonic-gate unsigned char *
mesg(str)3640Sstevel@tonic-gate mesg(str)
365802Scf46844 	unsigned char *str;
3660Sstevel@tonic-gate {
367802Scf46844 	unsigned char *cp;
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	str = (unsigned char *)strcpy(genbuf, str);
3700Sstevel@tonic-gate 	/* commented out for localizable messaging */
3710Sstevel@tonic-gate /*	for (cp = str; *cp; cp++)
3720Sstevel@tonic-gate 		switch (*cp) {
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 		case '@':
3750Sstevel@tonic-gate 			if (value(vi_TERSE))
3760Sstevel@tonic-gate 				*cp = 0;
3770Sstevel@tonic-gate 			else
3780Sstevel@tonic-gate 				*cp = ' ';
3790Sstevel@tonic-gate 			break;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 		case '|':
3820Sstevel@tonic-gate 			if (value(vi_TERSE) == 0)
3830Sstevel@tonic-gate 				return (cp + 1);
3840Sstevel@tonic-gate 			*cp = 0;
3850Sstevel@tonic-gate 			break;
3860Sstevel@tonic-gate 		}	*/
3870Sstevel@tonic-gate 	return (str);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate /*VARARGS2*/
391802Scf46844 void
merror(unsigned char * seekpt,int i)392802Scf46844 merror(unsigned char *seekpt, int i)
3930Sstevel@tonic-gate {
394802Scf46844 	unsigned char *cp = linebuf;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	if (seekpt == 0)
3970Sstevel@tonic-gate 		return;
3980Sstevel@tonic-gate 	merror1(seekpt);
3990Sstevel@tonic-gate 	if (*cp == '\n')
4000Sstevel@tonic-gate 		putnl(), cp++;
4010Sstevel@tonic-gate 	if (inopen > 0 && clr_eol)
4020Sstevel@tonic-gate 		vclreol();
4030Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
404802Scf46844 		putpad((unsigned char *)enter_standout_mode);
4050Sstevel@tonic-gate #ifdef PRESUNEUC
406802Scf46844 	viprintf(mesg(cp), i);
4070Sstevel@tonic-gate #else
408802Scf46844 	viprintf((char *)mesg(cp), i);
4090Sstevel@tonic-gate #endif /* PRESUNEUC */
4100Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
411802Scf46844 		putpad((unsigned char *)exit_bold);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate 
414802Scf46844 void
merror1(unsigned char * seekpt)415802Scf46844 merror1(unsigned char *seekpt)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	strcpy(linebuf, seekpt);
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate #define MAXDATA (56*1024)
422802Scf46844 int
morelines(void)423802Scf46844 morelines(void)
4240Sstevel@tonic-gate {
425802Scf46844 	unsigned char *end;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	if ((int) sbrk(1024 * sizeof (line)) == -1) {
4280Sstevel@tonic-gate 		if (endcore >= (line *) MAXDATA)
4290Sstevel@tonic-gate 			return -1;
4300Sstevel@tonic-gate 		end = (unsigned char *) MAXDATA;
4310Sstevel@tonic-gate 		/*
4320Sstevel@tonic-gate 		 * Ask for end+2 sice we want end to be the last used location.
4330Sstevel@tonic-gate 		 */
4340Sstevel@tonic-gate 		while (brk(end+2) == -1)
4350Sstevel@tonic-gate 			end -= 64;
4360Sstevel@tonic-gate 		if (end <= (unsigned char *) endcore)
4370Sstevel@tonic-gate 			return -1;
4380Sstevel@tonic-gate 		endcore = (line *) end;
4390Sstevel@tonic-gate 	} else {
4400Sstevel@tonic-gate 		endcore += 1024;
4410Sstevel@tonic-gate 	}
4420Sstevel@tonic-gate 	return (0);
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate 
445802Scf46844 void
nonzero(void)446802Scf46844 nonzero(void)
4470Sstevel@tonic-gate {
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	if (addr1 == zero) {
4500Sstevel@tonic-gate 		notempty();
4510Sstevel@tonic-gate 		error(value(vi_TERSE) ? gettext("Nonzero address required") :
4520Sstevel@tonic-gate gettext("Nonzero address required on this command"));
4530Sstevel@tonic-gate 	}
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate 
456802Scf46844 int
notable(int i)457802Scf46844 notable(int i)
4580Sstevel@tonic-gate {
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	return (hush == 0 && !inglobal && i > value(vi_REPORT));
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 
464802Scf46844 void
notempty(void)465802Scf46844 notempty(void)
4660Sstevel@tonic-gate {
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	if (dol == zero)
4690Sstevel@tonic-gate 		error(value(vi_TERSE) ? gettext("No lines") :
4700Sstevel@tonic-gate gettext("No lines in the buffer"));
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 
474802Scf46844 void
netchHAD(int cnt)475802Scf46844 netchHAD(int cnt)
4760Sstevel@tonic-gate {
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	netchange(lineDOL() - cnt);
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate 
481802Scf46844 void
netchange(int i)482802Scf46844 netchange(int i)
4830Sstevel@tonic-gate {
484802Scf46844 	unsigned char *cp;
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	if (i > 0)
4870Sstevel@tonic-gate 		notesgn = cp = (unsigned char *)"more ";
4880Sstevel@tonic-gate 	else
4890Sstevel@tonic-gate 		notesgn = cp = (unsigned char *)"fewer ", i = -i;
4900Sstevel@tonic-gate 	if (inopen) {
4910Sstevel@tonic-gate 		notecnt = i;
4920Sstevel@tonic-gate 		notenam = (unsigned char *)"";
4930Sstevel@tonic-gate 		return;
4940Sstevel@tonic-gate 	}
4950Sstevel@tonic-gate 	if (!notable(i))
4960Sstevel@tonic-gate 		return;
4970Sstevel@tonic-gate 	if (*cp == 'm')	/* for ease of messge localization */
4980Sstevel@tonic-gate #ifdef PRESUNEUC
499802Scf46844 		viprintf(mesg(value(vi_TERSE) ?
5000Sstevel@tonic-gate #else
501802Scf46844 		viprintf((char *)mesg(value(vi_TERSE) ?
5020Sstevel@tonic-gate #endif /* PRESUNEUC */
5030Sstevel@tonic-gate gettext("%d more lines") :
5040Sstevel@tonic-gate 		/*
5050Sstevel@tonic-gate 		 * TRANSLATION_NOTE
5060Sstevel@tonic-gate 		 *	Reference order of arguments must not
5070Sstevel@tonic-gate 		 *	be changed using '%digit$', since vi's
508802Scf46844 		 *	viprintf() does not support it.
5090Sstevel@tonic-gate 		 */
5100Sstevel@tonic-gate gettext("%d more lines in file after %s")), i, Command);
5110Sstevel@tonic-gate 	else
5120Sstevel@tonic-gate #ifdef PRESUNEUC
513802Scf46844 		viprintf(mesg(value(vi_TERSE) ?
5140Sstevel@tonic-gate #else
515802Scf46844 		viprintf((char *)mesg(value(vi_TERSE) ?
5160Sstevel@tonic-gate #endif /* PRESUNEUC */
5170Sstevel@tonic-gate gettext("%d fewer lines") :
5180Sstevel@tonic-gate 		/*
5190Sstevel@tonic-gate 		 * TRANSLATION_NOTE
5200Sstevel@tonic-gate 		 *	Reference order of arguments must not
5210Sstevel@tonic-gate 		 *	be changed using '%digit$', since vi's
522802Scf46844 		 *	viprintf() does not support it.
5230Sstevel@tonic-gate 		 */
5240Sstevel@tonic-gate gettext("%d fewer lines in file after %s")), i, Command);
5250Sstevel@tonic-gate 	putNFL();
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate 
528802Scf46844 void
putmark(line * addr)529802Scf46844 putmark(line *addr)
5300Sstevel@tonic-gate {
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	putmk1(addr, putline());
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate 
535802Scf46844 void
putmk1(line * addr,int n)536802Scf46844 putmk1(line *addr, int n)
5370Sstevel@tonic-gate {
538802Scf46844 	line *markp;
539802Scf46844 	int oldglobmk;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	oldglobmk = *addr & 1;
5420Sstevel@tonic-gate 	*addr &= ~1;
5430Sstevel@tonic-gate 	for (markp = (anymarks ? names : &names['z'-'a'+1]);
5440Sstevel@tonic-gate 	  markp <= &names['z'-'a'+1]; markp++)
5450Sstevel@tonic-gate 		if (*markp == *addr)
5460Sstevel@tonic-gate 			*markp = n;
5470Sstevel@tonic-gate 	*addr = n | oldglobmk;
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate unsigned char *
plural(i)5510Sstevel@tonic-gate plural(i)
5520Sstevel@tonic-gate 	long i;
5530Sstevel@tonic-gate {
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	return (i == 1 ? (unsigned char *)"" : (unsigned char *)"s");
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate int	qcount();
5590Sstevel@tonic-gate short	vcntcol;
5600Sstevel@tonic-gate 
561802Scf46844 int
qcolumn(unsigned char * lim,unsigned char * gp)562802Scf46844 qcolumn(unsigned char *lim, unsigned char *gp)
5630Sstevel@tonic-gate {
564802Scf46844 	int x, length;
5650Sstevel@tonic-gate 	int	col;
5660Sstevel@tonic-gate 	wchar_t wchar;
5670Sstevel@tonic-gate 	int (*OO)();
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	OO = Outchar;
5700Sstevel@tonic-gate 	Outchar = qcount;
5710Sstevel@tonic-gate 	vcntcol = 0;
5720Sstevel@tonic-gate 	if (lim != NULL) {
5730Sstevel@tonic-gate 		if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2])
5740Sstevel@tonic-gate 			length = 1;
5750Sstevel@tonic-gate 		else
5760Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX);
5770Sstevel@tonic-gate 		if(length < 0)
5780Sstevel@tonic-gate 			length = 1;
5790Sstevel@tonic-gate 		x = lim[length];
5800Sstevel@tonic-gate 		lim[length] = 0;
5810Sstevel@tonic-gate 	}
5820Sstevel@tonic-gate 	pline(0);
5830Sstevel@tonic-gate 	if (lim != NULL)
5840Sstevel@tonic-gate 		lim[length] = x;
5850Sstevel@tonic-gate 	if(length > 1 && !gp) {
5860Sstevel@tonic-gate 		/* put cursor at beginning of multibyte character */
5870Sstevel@tonic-gate 		if ((col = wcwidth(wchar)) < 0)
5880Sstevel@tonic-gate 			col = 0;
5890Sstevel@tonic-gate 		vcntcol = vcntcol - col + 1;
5900Sstevel@tonic-gate 	}
5910Sstevel@tonic-gate  	if (gp)
5920Sstevel@tonic-gate 		while (*gp) {
5930Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX);
5940Sstevel@tonic-gate 			if(length < 0) {
5950Sstevel@tonic-gate 				putoctal = 1;
5960Sstevel@tonic-gate 				putchar(*gp++);
5970Sstevel@tonic-gate 				putoctal = 0;
5980Sstevel@tonic-gate 			} else {
5990Sstevel@tonic-gate 				putchar(wchar);
6000Sstevel@tonic-gate 				gp += length;
6010Sstevel@tonic-gate 			}
6020Sstevel@tonic-gate 		}
6030Sstevel@tonic-gate 	Outchar = OO;
6040Sstevel@tonic-gate 	return (vcntcol);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate /* This routine puts cursor after multibyte character */
608802Scf46844 int
nqcolumn(unsigned char * lim,unsigned char * gp)609802Scf46844 nqcolumn(unsigned char *lim, unsigned char *gp)
6100Sstevel@tonic-gate {
611802Scf46844 	int x, length;
6120Sstevel@tonic-gate 	wchar_t wchar;
6130Sstevel@tonic-gate 	int (*OO)();
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	OO = Outchar;
6160Sstevel@tonic-gate 	Outchar = qcount;
6170Sstevel@tonic-gate 	vcntcol = 0;
6180Sstevel@tonic-gate 	if (lim != NULL) {
6190Sstevel@tonic-gate 		if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2])
6200Sstevel@tonic-gate 			length = 1;
6210Sstevel@tonic-gate 		else
6220Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX);
6230Sstevel@tonic-gate 		if(length < 0)
6240Sstevel@tonic-gate 			length = 1;
6250Sstevel@tonic-gate 		x = lim[length];
6260Sstevel@tonic-gate 		lim[length] = 0;
6270Sstevel@tonic-gate 	}
6280Sstevel@tonic-gate 	pline(0);
6290Sstevel@tonic-gate 	if (lim != NULL)
6300Sstevel@tonic-gate 		lim[length] = x;
6310Sstevel@tonic-gate  	if (gp)
6320Sstevel@tonic-gate 		while (*gp) {
6330Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX);
6340Sstevel@tonic-gate 			if(length < 0) {
6350Sstevel@tonic-gate 				putoctal = 1;
6360Sstevel@tonic-gate 				putchar(*gp++);
6370Sstevel@tonic-gate 				putoctal = 0;
6380Sstevel@tonic-gate 			} else {
6390Sstevel@tonic-gate 				putchar(wchar);
6400Sstevel@tonic-gate 				gp += length;
6410Sstevel@tonic-gate 			}
6420Sstevel@tonic-gate 		}
6430Sstevel@tonic-gate 	Outchar = OO;
6440Sstevel@tonic-gate 	return (vcntcol);
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate int
qcount(c)6480Sstevel@tonic-gate qcount(c)
6490Sstevel@tonic-gate wchar_t c;
6500Sstevel@tonic-gate {
651802Scf46844 	int cols;
6520Sstevel@tonic-gate #ifndef PRESUNEUC
653802Scf46844 	int remcols;
654802Scf46844 	short OWCOLS;
6550Sstevel@tonic-gate #endif /* PRESUNEUC */
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	if (c == '\t') {
6580Sstevel@tonic-gate 		vcntcol += value(vi_TABSTOP) - vcntcol % value(vi_TABSTOP);
659802Scf46844 		return (0);
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate #ifdef PRESUNEUC
6620Sstevel@tonic-gate 	if ((cols = wcwidth(c)) > 0)
6630Sstevel@tonic-gate 		vcntcol += cols;
6640Sstevel@tonic-gate #else
6650Sstevel@tonic-gate 	if ((cols = wcwidth(c)) < 0)
6660Sstevel@tonic-gate 		cols = 0;
6670Sstevel@tonic-gate 	OWCOLS = WCOLS;
6680Sstevel@tonic-gate 	if (WCOLS == 0)
6690Sstevel@tonic-gate 		WCOLS = columns;
6700Sstevel@tonic-gate 	if ((mc_wrap) == 1 && (remcols = (WCOLS - (vcntcol % WCOLS))) < cols)
6710Sstevel@tonic-gate 		vcntcol += remcols;
6720Sstevel@tonic-gate 	WCOLS = OWCOLS;
6730Sstevel@tonic-gate 	vcntcol += cols;
6740Sstevel@tonic-gate #endif /* PRESUNEUC */
675802Scf46844 	return (0);
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate 
678802Scf46844 void
reverse(line * a1,line * a2)679802Scf46844 reverse(line *a1, line *a2)
6800Sstevel@tonic-gate {
681802Scf46844 	line t;
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	for (;;) {
6840Sstevel@tonic-gate 		t = *--a2;
6850Sstevel@tonic-gate 		if (a2 <= a1)
6860Sstevel@tonic-gate 			return;
6870Sstevel@tonic-gate 		*a2 = *a1;
6880Sstevel@tonic-gate 		*a1++ = t;
6890Sstevel@tonic-gate 	}
6900Sstevel@tonic-gate }
6910Sstevel@tonic-gate 
692802Scf46844 void
save(line * a1,line * a2)693802Scf46844 save(line *a1, line *a2)
6940Sstevel@tonic-gate {
695802Scf46844 	int more;
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 	if (!FIXUNDO)
6980Sstevel@tonic-gate 		return;
6990Sstevel@tonic-gate #ifdef UNDOTRACE
7000Sstevel@tonic-gate 	if (trace)
7010Sstevel@tonic-gate 		vudump("before save");
7020Sstevel@tonic-gate #endif
7030Sstevel@tonic-gate 	undkind = UNDNONE;
7040Sstevel@tonic-gate 	undadot = dot;
7050Sstevel@tonic-gate 	more = (a2 - a1 + 1) - (unddol - dol);
7060Sstevel@tonic-gate 	while (more > (endcore - truedol))
7070Sstevel@tonic-gate 		if (morelines() < 0)
7080Sstevel@tonic-gate 			error(value(vi_TERSE) ? gettext("Out of memory") :
7090Sstevel@tonic-gate gettext("Out of memory saving lines for undo - try using ed"));
7100Sstevel@tonic-gate 	if (more)
7110Sstevel@tonic-gate 		(*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
7120Sstevel@tonic-gate 		    (truedol - unddol));
7130Sstevel@tonic-gate 	unddol += more;
7140Sstevel@tonic-gate 	truedol += more;
7150Sstevel@tonic-gate 	copyw(dol + 1, a1, a2 - a1 + 1);
7160Sstevel@tonic-gate 	undkind = UNDALL;
7170Sstevel@tonic-gate 	unddel = a1 - 1;
7180Sstevel@tonic-gate 	undap1 = a1;
7190Sstevel@tonic-gate 	undap2 = a2 + 1;
7200Sstevel@tonic-gate #ifdef UNDOTRACE
7210Sstevel@tonic-gate 	if (trace)
7220Sstevel@tonic-gate 		vudump("after save");
7230Sstevel@tonic-gate #endif
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate 
726802Scf46844 void
save12(void)727802Scf46844 save12(void)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	save(addr1, addr2);
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate 
733802Scf46844 void
saveall(void)734802Scf46844 saveall(void)
7350Sstevel@tonic-gate {
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	save(one, dol);
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate 
740802Scf46844 int
span(void)741802Scf46844 span(void)
7420Sstevel@tonic-gate {
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	return (addr2 - addr1 + 1);
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate 
747802Scf46844 void
sync(void)748802Scf46844 sync(void)
7490Sstevel@tonic-gate {
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	chng = 0;
7520Sstevel@tonic-gate 	tchng = 0;
7530Sstevel@tonic-gate 	xchng = 0;
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 
757802Scf46844 int
skipwh(void)758802Scf46844 skipwh(void)
7590Sstevel@tonic-gate {
760802Scf46844 	int wh;
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	wh = 0;
7630Sstevel@tonic-gate 	while (iswhite(peekchar())) {
7640Sstevel@tonic-gate 		wh++;
7650Sstevel@tonic-gate 		ignchar();
7660Sstevel@tonic-gate 	}
7670Sstevel@tonic-gate 	return (wh);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate /*VARARGS2*/
771802Scf46844 void
smerror(unsigned char * seekpt,unsigned char * cp)772802Scf46844 smerror(unsigned char *seekpt, unsigned char *cp)
7730Sstevel@tonic-gate {
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	errcnt++;
7760Sstevel@tonic-gate 	merror1(seekpt);
7770Sstevel@tonic-gate 	if (inopen && clr_eol)
7780Sstevel@tonic-gate 		vclreol();
7790Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
780802Scf46844 		putpad((unsigned char *)enter_standout_mode);
7810Sstevel@tonic-gate 	lprintf(mesg(linebuf), cp);
7820Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
783802Scf46844 		putpad((unsigned char *)exit_bold);
7840Sstevel@tonic-gate }
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate unsigned char *
strend(cp)7870Sstevel@tonic-gate strend(cp)
788802Scf46844 	unsigned char *cp;
7890Sstevel@tonic-gate {
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	while (*cp)
7920Sstevel@tonic-gate 		cp++;
7930Sstevel@tonic-gate 	return (cp);
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate 
796802Scf46844 void
strcLIN(unsigned char * dp)797802Scf46844 strcLIN(unsigned char *dp)
7980Sstevel@tonic-gate {
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 	CP(linebuf, dp);
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate /*
8040Sstevel@tonic-gate  * A system error has occurred that we need to perror.
8050Sstevel@tonic-gate  * danger is true if we are unsure of the contents of
8060Sstevel@tonic-gate  * the file or our buffer, e.g. a write error in the
8070Sstevel@tonic-gate  * middle of a write operation, or a temp file error.
8080Sstevel@tonic-gate  */
809802Scf46844 void
syserror(int danger)810802Scf46844 syserror(int danger)
8110Sstevel@tonic-gate {
812802Scf46844 	int e = errno;
8130Sstevel@tonic-gate 	char *errstr;
8140Sstevel@tonic-gate 	extern char *strerror();
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 	dirtcnt = 0;
8170Sstevel@tonic-gate 	putchar(' ');
8180Sstevel@tonic-gate 	if (danger)
8190Sstevel@tonic-gate 		edited = 0;	/* for temp file errors, for example */
8200Sstevel@tonic-gate 	if ((errstr = strerror(e)) != NULL)
8210Sstevel@tonic-gate 		error(errstr);
8220Sstevel@tonic-gate 	else
8230Sstevel@tonic-gate 		error(gettext("System error %d"), e);
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate /*
8270Sstevel@tonic-gate  * Return the column number that results from being in column col and
8280Sstevel@tonic-gate  * hitting a tab, where tabs are set every ts columns.  Work right for
8290Sstevel@tonic-gate  * the case where col > columns, even if ts does not divide columns.
8300Sstevel@tonic-gate  */
831802Scf46844 int
tabcol(int col,int ts)832802Scf46844 tabcol(int col, int ts)
8330Sstevel@tonic-gate {
8340Sstevel@tonic-gate 	int offset, result;
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	if (col >= columns) {
8370Sstevel@tonic-gate 		offset = columns * (col/columns);
8380Sstevel@tonic-gate 		col -= offset;
8390Sstevel@tonic-gate 	} else
8400Sstevel@tonic-gate 		offset = 0;
8410Sstevel@tonic-gate 	result = col + ts - (col % ts) + offset;
8420Sstevel@tonic-gate 	return (result);
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate unsigned char *
vfindcol(i)8460Sstevel@tonic-gate vfindcol(i)
8470Sstevel@tonic-gate 	int i;
8480Sstevel@tonic-gate {
849802Scf46844 	unsigned char *cp, *oldcp;
850802Scf46844 	int (*OO)() = Outchar;
851802Scf46844 	int length;
8520Sstevel@tonic-gate 	unsigned char x;
8530Sstevel@tonic-gate 	wchar_t wchar;
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 	Outchar = qcount;
856802Scf46844 	(void) qcolumn(linebuf - 1, (unsigned char *)NOSTR);
8570Sstevel@tonic-gate 	for (cp = linebuf; *cp && vcntcol < i; ) {
8580Sstevel@tonic-gate 		oldcp = cp;
8590Sstevel@tonic-gate 		length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX);
8600Sstevel@tonic-gate 		if(length < 0) {
8610Sstevel@tonic-gate 			putoctal = 1;
8620Sstevel@tonic-gate 			putchar(*cp++);
8630Sstevel@tonic-gate 			putoctal = 0;
8640Sstevel@tonic-gate 		} else {
8650Sstevel@tonic-gate 			putchar(wchar);
8660Sstevel@tonic-gate 			cp += length;
8670Sstevel@tonic-gate 		}
8680Sstevel@tonic-gate 	}
8690Sstevel@tonic-gate 	if (cp != linebuf)
8700Sstevel@tonic-gate 		cp = oldcp;
8710Sstevel@tonic-gate 	Outchar = OO;
8720Sstevel@tonic-gate 	return (cp);
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate unsigned char *
vskipwh(cp)8760Sstevel@tonic-gate vskipwh(cp)
877802Scf46844 	unsigned char *cp;
8780Sstevel@tonic-gate {
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 	while (iswhite(*cp) && cp[1])
8810Sstevel@tonic-gate 		cp++;
8820Sstevel@tonic-gate 	return (cp);
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate unsigned char *
vpastwh(cp)8870Sstevel@tonic-gate vpastwh(cp)
888802Scf46844 	unsigned char *cp;
8890Sstevel@tonic-gate {
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	while (iswhite(*cp))
8920Sstevel@tonic-gate 		cp++;
8930Sstevel@tonic-gate 	return (cp);
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate 
896802Scf46844 int
whitecnt(unsigned char * cp)897802Scf46844 whitecnt(unsigned char *cp)
8980Sstevel@tonic-gate {
899802Scf46844 	int i;
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	i = 0;
9020Sstevel@tonic-gate 	for (;;)
9030Sstevel@tonic-gate 		switch (*cp++) {
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 		case '\t':
9060Sstevel@tonic-gate 			i += value(vi_TABSTOP) - i % value(vi_TABSTOP);
9070Sstevel@tonic-gate 			break;
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 		case ' ':
9100Sstevel@tonic-gate 			i++;
9110Sstevel@tonic-gate 			break;
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 		default:
9140Sstevel@tonic-gate 			return (i);
9150Sstevel@tonic-gate 		}
9160Sstevel@tonic-gate }
9170Sstevel@tonic-gate 
918802Scf46844 void
markit(line * addr)919802Scf46844 markit(line *addr)
9200Sstevel@tonic-gate {
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	if (addr != dot && addr >= one && addr <= dol)
9230Sstevel@tonic-gate 		markDOT();
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate /*
9270Sstevel@tonic-gate  * The following code is defensive programming against a bug in the
9280Sstevel@tonic-gate  * pdp-11 overlay implementation.  Sometimes it goes nuts and asks
9290Sstevel@tonic-gate  * for an overlay with some garbage number, which generates an emt
9300Sstevel@tonic-gate  * trap.  This is a less than elegant solution, but it is somewhat
9310Sstevel@tonic-gate  * better than core dumping and losing your work, leaving your tty
9320Sstevel@tonic-gate  * in a weird state, etc.
9330Sstevel@tonic-gate  */
9340Sstevel@tonic-gate int _ovno;
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate /*ARGSUSED*/
9370Sstevel@tonic-gate void
onemt(sig)9380Sstevel@tonic-gate onemt(sig)
9390Sstevel@tonic-gate int sig;
9400Sstevel@tonic-gate {
9410Sstevel@tonic-gate 	int oovno;
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	signal(SIGEMT, onemt);
9440Sstevel@tonic-gate 	oovno = _ovno;
9450Sstevel@tonic-gate 	/* 2 and 3 are valid on 11/40 type vi, so */
9460Sstevel@tonic-gate 	if (_ovno < 0 || _ovno > 3)
9470Sstevel@tonic-gate 		_ovno = 0;
9480Sstevel@tonic-gate 	error(value(vi_TERSE) ? gettext("emt trap, _ovno is %d ") :
9490Sstevel@tonic-gate gettext("emt trap, _ovno is %d   - try again"));
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate /*
9530Sstevel@tonic-gate  * When a hangup occurs our actions are similar to a preserve
9540Sstevel@tonic-gate  * command.  If the buffer has not been [Modified], then we do
9550Sstevel@tonic-gate  * nothing but remove the temporary files and exit.
9560Sstevel@tonic-gate  * Otherwise, we sync the temp file and then attempt a preserve.
9570Sstevel@tonic-gate  * If the preserve succeeds, we unlink our temp files.
9580Sstevel@tonic-gate  * If the preserve fails, we leave the temp files as they are
9590Sstevel@tonic-gate  * as they are a backup even without preservation if they
9600Sstevel@tonic-gate  * are not removed.
9610Sstevel@tonic-gate  */
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate /*ARGSUSED*/
9640Sstevel@tonic-gate void
onhup(sig)9650Sstevel@tonic-gate onhup(sig)
9660Sstevel@tonic-gate int sig;
9670Sstevel@tonic-gate {
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	/*
9700Sstevel@tonic-gate 	 * USG tty driver can send multiple HUP's!!
9710Sstevel@tonic-gate 	 */
9720Sstevel@tonic-gate 	signal(SIGINT, SIG_IGN);
9730Sstevel@tonic-gate 	signal(SIGHUP, SIG_IGN);
9740Sstevel@tonic-gate 	if (chng == 0) {
9750Sstevel@tonic-gate 		cleanup(1);
9760Sstevel@tonic-gate 		exit(++errcnt);
9770Sstevel@tonic-gate 	}
9780Sstevel@tonic-gate 	if (setexit() == 0) {
9790Sstevel@tonic-gate 		if (preserve()) {
9800Sstevel@tonic-gate 			cleanup(1);
9810Sstevel@tonic-gate 			exit(++errcnt);
9820Sstevel@tonic-gate 		}
9830Sstevel@tonic-gate 	}
9840Sstevel@tonic-gate 	if (kflag)
9850Sstevel@tonic-gate 		crypt_close(perm);
9860Sstevel@tonic-gate 	if (xtflag)
9870Sstevel@tonic-gate 		crypt_close(tperm);
9880Sstevel@tonic-gate 	exit(++errcnt);
9890Sstevel@tonic-gate }
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate /*
9920Sstevel@tonic-gate  * Similar to onhup.  This happens when any random core dump occurs,
9930Sstevel@tonic-gate  * e.g. a bug in vi.  We preserve the file and then generate a core.
9940Sstevel@tonic-gate  */
oncore(sig)9950Sstevel@tonic-gate void oncore(sig)
9960Sstevel@tonic-gate int sig;
9970Sstevel@tonic-gate {
9980Sstevel@tonic-gate 	static int timescalled = 0;
9990Sstevel@tonic-gate 	char *messagep;	/* for message localization */
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 	/*
10020Sstevel@tonic-gate 	 * USG tty driver can send multiple HUP's!!
10030Sstevel@tonic-gate 	 */
10040Sstevel@tonic-gate 	signal(SIGINT, SIG_IGN);
10050Sstevel@tonic-gate 	signal(SIGHUP, SIG_IGN);
10060Sstevel@tonic-gate 	signal(sig, SIG_DFL);	/* Insure that we don't catch it again */
10070Sstevel@tonic-gate 	messagep = (char *)gettext("\r\nYour file has been preserved\r\n");
10080Sstevel@tonic-gate 	if (timescalled++ == 0 && chng && setexit() == 0) {
10090Sstevel@tonic-gate 		if (inopen)
10100Sstevel@tonic-gate 			vsave();
1011802Scf46844 		(void) preserve();
10120Sstevel@tonic-gate 		write(1, messagep, strlen(messagep));
10130Sstevel@tonic-gate 	}
10140Sstevel@tonic-gate 	if (timescalled < 2) {
10150Sstevel@tonic-gate 		normal(normf);
10160Sstevel@tonic-gate 		cleanup(2);
10170Sstevel@tonic-gate 		kill(getpid(), sig);	/* Resend ourselves the same signal */
10180Sstevel@tonic-gate 		/* We won't get past here */
10190Sstevel@tonic-gate 	}
10200Sstevel@tonic-gate 	if (kflag)
10210Sstevel@tonic-gate 		crypt_close(perm);
10220Sstevel@tonic-gate 	if (xtflag)
10230Sstevel@tonic-gate 		crypt_close(tperm);
10240Sstevel@tonic-gate 	exit(++errcnt);
10250Sstevel@tonic-gate }
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate /*
10280Sstevel@tonic-gate  * An interrupt occurred.  Drain any output which
10290Sstevel@tonic-gate  * is still in the output buffering pipeline.
10300Sstevel@tonic-gate  * Catch interrupts again.  Unless we are in visual
10310Sstevel@tonic-gate  * reset the output state (out of -nl mode, e.g).
10320Sstevel@tonic-gate  * Then like a normal error (with the \n before Interrupt
10330Sstevel@tonic-gate  * suppressed in visual mode).
10340Sstevel@tonic-gate  */
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate /*ARGSUSED*/
10370Sstevel@tonic-gate void
onintr(sig)10380Sstevel@tonic-gate onintr(sig)
10390Sstevel@tonic-gate int sig;
10400Sstevel@tonic-gate {
10410Sstevel@tonic-gate #ifndef CBREAK
10420Sstevel@tonic-gate 	signal(SIGINT, onintr);
10430Sstevel@tonic-gate #else
10440Sstevel@tonic-gate 	signal(SIGINT, inopen ? vintr : onintr);
10450Sstevel@tonic-gate #endif
10460Sstevel@tonic-gate 	cancelalarm();
10470Sstevel@tonic-gate 	draino();
10480Sstevel@tonic-gate 	if (!inopen) {
10490Sstevel@tonic-gate 		pstop();
10500Sstevel@tonic-gate 		setlastchar('\n');
10510Sstevel@tonic-gate #ifdef CBREAK
10520Sstevel@tonic-gate 	}
10530Sstevel@tonic-gate #else
10540Sstevel@tonic-gate 	} else
10550Sstevel@tonic-gate 		vraw();
10560Sstevel@tonic-gate #endif
10570Sstevel@tonic-gate 	error(gettext("\nInterrupt") + (inopen!=0));
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate /*
10610Sstevel@tonic-gate  * If we are interruptible, enable interrupts again.
10620Sstevel@tonic-gate  * In some critical sections we turn interrupts off,
10630Sstevel@tonic-gate  * but not very often.
10640Sstevel@tonic-gate  */
1065802Scf46844 void
setrupt(void)1066802Scf46844 setrupt(void)
10670Sstevel@tonic-gate {
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	if (ruptible) {
10700Sstevel@tonic-gate #ifndef CBREAK
10710Sstevel@tonic-gate 		signal(SIGINT, onintr);
10720Sstevel@tonic-gate #else
10730Sstevel@tonic-gate 		signal(SIGINT, inopen ? vintr : onintr);
10740Sstevel@tonic-gate #endif
10750Sstevel@tonic-gate #ifdef SIGTSTP
10760Sstevel@tonic-gate 		if (dosusp)
10770Sstevel@tonic-gate 			signal(SIGTSTP, onsusp);
10780Sstevel@tonic-gate #endif
10790Sstevel@tonic-gate 	}
10800Sstevel@tonic-gate }
10810Sstevel@tonic-gate 
1082802Scf46844 int
preserve(void)1083802Scf46844 preserve(void)
10840Sstevel@tonic-gate {
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate #ifdef VMUNIX
10870Sstevel@tonic-gate 	tflush();
10880Sstevel@tonic-gate #endif
10890Sstevel@tonic-gate 	synctmp();
10900Sstevel@tonic-gate 	pid = fork();
10910Sstevel@tonic-gate 	if (pid < 0)
10920Sstevel@tonic-gate 		return (0);
10930Sstevel@tonic-gate 	if (pid == 0) {
10940Sstevel@tonic-gate 		close(0);
10950Sstevel@tonic-gate 		dup(tfile);
10960Sstevel@tonic-gate 		execlp(EXPRESERVE, "expreserve", (char *) 0);
10970Sstevel@tonic-gate 		exit(++errcnt);
10980Sstevel@tonic-gate 	}
10990Sstevel@tonic-gate 	waitfor();
11000Sstevel@tonic-gate 	if (rpid == pid && status == 0)
11010Sstevel@tonic-gate 		return (1);
11020Sstevel@tonic-gate 	return (0);
11030Sstevel@tonic-gate }
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate #ifndef V6
exit(i)11060Sstevel@tonic-gate void exit(i)
11070Sstevel@tonic-gate 	int i;
11080Sstevel@tonic-gate {
11090Sstevel@tonic-gate 
1110802Scf46844 	extern void _exit(int) __NORETURN;
11110Sstevel@tonic-gate #ifdef TRACE
11120Sstevel@tonic-gate 	if (trace)
11130Sstevel@tonic-gate 		fclose(trace);
11140Sstevel@tonic-gate #endif
11150Sstevel@tonic-gate 	_exit(i);
11160Sstevel@tonic-gate }
11170Sstevel@tonic-gate #endif
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate #ifdef SIGTSTP
11200Sstevel@tonic-gate /*
11210Sstevel@tonic-gate  * We have just gotten a susp.  Suspend and prepare to resume.
11220Sstevel@tonic-gate  */
11230Sstevel@tonic-gate extern void redraw();
11240Sstevel@tonic-gate 
11250Sstevel@tonic-gate /*ARGSUSED*/
11260Sstevel@tonic-gate void
onsusp(sig)11270Sstevel@tonic-gate onsusp(sig)
11280Sstevel@tonic-gate int sig;
11290Sstevel@tonic-gate {
11300Sstevel@tonic-gate 	ttymode f;
11310Sstevel@tonic-gate 	int savenormtty;
11320Sstevel@tonic-gate 
11330Sstevel@tonic-gate 	f = setty(normf);
11340Sstevel@tonic-gate 	vnfl();
1135802Scf46844 	putpad((unsigned char *)exit_ca_mode);
11360Sstevel@tonic-gate 	flush();
11370Sstevel@tonic-gate 	resetterm();
11380Sstevel@tonic-gate 	savenormtty = normtty;
11390Sstevel@tonic-gate 	normtty = 0;
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	signal(SIGTSTP, SIG_DFL);
11420Sstevel@tonic-gate 	kill(0, SIGTSTP);
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate 	/* the pc stops here */
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate 	signal(SIGTSTP, onsusp);
11470Sstevel@tonic-gate 	normtty = savenormtty;
11480Sstevel@tonic-gate 	vcontin(0);
11490Sstevel@tonic-gate 	flush();
11500Sstevel@tonic-gate 	setty(f);
11510Sstevel@tonic-gate 	if (!inopen)
11520Sstevel@tonic-gate 		error(0);
11530Sstevel@tonic-gate 	else {
11540Sstevel@tonic-gate 		if(vcnt < 0) {
11550Sstevel@tonic-gate 			vcnt = -vcnt;
11560Sstevel@tonic-gate 			if(state == VISUAL)
11570Sstevel@tonic-gate 				vclear();
11580Sstevel@tonic-gate 			else if(state == CRTOPEN)
11590Sstevel@tonic-gate 				vcnt = 0;
11600Sstevel@tonic-gate 		}
11610Sstevel@tonic-gate 		vdirty(0, lines);
11620Sstevel@tonic-gate 		if (sig)
11630Sstevel@tonic-gate 			vrepaint(cursor);
11640Sstevel@tonic-gate 	}
11650Sstevel@tonic-gate }
11660Sstevel@tonic-gate #endif
11670Sstevel@tonic-gate 
nextchr(cursor)11680Sstevel@tonic-gate unsigned char *nextchr(cursor)
11690Sstevel@tonic-gate unsigned char *cursor;
11700Sstevel@tonic-gate {
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 	wchar_t wchar;
11730Sstevel@tonic-gate 	int length;
11740Sstevel@tonic-gate 	length = mbtowc(&wchar, (char *)cursor, MULTI_BYTE_MAX);
11750Sstevel@tonic-gate 	if(length <= 0)
11760Sstevel@tonic-gate 		return(++cursor);
11770Sstevel@tonic-gate 	return(cursor + length);
11780Sstevel@tonic-gate }
11790Sstevel@tonic-gate 
lastchr(linebuf,cursor)11800Sstevel@tonic-gate unsigned char *lastchr(linebuf, cursor)
11810Sstevel@tonic-gate unsigned char *linebuf, *cursor;
11820Sstevel@tonic-gate {
11830Sstevel@tonic-gate 	wchar_t wchar;
11840Sstevel@tonic-gate 	int length;
11850Sstevel@tonic-gate 	unsigned char *ccursor, *ocursor;
11860Sstevel@tonic-gate 	if(cursor == linebuf)
11870Sstevel@tonic-gate 		return(linebuf - 1);
11880Sstevel@tonic-gate 	ccursor = ocursor = linebuf;
11890Sstevel@tonic-gate 	while(ccursor < cursor) {
11900Sstevel@tonic-gate 		length = mbtowc(&wchar, (char *)ccursor, MULTI_BYTE_MAX);
11910Sstevel@tonic-gate 		ocursor =  ccursor;
11920Sstevel@tonic-gate 		if(length <= 0)
11930Sstevel@tonic-gate 			ccursor++;
11940Sstevel@tonic-gate 		else
11950Sstevel@tonic-gate 			ccursor += length;
11960Sstevel@tonic-gate 	}
11970Sstevel@tonic-gate 	return(ocursor);
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate 
1200802Scf46844 int
ixlatctl(int flag)1201802Scf46844 ixlatctl(int flag)
12020Sstevel@tonic-gate {
12030Sstevel@tonic-gate 	static struct strioctl sb = {0, 0, 0, 0};
12040Sstevel@tonic-gate 
12050Sstevel@tonic-gate 	if (!(MULTI_BYTE_MAX > 1))
12060Sstevel@tonic-gate 		return (0);
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate 	switch (flag) {
12090Sstevel@tonic-gate 	case 0:
12100Sstevel@tonic-gate 		sb.ic_cmd = EUC_MSAVE;
12110Sstevel@tonic-gate 		sb.ic_len = 0;
12120Sstevel@tonic-gate 		sb.ic_dp = 0;
12130Sstevel@tonic-gate 		if (ioctl(0, I_STR, &sb) < 0)
12140Sstevel@tonic-gate 			return (-1);
12150Sstevel@tonic-gate 		return (0);
12160Sstevel@tonic-gate 	case 1:
12170Sstevel@tonic-gate 		sb.ic_cmd = EUC_MREST;
12180Sstevel@tonic-gate 		sb.ic_len = 0;
12190Sstevel@tonic-gate 		sb.ic_dp = 0;
12200Sstevel@tonic-gate 		if (ioctl(0, I_STR, &sb) < 0)
12210Sstevel@tonic-gate 			return (-1);
12220Sstevel@tonic-gate 		return (0);
12230Sstevel@tonic-gate 	case 11:
12240Sstevel@tonic-gate 		return (0);
12250Sstevel@tonic-gate 	default:
12260Sstevel@tonic-gate 		return (-1);
12270Sstevel@tonic-gate 	}
12280Sstevel@tonic-gate }
12290Sstevel@tonic-gate #ifndef PRESUNEUC
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate /* locale specific initialization */
1232802Scf46844 void
localize(void)1233802Scf46844 localize(void)
12340Sstevel@tonic-gate {
12350Sstevel@tonic-gate 	wchar_t fillerchar;
12360Sstevel@tonic-gate 	extern int	wdchkind();
12370Sstevel@tonic-gate 	extern int	wdbindf();
12380Sstevel@tonic-gate 	extern wchar_t	*wddelim();
12390Sstevel@tonic-gate 	extern wchar_t	mcfiller();
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 	wdwc = wdchkind;
12420Sstevel@tonic-gate 	wdbdg = wdbindf;
12430Sstevel@tonic-gate 	wddlm = wddelim;
12440Sstevel@tonic-gate 	mcfllr = mcfiller;
12450Sstevel@tonic-gate 	mc_wrap = 1;
12460Sstevel@tonic-gate 	fillerchar = mcfiller();
12470Sstevel@tonic-gate 	mc_filler = isascii(fillerchar) ? (fillerchar & 0x7f) : '~';
12480Sstevel@tonic-gate }
12490Sstevel@tonic-gate #endif /* PRESUNEUC */
1250