Add Xft and follback-fonts support to graphics lib 14343e69
Eric Pruitt · 2015-03-05 20:26 6 file(s) · +299 −103
config.def.h +7 −2
1 1
/* See LICENSE file for copyright and license details. */
2 2
3 3
/* appearance */
4 -
static const char font[]            = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
4 +
static const char *fonts[] = {
5 +
    "Sans:size=10.5",
6 +
    "VL Gothic:size=10.5",
7 +
    "WenQuanYi Micro Hei:size=10.5",
8 +
};
9 +
static const char dmenufont[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
5 10
static const char normbordercolor[] = "#444444";
6 11
static const char normbgcolor[]     = "#222222";
7 12
static const char normfgcolor[]     = "#bbbbbb";
51 56
52 57
/* commands */
53 58
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
54 -
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
59 +
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
55 60
static const char *termcmd[]  = { "st", NULL };
56 61
57 62
static Key keys[] = {
config.mk +2 −2
15 15
XINERAMAFLAGS = -DXINERAMA
16 16
17 17
# includes and libs
18 -
INCS = -I${X11INC}
19 -
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS}
18 +
INCS = -I${X11INC} -I/usr/include/freetype2
19 +
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lfontconfig -lXft
20 20
21 21
# flags
22 22
CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
drw.c +267 −82
3 3
#include <stdlib.h>
4 4
#include <string.h>
5 5
#include <X11/Xlib.h>
6 +
#include <X11/Xft/Xft.h>
6 7
7 8
#include "drw.h"
8 9
#include "util.h"
9 10
11 +
#define UTF_INVALID 0xFFFD
12 +
#define UTF_SIZ 4
13 +
14 +
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80,    0, 0xC0, 0xE0, 0xF0};
15 +
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
16 +
static const long utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000};
17 +
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
18 +
19 +
static long
20 +
utf8decodebyte(const char c, size_t *i) {
21 +
	for(*i = 0; *i < (UTF_SIZ + 1); ++(*i))
22 +
		if(((unsigned char)c & utfmask[*i]) == utfbyte[*i])
23 +
			return (unsigned char)c & ~utfmask[*i];
24 +
	return 0;
25 +
}
26 +
27 +
static size_t
28 +
utf8validate(long *u, size_t i) {
29 +
	if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
30 +
		*u = UTF_INVALID;
31 +
	for(i = 1; *u > utfmax[i]; ++i)
32 +
		;
33 +
	return i;
34 +
}
35 +
36 +
static size_t
37 +
utf8decode(const char *c, long *u, size_t clen) {
38 +
	size_t i, j, len, type;
39 +
	long udecoded;
40 +
41 +
	*u = UTF_INVALID;
42 +
	if(!clen)
43 +
		return 0;
44 +
	udecoded = utf8decodebyte(c[0], &len);
45 +
	if(!BETWEEN(len, 1, UTF_SIZ))
46 +
		return 1;
47 +
	for(i = 1, j = 1; i < clen && j < len; ++i, ++j) {
48 +
		udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
49 +
		if(type != 0)
50 +
			return j;
51 +
	}
52 +
	if(j < len)
53 +
		return 0;
54 +
	*u = udecoded;
55 +
	utf8validate(u, len);
56 +
	return len;
57 +
}
58 +
10 59
Drw *
11 60
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) {
12 61
	Drw *drw = (Drw *)calloc(1, sizeof(Drw));
19 68
	drw->h = h;
20 69
	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
21 70
	drw->gc = XCreateGC(dpy, root, 0, NULL);
71 +
	drw->fontcount = 0;
22 72
	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
23 73
	return drw;
24 74
}
36 86
37 87
void
38 88
drw_free(Drw *drw) {
89 +
	size_t i;
90 +
	for (i = 0; i < drw->fontcount; i++) {
91 +
		drw_font_free(drw->fonts[i]);
92 +
	}
39 93
	XFreePixmap(drw->dpy, drw->drawable);
40 94
	XFreeGC(drw->dpy, drw->gc);
41 95
	free(drw);
42 96
}
43 97
44 -
Fnt *
45 -
drw_font_create(Display *dpy, const char *fontname) {
98 +
/* This function is an implementation detail. Library users should use
99 +
 * drw_font_create instead.
100 +
 */
101 +
static Fnt *
102 +
drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) {
46 103
	Fnt *font;
47 -
	char *def, **missing;
48 -
	int n;
49 104
50 -
	font = (Fnt *)calloc(1, sizeof(Fnt));
51 -
	if(!font)
105 +
	if (!(fontname || fontpattern))
106 +
		die("No font specified.\n");
107 +
108 +
	if (!(font = (Fnt *)calloc(1, sizeof(Fnt))))
52 109
		return NULL;
53 -
	font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def);
