137da2899SCharles.Forsyth #include <lib9.h>
237da2899SCharles.Forsyth #include <kernel.h>
337da2899SCharles.Forsyth #include "draw.h"
437da2899SCharles.Forsyth #include "tk.h"
537da2899SCharles.Forsyth #include "label.h"
637da2899SCharles.Forsyth
737da2899SCharles.Forsyth #define O(t, e) ((long)(&((t*)0)->e))
837da2899SCharles.Forsyth
937da2899SCharles.Forsyth TkOption tklabelopts[] =
1037da2899SCharles.Forsyth {
1137da2899SCharles.Forsyth "text", OPTtext, O(TkLabel, text), nil,
1237da2899SCharles.Forsyth "label", OPTtext, O(TkLabel, text), nil,
1337da2899SCharles.Forsyth "underline", OPTdist, O(TkLabel, ul), nil,
1437da2899SCharles.Forsyth "justify", OPTflag, O(TkLabel, justify), tkjustify,
1537da2899SCharles.Forsyth "anchor", OPTflag, O(TkLabel, anchor), tkanchor,
1637da2899SCharles.Forsyth "bitmap", OPTbmap, O(TkLabel, bitmap), nil,
1737da2899SCharles.Forsyth "image", OPTimag, O(TkLabel, img), nil,
1837da2899SCharles.Forsyth nil
1937da2899SCharles.Forsyth };
2037da2899SCharles.Forsyth
2137da2899SCharles.Forsyth char*
tklabel(TkTop * t,char * arg,char ** ret)2237da2899SCharles.Forsyth tklabel(TkTop *t, char *arg, char **ret)
2337da2899SCharles.Forsyth {
2437da2899SCharles.Forsyth Tk *tk;
2537da2899SCharles.Forsyth char *e;
2637da2899SCharles.Forsyth TkLabel *tkl;
2737da2899SCharles.Forsyth TkName *names;
2837da2899SCharles.Forsyth TkOptab tko[3];
2937da2899SCharles.Forsyth
3037da2899SCharles.Forsyth tk = tknewobj(t, TKlabel, sizeof(Tk)+sizeof(TkLabel));
3137da2899SCharles.Forsyth if(tk == nil)
3237da2899SCharles.Forsyth return TkNomem;
3337da2899SCharles.Forsyth
3437da2899SCharles.Forsyth tkl = TKobj(TkLabel, tk);
3537da2899SCharles.Forsyth tkl->ul = -1;
3637da2899SCharles.Forsyth tkl->justify = Tkleft;
3737da2899SCharles.Forsyth
3837da2899SCharles.Forsyth tko[0].ptr = tk;
3937da2899SCharles.Forsyth tko[0].optab = tkgeneric;
4037da2899SCharles.Forsyth tko[1].ptr = tkl;
4137da2899SCharles.Forsyth tko[1].optab = tklabelopts;
4237da2899SCharles.Forsyth tko[2].ptr = nil;
4337da2899SCharles.Forsyth
4437da2899SCharles.Forsyth names = nil;
4537da2899SCharles.Forsyth e = tkparse(t, arg, tko, &names);
4637da2899SCharles.Forsyth if(e != nil) {
4737da2899SCharles.Forsyth tkfreeobj(tk);
4837da2899SCharles.Forsyth return e;
4937da2899SCharles.Forsyth }
5037da2899SCharles.Forsyth
5137da2899SCharles.Forsyth tksizelabel(tk);
5237da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
5337da2899SCharles.Forsyth
5437da2899SCharles.Forsyth e = tkaddchild(t, tk, &names);
5537da2899SCharles.Forsyth tkfreename(names);
5637da2899SCharles.Forsyth if(e != nil) {
5737da2899SCharles.Forsyth tkfreeobj(tk);
5837da2899SCharles.Forsyth return e;
5937da2899SCharles.Forsyth }
6037da2899SCharles.Forsyth tk->name->link = nil;
6137da2899SCharles.Forsyth
6237da2899SCharles.Forsyth return tkvalue(ret, "%s", tk->name->name);
6337da2899SCharles.Forsyth }
6437da2899SCharles.Forsyth
6537da2899SCharles.Forsyth static char*
tklabelcget(Tk * tk,char * arg,char ** val)6637da2899SCharles.Forsyth tklabelcget(Tk *tk, char *arg, char **val)
6737da2899SCharles.Forsyth {
6837da2899SCharles.Forsyth TkOptab tko[3];
6937da2899SCharles.Forsyth TkLabel *tkl = TKobj(TkLabel, tk);
7037da2899SCharles.Forsyth
7137da2899SCharles.Forsyth tko[0].ptr = tk;
7237da2899SCharles.Forsyth tko[0].optab = tkgeneric;
7337da2899SCharles.Forsyth tko[1].ptr = tkl;
7437da2899SCharles.Forsyth tko[1].optab = tklabelopts;
7537da2899SCharles.Forsyth tko[2].ptr = nil;
7637da2899SCharles.Forsyth
7737da2899SCharles.Forsyth return tkgencget(tko, arg, val, tk->env->top);
7837da2899SCharles.Forsyth }
7937da2899SCharles.Forsyth
8037da2899SCharles.Forsyth static char*
tklabelconf(Tk * tk,char * arg,char ** val)8137da2899SCharles.Forsyth tklabelconf(Tk *tk, char *arg, char **val)
8237da2899SCharles.Forsyth {
8337da2899SCharles.Forsyth char *e;
8437da2899SCharles.Forsyth TkGeom g;
8537da2899SCharles.Forsyth int bd;
8637da2899SCharles.Forsyth TkOptab tko[3];
8737da2899SCharles.Forsyth TkLabel *tkl = TKobj(TkLabel, tk);
8837da2899SCharles.Forsyth
8937da2899SCharles.Forsyth tko[0].ptr = tk;
9037da2899SCharles.Forsyth tko[0].optab = tkgeneric;
9137da2899SCharles.Forsyth tko[1].ptr = tkl;
9237da2899SCharles.Forsyth tko[1].optab = tklabelopts;
9337da2899SCharles.Forsyth tko[2].ptr = nil;
9437da2899SCharles.Forsyth
9537da2899SCharles.Forsyth if(*arg == '\0')
9637da2899SCharles.Forsyth return tkconflist(tko, val);
9737da2899SCharles.Forsyth
9837da2899SCharles.Forsyth g = tk->req;
9937da2899SCharles.Forsyth bd = tk->borderwidth;
10037da2899SCharles.Forsyth e = tkparse(tk->env->top, arg, tko, nil);
10137da2899SCharles.Forsyth tksizelabel(tk);
10237da2899SCharles.Forsyth tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
10337da2899SCharles.Forsyth tkgeomchg(tk, &g, bd);
10437da2899SCharles.Forsyth
10537da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
10637da2899SCharles.Forsyth return e;
10737da2899SCharles.Forsyth }
10837da2899SCharles.Forsyth
10937da2899SCharles.Forsyth void
tksizelabel(Tk * tk)11037da2899SCharles.Forsyth tksizelabel(Tk *tk)
11137da2899SCharles.Forsyth {
11237da2899SCharles.Forsyth Point p;
11337da2899SCharles.Forsyth int w, h;
11437da2899SCharles.Forsyth TkLabel *tkl;
11537da2899SCharles.Forsyth
11637da2899SCharles.Forsyth tkl = TKobj(TkLabel, tk);
11737da2899SCharles.Forsyth if(tkl->anchor == 0)
11837da2899SCharles.Forsyth tkl->anchor = Tkcenter;
11937da2899SCharles.Forsyth
12037da2899SCharles.Forsyth w = 0;
12137da2899SCharles.Forsyth h = 0;
12237da2899SCharles.Forsyth tkl->textheight = 0;
12337da2899SCharles.Forsyth if(tkl->img != nil) {
12437da2899SCharles.Forsyth w = tkl->img->w + 2*Bitpadx;
12537da2899SCharles.Forsyth h = tkl->img->h + 2*Bitpady;
1260db9190eSforsyth } else if(tkl->bitmap != nil) {
12737da2899SCharles.Forsyth w = Dx(tkl->bitmap->r) + 2*Bitpadx;
12837da2899SCharles.Forsyth h = Dy(tkl->bitmap->r) + 2*Bitpady;
1290db9190eSforsyth } else if(tkl->text != nil) {
13037da2899SCharles.Forsyth p = tkstringsize(tk, tkl->text);
13137da2899SCharles.Forsyth w = p.x + 2*Textpadx;
13237da2899SCharles.Forsyth h = p.y + 2*Textpady;
13337da2899SCharles.Forsyth if(tkl->ul != -1 && tkl->ul > strlen(tkl->text))
1340db9190eSforsyth tkl->ul = strlen(tkl->text); /* underline all */
13537da2899SCharles.Forsyth tkl->textheight = p.y;
13637da2899SCharles.Forsyth }
13737da2899SCharles.Forsyth
1380b978350Sforsyth if(tk->type == TKcascade) {
13937da2899SCharles.Forsyth w += CheckButton + 2*CheckButtonBW;
14037da2899SCharles.Forsyth if(h < CheckButton)
14137da2899SCharles.Forsyth h = CheckButton;
14237da2899SCharles.Forsyth }
14337da2899SCharles.Forsyth w += 2*tk->highlightwidth;
14437da2899SCharles.Forsyth h += 2*tk->highlightwidth;
14537da2899SCharles.Forsyth tkl->w = w;
14637da2899SCharles.Forsyth tkl->h = h;
14737da2899SCharles.Forsyth if((tk->flag & Tksetwidth) == 0)
14837da2899SCharles.Forsyth tk->req.width = w;
14937da2899SCharles.Forsyth if((tk->flag & Tksetheight) == 0)
15037da2899SCharles.Forsyth tk->req.height = h;
15137da2899SCharles.Forsyth }
15237da2899SCharles.Forsyth
15337da2899SCharles.Forsyth int
tklabelmargin(Tk * tk)15437da2899SCharles.Forsyth tklabelmargin(Tk *tk)
15537da2899SCharles.Forsyth {
15637da2899SCharles.Forsyth TkLabel *tkl;
15737da2899SCharles.Forsyth Image *img;
15837da2899SCharles.Forsyth
1590b978350Sforsyth switch(tk->type){
1600b978350Sforsyth case TKseparator:
16137da2899SCharles.Forsyth return 0;
1620b978350Sforsyth
1630b978350Sforsyth case TKlabel:
1640b978350Sforsyth case TKcascade:
16537da2899SCharles.Forsyth tkl = TKobj(TkLabel, tk);
16637da2899SCharles.Forsyth img = nil;
16737da2899SCharles.Forsyth if (tkl->img != nil)
16837da2899SCharles.Forsyth img = tkl->img->img;
16937da2899SCharles.Forsyth else if (tkl->bitmap != nil)
17037da2899SCharles.Forsyth img = tkl->bitmap;
17137da2899SCharles.Forsyth if (img != nil)
17237da2899SCharles.Forsyth return Bitpadx;
17337da2899SCharles.Forsyth return Textpadx;
1740b978350Sforsyth
1750b978350Sforsyth default:
1760b978350Sforsyth fprint(2, "label margin: type %d\n", tk->type);
1770b978350Sforsyth return 0;
17837da2899SCharles.Forsyth }
17937da2899SCharles.Forsyth }
18037da2899SCharles.Forsyth
18137da2899SCharles.Forsyth void
tkfreelabel(Tk * tk)18237da2899SCharles.Forsyth tkfreelabel(Tk *tk)
18337da2899SCharles.Forsyth {
18437da2899SCharles.Forsyth Image *i;
18537da2899SCharles.Forsyth int locked;
18637da2899SCharles.Forsyth Display *d;
18737da2899SCharles.Forsyth TkLabel *tkl;
18837da2899SCharles.Forsyth
18937da2899SCharles.Forsyth tkl = TKobj(TkLabel, tk);
19037da2899SCharles.Forsyth
19137da2899SCharles.Forsyth if(tkl->text != nil)
19237da2899SCharles.Forsyth free(tkl->text);
19337da2899SCharles.Forsyth if(tkl->command != nil)
19437da2899SCharles.Forsyth free(tkl->command);
19537da2899SCharles.Forsyth if(tkl->value != nil)
19637da2899SCharles.Forsyth free(tkl->value);
19737da2899SCharles.Forsyth if(tkl->variable != nil) {
19837da2899SCharles.Forsyth tkfreevar(tk->env->top, tkl->variable, tk->flag & Tkswept);
19937da2899SCharles.Forsyth free(tkl->variable);
20037da2899SCharles.Forsyth }
20137da2899SCharles.Forsyth if(tkl->img != nil)
20237da2899SCharles.Forsyth tkimgput(tkl->img);
20337da2899SCharles.Forsyth i = tkl->bitmap;
20437da2899SCharles.Forsyth if(i != nil) {
20537da2899SCharles.Forsyth d = i->display;
20637da2899SCharles.Forsyth locked = lockdisplay(d);
20737da2899SCharles.Forsyth freeimage(i);
20837da2899SCharles.Forsyth if(locked)
20937da2899SCharles.Forsyth unlockdisplay(d);
21037da2899SCharles.Forsyth }
21137da2899SCharles.Forsyth if(tkl->menu != nil)
21237da2899SCharles.Forsyth free(tkl->menu);
21337da2899SCharles.Forsyth }
21437da2899SCharles.Forsyth
21537da2899SCharles.Forsyth static void
tktriangle(Point u,Image * i,TkEnv * e)21637da2899SCharles.Forsyth tktriangle(Point u, Image *i, TkEnv *e)
21737da2899SCharles.Forsyth {
21837da2899SCharles.Forsyth Point p[3];
21937da2899SCharles.Forsyth
22037da2899SCharles.Forsyth u.y++;
22137da2899SCharles.Forsyth p[0].x = u.x + CheckButton;
22237da2899SCharles.Forsyth p[0].y = u.y + CheckButton/2;
22337da2899SCharles.Forsyth p[1].x = u.x;
22437da2899SCharles.Forsyth p[1].y = u.y + CheckButton;
22537da2899SCharles.Forsyth p[2].x = u.x;
22637da2899SCharles.Forsyth p[2].y = u.y;
2270db9190eSforsyth fillpoly(i, p, 3, ~0, tkgc(e, TkCforegnd), p[0]);
22837da2899SCharles.Forsyth }
22937da2899SCharles.Forsyth
23037da2899SCharles.Forsyth /*
2310b978350Sforsyth * draw TKlabel, TKseparator, and TKcascade (cascade should really be a button)
23237da2899SCharles.Forsyth */
23337da2899SCharles.Forsyth char*
tkdrawlabel(Tk * tk,Point orig)23437da2899SCharles.Forsyth tkdrawlabel(Tk *tk, Point orig)
23537da2899SCharles.Forsyth {
23637da2899SCharles.Forsyth TkEnv *e;
23737da2899SCharles.Forsyth TkLabel *tkl;
23837da2899SCharles.Forsyth Rectangle r, s, mainr, focusr;
23937da2899SCharles.Forsyth int dx, dy, h;
2400b978350Sforsyth Point p, u, v;
2410b978350Sforsyth Image *i, *dst, *ct, *img;
24237da2899SCharles.Forsyth int relief, bgnd, fgnd;
24337da2899SCharles.Forsyth
24437da2899SCharles.Forsyth e = tk->env;
24537da2899SCharles.Forsyth
24637da2899SCharles.Forsyth dst = tkimageof(tk);
24737da2899SCharles.Forsyth if(dst == nil)
24837da2899SCharles.Forsyth return nil;
24937da2899SCharles.Forsyth
25037da2899SCharles.Forsyth v.x = tk->act.width + 2*tk->borderwidth;
25137da2899SCharles.Forsyth v.y = tk->act.height + 2*tk->borderwidth;
25237da2899SCharles.Forsyth
25337da2899SCharles.Forsyth r.min = ZP;
2540b978350Sforsyth r.max = v;
25537da2899SCharles.Forsyth focusr = insetrect(r, tk->borderwidth);
25637da2899SCharles.Forsyth mainr = insetrect(focusr, tk->highlightwidth);
25737da2899SCharles.Forsyth relief = tk->relief;
25837da2899SCharles.Forsyth
25937da2899SCharles.Forsyth tkl = TKobj(TkLabel, tk);
26037da2899SCharles.Forsyth
26137da2899SCharles.Forsyth fgnd = TkCforegnd;
26237da2899SCharles.Forsyth bgnd = TkCbackgnd;
26337da2899SCharles.Forsyth if (tk->flag & Tkdisabled)
26437da2899SCharles.Forsyth fgnd = TkCdisablefgnd;
26537da2899SCharles.Forsyth else if (tk->flag & Tkactive) {
26637da2899SCharles.Forsyth fgnd = TkCactivefgnd;
26737da2899SCharles.Forsyth bgnd = TkCactivebgnd;
26837da2899SCharles.Forsyth }
26937da2899SCharles.Forsyth
27037da2899SCharles.Forsyth i = tkitmp(e, r.max, bgnd);
27137da2899SCharles.Forsyth if(i == nil)
27237da2899SCharles.Forsyth return nil;
27337da2899SCharles.Forsyth
27437da2899SCharles.Forsyth if(tk->flag & Tkactive)
27537da2899SCharles.Forsyth draw(i, r, tkgc(e, bgnd), nil, ZP);
27637da2899SCharles.Forsyth
27737da2899SCharles.Forsyth p = mainr.min;
27837da2899SCharles.Forsyth h = tkl->h - 2 * tk->highlightwidth;
27937da2899SCharles.Forsyth
28037da2899SCharles.Forsyth dx = tk->act.width - tkl->w - tk->ipad.x;
28137da2899SCharles.Forsyth dy = tk->act.height - tkl->h - tk->ipad.y;
28237da2899SCharles.Forsyth if((tkl->anchor & (Tknorth|Tksouth)) == 0)
28337da2899SCharles.Forsyth p.y += dy/2;
2840db9190eSforsyth else if(tkl->anchor & Tksouth)
28537da2899SCharles.Forsyth p.y += dy;
28637da2899SCharles.Forsyth
28737da2899SCharles.Forsyth if((tkl->anchor & (Tkeast|Tkwest)) == 0)
28837da2899SCharles.Forsyth p.x += dx/2;
2890db9190eSforsyth else if(tkl->anchor & Tkeast)
29037da2899SCharles.Forsyth p.x += dx;
29137da2899SCharles.Forsyth
2920b978350Sforsyth if(tk->type == TKcascade) {
2930b978350Sforsyth u.x = mainr.max.x - CheckButton - CheckButtonBW; /* TO DO: CheckButton etc is really the triangle/arrow */
29437da2899SCharles.Forsyth u.y = p.y + ButtonBorder + (h-CheckSpace)/2;
29537da2899SCharles.Forsyth tktriangle(u, i, e);
29637da2899SCharles.Forsyth }
29737da2899SCharles.Forsyth
29837da2899SCharles.Forsyth p.x += tk->ipad.x/2;
29937da2899SCharles.Forsyth p.y += tk->ipad.y/2;
30037da2899SCharles.Forsyth u = ZP;
30137da2899SCharles.Forsyth
30237da2899SCharles.Forsyth img = nil;
30337da2899SCharles.Forsyth if(tkl->img != nil && tkl->img->img != nil)
30437da2899SCharles.Forsyth img = tkl->img->img;
30537da2899SCharles.Forsyth else if (tkl->bitmap != nil)
30637da2899SCharles.Forsyth img = tkl->bitmap;
30737da2899SCharles.Forsyth if(img != nil) {
30837da2899SCharles.Forsyth s.min.x = p.x + Bitpadx;
30937da2899SCharles.Forsyth s.min.y = p.y + Bitpady;
31037da2899SCharles.Forsyth s.max.x = s.min.x + Dx(img->r);
31137da2899SCharles.Forsyth s.max.y = s.min.y + Dy(img->r);
31237da2899SCharles.Forsyth s = rectaddpt(s, u);
31337da2899SCharles.Forsyth if(tkchanhastype(img->chan, CGrey))
31437da2899SCharles.Forsyth draw(i, s, tkgc(e, fgnd), img, ZP);
31537da2899SCharles.Forsyth else
31637da2899SCharles.Forsyth draw(i, s, img, nil, ZP);
31737da2899SCharles.Forsyth } else if(tkl->text != nil) {
31837da2899SCharles.Forsyth u.x += Textpadx;
31937da2899SCharles.Forsyth u.y += Textpady;
32037da2899SCharles.Forsyth ct = tkgc(e, fgnd);
32137da2899SCharles.Forsyth
32237da2899SCharles.Forsyth p.y += (h - tkl->textheight) / 2;
323*86018cd3Sforsyth tkdrawstring(tk, i, addpt(u, p), tkl->text, tkl->ul, ct, tkl->justify);
32437da2899SCharles.Forsyth }
32537da2899SCharles.Forsyth
32637da2899SCharles.Forsyth if(tkhaskeyfocus(tk))
32737da2899SCharles.Forsyth tkbox(i, focusr, tk->highlightwidth, tkgc(e, TkChighlightfgnd));
32837da2899SCharles.Forsyth tkdrawrelief(i, tk, ZP, bgnd, relief);
32937da2899SCharles.Forsyth
33037da2899SCharles.Forsyth p.x = tk->act.x + orig.x;
33137da2899SCharles.Forsyth p.y = tk->act.y + orig.y;
33237da2899SCharles.Forsyth r = rectaddpt(r, p);
33337da2899SCharles.Forsyth draw(dst, r, i, nil, ZP);
33437da2899SCharles.Forsyth
33537da2899SCharles.Forsyth return nil;
33637da2899SCharles.Forsyth }
33737da2899SCharles.Forsyth
33837da2899SCharles.Forsyth void
tklabelgetimgs(Tk * tk,Image ** image,Image ** mask)33937da2899SCharles.Forsyth tklabelgetimgs(Tk *tk, Image **image, Image **mask)
34037da2899SCharles.Forsyth {
34137da2899SCharles.Forsyth TkLabel *tkl;
34237da2899SCharles.Forsyth
34337da2899SCharles.Forsyth tkl = TKobj(TkLabel, tk);
34437da2899SCharles.Forsyth *mask = nil;
34537da2899SCharles.Forsyth if (tkl->img != nil)
34637da2899SCharles.Forsyth *image = tkl->img->img;
34737da2899SCharles.Forsyth else
34837da2899SCharles.Forsyth *image = tkl->bitmap;
34937da2899SCharles.Forsyth }
35037da2899SCharles.Forsyth
35137da2899SCharles.Forsyth static
35237da2899SCharles.Forsyth TkCmdtab tklabelcmd[] =
35337da2899SCharles.Forsyth {
35437da2899SCharles.Forsyth "cget", tklabelcget,
35537da2899SCharles.Forsyth "configure", tklabelconf,
35637da2899SCharles.Forsyth nil
35737da2899SCharles.Forsyth };
35837da2899SCharles.Forsyth
35937da2899SCharles.Forsyth TkMethod labelmethod = {
36037da2899SCharles.Forsyth "label",
36137da2899SCharles.Forsyth tklabelcmd,
36237da2899SCharles.Forsyth tkfreelabel,
36337da2899SCharles.Forsyth tkdrawlabel,
36437da2899SCharles.Forsyth nil,
36537da2899SCharles.Forsyth tklabelgetimgs
36637da2899SCharles.Forsyth };
367