xref: /onnv-gate/usr/src/cmd/vi/port/ex_vops3.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 "ex.h"
360Sstevel@tonic-gate #include "ex_tty.h"
370Sstevel@tonic-gate #include "ex_vis.h"
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate  * Routines to handle structure.
410Sstevel@tonic-gate  * Operations supported are:
420Sstevel@tonic-gate  *	( ) { } [ ]
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  * These cover:		LISP		TEXT
450Sstevel@tonic-gate  *	( )		s-exprs		sentences
460Sstevel@tonic-gate  *	{ }		list at same	paragraphs
470Sstevel@tonic-gate  *	[ ]		defuns		sections
480Sstevel@tonic-gate  *
490Sstevel@tonic-gate  * { and } for C used to attempt to do something with matching {}'s, but
500Sstevel@tonic-gate  * I couldn't find definitions which worked intuitively very well, so I
510Sstevel@tonic-gate  * scrapped this.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The code here is very hard to understand.
540Sstevel@tonic-gate  */
550Sstevel@tonic-gate line	*llimit;
560Sstevel@tonic-gate int	(*lf)();
570Sstevel@tonic-gate 
580Sstevel@tonic-gate int	lindent();
590Sstevel@tonic-gate 
600Sstevel@tonic-gate bool	wasend;
610Sstevel@tonic-gate 
62*802Scf46844 int endsent(bool);
63*802Scf46844 
640Sstevel@tonic-gate /*
650Sstevel@tonic-gate  * Find over structure, repeated count times.
660Sstevel@tonic-gate  * Don't go past line limit.  F is the operation to
670Sstevel@tonic-gate  * be performed eventually.  If pastatom then the user said {}
680Sstevel@tonic-gate  * rather than (), implying past atoms in a list (or a paragraph
690Sstevel@tonic-gate  * rather than a sentence.
700Sstevel@tonic-gate  */
71*802Scf46844 int
720Sstevel@tonic-gate lfind(pastatom, cnt, f, limit)
730Sstevel@tonic-gate 	bool pastatom;
740Sstevel@tonic-gate 	int cnt, (*f)();
750Sstevel@tonic-gate 	line *limit;
760Sstevel@tonic-gate {
77*802Scf46844 	int c;
78*802Scf46844 	int rc = 0;
790Sstevel@tonic-gate 	unsigned char save[LBSIZE];
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	/*
820Sstevel@tonic-gate 	 * Initialize, saving the current line buffer state
830Sstevel@tonic-gate 	 * and computing the limit; a 0 argument means
840Sstevel@tonic-gate 	 * directional end of file.
850Sstevel@tonic-gate 	 */
860Sstevel@tonic-gate 	wasend = 0;
870Sstevel@tonic-gate 	lf = f;
880Sstevel@tonic-gate 	strcpy(save, linebuf);
890Sstevel@tonic-gate 	if (limit == 0)
900Sstevel@tonic-gate 		limit = dir < 0 ? one : dol;
910Sstevel@tonic-gate 	llimit = limit;
920Sstevel@tonic-gate 	wdot = dot;
930Sstevel@tonic-gate 	wcursor = cursor;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	if (pastatom >= 2) {
960Sstevel@tonic-gate 
970Sstevel@tonic-gate  		if (pastatom == 3) {
980Sstevel@tonic-gate 			while(eend(f) && cnt-- > 0) {
990Sstevel@tonic-gate 				;
1000Sstevel@tonic-gate 			}
1010Sstevel@tonic-gate 		} else {
1020Sstevel@tonic-gate 			while (cnt > 0 && word(f, cnt))
1030Sstevel@tonic-gate 				cnt--;
1040Sstevel@tonic-gate 		}
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 		if (dot == wdot) {
1070Sstevel@tonic-gate 			wdot = 0;
1080Sstevel@tonic-gate 			if (cursor == wcursor)
1090Sstevel@tonic-gate 				rc = -1;
1100Sstevel@tonic-gate 		}
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 	else if (!value(vi_LISP)) {
1130Sstevel@tonic-gate 		unsigned char *icurs;
1140Sstevel@tonic-gate 		line *idot;
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 		if (linebuf[0] == 0) {
1170Sstevel@tonic-gate 			do
1180Sstevel@tonic-gate 				if (!lnext())
1190Sstevel@tonic-gate 					goto ret;
1200Sstevel@tonic-gate 			while (linebuf[0] == 0);
1210Sstevel@tonic-gate 			if (dir > 0) {
1220Sstevel@tonic-gate 				wdot--;
1230Sstevel@tonic-gate 				linebuf[0] = 0;
1240Sstevel@tonic-gate 				wcursor = linebuf;
1250Sstevel@tonic-gate 				/*
1260Sstevel@tonic-gate 				 * If looking for sentence, next line
1270Sstevel@tonic-gate 				 * starts one.
1280Sstevel@tonic-gate 				 */
1290Sstevel@tonic-gate 				if (!pastatom) {
1300Sstevel@tonic-gate 					icurs = wcursor;
1310Sstevel@tonic-gate 					idot = wdot;
1320Sstevel@tonic-gate 					goto begin;
1330Sstevel@tonic-gate 				}
1340Sstevel@tonic-gate 			}
1350Sstevel@tonic-gate 		}
1360Sstevel@tonic-gate 		icurs = wcursor;
1370Sstevel@tonic-gate 		idot = wdot;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 		/*
1400Sstevel@tonic-gate 		 * Advance so as to not find same thing again.
1410Sstevel@tonic-gate 		 */
1420Sstevel@tonic-gate 		if (dir > 0) {
1430Sstevel@tonic-gate 			if (!lnext()) {
1440Sstevel@tonic-gate 				rc = -1;
1450Sstevel@tonic-gate 				goto ret;
1460Sstevel@tonic-gate 			}
1470Sstevel@tonic-gate #ifdef XPG4
1480Sstevel@tonic-gate 		} else {
1490Sstevel@tonic-gate 			if (!lnext()) {
1500Sstevel@tonic-gate 				rc = -1;
1510Sstevel@tonic-gate 				goto ret;
1520Sstevel@tonic-gate 			}
1530Sstevel@tonic-gate 			(void) ltosol1("");
1540Sstevel@tonic-gate 		}
1550Sstevel@tonic-gate #else /* ! XPG4 */
1560Sstevel@tonic-gate 		} else
1570Sstevel@tonic-gate 			(void)lskipa1("");
1580Sstevel@tonic-gate #endif /* XPG4 */
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 		/*
1610Sstevel@tonic-gate 		 * Count times find end of sentence/paragraph.
1620Sstevel@tonic-gate 		 */
1630Sstevel@tonic-gate begin:
1640Sstevel@tonic-gate 		for (;;) {
1650Sstevel@tonic-gate 			while (!endsent(pastatom))
1660Sstevel@tonic-gate 				if (!lnext())
1670Sstevel@tonic-gate 					goto ret;
1680Sstevel@tonic-gate 			if (!pastatom || wcursor == linebuf && endPS())
1690Sstevel@tonic-gate 				if (--cnt <= 0)
1700Sstevel@tonic-gate 					break;
1710Sstevel@tonic-gate 			if (linebuf[0] == 0) {
1720Sstevel@tonic-gate 				do
1730Sstevel@tonic-gate 					if (!lnext())
1740Sstevel@tonic-gate 						goto ret;
1750Sstevel@tonic-gate 				while (linebuf[0] == 0);
1760Sstevel@tonic-gate 			} else
1770Sstevel@tonic-gate 				if (!lnext())
1780Sstevel@tonic-gate 					goto ret;
1790Sstevel@tonic-gate 		}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 		/*
1820Sstevel@tonic-gate 		 * If going backwards, and didn't hit the end of the buffer,
1830Sstevel@tonic-gate 		 * then reverse direction.
1840Sstevel@tonic-gate 		 */
1850Sstevel@tonic-gate 		if (dir < 0 && (wdot != llimit || wcursor != linebuf)) {
1860Sstevel@tonic-gate 			dir = 1;
1870Sstevel@tonic-gate 			llimit = dot;
1880Sstevel@tonic-gate 			/*
1890Sstevel@tonic-gate 			 * Empty line needs special treatement.
1900Sstevel@tonic-gate 			 * If moved to it from other than beginning of next line,
1910Sstevel@tonic-gate 			 * then a sentence starts on next line.
1920Sstevel@tonic-gate 			 */
1930Sstevel@tonic-gate 			if (linebuf[0] == 0 && !pastatom &&
1940Sstevel@tonic-gate 			   (wdot != dot - 1 || cursor != linebuf)) {
195*802Scf46844 				(void) lnext();
1960Sstevel@tonic-gate 				goto ret;
1970Sstevel@tonic-gate 			}
1980Sstevel@tonic-gate 		}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 		/*
2010Sstevel@tonic-gate 		 * If we are not at a section/paragraph division,
2020Sstevel@tonic-gate 		 * advance to next.
2030Sstevel@tonic-gate 		 */
2040Sstevel@tonic-gate 		if (wcursor == icurs && wdot == idot || wcursor != linebuf || !endPS())
2050Sstevel@tonic-gate 			(void)lskipa1("");
2060Sstevel@tonic-gate 	}
2070Sstevel@tonic-gate 	else {
2080Sstevel@tonic-gate 		c = *wcursor;
2090Sstevel@tonic-gate 		/*
2100Sstevel@tonic-gate 		 * Startup by skipping if at a ( going left or a ) going
2110Sstevel@tonic-gate 		 * right to keep from getting stuck immediately.
2120Sstevel@tonic-gate 		 */
2130Sstevel@tonic-gate 		if (dir < 0 && c == '(' || dir > 0 && c == ')') {
2140Sstevel@tonic-gate 			if (!lnext()) {
2150Sstevel@tonic-gate 				rc = -1;
2160Sstevel@tonic-gate 				goto ret;
2170Sstevel@tonic-gate 			}
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 		/*
2200Sstevel@tonic-gate 		 * Now chew up repetition count.  Each time around
2210Sstevel@tonic-gate 		 * if at the beginning of an s-exp (going forwards)
2220Sstevel@tonic-gate 		 * or the end of an s-exp (going backwards)
2230Sstevel@tonic-gate 		 * skip the s-exp.  If not at beg/end resp, then stop
2240Sstevel@tonic-gate 		 * if we hit a higher level paren, else skip an atom,
2250Sstevel@tonic-gate 		 * counting it unless pastatom.
2260Sstevel@tonic-gate 		 */
2270Sstevel@tonic-gate 		while (cnt > 0) {
2280Sstevel@tonic-gate 			c = *wcursor;
2290Sstevel@tonic-gate 			if (dir < 0 && c == ')' || dir > 0 && c == '(') {
2300Sstevel@tonic-gate 				if (!lskipbal("()"))
2310Sstevel@tonic-gate 					goto ret;
2320Sstevel@tonic-gate 				/*
2330Sstevel@tonic-gate  				 * Unless this is the last time going
2340Sstevel@tonic-gate 				 * backwards, skip past the matching paren
2350Sstevel@tonic-gate 				 * so we don't think it is a higher level paren.
2360Sstevel@tonic-gate 				 */
2370Sstevel@tonic-gate 				if (dir < 0 && cnt == 1)
2380Sstevel@tonic-gate 					goto ret;
2390Sstevel@tonic-gate 				if (!lnext() || !ltosolid())
2400Sstevel@tonic-gate 					goto ret;
2410Sstevel@tonic-gate 				--cnt;
2420Sstevel@tonic-gate 			} else if (dir < 0 && c == '(' || dir > 0 && c == ')')
2430Sstevel@tonic-gate 				/* Found a higher level paren */
2440Sstevel@tonic-gate 				goto ret;
2450Sstevel@tonic-gate 			else {
2460Sstevel@tonic-gate 				if (!lskipatom())
2470Sstevel@tonic-gate 					goto ret;
2480Sstevel@tonic-gate 				if (!pastatom)
2490Sstevel@tonic-gate 					--cnt;
2500Sstevel@tonic-gate 			}
2510Sstevel@tonic-gate 		}
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate ret:
2540Sstevel@tonic-gate 	strcLIN(save);
2550Sstevel@tonic-gate 	return (rc);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate  * Is this the end of a sentence?
2600Sstevel@tonic-gate  */
261*802Scf46844 int
262*802Scf46844 endsent(bool pastatom)
2630Sstevel@tonic-gate {
264*802Scf46844 	unsigned char *cp = wcursor;
265*802Scf46844 	int c, d;
2660Sstevel@tonic-gate 	int	len;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	/*
2690Sstevel@tonic-gate 	 * If this is the beginning of a line, then
2700Sstevel@tonic-gate 	 * check for the end of a paragraph or section.
2710Sstevel@tonic-gate 	 */
2720Sstevel@tonic-gate 	if (cp == linebuf)
2730Sstevel@tonic-gate 		return (endPS());
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	/*
2760Sstevel@tonic-gate 	 * Sentences end with . ! ? not at the beginning
2770Sstevel@tonic-gate 	 * of the line, and must be either at the end of the line,
2780Sstevel@tonic-gate 	 * or followed by 2 spaces.  Any number of intervening ) ] ' "
2790Sstevel@tonic-gate 	 * characters are allowed.
2800Sstevel@tonic-gate 	 */
2810Sstevel@tonic-gate 	if (!any(c = *cp, ".!?"))
2820Sstevel@tonic-gate 		goto tryps;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	do {
2850Sstevel@tonic-gate 		if ((len = mblen((char *)cp, MB_CUR_MAX)) <= 0)
2860Sstevel@tonic-gate 			len = 1;
2870Sstevel@tonic-gate 		cp += len;
2880Sstevel@tonic-gate 		if ((d = *cp) == 0)
2890Sstevel@tonic-gate 			return (1);
2900Sstevel@tonic-gate #ifdef XPG4
2910Sstevel@tonic-gate 	} while (any(d, ")]'\""));
2920Sstevel@tonic-gate #else /* ! XPG4 */
2930Sstevel@tonic-gate 	} while (any(d, ")]'"));
2940Sstevel@tonic-gate #endif /* XPG4 */
2950Sstevel@tonic-gate 	if (*cp == 0 || *cp++ == ' ' && *cp == ' ')
2960Sstevel@tonic-gate 		return (1);
2970Sstevel@tonic-gate tryps:
2980Sstevel@tonic-gate 	if (cp[1] == 0)
2990Sstevel@tonic-gate 		return (endPS());
3000Sstevel@tonic-gate 	return (0);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate /*
3040Sstevel@tonic-gate  * End of paragraphs/sections are respective
3050Sstevel@tonic-gate  * macros as well as blank lines and form feeds.
3060Sstevel@tonic-gate  */
307*802Scf46844 int
308*802Scf46844 endPS(void)
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	return (linebuf[0] == 0 ||
3120Sstevel@tonic-gate #ifdef XPG4
3130Sstevel@tonic-gate 		/* POSIX 1003.2 Section 5.35.7.1: control-L, "{"	*/
3140Sstevel@tonic-gate 		linebuf[0] == '{' ||
3150Sstevel@tonic-gate 		linebuf[0] == CTRL('L') ||
3160Sstevel@tonic-gate #endif /* XPG4 */
3170Sstevel@tonic-gate 		isa(svalue(vi_PARAGRAPHS)) || isa(svalue(vi_SECTIONS)));
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
321*802Scf46844 int
322*802Scf46844 lindent(line *addr)
3230Sstevel@tonic-gate {
324*802Scf46844 	int i;
3250Sstevel@tonic-gate 	unsigned char *swcurs = wcursor;
3260Sstevel@tonic-gate 	line *swdot = wdot;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate again:
3290Sstevel@tonic-gate 	if (addr > one) {
330*802Scf46844 		unsigned char *cp;
331*802Scf46844 		int cnt = 0;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 		addr--;
3340Sstevel@tonic-gate 		getline(*addr);
3350Sstevel@tonic-gate 		for (cp = linebuf; *cp; cp++)
3360Sstevel@tonic-gate 			if (*cp == '(')
3370Sstevel@tonic-gate 				cnt++;
3380Sstevel@tonic-gate 			else if (*cp == ')')
3390Sstevel@tonic-gate 				cnt--;
3400Sstevel@tonic-gate 		cp = vpastwh(linebuf);
3410Sstevel@tonic-gate 		if (*cp == 0)
3420Sstevel@tonic-gate 			goto again;
3430Sstevel@tonic-gate 		if (cnt == 0)
3440Sstevel@tonic-gate 			return (whitecnt(linebuf));
3450Sstevel@tonic-gate 		addr++;
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 	wcursor = linebuf;
3480Sstevel@tonic-gate 	linebuf[0] = 0;
3490Sstevel@tonic-gate 	wdot = addr;
3500Sstevel@tonic-gate 	dir = -1;
3510Sstevel@tonic-gate 	llimit = one;
3520Sstevel@tonic-gate 	lf = lindent;
3530Sstevel@tonic-gate 	if (!lskipbal("()"))
3540Sstevel@tonic-gate 		i = 0;
3550Sstevel@tonic-gate 	else if (wcursor == linebuf)
3560Sstevel@tonic-gate 		i = 2;
3570Sstevel@tonic-gate 	else {
358*802Scf46844 		unsigned char *wp = wcursor;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 		dir = 1;
3610Sstevel@tonic-gate 		llimit = wdot;
3620Sstevel@tonic-gate 		if (!lnext() || !ltosolid() || !lskipatom()) {
3630Sstevel@tonic-gate 			wcursor = wp;
3640Sstevel@tonic-gate 			i = 1;
3650Sstevel@tonic-gate 		} else
3660Sstevel@tonic-gate 			i = 0;
3670Sstevel@tonic-gate 		i += column(wcursor) - 1;
3680Sstevel@tonic-gate 		if (!inopen)
3690Sstevel@tonic-gate 			i--;
3700Sstevel@tonic-gate 	}
3710Sstevel@tonic-gate 	wdot = swdot;
3720Sstevel@tonic-gate 	wcursor = swcurs;
3730Sstevel@tonic-gate 	return (i);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
376*802Scf46844 int
377*802Scf46844 lmatchp(line *addr)
3780Sstevel@tonic-gate {
379*802Scf46844 	int i;
380*802Scf46844 	unsigned char *parens, *cp;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	for (cp = cursor; !any(*cp, "({[)}]");) {
3830Sstevel@tonic-gate 		if (*cp == 0)
3840Sstevel@tonic-gate 			return (0);
3850Sstevel@tonic-gate 		if ((i = mblen((char *)cp, MB_CUR_MAX)) <= 0)
3860Sstevel@tonic-gate 			i = 1;
3870Sstevel@tonic-gate 		cp += i;
3880Sstevel@tonic-gate 	}
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	lf = 0;
3910Sstevel@tonic-gate 	parens = any(*cp, "()") ? (unsigned char *)"()" : any(*cp, "[]") ? (unsigned char *)"[]" : (unsigned char *)"{}";
3920Sstevel@tonic-gate 	if (*cp == parens[1]) {
3930Sstevel@tonic-gate 		dir = -1;
3940Sstevel@tonic-gate 		llimit = one;
3950Sstevel@tonic-gate 	} else {
3960Sstevel@tonic-gate 		dir = 1;
3970Sstevel@tonic-gate 		llimit = dol;
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 	if (addr)
4000Sstevel@tonic-gate 		llimit = addr;
4010Sstevel@tonic-gate 	if (splitw)
4020Sstevel@tonic-gate 		llimit = dot;
4030Sstevel@tonic-gate 	wcursor = cp;
4040Sstevel@tonic-gate 	wdot = dot;
4050Sstevel@tonic-gate 	i = lskipbal(parens);
4060Sstevel@tonic-gate 	return (i);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate 
409*802Scf46844 void
410*802Scf46844 lsmatch(unsigned char *cp)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate 	unsigned char save[LBSIZE];
413*802Scf46844 	unsigned char *sp = save;
414*802Scf46844 	unsigned char *scurs = cursor;
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	wcursor = cp;
4170Sstevel@tonic-gate 	strcpy(sp, linebuf);
4180Sstevel@tonic-gate 	*wcursor = 0;
4190Sstevel@tonic-gate 	strcpy(cursor, genbuf);
4200Sstevel@tonic-gate 	cursor = strend(linebuf);
4210Sstevel@tonic-gate 	cursor = lastchr(linebuf, cursor);
4220Sstevel@tonic-gate 	if (lmatchp(dot - vcline)) {
423*802Scf46844 		int i = insmode;
424*802Scf46844 		int c = outcol;
425*802Scf46844 		int l = outline;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 		if (!move_insert_mode)
4280Sstevel@tonic-gate 			endim();
4290Sstevel@tonic-gate 		vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1);
4300Sstevel@tonic-gate 		flush();
4310Sstevel@tonic-gate 		sleep(1);
4320Sstevel@tonic-gate 		vgoto(l, c);
4330Sstevel@tonic-gate 		if (i)
4340Sstevel@tonic-gate 			goim();
4350Sstevel@tonic-gate 	}
4360Sstevel@tonic-gate 	else {
4370Sstevel@tonic-gate 		strcLIN(sp);
4380Sstevel@tonic-gate 		strcpy(scurs, genbuf);
4390Sstevel@tonic-gate 		if (!lmatchp((line *) 0))
440*802Scf46844 			(void) beep();
4410Sstevel@tonic-gate 	}
4420Sstevel@tonic-gate 	strcLIN(sp);
4430Sstevel@tonic-gate 	wdot = 0;
4440Sstevel@tonic-gate 	wcursor = 0;
4450Sstevel@tonic-gate 	cursor = scurs;
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate 
448*802Scf46844 int
449*802Scf46844 ltosolid(void)
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	return (ltosol1("()"));
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate 
455*802Scf46844 int
456*802Scf46844 ltosol1(unsigned char *parens)
4570Sstevel@tonic-gate {
458*802Scf46844 	unsigned char *cp;
4590Sstevel@tonic-gate 	int	len;
4600Sstevel@tonic-gate 	unsigned char	*ocp;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	if (*parens && !*wcursor && !lnext())
4630Sstevel@tonic-gate 		return (0);
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	while (isspace(*wcursor) || (*wcursor == 0 && *parens))
4660Sstevel@tonic-gate 		if (!lnext())
4670Sstevel@tonic-gate 			return (0);
4680Sstevel@tonic-gate 	if (any(*wcursor, parens) || dir > 0)
4690Sstevel@tonic-gate 		return (1);
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	ocp = linebuf;
4720Sstevel@tonic-gate 	for (cp = linebuf; cp < wcursor; cp += len) {
4730Sstevel@tonic-gate 		if (isascii(*cp)) {
4740Sstevel@tonic-gate 			len = 1;
4750Sstevel@tonic-gate 			if (isspace(*cp) || any(*cp, parens))
4760Sstevel@tonic-gate 				ocp = cp + 1;
4770Sstevel@tonic-gate 			continue;
4780Sstevel@tonic-gate 		}
4790Sstevel@tonic-gate 		if ((len = mblen((char *)cp, MB_CUR_MAX)) <= 0)
4800Sstevel@tonic-gate 			len = 1;
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate 	wcursor = ocp;
4830Sstevel@tonic-gate 	return (1);
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate 
486*802Scf46844 int
487*802Scf46844 lskipbal(unsigned char *parens)
4880Sstevel@tonic-gate {
489*802Scf46844 	int level = dir;
490*802Scf46844 	int c;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	do {
4930Sstevel@tonic-gate 		if (!lnext()) {
4940Sstevel@tonic-gate 			wdot = NOLINE;
4950Sstevel@tonic-gate 			return (0);
4960Sstevel@tonic-gate 		}
4970Sstevel@tonic-gate 		c = *wcursor;
4980Sstevel@tonic-gate 		if (c == parens[1])
4990Sstevel@tonic-gate 			level--;
5000Sstevel@tonic-gate 		else if (c == parens[0])
5010Sstevel@tonic-gate 			level++;
5020Sstevel@tonic-gate 	} while (level);
5030Sstevel@tonic-gate 	return (1);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate 
506*802Scf46844 int
507*802Scf46844 lskipatom(void)
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	return (lskipa1("()"));
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
513*802Scf46844 int
514*802Scf46844 lskipa1(unsigned char *parens)
5150Sstevel@tonic-gate {
516*802Scf46844 	int c;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	for (;;) {
5190Sstevel@tonic-gate 		if (dir < 0 && wcursor == linebuf) {
5200Sstevel@tonic-gate 			if (!lnext())
5210Sstevel@tonic-gate 				return (0);
5220Sstevel@tonic-gate 			break;
5230Sstevel@tonic-gate 		}
5240Sstevel@tonic-gate 		c = *wcursor;
5250Sstevel@tonic-gate 		if (c && (isspace(c) || any(c, parens)))
5260Sstevel@tonic-gate 			break;
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 		if (!lnext())
5290Sstevel@tonic-gate 			return (0);
5300Sstevel@tonic-gate 		if (dir > 0 && wcursor == linebuf)
5310Sstevel@tonic-gate 			break;
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 	return (ltosol1(parens));
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate 
536*802Scf46844 int
537*802Scf46844 lnext(void)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	if (dir > 0) {
5410Sstevel@tonic-gate 		if (*wcursor)
5420Sstevel@tonic-gate 			wcursor = nextchr(wcursor);
5430Sstevel@tonic-gate 		if (*wcursor)
5440Sstevel@tonic-gate 			return (1);
5450Sstevel@tonic-gate 		if (wdot >= llimit) {
5460Sstevel@tonic-gate 			if (lf == vmove && wcursor > linebuf)
5470Sstevel@tonic-gate 				wcursor = lastchr(linebuf, wcursor);
5480Sstevel@tonic-gate 			return (0);
5490Sstevel@tonic-gate 		}
5500Sstevel@tonic-gate 		wdot++;
5510Sstevel@tonic-gate 		getline(*wdot);
5520Sstevel@tonic-gate 		wcursor = linebuf;
5530Sstevel@tonic-gate 		return (1);
5540Sstevel@tonic-gate 	} else {
5550Sstevel@tonic-gate 		wcursor = lastchr(linebuf, wcursor);
5560Sstevel@tonic-gate 		if (wcursor >= linebuf)
5570Sstevel@tonic-gate 			return (1);
5580Sstevel@tonic-gate 		if (lf == lindent && linebuf[0] == '(')
5590Sstevel@tonic-gate 			llimit = wdot;
5600Sstevel@tonic-gate 		if (wdot <= llimit) {
5610Sstevel@tonic-gate 			wcursor = linebuf;
5620Sstevel@tonic-gate 			return (0);
5630Sstevel@tonic-gate 		}
5640Sstevel@tonic-gate 		wdot--;
5650Sstevel@tonic-gate 		getline(*wdot);
5660Sstevel@tonic-gate 		if(!*linebuf)
5670Sstevel@tonic-gate 			wcursor = linebuf;
5680Sstevel@tonic-gate 		else {
5690Sstevel@tonic-gate 			wcursor = strend(linebuf);
5700Sstevel@tonic-gate 			wcursor = lastchr(linebuf, wcursor);
5710Sstevel@tonic-gate 		}
5720Sstevel@tonic-gate 		return (1);
5730Sstevel@tonic-gate 	}
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate 
576*802Scf46844 int
577*802Scf46844 lbrack(int c, int (*f)())
5780Sstevel@tonic-gate {
579*802Scf46844 	line *addr;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	addr = dot;
5820Sstevel@tonic-gate 	for (;;) {
5830Sstevel@tonic-gate 		addr += dir;
5840Sstevel@tonic-gate 		if (addr < one || addr > dol) {
5850Sstevel@tonic-gate 			addr -= dir;
5860Sstevel@tonic-gate 			break;
5870Sstevel@tonic-gate 		}
5880Sstevel@tonic-gate 		getline(*addr);
5890Sstevel@tonic-gate 		if (linebuf[0] == '{' ||
5900Sstevel@tonic-gate #ifdef XPG4
5910Sstevel@tonic-gate 		    /* POSIX 1003.2 Section 5.35.7.1: control-L		*/
5920Sstevel@tonic-gate 		    linebuf[0] == CTRL('L') ||
5930Sstevel@tonic-gate #endif /* XPG4 */
5940Sstevel@tonic-gate 		    value(vi_LISP) && linebuf[0] == '(' ||
5950Sstevel@tonic-gate 		    isa(svalue(vi_SECTIONS))) {
5960Sstevel@tonic-gate 			if (c == ']' && f != vmove) {
5970Sstevel@tonic-gate 				addr--;
5980Sstevel@tonic-gate 				getline(*addr);
5990Sstevel@tonic-gate 			}
6000Sstevel@tonic-gate 			break;
6010Sstevel@tonic-gate 		}
6020Sstevel@tonic-gate 		if (c == ']' && f != vmove && linebuf[0] == '}')
6030Sstevel@tonic-gate 			break;
6040Sstevel@tonic-gate 	}
6050Sstevel@tonic-gate 	if (addr == dot)
6060Sstevel@tonic-gate 		return (0);
6070Sstevel@tonic-gate 	if (f != vmove)
6080Sstevel@tonic-gate 		wcursor = c == ']' ? strend(linebuf) : linebuf;
6090Sstevel@tonic-gate 	else
6100Sstevel@tonic-gate 		wcursor = 0;
6110Sstevel@tonic-gate 	wdot = addr;
6120Sstevel@tonic-gate 	vmoving = 0;
6130Sstevel@tonic-gate 	return (1);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate 
616*802Scf46844 int
617*802Scf46844 isa(unsigned char *cp)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	if (linebuf[0] != '.')
6210Sstevel@tonic-gate 		return (0);
6220Sstevel@tonic-gate 	for (; cp[0] && cp[1]; cp += 2)
6230Sstevel@tonic-gate 		if (linebuf[1] == cp[0]) {
6240Sstevel@tonic-gate 			if (linebuf[2] == cp[1])
6250Sstevel@tonic-gate 				return (1);
6260Sstevel@tonic-gate 			if (linebuf[2] == 0 && cp[1] == ' ')
6270Sstevel@tonic-gate 				return (1);
6280Sstevel@tonic-gate 		}
6290Sstevel@tonic-gate 	return (0);
6300Sstevel@tonic-gate }
631