From e63843d36910308338e442f848c763a02b825933 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bert=20M=C3=BCnnich?= <ber.t@posteo.de>
Date: Thu, 7 Dec 2017 21:29:41 +0100
Subject: Simplify drawing of bar text

Non-fitting text is truncated by simply cutting it off.

win_textwidth() has been replaced by a simple macro wrapper around
win_draw_text() with a maximum width of zero, which results in a dry-run that
still calculates the number of pixels used by the text, much like snprintf(3)
with a buffer length of zero.
---
 window.c | 87 +++++++++++++++++++++++++---------------------------------------
 1 file changed, 34 insertions(+), 53 deletions(-)

diff --git a/window.c b/window.c
index b2d72d1..8c233d8 100644
--- a/window.c
+++ b/window.c
@@ -362,50 +362,45 @@ void win_clear(win_t *win)
 	XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
 }
 
-int win_textwidth(const win_env_t *e, const char *text, unsigned int len, bool with_padding, XftFont *fnt)
+#define TEXTWIDTH(win, text, len) \
+	win_draw_text(win, NULL, NULL, 0, 0, text, len, 0)
+
+int win_draw_text(win_t *win, XftDraw *d, XftColor *color, int x, int y,
+                  char *text, int len, int w)
 {
+	int err, tw = 0;
+	char *t, *next;
+	uint32_t rune;
+	XftFont *f;
+	FcCharSet *fccharset;
 	XGlyphInfo ext;
 
-	XftTextExtentsUtf8(e->dpy, fnt, (XftChar8*)text, len, &ext);
-	return ext.xOff + (with_padding ? 2 * H_TEXT_PAD : 0);
-}
-
-void win_draw_bar_text(win_t *win, XftDraw *d, XftColor *color, XftFont *font, int x, int y, char *text, int maxlen, int maximum_x)
-{
-	size_t len = 0;
-	int err, xshift = 0, newshift;
-	uint32_t codep;
-	char *p, *nextp;
-	FcCharSet* fccharset;
-	XftFont* fallback = NULL;
-
-	for (p = text; *p && (len < maxlen); p = nextp, len++) {
-		nextp = utf8_decode(p, &codep, &err);
-		if (!XftCharExists(win->env.dpy, font, codep)) {
+	for (t = text; t - text < len; t = next) {
+		next = utf8_decode(t, &rune, &err);
+		if (XftCharExists(win->env.dpy, font, rune)) {
+			f = font;
+		} else { /* fallback font */
 			fccharset = FcCharSetCreate();
-			FcCharSetAddChar(fccharset, codep);
-			fallback = XftFontOpen(win->env.dpy, win->env.scr,
-					FC_CHARSET, FcTypeCharSet, fccharset,
-					FC_SCALABLE, FcTypeBool, FcTrue,
-					NULL);
+			FcCharSetAddChar(fccharset, rune);
+			f = XftFontOpen(win->env.dpy, win->env.scr, FC_CHARSET, FcTypeCharSet,
+			                fccharset, FC_SCALABLE, FcTypeBool, FcTrue, NULL);
 			FcCharSetDestroy(fccharset);
 		}
-		newshift = win_textwidth(&win->env, p, (int) (nextp-p), false, (fallback ? fallback : font));
-		if (xshift + newshift <= maximum_x)
-			XftDrawStringUtf8(d, color, (fallback ? fallback : font), x + xshift, y, (XftChar8*)p, (int) (nextp-p));
-		xshift += newshift;
-		if (fallback) {
-			XftFontClose(win->env.dpy, fallback);
-			fallback = NULL;
+		XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext);
+		tw += ext.xOff;
+		if (tw <= w) {
+			XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t);
+			x += ext.xOff;
 		}
+		if (f != font)
+			XftFontClose(win->env.dpy, f);
 	}
+	return tw;
 }
 
 void win_draw_bar(win_t *win)
 {
-	int len, olen, x, y, w, tw, maximum_x;
-	char rest[3];
-	const char *dots = "...";
+	int len, x, y, w, tw;
 	win_env_t *e;
 	win_bar_t *l, *r;
 	XftDraw *d;
@@ -415,7 +410,7 @@ void win_draw_bar(win_t *win)
 
 	e = &win->env;
 	y = win->h + font->ascent + V_TEXT_PAD;
-	w = win->w;
+	w = win->w - 2*H_TEXT_PAD;
 	d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr),
 	                  DefaultColormap(e->dpy, e->scr));
 
@@ -426,30 +421,16 @@ void win_draw_bar(win_t *win)
 	XSetBackground(e->dpy, gc, win->bar.bgcol.pixel);
 
 	if ((len = strlen(r->buf)) > 0) {
-		if ((tw = win_textwidth(e, r->buf, len, true, font)) > w)
+		if ((tw = TEXTWIDTH(win, r->buf, len)) > w)
 			return;
-		x = win->w - tw + H_TEXT_PAD;
+		x = win->w - tw - H_TEXT_PAD;
 		w -= tw;
-		XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, (XftChar8*)r->buf, len);
+		win_draw_text(win, d, &win->bar.fgcol, x, y, r->buf, len, tw);
 	}
 	if ((len = strlen(l->buf)) > 0) {
-		olen = len;
-		while (len > 0 && (tw = win_textwidth(e, l->buf, len, true, font)) > w)
-			len--;
-		if (len > 0) {
-			maximum_x = w;
-			if (len != olen) {
-				w = strlen(dots);
-				if (len <= w)
-					return;
-				memcpy(rest, l->buf + len - w, w);
-				memcpy(l->buf + len - w, dots, w);
-			}
-			x = H_TEXT_PAD;
-			win_draw_bar_text(win, d, &win->bar.fgcol, font, x, y, l->buf, len, maximum_x);
-			if (len != olen)
-			  memcpy(l->buf + len - w, rest, w);
-		}
+		x = H_TEXT_PAD;
+		w -= 2 * H_TEXT_PAD; /* gap between left and right parts */
+		win_draw_text(win, d, &win->bar.fgcol, x, y, l->buf, len, w);
 	}
 	XftDrawDestroy(d);
 }
-- 
cgit v1.2.3