diff options
| author | Hiltjo Posthuma <hiltjo@codemadness.org> | 2022-05-10 19:07:56 +0200 | 
|---|---|---|
| committer | Hiltjo Posthuma <hiltjo@codemadness.org> | 2022-05-10 19:07:56 +0200 | 
| commit | d3f93c7c1a13a2a78f04fb41ad1935525df948db (patch) | |
| tree | 71f8aef49ea9300abd1cd9204ca80cb828bcaf90 | |
| parent | cd0773cee9bad694dc9a6b1355a32bbe61abadff (diff) | |
| download | dwm-d3f93c7c1a13a2a78f04fb41ad1935525df948db.tar.gz dwm-d3f93c7c1a13a2a78f04fb41ad1935525df948db.zip | |
sync latest drw.{c,h} changes from dmenu
| -rw-r--r-- | drw.c | 88 | ||||
| -rw-r--r-- | drw.h | 1 | 
2 files changed, 59 insertions, 30 deletions
| @@ -251,12 +251,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int  int  drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)  { -	char buf[1024]; -	int ty; -	unsigned int ew; +	int i, ty, ellipsis_x = 0; +	unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;  	XftDraw *d = NULL;  	Fnt *usedfont, *curfont, *nextfont; -	size_t i, len;  	int utf8strlen, utf8charlen, render = x || y || w || h;  	long utf8codepoint = 0;  	const char *utf8str; @@ -264,13 +262,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  	FcPattern *fcpattern;  	FcPattern *match;  	XftResult result; -	int charexists = 0; +	int charexists = 0, overflow = 0; +	/* keep track of a couple codepoints for which we have no match. */ +	enum { nomatches_len = 64 }; +	static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; +	static unsigned int ellipsis_width = 0; -	if (!drw || (render && !drw->scheme) || !text || !drw->fonts) +	if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)  		return 0;  	if (!render) { -		w = ~w; +		w = invert ? invert : ~invert;  	} else {  		XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);  		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); @@ -282,8 +284,10 @@ 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, "...");  	while (1) { -		utf8strlen = 0; +		ew = ellipsis_len = utf8strlen = 0;  		utf8str = text;  		nextfont = NULL;  		while (*text) { @@ -291,9 +295,27 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  			for (curfont = drw->fonts; curfont; curfont = curfont->next) {  				charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);  				if (charexists) { -					if (curfont == usedfont) { +					drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); +					if (ew + ellipsis_width <= w) { +						/* keep track where the ellipsis still fits */ +						ellipsis_x = x + ew; +						ellipsis_w = w - ew; +						ellipsis_len = utf8strlen; +					} + +					if (ew + tmpw > w) { +						overflow = 1; +						/* called from drw_fontset_getwidth_clamp(): +						 * it wants the width AFTER the overflow +						 */ +						if (!render) +							x += tmpw; +						else +							utf8strlen = ellipsis_len; +					} else if (curfont == usedfont) {  						utf8strlen += utf8charlen;  						text += utf8charlen; +						ew += tmpw;  					} else {  						nextfont = curfont;  					} @@ -301,36 +323,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  				}  			} -			if (!charexists || nextfont) +			if (overflow || !charexists || nextfont)  				break;  			else  				charexists = 0;  		}  		if (utf8strlen) { -			drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); -			/* shorten text if necessary */ -			for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) -				drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - -			if (len) { -				memcpy(buf, utf8str, len); -				buf[len] = '\0'; -				if (len < utf8strlen) -					for (i = len; i && i > len - 3; buf[--i] = '.') -						; /* NOP */ - -				if (render) { -					ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; -					XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], -					                  usedfont->xfont, x, ty, (XftChar8 *)buf, len); -				} -				x += ew; -				w -= ew; +			if (render) { +				ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; +				XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], +				                  usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);  			} +			x += ew; +			w -= ew;  		} +		if (render && overflow) +			drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); -		if (!*text) { +		if (!*text || overflow) {  			break;  		} else if (nextfont) {  			charexists = 0; @@ -340,6 +351,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  			 * character must be drawn. */  			charexists = 1; +			for (i = 0; i < nomatches_len; ++i) { +				/* avoid calling XftFontMatch if we know we won't find a match */ +				if (utf8codepoint == nomatches.codepoint[i]) +					goto no_match; +			} +  			fccharset = FcCharSetCreate();  			FcCharSetAddChar(fccharset, utf8codepoint); @@ -368,6 +385,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  					curfont->next = usedfont;  				} else {  					xfont_free(usedfont); +					nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; +no_match:  					usedfont = drw->fonts;  				}  			} @@ -397,6 +416,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)  	return drw_text(drw, 0, 0, 0, 0, 0, text, 0);  } +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ +	unsigned int tmp = 0; +	if (drw && drw->fonts && text && n) +		tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); +	return MIN(n, tmp); +} +  void  drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)  { @@ -35,6 +35,7 @@ void drw_free(Drw *drw);  Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);  void drw_fontset_free(Fnt* set);  unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);  void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);  /* Colorscheme abstraction */ | 
