diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libprefab/compound.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libprefab/compound.c')
| -rw-r--r-- | libprefab/compound.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/libprefab/compound.c b/libprefab/compound.c new file mode 100644 index 00000000..b9cf820e --- /dev/null +++ b/libprefab/compound.c @@ -0,0 +1,193 @@ +#include <lib9.h> +#include <draw.h> +#include <interp.h> +#include <isa.h> +#include "../libinterp/runt.h" +#include <drawif.h> +#include <prefab.h> + +extern void queuerefresh(Image *i, Rectangle r, Reffn reffn, void *refptr); + +Draw_Rect +edgerect(Prefab_Environ *e, Draw_Point p, Draw_Rect *rin) +{ + Draw_Rect r; + Screen *s; + + r.min.x = p.x; + r.min.y = p.y; + r.max.x = p.x + 1 + Dx(*rin) + 1; + r.max.y = p.y + 1 + Dy(*rin) + 1; + /* outer box computed; now make sure it's all visible */ + s = lookupscreen(e->screen); + if(s != nil) + fitrect((Rectangle*)&r, s->display->image->r); + + rin->min.x = r.min.x+1; + rin->min.y = r.min.y+1; + rin->max.x = r.max.x-1; + rin->max.y = r.max.y-1; + + return r; +} + +/* + * Draw edge around r. + * Assume geometry has already been clipped and adjusted. + */ +void +edge(Prefab_Environ *e, Image *box, Draw_Rect dr, Draw_Rect dclipr) +{ + Rectangle r, r1, clipr; + Image *ec; + Screen *s; + + R2R(r, dr); + R2R(clipr, dclipr); + r.min.x -= 1; + r.min.y -= 1; + r.max.x += 1; + r.max.y += 1; + s = lookupscreen(e->screen); + if(s == nil) + return; + ec = lookupimage(e->style->edgecolor); + if(ec == nil) + return; + + r1 = r; + r1.min.y++; + r1.max.y = r1.min.y+2; + r1.max.x = r1.min.x+2*(r1.max.x-r1.min.x)/3; + if(rectclip(&r1, clipr)) + draw(box, r1, ec, nil, r1.min); + r1 = r; + r1.min.x++; + r1.max.x = r1.min.x+2; + r1.max.y = r1.min.y+2*(r1.max.y-r1.min.y)/3; + if(rectclip(&r1, clipr)) + draw(box, r1, ec, nil, r1.min); + r1=r; + r1.min.x = r1.max.x-1; + if(rectclip(&r1, clipr)) + draw(box, r1, ec, nil, r1.min); + r1=r; + r1.min.y = r1.max.y-1; + if(rectclip(&r1, clipr)) + draw(box, r1, ec, nil, r1.min); + r1 = r; + r1.max.y = r1.min.y+1; + if(rectclip(&r1, clipr)) + draw(box, r1, ec, nil, r1.min); + r1=r; + r1.max.x = r1.min.x+1; + if(rectclip(&r1, clipr)) + draw(box, r1, ec, nil, r1.min); +} + +void +redrawcompound(Image *i, Rectangle clipr, Prefab_Compound *c) +{ + Rectangle r1, rt, r; + int l, len; + Prefab_Style *s; + Image *elemcolor, *edgecolor; + List *list; + Font *font; + Prefab_Element *e; + + if(c==H || badenviron(c->environ, 0)) + return; + + r = clipr; + s = c->environ->style; + elemcolor = lookupimage(s->elemcolor); + edgecolor = lookupimage(s->edgecolor); + if(elemcolor==nil || edgecolor==nil) + return; + draw(i, r, elemcolor, nil, r.min); + if(lookupelement(c->title) != H){ + R2R(rt, c->title->r); + if(c->title->environ!=H && c->title->environ->style!=H && rectXrect(r, rt)){ + drawelement(c->title, i, r, c->environ==c->title->environ, 0); + r1.min.x = c->r.min.x; + r1.min.y = c->title->r.max.y; + s = c->title->environ->style; + len = 0; + switch(c->title->kind){ + case ETitle: + font = lookupfont(s->titlefont); + if(font != nil) + len = 2+1+stringwidth(font, string2c(c->title->str)); + break; + case EVertical: + font = lookupfont(s->titlefont); + if(font != nil) + for(list=c->title->kids; list!=H; list=list->tail){ + e = *(Prefab_Element**)list->data; + l = stringwidth(font, string2c(e->str)); + if(l > len) + len = l; + } + len += 2+1; + break; + default: + len = r1.min.x+2*Dx(c->r)/3; + } + r1.max.x = r1.min.x + len; + r1.max.y = r1.min.y+1; + draw(i, r1, edgecolor, nil, r.min); + r.min.y = r1.max.y; + } + } + if(c->contents!=H) + drawelement(c->contents, i, r, c->environ==c->contents->environ, 0); + edge(c->environ, i, c->r, DRECT(clipr)); +} + +void +refreshcompound(Image *i, Rectangle r, void *ptr) +{ + Prefab_Compound *c; + + c = ptr; + if(c == nil) + return; + if(i == nil){ /* called from flushimage */ + i = lookupimage(c->image); + if(i == nil) + return; + } + redrawcompound(i, r, c); +} + +void +localrefreshcompound(Memimage *mi, Rectangle r, void *ptr) +{ + Prefab_Compound *c; + Image *i; + + USED(mi); /* can't do anything with this, but it's part of the memlayer interface */ + c = ptr; + if(c == nil) + return; + i = lookupimage(c->image); + if(i == nil) + return; + queuerefresh(i, r, refreshcompound, ptr); +} + +void +drawcompound(Prefab_Compound *c) +{ + Image *i; + + if(c==H || c->image==H) + return; + i = lookupimage(c->image); + redrawcompound(i, insetrect(IRECT(c->r), -1), c); + if(i->display->local && i->refptr==nil) + if(drawlsetrefresh(i->display->dataqid, i->id, localrefreshcompound, c) <= 0) + fprint(2, "drawcompound: can't set refresh\n"); + i->refptr = c; /* can now be refreshed */ +} |
