[PATCH] Port drawing to dwm's libdraw

From: Gregor Best <gbe_AT_ring0.de>
Date: Wed, 22 Jan 2014 16:06:53 +0100

Signed-off-by: Gregor Best <gbe_AT_ring0.de>
---
 Makefile |   9 ++-
 drw.c    | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 drw.h    |  61 ++++++++++++++++++
 tabbed.c | 214 ++++++++++++++-------------------------------------------------
 util.c   |  17 +++++
 util.h   |   6 ++
 6 files changed, 342 insertions(+), 172 deletions(-)
 create mode 100644 drw.c
 create mode 100644 drw.h
 create mode 100644 util.c
 create mode 100644 util.h
diff --git a/Makefile b/Makefile
index 32cc25b..998e58d 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -3,7 +3,9 @@
 
 include config.mk
 
-SRC = tabbed.c
+SRC = tabbed.c \
+		drw.c \
+		util.c
 OBJ = ${SRC:.c=.o}
 
 all: options tabbed
_AT_@ -24,9 +26,10 @@ config.h:
 	_AT_echo creating $@ from config.def.h
 	_AT_cp config.def.h $@
 
-tabbed: tabbed.o
+# TODO explicit deps suck
+tabbed: tabbed.o drw.o drw.h util.c util.h util.o
 	_AT_echo CC -o $@
-	_AT_${CC} -o $@ tabbed.o ${LDFLAGS}
+	_AT_${CC} -o $@ tabbed.o drw.o util.o ${LDFLAGS}
 
 clean:
 	_AT_echo cleaning