54 -
	if(missing) {
55 -
		while(n--)
56 -
			fprintf(stderr, "drw: missing fontset: %s\n", missing[n]);
57 -
		XFreeStringList(missing);
58 -
	}
59 -
	if(font->set) {
60 -
		XFontStruct **xfonts;
61 -
		char **font_names;
62 -
		XExtentsOfFontSet(font->set);
63 -
		n = XFontsOfFontSet(font->set, &xfonts, &font_names);
64 -
		while(n--) {
65 -
			font->ascent = MAX(font->ascent, (*xfonts)->ascent);
66 -
			font->descent = MAX(font->descent,(*xfonts)->descent);
67 -
			xfonts++;
110 +
111 +
	if (fontname) {
112 +
		/* Using the pattern found at font->xfont->pattern does not yield same
113 +
		 * the same substitution results as using the pattern returned by
114 +
		 * FcNameParse; using the latter results in the desired fallback
115 +
		 * behaviour whereas the former just results in
116 +
		 * missing-character-rectangles being drawn, at least with some fonts.
117 +
		 */
118 +
		if (!(font->xfont = XftFontOpenName(drw->dpy, drw->screen, fontname)) ||
119 +
		    !(font->pattern = FcNameParse((FcChar8 *) fontname))) {
120 +
			if (font->xfont) {
121 +
				XftFontClose(drw->dpy, font->xfont);
122 +
				font->xfont = NULL;
123 +
			}
124 +
			fprintf(stderr, "error, cannot load font: '%s'\n", fontname);
125 +
		}
126 +
	} else if (fontpattern) {
127 +
		if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
128 +
			fprintf(stderr, "error, cannot load font pattern.\n");
129 +
		} else {
130 +
			font->pattern = NULL;
68 131
		}
69 132
	}
70 -
	else {
71 -
		if(!(font->xfont = XLoadQueryFont(dpy, fontname))
72 -
		&& !(font->xfont = XLoadQueryFont(dpy, "fixed")))
73 -
			die("error, cannot load font: '%s'\n", fontname);
74 -
		font->ascent = font->xfont->ascent;
75 -
		font->descent = font->xfont->descent;
133 +
134 +
	if (!font->xfont) {
135 +
		free(font);
136 +
		return NULL;
76 137
	}
138 +
139 +
	font->ascent = font->xfont->ascent;
140 +
	font->descent = font->xfont->descent;
77 141
	font->h = font->ascent + font->descent;
142 +
	font->dpy = drw->dpy;
78 143
	return font;
79 144
}
80 145
146 +
Fnt*
147 +
drw_font_create(Drw *drw, const char *fontname) {
148 +
	return drw_font_xcreate(drw, fontname, NULL);
149 +
}
150 +
81 151
void
82 -
drw_font_free(Display *dpy, Fnt *font) {
152 +
drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) {
153 +
	size_t i;
154 +
	Fnt *font;
155 +
	for (i = 0; i < fontcount; i++) {
156 +
		if (drw->fontcount >= DRW_FONT_CACHE_SIZE) {
157 +
			die("Font cache exhausted.\n");
158 +
		} else if ((font = drw_font_xcreate(drw, fonts[i], NULL))) {
159 +
			drw->fonts[drw->fontcount++] = font;
160 +
		}
161 +
	}
162 +
}
163 +
164 +
void
165 +
drw_font_free(Fnt *font) {
83 166
	if(!font)
84 167
		return;
85 -
	if(font->set)
86 -
		XFreeFontSet(dpy, font->set);
87 -
	else
88 -
		XFreeFont(dpy, font->xfont);
168 +
	if(font->pattern)
169 +
		FcPatternDestroy(font->pattern);
170 +
	XftFontClose(font->dpy, font->xfont);
89 171
	free(font);
90 172
}
91 173
93 175
drw_clr_create(Drw *drw, const char *clrname) {
94 176
	Clr *clr;
95 177
	Colormap cmap;
96 -
	XColor color;
178 +
	Visual *vis;
97 179
98 180
	if(!drw)
99 181
		return NULL;
101 183
	if(!clr)
102 184
		return NULL;
103 185
	cmap = DefaultColormap(drw->dpy, drw->screen);
104 -
	if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color))
