#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
line *llimit;
int (*lf)();
int lindent();
bool wasend;
int endsent(bool);
int
lfind(pastatom, cnt, f, limit)
bool pastatom;
int cnt, (*f)();
line *limit;
{
int c;
int rc = 0;
unsigned char save[LBSIZE];
wasend = 0;
lf = f;
strcpy(save, linebuf);
if (limit == 0)
limit = dir < 0 ? one : dol;
llimit = limit;
wdot = dot;
wcursor = cursor;
if (pastatom >= 2) {
if (pastatom == 3) {
while(eend(f) && cnt-- > 0) {
;
}
} else {
while (cnt > 0 && word(f, cnt))
cnt--;
}
if (dot == wdot) {
wdot = 0;
if (cursor == wcursor)
rc = -1;
}
}
else if (!value(vi_LISP)) {
unsigned char *icurs;
line *idot;
if (linebuf[0] == 0) {
do
if (!lnext())
goto ret;
while (linebuf[0] == 0);
if (dir > 0) {
wdot--;
linebuf[0] = 0;
wcursor = linebuf;
if (!pastatom) {
icurs = wcursor;
idot = wdot;
goto begin;
}
}
}
icurs = wcursor;
idot = wdot;
if (dir > 0) {
if (!lnext()) {
rc = -1;
goto ret;
}
#ifdef XPG4
} else {
if (!lnext()) {
rc = -1;
goto ret;
}
(void) ltosol1("");
}
#else
} else
(void)lskipa1("");
#endif
begin:
for (;;) {
while (!endsent(pastatom))
if (!lnext())
goto ret;
if (!pastatom || wcursor == linebuf && endPS())
if (--cnt <= 0)
break;
if (linebuf[0] == 0) {
do
if (!lnext())
goto ret;
while (linebuf[0] == 0);
} else
if (!lnext())
goto ret;
}
if (dir < 0 && (wdot != llimit || wcursor != linebuf)) {
dir = 1;
llimit = dot;
if (linebuf[0] == 0 && !pastatom &&
(wdot != dot - 1 || cursor != linebuf)) {
(void) lnext();
goto ret;
}
}
if (wcursor == icurs && wdot == idot || wcursor != linebuf || !endPS())
(void)lskipa1("");
}
else {
c = *wcursor;
if (dir < 0 && c == '(' || dir > 0 && c == ')') {
if (!lnext()) {
rc = -1;
goto ret;
}
}
while (cnt > 0) {
c = *wcursor;
if (dir < 0 && c == ')' || dir > 0 && c == '(') {
if (!lskipbal("()"))
goto ret;
if (dir < 0 && cnt == 1)
goto ret;
if (!lnext() || !ltosolid())
goto ret;
--cnt;
} else if (dir < 0 && c == '(' || dir > 0 && c == ')')
goto ret;
else {
if (!lskipatom())
goto ret;
if (!pastatom)
--cnt;
}
}
}
ret:
strcLIN(save);
return (rc);
}
int
endsent(bool pastatom)
{
unsigned char *cp = wcursor;
int c, d;
int len;
if (cp == linebuf)
return (endPS());
if (!any(c = *cp, ".!?"))
goto tryps;
do {
if ((len = mblen((char *)cp, MB_CUR_MAX)) <= 0)
len = 1;
cp += len;
if ((d = *cp) == 0)
return (1);
#ifdef XPG4
} while (any(d, ")]'\""));
#else
} while (any(d, ")]'"));
#endif
if (*cp == 0 || *cp++ == ' ' && *cp == ' ')
return (1);
tryps:
if (cp[1] == 0)
return (endPS());
return (0);
}
int
endPS(void)
{
return (linebuf[0] == 0 ||
#ifdef XPG4
linebuf[0] == '{' ||
linebuf[0] == CTRL('L') ||
#endif
isa(svalue(vi_PARAGRAPHS)) || isa(svalue(vi_SECTIONS)));
}
int
lindent(line *addr)
{
int i;
unsigned char *swcurs = wcursor;
line *swdot = wdot;
again:
if (addr > one) {
unsigned char *cp;
int cnt = 0;
addr--;
getaline(*addr);
for (cp = linebuf; *cp; cp++)
if (*cp == '(')
cnt++;
else if (*cp == ')')
cnt--;
cp = vpastwh(linebuf);
if (*cp == 0)
goto again;
if (cnt == 0)
return (whitecnt(linebuf));
addr++;
}
wcursor = linebuf;
linebuf[0] = 0;
wdot = addr;
dir = -1;
llimit = one;
lf = lindent;
if (!lskipbal("()"))
i = 0;
else if (wcursor == linebuf)
i = 2;
else {
unsigned char *wp = wcursor;
dir = 1;
llimit = wdot;
if (!lnext() || !ltosolid() || !lskipatom()) {
wcursor = wp;
i = 1;
} else
i = 0;
i += column(wcursor) - 1;
if (!inopen)
i--;
}
wdot = swdot;
wcursor = swcurs;
return (i);
}
int
lmatchp(line *addr)
{
int i;
unsigned char *parens, *cp;
for (cp = cursor; !any(*cp, "({[)}]");) {
if (*cp == 0)
return (0);
if ((i = mblen((char *)cp, MB_CUR_MAX)) <= 0)
i = 1;
cp += i;
}
lf = 0;
parens = any(*cp, "()") ? (unsigned char *)"()" : any(*cp, "[]") ? (unsigned char *)"[]" : (unsigned char *)"{}";
if (*cp == parens[1]) {
dir = -1;
llimit = one;
} else {
dir = 1;
llimit = dol;
}
if (addr)
llimit = addr;
if (splitw)
llimit = dot;
wcursor = cp;
wdot = dot;
i = lskipbal(parens);
return (i);
}
void
lsmatch(unsigned char *cp)
{
unsigned char save[LBSIZE];
unsigned char *sp = save;
unsigned char *scurs = cursor;
wcursor = cp;
strcpy(sp, linebuf);
*wcursor = 0;
strcpy(cursor, genbuf);
cursor = strend(linebuf);
cursor = lastchr(linebuf, cursor);
if (lmatchp(dot - vcline)) {
int i = insmode;
int c = outcol;
int l = outline;
if (!move_insert_mode)
endim();
vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1);
flush();
sleep(1);
vgoto(l, c);
if (i)
goim();
}
else {
strcLIN(sp);
strcpy(scurs, genbuf);
if (!lmatchp((line *) 0))
(void) beep();
}
strcLIN(sp);
wdot = 0;
wcursor = 0;
cursor = scurs;
}
int
ltosolid(void)
{
return (ltosol1("()"));
}
int
ltosol1(unsigned char *parens)
{
unsigned char *cp;
int len;
unsigned char *ocp;
if (*parens && !*wcursor && !lnext())
return (0);
while (isspace(*wcursor) || (*wcursor == 0 && *parens))
if (!lnext())
return (0);
if (any(*wcursor, parens) || dir > 0)
return (1);
ocp = linebuf;
for (cp = linebuf; cp < wcursor; cp += len) {
if (isascii(*cp)) {
len = 1;
if (isspace(*cp) || any(*cp, parens))
ocp = cp + 1;
continue;
}
if ((len = mblen((char *)cp, MB_CUR_MAX)) <= 0)
len = 1;
}
wcursor = ocp;
return (1);
}
int
lskipbal(unsigned char *parens)
{
int level = dir;
int c;
do {
if (!lnext()) {
wdot = NOLINE;
return (0);
}
c = *wcursor;
if (c == parens[1])
level--;
else if (c == parens[0])
level++;
} while (level);
return (1);
}
int
lskipatom(void)
{
return (lskipa1("()"));
}
int
lskipa1(unsigned char *parens)
{
int c;
for (;;) {
if (dir < 0 && wcursor == linebuf) {
if (!lnext())
return (0);
break;
}
c = *wcursor;
if (c && (isspace(c) || any(c, parens)))
break;
if (!lnext())
return (0);
if (dir > 0 && wcursor == linebuf)
break;
}
return (ltosol1(parens));
}
int
lnext(void)
{
if (dir > 0) {
if (*wcursor)
wcursor = nextchr(wcursor);
if (*wcursor)
return (1);
if (wdot >= llimit) {
if (lf == vmove && wcursor > linebuf)
wcursor = lastchr(linebuf, wcursor);
return (0);
}
wdot++;
getaline(*wdot);
wcursor = linebuf;
return (1);
} else {
wcursor = lastchr(linebuf, wcursor);
if (wcursor >= linebuf)
return (1);
if (lf == lindent && linebuf[0] == '(')
llimit = wdot;
if (wdot <= llimit) {
wcursor = linebuf;
return (0);
}
wdot--;
getaline(*wdot);
if(!*linebuf)
wcursor = linebuf;
else {
wcursor = strend(linebuf);
wcursor = lastchr(linebuf, wcursor);
}
return (1);
}
}
int
lbrack(int c, int (*f)())
{
line *addr;
addr = dot;
for (;;) {
addr += dir;
if (addr < one || addr > dol) {
addr -= dir;
break;
}
getaline(*addr);
if (linebuf[0] == '{' ||
#ifdef XPG4
linebuf[0] == CTRL('L') ||
#endif
value(vi_LISP) && linebuf[0] == '(' ||
isa(svalue(vi_SECTIONS))) {
if (c == ']' && f != vmove) {
addr--;
getaline(*addr);
}
break;
}
if (c == ']' && f != vmove && linebuf[0] == '}')
break;
}
if (addr == dot)
return (0);
if (f != vmove)
wcursor = c == ']' ? strend(linebuf) : linebuf;
else
wcursor = 0;
wdot = addr;
vmoving = 0;
return (1);
}
int
isa(unsigned char *cp)
{
if (linebuf[0] != '.')
return (0);
for (; cp[0] && cp[1]; cp += 2)
if (linebuf[1] == cp[0]) {
if (linebuf[2] == cp[1])
return (1);
if (linebuf[2] == 0 && cp[1] == ' ')
return (1);
}
return (0);
}