diff --git a/drw.c b/drw.c
new file mode 100644
index 0000000..749795d
--- /dev/null
+++ b/drw.c
_AT_@ -0,0 +1,207 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+
+#include "drw.h"
+#include "util.h"
+
+Drw *
+drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) {
+	Drw *drw = (Drw *)calloc(1, sizeof(Drw));
+	if(!drw)
+		return NULL;
+	drw->dpy = dpy;
+	drw->screen = screen;
+	drw->root = root;
+	drw->w = w;
+	drw->h = h;
+	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
+	drw->gc = XCreateGC(dpy, root, 0, NULL);
+	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
+	return drw;
+}
+
+void
+drw_resize(Drw *drw, unsigned int w, unsigned int h) {
+	if(!drw)
+		return;
+	drw->w = w;
+	drw->h = h;
+	if(drw->drawable != 0)
+		XFreePixmap(drw->dpy, drw->drawable);
+	drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
+}
+
+void
+drw_free(Drw *drw) {
+	XFreePixmap(drw->dpy, drw->drawable);
+	XFreeGC(drw->dpy, drw->gc);
+	free(drw);
+}
+
+Fnt *
+drw_font_create(Display *dpy, const char *fontname) {
+	Fnt *font;
+	char *def, **missing;
+	int n;
+
+	font = (Fnt *)calloc(1, sizeof(Fnt));
+	if(!font)
+		return NULL;
+	font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def);
+	if(missing) {
+		while(n--)
+			fprintf(stderr, "drw: missing fontset: %s\n", missing[n]);
+		XFreeStringList(missing);
+	}
+	if(font->set) {
+		XFontStruct **xfonts;
+		char **font_names;
+		XExtentsOfFontSet(font->set);
+		n = XFontsOfFontSet(font->set, &xfonts, &font_names);
+		while(n--) {
+			font->ascent = MAX(font->ascent, (*xfonts)->ascent);
+			font->descent = MAX(font->descent,(*xfonts)->descent);
+			xfonts++;
+		}
+	}
+	else {
+		if(!(font->xfont = XLoadQueryFont(dpy, fontname))
+		&& !(font->xfont = XLoadQueryFont(dpy, "fixed")))
+			die("error, cannot load font: '%s'\n", fontname);
+		font->ascent = font->xfont->ascent;
+		font->descent = font->xfont->descent;
+	}
+	font->h = font->ascent + font->descent;
+	return font;
+}
+
+void
+drw_font_free(Display *dpy, Fnt *font) {
+	if(!font)
+		return;
+	if(font->set)
+		XFreeFontSet(dpy, font->set);
+	else
+		XFreeFont(dpy, font->xfont);
+	free(font);
+}
+
+Clr *
+drw_clr_create(Drw *drw, const char *clrname) {
+	Clr *clr;
+	Colormap cmap;
+	XColor color;
+
+	if(!drw)
+		return NULL;
+	clr = (Clr *)calloc(1, sizeof(Clr));
+	if(!clr)
+		return NULL;
+	cmap = DefaultColormap(drw->dpy, drw->screen);
+	if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color))
+		die("error, cannot allocate color '%s'\n", clrname);
+	clr->rgb = color.pixel;
+	return clr;
+}
+
+void
+drw_clr_free(Clr *clr) {
+	free(clr);
+}
+
+void
+drw_setfont(Drw *drw, Fnt *font) {
+	if(drw)
+		drw->font = font;
+}
+
+void
+drw_setscheme(Drw *drw, ClrScheme *scheme) {
+	if(drw && scheme) 
+		drw->scheme = scheme;
+}
+
+void
+drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) {
+	int dx;
+
+	if(!drw || !drw->font || !drw->scheme)
+		return;
+	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb);
+	dx = (drw->font->ascent + drw->font->descent + 2) / 4;
+	if(filled)
+		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1);
+	else if(empty)
+		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx);
+}
+
+void
+drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) {
+	char buf[256];
+	int i, tx, ty, th, len, olen;
+	Extnts tex;
+
+	if(!drw || !drw->scheme)
+		return;
+	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb : drw->scheme->bg->rgb);
+	XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+	if(!text || !drw->font)
+		return;
+	olen = strlen(text);
+	drw_font_getexts(drw->font, text, olen, &tex);
+	th = drw->font->ascent + drw->font->descent;
+	ty = y + (h / 2) - (th / 2) + drw->font->ascent;
+	tx = x + (h / 2);
+	/* shorten text if necessary */
+	for(len = MIN(olen, sizeof buf); len && (tex.w > w - tex.h || w < tex.h); len--)
+		drw_font_getexts(drw->font, text, len, &tex);
+	if(!len)
+		return;
+	memcpy(buf, text, len);
+	if(len < olen)
+		for(i = len; i && i > len - 3; buf[--i] = '.');
+	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb);
+	if(drw->font->set)
+		XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len);
+	else
+		XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len);
+}
+
+void
+drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
+	if(!drw)
+		return;
+	XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
+	XSync(drw->dpy, False);
+}
+
+
+void
+drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) {
+	XRectangle r;
+
+	if(!font || !text)
+		return;
+	if(font->set) {
+		XmbTextExtents(font->set, text, len, NULL, &r);
+		tex->w = r.width;
+		tex->h = r.height;
+	}
+	else {
+		tex->h = font->ascent + font->descent;
+		tex->w = XTextWidth(font->xfont, text, len);
+	}
+}
+
+unsigned int
+drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) {
+	Extnts tex;
+
+	if(!font)
+		return -1;
+	drw_font_getexts(font, text, len, &tex);
+	return tex.w;
+}
diff --git a/drw.h b/drw.h
new file mode 100644
index 0000000..e77a49c
--- /dev/null
+++ b/drw.h
_AT_@ -0,0 +1,61 @@
+/* See LICENSE file for copyright and license details. */
+
+typedef struct {
+	unsigned long rgb;
+} Clr;
+
+typedef struct {
+	int ascent;
+	int descent;
+	unsigned int h;
+	XFontSet set;
+	XFontStruct *xfont;
+} Fnt;
+
+typedef struct {
+	Clr *fg;
+	Clr *bg;
+	Clr *border;
+} ClrScheme;
+
+typedef struct {
+	unsigned int w, h;
+	Display *dpy;
+	int screen;
+	Window root;
+	Drawable drawable;
+	GC gc;
+	ClrScheme *scheme;
+	Fnt *font;
+} Drw;
+
+typedef struct {
+	unsigned int w;
+	unsigned int h;
+} Extnts;
+
+/* Drawable abstraction */
+Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
+void drw_resize(Drw *drw, unsigned int w, unsigned int h);
+void drw_free(Drw *drw);
+
+/* Fnt abstraction */
+Fnt *drw_font_create(Display *dpy, const char *fontname);
+void drw_font_free(Display *dpy, Fnt *font);
+void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts);
+unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len);
+
+/* Colour abstraction */
+Clr *drw_clr_create(Drw *drw, const char *clrname);
+void drw_clr_free(Clr *clr);
+
+/* Drawing context manipulation */
+void drw_setfont(Drw *drw, Fnt *font);
+void drw_setscheme(Drw *drw, ClrScheme *scheme);
+
+/* Drawing functions */
+void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert);
+void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
+
+/* Map functions */
+void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
diff --git a/tabbed.c b/tabbed.c
index 93a213a..3ef5968 100644
--- a/tabbed.c
+++ b/tabbed.c
_AT_@ -17,6 +17,7 @@
 #include <X11/XKBlib.h>
 
 #include "arg.h"
