19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <thread.h>
49a747e4fSDavid du Colombier #include <draw.h>
59a747e4fSDavid du Colombier #include <mouse.h>
69a747e4fSDavid du Colombier #include <keyboard.h>
79a747e4fSDavid du Colombier #include <control.h>
89a747e4fSDavid du Colombier #include "group.h"
99a747e4fSDavid du Colombier
109a747e4fSDavid du Colombier static int debug = 0;
11*6f314b92SDavid du Colombier static int debugm = 0;
12*6f314b92SDavid du Colombier static int debugr = 0;
139a747e4fSDavid du Colombier
149a747e4fSDavid du Colombier enum{
159a747e4fSDavid du Colombier EAdd,
169a747e4fSDavid du Colombier EBorder,
179a747e4fSDavid du Colombier EBordercolor,
189a747e4fSDavid du Colombier EFocus,
199a747e4fSDavid du Colombier EHide,
209a747e4fSDavid du Colombier EImage,
219a747e4fSDavid du Colombier ERect,
229a747e4fSDavid du Colombier ERemove,
239a747e4fSDavid du Colombier EReveal,
249a747e4fSDavid du Colombier ESeparation,
259a747e4fSDavid du Colombier EShow,
269a747e4fSDavid du Colombier ESize,
279a747e4fSDavid du Colombier };
289a747e4fSDavid du Colombier
299a747e4fSDavid du Colombier static char *cmds[] = {
309a747e4fSDavid du Colombier [EAdd] = "add",
319a747e4fSDavid du Colombier [EBorder] = "border",
329a747e4fSDavid du Colombier [EBordercolor] = "bordercolor",
339a747e4fSDavid du Colombier [EFocus] = "focus",
349a747e4fSDavid du Colombier [EHide] = "hide",
359a747e4fSDavid du Colombier [EImage] = "image",
369a747e4fSDavid du Colombier [ERect] = "rect",
379a747e4fSDavid du Colombier [ERemove] = "remove",
389a747e4fSDavid du Colombier [EReveal] = "reveal",
399a747e4fSDavid du Colombier [ESeparation] = "separation",
409a747e4fSDavid du Colombier [EShow] = "show",
419a747e4fSDavid du Colombier [ESize] = "size",
429a747e4fSDavid du Colombier };
439a747e4fSDavid du Colombier
449a747e4fSDavid du Colombier static void boxboxresize(Group*, Rectangle);
459a747e4fSDavid du Colombier static void columnresize(Group*, Rectangle);
469a747e4fSDavid du Colombier static void groupctl(Control *c, CParse *cp);
479a747e4fSDavid du Colombier static void groupfree(Control*);
489a747e4fSDavid du Colombier static void groupmouse(Control *, Mouse *);
499a747e4fSDavid du Colombier static void groupsize(Control *c);
509a747e4fSDavid du Colombier static void removegroup(Group*, int);
519a747e4fSDavid du Colombier static void rowresize(Group*, Rectangle);
529a747e4fSDavid du Colombier static void stackresize(Group*, Rectangle);
539a747e4fSDavid du Colombier
549a747e4fSDavid du Colombier static void
groupinit(Group * g)559a747e4fSDavid du Colombier groupinit(Group *g)
569a747e4fSDavid du Colombier {
579a747e4fSDavid du Colombier g->bordercolor = _getctlimage("black");
589a747e4fSDavid du Colombier g->image = _getctlimage("white");
599a747e4fSDavid du Colombier g->border = 0;
609a747e4fSDavid du Colombier g->mansize = 0;
619a747e4fSDavid du Colombier g->separation = 0;
629a747e4fSDavid du Colombier g->selected = -1;
63*6f314b92SDavid du Colombier g->lastkid = -1;
649a747e4fSDavid du Colombier g->kids = nil;
659a747e4fSDavid du Colombier g->separators = nil;
669a747e4fSDavid du Colombier g->nkids = 0;
679a747e4fSDavid du Colombier g->nseparators = 0;
689a747e4fSDavid du Colombier g->ctl = groupctl;
699a747e4fSDavid du Colombier g->mouse = groupmouse;
709a747e4fSDavid du Colombier g->exit = groupfree;
719a747e4fSDavid du Colombier }
729a747e4fSDavid du Colombier
739a747e4fSDavid du Colombier static void
groupctl(Control * c,CParse * cp)749a747e4fSDavid du Colombier groupctl(Control *c, CParse *cp)
759a747e4fSDavid du Colombier {
769a747e4fSDavid du Colombier int cmd, i, n;
779a747e4fSDavid du Colombier
789a747e4fSDavid du Colombier Rectangle r;
799a747e4fSDavid du Colombier Group *g;
809a747e4fSDavid du Colombier
819a747e4fSDavid du Colombier g = (Group*)c;
829a747e4fSDavid du Colombier cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
839a747e4fSDavid du Colombier switch(cmd){
849a747e4fSDavid du Colombier case EAdd:
859a747e4fSDavid du Colombier for (i = 1; i < cp->nargs; i++){
869a747e4fSDavid du Colombier c = controlcalled(cp->args[i]);
879a747e4fSDavid du Colombier if (c == nil)
889a747e4fSDavid du Colombier ctlerror("%q: no such control: %s", g->name, cp->args[i]);
899a747e4fSDavid du Colombier _ctladdgroup(g, c);
909a747e4fSDavid du Colombier }
919a747e4fSDavid du Colombier if (g->setsize)
929a747e4fSDavid du Colombier g->setsize((Control*)g);
939a747e4fSDavid du Colombier break;
949a747e4fSDavid du Colombier case EBorder:
959a747e4fSDavid du Colombier _ctlargcount(g, cp, 2);
969a747e4fSDavid du Colombier if(cp->iargs[1] < 0)
979a747e4fSDavid du Colombier ctlerror("%q: bad border: %c", g->name, cp->str);
989a747e4fSDavid du Colombier g->border = cp->iargs[1];
999a747e4fSDavid du Colombier break;
1009a747e4fSDavid du Colombier case EBordercolor:
1019a747e4fSDavid du Colombier _ctlargcount(g, cp, 2);
1029a747e4fSDavid du Colombier _setctlimage(g, &g->bordercolor, cp->args[1]);
1039a747e4fSDavid du Colombier break;
1049a747e4fSDavid du Colombier case EFocus:
1059a747e4fSDavid du Colombier /* ignore focus change */
1069a747e4fSDavid du Colombier break;
1079a747e4fSDavid du Colombier case EHide:
1089a747e4fSDavid du Colombier _ctlargcount(g, cp, 1);
1099a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++)
1109a747e4fSDavid du Colombier if (g->kids[i]->ctl)
1119a747e4fSDavid du Colombier _ctlprint(g->kids[i], "hide");
1129a747e4fSDavid du Colombier g->hidden = 1;
1139a747e4fSDavid du Colombier break;
1149a747e4fSDavid du Colombier case EImage:
1159a747e4fSDavid du Colombier _ctlargcount(g, cp, 2);
1169a747e4fSDavid du Colombier _setctlimage(g, &g->image, cp->args[1]);
1179a747e4fSDavid du Colombier break;
1189a747e4fSDavid du Colombier case ERect:
1199a747e4fSDavid du Colombier _ctlargcount(g, cp, 5);
1209a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
1219a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
1229a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
1239a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
1249a747e4fSDavid du Colombier if(Dx(r)<=0 || Dy(r)<=0)
1259a747e4fSDavid du Colombier ctlerror("%q: bad rectangle: %s", g->name, cp->str);
1269a747e4fSDavid du Colombier g->rect = r;
1279a747e4fSDavid du Colombier r = insetrect(r, g->border);
1289a747e4fSDavid du Colombier if (g->nkids == 0)
1299a747e4fSDavid du Colombier return;
1309a747e4fSDavid du Colombier switch(g->type){
1319a747e4fSDavid du Colombier case Ctlboxbox:
1329a747e4fSDavid du Colombier boxboxresize(g, r);
1339a747e4fSDavid du Colombier break;
1349a747e4fSDavid du Colombier case Ctlcolumn:
1359a747e4fSDavid du Colombier columnresize(g, r);
1369a747e4fSDavid du Colombier break;
1379a747e4fSDavid du Colombier case Ctlrow:
1389a747e4fSDavid du Colombier rowresize(g, r);
1399a747e4fSDavid du Colombier break;
1409a747e4fSDavid du Colombier case Ctlstack:
1419a747e4fSDavid du Colombier stackresize(g, r);
1429a747e4fSDavid du Colombier break;
1439a747e4fSDavid du Colombier }
1449a747e4fSDavid du Colombier break;
1459a747e4fSDavid du Colombier case ERemove:
1469a747e4fSDavid du Colombier _ctlargcount(g, cp, 2);
1479a747e4fSDavid du Colombier for (n = 0; n < g->nkids; n++)
1489a747e4fSDavid du Colombier if (strcmp(cp->args[1], g->kids[n]->name) == 0)
1499a747e4fSDavid du Colombier break;
1509a747e4fSDavid du Colombier if (n == g->nkids)
1519a747e4fSDavid du Colombier ctlerror("%s: remove nonexistent control: %q", g->name, cp->args[1]);
1529a747e4fSDavid du Colombier removegroup(g, n);
1539a747e4fSDavid du Colombier if (g->setsize)
1549a747e4fSDavid du Colombier g->setsize((Control*)g);
1559a747e4fSDavid du Colombier break;
1569a747e4fSDavid du Colombier case EReveal:
1579a747e4fSDavid du Colombier g->hidden = 0;
158*6f314b92SDavid du Colombier if (debugr) fprint(2, "reveal %s\n", g->name);
1599a747e4fSDavid du Colombier if (g->type == Ctlstack){
1609a747e4fSDavid du Colombier if (cp->nargs == 2){
1619a747e4fSDavid du Colombier if (cp->iargs[1] < 0 || cp->iargs[1] >= g->nkids)
1629a747e4fSDavid du Colombier ctlerror("%s: control out of range: %q", g->name, cp->str);
1639a747e4fSDavid du Colombier g->selected = cp->iargs[1];
1649a747e4fSDavid du Colombier }else
1659a747e4fSDavid du Colombier _ctlargcount(g, cp, 1);
1669a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++)
1679a747e4fSDavid du Colombier if (g->kids[i]->ctl){
1689a747e4fSDavid du Colombier if (g->selected == i){
169*6f314b92SDavid du Colombier if (debugr) fprint(2, "reveal %s: reveal kid %s\n", g->name, g->kids[i]->name);
1709a747e4fSDavid du Colombier _ctlprint(g->kids[i], "reveal");
1719a747e4fSDavid du Colombier }else{
172*6f314b92SDavid du Colombier if (debugr) fprint(2, "reveal %s: hide kid %s\n", g->name, g->kids[i]->name);
1739a747e4fSDavid du Colombier _ctlprint(g->kids[i], "hide");
1749a747e4fSDavid du Colombier }
1759a747e4fSDavid du Colombier }
1769a747e4fSDavid du Colombier break;
1779a747e4fSDavid du Colombier }
1789a747e4fSDavid du Colombier _ctlargcount(g, cp, 1);
1799a747e4fSDavid du Colombier if (debug) fprint(2, "reveal %s: border %R/%d\n", g->name, g->rect, g->border);
1809a747e4fSDavid du Colombier border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min);
1819a747e4fSDavid du Colombier r = insetrect(g->rect, g->border);
1829a747e4fSDavid du Colombier if (debug) fprint(2, "reveal %s: draw %R\n", g->name, r);
1839a747e4fSDavid du Colombier draw(g->screen, r, g->image->image, nil, g->image->image->r.min);
1849a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++)
1859a747e4fSDavid du Colombier if (g->kids[i]->ctl)
1869a747e4fSDavid du Colombier _ctlprint(g->kids[i], "reveal");
1879a747e4fSDavid du Colombier break;
1889a747e4fSDavid du Colombier case EShow:
1899a747e4fSDavid du Colombier _ctlargcount(g, cp, 1);
1909a747e4fSDavid du Colombier if (g->hidden)
1919a747e4fSDavid du Colombier break;
1929a747e4fSDavid du Colombier // pass it on to the kiddies
1939a747e4fSDavid du Colombier if (debug) fprint(2, "show %s: border %R/%d\n", g->name, g->rect, g->border);
1949a747e4fSDavid du Colombier border(g->screen, g->rect, g->border, g->bordercolor->image, g->bordercolor->image->r.min);
1959a747e4fSDavid du Colombier r = insetrect(g->rect, g->border);
1969a747e4fSDavid du Colombier if (debug) fprint(2, "show %s: draw %R\n", g->name, r);
1979a747e4fSDavid du Colombier draw(g->screen, r, g->image->image, nil, g->image->image->r.min);
1989a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++)
1999a747e4fSDavid du Colombier if (g->kids[i]->ctl){
2009a747e4fSDavid du Colombier if (debug) fprint(2, "show %s: kid %s: %q\n", g->name, g->kids[i]->name, cp->str);
2019a747e4fSDavid du Colombier _ctlprint(g->kids[i], "show");
2029a747e4fSDavid du Colombier }
2039a747e4fSDavid du Colombier flushimage(display, 1);
2049a747e4fSDavid du Colombier break;
2059a747e4fSDavid du Colombier case ESize:
2069a747e4fSDavid du Colombier r.max = Pt(_Ctlmaxsize, _Ctlmaxsize);
2079a747e4fSDavid du Colombier if (g->type == Ctlboxbox)
2089a747e4fSDavid du Colombier _ctlargcount(g, cp, 5);
2099a747e4fSDavid du Colombier switch(cp->nargs){
2109a747e4fSDavid du Colombier default:
2119a747e4fSDavid du Colombier ctlerror("%s: args of %q", g->name, cp->str);
2129a747e4fSDavid du Colombier case 1:
2139a747e4fSDavid du Colombier /* recursively set size */
2149a747e4fSDavid du Colombier g->mansize = 0;
2159a747e4fSDavid du Colombier if (g->setsize)
2169a747e4fSDavid du Colombier g->setsize((Control*)g);
2179a747e4fSDavid du Colombier break;
2189a747e4fSDavid du Colombier case 5:
2199a747e4fSDavid du Colombier _ctlargcount(g, cp, 5);
2209a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
2219a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
2229a747e4fSDavid du Colombier /* fall through */
2239a747e4fSDavid du Colombier case 3:
2249a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
2259a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
2269a747e4fSDavid du Colombier if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)
2279a747e4fSDavid du Colombier ctlerror("%q: bad sizes: %s", g->name, cp->str);
2289a747e4fSDavid du Colombier g->size = r;
2299a747e4fSDavid du Colombier g->mansize = 1;
2309a747e4fSDavid du Colombier break;
2319a747e4fSDavid du Colombier }
2329a747e4fSDavid du Colombier break;
2339a747e4fSDavid du Colombier case ESeparation:
2349a747e4fSDavid du Colombier if (g->type != Ctlstack){
2359a747e4fSDavid du Colombier _ctlargcount(g, cp, 2);
2369a747e4fSDavid du Colombier if(cp->iargs[1] < 0)
2379a747e4fSDavid du Colombier ctlerror("%q: illegal value: %c", g->name, cp->str);
2389a747e4fSDavid du Colombier g->separation = cp->iargs[1];
2399a747e4fSDavid du Colombier break;
2409a747e4fSDavid du Colombier }
2419a747e4fSDavid du Colombier // fall through for Ctlstack
2429a747e4fSDavid du Colombier default:
2439a747e4fSDavid du Colombier ctlerror("%q: unrecognized message '%s'", g->name, cp->str);
2449a747e4fSDavid du Colombier break;
2459a747e4fSDavid du Colombier }
2469a747e4fSDavid du Colombier }
2479a747e4fSDavid du Colombier
2489a747e4fSDavid du Colombier static void
groupfree(Control * c)2499a747e4fSDavid du Colombier groupfree(Control *c)
2509a747e4fSDavid du Colombier {
2519a747e4fSDavid du Colombier Group *g;
2529a747e4fSDavid du Colombier
2539a747e4fSDavid du Colombier g = (Group*)c;
2549a747e4fSDavid du Colombier _putctlimage(g->bordercolor);
2559a747e4fSDavid du Colombier free(g->kids);
2569a747e4fSDavid du Colombier }
2579a747e4fSDavid du Colombier
2589a747e4fSDavid du Colombier static void
groupmouse(Control * c,Mouse * m)2599a747e4fSDavid du Colombier groupmouse(Control *c, Mouse *m)
2609a747e4fSDavid du Colombier {
2619a747e4fSDavid du Colombier Group *g;
262*6f314b92SDavid du Colombier int i, lastkid;
2639a747e4fSDavid du Colombier
2649a747e4fSDavid du Colombier g = (Group*)c;
2659a747e4fSDavid du Colombier if (g->type == Ctlstack){
266*6f314b92SDavid du Colombier i = g->selected;
267*6f314b92SDavid du Colombier if (i >= 0 && g->kids[i]->mouse &&
268*6f314b92SDavid du Colombier ( ( ((m->buttons == 0) || (g->lastbut == 0)) &&
269*6f314b92SDavid du Colombier ptinrect(m->xy, g->kids[i]->rect) ) ||
270*6f314b92SDavid du Colombier ( ((m->buttons != 0) || (g->lastbut != 0)) &&
271*6f314b92SDavid du Colombier (g->lastkid == i) ) ) ) {
272*6f314b92SDavid du Colombier if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n",
273*6f314b92SDavid du Colombier g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut,
274*6f314b92SDavid du Colombier ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0);
275*6f314b92SDavid du Colombier (g->kids[i]->mouse)(g->kids[i], m);
276*6f314b92SDavid du Colombier g->lastkid = i;
277*6f314b92SDavid du Colombier g->lastbut = m->buttons;
278*6f314b92SDavid du Colombier } else {
279*6f314b92SDavid du Colombier if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n",
280*6f314b92SDavid du Colombier g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut,
281*6f314b92SDavid du Colombier ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0);
2829a747e4fSDavid du Colombier }
2839a747e4fSDavid du Colombier return;
2849a747e4fSDavid du Colombier }
2859a747e4fSDavid du Colombier
286*6f314b92SDavid du Colombier lastkid = -1;
287*6f314b92SDavid du Colombier for(i=0; i<g->nkids; i++) {
288*6f314b92SDavid du Colombier if(g->kids[i]->mouse &&
289*6f314b92SDavid du Colombier ( ( ((m->buttons == 0) || (g->lastbut == 0)) &&
290*6f314b92SDavid du Colombier ptinrect(m->xy, g->kids[i]->rect) ) ||
291*6f314b92SDavid du Colombier ( ((m->buttons != 0) || (g->lastbut != 0)) &&
292*6f314b92SDavid du Colombier (g->lastkid == i) ) ) ) {
293*6f314b92SDavid du Colombier if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n",
294*6f314b92SDavid du Colombier g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut,
295*6f314b92SDavid du Colombier ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0);
2969a747e4fSDavid du Colombier (g->kids[i]->mouse)(g->kids[i], m);
297*6f314b92SDavid du Colombier lastkid = i;
298*6f314b92SDavid du Colombier } else {
299*6f314b92SDavid du Colombier if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n",
300*6f314b92SDavid du Colombier g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut,
301*6f314b92SDavid du Colombier ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0);
3029a747e4fSDavid du Colombier }
303*6f314b92SDavid du Colombier }
304*6f314b92SDavid du Colombier g->lastkid = lastkid;
305*6f314b92SDavid du Colombier g->lastbut = m->buttons;
3069a747e4fSDavid du Colombier
3079a747e4fSDavid du Colombier #ifdef notdef
3089a747e4fSDavid du Colombier if(m->buttons == 0){
3099a747e4fSDavid du Colombier /* buttons now up */
3109a747e4fSDavid du Colombier g->lastbut = 0;
3119a747e4fSDavid du Colombier return;
3129a747e4fSDavid du Colombier }
3139a747e4fSDavid du Colombier if(g->lastbut == 0 && m->buttons != 0){
3149a747e4fSDavid du Colombier /* button went down, start tracking border */
3159a747e4fSDavid du Colombier switch(g->stacking){
3169a747e4fSDavid du Colombier default:
3179a747e4fSDavid du Colombier return;
3189a747e4fSDavid du Colombier case Vertical:
3199a747e4fSDavid du Colombier p = Pt(m->xy.x, middle_of_border.y);
3209a747e4fSDavid du Colombier p0 = Pt(g->r.min.x, m->xy.y);
3219a747e4fSDavid du Colombier p1 = Pt(g->r.max.x, m->xy.y);
3229a747e4fSDavid du Colombier break;
3239a747e4fSDavid du Colombier case Horizontal:
3249a747e4fSDavid du Colombier p = Pt(middle_of_border.x, m->xy.y);
3259a747e4fSDavid du Colombier p0 = Pt(m->xy.x, g->r.min.y);
3269a747e4fSDavid du Colombier p1 = Pt(m->xy.x, g->r.max.y);
3279a747e4fSDavid du Colombier break;
3289a747e4fSDavid du Colombier }
3299a747e4fSDavid du Colombier // setcursor();
3309a747e4fSDavid du Colombier oi = nil;
3319a747e4fSDavid du Colombier } else if (g->lastbut != 0 && s->m.buttons != 0){
3329a747e4fSDavid du Colombier /* button is down, keep tracking border */
3339a747e4fSDavid du Colombier if(!eqpt(s->m.xy, p)){
3349a747e4fSDavid du Colombier p = onscreen(s->m.xy);
3359a747e4fSDavid du Colombier r = canonrect(Rpt(p0, p));
3369a747e4fSDavid du Colombier if(Dx(r)>5 && Dy(r)>5){
3379a747e4fSDavid du Colombier i = allocwindow(wscreen, r, Refnone, 0xEEEEEEFF); /* grey */
3389a747e4fSDavid du Colombier freeimage(oi);
3399a747e4fSDavid du Colombier if(i == nil)
3409a747e4fSDavid du Colombier goto Rescue;
3419a747e4fSDavid du Colombier oi = i;
3429a747e4fSDavid du Colombier border(i, r, Selborder, red, ZP);
3439a747e4fSDavid du Colombier flushimage(display, 1);
3449a747e4fSDavid du Colombier }
3459a747e4fSDavid du Colombier }
3469a747e4fSDavid du Colombier } else if (g->lastbut != 0 && s->m.buttons == 0){
3479a747e4fSDavid du Colombier /* button went up, resize kiddies */
3489a747e4fSDavid du Colombier }
3499a747e4fSDavid du Colombier g->lastbut = s->m.buttons;
3509a747e4fSDavid du Colombier #endif
3519a747e4fSDavid du Colombier }
3529a747e4fSDavid du Colombier
3539a747e4fSDavid du Colombier static void
activategroup(Control * c,int act)3549a747e4fSDavid du Colombier activategroup(Control *c, int act)
3559a747e4fSDavid du Colombier {
3569a747e4fSDavid du Colombier int i;
3579a747e4fSDavid du Colombier Group *g;
3589a747e4fSDavid du Colombier
3599a747e4fSDavid du Colombier g = (Group*)c;
3609a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++)
3619a747e4fSDavid du Colombier if (act)
3629a747e4fSDavid du Colombier activate(g->kids[i]);
3639a747e4fSDavid du Colombier else
3649a747e4fSDavid du Colombier deactivate(g->kids[i]);
3659a747e4fSDavid du Colombier }
3669a747e4fSDavid du Colombier
3679a747e4fSDavid du Colombier Control *
createrow(Controlset * cs,char * name)3689a747e4fSDavid du Colombier createrow(Controlset *cs, char *name)
3699a747e4fSDavid du Colombier {
3709a747e4fSDavid du Colombier Control *c;
3719a747e4fSDavid du Colombier c = _createctl(cs, "row", sizeof(Group), name);
3729a747e4fSDavid du Colombier groupinit((Group*)c);
3739a747e4fSDavid du Colombier c->setsize = groupsize;
3749a747e4fSDavid du Colombier c->activate = activategroup;
3759a747e4fSDavid du Colombier return c;
3769a747e4fSDavid du Colombier }
3779a747e4fSDavid du Colombier
3789a747e4fSDavid du Colombier Control *
createcolumn(Controlset * cs,char * name)3799a747e4fSDavid du Colombier createcolumn(Controlset *cs, char *name)
3809a747e4fSDavid du Colombier {
3819a747e4fSDavid du Colombier Control *c;
3829a747e4fSDavid du Colombier c = _createctl(cs, "column", sizeof(Group), name);
3839a747e4fSDavid du Colombier groupinit((Group*)c);
3849a747e4fSDavid du Colombier c->setsize = groupsize;
3859a747e4fSDavid du Colombier c->activate = activategroup;
3869a747e4fSDavid du Colombier return c;
3879a747e4fSDavid du Colombier }
3889a747e4fSDavid du Colombier
3899a747e4fSDavid du Colombier Control *
createboxbox(Controlset * cs,char * name)3909a747e4fSDavid du Colombier createboxbox(Controlset *cs, char *name)
3919a747e4fSDavid du Colombier {
3929a747e4fSDavid du Colombier Control *c;
3939a747e4fSDavid du Colombier c = _createctl(cs, "boxbox", sizeof(Group), name);
3949a747e4fSDavid du Colombier groupinit((Group*)c);
3959a747e4fSDavid du Colombier c->activate = activategroup;
3969a747e4fSDavid du Colombier return c;
3979a747e4fSDavid du Colombier }
3989a747e4fSDavid du Colombier
3999a747e4fSDavid du Colombier Control *
createstack(Controlset * cs,char * name)4009a747e4fSDavid du Colombier createstack(Controlset *cs, char *name)
4019a747e4fSDavid du Colombier {
4029a747e4fSDavid du Colombier Control *c;
4039a747e4fSDavid du Colombier c = _createctl(cs, "stack", sizeof(Group), name);
4049a747e4fSDavid du Colombier groupinit((Group*)c);
4059a747e4fSDavid du Colombier c->setsize = groupsize;
4069a747e4fSDavid du Colombier return c;
4079a747e4fSDavid du Colombier }
4089a747e4fSDavid du Colombier
4099a747e4fSDavid du Colombier void
_ctladdgroup(Control * c,Control * q)4109a747e4fSDavid du Colombier _ctladdgroup(Control *c, Control *q)
4119a747e4fSDavid du Colombier {
4129a747e4fSDavid du Colombier Group *g = (Group*)c;
4139a747e4fSDavid du Colombier
4149a747e4fSDavid du Colombier g->kids = ctlrealloc(g->kids, sizeof(Group*)*(g->nkids+1));
4159a747e4fSDavid du Colombier g->kids[g->nkids++] = q;
4169a747e4fSDavid du Colombier }
4179a747e4fSDavid du Colombier
4189a747e4fSDavid du Colombier static void
removegroup(Group * g,int n)4199a747e4fSDavid du Colombier removegroup(Group *g, int n)
4209a747e4fSDavid du Colombier {
4219a747e4fSDavid du Colombier int i;
4229a747e4fSDavid du Colombier
4239a747e4fSDavid du Colombier if (g->selected == n)
4249a747e4fSDavid du Colombier g->selected = -1;
4259a747e4fSDavid du Colombier else if (g->selected > n)
4269a747e4fSDavid du Colombier g->selected--;
4279a747e4fSDavid du Colombier
4289a747e4fSDavid du Colombier for (i = n+1; i < g->nkids; i++)
4299a747e4fSDavid du Colombier g->kids[i-1] = g->kids[i];
4309a747e4fSDavid du Colombier g->nkids--;
4319a747e4fSDavid du Colombier }
4329a747e4fSDavid du Colombier
4339a747e4fSDavid du Colombier static void
groupsize(Control * c)4349a747e4fSDavid du Colombier groupsize(Control *c)
4359a747e4fSDavid du Colombier {
4369a747e4fSDavid du Colombier Rectangle r;
4379a747e4fSDavid du Colombier int i;
4389a747e4fSDavid du Colombier Control *q;
4399a747e4fSDavid du Colombier Group *g;
4409a747e4fSDavid du Colombier
4419a747e4fSDavid du Colombier g = (Group*)c;
4429a747e4fSDavid du Colombier assert(g->type == Ctlcolumn || g->type == Ctlrow || g->type == Ctlstack);
4439a747e4fSDavid du Colombier if (g->mansize) return;
4449a747e4fSDavid du Colombier r = Rect(1, 1, 1, 1);
4459a747e4fSDavid du Colombier if (debug) fprint(2, "groupsize %q\n", g->name);
4469a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++){
4479a747e4fSDavid du Colombier q = g->kids[i];
4489a747e4fSDavid du Colombier if (q->setsize)
4499a747e4fSDavid du Colombier q->setsize(q);
4509a747e4fSDavid du Colombier if (q->size.min.x == 0 || q->size.min.y == 0 || q->size.max.x == 0 || q->size.max.y == 0)
4519a747e4fSDavid du Colombier ctlerror("%q: bad size %R", q->name, q->size);
4529a747e4fSDavid du Colombier if (debug) fprint(2, "groupsize %q: [%d %q]: %R\n", g->name, i, q->name, q->size);
4539a747e4fSDavid du Colombier switch(g->type){
4549a747e4fSDavid du Colombier case Ctlrow:
4559a747e4fSDavid du Colombier if (i)
4569a747e4fSDavid du Colombier r.min.x += q->size.min.x + g->border;
4579a747e4fSDavid du Colombier else
4589a747e4fSDavid du Colombier r.min.x = q->size.min.x;
4599a747e4fSDavid du Colombier if (i)
4609a747e4fSDavid du Colombier r.max.x += q->size.max.x + g->border;
4619a747e4fSDavid du Colombier else
4629a747e4fSDavid du Colombier r.max.x = q->size.max.x;
4639a747e4fSDavid du Colombier if (r.min.y < q->size.min.y) r.min.y = q->size.min.y;
4649a747e4fSDavid du Colombier if (r.max.y < q->size.max.y) r.max.y = q->size.max.y;
4659a747e4fSDavid du Colombier break;
4669a747e4fSDavid du Colombier case Ctlcolumn:
4679a747e4fSDavid du Colombier if (r.min.x < q->size.min.x) r.min.x = q->size.min.x;
4689a747e4fSDavid du Colombier if (r.max.x < q->size.max.x) r.max.x = q->size.max.x;
4699a747e4fSDavid du Colombier if (i)
4709a747e4fSDavid du Colombier r.min.y += q->size.min.y + g->border;
4719a747e4fSDavid du Colombier else
4729a747e4fSDavid du Colombier r.min.y = q->size.min.y;
4739a747e4fSDavid du Colombier if (i)
4749a747e4fSDavid du Colombier r.max.y += q->size.max.y + g->border;
4759a747e4fSDavid du Colombier else
4769a747e4fSDavid du Colombier r.max.y = q->size.max.y;
4779a747e4fSDavid du Colombier break;
4789a747e4fSDavid du Colombier case Ctlstack:
4799a747e4fSDavid du Colombier if (r.min.x < q->size.min.x) r.min.x = q->size.min.x;
4809a747e4fSDavid du Colombier if (r.max.x < q->size.max.x) r.max.x = q->size.max.x;
4819a747e4fSDavid du Colombier if (r.min.y < q->size.min.y) r.min.y = q->size.min.y;
4829a747e4fSDavid du Colombier if (r.max.y < q->size.max.y) r.max.y = q->size.max.y;
4839a747e4fSDavid du Colombier break;
4849a747e4fSDavid du Colombier }
4859a747e4fSDavid du Colombier }
4869a747e4fSDavid du Colombier g->size = rectaddpt(r, Pt(g->border, g->border));
4879a747e4fSDavid du Colombier if (debug) fprint(2, "groupsize %q: %R\n", g->name, g->size);
4889a747e4fSDavid du Colombier }
4899a747e4fSDavid du Colombier
4909a747e4fSDavid du Colombier static void
boxboxresize(Group * g,Rectangle r)4919a747e4fSDavid du Colombier boxboxresize(Group *g, Rectangle r)
4929a747e4fSDavid du Colombier {
4939a747e4fSDavid du Colombier int rows, cols, ht, wid, i, hpad, wpad;
4949a747e4fSDavid du Colombier Rectangle rr;
4959a747e4fSDavid du Colombier
4969a747e4fSDavid du Colombier if(debug) fprint(2, "boxboxresize %q %R (%d×%d) min/max %R separation %d\n", g->name, r, Dx(r), Dy(r), g->size, g->separation);
4979a747e4fSDavid du Colombier ht = 0;
4989a747e4fSDavid du Colombier for(i=0; i<g->nkids; i++){
4999a747e4fSDavid du Colombier if (g->kids[i]->size.min.y > ht)
5009a747e4fSDavid du Colombier ht = g->kids[i]->size.min.y;
5019a747e4fSDavid du Colombier }
5029a747e4fSDavid du Colombier if (ht == 0)
5039a747e4fSDavid du Colombier ctlerror("boxboxresize: height");
5049a747e4fSDavid du Colombier rows = Dy(r) / (ht+g->separation);
5059a747e4fSDavid du Colombier hpad = (Dy(r) % (ht+g->separation)) / g->nkids;
5069a747e4fSDavid du Colombier cols = (g->nkids+rows-1)/rows;
5079a747e4fSDavid du Colombier wid = Dx(r) / cols - g->separation;
5089a747e4fSDavid du Colombier for(i=0; i<g->nkids; i++){
5099a747e4fSDavid du Colombier if (g->kids[i]->size.max.x < wid)
5109a747e4fSDavid du Colombier wid = g->kids[i]->size.max.x;
5119a747e4fSDavid du Colombier }
5129a747e4fSDavid du Colombier for(i=0; i<g->nkids; i++){
5139a747e4fSDavid du Colombier if (g->kids[i]->size.min.x > wid)
5149a747e4fSDavid du Colombier wid = g->kids[i]->size.min.x;
5159a747e4fSDavid du Colombier }
5169a747e4fSDavid du Colombier if (wid > Dx(r) / cols)
5179a747e4fSDavid du Colombier ctlerror("can't fit controls in boxbox");
5189a747e4fSDavid du Colombier wpad = (Dx(r) % (wid+g->separation)) / g->nkids;
5199a747e4fSDavid du Colombier rr = rectaddpt(Rect(0,0,wid, ht), addpt(r.min, Pt(g->separation/2, g->separation/2)));
5209a747e4fSDavid du Colombier if(debug) fprint(2, "boxboxresize rows %d, cols %d, wid %d, ht %d, wpad %d, hpad %d\n", rows, cols, wid, ht, wpad, hpad);
5219a747e4fSDavid du Colombier for(i=0; i<g->nkids; i++){
5229a747e4fSDavid du Colombier if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, g->kids[i]->name, rr, Dx(rr), Dy(rr));
5239a747e4fSDavid du Colombier _ctlprint(g->kids[i], "rect %R",
5249a747e4fSDavid du Colombier rectaddpt(rr, Pt((wpad+wid+g->separation)*(i/rows), (hpad+ht+g->separation)*(i%rows))));
5259a747e4fSDavid du Colombier }
5269a747e4fSDavid du Colombier g->nseparators = rows + cols - 2;
5279a747e4fSDavid du Colombier g->separators = realloc(g->separators, g->nseparators*sizeof(Rectangle));
5289a747e4fSDavid du Colombier rr = r;
5299a747e4fSDavid du Colombier rr.max.y = rr.min.y + g->separation+hpad;
5309a747e4fSDavid du Colombier for (i = 1; i < rows; i++){
5319a747e4fSDavid du Colombier g->separators[i-1] = rectaddpt(rr, Pt(0, (hpad+ht+g->separation)*i-g->separation-hpad));
5329a747e4fSDavid du Colombier if(debug) fprint(2, "row separation %d [%d]: %R\n", i, i-1, rectaddpt(rr, Pt(0, (hpad+ht+g->separation)*i-g->separation)));
5339a747e4fSDavid du Colombier }
5349a747e4fSDavid du Colombier rr = r;
5359a747e4fSDavid du Colombier rr.max.x = rr.min.x + g->separation+wpad;
5369a747e4fSDavid du Colombier for (i = 1; i < cols; i++){
5379a747e4fSDavid du Colombier g->separators[i+rows-2] = rectaddpt(rr, Pt((wpad+wid+g->separation)*i-g->separation-wpad, 0));
5389a747e4fSDavid du Colombier if(debug) fprint(2, "col separation %d [%d]: %R\n", i, i+rows-2, rectaddpt(rr, Pt((wpad+wid+g->separation)*i-g->separation, 0)));
5399a747e4fSDavid du Colombier }
5409a747e4fSDavid du Colombier }
5419a747e4fSDavid du Colombier
5429a747e4fSDavid du Colombier static void
columnresize(Group * g,Rectangle r)5439a747e4fSDavid du Colombier columnresize(Group *g, Rectangle r)
5449a747e4fSDavid du Colombier {
5459a747e4fSDavid du Colombier int x, y, *d, *p, i, j, t;
5469a747e4fSDavid du Colombier Rectangle rr;
5479a747e4fSDavid du Colombier Control *q;
5489a747e4fSDavid du Colombier
5499a747e4fSDavid du Colombier x = Dx(r);
5509a747e4fSDavid du Colombier y = Dy(r);
5519a747e4fSDavid du Colombier if(debug) fprint(2, "columnresize %q %R (%d×%d) min/max %R separation %d\n", g->name, r, Dx(r), Dy(r), g->size, g->separation);
5529a747e4fSDavid du Colombier if (x < g->size.min.x) {
5539a747e4fSDavid du Colombier werrstr("resize %s: too narrow: need %d, have %d", g->name, g->size.min.x, x);
5549a747e4fSDavid du Colombier r.max.x = r.min.x + g->size.min.x;
5559a747e4fSDavid du Colombier }
5569a747e4fSDavid du Colombier if (y < g->size.min.y) {
5579a747e4fSDavid du Colombier werrstr("resize %s: too short: need %d, have %d", g->name, g->size.min.y, y);
5589a747e4fSDavid du Colombier r.max.y = r.min.y + g->size.min.y;
5599a747e4fSDavid du Colombier y = Dy(r);
5609a747e4fSDavid du Colombier }
5619a747e4fSDavid du Colombier d = ctlmalloc(g->nkids*sizeof(int));
5629a747e4fSDavid du Colombier p = ctlmalloc(g->nkids*sizeof(int));
5639a747e4fSDavid du Colombier if(debug) fprint(2, "kiddies: ");
5649a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++) {
5659a747e4fSDavid du Colombier q = g->kids[i];
5669a747e4fSDavid du Colombier if(debug) fprint(2, "[%q]: %d⋯%d\t", q->name, q->size.min.y, q->size.max.y);
5679a747e4fSDavid du Colombier d[i] = q->size.min.y;
5689a747e4fSDavid du Colombier y -= d[i];
5699a747e4fSDavid du Colombier p[i] = q->size.max.y - q->size.min.y;
5709a747e4fSDavid du Colombier }
5719a747e4fSDavid du Colombier if(debug) fprint(2, "\n");
5729a747e4fSDavid du Colombier y -= (g->nkids-1) * g->separation;
5739a747e4fSDavid du Colombier if(y < 0){
5749a747e4fSDavid du Colombier if (debug) fprint(2, "columnresize: y == %d\n", y);
5759a747e4fSDavid du Colombier y = 0;
5769a747e4fSDavid du Colombier }
5779a747e4fSDavid du Colombier if (y >= g->size.max.y - g->size.min.y) {
5789a747e4fSDavid du Colombier // all rects can be maximum width
5799a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++)
5809a747e4fSDavid du Colombier d[i] += p[i];
5819a747e4fSDavid du Colombier y -= g->size.max.y - g->size.min.y;
5829a747e4fSDavid du Colombier } else {
5839a747e4fSDavid du Colombier // rects can't be max width, divide up the rest
5849a747e4fSDavid du Colombier j = y;
5859a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++) {
5869a747e4fSDavid du Colombier t = p[i] * y/(g->size.max.y - g->size.min.y);
5879a747e4fSDavid du Colombier d[i] += t;
5889a747e4fSDavid du Colombier j -= t;
5899a747e4fSDavid du Colombier }
5909a747e4fSDavid du Colombier d[0] += j;
5919a747e4fSDavid du Colombier y = 0;
5929a747e4fSDavid du Colombier }
5939a747e4fSDavid du Colombier g->nseparators = g->nkids-1;
5949a747e4fSDavid du Colombier g->separators = realloc(g->separators, g->nseparators*sizeof(Rectangle));
5959a747e4fSDavid du Colombier j = 0;
5969a747e4fSDavid du Colombier rr = r;
5979a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++) {
5989a747e4fSDavid du Colombier q = g->kids[i];
5999a747e4fSDavid du Colombier if (i < g->nkids - 1){
6009a747e4fSDavid du Colombier g->separators[i].min.x = r.min.x;
6019a747e4fSDavid du Colombier g->separators[i].max.x = r.max.x;
6029a747e4fSDavid du Colombier }
6039a747e4fSDavid du Colombier t = y / (g->nkids - i);
6049a747e4fSDavid du Colombier y -= t;
6059a747e4fSDavid du Colombier j += t/2;
6069a747e4fSDavid du Colombier rr.min.y = r.min.y + j;
6079a747e4fSDavid du Colombier if (i)
6089a747e4fSDavid du Colombier g->separators[i-1].max.y = rr.min.y;
6099a747e4fSDavid du Colombier j += d[i];
6109a747e4fSDavid du Colombier rr.max.y = r.min.y + j;
6119a747e4fSDavid du Colombier if (i < g->nkids - 1)
6129a747e4fSDavid du Colombier g->separators[i].min.y = rr.max.y;
6139a747e4fSDavid du Colombier j += g->separation + t - t/2;
6149a747e4fSDavid du Colombier _ctlprint(q, "rect %R", rr);
6159a747e4fSDavid du Colombier if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, q->name, rr, Dx(rr), Dy(rr));
6169a747e4fSDavid du Colombier }
6179a747e4fSDavid du Colombier free(d);
6189a747e4fSDavid du Colombier free(p);
6199a747e4fSDavid du Colombier }
6209a747e4fSDavid du Colombier
6219a747e4fSDavid du Colombier static void
rowresize(Group * g,Rectangle r)6229a747e4fSDavid du Colombier rowresize(Group *g, Rectangle r)
6239a747e4fSDavid du Colombier {
6249a747e4fSDavid du Colombier int x, y, *d, *p, i, j, t;
6259a747e4fSDavid du Colombier Rectangle rr;
6269a747e4fSDavid du Colombier Control *q;
6279a747e4fSDavid du Colombier
6289a747e4fSDavid du Colombier x = Dx(r);
6299a747e4fSDavid du Colombier y = Dy(r);
6309a747e4fSDavid du Colombier if(debug) fprint(2, "rowresize %q %R (%d×%d), separation %d\n", g->name, r, Dx(r), Dy(r), g->separation);
6319a747e4fSDavid du Colombier if (x < g->size.min.x) {
6329a747e4fSDavid du Colombier werrstr("resize %s: too narrow: need %d, have %d", g->name, g->size.min.x, x);
6339a747e4fSDavid du Colombier r.max.x = r.min.x + g->size.min.x;
6349a747e4fSDavid du Colombier x = Dx(r);
6359a747e4fSDavid du Colombier }
6369a747e4fSDavid du Colombier if (y < g->size.min.y) {
6379a747e4fSDavid du Colombier werrstr("resize %s: too short: need %d, have %d", g->name, g->size.min.y, y);
6389a747e4fSDavid du Colombier r.max.y = r.min.y + g->size.min.y;
6399a747e4fSDavid du Colombier }
6409a747e4fSDavid du Colombier d = ctlmalloc(g->nkids*sizeof(int));
6419a747e4fSDavid du Colombier p = ctlmalloc(g->nkids*sizeof(int));
6429a747e4fSDavid du Colombier if(debug) fprint(2, "kiddies: ");
6439a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++) {
6449a747e4fSDavid du Colombier q = g->kids[i];
6459a747e4fSDavid du Colombier if(debug) fprint(2, "[%q]: %d⋯%d\t", q->name, q->size.min.x, q->size.max.x);
6469a747e4fSDavid du Colombier d[i] = q->size.min.x;
6479a747e4fSDavid du Colombier x -= d[i];
6489a747e4fSDavid du Colombier p[i] = q->size.max.x - q->size.min.x;
6499a747e4fSDavid du Colombier }
6509a747e4fSDavid du Colombier if(debug) fprint(2, "\n");
6519a747e4fSDavid du Colombier x -= (g->nkids-1) * g->separation;
6529a747e4fSDavid du Colombier if(x < 0){
6539a747e4fSDavid du Colombier if (debug) fprint(2, "rowresize: x == %d\n", x);
6549a747e4fSDavid du Colombier x = 0;
6559a747e4fSDavid du Colombier }
6569a747e4fSDavid du Colombier if (x >= g->size.max.x - g->size.min.x) {
6579a747e4fSDavid du Colombier if (debug) fprint(2, "max: %d > %d - %d", x, g->size.max.x, g->size.min.x);
6589a747e4fSDavid du Colombier // all rects can be maximum width
6599a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++)
6609a747e4fSDavid du Colombier d[i] += p[i];
6619a747e4fSDavid du Colombier x -= g->size.max.x - g->size.min.x;
6629a747e4fSDavid du Colombier } else {
6639a747e4fSDavid du Colombier if (debug) fprint(2, "divvie up: %d < %d - %d", x, g->size.max.x, g->size.min.x);
6649a747e4fSDavid du Colombier // rects can't be max width, divide up the rest
6659a747e4fSDavid du Colombier j = x;
6669a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++) {
6679a747e4fSDavid du Colombier t = p[i] * x/(g->size.max.x - g->size.min.x);
6689a747e4fSDavid du Colombier d[i] += t;
6699a747e4fSDavid du Colombier j -= t;
6709a747e4fSDavid du Colombier }
6719a747e4fSDavid du Colombier d[0] += j;
6729a747e4fSDavid du Colombier x = 0;
6739a747e4fSDavid du Colombier }
6749a747e4fSDavid du Colombier j = 0;
6759a747e4fSDavid du Colombier g->nseparators = g->nkids-1;
6769a747e4fSDavid du Colombier g->separators = realloc(g->separators, g->nseparators*sizeof(Rectangle));
6779a747e4fSDavid du Colombier rr = r;
6789a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++) {
6799a747e4fSDavid du Colombier q = g->kids[i];
6809a747e4fSDavid du Colombier if (i < g->nkids - 1){
6819a747e4fSDavid du Colombier g->separators[i].min.y = r.min.y;
6829a747e4fSDavid du Colombier g->separators[i].max.y = r.max.y;
6839a747e4fSDavid du Colombier }
6849a747e4fSDavid du Colombier t = x / (g->nkids - i);
6859a747e4fSDavid du Colombier x -= t;
6869a747e4fSDavid du Colombier j += t/2;
6879a747e4fSDavid du Colombier rr.min.x = r.min.x + j;
6889a747e4fSDavid du Colombier if (i)
6899a747e4fSDavid du Colombier g->separators[i-1].max.x = rr.min.x;
6909a747e4fSDavid du Colombier j += d[i];
6919a747e4fSDavid du Colombier rr.max.x = r.min.x + j;
6929a747e4fSDavid du Colombier if (i < g->nkids - 1)
6939a747e4fSDavid du Colombier g->separators[i].min.x = rr.max.x;
6949a747e4fSDavid du Colombier j += g->separation + t - t/2;
6959a747e4fSDavid du Colombier _ctlprint(q, "rect %R", rr);
6969a747e4fSDavid du Colombier if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, q->name, rr, Dx(rr), Dy(rr));
6979a747e4fSDavid du Colombier }
6989a747e4fSDavid du Colombier free(d);
6999a747e4fSDavid du Colombier free(p);
7009a747e4fSDavid du Colombier }
7019a747e4fSDavid du Colombier
7029a747e4fSDavid du Colombier static void
stackresize(Group * g,Rectangle r)7039a747e4fSDavid du Colombier stackresize(Group *g, Rectangle r)
7049a747e4fSDavid du Colombier {
7059a747e4fSDavid du Colombier int x, y, i;
7069a747e4fSDavid du Colombier Control *q;
7079a747e4fSDavid du Colombier
7089a747e4fSDavid du Colombier x = Dx(r);
7099a747e4fSDavid du Colombier y = Dy(r);
7109a747e4fSDavid du Colombier if(debug) fprint(2, "stackresize %q %R (%d×%d)\n", g->name, r, Dx(r), Dy(r));
7119a747e4fSDavid du Colombier if (x < g->size.min.x){
7129a747e4fSDavid du Colombier werrstr("resize %s: too narrow: need %d, have %d", g->name, g->size.min.x, x);
7139a747e4fSDavid du Colombier return;
7149a747e4fSDavid du Colombier }
7159a747e4fSDavid du Colombier if (y < g->size.min.y){
7169a747e4fSDavid du Colombier werrstr("resize %s: too short: need %d, have %d", g->name, g->size.min.y, y);
7179a747e4fSDavid du Colombier return;
7189a747e4fSDavid du Colombier }
7199a747e4fSDavid du Colombier if (x > g->size.max.x) {
7209a747e4fSDavid du Colombier x = (x - g->size.max.x)/2;
7219a747e4fSDavid du Colombier r.min.x += x;
7229a747e4fSDavid du Colombier r.max.x -= x;
7239a747e4fSDavid du Colombier }
7249a747e4fSDavid du Colombier if (y > g->size.max.y) {
7259a747e4fSDavid du Colombier y = (y - g->size.max.y)/2;
7269a747e4fSDavid du Colombier r.min.y += y;
7279a747e4fSDavid du Colombier r.max.y -= y;
7289a747e4fSDavid du Colombier }
7299a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++){
7309a747e4fSDavid du Colombier q = g->kids[i];
7319a747e4fSDavid du Colombier if(debug) fprint(2, " %d %q: %R (%d×%d)\n", i, q->name, r, Dx(r), Dy(r));
7329a747e4fSDavid du Colombier }
7339a747e4fSDavid du Colombier for (i = 0; i < g->nkids; i++){
7349a747e4fSDavid du Colombier q = g->kids[i];
7359a747e4fSDavid du Colombier _ctlprint(q, "rect %R", r);
7369a747e4fSDavid du Colombier }
7379a747e4fSDavid du Colombier }
738