Charles.Forsyth20061220965a0ca19 years agoHistory
717 lines · 12.5 KB · C
RawDownload
#include "lib9.h"#include "draw.h"#include "tk.h"#include "canvs.h"#include "textw.h"#include "kernel.h" TkCtxt*tknewctxt(Display *d){	TkCtxt *c;	c = malloc(sizeof(TkCtxt));	if(c == nil)		return nil;	c->lock = libqlalloc();	if(c->lock == nil){		free(c);		return nil;	}	if (tkextnnewctxt(c) != 0) {		free(c->lock);		free(c);		return nil;	}	c->display = d;	return c;} voidtkfreectxt(TkCtxt *c){	int locked;	Display *d; 	if(c == nil)		return; 	tkextnfreectxt(c); 	d = c->display;	locked = lockdisplay(d);	tkfreecolcache(c);	freeimage(c->i);	freeimage(c->ia);	if(locked)		unlockdisplay(d);	libqlfree(c->lock);	free(c);} Image*tkitmp(TkEnv *e, Point p, int fillcol){	Image *i, **ip;	TkTop *t;	TkCtxt *ti;	Display *d;	Rectangle r;	ulong pix;	int alpha;		t = e->top;	ti = t->ctxt;	d = t->display; 	pix = e->colors[fillcol];	alpha = (pix & 0xff) != 0xff;	ip = alpha ? &ti->ia : &ti->i; 	if(*ip != nil) {		i = *ip;		if(p.x <= i->r.max.x && p.y <= i->r.max.y) {			r.min = ZP;			r.max = p;			if (alpha)				drawop(i, r, nil, nil, ZP, Clear);			draw(i, r, tkgc(e, fillcol), nil, ZP);			return i;		}		r = i->r;		freeimage(i);		if(p.x < r.max.x)			p.x = r.max.x;		if(p.y < r.max.y)			p.y = r.max.y;	} 	r.min = ZP;	r.max = p;	*ip = allocimage(d, r, alpha?RGBA32:d->image->chan, 0, pix); 	return *ip;} voidtkgeomchg(Tk *tk, TkGeom *g, int bd){	int w, h;	void (*geomfn)(Tk*);	if(memcmp(&tk->req, g, sizeof(TkGeom)) == 0 && bd == tk->borderwidth)		return; 	geomfn = tkmethod[tk->type]->geom;	if(geomfn != nil)		geomfn(tk); 	if(tk->master != nil) {		tkpackqit(tk->master);		tkrunpack(tk->env->top);	}	else	if(tk->geom != nil) {		w = tk->req.width;		h = tk->req.height;		tk->req.width = 0;		tk->req.height = 0;		tk->geom(tk, tk->act.x, tk->act.y, w, h);		if (tk->slave) {			tkpackqit(tk);			tkrunpack(tk->env->top);		}	}	tkdeliver(tk, TkConfigure, g);} /* * return the widget within tk with by point p (in widget coords) */Tk*tkinwindow(Tk *tk, Point p, int descend){	Tk *f;	Point q;	if (ptinrect(p, tkrect(tk, 1)) == 0)		return nil;	for (;;) {		if (descend && tkmethod[tk->type]->inwindow != nil)			f = tkmethod[tk->type]->inwindow(tk, &p);		else {			q = p;			for (f = tk->slave; f; f = f->next) {				q.x = p.x - (f->act.x + f->borderwidth);				q.y = p.y - (f->act.y + f->borderwidth);				if (ptinrect(q, tkrect(f, 1)))					break;			}			p = q;		}		if (f == nil || f == tk)			return tk;		tk = f;	}	return nil;	/* for compiler */} Tk*tkfindfocus(TkTop *t, int x, int y, int descend){	Point p, q;	Tk *tk, *f;	TkWin *tkw;	p.x = x;	p.y = y;	for(f = t->windows; f != nil; f = TKobj(TkWin, f)->next) {		assert(f->flag&Tkwindow);		if(f->flag & Tkmapped) {			tkw = TKobj(TkWin, f);			q.x = p.x - (tkw->act.x+f->borderwidth);			q.y = p.y - (tkw->act.y+f->borderwidth);			tk = tkinwindow(f, q, descend);			if(tk != nil)				return tk;		}	}	return nil;} voidtkmovewin(Tk *tk, Point p){	TkWin *tkw;	if((tk->flag & Tkwindow) == 0)		return;	tkw = TKobj(TkWin, tk);	if(! eqpt(p, tkw->req)){		tkw->req = p;		tkw->changed = 1;	}} voidtkmoveresize(Tk *tk, int x, int y, int w, int h){	TkWin *tkw;	USED(x);	USED(y);	assert(tk->flag&Tkwindow);	tkw = TKobj(TkWin, tk);	if(w < 0)		w = 0;	if(h < 0)		h = 0;//print("moveresize %s %d %d +[%d %d], callerpc %lux\n", tk->name->name, x, y, w, h, getcallerpc(&tk));	tk->req.width = w;	tk->req.height = h;	tk->act = tk->req;	/* XXX perhaps should actually suspend the window here? */	tkw->changed = 1;} static voidtkexterncreatewin(Tk *tk, Rectangle r){	TkWin *tkw;	TkTop *top;	char *name; 	top = tk->env->top;	tkw = TKobj(TkWin, tk); 	/*	 * for a choicebutton menu, use the name of the choicebutton which created it	 */	if(tk->name == nil){		name = tkw->cbname;		assert(name != nil);	} else		name = tk->name->name; 	tkw->reqid++;	tkwreq(top, "!reshape %s %d %d %d %d %d", name, tkw->reqid, r.min.x, r.min.y, r.max.x, r.max.y);	tkw->changed = 0;	tk->flag |= Tksuspended;} /* * return non-zero if the window size has changed (XXX choose better return value/function name!) */inttkupdatewinsize(Tk *tk){	TkWin *tkw;	Image *previ;	Rectangle r, or;	int bw2; 	tkw = TKobj(TkWin, tk);	bw2 = 2*tk->borderwidth;	r.min.x = tkw->req.x;	r.min.y = tkw->req.y;	r.max.x = r.min.x + tk->act.width + bw2;	r.max.y = r.min.y + tk->act.height + bw2;	previ = tkw->image;	if(previ != nil){		or.min.x = tkw->act.x;		or.min.y = tkw->act.y;		or.max.x = tkw->act.x + Dx(previ->r);		or.max.y = tkw->act.y + Dy(previ->r);		if(eqrect(or, r))			return 0;	}	tkexterncreatewin(tk, r);	return 1;} static char*tkdrawslaves1(Tk *tk, Point orig, Image *dst, int *dirty){	Tk *f;	char *e = nil;	Point worig;	Rectangle r, oclip; 	worig.x = orig.x + tk->act.x + tk->borderwidth;	worig.y = orig.y + tk->act.y + tk->borderwidth; 	r = rectaddpt(tk->dirty, worig);	if (Dx(r) > 0 && rectXrect(r, dst->clipr)) {		e = tkmethod[tk->type]->draw(tk, orig);		tk->dirty = bbnil;		*dirty = 1;	}	if(e != nil)		return e; 	/*	 * grids need clipping	 * XXX BUG: they can't, 'cos text widgets don't clip appropriately.	 */	if (tk->grid != nil) {		r = rectaddpt(tkrect(tk, 0), worig);		if (rectclip(&r, dst->clipr) == 0)			return nil;		oclip = dst->clipr;		replclipr(dst, 0, r);	}	for(f = tk->slave; e == nil && f; f = f->next)		e = tkdrawslaves1(f, worig, dst, dirty);	if (tk->grid != nil)		replclipr(dst, 0, oclip);	return e;}	char*tkdrawslaves(Tk *tk, Point orig, int *dirty){	Image *i;	char *e;	i = tkimageof(tk);	if (i == nil)		return nil;	e =  tkdrawslaves1(tk, orig, i, dirty);	return e;} char*tkupdate(TkTop *t){	Tk* tk;	int locked;	TkWin *tkw;	Display *d;	char *e;	int dirty = 0;	if(t->noupdate)		return nil; 	d = t->display;	locked = lockdisplay(d);	tk = t->windows;	while(tk) {		tkw = TKobj(TkWin, tk);		if((tk->flag & (Tkmapped|Tksuspended)) == Tkmapped) {			if (tkupdatewinsize(tk) == 0){				e = tkdrawslaves(tk, ZP, &dirty);				if(e != nil)					return e;			}		}		tk = tkw->next;	}	if (dirty || t->dirty) {		flushimage(d, 1);		t->dirty = 0;	}	if(locked)		unlockdisplay(d);	return nil;} inttkischild(Tk *tk, Tk *child){	while(child != nil && child != tk){		if(child->master)			child = child->master;		else			child = child->parent;	}	return child == tk;} voidtksetbits(Tk *tk, int mask){	tk->flag |= mask;	for(tk = tk->slave; tk; tk = tk->next)		tksetbits(tk, mask);} char*tkmap(Tk *tk){/*	is this necessary?	tkw = TKobj(TkWin, tk);	if(tkw->image != nil)		tkwreq(tk->env->top, "raise %s", tk->name->name);*/ 	if(tk->flag & Tkmapped)		return nil; 	tk->flag |= Tkmapped;	tkmoveresize(tk, 0, 0, tk->act.width, tk->act.height);	tkdeliver(tk, TkMap, nil);	return nil;//tkupdate(tk->env->top);} voidtkclrfocus(Tk *master){	TkCtxt *c;	Tk *tk;	TkTop *top; 	if(master == nil)		return;	top = master->env->top;	c = top->ctxt; 	tk = c->mgrab;	if(tkischild(master, tk))		tksetmgrab(top, nil); 	tk = c->entered;	if(tkischild(master, tk)){		c->entered = nil;		tkdeliver(tk, TkLeave, nil);	}} voidtkunmap(Tk *tk){	TkTop *t;	TkCtxt *c; 	while(tk->master)		tk = tk->master; 	if((tk->flag & Tkmapped) == 0)		return; 	t = tk->env->top;	c = t->ctxt; 	if(tkischild(tk, c->mgrab))		tksetmgrab(t, nil);	if(tkischild(tk, c->entered)){		tkdeliver(c->entered, TkLeave, nil);		c->entered = nil;	}	if(tk == t->root)		tksetglobalfocus(t, 0); 	tk->flag &= ~(Tkmapped|Tksuspended); 	tkdestroywinimage(tk);	tkdeliver(tk, TkUnmap, nil);	tkenterleave(t);	/* XXX should unmap menus too */} Image*tkimageof(Tk *tk){	while(tk) {		if(tk->flag & Tkwindow)			return TKobj(TkWin, tk)->image;		if(tk->parent != nil) {			tk = tk->parent;			switch(tk->type) {			case TKmenu:				return TKobj(TkWin, tk)->image;			case TKcanvas:				return TKobj(TkCanvas, tk)->image;			case TKtext:				return TKobj(TkText, tk)->image;			}			abort();		}		tk = tk->master;	}	return nil;} voidtktopopt(Tk *tk, char *opt){	TkTop *t;	TkWin *tkw;	TkOptab tko[4]; 	tkw = TKobj(TkWin, tk); 	t = tk->env->top; 	tko[0].ptr = tkw;	tko[0].optab = tktop;	tko[1].ptr = tk;	tko[1].optab = tkgeneric;	tko[2].ptr = t;	tko[2].optab = tktopdbg;	tko[3].ptr = nil; 	tkparse(t, opt, tko, nil);} /* general compare - compare top-left corners, y takes priority */static inttkfcmpgen(void *ap, void *bp){	TkWinfo *a = ap, *b = bp; 	if (a->r.min.y > b->r.min.y)		return 1;	if (a->r.min.y < b->r.min.y)		return -1;

Lines 1–500 of 717.