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, ...);