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