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