diff options
Diffstat (limited to 'src/cmd/acme')
-rw-r--r-- | src/cmd/acme/dat.h | 1 | ||||
-rw-r--r-- | src/cmd/acme/text.c | 110 |
2 files changed, 111 insertions, 0 deletions
diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h index 93af258d..8242da69 100644 --- a/src/cmd/acme/dat.h +++ b/src/cmd/acme/dat.h @@ -198,6 +198,7 @@ struct Text uint textbacknl(Text*, uint, uint); uint textbsinsert(Text*, uint, Rune*, uint, int, int*); int textbswidth(Text*, Rune); +int textclickhtmlmatch(Text*, uint*, uint*); int textclickmatch(Text*, int, int, int, uint*); void textclose(Text*); void textcolumnate(Text*, Dirlist**, int); diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c index f330d4b8..f1fc7329 100644 --- a/src/cmd/acme/text.c +++ b/src/cmd/acme/text.c @@ -1381,6 +1381,10 @@ textdoubleclick(Text *t, uint *q0, uint *q1) return; } } + + if(textclickhtmlmatch(t, q0, q1)) + return; + /* try filling out word to right */ while(*q1<t->file->b.nc && isalnum(textreadc(t, *q1))) (*q1)++; @@ -1417,6 +1421,112 @@ textclickmatch(Text *t, int cl, int cr, int dir, uint *q) return cl=='\n' && nest==1; } +// Is the text starting at location q an html tag? +// Return 1 for <a>, -1 for </a>, 0 for no tag or <a />. +// Set *q1, if non-nil, to the location after the tag. +static int +ishtmlstart(Text *t, uint q, uint *q1) +{ + int c, c1, c2; + + if(q+2 > t->file->b.nc) + return 0; + if(textreadc(t, q++) != '<') + return 0; + c = textreadc(t, q++); + c1 = c; + c2 = c; + while(c != '>') { + if(q >= t->file->b.nc) + return 0; + c2 = c; + c = textreadc(t, q++); + } + if(q1) + *q1 = q; + if(c1 == '/') // closing tag + return -1; + if(c2 == '/' || c2 == '!') // open + close tag or comment + return 0; + return 1; +} + +// Is the text ending at location q an html tag? +// Return 1 for <a>, -1 for </a>, 0 for no tag or <a />. +// Set *q0, if non-nil, to the start of the tag. +static int +ishtmlend(Text *t, uint q, uint *q0) +{ + int c, c1, c2; + + if(q < 2) + return 0; + if(textreadc(t, --q) != '>') + return 0; + c = textreadc(t, --q); + c1 = c; + c2 = c; + while(c != '<') { + if(q == 0) + return 0; + c1 = c; + c = textreadc(t, --q); + } + if(q0) + *q0 = q; + if(c1 == '/') // closing tag + return -1; + if(c2 == '/' || c2 == '!') // open + close tag or comment + return 0; + return 1; +} + +int +textclickhtmlmatch(Text *t, uint *q0, uint *q1) +{ + int depth, n; + uint q, nq; + + q = *q0; + // after opening tag? scan forward for closing tag + if(ishtmlend(t, q, nil) == 1) { + depth = 1; + while(q < t->file->b.nc) { + n = ishtmlstart(t, q, &nq); + if(n != 0) { + depth += n; + if(depth == 0) { + *q1 = q; + return 1; + } + q = nq; + continue; + } + q++; + } + } + + // before closing tag? scan backward for opening tag + if(ishtmlstart(t, q, nil) == -1) { + depth = -1; + while(q > 0) { + n = ishtmlend(t, q, &nq); + if(n != 0) { + depth += n; + if(depth == 0) { + *q0 = q; + return 1; + } + q = nq; + continue; + } + q--; + } + } + + return 0; +} + uint textbacknl(Text *t, uint p, uint n) { |