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