t* dwm + patches
       
   URI git clone git://git.codevoid.de/dwm-sdk
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 39677ec76616fe4165ef92afb14db2bef2488e30
   DIR parent 8a34fa50f75f4d6d8af234ac0c4f6d40b988d700
   URI Author: Anselm R. Garbe <garbeam@wmii.de>
       Date:   Mon, 10 Jul 2006 19:46:24 +0200
       
       several new changes, made gridmenu working
       
       Diffstat:
         M Makefile                            |      14 ++++++++++----
         M config.h                            |       8 ++++----
         M draw.c                              |      41 ++++++++++++++++---------------
         M draw.h                              |      31 ++++++++++++++++++++++++++++++-
         M gridmenu.c                          |     239 +++++++++++++------------------
         M util.c                              |      59 +++++++++++++++++++++++++++++++
         M util.h                              |      47 ++++++++-----------------------
         M wm.c                                |      15 ++++++++++++---
         M wm.h                                |       8 ++++++--
       
       9 files changed, 256 insertions(+), 206 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       t@@ -5,10 +5,12 @@ include config.mk
        
        WMSRC = wm.c draw.c util.c
        WMOBJ = ${WMSRC:.c=.o}
       +MENSRC = gridmenu.c draw.c util.c
       +MENOBJ = ${MENSRC:.c=.o}
        MAN = gridwm.1
        BIN = gridwm gridmenu     
        
       -all: config gridwm
       +all: config gridwm gridmenu
                @echo finished
        
        config:
       t@@ -22,18 +24,22 @@ config:
                @echo CC $<
                @${CC} -c ${CFLAGS} $<
        
       -${WMOBJ}: wm.h draw.h config.h
       +${WMOBJ}: wm.h draw.h config.h util.h
       +
       +gridmenu: ${MENOBJ}
       +        @echo LD $@
       +        @${CC} -o $@ ${MENOBJ} ${LDFLAGS}
        
        gridwm: ${WMOBJ}
                @echo LD $@
                @${CC} -o $@ ${WMOBJ} ${LDFLAGS}
        
        clean:
       -        rm -f gridwm *.o
       +        rm -f gridwm gridmenu *.o core
        
        dist: clean
                mkdir -p gridwm-${VERSION}
       -        cp -R Makefile README LICENSE config.mk ${WMSRC} ${MAN} gridwm-${VERSION}
       +        cp -R Makefile README LICENSE config.mk *.h *.c ${MAN} gridwm-${VERSION}
                tar -cf gridwm-${VERSION}.tar gridwm-${VERSION}
                gzip gridwm-${VERSION}.tar
                rm -rf gridwm-${VERSION}
   DIR diff --git a/config.h b/config.h
       t@@ -3,7 +3,7 @@
         * See LICENSE file for license details.
         */
        
       -#define FONT        "fixed"
       -#define FGCOLOR        "#000000"
       -#define BGCOLOR        "#ffaa00"
       -#define BOCOLOR        "#000000"
       +#define FONT                "-*-terminus-medium-*-*-*-14-*-*-*-*-*-iso10646-*"
       +#define FGCOLOR                "#000000"
       +#define BGCOLOR                "#ffaa00"
       +#define BORDERCOLOR        "#000000"
   DIR diff --git a/draw.c b/draw.c
       t@@ -14,7 +14,7 @@ drawborder(Display *dpy, Brush *b)
        {
                XPoint points[5];
                XSetLineAttributes(dpy, b->gc, 1, LineSolid, CapButt, JoinMiter);
       -        XSetForeground(dpy, b->gc, b->color.border);
       +        XSetForeground(dpy, b->gc, b->border);
                points[0].x = b->rect.x;
                points[0].y = b->rect.y;
                points[1].x = b->rect.width - 1;
       t@@ -29,54 +29,54 @@ drawborder(Display *dpy, Brush *b)
        }
        
        void
       -draw(Display *dpy, Brush *b)
       +draw(Display *dpy, Brush *b, Bool border, const char *text)
        {
                unsigned int x, y, w, h, len;
                static char buf[256];
                XGCValues gcv;
        
       -        XSetForeground(dpy, b->gc, b->color.bg);
       +        XSetForeground(dpy, b->gc, b->bg);
                XFillRectangles(dpy, b->drawable, b->gc, &b->rect, 1);
        
       -        if(b->border)
       +        if(border)
                        drawborder(dpy, b);
        
       -        if(!b->text)
       +        if(!text)
                        return;
        
       -        len = strlen(b->text);
       +        len = strlen(text);
                if(len >= sizeof(buf))
                        len = sizeof(buf) - 1;
       -        memcpy(buf, b->text, len);
       +        memcpy(buf, text, len);
                buf[len] = 0;
        
       -        h = b->font->ascent + b->font->descent;
       -        y = b->rect.y + (b->rect.height / 2) - (h / 2) + b->font->ascent;
       +        h = b->font.ascent + b->font.descent;
       +        y = b->rect.y + (b->rect.height / 2) - (h / 2) + b->font.ascent;
                x = b->rect.x + (h / 2);
        
                /* shorten text if necessary */
       -        while(len && (w = textwidth_l(b->font, buf, len)) > b->rect.width - h)
       +        while(len && (w = textwidth_l(&b->font, buf, len)) > b->rect.width - h)
                        buf[--len] = 0;
        
                if(w > b->rect.width)
                        return; /* too long */
        
       -        gcv.foreground = b->color.fg;
       -        gcv.background = b->color.bg;
       -        if(b->font->set) {
       +        gcv.foreground = b->fg;
       +        gcv.background = b->bg;
       +        if(b->font.set) {
                        XChangeGC(dpy, b->gc, GCForeground | GCBackground, &gcv);
       -                XmbDrawImageString(dpy, b->drawable, b->font->set, b->gc,
       +                XmbDrawImageString(dpy, b->drawable, b->font.set, b->gc,
                                        x, y, buf, len);
                }
                else {
       -                gcv.font = b->font->xfont->fid;
       +                gcv.font = b->font.xfont->fid;
                        XChangeGC(dpy, b->gc, GCForeground | GCBackground | GCFont, &gcv);
                        XDrawImageString(dpy, b->drawable, b->gc, x, y, buf, len);
                }
        }
        
        static unsigned long
       -xloadcolor(Display *dpy, Colormap cmap, const char *colstr)
       +xloadcolors(Display *dpy, Colormap cmap, const char *colstr)
        {
                XColor color;
                XAllocNamedColor(dpy, cmap, colstr, &color, &color);
       t@@ -84,13 +84,13 @@ xloadcolor(Display *dpy, Colormap cmap, const char *colstr)
        }
        
        void
       -loadcolor(Display *dpy, int screen, Color *c,
       +loadcolors(Display *dpy, int screen, Brush *b,
                        const char *bg, const char *fg, const char *border)
        {
                Colormap cmap = DefaultColormap(dpy, screen);
       -        c->bg = xloadcolor(dpy, cmap, bg);
       -        c->fg = xloadcolor(dpy, cmap, fg);
       -        c->border = xloadcolor(dpy, cmap, border);
       +        b->bg = xloadcolors(dpy, cmap, bg);
       +        b->fg = xloadcolors(dpy, cmap, fg);
       +        b->border = xloadcolors(dpy, cmap, border);
        }
        
        unsigned int
       t@@ -160,4 +160,5 @@ loadfont(Display *dpy, Fnt *font, const char *fontstr)
                        font->ascent = font->xfont->ascent;
                        font->descent = font->xfont->descent;
                }
       +        font->height = font->ascent + font->descent;
        }
   DIR diff --git a/draw.h b/draw.h
       t@@ -3,4 +3,33 @@
         * See LICENSE file for license details.
         */
        
       -extern void error(char *errstr, ...);
       +#include <X11/Xlib.h>
       +#include <X11/Xlocale.h>
       +
       +typedef struct Brush Brush;
       +typedef struct Fnt Fnt;
       +
       +struct Fnt {
       +        XFontStruct *xfont;
       +        XFontSet set;
       +        int ascent;
       +        int descent;
       +        int height;
       +};
       +
       +struct Brush {
       +        GC gc;
       +        Drawable drawable;
       +        XRectangle rect;
       +        Fnt font;
       +        unsigned long bg;
       +        unsigned long fg;
       +        unsigned long border;
       +};
       +
       +extern void draw(Display *dpy, Brush *b, Bool border, const char *text);
       +extern void loadcolors(Display *dpy, int screen, Brush *b,
       +                const char *bg, const char *fg, const char *bo);
       +extern void loadfont(Display *dpy, Fnt *font, const char *fontstr);
       +extern unsigned int textwidth_l(Fnt *font, char *text, unsigned int len);
       +extern unsigned int textwidth(Fnt *font, char *text);
   DIR diff --git a/gridmenu.c b/gridmenu.c
       t@@ -4,6 +4,10 @@
         * See LICENSE file for license details.
         */
        
       +#include "config.h"
       +#include "draw.h"
       +#include "util.h"
       +
        #include <ctype.h>
        #include <stdlib.h>
        #include <stdio.h>
       t@@ -12,14 +16,10 @@
        #include <sys/wait.h>
        #include <time.h>
        #include <unistd.h>
       -#include <X11/Xlib.h>
        #include <X11/cursorfont.h>
        #include <X11/Xutil.h>
        #include <X11/keysym.h>
        
       -#include <blitz.h>
       -#include <cext.h>
       -
        typedef struct Item Item;
        
        struct Item {
       t@@ -28,37 +28,40 @@ struct Item {
                char *text;
        };
        
       -static char *title = nil;
       +static Display *dpy;
       +static Window root;
       +static Window win;
       +static XRectangle rect;
        static Bool done = False;
       -static int ret = 0;
       +
       +static Item *allitem = 0;        /* first of all items */
       +static Item *item = 0;        /* first of pattern matching items */
       +static Item *sel = 0;
       +static Item *nextoff = 0;
       +static Item *prevoff = 0;
       +static Item *curroff = 0;
       +
       +static int screen;
       +static char *title = 0;
        static char text[4096];
       -static BlitzColor selcolor;
       -static BlitzColor normcolor;
       -static Window win;
       -static XRectangle mrect;
       -static Item *allitem = nil;        /* first of all items */
       -static Item *item = nil;        /* first of pattern matching items */
       -static Item *sel = nil;
       -static Item *nextoff = nil;
       -static Item *prevoff = nil;
       -static Item *curroff = nil;
       +static int ret = 0;
        static int nitem = 0;
        static unsigned int cmdw = 0;
        static unsigned int twidth = 0;
        static unsigned int cwidth = 0;
       -static Blitz blz = {0};
       -static BlitzBrush brush = {0};
        static const int seek = 30;                /* 30px */
        
       +static Brush brush = {0};
       +
        static void draw_menu(void);
       -static void handle_kpress(XKeyEvent * e);
       +static void kpress(XKeyEvent * e);
        
       -static char version[] = "wmiimenu - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
       +static char version[] = "gridmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n";
        
        static void
        usage()
        {
       -        fprintf(stderr, "%s", "usage: wmiimenu [-v] [-t <title>]\n");
       +        fprintf(stderr, "%s", "usage: gridmenu [-v] [-t <title>]\n");
                exit(1);
        }
        
       t@@ -71,21 +74,21 @@ update_offsets()
                        return;
        
                for(nextoff = curroff; nextoff; nextoff=nextoff->right) {
       -                tw = blitz_textwidth(brush.font, nextoff->text);
       -                if(tw > mrect.width / 3)
       -                        tw = mrect.width / 3;
       -                w += tw + mrect.height;
       -                if(w > mrect.width)
       +                tw = textwidth(&brush.font, nextoff->text);
       +                if(tw > rect.width / 3)
       +                        tw = rect.width / 3;
       +                w += tw + brush.font.height;
       +                if(w > rect.width)
                                break;
                }
        
                w = cmdw + 2 * seek;
                for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) {
       -                tw = blitz_textwidth(brush.font, prevoff->left->text);
       -                if(tw > mrect.width / 3)
       -                        tw = mrect.width / 3;
       -                w += tw + mrect.height;
       -                if(w > mrect.width)
       +                tw = textwidth(&brush.font, prevoff->left->text);
       +                if(tw > rect.width / 3)
       +                        tw = rect.width / 3;
       +                w += tw + brush.font.height;
       +                if(w > rect.width)
                                break;
                }
        }
       t@@ -104,7 +107,7 @@ update_items(char *pattern)
                else
                        cmdw = twidth;
        
       -        item = j = nil;
       +        item = j = 0;
                nitem = 0;
        
                for(i = allitem; i; i=i->next)
       t@@ -114,7 +117,7 @@ update_items(char *pattern)
                                else
                                        j->right = i;
                                i->left = j;
       -                        i->right = nil;
       +                        i->right = 0;
                                j = i;
                                nitem++;
                        }
       t@@ -126,7 +129,7 @@ update_items(char *pattern)
                                else
                                        j->right = i;
                                i->left = j;
       -                        i->right = nil;
       +                        i->right = 0;
                                j = i;
                                nitem++;
                        }
       t@@ -141,72 +144,62 @@ static void
        draw_menu()
        {
                unsigned int offx = 0;
       -
                Item *i;
        
       -        brush.align = WEST;
       -
       -        brush.rect = mrect;
       +        brush.rect = rect;
                brush.rect.x = 0;
                brush.rect.y = 0;
       -        brush.color = normcolor;
       -        brush.border = False;
       -        blitz_draw_tile(&brush);
       +        draw(dpy, &brush, False, 0);
        
                /* print command */
                if(!title || text[0]) {
       -                brush.color = normcolor;
                        cmdw = cwidth;
                        if(cmdw && item)
                                brush.rect.width = cmdw;
       -                blitz_draw_label(&brush, text);
       +                draw(dpy, &brush, False, text);
                }
                else {
                        cmdw = twidth;
       -                brush.color = selcolor;
                        brush.rect.width = cmdw;
       -                blitz_draw_label(&brush, title);
       +                draw(dpy, &brush, False, title);
                }
                offx += brush.rect.width;
        
       -        brush.align = CENTER;
                if(curroff) {
       -                brush.color = normcolor;
                        brush.rect.x = offx;
                        brush.rect.width = seek;
                        offx += brush.rect.width;
       -                blitz_draw_label(&brush, (curroff && curroff->left) ? "<" : nil);
       +                draw(dpy, &brush, False, (curroff && curroff->left) ? "<" : 0);
        
                        /* determine maximum items */
                        for(i = curroff; i != nextoff; i=i->right) {
       -                        brush.color = normcolor;
                                brush.border = False;
                                brush.rect.x = offx;
       -                        brush.rect.width = blitz_textwidth(brush.font, i->text);
       -                        if(brush.rect.width > mrect.width / 3)
       -                                brush.rect.width = mrect.width / 3;
       -                        brush.rect.width += mrect.height;
       +                        brush.rect.width = textwidth(&brush.font, i->text);
       +                        if(brush.rect.width > rect.width / 3)
       +                                brush.rect.width = rect.width / 3;
       +                        brush.rect.width += brush.font.height;
                                if(sel == i) {
       -                                brush.color = selcolor;
       -                                brush.border = True;
       +                                swap((void **)&brush.fg, (void **)&brush.bg);
       +                                draw(dpy, &brush, True, i->text);
       +                                swap((void **)&brush.fg, (void **)&brush.bg);
                                }
       -                        blitz_draw_label(&brush, i->text);
       +                        else
       +                                draw(dpy, &brush, False, i->text);
                                offx += brush.rect.width;
                        }
        
       -                brush.color = normcolor;
       -                brush.border = False;
       -                brush.rect.x = mrect.width - seek;
       +                brush.rect.x = rect.width - seek;
                        brush.rect.width = seek;
       -                blitz_draw_label(&brush, nextoff ? ">" : nil);
       +                draw(dpy, &brush, False, nextoff ? ">" : 0);
                }
       -        XCopyArea(blz.dpy, brush.drawable, win, brush.gc, 0, 0, mrect.width,
       -                        mrect.height, 0, 0);
       -        XSync(blz.dpy, False);
       +        XCopyArea(dpy, brush.drawable, win, brush.gc, 0, 0, rect.width,
       +                        rect.height, 0, 0);
       +        XFlush(dpy);
        }
        
        static void
       -handle_kpress(XKeyEvent * e)
       +kpress(XKeyEvent * e)
        {
                KeySym ksym;
                char buf[32];
       t@@ -272,7 +265,7 @@ handle_kpress(XKeyEvent * e)
                case XK_Tab:
                        if(!sel)
                                return;
       -                cext_strlcpy(text, sel->text, sizeof(text));
       +                strncpy(text, sel->text, sizeof(text));
                        update_items(text);
                        break;
                case XK_Right:
       t@@ -314,9 +307,9 @@ handle_kpress(XKeyEvent * e)
                        if((num == 1) && !iscntrl((int) buf[0])) {
                                buf[num] = 0;
                                if(len > 0)
       -                                cext_strlcat(text, buf, sizeof(text));
       +                                strncat(text, buf, sizeof(text));
                                else
       -                                cext_strlcpy(text, buf, sizeof(text));
       +                                strncpy(text, buf, sizeof(text));
                                update_items(text);
                        }
                }
       t@@ -326,24 +319,24 @@ handle_kpress(XKeyEvent * e)
        static char *
        read_allitems()
        {
       -        static char *maxname = nil;
       +        static char *maxname = 0;
                char *p, buf[1024];
                unsigned int len = 0, max = 0;
                Item *i, *new;
        
       -        i = nil;
       +        i = 0;
                while(fgets(buf, sizeof(buf), stdin)) {
                        len = strlen(buf);
                        if (buf[len - 1] == '\n')
                                buf[len - 1] = 0;
       -                p = cext_estrdup(buf);
       +                p = estrdup(buf);
                        if(max < len) {
                                maxname = p;
                                max = len;
                        }
        
       -                new = cext_emalloc(sizeof(Item));
       -                new->next = new->left = new->right = nil;
       +                new = emalloc(sizeof(Item));
       +                new->next = new->left = new->right = 0;
                        new->text = p;
                        if(!i)
                                allitem = new;
       t@@ -360,10 +353,7 @@ main(int argc, char *argv[])
        {
                int i;
                XSetWindowAttributes wa;
       -        char *maxname, *p;
       -        BlitzFont font = {0};
       -        GC gc;
       -        Drawable pmap;
       +        char *maxname;
                XEvent ev;
        
                /* command line args */
       t@@ -388,93 +378,70 @@ main(int argc, char *argv[])
                                usage();
                }
        
       -        blz.dpy = XOpenDisplay(0);
       -        if(!blz.dpy) {
       -                fprintf(stderr, "%s", "wmiimenu: cannot open dpy\n");
       -                exit(1);
       -        }
       -        blz.screen = DefaultScreen(blz.dpy);
       -        blz.root = RootWindow(blz.dpy, blz.screen);
       +        dpy = XOpenDisplay(0);
       +        if(!dpy)
       +                error("gridmenu: cannot open dpy\n");
       +        screen = DefaultScreen(dpy);
       +        root = RootWindow(dpy, screen);
        
                maxname = read_allitems();
        
                /* grab as early as possible, but after reading all items!!! */
       -        while(XGrabKeyboard
       -                        (blz.dpy, blz.root, True, GrabModeAsync,
       +        while(XGrabKeyboard(dpy, root, True, GrabModeAsync,
                                 GrabModeAsync, CurrentTime) != GrabSuccess)
                        usleep(1000);
        
       -        font.fontstr = getenv("WMII_FONT");
       -        if (!font.fontstr)
       -                font.fontstr = cext_estrdup(BLITZ_FONT);
       -        blitz_loadfont(&blz, &font);
       -
       -        if((p = getenv("WMII_NORMCOLORS")))
       -                cext_strlcpy(normcolor.colstr, p, sizeof(normcolor.colstr));
       -        if(strlen(normcolor.colstr) != 23)
       -                cext_strlcpy(normcolor.colstr, BLITZ_NORMCOLORS, sizeof(normcolor.colstr));
       -        blitz_loadcolor(&blz, &normcolor);
       -
       -        if((p = getenv("WMII_SELCOLORS")))
       -                cext_strlcpy(selcolor.colstr, p, sizeof(selcolor.colstr));
       -        if(strlen(selcolor.colstr) != 23)
       -                cext_strlcpy(selcolor.colstr, BLITZ_SELCOLORS, sizeof(selcolor.colstr));
       -        blitz_loadcolor(&blz, &selcolor);
       +        /* style */
       +        loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);
       +        loadfont(dpy, &brush.font, FONT);
        
                wa.override_redirect = 1;
                wa.background_pixmap = ParentRelative;
                wa.event_mask = ExposureMask | ButtonPressMask | KeyPressMask
                        | SubstructureRedirectMask | SubstructureNotifyMask;
        
       -        mrect.width = DisplayWidth(blz.dpy, blz.screen);
       -        mrect.height = font.ascent + font.descent + 4;
       -        mrect.y = DisplayHeight(blz.dpy, blz.screen) - mrect.height;
       -        mrect.x = 0;
       +        rect.width = DisplayWidth(dpy, screen);
       +        rect.height = brush.font.height + 4;
       +        rect.y = DisplayHeight(dpy, screen) - rect.height;
       +        rect.x = 0;
        
       -        win = XCreateWindow(blz.dpy, blz.root, mrect.x, mrect.y,
       -                        mrect.width, mrect.height, 0, DefaultDepth(blz.dpy, blz.screen),
       -                        CopyFromParent, DefaultVisual(blz.dpy, blz.screen),
       +        win = XCreateWindow(dpy, root, rect.x, rect.y,
       +                        rect.width, rect.height, 0, DefaultDepth(dpy, screen),
       +                        CopyFromParent, DefaultVisual(dpy, screen),
                                CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
       -        XDefineCursor(blz.dpy, win, XCreateFontCursor(blz.dpy, XC_xterm));
       -        XSync(blz.dpy, False);
       +        XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm));
       +        XFlush(dpy);
        
                /* pixmap */
       -        gc = XCreateGC(blz.dpy, win, 0, 0);
       -        pmap = XCreatePixmap(blz.dpy, win, mrect.width, mrect.height,
       -                        DefaultDepth(blz.dpy, blz.screen));
       -
       -        XSync(blz.dpy, False);
       -
       -        brush.blitz = &blz;
       -        brush.color = normcolor;
       -        brush.drawable = pmap;
       -        brush.gc = gc;
       -        brush.font = &font;
       +        brush.gc = XCreateGC(dpy, win, 0, 0);
       +        brush.drawable = XCreatePixmap(dpy, win, rect.width, rect.height,
       +                        DefaultDepth(dpy, screen));
       +        XFlush(dpy);
        
                if(maxname)
       -                cwidth = blitz_textwidth(brush.font, maxname) + mrect.height;
       -        if(cwidth > mrect.width / 3)
       -                cwidth = mrect.width / 3;
       +                cwidth = textwidth(&brush.font, maxname) + brush.font.height;
       +        if(cwidth > rect.width / 3)
       +                cwidth = rect.width / 3;
        
                if(title) {
       -                twidth = blitz_textwidth(brush.font, title) + mrect.height;
       -                if(twidth > mrect.width / 3)
       -                        twidth = mrect.width / 3;
       +                twidth = textwidth(&brush.font, title) + brush.font.height;
       +                if(twidth > rect.width / 3)
       +                        twidth = rect.width / 3;
                }
        
                cmdw = title ? twidth : cwidth;
        
                text[0] = 0;
                update_items(text);
       -        XMapRaised(blz.dpy, win);
       +        XMapRaised(dpy, win);
                draw_menu();
       -        XSync(blz.dpy, False);
       +        XFlush(dpy);
        
                /* main event loop */
       -        while(!XNextEvent(blz.dpy, &ev)) {
       +        while(!XNextEvent(dpy, &ev)) {
                        switch (ev.type) {
                                case KeyPress:
       -                                handle_kpress(&ev.xkey);
       +                                kpress(&ev.xkey);
                                        break;
                                case Expose:
                                        if(ev.xexpose.count == 0) {
       t@@ -488,11 +455,11 @@ main(int argc, char *argv[])
                                break;
                }
        
       -        XUngrabKeyboard(blz.dpy, CurrentTime);
       -        XFreePixmap(blz.dpy, pmap);
       -        XFreeGC(blz.dpy, gc);
       -        XDestroyWindow(blz.dpy, win);
       -        XCloseDisplay(blz.dpy);
       +        XUngrabKeyboard(dpy, CurrentTime);
       +        XFreePixmap(dpy, brush.drawable);
       +        XFreeGC(dpy, brush.gc);
       +        XDestroyWindow(dpy, win);
       +        XCloseDisplay(dpy);
        
                return ret;
        }
   DIR diff --git a/util.c b/util.c
       t@@ -6,6 +6,7 @@
        #include <stdarg.h>
        #include <stdio.h>
        #include <stdlib.h>
       +#include <string.h>
        
        void
        error(char *errstr, ...) {
       t@@ -16,3 +17,61 @@ error(char *errstr, ...) {
                exit(1);
        }
        
       +static void
       +bad_malloc(unsigned int size)
       +{
       +        fprintf(stderr, "fatal: could not malloc() %d bytes\n",
       +                        (int) size);
       +        exit(1);
       +}
       +
       +void *
       +emallocz(unsigned int size)
       +{
       +        void *res = calloc(1, size);
       +        if(!res)
       +                bad_malloc(size);
       +        return res;
       +}
       +
       +void *
       +emalloc(unsigned int size)
       +{
       +        void *res = malloc(size);
       +        if(!res)
       +                bad_malloc(size);
       +        return res;
       +}
       +
       +void *
       +erealloc(void *ptr, unsigned int size)
       +{
       +        void *res = realloc(ptr, size);
       +        if(!res)
       +                bad_malloc(size);
       +        return res;
       +}
       +
       +char *
       +estrdup(const char *str)
       +{
       +        void *res = strdup(str);
       +        if(!res)
       +                bad_malloc(strlen(str));
       +        return res;
       +}
       +
       +void
       +failed_assert(char *a, char *file, int line)
       +{
       +        fprintf(stderr, "Assertion \"%s\" failed at %s:%d\n", a, file, line);
       +        abort();
       +}
       +
       +void
       +swap(void **p1, void **p2)
       +{
       +        void *tmp = *p1;
       +        *p1 = *p2;
       +        *p2 = tmp;
       +}
   DIR diff --git a/util.h b/util.h
       t@@ -3,39 +3,14 @@
         * See LICENSE file for license details.
         */
        
       -#include <X11/Xlib.h>
       -#include <X11/Xlocale.h>
       -
       -typedef struct Brush Brush;
       -typedef struct Color Color;
       -typedef struct Fnt Fnt;
       -
       -struct Color {
       -        unsigned long bg;
       -        unsigned long fg;
       -        unsigned long border;
       -};
       -
       -struct Fnt {
       -        XFontStruct *xfont;
       -        XFontSet set;
       -        int ascent;
       -        int descent;
       -};
       -
       -struct Brush {
       -        GC gc;
       -        Drawable drawable;
       -        XRectangle rect;
       -        Bool border;
       -        Fnt *font;
       -        Color color;
       -        const char *text;
       -};
       -
       -extern void draw(Display *dpy, Brush *b);
       -extern void loadcolor(Display *dpy, int screen, Color *c,
       -                const char *bg, const char *fg, const char *bo);
       -extern unsigned int textwidth_l(Fnt *font, char *text, unsigned int len);
       -extern unsigned int textwidth(Fnt *font, char *text);
       -extern void loadfont(Display *dpy, Fnt *font, const char *fontstr);
       +extern void error(char *errstr, ...);
       +extern void *emallocz(unsigned int size);
       +extern void *emalloc(unsigned int size);
       +extern void *erealloc(void *ptr, unsigned int size);
       +extern char *estrdup(const char *str);
       +#define eassert(a) do { \
       +                if(!(a)) \
       +                        failed_assert(#a, __FILE__, __LINE__); \
       +        } while (0)
       +void failed_assert(char *a, char *file, int line);
       +void swap(void **p1, void **p2);
   DIR diff --git a/wm.c b/wm.c
       t@@ -13,15 +13,20 @@
        
        #include "wm.h"
        
       +/* X structs */
        Display *dpy;
        Window root;
        XRectangle rect;
       -int screen, sel_screen;
       +Pixmap pmap;
        Atom wm_atom[WMLast];
        Atom net_atom[NetLast];
        Cursor cursor[CurLast];
       +
       +int screen, sel_screen;
        unsigned int kmask, numlock_mask;
       -Pixmap pmap;
       +
       +/* draw structs */
       +Brush brush = {0};
        
        enum { WM_PROTOCOL_DELWIN = 1 };
        
       t@@ -208,7 +213,7 @@ main(int argc, char *argv[])
                XSetErrorHandler(startup_error_handler);
                /* this causes an error if some other WM is running */
                XSelectInput(dpy, root, SubstructureRedirectMask);
       -        XSync(dpy, False);
       +        XFlush(dpy);
        
                if(other_wm_running)
                        error("gridwm: another window manager is already running\n");
       t@@ -246,6 +251,10 @@ main(int argc, char *argv[])
                wa.cursor = cursor[CurNormal];
                XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
        
       +        /* style */
       +        loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR);
       +        loadfont(dpy, &brush.font, FONT);
       +
                scan_wins();
        
                cleanup();
   DIR diff --git a/wm.h b/wm.h
       t@@ -3,6 +3,7 @@
         * See LICENSE file for license details.
         */
        
       +#include "config.h"
        #include "draw.h"
        #include "util.h"
        
       t@@ -48,11 +49,14 @@ struct Tag {
        extern Display *dpy;
        extern Window root;
        extern XRectangle rect;
       -extern int screen, sel_screen;
       -extern unsigned int kmask, numlock_mask;
        extern Atom wm_atom[WMLast];
        extern Atom net_atom[NetLast];
        extern Cursor cursor[CurLast];
        extern Pixmap pmap;
        
       +extern int screen, sel_screen;
       +extern unsigned int kmask, numlock_mask;
       +
       +extern Brush brush;
       +
        /* wm.c */