static void tkcvswindgeom(Tk *sub, int x, int y, int w, int h) { TkCitem *i; Tk *parent; TkCanvas *c; TkCwind *win; USED(x); USED(y); parent = sub->parent; win = nil; c = TKobj(TkCanvas, parent); for(i = c->head; i; i = i->next) { if(i->type == TkCVwindow) { win = TKobj(TkCwind, i); if(win->sub == sub) break; } } tkbbmax(&c->update, &i->p.bb); if((win->flags & Tksetwidth) == 0) win->width = w; if ((win->flags & Tksetheight) == 0) win->height = h; sub->req.width = w; sub->req.height = h; tkcvswindsize(i); tkbbmax(&c->update, &i->p.bb); tkcvsdirty(parent); }
static void tkcvssubdestry(Tk *sub) { Tk *tk; TkCitem *i; TkCanvas *c; TkCwind *win; tk = sub->parent; if(tk == nil) return; if(0)print("tkcvssubdestry %p %q\n", sub, tkname(sub)); i = tkcvsfindwin(sub); if(i == nil) return; win = TKobj(TkCwind, i); if(win->sub != sub){ if(win->sub != nil) print("inconsistent tkcvssubdestry %p %q\n", sub, tkname(sub)); return; } c = TKobj(TkCanvas, tk); tkbbmax(&c->update, &i->p.bb); tkcvssetdirty(tk); win->focus = nil; win->sub = nil; sub->parent = nil; sub->geom = nil; }
char* tkcvsrectcreat(Tk* tk, char *arg, char **val) { char *e; TkCrect *r; TkCitem *i; TkCanvas *c; TkOptab tko[3]; c = TKobj(TkCanvas, tk); i = tkcnewitem(tk, TkCVrect, sizeof(TkCitem)+sizeof(TkCrect)); if(i == nil) return TkNomem; r = TKobj(TkCrect, i); r->width = TKI2F(1); e = tkparsepts(tk->env->top, &i->p, &arg, 0); if(e != nil) { tkcvsfreeitem(i); return e; } if(i->p.npoint != 2) { tkcvsfreeitem(i); return TkFewpt; } tko[0].ptr = r; tko[0].optab = rectopts; tko[1].ptr = i; tko[1].optab = itemopts; tko[2].ptr = nil; e = tkparse(tk->env->top, arg, tko, nil); if(e != nil) { tkcvsfreeitem(i); return e; } tkmkstipple(r->stipple); e = tkcaddtag(tk, i, 1); if(e != nil) { tkcvsfreeitem(i); return e; } tkcvsrectsize(i); e = tkvalue(val, "%d", i->id); if(e != nil) { tkcvsfreeitem(i); return e; } tkcvsappend(c, i); tkbbmax(&c->update, &i->p.bb); tkcvssetdirty(tk); return nil; }
char* tkcvslinecreat(Tk* tk, char *arg, char **val) { char *e; TkCline *l; TkCitem *i; TkCanvas *c; TkOptab tko[3]; c = TKobj(TkCanvas, tk); i = tkcnewitem(tk, TkCVline, sizeof(TkCitem)+sizeof(TkCline)); if(i == nil) return TkNomem; l = TKobj(TkCline, i); l->width = TKI2F(1); e = tkparsepts(tk->env->top, &i->p, &arg, 0); if(e != nil) { tkcvsfreeitem(i); return e; } tko[0].ptr = l; tko[0].optab = lineopts; tko[1].ptr = i; tko[1].optab = itemopts; tko[2].ptr = nil; e = tkparse(tk->env->top, arg, tko, nil); if(e != nil) { tkcvsfreeitem(i); return e; } tkmkpen(&l->pen, i->env, l->stipple); e = tkcaddtag(tk, i, 1); if(e != nil) { tkcvsfreeitem(i); return e; } tkcvslinesize(i); e = tkvalue(val, "%d", i->id); if(e != nil) { tkcvsfreeitem(i); return e; } tkcvsappend(c, i); tkbbmax(&c->update, &i->p.bb); tkcvssetdirty(tk); return nil; }
int tklabelmargin(Tk *tk) { TkLabel *tkl; Image *img; switch(tk->type){ case TKseparator: return 0; case TKlabel: case TKcascade: tkl = TKobj(TkLabel, tk); img = nil; if (tkl->img != nil) img = tkl->img->img; else if (tkl->bitmap != nil) img = tkl->bitmap; if (img != nil) return Bitpadx; return Textpadx; default: fprint(2, "label margin: type %d\n", tk->type); return 0; } }
static int x2index(Tk *tk, int x, int *xc) { TkEntry *tke = TKobj(TkEntry, tk); int t0, t1, r, q; t0 = 0; t1 = tke->textlen; while (t0 <= t1) { r = (t0 + t1) / 2; q = entrytextwidth(tk, r); if (q == x) { if (xc != nil) *xc = q; return r; } if (q < x) t0 = r + 1; else t1 = r - 1; } if (xc != nil) *xc = t1 > 0 ? entrytextwidth(tk, t1) : 0; if (t1 < 0) t1 = 0; return t1; }
static char* tkscalebut1p(Tk *tk, char *arg, char **val) { int z[2]; char *v, *e; TkScale *tks = TKobj(TkScale, tk); int repeat; USED(val); v = tkscaleposn(tk->env, tk, arg, z); if(v == nil) return TkBadvl; e = nil; if(v[0] == '\0' || z[0] < tks->center-tks->sw || z[0] > tks->center+tks->sw) return nil; if(v == slider) { tks->flag |= Dragging; tks->relief = TKsunken; tks->pix = z[1]; tks->base = tks->value; tkscalecheckvalue(tk); } else { e = stepscale(tk, v, &repeat); if (e == nil && repeat) { tks->flag |= Autorepeat; tkrepeat(tk, screpeat, v, TkRptpause, TkRptinterval); } } tk->dirty = tkrect(tk, 1); return e; }
/* * return bounding box of character at index, in coords relative to * the top left position of the text. */ static Rectangle tkentrybbox(Tk *tk, int index) { TkEntry *tke; TkEnv *env; Display *d; int x, cw, locked; Rectangle r; tke = TKobj(TkEntry, tk); env = tk->env; d = env->top->display; locked = lockdisplay(d); x = entrytextwidth(tk, index); if (index < tke->textlen) cw = entrytextwidth(tk, index+1) - x; else cw = Inswidth; if(locked) unlockdisplay(d); r.min.x = x; r.min.y = 0; r.max.x = x + cw; r.max.y = env->font->height; return r; }
static void tkcvswindsize(TkCitem *i) { Tk *s; int bw; Point p; TkGeom old; TkCwind *w; w = TKobj(TkCwind, i); s = w->sub; if(s == nil) return; if(w->width != s->act.width || w->height != s->act.height) { old = s->act; s->act.width = w->width; s->act.height = w->height; if(s->slave) { tkpackqit(s); tkrunpack(s->env->top); } tkdeliver(s, TkConfigure, &old); } p = tkcvsanchor(i->p.drawpt[0], s->act.width, s->act.height, w->flags); s->act.x = p.x; s->act.y = p.y; bw = 2*s->borderwidth; i->p.bb.min = p; i->p.bb.max.x = p.x + s->act.width + bw; i->p.bb.max.y = p.y + s->act.height + bw; }
static char* tkcvsitemconf(Tk *tk, char *arg, char **val) { char *e; TkName *f; TkCtag *t; TkCitem *i; TkCanvas *c; char buf[Tkmaxitem]; USED(val); arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); f = tkctaglook(tk, nil, buf); if(f == nil || f->obj == nil) return TkBadtg; c = TKobj(TkCanvas, tk); for(t = f->obj; t; t = t->taglist) { for(i = c->head; i; i = i->next) { if(i == t->item) { tkbbmax(&c->update, &i->p.bb); e = tkcimethod[i->type].conf(tk, i, arg); tkbbmax(&c->update, &i->p.bb); tkcvssetdirty(tk); if(e != nil) return e; } } } return nil; }
void tkcvssv(Tk *tk) { TkCanvas *c; int top, bot, height; char val[Tkminitem], cmd[Tkmaxitem], *v, *e; c = TKobj(TkCanvas, tk); if(c->yscroll == nil) return; top = 0; bot = TKI2F(1); height = Dy(c->region); if(height != 0) { top = TKI2F(c->view.y)/height; bot = TKI2F(c->view.y+tk->act.height)/height; } v = tkfprint(val, top); *v++ = ' '; tkfprint(v, bot); snprint(cmd, sizeof(cmd), "%s %s", c->yscroll, val); e = tkexec(tk->env->top, cmd, nil); if ((e != nil) && (tk->name != nil)) print("tk: yscrollcommand \"%s\": %s\n", tk->name->name, e); }
void tkfreelabel(Tk *tk) { Image *i; int locked; Display *d; TkLabel *tkl; tkl = TKobj(TkLabel, tk); if(tkl->text != nil) free(tkl->text); if(tkl->command != nil) free(tkl->command); if(tkl->value != nil) free(tkl->value); if(tkl->variable != nil) { tkfreevar(tk->env->top, tkl->variable, tk->flag & Tkswept); free(tkl->variable); } if(tkl->img != nil) tkimgput(tkl->img); i = tkl->bitmap; if(i != nil) { d = i->display; locked = lockdisplay(d); freeimage(i); if(locked) unlockdisplay(d); } if(tkl->menu != nil) free(tkl->menu); }
static char* tkcvscanvx(Tk *tk, char *arg, char **val) { int x, s; TkCanvas *c; Point p; char buf[Tkmaxitem]; c = TKobj(TkCanvas, tk); arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); if(buf[0] == '\0') return TkBadvl; p = tkposn(tk); x = atoi(buf) + c->view.x - (p.x + tk->borderwidth); if(*arg) { tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); s = atoi(buf); if (s) { if (x>=0) x = ((x+s/2)/s)*s; else x = ((x-s/2)/s)*s; } } return tkvalue(val, "%d", x); }
void tkcvslinesize(TkCitem *i) { TkCline *l; int j, w, as, shape[3], arrow; l = TKobj(TkCline, i); w = TKF2I(l->width); i->p.bb = bbnil; tkpolybound(i->p.drawpt, i->p.npoint, &i->p.bb); l->arrowf = l->capstyle; l->arrowl = l->capstyle; if(l->arrow != 0) { as = w/3; if(as < 1) as = 1; for(j = 0; j < 3; j++) { shape[j] = l->shape[j]; if(shape[j] == 0) shape[j] = as * cvslshape[j]; } arrow = ARROW(TKF2I(shape[0]), TKF2I(shape[1]), TKF2I(shape[2])); if(l->arrow & TkCarrowf) l->arrowf = arrow; if(l->arrow & TkCarrowl) l->arrowl = arrow; w += shape[2]; } i->p.bb = insetrect(i->p.bb, -w); }
void tkcvslinedraw(Image *img, TkCitem *i, TkEnv *pe) { int w; Point *p; TkCline *l; Image *pen; USED(pe); l = TKobj(TkCline, i); pen = l->pen; if(pen == nil) pen = tkgc(i->env, TkCforegnd); w = TKF2I(l->width)/2; if(w < 0) return; p = i->p.drawpt; if(l->smooth == BoolT && i->p.npoint >= 3) bezspline(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]); else poly(img, p, i->p.npoint, l->arrowf, l->arrowl, w, pen, p[0]); }
static void tkentrysee(Tk *tk, int index, int jump) { TkEntry *tke = TKobj(TkEntry, tk); int dx, margin; Rectangle r; r = tkentrybbox(tk, index); dx = tk->act.width - 2*xinset(tk); if (jump) margin = dx / 4; else margin = 0; if (r.min.x <= tke->x0 || r.max.x > tke->x0 + dx) { if (r.min.x <= tke->x0) { tke->x0 = r.min.x - margin; if (tke->x0 < 0) tke->x0 = 0; } else if (r.max.x >= tke->x0 + dx) { tke->x0 = r.max.x - dx + margin; if (tke->x0 > tke->xlen - dx) tke->x0 = tke->xlen - dx; } tk->dirty = tkrect(tk, 0); } r = rectaddpt(r, Pt(xinset(tk) - tke->x0, yinset(tk))); tksee(tk, r, r.min); }
static char* tkentrybw(Tk *tk, char *arg, char **val) { int start; Rune *text; TkEntry *tke; char buf[32]; USED(val); USED(arg); tke = TKobj(TkEntry, tk); if(tke->textlen == 0 || tke->icursor == 0) return nil; text = tke->text; start = tke->icursor-1; while(start > 0 && !tkiswordchar(text[start])) --start; while(start > 0 && tkiswordchar(text[start-1])) --start; snprint(buf, sizeof(buf), "%d %d", start, tke->icursor); return tkentrydelete(tk, buf, nil); }
static char* tkentryicursor(Tk *tk, char *arg, char **val) { TkEntry *tke = TKobj(TkEntry, tk); int index, locked; char *r, *buf; USED(val); buf = mallocz(Tkmaxitem, 0); if(buf == nil) return TkNomem; tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil); r = tkentryparseindex(tk, buf, &index); free(buf); if(r != nil) return r; tke->icursor = index; locked = lockdisplay(tk->env->top->display); tke->xicursor = entrytextwidth(tk, tke->icursor); if (locked) unlockdisplay(tk->env->top->display); blinkreset(tk); tk->dirty = tkrect(tk, 1); return nil; }
static char* tklabelconf(Tk *tk, char *arg, char **val) { char *e; TkGeom g; int bd; TkOptab tko[3]; TkLabel *tkl = TKobj(TkLabel, tk); tko[0].ptr = tk; tko[0].optab = tkgeneric; tko[1].ptr = tkl; tko[1].optab = tklabelopts; tko[2].ptr = nil; if(*arg == '\0') return tkconflist(tko, val); g = tk->req; bd = tk->borderwidth; e = tkparse(tk->env->top, arg, tko, nil); tksizelabel(tk); tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd)); tkgeomchg(tk, &g, bd); tk->dirty = tkrect(tk, 1); return e; }
static char* tkscrollset(Tk *tk, char *arg, char **val) { TkTop *t; char *e; TkScroll *tks = TKobj(TkScroll, tk); USED(val); t = tk->env->top; e = tkfracword(t, &arg, &tks->top, nil); if (e != nil) return e; e = tkfracword(t, &arg, &tks->bot, nil); if (e != nil) return e; if(tks->top < 0) tks->top = 0; if(tks->top > TKI2F(1)) tks->top = TKI2F(1); if(tks->bot < 0) tks->bot = 0; if(tks->bot > TKI2F(1)) tks->bot = TKI2F(1); tk->dirty = tkrect(tk, 1); return nil; }
static char* tkcvscanvy(Tk *tk, char *arg, char **val) { int y, s; TkCanvas *c; Point p; char buf[Tkmaxitem]; c = TKobj(TkCanvas, tk); arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); if(buf[0] == '\0') return TkBadvl; p = tkposn(tk); y = atoi(buf) + c->view.y - (p.y + tk->borderwidth); if(*arg) { tkitem(buf, arg); s = atoi(buf); if (s) { if (y>=0) y = ((y+s/2)/s)*s; else y = ((y-s/2)/s)*s; } } return tkvalue(val, "%d", y); }
static char* tkscrollfraction(Tk *tk, char *arg, char **val) { int len, frac, pos; char buf[Tkmaxitem]; TkScroll *tks = TKobj(TkScroll, tk); arg = tkitem(buf, arg); if(tks->orient == Tkvertical) tkitem(buf, arg); if(*arg == '\0' || *buf == '\0') return TkBadvl; pos = atoi(buf); if(pos < tks->a1) pos = tks->a1; if(pos > tks->a2) pos = tks->a2; len = tks->a2 - tks->a1 - 4*Elembw; frac = TKI2F(1); if(len != 0) frac = TKI2F(pos-tks->a1)/len; tkfprint(buf, frac); return tkvalue(val, "%s", buf); }
static char* tkcvslower(Tk *tk, char *arg, char **val) { TkCtag *t; TkCanvas *c; TkName *f, *b; char buf[Tkmaxitem]; TkCitem *it, **l, **below, *items, **itemtail, *prev, *iprev; USED(val); c = TKobj(TkCanvas, tk); arg = tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); f = tkctaglook(tk, nil, buf); if(f == nil || f->obj == nil) return nil; below = &c->head; tkword(tk->env->top, arg, buf, buf+sizeof(buf), nil); if(buf[0] != '\0') { b = tkctaglook(tk, nil, buf); if(b == nil || f->obj == nil) return TkBadtg; for(it = c->head; it; it = it->next) { for(t = b->obj; t; t = t->taglist) if(t->item == it) goto found; below = &it->next; } found:; } l = &c->head; prev = iprev = nil; itemtail = &items;; for (it = *l; it != nil; it = *l) { for (t = f->obj; t; t = t->taglist) { if(t->item == it) { if (it == *below || below == &it->next) below = l; if (it == c->tail) c->tail = prev; *l = it->next; *itemtail = it; iprev = it; itemtail = &it->next; tkbbmax(&c->update, &it->p.bb); goto next; } } prev = it; l = &it->next; next:; } if (prev == nil) c->tail = iprev; *itemtail = *below; *below = items; tkcvssetdirty(tk); return nil; }
static char* tkinitscroll(Tk *tk) { int gap; TkScroll *tks; tks = TKobj(TkScroll, tk); gap = 2*tk->borderwidth; if(tks->orient == Tkvertical) { if(tk->req.width == 0) tk->req.width = Triangle + gap; if(tk->req.height == 0) tk->req.height = 2*Triangle + gap + 6*Elembw; } else { if(tk->req.width == 0) tk->req.width = 2*Triangle + gap + 6*Elembw; if(tk->req.height == 0) tk->req.height = Triangle + gap; } return tkbindings(tk->env->top, tk, b, nelem(b)); }
void tkcvssh(Tk *tk) { int top, bot, width; TkCanvas *c = TKobj(TkCanvas, tk); char val[Tkminitem], cmd[Tkmaxitem], *v, *e; if(c->xscroll == nil) return; top = 0; bot = TKI2F(1); width = Dx(c->region); if(width != 0) { top = TKI2F(c->view.x)/width; bot = TKI2F(c->view.x+tk->act.width)/width; } v = tkfprint(val, top); *v++ = ' '; tkfprint(v, bot); snprint(cmd, sizeof(cmd), "%s %s", c->xscroll, val); e = tkexec(tk->env->top, cmd, nil); if ((e != nil) && (tk->name != nil)) print("tk: xscrollcommand \"%s\": %s\n", tk->name->name, e); }
static int tkscalecheckvalue(Tk *tk) { int v; TkScale *tks = TKobj(TkScale, tk); int limit = 1; v = tks->value; if (tks->res > 0) v = (v / tks->res) * tks->res; if (tks->to >= tks->from) { if (v < tks->from) v = tks->from; else if (v > tks->to) v = tks->to; else limit = 0; } else { if (v < tks->to) v = tks->to; else if (v > tks->from) v = tks->from; else limit = 0; } /* * it's possible for the value to end up as a non-whole * multiple of resolution here, if the end points aren't * themselves such a multiple. if so, tough - that's * what you asked for! (it does mean that the endpoints * are always accessible however, which could be a good thing). */ tks->value = v; return limit; }
static char* tkscalecoords(Tk *tk, char *arg, char **val) { int p, x, y, l, value; TkScale *tks = TKobj(TkScale, tk); char *e; value = tks->value; if(arg != nil && arg[0] != '\0') { e = tkfracword(tk->env->top, &arg, &value, tk->env); if (e != nil) return e; } value -= tks->from; p = tks->pixmax - tks->pixmin; l = TKF2I(tks->to-tks->from); if (l==0) p /= 2; else p = TKF2I(value*p/l); p += tks->pixmin; if(tks->orient == Tkvertical) { x = tks->center; y = p; } else { x = p; y = tks->center; } return tkvalue(val, "%d %d", x, y); }
static char* stepscale(Tk *tk, char *pos, int *end) { TkScale *tks = TKobj(TkScale, tk); char *e, buf[Tkmaxitem], f[32]; int s; s = sgn(tks->to - tks->from); if(pos == trough1) { tks->value -= s * tks->bigi; } else { /* trough2 */ tks->value += s * tks->bigi; } s = !tkscalecheckvalue(tk); if (end != nil) *end = s; e = nil; if(tks->command != nil) { /* XXX perhaps should only send command if value has actually changed */ tkfprint(f, tks->value); snprint(buf, sizeof(buf), "%s %s", tks->command, f); e = tkexec(tk->env->top, buf, nil); } return e; }
int tkcvstextsrch(TkCitem *i, int x, int y) { TkCtext *t; Font *font; Display *d; char *p, *next; int n, len, locked; t = TKobj(TkCtext, i); n = 0; font = i->env->font; d = i->env->top->display; p = t->text; if(p == nil) return 0; while(*p) { next = tkcvstextgetl(t, font, p, &len); if(y <= font->height) { locked = lockdisplay(d); for(n = 0; n < len && x > stringnwidth(font, p, n+1); n++) ; if(locked) unlockdisplay(d); break; } y -= font->height; p = next; } return p - t->text + n; }
static char* tkentryb1p(Tk *tk, char* arg, char **ret) { TkEntry *tke = TKobj(TkEntry, tk); Point p; int i, locked, x; char buf[32], *e; USED(ret); x = atoi(arg); p = tkscrn2local(tk, Pt(x, 0)); sprint(buf, "@%d", p.x); e = tkentryparseindex(tk, buf, &i); if (e != nil) return e; tke->sel0 = 0; tke->sel1 = 0; tke->icursor = i; tke->anchor = i; tke->flag &= ~Ewordsel; locked = lockdisplay(tk->env->top->display); tke->xsel0 = 0; tke->xsel1 = 0; tke->xicursor = entrytextwidth(tk, tke->icursor); if (locked) unlockdisplay(tk->env->top->display); tke->oldx = x; blinkreset(tk); tkrepeat(tk, autoselect, nil, TkRptpause, TkRptinterval); tk->dirty = tkrect(tk, 0); return nil; }