137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "draw.h"
337da2899SCharles.Forsyth #include "tk.h"
437da2899SCharles.Forsyth
50db9190eSforsyth struct TkCol
60db9190eSforsyth {
70db9190eSforsyth ulong rgba1;
80db9190eSforsyth ulong rgba3; /* if mixed, otherwise DNotacolor */
90db9190eSforsyth Image* i;
100db9190eSforsyth TkCol* forw;
110db9190eSforsyth };
120db9190eSforsyth
1337da2899SCharles.Forsyth extern void rptwakeup(void*, void*);
1437da2899SCharles.Forsyth extern void* rptproc(char*, int, void*, int (*)(void*), int (*)(void*,int), void (*)(void*));
1537da2899SCharles.Forsyth
1637da2899SCharles.Forsyth typedef struct Cmd Cmd;
1737da2899SCharles.Forsyth struct Cmd
1837da2899SCharles.Forsyth {
1937da2899SCharles.Forsyth char* name;
2037da2899SCharles.Forsyth char* (*fn)(TkTop*, char*, char**);
2137da2899SCharles.Forsyth };
2237da2899SCharles.Forsyth static struct Cmd cmdmain[] =
2337da2899SCharles.Forsyth {
2437da2899SCharles.Forsyth "bind", tkbind,
2537da2899SCharles.Forsyth "button", tkbutton,
2637da2899SCharles.Forsyth "canvas", tkcanvas,
2737da2899SCharles.Forsyth "checkbutton", tkcheckbutton,
2837da2899SCharles.Forsyth "choicebutton", tkchoicebutton,
2937da2899SCharles.Forsyth "cursor", tkcursorcmd,
3037da2899SCharles.Forsyth "destroy", tkdestroy,
3137da2899SCharles.Forsyth "entry", tkentry,
3237da2899SCharles.Forsyth "focus", tkfocus,
3337da2899SCharles.Forsyth "frame", tkframe,
3437da2899SCharles.Forsyth "grab", tkgrab,
3537da2899SCharles.Forsyth "grid", tkgrid,
3637da2899SCharles.Forsyth "image", tkimage,
3737da2899SCharles.Forsyth "label", tklabel,
3837da2899SCharles.Forsyth "listbox", tklistbox,
3937da2899SCharles.Forsyth "lower", tklower,
4037da2899SCharles.Forsyth "menu", tkmenu,
4137da2899SCharles.Forsyth "menubutton", tkmenubutton,
4237da2899SCharles.Forsyth "pack", tkpack,
4337da2899SCharles.Forsyth "panel", tkpanel,
4437da2899SCharles.Forsyth "puts", tkputs,
4537da2899SCharles.Forsyth "radiobutton", tkradiobutton,
4637da2899SCharles.Forsyth "raise", tkraise,
4737da2899SCharles.Forsyth "scale", tkscale,
4837da2899SCharles.Forsyth "scrollbar", tkscrollbar,
4937da2899SCharles.Forsyth "see", tkseecmd,
5037da2899SCharles.Forsyth "send", tksend,
5137da2899SCharles.Forsyth "text", tktext,
5237da2899SCharles.Forsyth "update", tkupdatecmd,
5337da2899SCharles.Forsyth "variable", tkvariable,
5437da2899SCharles.Forsyth "winfo", tkwinfo,
5537da2899SCharles.Forsyth };
5637da2899SCharles.Forsyth
5737da2899SCharles.Forsyth char* tkfont;
5837da2899SCharles.Forsyth
59*5849851aSforsyth /*
60*5849851aSforsyth * auto-repeating support
6137da2899SCharles.Forsyth * should perhaps be one rptproc per TkCtxt
6237da2899SCharles.Forsyth * This is not done for the moment as there isn't
6337da2899SCharles.Forsyth * a mechanism for terminating the rptproc
6437da2899SCharles.Forsyth */
6537da2899SCharles.Forsyth static void *autorpt;
6637da2899SCharles.Forsyth static int rptid;
6737da2899SCharles.Forsyth static Tk *rptw;
6837da2899SCharles.Forsyth static void *rptnote;
6937da2899SCharles.Forsyth static void (*rptcb)(Tk*, void*, int);
7037da2899SCharles.Forsyth static long rptto;
7137da2899SCharles.Forsyth static int rptint;
7237da2899SCharles.Forsyth
7337da2899SCharles.Forsyth /* blinking carets - should be per TkCtxt */
7437da2899SCharles.Forsyth static void *blinkrpt;
7537da2899SCharles.Forsyth static Tk *blinkw;
7637da2899SCharles.Forsyth static void (*blinkcb)(Tk*, int);
7737da2899SCharles.Forsyth static int blinkignore;
7837da2899SCharles.Forsyth static int blinkon;
7937da2899SCharles.Forsyth
8037da2899SCharles.Forsyth
8137da2899SCharles.Forsyth ulong
tkrgba(int r,int g,int b,int a)8237da2899SCharles.Forsyth tkrgba(int r, int g, int b, int a)
8337da2899SCharles.Forsyth {
8437da2899SCharles.Forsyth ulong p;
8537da2899SCharles.Forsyth
8637da2899SCharles.Forsyth if(r < 0)
8737da2899SCharles.Forsyth r = 0;
8837da2899SCharles.Forsyth else if(r > 255)
8937da2899SCharles.Forsyth r = 255;
9037da2899SCharles.Forsyth if(g < 0)
9137da2899SCharles.Forsyth g = 0;
9237da2899SCharles.Forsyth else if(g > 255)
9337da2899SCharles.Forsyth g = 255;
9437da2899SCharles.Forsyth if(b < 0)
9537da2899SCharles.Forsyth b = 0;
9637da2899SCharles.Forsyth else if(b > 255)
9737da2899SCharles.Forsyth b = 255;
9837da2899SCharles.Forsyth p = (r<<24)|(g<<16)|(b<<8)|0xFF;
9937da2899SCharles.Forsyth if(a == 255)
10037da2899SCharles.Forsyth return p;
10137da2899SCharles.Forsyth return setalpha(p, a);
10237da2899SCharles.Forsyth }
10337da2899SCharles.Forsyth
10437da2899SCharles.Forsyth /* to be replaced */
10537da2899SCharles.Forsyth static int
revalpha(int c,int a)10637da2899SCharles.Forsyth revalpha(int c, int a)
10737da2899SCharles.Forsyth {
10837da2899SCharles.Forsyth if (a == 0)
10937da2899SCharles.Forsyth return 0;
11037da2899SCharles.Forsyth return (c & 0xff) * 255 / a;
11137da2899SCharles.Forsyth }
11237da2899SCharles.Forsyth
11337da2899SCharles.Forsyth void
tkrgbavals(ulong rgba,int * R,int * G,int * B,int * A)11437da2899SCharles.Forsyth tkrgbavals(ulong rgba, int *R, int *G, int *B, int *A)
11537da2899SCharles.Forsyth {
11637da2899SCharles.Forsyth int a;
11737da2899SCharles.Forsyth
11837da2899SCharles.Forsyth a = rgba & 0xff;
11937da2899SCharles.Forsyth *A = a;
12037da2899SCharles.Forsyth if (a != 0xff) {
12137da2899SCharles.Forsyth *R = revalpha(rgba>>24, a);
12237da2899SCharles.Forsyth *G = revalpha((rgba>>16) & 0xFF, a);
12337da2899SCharles.Forsyth *B = revalpha((rgba >> 8) & 0xFF, a);
12437da2899SCharles.Forsyth } else {
12537da2899SCharles.Forsyth *R = (rgba>>24);
12637da2899SCharles.Forsyth *G = ((rgba>>16) & 0xFF);
12737da2899SCharles.Forsyth *B = ((rgba >> 8) & 0xFF);
12837da2899SCharles.Forsyth }
12937da2899SCharles.Forsyth }
13037da2899SCharles.Forsyth
1310db9190eSforsyth static int
tkcachecol(TkCtxt * c,Image * i,ulong one,ulong three)1320db9190eSforsyth tkcachecol(TkCtxt *c, Image *i, ulong one, ulong three)
1330db9190eSforsyth {
1340db9190eSforsyth TkCol *cc;
1350db9190eSforsyth
1360db9190eSforsyth cc = malloc(sizeof(*cc));
1370db9190eSforsyth if(cc == nil)
1380db9190eSforsyth return 0;
1390db9190eSforsyth cc->rgba1 = one;
1400db9190eSforsyth cc->rgba3 = three;
1410db9190eSforsyth cc->i = i;
1420db9190eSforsyth cc->forw = c->chead;
1430db9190eSforsyth c->chead = cc;
1440db9190eSforsyth c->ncol++;
1450db9190eSforsyth /* we'll do LRU management at some point */
1460db9190eSforsyth if(c->ncol > TkColcachesize){
1470db9190eSforsyth static int warn;
1480db9190eSforsyth if(warn == 0){
1490db9190eSforsyth warn = 1;
1500db9190eSforsyth print("tk: %d colours cached\n", TkColcachesize);
1510db9190eSforsyth }
1520db9190eSforsyth }
1530db9190eSforsyth return 1;
1540db9190eSforsyth }
1550db9190eSforsyth
1560db9190eSforsyth static Image*
tkfindcol(TkCtxt * c,ulong one,ulong three)1570db9190eSforsyth tkfindcol(TkCtxt *c, ulong one, ulong three)
1580db9190eSforsyth {
1590db9190eSforsyth TkCol *cc, **l;
1600db9190eSforsyth
1610db9190eSforsyth for(l = &c->chead; (cc = *l) != nil; l = &cc->forw)
1620db9190eSforsyth if(cc->rgba1 == one && cc->rgba3 == three){
1630db9190eSforsyth /* move it up in the list */
1640db9190eSforsyth *l = cc->forw;
1650db9190eSforsyth cc->forw = c->chead;
1660db9190eSforsyth c->chead = cc;
1670db9190eSforsyth /* we assume it will be used right away and not stored */
1680db9190eSforsyth return cc->i;
1690db9190eSforsyth }
1700db9190eSforsyth return nil;
1710db9190eSforsyth }
1720db9190eSforsyth
17337da2899SCharles.Forsyth void
tkfreecolcache(TkCtxt * c)17437da2899SCharles.Forsyth tkfreecolcache(TkCtxt *c)
17537da2899SCharles.Forsyth {
17637da2899SCharles.Forsyth TkCol *cc;
17737da2899SCharles.Forsyth
17837da2899SCharles.Forsyth if(c == nil)
17937da2899SCharles.Forsyth return;
18037da2899SCharles.Forsyth while((cc = c->chead) != nil){
18137da2899SCharles.Forsyth c->chead = cc->forw;
18237da2899SCharles.Forsyth freeimage(cc->i);
18337da2899SCharles.Forsyth free(cc);
18437da2899SCharles.Forsyth }
18537da2899SCharles.Forsyth c->ctail = nil;
18637da2899SCharles.Forsyth c->ncol = 0;
18737da2899SCharles.Forsyth }
18837da2899SCharles.Forsyth
18937da2899SCharles.Forsyth Image*
tkcolormix(TkCtxt * c,ulong one,ulong three)1900db9190eSforsyth tkcolormix(TkCtxt *c, ulong one, ulong three)
1910db9190eSforsyth {
1920db9190eSforsyth Image *i;
1930db9190eSforsyth Display *d;
1940db9190eSforsyth
1950db9190eSforsyth i = tkfindcol(c, one, three);
1960db9190eSforsyth if(i != nil)
1970db9190eSforsyth return i;
1980db9190eSforsyth d = c->display;
1990db9190eSforsyth i = allocimagemix(d, one, three);
2000db9190eSforsyth if(i == nil)
2010db9190eSforsyth return d->black;
2020db9190eSforsyth if(!tkcachecol(c, i, one, three)){
2030db9190eSforsyth freeimage(i);
2040db9190eSforsyth return d->black;
2050db9190eSforsyth }
2060db9190eSforsyth return i;
2070db9190eSforsyth }
2080db9190eSforsyth
2090db9190eSforsyth Image*
tkcolor(TkCtxt * c,ulong pix)21037da2899SCharles.Forsyth tkcolor(TkCtxt *c, ulong pix)
21137da2899SCharles.Forsyth {
21237da2899SCharles.Forsyth Image *i;
21337da2899SCharles.Forsyth Display *d;
21437da2899SCharles.Forsyth Rectangle r;
21537da2899SCharles.Forsyth
21637da2899SCharles.Forsyth d = c->display;
21737da2899SCharles.Forsyth if(pix == DWhite)
21837da2899SCharles.Forsyth return d->white;
21937da2899SCharles.Forsyth if(pix == DBlack)
22037da2899SCharles.Forsyth return d->black;
2210db9190eSforsyth i = tkfindcol(c, pix, DNotacolor);
2220db9190eSforsyth if(i != nil)
2230db9190eSforsyth return i;
22437da2899SCharles.Forsyth r.min = ZP;
22537da2899SCharles.Forsyth r.max.x = 1;
22637da2899SCharles.Forsyth r.max.y = 1;
22737da2899SCharles.Forsyth if ((pix & 0xff) == 0xff)
22837da2899SCharles.Forsyth i = allocimage(d, r, RGB24, 1, pix);
22937da2899SCharles.Forsyth else
23037da2899SCharles.Forsyth i = allocimage(d, r, RGBA32, 1, pix);
23137da2899SCharles.Forsyth if(i == nil)
23237da2899SCharles.Forsyth return d->black;
2330db9190eSforsyth if(!tkcachecol(c, i, pix, DNotacolor)) {
23437da2899SCharles.Forsyth freeimage(i);
23537da2899SCharles.Forsyth return d->black;
23637da2899SCharles.Forsyth }
2370db9190eSforsyth return i;
23837da2899SCharles.Forsyth }
2390db9190eSforsyth
2400db9190eSforsyth Image*
tkgradient(TkCtxt * c,Rectangle r,int dir,ulong pix0,ulong pix1)2410db9190eSforsyth tkgradient(TkCtxt *c, Rectangle r, int dir, ulong pix0, ulong pix1)
2420db9190eSforsyth {
2430db9190eSforsyth Display *d;
2440db9190eSforsyth Image *i;
2450db9190eSforsyth uchar *b, *p, *e;
2460db9190eSforsyth int c0[3], c1[3], delta[3], a, j, x, y, n, locked;
2470db9190eSforsyth Rectangle s;
2480db9190eSforsyth
2490db9190eSforsyth d = c->display;
2500db9190eSforsyth y = Dy(r);
2510db9190eSforsyth x = Dx(r);
25234077fb0Sforsyth if(x <= 0 || y <= 0) {
25334077fb0Sforsyth r = Rect(0, 0, 1, 1);
25434077fb0Sforsyth x = y = 1;
25534077fb0Sforsyth }
2560db9190eSforsyth /* TO DO: diagonal */
2570db9190eSforsyth s = r;
2580db9190eSforsyth if(dir == Tkhorizontal){
2590db9190eSforsyth n = x;
2600db9190eSforsyth r.max.y = r.min.y+1;
2610db9190eSforsyth }else{
2620db9190eSforsyth n = y;
2630db9190eSforsyth r.max.x = r.min.x+1;
26437da2899SCharles.Forsyth }
2650db9190eSforsyth b = mallocz(3*n, 0);
2660db9190eSforsyth if(b == nil)
26734077fb0Sforsyth return nil;
2680db9190eSforsyth locked = lockdisplay(d);
2690db9190eSforsyth i = allocimage(d, r, RGB24, 1, DNofill);
2700db9190eSforsyth if(i == nil)
2710db9190eSforsyth goto Ret;
2720db9190eSforsyth tkrgbavals(pix0, &c0[2], &c0[1], &c0[0], &a);
2730db9190eSforsyth tkrgbavals(pix1, &c1[2], &c1[1], &c1[0], &a);
2740db9190eSforsyth for(j = 0; j < 3; j++){
2750db9190eSforsyth c0[j] <<= 12;
2760db9190eSforsyth c1[j] <<= 12;
2770db9190eSforsyth delta[j] = ((c1[j]-c0[j])+(1<<11))/n;
2780db9190eSforsyth }
2790db9190eSforsyth e = b+3*n;
2800db9190eSforsyth for(p = b; p < e; p += 3) {
2810db9190eSforsyth p[0] = c0[0]>>12;
2820db9190eSforsyth p[1] = c0[1]>>12;
2830db9190eSforsyth p[2] = c0[2]>>12;
2840db9190eSforsyth c0[0] += delta[0];
2850db9190eSforsyth c0[1] += delta[1];
2860db9190eSforsyth c0[2] += delta[2];
2870db9190eSforsyth }
2880db9190eSforsyth loadimage(i, r, b, 3*n);
2890db9190eSforsyth replclipr(i, 1, s);
2900db9190eSforsyth Ret:
2910db9190eSforsyth if(locked)
2920db9190eSforsyth unlockdisplay(d);
2930db9190eSforsyth free(b);
29437da2899SCharles.Forsyth return i;
29537da2899SCharles.Forsyth }
29637da2899SCharles.Forsyth
29737da2899SCharles.Forsyth /*
29837da2899SCharles.Forsyth * XXX should be in libdraw?
29937da2899SCharles.Forsyth */
30037da2899SCharles.Forsyth int
tkchanhastype(ulong c,int t)30137da2899SCharles.Forsyth tkchanhastype(ulong c, int t)
30237da2899SCharles.Forsyth {
30337da2899SCharles.Forsyth for(; c; c>>=8)
30437da2899SCharles.Forsyth if(TYPE(c) == t)
30537da2899SCharles.Forsyth return 1;
30637da2899SCharles.Forsyth return 0;
30737da2899SCharles.Forsyth }
30837da2899SCharles.Forsyth
30937da2899SCharles.Forsyth void
tksettransparent(Tk * tk,int transparent)31037da2899SCharles.Forsyth tksettransparent(Tk *tk, int transparent)
31137da2899SCharles.Forsyth {
31237da2899SCharles.Forsyth if (transparent)
31337da2899SCharles.Forsyth tk->flag |= Tktransparent;
31437da2899SCharles.Forsyth else
31537da2899SCharles.Forsyth tk->flag &= ~Tktransparent;
31637da2899SCharles.Forsyth }
31737da2899SCharles.Forsyth
31837da2899SCharles.Forsyth int
tkhasalpha(TkEnv * e,int col)31937da2899SCharles.Forsyth tkhasalpha(TkEnv *e, int col)
32037da2899SCharles.Forsyth {
32137da2899SCharles.Forsyth return (e->colors[col] & 0xff) != 0xff;
32237da2899SCharles.Forsyth }
32337da2899SCharles.Forsyth
32437da2899SCharles.Forsyth Image*
tkgc(TkEnv * e,int col)32537da2899SCharles.Forsyth tkgc(TkEnv *e, int col)
32637da2899SCharles.Forsyth {
32737da2899SCharles.Forsyth return tkcolor(e->top->ctxt, e->colors[col]);
32837da2899SCharles.Forsyth }
32937da2899SCharles.Forsyth
33037da2899SCharles.Forsyth
33137da2899SCharles.Forsyth /*
33237da2899SCharles.Forsyth * Todo: improve the fixed-point code
33337da2899SCharles.Forsyth * the 255 scale factor is used because RGB ranges 0-255
33437da2899SCharles.Forsyth */
33537da2899SCharles.Forsyth static void
rgb2hsv(int r,int g,int b,int * h,int * s,int * v)33637da2899SCharles.Forsyth rgb2hsv(int r, int g, int b, int *h, int *s, int *v)
33737da2899SCharles.Forsyth {
33837da2899SCharles.Forsyth int min, max, delta;
33937da2899SCharles.Forsyth
34037da2899SCharles.Forsyth max = r;
34137da2899SCharles.Forsyth if(g > max)
34237da2899SCharles.Forsyth max = g;
34337da2899SCharles.Forsyth if(b > max)
34437da2899SCharles.Forsyth max = b;
34537da2899SCharles.Forsyth min = r;
34637da2899SCharles.Forsyth if(g < min)
34737da2899SCharles.Forsyth min = g;
34837da2899SCharles.Forsyth if(b < min)
34937da2899SCharles.Forsyth min = b;
35037da2899SCharles.Forsyth *v = max;
35137da2899SCharles.Forsyth if (max != 0)
35237da2899SCharles.Forsyth *s = ((max - min)*255) / max;
35337da2899SCharles.Forsyth else
35437da2899SCharles.Forsyth *s = 0;
35537da2899SCharles.Forsyth
35637da2899SCharles.Forsyth if (*s == 0) {
35737da2899SCharles.Forsyth *h = 0; /* undefined */
35837da2899SCharles.Forsyth } else {
35937da2899SCharles.Forsyth delta = max - min;
36037da2899SCharles.Forsyth if (r == max)
36137da2899SCharles.Forsyth *h = (g - b)*255 / delta;
36237da2899SCharles.Forsyth else if (g == max)
36337da2899SCharles.Forsyth *h = (2*255) + ((b - r)*255) / delta;
36437da2899SCharles.Forsyth else if (b == max)
36537da2899SCharles.Forsyth *h = (4*255) + ((r - g)*255)/ delta;
36637da2899SCharles.Forsyth *h *= 60;
36737da2899SCharles.Forsyth if (*h < 0)
36837da2899SCharles.Forsyth *h += 360*255;
36937da2899SCharles.Forsyth *h /= 255;
37037da2899SCharles.Forsyth }
37137da2899SCharles.Forsyth }
37237da2899SCharles.Forsyth
37337da2899SCharles.Forsyth static void
hsv2rgb(int h,int s,int v,int * r,int * g,int * b)37437da2899SCharles.Forsyth hsv2rgb(int h, int s, int v, int *r, int *g, int *b)
37537da2899SCharles.Forsyth {
37637da2899SCharles.Forsyth int i;
37737da2899SCharles.Forsyth int f,p,q,t;
37837da2899SCharles.Forsyth
37937da2899SCharles.Forsyth if (s == 0 && h == 0) {
38037da2899SCharles.Forsyth *r = *g = *b = v; /* achromatic case */
38137da2899SCharles.Forsyth } else {
38237da2899SCharles.Forsyth if (h >= 360)
38337da2899SCharles.Forsyth h = 0;
38437da2899SCharles.Forsyth i = h / 60;
38537da2899SCharles.Forsyth h *= 255;
38637da2899SCharles.Forsyth h /= 60;
38737da2899SCharles.Forsyth
38837da2899SCharles.Forsyth f = h % 255;
38937da2899SCharles.Forsyth p = v * (255 - s);
39037da2899SCharles.Forsyth q = v * (255 - ((s * f)/255));
39137da2899SCharles.Forsyth t = v * (255- ((s * (255 - f))/255));
39237da2899SCharles.Forsyth p /= 255;
39337da2899SCharles.Forsyth q /= 255;
39437da2899SCharles.Forsyth t /= 255;
39537da2899SCharles.Forsyth switch (i) {
39637da2899SCharles.Forsyth case 0: *r = v; *g = t; *b = p; break;
39737da2899SCharles.Forsyth case 1: *r = q; *g = v; *b = p; break;
39837da2899SCharles.Forsyth case 2: *r = p; *g = v; *b = t; break;
39937da2899SCharles.Forsyth case 3: *r = p; *g = q; *b = v; break;
40037da2899SCharles.Forsyth case 4: *r = t; *g = p; *b = v; break;
40137da2899SCharles.Forsyth case 5: *r = v; *g = p; *b = q; break;
40237da2899SCharles.Forsyth }
40337da2899SCharles.Forsyth }
40437da2899SCharles.Forsyth }
40537da2899SCharles.Forsyth
40637da2899SCharles.Forsyth enum {
40737da2899SCharles.Forsyth MINDELTA = 0x10,
40837da2899SCharles.Forsyth DELTA = 0x30,
40937da2899SCharles.Forsyth };
41037da2899SCharles.Forsyth
41137da2899SCharles.Forsyth ulong
tkrgbashade(ulong rgba,int shade)41237da2899SCharles.Forsyth tkrgbashade(ulong rgba, int shade)
41337da2899SCharles.Forsyth {
41437da2899SCharles.Forsyth int R, G, B, A, h, s, v, vl, vd;
41537da2899SCharles.Forsyth
41637da2899SCharles.Forsyth if (shade == TkSameshade)
41737da2899SCharles.Forsyth return rgba;
41837da2899SCharles.Forsyth
41937da2899SCharles.Forsyth tkrgbavals(rgba, &R, &G, &B, &A);
4206e425a9dSCharles.Forsyth h = s = v = 0;
42137da2899SCharles.Forsyth rgb2hsv(R, G, B, &h, &s, &v);
42237da2899SCharles.Forsyth
42337da2899SCharles.Forsyth if (v < MINDELTA) {
42437da2899SCharles.Forsyth vd = v+DELTA;
42537da2899SCharles.Forsyth vl = vd+DELTA;
42637da2899SCharles.Forsyth } else if (v > 255-MINDELTA) {
42737da2899SCharles.Forsyth vl = v-DELTA;
42837da2899SCharles.Forsyth vd = vl-DELTA;
42937da2899SCharles.Forsyth } else {
43037da2899SCharles.Forsyth vl = v+DELTA;
43137da2899SCharles.Forsyth vd = v-DELTA;
43237da2899SCharles.Forsyth }
43337da2899SCharles.Forsyth
43437da2899SCharles.Forsyth v = (shade == TkLightshade)?vl:vd;
43537da2899SCharles.Forsyth if (v < 0)
43637da2899SCharles.Forsyth v = 0;
43737da2899SCharles.Forsyth if (v > 255)
43837da2899SCharles.Forsyth v = 255;
43937da2899SCharles.Forsyth hsv2rgb(h, s, v, &R, &G, &B);
44037da2899SCharles.Forsyth
44137da2899SCharles.Forsyth return tkrgba(R, G, B, A);
44237da2899SCharles.Forsyth }
44337da2899SCharles.Forsyth
44437da2899SCharles.Forsyth Image*
tkgshade(TkEnv * e,int col,int shade)44537da2899SCharles.Forsyth tkgshade(TkEnv *e, int col, int shade)
44637da2899SCharles.Forsyth {
44737da2899SCharles.Forsyth ulong rgba;
44837da2899SCharles.Forsyth
44937da2899SCharles.Forsyth if (col == TkCbackgnd || col == TkCselectbgnd || col == TkCactivebgnd)
45037da2899SCharles.Forsyth return tkgc(e, col+shade);
45137da2899SCharles.Forsyth rgba = tkrgbashade(e->colors[col], shade);
45237da2899SCharles.Forsyth return tkcolor(e->top->ctxt, rgba);
45337da2899SCharles.Forsyth }
45437da2899SCharles.Forsyth
45537da2899SCharles.Forsyth TkEnv*
tknewenv(TkTop * t)45637da2899SCharles.Forsyth tknewenv(TkTop *t)
45737da2899SCharles.Forsyth {
45837da2899SCharles.Forsyth TkEnv *e;
45937da2899SCharles.Forsyth
46037da2899SCharles.Forsyth e = malloc(sizeof(TkEnv));
46137da2899SCharles.Forsyth if(e == nil)
46237da2899SCharles.Forsyth return nil;
46337da2899SCharles.Forsyth
46437da2899SCharles.Forsyth e->ref = 1;
46537da2899SCharles.Forsyth e->top = t;
46637da2899SCharles.Forsyth return e;
46737da2899SCharles.Forsyth }
46837da2899SCharles.Forsyth
46937da2899SCharles.Forsyth TkEnv*
tkdefaultenv(TkTop * t)47037da2899SCharles.Forsyth tkdefaultenv(TkTop *t)
47137da2899SCharles.Forsyth {
47237da2899SCharles.Forsyth int locked;
47337da2899SCharles.Forsyth TkEnv *env;
47437da2899SCharles.Forsyth Display *d;
47537da2899SCharles.Forsyth
47637da2899SCharles.Forsyth if(t->env != nil) {
47737da2899SCharles.Forsyth t->env->ref++;
47837da2899SCharles.Forsyth return t->env;
47937da2899SCharles.Forsyth }
48037da2899SCharles.Forsyth t->env = malloc(sizeof(TkEnv));
48137da2899SCharles.Forsyth if(t->env == nil)
48237da2899SCharles.Forsyth return nil;
48337da2899SCharles.Forsyth
48437da2899SCharles.Forsyth env = t->env;
48537da2899SCharles.Forsyth env->ref = 1;
48637da2899SCharles.Forsyth env->top = t;
48737da2899SCharles.Forsyth
48837da2899SCharles.Forsyth if(tkfont == nil)
48937da2899SCharles.Forsyth tkfont = "/fonts/pelm/unicode.8.font";
49037da2899SCharles.Forsyth
49137da2899SCharles.Forsyth d = t->display;
49237da2899SCharles.Forsyth env->font = font_open(d, tkfont);
49337da2899SCharles.Forsyth if(env->font == nil) {
49437da2899SCharles.Forsyth static int warn;
49537da2899SCharles.Forsyth if(warn == 0) {
49637da2899SCharles.Forsyth warn = 1;
49737da2899SCharles.Forsyth print("tk: font not found: %s\n", tkfont);
49837da2899SCharles.Forsyth }
49937da2899SCharles.Forsyth env->font = font_open(d, "*default*");
50037da2899SCharles.Forsyth if(env->font == nil) {
50137da2899SCharles.Forsyth free(t->env);
50237da2899SCharles.Forsyth t->env = nil;
50337da2899SCharles.Forsyth return nil;
50437da2899SCharles.Forsyth }
50537da2899SCharles.Forsyth }
50637da2899SCharles.Forsyth
50737da2899SCharles.Forsyth locked = lockdisplay(d);
50837da2899SCharles.Forsyth env->wzero = stringwidth(env->font, "0");
50937da2899SCharles.Forsyth if ( env->wzero <= 0 )
51037da2899SCharles.Forsyth env->wzero = env->font->height / 2;
51137da2899SCharles.Forsyth if(locked)
51237da2899SCharles.Forsyth unlockdisplay(d);
51337da2899SCharles.Forsyth
51437da2899SCharles.Forsyth tksetenvcolours(env);
51537da2899SCharles.Forsyth return env;
51637da2899SCharles.Forsyth }
51737da2899SCharles.Forsyth
51837da2899SCharles.Forsyth void
tkputenv(TkEnv * env)51937da2899SCharles.Forsyth tkputenv(TkEnv *env)
52037da2899SCharles.Forsyth {
52137da2899SCharles.Forsyth Display *d;
52237da2899SCharles.Forsyth int locked;
52337da2899SCharles.Forsyth
52437da2899SCharles.Forsyth if(env == nil)
52537da2899SCharles.Forsyth return;
52637da2899SCharles.Forsyth
52737da2899SCharles.Forsyth env->ref--;
52837da2899SCharles.Forsyth if(env->ref != 0)
52937da2899SCharles.Forsyth return;
53037da2899SCharles.Forsyth
53137da2899SCharles.Forsyth d = env->top->display;
53237da2899SCharles.Forsyth locked = lockdisplay(d);
53337da2899SCharles.Forsyth
53437da2899SCharles.Forsyth if(env->font != nil)
53537da2899SCharles.Forsyth font_close(env->font);
53637da2899SCharles.Forsyth
53737da2899SCharles.Forsyth if(locked)
53837da2899SCharles.Forsyth unlockdisplay(d);
53937da2899SCharles.Forsyth
54037da2899SCharles.Forsyth free(env);
54137da2899SCharles.Forsyth }
54237da2899SCharles.Forsyth
54337da2899SCharles.Forsyth TkEnv*
tkdupenv(TkEnv ** env)54437da2899SCharles.Forsyth tkdupenv(TkEnv **env)
54537da2899SCharles.Forsyth {
54637da2899SCharles.Forsyth Display *d;
54737da2899SCharles.Forsyth TkEnv *e, *ne;
54837da2899SCharles.Forsyth
54937da2899SCharles.Forsyth e = *env;
55037da2899SCharles.Forsyth if(e->ref == 1)
55137da2899SCharles.Forsyth return e;
55237da2899SCharles.Forsyth
55337da2899SCharles.Forsyth ne = malloc(sizeof(TkEnv));
55437da2899SCharles.Forsyth if(ne == nil)
55537da2899SCharles.Forsyth return nil;
55637da2899SCharles.Forsyth
55737da2899SCharles.Forsyth ne->ref = 1;
55837da2899SCharles.Forsyth ne->top = e->top;
55937da2899SCharles.Forsyth
56037da2899SCharles.Forsyth d = e->top->display;
56137da2899SCharles.Forsyth memmove(ne->colors, e->colors, sizeof(e->colors));
56237da2899SCharles.Forsyth ne->set = e->set;
56337da2899SCharles.Forsyth ne->font = font_open(d, e->font->name);
56437da2899SCharles.Forsyth ne->wzero = e->wzero;
56537da2899SCharles.Forsyth
56637da2899SCharles.Forsyth e->ref--;
56737da2899SCharles.Forsyth *env = ne;
56837da2899SCharles.Forsyth return ne;
56937da2899SCharles.Forsyth }
57037da2899SCharles.Forsyth
57137da2899SCharles.Forsyth Tk*
tknewobj(TkTop * t,int type,int n)57237da2899SCharles.Forsyth tknewobj(TkTop *t, int type, int n)
57337da2899SCharles.Forsyth {
57437da2899SCharles.Forsyth Tk *tk;
57537da2899SCharles.Forsyth
57637da2899SCharles.Forsyth tk = malloc(n);
57737da2899SCharles.Forsyth if(tk == 0)
57837da2899SCharles.Forsyth return 0;
57937da2899SCharles.Forsyth
58037da2899SCharles.Forsyth tk->type = type; /* Defaults */
58137da2899SCharles.Forsyth tk->flag = Tktop;
58237da2899SCharles.Forsyth tk->relief = TKflat;
58337da2899SCharles.Forsyth tk->env = tkdefaultenv(t);
58437da2899SCharles.Forsyth if(tk->env == nil) {
58537da2899SCharles.Forsyth free(tk);
58637da2899SCharles.Forsyth return nil;
58737da2899SCharles.Forsyth }
58837da2899SCharles.Forsyth
58937da2899SCharles.Forsyth return tk;
59037da2899SCharles.Forsyth }
59137da2899SCharles.Forsyth
59237da2899SCharles.Forsyth void
tkfreebind(TkAction * a)59337da2899SCharles.Forsyth tkfreebind(TkAction *a)
59437da2899SCharles.Forsyth {
59537da2899SCharles.Forsyth TkAction *next;
59637da2899SCharles.Forsyth
59737da2899SCharles.Forsyth while(a != nil) {
59837da2899SCharles.Forsyth next = a->link;
59937da2899SCharles.Forsyth if((a->type & 0xff) == TkDynamic)
60037da2899SCharles.Forsyth free(a->arg);
60137da2899SCharles.Forsyth free(a);
60237da2899SCharles.Forsyth a = next;
60337da2899SCharles.Forsyth }
60437da2899SCharles.Forsyth }
60537da2899SCharles.Forsyth
60637da2899SCharles.Forsyth void
tkfreename(TkName * f)60737da2899SCharles.Forsyth tkfreename(TkName *f)
60837da2899SCharles.Forsyth {
60937da2899SCharles.Forsyth TkName *n;
61037da2899SCharles.Forsyth
61137da2899SCharles.Forsyth while(f != nil) {
61237da2899SCharles.Forsyth n = f->link;
61337da2899SCharles.Forsyth free(f);
61437da2899SCharles.Forsyth f = n;
61537da2899SCharles.Forsyth }
61637da2899SCharles.Forsyth }
61737da2899SCharles.Forsyth
61837da2899SCharles.Forsyth void
tkfreeobj(Tk * tk)61937da2899SCharles.Forsyth tkfreeobj(Tk *tk)
62037da2899SCharles.Forsyth {
62137da2899SCharles.Forsyth TkCtxt *c;
62237da2899SCharles.Forsyth
62337da2899SCharles.Forsyth c = tk->env->top->ctxt;
62437da2899SCharles.Forsyth if(c != nil) {
62537da2899SCharles.Forsyth if(c->tkkeygrab == tk)
62637da2899SCharles.Forsyth c->tkkeygrab = nil;
62737da2899SCharles.Forsyth if(c->mgrab == tk)
62837da2899SCharles.Forsyth tksetmgrab(tk->env->top, nil);
62937da2899SCharles.Forsyth if(c->mfocus == tk)
63037da2899SCharles.Forsyth c->mfocus = nil;
63137da2899SCharles.Forsyth if(c->entered == tk)
63237da2899SCharles.Forsyth c->entered = nil;
63337da2899SCharles.Forsyth }
63437da2899SCharles.Forsyth
63537da2899SCharles.Forsyth if (tk == rptw) {
63637da2899SCharles.Forsyth /* cancel the autorepeat without notifying the widget */
63737da2899SCharles.Forsyth rptid++;
63837da2899SCharles.Forsyth rptw = nil;
63937da2899SCharles.Forsyth }
64037da2899SCharles.Forsyth if (tk == blinkw)
64137da2899SCharles.Forsyth blinkw = nil;
64237da2899SCharles.Forsyth tkextnfreeobj(tk);
64337da2899SCharles.Forsyth tkmethod[tk->type]->free(tk);
64437da2899SCharles.Forsyth tkputenv(tk->env);
64537da2899SCharles.Forsyth tkfreebind(tk->binds);
64637da2899SCharles.Forsyth if(tk->name != nil)
64737da2899SCharles.Forsyth free(tk->name);
64837da2899SCharles.Forsyth free(tk);
64937da2899SCharles.Forsyth }
65037da2899SCharles.Forsyth
65137da2899SCharles.Forsyth char*
tkaddchild(TkTop * t,Tk * tk,TkName ** names)65237da2899SCharles.Forsyth tkaddchild(TkTop *t, Tk *tk, TkName **names)
65337da2899SCharles.Forsyth {
65437da2899SCharles.Forsyth TkName *n;
65537da2899SCharles.Forsyth Tk *f, **l;
65637da2899SCharles.Forsyth int found, len;
65737da2899SCharles.Forsyth char *s, *ep;
65837da2899SCharles.Forsyth
65937da2899SCharles.Forsyth n = *names;
66037da2899SCharles.Forsyth if(n == nil || n->name[0] != '.'){
66137da2899SCharles.Forsyth if(n != nil)
66237da2899SCharles.Forsyth tkerr(t, n->name);
66337da2899SCharles.Forsyth return TkBadwp;
66437da2899SCharles.Forsyth }
66537da2899SCharles.Forsyth
66637da2899SCharles.Forsyth if (n->name[1] == '\0')
66737da2899SCharles.Forsyth return TkDupli;
66837da2899SCharles.Forsyth
66937da2899SCharles.Forsyth /*
67037da2899SCharles.Forsyth * check that the name is well-formed.
67137da2899SCharles.Forsyth * ep will point to end of parent component of the name.
67237da2899SCharles.Forsyth */
67337da2899SCharles.Forsyth ep = nil;
67437da2899SCharles.Forsyth for (s = n->name + 1; *s; s++) {
67537da2899SCharles.Forsyth if (*s == '.'){
67637da2899SCharles.Forsyth tkerr(t, n->name);
67737da2899SCharles.Forsyth return TkBadwp;
67837da2899SCharles.Forsyth }
67937da2899SCharles.Forsyth for (; *s && *s != '.'; s++)
68037da2899SCharles.Forsyth ;
68137da2899SCharles.Forsyth if (*s == '\0')
68237da2899SCharles.Forsyth break;
68337da2899SCharles.Forsyth ep = s;
68437da2899SCharles.Forsyth }
68537da2899SCharles.Forsyth if (ep == s - 1){
68637da2899SCharles.Forsyth tkerr(t, n->name);
68737da2899SCharles.Forsyth return TkBadwp;
68837da2899SCharles.Forsyth }
68937da2899SCharles.Forsyth if (ep == nil)
69037da2899SCharles.Forsyth ep = n->name + 1;
69137da2899SCharles.Forsyth len = ep - n->name;
69237da2899SCharles.Forsyth
69337da2899SCharles.Forsyth found = 0;
69437da2899SCharles.Forsyth l = &t->root;
69537da2899SCharles.Forsyth for(f = *l; f; f = f->siblings) {
69637da2899SCharles.Forsyth if (f->name != nil) {
69737da2899SCharles.Forsyth if (strcmp(n->name, f->name->name) == 0)
69837da2899SCharles.Forsyth return TkDupli;
69937da2899SCharles.Forsyth if (!found &&
70037da2899SCharles.Forsyth strncmp(n->name, f->name->name, len) == 0 &&
70137da2899SCharles.Forsyth f->name->name[len] == '\0')
70237da2899SCharles.Forsyth found = 1;
70337da2899SCharles.Forsyth }
70437da2899SCharles.Forsyth l = &f->siblings;
70537da2899SCharles.Forsyth }
70637da2899SCharles.Forsyth if (0) { /* don't enable this until a reasonably major release... if ever */
70737da2899SCharles.Forsyth /*
70837da2899SCharles.Forsyth * parent widget must already exist
70937da2899SCharles.Forsyth */
71037da2899SCharles.Forsyth if (!found){
71137da2899SCharles.Forsyth tkerr(t, n->name);
71237da2899SCharles.Forsyth return TkBadwp;
71337da2899SCharles.Forsyth }
71437da2899SCharles.Forsyth }
71537da2899SCharles.Forsyth *l = tk;
71637da2899SCharles.Forsyth tk->name = n;
71737da2899SCharles.Forsyth *names = n->link;
71837da2899SCharles.Forsyth
71937da2899SCharles.Forsyth return nil;
72037da2899SCharles.Forsyth }
72137da2899SCharles.Forsyth
72237da2899SCharles.Forsyth Tk*
tklook(TkTop * t,char * wp,int parent)72337da2899SCharles.Forsyth tklook(TkTop *t, char *wp, int parent)
72437da2899SCharles.Forsyth {
72537da2899SCharles.Forsyth Tk *f;
72637da2899SCharles.Forsyth char *p, *q;
72737da2899SCharles.Forsyth
72837da2899SCharles.Forsyth if(wp == nil)
72937da2899SCharles.Forsyth return nil;
73037da2899SCharles.Forsyth
73137da2899SCharles.Forsyth if(parent) {
73237da2899SCharles.Forsyth p = strdup(wp);
73337da2899SCharles.Forsyth if(p == nil)
73437da2899SCharles.Forsyth return nil;
73537da2899SCharles.Forsyth q = strrchr(p, '.');
73637da2899SCharles.Forsyth if(q == nil)
73737da2899SCharles.Forsyth abort();
73837da2899SCharles.Forsyth if(q == p) {
73937da2899SCharles.Forsyth free(p);
74037da2899SCharles.Forsyth return t->root;
74137da2899SCharles.Forsyth }
74237da2899SCharles.Forsyth *q = '\0';
74337da2899SCharles.Forsyth } else
74437da2899SCharles.Forsyth p = wp;
74537da2899SCharles.Forsyth
74637da2899SCharles.Forsyth for(f = t->root; f; f = f->siblings)
74737da2899SCharles.Forsyth if ((f->name != nil) && (strcmp(f->name->name, p) == 0))
74837da2899SCharles.Forsyth break;
74937da2899SCharles.Forsyth
75037da2899SCharles.Forsyth if(f != nil && (f->flag & Tkdestroy))
75137da2899SCharles.Forsyth f = nil;
75237da2899SCharles.Forsyth
75337da2899SCharles.Forsyth if (parent)
75437da2899SCharles.Forsyth free(p);
75537da2899SCharles.Forsyth return f;
75637da2899SCharles.Forsyth }
75737da2899SCharles.Forsyth
75837da2899SCharles.Forsyth void
tktextsdraw(Image * img,Rectangle r,TkEnv * e,int sbw)75937da2899SCharles.Forsyth tktextsdraw(Image *img, Rectangle r, TkEnv *e, int sbw)
76037da2899SCharles.Forsyth {
76137da2899SCharles.Forsyth Image *l, *d;
76237da2899SCharles.Forsyth Rectangle s;
76337da2899SCharles.Forsyth
76437da2899SCharles.Forsyth draw(img, r, tkgc(e, TkCselectbgnd), nil, ZP);
76537da2899SCharles.Forsyth s.min = r.min;
76637da2899SCharles.Forsyth s.min.x -= sbw;
76737da2899SCharles.Forsyth s.min.y -= sbw;
76837da2899SCharles.Forsyth s.max.x = r.max.x;
76937da2899SCharles.Forsyth s.max.y = r.min.y;
77037da2899SCharles.Forsyth l = tkgc(e, TkCselectbgndlght);
77137da2899SCharles.Forsyth draw(img, s, l, nil, ZP);
77237da2899SCharles.Forsyth s.max.x = s.min.x + sbw;
77337da2899SCharles.Forsyth s.max.y = r.max.y + sbw;
77437da2899SCharles.Forsyth draw(img, s, l, nil, ZP);
77537da2899SCharles.Forsyth s.max = r.max;
77637da2899SCharles.Forsyth s.max.x += sbw;
77737da2899SCharles.Forsyth s.max.y += sbw;
77837da2899SCharles.Forsyth s.min.x = r.min.x;
77937da2899SCharles.Forsyth s.min.y = r.max.y;
78037da2899SCharles.Forsyth d = tkgc(e, TkCselectbgnddark);
78137da2899SCharles.Forsyth draw(img, s, d, nil, ZP);
78237da2899SCharles.Forsyth s.min.x = r.max.x;
78337da2899SCharles.Forsyth s.min.y = r.min.y - sbw;
78437da2899SCharles.Forsyth draw(img, s, d, nil, ZP);
78537da2899SCharles.Forsyth }
78637da2899SCharles.Forsyth
78737da2899SCharles.Forsyth void
tkbox(Image * i,Rectangle r,int bd,Image * fill)78837da2899SCharles.Forsyth tkbox(Image *i, Rectangle r, int bd, Image *fill)
78937da2899SCharles.Forsyth {
79037da2899SCharles.Forsyth if (bd > 0) {
79137da2899SCharles.Forsyth draw(i, Rect(r.min.x, r.min.y, r.max.x, r.min.y+bd), fill, nil, ZP);
79237da2899SCharles.Forsyth draw(i, Rect(r.min.x, r.min.y+bd, r.min.x+bd, r.max.y-bd), fill, nil, ZP);
79337da2899SCharles.Forsyth draw(i, Rect(r.min.x, r.max.y-bd, r.max.x, r.max.y), fill, nil, ZP);
79437da2899SCharles.Forsyth draw(i, Rect(r.max.x-bd, r.min.y+bd, r.max.x, r.max.y), fill, nil, ZP);
79537da2899SCharles.Forsyth }
79637da2899SCharles.Forsyth }
79737da2899SCharles.Forsyth
79837da2899SCharles.Forsyth void
tkbevel(Image * i,Point o,int w,int h,int bw,Image * top,Image * bottom)79937da2899SCharles.Forsyth tkbevel(Image *i, Point o, int w, int h, int bw, Image *top, Image *bottom)
80037da2899SCharles.Forsyth {
80137da2899SCharles.Forsyth Rectangle r;
80237da2899SCharles.Forsyth int x, border;
80337da2899SCharles.Forsyth
80437da2899SCharles.Forsyth border = 2 * bw;
80537da2899SCharles.Forsyth
80637da2899SCharles.Forsyth r.min = o;
80737da2899SCharles.Forsyth r.max.x = r.min.x + w + border;
80837da2899SCharles.Forsyth r.max.y = r.min.y + bw;
80937da2899SCharles.Forsyth draw(i, r, top, nil, ZP);
81037da2899SCharles.Forsyth
81137da2899SCharles.Forsyth r.max.x = r.min.x + bw;
81237da2899SCharles.Forsyth r.max.y = r.min.y + h + border;
81337da2899SCharles.Forsyth draw(i, r, top, nil, ZP);
81437da2899SCharles.Forsyth
81537da2899SCharles.Forsyth r.max.x = o.x + w + border;
81637da2899SCharles.Forsyth r.max.y = o.y + h + border;
81737da2899SCharles.Forsyth r.min.x = o.x + bw;
81837da2899SCharles.Forsyth r.min.y = r.max.y - bw;
81937da2899SCharles.Forsyth for(x = 0; x < bw; x++) {
82037da2899SCharles.Forsyth draw(i, r, bottom, nil, ZP);
82137da2899SCharles.Forsyth r.min.x--;
82237da2899SCharles.Forsyth r.min.y++;
82337da2899SCharles.Forsyth }
82437da2899SCharles.Forsyth r.min.x = o.x + bw + w;
82537da2899SCharles.Forsyth r.min.y = o.y + bw;
82637da2899SCharles.Forsyth for(x = bw; x >= 0; x--) {
82737da2899SCharles.Forsyth draw(i, r, bottom, nil, ZP);
82837da2899SCharles.Forsyth r.min.x++;
82937da2899SCharles.Forsyth r.min.y--;
83037da2899SCharles.Forsyth }
83137da2899SCharles.Forsyth }
83237da2899SCharles.Forsyth
83337da2899SCharles.Forsyth /*
83437da2899SCharles.Forsyth * draw a relief border.
83537da2899SCharles.Forsyth * color is an index into tk->env->colors and assumes
83637da2899SCharles.Forsyth * light and dark versions following immediately after
83737da2899SCharles.Forsyth * that index
83837da2899SCharles.Forsyth */
83937da2899SCharles.Forsyth void
tkdrawrelief(Image * i,Tk * tk,Point o,int color,int rlf)84037da2899SCharles.Forsyth tkdrawrelief(Image *i, Tk *tk, Point o, int color, int rlf)
84137da2899SCharles.Forsyth {
84237da2899SCharles.Forsyth TkEnv *e;
84337da2899SCharles.Forsyth Image *l, *d, *t;
84437da2899SCharles.Forsyth int h, w, bd, bd1, bd2;
84537da2899SCharles.Forsyth
84637da2899SCharles.Forsyth if(tk->borderwidth == 0)
84737da2899SCharles.Forsyth return;
84837da2899SCharles.Forsyth
84937da2899SCharles.Forsyth h = tk->act.height;
85037da2899SCharles.Forsyth w = tk->act.width;
85137da2899SCharles.Forsyth
85237da2899SCharles.Forsyth e = tk->env;
85337da2899SCharles.Forsyth if (color == TkCbackgnd || color == TkCselectbgnd || color == TkCactivebgnd) {
85437da2899SCharles.Forsyth l = tkgc(e, color+TkLightshade);
85537da2899SCharles.Forsyth d = tkgc(e, color+TkDarkshade);
85637da2899SCharles.Forsyth } else {
85737da2899SCharles.Forsyth l = tkgshade(e, color, TkLightshade);
85837da2899SCharles.Forsyth d = tkgshade(e, color, TkDarkshade);
85937da2899SCharles.Forsyth }
86037da2899SCharles.Forsyth bd = tk->borderwidth;
86137da2899SCharles.Forsyth if(rlf < 0)
86237da2899SCharles.Forsyth rlf = TKraised;
86337da2899SCharles.Forsyth switch(rlf) {
86437da2899SCharles.Forsyth case TKflat:
86537da2899SCharles.Forsyth break;
86637da2899SCharles.Forsyth case TKsunken:
86737da2899SCharles.Forsyth tkbevel(i, o, w, h, bd, d, l);
86837da2899SCharles.Forsyth break;
86937da2899SCharles.Forsyth case TKraised:
87037da2899SCharles.Forsyth tkbevel(i, o, w, h, bd, l, d);
87137da2899SCharles.Forsyth break;
87237da2899SCharles.Forsyth case TKgroove:
87337da2899SCharles.Forsyth t = d;
87437da2899SCharles.Forsyth d = l;
87537da2899SCharles.Forsyth l = t;
87637da2899SCharles.Forsyth /* fall through */
87737da2899SCharles.Forsyth case TKridge:
87837da2899SCharles.Forsyth bd1 = bd/2;
87937da2899SCharles.Forsyth bd2 = bd - bd1;
88037da2899SCharles.Forsyth if(bd1 > 0)
88137da2899SCharles.Forsyth tkbevel(i, o, w + 2*bd2, h + 2*bd2, bd1, l, d);
88237da2899SCharles.Forsyth o.x += bd1;
88337da2899SCharles.Forsyth o.y += bd1;
88437da2899SCharles.Forsyth tkbevel(i, o, w, h, bd2, d, l);
88537da2899SCharles.Forsyth break;
88637da2899SCharles.Forsyth }
88737da2899SCharles.Forsyth }
88837da2899SCharles.Forsyth
88937da2899SCharles.Forsyth Point
tkstringsize(Tk * tk,char * text)89037da2899SCharles.Forsyth tkstringsize(Tk *tk, char *text)
89137da2899SCharles.Forsyth {
89237da2899SCharles.Forsyth char *q;
89337da2899SCharles.Forsyth int locked;
89437da2899SCharles.Forsyth Display *d;
89537da2899SCharles.Forsyth Point p, t;
89637da2899SCharles.Forsyth
89737da2899SCharles.Forsyth if(text == nil) {
89837da2899SCharles.Forsyth p.x = 0;
89937da2899SCharles.Forsyth p.y = tk->env->font->height;
90037da2899SCharles.Forsyth return p;
90137da2899SCharles.Forsyth }
90237da2899SCharles.Forsyth
90337da2899SCharles.Forsyth d = tk->env->top->display;
90437da2899SCharles.Forsyth locked = lockdisplay(d);
90537da2899SCharles.Forsyth
90637da2899SCharles.Forsyth p = ZP;
90737da2899SCharles.Forsyth while(*text) {
90837da2899SCharles.Forsyth q = strchr(text, '\n');
90937da2899SCharles.Forsyth if(q != nil)
91037da2899SCharles.Forsyth *q = '\0';
91137da2899SCharles.Forsyth t = stringsize(tk->env->font, text);
91237da2899SCharles.Forsyth p.y += t.y;
91337da2899SCharles.Forsyth if(p.x < t.x)
91437da2899SCharles.Forsyth p.x = t.x;
91537da2899SCharles.Forsyth if(q == nil)
91637da2899SCharles.Forsyth break;
91737da2899SCharles.Forsyth text = q+1;
91837da2899SCharles.Forsyth *q = '\n';
91937da2899SCharles.Forsyth }
92037da2899SCharles.Forsyth if(locked)
92137da2899SCharles.Forsyth unlockdisplay(d);
92237da2899SCharles.Forsyth
92337da2899SCharles.Forsyth return p;
92437da2899SCharles.Forsyth }
92537da2899SCharles.Forsyth
9260db9190eSforsyth static void
tkulall(Image * i,Point o,Image * col,Font * f,char * text)9270db9190eSforsyth tkulall(Image *i, Point o, Image *col, Font *f, char *text)
9280db9190eSforsyth {
9290db9190eSforsyth Rectangle r;
9300db9190eSforsyth
9310db9190eSforsyth r.max = stringsize(f, text);
9320db9190eSforsyth r.max = addpt(r.max, o);
9330db9190eSforsyth r.min.x = o.x;
9340db9190eSforsyth r.min.y = r.max.y - 1;
9350db9190eSforsyth draw(i, r, col, nil, ZP);
9360db9190eSforsyth }
9370db9190eSforsyth
9380db9190eSforsyth static void
tkul(Image * i,Point o,Image * col,int ul,Font * f,char * text)93937da2899SCharles.Forsyth tkul(Image *i, Point o, Image *col, int ul, Font *f, char *text)
94037da2899SCharles.Forsyth {
94137da2899SCharles.Forsyth char c, *v;
94237da2899SCharles.Forsyth Rectangle r;
94337da2899SCharles.Forsyth
94437da2899SCharles.Forsyth v = text+ul+1;
94537da2899SCharles.Forsyth c = *v;
94637da2899SCharles.Forsyth *v = '\0';
94737da2899SCharles.Forsyth r.max = stringsize(f, text);
94837da2899SCharles.Forsyth r.max = addpt(r.max, o);
94937da2899SCharles.Forsyth r.min = stringsize(f, v-1);
95037da2899SCharles.Forsyth *v = c;
95137da2899SCharles.Forsyth r.min.x = r.max.x - r.min.x;
95237da2899SCharles.Forsyth r.min.y = r.max.y - 1;
9531b078c23Sforsyth r.max.y++;
95437da2899SCharles.Forsyth draw(i, r, col, nil, ZP);
95537da2899SCharles.Forsyth }
95637da2899SCharles.Forsyth
9577668638cSforsyth void
tkdrawstring(Tk * tk,Image * i,Point o,char * text,int ul,Image * col,int j)95837da2899SCharles.Forsyth tkdrawstring(Tk *tk, Image *i, Point o, char *text, int ul, Image *col, int j)
95937da2899SCharles.Forsyth {
96037da2899SCharles.Forsyth int n, l, maxl, sox;
96137da2899SCharles.Forsyth char *q, *txt;
96237da2899SCharles.Forsyth Point p;
96337da2899SCharles.Forsyth TkEnv *e;
96437da2899SCharles.Forsyth
96537da2899SCharles.Forsyth e = tk->env;
96637da2899SCharles.Forsyth sox = maxl = 0;
96737da2899SCharles.Forsyth if(j != Tkleft){
96837da2899SCharles.Forsyth maxl = 0;
96937da2899SCharles.Forsyth txt = text;
97037da2899SCharles.Forsyth while(*txt){
97137da2899SCharles.Forsyth q = strchr(txt, '\n');
97237da2899SCharles.Forsyth if(q != nil)
97337da2899SCharles.Forsyth *q = '\0';
97437da2899SCharles.Forsyth l = stringwidth(e->font, txt);
97537da2899SCharles.Forsyth if(l > maxl)
97637da2899SCharles.Forsyth maxl = l;
97737da2899SCharles.Forsyth if(q == nil)
97837da2899SCharles.Forsyth break;
97937da2899SCharles.Forsyth txt = q+1;
98037da2899SCharles.Forsyth *q = '\n';
98137da2899SCharles.Forsyth }
98237da2899SCharles.Forsyth sox = o.x;
98337da2899SCharles.Forsyth }
98437da2899SCharles.Forsyth while(*text) {
98537da2899SCharles.Forsyth q = strchr(text, '\n');
98637da2899SCharles.Forsyth if(q != nil)
98737da2899SCharles.Forsyth *q = '\0';
98837da2899SCharles.Forsyth if(j != Tkleft){
98937da2899SCharles.Forsyth o.x = sox;
99037da2899SCharles.Forsyth l = stringwidth(e->font, text);
99137da2899SCharles.Forsyth if(j == Tkcenter)
99237da2899SCharles.Forsyth o.x += (maxl-l)/2;
99337da2899SCharles.Forsyth else
99437da2899SCharles.Forsyth o.x += maxl-l;
99537da2899SCharles.Forsyth }
99637da2899SCharles.Forsyth p = string(i, o, col, o, e->font, text);
99737da2899SCharles.Forsyth if(ul >= 0) {
99837da2899SCharles.Forsyth n = strlen(text);
99937da2899SCharles.Forsyth if(ul < n) {
10000db9190eSforsyth tkul(i, o, col, ul, e->font, text);
100137da2899SCharles.Forsyth ul = -1;
10020db9190eSforsyth } else if(ul == n) {
10030db9190eSforsyth tkulall(i, o, col, e->font, text);
10040db9190eSforsyth ul = -1;
10050db9190eSforsyth } else
100637da2899SCharles.Forsyth ul -= n;
100737da2899SCharles.Forsyth }
100837da2899SCharles.Forsyth o.y += e->font->height;
100937da2899SCharles.Forsyth if(q == nil)
101037da2899SCharles.Forsyth break;
101137da2899SCharles.Forsyth text = q+1;
101237da2899SCharles.Forsyth *q = '\n';
101337da2899SCharles.Forsyth }
101437da2899SCharles.Forsyth }
101537da2899SCharles.Forsyth
101637da2899SCharles.Forsyth /* for debugging */
101737da2899SCharles.Forsyth char*
tkname(Tk * tk)101837da2899SCharles.Forsyth tkname(Tk *tk)
101937da2899SCharles.Forsyth {
1020*5849851aSforsyth if(tk == nil)
1021*5849851aSforsyth return "(nil)";
1022*5849851aSforsyth if(tk->name == nil)
1023*5849851aSforsyth return "(noname)";
1024*5849851aSforsyth return tk->name->name;
102537da2899SCharles.Forsyth }
102637da2899SCharles.Forsyth
102737da2899SCharles.Forsyth Tk*
tkdeliver(Tk * tk,int event,void * data)102837da2899SCharles.Forsyth tkdeliver(Tk *tk, int event, void *data)
102937da2899SCharles.Forsyth {
103037da2899SCharles.Forsyth Tk *dest;
1031*5849851aSforsyth
1032*5849851aSforsyth if(tk != nil && ((ulong)tk->type >= TKwidgets || (ulong)tk->name < 4096 && tk->name != nil)){
1033*5849851aSforsyth print("invalid Tk: type %d name %p\n", tk->type, tk->name);
1034*5849851aSforsyth abort();
1035*5849851aSforsyth }
103637da2899SCharles.Forsyth //print("tkdeliver %v to %s\n", event, tkname(tk));
103737da2899SCharles.Forsyth if(tk == nil || ((tk->flag&Tkdestroy) && event != TkDestroy))
103837da2899SCharles.Forsyth return tk;
103937da2899SCharles.Forsyth if(event&(TkFocusin|TkFocusout) && (tk->flag&Tktakefocus))
104037da2899SCharles.Forsyth tk->dirty = tkrect(tk, 1);
104137da2899SCharles.Forsyth
104237da2899SCharles.Forsyth if (tkmethod[tk->type]->deliver != nil) {
104337da2899SCharles.Forsyth dest = tkmethod[tk->type]->deliver(tk, event, data);
104437da2899SCharles.Forsyth if (dest == nil)
104537da2899SCharles.Forsyth return tk;
104637da2899SCharles.Forsyth tkdirty(tk);
104737da2899SCharles.Forsyth return dest;
104837da2899SCharles.Forsyth }
104937da2899SCharles.Forsyth
105037da2899SCharles.Forsyth if((tk->flag & Tkdisabled) == 0)
105137da2899SCharles.Forsyth tksubdeliver(tk, tk->binds, event, data, 0);
105237da2899SCharles.Forsyth tkdirty(tk);
105337da2899SCharles.Forsyth return tk;
105437da2899SCharles.Forsyth }
105537da2899SCharles.Forsyth
105637da2899SCharles.Forsyth static int
nullop(char * fmt,...)105737da2899SCharles.Forsyth nullop(char *fmt, ...)
105837da2899SCharles.Forsyth {
105937da2899SCharles.Forsyth USED(fmt);
106037da2899SCharles.Forsyth return 0;
106137da2899SCharles.Forsyth }
106237da2899SCharles.Forsyth
106337da2899SCharles.Forsyth int
tksubdeliver(Tk * tk,TkAction * binds,int event,void * data,int extn)106437da2899SCharles.Forsyth tksubdeliver(Tk *tk, TkAction *binds, int event, void *data, int extn)
106537da2899SCharles.Forsyth {
106637da2899SCharles.Forsyth
106737da2899SCharles.Forsyth TkAction *a;
106837da2899SCharles.Forsyth int delivered, genkey, delivered2, iskey;
106937da2899SCharles.Forsyth //int (*debug)(char *fmt, ...);
1070*5849851aSforsyth
107137da2899SCharles.Forsyth if (!extn)
107237da2899SCharles.Forsyth return tkextndeliver(tk, binds, event, data);
107337da2899SCharles.Forsyth
107437da2899SCharles.Forsyth //debug = (tk->name && !strcmp(tk->name->name, ".cd")) ? print : nullop;
107537da2899SCharles.Forsyth //debug("subdeliver %v\n", event);
107637da2899SCharles.Forsyth
107737da2899SCharles.Forsyth if (event & TkTakefocus) {
107837da2899SCharles.Forsyth if (tk->flag & Tktakefocus)
107937da2899SCharles.Forsyth tksetkeyfocus(tk->env->top, tk, 0);
108037da2899SCharles.Forsyth return TkDdelivered;
108137da2899SCharles.Forsyth }
108237da2899SCharles.Forsyth
108337da2899SCharles.Forsyth delivered = TkDnone;
108437da2899SCharles.Forsyth genkey = 0;
108537da2899SCharles.Forsyth for(a = binds; a != nil; a = a->link) {
108637da2899SCharles.Forsyth if(event == a->event) {
108737da2899SCharles.Forsyth //debug(" exact match on %v\n", a->event);
108837da2899SCharles.Forsyth tkcmdbind(tk, event, a->arg, data);
108937da2899SCharles.Forsyth delivered = TkDdelivered;
109037da2899SCharles.Forsyth } else if (a->event == TkKey && (a->type>>8)==TkAadd)
109137da2899SCharles.Forsyth genkey = 1;
109237da2899SCharles.Forsyth }
109337da2899SCharles.Forsyth if(delivered != TkDnone && !((event & TkKey) && genkey))
109437da2899SCharles.Forsyth return delivered;
109537da2899SCharles.Forsyth
109637da2899SCharles.Forsyth delivered2 = delivered;
109737da2899SCharles.Forsyth for(a = binds; a != nil; a = a->link) {
109837da2899SCharles.Forsyth /*
109937da2899SCharles.Forsyth * only bind to non-specific key events; if a specific
110037da2899SCharles.Forsyth * key event has already been delivered, only deliver event if
110137da2899SCharles.Forsyth * the non-specific binding was added. (TkAadd)
110237da2899SCharles.Forsyth */
110337da2899SCharles.Forsyth if (a->event & TkExtns)
110437da2899SCharles.Forsyth continue;
110537da2899SCharles.Forsyth iskey = (a->event & TkKey);
110637da2899SCharles.Forsyth if (iskey ^ (event & TkKey))
110737da2899SCharles.Forsyth continue;
110837da2899SCharles.Forsyth if(iskey && (TKKEY(a->event) != 0
110937da2899SCharles.Forsyth || ((a->type>>8) != TkAadd && delivered != TkDnone)))
111037da2899SCharles.Forsyth continue;
111137da2899SCharles.Forsyth if(!iskey && (a->event & TkMotion) && (a->event&TkEpress) != 0)
111237da2899SCharles.Forsyth continue;
111337da2899SCharles.Forsyth if(!(event & TkDouble) && (a->event & TkDouble))
111437da2899SCharles.Forsyth continue;
111537da2899SCharles.Forsyth if((event & ~TkDouble) & a->event) {
111637da2899SCharles.Forsyth //debug(" partial match on %v\n", a->event);
111737da2899SCharles.Forsyth tkcmdbind(tk, event, a->arg, data);
111837da2899SCharles.Forsyth delivered2 = TkDdelivered;
111937da2899SCharles.Forsyth }
112037da2899SCharles.Forsyth }
112137da2899SCharles.Forsyth return delivered2;
112237da2899SCharles.Forsyth }
112337da2899SCharles.Forsyth
112437da2899SCharles.Forsyth void
tkcancel(TkAction ** l,int event)112537da2899SCharles.Forsyth tkcancel(TkAction **l, int event)
112637da2899SCharles.Forsyth {
112737da2899SCharles.Forsyth TkAction *a;
112837da2899SCharles.Forsyth
112937da2899SCharles.Forsyth for(a = *l; a; a = *l) {
113037da2899SCharles.Forsyth if(a->event == event) {
113137da2899SCharles.Forsyth *l = a->link;
113237da2899SCharles.Forsyth a->link = nil;
113337da2899SCharles.Forsyth tkfreebind(a);
113437da2899SCharles.Forsyth continue;
113537da2899SCharles.Forsyth }
113637da2899SCharles.Forsyth l = &a->link;
113737da2899SCharles.Forsyth }
113837da2899SCharles.Forsyth }
113937da2899SCharles.Forsyth
114037da2899SCharles.Forsyth static void
tkcancela(TkAction ** l,int event,int type,char * arg)114137da2899SCharles.Forsyth tkcancela(TkAction **l, int event, int type, char *arg)
114237da2899SCharles.Forsyth {
114337da2899SCharles.Forsyth TkAction *a;
114437da2899SCharles.Forsyth
114537da2899SCharles.Forsyth for(a = *l; a; a = *l) {
114637da2899SCharles.Forsyth if(a->event == event && strcmp(a->arg, arg) == 0 && (a->type&0xff) == type){
114737da2899SCharles.Forsyth *l = a->link;
114837da2899SCharles.Forsyth a->link = nil;
114937da2899SCharles.Forsyth tkfreebind(a);
115037da2899SCharles.Forsyth continue;
115137da2899SCharles.Forsyth }
115237da2899SCharles.Forsyth l = &a->link;
115337da2899SCharles.Forsyth }
115437da2899SCharles.Forsyth }
115537da2899SCharles.Forsyth
115637da2899SCharles.Forsyth char*
tkaction(TkAction ** l,int event,int type,char * arg,int how)115737da2899SCharles.Forsyth tkaction(TkAction **l, int event, int type, char *arg, int how)
115837da2899SCharles.Forsyth {
115937da2899SCharles.Forsyth TkAction *a;
116037da2899SCharles.Forsyth
116137da2899SCharles.Forsyth if(arg == nil)
116237da2899SCharles.Forsyth return nil;
116337da2899SCharles.Forsyth if(how == TkArepl)
116437da2899SCharles.Forsyth tkcancel(l, event);
116537da2899SCharles.Forsyth else if(how == TkAadd){
116637da2899SCharles.Forsyth for(a = *l; a; a = a->link)
116737da2899SCharles.Forsyth if(a->event == event && strcmp(a->arg, arg) == 0 && (a->type&0xff) == type){
116837da2899SCharles.Forsyth a->type = type + (how << 8);
116937da2899SCharles.Forsyth return nil;
117037da2899SCharles.Forsyth }
117137da2899SCharles.Forsyth }
117237da2899SCharles.Forsyth else if(how == TkAsub){
117337da2899SCharles.Forsyth tkcancela(l, event, type, arg);
117437da2899SCharles.Forsyth if(type == TkDynamic) /* should always be the case */
117537da2899SCharles.Forsyth free(arg);
117637da2899SCharles.Forsyth return nil;
117737da2899SCharles.Forsyth }
117837da2899SCharles.Forsyth
117937da2899SCharles.Forsyth a = malloc(sizeof(TkAction));
118037da2899SCharles.Forsyth if(a == nil) {
118137da2899SCharles.Forsyth if(type == TkDynamic)
118237da2899SCharles.Forsyth free(arg);
118337da2899SCharles.Forsyth return TkNomem;
118437da2899SCharles.Forsyth }
118537da2899SCharles.Forsyth
118637da2899SCharles.Forsyth a->event = event;
118737da2899SCharles.Forsyth a->arg = arg;
118837da2899SCharles.Forsyth a->type = type + (how << 8);
118937da2899SCharles.Forsyth
119037da2899SCharles.Forsyth a->link = *l;
119137da2899SCharles.Forsyth *l = a;
119237da2899SCharles.Forsyth
119337da2899SCharles.Forsyth return nil;
119437da2899SCharles.Forsyth }
119537da2899SCharles.Forsyth
119637da2899SCharles.Forsyth char*
tkitem(char * buf,char * a)119737da2899SCharles.Forsyth tkitem(char *buf, char *a)
119837da2899SCharles.Forsyth {
119937da2899SCharles.Forsyth char *e;
120037da2899SCharles.Forsyth
120137da2899SCharles.Forsyth while(*a && (*a == ' ' || *a == '\t'))
120237da2899SCharles.Forsyth a++;
120337da2899SCharles.Forsyth
120437da2899SCharles.Forsyth e = buf + Tkmaxitem - 1;
120537da2899SCharles.Forsyth while(*a && *a != ' ' && *a != '\t' && buf < e)
120637da2899SCharles.Forsyth *buf++ = *a++;
120737da2899SCharles.Forsyth
120837da2899SCharles.Forsyth *buf = '\0';
120937da2899SCharles.Forsyth while(*a && (*a == ' ' || *a == '\t'))
121037da2899SCharles.Forsyth a++;
121137da2899SCharles.Forsyth return a;
121237da2899SCharles.Forsyth }
121337da2899SCharles.Forsyth
1214*5849851aSforsyth /*
1215*5849851aSforsyth * if tk is a subwindow or a descendent, return the subwindow;
1216*5849851aSforsyth * return nil otherwise
121737da2899SCharles.Forsyth */
1218*5849851aSforsyth Tk*
tkfindsub(Tk * tk)1219*5849851aSforsyth tkfindsub(Tk *tk)
1220*5849851aSforsyth {
1221*5849851aSforsyth for(; tk != nil; tk = tk->master){
1222*5849851aSforsyth if(tk->parent != nil)
1223*5849851aSforsyth return tk; /* tk->parent is canvas or text */
1224*5849851aSforsyth }
1225*5849851aSforsyth return nil;
122637da2899SCharles.Forsyth }
122737da2899SCharles.Forsyth
122837da2899SCharles.Forsyth /*
122937da2899SCharles.Forsyth * Return absolute screen position of tk (just outside its top-left border).
123037da2899SCharles.Forsyth * When a widget is embedded in a text or canvas widget, we need to
123137da2899SCharles.Forsyth * use the text or canvas's relpos() function instead of act{x,y}, and we
123237da2899SCharles.Forsyth * need to folow up the parent pointer rather than the master one.
123337da2899SCharles.Forsyth */
123437da2899SCharles.Forsyth Point
tkposn(Tk * tk)123537da2899SCharles.Forsyth tkposn(Tk *tk)
123637da2899SCharles.Forsyth {
123737da2899SCharles.Forsyth Tk *f, *last;
123837da2899SCharles.Forsyth Point g;
123937da2899SCharles.Forsyth
124037da2899SCharles.Forsyth last = tk;
124137da2899SCharles.Forsyth if(tk->parent != nil) {
124237da2899SCharles.Forsyth g = tkmethod[tk->parent->type]->relpos(tk);
124337da2899SCharles.Forsyth f = tk->parent;
1244*5849851aSforsyth } else {
124537da2899SCharles.Forsyth g.x = tk->act.x;
124637da2899SCharles.Forsyth g.y = tk->act.y;
124737da2899SCharles.Forsyth f = tk->master;
124837da2899SCharles.Forsyth }
1249*5849851aSforsyth while(f != nil) {
125037da2899SCharles.Forsyth g.x += f->borderwidth;
125137da2899SCharles.Forsyth g.y += f->borderwidth;
125237da2899SCharles.Forsyth last = f;
125337da2899SCharles.Forsyth if(f->parent != nil) {
125437da2899SCharles.Forsyth g = addpt(g, tkmethod[f->parent->type]->relpos(f));
125537da2899SCharles.Forsyth f = f->parent;
1256*5849851aSforsyth } else {
125737da2899SCharles.Forsyth g.x += f->act.x;
125837da2899SCharles.Forsyth g.y += f->act.y;
125937da2899SCharles.Forsyth f = f->master;
126037da2899SCharles.Forsyth }
126137da2899SCharles.Forsyth }
126237da2899SCharles.Forsyth if (last->flag & Tkwindow)
126337da2899SCharles.Forsyth g = addpt(g, TKobj(TkWin, last)->req);
126437da2899SCharles.Forsyth return g;
126537da2899SCharles.Forsyth }
126637da2899SCharles.Forsyth
126737da2899SCharles.Forsyth /*
126837da2899SCharles.Forsyth * convert screen coords to local widget coords
126937da2899SCharles.Forsyth */
127037da2899SCharles.Forsyth Point
tkscrn2local(Tk * tk,Point p)127137da2899SCharles.Forsyth tkscrn2local(Tk *tk, Point p)
127237da2899SCharles.Forsyth {
127337da2899SCharles.Forsyth p = subpt(p, tkposn(tk));
127437da2899SCharles.Forsyth p.x -= tk->borderwidth;
127537da2899SCharles.Forsyth p.y -= tk->borderwidth;
127637da2899SCharles.Forsyth return p;
127737da2899SCharles.Forsyth }
127837da2899SCharles.Forsyth
127937da2899SCharles.Forsyth int
tkvisiblerect(Tk * tk,Rectangle * rr)128037da2899SCharles.Forsyth tkvisiblerect(Tk *tk, Rectangle *rr)
128137da2899SCharles.Forsyth {
128237da2899SCharles.Forsyth Rectangle r;
128337da2899SCharles.Forsyth Point g;
128437da2899SCharles.Forsyth Tk *f, *last;
128537da2899SCharles.Forsyth g = Pt(tk->borderwidth, tk->borderwidth);
128637da2899SCharles.Forsyth last = tk;
128737da2899SCharles.Forsyth if(tk->parent != nil) {
128837da2899SCharles.Forsyth g = addpt(g, tkmethod[tk->parent->type]->relpos(tk));
128937da2899SCharles.Forsyth f = tk->parent;
129037da2899SCharles.Forsyth } else {
129137da2899SCharles.Forsyth g.x += tk->act.x;
129237da2899SCharles.Forsyth g.y += tk->act.y;
129337da2899SCharles.Forsyth f = tk->master;
129437da2899SCharles.Forsyth }
129537da2899SCharles.Forsyth if (f == nil) {
129637da2899SCharles.Forsyth *rr = tkrect(tk, 1);
129737da2899SCharles.Forsyth return 1;
129837da2899SCharles.Forsyth }
129937da2899SCharles.Forsyth r = rectaddpt(tkrect(tk, 1), g);
130037da2899SCharles.Forsyth while (f) {
130137da2899SCharles.Forsyth if (!rectclip(&r, tkrect(f, 0)))
130237da2899SCharles.Forsyth return 0;
130337da2899SCharles.Forsyth g.x = f->borderwidth;
130437da2899SCharles.Forsyth g.y = f->borderwidth;
130537da2899SCharles.Forsyth last = f;
130637da2899SCharles.Forsyth if (f->parent != nil) {
130737da2899SCharles.Forsyth g = addpt(g, tkmethod[f->parent->type]->relpos(f));
130837da2899SCharles.Forsyth f = f->parent;
130937da2899SCharles.Forsyth } else {
131037da2899SCharles.Forsyth g.x += f->act.x;
131137da2899SCharles.Forsyth g.y += f->act.y;
131237da2899SCharles.Forsyth f = f->master;
131337da2899SCharles.Forsyth }
131437da2899SCharles.Forsyth r = rectaddpt(r, g);
131537da2899SCharles.Forsyth }
131637da2899SCharles.Forsyth if (last->flag & Tkwindow)
131737da2899SCharles.Forsyth r = rectaddpt(r, TKobj(TkWin, last)->act);
131837da2899SCharles.Forsyth /*
131937da2899SCharles.Forsyth * now we have the visible rectangle in screen coords;
132037da2899SCharles.Forsyth * subtract actx+borderwidth and we've got it back in
132137da2899SCharles.Forsyth * widget-local coords again
132237da2899SCharles.Forsyth */
132337da2899SCharles.Forsyth r = rectsubpt(r, tkposn(tk));
132437da2899SCharles.Forsyth *rr = rectsubpt(r, Pt(tk->borderwidth, tk->borderwidth));
132537da2899SCharles.Forsyth return 1;
132637da2899SCharles.Forsyth }
132737da2899SCharles.Forsyth
132837da2899SCharles.Forsyth Point
tkanchorpoint(Rectangle r,Point size,int anchor)132937da2899SCharles.Forsyth tkanchorpoint(Rectangle r, Point size, int anchor)
133037da2899SCharles.Forsyth {
133137da2899SCharles.Forsyth int dx, dy;
133237da2899SCharles.Forsyth Point p;
133337da2899SCharles.Forsyth
133437da2899SCharles.Forsyth p = r.min;
133537da2899SCharles.Forsyth dx = Dx(r) - size.x;
133637da2899SCharles.Forsyth dy = Dy(r) - size.y;
133737da2899SCharles.Forsyth if((anchor & (Tknorth|Tksouth)) == 0)
133837da2899SCharles.Forsyth p.y += dy/2;
13390db9190eSforsyth else if(anchor & Tksouth)
134037da2899SCharles.Forsyth p.y += dy;
134137da2899SCharles.Forsyth
134237da2899SCharles.Forsyth if((anchor & (Tkeast|Tkwest)) == 0)
134337da2899SCharles.Forsyth p.x += dx/2;
13440db9190eSforsyth else if(anchor & Tkeast)
134537da2899SCharles.Forsyth p.x += dx;
134637da2899SCharles.Forsyth return p;
134737da2899SCharles.Forsyth }
134837da2899SCharles.Forsyth
134937da2899SCharles.Forsyth static char*
tkunits(char c,int * d,TkEnv * e)135037da2899SCharles.Forsyth tkunits(char c, int *d, TkEnv *e)
135137da2899SCharles.Forsyth {
135237da2899SCharles.Forsyth switch(c) {
135337da2899SCharles.Forsyth default:
135437da2899SCharles.Forsyth if(c >= '0' || c <= '9' || c == '.')
135537da2899SCharles.Forsyth break;
135637da2899SCharles.Forsyth return TkBadvl;
135737da2899SCharles.Forsyth case '\0':
135837da2899SCharles.Forsyth break;
135937da2899SCharles.Forsyth case 'c': /* Centimeters */
136037da2899SCharles.Forsyth *d *= (Tkdpi*100)/254;
136137da2899SCharles.Forsyth break;
136237da2899SCharles.Forsyth case 'm': /* Millimeters */
136337da2899SCharles.Forsyth *d *= (Tkdpi*10)/254;
136437da2899SCharles.Forsyth break;
136537da2899SCharles.Forsyth case 'i': /* Inches */
136637da2899SCharles.Forsyth *d *= Tkdpi;
136737da2899SCharles.Forsyth break;
136837da2899SCharles.Forsyth case 'p': /* Points */
136937da2899SCharles.Forsyth *d = (*d*Tkdpi)/72;
137037da2899SCharles.Forsyth break;
137137da2899SCharles.Forsyth case 'w': /* Character width */
137237da2899SCharles.Forsyth if(e == nil)
137337da2899SCharles.Forsyth return TkBadvl;
137437da2899SCharles.Forsyth *d = *d * e->wzero;
137537da2899SCharles.Forsyth break;
137637da2899SCharles.Forsyth case 'h': /* Character height */
137737da2899SCharles.Forsyth if(e == nil)
137837da2899SCharles.Forsyth return TkBadvl;
137937da2899SCharles.Forsyth *d = *d * e->font->height;
138037da2899SCharles.Forsyth break;
138137da2899SCharles.Forsyth }
138237da2899SCharles.Forsyth return nil;
138337da2899SCharles.Forsyth }
138437da2899SCharles.Forsyth
138537da2899SCharles.Forsyth int
TKF2I(int f)138637da2899SCharles.Forsyth TKF2I(int f)
138737da2899SCharles.Forsyth {
138837da2899SCharles.Forsyth if (f >= 0)
138937da2899SCharles.Forsyth return (f + Tkfpscalar/2) / Tkfpscalar;
139037da2899SCharles.Forsyth return (f - Tkfpscalar/2) / Tkfpscalar;
139137da2899SCharles.Forsyth }
139237da2899SCharles.Forsyth
139337da2899SCharles.Forsyth /*
139437da2899SCharles.Forsyth * Parse a floating point number into a decimal fixed point representation
139537da2899SCharles.Forsyth */
139637da2899SCharles.Forsyth char*
tkfrac(char ** arg,int * f,TkEnv * env)139737da2899SCharles.Forsyth tkfrac(char **arg, int *f, TkEnv *env)
139837da2899SCharles.Forsyth {
139937da2899SCharles.Forsyth int c, minus, i, fscale, seendigit;
140037da2899SCharles.Forsyth char *p, *e;
140137da2899SCharles.Forsyth
140237da2899SCharles.Forsyth seendigit = 0;
140337da2899SCharles.Forsyth
140437da2899SCharles.Forsyth p = *arg;
140537da2899SCharles.Forsyth p = tkskip(p, " \t");
140637da2899SCharles.Forsyth
140737da2899SCharles.Forsyth minus = 0;
140837da2899SCharles.Forsyth if(*p == '-') {
140937da2899SCharles.Forsyth minus = 1;
141037da2899SCharles.Forsyth p++;
141137da2899SCharles.Forsyth }
141237da2899SCharles.Forsyth i = 0;
141337da2899SCharles.Forsyth while(*p) {
141437da2899SCharles.Forsyth c = *p;
141537da2899SCharles.Forsyth if(c == '.')
141637da2899SCharles.Forsyth break;
141737da2899SCharles.Forsyth if(c < '0' || c > '9')
141837da2899SCharles.Forsyth break;
141937da2899SCharles.Forsyth i = i*10 + (c - '0');
142037da2899SCharles.Forsyth seendigit = 1;
142137da2899SCharles.Forsyth p++;
142237da2899SCharles.Forsyth }
142337da2899SCharles.Forsyth i *= Tkfpscalar;
142437da2899SCharles.Forsyth if(*p == '.')
142537da2899SCharles.Forsyth p++;
142637da2899SCharles.Forsyth fscale = Tkfpscalar;
142737da2899SCharles.Forsyth while(*p && *p >= '0' && *p <= '9') {
142837da2899SCharles.Forsyth fscale /= 10;
142937da2899SCharles.Forsyth i += fscale * (*p++ - '0');
143037da2899SCharles.Forsyth seendigit = 1;
143137da2899SCharles.Forsyth }
143237da2899SCharles.Forsyth
143337da2899SCharles.Forsyth if(minus)
143437da2899SCharles.Forsyth i = -i;
143537da2899SCharles.Forsyth
143637da2899SCharles.Forsyth if(!seendigit)
143737da2899SCharles.Forsyth return TkBadvl;
143837da2899SCharles.Forsyth e = tkunits(*p, &i, env);
143937da2899SCharles.Forsyth if (e != nil)
144037da2899SCharles.Forsyth return e;
144137da2899SCharles.Forsyth while (*p && *p != ' ' && *p != '\t')
144237da2899SCharles.Forsyth p++;
144337da2899SCharles.Forsyth *arg = p;
144437da2899SCharles.Forsyth *f = i;
144537da2899SCharles.Forsyth return nil;
144637da2899SCharles.Forsyth }
144737da2899SCharles.Forsyth
144837da2899SCharles.Forsyth char*
tkfracword(TkTop * t,char ** arg,int * f,TkEnv * env)144937da2899SCharles.Forsyth tkfracword(TkTop *t, char **arg, int *f, TkEnv *env)
145037da2899SCharles.Forsyth {
145137da2899SCharles.Forsyth char *p;
145237da2899SCharles.Forsyth char buf[Tkminitem];
145337da2899SCharles.Forsyth
145437da2899SCharles.Forsyth *arg = tkword(t, *arg, buf, buf+sizeof(buf), nil);
145537da2899SCharles.Forsyth p = buf;
145637da2899SCharles.Forsyth return tkfrac(&p, f, env);
145737da2899SCharles.Forsyth }
145837da2899SCharles.Forsyth
145937da2899SCharles.Forsyth char*
tkfprint(char * v,int frac)146037da2899SCharles.Forsyth tkfprint(char *v, int frac)
146137da2899SCharles.Forsyth {
146237da2899SCharles.Forsyth int fscale;
146337da2899SCharles.Forsyth
146437da2899SCharles.Forsyth if(frac < 0) {
146537da2899SCharles.Forsyth *v++ = '-';
146637da2899SCharles.Forsyth frac = -frac;
146737da2899SCharles.Forsyth }
146837da2899SCharles.Forsyth v += sprint(v, "%d", frac/Tkfpscalar);
146937da2899SCharles.Forsyth frac = frac%Tkfpscalar;
147037da2899SCharles.Forsyth if(frac != 0)
147137da2899SCharles.Forsyth *v++ = '.';
147237da2899SCharles.Forsyth fscale = Tkfpscalar/10;
147337da2899SCharles.Forsyth while(frac) {
147437da2899SCharles.Forsyth *v++ = '0' + frac/fscale;
147537da2899SCharles.Forsyth frac %= fscale;
147637da2899SCharles.Forsyth fscale /= 10;
147737da2899SCharles.Forsyth }
147837da2899SCharles.Forsyth *v = '\0';
147937da2899SCharles.Forsyth return v;
148037da2899SCharles.Forsyth }
148137da2899SCharles.Forsyth
148237da2899SCharles.Forsyth char*
tkvalue(char ** val,char * fmt,...)148337da2899SCharles.Forsyth tkvalue(char **val, char *fmt, ...)
148437da2899SCharles.Forsyth {
148537da2899SCharles.Forsyth va_list arg;
148637da2899SCharles.Forsyth Fmt fmtx;
148737da2899SCharles.Forsyth
148837da2899SCharles.Forsyth if(val == nil)
148937da2899SCharles.Forsyth return nil;
149037da2899SCharles.Forsyth
149137da2899SCharles.Forsyth fmtstrinit(&fmtx);
149237da2899SCharles.Forsyth if(*val != nil)
149337da2899SCharles.Forsyth if(fmtprint(&fmtx, "%s", *val) < 0)
149437da2899SCharles.Forsyth return TkNomem;
149537da2899SCharles.Forsyth va_start(arg, fmt);
149637da2899SCharles.Forsyth fmtvprint(&fmtx, fmt, arg);
149737da2899SCharles.Forsyth va_end(arg);
149837da2899SCharles.Forsyth free(*val);
149937da2899SCharles.Forsyth *val = fmtstrflush(&fmtx);
150037da2899SCharles.Forsyth if(*val == nil)
150137da2899SCharles.Forsyth return TkNomem;
150237da2899SCharles.Forsyth return nil;
150337da2899SCharles.Forsyth }
150437da2899SCharles.Forsyth
150537da2899SCharles.Forsyth static char*
tkwidgetcmd(TkTop * t,Tk * tk,char * arg,char ** val)150637da2899SCharles.Forsyth tkwidgetcmd(TkTop *t, Tk *tk, char *arg, char **val)
150737da2899SCharles.Forsyth {
150837da2899SCharles.Forsyth TkMethod *cm;
150937da2899SCharles.Forsyth TkCmdtab *ct;
151037da2899SCharles.Forsyth int bot, top, new, r;
151137da2899SCharles.Forsyth char *e, *buf;
151237da2899SCharles.Forsyth
151337da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
151437da2899SCharles.Forsyth if(buf == nil)
151537da2899SCharles.Forsyth return TkNomem;
151637da2899SCharles.Forsyth
151737da2899SCharles.Forsyth arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);
151837da2899SCharles.Forsyth if(val != nil)
151937da2899SCharles.Forsyth *val = nil;
152037da2899SCharles.Forsyth
152137da2899SCharles.Forsyth cm = tkmethod[tk->type];
152237da2899SCharles.Forsyth
152337da2899SCharles.Forsyth e = TkBadcm;
152437da2899SCharles.Forsyth bot = 0;
152537da2899SCharles.Forsyth top = cm->ncmd - 1;
152637da2899SCharles.Forsyth
152737da2899SCharles.Forsyth while(bot <= top) {
152837da2899SCharles.Forsyth new = (bot + top)/2;
152937da2899SCharles.Forsyth ct = &cm->cmd[new];
153037da2899SCharles.Forsyth r = strcmp(ct->name, buf);
153137da2899SCharles.Forsyth if(r == 0) {
153237da2899SCharles.Forsyth e = ct->fn(tk, arg, val);
153337da2899SCharles.Forsyth break;
153437da2899SCharles.Forsyth }
153537da2899SCharles.Forsyth if(r < 0)
153637da2899SCharles.Forsyth bot = new + 1;
153737da2899SCharles.Forsyth else
153837da2899SCharles.Forsyth top = new - 1;
153937da2899SCharles.Forsyth }
154037da2899SCharles.Forsyth free(buf);
154137da2899SCharles.Forsyth tkdirty(tk);
154237da2899SCharles.Forsyth return e;
154337da2899SCharles.Forsyth }
154437da2899SCharles.Forsyth
154537da2899SCharles.Forsyth Rectangle
tkrect(Tk * tk,int withborder)154637da2899SCharles.Forsyth tkrect(Tk *tk, int withborder)
154737da2899SCharles.Forsyth {
154837da2899SCharles.Forsyth Rectangle r;
154937da2899SCharles.Forsyth int bd;
15500b978350Sforsyth
155137da2899SCharles.Forsyth bd = withborder? tk->borderwidth: 0;
155237da2899SCharles.Forsyth r.min.x = -bd;
155337da2899SCharles.Forsyth r.min.y = -bd;
155437da2899SCharles.Forsyth r.max.x = tk->act.width + bd;
155537da2899SCharles.Forsyth r.max.y = tk->act.height + bd;
155637da2899SCharles.Forsyth return r;
155737da2899SCharles.Forsyth }
155837da2899SCharles.Forsyth
155937da2899SCharles.Forsyth void
tkdirty(Tk * tk)156037da2899SCharles.Forsyth tkdirty(Tk *tk)
156137da2899SCharles.Forsyth {
156237da2899SCharles.Forsyth Tk *sub;
156337da2899SCharles.Forsyth Point rel;
156437da2899SCharles.Forsyth Rectangle dirty;
156537da2899SCharles.Forsyth int isdirty, transparent;
156637da2899SCharles.Forsyth
156737da2899SCharles.Forsyth /*
156837da2899SCharles.Forsyth * mark as dirty all views underneath a dirty transparent widget
156937da2899SCharles.Forsyth * down to the first opaque widget.
157037da2899SCharles.Forsyth * inform parents about any dirtiness.
157137da2899SCharles.Forsyth
157237da2899SCharles.Forsyth * XXX as Tksubsub never gets reset, testing against Tksubsub doesn't *exactly* test
157337da2899SCharles.Forsyth * whether we're in a canvas/text widget, but merely
157437da2899SCharles.Forsyth * whether it has ever been. Tksubsub should probably be reset on unpack.
157537da2899SCharles.Forsyth */
157637da2899SCharles.Forsyth isdirty = Dx(tk->dirty) > 0;
157737da2899SCharles.Forsyth transparent = tk->flag & Tktransparent;
157837da2899SCharles.Forsyth sub = tk;
157937da2899SCharles.Forsyth while (isdirty && ((tk->flag&Tksubsub) || transparent)) {
158037da2899SCharles.Forsyth if (tk->master != nil) {
158137da2899SCharles.Forsyth if (transparent) {
158237da2899SCharles.Forsyth rel.x = tk->act.x + tk->borderwidth;
158337da2899SCharles.Forsyth rel.y = tk->act.y + tk->borderwidth;
158437da2899SCharles.Forsyth dirty = rectaddpt(sub->dirty, rel);
158537da2899SCharles.Forsyth sub = tk->master;
158637da2899SCharles.Forsyth combinerect(&sub->dirty, dirty);
158737da2899SCharles.Forsyth transparent = sub->flag & Tktransparent;
158837da2899SCharles.Forsyth }
158937da2899SCharles.Forsyth tk = tk->master;
159037da2899SCharles.Forsyth } else if (tk->parent != nil) {
159137da2899SCharles.Forsyth tkmethod[tk->parent->type]->dirtychild(sub);
159237da2899SCharles.Forsyth tk = sub = tk->parent;
159337da2899SCharles.Forsyth isdirty = Dx(sub->dirty) > 0;
159437da2899SCharles.Forsyth transparent = sub->flag & Tktransparent;
159537da2899SCharles.Forsyth } else
159637da2899SCharles.Forsyth break;
159737da2899SCharles.Forsyth }
159837da2899SCharles.Forsyth }
159937da2899SCharles.Forsyth
160037da2899SCharles.Forsyth static int
qcmdcmp(const void * a,const void * b)160137da2899SCharles.Forsyth qcmdcmp(const void *a, const void *b)
160237da2899SCharles.Forsyth {
160337da2899SCharles.Forsyth return strcmp(((TkCmdtab*)a)->name, ((TkCmdtab*)b)->name);
160437da2899SCharles.Forsyth }
160537da2899SCharles.Forsyth
160637da2899SCharles.Forsyth void
tksorttable(void)160737da2899SCharles.Forsyth tksorttable(void)
160837da2899SCharles.Forsyth {
160937da2899SCharles.Forsyth int i;
161037da2899SCharles.Forsyth TkMethod *c;
161137da2899SCharles.Forsyth TkCmdtab *cmd;
161237da2899SCharles.Forsyth
161337da2899SCharles.Forsyth for(i = 0; i < TKwidgets; i++) {
161437da2899SCharles.Forsyth c = tkmethod[i];
161537da2899SCharles.Forsyth if(c->cmd == nil)
161637da2899SCharles.Forsyth continue;
161737da2899SCharles.Forsyth
161837da2899SCharles.Forsyth for(cmd = c->cmd; cmd->name != nil; cmd++)
161937da2899SCharles.Forsyth ;
162037da2899SCharles.Forsyth c->ncmd = cmd - c->cmd;
162137da2899SCharles.Forsyth
162237da2899SCharles.Forsyth qsort(c->cmd, c->ncmd, sizeof(TkCmdtab), qcmdcmp);
162337da2899SCharles.Forsyth }
162437da2899SCharles.Forsyth }
162537da2899SCharles.Forsyth
162637da2899SCharles.Forsyth static char*
tksinglecmd(TkTop * t,char * arg,char ** val)162737da2899SCharles.Forsyth tksinglecmd(TkTop *t, char *arg, char **val)
162837da2899SCharles.Forsyth {
162937da2899SCharles.Forsyth Tk *tk;
163037da2899SCharles.Forsyth int bot, top, new;
163137da2899SCharles.Forsyth char *e, *buf;
163237da2899SCharles.Forsyth
163337da2899SCharles.Forsyth if(t->debug)
163437da2899SCharles.Forsyth print("tk: '%s'\n", arg);
163537da2899SCharles.Forsyth
163637da2899SCharles.Forsyth buf = mallocz(Tkmaxitem, 0);
163737da2899SCharles.Forsyth if(buf == nil)
163837da2899SCharles.Forsyth return TkNomem;
163937da2899SCharles.Forsyth
164037da2899SCharles.Forsyth arg = tkword(t, arg, buf, buf+Tkmaxitem, nil);
164137da2899SCharles.Forsyth switch(buf[0]) {
164237da2899SCharles.Forsyth case '\0':
164337da2899SCharles.Forsyth free(buf);
164437da2899SCharles.Forsyth return nil;
164537da2899SCharles.Forsyth case '.':
164637da2899SCharles.Forsyth tk = tklook(t, buf, 0);
164737da2899SCharles.Forsyth if(tk == nil){
164837da2899SCharles.Forsyth tkerr(t, buf);
164937da2899SCharles.Forsyth free(buf);
165037da2899SCharles.Forsyth return TkBadwp;
165137da2899SCharles.Forsyth }
165237da2899SCharles.Forsyth e = tkwidgetcmd(t, tk, arg, val);
165337da2899SCharles.Forsyth free(buf);
165437da2899SCharles.Forsyth return e;
165537da2899SCharles.Forsyth }
165637da2899SCharles.Forsyth
165737da2899SCharles.Forsyth bot = 0;
165837da2899SCharles.Forsyth top = nelem(cmdmain) - 1;
165937da2899SCharles.Forsyth e = TkBadcm;
166037da2899SCharles.Forsyth while(bot <= top) {
166137da2899SCharles.Forsyth int rc;
166237da2899SCharles.Forsyth new = (bot + top)/2;
166337da2899SCharles.Forsyth rc = strcmp(cmdmain[new].name, buf);
166437da2899SCharles.Forsyth if(!rc) {
166537da2899SCharles.Forsyth e = cmdmain[new].fn(t, arg, val);
166637da2899SCharles.Forsyth break;
166737da2899SCharles.Forsyth }
166837da2899SCharles.Forsyth
166937da2899SCharles.Forsyth if(rc < 0)
167037da2899SCharles.Forsyth bot = new + 1;
167137da2899SCharles.Forsyth else
167237da2899SCharles.Forsyth top = new - 1;
167337da2899SCharles.Forsyth }
167437da2899SCharles.Forsyth free(buf);
167537da2899SCharles.Forsyth return e;
167637da2899SCharles.Forsyth }
167737da2899SCharles.Forsyth
167837da2899SCharles.Forsyth static char*
tkmatch(int inc,int dec,char * p)167937da2899SCharles.Forsyth tkmatch(int inc, int dec, char *p)
168037da2899SCharles.Forsyth {
168137da2899SCharles.Forsyth int depth, esc, c;
168237da2899SCharles.Forsyth
168337da2899SCharles.Forsyth esc = 0;
168437da2899SCharles.Forsyth depth = 1;
168537da2899SCharles.Forsyth while(*p) {
168637da2899SCharles.Forsyth c = *p;
168737da2899SCharles.Forsyth if(esc == 0) {
168837da2899SCharles.Forsyth if(c == inc)
168937da2899SCharles.Forsyth depth++;
169037da2899SCharles.Forsyth if(c == dec)
169137da2899SCharles.Forsyth depth--;
169237da2899SCharles.Forsyth if(depth == 0)
169337da2899SCharles.Forsyth return p;
169437da2899SCharles.Forsyth }
169537da2899SCharles.Forsyth if(c == '\\' && esc == 0)
169637da2899SCharles.Forsyth esc = 1;
169737da2899SCharles.Forsyth else
169837da2899SCharles.Forsyth esc = 0;
169937da2899SCharles.Forsyth p++;
170037da2899SCharles.Forsyth }
170137da2899SCharles.Forsyth return nil;
170237da2899SCharles.Forsyth }
170337da2899SCharles.Forsyth
170437da2899SCharles.Forsyth char*
tkexec(TkTop * t,char * arg,char ** val)170537da2899SCharles.Forsyth tkexec(TkTop *t, char *arg, char **val)
170637da2899SCharles.Forsyth {
170737da2899SCharles.Forsyth int cmdsz, n;
170837da2899SCharles.Forsyth char *p, *cmd, *e, *c;
170937da2899SCharles.Forsyth
171037da2899SCharles.Forsyth if(t->execdepth >= 0 && ++t->execdepth > 128)
171137da2899SCharles.Forsyth return TkDepth;
171237da2899SCharles.Forsyth
171337da2899SCharles.Forsyth cmd = nil;
171437da2899SCharles.Forsyth cmdsz = 0;
171537da2899SCharles.Forsyth
171637da2899SCharles.Forsyth p = arg;
171737da2899SCharles.Forsyth for(;;) {
171837da2899SCharles.Forsyth switch(*p++) {
171937da2899SCharles.Forsyth case '[':
172037da2899SCharles.Forsyth p = tkmatch('[', ']', p);
172137da2899SCharles.Forsyth if(p == nil){
172237da2899SCharles.Forsyth free(cmd);
172337da2899SCharles.Forsyth return TkSyntx;
172437da2899SCharles.Forsyth }
172537da2899SCharles.Forsyth break;
172637da2899SCharles.Forsyth case '{':
172737da2899SCharles.Forsyth p = tkmatch('{', '}', p);
172837da2899SCharles.Forsyth if(p == nil){
172937da2899SCharles.Forsyth free(cmd);
173037da2899SCharles.Forsyth return TkSyntx;
173137da2899SCharles.Forsyth }
173237da2899SCharles.Forsyth break;
173337da2899SCharles.Forsyth case ';':
173437da2899SCharles.Forsyth n = p - arg - 1;
173537da2899SCharles.Forsyth if(cmdsz < n)
173637da2899SCharles.Forsyth cmdsz = n;
173737da2899SCharles.Forsyth c = realloc(cmd, cmdsz+1);
173837da2899SCharles.Forsyth if(c == nil){
173937da2899SCharles.Forsyth free(cmd);
174037da2899SCharles.Forsyth return TkNomem;
174137da2899SCharles.Forsyth }
174237da2899SCharles.Forsyth cmd = c;
174337da2899SCharles.Forsyth memmove(cmd, arg, n);
174437da2899SCharles.Forsyth cmd[n] = '\0';
174537da2899SCharles.Forsyth e = tksinglecmd(t, cmd, nil);
174637da2899SCharles.Forsyth if(e != nil) {
174737da2899SCharles.Forsyth t->err = e;
174837da2899SCharles.Forsyth strncpy(t->errcmd, cmd, sizeof(t->errcmd));
174937da2899SCharles.Forsyth t->errcmd[sizeof(t->errcmd)-1] = '\0';
175037da2899SCharles.Forsyth free(cmd);
175137da2899SCharles.Forsyth return e;
175237da2899SCharles.Forsyth }
175337da2899SCharles.Forsyth arg = p;
175437da2899SCharles.Forsyth break;
175537da2899SCharles.Forsyth case '\0':
175637da2899SCharles.Forsyth case '\'':
175737da2899SCharles.Forsyth free(cmd);
175837da2899SCharles.Forsyth e = tksinglecmd(t, arg, val);
175937da2899SCharles.Forsyth if(e != nil) {
176037da2899SCharles.Forsyth t->err = e;
176137da2899SCharles.Forsyth strncpy(t->errcmd, arg, sizeof(t->errcmd));
176237da2899SCharles.Forsyth t->errcmd[sizeof(t->errcmd)-1] = '\0';
176337da2899SCharles.Forsyth }
176437da2899SCharles.Forsyth return e;
176537da2899SCharles.Forsyth }
176637da2899SCharles.Forsyth }
176737da2899SCharles.Forsyth }
176837da2899SCharles.Forsyth
176937da2899SCharles.Forsyth static struct {
177037da2899SCharles.Forsyth char *name;
177137da2899SCharles.Forsyth int mask;
177237da2899SCharles.Forsyth } events[] = {
177337da2899SCharles.Forsyth "Button1P", TkButton1P,
177437da2899SCharles.Forsyth "Button1R", TkButton1R,
177537da2899SCharles.Forsyth "Button2P", TkButton2P,
177637da2899SCharles.Forsyth "Button2R", TkButton2R,
177737da2899SCharles.Forsyth "Button3P", TkButton3P,
177837da2899SCharles.Forsyth "Button3R", TkButton3R,
177937da2899SCharles.Forsyth "Button4P", TkButton4P,
178037da2899SCharles.Forsyth "Button4R", TkButton4R,
178137da2899SCharles.Forsyth "Button5P", TkButton5P,
178237da2899SCharles.Forsyth "Button5R", TkButton5R,
178337da2899SCharles.Forsyth "Button6P", TkButton6P,
178437da2899SCharles.Forsyth "Button6R", TkButton6R,
178537da2899SCharles.Forsyth "Extn1", TkExtn1,
178637da2899SCharles.Forsyth "Extn2", TkExtn2,
178737da2899SCharles.Forsyth "Takefocus", TkTakefocus,
178837da2899SCharles.Forsyth "Destroy", TkDestroy,
178937da2899SCharles.Forsyth "Enter", TkEnter,
179037da2899SCharles.Forsyth "Leave", TkLeave,
179137da2899SCharles.Forsyth "Motion", TkMotion,
179237da2899SCharles.Forsyth "Map", TkMap,
179337da2899SCharles.Forsyth "Unmap", TkUnmap,
179437da2899SCharles.Forsyth "Key", TkKey,
179537da2899SCharles.Forsyth "Focusin", TkFocusin,
179637da2899SCharles.Forsyth "Focusout", TkFocusout,
179737da2899SCharles.Forsyth "Configure", TkConfigure,
179837da2899SCharles.Forsyth "Double", TkDouble,
179937da2899SCharles.Forsyth 0
180037da2899SCharles.Forsyth };
180137da2899SCharles.Forsyth
180237da2899SCharles.Forsyth int
tkeventfmt(Fmt * f)180337da2899SCharles.Forsyth tkeventfmt(Fmt *f)
180437da2899SCharles.Forsyth {
180537da2899SCharles.Forsyth int k, i, d;
180637da2899SCharles.Forsyth int e;
180737da2899SCharles.Forsyth
180837da2899SCharles.Forsyth e = va_arg(f->args, int);
180937da2899SCharles.Forsyth
181037da2899SCharles.Forsyth if ((f->flags & FmtSharp) && e == TkMotion)
181137da2899SCharles.Forsyth return 0;
181237da2899SCharles.Forsyth fmtprint(f, "<");
181337da2899SCharles.Forsyth k = -1;
181437da2899SCharles.Forsyth if (e & TkKey) {
181537da2899SCharles.Forsyth k = e & 0xffff;
181637da2899SCharles.Forsyth e &= ~0xffff;
181737da2899SCharles.Forsyth }
181837da2899SCharles.Forsyth d = 0;
181937da2899SCharles.Forsyth for (i = 0; events[i].name; i++) {
182037da2899SCharles.Forsyth if (e & events[i].mask) {
182137da2899SCharles.Forsyth if (d++)
182237da2899SCharles.Forsyth fmtprint(f, "|");
182337da2899SCharles.Forsyth fmtprint(f, "%s", events[i].name);
182437da2899SCharles.Forsyth }
182537da2899SCharles.Forsyth }
182637da2899SCharles.Forsyth if (k != -1) {
182737da2899SCharles.Forsyth fmtprint(f, "[%c]", k);
182837da2899SCharles.Forsyth } else if (e == 0)
182937da2899SCharles.Forsyth fmtprint(f, "Noevent");
183037da2899SCharles.Forsyth fmtprint(f, ">");
183137da2899SCharles.Forsyth return 0;
183237da2899SCharles.Forsyth }
183337da2899SCharles.Forsyth
183437da2899SCharles.Forsyth void
tkerr(TkTop * t,char * e)183537da2899SCharles.Forsyth tkerr(TkTop *t, char *e)
183637da2899SCharles.Forsyth {
183737da2899SCharles.Forsyth if(t != nil && e != nil){
183837da2899SCharles.Forsyth strncpy(t->errx, e, sizeof(t->errx));
183937da2899SCharles.Forsyth t->errx[sizeof(t->errx)-1] = '\0';
184037da2899SCharles.Forsyth }
184137da2899SCharles.Forsyth }
184237da2899SCharles.Forsyth
184337da2899SCharles.Forsyth char*
tkerrstr(TkTop * t,char * e)184437da2899SCharles.Forsyth tkerrstr(TkTop *t, char *e)
184537da2899SCharles.Forsyth {
184637da2899SCharles.Forsyth char *s = malloc(strlen(e)+1+strlen(t->errx)+1);
184737da2899SCharles.Forsyth
184837da2899SCharles.Forsyth if(s == nil)
184937da2899SCharles.Forsyth return nil;
185037da2899SCharles.Forsyth strcpy(s, e);
185137da2899SCharles.Forsyth if(*e == '!'){
185237da2899SCharles.Forsyth strcat(s, " ");
185337da2899SCharles.Forsyth strcat(s, t->errx);
185437da2899SCharles.Forsyth }
185537da2899SCharles.Forsyth t->errx[0] = '\0';
185637da2899SCharles.Forsyth return s;
185737da2899SCharles.Forsyth }
185837da2899SCharles.Forsyth
185937da2899SCharles.Forsyth char*
tksetmgrab(TkTop * t,Tk * tk)186037da2899SCharles.Forsyth tksetmgrab(TkTop *t, Tk *tk)
186137da2899SCharles.Forsyth {
186237da2899SCharles.Forsyth Tk *omgrab;
186337da2899SCharles.Forsyth TkCtxt *c;
186437da2899SCharles.Forsyth c = t->ctxt;
186537da2899SCharles.Forsyth if (tk == nil) {
186637da2899SCharles.Forsyth omgrab = c->mgrab;
186737da2899SCharles.Forsyth c->mgrab = nil;
186837da2899SCharles.Forsyth /*
186937da2899SCharles.Forsyth * don't enterleave if grab reset would cause no leave event
187037da2899SCharles.Forsyth */
187137da2899SCharles.Forsyth if (!(omgrab != nil && (omgrab->flag & Tknograb) &&
187237da2899SCharles.Forsyth c->entered != nil && (c->entered->flag & Tknograb)))
187337da2899SCharles.Forsyth tkenterleave(t);
187437da2899SCharles.Forsyth } else {
187537da2899SCharles.Forsyth if (c->focused && c->mfocus != nil && c->mfocus->env->top != tk->env->top)
187637da2899SCharles.Forsyth return "!grab already taken on another toplevel";
187737da2899SCharles.Forsyth c->mgrab = tk;
187837da2899SCharles.Forsyth if (tk->flag & Tknograb) {
187937da2899SCharles.Forsyth if (c->focused) {
188037da2899SCharles.Forsyth c->focused = 0;
188137da2899SCharles.Forsyth c->mfocus = nil;
188237da2899SCharles.Forsyth }
188337da2899SCharles.Forsyth } else if (c->focused || c->mstate.b != 0) {
188437da2899SCharles.Forsyth c->focused = 1;
188537da2899SCharles.Forsyth c->mfocus = tk;
188637da2899SCharles.Forsyth }
188737da2899SCharles.Forsyth //print("setmgrab(%s) focus now %s\n", tkname(tk), tkname(c->mfocus));
188837da2899SCharles.Forsyth tkenterleave(t);
188937da2899SCharles.Forsyth }
189037da2899SCharles.Forsyth return nil;
189137da2899SCharles.Forsyth }
189237da2899SCharles.Forsyth
189337da2899SCharles.Forsyth int
tkinsidepoly(Point * poly,int np,int winding,Point p)189437da2899SCharles.Forsyth tkinsidepoly(Point *poly, int np, int winding, Point p)
189537da2899SCharles.Forsyth {
189637da2899SCharles.Forsyth Point pi, pj;
189737da2899SCharles.Forsyth int i, j, hit;
189837da2899SCharles.Forsyth
189937da2899SCharles.Forsyth hit = 0;
190037da2899SCharles.Forsyth j = np - 1;
190137da2899SCharles.Forsyth for(i = 0; i < np; j = i++) {
190237da2899SCharles.Forsyth pi = poly[i];
190337da2899SCharles.Forsyth pj = poly[j];
190437da2899SCharles.Forsyth if((pi.y <= p.y && p.y < pj.y || pj.y <= p.y && p.y < pi.y) &&
190537da2899SCharles.Forsyth p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x) {
190637da2899SCharles.Forsyth if(winding == 1 || pi.y > p.y)
190737da2899SCharles.Forsyth hit++;
190837da2899SCharles.Forsyth else
190937da2899SCharles.Forsyth hit--;
191037da2899SCharles.Forsyth }
191137da2899SCharles.Forsyth }
191237da2899SCharles.Forsyth return (hit & winding) != 0;
191337da2899SCharles.Forsyth }
191437da2899SCharles.Forsyth
191537da2899SCharles.Forsyth int
tklinehit(Point * a,int np,int w,Point p)191637da2899SCharles.Forsyth tklinehit(Point *a, int np, int w, Point p)
191737da2899SCharles.Forsyth {
191837da2899SCharles.Forsyth Point *b;
191937da2899SCharles.Forsyth int z, nx, ny, nrm;
19200b978350Sforsyth
192137da2899SCharles.Forsyth while(np-- > 1) {
192237da2899SCharles.Forsyth b = a+1;
192337da2899SCharles.Forsyth nx = a->y - b->y;
192437da2899SCharles.Forsyth ny = b->x - a->x;
192537da2899SCharles.Forsyth nrm = (nx < 0? -nx : nx) + (ny < 0? -ny : ny);
192637da2899SCharles.Forsyth if(nrm)
192737da2899SCharles.Forsyth z = (p.x-b->x)*nx/nrm + (p.y-b->y)*ny/nrm;
192837da2899SCharles.Forsyth else
192937da2899SCharles.Forsyth z = (p.x-b->x) + (p.y-b->y);
193037da2899SCharles.Forsyth if(z < 0)
193137da2899SCharles.Forsyth z = -z;
193237da2899SCharles.Forsyth if(z < w)
193337da2899SCharles.Forsyth return 1;
193437da2899SCharles.Forsyth a++;
193537da2899SCharles.Forsyth }
193637da2899SCharles.Forsyth return 0;
193737da2899SCharles.Forsyth }
193837da2899SCharles.Forsyth
193937da2899SCharles.Forsyth int
tkiswordchar(int c)194037da2899SCharles.Forsyth tkiswordchar(int c)
194137da2899SCharles.Forsyth {
194237da2899SCharles.Forsyth return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c >= 0xA0;
194337da2899SCharles.Forsyth }
194437da2899SCharles.Forsyth
194537da2899SCharles.Forsyth int
tkhaskeyfocus(Tk * tk)194637da2899SCharles.Forsyth tkhaskeyfocus(Tk *tk)
194737da2899SCharles.Forsyth {
194837da2899SCharles.Forsyth if (tk == nil || tk->env->top->focused == 0)
194937da2899SCharles.Forsyth return 0;
195037da2899SCharles.Forsyth return tk == tk->env->top->ctxt->tkkeygrab;
195137da2899SCharles.Forsyth }
195237da2899SCharles.Forsyth
195337da2899SCharles.Forsyth static int
rptactive(void * v)195437da2899SCharles.Forsyth rptactive(void *v)
195537da2899SCharles.Forsyth {
195637da2899SCharles.Forsyth int id = (int)v;
195737da2899SCharles.Forsyth if (id == rptid)
195837da2899SCharles.Forsyth return 1;
195937da2899SCharles.Forsyth return 0;
196037da2899SCharles.Forsyth }
196137da2899SCharles.Forsyth
196237da2899SCharles.Forsyth static int
ckrpt(void * v,int interval)196337da2899SCharles.Forsyth ckrpt(void *v, int interval)
196437da2899SCharles.Forsyth {
196537da2899SCharles.Forsyth int id = (int)v;
196637da2899SCharles.Forsyth if (id != rptid)
196737da2899SCharles.Forsyth return -1;
196837da2899SCharles.Forsyth if (interval < rptto)
196937da2899SCharles.Forsyth return 0;
197037da2899SCharles.Forsyth return 1;
197137da2899SCharles.Forsyth }
197237da2899SCharles.Forsyth
197337da2899SCharles.Forsyth static void
dorpt(void * v)197437da2899SCharles.Forsyth dorpt(void *v)
197537da2899SCharles.Forsyth {
197637da2899SCharles.Forsyth int id = (int)v;
197737da2899SCharles.Forsyth
197837da2899SCharles.Forsyth if (id == rptid) {
197937da2899SCharles.Forsyth rptto = rptint;
198037da2899SCharles.Forsyth (*rptcb)(rptw, rptnote, 0);
198137da2899SCharles.Forsyth if (rptint <= 0) {
198237da2899SCharles.Forsyth rptid++;
198337da2899SCharles.Forsyth rptw = nil;
198437da2899SCharles.Forsyth }
198537da2899SCharles.Forsyth }
198637da2899SCharles.Forsyth }
198737da2899SCharles.Forsyth
198837da2899SCharles.Forsyth void
tkcancelrepeat(Tk * tk)198937da2899SCharles.Forsyth tkcancelrepeat(Tk *tk)
199037da2899SCharles.Forsyth {
199137da2899SCharles.Forsyth if (tk == rptw) {
199237da2899SCharles.Forsyth rptid++;
199337da2899SCharles.Forsyth rptw = nil;
199437da2899SCharles.Forsyth }
199537da2899SCharles.Forsyth }
199637da2899SCharles.Forsyth
199737da2899SCharles.Forsyth void
tkrepeat(Tk * tk,void (* callback)(Tk *,void *,int),void * note,int pause,int interval)199837da2899SCharles.Forsyth tkrepeat(Tk *tk, void (*callback)(Tk*, void*, int), void *note, int pause, int interval)
199937da2899SCharles.Forsyth {
200037da2899SCharles.Forsyth rptid++;
200137da2899SCharles.Forsyth if (tk != rptw && rptw != nil)
200237da2899SCharles.Forsyth /* existing callback being replaced- report to owner */
200337da2899SCharles.Forsyth (*rptcb)(rptw, rptnote, 1);
200437da2899SCharles.Forsyth rptw = tk;
200537da2899SCharles.Forsyth if (tk == nil || callback == nil)
200637da2899SCharles.Forsyth return;
200737da2899SCharles.Forsyth rptnote = note;
200837da2899SCharles.Forsyth rptcb = callback;
200937da2899SCharles.Forsyth rptto = pause;
201037da2899SCharles.Forsyth rptint = interval;
201137da2899SCharles.Forsyth if (!autorpt)
201237da2899SCharles.Forsyth autorpt = rptproc("autorepeat", TkRptclick, (void*)rptid, rptactive, ckrpt, dorpt);
201337da2899SCharles.Forsyth else
201437da2899SCharles.Forsyth rptwakeup((void*)rptid, autorpt);
201537da2899SCharles.Forsyth }
201637da2899SCharles.Forsyth
201737da2899SCharles.Forsyth static int
blinkactive(void * v)201837da2899SCharles.Forsyth blinkactive(void *v)
201937da2899SCharles.Forsyth {
202037da2899SCharles.Forsyth USED(v);
202137da2899SCharles.Forsyth return blinkw != nil;
202237da2899SCharles.Forsyth }
202337da2899SCharles.Forsyth
202437da2899SCharles.Forsyth static int
ckblink(void * v,int interval)202537da2899SCharles.Forsyth ckblink(void *v, int interval)
202637da2899SCharles.Forsyth {
202737da2899SCharles.Forsyth USED(v);
202837da2899SCharles.Forsyth USED(interval);
202937da2899SCharles.Forsyth
203037da2899SCharles.Forsyth if (blinkw == nil)
203137da2899SCharles.Forsyth return -1;
203237da2899SCharles.Forsyth if (blinkignore) {
203337da2899SCharles.Forsyth blinkignore = 0;
203437da2899SCharles.Forsyth return 0;
203537da2899SCharles.Forsyth }
203637da2899SCharles.Forsyth return 1;
203737da2899SCharles.Forsyth }
203837da2899SCharles.Forsyth
203937da2899SCharles.Forsyth static void
doblink(void * v)204037da2899SCharles.Forsyth doblink(void *v)
204137da2899SCharles.Forsyth {
204237da2899SCharles.Forsyth USED(v);
204337da2899SCharles.Forsyth
204437da2899SCharles.Forsyth if (blinkw == nil)
204537da2899SCharles.Forsyth return;
204637da2899SCharles.Forsyth blinkcb(blinkw, blinkon++ & 1);
204737da2899SCharles.Forsyth tkupdate(blinkw->env->top);
204837da2899SCharles.Forsyth }
204937da2899SCharles.Forsyth
205037da2899SCharles.Forsyth void
tkblinkreset(Tk * tk)205137da2899SCharles.Forsyth tkblinkreset(Tk *tk)
205237da2899SCharles.Forsyth {
205337da2899SCharles.Forsyth if (blinkw == tk) {
205437da2899SCharles.Forsyth blinkignore = 1;
205537da2899SCharles.Forsyth blinkon = 0;
205637da2899SCharles.Forsyth }
205737da2899SCharles.Forsyth }
205837da2899SCharles.Forsyth
205937da2899SCharles.Forsyth void
tkblink(Tk * tk,void (* callback)(Tk *,int))206037da2899SCharles.Forsyth tkblink(Tk *tk, void (*callback)(Tk*, int))
206137da2899SCharles.Forsyth {
206237da2899SCharles.Forsyth if (tk == nil || callback == nil) {
206337da2899SCharles.Forsyth blinkw = nil;
206437da2899SCharles.Forsyth return;
206537da2899SCharles.Forsyth }
206637da2899SCharles.Forsyth blinkw = tk;
206737da2899SCharles.Forsyth blinkcb = callback;
206837da2899SCharles.Forsyth if (!blinkrpt)
206937da2899SCharles.Forsyth blinkrpt = rptproc("blinker", TkBlinkinterval, nil, blinkactive, ckblink, doblink);
207037da2899SCharles.Forsyth else
207137da2899SCharles.Forsyth rptwakeup(nil, blinkrpt);
207237da2899SCharles.Forsyth }
2073*5849851aSforsyth
2074*5849851aSforsyth /*
2075*5849851aSforsyth * debugging
2076*5849851aSforsyth */
2077*5849851aSforsyth void
tkdump(Tk * tk)2078*5849851aSforsyth tkdump(Tk *tk)
2079*5849851aSforsyth {
2080*5849851aSforsyth Tk *sl;
2081*5849851aSforsyth
2082*5849851aSforsyth if(tk == nil)
2083*5849851aSforsyth return;
2084*5849851aSforsyth if((uint)tk->type < TKwidgets)
2085*5849851aSforsyth print("%s", tkmethod[tk->type]->name);
2086*5849851aSforsyth else
2087*5849851aSforsyth print("TYPE#%#ux", tk->type);
2088*5849851aSforsyth if(tk->name == nil || (ulong)tk->name < 512)
2089*5849851aSforsyth print(" NAME %p", tk->name);
2090*5849851aSforsyth else
2091*5849851aSforsyth print(" %s", tkname(tk));
2092*5849851aSforsyth print(" # tk %#p flag %#ux grid %#p", tk, tk->flag, tk->grid);
2093*5849851aSforsyth if(tk->parent != nil)
2094*5849851aSforsyth print(" parent [%#p %q]", tk->parent, tkname(tk->parent));
2095*5849851aSforsyth if(tk->master != nil)
2096*5849851aSforsyth print(" master [%#p %q]", tk->master, tkname(tk->master));
2097*5849851aSforsyth if(tk->slave != nil){
2098*5849851aSforsyth print(" slaves");
2099*5849851aSforsyth for(sl = tk->slave; sl != nil; sl = sl->next)
2100*5849851aSforsyth print(" [%#p %q]", sl, tkname(sl));
2101*5849851aSforsyth }
2102*5849851aSforsyth print("\n");
2103*5849851aSforsyth if(tk->type != TKcanvas)
2104*5849851aSforsyth return;
2105*5849851aSforsyth tkcvsdump(tk);
2106*5849851aSforsyth }
2107*5849851aSforsyth
2108*5849851aSforsyth void
tktopdump(Tk * tk)2109*5849851aSforsyth tktopdump(Tk *tk)
2110*5849851aSforsyth {
2111*5849851aSforsyth TkTop *top;
2112*5849851aSforsyth Tk *sub;
2113*5849851aSforsyth
2114*5849851aSforsyth if(tk == nil || tk->env == nil){
2115*5849851aSforsyth print("# %#p no top\n", tk);
2116*5849851aSforsyth return;
2117*5849851aSforsyth }
2118*5849851aSforsyth top = tk->env->top;
2119*5849851aSforsyth print("# env %#p top %#p\n", tk->env, top);
2120*5849851aSforsyth if(top != nil){
2121*5849851aSforsyth for(sub = top->root; sub != nil; sub = sub->siblings)
2122*5849851aSforsyth tkdump(sub);
2123*5849851aSforsyth }
2124*5849851aSforsyth }
2125