137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include <kernel.h>
337da2899SCharles.Forsyth #include "draw.h"
437da2899SCharles.Forsyth #include "tk.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
737da2899SCharles.Forsyth
837da2899SCharles.Forsyth char* tkimgbmcreate(TkTop*, char*, int, char**);
937da2899SCharles.Forsyth char* tkimgbmdel(TkImg*);
1037da2899SCharles.Forsyth void tkimgbmfree(TkImg*);
1137da2899SCharles.Forsyth
1237da2899SCharles.Forsyth static Rectangle huger = { -1000000, -1000000, 1000000, 1000000 };
1337da2899SCharles.Forsyth
1437da2899SCharles.Forsyth typedef struct TkImgtype TkImgtype;
1537da2899SCharles.Forsyth struct TkImgtype
1637da2899SCharles.Forsyth {
1737da2899SCharles.Forsyth char* type;
1837da2899SCharles.Forsyth char* (*create)(TkTop*, char*, int, char**);
1937da2899SCharles.Forsyth char* (*delete)(TkImg*);
2037da2899SCharles.Forsyth void (*destroy)(TkImg*);
2137da2899SCharles.Forsyth } tkimgopts[] =
2237da2899SCharles.Forsyth {
2337da2899SCharles.Forsyth "bitmap", tkimgbmcreate, tkimgbmdel, tkimgbmfree,
2437da2899SCharles.Forsyth nil,
2537da2899SCharles.Forsyth };
2637da2899SCharles.Forsyth
2737da2899SCharles.Forsyth typedef struct Imgargs Imgargs;
2837da2899SCharles.Forsyth struct Imgargs {
2937da2899SCharles.Forsyth Image* fgimg;
3037da2899SCharles.Forsyth Image* maskimg;
3137da2899SCharles.Forsyth };
3237da2899SCharles.Forsyth
3337da2899SCharles.Forsyth TkImg*
tkname2img(TkTop * t,char * name)3437da2899SCharles.Forsyth tkname2img(TkTop *t, char *name)
3537da2899SCharles.Forsyth {
3637da2899SCharles.Forsyth TkImg *tki;
3737da2899SCharles.Forsyth
3837da2899SCharles.Forsyth for(tki = t->imgs; tki; tki = tki->link)
3937da2899SCharles.Forsyth if((tki->name != nil) && strcmp(tki->name->name, name) == 0)
4037da2899SCharles.Forsyth return tki;
4137da2899SCharles.Forsyth
4237da2899SCharles.Forsyth return nil;
4337da2899SCharles.Forsyth }
4437da2899SCharles.Forsyth
4537da2899SCharles.Forsyth TkOption
4637da2899SCharles.Forsyth bitopt[] =
4737da2899SCharles.Forsyth {
4837da2899SCharles.Forsyth "file", OPTbmap, O(Imgargs, fgimg), nil,
4937da2899SCharles.Forsyth "maskfile", OPTbmap, O(Imgargs, maskimg), nil,
5037da2899SCharles.Forsyth nil
5137da2899SCharles.Forsyth };
5237da2899SCharles.Forsyth
5337da2899SCharles.Forsyth void
tksizeimage(Tk * tk,TkImg * tki)5437da2899SCharles.Forsyth tksizeimage(Tk *tk, TkImg *tki)
5537da2899SCharles.Forsyth {
5637da2899SCharles.Forsyth int dx, dy, repack;
5737da2899SCharles.Forsyth
5837da2899SCharles.Forsyth dx = 0;
5937da2899SCharles.Forsyth dy = 0;
6037da2899SCharles.Forsyth if(tki->img != nil) {
6137da2899SCharles.Forsyth dx = Dx(tki->img->r);
6237da2899SCharles.Forsyth dy = Dy(tki->img->r);
6337da2899SCharles.Forsyth }
6437da2899SCharles.Forsyth repack = 0;
6537da2899SCharles.Forsyth if(tki->ref > 1 && (tki->w != dx || tki->h != dy))
6637da2899SCharles.Forsyth repack = 1;
6737da2899SCharles.Forsyth tki->w = dx;
6837da2899SCharles.Forsyth tki->h = dy;
6937da2899SCharles.Forsyth
7037da2899SCharles.Forsyth if(repack) {
7137da2899SCharles.Forsyth tkpackqit(tk);
7237da2899SCharles.Forsyth tkrunpack(tk->env->top);
7337da2899SCharles.Forsyth }
7437da2899SCharles.Forsyth }
7537da2899SCharles.Forsyth
7637da2899SCharles.Forsyth char*
tkimgbmcreate(TkTop * t,char * arg,int type,char ** ret)7737da2899SCharles.Forsyth tkimgbmcreate(TkTop *t, char *arg, int type, char **ret)
7837da2899SCharles.Forsyth {
7937da2899SCharles.Forsyth TkName *names;
8037da2899SCharles.Forsyth TkImg *tki, *f;
8137da2899SCharles.Forsyth TkOptab tko[2];
8237da2899SCharles.Forsyth char buf[32];
8337da2899SCharles.Forsyth static int id;
8437da2899SCharles.Forsyth char *e = nil;
8537da2899SCharles.Forsyth Imgargs iargs;
8637da2899SCharles.Forsyth Rectangle r;
8737da2899SCharles.Forsyth Display *d;
8837da2899SCharles.Forsyth int chan;
8937da2899SCharles.Forsyth int locked;
9037da2899SCharles.Forsyth
9137da2899SCharles.Forsyth d = t->display;
9237da2899SCharles.Forsyth locked = 0;
9337da2899SCharles.Forsyth
9437da2899SCharles.Forsyth tki = malloc(sizeof(TkImg));
9537da2899SCharles.Forsyth if(tki == nil)
9637da2899SCharles.Forsyth return TkNomem;
9737da2899SCharles.Forsyth
9837da2899SCharles.Forsyth tki->env = tkdefaultenv(t);
9937da2899SCharles.Forsyth if(tki->env == nil)
10037da2899SCharles.Forsyth goto err;
10137da2899SCharles.Forsyth tki->type = type;
10237da2899SCharles.Forsyth tki->ref = 1;
10337da2899SCharles.Forsyth tki->top = t;
10437da2899SCharles.Forsyth
10537da2899SCharles.Forsyth iargs.fgimg = nil;
10637da2899SCharles.Forsyth iargs.maskimg = nil;
10737da2899SCharles.Forsyth
10837da2899SCharles.Forsyth tko[0].ptr = &iargs;
10937da2899SCharles.Forsyth tko[0].optab = bitopt;
11037da2899SCharles.Forsyth tko[1].ptr = nil;
11137da2899SCharles.Forsyth
11237da2899SCharles.Forsyth names = nil;
11337da2899SCharles.Forsyth e = tkparse(t, arg, tko, &names);
11437da2899SCharles.Forsyth if(e != nil)
11537da2899SCharles.Forsyth goto err;
11637da2899SCharles.Forsyth
11737da2899SCharles.Forsyth if (iargs.fgimg == nil && iargs.maskimg != nil) {
11837da2899SCharles.Forsyth locked = lockdisplay(d);
11937da2899SCharles.Forsyth r = Rect(0, 0, Dx(iargs.maskimg->r), Dy(iargs.maskimg->r));
12037da2899SCharles.Forsyth tki->img = allocimage(d, r, CHAN2(CAlpha, 8, CGrey, 8), 0, DTransparent);
12137da2899SCharles.Forsyth if (tki->img != nil)
12237da2899SCharles.Forsyth draw(tki->img, r, nil, iargs.maskimg, iargs.maskimg->r.min);
12337da2899SCharles.Forsyth freeimage(iargs.maskimg);
12437da2899SCharles.Forsyth
12537da2899SCharles.Forsyth } else if (iargs.fgimg != nil && iargs.maskimg != nil) {
12637da2899SCharles.Forsyth locked = lockdisplay(d);
12737da2899SCharles.Forsyth r = Rect(0, 0, Dx(iargs.fgimg->r), Dy(iargs.fgimg->r));
12837da2899SCharles.Forsyth if (tkchanhastype(iargs.fgimg->chan, CGrey))
12937da2899SCharles.Forsyth chan = CHAN2(CAlpha, 8, CGrey, 8);
13037da2899SCharles.Forsyth else
13137da2899SCharles.Forsyth chan = RGBA32;
13237da2899SCharles.Forsyth tki->img = allocimage(d, r, chan, 0, DTransparent);
13337da2899SCharles.Forsyth if (tki->img != nil)
13437da2899SCharles.Forsyth draw(tki->img, r, iargs.fgimg, iargs.maskimg, iargs.fgimg->r.min);
13537da2899SCharles.Forsyth freeimage(iargs.fgimg);
13637da2899SCharles.Forsyth freeimage(iargs.maskimg);
13737da2899SCharles.Forsyth } else {
13837da2899SCharles.Forsyth tki->img = iargs.fgimg;
13937da2899SCharles.Forsyth }
14037da2899SCharles.Forsyth if (locked)
14137da2899SCharles.Forsyth unlockdisplay(d);
14237da2899SCharles.Forsyth
14337da2899SCharles.Forsyth if(names == nil) {
14437da2899SCharles.Forsyth sprint(buf, "image%d", id++);
14537da2899SCharles.Forsyth tki->name = tkmkname(buf);
14637da2899SCharles.Forsyth if(tki->name == nil)
14737da2899SCharles.Forsyth goto err;
14837da2899SCharles.Forsyth }
14937da2899SCharles.Forsyth else {
15037da2899SCharles.Forsyth /* XXX should mark as dirty any widgets using the named
15137da2899SCharles.Forsyth * image - some notification scheme needs putting in place
15237da2899SCharles.Forsyth */
15337da2899SCharles.Forsyth tki->name = names;
15437da2899SCharles.Forsyth tkfreename(names->link);
15537da2899SCharles.Forsyth names->link = nil;
15637da2899SCharles.Forsyth }
15737da2899SCharles.Forsyth
15837da2899SCharles.Forsyth tksizeimage(t->root, tki);
15937da2899SCharles.Forsyth
16037da2899SCharles.Forsyth if (tki->name != nil) {
16137da2899SCharles.Forsyth f = tkname2img(t, tki->name->name);
16237da2899SCharles.Forsyth if(f != nil)
16337da2899SCharles.Forsyth tkimgopts[f->type].delete(f);
16437da2899SCharles.Forsyth }
16537da2899SCharles.Forsyth
16637da2899SCharles.Forsyth tki->link = t->imgs;
16737da2899SCharles.Forsyth t->imgs = tki;
16837da2899SCharles.Forsyth
16937da2899SCharles.Forsyth if (tki->name != nil) {
17037da2899SCharles.Forsyth e = tkvalue(ret, "%s", tki->name->name);
17137da2899SCharles.Forsyth if(e == nil)
17237da2899SCharles.Forsyth return nil;
17337da2899SCharles.Forsyth }
17437da2899SCharles.Forsyth err:
17537da2899SCharles.Forsyth tkputenv(tki->env);
17637da2899SCharles.Forsyth if(tki->img != nil) {
17737da2899SCharles.Forsyth locked = lockdisplay(d);
17837da2899SCharles.Forsyth freeimage(tki->img);
17937da2899SCharles.Forsyth if (locked)
18037da2899SCharles.Forsyth unlockdisplay(d);
18137da2899SCharles.Forsyth }
18237da2899SCharles.Forsyth tkfreename(tki->name);
18337da2899SCharles.Forsyth free(tki);
18437da2899SCharles.Forsyth return e != nil ? e : TkNomem;
18537da2899SCharles.Forsyth }
18637da2899SCharles.Forsyth
18737da2899SCharles.Forsyth char*
tkimgbmdel(TkImg * tki)18837da2899SCharles.Forsyth tkimgbmdel(TkImg *tki)
18937da2899SCharles.Forsyth {
19037da2899SCharles.Forsyth TkImg **l, *f;
19137da2899SCharles.Forsyth
19237da2899SCharles.Forsyth l = &tki->top->imgs;
19337da2899SCharles.Forsyth for(f = *l; f; f = f->link) {
19437da2899SCharles.Forsyth if(f == tki) {
19537da2899SCharles.Forsyth *l = tki->link;
19637da2899SCharles.Forsyth tkimgput(tki);
19737da2899SCharles.Forsyth return nil;
19837da2899SCharles.Forsyth }
19937da2899SCharles.Forsyth l = &f->link;
20037da2899SCharles.Forsyth }
20137da2899SCharles.Forsyth return TkBadvl;
20237da2899SCharles.Forsyth }
20337da2899SCharles.Forsyth
20437da2899SCharles.Forsyth void
tkimgbmfree(TkImg * tki)20537da2899SCharles.Forsyth tkimgbmfree(TkImg *tki)
20637da2899SCharles.Forsyth {
20737da2899SCharles.Forsyth int locked;
20837da2899SCharles.Forsyth Display *d;
20937da2899SCharles.Forsyth
21037da2899SCharles.Forsyth d = tki->top->display;
21137da2899SCharles.Forsyth locked = lockdisplay(d);
21237da2899SCharles.Forsyth freeimage(tki->img);
21337da2899SCharles.Forsyth if(locked)
21437da2899SCharles.Forsyth unlockdisplay(d);
21537da2899SCharles.Forsyth
21637da2899SCharles.Forsyth free(tki->cursor);
21737da2899SCharles.Forsyth tkfreename(tki->name);
21837da2899SCharles.Forsyth tkputenv(tki->env);
21937da2899SCharles.Forsyth
22037da2899SCharles.Forsyth free(tki);
22137da2899SCharles.Forsyth }
22237da2899SCharles.Forsyth
22337da2899SCharles.Forsyth char*
tkimage(TkTop * t,char * arg,char ** ret)22437da2899SCharles.Forsyth tkimage(TkTop *t, char *arg, char **ret)
22537da2899SCharles.Forsyth {
22637da2899SCharles.Forsyth int i;
22737da2899SCharles.Forsyth TkImg *tkim;
22837da2899SCharles.Forsyth char *fmt, *e, *buf, *cmd;
22937da2899SCharles.Forsyth
23037da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
23137da2899SCharles.Forsyth if(buf == nil)
23237da2899SCharles.Forsyth return TkNomem;
23337da2899SCharles.Forsyth cmd = mallocz(Tkminitem, 0);
23437da2899SCharles.Forsyth if(cmd == nil) {
23537da2899SCharles.Forsyth free(buf);
23637da2899SCharles.Forsyth return TkNomem;
23737da2899SCharles.Forsyth }
23837da2899SCharles.Forsyth
23937da2899SCharles.Forsyth arg = tkword(t, arg, cmd, cmd+Tkminitem, nil);
24037da2899SCharles.Forsyth if(strcmp(cmd, "create") == 0) {
24137da2899SCharles.Forsyth arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);
24237da2899SCharles.Forsyth for(i = 0; tkimgopts[i].type != nil; i++)
24337da2899SCharles.Forsyth if(strcmp(buf, tkimgopts[i].type) == 0) {
24437da2899SCharles.Forsyth e = tkimgopts[i].create(t, arg, i, ret);
24537da2899SCharles.Forsyth goto ret;
24637da2899SCharles.Forsyth }
24737da2899SCharles.Forsyth e = TkBadvl;
24837da2899SCharles.Forsyth goto ret;
24937da2899SCharles.Forsyth }
25037da2899SCharles.Forsyth if(strcmp(cmd, "names") == 0) {
25137da2899SCharles.Forsyth fmt = "%s";
25237da2899SCharles.Forsyth for(tkim = t->imgs; tkim; tkim = tkim->link) {
25337da2899SCharles.Forsyth if (tkim->name != nil) {
25437da2899SCharles.Forsyth e = tkvalue(ret, fmt, tkim->name->name);
25537da2899SCharles.Forsyth if(e != nil)
25637da2899SCharles.Forsyth goto ret;
25737da2899SCharles.Forsyth }
25837da2899SCharles.Forsyth fmt = " %s";
25937da2899SCharles.Forsyth }
26037da2899SCharles.Forsyth e = nil;
26137da2899SCharles.Forsyth goto ret;
26237da2899SCharles.Forsyth }
26337da2899SCharles.Forsyth
26437da2899SCharles.Forsyth arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);
26537da2899SCharles.Forsyth tkim = tkname2img(t, buf);
26637da2899SCharles.Forsyth if(tkim == nil) {
26737da2899SCharles.Forsyth e = TkBadvl;
26837da2899SCharles.Forsyth goto ret;
26937da2899SCharles.Forsyth }
27037da2899SCharles.Forsyth
27137da2899SCharles.Forsyth if(strcmp(cmd, "height") == 0) {
27237da2899SCharles.Forsyth e = tkvalue(ret, "%d", tkim->h);
27337da2899SCharles.Forsyth goto ret;
27437da2899SCharles.Forsyth }
27537da2899SCharles.Forsyth if(strcmp(cmd, "width") == 0) {
27637da2899SCharles.Forsyth e = tkvalue(ret, "%d", tkim->w);
27737da2899SCharles.Forsyth goto ret;
27837da2899SCharles.Forsyth }
27937da2899SCharles.Forsyth if(strcmp(cmd, "type") == 0) {
28037da2899SCharles.Forsyth e = tkvalue(ret, "%s", tkimgopts[tkim->type].type);
28137da2899SCharles.Forsyth goto ret;
28237da2899SCharles.Forsyth }
28337da2899SCharles.Forsyth if(strcmp(cmd, "delete") == 0) {
28437da2899SCharles.Forsyth for (;;) {
28537da2899SCharles.Forsyth e = tkimgopts[tkim->type].delete(tkim);
28637da2899SCharles.Forsyth if (e != nil)
28737da2899SCharles.Forsyth break;
28837da2899SCharles.Forsyth arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);
28937da2899SCharles.Forsyth if (buf[0] == '\0')
29037da2899SCharles.Forsyth break;
29137da2899SCharles.Forsyth tkim = tkname2img(t, buf);
29237da2899SCharles.Forsyth if (tkim == nil) {
29337da2899SCharles.Forsyth e = TkBadvl;
29437da2899SCharles.Forsyth break;
29537da2899SCharles.Forsyth }
29637da2899SCharles.Forsyth }
29737da2899SCharles.Forsyth goto ret;
29837da2899SCharles.Forsyth }
29937da2899SCharles.Forsyth
30037da2899SCharles.Forsyth e = TkBadcm;
30137da2899SCharles.Forsyth ret:
30237da2899SCharles.Forsyth free(cmd);
30337da2899SCharles.Forsyth free(buf);
30437da2899SCharles.Forsyth return e;
30537da2899SCharles.Forsyth }
30637da2899SCharles.Forsyth
30737da2899SCharles.Forsyth void
tkimgput(TkImg * tki)30837da2899SCharles.Forsyth tkimgput(TkImg *tki)
30937da2899SCharles.Forsyth {
31037da2899SCharles.Forsyth if(tki == nil)
31137da2899SCharles.Forsyth return;
31237da2899SCharles.Forsyth
31337da2899SCharles.Forsyth if(--tki->ref > 0)
31437da2899SCharles.Forsyth return;
31537da2899SCharles.Forsyth
31637da2899SCharles.Forsyth tkimgopts[tki->type].destroy(tki);
31737da2899SCharles.Forsyth }
31837da2899SCharles.Forsyth
31937da2899SCharles.Forsyth TkImg*
tkauximage(TkTop * t,char * s,TkMemimage * m,int repl)320*0db9190eSforsyth tkauximage(TkTop *t, char* s, TkMemimage *m, int repl)
32137da2899SCharles.Forsyth {
32237da2899SCharles.Forsyth TkName *name;
32337da2899SCharles.Forsyth TkCtxt *c;
32437da2899SCharles.Forsyth TkImg *tki;
32537da2899SCharles.Forsyth Display *d;
32637da2899SCharles.Forsyth Image *i;
327*0db9190eSforsyth int locked, nbytes;
32837da2899SCharles.Forsyth
32937da2899SCharles.Forsyth tki = tkname2img(t, s);
33037da2899SCharles.Forsyth if (tki != nil) {
33137da2899SCharles.Forsyth tki->ref++;
33237da2899SCharles.Forsyth return tki;
33337da2899SCharles.Forsyth }
33437da2899SCharles.Forsyth
33537da2899SCharles.Forsyth name = tkmkname(s);
33637da2899SCharles.Forsyth if (name == nil)
33737da2899SCharles.Forsyth return nil;
338*0db9190eSforsyth tki = mallocz(sizeof(*tki), 1);
33937da2899SCharles.Forsyth if (tki == nil)
34037da2899SCharles.Forsyth goto err;
34137da2899SCharles.Forsyth tki->env = tkdefaultenv(t);
34237da2899SCharles.Forsyth if(tki->env == nil)
34337da2899SCharles.Forsyth goto err;
34437da2899SCharles.Forsyth
34537da2899SCharles.Forsyth c = t->ctxt;
34637da2899SCharles.Forsyth d = c->display;
34737da2899SCharles.Forsyth
348*0db9190eSforsyth nbytes = bytesperline(m->r, chantodepth(m->chans))*Dy(m->r);
34937da2899SCharles.Forsyth locked = lockdisplay(d);
350*0db9190eSforsyth i = allocimage(d, m->r, m->chans, repl, DTransparent);
35137da2899SCharles.Forsyth if (i != nil) {
352*0db9190eSforsyth if (loadimage(i, m->r, m->data, nbytes) != nbytes) {
35337da2899SCharles.Forsyth freeimage(i);
35437da2899SCharles.Forsyth i = nil;
35537da2899SCharles.Forsyth }
35637da2899SCharles.Forsyth if (repl)
357*0db9190eSforsyth replclipr(i, 1, huger); /* TO DO: doesn't allocimage do this? */
35837da2899SCharles.Forsyth }
35937da2899SCharles.Forsyth if (locked)
36037da2899SCharles.Forsyth unlockdisplay(d);
36137da2899SCharles.Forsyth if (i == nil)
36237da2899SCharles.Forsyth goto err;
36337da2899SCharles.Forsyth tki->top = t;
36437da2899SCharles.Forsyth tki->ref = 2; /* t->imgs ref and the ref we are returning */
36537da2899SCharles.Forsyth tki->type = 0; /* bitmap */
366*0db9190eSforsyth tki->w = Dx(m->r);
367*0db9190eSforsyth tki->h = Dy(m->r);
36837da2899SCharles.Forsyth tki->img = i;
36937da2899SCharles.Forsyth tki->name = name;
37037da2899SCharles.Forsyth tki->link = t->imgs;
37137da2899SCharles.Forsyth t->imgs = tki;
37237da2899SCharles.Forsyth return tki;
37337da2899SCharles.Forsyth err:
37437da2899SCharles.Forsyth if (tki != nil) {
37537da2899SCharles.Forsyth tkputenv(tki->env);
37637da2899SCharles.Forsyth free(tki);
37737da2899SCharles.Forsyth }
37837da2899SCharles.Forsyth tkfreename(name);
37937da2899SCharles.Forsyth return nil;
38037da2899SCharles.Forsyth }
381