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