#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; }} 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);} 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; if (a->r.min.x > b->r.min.x) return 1; if (a->r.min.x < b->r.min.x) return -1; return 0;} /* compare x-coords only */static inttkfcmpx(void *ap, void *bp){ TkWinfo *a = ap, *b = bp; return a->r.min.x - b->r.min.x;} /* compare y-coords only */static inttkfcmpy(void *ap, void *bp){ TkWinfo *a = ap, *b = bp; return a->r.min.y - b->r.min.y;} static voidLines 1–500 of 693. Load more
#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; } void tkfreectxt(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; } void tkgeomchg(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; } } 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; } void tkmovewin(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; } } void tkmoveresize(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 void tkexterncreatewin(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!) */ int tkupdatewinsize(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; } int tkischild(Tk *tk, Tk *child) { while(child != nil && child != tk){ if(child->master) child = child->master; else child = child->parent; } return child == tk; } void tksetbits(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); } void tkunmap(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; } void tktopopt(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 int tkfcmpgen(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; if (a->r.min.x > b->r.min.x) return 1; if (a->r.min.x < b->r.min.x) return -1; return 0; } /* compare x-coords only */ static int tkfcmpx(void *ap, void *bp) { TkWinfo *a = ap, *b = bp; return a->r.min.x - b->r.min.x; } /* compare y-coords only */ static int tkfcmpy(void *ap, void *bp) { TkWinfo *a = ap, *b = bp; return a->r.min.y - b->r.min.y; } static void