17ab27030SDavid du Colombier #include <u.h>
27ab27030SDavid du Colombier #include <libc.h>
37ab27030SDavid du Colombier #include <bio.h>
47ab27030SDavid du Colombier #include <draw.h>
57ab27030SDavid du Colombier #include <memdraw.h>
67ab27030SDavid du Colombier #include <thread.h>
77ab27030SDavid du Colombier #include <cursor.h>
87ab27030SDavid du Colombier #include <mouse.h>
97ab27030SDavid du Colombier #include <keyboard.h>
107ab27030SDavid du Colombier #include <frame.h>
117ab27030SDavid du Colombier #include <plumb.h>
127ab27030SDavid du Colombier #include <html.h>
137ab27030SDavid du Colombier #include <regexp.h>
147ab27030SDavid du Colombier #include "dat.h"
157ab27030SDavid du Colombier #include "fns.h"
167ab27030SDavid du Colombier
177ab27030SDavid du Colombier static Point prevmouse;
187ab27030SDavid du Colombier static Window *mousew;
197ab27030SDavid du Colombier
207ab27030SDavid du Colombier int
min(int a,int b)217ab27030SDavid du Colombier min(int a, int b)
227ab27030SDavid du Colombier {
237ab27030SDavid du Colombier if(a < b)
247ab27030SDavid du Colombier return a;
257ab27030SDavid du Colombier return b;
267ab27030SDavid du Colombier }
277ab27030SDavid du Colombier
287ab27030SDavid du Colombier int
max(int a,int b)297ab27030SDavid du Colombier max(int a, int b)
307ab27030SDavid du Colombier {
317ab27030SDavid du Colombier if(a > b)
327ab27030SDavid du Colombier return a;
337ab27030SDavid du Colombier return b;
347ab27030SDavid du Colombier }
357ab27030SDavid du Colombier
367ab27030SDavid du Colombier void
cvttorunes(char * p,int n,Rune * r,int * nb,int * nr,int * nulls)377ab27030SDavid du Colombier cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
387ab27030SDavid du Colombier {
397ab27030SDavid du Colombier uchar *q;
407ab27030SDavid du Colombier Rune *s;
417ab27030SDavid du Colombier int j, w;
427ab27030SDavid du Colombier
437ab27030SDavid du Colombier /*
447ab27030SDavid du Colombier * Always guaranteed that n bytes may be interpreted
457ab27030SDavid du Colombier * without worrying about partial runes. This may mean
467ab27030SDavid du Colombier * reading up to UTFmax-1 more bytes than n; the caller
477ab27030SDavid du Colombier * knows this. If n is a firm limit, the caller should
487ab27030SDavid du Colombier * set p[n] = 0.
497ab27030SDavid du Colombier */
507ab27030SDavid du Colombier q = (uchar*)p;
517ab27030SDavid du Colombier s = r;
527ab27030SDavid du Colombier for(j=0; j<n; j+=w){
537ab27030SDavid du Colombier if(*q < Runeself){
547ab27030SDavid du Colombier w = 1;
557ab27030SDavid du Colombier *s = *q++;
567ab27030SDavid du Colombier }else{
577ab27030SDavid du Colombier w = chartorune(s, (char*)q);
587ab27030SDavid du Colombier q += w;
597ab27030SDavid du Colombier }
607ab27030SDavid du Colombier if(*s)
617ab27030SDavid du Colombier s++;
627ab27030SDavid du Colombier else if(nulls)
637ab27030SDavid du Colombier *nulls = TRUE;
647ab27030SDavid du Colombier }
657ab27030SDavid du Colombier *nb = (char*)q-p;
667ab27030SDavid du Colombier *nr = s-r;
677ab27030SDavid du Colombier }
687ab27030SDavid du Colombier
697ab27030SDavid du Colombier void
bytetorunestr(char * s,Runestr * rs)707ab27030SDavid du Colombier bytetorunestr(char *s, Runestr *rs)
717ab27030SDavid du Colombier {
727ab27030SDavid du Colombier Rune *r;
737ab27030SDavid du Colombier int nb, nr;
747ab27030SDavid du Colombier
757ab27030SDavid du Colombier nb = strlen(s);
767ab27030SDavid du Colombier r = runemalloc(nb+1);
777ab27030SDavid du Colombier cvttorunes(s, nb, r, &nb, &nr, nil);
787ab27030SDavid du Colombier r[nr] = '\0';
797ab27030SDavid du Colombier rs->nr = nr;
807ab27030SDavid du Colombier rs->r = r;
817ab27030SDavid du Colombier }
827ab27030SDavid du Colombier
837ab27030SDavid du Colombier void
error(char * s)847ab27030SDavid du Colombier error(char *s)
857ab27030SDavid du Colombier {
867ab27030SDavid du Colombier fprint(2, "abaco: %s: %r\n", s);
877ab27030SDavid du Colombier // abort();
887ab27030SDavid du Colombier threadexitsall(s);
897ab27030SDavid du Colombier }
907ab27030SDavid du Colombier
917ab27030SDavid du Colombier void*
emalloc(ulong n)927ab27030SDavid du Colombier emalloc(ulong n)
937ab27030SDavid du Colombier {
947ab27030SDavid du Colombier void *p;
957ab27030SDavid du Colombier
967ab27030SDavid du Colombier p = malloc(n);
977ab27030SDavid du Colombier if(p == nil)
987ab27030SDavid du Colombier error("malloc failed");
997ab27030SDavid du Colombier setmalloctag(p, getcallerpc(&n));
1007ab27030SDavid du Colombier memset(p, 0, n);
1017ab27030SDavid du Colombier return p;
1027ab27030SDavid du Colombier }
1037ab27030SDavid du Colombier
1047ab27030SDavid du Colombier void*
erealloc(void * p,ulong n)1057ab27030SDavid du Colombier erealloc(void *p, ulong n)
1067ab27030SDavid du Colombier {
1077ab27030SDavid du Colombier p = realloc(p, n);
1087ab27030SDavid du Colombier if(p == nil)
1097ab27030SDavid du Colombier error("realloc failed");
1107ab27030SDavid du Colombier setmalloctag(p, getcallerpc(&n));
1117ab27030SDavid du Colombier return p;
1127ab27030SDavid du Colombier }
1137ab27030SDavid du Colombier
1147ab27030SDavid du Colombier Rune*
erunestrdup(Rune * r)1157ab27030SDavid du Colombier erunestrdup(Rune *r)
1167ab27030SDavid du Colombier {
1177ab27030SDavid du Colombier void *p;
1187ab27030SDavid du Colombier
1197ab27030SDavid du Colombier if(r == nil)
1207ab27030SDavid du Colombier return nil;
1217ab27030SDavid du Colombier p = runestrdup(r);
1227ab27030SDavid du Colombier if(p == nil)
1237ab27030SDavid du Colombier error("runestrdup failed");
1247ab27030SDavid du Colombier setmalloctag(p, getcallerpc(&r));
1257ab27030SDavid du Colombier return p;
1267ab27030SDavid du Colombier }
1277ab27030SDavid du Colombier
1287ab27030SDavid du Colombier char*
estrdup(char * s)1297ab27030SDavid du Colombier estrdup(char *s)
1307ab27030SDavid du Colombier {
1317ab27030SDavid du Colombier char *t;
1327ab27030SDavid du Colombier
1337ab27030SDavid du Colombier t = strdup(s);
1347ab27030SDavid du Colombier if(t == nil)
1357ab27030SDavid du Colombier error("strdup failed");
1367ab27030SDavid du Colombier setmalloctag(t, getcallerpc(&s));
1377ab27030SDavid du Colombier return t;
1387ab27030SDavid du Colombier }
1397ab27030SDavid du Colombier
1407ab27030SDavid du Colombier int
runestreq(Runestr a,Runestr b)1417ab27030SDavid du Colombier runestreq(Runestr a, Runestr b)
1427ab27030SDavid du Colombier {
1437ab27030SDavid du Colombier return runeeq(a.r, a.nr, b.r, b.nr);
1447ab27030SDavid du Colombier }
1457ab27030SDavid du Colombier
1467ab27030SDavid du Colombier int
runeeq(Rune * s1,uint n1,Rune * s2,uint n2)1477ab27030SDavid du Colombier runeeq(Rune *s1, uint n1, Rune *s2, uint n2)
1487ab27030SDavid du Colombier {
1497ab27030SDavid du Colombier if(n1 != n2)
1507ab27030SDavid du Colombier return FALSE;
1517ab27030SDavid du Colombier return memcmp(s1, s2, n1*sizeof(Rune)) == 0;
1527ab27030SDavid du Colombier }
1537ab27030SDavid du Colombier
1547ab27030SDavid du Colombier void
closerunestr(Runestr * rs)1557ab27030SDavid du Colombier closerunestr(Runestr *rs)
1567ab27030SDavid du Colombier {
1577ab27030SDavid du Colombier
1587ab27030SDavid du Colombier rs->nr = 0;
1597ab27030SDavid du Colombier if(rs->r)
1607ab27030SDavid du Colombier free(rs->r);
1617ab27030SDavid du Colombier rs->r = nil;
1627ab27030SDavid du Colombier }
1637ab27030SDavid du Colombier
1647ab27030SDavid du Colombier void
copyrunestr(Runestr * a,Runestr * b)1657ab27030SDavid du Colombier copyrunestr(Runestr *a, Runestr *b)
1667ab27030SDavid du Colombier {
1677ab27030SDavid du Colombier closerunestr(a);
1687ab27030SDavid du Colombier a->r = runemalloc(b->nr+1);
1697ab27030SDavid du Colombier runemove(a->r, b->r, b->nr);
1707ab27030SDavid du Colombier a->r[b->nr] = 0;
1717ab27030SDavid du Colombier a->nr = b->nr;
1727ab27030SDavid du Colombier }
1737ab27030SDavid du Colombier
1747ab27030SDavid du Colombier int
isalnum(Rune c)1757ab27030SDavid du Colombier isalnum(Rune c)
1767ab27030SDavid du Colombier {
1777ab27030SDavid du Colombier /*
1787ab27030SDavid du Colombier * Hard to get absolutely right. Use what we know about ASCII
1797ab27030SDavid du Colombier * and assume anything above the Latin control characters is
1807ab27030SDavid du Colombier * potentially an alphanumeric.
1817ab27030SDavid du Colombier */
1827ab27030SDavid du Colombier if(c <= ' ')
1837ab27030SDavid du Colombier return FALSE;
1847ab27030SDavid du Colombier if(0x7F<=c && c<=0xA0)
1857ab27030SDavid du Colombier return FALSE;
1867ab27030SDavid du Colombier if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
1877ab27030SDavid du Colombier return FALSE;
1887ab27030SDavid du Colombier return TRUE;
1897ab27030SDavid du Colombier }
1907ab27030SDavid du Colombier
1917ab27030SDavid du Colombier Rune*
skipbl(Rune * r,int n,int * np)1927ab27030SDavid du Colombier skipbl(Rune *r, int n, int *np)
1937ab27030SDavid du Colombier {
1947ab27030SDavid du Colombier while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){
1957ab27030SDavid du Colombier --n;
1967ab27030SDavid du Colombier r++;
1977ab27030SDavid du Colombier }
1987ab27030SDavid du Colombier *np = n;
1997ab27030SDavid du Colombier return r;
2007ab27030SDavid du Colombier }
2017ab27030SDavid du Colombier
2027ab27030SDavid du Colombier Rune*
findbl(Rune * r,int n,int * np)2037ab27030SDavid du Colombier findbl(Rune *r, int n, int *np)
2047ab27030SDavid du Colombier {
2057ab27030SDavid du Colombier while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){
2067ab27030SDavid du Colombier --n;
2077ab27030SDavid du Colombier r++;
2087ab27030SDavid du Colombier }
2097ab27030SDavid du Colombier *np = n;
2107ab27030SDavid du Colombier return r;
2117ab27030SDavid du Colombier }
2127ab27030SDavid du Colombier
2137ab27030SDavid du Colombier int
istextfield(Item * i)2147ab27030SDavid du Colombier istextfield(Item *i)
2157ab27030SDavid du Colombier {
2167ab27030SDavid du Colombier Formfield *ff;
2177ab27030SDavid du Colombier
2187ab27030SDavid du Colombier ff = ((Iformfield *)i)->formfield;
2197ab27030SDavid du Colombier if(ff->ftype==Ftext || ff->ftype==Ftextarea || ff->ftype==Fpassword)
2207ab27030SDavid du Colombier return TRUE;
2217ab27030SDavid du Colombier
2227ab27030SDavid du Colombier return FALSE;
2237ab27030SDavid du Colombier }
2247ab27030SDavid du Colombier
2257ab27030SDavid du Colombier int
forceitem(Item * i)2267ab27030SDavid du Colombier forceitem(Item *i)
2277ab27030SDavid du Colombier {
2287ab27030SDavid du Colombier if(i->state&IFwrap && i->tag!=Iruletag && i->tag!=Itabletag)
2297ab27030SDavid du Colombier return FALSE;
2307ab27030SDavid du Colombier
2317ab27030SDavid du Colombier return TRUE;
2327ab27030SDavid du Colombier }
2337ab27030SDavid du Colombier
2347ab27030SDavid du Colombier int
dimwidth(Dimen d,int w)2357ab27030SDavid du Colombier dimwidth(Dimen d, int w)
2367ab27030SDavid du Colombier {
2377ab27030SDavid du Colombier int s, k;
2387ab27030SDavid du Colombier
2397ab27030SDavid du Colombier k = dimenkind(d);
2407ab27030SDavid du Colombier if(k == Dnone)
2417ab27030SDavid du Colombier return w;
2427ab27030SDavid du Colombier s = dimenspec(d);
2437ab27030SDavid du Colombier if(k == Dpixels)
2447ab27030SDavid du Colombier w = s;
2457ab27030SDavid du Colombier else if(k==Dpercent && s<100)
2467ab27030SDavid du Colombier w = s*w/100;
2477ab27030SDavid du Colombier
2487ab27030SDavid du Colombier return w;
2497ab27030SDavid du Colombier }
2507ab27030SDavid du Colombier
2517ab27030SDavid du Colombier void
frdims(Dimen * d,int n,int t,int ** ret)2527ab27030SDavid du Colombier frdims(Dimen *d, int n, int t, int **ret)
2537ab27030SDavid du Colombier {
2547ab27030SDavid du Colombier int totpix, totpcnt, totrel;
2557ab27030SDavid du Colombier double spix, spcnt, relu, vd;
2567ab27030SDavid du Colombier int tt, trest, totpixrel, minrelu, i;
2577ab27030SDavid du Colombier int *x, *spec, *kind;
2587ab27030SDavid du Colombier
2597ab27030SDavid du Colombier if(n == 1){
2607ab27030SDavid du Colombier *ret = x = emalloc(sizeof(int));
2617ab27030SDavid du Colombier x[0] = t;
2627ab27030SDavid du Colombier return;
2637ab27030SDavid du Colombier }
2647ab27030SDavid du Colombier totpix = totpcnt = totrel = 0;
2657ab27030SDavid du Colombier spec = emalloc(n*sizeof(int));
2667ab27030SDavid du Colombier kind = emalloc(n*sizeof(int));
2677ab27030SDavid du Colombier for(i=0; i<n; i++){
2687ab27030SDavid du Colombier spec[i] = dimenspec(d[i]);
2697ab27030SDavid du Colombier if(spec[i] < 0)
2707ab27030SDavid du Colombier spec[i] = 0;
2717ab27030SDavid du Colombier kind[i] = dimenkind(d[i]);
2727ab27030SDavid du Colombier switch(kind[i]){
2737ab27030SDavid du Colombier case Dpixels:
2747ab27030SDavid du Colombier totpix += spec[i];
2757ab27030SDavid du Colombier break;
2767ab27030SDavid du Colombier case Dpercent:
2777ab27030SDavid du Colombier totpcnt += spec[i];
2787ab27030SDavid du Colombier break;
2797ab27030SDavid du Colombier case Drelative:
2807ab27030SDavid du Colombier totrel += spec[i];
2817ab27030SDavid du Colombier break;
2827ab27030SDavid du Colombier case Dnone:
2837ab27030SDavid du Colombier totrel++;
2847ab27030SDavid du Colombier break;
2857ab27030SDavid du Colombier }
2867ab27030SDavid du Colombier }
2877ab27030SDavid du Colombier spix = spcnt = 1.0;
2887ab27030SDavid du Colombier minrelu = 0;
2897ab27030SDavid du Colombier if(totrel > 0)
2907ab27030SDavid du Colombier minrelu = Scrollsize+Scrollgap;
2917ab27030SDavid du Colombier relu = (double)minrelu;
2927ab27030SDavid du Colombier tt = totpix + t*totpcnt/100 + totrel*minrelu;
2937ab27030SDavid du Colombier if(tt < t){
2947ab27030SDavid du Colombier if(totrel == 0){
2957ab27030SDavid du Colombier if(totpcnt != 0)
2967ab27030SDavid du Colombier spcnt = (double)((t-totpix)*100)/(double)(t*totpcnt);
2977ab27030SDavid du Colombier else
2987ab27030SDavid du Colombier spix = (double)t/(double)totpix;
2997ab27030SDavid du Colombier }else
3007ab27030SDavid du Colombier relu += (double)(t-tt)/(double)totrel;
3017ab27030SDavid du Colombier }else{
3027ab27030SDavid du Colombier totpixrel = totpix + totrel*minrelu;
3037ab27030SDavid du Colombier if(totpixrel < t)
3047ab27030SDavid du Colombier spcnt = (double)((t-totpixrel)*100)/(double)(t*totpcnt);
3057ab27030SDavid du Colombier else{
3067ab27030SDavid du Colombier trest = t - totrel*minrelu;
3077ab27030SDavid du Colombier if(trest > 0)
3087ab27030SDavid du Colombier spcnt = (double)trest/(double)(totpix + (t*totpcnt/100));
3097ab27030SDavid du Colombier else{
3107ab27030SDavid du Colombier spcnt = (double)t/(double)tt;
3117ab27030SDavid du Colombier relu = 0.0;
3127ab27030SDavid du Colombier }
3137ab27030SDavid du Colombier spix = spcnt;
3147ab27030SDavid du Colombier }
3157ab27030SDavid du Colombier }
3167ab27030SDavid du Colombier x = emalloc(n * sizeof(int));
3177ab27030SDavid du Colombier tt = 0;
3187ab27030SDavid du Colombier for(i=0; i<n-1; i++){
3197ab27030SDavid du Colombier vd = (double)spec[i];
3207ab27030SDavid du Colombier switch(kind[i]){
3217ab27030SDavid du Colombier case Dpixels:
3227ab27030SDavid du Colombier vd = vd*spix;
3237ab27030SDavid du Colombier break;
3247ab27030SDavid du Colombier case Dpercent:
3257ab27030SDavid du Colombier vd = vd*(double)t*spcnt/100.0;
3267ab27030SDavid du Colombier break;
3277ab27030SDavid du Colombier case Drelative:
3287ab27030SDavid du Colombier vd = vd*relu;
3297ab27030SDavid du Colombier break;
3307ab27030SDavid du Colombier case Dnone:
3317ab27030SDavid du Colombier vd = relu;
3327ab27030SDavid du Colombier break;
3337ab27030SDavid du Colombier }
3347ab27030SDavid du Colombier x[i] = (int)(vd+.5);
3357ab27030SDavid du Colombier tt += x[i];
3367ab27030SDavid du Colombier }
3377ab27030SDavid du Colombier x[n - 1] = t - tt;
3387ab27030SDavid du Colombier *ret = x;
3397ab27030SDavid du Colombier free(spec);
3407ab27030SDavid du Colombier free(kind);
3417ab27030SDavid du Colombier }
3427ab27030SDavid du Colombier
3437ab27030SDavid du Colombier Image *
getbg(Page * p)3447ab27030SDavid du Colombier getbg(Page *p)
3457ab27030SDavid du Colombier {
3467ab27030SDavid du Colombier Docinfo *d;
3477ab27030SDavid du Colombier Cimage *ci;
3487ab27030SDavid du Colombier Image *bg;
3497ab27030SDavid du Colombier
3507ab27030SDavid du Colombier d = p->doc;
3517ab27030SDavid du Colombier if(d->backgrounditem){
3527ab27030SDavid du Colombier if(d->backgrounditem->aux){
3537ab27030SDavid du Colombier ci = d->backgrounditem->aux;
3547ab27030SDavid du Colombier if(ci->mi)
3557ab27030SDavid du Colombier getimage(ci, d->backgrounditem->altrep);
3567ab27030SDavid du Colombier bg = ci->i;
3577ab27030SDavid du Colombier }else
3587ab27030SDavid du Colombier bg = display->white;
3597ab27030SDavid du Colombier }else
3607ab27030SDavid du Colombier bg = getcolor(d->background.color);
3617ab27030SDavid du Colombier
3627ab27030SDavid du Colombier return bg;
3637ab27030SDavid du Colombier }
3647ab27030SDavid du Colombier
3657ab27030SDavid du Colombier Rune *
getbase(Page * p)3667ab27030SDavid du Colombier getbase(Page *p)
3677ab27030SDavid du Colombier {
3687ab27030SDavid du Colombier if(p->doc)
3697ab27030SDavid du Colombier return p->doc->base;
3707ab27030SDavid du Colombier if(p->url->act.r)
3717ab27030SDavid du Colombier return p->url->act.r;
3727ab27030SDavid du Colombier return p->url->src.r;
3737ab27030SDavid du Colombier }
3747ab27030SDavid du Colombier
3757ab27030SDavid du Colombier Image *
eallocimage(Display * d,Rectangle r,ulong chan,int repl,int col)3767ab27030SDavid du Colombier eallocimage(Display *d, Rectangle r, ulong chan, int repl, int col)
3777ab27030SDavid du Colombier {
3787ab27030SDavid du Colombier Image *i;
3797ab27030SDavid du Colombier
3807ab27030SDavid du Colombier i = allocimage(d, r, chan, repl, col);
3817ab27030SDavid du Colombier if(i == nil)
3827ab27030SDavid du Colombier error("allocimage failed");
3837ab27030SDavid du Colombier return i;
3847ab27030SDavid du Colombier }
3857ab27030SDavid du Colombier
3867ab27030SDavid du Colombier void
rect3d(Image * im,Rectangle r,int i,Image ** c,Point sp)3877ab27030SDavid du Colombier rect3d(Image *im, Rectangle r, int i, Image **c, Point sp)
3887ab27030SDavid du Colombier {
3897ab27030SDavid du Colombier Point p[6];
3907ab27030SDavid du Colombier
3917ab27030SDavid du Colombier if(i < 0){
3927ab27030SDavid du Colombier r = insetrect(r, i);
3937ab27030SDavid du Colombier sp = addpt(sp, Pt(i,i));
3947ab27030SDavid du Colombier i = -i;
3957ab27030SDavid du Colombier }
3967ab27030SDavid du Colombier draw(im, Rect(r.min.x+i, r.min.y+i, r.max.x-i, r.max.y-i), c[2], nil, sp);
3977ab27030SDavid du Colombier p[0] = r.min;
3987ab27030SDavid du Colombier p[1] = Pt(r.min.x, r.max.y);
3997ab27030SDavid du Colombier p[2] = Pt(r.min.x+i, r.max.y-i);
4007ab27030SDavid du Colombier p[3] = Pt(r.min.x+i, r.min.y+i);
4017ab27030SDavid du Colombier p[4] = Pt(r.max.x-i, r.min.y+i);
4027ab27030SDavid du Colombier p[5] = Pt(r.max.x, r.min.y);
4037ab27030SDavid du Colombier fillpoly(im, p, 6, 0, c[0], sp);
4047ab27030SDavid du Colombier p[0] = r.max;
4057ab27030SDavid du Colombier p[1] = Pt(r.min.x, r.max.y);
4067ab27030SDavid du Colombier p[2] = Pt(r.min.x+i, r.max.y-i);
4077ab27030SDavid du Colombier p[3] = Pt(r.max.x-i, r.max.y-i);
4087ab27030SDavid du Colombier p[4] = Pt(r.max.x-i, r.min.y+i);
4097ab27030SDavid du Colombier p[5] = Pt(r.max.x, r.min.y);
4107ab27030SDavid du Colombier fillpoly(im, p, 6, 0, c[1], sp);
4117ab27030SDavid du Colombier }
4127ab27030SDavid du Colombier
4137ab27030SDavid du Colombier void
ellipse3d(Image * im,Point p,int rad,int i,Image ** c,Point sp)4147ab27030SDavid du Colombier ellipse3d(Image *im, Point p, int rad, int i, Image **c, Point sp)
4157ab27030SDavid du Colombier {
4167ab27030SDavid du Colombier fillarc(im, p, rad, rad, c[0], sp, 45, 180);
4177ab27030SDavid du Colombier fillarc(im, p, rad, rad, c[1], sp, 45, -180);
4187ab27030SDavid du Colombier fillellipse(im, p, rad-i, rad-i, c[2], sp);
4197ab27030SDavid du Colombier }
4207ab27030SDavid du Colombier
4217ab27030SDavid du Colombier void
colarray(Image ** c,Image * c0,Image * c1,Image * c2,int checked)4227ab27030SDavid du Colombier colarray(Image **c, Image *c0, Image *c1, Image *c2, int checked)
4237ab27030SDavid du Colombier {
4247ab27030SDavid du Colombier if(checked){
4257ab27030SDavid du Colombier c[0] = c0;
4267ab27030SDavid du Colombier c[1] = c1;
4277ab27030SDavid du Colombier }else{
4287ab27030SDavid du Colombier c[0] = c1;
4297ab27030SDavid du Colombier c[1] = c0;
4307ab27030SDavid du Colombier }
4317ab27030SDavid du Colombier c[2] = c2;
4327ab27030SDavid du Colombier }
4337ab27030SDavid du Colombier
4347ab27030SDavid du Colombier static char *deffontpaths[] = {
4357ab27030SDavid du Colombier #include "fonts.h"
4367ab27030SDavid du Colombier };
4377ab27030SDavid du Colombier
4387ab27030SDavid du Colombier static char *fontpaths[NumFnt];
4397ab27030SDavid du Colombier static Font *fonts[NumFnt];
4407ab27030SDavid du Colombier
4417ab27030SDavid du Colombier void
initfontpaths(void)4427ab27030SDavid du Colombier initfontpaths(void)
4437ab27030SDavid du Colombier {
4447ab27030SDavid du Colombier Biobufhdr *bp;
4457ab27030SDavid du Colombier char buf[128];
4467ab27030SDavid du Colombier int i;
4477ab27030SDavid du Colombier
4487ab27030SDavid du Colombier /* we don't care if getenv(2) fails */
4497ab27030SDavid du Colombier snprint(buf, sizeof(buf)-1, "%s/lib/abaco.fonts", getenv("home"));
4507ab27030SDavid du Colombier if((bp=Bopen(buf, OREAD)) == nil)
4517ab27030SDavid du Colombier goto Default;
4527ab27030SDavid du Colombier
4537ab27030SDavid du Colombier for(i=0; i<NumFnt; i++)
4547ab27030SDavid du Colombier if((fontpaths[i]=Brdstr(bp, '\n', 1)) == nil)
4557ab27030SDavid du Colombier goto Error;
4567ab27030SDavid du Colombier
4577ab27030SDavid du Colombier Bterm(bp);
4587ab27030SDavid du Colombier return;
4597ab27030SDavid du Colombier Error:
4607ab27030SDavid du Colombier fprint(2, "abaco: not enough fontpaths in '%s'\n", buf);
4617ab27030SDavid du Colombier Bterm(bp);
4627ab27030SDavid du Colombier for(i--; i>=0; i--)
4637ab27030SDavid du Colombier free(fontpaths[i]);
4647ab27030SDavid du Colombier Default:
4657ab27030SDavid du Colombier for(i=0; i<NumFnt; i++)
4667ab27030SDavid du Colombier fontpaths[i] = deffontpaths[i];
4677ab27030SDavid du Colombier }
4687ab27030SDavid du Colombier
4697ab27030SDavid du Colombier Font *
getfont(int i)4707ab27030SDavid du Colombier getfont(int i)
4717ab27030SDavid du Colombier {
4727ab27030SDavid du Colombier if(fonts[i] == nil){
4737ab27030SDavid du Colombier fonts[i] = openfont(display, fontpaths[i]);
4747ab27030SDavid du Colombier if(fonts[i] == nil)
4757ab27030SDavid du Colombier error("can't open font file");
4767ab27030SDavid du Colombier }
4777ab27030SDavid du Colombier return fonts[i];
4787ab27030SDavid du Colombier }
4797ab27030SDavid du Colombier
4807ab27030SDavid du Colombier typedef struct Color Color;
4817ab27030SDavid du Colombier
4827ab27030SDavid du Colombier struct Color {
4837ab27030SDavid du Colombier int rgb;
4847ab27030SDavid du Colombier Image *i;
4857ab27030SDavid du Colombier Color *next;
4867ab27030SDavid du Colombier };
4877ab27030SDavid du Colombier
4887ab27030SDavid du Colombier enum {
4897ab27030SDavid du Colombier NHASH = 19,
4907ab27030SDavid du Colombier };
4917ab27030SDavid du Colombier
4927ab27030SDavid du Colombier static Color *colortab[NHASH];
4937ab27030SDavid du Colombier
4947ab27030SDavid du Colombier Image *
getcolor(int rgb)4957ab27030SDavid du Colombier getcolor(int rgb)
4967ab27030SDavid du Colombier {
4977ab27030SDavid du Colombier Color *c;
4987ab27030SDavid du Colombier int h;
4997ab27030SDavid du Colombier
5007ab27030SDavid du Colombier if(rgb == 0xFFFFFF)
5017ab27030SDavid du Colombier return display->white;
5027ab27030SDavid du Colombier else if(rgb == 0x000000)
5037ab27030SDavid du Colombier return display->black;
5047ab27030SDavid du Colombier
5057ab27030SDavid du Colombier h = rgb%NHASH;
5067ab27030SDavid du Colombier for(c=colortab[h]; c!=nil; c=c->next)
5077ab27030SDavid du Colombier if(c->rgb == rgb){
5087ab27030SDavid du Colombier flushimage(display, 0); /* BUG? */
5097ab27030SDavid du Colombier return c->i;
5107ab27030SDavid du Colombier }
5117ab27030SDavid du Colombier c = emalloc(sizeof(Color));
5127ab27030SDavid du Colombier c->i = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, (rgb<<8)|0xFF);
5137ab27030SDavid du Colombier c->rgb = rgb;
5147ab27030SDavid du Colombier c->next = colortab[h];
5157ab27030SDavid du Colombier colortab[h] = c;
5167ab27030SDavid du Colombier
5177ab27030SDavid du Colombier return c->i;
5187ab27030SDavid du Colombier }
5197ab27030SDavid du Colombier
5207ab27030SDavid du Colombier int
plumbrunestr(Runestr * rs,char * attr)5217ab27030SDavid du Colombier plumbrunestr(Runestr *rs, char *attr)
5227ab27030SDavid du Colombier {
5237ab27030SDavid du Colombier Plumbmsg *m;
5247ab27030SDavid du Colombier int i;
5257ab27030SDavid du Colombier
5267ab27030SDavid du Colombier i = -1;
5277ab27030SDavid du Colombier if(plumbsendfd >= 0){
5287ab27030SDavid du Colombier m = emalloc(sizeof(Plumbmsg));
5297ab27030SDavid du Colombier m->src = estrdup("abaco");
5307ab27030SDavid du Colombier m->dst = nil;
5317ab27030SDavid du Colombier m->wdir = estrdup("/tmp");
5327ab27030SDavid du Colombier m->type = estrdup("text");
5337ab27030SDavid du Colombier if(attr)
5347ab27030SDavid du Colombier m->attr = plumbunpackattr(attr);
5357ab27030SDavid du Colombier else
5367ab27030SDavid du Colombier m->attr = nil;
5377ab27030SDavid du Colombier m->data = smprint("%.*S", rs->nr, rs->r);
5387ab27030SDavid du Colombier m->ndata = -1;
5397ab27030SDavid du Colombier i = plumbsend(plumbsendfd, m);
5407ab27030SDavid du Colombier plumbfree(m);
5417ab27030SDavid du Colombier }
5427ab27030SDavid du Colombier return i;
5437ab27030SDavid du Colombier }
5447ab27030SDavid du Colombier
5457ab27030SDavid du Colombier int
hexdigit(int v)5467ab27030SDavid du Colombier hexdigit(int v)
5477ab27030SDavid du Colombier {
5487ab27030SDavid du Colombier if(0<=v && v<=9)
5497ab27030SDavid du Colombier return '0' + v;
5507ab27030SDavid du Colombier else
5517ab27030SDavid du Colombier return 'A' + v - 10;
5527ab27030SDavid du Colombier }
5537ab27030SDavid du Colombier
5547ab27030SDavid du Colombier static int
inclass(char c,Rune * cl)5557ab27030SDavid du Colombier inclass(char c, Rune* cl)
5567ab27030SDavid du Colombier {
5577ab27030SDavid du Colombier int n, ans, negate, i;
5587ab27030SDavid du Colombier
5597ab27030SDavid du Colombier n = runestrlen(cl);
5607ab27030SDavid du Colombier if(n == 0)
5617ab27030SDavid du Colombier return 0;
5627ab27030SDavid du Colombier ans = 0;
5637ab27030SDavid du Colombier negate = 0;
5647ab27030SDavid du Colombier if(cl[0] == '^'){
5657ab27030SDavid du Colombier negate = 1;
5667ab27030SDavid du Colombier cl++;
5677ab27030SDavid du Colombier n--;
5687ab27030SDavid du Colombier }
5697ab27030SDavid du Colombier for(i=0; i<n; i++){
5707ab27030SDavid du Colombier if(cl[i]=='-' && i>0 && i<n-1){
5717ab27030SDavid du Colombier if(c>=cl[i - 1] && c<=cl[i+1]){
5727ab27030SDavid du Colombier ans = 1;
5737ab27030SDavid du Colombier break;
5747ab27030SDavid du Colombier }
5757ab27030SDavid du Colombier i++;
5767ab27030SDavid du Colombier }
5777ab27030SDavid du Colombier else if(c == cl[i]){
5787ab27030SDavid du Colombier ans = 1;
5797ab27030SDavid du Colombier break;
5807ab27030SDavid du Colombier }
5817ab27030SDavid du Colombier }
5827ab27030SDavid du Colombier if(negate)
5837ab27030SDavid du Colombier ans = !ans;
5847ab27030SDavid du Colombier return ans;
5857ab27030SDavid du Colombier }
5867ab27030SDavid du Colombier
5877ab27030SDavid du Colombier Rune*
ucvt(Rune * s)5887ab27030SDavid du Colombier ucvt(Rune* s)
5897ab27030SDavid du Colombier {
5907ab27030SDavid du Colombier Rune* u;
5917ab27030SDavid du Colombier char *t;
5927ab27030SDavid du Colombier int i, c, n, j, len;
5937ab27030SDavid du Colombier
5947ab27030SDavid du Colombier t = smprint("%S", s);
5957ab27030SDavid du Colombier n = strlen(t);
5967ab27030SDavid du Colombier len = 0;
5977ab27030SDavid du Colombier for(i=0; i<n; i++){
5987ab27030SDavid du Colombier c = t[i];
5997ab27030SDavid du Colombier if(inclass(c, L"- /$_@.!*'(),a-zA-Z0-9"))
6007ab27030SDavid du Colombier len++;
6017ab27030SDavid du Colombier else
6027ab27030SDavid du Colombier len += 3;
6037ab27030SDavid du Colombier }
6047ab27030SDavid du Colombier u = runemalloc(len+1);
6057ab27030SDavid du Colombier j = 0;
6067ab27030SDavid du Colombier
6077ab27030SDavid du Colombier for(i=0; i<n; i++){
6087ab27030SDavid du Colombier c = t[i];
6097ab27030SDavid du Colombier if(inclass(c, L"-/$_@.!*'(),a-zA-Z0-9"))
6107ab27030SDavid du Colombier u[j++] = c;
6117ab27030SDavid du Colombier else if(c == ' ')
6127ab27030SDavid du Colombier u[j++] = '+';
6137ab27030SDavid du Colombier else {
6147ab27030SDavid du Colombier u[j++] = '%';
6157ab27030SDavid du Colombier u[j++] = hexdigit((c >> 4)&15);
6167ab27030SDavid du Colombier u[j++] = hexdigit(c&15);
6177ab27030SDavid du Colombier }
6187ab27030SDavid du Colombier }
6197ab27030SDavid du Colombier u[j] = 0;
6207ab27030SDavid du Colombier free(t);
6217ab27030SDavid du Colombier return u;
6227ab27030SDavid du Colombier }
6237ab27030SDavid du Colombier
6247ab27030SDavid du Colombier void
reverseimages(Iimage ** head)6257ab27030SDavid du Colombier reverseimages(Iimage **head)
6267ab27030SDavid du Colombier {
6277ab27030SDavid du Colombier Iimage *r, *c, *n;
6287ab27030SDavid du Colombier
6297ab27030SDavid du Colombier r = nil;
6307ab27030SDavid du Colombier for(c=*head; c!=nil; c=n){
6317ab27030SDavid du Colombier n = c->nextimage;
6327ab27030SDavid du Colombier c->nextimage = r;
6337ab27030SDavid du Colombier r = c;
6347ab27030SDavid du Colombier }
6357ab27030SDavid du Colombier *head = r;
6367ab27030SDavid du Colombier }
6377ab27030SDavid du Colombier
6387ab27030SDavid du Colombier char urlexpr[] = "^(https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|"
6397ab27030SDavid du Colombier "prospero)://([a-zA-Z0-9_@\\-]+([.:][a-zA-Z0-9_@\\-]+)*)";
6407ab27030SDavid du Colombier Reprog *urlprog;
6417ab27030SDavid du Colombier
6427ab27030SDavid du Colombier int
validurl(Rune * r)6437ab27030SDavid du Colombier validurl(Rune *r)
6447ab27030SDavid du Colombier {
6457ab27030SDavid du Colombier Resub rs[10];
6467ab27030SDavid du Colombier
6477ab27030SDavid du Colombier if(urlprog == nil){
6487ab27030SDavid du Colombier urlprog = regcomp(urlexpr);
6497ab27030SDavid du Colombier if(urlprog == nil)
6507ab27030SDavid du Colombier error("regcomp");
6517ab27030SDavid du Colombier }
6527ab27030SDavid du Colombier memset(rs, 0, sizeof(rs));
6537ab27030SDavid du Colombier if(rregexec(urlprog, r, rs, nelem(rs)) == 0)
6547ab27030SDavid du Colombier return FALSE;
6557ab27030SDavid du Colombier return TRUE;
6567ab27030SDavid du Colombier }
6577ab27030SDavid du Colombier
6587ab27030SDavid du Colombier void
execproc(void * v)6597ab27030SDavid du Colombier execproc(void *v)
6607ab27030SDavid du Colombier {
6617ab27030SDavid du Colombier Channel *sync;
6627ab27030SDavid du Colombier Exec *e;
6637ab27030SDavid du Colombier int p[2], q[2];
6647ab27030SDavid du Colombier char *cmd;
6657ab27030SDavid du Colombier
6667ab27030SDavid du Colombier threadsetname("execproc");
6677ab27030SDavid du Colombier e = v;
6687ab27030SDavid du Colombier p[0] = e->p[0];
6697ab27030SDavid du Colombier p[1] = e->p[1];
6707ab27030SDavid du Colombier q[0] = e->q[0];
6717ab27030SDavid du Colombier q[1] = e->q[1];
6727ab27030SDavid du Colombier cmd = e->cmd;
6737ab27030SDavid du Colombier sync = e->sync;
6747ab27030SDavid du Colombier rfork(RFFDG);
6757ab27030SDavid du Colombier free(e);
6767ab27030SDavid du Colombier dup(p[0], 0);
6777ab27030SDavid du Colombier close(p[0]);
6787ab27030SDavid du Colombier close(p[1]);
6797ab27030SDavid du Colombier if(q[0]){
6807ab27030SDavid du Colombier dup(q[1], 1);
6817ab27030SDavid du Colombier close(q[0]);
6827ab27030SDavid du Colombier close(q[1]);
6837ab27030SDavid du Colombier }
6847ab27030SDavid du Colombier if(!procstderr)
6857ab27030SDavid du Colombier close(2);
6867ab27030SDavid du Colombier procexecl(sync, "/bin/rc", "rc", "-c", cmd, 0);
6877ab27030SDavid du Colombier error("can't exec");
6887ab27030SDavid du Colombier }
6897ab27030SDavid du Colombier
6907ab27030SDavid du Colombier static void
writeproc(void * v)6917ab27030SDavid du Colombier writeproc(void *v)
6927ab27030SDavid du Colombier {
6937ab27030SDavid du Colombier Channel *sync;
6947ab27030SDavid du Colombier void **a;
6957ab27030SDavid du Colombier char *s;
6967ab27030SDavid du Colombier long np;
6977ab27030SDavid du Colombier int fd, i, n;
6987ab27030SDavid du Colombier
6997ab27030SDavid du Colombier threadsetname("writeproc");
7007ab27030SDavid du Colombier a = v;
7017ab27030SDavid du Colombier sync = a[0];
702*6872394cSDavid du Colombier fd = (uintptr)a[1];
7037ab27030SDavid du Colombier s = a[2];
704*6872394cSDavid du Colombier np =(uintptr)a[3];
7057ab27030SDavid du Colombier free(a);
7067ab27030SDavid du Colombier
7077ab27030SDavid du Colombier for(i=0; i<np; i+=n){
7087ab27030SDavid du Colombier n = np-i;
7097ab27030SDavid du Colombier if(n > BUFSIZE)
7107ab27030SDavid du Colombier n = BUFSIZE;
7117ab27030SDavid du Colombier if(write(fd, s+i, n) != n)
7127ab27030SDavid du Colombier break;
7137ab27030SDavid du Colombier }
7147ab27030SDavid du Colombier close(fd);
7157ab27030SDavid du Colombier sendul(sync, i);
7167ab27030SDavid du Colombier }
7177ab27030SDavid du Colombier
7187ab27030SDavid du Colombier struct {
7197ab27030SDavid du Colombier char *mime;
7207ab27030SDavid du Colombier char *tcs;
7217ab27030SDavid du Colombier }tcstab[] = {
7227ab27030SDavid du Colombier
7237ab27030SDavid du Colombier #include "tcs.h"
7247ab27030SDavid du Colombier
7257ab27030SDavid du Colombier /* not generated by the script */
7267ab27030SDavid du Colombier "euc_jp", "jis",
7277ab27030SDavid du Colombier "euc_kr", "euc-k",
7287ab27030SDavid du Colombier "windows-874", "tis",
7297ab27030SDavid du Colombier nil, nil,
7307ab27030SDavid du Colombier };
7317ab27030SDavid du Colombier
7327ab27030SDavid du Colombier enum {
7337ab27030SDavid du Colombier Winstart = 127,
7347ab27030SDavid du Colombier Winend = 159
7357ab27030SDavid du Colombier };
7367ab27030SDavid du Colombier
7377ab27030SDavid du Colombier static int winchars[] = {
7387ab27030SDavid du Colombier 8226, /* 8226 is a bullet */
7397ab27030SDavid du Colombier 8226, 8226, 8218, 402, 8222, 8230, 8224, 8225,
7407ab27030SDavid du Colombier 710, 8240, 352, 8249, 338, 8226, 8226, 8226,
7417ab27030SDavid du Colombier 8226, 8216, 8217, 8220, 8221, 8226, 8211, 8212,
7427ab27030SDavid du Colombier 732, 8482, 353, 8250, 339, 8226, 8226, 376
7437ab27030SDavid du Colombier };
7447ab27030SDavid du Colombier
7457ab27030SDavid du Colombier char *
tcs(char * cs,char * s,long * np)7467ab27030SDavid du Colombier tcs(char *cs, char *s, long *np)
7477ab27030SDavid du Colombier {
7487ab27030SDavid du Colombier Channel *sync;
7497ab27030SDavid du Colombier Exec *e;
7507ab27030SDavid du Colombier Rune r;
7517ab27030SDavid du Colombier long i, n;
7527ab27030SDavid du Colombier void **a;
7537ab27030SDavid du Colombier uchar *us;
7547ab27030SDavid du Colombier char buf[BUFSIZE], cmd[50];
7557ab27030SDavid du Colombier char *t, *u;
7567ab27030SDavid du Colombier int p[2], q[2];
7577ab27030SDavid du Colombier
7587ab27030SDavid du Colombier
7597ab27030SDavid du Colombier if(s==nil || *s=='\0' || *np==0){
7607ab27030SDavid du Colombier werrstr("tcs failed: no data");
7617ab27030SDavid du Colombier return s;
7627ab27030SDavid du Colombier }
7637ab27030SDavid du Colombier
7647ab27030SDavid du Colombier if(cs == nil){
7657ab27030SDavid du Colombier werrstr("tcs failed: no charset");
7667ab27030SDavid du Colombier return s;
7677ab27030SDavid du Colombier }
7687ab27030SDavid du Colombier
7697ab27030SDavid du Colombier if(cistrncmp(cs, "utf-8", 5)==0 || cistrncmp(cs, "utf8", 4)==0)
7707ab27030SDavid du Colombier return s;
7717ab27030SDavid du Colombier
7727ab27030SDavid du Colombier for(i=0; tcstab[i].mime!=nil; i++)
7737ab27030SDavid du Colombier if(cistrncmp(cs, tcstab[i].mime, strlen(tcstab[i].mime)) == 0)
7747ab27030SDavid du Colombier break;
7757ab27030SDavid du Colombier
7767ab27030SDavid du Colombier if(tcstab[i].mime == nil){
7777ab27030SDavid du Colombier fprint(2, "abaco: charset: %s not supported\n", cs);
7787ab27030SDavid du Colombier goto latin1;
7797ab27030SDavid du Colombier }
7807ab27030SDavid du Colombier if(cistrcmp(tcstab[i].tcs, "8859-1")==0 || cistrcmp(tcstab[i].tcs, "ascii")==0){
7817ab27030SDavid du Colombier latin1:
7827ab27030SDavid du Colombier n = 0;
7837ab27030SDavid du Colombier for(us=(uchar*)s; *us; us++)
7847ab27030SDavid du Colombier n += runelen(*us);
7857ab27030SDavid du Colombier n++;
7867ab27030SDavid du Colombier t = emalloc(n);
7877ab27030SDavid du Colombier for(us=(uchar*)s, u=t; *us; us++){
7887ab27030SDavid du Colombier if(*us>=Winstart && *us<=Winend)
7897ab27030SDavid du Colombier *u++ = winchars[*us-Winstart];
7907ab27030SDavid du Colombier else{
7917ab27030SDavid du Colombier r = *us;
7927ab27030SDavid du Colombier u += runetochar(u, &r);
7937ab27030SDavid du Colombier }
7947ab27030SDavid du Colombier }
7957ab27030SDavid du Colombier *u = 0;
7967ab27030SDavid du Colombier free(s);
7977ab27030SDavid du Colombier return t;
7987ab27030SDavid du Colombier }
7997ab27030SDavid du Colombier
8007ab27030SDavid du Colombier if(pipe(p)<0 || pipe(q)<0)
8017ab27030SDavid du Colombier error("can't create pipe");
8027ab27030SDavid du Colombier
8037ab27030SDavid du Colombier sync = chancreate(sizeof(ulong), 0);
8047ab27030SDavid du Colombier if(sync == nil)
8057ab27030SDavid du Colombier error("can't create channel");
8067ab27030SDavid du Colombier
8077ab27030SDavid du Colombier snprint(cmd, sizeof cmd, "tcs -f %s", tcstab[i].tcs);
8087ab27030SDavid du Colombier e = emalloc(sizeof(Exec));
8097ab27030SDavid du Colombier e->p[0] = p[0];
8107ab27030SDavid du Colombier e->p[1] = p[1];
8117ab27030SDavid du Colombier e->q[0] = q[0];
8127ab27030SDavid du Colombier e->q[1] = q[1];
8137ab27030SDavid du Colombier e->cmd = cmd;
8147ab27030SDavid du Colombier e->sync = sync;
8157ab27030SDavid du Colombier proccreate(execproc, e, STACK);
8167ab27030SDavid du Colombier recvul(sync);
8177ab27030SDavid du Colombier chanfree(sync);
8187ab27030SDavid du Colombier close(p[0]);
8197ab27030SDavid du Colombier close(q[1]);
8207ab27030SDavid du Colombier
8217ab27030SDavid du Colombier /* in case tcs fails */
8227ab27030SDavid du Colombier t = s;
8237ab27030SDavid du Colombier sync = chancreate(sizeof(ulong), 0);
8247ab27030SDavid du Colombier if(sync == nil)
8257ab27030SDavid du Colombier error("can't create channel");
8267ab27030SDavid du Colombier
8277ab27030SDavid du Colombier a = emalloc(4*sizeof(void *));
8287ab27030SDavid du Colombier a[0] = sync;
8297ab27030SDavid du Colombier a[1] = (void *)p[1];
8307ab27030SDavid du Colombier a[2] = s;
8317ab27030SDavid du Colombier a[3] = (void *)*np;
8327ab27030SDavid du Colombier proccreate(writeproc, a, STACK);
8337ab27030SDavid du Colombier
8347ab27030SDavid du Colombier s = nil;
8357ab27030SDavid du Colombier while((n = read(q[0], buf, sizeof(buf))) > 0){
8367ab27030SDavid du Colombier s = erealloc(s, i+n+1);
8377ab27030SDavid du Colombier memmove(s+i, buf, n);
8387ab27030SDavid du Colombier i += n;
8397ab27030SDavid du Colombier s[i] = '\0';
8407ab27030SDavid du Colombier }
8417ab27030SDavid du Colombier n = recvul(sync);
8427ab27030SDavid du Colombier if(n != *np)
8437ab27030SDavid du Colombier fprint(2, "tcs: did not write %ld; wrote %uld\n", *np, n);
8447ab27030SDavid du Colombier
8457ab27030SDavid du Colombier *np = i;
8467ab27030SDavid du Colombier chanfree(sync);
8477ab27030SDavid du Colombier close(q[0]);
8487ab27030SDavid du Colombier
8497ab27030SDavid du Colombier if(s == nil){
8507ab27030SDavid du Colombier fprint(2, "tcs failed: can't convert charset=%s to %s\n", cs, tcstab[i].tcs);
8517ab27030SDavid du Colombier return t;
8527ab27030SDavid du Colombier }
8537ab27030SDavid du Colombier free(t);
8547ab27030SDavid du Colombier
8557ab27030SDavid du Colombier return s;
8567ab27030SDavid du Colombier }
8577ab27030SDavid du Colombier
8587ab27030SDavid du Colombier static
8597ab27030SDavid du Colombier int
isspace(char c)8607ab27030SDavid du Colombier isspace(char c)
8617ab27030SDavid du Colombier {
8627ab27030SDavid du Colombier return c==' ' || c== '\t' || c=='\r' || c=='\n';
8637ab27030SDavid du Colombier }
8647ab27030SDavid du Colombier
8657ab27030SDavid du Colombier static
8667ab27030SDavid du Colombier int
findctype(char * b,int l,char * keyword,char * s)8677ab27030SDavid du Colombier findctype(char *b, int l, char *keyword, char *s)
8687ab27030SDavid du Colombier {
8697ab27030SDavid du Colombier char *p, *e;
8707ab27030SDavid du Colombier int i;
8717ab27030SDavid du Colombier
8727ab27030SDavid du Colombier p = cistrstr(s, keyword);
8737ab27030SDavid du Colombier if(!p)
8747ab27030SDavid du Colombier return -1;
8757ab27030SDavid du Colombier p += strlen(keyword);
8767ab27030SDavid du Colombier while(*p && isspace(*p))
8777ab27030SDavid du Colombier p++;
8787ab27030SDavid du Colombier if(*p != '=')
8797ab27030SDavid du Colombier return -1;
8807ab27030SDavid du Colombier p++;
8817ab27030SDavid du Colombier while(*p && isspace(*p))
8827ab27030SDavid du Colombier p++;
8837ab27030SDavid du Colombier if(!*p)
8847ab27030SDavid du Colombier return -1;
8857ab27030SDavid du Colombier if(*p == '"'){
8867ab27030SDavid du Colombier p++;
8877ab27030SDavid du Colombier e = strchr(p, '"');
8887ab27030SDavid du Colombier if(!e)
8897ab27030SDavid du Colombier return -1;
8907ab27030SDavid du Colombier }else
8917ab27030SDavid du Colombier for(e = p; *e < 127 && *e > ' ' ; e++)
8927ab27030SDavid du Colombier ;
8937ab27030SDavid du Colombier i = e-p;
8947ab27030SDavid du Colombier if(i < 1)
8957ab27030SDavid du Colombier return -1;
8967ab27030SDavid du Colombier snprint(b, l, "%.*s", i, p);
8977ab27030SDavid du Colombier return 0;
8987ab27030SDavid du Colombier }
8997ab27030SDavid du Colombier
9007ab27030SDavid du Colombier static
9017ab27030SDavid du Colombier int
finddocctype(char * b,int l,char * s)9027ab27030SDavid du Colombier finddocctype(char *b, int l, char *s)
9037ab27030SDavid du Colombier {
9047ab27030SDavid du Colombier char *p, *e;
9057ab27030SDavid du Colombier
9067ab27030SDavid du Colombier p = cistrstr(s, "<meta");
9077ab27030SDavid du Colombier if(!p)
9087ab27030SDavid du Colombier return -1;
9097ab27030SDavid du Colombier p += 5;
9107ab27030SDavid du Colombier e = strchr(s, '>');
9117ab27030SDavid du Colombier if(!e)
9127ab27030SDavid du Colombier return -1;
9137ab27030SDavid du Colombier snprint(b, l, "%.*s", (int)(e-p), p);
9147ab27030SDavid du Colombier return 0;
9157ab27030SDavid du Colombier }
9167ab27030SDavid du Colombier
9177ab27030SDavid du Colombier static
9187ab27030SDavid du Colombier int
findxmltype(char * b,int l,char * s)9197ab27030SDavid du Colombier findxmltype(char *b, int l, char *s)
9207ab27030SDavid du Colombier {
9217ab27030SDavid du Colombier char *p, *e;
9227ab27030SDavid du Colombier
9237ab27030SDavid du Colombier p = cistrstr(s, "<?xml ");
9247ab27030SDavid du Colombier if(!p)
9257ab27030SDavid du Colombier return -1;
9267ab27030SDavid du Colombier
9277ab27030SDavid du Colombier p += 6;
9287ab27030SDavid du Colombier e = strstr(p, "?>");
9297ab27030SDavid du Colombier if(!e)
9307ab27030SDavid du Colombier return -1;
9317ab27030SDavid du Colombier snprint(b, l, "%.*s", (int)(e-p), p);
9327ab27030SDavid du Colombier
9337ab27030SDavid du Colombier return 0;
9347ab27030SDavid du Colombier }
9357ab27030SDavid du Colombier
9367ab27030SDavid du Colombier /*
9377ab27030SDavid du Colombier * servers can lie about lie about the charset,
9387ab27030SDavid du Colombier * so we use the charset based on the priority.
9397ab27030SDavid du Colombier */
9407ab27030SDavid du Colombier char *
convert(Runestr ctype,char * s,long * np)9417ab27030SDavid du Colombier convert(Runestr ctype, char *s, long *np)
9427ab27030SDavid du Colombier {
9437ab27030SDavid du Colombier char t[25], buf[256];
9447ab27030SDavid du Colombier
9457ab27030SDavid du Colombier *t = '\0';
9467ab27030SDavid du Colombier if(ctype.nr){
9477ab27030SDavid du Colombier snprint(buf, sizeof(buf), "%.*S", ctype.nr, ctype.r);
9487ab27030SDavid du Colombier findctype(t, sizeof(t), "charset", buf);
9497ab27030SDavid du Colombier }
9507ab27030SDavid du Colombier if(findxmltype(buf, sizeof(buf), s)==0)
9517ab27030SDavid du Colombier findctype(t, sizeof(t), "encoding", buf);
9527ab27030SDavid du Colombier if(finddocctype(buf, sizeof(buf), s) == 0)
9537ab27030SDavid du Colombier findctype(t, sizeof(t), "charset", buf);
9547ab27030SDavid du Colombier
9557ab27030SDavid du Colombier if(*t == '\0')
9567ab27030SDavid du Colombier strcpy(t, charset);
9577ab27030SDavid du Colombier return tcs(t, s, np);
9587ab27030SDavid du Colombier }
9597ab27030SDavid du Colombier
9607ab27030SDavid du Colombier int
xtofchar(Rune * s,Font * f,long p)9617ab27030SDavid du Colombier xtofchar(Rune *s, Font *f, long p)
9627ab27030SDavid du Colombier {
9637ab27030SDavid du Colombier Rune *r;
9647ab27030SDavid du Colombier int q;
9657ab27030SDavid du Colombier
9667ab27030SDavid du Colombier if(p == 0)
9677ab27030SDavid du Colombier return 0;
9687ab27030SDavid du Colombier
9697ab27030SDavid du Colombier q = 0;
9707ab27030SDavid du Colombier for(r=s; *r!=L'\0'; r++){
9717ab27030SDavid du Colombier p -= runestringnwidth(f, r, 1);
9727ab27030SDavid du Colombier if(p < 0)
9737ab27030SDavid du Colombier break;
9747ab27030SDavid du Colombier q++;
9757ab27030SDavid du Colombier }
9767ab27030SDavid du Colombier return q;
9777ab27030SDavid du Colombier }
9787ab27030SDavid du Colombier
9797ab27030SDavid du Colombier int
istextsel(Page * p,Rectangle r,int * q0,int * q1,Rune * s,Font * f)9807ab27030SDavid du Colombier istextsel(Page *p, Rectangle r, int *q0, int *q1, Rune *s, Font *f)
9817ab27030SDavid du Colombier {
9827ab27030SDavid du Colombier int topinr, botinr;
9837ab27030SDavid du Colombier
9847ab27030SDavid du Colombier *q0 = *q1 = 0;
9857ab27030SDavid du Colombier topinr= ptinrect(p->top, r);
9867ab27030SDavid du Colombier if(topinr || (r.min.y>p->top.y && r.max.y<p->bot.y))
9877ab27030SDavid du Colombier p->selecting = TRUE;
9887ab27030SDavid du Colombier botinr = ptinrect(p->bot, r);
9897ab27030SDavid du Colombier if(botinr || r.min.y>p->bot.y)
9907ab27030SDavid du Colombier p->selecting = FALSE;
9917ab27030SDavid du Colombier
9927ab27030SDavid du Colombier if(topinr || botinr){
9937ab27030SDavid du Colombier if(topinr)
9947ab27030SDavid du Colombier *q0 = xtofchar(s, f, p->top.x-r.min.x);
9957ab27030SDavid du Colombier if(botinr)
9967ab27030SDavid du Colombier *q1 = xtofchar(s, f, p->bot.x-r.min.x);
9977ab27030SDavid du Colombier if(*q0!=0 || *q1!=0)
9987ab27030SDavid du Colombier return TRUE;
9997ab27030SDavid du Colombier }
10007ab27030SDavid du Colombier return p->selecting;
10017ab27030SDavid du Colombier }
10027ab27030SDavid du Colombier
10037ab27030SDavid du Colombier Point
getpt(Page * p,Point xy)10047ab27030SDavid du Colombier getpt(Page *p, Point xy)
10057ab27030SDavid du Colombier {
10067ab27030SDavid du Colombier xy.x = xy.x-p->r.min.x+p->pos.x;
10077ab27030SDavid du Colombier xy.y = xy.y-p->r.min.y+p->pos.y;
10087ab27030SDavid du Colombier
10097ab27030SDavid du Colombier return xy;
10107ab27030SDavid du Colombier }
10117ab27030SDavid du Colombier
10127ab27030SDavid du Colombier void
getimage(Cimage * ci,Rune * altr)10137ab27030SDavid du Colombier getimage(Cimage *ci, Rune *altr)
10147ab27030SDavid du Colombier {
10157ab27030SDavid du Colombier Rectangle r;
10167ab27030SDavid du Colombier Memimage *mi;
10177ab27030SDavid du Colombier Image *i, *i2;
10187ab27030SDavid du Colombier char buf[128];
10197ab27030SDavid du Colombier uchar *bits;
10207ab27030SDavid du Colombier int nbits;
10217ab27030SDavid du Colombier
10227ab27030SDavid du Colombier mi = ci->mi;
10237ab27030SDavid du Colombier if(mi == nil){
10247ab27030SDavid du Colombier snprint(buf, sizeof(buf), "[%S]", altr ? altr : L"IMG");
10257ab27030SDavid du Colombier r.min = Pt(0, 0);
10267ab27030SDavid du Colombier r.max.x = 2*Space + stringwidth(font, buf);
10277ab27030SDavid du Colombier r.max.y = 2*Space + font->height;
10287ab27030SDavid du Colombier ci->i = eallocimage(display, r, GREY1, 1, DBlack);
10297ab27030SDavid du Colombier r.min.x += Space;
10307ab27030SDavid du Colombier r.min.y += Space;
10317ab27030SDavid du Colombier string(ci->i, r.min, display->white, ZP, font, buf);
10327ab27030SDavid du Colombier return;
10337ab27030SDavid du Colombier }
10347ab27030SDavid du Colombier nbits = bytesperline(mi->r, mi->depth)*Dy(mi->r);
10357ab27030SDavid du Colombier bits = emalloc(nbits);
10367ab27030SDavid du Colombier unloadmemimage(mi, mi->r, bits, nbits);
10377ab27030SDavid du Colombier /*
10387ab27030SDavid du Colombier /* get rid of alpha channel from transparent gif * /
10397ab27030SDavid du Colombier
10407ab27030SDavid du Colombier if(mi->depth == 16){
10417ab27030SDavid du Colombier for(y=1; y<nbits; y+=2)
10427ab27030SDavid du Colombier bits[y>>1] = bits[y];
10437ab27030SDavid du Colombier }
10447ab27030SDavid du Colombier */
10457ab27030SDavid du Colombier i = eallocimage(display, mi->r, mi->chan, 0, DNofill);
10467ab27030SDavid du Colombier loadimage(i, i->r, bits, nbits);
10477ab27030SDavid du Colombier i2 = eallocimage(display, i->r, RGB24, 1, DNofill);
10487ab27030SDavid du Colombier draw(i2, i2->r, display->black, nil, ZP);
10497ab27030SDavid du Colombier draw(i2, i2->r, i, nil, i->r.min);
10507ab27030SDavid du Colombier free(bits);
10517ab27030SDavid du Colombier freememimage(mi);
10527ab27030SDavid du Colombier freeimage(i);
10537ab27030SDavid du Colombier ci->i = i2;
10547ab27030SDavid du Colombier ci->mi = nil;
10557ab27030SDavid du Colombier }
10567ab27030SDavid du Colombier
10577ab27030SDavid du Colombier static
10587ab27030SDavid du Colombier void
fixtext1(Item ** list)10597ab27030SDavid du Colombier fixtext1(Item **list)
10607ab27030SDavid du Colombier {
10617ab27030SDavid du Colombier Itext *text, *ntext;
10627ab27030SDavid du Colombier Item *it, *prev;
10637ab27030SDavid du Colombier Rune *s, *s1, *s2;
10647ab27030SDavid du Colombier int n;
10657ab27030SDavid du Colombier
10667ab27030SDavid du Colombier if(*list == nil)
10677ab27030SDavid du Colombier return;
10687ab27030SDavid du Colombier
10697ab27030SDavid du Colombier prev = nil;
10707ab27030SDavid du Colombier for(it=*list; it!=nil; it=prev->next){
10717ab27030SDavid du Colombier if(it->tag!=Itexttag || forceitem(it))
10727ab27030SDavid du Colombier goto Continue;
10737ab27030SDavid du Colombier
10747ab27030SDavid du Colombier text = (Itext *)it;
10757ab27030SDavid du Colombier s = text->s;
10767ab27030SDavid du Colombier while(*s && isspacerune(*s))
10777ab27030SDavid du Colombier s++;
10787ab27030SDavid du Colombier if(!*s){
10797ab27030SDavid du Colombier if(prev == nil)
10807ab27030SDavid du Colombier prev = *list = it->next;
10817ab27030SDavid du Colombier else
10827ab27030SDavid du Colombier prev->next = it->next;
10837ab27030SDavid du Colombier
10847ab27030SDavid du Colombier it->next = nil;
10857ab27030SDavid du Colombier freeitems(it);
10867ab27030SDavid du Colombier if(prev == nil)
10877ab27030SDavid du Colombier return;
10887ab27030SDavid du Colombier continue;
10897ab27030SDavid du Colombier }
10907ab27030SDavid du Colombier n = 0;
10917ab27030SDavid du Colombier while(s[n] && !isspacerune(s[n]))
10927ab27030SDavid du Colombier n++;
10937ab27030SDavid du Colombier
10947ab27030SDavid du Colombier if(!s[n])
10957ab27030SDavid du Colombier goto Continue;
10967ab27030SDavid du Colombier
10977ab27030SDavid du Colombier s1 = runemalloc(n+1);
10987ab27030SDavid du Colombier s1 = runemove(s1, s, n);
10997ab27030SDavid du Colombier s1[n] = L'\0';
11007ab27030SDavid du Colombier s += n;
11017ab27030SDavid du Colombier
11027ab27030SDavid du Colombier while(*s && isspacerune(*s))
11037ab27030SDavid du Colombier s++;
11047ab27030SDavid du Colombier
11057ab27030SDavid du Colombier if(*s){
11067ab27030SDavid du Colombier n = runestrlen(s);
11077ab27030SDavid du Colombier s2 = runemalloc(n+1);
11087ab27030SDavid du Colombier runemove(s2, s, n);
11097ab27030SDavid du Colombier s2[n] = L'\0';
11107ab27030SDavid du Colombier ntext = emalloc(sizeof(Itext));
11117ab27030SDavid du Colombier ntext->s = s2;
11127ab27030SDavid du Colombier ntext->ascent = text->ascent;
11137ab27030SDavid du Colombier ntext->anchorid = text->anchorid;
11147ab27030SDavid du Colombier ntext->state = text->state&~(IFbrk|IFbrksp|IFnobrk|IFcleft|IFcright);
11157ab27030SDavid du Colombier ntext->tag = text->tag;
11167ab27030SDavid du Colombier ntext->fnt = text->fnt;
11177ab27030SDavid du Colombier ntext->fg = text->fg;
11187ab27030SDavid du Colombier ntext->ul = text->ul;
11197ab27030SDavid du Colombier ntext->next = (Item *)text->next;
11207ab27030SDavid du Colombier text->next = (Item *)ntext;
11217ab27030SDavid du Colombier }
11227ab27030SDavid du Colombier free(text->s);
11237ab27030SDavid du Colombier text->s = s1;
11247ab27030SDavid du Colombier Continue:
11257ab27030SDavid du Colombier prev = it;
11267ab27030SDavid du Colombier }
11277ab27030SDavid du Colombier }
11287ab27030SDavid du Colombier
11297ab27030SDavid du Colombier void
fixtext(Page * p)11307ab27030SDavid du Colombier fixtext(Page *p)
11317ab27030SDavid du Colombier {
11327ab27030SDavid du Colombier Tablecell *c;
11337ab27030SDavid du Colombier Table *t;
11347ab27030SDavid du Colombier
11357ab27030SDavid du Colombier fixtext1(&p->items);
11367ab27030SDavid du Colombier for(t=p->doc->tables; t!=nil; t=t->next)
11377ab27030SDavid du Colombier for(c=t->cells; c!=nil; c=c->next)
11387ab27030SDavid du Colombier fixtext1(&c->content);
11397ab27030SDavid du Colombier }
11407ab27030SDavid du Colombier
11417ab27030SDavid du Colombier typedef struct Refresh Refresh;
11427ab27030SDavid du Colombier
11437ab27030SDavid du Colombier struct Refresh
11447ab27030SDavid du Colombier {
11457ab27030SDavid du Colombier Page *p;
11467ab27030SDavid du Colombier Refresh *next;
11477ab27030SDavid du Colombier };
11487ab27030SDavid du Colombier
11497ab27030SDavid du Colombier static Refresh *refreshs = nil;
11507ab27030SDavid du Colombier static QLock refreshlock;
11517ab27030SDavid du Colombier
11527ab27030SDavid du Colombier void
addrefresh(Page * p,char * fmt,...)11537ab27030SDavid du Colombier addrefresh(Page *p, char *fmt, ...)
11547ab27030SDavid du Colombier {
11557ab27030SDavid du Colombier Refresh *r;
11567ab27030SDavid du Colombier Rune *s;
11577ab27030SDavid du Colombier va_list arg;
11587ab27030SDavid du Colombier
11597ab27030SDavid du Colombier if(p->aborting)
11607ab27030SDavid du Colombier return;
11617ab27030SDavid du Colombier
11627ab27030SDavid du Colombier va_start(arg, fmt);
11637ab27030SDavid du Colombier s = runevsmprint(fmt, arg);
11647ab27030SDavid du Colombier va_end(arg);
11657ab27030SDavid du Colombier if(s == nil)
11667ab27030SDavid du Colombier error("runevsmprint failed");
11677ab27030SDavid du Colombier
11687ab27030SDavid du Colombier if(p->status){
11697ab27030SDavid du Colombier free(p->status);
11707ab27030SDavid du Colombier p->status = nil;
11717ab27030SDavid du Colombier }
11727ab27030SDavid du Colombier p->status = s;
11737ab27030SDavid du Colombier qlock(&refreshlock);
11747ab27030SDavid du Colombier for(r=refreshs; r!=nil; r=r->next)
11757ab27030SDavid du Colombier if(r->p == p)
11767ab27030SDavid du Colombier goto Return;
11777ab27030SDavid du Colombier
11787ab27030SDavid du Colombier incref(p->w); /* flushrefresh will decref */
11797ab27030SDavid du Colombier r = emalloc(sizeof(Refresh));
11807ab27030SDavid du Colombier r->p = p;
11817ab27030SDavid du Colombier r->next = refreshs;
11827ab27030SDavid du Colombier refreshs = r;
11837ab27030SDavid du Colombier
11847ab27030SDavid du Colombier Return:
11857ab27030SDavid du Colombier nbsendp(crefresh, nil);
11867ab27030SDavid du Colombier qunlock(&refreshlock);
11877ab27030SDavid du Colombier }
11887ab27030SDavid du Colombier
11897ab27030SDavid du Colombier /* called while row is locked */
11907ab27030SDavid du Colombier void
flushrefresh(void)11917ab27030SDavid du Colombier flushrefresh(void)
11927ab27030SDavid du Colombier {
11937ab27030SDavid du Colombier Refresh *r, *next;
11947ab27030SDavid du Colombier Page *p;
11957ab27030SDavid du Colombier
11967ab27030SDavid du Colombier qlock(&refreshlock);
11977ab27030SDavid du Colombier for(r=refreshs; r!=nil; r=next){
11987ab27030SDavid du Colombier p = r->p;
11997ab27030SDavid du Colombier if(p->changed==TRUE && p->aborting==FALSE){
12007ab27030SDavid du Colombier p->changed = FALSE;
12017ab27030SDavid du Colombier if(p->parent==nil || p->loading==FALSE)
12027ab27030SDavid du Colombier pagerender(p);
12037ab27030SDavid du Colombier if(!p->refresh.t)
12047ab27030SDavid du Colombier pagesetrefresh(p);
12057ab27030SDavid du Colombier }
12067ab27030SDavid du Colombier if(p->status){
12077ab27030SDavid du Colombier winsetstatus(p->w, p->status);
12087ab27030SDavid du Colombier free(p->status);
12097ab27030SDavid du Colombier p->status = nil;
12107ab27030SDavid du Colombier }
12117ab27030SDavid du Colombier winseturl(p->w);
12127ab27030SDavid du Colombier winsettag(p->w);
12137ab27030SDavid du Colombier decref(p->w);
12147ab27030SDavid du Colombier next = r->next;
12157ab27030SDavid du Colombier free(r);
12167ab27030SDavid du Colombier }
12177ab27030SDavid du Colombier refreshs = nil;
12187ab27030SDavid du Colombier qunlock(&refreshlock);
12197ab27030SDavid du Colombier }
12207ab27030SDavid du Colombier
12217ab27030SDavid du Colombier void
savemouse(Window * w)12227ab27030SDavid du Colombier savemouse(Window *w)
12237ab27030SDavid du Colombier {
12247ab27030SDavid du Colombier prevmouse = mouse->xy;
12257ab27030SDavid du Colombier mousew = w;
12267ab27030SDavid du Colombier }
12277ab27030SDavid du Colombier
12287ab27030SDavid du Colombier void
restoremouse(Window * w)12297ab27030SDavid du Colombier restoremouse(Window *w)
12307ab27030SDavid du Colombier {
12317ab27030SDavid du Colombier if(mousew!=nil && mousew==w)
12327ab27030SDavid du Colombier moveto(mousectl, prevmouse);
12337ab27030SDavid du Colombier mousew = nil;
12347ab27030SDavid du Colombier }
12357ab27030SDavid du Colombier
12367ab27030SDavid du Colombier void
clearmouse()12377ab27030SDavid du Colombier clearmouse()
12387ab27030SDavid du Colombier {
12397ab27030SDavid du Colombier mousew = nil;
12407ab27030SDavid du Colombier }
12417ab27030SDavid du Colombier
12427ab27030SDavid du Colombier /*
12437ab27030SDavid du Colombier * Heuristic city.
12447ab27030SDavid du Colombier */
12457ab27030SDavid du Colombier Window*
makenewwindow(Page * p)12467ab27030SDavid du Colombier makenewwindow(Page *p)
12477ab27030SDavid du Colombier {
12487ab27030SDavid du Colombier Column *c;
12497ab27030SDavid du Colombier Window *w, *bigw, *emptyw;
12507ab27030SDavid du Colombier Page *emptyp;
12517ab27030SDavid du Colombier int i, y, el;
12527ab27030SDavid du Colombier
12537ab27030SDavid du Colombier if(activecol)
12547ab27030SDavid du Colombier c = activecol;
12557ab27030SDavid du Colombier else if(selpage && selpage->col)
12567ab27030SDavid du Colombier c = selpage->col;
12577ab27030SDavid du Colombier else if(p && p->col)
12587ab27030SDavid du Colombier c = p->col;
12597ab27030SDavid du Colombier else{
12607ab27030SDavid du Colombier if(row.ncol==0 && rowadd(&row, nil, -1)==nil)
12617ab27030SDavid du Colombier error("can't make column");
12627ab27030SDavid du Colombier c = row.col[row.ncol-1];
12637ab27030SDavid du Colombier }
12647ab27030SDavid du Colombier activecol = c;
12657ab27030SDavid du Colombier if(p==nil || p->w==nil || c->nw==0)
12667ab27030SDavid du Colombier return coladd(c, nil, nil, -1);
12677ab27030SDavid du Colombier
12687ab27030SDavid du Colombier /* find biggest window and biggest blank spot */
12697ab27030SDavid du Colombier emptyw = c->w[0];
12707ab27030SDavid du Colombier bigw = emptyw;
12717ab27030SDavid du Colombier for(i=1; i<c->nw; i++){
12727ab27030SDavid du Colombier w = c->w[i];
12737ab27030SDavid du Colombier /* use >= to choose one near bottom of screen */
12747ab27030SDavid du Colombier if(Dy(w->page.all) >= Dy(bigw->page.all))
12757ab27030SDavid du Colombier bigw = w;
12767ab27030SDavid du Colombier if(w->page.lay==nil && Dy(w->page.all) >= Dy(emptyw->page.all))
12777ab27030SDavid du Colombier emptyw = w;
12787ab27030SDavid du Colombier }
12797ab27030SDavid du Colombier emptyp = &emptyw->page;
12807ab27030SDavid du Colombier el = Dy(emptyp->all);
12817ab27030SDavid du Colombier /* if empty space is big, use it */
12827ab27030SDavid du Colombier if(el>15 || (el>3 && el>(Dy(bigw->page.all)-1)/2))
12837ab27030SDavid du Colombier y = emptyp->all.max.y;
12847ab27030SDavid du Colombier else{
12857ab27030SDavid du Colombier /* if this window is in column and isn't much smaller, split it */
12867ab27030SDavid du Colombier if(p->col==c && Dy(p->w->r)>2*Dy(bigw->r)/3)
12877ab27030SDavid du Colombier bigw = p->w;
12887ab27030SDavid du Colombier y = (bigw->r.min.y + bigw->r.max.y)/2;
12897ab27030SDavid du Colombier }
12907ab27030SDavid du Colombier w = coladd(c, nil, nil, y);
12917ab27030SDavid du Colombier colgrow(w->col, w, 1);
12927ab27030SDavid du Colombier return w;
12937ab27030SDavid du Colombier }
1294