123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- #include "lib9.h"
- #include "draw.h"
- #include "tk.h"
- #include "textw.h"
- #define istring u.string
- #define iwin u.win
- #define imark u.mark
- #define iline u.line
- #define O(t, e) ((long)(&((t*)0)->e))
- static char* tktwincget(Tk*, char*, char**);
- static char* tktwinconfigure(Tk*, char*, char**);
- static char* tktwincreate(Tk*, char*, char**);
- static char* tktwinnames(Tk*, char*, char**);
- static int winowned(Tk *tk, Tk *sub);
- static
- TkStab tkalign[] =
- {
- "top", Tktop,
- "bottom", Tkbottom,
- "center", Tkcenter,
- "baseline", Tkbaseline,
- nil
- };
- static
- TkOption twinopts[] =
- {
- "align", OPTstab, O(TkTwind, align), tkalign,
- "create", OPTtext, O(TkTwind, create), nil,
- "padx", OPTnndist, O(TkTwind, padx), nil,
- "pady", OPTnndist, O(TkTwind, pady), nil,
- "stretch", OPTstab, O(TkTwind, stretch), tkbool,
- "window", OPTwinp, O(TkTwind, sub), nil,
- "ascent", OPTdist, O(TkTwind, ascent), nil,
- nil
- };
- TkCmdtab
- tktwincmd[] =
- {
- "cget", tktwincget,
- "configure", tktwinconfigure,
- "create", tktwincreate,
- "names", tktwinnames,
- nil
- };
- int
- tktfindsubitem(Tk *sub, TkTindex *ix)
- {
- Tk *tk, *isub;
- TkText *tkt;
- tk = sub->parent;
- if(tk != nil) {
- tkt = TKobj(TkText, tk);
- tktstartind(tkt, ix);
- do {
- if(ix->item->kind == TkTwin) {
- isub = ix->item->iwin->sub;
- if(isub != nil &&
- isub->name != nil &&
- strcmp(isub->name->name, sub->name->name) == 0)
- return 1;
- }
- } while(tktadjustind(tkt, TkTbyitem, ix));
- }
- return 0;
- }
- static void
- tktwindsize(Tk *tk, TkTindex *ix)
- {
- Tk *s;
- TkTitem *i;
- TkTwind *w;
- i = ix->item;
- /* assert(i->kind == TkTwin); */
- w = i->iwin;
- s = w->sub;
- if(s == nil)
- return;
- if(w->width != s->act.width || w->height != s->act.height) {
- s->act.width = w->width;
- s->act.height = w->height;
- if(s->slave) {
- tkpackqit(s);
- tkrunpack(tk->env->top);
- }
- }
- tktfixgeom(tk, tktprevwrapline(tk, ix->line), ix->line, 0);
- tktextsize(tk, 1);
- }
- void
- tktxtforgetsub(Tk *sub, Tk *tk)
- {
- TkTwind *w;
- TkTindex ix;
- if(!tktfindsubitem(sub, &ix))
- return;
- w = ix.item->iwin;
- if(w->focus == tk) {
- if(0)print("tktxtforget sub %p %q focus %p %q\n", sub, tkname(sub), tk, tkname(tk));
- w->focus = nil;
- }
- }
- static void
- tktwingeom(Tk *sub, int x, int y, int w, int h)
- {
- TkTindex ix;
- Tk *tk;
- TkTwind *win;
- USED(x);
- USED(y);
- tk = sub->parent;
- if(!tktfindsubitem(sub, &ix)) {
- print("tktwingeom: %s not found\n", sub->name->name);
- return;
- }
- win = ix.item->iwin;
- win->width = w;
- win->height = h;
- sub->req.width = w;
- sub->req.height = h;
- tktwindsize(tk, &ix);
- }
- static void
- tktdestroyed(Tk *sub)
- {
- TkTindex ix;
- Tk *tk;
- if(tktfindsubitem(sub, &ix)) {
- ix.item->iwin->sub = nil;
- ix.item->iwin->focus = nil;
- if((tk = sub->parent) != nil) {
- tktfixgeom(tk, tktprevwrapline(tk, ix.line), ix.line, 0);
- tktextsize(tk, 1);
- sub->parent = nil;
- }
- }
- }
- void
- tktdirty(Tk *sub)
- {
- Tk *tk, *parent, *isub;
- TkText *tkt;
- TkTindex ix;
- parent = nil;
- for(tk = sub; tk && parent == nil; tk = tk->master)
- parent = tk->parent;
- if(tk == nil)
- return;
- tkt = TKobj(TkText, parent);
- tktstartind(tkt, &ix);
- do {
- if(ix.item->kind == TkTwin) {
- isub = ix.item->iwin->sub;
- if(isub != nil) {
- tktfixgeom(parent, tktprevwrapline(parent, ix.line), ix.line, 0);
- if (sub->flag & Tktransparent)
- parent->flag |= Tkrefresh; /* XXX could be more efficient, by drawing the background locally? */
- return;
- }
- }
- } while(tktadjustind(tkt, TkTbyitem, &ix));
- tktextsize(parent, 1);
- }
- static char*
- tktwinchk(Tk *tk, TkTwind *w, Tk *oldsub)
- {
- Tk *sub;
- sub = w->sub;
- if (sub != oldsub) {
- w->sub = oldsub;
- if(sub == nil)
- return nil;
- if(sub->flag & Tkwindow)
- return TkIstop;
-
- if(sub->master != nil || sub->parent != nil)
- return TkWpack;
- if (oldsub != nil) {
- oldsub->parent = nil;
- oldsub->geom = nil;
- oldsub->destroyed = nil;
- }
- w->sub = sub;
- w->focus = nil;
- sub->parent = tk;
- tksetbits(sub, Tksubsub);
- sub->geom = tktwingeom;
- sub->destroyed = tktdestroyed;
- w->width = sub->req.width;
- w->height = sub->req.height;
- w->owned = winowned(tk, sub);
- }
- return nil;
- }
- /* Text Window Command (+ means implemented)
- +cget
- +configure
- +create
- +names
- */
- static char*
- tktwincget(Tk *tk, char *arg, char **val)
- {
- char *e;
- TkTindex ix;
- TkOptab tko[2];
- e = tktindparse(tk, &arg, &ix);
- if(e != nil)
- return e;
- if(ix.item->kind != TkTwin)
- return TkBadwp;
- tko[0].ptr = ix.item->iwin;
- tko[0].optab = twinopts;
- tko[1].ptr = nil;
- return tkgencget(tko, arg, val, tk->env->top);
- }
- static char*
- tktwinconfigure(Tk *tk, char *arg, char **val)
- {
- char *e;
- TkTindex ix;
- TkOptab tko[2];
- Tk *oldsub;
- USED(val);
- e = tktindparse(tk, &arg, &ix);
- if(e != nil)
- return e;
- if(ix.item->kind != TkTwin)
- return TkBadwp;
- oldsub = ix.item->iwin->sub;
- tko[0].ptr = ix.item->iwin;
- tko[0].optab = twinopts;
- tko[1].ptr = nil;
- e = tkparse(tk->env->top, arg, tko, nil);
- if(e != nil)
- return e;
- e = tktwinchk(tk, ix.item->iwin, oldsub);
- if(e != nil)
- return e;
- tktwindsize(tk, &ix);
- return nil;
- }
- /*
- * return true if tk is an ancestor of sub
- */
- static int
- winowned(Tk *tk, Tk *sub)
- {
- int len;
- if (tk->name == nil || sub->name == nil)
- return 0;
- len = strlen(tk->name->name);
- if (strncmp(tk->name->name, sub->name->name, len) == 0 &&
- sub->name->name[len] == '.')
- return 1;
- return 0;
- }
- static char*
- tktwincreate(Tk *tk, char *arg, char **val)
- {
- char *e;
- TkTindex ix;
- TkTitem *i;
- TkText *tkt;
- TkOptab tko[2];
- USED(val);
- tkt = TKobj(TkText, tk);
- e = tktindparse(tk, &arg, &ix);
- if(e != nil)
- return e;
- e = tktnewitem(TkTwin, 0, &i);
- if(e != nil)
- return e;
- i->iwin = malloc(sizeof(TkTwind));
- if(i->iwin == nil) {
- tktfreeitems(tkt, i, 1);
- return TkNomem;
- }
- memset(i->iwin, 0, sizeof(TkTwind));
- i->iwin->align = Tkcenter;
- i->iwin->ascent = -1;
- tko[0].ptr = i->iwin;
- tko[0].optab = twinopts;
- tko[1].ptr = nil;
- e = tkparse(tk->env->top, arg, tko, nil);
- if(e != nil) {
- err1:
- tktfreeitems(tkt, i, 1);
- return e;
- }
- e = tktwinchk(tk, i->iwin, nil);
- if(e != nil)
- goto err1;
- e = tktsplititem(&ix);
- if(e != nil)
- goto err1;
- tktiteminsert(tkt, &ix, i);
- if(e != nil)
- goto err1;
- tktadjustind(tkt, TkTbyitemback, &ix);
- tktwindsize(tk, &ix);
- return nil;
- }
- static char*
- tktwinnames(Tk *tk, char *arg, char **val)
- {
- char *e, *fmt;
- TkTindex ix;
- TkText *tkt = TKobj(TkText, tk);
- USED(arg);
- tktstartind(tkt, &ix);
- fmt = "%s";
- do {
- if(ix.item->kind == TkTwin &&
- ix.item->iwin->sub != nil &&
- ix.item->iwin->sub->name != nil) {
- e = tkvalue(val, fmt, ix.item->iwin->sub->name->name);
- if(e != nil)
- return e;
- fmt = " %s";
- }
- } while(tktadjustind(tkt, TkTbyitem, &ix));
- return nil;
- }
|