Charles.Forsyth20060303a828770d19 years agoHistory
506 lines · 8.6 KB · C
RawDownload
#include <lib9.h>#include <kernel.h>#include "draw.h"#include "tk.h"#include "canvs.h" char*tkparsepts(TkTop *t, TkCpoints *i, char **arg, int close){	char *s, *e;	Point *p, *d;	int n, npoint; 	i->parampt = nil;	i->drawpt = nil;	i->bb = bbnil;	s = *arg;	npoint = 0;	while(*s) {		s = tkskip(s, " \t");		if(*s == '-' && (s[1] < '0' || s[1] > '9'))			break;		while(*s && *s != ' ' && *s != '\t')			s++;		npoint++;	} 	i->parampt = mallocz(npoint*sizeof(Point), 0);	if(i->parampt == nil)		return TkNomem; 	s = *arg;	p = i->parampt;	npoint = 0;	while(*s) {		e = tkfracword(t, &s, &p->x, nil);		if(e != nil)			goto Error;		e = tkfracword(t, &s, &p->y, nil);		if(e != nil)			goto Error;		npoint++;		s = tkskip(s, " \t");		if(*s == '-' && (s[1] < '0' || s[1] > '9'))			break;		p++;	}	*arg = s;	close = (close != 0);	i->drawpt = mallocz((npoint+close)*sizeof(Point), 0);	if(i->drawpt == nil){		e = TkNomem;		goto Error;	} 	d = i->drawpt;	p = i->parampt;	for(n = 0; n < npoint; n++) {		d->x = TKF2I(p->x);		d->y = TKF2I(p->y);		if(d->x < i->bb.min.x)			i->bb.min.x = d->x;		if(d->x > i->bb.max.x)			i->bb.max.x = d->x;		if(d->y < i->bb.min.y)			i->bb.min.y = d->y;		if(d->y > i->bb.max.y)			i->bb.max.y = d->y;		d++;		p++;	}	if (close)		*d = i->drawpt[0];			 	i->npoint = npoint;	return nil; Error:	tkfreepoint(i);	i->parampt = nil;	i->drawpt = nil;	return e;} TkCitem*tkcnewitem(Tk *tk, int t, int n){	TkCitem *i; 	i = malloc(n);	if(i == nil)		return nil;	memset(i, 0, n); 	i->type = t;	i->env = tk->env;	i->env->ref++; 	return i;} /* * expand the canvas's dirty rectangle, clipping * appropriately to its boundaries. */voidtkcvssetdirty(Tk *tk){	TkCanvas *c;	Rectangle r;	c = TKobj(TkCanvas, tk); 	r = tkrect(tk, 0);	if (rectclip(&r, rectsubpt(c->update, c->view)))		combinerect(&tk->dirty, r);} voidtkxlatepts(Point *p, int npoints, int x, int y){	while(npoints--) {		p->x += x;		p->y += y;		p++;	}} voidtkbbmax(Rectangle *bb, Rectangle *r){	if(r->min.x < bb->min.x)		bb->min.x = r->min.x;	if(r->min.y < bb->min.y)		bb->min.y = r->min.y;	if(r->max.x > bb->max.x)		bb->max.x = r->max.x;	if(r->max.y > bb->max.y)		bb->max.y = r->max.y;} voidtkpolybound(Point *p, int n, Rectangle *r){	while(n--) {		if(p->x < r->min.x)			r->min.x = p->x;		if(p->y < r->min.y)			r->min.y = p->y;		if(p->x > r->max.x)			r->max.x = p->x;		if(p->y > r->max.y)			r->max.y = p->y;		p++;	}} /* * look up a tag for a canvas item. * if n is non-nil, and the tag isn't found, * then add it to the canvas's taglist. * NB if there are no binds done on the * canvas, these tags never get cleared out, * even if nothing refers to them. */TkName*tkctaglook(Tk* tk, TkName *n, char *name){	ulong h;	TkCanvas *c;	char *p, *s;	TkName *f, **l; 	c = TKobj(TkCanvas, tk); 	s = name;	if(s == nil)		s = n->name; 	if(strcmp(s, "current") == 0)		return c->current; 	h = 0;	for(p = s; *p; p++)		h += 3*h + *p; 	l = &c->thash[h%TkChash];	for(f = *l; f; f = f->link)		if(strcmp(f->name, s) == 0)			return f; 	if(n == nil)		return nil;	n->link = *l;	*l = n;	return n;} char*tkcaddtag(Tk *tk, TkCitem *i, int new){	TkCtag *t;	TkCanvas *c;	char buf[16];	TkName *n, *f, *link; 	c = TKobj(TkCanvas, tk);	if(new != 0) {		i->id = ++c->id;		snprint(buf, sizeof(buf), "%d", i->id);		n = tkmkname(buf);		if(n == nil)			return TkNomem;		n->link = i->tags;		i->tags = n;	} 	for(n = i->tags; n; n = link) {		link = n->link;		f = tkctaglook(tk, n, nil);		if(n != f)			free(n); 		for(t = i->stag; t; t = t->itemlist)			if(t->name == f)				break;		if(t == nil) {			t = malloc(sizeof(TkCtag));			if(t == nil) {				tkfreename(link);				return TkNomem;			}			t->name = f;			t->taglist = f->obj;		/* add to head of items with this tag */			f->obj = t;			t->item = i;			t->itemlist = i->stag;	/* add to head of tags for this item */			i->stag = t;		}	}	i->tags = nil; 	if(new != 0) {		i->tags = tkmkname("all");		if(i->tags == nil)			return TkNomem;		/* XXX - Tad: memory leak? */		return tkcaddtag(tk, i, 0);	} 	return nil;} voidtkfreepoint(TkCpoints *p){	free(p->drawpt);	free(p->parampt);} /* * of all the items in ilist tagged with tag, * return that tag for the first (topmost) item. */TkCtag*tkclasttag(TkCitem *ilist, TkCtag* tag){	TkCtag *last, *t; 	if (tag == nil || tag->taglist == nil)		return tag;	last = nil;	while(ilist) {		for(t = tag; t; t = t->taglist) {			if(t->item == ilist) {				last = t;				break;			}		}		ilist = ilist->next;	}	return last;} /* * of all the items in ilist tagged with tag, * return that tag for the first (bottommost) item. */TkCtag*tkcfirsttag(TkCitem *ilist, TkCtag* tag){	TkCtag *t; 	if (tag == nil || tag->taglist == nil)		return tag;	for (; ilist != nil; ilist = ilist->next)		for(t = tag; t; t = t->taglist)			if(t->item == ilist)				return t;	return nil;}		voidtkmkpen(Image **pen, TkEnv *e, Image *stipple){	int locked;	Display *d;	Image *new, *fill; 	fill = tkgc(e, TkCfill); 	d = e->top->display;	locked = lockdisplay(d);	if(*pen != nil) {		freeimage(*pen);		*pen = nil;	}	if(stipple == nil) {		if(locked)			unlockdisplay(d);		return;	} 	if(fill == nil)		fill = d->black;	new = allocimage(d, stipple->r, RGBA32, 1, DTransparent);	/* XXX RGBA32 is excessive sometimes... */	if (new != nil)		draw(new, stipple->r, fill, stipple, ZP);	else		new = fill;	if(locked)		unlockdisplay(d);	*pen = new;} Pointtkcvsanchor(Point dp, int w, int h, int anchor){	Point o; 	if(anchor & Tknorth)		o.y = dp.y;	else	if(anchor & Tksouth)		o.y = dp.y - h;	else		o.y = dp.y - h/2; 	if(anchor & Tkwest)		o.x = dp.x;	else	if(anchor & Tkeast)		o.x = dp.x - w;	else		o.x = dp.x - w/2; 	return o;} static TkCitem*tkcvsmousefocus(TkCanvas *c, Point p){	TkCitem *i, *s;	int (*hit)(TkCitem*, Point); 	if (c->grab != nil)		return c->grab;	s = nil;	for(i = c->head; i; i = i->next)		if(ptinrect(p, i->p.bb)) {			if ((hit = tkcimethod[i->type].hit) != nil && !(*hit)(i, p))				continue;			s = i;		} 	return s;} Tk*tkcvsinwindow(Tk *tk, Point *p){	TkCanvas *c;	TkCitem *i;	Point q;	TkCwind *w; 	c = TKobj(TkCanvas, tk); 	q = addpt(*p, c->view);	i = tkcvsmousefocus(c, addpt(*p, c->view));	if (i == nil || i->type != TkCVwindow)		return tk;	w = TKobj(TkCwind, i);	if (w->sub == nil)		return tk;	p->x = q.x - (i->p.bb.min.x + w->sub->borderwidth);	p->y = q.y - (i->p.bb.min.y + w->sub->borderwidth);	return w->sub;} static Tk*tkcvsmouseinsub(TkCwind *w, TkMouse m){	Point g, mp;	int bd; 	g = tkposn(w->sub);	bd = w->sub->borderwidth;	mp.x = m.x - (g.x + bd);	mp.y = m.y - (g.y + bd);	return tkinwindow(w->sub, mp, 0);} static Tk*tkcvsdeliver(Tk *tk, TkCitem *i, int event, void *data){	Tk *ftk, *dest;	TkCtag *t;	TkCwind *w;	TkAction *a; 	if(i->type == TkCVwindow) {		dest = nil;		w = TKobj(TkCwind, i);		if(w->sub == nil)			return nil; 		if(!(event & TkKey) && (event & TkEmouse)) {			ftk = tkcvsmouseinsub(w, *(TkMouse*)data);			if(ftk != w->focus) {				tkdeliver(w->focus, TkLeave, data);				tkdeliver(ftk, TkEnter, data);				w->focus = ftk;			}			if(ftk != nil)				dest = tkdeliver(ftk, event, data);		}		else {			if (event & TkLeave) {				tkdeliver(w->focus, TkLeave, data);				w->focus = nil;			} else if (event & TkEnter) {				ftk = tkcvsmouseinsub(w, *(TkMouse*)data);				tkdeliver(ftk, TkEnter, data);				w->focus = ftk;			} else				dest = tkdeliver(w->sub, event, data);		}		return dest;	} 	for(t = i->stag; t != nil; t = t->itemlist) {		a = t->name->prop.binds;		if(a != nil)			tksubdeliver(tk, a, event, data, 0);	}	return nil;} Tk*tkcvsevent(Tk *tk, int event, void *data){	TkMouse m;	TkCitem *f;	Point mp, g;	TkCanvas *c;	Tk *dest; 	c = TKobj(TkCanvas, tk); 	if(event == TkLeave && c->mouse != nil) {		tkcvsdeliver(tk, c->mouse, TkLeave, data);		c->mouse = nil;	} 	dest = nil;	if(!(event & TkKey) && (event & TkEmouse) || (event & TkEnter)) {		m = *(TkMouse*)data;		g = tkposn(tk);		mp.x = (m.x - g.x - tk->borderwidth) + c->view.x;		mp.y = (m.y - g.y - tk->borderwidth) + c->view.y;		f = tkcvsmousefocus(c, mp);		if(c->mouse != f) {			if(c->mouse != nil) {				tkcvsdeliver(tk, c->mouse, TkLeave, data);				c->current->obj = nil;			}			if(f != nil) {				c->current->obj = &c->curtag;				c->curtag.item = f;				tkcvsdeliver(tk, f, TkEnter, data);			}			c->mouse = f;		}		f = c->mouse;		if(f != nil && (event & TkEnter) == 0)			dest = tkcvsdeliver(tk, f, event, &m);	} 	if(event & TkKey) {		f = c->focus;		if(f != nil)

Lines 1–500 of 506.