aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drw.c165
-rw-r--r--drw.h34
2 files changed, 106 insertions, 93 deletions
diff --git a/drw.c b/drw.c
index 0423873..6aeb59d 100644
--- a/drw.c
+++ b/drw.c
@@ -9,7 +9,7 @@
9#include "util.h" 9#include "util.h"
10 10
11#define UTF_INVALID 0xFFFD 11#define UTF_INVALID 0xFFFD
12#define UTF_SIZ 4 12#define UTF_SIZ 4
13 13
14static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 14static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
15static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 15static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
@@ -17,49 +17,55 @@ static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000
17static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 17static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
18 18
19static long 19static long
20utf8decodebyte(const char c, size_t *i) { 20utf8decodebyte(const char c, size_t *i)
21 for(*i = 0; *i < (UTF_SIZ + 1); ++(*i)) 21{
22 if(((unsigned char)c & utfmask[*i]) == utfbyte[*i]) 22 for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
23 if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
23 return (unsigned char)c & ~utfmask[*i]; 24 return (unsigned char)c & ~utfmask[*i];
24 return 0; 25 return 0;
25} 26}
26 27
27static size_t 28static size_t
28utf8validate(long *u, size_t i) { 29utf8validate(long *u, size_t i)
29 if(!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) 30{
31 if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
30 *u = UTF_INVALID; 32 *u = UTF_INVALID;
31 for(i = 1; *u > utfmax[i]; ++i) 33 for (i = 1; *u > utfmax[i]; ++i)
32 ; 34 ;
33 return i; 35 return i;
34} 36}
35 37
36static size_t 38static size_t
37utf8decode(const char *c, long *u, size_t clen) { 39utf8decode(const char *c, long *u, size_t clen)
40{
38 size_t i, j, len, type; 41 size_t i, j, len, type;
39 long udecoded; 42 long udecoded;
40 43
41 *u = UTF_INVALID; 44 *u = UTF_INVALID;
42 if(!clen) 45 if (!clen)
43 return 0; 46 return 0;
44 udecoded = utf8decodebyte(c[0], &len); 47 udecoded = utf8decodebyte(c[0], &len);
45 if(!BETWEEN(len, 1, UTF_SIZ)) 48 if (!BETWEEN(len, 1, UTF_SIZ))
46 return 1; 49 return 1;
47 for(i = 1, j = 1; i < clen && j < len; ++i, ++j) { 50 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
48 udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); 51 udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
49 if(type != 0) 52 if (type)
50 return j; 53 return j;
51 } 54 }
52 if(j < len) 55 if (j < len)
53 return 0; 56 return 0;
54 *u = udecoded; 57 *u = udecoded;
55 utf8validate(u, len); 58 utf8validate(u, len);
59
56 return len; 60 return len;
57} 61}
58 62
59Drw * 63Drw *
60drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) { 64drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
61 Drw *drw = (Drw *)calloc(1, sizeof(Drw)); 65{
62 if(!drw) 66 Drw *drw;
67
68 if (!(drw = calloc(1, sizeof(Drw))))
63 return NULL; 69 return NULL;
64 drw->dpy = dpy; 70 drw->dpy = dpy;
65 drw->screen = screen; 71 drw->screen = screen;
@@ -70,27 +76,29 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
70 drw->gc = XCreateGC(dpy, root, 0, NULL); 76 drw->gc = XCreateGC(dpy, root, 0, NULL);
71 drw->fontcount = 0; 77 drw->fontcount = 0;
72 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); 78 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
79
73 return drw; 80 return drw;
74} 81}
75 82
76void 83void
77drw_resize(Drw *drw, unsigned int w, unsigned int h) { 84drw_resize(Drw *drw, unsigned int w, unsigned int h)
78 if(!drw) 85{
86 if (!drw)
79 return; 87 return;
80 drw->w = w; 88 drw->w = w;
81 drw->h = h; 89 drw->h = h;
82 if(drw->drawable != 0) 90 if (drw->drawable)
83 XFreePixmap(drw->dpy, drw->drawable); 91 XFreePixmap(drw->dpy, drw->drawable);
84 drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); 92 drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
85} 93}
86 94
87void 95void
88drw_free(Drw *drw) { 96drw_free(Drw *drw)
97{
89 size_t i; 98 size_t i;
90 99
91 for (i = 0; i < drw->fontcount; i++) { 100 for (i = 0; i < drw->fontcount; i++)
92 drw_font_free(drw->fonts[i]); 101 drw_font_free(drw->fonts[i]);
93 }
94 XFreePixmap(drw->dpy, drw->drawable); 102 XFreePixmap(drw->dpy, drw->drawable);
95 XFreeGC(drw->dpy, drw->gc); 103 XFreeGC(drw->dpy, drw->gc);
96 free(drw); 104 free(drw);
@@ -100,13 +108,14 @@ drw_free(Drw *drw) {
100 * drw_font_create instead. 108 * drw_font_create instead.
101 */ 109 */
102static Fnt * 110static Fnt *
103drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) { 111drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern)
112{
104 Fnt *font; 113 Fnt *font;
105 114
106 if (!(fontname || fontpattern)) 115 if (!(fontname || fontpattern))
107 die("No font specified.\n"); 116 die("No font specified.\n");
108 117
109 if (!(font = (Fnt *)calloc(1, sizeof(Fnt)))) 118 if (!(font = calloc(1, sizeof(Fnt))))
110 return NULL; 119 return NULL;
111 120
112 if (fontname) { 121 if (fontname) {
@@ -125,11 +134,10 @@ drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) {
125 fprintf(stderr, "error, cannot load font: '%s'\n", fontname); 134 fprintf(stderr, "error, cannot load font: '%s'\n", fontname);
126 } 135 }
127 } else if (fontpattern) { 136 } else if (fontpattern) {
128 if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { 137 if (!(font->xfont = XftFontOpenPattern(drw->dpy, fontpattern)))
129 fprintf(stderr, "error, cannot load font pattern.\n"); 138 fprintf(stderr, "error, cannot load font pattern.\n");
130 } else { 139 else
131 font->pattern = NULL; 140 font->pattern = NULL;
132 }
133 } 141 }
134 142
135 if (!font->xfont) { 143 if (!font->xfont) {
@@ -141,16 +149,19 @@ drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) {
141 font->descent = font->xfont->descent; 149 font->descent = font->xfont->descent;
142 font->h = font->ascent + font->descent; 150 font->h = font->ascent + font->descent;
143 font->dpy = drw->dpy; 151 font->dpy = drw->dpy;
152
144 return font; 153 return font;
145} 154}
146 155
147Fnt* 156Fnt*
148drw_font_create(Drw *drw, const char *fontname) { 157drw_font_create(Drw *drw, const char *fontname)
158{
149 return drw_font_xcreate(drw, fontname, NULL); 159 return drw_font_xcreate(drw, fontname, NULL);
150} 160}
151 161
152void 162void
153drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) { 163drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount)
164{
154 size_t i; 165 size_t i;
155 Fnt *font; 166 Fnt *font;
156 167
@@ -164,59 +175,65 @@ drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) {
164} 175}
165 176
166void 177void
167drw_font_free(Fnt *font) { 178drw_font_free(Fnt *font)
168 if(!font) 179{
180 if (!font)
169 return; 181 return;
170 if(font->pattern) 182 if (font->pattern)
171 FcPatternDestroy(font->pattern); 183 FcPatternDestroy(font->pattern);
172 XftFontClose(font->dpy, font->xfont); 184 XftFontClose(font->dpy, font->xfont);
173 free(font); 185 free(font);
174} 186}
175 187
176Clr * 188Clr *
177drw_clr_create(Drw *drw, const char *clrname) { 189drw_clr_create(Drw *drw, const char *clrname)
190{
178 Clr *clr; 191 Clr *clr;
179 Colormap cmap; 192 Colormap cmap;
180 Visual *vis; 193 Visual *vis;
181 194
182 if(!drw) 195 if (!drw)
183 return NULL; 196 return NULL;
184 clr = (Clr *)calloc(1, sizeof(Clr)); 197 if (!(clr = calloc(1, sizeof(Clr))))
185 if(!clr)
186 return NULL; 198 return NULL;
187 cmap = DefaultColormap(drw->dpy, drw->screen); 199 cmap = DefaultColormap(drw->dpy, drw->screen);
188 vis = DefaultVisual(drw->dpy, drw->screen); 200 vis = DefaultVisual(drw->dpy, drw->screen);
189 if(!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb)) 201 if (!XftColorAllocName(drw->dpy, vis, cmap, clrname, &clr->rgb))
190 die("error, cannot allocate color '%s'\n", clrname); 202 die("error, cannot allocate color '%s'\n", clrname);
191 clr->pix = clr->rgb.pixel; 203 clr->pix = clr->rgb.pixel;
204
192 return clr; 205 return clr;
193} 206}
194 207
195void 208void
196drw_clr_free(Clr *clr) { 209drw_clr_free(Clr *clr)
210{
197 free(clr); 211 free(clr);
198} 212}
199 213
200void 214void
201drw_setscheme(Drw *drw, ClrScheme *scheme) { 215drw_setscheme(Drw *drw, ClrScheme *scheme)
202 if(!drw) 216{
217 if (!drw)
203 return; 218 return;
204 drw->scheme = scheme; 219 drw->scheme = scheme;
205} 220}
206 221
207void 222void
208drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) { 223drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert)
209 if(!drw || !drw->scheme) 224{
225 if (!drw || !drw->scheme)
210 return; 226 return;
211 XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix); 227 XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix);
212 if(filled) 228 if (filled)
213 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1); 229 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1);
214 else if(empty) 230 else if (empty)
215 XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); 231 XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
216} 232}
217 233
218int 234int
219drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) { 235drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert)
236{
220 char buf[1024]; 237 char buf[1024];
221 int tx, ty, th; 238 int tx, ty, th;
222 Extnts tex; 239 Extnts tex;
@@ -234,9 +251,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
234 XftResult result; 251 XftResult result;
235 int charexists = 0; 252 int charexists = 0;
236 253
237 if (!(render = x || y || w || h)) { 254 if (!(render = x || y || w || h))
238 w = ~w; 255 w = ~w;
239 }
240 256
241 if (!drw || !drw->scheme) { 257 if (!drw || !drw->scheme) {
242 return 0; 258 return 0;
@@ -273,24 +289,23 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
273 } 289 }
274 } 290 }
275 291
276 if (!charexists || (nextfont && nextfont != curfont)) { 292 if (!charexists || (nextfont && nextfont != curfont))
277 break; 293 break;
278 } else { 294 else
279 charexists = 0; 295 charexists = 0;
280 }
281 } 296 }
282 297
283 if (utf8strlen) { 298 if (utf8strlen) {
284 drw_font_getexts(curfont, utf8str, utf8strlen, &tex); 299 drw_font_getexts(curfont, utf8str, utf8strlen, &tex);
285 /* shorten text if necessary */ 300 /* shorten text if necessary */
286 for(len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--) 301 for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--)
287 drw_font_getexts(curfont, utf8str, len, &tex); 302 drw_font_getexts(curfont, utf8str, len, &tex);
288 303
289 if (len) { 304 if (len) {
290 memcpy(buf, utf8str, len); 305 memcpy(buf, utf8str, len);
291 buf[len] = '\0'; 306 buf[len] = '\0';
292 if(len < utf8strlen) 307 if (len < utf8strlen)
293 for(i = len; i && i > len - 3; buf[--i] = '.'); 308 for (i = len; i && i > len - 3; buf[--i] = '.');
294 309
295 if (render) { 310 if (render) {
296 th = curfont->ascent + curfont->descent; 311 th = curfont->ascent + curfont->descent;
@@ -298,7 +313,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
298 tx = x + (h / 2); 313 tx = x + (h / 2);
299 XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len); 314 XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len);
300 } 315 }
301
302 x += tex.w; 316 x += tex.w;
303 w -= tex.w; 317 w -= tex.w;
304 } 318 }
@@ -315,17 +329,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
315 */ 329 */
316 charexists = 1; 330 charexists = 1;
317 331
318 if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { 332 if (drw->fontcount >= DRW_FONT_CACHE_SIZE)
319 continue; 333 continue;
320 }
321 334
322 fccharset = FcCharSetCreate(); 335 fccharset = FcCharSetCreate();
323 FcCharSetAddChar(fccharset, utf8codepoint); 336 FcCharSetAddChar(fccharset, utf8codepoint);
324 337
325 if (!drw->fonts[0]->pattern) { 338 if (!drw->fonts[0]->pattern) {
326 /* Refer to the comment in drw_font_xcreate for more 339 /* Refer to the comment in drw_font_xcreate for more
327 * information. 340 * information. */
328 */
329 die("The first font in the cache must be loaded from a font string.\n"); 341 die("The first font in the cache must be loaded from a font string.\n");
330 } 342 }
331 343
@@ -345,36 +357,34 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
345 if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) { 357 if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) {
346 drw->fonts[drw->fontcount++] = curfont; 358 drw->fonts[drw->fontcount++] = curfont;
347 } else { 359 } else {
348 if (curfont) { 360 if (curfont)
349 drw_font_free(curfont); 361 drw_font_free(curfont);
350 }
351 curfont = drw->fonts[0]; 362 curfont = drw->fonts[0];
352 } 363 }
353 } 364 }
354 } 365 }
355 } 366 }
356 367 if (render)
357 if (render) {
358 XftDrawDestroy(d); 368 XftDrawDestroy(d);
359 }
360 369
361 return x; 370 return x;
362} 371}
363 372
364void 373void
365drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { 374drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
366 if(!drw) 375{
376 if (!drw)
367 return; 377 return;
368 XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); 378 XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
369 XSync(drw->dpy, False); 379 XSync(drw->dpy, False);
370} 380}
371 381
372
373void 382void
374drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) { 383drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex)
384{
375 XGlyphInfo ext; 385 XGlyphInfo ext;
376 386
377 if(!font || !text) 387 if (!font || !text)
378 return; 388 return;
379 XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); 389 XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
380 tex->h = font->h; 390 tex->h = font->h;
@@ -382,31 +392,34 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) {
382} 392}
383 393
384unsigned int 394unsigned int
385drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) { 395drw_font_getexts_width(Fnt *font, const char *text, unsigned int len)
396{
386 Extnts tex; 397 Extnts tex;
387 398
388 if(!font) 399 if (!font)
389 return -1; 400 return -1;
390 drw_font_getexts(font, text, len, &tex); 401 drw_font_getexts(font, text, len, &tex);
391 return tex.w; 402 return tex.w;
392} 403}
393 404
394Cur * 405Cur *
395drw_cur_create(Drw *drw, int shape) { 406drw_cur_create(Drw *drw, int shape)
407{
396 Cur *cur; 408 Cur *cur;
397 409
398 if(!drw) 410 if (!drw)
399 return NULL; 411 return NULL;
400 cur = (Cur *)calloc(1, sizeof(Cur)); 412 if (!(cur = calloc(1, sizeof(Cur))))
401 if (!cur)
402 return NULL; 413 return NULL;
403 cur->cursor = XCreateFontCursor(drw->dpy, shape); 414 cur->cursor = XCreateFontCursor(drw->dpy, shape);
415
404 return cur; 416 return cur;
405} 417}
406 418
407void 419void
408drw_cur_free(Drw *drw, Cur *cursor) { 420drw_cur_free(Drw *drw, Cur *cursor)
409 if(!drw || !cursor) 421{
422 if (!drw || !cursor)
410 return; 423 return;
411 XFreeCursor(drw->dpy, cursor->cursor); 424 XFreeCursor(drw->dpy, cursor->cursor);
412 free(cursor); 425 free(cursor);
diff --git a/drw.h b/drw.h
index 536171b..e3b8515 100644
--- a/drw.h
+++ b/drw.h
@@ -43,32 +43,32 @@ typedef struct {
43} Extnts; 43} Extnts;
44 44
45/* Drawable abstraction */ 45/* Drawable abstraction */
46Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); 46Drw *drw_create(Display *, int, Window, unsigned int, unsigned int);
47void drw_resize(Drw *drw, unsigned int w, unsigned int h); 47void drw_resize(Drw *, unsigned int, unsigned int);
48void drw_free(Drw *drw); 48void drw_free(Drw *);
49 49
50/* Fnt abstraction */ 50/* Fnt abstraction */
51Fnt *drw_font_create(Drw *drw, const char *fontname); 51Fnt *drw_font_create(Drw *, const char *);
52void drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount); 52void drw_load_fonts(Drw *, const char *[], size_t);
53void drw_font_free(Fnt *font); 53void drw_font_free(Fnt *);
54void drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *extnts); 54void drw_font_getexts(Fnt *, const char *, unsigned int, Extnts *);
55unsigned int drw_font_getexts_width(Fnt *font, const char *text, unsigned int len); 55unsigned int drw_font_getexts_width(Fnt *, const char *, unsigned int);
56 56
57/* Colour abstraction */ 57/* Colour abstraction */
58Clr *drw_clr_create(Drw *drw, const char *clrname); 58Clr *drw_clr_create(Drw *, const char *);
59void drw_clr_free(Clr *clr); 59void drw_clr_free(Clr *);
60 60
61/* Cursor abstraction */ 61/* Cursor abstraction */
62Cur *drw_cur_create(Drw *drw, int shape); 62Cur *drw_cur_create(Drw *, int);
63void drw_cur_free(Drw *drw, Cur *cursor); 63void drw_cur_free(Drw *, Cur *);
64 64
65/* Drawing context manipulation */ 65/* Drawing context manipulation */
66void drw_setfont(Drw *drw, Fnt *font); 66void drw_setfont(Drw *, Fnt *);
67void drw_setscheme(Drw *drw, ClrScheme *scheme); 67void drw_setscheme(Drw *, ClrScheme *);
68 68
69/* Drawing functions */ 69/* Drawing functions */
70void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert); 70void drw_rect(Drw *, int, int, unsigned int, unsigned int, int, int, int);
71int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert); 71int drw_text(Drw *, int, int, unsigned int, unsigned int, const char *, int);
72 72
73/* Map functions */ 73/* Map functions */
74void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); 74void drw_map(Drw *, Window, int, int, unsigned int, unsigned int);