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 <[email protected]>
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