dwm-6.1-xft-with-fallback-font.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
dwm-6.1-xft-with-fallback-font.diff (19598B)
---
1 Author: Eric Pruitt, https://github.com/ericpruitt/
2 Description: Xft with fallback font support built on top of the Xft patch
3 written by Quentin (http://lists.suckless.org/dev/1311/18279.html). The utf8*
4 functions were written by Damian Okrasa for the MIT/X licensed
5 (http://opensource.org/licenses/MIT) terminal emulator st
6 (http://st.suckless.org/).
7
8 With this patch, the "font" variable in config.h is superseded by the "fonts"
9 variable which is a priority-ordered list of fonts that should be used to
10 render text. Here's an example "fonts" definition:
11
12 static const char *fonts[] = {
13 "Sans:size=10.5",
14 "VL Gothic:size=10.5",
15 "WenQuanYi Micro Hei:size=10.5",
16 };
17
18 At least one font must be specified, and a maximum of DRW_FONT_CACHE_SIZE fonts
19 can be used.
20
21 diff --git a/config.def.h b/config.def.h
22 index 875885b..eaae8f3 100644
23 --- a/config.def.h
24 +++ b/config.def.h
25 @@ -1,7 +1,12 @@
26 /* See LICENSE file for copyright and license details. */
27
28 /* appearance */
29 -static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
30 +static const char *fonts[] = {
31 + "Sans:size=10.5",
32 + "VL Gothic:size=10.5",
33 + "WenQuanYi Micro Hei:size=10.5",
34 +};
35 +static const char dmenufont[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*";
36 static const char normbordercolor[] = "#444444";
37 static const char normbgcolor[] = "#222222";
38 static const char normfgcolor[] = "#bbbbbb";
39 @@ -51,7 +56,7 @@ static const Layout layouts[] = {
40
41 /* commands */
42 static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
43 -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
44 +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
45 static const char *termcmd[] = { "st", NULL };
46
47 static Key keys[] = {
48 diff --git a/config.mk b/config.mk
49 index bc3d80e..50b2175 100644
50 --- a/config.mk
51 +++ b/config.mk
52 @@ -11,12 +11,12 @@ X11INC = /usr/X11R6/include
53 X11LIB = /usr/X11R6/lib
54
55 # Xinerama, comment if you don't want it
56 -XINERAMALIBS = -lXinerama
57 -XINERAMAFLAGS = -DXINERAMA
58 +#XINERAMALIBS = -lXinerama
59 +#XINERAMAFLAGS = -DXINERAMA
60
61 # includes and libs
62 -INCS = -I${X11INC}
63 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS}
64 +INCS = -I${X11INC} -I/usr/include/freetype2
65 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} -lfontconfig -lXft
66
67 # flags
68 CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
69 diff --git a/drw.c b/drw.c
70 index b130405..36cf992 100644
71 --- a/drw.c
72 +++ b/drw.c
73 @@ -3,10 +3,59 @@
74 #include <stdlib.h>
75 #include <string.h>
76 #include <X11/Xlib.h>
77 +#include <X11/Xft/Xft.h>
78
79 #include "drw.h"
80 #include "util.h"
81
82 +#define UTF_INVALID 0xFFFD
83 +#define UTF_SIZ 4
84 +
85 +static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
86 +static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
87 +static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
88 +static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
89 +
90 +static long
91 +utf8decodebyte(const char c, size_t *i) {
92 + for(*i = 0; *i < (UTF_SIZ + 1); ++(*i))
93 + if(((unsigned char)c & utfmask[*i]) == utfbyte[*i])
94 + return (unsigned char)c & ~utfmask[*i];
95 + return 0;
96 +}
97 +
98 +static size_t
99 +utf8validate(long *u, size_t i) {
100 + if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
101 + *u = UTF_INVALID;
102 + for(i = 1; *u > utfmax[i]; ++i)
103 + ;
104 + return i;
105 +}
106 +
107 +static size_t
108 +utf8decode(const char *c, long *u, size_t clen) {
109 + size_t i, j, len, type;
110 + long udecoded;
111 +
112 + *u = UTF_INVALID;
113 + if(!clen)
114 + return 0;
115 + udecoded = utf8decodebyte(c[0], &len);
116 + if(!BETWEEN(len, 1, UTF_SIZ))
117 + return 1;
118 + for(i = 1, j = 1; i < clen && j < len; ++i, ++j) {
119 + udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
120 + if(type != 0)
121 + return j;
122 + }
123 + if(j < len)
124 + return 0;
125 + *u = udecoded;
126 + utf8validate(u, len);
127 + return len;
128 +}
129 +
130 Drw *
131 drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) {
132 Drw *drw = (Drw *)calloc(1, sizeof(Drw));
133 @@ -19,6 +68,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
134 drw->h = h;
135 drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
136 drw->gc = XCreateGC(dpy, root, 0, NULL);
137 + drw->fontcount = 0;
138 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
139 return drw;
140 }
141 @@ -36,56 +86,79 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) {
142
143 void
144 drw_free(Drw *drw) {
145 + size_t i;
146 + for (i = 0; i < drw->fontcount; i++) {
147 + drw_font_free(drw->fonts[i]);
148 + }
149 XFreePixmap(drw->dpy, drw->drawable);
150 XFreeGC(drw->dpy, drw->gc);
151 free(drw);
152 }
153
154 Fnt *
155 -drw_font_create(Display *dpy, const char *fontname) {
156 +drw_font_create(Drw *drw, const char *fontname, FcPattern *fontpattern) {
157 Fnt *font;
158 - char *def, **missing;
159 - int n;
160
161 - font = (Fnt *)calloc(1, sizeof(Fnt));
162 - if(!font)
163 + if (!(fontname || fontpattern))
164 + die("No font specified.\n");
165 +
166 + if (!(font = (Fnt *)calloc(1, sizeof(Fnt))))
167 return NULL;
168 - font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def);
169 - if(missing) {
170 - while(n--)
171 - fprintf(stderr, "drw: missing fontset: %s\n", missing[n]);
172 - XFreeStringList(missing);
173 - }
174 - if(font->set) {
175 - XFontStruct **xfonts;
176 - char **font_names;
177 - XExtentsOfFontSet(font->set);
178 - n = XFontsOfFontSet(font->set, &xfonts, &font_names);
179 - while(n--) {
180 - font->ascent = MAX(font->ascent, (*xfonts)->ascent);
181 - font->descent = MAX(font->descent,(*xfonts)->descent);
182 - xfonts++;
183 +
184 + if (fontname) {
185 + // Using the pattern found at font->xfont->pattern does not yield same
186 + // the same substitution results as using the pattern returned by
187 + // FcNameParse; using the latter results in the desired fallback
188 + // behaviour whereas the former just results in
189 + // missing-character-rectangles being drawn, at least with some fonts.
190 + if (!(font->xfont = XftFontOpenName(drw->dpy, drw->screen, fontname)) ||
191 + !(font->pattern = FcNameParse((FcChar8 *) fontname))) {
192 + if (font->xfont)
193 + XftFontClose(font->dpy, font->xfont);
194 + fprintf(stderr, "error, cannot load font: '%s'\n", fontname);
195 + }
196 + } else if (fontpattern) {
197 + if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
198 + fprintf(stderr, "error, cannot load font pattern.\n");
199 + } else {
200 + font->pattern = NULL;
201 }
202 }
203 - else {
204 - if(!(font->xfont = XLoadQueryFont(dpy, fontname))
205 - && !(font->xfont = XLoadQueryFont(dpy, "fixed")))
206 - die("error, cannot load font: '%s'\n", fontname);
207 - font->ascent = font->xfont->ascent;
208 - font->descent = font->xfont->descent;
209 +
210 + if (!font->xfont) {
211 + free(font);
212 + return NULL;
213 }
214 +
215 + font->ascent = font->xfont->ascent;
216 + font->descent = font->xfont->descent;
217 font->h = font->ascent + font->descent;
218 + font->dpy = drw->dpy;
219 return font;
220 }
221
222 void
223 -drw_font_free(Display *dpy, Fnt *font) {
224 +drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) {
225 + size_t i;
226 + Fnt *font;
227 + for (i = 0; i < fontcount && drw->fontcount < DRW_FONT_CACHE_SIZE; i++) {
228 + if ((font = drw_font_create(drw, fonts[i], NULL))) {
229 + drw->fonts[drw->fontcount++] = font;
230 + }
231 + }
232 +
233 + if (i != fontcount) {
234 + die("Font cache exhausted.\n");
235 + }
236 +}
237 +
238 +void
239 +drw_font_free(Fnt *font) {
240 if(!font)
241 return;
242 - if(font->set)
243 - XFreeFontSet(dpy, font->set);
244 - else
245 - XFreeFont(dpy, font->xfont);
246 + if(font->pattern)
247 + FcPatternDestroy(font->pattern);
248 + XftFontClose(font->dpy, font->xfont);
249 free(font);
250 }
251
252 @@ -93,7 +166,7 @@ Clr *
253 drw_clr_create(Drw *drw, const char *clrname) {
254 Clr *clr;
255 Colormap cmap;
256 - XColor color;
257 + Visual *vis;
258
259 if(!drw)
260 return NULL;
261 @@ -101,9 +174,10 @@ drw_clr_create(Drw *drw, const char *clrname) {
262 if(!clr)
263 return NULL;
264 cmap = DefaultColormap(drw->dpy, drw->screen);
265 - if(!XAllocNamedColor(drw->dpy, cmap, clrname, &color, &color))
266 + vis = DefaultVisual(drw->dpy, drw->screen);
267 + if(!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb))
268 die("error, cannot allocate color '%s'\n", clrname);
269 - clr->rgb = color.pixel;
270 + clr->pix = clr->rgb.pixel;
271 return clr;
272 }
273
274 @@ -114,14 +188,8 @@ drw_clr_free(Clr *clr) {
275 }
276
277 void
278 -drw_setfont(Drw *drw, Fnt *font) {
279 - if(drw)
280 - drw->font = font;
281 -}
282 -
283 -void
284 drw_setscheme(Drw *drw, ClrScheme *scheme) {
285 - if(drw && scheme)
286 + if(drw && scheme)
287 drw->scheme = scheme;
288 }
289
290 @@ -129,46 +197,158 @@ void
291 drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) {
292 int dx;
293
294 - if(!drw || !drw->font || !drw->scheme)
295 + if(!drw || !drw->fontcount || !drw->scheme)
296 return;
297 - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb);
298 - dx = (drw->font->ascent + drw->font->descent + 2) / 4;
299 + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix);
300 + dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4;
301 if(filled)
302 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx+1, dx+1);
303 else if(empty)
304 XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x+1, y+1, dx, dx);
305 }
306
307 -void
308 +int
309 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) {
310 - char buf[256];
311 - int i, tx, ty, th, len, olen;
312 + char buf[1024];
313 + int tx, ty, th;
314 Extnts tex;
315 + Colormap cmap;
316 + Visual *vis;
317 + XftDraw *d;
318 + Fnt *curfont, *nextfont;
319 + size_t i, len;
320 + int utf8strlen, utf8charlen, render;
321 + long utf8codepoint = 0;
322 + const char *utf8str;
323 + FcCharSet *fccharset;
324 + FcPattern *fcpattern;
325 + FcPattern *match;
326 + XftResult result;
327 + int charexists = 0;
328
329 - if(!drw || !drw->scheme)
330 - return;
331 - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->rgb : drw->scheme->bg->rgb);
332 - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
333 - if(!text || !drw->font)
334 - return;
335 - olen = strlen(text);
336 - drw_font_getexts(drw->font, text, olen, &tex);
337 - th = drw->font->ascent + drw->font->descent;
338 - ty = y + (h / 2) - (th / 2) + drw->font->ascent;
339 - tx = x + (h / 2);
340 - /* shorten text if necessary */
341 - for(len = MIN(olen, sizeof buf); len && (tex.w > w - tex.h || w < tex.h); len--)
342 - drw_font_getexts(drw->font, text, len, &tex);
343 - if(!len)
344 - return;
345 - memcpy(buf, text, len);
346 - if(len < olen)
347 - for(i = len; i && i > len - 3; buf[--i] = '.');
348 - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->rgb : drw->scheme->fg->rgb);
349 - if(drw->font->set)
350 - XmbDrawString(drw->dpy, drw->drawable, drw->font->set, drw->gc, tx, ty, buf, len);
351 - else
352 - XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len);
353 + if (!(render = x || y || w || h)) {
354 + w = ~w;
355 + }
356 +
357 + if (!drw || !drw->scheme) {
358 + return 0;
359 + } else if (render) {
360 + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->fg->pix : drw->scheme->bg->pix);
361 + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
362 + }
363 +
364 + if (!text || !drw->fontcount) {
365 + return 0;
366 + } else if (render) {
367 + cmap = DefaultColormap(drw->dpy, drw->screen);
368 + vis = DefaultVisual(drw->dpy, drw->screen);
369 + d = XftDrawCreate(drw->dpy, drw->drawable, vis, cmap);
370 + }
371 +
372 + curfont = drw->fonts[0];
373 + while (1) {
374 + utf8strlen = 0;
375 + utf8str = text;
376 + nextfont = NULL;
377 + while (*text) {
378 + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
379 + for (i = 0; i < drw->fontcount; i++) {
380 + charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint);
381 + if (charexists) {
382 + if (drw->fonts[i] == curfont) {
383 + utf8strlen += utf8charlen;
384 + text += utf8charlen;
385 + } else {
386 + nextfont = drw->fonts[i];
387 + }
388 + break;
389 + }
390 + }
391 +
392 + if (!charexists || (nextfont && nextfont != curfont)) {
393 + break;
394 + } else {
395 + charexists = 0;
396 + }
397 + }
398 +
399 + if (utf8strlen) {
400 + drw_font_getexts(curfont, utf8str, utf8strlen, &tex);
401 + /* shorten text if necessary */
402 + for(len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--)
403 + drw_font_getexts(curfont, utf8str, len, &tex);
404 +
405 + if (len) {
406 + memcpy(buf, utf8str, len);
407 + buf[len] = '\0';
408 + if(len < utf8strlen)
409 + for(i = len; i && i > len - 3; buf[--i] = '.');
410 +
411 + if (render) {
412 + th = curfont->ascent + curfont->descent;
413 + ty = y + (h / 2) - (th / 2) + curfont->ascent;
414 + tx = x + (h / 2);
415 + XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len);
416 + }
417 +
418 + x += tex.w;
419 + w -= tex.w;
420 + }
421 + }
422 +
423 + if (!*text) {
424 + break;
425 + } else if (nextfont) {
426 + charexists = 0;
427 + curfont = nextfont;
428 + } else {
429 + // Regardless of whether or not a fallback font is found, the
430 + // character must be drawn.
431 + charexists = 1;
432 +
433 + if (drw->fontcount >= DRW_FONT_CACHE_SIZE) {
434 + continue;
435 + }
436 +
437 + fccharset = FcCharSetCreate();
438 + FcCharSetAddChar(fccharset, utf8codepoint);
439 +
440 + if (!drw->fonts[0]->pattern) {
441 + // Refer to the comment in drw_font_create for more
442 + // information.
443 + die("The first font in the cache must be loaded from a font string.\n");
444 + }
445 +
446 + fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern);
447 + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
448 + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
449 +
450 + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
451 + FcDefaultSubstitute(fcpattern);
452 + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
453 +
454 + FcCharSetDestroy(fccharset);
455 + FcPatternDestroy(fcpattern);
456 +
457 + if (match) {
458 + curfont = drw_font_create(drw, NULL, match);
459 + if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) {
460 + drw->fonts[drw->fontcount++] = curfont;
461 + } else {
462 + if (curfont) {
463 + drw_font_free(curfont);
464 + }
465 + curfont = drw->fonts[0];
466 + }
467 + }
468 + }
469 + }
470 +
471 + if (render) {
472 + XftDrawDestroy(d);
473 + }
474 +
475 + return x;
476 }
477
478 void
479 @@ -182,19 +362,13 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
480
481 void
482 drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) {
483 - XRectangle r;
484 + XGlyphInfo ext;
485
486 if(!font || !text)
487 return;
488 - if(font->set) {
489 - XmbTextExtents(font->set, text, len, NULL, &r);
490 - tex->w = r.width;
491 - tex->h = r.height;
492 - }
493 - else {
494 - tex->h = font->ascent + font->descent;
495 - tex->w = XTextWidth(font->xfont, text, len);
496 - }
497 + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
498 + tex->h = font->h;
499 + tex->w = ext.xOff;
500 }
501
502 unsigned int
503 diff --git a/drw.h b/drw.h
504 index a5f34e0..02bfefc 100644
505 --- a/drw.h
506 +++ b/drw.h
507 @@ -1,7 +1,9 @@
508 /* See LICENSE file for copyright and license details. */
509 +#define DRW_FONT_CACHE_SIZE 32
510
511 typedef struct {
512 - unsigned long rgb;
513 + unsigned long pix;
514 + XftColor rgb;
515 } Clr;
516
517 typedef struct {
518 @@ -9,11 +11,12 @@ typedef struct {
519 } Cur;
520
521 typedef struct {
522 + Display *dpy;
523 int ascent;
524 int descent;
525 unsigned int h;
526 - XFontSet set;
527 - XFontStruct *xfont;
528 + XftFont *xfont;
529 + FcPattern *pattern;
530 } Fnt;
531
532 typedef struct {
533 @@ -30,7 +33,8 @@ typedef struct {
534 Drawable drawable;
535 GC gc;
536 ClrScheme *scheme;
537 - Fnt *font;
538 + size_t fontcount;
539 + Fnt *fonts[DRW_FONT_CACHE_SIZE];
540 } Drw;
541
542 typedef struct {
543 @@ -44,8 +48,9 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h);
544 void drw_free(Drw *drw);
545
546 /* Fnt abstraction */
547 -Fnt *drw_font_create(Display *dpy, const char *fontname);
548 -void drw_font_free(Display *dpy, Fnt *font);
549 +Fnt *drw_font_create(Drw *drw, const char *fontname, FcPattern *fontpattern);
550 +void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount);
551 +void drw_font_free(Fnt *font);
552 void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts);
553 unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len);
554
555 @@ -63,7 +68,7 @@ void drw_setscheme(Drw *drw, ClrScheme *scheme);
556
557 /* Drawing functions */
558 void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert);
559 -void drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
560 +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert);
561
562 /* Map functions */
563 void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
564 diff --git a/dwm.c b/dwm.c
565 index f896170..169adcb 100644
566 --- a/dwm.c
567 +++ b/dwm.c
568 @@ -39,6 +39,7 @@
569 #ifdef XINERAMA
570 #include <X11/extensions/Xinerama.h>
571 #endif /* XINERAMA */
572 +#include <X11/Xft/Xft.h>
573
574 #include "drw.h"
575 #include "util.h"
576 @@ -54,7 +55,7 @@
577 #define WIDTH(X) ((X)->w + 2 * (X)->bw)
578 #define HEIGHT(X) ((X)->h + 2 * (X)->bw)
579 #define TAGMASK ((1 << LENGTH(tags)) - 1)
580 -#define TEXTW(X) (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h)
581 +#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
582
583 /* enums */
584 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
585 @@ -263,7 +264,6 @@ static Cur *cursor[CurLast];
586 static ClrScheme scheme[SchemeLast];
587 static Display *dpy;
588 static Drw *drw;
589 -static Fnt *fnt;
590 static Monitor *mons, *selmon;
591 static Window root;
592
593 @@ -474,7 +474,6 @@ cleanup(void) {
594 drw_cur_free(drw, cursor[CurNormal]);
595 drw_cur_free(drw, cursor[CurResize]);
596 drw_cur_free(drw, cursor[CurMove]);
597 - drw_font_free(dpy, fnt);
598 drw_clr_free(scheme[SchemeNorm].border);
599 drw_clr_free(scheme[SchemeNorm].bg);
600 drw_clr_free(scheme[SchemeNorm].fg);
601 @@ -792,7 +791,7 @@ focus(Client *c) {
602 detachstack(c);
603 attachstack(c);
604 grabbuttons(c, True);
605 - XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->rgb);
606 + XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix);
607 setfocus(c);
608 }
609 else {
610 @@ -1040,7 +1039,7 @@ manage(Window w, XWindowAttributes *wa) {
611
612 wc.border_width = c->bw;
613 XConfigureWindow(dpy, w, CWBorderWidth, &wc);
614 - XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb);
615 + XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix);
616 configure(c); /* propagates border_width, if size doesn't change */
617 updatewindowtype(c);
618 updatesizehints(c);
619 @@ -1505,13 +1504,14 @@ setup(void) {
620
621 /* init screen */
622 screen = DefaultScreen(dpy);
623 - root = RootWindow(dpy, screen);
624 - fnt = drw_font_create(dpy, font);
625 sw = DisplayWidth(dpy, screen);
626 sh = DisplayHeight(dpy, screen);
627 - bh = fnt->h + 2;
628 + root = RootWindow(dpy, screen);
629 drw = drw_create(dpy, screen, root, sw, sh);
630 - drw_setfont(drw, fnt);
631 + drw_load_fonts(drw, fonts, LENGTH(fonts));
632 + if (!drw->fontcount)
633 + die("No fonts could be loaded.\n");
634 + bh = drw->fonts[0]->h + 2;
635 updategeom();
636 /* init atoms */
637 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
638 @@ -1685,7 +1685,7 @@ unfocus(Client *c, Bool setfocus) {
639 if(!c)
640 return;
641 grabbuttons(c, False);
642 - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb);
643 + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix);
644 if(setfocus) {
645 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
646 XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
647 diff --git a/util.h b/util.h
648 index 033700c..f7ce721 100644
649 --- a/util.h
650 +++ b/util.h
651 @@ -2,5 +2,6 @@
652
653 #define MAX(A, B) ((A) > (B) ? (A) : (B))
654 #define MIN(A, B) ((A) < (B) ? (A) : (B))
655 +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
656
657 void die(const char *errstr, ...);