186 +
	vis = DefaultVisual(drw->dpy, drw->screen);
187 +
	if(!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb))
105 188
		die("error, cannot allocate color '%s'\n", clrname);
106 -
	clr->rgb = color.pixel;
189 +
	clr->pix = clr->rgb.pixel;
107 190
	return clr;
108 191
}
109 192
114 197
}
115 198
116 199
void
117 -
drw_setfont(Drw *drw, Fnt *font) {
118 -
	if(drw)
119 -
		drw->font = font;
120 -
}
121 -
122 -
void
123 200
drw_setscheme(Drw *drw, ClrScheme *scheme) {
124 -
	if(drw && scheme) 
201 +
	if(drw && scheme)
125 202
		drw->scheme = scheme;
126 203
}
127 204
129 206
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) {
130 207
	int dx;
131 208
132 -
	if(!drw || !drw->font || !drw->scheme)
209 +
	if(!drw || !drw->fontcount || !drw->scheme)
133 210
		return;
134 -
	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb);
135 -
	dx = (drw->font->ascent + drw->font->descent + 2) / 4;
211 +
	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix);
212 +
	dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4;
136 213
	if(filled)
137 214
		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1);
138 215
	else if(empty)
139 216
		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx);
140 217
}
141 218
142 -
void
219 +
int
143 220
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) {
144 -
	char buf[256];
145 -
	int i, tx, ty, th, len, olen;
221 +
	char buf[1024];
222 +
	int tx, ty, th;
146 223
	Extnts tex;
224 +
	Colormap cmap;
225 +
	Visual *vis;
226 +
	XftDraw *d;
227 +
	Fnt *curfont, *nextfont;
228 +
	size_t i, len;
229 +
	int utf8strlen, utf8charlen, render;
230 +
	long utf8codepoint = 0;
231 +
	const char *utf8str;
232 +
	FcCharSet *fccharset;
233 +
	FcPattern *fcpattern;
234 +
	FcPattern *match;
235 +
	XftResult result;
236 +
	int charexists = 0;
147 237
148 -
	if(!drw || !drw->scheme)
149 -
		return;
150 -
	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb : drw->scheme->bg->rgb);
151 -
	XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
152 -
	if(!text || !drw->font)
153 -
		return;
154 -
	olen = strlen(text);
155 -
	drw_font_getexts(drw->font, text, olen, &tex);
156 -
	th = drw->font->ascent + drw->font->descent;
157 -
	ty = y + (h / 2) - (th / 2) + drw->font->ascent;
158 -
	tx = x + (h / 2);
159 -
	/* shorten text if necessary */
160 -
	for(len = MIN(olen, sizeof buf); len && (tex.w > w - tex.h || w < tex.h); len--)
161 -
		drw_font_getexts(drw->font, text, len, &tex);
162 -
	if(!len)
163 -
		return;
164 -
	memcpy(buf, text, len);
165 -
	if(len < olen)
166 -
		for(i = len; i && i > len - 3; buf[--i] = '.');
167 -
	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb);
168 -
	if(drw->font->set)
169 -
		XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len);
170 -
	else
171 -
		XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len);
238 +
	if (!(render = x || y || w || h)) {
239 +
		w = ~w;
240 +
	}
241 +
242 +
	if (!drw || !drw->scheme) {
243 +
		return 0;
244 +
	} else if (render) {
245 +
		XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->pix : drw->scheme->bg->pix);
246 +
		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
247 +
	}
248 +
249 +
	if (!text || !drw->fontcount) {
250 +
		return 0;
251 +
	} else if (render) {
252 +
		cmap = DefaultColormap(drw->dpy, drw->screen);
253 +
		vis = DefaultVisual(drw->dpy, drw->screen);
254 +
		d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap);
255 +
	}
256 +
257 +
	curfont = drw->fonts[0];
258 +
	while (1) {
259 +
		utf8strlen = 0;
260 +
		utf8str = text;
261 +
		nextfont = NULL;
262 +
		while (*text) {
263 +
			utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
264 +
			for (i = 0; i < drw->fontcount; i++) {
265 +
				charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint);
266 +
				if (charexists) {
267 +
					if (drw->fonts[i] == curfont) {
268 +
						utf8strlen += utf8charlen;
269 +
						text += utf8charlen;
270 +
					} else {
271 +
						nextfont = drw->fonts[i];
272 +
					}
273 +
					break;
274 +
				}
275 +
			}
276 +
277 +
			if (!charexists || (nextfont && nextfont != curfont)) {
278 +
				break;
279 +
			} else {
280 +
				charexists = 0;
281 +
			}
282 +
		}
