#include <lib9.h>#include <kernel.h>#include "draw.h"#include "tk.h"#include "label.h" #define O(t, e) ((long)(&((t*)0)->e)) TkOption tklabelopts[] ={ "text", OPTtext, O(TkLabel, text), nil, "label", OPTtext, O(TkLabel, text), nil, "underline", OPTdist, O(TkLabel, ul), nil, "justify", OPTflag, O(TkLabel, justify), tkjustify, "anchor", OPTflag, O(TkLabel, anchor), tkanchor, "bitmap", OPTbmap, O(TkLabel, bitmap), nil, "image", OPTimag, O(TkLabel, img), nil, nil}; char*tklabel(TkTop *t, char *arg, char **ret){ Tk *tk; char *e; TkLabel *tkl; TkName *names; TkOptab tko[3]; tk = tknewobj(t, TKlabel, sizeof(Tk)+sizeof(TkLabel)); if(tk == nil) return TkNomem; tkl = TKobj(TkLabel, tk); tkl->ul = -1; tkl->justify = Tkleft; tko[0].ptr = tk; tko[0].optab = tkgeneric; tko[1].ptr = tkl; tko[1].optab = tklabelopts; tko[2].ptr = nil; names = nil; e = tkparse(t, arg, tko, &names); if(e != nil) { tkfreeobj(tk); return e; } tksizelabel(tk); tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); e = tkaddchild(t, tk, &names); tkfreename(names); if(e != nil) { tkfreeobj(tk); return e; } tk->name->link = nil; return tkvalue(ret, "%s", tk->name->name);} static char*tklabelcget(Tk *tk, char *arg, char **val){ TkOptab tko[3]; TkLabel *tkl = TKobj(TkLabel, tk); tko[0].ptr = tk; tko[0].optab = tkgeneric; tko[1].ptr = tkl; tko[1].optab = tklabelopts; tko[2].ptr = nil; return tkgencget(tko, arg, val, tk->env->top);} static char*tklabelconf(Tk *tk, char *arg, char **val){ char *e; TkGeom g; int bd; TkOptab tko[3]; TkLabel *tkl = TKobj(TkLabel, tk); tko[0].ptr = tk; tko[0].optab = tkgeneric; tko[1].ptr = tkl; tko[1].optab = tklabelopts; tko[2].ptr = nil; if(*arg == '\0') return tkconflist(tko, val); g = tk->req; bd = tk->borderwidth; e = tkparse(tk->env->top, arg, tko, nil); tksizelabel(tk); tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); tkgeomchg(tk, &g, bd); tk->dirty = tkrect(tk, 1); return e;} voidtksizelabel(Tk *tk){ Point p; int w, h; TkLabel *tkl; tkl = TKobj(TkLabel, tk); if(tkl->anchor == 0) tkl->anchor = Tkcenter; w = 0; h = 0; tkl->textheight = 0; if(tkl->img != nil) { w = tkl->img->w + 2*Bitpadx; h = tkl->img->h + 2*Bitpady; } else if(tkl->bitmap != nil) { w = Dx(tkl->bitmap->r) + 2*Bitpadx; h = Dy(tkl->bitmap->r) + 2*Bitpady; } else if(tkl->text != nil) { p = tkstringsize(tk, tkl->text); w = p.x + 2*Textpadx; h = p.y + 2*Textpady; if(tkl->ul != -1 && tkl->ul > strlen(tkl->text)) tkl->ul = strlen(tkl->text); /* underline all */ tkl->textheight = p.y; } if(tk->type == TKcascade) { w += CheckButton + 2*CheckButtonBW; if(h < CheckButton) h = CheckButton; } w += 2*tk->highlightwidth; h += 2*tk->highlightwidth; tkl->w = w; tkl->h = h; if((tk->flag & Tksetwidth) == 0) tk->req.width = w; if((tk->flag & Tksetheight) == 0) tk->req.height = h;} inttklabelmargin(Tk *tk){ TkLabel *tkl; Image *img; switch(tk->type){ case TKseparator: return 0; case TKlabel: case TKcascade: tkl = TKobj(TkLabel, tk); img = nil; if (tkl->img != nil) img = tkl->img->img; else if (tkl->bitmap != nil) img = tkl->bitmap; if (img != nil) return Bitpadx; return Textpadx; default: fprint(2, "label margin: type %d\n", tk->type); return 0; }} voidtkfreelabel(Tk *tk){ Image *i; int locked; Display *d; TkLabel *tkl; tkl = TKobj(TkLabel, tk); if(tkl->text != nil) free(tkl->text); if(tkl->command != nil) free(tkl->command); if(tkl->value != nil) free(tkl->value); if(tkl->variable != nil) { tkfreevar(tk->env->top, tkl->variable, tk->flag & Tkswept); free(tkl->variable); } if(tkl->img != nil) tkimgput(tkl->img); i = tkl->bitmap; if(i != nil) { d = i->display; locked = lockdisplay(d); freeimage(i); if(locked) unlockdisplay(d); } if(tkl->menu != nil) free(tkl->menu);} static voidtktriangle(Point u, Image *i, TkEnv *e){ Point p[3]; u.y++; p[0].x = u.x + CheckButton; p[0].y = u.y + CheckButton/2; p[1].x = u.x; p[1].y = u.y + CheckButton; p[2].x = u.x; p[2].y = u.y; fillpoly(i, p, 3, ~0, tkgc(e, TkCforegnd), p[0]);} /* * draw TKlabel, TKseparator, and TKcascade (cascade should really be a button) */char*tkdrawlabel(Tk *tk, Point orig){ TkEnv *e; TkLabel *tkl; Rectangle r, s, mainr, focusr; int dx, dy, h; Point p, u, v; Image *i, *dst, *ct, *img; int relief, bgnd, fgnd; e = tk->env; dst = tkimageof(tk); if(dst == nil) return nil; v.x = tk->act.width + 2*tk->borderwidth; v.y = tk->act.height + 2*tk->borderwidth; r.min = ZP; r.max = v; focusr = insetrect(r, tk->borderwidth); mainr = insetrect(focusr, tk->highlightwidth); relief = tk->relief; tkl = TKobj(TkLabel, tk); fgnd = TkCforegnd; bgnd = TkCbackgnd; if (tk->flag & Tkdisabled) fgnd = TkCdisablefgnd; else if (tk->flag & Tkactive) { fgnd = TkCactivefgnd; bgnd = TkCactivebgnd; } i = tkitmp(e, r.max, bgnd); if(i == nil) return nil; if(tk->flag & Tkactive) draw(i, r, tkgc(e, bgnd), nil, ZP); p = mainr.min; h = tkl->h - 2 * tk->highlightwidth; dx = tk->act.width - tkl->w - tk->ipad.x; dy = tk->act.height - tkl->h - tk->ipad.y; if((tkl->anchor & (Tknorth|Tksouth)) == 0) p.y += dy/2; else if(tkl->anchor & Tksouth) p.y += dy; if((tkl->anchor & (Tkeast|Tkwest)) == 0) p.x += dx/2; else if(tkl->anchor & Tkeast) p.x += dx; if(tk->type == TKcascade) { u.x = mainr.max.x - CheckButton - CheckButtonBW; /* TO DO: CheckButton etc is really the triangle/arrow */ u.y = p.y + ButtonBorder + (h-CheckSpace)/2; tktriangle(u, i, e); } p.x += tk->ipad.x/2; p.y += tk->ipad.y/2; u = ZP; img = nil; if(tkl->img != nil && tkl->img->img != nil) img = tkl->img->img; else if (tkl->bitmap != nil) img = tkl->bitmap; if(img != nil) { s.min.x = p.x + Bitpadx; s.min.y = p.y + Bitpady; s.max.x = s.min.x + Dx(img->r); s.max.y = s.min.y + Dy(img->r); s = rectaddpt(s, u); if(tkchanhastype(img->chan, CGrey)) draw(i, s, tkgc(e, fgnd), img, ZP); else draw(i, s, img, nil, ZP); } else if(tkl->text != nil) { u.x += Textpadx; u.y += Textpady; ct = tkgc(e, fgnd); p.y += (h - tkl->textheight) / 2; tkdrawstring(tk, i, addpt(u, p), tkl->text, tkl->ul, ct, tkl->justify); } if(tkhaskeyfocus(tk)) tkbox(i, focusr, tk->highlightwidth, tkgc(e, TkChighlightfgnd)); tkdrawrelief(i, tk, ZP, bgnd, relief); p.x = tk->act.x + orig.x; p.y = tk->act.y + orig.y; r = rectaddpt(r, p); draw(dst, r, i, nil, ZP); return nil;} voidtklabelgetimgs(Tk *tk, Image **image, Image **mask){ TkLabel *tkl; tkl = TKobj(TkLabel, tk); *mask = nil; if (tkl->img != nil) *image = tkl->img->img; else *image = tkl->bitmap;} staticTkCmdtab tklabelcmd[] ={ "cget", tklabelcget, "configure", tklabelconf, nil}; TkMethod labelmethod = { "label", tklabelcmd, tkfreelabel, tkdrawlabel, nil, tklabelgetimgs};
#include <lib9.h>
#include <kernel.h>
#include "draw.h"
#include "tk.h"
#include "label.h"
#define O(t, e) ((long)(&((t*)0)->e))
TkOption tklabelopts[] =
{
"text", OPTtext, O(TkLabel, text), nil,
"label", OPTtext, O(TkLabel, text), nil,
"underline", OPTdist, O(TkLabel, ul), nil,
"justify", OPTflag, O(TkLabel, justify), tkjustify,
"anchor", OPTflag, O(TkLabel, anchor), tkanchor,
"bitmap", OPTbmap, O(TkLabel, bitmap), nil,
"image", OPTimag, O(TkLabel, img), nil,
nil
};
char*
tklabel(TkTop *t, char *arg, char **ret)
{
Tk *tk;
char *e;
TkLabel *tkl;
TkName *names;
TkOptab tko[3];
tk = tknewobj(t, TKlabel, sizeof(Tk)+sizeof(TkLabel));
if(tk == nil)
return TkNomem;
tkl = TKobj(TkLabel, tk);
tkl->ul = -1;
tkl->justify = Tkleft;
tko[0].ptr = tk;
tko[0].optab = tkgeneric;
tko[1].ptr = tkl;
tko[1].optab = tklabelopts;
tko[2].ptr = nil;
names = nil;
e = tkparse(t, arg, tko, &names);
if(e != nil) {
tkfreeobj(tk);
return e;
}
tksizelabel(tk);
tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
e = tkaddchild(t, tk, &names);
tkfreename(names);
if(e != nil) {
tkfreeobj(tk);
return e;
}
tk->name->link = nil;
return tkvalue(ret, "%s", tk->name->name);
}
static char*
tklabelcget(Tk *tk, char *arg, char **val)
{
TkOptab tko[3];
TkLabel *tkl = TKobj(TkLabel, tk);
tko[0].ptr = tk;
tko[0].optab = tkgeneric;
tko[1].ptr = tkl;
tko[1].optab = tklabelopts;
tko[2].ptr = nil;
return tkgencget(tko, arg, val, tk->env->top);
}
static char*
tklabelconf(Tk *tk, char *arg, char **val)
{
char *e;
TkGeom g;
int bd;
TkOptab tko[3];
TkLabel *tkl = TKobj(TkLabel, tk);
tko[0].ptr = tk;
tko[0].optab = tkgeneric;
tko[1].ptr = tkl;
tko[1].optab = tklabelopts;
tko[2].ptr = nil;
if(*arg == '\0')
return tkconflist(tko, val);
g = tk->req;
bd = tk->borderwidth;
e = tkparse(tk->env->top, arg, tko, nil);
tksizelabel(tk);
tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
tkgeomchg(tk, &g, bd);
tk->dirty = tkrect(tk, 1);
return e;
}
void
tksizelabel(Tk *tk)
{
Point p;
int w, h;
TkLabel *tkl;
tkl = TKobj(TkLabel, tk);
if(tkl->anchor == 0)
tkl->anchor = Tkcenter;
w = 0;
h = 0;
tkl->textheight = 0;
if(tkl->img != nil) {
w = tkl->img->w + 2*Bitpadx;
h = tkl->img->h + 2*Bitpady;
} else if(tkl->bitmap != nil) {
w = Dx(tkl->bitmap->r) + 2*Bitpadx;
h = Dy(tkl->bitmap->r) + 2*Bitpady;
} else if(tkl->text != nil) {
p = tkstringsize(tk, tkl->text);
w = p.x + 2*Textpadx;
h = p.y + 2*Textpady;
if(tkl->ul != -1 && tkl->ul > strlen(tkl->text))
tkl->ul = strlen(tkl->text); /* underline all */
tkl->textheight = p.y;
}
if(tk->type == TKcascade) {
w += CheckButton + 2*CheckButtonBW;
if(h < CheckButton)
h = CheckButton;
}
w += 2*tk->highlightwidth;
h += 2*tk->highlightwidth;
tkl->w = w;
tkl->h = h;
if((tk->flag & Tksetwidth) == 0)
tk->req.width = w;
if((tk->flag & Tksetheight) == 0)
tk->req.height = h;
}
int
tklabelmargin(Tk *tk)
{
TkLabel *tkl;
Image *img;
switch(tk->type){
case TKseparator:
return 0;
case TKlabel:
case TKcascade:
tkl = TKobj(TkLabel, tk);
img = nil;
if (tkl->img != nil)
img = tkl->img->img;
else if (tkl->bitmap != nil)
img = tkl->bitmap;
if (img != nil)
return Bitpadx;
return Textpadx;
default:
fprint(2, "label margin: type %d\n", tk->type);
return 0;
}
}
void
tkfreelabel(Tk *tk)
{
Image *i;
int locked;
Display *d;
TkLabel *tkl;
tkl = TKobj(TkLabel, tk);
if(tkl->text != nil)
free(tkl->text);
if(tkl->command != nil)
free(tkl->command);
if(tkl->value != nil)
free(tkl->value);
if(tkl->variable != nil) {
tkfreevar(tk->env->top, tkl->variable, tk->flag & Tkswept);
free(tkl->variable);
}
if(tkl->img != nil)
tkimgput(tkl->img);
i = tkl->bitmap;
if(i != nil) {
d = i->display;
locked = lockdisplay(d);
freeimage(i);
if(locked)
unlockdisplay(d);
}
if(tkl->menu != nil)
free(tkl->menu);
}
static void
tktriangle(Point u, Image *i, TkEnv *e)
{
Point p[3];
u.y++;
p[0].x = u.x + CheckButton;
p[0].y = u.y + CheckButton/2;
p[1].x = u.x;
p[1].y = u.y + CheckButton;
p[2].x = u.x;
p[2].y = u.y;
fillpoly(i, p, 3, ~0, tkgc(e, TkCforegnd), p[0]);
}
/*
* draw TKlabel, TKseparator, and TKcascade (cascade should really be a button)
*/
char*
tkdrawlabel(Tk *tk, Point orig)
{
TkEnv *e;
TkLabel *tkl;
Rectangle r, s, mainr, focusr;
int dx, dy, h;
Point p, u, v;
Image *i, *dst, *ct, *img;
int relief, bgnd, fgnd;
e = tk->env;
dst = tkimageof(tk);
if(dst == nil)
return nil;
v.x = tk->act.width + 2*tk->borderwidth;
v.y = tk->act.height + 2*tk->borderwidth;
r.min = ZP;
r.max = v;
focusr = insetrect(r, tk->borderwidth);
mainr = insetrect(focusr, tk->highlightwidth);
relief = tk->relief;
tkl = TKobj(TkLabel, tk);
fgnd = TkCforegnd;
bgnd = TkCbackgnd;
if (tk->flag & Tkdisabled)
fgnd = TkCdisablefgnd;
else if (tk->flag & Tkactive) {
fgnd = TkCactivefgnd;
bgnd = TkCactivebgnd;
}
i = tkitmp(e, r.max, bgnd);
if(i == nil)
return nil;
if(tk->flag & Tkactive)
draw(i, r, tkgc(e, bgnd), nil, ZP);
p = mainr.min;
h = tkl->h - 2 * tk->highlightwidth;
dx = tk->act.width - tkl->w - tk->ipad.x;
dy = tk->act.height - tkl->h - tk->ipad.y;
if((tkl->anchor & (Tknorth|Tksouth)) == 0)
p.y += dy/2;
else if(tkl->anchor & Tksouth)
p.y += dy;
if((tkl->anchor & (Tkeast|Tkwest)) == 0)
p.x += dx/2;
else if(tkl->anchor & Tkeast)
p.x += dx;
if(tk->type == TKcascade) {
u.x = mainr.max.x - CheckButton - CheckButtonBW; /* TO DO: CheckButton etc is really the triangle/arrow */
u.y = p.y + ButtonBorder + (h-CheckSpace)/2;
tktriangle(u, i, e);
}
p.x += tk->ipad.x/2;
p.y += tk->ipad.y/2;
u = ZP;
img = nil;
if(tkl->img != nil && tkl->img->img != nil)
img = tkl->img->img;
else if (tkl->bitmap != nil)
img = tkl->bitmap;
if(img != nil) {
s.min.x = p.x + Bitpadx;
s.min.y = p.y + Bitpady;
s.max.x = s.min.x + Dx(img->r);
s.max.y = s.min.y + Dy(img->r);
s = rectaddpt(s, u);
if(tkchanhastype(img->chan, CGrey))
draw(i, s, tkgc(e, fgnd), img, ZP);
else
draw(i, s, img, nil, ZP);
} else if(tkl->text != nil) {
u.x += Textpadx;
u.y += Textpady;
ct = tkgc(e, fgnd);
p.y += (h - tkl->textheight) / 2;
tkdrawstring(tk, i, addpt(u, p), tkl->text, tkl->ul, ct, tkl->justify);
}
if(tkhaskeyfocus(tk))
tkbox(i, focusr, tk->highlightwidth, tkgc(e, TkChighlightfgnd));
tkdrawrelief(i, tk, ZP, bgnd, relief);
p.x = tk->act.x + orig.x;
p.y = tk->act.y + orig.y;
r = rectaddpt(r, p);
draw(dst, r, i, nil, ZP);
return nil;
}
void
tklabelgetimgs(Tk *tk, Image **image, Image **mask)
{
TkLabel *tkl;
tkl = TKobj(TkLabel, tk);
*mask = nil;
if (tkl->img != nil)
*image = tkl->img->img;
else
*image = tkl->bitmap;
}
static
TkCmdtab tklabelcmd[] =
{
"cget", tklabelcget,
"configure", tklabelconf,
nil
};
TkMethod labelmethod = {
"label",
tklabelcmd,
tkfreelabel,
tkdrawlabel,
nil,
tklabelgetimgs
};