+#include "drw.h"
 
 /* XEMBED messages */
 #define XEMBED_EMBEDDED_NOTIFY          0
_AT_@ -44,9 +45,9 @@
 #define MIN(a, b)                ((a) < (b) ? (a) : (b))
 #define LENGTH(x)                (sizeof((x)) / sizeof(*(x)))
 #define CLEANMASK(mask)          (mask & ~(numlockmask|LockMask))
-#define TEXTW(x)                 (textnw(x, strlen(x)) + dc.font.height)
+#define TEXTW(X)                 (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h)
 
-enum { ColFG, ColBG, ColLast };                         /* color */
+enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
 enum { WMProtocols, WMDelete, WMName, WMState, WMFullscreen,
 	XEmbed, WMSelectTab, WMLast };                      /* default atoms */
 
_AT_@ -62,21 +63,6 @@ typedef struct {
 	const Arg arg;
 } Key;
 
-typedef struct {
-	int x, y, w, h;
-	unsigned long norm[ColLast];
-	unsigned long sel[ColLast];
-	Drawable drawable;
-	GC gc;
-	struct {
-		int ascent;
-		int descent;
-		int height;
-		XFontSet set;
-		XFontStruct *xfont;
-	} font;
-} DC; /* draw context */
-
 typedef struct Client {
 	char name[256];
 	Window win;
_AT_@ -95,7 +81,6 @@ static void createnotify(const XEvent *e);
 static void destroynotify(const XEvent *e);
 static void die(const char *errstr, ...);
 static void drawbar(void);
-static void drawtext(const char *text, unsigned long col[ColLast]);
 static void *emallocz(size_t size);
 static void *erealloc(void *o, size_t size);
 static void expose(const XEvent *e);
_AT_@ -105,10 +90,8 @@ static void focusonce(const Arg *arg);
 static void fullscreen(const Arg *arg);
 static char* getatom(int a);
 static int getclient(Window w);
-static unsigned long getcolor(const char *colstr);
 static int getfirsttab(void);
 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
-static void initfont(const char *fontstr);
 static Bool isprotodel(int c);
 static void keypress(const XEvent *e);
 static void killclient(const Arg *arg);
_AT_@ -125,7 +108,6 @@ static void setup(void);
 static void setcmd(int argc, char *argv[], int);
 static void sigchld(int unused);
 static void spawn(const Arg *arg);
-static int textnw(const char *text, unsigned int len);
 static void unmanage(int c);
 static void updatenumlockmask(void);
 static void updatetitle(int c);
_AT_@ -152,7 +134,9 @@ static unsigned int numlockmask = 0;
 static Bool running = True, nextfocus, doinitspawn = True,
 	    fillagain = False, closelastclient = False;
 static Display *dpy;
-static DC dc;
+static Drw* drw;
+static Fnt* fnt;
+static ClrScheme scheme[SchemeLast];
 static Atom wmatom[WMLast];
 static Window root, win;
 static Client **clients = NULL;
_AT_@ -219,14 +203,13 @@ cleanup(void) {
 	free(clients);
 	clients = NULL;
 
-	if(dc.font.set) {
-		XFreeFontSet(dpy, dc.font.set);
-	} else {
-		XFreeFont(dpy, dc.font.xfont);
-	}
+	drw_font_free(dpy, fnt);
+	drw_clr_free(scheme[SchemeNorm].bg);
+	drw_clr_free(scheme[SchemeNorm].fg);
+	drw_clr_free(scheme[SchemeSel].bg);
+	drw_clr_free(scheme[SchemeSel].fg);
+	drw_free(drw);
 
-	XFreePixmap(dpy, dc.drawable);
-	XFreeGC(dpy, dc.gc);
 	XDestroyWindow(dpy, win);
 	XSync(dpy, False);
 	free(cmd);
_AT_@ -249,9 +232,7 @@ configurenotify(const XEvent *e) {
 	if(ev->window == win && (ev->width != ww || ev->height != wh)) {
 		ww = ev->width;
 		wh = ev->height;
-		XFreePixmap(dpy, dc.drawable);
-		dc.drawable = XCreatePixmap(dpy, root, ww, wh,
-				DefaultDepth(dpy, screen));
+		drw_resize(drw, ww, bh);
 		if(sel > -1)
 			resize(sel, ww, wh - bh);
 		XSync(dpy, False);
_AT_@ -305,16 +286,13 @@ die(const char *errstr, ...) {
 
 void
 drawbar(void) {
-	unsigned long *col;
-	int c, fc, width, n = 0;
+	int c, fc, width, n = 0, xoff = 0, draww = 0;
 	char *name = NULL;
 
 	if(nclients == 0) {
-		dc.x = 0;
-		dc.w = ww;
 		XFetchName(dpy, win, &name);
-		drawtext(name ? name : "", dc.norm);
-		XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, ww, bh, 0, 0);
+		drw_text(drw, 0, /* y */ 0, ww, bh, name ? name : "", False);
+		XCopyArea(dpy, drw->drawable, win, drw->gc, 0, 0, ww, bh, 0, 0);
 		XSync(dpy, False);
 
 		return;
_AT_@ -327,76 +305,40 @@ drawbar(void) {
 		n = nclients - fc;
 
 	if((n * tabwidth) > width) {
-		dc.w = TEXTW(after);
-		dc.x = width - dc.w;
-		drawtext(after, dc.sel);
-		width -= dc.w;
+		draww = TEXTW(after);
+		drw_setscheme(drw, &scheme[SchemeSel]);
+		drw_text(drw, width - draww, /* y */ 0, draww, bh, after, False);
+		width -= draww;
 	}
-	dc.x = 0;
 
 	if(fc > 0) {
-		dc.w = TEXTW(before);
-		drawtext(before, dc.sel);
-		dc.x += dc.w;
-		width -= dc.w;
+		draww = TEXTW(before);
+		drw_setscheme(drw, &scheme[SchemeSel]);
+		drw_text(drw, 0, /* y */ 0, draww, bh, before, False);
+		xoff = draww;
+		width -= draww;
 	}
 
-	for(c = (fc > 0)? fc : 0; c < nclients && dc.x < width; c++) {
-		dc.w = tabwidth;
+	for(c = (fc > 0)? fc : 0; c < nclients && xoff < width; c++) {
+		draww = tabwidth;
 		if(c == sel) {
-			col = dc.sel;
+			drw_setscheme(drw, &scheme[SchemeSel]);
 			if((n * tabwidth) > width) {
-				dc.w += width % tabwidth;
+				draww += width % tabwidth;
 			} else {
-				dc.w = width - (n - 1) * tabwidth;
+				draww = width - (n - 1) * tabwidth;
 			}
 		} else {
-			col = dc.norm;
+			drw_setscheme(drw, &scheme[SchemeNorm]);
 		}
-		drawtext(clients[c]->name, col);
-		dc.x += dc.w;
-		clients[c]->tabx = dc.x;
+		drw_text(drw, xoff, /* y */ 0, draww, bh, clients[c]->name, False);
+		xoff += draww;
+		clients[c]->tabx = xoff;
 	}
-	XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, ww, bh, 0, 0);
+	XCopyArea(dpy, drw->drawable, win, drw->gc, 0, 0, ww, bh, 0, 0);
 	XSync(dpy, False);
 }
 
-void
-drawtext(const char *text, unsigned long col[ColLast]) {
-	int i, x, y, h, len, olen;
-	char buf[256];
-	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
-
-	XSetForeground(dpy, dc.gc, col[ColBG]);
-	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
-	if(!text)
-		return;
-
-	olen = strlen(text);
-	h = dc.font.ascent + dc.font.descent;
-	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
-	x = dc.x + (h / 2);
-
-	/* shorten text if necessary */
-	for(len = MIN(olen, sizeof(buf));
-			len && textnw(text, len) > dc.w - h; len--);
-	if(!len)
-		return;
-
-	memcpy(buf, text, len);
-	if(len < olen) {
-		for(i = len; i && i > len - 3; buf[--i] = '.');
-	}
-
-	XSetForeground(dpy, dc.gc, col[ColFG]);
-	if(dc.font.set) {
-		XmbDrawString(dpy, dc.drawable, dc.font.set,
-				dc.gc, x, y, buf, len);
-	} else {
-		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
-	}
-}
-
 void *
 emallocz(size_t size) {
 	void *p;
_AT_@ -524,17 +466,6 @@ getclient(Window w) {
 	return -1;
 }
 
-unsigned long
-getcolor(const char *colstr) {
-	Colormap cmap = DefaultColormap(dpy, screen);
-	XColor color;
-
-	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
-		die("tabbed: cannot allocate color '%s'\n", colstr);
-
-	return color.pixel;
-}
-
 int
 getfirsttab(void) {
 	int c, n, fc;
_AT_@ -583,46 +514,6 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
 	return True;
 }
 
-void
-initfont(const char *fontstr) {
-	char *def, **missing, **font_names;
-	int i, n;
-	XFontStruct **xfonts;
-
-	missing = NULL;
-	if(dc.font.set)
-		XFreeFontSet(dpy, dc.font.set);
-
-	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
-	if(missing) {
-		while(n--)
-			fprintf(stderr, "tabbed: missing fontset: %s\n", missing[n]);
-		XFreeStringList(missing);
-	}
-
-	if(dc.font.set) {
-		dc.font.ascent = dc.font.descent = 0;
-		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
-		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
-			dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
-			dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
-			xfonts++;
-		}
-	} else {
-		if(dc.font.xfont)
-			XFreeFont(dpy, dc.font.xfont);
-		dc.font.xfont = NULL;
-		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
-				&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) {
-			die("tabbed: cannot load font: '%s'\n", fontstr);
-		}
-
-		dc.font.ascent = dc.font.xfont->ascent;
-		dc.font.descent = dc.font.xfont->descent;
-	}
-	dc.font.height = dc.font.ascent + dc.font.descent;
-}
-
 Bool
 isprotodel(int c) {
 	int i, n;
_AT_@ -919,8 +810,8 @@ setup(void) {
 	/* init screen */
 	screen = DefaultScreen(dpy);
 	root = RootWindow(dpy, screen);
-	initfont(font);
-	bh = dc.h = dc.font.height + 2;
+	fnt = drw_font_create(dpy, font);
+	bh = fnt->h + 2;
 
 	/* init atoms */
 	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
_AT_@ -965,18 +856,16 @@ setup(void) {
 			wy = dh + wy - wh - 1;
 	}
 
-	dc.norm[ColBG] = getcolor(normbgcolor);
-	dc.norm[ColFG] = getcolor(normfgcolor);
-	dc.sel[ColBG] = getcolor(selbgcolor);
-	dc.sel[ColFG] = getcolor(selfgcolor);
-	dc.drawable = XCreatePixmap(dpy, root, ww, wh,
-			DefaultDepth(dpy, screen));
-	dc.gc = XCreateGC(dpy, root, 0, 0);
-	if(!dc.font.set)
-		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
+	drw = drw_create(dpy, screen, root, ww, bh);
+	drw_setfont(drw, fnt);
+
+	scheme[SchemeNorm].bg = drw_clr_create(drw, normbgcolor);
+	scheme[SchemeNorm].fg = drw_clr_create(drw, normfgcolor);
+	scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor);
+	scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor);
 
 	win = XCreateSimpleWindow(dpy, root, wx, wy, ww, wh, 0,
-			dc.norm[ColFG], dc.norm[ColBG]);
+			scheme[SchemeNorm].fg->rgb, scheme[SchemeNorm].bg->rgb);
 	XMapRaised(dpy, win);
 	XSelectInput(dpy, win, SubstructureNotifyMask|FocusChangeMask|
 			ButtonPressMask|ExposureMask|KeyPressMask|PropertyChangeMask|
_AT_@ -1038,19 +927,6 @@ spawn(const Arg *arg) {
 	}
 }
 
-int
-textnw(const char *text, unsigned int len) {
-	XRectangle r;
-
-	if(dc.font.set) {
-		XmbTextExtents(dc.font.set, text, len, NULL, &r);
-
-		return r.width;
-	}
-
-	return XTextWidth(dc.font.xfont, text, len);
-}
-
 void
 unmanage(int c) {
 	if(c < 0 || c >= nclients) {
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..51acd1a
--- /dev/null
+++ b/util.c
_AT_@ -0,0 +1,17 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+void
+die(const char *errstr, ...) {
+	va_list ap;
+
+	va_start(ap, errstr);
+	vfprintf(stderr, errstr, ap);
+	va_end(ap);
+	exit(EXIT_FAILURE);
+}
+
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..033700c
--- /dev/null
+++ b/util.h
_AT_@ -0,0 +1,6 @@
+/* See LICENSE file for copyright and license details. */
+
+#define MAX(A, B)               ((A) > (B) ? (A) : (B))
+#define MIN(A, B)               ((A) < (B) ? (A) : (B))
+
+void die(const char *errstr, ...);
-- 
1.8.5.3
--Bn2rw/3z4jIqBvZU--
Received on Mon Sep 17 2001 - 00:00:00 CEST

This archive was generated by hypermail 2.3.0 : Wed Jan 22 2014 - 17:36:03 CET