+void
+configurerequest(XEvent *e) {
+ Client *c;
+ XConfigureRequestEvent *ev = &e->xconfigurerequest;
+ XWindowChanges wc;
+
+ if((c = getclient(ev->window))) {
+ Monitor *m = &monitors[c->monitor];
+ if(ev->value_mask & CWBorderWidth)
+ c->border = ev->border_width;
+ if(c->isfixed || c->isfloating || (floating == m->layout->arrange)) {
+ if(ev->value_mask & CWX)
+ c->x = m->sx+ev->x;
+ if(ev->value_mask & CWY)
+ c->y = m->sy+ev->y;
+ if(ev->value_mask & CWWidth)
+ c->w = ev->width;
+ if(ev->value_mask & CWHeight)
+ c->h = ev->height;
+ if((c->x - m->sx + c->w) > m->sw && c->isfloating)
+ c->x = m->sx + (m->sw / 2 - c->w / 2); /* center in x direction */
+ if((c->y - m->sy + c->h) > m->sh && c->isfloating)
+ c->y = m->sy + (m->sh / 2 - c->h / 2); /* center in y direction */
+ if((ev->value_mask & (CWX | CWY))
+ && !(ev->value_mask & (CWWidth | CWHeight)))
+ configure(c);
+ if(isvisible(c, monitorat()))
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
+ }
+ else
+ configure(c);
+ }
+ else {
+ wc.x = ev->x;
+ wc.y = ev->y;
+ wc.width = ev->width;
+ wc.height = ev->height;
+ wc.border_width = ev->border_width;
+ wc.sibling = ev->above;
+ wc.stack_mode = ev->detail;
+ XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
+ }
+ XSync(dpy, False);
+}
+
+void
+destroynotify(XEvent *e) {
+ Client *c;
+ XDestroyWindowEvent *ev = &e->xdestroywindow;
+
+ if((c = getclient(ev->window)))
+ unmanage(c);
+}
+
+void
+detach(Client *c) {
+ if(c->prev)
+ c->prev->next = c->next;
+ if(c->next)
+ c->next->prev = c->prev;
+ if(c == clients)
+ clients = c->next;
+ c->next = c->prev = NULL;
+}
+
+void
+detachstack(Client *c) {
+ Client **tc;
+
+ for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
+ *tc = c->snext;
+}
+
+void
+drawbar(void) {
+ int i, j, x;
+ Client *c;
+
+ for(i = 0; i < mcount; i++) {
+ Monitor *m = &monitors[i];
+ dc.x = 0;
+ for(c = stack; c && !isvisible(c, i); c = c->snext);
+ fprintf(stderr, "m%d %s\n", i, c ? c->name : "NIL");
+ for(j = 0; j < LENGTH(tags); j++) {
+ dc.w = textw(tags[j]);
+ if(m->seltags[j]) {
+ drawtext(m, tags[j], dc.sel, isurgent(i, j));
+ drawsquare(m, c && c->tags[j] && c->monitor == i,
+ isoccupied(i, j), isurgent(i, j), dc.sel);
+ }
+ else {
+ drawtext(m, tags[j], dc.norm, isurgent(i, j));
+ drawsquare(m, c && c->tags[j] && c->monitor == i,
+ isoccupied(i, j), isurgent(i, j), dc.norm);
+ }
+ dc.x += dc.w;
+ }
+ dc.w = blw;
+ drawtext(m, m->layout->symbol, dc.norm, False);
+ x = dc.x + dc.w;
+ if(i == selmonitor) {
+ dc.w = textw(stext);
+ dc.x = m->sw - dc.w;
+ if(dc.x < x) {
+ dc.x = x;
+ dc.w = m->sw - x;
+ }
+ drawtext(m, stext, dc.norm, False);
+ }
+ else
+ dc.x = m->sw;
+ if((dc.w = dc.x - x) > bh) {
+ dc.x = x;
+ if(c) {
+ drawtext(m, c->name, dc.sel, False);
+ drawsquare(m, False, c->isfloating, False, dc.sel);
+ }
+ else
+ drawtext(m, NULL, dc.norm, False);
+ }
+ XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->sw, bh, 0, 0);
+ XSync(dpy, False);
+ }
+}
+
+void
+drawsquare(Monitor *m, Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
+ int x;
+ XGCValues gcv;
+ XRectangle r = { dc.x, dc.y, dc.w, dc.h };
+
+ gcv.foreground = col[invert ? ColBG : ColFG];
+ XChangeGC(dpy, dc.gc, GCForeground, &gcv);
+ x = (dc.font.ascent + dc.font.descent + 2) / 4;
+ r.x = dc.x + 1;
+ r.y = dc.y + 1;
+ if(filled) {
+ r.width = r.height = x + 1;
+ XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
+ }
+ else if(empty) {
+ r.width = r.height = x;
+ XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
+ }
+}
+
+void
+drawtext(Monitor *m, const char *text, unsigned long col[ColLast], Bool invert) {
+ int x, y, w, h;
+ static char buf[256];
+ unsigned int len, olen;
+ XRectangle r = { dc.x, dc.y, dc.w, dc.h };