#include #include #include "draw.h" #include "tk.h" #include "frame.h" char* tkframe(TkTop *t, char *arg, char **ret) { Tk *tk; char *e; TkOptab tko[2]; TkName *names; tk = tknewobj(t, TKframe, sizeof(Tk)); if(tk == nil) return TkNomem; tko[0].ptr = tk; tko[0].optab = tkgeneric; tko[1].ptr = nil; names = nil; e = tkparse(t, arg, tko, &names); if(e != nil) { tkfreeobj(tk); return e; } tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); e = tkaddchild(t, tk, &names); tkfreename(names); if(e != nil) { tkfreeobj(tk); return e; } tk->name->link = nil; return tkvalue(ret, "%s", tk->name->name); } /* * Also used for windows, menus, separators */ void tkfreeframe(Tk *tk) { TkWin *tkw; if((tk->flag & Tkwindow) == 0) return; if(tk->type == TKmenu) { tkw = TKobj(TkWin, tk); free(tkw->postcmd); free(tkw->cascade); free(tkw->cbname); } tkunmap(tk); /* XXX do this only if (tk->flag&Tkswept)==0 ?? */ } char* tkdrawframe(Tk *tk, Point orig) { int bw; Point p; Image *i; Tk *f; Rectangle r, slaver; /* dribbling, whipping or just square? */ i = tkimageof(tk); if(i == nil) return nil; p.x = orig.x + tk->act.x + tk->borderwidth; p.y = orig.y + tk->act.y + tk->borderwidth; draw(i, rectaddpt(tk->dirty, p), tkgc(tk->env, TkCbackgnd), nil, ZP); /* * doesn't matter about drawing TKseparator * oblivious of dirty rect, as it never has any children to sully anyway */ if(tk->type == TKseparator) { r = rectaddpt(tkrect(tk, 1), p); r.min.x += 4; r.max.x -= 4; r.min.y += (Dy(r) - 2)/2; r.max.y = r.min.y+1; draw(i, r, tkgc(tk->env, TkCbackgnddark), nil, ZP); r.min.y += 1; r.max.y += 1; draw(i, r, tkgc(tk->env, TkCbackgndlght), nil, ZP); return nil; } /* * make sure all the slaves inside the area we've just drawn * refresh themselves properly. */ for(f = tk->slave; f; f = f->next) { bw = f->borderwidth; slaver.min.x = f->act.x; slaver.min.y = f->act.y; slaver.max.x = slaver.min.x + f->act.width + 2*bw; slaver.max.y = slaver.min.y + f->act.height + 2*bw; if (rectclip(&slaver, tk->dirty)) { f->flag |= Tkrefresh; slaver = rectsubpt(slaver, Pt(f->act.x + bw, f->act.y + bw)); combinerect(&f->dirty, slaver); } } p.x -= tk->borderwidth; p.y -= tk->borderwidth; if (!rectinrect(tk->dirty, tkrect(tk, 0))) tkdrawrelief(i, tk, p, TkCbackgnd, tk->relief); return nil; } /* Frame commands */ static char* tkframecget(Tk *tk, char *arg, char **val) { TkOptab tko[3]; tko[0].ptr = tk; tko[0].optab = tkgeneric; tko[1].ptr = nil; if(tk->flag & Tkwindow){ tko[1].ptr = TKobj(TkWin, tk); tko[1].optab = tktop; tko[2].ptr = nil; } return tkgencget(tko, arg, val, tk->env->top); } static char* tkframeconf(Tk *tk, char *arg, char **val) { char *e; TkGeom g; int bd; Point oldp; TkOptab tko[3]; TkWin *tkw; tko[0].ptr = tk; tko[0].optab = tkgeneric; tko[1].ptr = nil; tkw = nil; if(tk->flag & Tkwindow) { tkw = TKobj(TkWin, tk); tko[1].ptr = tkw; tko[1].optab = tktop; tko[2].ptr = nil; oldp = tkw->act; } if(*arg == '\0') return tkconflist(tko, val); if(tkw != nil){ /* * see whether only -x or -y is being configured, * in which case just move the window; don't redraw * everything */ e = tkparse(tk->env->top, arg, &tko[1], nil); if(e == nil){ if(!eqpt(oldp, tkw->req)) tkmovewin(tk, tkw->req); return nil; } } g = tk->req; bd = tk->borderwidth; e = tkparse(tk->env->top, arg, tko, nil); tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); tk->req.x = tk->act.x; tk->req.y = tk->act.y; tkgeomchg(tk, &g, bd); if(tkw != nil && !eqpt(oldp, tkw->act)) tkmovewin(tk, tkw->req); tk->dirty = tkrect(tk, 1); return e; } static char* tkframesuspend(Tk *tk, char *arg, char **val) { USED(arg); USED(val); if((tk->flag & Tkwindow) == 0) return TkNotwm; tk->flag |= Tksuspended; return nil; } static char* tkframemap(Tk *tk, char *arg, char **val) { USED(arg); USED(val); if(tk->flag & Tkwindow) return tkmap(tk); return TkNotwm; } static char* tkframeunmap(Tk *tk, char *arg, char **val) { USED(arg); USED(val); if(tk->flag & Tkwindow) { tkunmap(tk); return nil; } return TkNotwm; } static void tkframefocusorder(Tk *tk) { int i, n; Tk *sub; TkWinfo *inf; n = 0; for (sub = tk->slave; sub != nil; sub = sub->next) n++; if (n == 0) return; inf = malloc(sizeof(*inf) * n); if (inf == nil) return; i = 0; for (sub = tk->slave; sub != nil; sub = sub->next) { inf[i].w = sub; inf[i].r = rectaddpt(tkrect(sub, 1), Pt(sub->act.x, sub->act.y)); i++; } tksortfocusorder(inf, n); for (i = 0; i < n; i++) tkappendfocusorder(inf[i].w); free(inf); } static TkCmdtab tkframecmd[] = { "cget", tkframecget, "configure", tkframeconf, "map", tkframemap, "unmap", tkframeunmap, "suspend", tkframesuspend, nil }; TkMethod framemethod = { "frame", tkframecmd, tkfreeframe, tkdrawframe, nil, nil, tkframefocusorder };