int
isalnum(int c)
{
/*
* Hard to get absolutely right. Use what we know about ASCII
* and assume anything above the Latin control characters is
* potentially an alphanumeric.
*/
if(c<=' ')
return 0;
if(0x7F<=c && c<=0xA0)
return 0;
if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
return 0;
return 1;
}
int
isspace(Rune c)
{
return c == 0 || c == ' ' || c == '\t' ||
c == '\n' || c == '\r' || c == '\v';
}
int
inmode(Rune r, int mode)
{
return (mode == 0) ? isalnum(r) : r && !isspace(r);
}
int
clickmatch(File *f, int cl, int cr, int dir, Posn *p)
{
int c;
int nest = 1;
/*
* Stretches a selection out over current text,
* selecting matching range if possible.
* If there's no matching range, mode 0 selects
* a single alphanumeric region. Mode 1 selects
* a non-whitespace region.
*/
void
stretchsel(File *f, Posn p1, int mode)
{
int c, i;
Rune *r, *l;
Posn p;
if(p1 > f->nc)
return;
f->dot.r.p1 = f->dot.r.p2 = p1;
for(i=0; left[i]; i++){
l = left[i];
r = right[i];
/* try left match */
p = p1;
if(p1 == 0)
c = '\n';
else
c = filereadc(f, p - 1);
if(strrune(l, c)){
if(clickmatch(f, c, r[strrune(l, c)-l], 1, &p)){
f->dot.r.p1 = p1;
f->dot.r.p2 = p-(c!='\n');
}
return;
}
/* try right match */
p = p1;
if(p1 == f->nc)
c = '\n';
else
c = filereadc(f, p);
if(strrune(r, c)){
if(clickmatch(f, c, l[strrune(r, c)-r], -1, &p)){
f->dot.r.p1 = p;
if(c!='\n' || p!=0 || filereadc(f, 0)=='\n')
f->dot.r.p1++;
f->dot.r.p2 = p1+(p1<f->nc && c=='\n');
}
return;
}
}
/* try filling out word to right */
p = p1;
while(p < f->nc && inmode(filereadc(f, p++), mode))
f->dot.r.p2++;
/* try filling out word to left */
p = p1;
while(--p >= 0 && inmode(filereadc(f, p), mode))
f->dot.r.p1--;
}