283 +
284 +
		if (utf8strlen) {
285 +
			drw_font_getexts(curfont, utf8str, utf8strlen, &tex);
286 +
			/* shorten text if necessary */
287 +
			for(len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--)
288 +
				drw_font_getexts(curfont, utf8str, len, &tex);
289 +
290 +
			if (len) {
291 +
				memcpy(buf, utf8str, len);
292 +
				buf[len] = '\0';
293 +
				if(len < utf8strlen)
294 +
					for(i = len; i && i > len - 3; buf[--i] = '.');
295 +
296 +
				if (render) {
297 +
					th = curfont->ascent + curfont->descent;
298 +
					ty = y + (h / 2) - (th / 2) + curfont->ascent;
299 +
					tx = x + (h / 2);
300 +
					XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len);
301 +
				}
302 +
303 +
				x += tex.w;
304 +
				w -= tex.w;
305 +
			}
306 +
		}
307 +
308 +
		if (!*text) {
309 +
			break;
310 +
		} else if (nextfont) {
311 +
			charexists = 0;
312 +
			curfont = nextfont;
313 +
		} else {
314 +
			/* Regardless of whether or not a fallback font is found, the
315 +
			 * character must be drawn.
316 +
			 */
317 +
			charexists = 1;
318 +
319 +
			if (drw->fontcount >= DRW_FONT_CACHE_SIZE) {
320 +
				continue;
321 +
			}
322 +
323 +
			fccharset = FcCharSetCreate();
324 +
			FcCharSetAddChar(fccharset, utf8codepoint);
325 +
326 +
			if (!drw->fonts[0]->pattern) {
327 +
				/* Refer to the comment in drw_font_xcreate for more
328 +
				 * information.
329 +
				 */
330 +
				die("The first font in the cache must be loaded from a font string.\n");
331 +
			}
332 +
333 +
			fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern);
334 +
			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
335 +
			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
336 +
337 +
			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
338 +
			FcDefaultSubstitute(fcpattern);
339 +
			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
340 +
341 +
			FcCharSetDestroy(fccharset);
342 +
			FcPatternDestroy(fcpattern);
343 +
344 +
			if (match) {
345 +
				curfont = drw_font_xcreate(drw, NULL, match);
346 +
				if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) {
347 +
					drw->fonts[drw->fontcount++] = curfont;
348 +
				} else {
349 +
					if (curfont) {
350 +
						drw_font_free(curfont);
351 +
					}
352 +
					curfont = drw->fonts[0];
353 +
				}
354 +
			}
355 +
		}
356 +
	}
357 +
358 +
	if (render) {
359 +
		XftDrawDestroy(d);
360 +
	}
361 +
362 +
	return x;
