Charles.Forsyth20061220965a0ca19 years agoHistory
1952 lines · 32.6 KB · C
RawDownload
#include "lib9.h"#include "draw.h"#include "tk.h" extern void	rptwakeup(void*, void*);extern void*	rptproc(char*, int, void*, int (*)(void*), int (*)(void*,int), void (*)(void*)); typedef struct Cmd Cmd;struct Cmd{	char*	name;	char*	(*fn)(TkTop*, char*, char**);};static struct Cmd cmdmain[] ={	"bind",		tkbind,	"button",	tkbutton,	"canvas",	tkcanvas,	"checkbutton",	tkcheckbutton,	"choicebutton", tkchoicebutton,	"cursor",	tkcursorcmd,	"destroy",	tkdestroy,	"entry",	tkentry,	"focus",	tkfocus,	"frame",	tkframe,	"grab",		tkgrab,	"grid",	tkgrid,	"image",	tkimage,	"label",	tklabel,	"listbox",	tklistbox,	"lower",	tklower,	"menu",		tkmenu,	"menubutton",	tkmenubutton,	"pack",		tkpack,	"panel",		tkpanel,	"puts",		tkputs,	"radiobutton",	tkradiobutton,	"raise",	tkraise,	"scale",	tkscale,	"scrollbar",	tkscrollbar,	"see",	tkseecmd,	"send",		tksend,	"text",		tktext,	"update",	tkupdatecmd,	"variable",	tkvariable,	"winfo",	tkwinfo,}; char*	tkfont; /* auto-repeating support * should perhaps be one rptproc per TkCtxt * This is not done for the moment as there isn't * a mechanism for terminating the rptproc */static void *autorpt;static int rptid;static Tk *rptw;static void *rptnote;static void (*rptcb)(Tk*, void*, int);static long rptto;static int rptint; /* blinking carets - should be per TkCtxt */static void *blinkrpt;static Tk *blinkw;static void (*blinkcb)(Tk*, int);static int blinkignore;static int blinkon;  ulongtkrgba(int r, int g, int b, int a){	ulong p; 	if(r < 0)		r = 0;	else if(r > 255)		r = 255;	if(g < 0)		g = 0;	else if(g > 255)		g = 255;	if(b < 0)		b = 0;	else if(b > 255)		b = 255;	p = (r<<24)|(g<<16)|(b<<8)|0xFF;	if(a == 255)		return p;	return setalpha(p, a);} /* to be replaced */static intrevalpha(int c, int a){	if (a == 0)		return 0;	return (c & 0xff) * 255 / a;} voidtkrgbavals(ulong rgba, int *R, int *G, int *B, int *A){	int a; 	a = rgba & 0xff;	*A = a;	if (a != 0xff) {		*R = revalpha(rgba>>24, a);		*G = revalpha((rgba>>16) & 0xFF, a);		*B = revalpha((rgba >> 8) & 0xFF, a);	} else {		*R = (rgba>>24);		*G = ((rgba>>16) & 0xFF);		*B = ((rgba >> 8) & 0xFF);	}} voidtkfreecolcache(TkCtxt *c){	TkCol *cc; 	if(c == nil)		return;	while((cc = c->chead) != nil){		c->chead = cc->forw;		freeimage(cc->i);		free(cc);	}	c->ctail = nil;	c->ncol = 0;} Image*tkcolor(TkCtxt *c, ulong pix){	Image *i;	TkCol *cc, **l;	Display *d;	Rectangle r; 	for(l = &c->chead; (cc = *l) != nil; l = &cc->forw)		if(cc->rgba == pix){			/* move it up in the list */			*l = cc->forw;			cc->forw = c->chead;			c->chead = cc;			/* we assume it will be used right away and not stored */			return cc->i;		}	d = c->display;	if(pix == DWhite)		return d->white;	if(pix == DBlack)		return d->black;	r.min = ZP;	r.max.x = 1;	r.max.y = 1;	if ((pix & 0xff) == 0xff)		i = allocimage(d, r, RGB24, 1, pix);	else		i = allocimage(d, r, RGBA32, 1, pix);	if(i == nil)		return d->black;	cc = malloc(sizeof(*cc));	if(cc == nil){		freeimage(i);		return d->black;	}	cc->rgba = pix;	cc->i = i;	cc->forw = c->chead;	c->chead = cc;	c->ncol++;	/* we'll do LRU management at some point */	if(c->ncol > TkColcachesize){		static int warn;		if(warn == 0){			warn = 1;			print("tk: %d colours cached\n", TkColcachesize);		}	}	return i;} /* * XXX should be in libdraw? */inttkchanhastype(ulong c, int t){	for(; c; c>>=8)		if(TYPE(c) == t)			return 1;	return 0;} voidtksettransparent(Tk *tk, int transparent){	if (transparent)		tk->flag |= Tktransparent;	else		tk->flag &= ~Tktransparent;} inttkhasalpha(TkEnv *e, int col){	return (e->colors[col] & 0xff) != 0xff;} Image*tkgc(TkEnv *e, int col){	return tkcolor(e->top->ctxt, e->colors[col]);}  /* * Todo: improve the fixed-point code * the 255 scale factor is used because RGB ranges 0-255 */static voidrgb2hsv(int r, int g, int b, int *h, int *s, int *v){	int min, max, delta; 	max = r;	if(g > max)		max = g;	if(b > max)		max = b;	min = r;	if(g < min)		min = g;	if(b < min)		min = b;	*v = max;	if (max != 0)		*s = ((max - min)*255) / max;	else		*s = 0; 	if (*s == 0) {		*h = 0;	/* undefined */	} else {		delta = max - min;		if (r == max) 			*h = (g - b)*255 / delta;		else if (g == max)			*h = (2*255) + ((b - r)*255) / delta;		else if (b == max)			*h = (4*255) + ((r - g)*255)/ delta;		*h *= 60;		if (*h < 0)			*h += 360*255;		*h /= 255;	}} static voidhsv2rgb(int h, int s, int v, int *r, int *g, int *b){	int	i;	int	f,p,q,t; 	if (s == 0 && h == 0) {		*r = *g = *b = v;	/* achromatic case */	} else {		if (h >= 360)			h = 0;		i = h / 60;		h *= 255;		h /= 60; 		f = h % 255;		p = v * (255 - s);		q = v * (255 - ((s * f)/255));		t = v * (255- ((s * (255 - f))/255));		p /= 255;		q /= 255;		t /= 255;		switch (i) {		case 0: *r = v; *g = t; *b = p; break;		case 1: *r = q; *g = v; *b = p; break;		case 2: *r = p; *g = v; *b = t; break;		case 3: *r = p; *g = q; *b = v; break;		case 4: *r = t; *g = p; *b = v; break;		case 5: *r = v; *g = p; *b = q; break;		}	}} enum {	MINDELTA	= 0x10,	DELTA	= 0x30,}; ulongtkrgbashade(ulong rgba, int shade){	int R, G, B, A, h, s, v, vl, vd; 	if (shade == TkSameshade)		return rgba; 	tkrgbavals(rgba, &R, &G, &B, &A);	h = s = v = 0;	rgb2hsv(R, G, B, &h, &s, &v); 	if (v < MINDELTA) {		vd = v+DELTA;		vl = vd+DELTA;	} else if (v > 255-MINDELTA) {		vl = v-DELTA;		vd = vl-DELTA;	} else {		vl = v+DELTA;		vd = v-DELTA;	} 	v = (shade == TkLightshade)?vl:vd;	if (v < 0)		v = 0;	if (v > 255)		v = 255;	hsv2rgb(h, s, v, &R, &G, &B); 	return tkrgba(R, G, B, A);} Image*tkgshade(TkEnv *e, int col, int shade){	ulong rgba; 	if (col == TkCbackgnd || col == TkCselectbgnd || col == TkCactivebgnd)		return tkgc(e, col+shade);	rgba = tkrgbashade(e->colors[col], shade);	return tkcolor(e->top->ctxt, rgba);} TkEnv*tknewenv(TkTop *t){	TkEnv *e; 	e = malloc(sizeof(TkEnv));	if(e == nil)		return nil; 	e->ref = 1;	e->top = t;	return e;} TkEnv*tkdefaultenv(TkTop *t){	int locked;	TkEnv *env;	Display *d; 	if(t->env != nil) {		t->env->ref++;		return t->env;	}	t->env = malloc(sizeof(TkEnv));	if(t->env == nil)		return nil; 	env = t->env;	env->ref = 1;	env->top = t; 	if(tkfont == nil)		tkfont = "/fonts/pelm/unicode.8.font"; 	d = t->display;	env->font = font_open(d, tkfont);	if(env->font == nil) {		static int warn;		if(warn == 0) {			warn = 1;			print("tk: font not found: %s\n", tkfont);		}		env->font = font_open(d, "*default*");		if(env->font == nil) {			free(t->env);			t->env = nil;			return nil;		}	} 	locked = lockdisplay(d);	env->wzero = stringwidth(env->font, "0");	if ( env->wzero <= 0 )		env->wzero = env->font->height / 2;	if(locked)		unlockdisplay(d); 	tksetenvcolours(env);	return env;} voidtkputenv(TkEnv *env){	Display *d;	int locked; 	if(env == nil)		return; 	env->ref--;	if(env->ref != 0)		return; 	d = env->top->display;	locked = lockdisplay(d); 	if(env->font != nil)		font_close(env->font); 	if(locked)		unlockdisplay(d); 	free(env);} TkEnv*tkdupenv(TkEnv **env){	Display *d;	TkEnv *e, *ne; 	e = *env;	if(e->ref == 1)		return e; 	ne = malloc(sizeof(TkEnv));	if(ne == nil)		return nil; 	ne->ref = 1;	ne->top = e->top; 	d = e->top->display;	memmove(ne->colors, e->colors, sizeof(e->colors));	ne->set = e->set;	ne->font = font_open(d, e->font->name);	ne->wzero = e->wzero; 	e->ref--;	*env = ne;	return ne;} Tk*tknewobj(TkTop *t, int type, int n){	Tk *tk; 	tk = malloc(n);	if(tk == 0)		return 0; 	tk->type = type;		/* Defaults */	tk->flag = Tktop;	tk->relief = TKflat;	tk->env = tkdefaultenv(t);	if(tk->env == nil) {		free(tk);		return nil;	} 	return tk;} voidtkfreebind(TkAction *a){	TkAction *next; 	while(a != nil) {		next = a->link;		if((a->type & 0xff) == TkDynamic)			free(a->arg);		free(a);		a = next;	}} voidtkfreename(TkName *f)

Lines 1–500 of 1952.