diff options
Diffstat (limited to 'drw.c')
-rw-r--r-- | drw.c | 241 |
1 files changed, 132 insertions, 109 deletions
@@ -63,9 +63,8 @@ utf8decode(const char *c, long *u, size_t clen) | |||
63 | Drw * | 63 | Drw * |
64 | drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) | 64 | drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) |
65 | { | 65 | { |
66 | Drw *drw; | 66 | Drw *drw = ecalloc(1, sizeof(Drw)); |
67 | 67 | ||
68 | drw = ecalloc(1, sizeof(Drw)); | ||
69 | drw->dpy = dpy; | 68 | drw->dpy = dpy; |
70 | drw->screen = screen; | 69 | drw->screen = screen; |
71 | drw->root = root; | 70 | drw->root = root; |
@@ -73,7 +72,6 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h | |||
73 | drw->h = h; | 72 | drw->h = h; |
74 | drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); | 73 | drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); |
75 | drw->gc = XCreateGC(dpy, root, 0, NULL); | 74 | drw->gc = XCreateGC(dpy, root, 0, NULL); |
76 | drw->fontcount = 0; | ||
77 | XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); | 75 | XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); |
78 | 76 | ||
79 | return drw; | 77 | return drw; |
@@ -82,6 +80,9 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h | |||
82 | void | 80 | void |
83 | drw_resize(Drw *drw, unsigned int w, unsigned int h) | 81 | drw_resize(Drw *drw, unsigned int w, unsigned int h) |
84 | { | 82 | { |
83 | if (!drw) | ||
84 | return; | ||
85 | |||
85 | drw->w = w; | 86 | drw->w = w; |
86 | drw->h = h; | 87 | drw->h = h; |
87 | if (drw->drawable) | 88 | if (drw->drawable) |
@@ -92,44 +93,39 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) | |||
92 | void | 93 | void |
93 | drw_free(Drw *drw) | 94 | drw_free(Drw *drw) |
94 | { | 95 | { |
95 | size_t i; | ||
96 | |||
97 | for (i = 0; i < drw->fontcount; i++) | ||
98 | drw_font_free(drw->fonts[i]); | ||
99 | XFreePixmap(drw->dpy, drw->drawable); | 96 | XFreePixmap(drw->dpy, drw->drawable); |
100 | XFreeGC(drw->dpy, drw->gc); | 97 | XFreeGC(drw->dpy, drw->gc); |
101 | free(drw); | 98 | free(drw); |
102 | } | 99 | } |
103 | 100 | ||
104 | /* This function is an implementation detail. Library users should use | 101 | /* This function is an implementation detail. Library users should use |
105 | * drw_font_create instead. | 102 | * drw_fontset_create instead. |
106 | */ | 103 | */ |
107 | static Fnt * | 104 | static Fnt * |
108 | drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) | 105 | xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) |
109 | { | 106 | { |
110 | Fnt *font; | 107 | Fnt *font; |
111 | XftFont *xfont = NULL; | 108 | XftFont *xfont = NULL; |
112 | FcPattern *pattern = NULL; | 109 | FcPattern *pattern = NULL; |
113 | 110 | ||
114 | if (fontname) { | 111 | if (fontname) { |
115 | /* Using the pattern found at font->xfont->pattern does not yield same | 112 | /* Using the pattern found at font->xfont->pattern does not yield the |
116 | * the same substitution results as using the pattern returned by | 113 | * same substitution results as using the pattern returned by |
117 | * FcNameParse; using the latter results in the desired fallback | 114 | * FcNameParse; using the latter results in the desired fallback |
118 | * behaviour whereas the former just results in | 115 | * behaviour whereas the former just results in missing-character |
119 | * missing-character-rectangles being drawn, at least with some fonts. | 116 | * rectangles being drawn, at least with some fonts. */ |
120 | */ | ||
121 | if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { | 117 | if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { |
122 | fprintf(stderr, "error, cannot load font: '%s'\n", fontname); | 118 | fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); |
123 | return NULL; | 119 | return NULL; |
124 | } | 120 | } |
125 | if (!(pattern = FcNameParse((FcChar8 *) fontname))) { | 121 | if (!(pattern = FcNameParse((FcChar8 *) fontname))) { |
126 | fprintf(stderr, "error, cannot load font: '%s'\n", fontname); | 122 | fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); |
127 | XftFontClose(drw->dpy, xfont); | 123 | XftFontClose(drw->dpy, xfont); |
128 | return NULL; | 124 | return NULL; |
129 | } | 125 | } |
130 | } else if (fontpattern) { | 126 | } else if (fontpattern) { |
131 | if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { | 127 | if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { |
132 | fprintf(stderr, "error, cannot load font pattern.\n"); | 128 | fprintf(stderr, "error, cannot load font from pattern.\n"); |
133 | return NULL; | 129 | return NULL; |
134 | } | 130 | } |
135 | } else { | 131 | } else { |
@@ -139,95 +135,115 @@ drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern) | |||
139 | font = ecalloc(1, sizeof(Fnt)); | 135 | font = ecalloc(1, sizeof(Fnt)); |
140 | font->xfont = xfont; | 136 | font->xfont = xfont; |
141 | font->pattern = pattern; | 137 | font->pattern = pattern; |
142 | font->ascent = xfont->ascent; | 138 | font->h = xfont->ascent + xfont->descent; |
143 | font->descent = xfont->descent; | ||
144 | font->h = font->ascent + font->descent; | ||
145 | font->dpy = drw->dpy; | 139 | font->dpy = drw->dpy; |
146 | 140 | ||
147 | return font; | 141 | return font; |
148 | } | 142 | } |
149 | 143 | ||
150 | Fnt* | 144 | static void |
151 | drw_font_create(Drw *drw, const char *fontname) | 145 | xfont_free(Fnt *font) |
152 | { | 146 | { |
153 | return drw_font_xcreate(drw, fontname, NULL); | 147 | if (!font) |
148 | return; | ||
149 | if (font->pattern) | ||
150 | FcPatternDestroy(font->pattern); | ||
151 | XftFontClose(font->dpy, font->xfont); | ||
152 | free(font); | ||
154 | } | 153 | } |
155 | 154 | ||
156 | void | 155 | Fnt* |
157 | drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount) | 156 | drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) |
158 | { | 157 | { |
158 | Fnt *cur, *ret = NULL; | ||
159 | size_t i; | 159 | size_t i; |
160 | Fnt *font; | ||
161 | 160 | ||
162 | for (i = 0; i < fontcount; i++) { | 161 | if (!drw || !fonts) |
163 | if (drw->fontcount >= DRW_FONT_CACHE_SIZE) { | 162 | return NULL; |
164 | die("Font cache exhausted.\n"); | 163 | |
165 | } else if ((font = drw_font_xcreate(drw, fonts[i], NULL))) { | 164 | for (i = 1; i <= fontcount; i++) { |
166 | drw->fonts[drw->fontcount++] = font; | 165 | if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { |
166 | cur->next = ret; | ||
167 | ret = cur; | ||
167 | } | 168 | } |
168 | } | 169 | } |
170 | return (drw->fonts = ret); | ||
169 | } | 171 | } |
170 | 172 | ||
171 | void | 173 | void |
172 | drw_font_free(Fnt *font) | 174 | drw_fontset_free(Fnt *font) |
173 | { | 175 | { |
174 | if (!font) | 176 | if (font) { |
175 | return; | 177 | drw_fontset_free(font->next); |
176 | if (font->pattern) | 178 | xfont_free(font); |
177 | FcPatternDestroy(font->pattern); | 179 | } |
178 | XftFontClose(font->dpy, font->xfont); | ||
179 | free(font); | ||
180 | } | 180 | } |
181 | 181 | ||
182 | Clr * | 182 | void |
183 | drw_clr_create(Drw *drw, const char *clrname) | 183 | drw_clr_create(Drw *drw, Clr *dest, const char *clrname) |
184 | { | 184 | { |
185 | Clr *clr; | 185 | if (!drw || !dest || !clrname) |
186 | return; | ||
186 | 187 | ||
187 | clr = ecalloc(1, sizeof(Clr)); | ||
188 | if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), | 188 | if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), |
189 | DefaultColormap(drw->dpy, drw->screen), | 189 | DefaultColormap(drw->dpy, drw->screen), |
190 | clrname, &clr->rgb)) | 190 | clrname, dest)) |
191 | die("error, cannot allocate color '%s'\n", clrname); | 191 | die("error, cannot allocate color '%s'\n", clrname); |
192 | clr->pix = clr->rgb.pixel; | 192 | } |
193 | |||
194 | /* Wrapper to create color schemes. The caller has to call free(3) on the | ||
195 | * returned color scheme when done using it. */ | ||
196 | Clr * | ||
197 | drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) | ||
198 | { | ||
199 | size_t i; | ||
200 | Clr *ret; | ||
193 | 201 | ||
194 | return clr; | 202 | /* need at least two colors for a scheme */ |
203 | if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) | ||
204 | return NULL; | ||
205 | |||
206 | for (i = 0; i < clrcount; i++) | ||
207 | drw_clr_create(drw, &ret[i], clrnames[i]); | ||
208 | return ret; | ||
195 | } | 209 | } |
196 | 210 | ||
197 | void | 211 | void |
198 | drw_clr_free(Clr *clr) | 212 | drw_setfontset(Drw *drw, Fnt *set) |
199 | { | 213 | { |
200 | free(clr); | 214 | if (drw) |
215 | drw->fonts = set; | ||
201 | } | 216 | } |
202 | 217 | ||
203 | void | 218 | void |
204 | drw_setscheme(Drw *drw, ClrScheme *scheme) | 219 | drw_setscheme(Drw *drw, Clr *scm) |
205 | { | 220 | { |
206 | drw->scheme = scheme; | 221 | if (drw) |
222 | drw->scheme = scm; | ||
207 | } | 223 | } |
208 | 224 | ||
209 | void | 225 | void |
210 | drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert) | 226 | drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) |
211 | { | 227 | { |
212 | if (!drw->scheme) | 228 | if (!drw || !drw->scheme) |
213 | return; | 229 | return; |
214 | XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix); | 230 | XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); |
215 | if (filled) | 231 | if (filled) |
216 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1); | 232 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); |
217 | else if (empty) | 233 | else |
218 | XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | 234 | XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); |
219 | } | 235 | } |
220 | 236 | ||
221 | int | 237 | int |
222 | drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert) | 238 | drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) |
223 | { | 239 | { |
224 | char buf[1024]; | 240 | char buf[1024]; |
225 | int tx, ty, th; | 241 | int ty; |
226 | Extnts tex; | 242 | unsigned int ew; |
227 | XftDraw *d = NULL; | 243 | XftDraw *d = NULL; |
228 | Fnt *curfont, *nextfont; | 244 | Fnt *usedfont, *curfont, *nextfont; |
229 | size_t i, len; | 245 | size_t i, len; |
230 | int utf8strlen, utf8charlen, render; | 246 | int utf8strlen, utf8charlen, render = x || y || w || h; |
231 | long utf8codepoint = 0; | 247 | long utf8codepoint = 0; |
232 | const char *utf8str; | 248 | const char *utf8str; |
233 | FcCharSet *fccharset; | 249 | FcCharSet *fccharset; |
@@ -236,66 +252,67 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | |||
236 | XftResult result; | 252 | XftResult result; |
237 | int charexists = 0; | 253 | int charexists = 0; |
238 | 254 | ||
239 | if (!drw->scheme || !drw->fontcount) | 255 | if (!drw || (render && !drw->scheme) || !text || !drw->fonts) |
240 | return 0; | 256 | return 0; |
241 | 257 | ||
242 | if (!(render = x || y || w || h)) { | 258 | if (!render) { |
243 | w = ~w; | 259 | w = ~w; |
244 | } else { | 260 | } else { |
245 | XSetForeground(drw->dpy, drw->gc, invert ? | 261 | XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); |
246 | drw->scheme->fg->pix : drw->scheme->bg->pix); | ||
247 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); | 262 | XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); |
248 | d = XftDrawCreate(drw->dpy, drw->drawable, | 263 | d = XftDrawCreate(drw->dpy, drw->drawable, |
249 | DefaultVisual(drw->dpy, drw->screen), | 264 | DefaultVisual(drw->dpy, drw->screen), |
250 | DefaultColormap(drw->dpy, drw->screen)); | 265 | DefaultColormap(drw->dpy, drw->screen)); |
266 | x += lpad; | ||
267 | w -= lpad; | ||
251 | } | 268 | } |
252 | 269 | ||
253 | curfont = drw->fonts[0]; | 270 | usedfont = drw->fonts; |
254 | while (1) { | 271 | while (1) { |
255 | utf8strlen = 0; | 272 | utf8strlen = 0; |
256 | utf8str = text; | 273 | utf8str = text; |
257 | nextfont = NULL; | 274 | nextfont = NULL; |
258 | while (*text) { | 275 | while (*text) { |
259 | utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); | 276 | utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); |
260 | for (i = 0; i < drw->fontcount; i++) { | 277 | for (curfont = drw->fonts; curfont; curfont = curfont->next) { |
261 | charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint); | 278 | charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); |
262 | if (charexists) { | 279 | if (charexists) { |
263 | if (drw->fonts[i] == curfont) { | 280 | if (curfont == usedfont) { |
264 | utf8strlen += utf8charlen; | 281 | utf8strlen += utf8charlen; |
265 | text += utf8charlen; | 282 | text += utf8charlen; |
266 | } else { | 283 | } else { |
267 | nextfont = drw->fonts[i]; | 284 | nextfont = curfont; |
268 | } | 285 | } |
269 | break; | 286 | break; |
270 | } | 287 | } |
271 | } | 288 | } |
272 | 289 | ||
273 | if (!charexists || (nextfont && nextfont != curfont)) | 290 | if (!charexists || nextfont) |
274 | break; | 291 | break; |
275 | else | 292 | else |
276 | charexists = 0; | 293 | charexists = 0; |
277 | } | 294 | } |
278 | 295 | ||
279 | if (utf8strlen) { | 296 | if (utf8strlen) { |
280 | drw_font_getexts(curfont, utf8str, utf8strlen, &tex); | 297 | drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); |
281 | /* shorten text if necessary */ | 298 | /* shorten text if necessary */ |
282 | for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--) | 299 | for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) |
283 | drw_font_getexts(curfont, utf8str, len, &tex); | 300 | drw_font_getexts(usedfont, utf8str, len, &ew, NULL); |
284 | 301 | ||
285 | if (len) { | 302 | if (len) { |
286 | memcpy(buf, utf8str, len); | 303 | memcpy(buf, utf8str, len); |
287 | buf[len] = '\0'; | 304 | buf[len] = '\0'; |
288 | if (len < utf8strlen) | 305 | if (len < utf8strlen) |
289 | for (i = len; i && i > len - 3; buf[--i] = '.'); | 306 | for (i = len; i && i > len - 3; buf[--i] = '.') |
307 | ; /* NOP */ | ||
290 | 308 | ||
291 | if (render) { | 309 | if (render) { |
292 | th = curfont->ascent + curfont->descent; | 310 | ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; |
293 | ty = y + (h / 2) - (th / 2) + curfont->ascent; | 311 | XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], |
294 | tx = x + (h / 2); | 312 | usedfont->xfont, x, ty, (XftChar8 *)buf, len); |
295 | XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len); | ||
296 | } | 313 | } |
297 | x += tex.w; | 314 | x += ew; |
298 | w -= tex.w; | 315 | w -= ew; |
299 | } | 316 | } |
300 | } | 317 | } |
301 | 318 | ||
@@ -303,26 +320,21 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | |||
303 | break; | 320 | break; |
304 | } else if (nextfont) { | 321 | } else if (nextfont) { |
305 | charexists = 0; | 322 | charexists = 0; |
306 | curfont = nextfont; | 323 | usedfont = nextfont; |
307 | } else { | 324 | } else { |
308 | /* Regardless of whether or not a fallback font is found, the | 325 | /* Regardless of whether or not a fallback font is found, the |
309 | * character must be drawn. | 326 | * character must be drawn. */ |
310 | */ | ||
311 | charexists = 1; | 327 | charexists = 1; |
312 | 328 | ||
313 | if (drw->fontcount >= DRW_FONT_CACHE_SIZE) | ||
314 | continue; | ||
315 | |||
316 | fccharset = FcCharSetCreate(); | 329 | fccharset = FcCharSetCreate(); |
317 | FcCharSetAddChar(fccharset, utf8codepoint); | 330 | FcCharSetAddChar(fccharset, utf8codepoint); |
318 | 331 | ||
319 | if (!drw->fonts[0]->pattern) { | 332 | if (!drw->fonts->pattern) { |
320 | /* Refer to the comment in drw_font_xcreate for more | 333 | /* Refer to the comment in xfont_create for more information. */ |
321 | * information. */ | ||
322 | die("the first font in the cache must be loaded from a font string.\n"); | 334 | die("the first font in the cache must be loaded from a font string.\n"); |
323 | } | 335 | } |
324 | 336 | ||
325 | fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern); | 337 | fcpattern = FcPatternDuplicate(drw->fonts->pattern); |
326 | FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); | 338 | FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); |
327 | FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); | 339 | FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); |
328 | 340 | ||
@@ -334,12 +346,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | |||
334 | FcPatternDestroy(fcpattern); | 346 | FcPatternDestroy(fcpattern); |
335 | 347 | ||
336 | if (match) { | 348 | if (match) { |
337 | curfont = drw_font_xcreate(drw, NULL, match); | 349 | usedfont = xfont_create(drw, NULL, match); |
338 | if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) { | 350 | if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { |
339 | drw->fonts[drw->fontcount++] = curfont; | 351 | for (curfont = drw->fonts; curfont->next; curfont = curfont->next) |
352 | ; /* NOP */ | ||
353 | curfont->next = usedfont; | ||
340 | } else { | 354 | } else { |
341 | drw_font_free(curfont); | 355 | xfont_free(usedfont); |
342 | curfont = drw->fonts[0]; | 356 | usedfont = drw->fonts; |
343 | } | 357 | } |
344 | } | 358 | } |
345 | } | 359 | } |
@@ -347,34 +361,40 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex | |||
347 | if (d) | 361 | if (d) |
348 | XftDrawDestroy(d); | 362 | XftDrawDestroy(d); |
349 | 363 | ||
350 | return x; | 364 | return x + (render ? w : 0); |
351 | } | 365 | } |
352 | 366 | ||
353 | void | 367 | void |
354 | drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) | 368 | drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) |
355 | { | 369 | { |
370 | if (!drw) | ||
371 | return; | ||
372 | |||
356 | XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); | 373 | XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); |
357 | XSync(drw->dpy, False); | 374 | XSync(drw->dpy, False); |
358 | } | 375 | } |
359 | 376 | ||
360 | void | 377 | unsigned int |
361 | drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex) | 378 | drw_fontset_getwidth(Drw *drw, const char *text) |
362 | { | 379 | { |
363 | XGlyphInfo ext; | 380 | if (!drw || !drw->fonts || !text) |
364 | 381 | return 0; | |
365 | XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); | 382 | return drw_text(drw, 0, 0, 0, 0, 0, text, 0); |
366 | tex->h = font->h; | ||
367 | tex->w = ext.xOff; | ||
368 | } | 383 | } |
369 | 384 | ||
370 | unsigned int | 385 | void |
371 | drw_font_getexts_width(Fnt *font, const char *text, unsigned int len) | 386 | drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) |
372 | { | 387 | { |
373 | Extnts tex; | 388 | XGlyphInfo ext; |
374 | 389 | ||
375 | drw_font_getexts(font, text, len, &tex); | 390 | if (!font || !text) |
391 | return; | ||
376 | 392 | ||
377 | return tex.w; | 393 | XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); |
394 | if (w) | ||
395 | *w = ext.xOff; | ||
396 | if (h) | ||
397 | *h = font->h; | ||
378 | } | 398 | } |
379 | 399 | ||
380 | Cur * | 400 | Cur * |
@@ -382,7 +402,9 @@ drw_cur_create(Drw *drw, int shape) | |||
382 | { | 402 | { |
383 | Cur *cur; | 403 | Cur *cur; |
384 | 404 | ||
385 | cur = ecalloc(1, sizeof(Cur)); | 405 | if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) |
406 | return NULL; | ||
407 | |||
386 | cur->cursor = XCreateFontCursor(drw->dpy, shape); | 408 | cur->cursor = XCreateFontCursor(drw->dpy, shape); |
387 | 409 | ||
388 | return cur; | 410 | return cur; |
@@ -393,6 +415,7 @@ drw_cur_free(Drw *drw, Cur *cursor) | |||
393 | { | 415 | { |
394 | if (!cursor) | 416 | if (!cursor) |
395 | return; | 417 | return; |
418 | |||
396 | XFreeCursor(drw->dpy, cursor->cursor); | 419 | XFreeCursor(drw->dpy, cursor->cursor); |
397 | free(cursor); | 420 | free(cursor); |
398 | } | 421 | } |