Charles.Forsyth20060303a828770d19 years agoHistory
723 lines · 15.3 KB · C
RawDownload
#include <lib9.h>#include <draw.h>#include <interp.h>#include <isa.h>#include "../libinterp/runt.h"#include <drawif.h>#include <prefab.h>  void	icondraw(Prefab_Element*, Image*, Rectangle, int, int);void	textdraw(Prefab_Element*, Image*, Rectangle, int, int);void	listdraw(Prefab_Element*, Image*, Rectangle, int, int);void	outlinehighlight(Prefab_Element*, Image*, Prefab_Compound*, int);void	texthighlight(Prefab_Element*, Image*, Prefab_Compound*, int);void	simpleclip(Prefab_Element*, Rectangle);void	horizontalclip(Prefab_Element*, Rectangle);void	verticalclip(Prefab_Element*, Rectangle);void	textscroll(Prefab_Element*, Point, int*);void	horizontalscroll(Prefab_Element*, Point, int*);void	verticalscroll(Prefab_Element*, Point, int*);void	iconscroll(Prefab_Element*, Point, int*); struct{	void	(*draw)(Prefab_Element*, Image*, Rectangle, int, int);	void	(*highlight)(Prefab_Element*, Image*, Prefab_Compound*, int);	void	(*clip)(Prefab_Element*, Rectangle);	void	(*scroll)(Prefab_Element*, Point, int*);}elemfn[] = { /* EIcon */		{ icondraw, outlinehighlight, simpleclip, iconscroll, }, /* EText */		{ textdraw, texthighlight, simpleclip, textscroll, }, /* ETitle */		{ textdraw, outlinehighlight, simpleclip, textscroll, }, /* EHorizontal */	{ listdraw, outlinehighlight, horizontalclip, horizontalscroll, }, /* EVertical */	{ listdraw, outlinehighlight, verticalclip, verticalscroll, }, /* ESeparator */	{ icondraw, outlinehighlight, simpleclip, iconscroll, },}; Pointiconsize(Image *image){	Point dd; 	if(image->repl){		dd.x = Dx(image->clipr);		dd.y = Dy(image->clipr);	}else{		dd.x = Dx(image->r);		dd.y = Dy(image->r);	}	return dd;} voidicondraw(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight){	Prefab_Style *style;	Rectangle r;	Point p;	PElement *pelem;	Image *image, *c;	Point size; 	USED(highlight);	pelem = lookupelement(elem);	if(pelem == H)		return;	if(!rectclip(&clipr, i->clipr))		return;	R2R(r, elem->r);	if(!rectclip(&clipr, r))		return;	if(elem->image==H || elem->mask==H || badenviron(elem->environ, 0))		return;	style = elem->environ->style;	if(!clean){		c = lookupimage(style->elemcolor);		if(c != nil)			draw(i, clipr, c, nil, clipr.min);	}	r.min = pelem->drawpt;	image = lookupimage(elem->image);	if(image == nil)		return;	size = iconsize(image);	r.max.x = r.min.x+size.x;	r.max.y = r.min.y+size.y;	if(rectclip(&r, clipr)){		p = image->r.min;		p.x += r.min.x-pelem->drawpt.x;		p.y += r.min.y-pelem->drawpt.y;		c = lookupimage(elem->mask);		if(c != nil)			draw(i, r, image, c, p);	}} voidtextdraw(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight){	Prefab_Style *style;	Rectangle r;	PElement *pelem;	Image *color, *c;	Font *font; 	USED(highlight);	pelem = lookupelement(elem);	if(pelem == H)		return;	if(!rectclip(&clipr, i->clipr))		return;	R2R(r, elem->r);	if(!rectclip(&clipr, r))		return;	if(elem->str==H || badenviron(elem->environ, 0))		return;	style = elem->environ->style;	font = lookupfont(elem->font);	if(font == nil)		return;	if(highlight)		color = lookupimage(style->highlightcolor);	else		color = lookupimage(elem->image);	if(!clean){		c = lookupimage(style->elemcolor);		if(c != nil)			draw(i, clipr, c, nil, clipr.min);	}	if(color != nil)		_string(i, pelem->drawpt, color, pelem->drawpt, font, string2c(elem->str), nil, 1<<24, clipr, nil, pelem->drawpt, SoverD);} voidlistdraw(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight){	Prefab_Style *style;	Prefab_Element *e;	List *l;	Rectangle r;	PElement *pelem;	Image *c; 	pelem = lookupelement(elem);	if(pelem == H)		return;	if(!rectclip(&clipr, i->clipr))		return;	R2R(r, elem->r);	if(!rectclip(&clipr, r))		return;	if(elem->kids==H || badenviron(elem->environ, 0))		return;	if(pelem->first != elem->kids)	/* error? */		return;	style = elem->environ->style;	if(!clean){		c = lookupimage(style->elemcolor);		if(c != nil)			draw(i, clipr, c, nil, clipr.min);	}	for(l=pelem->vfirst; l!=H; l=l->tail){		e = *(Prefab_Element**)l->data;		R2R(r, e->r);		if(rectXrect(r, clipr))			drawelement(e, i, clipr, elem->environ==e->environ, highlight);		if(l == pelem->vlast)			break;	}} voiddrawelement(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight){	PElement *pelem; 	if(elem != H){		pelem = lookupelement(elem);		if(pelem == H)			return;		(*elemfn[elem->kind].draw)(elem, i, clipr, clean, highlight);		if(!highlight && pelem->highlight!=H)			(*elemfn[elem->kind].highlight)(elem, i, pelem->highlight, 1);	}} voidtranslateelement(Prefab_Element *elem, Point delta){	PElement *pelem;	List *l; 	if(elem == H)		return;	pelem = lookupelement(elem);	if(pelem == H)		return;	elem->r.min.x += delta.x;	elem->r.min.y += delta.y;	elem->r.max.x += delta.x;	elem->r.max.y += delta.y;	pelem->drawpt.x += delta.x;	pelem->drawpt.y += delta.y;	switch(elem->kind){	case EHorizontal:	case EVertical:		if(pelem->first != elem->kids)			return;		for(l=elem->kids; l!=H; l=l->tail)			translateelement(*(Prefab_Element**)l->data, delta);		break;	}} intfitrect(Rectangle *r, Rectangle sr){	if(r->max.x > sr.max.x){		r->min.x -= r->max.x-sr.max.x;		r->max.x = sr.max.x;	}	if(r->max.y > sr.max.y){		r->min.y -= r->max.y-sr.max.y;		r->max.y = sr.max.y;	}	if(r->min.x < sr.min.x){		r->max.x += sr.min.x-r->min.x;		r->min.x = sr.min.x;	}	if(r->min.y < sr.min.y){		r->max.y += sr.min.y-r->min.y;		r->min.y = sr.min.y;	}	return rectinrect(*r, sr);} voidadjusthorizontal(Prefab_Element *elem, int spacing, int position){	int edx, dx, i, x;	int nlist;	/* BUG: should precompute */	List *l;	PElement *pelem;	Prefab_Element *e;	Point p; 	pelem = lookupelement(elem);	if(pelem == H)		return;	if(pelem->first != elem->kids)		return;	p.y = 0;	switch(spacing){	default:	/* shouldn't happen; protected by adjustelement */	case Adjpack:		x = elem->r.min.x;		for(l=elem->kids; l!=H; l=l->tail){			e = *(Prefab_Element**)l->data;			p.x = x - e->r.min.x;			translateelement(e, p);			x += Dx(e->r);		}		elem->r.max.x = x;		return; 	case Adjequal:		dx = 0;		nlist = 0;		for(l=elem->kids; l!=H; l=l->tail){			e = *(Prefab_Element**)l->data;			if(dx < Dx(e->r))				dx = Dx(e->r);			nlist++;		}		elem->r.max.x = elem->r.min.x+nlist*dx;		break; 	case Adjfill:		nlist = 0;		for(l=elem->kids; l!=H; l=l->tail)			nlist++;		dx = Dx(elem->r)/nlist;		break;	}	i = 0;	for(l=elem->kids; l!=H; l=l->tail){		e = *(Prefab_Element**)l->data;		edx = Dx(e->r);		if(position == Adjleft)			edx = 0;		else if(position == Adjcenter)			edx = (dx-edx)/2;		else	/* right */			edx = dx-edx;		p.x = (elem->r.min.x+i*dx + edx) - e->r.min.x;		translateelement(e, p);		i++;	}} voidadjustvertical(Prefab_Element *elem, int spacing, int position){	int edy, dy, i, y;	int nlist;	/* BUG: should precompute */	List *l;	PElement *pelem;	Prefab_Element *e;	Point p; 	pelem = lookupelement(elem);	if(pelem == H)		return;	if(pelem->first != elem->kids)		return;	p.x = 0;	switch(spacing){	default:	/* shouldn't happen; protected by adjustelement */	case Adjpack:		y = elem->r.min.y;		for(l=elem->kids; l!=H; l=l->tail){			e = *(Prefab_Element**)l->data;			p.y = y - e->r.min.y;			translateelement(e, p);			y += Dy(e->r);		}		elem->r.max.y = y;		return; 	case Adjequal:		dy = 0;		nlist = 0;		for(l=elem->kids; l!=H; l=l->tail){			e = *(Prefab_Element**)l->data;			if(dy < Dy(e->r))				dy = Dy(e->r);			nlist++;		}		elem->r.max.y = elem->r.min.y+nlist*dy;		break; 	case Adjfill:		nlist = 0;		for(l=elem->kids; l!=H; l=l->tail)			nlist++;		dy = Dy(elem->r)/nlist;		break;	}	i = 0;	for(l=elem->kids; l!=H; l=l->tail){		e = *(Prefab_Element**)l->data;		edy = Dy(e->r);		if(position == Adjup)			edy = 0;		else if(position == Adjcenter)			edy = (dy-edy)/2;		else	/* down */			edy = dy-edy;		p.y = (elem->r.min.y+i*dy + edy) - e->r.min.y;		translateelement(e, p);		i++;	}} voidadjustelement(Prefab_Element *elem, int spacing, int position){	if(lookupelement(elem) == H)		return;	if(spacing<Adjpack || spacing>Adjfill || position<Adjleft || position>Adjdown)		return;	switch(elem->kind){	case EVertical:		adjustvertical(elem, spacing, position);		break;	case EHorizontal:		adjusthorizontal(elem, spacing, position);		break;	}} voidhighlightelement(Prefab_Element *elem, Image *i, Prefab_Compound *comp, int on){	PElement *pelem; 	pelem = lookupelement(elem);	if(pelem!=H && lookupcompound(comp)!=H){		if(on)			pelem->highlight = comp;		else			pelem->highlight = H;		(*elemfn[elem->kind].highlight)(elem, i, comp, on);	}} staticintanytextelements(Prefab_Element *e){	Prefab_Element *t;	List *l; 	for(l=e->kids; l!=H; l=l->tail){		t = *(Prefab_Element**)l->data;		if(t->kind == EText)			return 1;	}	return 0;} voidtextlisthighlight(Prefab_Element *e, Image *i, Prefab_Compound *c, int on){	Prefab_Element *t;	List *l; 	for(l=e->kids; l!=H; l=l->tail){		t = *(Prefab_Element**)l->data;		if(t->kind == EText)			texthighlight(t, i, c, on);	}} voidoutlinehighlight(Prefab_Element *e, Image *i, Prefab_Compound *c, int on){	List *l;	Prefab_Element *t;	Image *color;	Rectangle r, r1, r2;	Point dp;	int done; 	/* see if we can do it by highlighting just a text element */	if((e->kind==EVertical || e->kind==EHorizontal) && e->kids!=H){		/* is any child a text element? */		if(anytextelements(e)){			textlisthighlight(e, i, c, on);			return;		}		/* grandchild? */		done = 0;		for(l=e->kids; l!=H; l=l->tail){			t = *(Prefab_Element**)l->data;			if(t->kind==EVertical || t->kind==EHorizontal)				if(anytextelements(t)){					textlisthighlight(t, i, c, on);					done = 1;				}		}		if(done)			return;	}	if(on){		color = lookupimage(e->environ->style->highlightcolor);		if(color == nil)			return;		R2R(r, e->r);		/* avoid outlining empty space around images */		dp = ((PElement*)e)->drawpt;		if(e->kind==EIcon && e->image->repl==0 && ptinrect(dp, r)){			R2R(r1, e->image->r);			R2R(r2, e->image->clipr);			if(rectclip(&r1, r2)){				dp.x += Dx(r1);				dp.y += Dy(r1);				if(ptinrect(dp, r))					r = Rpt(((PElement*)e)->drawpt, dp);			}		}		draw(i, r, color, nil, r.min);		drawelement(e, i, insetrect(r, 2), Dirty, 1);	}else{		drawelement(e, i, IRECT(e->r), Dirty, 0);		edge(c->environ, i, c->r, e->r);	}} voidtexthighlight(Prefab_Element *e, Image *i, Prefab_Compound *c, int on){	drawelement(e, i, IRECT(e->r), Clean, on);	edge(c->environ, i, c->r, e->r);} voidclipelement(Prefab_Element *elem, Rectangle r){	if(lookupelement(elem) != H)		(*elemfn[elem->kind].clip)(elem, r);} voidsimpleclip(Prefab_Element *elem, Rectangle r){	R2R(elem->r, r);} void

Lines 1–500 of 723.