Skip to content

Commit d3f93c7

Browse files
committed
sync latest drw.{c,h} changes from dmenu
1 parent cd0773c commit d3f93c7

File tree

2 files changed

+59
-30
lines changed

2 files changed

+59
-30
lines changed

drw.c

+58-30
Original file line numberDiff line numberDiff line change
@@ -251,26 +251,28 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
251251
int
252252
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
253253
{
254-
char buf[1024];
255-
int ty;
256-
unsigned int ew;
254+
int i, ty, ellipsis_x = 0;
255+
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
257256
XftDraw *d = NULL;
258257
Fnt *usedfont, *curfont, *nextfont;
259-
size_t i, len;
260258
int utf8strlen, utf8charlen, render = x || y || w || h;
261259
long utf8codepoint = 0;
262260
const char *utf8str;
263261
FcCharSet *fccharset;
264262
FcPattern *fcpattern;
265263
FcPattern *match;
266264
XftResult result;
267-
int charexists = 0;
265+
int charexists = 0, overflow = 0;
266+
/* keep track of a couple codepoints for which we have no match. */
267+
enum { nomatches_len = 64 };
268+
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
269+
static unsigned int ellipsis_width = 0;
268270

269-
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
271+
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
270272
return 0;
271273

272274
if (!render) {
273-
w = ~w;
275+
w = invert ? invert : ~invert;
274276
} else {
275277
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
276278
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
@@ -282,55 +284,64 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
282284
}
283285

284286
usedfont = drw->fonts;
287+
if (!ellipsis_width && render)
288+
ellipsis_width = drw_fontset_getwidth(drw, "...");
285289
while (1) {
286-
utf8strlen = 0;
290+
ew = ellipsis_len = utf8strlen = 0;
287291
utf8str = text;
288292
nextfont = NULL;
289293
while (*text) {
290294
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
291295
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
292296
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
293297
if (charexists) {
294-
if (curfont == usedfont) {
298+
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
299+
if (ew + ellipsis_width <= w) {
300+
/* keep track where the ellipsis still fits */
301+
ellipsis_x = x + ew;
302+
ellipsis_w = w - ew;
303+
ellipsis_len = utf8strlen;
304+
}
305+
306+
if (ew + tmpw > w) {
307+
overflow = 1;
308+
/* called from drw_fontset_getwidth_clamp():
309+
* it wants the width AFTER the overflow
310+
*/
311+
if (!render)
312+
x += tmpw;
313+
else
314+
utf8strlen = ellipsis_len;
315+
} else if (curfont == usedfont) {
295316
utf8strlen += utf8charlen;
296317
text += utf8charlen;
318+
ew += tmpw;
297319
} else {
298320
nextfont = curfont;
299321
}
300322
break;
301323
}
302324
}
303325

304-
if (!charexists || nextfont)
326+
if (overflow || !charexists || nextfont)
305327
break;
306328
else
307329
charexists = 0;
308330
}
309331

310332
if (utf8strlen) {
311-
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
312-
/* shorten text if necessary */
313-
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
314-
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
315-
316-
if (len) {
317-
memcpy(buf, utf8str, len);
318-
buf[len] = '\0';
319-
if (len < utf8strlen)
320-
for (i = len; i && i > len - 3; buf[--i] = '.')
321-
; /* NOP */
322-
323-
if (render) {
324-
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
325-
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
326-
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
327-
}
328-
x += ew;
329-
w -= ew;
333+
if (render) {
334+
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
335+
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
336+
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
330337
}
338+
x += ew;
339+
w -= ew;
331340
}
341+
if (render && overflow)
342+
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
332343

333-
if (!*text) {
344+
if (!*text || overflow) {
334345
break;
335346
} else if (nextfont) {
336347
charexists = 0;
@@ -340,6 +351,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
340351
* character must be drawn. */
341352
charexists = 1;
342353

354+
for (i = 0; i < nomatches_len; ++i) {
355+
/* avoid calling XftFontMatch if we know we won't find a match */
356+
if (utf8codepoint == nomatches.codepoint[i])
357+
goto no_match;
358+
}
359+
343360
fccharset = FcCharSetCreate();
344361
FcCharSetAddChar(fccharset, utf8codepoint);
345362

@@ -368,6 +385,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
368385
curfont->next = usedfont;
369386
} else {
370387
xfont_free(usedfont);
388+
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
389+
no_match:
371390
usedfont = drw->fonts;
372391
}
373392
}
@@ -397,6 +416,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
397416
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
398417
}
399418

419+
unsigned int
420+
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
421+
{
422+
unsigned int tmp = 0;
423+
if (drw && drw->fonts && text && n)
424+
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
425+
return MIN(n, tmp);
426+
}
427+
400428
void
401429
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
402430
{

drw.h

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ void drw_free(Drw *drw);
3535
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
3636
void drw_fontset_free(Fnt* set);
3737
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
38+
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
3839
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
3940

4041
/* Colorscheme abstraction */

0 commit comments

Comments
 (0)