Hello, > This is what I had initially but this caused some bug because it causes > mismatch between drw_fontset_getwidth() vs the width that actually gets > rendered. On the first call, drw_fontset_getwidth() will calculate the > width with invalid_width being 0 but when rendering it will be non-zero > which messes up some calculation.
I've attached a patch that fixes this. > I'm also noticing now that if you put an invalid byte at the very end it > fails to render the ellipsis when truncating the text. To reproduce try > to put as many 'a' in there to push the invalid byte *just* beyond the > width of the reigion. > > $ printf "aaaaa....aaaaa\xff" | ./dmenu > > I've attached a pic where there should be an ellipsis at the end but > isn't. > > I remember testing this case and fixing it by doing the > `invalid_width = -1` thing so that it gets initialized even when not > rendering. But now it happens even after I revert this patch. Weird. > I'll look into what's going wrong here and fix it. This bug is not fixed yet. I had a bunch of unexpected things happen last week and so I wasn't able to work on it. I did figure out the cause of the bug though, if someone wants to work out a patch before I get to this, feel free. Basically, the issue seems to be here: if (charexists) { drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); In the case of error, this sets `tmpw` to 0 instead of `invalid_width` which is messing up the ellipsis calculation. I tried doing something like this, which fixes certain cases, but still is buggy on some other cases: if (charexists) { - drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); + if (utf8err) + tmpw = invalid_width; + else + drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); - NRK
>From dfec151bcb3f5d152b59b15418e11da96ee026d6 Mon Sep 17 00:00:00 2001 From: NRK <n...@disroot.org> Date: Wed, 17 Jul 2024 10:57:39 +0000 Subject: [PATCH] move {ellipsis,invalid}_width initialization to drw_fontset_create currently invalid_width will be 0 on the first getwidth call but non-zero when rendering. this patch fixes this de-sync which can cause width calculation issues. this is also simpler this way since we don't need to worry about doing weird dance to avoid infinite recursion. --- drw.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drw.c b/drw.c index 344de61..2db2a5d 100644 --- a/drw.c +++ b/drw.c @@ -9,6 +9,8 @@ #include "util.h" #define UTF_INVALID 0xFFFD +static int ellipsis_width, invalid_width; +static const char INVALID[] = "�", ELLIPSIS[] = "..."; static int utf8decode(const char *s_in, long *u, int *err) @@ -139,8 +141,8 @@ xfont_free(Fnt *font) free(font); } -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +Fnt * +drw_fontset_create(Drw *drw, const char *fonts[], size_t fontcount) { Fnt *cur, *ret = NULL; size_t i; @@ -154,7 +156,12 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) ret = cur; } } - return (drw->fonts = ret); + drw->fonts = ret; + if (drw->fonts) { + invalid_width = drw_fontset_getwidth(drw, INVALID); + ellipsis_width = drw_fontset_getwidth(drw, ELLIPSIS); + } + return ret; } void @@ -237,8 +244,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp XftResult result; int charexists = 0, overflow = 0; /* keep track of a couple codepoints for which we have no match. */ - static unsigned int nomatches[128], ellipsis_width, invalid_width; - static const char invalid[] = "�"; + static unsigned int nomatches[128]; if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) return 0; @@ -256,10 +262,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } usedfont = drw->fonts; - if (!ellipsis_width && render) - ellipsis_width = drw_fontset_getwidth(drw, "..."); - if (!invalid_width && render) - invalid_width = drw_fontset_getwidth(drw, invalid); while (1) { ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0; utf8str = text; @@ -314,12 +316,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } if (utf8err && (!render || invalid_width < w)) { if (render) - drw_text(drw, x, y, w, h, 0, invalid, invert); + drw_text(drw, x, y, w, h, 0, INVALID, invert); x += invalid_width; w -= invalid_width; } if (render && overflow) - drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, ELLIPSIS, invert); if (!*text || overflow) { break; -- 2.42.0