172 363
}
173 364
174 365
void
182 373
183 374
void
184 375
drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) {
185 -
	XRectangle r;
376 +
	XGlyphInfo ext;
186 377
187 378
	if(!font || !text)
188 379
		return;
189 -
	if(font->set) {
190 -
		XmbTextExtents(font->set, text, len, NULL, &r);
191 -
		tex->w = r.width;
192 -
		tex->h = r.height;
193 -
	}
194 -
	else {
195 -
		tex->h = font->ascent + font->descent;
196 -
		tex->w = XTextWidth(font->xfont, text, len);
197 -
	}
380 +
	XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
381 +
	tex->h = font->h;
382 +
	tex->w = ext.xOff;
198 383
}
199 384
200 385
unsigned int
drw.h +12 −7
1 1
/* See LICENSE file for copyright and license details. */
2 +
#define DRW_FONT_CACHE_SIZE 32
2 3
3 4
typedef struct {
4 -
	unsigned long rgb;
5 +
	unsigned long pix;
6 +
	XftColor rgb;
5 7
} Clr;
6 8
7 9
typedef struct {
9 11
} Cur;
10 12
11 13
typedef struct {
14 +
	Display *dpy;
12 15
	int ascent;
13 16
	int descent;
14 17
	unsigned int h;
15 -
	XFontSet set;
16 -
	XFontStruct *xfont;
18 +
	XftFont *xfont;
19 +
	FcPattern *pattern;
17 20
} Fnt;
18 21
19 22
typedef struct {
30 33
	Drawable drawable;
31 34
	GC gc;
32 35
	ClrScheme *scheme;
33 -
	Fnt *font;
36 +
	size_t fontcount;
37 +
	Fnt *fonts[DRW_FONT_CACHE_SIZE];
34 38
} Drw;
35 39
36 40
typedef struct {
44 48
void drw_free(Drw *drw);
45 49
46 50
/* Fnt abstraction */
47 -
Fnt *drw_font_create(Display *dpy, const char *fontname);
48 -
void drw_font_free(Display *dpy, Fnt *font);
51 +
Fnt *drw_font_create(Drw *drw, const char *fontname);
52 +
void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount);
53 +
void drw_font_free(Fnt *font);
49 54
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts);
50 55
unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len);
51 56
63 68
64 69
/* Drawing functions */
65 70
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert);
66 -
void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
71 +
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
67 72
68 73
/* Map functions */
69 74
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
dwm.c +10 −10
39 39
#ifdef XINERAMA
40 40
#include <X11/extensions/Xinerama.h>
41 41
#endif /* XINERAMA */
42 +
#include <X11/Xft/Xft.h>
42 43
43 44
#include "drw.h"
44 45
#include "util.h"
54 55
#define WIDTH(X)                ((X)->w + 2 * (X)->bw)
55 56
#define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
56 57
#define TAGMASK                 ((1 << LENGTH(tags)) - 1)
57 -
#define TEXTW(X)                (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h)
58 +
#define TEXTW(X)                (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
58 59
59 60
/* enums */
60 61
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
263 264
static ClrScheme scheme[SchemeLast];
264 265
static Display *dpy;
265 266
static Drw *drw;
266 -
static Fnt *fnt;
267 267
static Monitor *mons, *selmon;
268 268
static Window root;
269 269
474 474
	drw_cur_free(drw, cursor[CurNormal]);
475 475
	drw_cur_free(drw, cursor[CurResize]);
476 476
	drw_cur_free(drw, cursor[CurMove]);
477 -
	drw_font_free(dpy, fnt);
478 477
	drw_clr_free(scheme[SchemeNorm].border);
479 478
	drw_clr_free(scheme[SchemeNorm].bg);
480 479
	drw_clr_free(scheme[SchemeNorm].fg);
792 791
		detachstack(c);
793 792
		attachstack(c);
794 793
		grabbuttons(c, True);
795 -
		XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->rgb);
794 +
		XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix);
796 795
		setfocus(c);
797 796
	}
798 797
	else {
1040 1039
1041 1040
	wc.border_width = c->bw;
1042 1041
	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
1043 -
	XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb);
1042 +
	XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix);
1044 1043
	configure(c); /* propagates border_width, if size doesn't change */
1045 1044
	updatewindowtype(c);
1046 1045
	updatesizehints(c);
1505 1504
1506 1505
	/* init screen */
1507 1506
	screen = DefaultScreen(dpy);
1508 -
	root = RootWindow(dpy, screen);
1509 -
	fnt = drw_font_create(dpy, font);
1510 1507
	sw = DisplayWidth(dpy, screen);
1511 1508
	sh = DisplayHeight(dpy, screen);
1512 -
	bh = fnt->h + 2;
1509 +
	root = RootWindow(dpy, screen);
1513 1510
	drw = drw_create(dpy, screen, root, sw, sh);
1514 -
	drw_setfont(drw, fnt);
1511 +
	drw_load_fonts(drw, fonts, LENGTH(fonts));
1512 +
	if (!drw->fontcount)
1513 +
		die("No fonts could be loaded.\n");
1514 +
	bh = drw->fonts[0]->h + 2;
1515 1515
	updategeom();
1516 1516
	/* init atoms */
1517 1517
	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
1685 1685
	if(!c)
1686 1686
		return;
1687 1687
	grabbuttons(c, False);
1688 -
	XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb);
1688 +
	XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix);
1689 1689
	if(setfocus) {
1690 1690
		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
1691 1691
		XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
util.h +1 −0
2 2
3 3
#define MAX(A, B)               ((A) > (B) ? (A) : (B))
4 4
#define MIN(A, B)               ((A) < (B) ? (A) : (B))
5 +
#define BETWEEN(X, A, B)        ((A) <= (X) && (X) <= (B))
5 6
6 7
void die(const char *errstr, ...);