xref: /onnv-gate/usr/src/cmd/vi/port/ex_subr.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  */
220Sstevel@tonic-gate /*
23*802Scf46844  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
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 <sys/stropts.h>
360Sstevel@tonic-gate #include <sys/eucioctl.h>
370Sstevel@tonic-gate #ifndef PRESUNEUC
380Sstevel@tonic-gate #include <locale.h>
390Sstevel@tonic-gate /* Undef putchar/getchar if they're defined. */
400Sstevel@tonic-gate #ifdef putchar
410Sstevel@tonic-gate #	undef putchar
420Sstevel@tonic-gate #endif
430Sstevel@tonic-gate #ifdef getchar
440Sstevel@tonic-gate #	undef getchar
450Sstevel@tonic-gate #endif
460Sstevel@tonic-gate #endif /* PRESUNEUC */
470Sstevel@tonic-gate 
480Sstevel@tonic-gate #include "ex.h"
490Sstevel@tonic-gate #include "ex_re.h"
500Sstevel@tonic-gate #include "ex_tty.h"
510Sstevel@tonic-gate #include "ex_vis.h"
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /*
540Sstevel@tonic-gate  * Random routines, in alphabetical order.
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate 
57*802Scf46844 int
58*802Scf46844 any(int c, unsigned char *s)
590Sstevel@tonic-gate {
60*802Scf46844 	int x;
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	while (x = *s++)
630Sstevel@tonic-gate 		if (x == c)
640Sstevel@tonic-gate 			return (1);
650Sstevel@tonic-gate 	return (0);
660Sstevel@tonic-gate }
670Sstevel@tonic-gate 
68*802Scf46844 int
69*802Scf46844 backtab(int i)
700Sstevel@tonic-gate {
71*802Scf46844 	int j;
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	j = i % value(vi_SHIFTWIDTH);
740Sstevel@tonic-gate 	if (j == 0)
750Sstevel@tonic-gate 		j = value(vi_SHIFTWIDTH);
760Sstevel@tonic-gate 	i -= j;
770Sstevel@tonic-gate 	if (i < 0)
780Sstevel@tonic-gate 		i = 0;
790Sstevel@tonic-gate 	return (i);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate 
82*802Scf46844 void
83*802Scf46844 change(void)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	tchng++;
870Sstevel@tonic-gate 	chng = tchng;
880Sstevel@tonic-gate }
890Sstevel@tonic-gate 
900Sstevel@tonic-gate /*
910Sstevel@tonic-gate  * Column returns the number of
920Sstevel@tonic-gate  * columns occupied by printing the
930Sstevel@tonic-gate  * characters through position cp of the
940Sstevel@tonic-gate  * current line.
950Sstevel@tonic-gate  */
96*802Scf46844 int
97*802Scf46844 column(unsigned char *cp)
980Sstevel@tonic-gate {
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	if (cp == 0)
1010Sstevel@tonic-gate 		cp = &linebuf[LBSIZE - 2];
102*802Scf46844 	return (qcolumn(cp, (unsigned char *)0));
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /* lcolumn is same as column except it returns number of columns
1060Sstevel@tonic-gate  * occupied by characters before position
1070Sstevel@tonic-gate  * cp of the current line
1080Sstevel@tonic-gate  */
109*802Scf46844 int
110*802Scf46844 lcolumn(unsigned char *cp)
1110Sstevel@tonic-gate {
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	if (cp == 0)
1140Sstevel@tonic-gate 		cp = &linebuf[LBSIZE - 2];
115*802Scf46844 	return (nqcolumn(lastchr(linebuf, cp), (unsigned char *)0));
1160Sstevel@tonic-gate }
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate /*
1190Sstevel@tonic-gate  * Ignore a comment to the end of the line.
1200Sstevel@tonic-gate  * This routine eats the trailing newline so don't call donewline().
1210Sstevel@tonic-gate  */
122*802Scf46844 void
123*802Scf46844 comment(void)
1240Sstevel@tonic-gate {
125*802Scf46844 	int c;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	do {
1280Sstevel@tonic-gate 		c = getchar();
1290Sstevel@tonic-gate 	} while (c != '\n' && c != EOF);
1300Sstevel@tonic-gate 	if (c == EOF)
1310Sstevel@tonic-gate 		ungetchar(c);
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate 
134*802Scf46844 void
135*802Scf46844 Copy(unsigned char *to, unsigned char *from, int size)
1360Sstevel@tonic-gate {
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	if (size > 0)
1390Sstevel@tonic-gate 		do
1400Sstevel@tonic-gate 			*to++ = *from++;
1410Sstevel@tonic-gate 		while (--size > 0);
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate 
144*802Scf46844 void
145*802Scf46844 copyw(line *to, line *from, int size)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	if (size > 0)
1490Sstevel@tonic-gate 		do
1500Sstevel@tonic-gate 			*to++ = *from++;
1510Sstevel@tonic-gate 		while (--size > 0);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate 
154*802Scf46844 void
155*802Scf46844 copywR(line *to, line *from, int size)
1560Sstevel@tonic-gate {
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	while (--size >= 0)
1590Sstevel@tonic-gate 		to[size] = from[size];
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate 
162*802Scf46844 int
163*802Scf46844 ctlof(int c)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	return (c == DELETE ? '?' : c | ('A' - 1));
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
169*802Scf46844 void
170*802Scf46844 dingdong(void)
1710Sstevel@tonic-gate {
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	if (flash_screen && value(vi_FLASH))
174*802Scf46844 		putpad((unsigned char *)flash_screen);
1750Sstevel@tonic-gate 	else if (value(vi_ERRORBELLS))
176*802Scf46844 		putpad((unsigned char *)bell);
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate 
179*802Scf46844 int
180*802Scf46844 fixindent(int indent)
1810Sstevel@tonic-gate {
182*802Scf46844 	int i;
183*802Scf46844 	unsigned char *cp;
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	i = whitecnt(genbuf);
1860Sstevel@tonic-gate 	cp = vpastwh(genbuf);
1870Sstevel@tonic-gate 	if (*cp == 0 && i == indent && linebuf[0] == 0) {
1880Sstevel@tonic-gate 		genbuf[0] = 0;
1890Sstevel@tonic-gate 		return (i);
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 	CP(genindent(i), cp);
1920Sstevel@tonic-gate 	return (i);
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate 
195*802Scf46844 void
196*802Scf46844 filioerr(unsigned char *cp)
1970Sstevel@tonic-gate {
198*802Scf46844 	int oerrno = errno;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	lprintf("\"%s\"", cp);
2010Sstevel@tonic-gate 	errno = oerrno;
2020Sstevel@tonic-gate 	syserror(1);
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate unsigned char *
2060Sstevel@tonic-gate genindent(indent)
207*802Scf46844 	int indent;
2080Sstevel@tonic-gate {
209*802Scf46844 	unsigned char *cp;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	for (cp = genbuf; indent >= value(vi_TABSTOP); indent -= value(vi_TABSTOP))
2120Sstevel@tonic-gate 		*cp++ = '\t';
2130Sstevel@tonic-gate 	for (; indent > 0; indent--)
2140Sstevel@tonic-gate 		*cp++ = ' ';
2150Sstevel@tonic-gate 	return (cp);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate 
218*802Scf46844 void
219*802Scf46844 getDOT(void)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	getline(*dot);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate line *
2260Sstevel@tonic-gate getmark(c)
227*802Scf46844 	int c;
2280Sstevel@tonic-gate {
229*802Scf46844 	line *addr;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	for (addr = one; addr <= dol; addr++)
2320Sstevel@tonic-gate 		if (names[c - 'a'] == (*addr &~ 01)) {
2330Sstevel@tonic-gate 			return (addr);
2340Sstevel@tonic-gate 		}
2350Sstevel@tonic-gate 	return (0);
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate 
238*802Scf46844 void
239*802Scf46844 ignnEOF(void)
2400Sstevel@tonic-gate {
241*802Scf46844 	int c = getchar();
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	if (c == EOF)
2440Sstevel@tonic-gate 		ungetchar(c);
2450Sstevel@tonic-gate 	else if (c=='"')
2460Sstevel@tonic-gate 		comment();
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate 
249*802Scf46844 int
250*802Scf46844 iswhite(int c)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	return (c == ' ' || c == '\t');
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate 
256*802Scf46844 int
257*802Scf46844 junk(wchar_t c)
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	if (c && !value(vi_BEAUTIFY))
2610Sstevel@tonic-gate 		return (0);
2620Sstevel@tonic-gate 	if (c >= ' ' && c != DELETE)
2630Sstevel@tonic-gate 		return (0);
2640Sstevel@tonic-gate 	switch (c) {
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	case '\t':
2670Sstevel@tonic-gate 	case '\n':
2680Sstevel@tonic-gate 	case '\f':
2690Sstevel@tonic-gate 		return (0);
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	default:
2720Sstevel@tonic-gate 		return (1);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate 
276*802Scf46844 void
277*802Scf46844 killed(void)
2780Sstevel@tonic-gate {
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	killcnt(addr2 - addr1 + 1);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate 
283*802Scf46844 void
284*802Scf46844 killcnt(int cnt)
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate 	extern char *verbalize();
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	if (inopen) {
2890Sstevel@tonic-gate 		notecnt = cnt;
2900Sstevel@tonic-gate 		notenam = notesgn = (unsigned char *)"";
2910Sstevel@tonic-gate 		return;
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 	if (!notable(cnt))
2940Sstevel@tonic-gate 		return;
2950Sstevel@tonic-gate 	if (value(vi_TERSE) == 0) {
2960Sstevel@tonic-gate 		verbalize(cnt, Command, "");
2970Sstevel@tonic-gate 	} else {
2980Sstevel@tonic-gate 		if (cnt == 1) {
299*802Scf46844 			viprintf(gettext("1 line"), cnt);
3000Sstevel@tonic-gate 		} else {
301*802Scf46844 			viprintf(gettext("%d lines"), cnt);
3020Sstevel@tonic-gate 		}
3030Sstevel@tonic-gate 	}
3040Sstevel@tonic-gate 	putNFL();
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate 
307*802Scf46844 int
308*802Scf46844 lineno(line *a)
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	return (a - zero);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
314*802Scf46844 int
315*802Scf46844 lineDOL(void)
3160Sstevel@tonic-gate {
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	return (lineno(dol));
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
321*802Scf46844 int
322*802Scf46844 lineDOT(void)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	return (lineno(dot));
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate 
328*802Scf46844 void
329*802Scf46844 markDOT(void)
3300Sstevel@tonic-gate {
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	markpr(dot);
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate 
335*802Scf46844 void
336*802Scf46844 markpr(line *which)
3370Sstevel@tonic-gate {
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	if ((inglobal == 0 || inopen) && which <= endcore) {
3400Sstevel@tonic-gate 		names['z'-'a'+1] = *which & ~01;
3410Sstevel@tonic-gate 		if (inopen)
3420Sstevel@tonic-gate 			ncols['z'-'a'+1] = cursor;
3430Sstevel@tonic-gate 	}
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate 
346*802Scf46844 int
347*802Scf46844 markreg(int c)
3480Sstevel@tonic-gate {
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	if (c == '\'' || c == '`')
3510Sstevel@tonic-gate 		return ('z' + 1);
3520Sstevel@tonic-gate 	if (c >= 'a' && c <= 'z')
3530Sstevel@tonic-gate 		return (c);
3540Sstevel@tonic-gate 	return (0);
3550Sstevel@tonic-gate }
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate /*
3580Sstevel@tonic-gate  * Mesg decodes the terse/verbose strings. Thus
3590Sstevel@tonic-gate  *	'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy'
3600Sstevel@tonic-gate  *	'xxx|yyy' -> 'xxx' if terse, else 'yyy'
3610Sstevel@tonic-gate  * All others map to themselves.
3620Sstevel@tonic-gate  */
3630Sstevel@tonic-gate /*
3640Sstevel@tonic-gate  * The feature described above was disabled for localizable messaging.
3650Sstevel@tonic-gate  */
3660Sstevel@tonic-gate unsigned char *
3670Sstevel@tonic-gate mesg(str)
368*802Scf46844 	unsigned char *str;
3690Sstevel@tonic-gate {
370*802Scf46844 	unsigned char *cp;
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	str = (unsigned char *)strcpy(genbuf, str);
3730Sstevel@tonic-gate 	/* commented out for localizable messaging */
3740Sstevel@tonic-gate /*	for (cp = str; *cp; cp++)
3750Sstevel@tonic-gate 		switch (*cp) {
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 		case '@':
3780Sstevel@tonic-gate 			if (value(vi_TERSE))
3790Sstevel@tonic-gate 				*cp = 0;
3800Sstevel@tonic-gate 			else
3810Sstevel@tonic-gate 				*cp = ' ';
3820Sstevel@tonic-gate 			break;
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 		case '|':
3850Sstevel@tonic-gate 			if (value(vi_TERSE) == 0)
3860Sstevel@tonic-gate 				return (cp + 1);
3870Sstevel@tonic-gate 			*cp = 0;
3880Sstevel@tonic-gate 			break;
3890Sstevel@tonic-gate 		}	*/
3900Sstevel@tonic-gate 	return (str);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate /*VARARGS2*/
394*802Scf46844 void
395*802Scf46844 merror(unsigned char *seekpt, int i)
3960Sstevel@tonic-gate {
397*802Scf46844 	unsigned char *cp = linebuf;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	if (seekpt == 0)
4000Sstevel@tonic-gate 		return;
4010Sstevel@tonic-gate 	merror1(seekpt);
4020Sstevel@tonic-gate 	if (*cp == '\n')
4030Sstevel@tonic-gate 		putnl(), cp++;
4040Sstevel@tonic-gate 	if (inopen > 0 && clr_eol)
4050Sstevel@tonic-gate 		vclreol();
4060Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
407*802Scf46844 		putpad((unsigned char *)enter_standout_mode);
4080Sstevel@tonic-gate #ifdef PRESUNEUC
409*802Scf46844 	viprintf(mesg(cp), i);
4100Sstevel@tonic-gate #else
411*802Scf46844 	viprintf((char *)mesg(cp), i);
4120Sstevel@tonic-gate #endif /* PRESUNEUC */
4130Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
414*802Scf46844 		putpad((unsigned char *)exit_bold);
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate 
417*802Scf46844 void
418*802Scf46844 merror1(unsigned char *seekpt)
4190Sstevel@tonic-gate {
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	strcpy(linebuf, seekpt);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate #define MAXDATA (56*1024)
425*802Scf46844 int
426*802Scf46844 morelines(void)
4270Sstevel@tonic-gate {
428*802Scf46844 	unsigned char *end;
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	if ((int) sbrk(1024 * sizeof (line)) == -1) {
4310Sstevel@tonic-gate 		if (endcore >= (line *) MAXDATA)
4320Sstevel@tonic-gate 			return -1;
4330Sstevel@tonic-gate 		end = (unsigned char *) MAXDATA;
4340Sstevel@tonic-gate 		/*
4350Sstevel@tonic-gate 		 * Ask for end+2 sice we want end to be the last used location.
4360Sstevel@tonic-gate 		 */
4370Sstevel@tonic-gate 		while (brk(end+2) == -1)
4380Sstevel@tonic-gate 			end -= 64;
4390Sstevel@tonic-gate 		if (end <= (unsigned char *) endcore)
4400Sstevel@tonic-gate 			return -1;
4410Sstevel@tonic-gate 		endcore = (line *) end;
4420Sstevel@tonic-gate 	} else {
4430Sstevel@tonic-gate 		endcore += 1024;
4440Sstevel@tonic-gate 	}
4450Sstevel@tonic-gate 	return (0);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate 
448*802Scf46844 void
449*802Scf46844 nonzero(void)
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	if (addr1 == zero) {
4530Sstevel@tonic-gate 		notempty();
4540Sstevel@tonic-gate 		error(value(vi_TERSE) ? gettext("Nonzero address required") :
4550Sstevel@tonic-gate gettext("Nonzero address required on this command"));
4560Sstevel@tonic-gate 	}
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate 
459*802Scf46844 int
460*802Scf46844 notable(int i)
4610Sstevel@tonic-gate {
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	return (hush == 0 && !inglobal && i > value(vi_REPORT));
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 
467*802Scf46844 void
468*802Scf46844 notempty(void)
4690Sstevel@tonic-gate {
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	if (dol == zero)
4720Sstevel@tonic-gate 		error(value(vi_TERSE) ? gettext("No lines") :
4730Sstevel@tonic-gate gettext("No lines in the buffer"));
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 
477*802Scf46844 void
478*802Scf46844 netchHAD(int cnt)
4790Sstevel@tonic-gate {
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	netchange(lineDOL() - cnt);
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate 
484*802Scf46844 void
485*802Scf46844 netchange(int i)
4860Sstevel@tonic-gate {
487*802Scf46844 	unsigned char *cp;
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	if (i > 0)
4900Sstevel@tonic-gate 		notesgn = cp = (unsigned char *)"more ";
4910Sstevel@tonic-gate 	else
4920Sstevel@tonic-gate 		notesgn = cp = (unsigned char *)"fewer ", i = -i;
4930Sstevel@tonic-gate 	if (inopen) {
4940Sstevel@tonic-gate 		notecnt = i;
4950Sstevel@tonic-gate 		notenam = (unsigned char *)"";
4960Sstevel@tonic-gate 		return;
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 	if (!notable(i))
4990Sstevel@tonic-gate 		return;
5000Sstevel@tonic-gate 	if (*cp == 'm')	/* for ease of messge localization */
5010Sstevel@tonic-gate #ifdef PRESUNEUC
502*802Scf46844 		viprintf(mesg(value(vi_TERSE) ?
5030Sstevel@tonic-gate #else
504*802Scf46844 		viprintf((char *)mesg(value(vi_TERSE) ?
5050Sstevel@tonic-gate #endif /* PRESUNEUC */
5060Sstevel@tonic-gate gettext("%d more lines") :
5070Sstevel@tonic-gate 		/*
5080Sstevel@tonic-gate 		 * TRANSLATION_NOTE
5090Sstevel@tonic-gate 		 *	Reference order of arguments must not
5100Sstevel@tonic-gate 		 *	be changed using '%digit$', since vi's
511*802Scf46844 		 *	viprintf() does not support it.
5120Sstevel@tonic-gate 		 */
5130Sstevel@tonic-gate gettext("%d more lines in file after %s")), i, Command);
5140Sstevel@tonic-gate 	else
5150Sstevel@tonic-gate #ifdef PRESUNEUC
516*802Scf46844 		viprintf(mesg(value(vi_TERSE) ?
5170Sstevel@tonic-gate #else
518*802Scf46844 		viprintf((char *)mesg(value(vi_TERSE) ?
5190Sstevel@tonic-gate #endif /* PRESUNEUC */
5200Sstevel@tonic-gate gettext("%d fewer lines") :
5210Sstevel@tonic-gate 		/*
5220Sstevel@tonic-gate 		 * TRANSLATION_NOTE
5230Sstevel@tonic-gate 		 *	Reference order of arguments must not
5240Sstevel@tonic-gate 		 *	be changed using '%digit$', since vi's
525*802Scf46844 		 *	viprintf() does not support it.
5260Sstevel@tonic-gate 		 */
5270Sstevel@tonic-gate gettext("%d fewer lines in file after %s")), i, Command);
5280Sstevel@tonic-gate 	putNFL();
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate 
531*802Scf46844 void
532*802Scf46844 putmark(line *addr)
5330Sstevel@tonic-gate {
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	putmk1(addr, putline());
5360Sstevel@tonic-gate }
5370Sstevel@tonic-gate 
538*802Scf46844 void
539*802Scf46844 putmk1(line *addr, int n)
5400Sstevel@tonic-gate {
541*802Scf46844 	line *markp;
542*802Scf46844 	int oldglobmk;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	oldglobmk = *addr & 1;
5450Sstevel@tonic-gate 	*addr &= ~1;
5460Sstevel@tonic-gate 	for (markp = (anymarks ? names : &names['z'-'a'+1]);
5470Sstevel@tonic-gate 	  markp <= &names['z'-'a'+1]; markp++)
5480Sstevel@tonic-gate 		if (*markp == *addr)
5490Sstevel@tonic-gate 			*markp = n;
5500Sstevel@tonic-gate 	*addr = n | oldglobmk;
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate unsigned char *
5540Sstevel@tonic-gate plural(i)
5550Sstevel@tonic-gate 	long i;
5560Sstevel@tonic-gate {
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	return (i == 1 ? (unsigned char *)"" : (unsigned char *)"s");
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate int	qcount();
5620Sstevel@tonic-gate short	vcntcol;
5630Sstevel@tonic-gate 
564*802Scf46844 int
565*802Scf46844 qcolumn(unsigned char *lim, unsigned char *gp)
5660Sstevel@tonic-gate {
567*802Scf46844 	int x, length;
5680Sstevel@tonic-gate 	int	col;
5690Sstevel@tonic-gate 	wchar_t wchar;
5700Sstevel@tonic-gate 	int (*OO)();
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	OO = Outchar;
5730Sstevel@tonic-gate 	Outchar = qcount;
5740Sstevel@tonic-gate 	vcntcol = 0;
5750Sstevel@tonic-gate 	if (lim != NULL) {
5760Sstevel@tonic-gate 		if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2])
5770Sstevel@tonic-gate 			length = 1;
5780Sstevel@tonic-gate 		else
5790Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX);
5800Sstevel@tonic-gate 		if(length < 0)
5810Sstevel@tonic-gate 			length = 1;
5820Sstevel@tonic-gate 		x = lim[length];
5830Sstevel@tonic-gate 		lim[length] = 0;
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate 	pline(0);
5860Sstevel@tonic-gate 	if (lim != NULL)
5870Sstevel@tonic-gate 		lim[length] = x;
5880Sstevel@tonic-gate 	if(length > 1 && !gp) {
5890Sstevel@tonic-gate 		/* put cursor at beginning of multibyte character */
5900Sstevel@tonic-gate 		if ((col = wcwidth(wchar)) < 0)
5910Sstevel@tonic-gate 			col = 0;
5920Sstevel@tonic-gate 		vcntcol = vcntcol - col + 1;
5930Sstevel@tonic-gate 	}
5940Sstevel@tonic-gate  	if (gp)
5950Sstevel@tonic-gate 		while (*gp) {
5960Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX);
5970Sstevel@tonic-gate 			if(length < 0) {
5980Sstevel@tonic-gate 				putoctal = 1;
5990Sstevel@tonic-gate 				putchar(*gp++);
6000Sstevel@tonic-gate 				putoctal = 0;
6010Sstevel@tonic-gate 			} else {
6020Sstevel@tonic-gate 				putchar(wchar);
6030Sstevel@tonic-gate 				gp += length;
6040Sstevel@tonic-gate 			}
6050Sstevel@tonic-gate 		}
6060Sstevel@tonic-gate 	Outchar = OO;
6070Sstevel@tonic-gate 	return (vcntcol);
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate /* This routine puts cursor after multibyte character */
611*802Scf46844 int
612*802Scf46844 nqcolumn(unsigned char *lim, unsigned char *gp)
6130Sstevel@tonic-gate {
614*802Scf46844 	int x, length;
6150Sstevel@tonic-gate 	wchar_t wchar;
6160Sstevel@tonic-gate 	int (*OO)();
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	OO = Outchar;
6190Sstevel@tonic-gate 	Outchar = qcount;
6200Sstevel@tonic-gate 	vcntcol = 0;
6210Sstevel@tonic-gate 	if (lim != NULL) {
6220Sstevel@tonic-gate 		if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2])
6230Sstevel@tonic-gate 			length = 1;
6240Sstevel@tonic-gate 		else
6250Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX);
6260Sstevel@tonic-gate 		if(length < 0)
6270Sstevel@tonic-gate 			length = 1;
6280Sstevel@tonic-gate 		x = lim[length];
6290Sstevel@tonic-gate 		lim[length] = 0;
6300Sstevel@tonic-gate 	}
6310Sstevel@tonic-gate 	pline(0);
6320Sstevel@tonic-gate 	if (lim != NULL)
6330Sstevel@tonic-gate 		lim[length] = x;
6340Sstevel@tonic-gate  	if (gp)
6350Sstevel@tonic-gate 		while (*gp) {
6360Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX);
6370Sstevel@tonic-gate 			if(length < 0) {
6380Sstevel@tonic-gate 				putoctal = 1;
6390Sstevel@tonic-gate 				putchar(*gp++);
6400Sstevel@tonic-gate 				putoctal = 0;
6410Sstevel@tonic-gate 			} else {
6420Sstevel@tonic-gate 				putchar(wchar);
6430Sstevel@tonic-gate 				gp += length;
6440Sstevel@tonic-gate 			}
6450Sstevel@tonic-gate 		}
6460Sstevel@tonic-gate 	Outchar = OO;
6470Sstevel@tonic-gate 	return (vcntcol);
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate int
6510Sstevel@tonic-gate qcount(c)
6520Sstevel@tonic-gate wchar_t c;
6530Sstevel@tonic-gate {
654*802Scf46844 	int cols;
6550Sstevel@tonic-gate #ifndef PRESUNEUC
656*802Scf46844 	int remcols;
657*802Scf46844 	short OWCOLS;
6580Sstevel@tonic-gate #endif /* PRESUNEUC */
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	if (c == '\t') {
6610Sstevel@tonic-gate 		vcntcol += value(vi_TABSTOP) - vcntcol % value(vi_TABSTOP);
662*802Scf46844 		return (0);
6630Sstevel@tonic-gate 	}
6640Sstevel@tonic-gate #ifdef PRESUNEUC
6650Sstevel@tonic-gate 	if ((cols = wcwidth(c)) > 0)
6660Sstevel@tonic-gate 		vcntcol += cols;
6670Sstevel@tonic-gate #else
6680Sstevel@tonic-gate 	if ((cols = wcwidth(c)) < 0)
6690Sstevel@tonic-gate 		cols = 0;
6700Sstevel@tonic-gate 	OWCOLS = WCOLS;
6710Sstevel@tonic-gate 	if (WCOLS == 0)
6720Sstevel@tonic-gate 		WCOLS = columns;
6730Sstevel@tonic-gate 	if ((mc_wrap) == 1 && (remcols = (WCOLS - (vcntcol % WCOLS))) < cols)
6740Sstevel@tonic-gate 		vcntcol += remcols;
6750Sstevel@tonic-gate 	WCOLS = OWCOLS;
6760Sstevel@tonic-gate 	vcntcol += cols;
6770Sstevel@tonic-gate #endif /* PRESUNEUC */
678*802Scf46844 	return (0);
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate 
681*802Scf46844 void
682*802Scf46844 reverse(line *a1, line *a2)
6830Sstevel@tonic-gate {
684*802Scf46844 	line t;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	for (;;) {
6870Sstevel@tonic-gate 		t = *--a2;
6880Sstevel@tonic-gate 		if (a2 <= a1)
6890Sstevel@tonic-gate 			return;
6900Sstevel@tonic-gate 		*a2 = *a1;
6910Sstevel@tonic-gate 		*a1++ = t;
6920Sstevel@tonic-gate 	}
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate 
695*802Scf46844 void
696*802Scf46844 save(line *a1, line *a2)
6970Sstevel@tonic-gate {
698*802Scf46844 	int more;
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 	if (!FIXUNDO)
7010Sstevel@tonic-gate 		return;
7020Sstevel@tonic-gate #ifdef UNDOTRACE
7030Sstevel@tonic-gate 	if (trace)
7040Sstevel@tonic-gate 		vudump("before save");
7050Sstevel@tonic-gate #endif
7060Sstevel@tonic-gate 	undkind = UNDNONE;
7070Sstevel@tonic-gate 	undadot = dot;
7080Sstevel@tonic-gate 	more = (a2 - a1 + 1) - (unddol - dol);
7090Sstevel@tonic-gate 	while (more > (endcore - truedol))
7100Sstevel@tonic-gate 		if (morelines() < 0)
7110Sstevel@tonic-gate 			error(value(vi_TERSE) ? gettext("Out of memory") :
7120Sstevel@tonic-gate gettext("Out of memory saving lines for undo - try using ed"));
7130Sstevel@tonic-gate 	if (more)
7140Sstevel@tonic-gate 		(*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
7150Sstevel@tonic-gate 		    (truedol - unddol));
7160Sstevel@tonic-gate 	unddol += more;
7170Sstevel@tonic-gate 	truedol += more;
7180Sstevel@tonic-gate 	copyw(dol + 1, a1, a2 - a1 + 1);
7190Sstevel@tonic-gate 	undkind = UNDALL;
7200Sstevel@tonic-gate 	unddel = a1 - 1;
7210Sstevel@tonic-gate 	undap1 = a1;
7220Sstevel@tonic-gate 	undap2 = a2 + 1;
7230Sstevel@tonic-gate #ifdef UNDOTRACE
7240Sstevel@tonic-gate 	if (trace)
7250Sstevel@tonic-gate 		vudump("after save");
7260Sstevel@tonic-gate #endif
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate 
729*802Scf46844 void
730*802Scf46844 save12(void)
7310Sstevel@tonic-gate {
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate 	save(addr1, addr2);
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate 
736*802Scf46844 void
737*802Scf46844 saveall(void)
7380Sstevel@tonic-gate {
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	save(one, dol);
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate 
743*802Scf46844 int
744*802Scf46844 span(void)
7450Sstevel@tonic-gate {
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 	return (addr2 - addr1 + 1);
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate 
750*802Scf46844 void
751*802Scf46844 sync(void)
7520Sstevel@tonic-gate {
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	chng = 0;
7550Sstevel@tonic-gate 	tchng = 0;
7560Sstevel@tonic-gate 	xchng = 0;
7570Sstevel@tonic-gate }
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 
760*802Scf46844 int
761*802Scf46844 skipwh(void)
7620Sstevel@tonic-gate {
763*802Scf46844 	int wh;
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	wh = 0;
7660Sstevel@tonic-gate 	while (iswhite(peekchar())) {
7670Sstevel@tonic-gate 		wh++;
7680Sstevel@tonic-gate 		ignchar();
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 	return (wh);
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate /*VARARGS2*/
774*802Scf46844 void
775*802Scf46844 smerror(unsigned char *seekpt, unsigned char *cp)
7760Sstevel@tonic-gate {
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	errcnt++;
7790Sstevel@tonic-gate 	merror1(seekpt);
7800Sstevel@tonic-gate 	if (inopen && clr_eol)
7810Sstevel@tonic-gate 		vclreol();
7820Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
783*802Scf46844 		putpad((unsigned char *)enter_standout_mode);
7840Sstevel@tonic-gate 	lprintf(mesg(linebuf), cp);
7850Sstevel@tonic-gate 	if (enter_standout_mode && exit_bold)
786*802Scf46844 		putpad((unsigned char *)exit_bold);
7870Sstevel@tonic-gate }
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate unsigned char *
7900Sstevel@tonic-gate strend(cp)
791*802Scf46844 	unsigned char *cp;
7920Sstevel@tonic-gate {
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate 	while (*cp)
7950Sstevel@tonic-gate 		cp++;
7960Sstevel@tonic-gate 	return (cp);
7970Sstevel@tonic-gate }
7980Sstevel@tonic-gate 
799*802Scf46844 void
800*802Scf46844 strcLIN(unsigned char *dp)
8010Sstevel@tonic-gate {
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	CP(linebuf, dp);
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate /*
8070Sstevel@tonic-gate  * A system error has occurred that we need to perror.
8080Sstevel@tonic-gate  * danger is true if we are unsure of the contents of
8090Sstevel@tonic-gate  * the file or our buffer, e.g. a write error in the
8100Sstevel@tonic-gate  * middle of a write operation, or a temp file error.
8110Sstevel@tonic-gate  */
812*802Scf46844 void
813*802Scf46844 syserror(int danger)
8140Sstevel@tonic-gate {
815*802Scf46844 	int e = errno;
8160Sstevel@tonic-gate 	char *errstr;
8170Sstevel@tonic-gate 	extern char *strerror();
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 	dirtcnt = 0;
8200Sstevel@tonic-gate 	putchar(' ');
8210Sstevel@tonic-gate 	if (danger)
8220Sstevel@tonic-gate 		edited = 0;	/* for temp file errors, for example */
8230Sstevel@tonic-gate 	if ((errstr = strerror(e)) != NULL)
8240Sstevel@tonic-gate 		error(errstr);
8250Sstevel@tonic-gate 	else
8260Sstevel@tonic-gate 		error(gettext("System error %d"), e);
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate /*
8300Sstevel@tonic-gate  * Return the column number that results from being in column col and
8310Sstevel@tonic-gate  * hitting a tab, where tabs are set every ts columns.  Work right for
8320Sstevel@tonic-gate  * the case where col > columns, even if ts does not divide columns.
8330Sstevel@tonic-gate  */
834*802Scf46844 int
835*802Scf46844 tabcol(int col, int ts)
8360Sstevel@tonic-gate {
8370Sstevel@tonic-gate 	int offset, result;
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	if (col >= columns) {
8400Sstevel@tonic-gate 		offset = columns * (col/columns);
8410Sstevel@tonic-gate 		col -= offset;
8420Sstevel@tonic-gate 	} else
8430Sstevel@tonic-gate 		offset = 0;
8440Sstevel@tonic-gate 	result = col + ts - (col % ts) + offset;
8450Sstevel@tonic-gate 	return (result);
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate unsigned char *
8490Sstevel@tonic-gate vfindcol(i)
8500Sstevel@tonic-gate 	int i;
8510Sstevel@tonic-gate {
852*802Scf46844 	unsigned char *cp, *oldcp;
853*802Scf46844 	int (*OO)() = Outchar;
854*802Scf46844 	int length;
8550Sstevel@tonic-gate 	unsigned char x;
8560Sstevel@tonic-gate 	wchar_t wchar;
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 	Outchar = qcount;
859*802Scf46844 	(void) qcolumn(linebuf - 1, (unsigned char *)NOSTR);
8600Sstevel@tonic-gate 	for (cp = linebuf; *cp && vcntcol < i; ) {
8610Sstevel@tonic-gate 		oldcp = cp;
8620Sstevel@tonic-gate 		length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX);
8630Sstevel@tonic-gate 		if(length < 0) {
8640Sstevel@tonic-gate 			putoctal = 1;
8650Sstevel@tonic-gate 			putchar(*cp++);
8660Sstevel@tonic-gate 			putoctal = 0;
8670Sstevel@tonic-gate 		} else {
8680Sstevel@tonic-gate 			putchar(wchar);
8690Sstevel@tonic-gate 			cp += length;
8700Sstevel@tonic-gate 		}
8710Sstevel@tonic-gate 	}
8720Sstevel@tonic-gate 	if (cp != linebuf)
8730Sstevel@tonic-gate 		cp = oldcp;
8740Sstevel@tonic-gate 	Outchar = OO;
8750Sstevel@tonic-gate 	return (cp);
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate unsigned char *
8790Sstevel@tonic-gate vskipwh(cp)
880*802Scf46844 	unsigned char *cp;
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate 
8830Sstevel@tonic-gate 	while (iswhite(*cp) && cp[1])
8840Sstevel@tonic-gate 		cp++;
8850Sstevel@tonic-gate 	return (cp);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate unsigned char *
8900Sstevel@tonic-gate vpastwh(cp)
891*802Scf46844 	unsigned char *cp;
8920Sstevel@tonic-gate {
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 	while (iswhite(*cp))
8950Sstevel@tonic-gate 		cp++;
8960Sstevel@tonic-gate 	return (cp);
8970Sstevel@tonic-gate }
8980Sstevel@tonic-gate 
899*802Scf46844 int
900*802Scf46844 whitecnt(unsigned char *cp)
9010Sstevel@tonic-gate {
902*802Scf46844 	int i;
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	i = 0;
9050Sstevel@tonic-gate 	for (;;)
9060Sstevel@tonic-gate 		switch (*cp++) {
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 		case '\t':
9090Sstevel@tonic-gate 			i += value(vi_TABSTOP) - i % value(vi_TABSTOP);
9100Sstevel@tonic-gate 			break;
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 		case ' ':
9130Sstevel@tonic-gate 			i++;
9140Sstevel@tonic-gate 			break;
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 		default:
9170Sstevel@tonic-gate 			return (i);
9180Sstevel@tonic-gate 		}
9190Sstevel@tonic-gate }
9200Sstevel@tonic-gate 
921*802Scf46844 void
922*802Scf46844 markit(line *addr)
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	if (addr != dot && addr >= one && addr <= dol)
9260Sstevel@tonic-gate 		markDOT();
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate /*
9300Sstevel@tonic-gate  * The following code is defensive programming against a bug in the
9310Sstevel@tonic-gate  * pdp-11 overlay implementation.  Sometimes it goes nuts and asks
9320Sstevel@tonic-gate  * for an overlay with some garbage number, which generates an emt
9330Sstevel@tonic-gate  * trap.  This is a less than elegant solution, but it is somewhat
9340Sstevel@tonic-gate  * better than core dumping and losing your work, leaving your tty
9350Sstevel@tonic-gate  * in a weird state, etc.
9360Sstevel@tonic-gate  */
9370Sstevel@tonic-gate int _ovno;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate /*ARGSUSED*/
9400Sstevel@tonic-gate void
9410Sstevel@tonic-gate onemt(sig)
9420Sstevel@tonic-gate int sig;
9430Sstevel@tonic-gate {
9440Sstevel@tonic-gate 	int oovno;
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	signal(SIGEMT, onemt);
9470Sstevel@tonic-gate 	oovno = _ovno;
9480Sstevel@tonic-gate 	/* 2 and 3 are valid on 11/40 type vi, so */
9490Sstevel@tonic-gate 	if (_ovno < 0 || _ovno > 3)
9500Sstevel@tonic-gate 		_ovno = 0;
9510Sstevel@tonic-gate 	error(value(vi_TERSE) ? gettext("emt trap, _ovno is %d ") :
9520Sstevel@tonic-gate gettext("emt trap, _ovno is %d   - try again"));
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate /*
9560Sstevel@tonic-gate  * When a hangup occurs our actions are similar to a preserve
9570Sstevel@tonic-gate  * command.  If the buffer has not been [Modified], then we do
9580Sstevel@tonic-gate  * nothing but remove the temporary files and exit.
9590Sstevel@tonic-gate  * Otherwise, we sync the temp file and then attempt a preserve.
9600Sstevel@tonic-gate  * If the preserve succeeds, we unlink our temp files.
9610Sstevel@tonic-gate  * If the preserve fails, we leave the temp files as they are
9620Sstevel@tonic-gate  * as they are a backup even without preservation if they
9630Sstevel@tonic-gate  * are not removed.
9640Sstevel@tonic-gate  */
9650Sstevel@tonic-gate 
9660Sstevel@tonic-gate /*ARGSUSED*/
9670Sstevel@tonic-gate void
9680Sstevel@tonic-gate onhup(sig)
9690Sstevel@tonic-gate int sig;
9700Sstevel@tonic-gate {
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	/*
9730Sstevel@tonic-gate 	 * USG tty driver can send multiple HUP's!!
9740Sstevel@tonic-gate 	 */
9750Sstevel@tonic-gate 	signal(SIGINT, SIG_IGN);
9760Sstevel@tonic-gate 	signal(SIGHUP, SIG_IGN);
9770Sstevel@tonic-gate 	if (chng == 0) {
9780Sstevel@tonic-gate 		cleanup(1);
9790Sstevel@tonic-gate 		exit(++errcnt);
9800Sstevel@tonic-gate 	}
9810Sstevel@tonic-gate 	if (setexit() == 0) {
9820Sstevel@tonic-gate 		if (preserve()) {
9830Sstevel@tonic-gate 			cleanup(1);
9840Sstevel@tonic-gate 			exit(++errcnt);
9850Sstevel@tonic-gate 		}
9860Sstevel@tonic-gate 	}
9870Sstevel@tonic-gate 	if (kflag)
9880Sstevel@tonic-gate 		crypt_close(perm);
9890Sstevel@tonic-gate 	if (xtflag)
9900Sstevel@tonic-gate 		crypt_close(tperm);
9910Sstevel@tonic-gate 	exit(++errcnt);
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate /*
9950Sstevel@tonic-gate  * Similar to onhup.  This happens when any random core dump occurs,
9960Sstevel@tonic-gate  * e.g. a bug in vi.  We preserve the file and then generate a core.
9970Sstevel@tonic-gate  */
9980Sstevel@tonic-gate void oncore(sig)
9990Sstevel@tonic-gate int sig;
10000Sstevel@tonic-gate {
10010Sstevel@tonic-gate 	static int timescalled = 0;
10020Sstevel@tonic-gate 	char *messagep;	/* for message localization */
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 	/*
10050Sstevel@tonic-gate 	 * USG tty driver can send multiple HUP's!!
10060Sstevel@tonic-gate 	 */
10070Sstevel@tonic-gate 	signal(SIGINT, SIG_IGN);
10080Sstevel@tonic-gate 	signal(SIGHUP, SIG_IGN);
10090Sstevel@tonic-gate 	signal(sig, SIG_DFL);	/* Insure that we don't catch it again */
10100Sstevel@tonic-gate 	messagep = (char *)gettext("\r\nYour file has been preserved\r\n");
10110Sstevel@tonic-gate 	if (timescalled++ == 0 && chng && setexit() == 0) {
10120Sstevel@tonic-gate 		if (inopen)
10130Sstevel@tonic-gate 			vsave();
1014*802Scf46844 		(void) preserve();
10150Sstevel@tonic-gate 		write(1, messagep, strlen(messagep));
10160Sstevel@tonic-gate 	}
10170Sstevel@tonic-gate 	if (timescalled < 2) {
10180Sstevel@tonic-gate 		normal(normf);
10190Sstevel@tonic-gate 		cleanup(2);
10200Sstevel@tonic-gate 		kill(getpid(), sig);	/* Resend ourselves the same signal */
10210Sstevel@tonic-gate 		/* We won't get past here */
10220Sstevel@tonic-gate 	}
10230Sstevel@tonic-gate 	if (kflag)
10240Sstevel@tonic-gate 		crypt_close(perm);
10250Sstevel@tonic-gate 	if (xtflag)
10260Sstevel@tonic-gate 		crypt_close(tperm);
10270Sstevel@tonic-gate 	exit(++errcnt);
10280Sstevel@tonic-gate }
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate /*
10310Sstevel@tonic-gate  * An interrupt occurred.  Drain any output which
10320Sstevel@tonic-gate  * is still in the output buffering pipeline.
10330Sstevel@tonic-gate  * Catch interrupts again.  Unless we are in visual
10340Sstevel@tonic-gate  * reset the output state (out of -nl mode, e.g).
10350Sstevel@tonic-gate  * Then like a normal error (with the \n before Interrupt
10360Sstevel@tonic-gate  * suppressed in visual mode).
10370Sstevel@tonic-gate  */
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate /*ARGSUSED*/
10400Sstevel@tonic-gate void
10410Sstevel@tonic-gate onintr(sig)
10420Sstevel@tonic-gate int sig;
10430Sstevel@tonic-gate {
10440Sstevel@tonic-gate #ifndef CBREAK
10450Sstevel@tonic-gate 	signal(SIGINT, onintr);
10460Sstevel@tonic-gate #else
10470Sstevel@tonic-gate 	signal(SIGINT, inopen ? vintr : onintr);
10480Sstevel@tonic-gate #endif
10490Sstevel@tonic-gate 	cancelalarm();
10500Sstevel@tonic-gate 	draino();
10510Sstevel@tonic-gate 	if (!inopen) {
10520Sstevel@tonic-gate 		pstop();
10530Sstevel@tonic-gate 		setlastchar('\n');
10540Sstevel@tonic-gate #ifdef CBREAK
10550Sstevel@tonic-gate 	}
10560Sstevel@tonic-gate #else
10570Sstevel@tonic-gate 	} else
10580Sstevel@tonic-gate 		vraw();
10590Sstevel@tonic-gate #endif
10600Sstevel@tonic-gate 	error(gettext("\nInterrupt") + (inopen!=0));
10610Sstevel@tonic-gate }
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate /*
10640Sstevel@tonic-gate  * If we are interruptible, enable interrupts again.
10650Sstevel@tonic-gate  * In some critical sections we turn interrupts off,
10660Sstevel@tonic-gate  * but not very often.
10670Sstevel@tonic-gate  */
1068*802Scf46844 void
1069*802Scf46844 setrupt(void)
10700Sstevel@tonic-gate {
10710Sstevel@tonic-gate 
10720Sstevel@tonic-gate 	if (ruptible) {
10730Sstevel@tonic-gate #ifndef CBREAK
10740Sstevel@tonic-gate 		signal(SIGINT, onintr);
10750Sstevel@tonic-gate #else
10760Sstevel@tonic-gate 		signal(SIGINT, inopen ? vintr : onintr);
10770Sstevel@tonic-gate #endif
10780Sstevel@tonic-gate #ifdef SIGTSTP
10790Sstevel@tonic-gate 		if (dosusp)
10800Sstevel@tonic-gate 			signal(SIGTSTP, onsusp);
10810Sstevel@tonic-gate #endif
10820Sstevel@tonic-gate 	}
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate 
1085*802Scf46844 int
1086*802Scf46844 preserve(void)
10870Sstevel@tonic-gate {
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate #ifdef VMUNIX
10900Sstevel@tonic-gate 	tflush();
10910Sstevel@tonic-gate #endif
10920Sstevel@tonic-gate 	synctmp();
10930Sstevel@tonic-gate 	pid = fork();
10940Sstevel@tonic-gate 	if (pid < 0)
10950Sstevel@tonic-gate 		return (0);
10960Sstevel@tonic-gate 	if (pid == 0) {
10970Sstevel@tonic-gate 		close(0);
10980Sstevel@tonic-gate 		dup(tfile);
10990Sstevel@tonic-gate 		execlp(EXPRESERVE, "expreserve", (char *) 0);
11000Sstevel@tonic-gate 		exit(++errcnt);
11010Sstevel@tonic-gate 	}
11020Sstevel@tonic-gate 	waitfor();
11030Sstevel@tonic-gate 	if (rpid == pid && status == 0)
11040Sstevel@tonic-gate 		return (1);
11050Sstevel@tonic-gate 	return (0);
11060Sstevel@tonic-gate }
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate #ifndef V6
11090Sstevel@tonic-gate void exit(i)
11100Sstevel@tonic-gate 	int i;
11110Sstevel@tonic-gate {
11120Sstevel@tonic-gate 
1113*802Scf46844 	extern void _exit(int) __NORETURN;
11140Sstevel@tonic-gate #ifdef TRACE
11150Sstevel@tonic-gate 	if (trace)
11160Sstevel@tonic-gate 		fclose(trace);
11170Sstevel@tonic-gate #endif
11180Sstevel@tonic-gate 	_exit(i);
11190Sstevel@tonic-gate }
11200Sstevel@tonic-gate #endif
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate #ifdef SIGTSTP
11230Sstevel@tonic-gate /*
11240Sstevel@tonic-gate  * We have just gotten a susp.  Suspend and prepare to resume.
11250Sstevel@tonic-gate  */
11260Sstevel@tonic-gate extern void redraw();
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate /*ARGSUSED*/
11290Sstevel@tonic-gate void
11300Sstevel@tonic-gate onsusp(sig)
11310Sstevel@tonic-gate int sig;
11320Sstevel@tonic-gate {
11330Sstevel@tonic-gate 	ttymode f;
11340Sstevel@tonic-gate 	int savenormtty;
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate 	f = setty(normf);
11370Sstevel@tonic-gate 	vnfl();
1138*802Scf46844 	putpad((unsigned char *)exit_ca_mode);
11390Sstevel@tonic-gate 	flush();
11400Sstevel@tonic-gate 	resetterm();
11410Sstevel@tonic-gate 	savenormtty = normtty;
11420Sstevel@tonic-gate 	normtty = 0;
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate 	signal(SIGTSTP, SIG_DFL);
11450Sstevel@tonic-gate 	kill(0, SIGTSTP);
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	/* the pc stops here */
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 	signal(SIGTSTP, onsusp);
11500Sstevel@tonic-gate 	normtty = savenormtty;
11510Sstevel@tonic-gate 	vcontin(0);
11520Sstevel@tonic-gate 	flush();
11530Sstevel@tonic-gate 	setty(f);
11540Sstevel@tonic-gate 	if (!inopen)
11550Sstevel@tonic-gate 		error(0);
11560Sstevel@tonic-gate 	else {
11570Sstevel@tonic-gate 		if(vcnt < 0) {
11580Sstevel@tonic-gate 			vcnt = -vcnt;
11590Sstevel@tonic-gate 			if(state == VISUAL)
11600Sstevel@tonic-gate 				vclear();
11610Sstevel@tonic-gate 			else if(state == CRTOPEN)
11620Sstevel@tonic-gate 				vcnt = 0;
11630Sstevel@tonic-gate 		}
11640Sstevel@tonic-gate 		vdirty(0, lines);
11650Sstevel@tonic-gate 		if (sig)
11660Sstevel@tonic-gate 			vrepaint(cursor);
11670Sstevel@tonic-gate 	}
11680Sstevel@tonic-gate }
11690Sstevel@tonic-gate #endif
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate unsigned char *nextchr(cursor)
11720Sstevel@tonic-gate unsigned char *cursor;
11730Sstevel@tonic-gate {
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 	wchar_t wchar;
11760Sstevel@tonic-gate 	int length;
11770Sstevel@tonic-gate 	length = mbtowc(&wchar, (char *)cursor, MULTI_BYTE_MAX);
11780Sstevel@tonic-gate 	if(length <= 0)
11790Sstevel@tonic-gate 		return(++cursor);
11800Sstevel@tonic-gate 	return(cursor + length);
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate unsigned char *lastchr(linebuf, cursor)
11840Sstevel@tonic-gate unsigned char *linebuf, *cursor;
11850Sstevel@tonic-gate {
11860Sstevel@tonic-gate 	wchar_t wchar;
11870Sstevel@tonic-gate 	int length;
11880Sstevel@tonic-gate 	unsigned char *ccursor, *ocursor;
11890Sstevel@tonic-gate 	if(cursor == linebuf)
11900Sstevel@tonic-gate 		return(linebuf - 1);
11910Sstevel@tonic-gate 	ccursor = ocursor = linebuf;
11920Sstevel@tonic-gate 	while(ccursor < cursor) {
11930Sstevel@tonic-gate 		length = mbtowc(&wchar, (char *)ccursor, MULTI_BYTE_MAX);
11940Sstevel@tonic-gate 		ocursor =  ccursor;
11950Sstevel@tonic-gate 		if(length <= 0)
11960Sstevel@tonic-gate 			ccursor++;
11970Sstevel@tonic-gate 		else
11980Sstevel@tonic-gate 			ccursor += length;
11990Sstevel@tonic-gate 	}
12000Sstevel@tonic-gate 	return(ocursor);
12010Sstevel@tonic-gate }
12020Sstevel@tonic-gate 
1203*802Scf46844 int
1204*802Scf46844 ixlatctl(int flag)
12050Sstevel@tonic-gate {
12060Sstevel@tonic-gate 	static struct strioctl sb = {0, 0, 0, 0};
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate 	if (!(MULTI_BYTE_MAX > 1))
12090Sstevel@tonic-gate 		return (0);
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 	switch (flag) {
12120Sstevel@tonic-gate 	case 0:
12130Sstevel@tonic-gate 		sb.ic_cmd = EUC_MSAVE;
12140Sstevel@tonic-gate 		sb.ic_len = 0;
12150Sstevel@tonic-gate 		sb.ic_dp = 0;
12160Sstevel@tonic-gate 		if (ioctl(0, I_STR, &sb) < 0)
12170Sstevel@tonic-gate 			return (-1);
12180Sstevel@tonic-gate 		return (0);
12190Sstevel@tonic-gate 	case 1:
12200Sstevel@tonic-gate 		sb.ic_cmd = EUC_MREST;
12210Sstevel@tonic-gate 		sb.ic_len = 0;
12220Sstevel@tonic-gate 		sb.ic_dp = 0;
12230Sstevel@tonic-gate 		if (ioctl(0, I_STR, &sb) < 0)
12240Sstevel@tonic-gate 			return (-1);
12250Sstevel@tonic-gate 		return (0);
12260Sstevel@tonic-gate 	case 11:
12270Sstevel@tonic-gate 		return (0);
12280Sstevel@tonic-gate 	default:
12290Sstevel@tonic-gate 		return (-1);
12300Sstevel@tonic-gate 	}
12310Sstevel@tonic-gate }
12320Sstevel@tonic-gate #ifndef PRESUNEUC
12330Sstevel@tonic-gate 
12340Sstevel@tonic-gate /* locale specific initialization */
1235*802Scf46844 void
1236*802Scf46844 localize(void)
12370Sstevel@tonic-gate {
12380Sstevel@tonic-gate 	wchar_t fillerchar;
12390Sstevel@tonic-gate 	extern int	wdchkind();
12400Sstevel@tonic-gate 	extern int	wdbindf();
12410Sstevel@tonic-gate 	extern wchar_t	*wddelim();
12420Sstevel@tonic-gate 	extern wchar_t	mcfiller();
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate 	wdwc = wdchkind;
12450Sstevel@tonic-gate 	wdbdg = wdbindf;
12460Sstevel@tonic-gate 	wddlm = wddelim;
12470Sstevel@tonic-gate 	mcfllr = mcfiller;
12480Sstevel@tonic-gate 	mc_wrap = 1;
12490Sstevel@tonic-gate 	fillerchar = mcfiller();
12500Sstevel@tonic-gate 	mc_filler = isascii(fillerchar) ? (fillerchar & 0x7f) : '~';
12510Sstevel@tonic-gate }
12520Sstevel@tonic-gate #endif /* PRESUNEUC */
1253