diff options
Diffstat (limited to 'draw.c')
| -rw-r--r-- | draw.c | 143 | 
1 files changed, 143 insertions, 0 deletions
@@ -0,0 +1,143 @@ +/* See LICENSE file for copyright and license details. */ + +/* enums */ +enum { ColFG, ColBG, ColLast }; + +/* typedefs */ +typedef struct { +	int x, y, w, h; +	unsigned long norm[ColLast]; +	unsigned long sel[ColLast]; +	Drawable drawable; +	GC gc; +	struct { +		XFontStruct *xfont; +		XFontSet set; +		int ascent; +		int descent; +		int height; +	} font; +} DC; /* draw context */ + +/* forward declarations */ +static void dccleanup(void); +static void dcsetup(void); +static void drawtext(const char *text, unsigned long col[ColLast]); +static unsigned long getcolor(const char *colstr); +static void initfont(const char *fontstr); +static int textnw(const char *text, unsigned int len); +static int textw(const char *text); + +static DC dc; + +void +dccleanup(void) { +	if(dc.font.set) +		XFreeFontSet(dpy, dc.font.set); +	else +		XFreeFont(dpy, dc.font.xfont); +	XFreePixmap(dpy, dc.drawable); +	XFreeGC(dpy, dc.gc); +} + +void +dcsetup() { +	/* style */ +	dc.norm[ColBG] = getcolor(normbgcolor); +	dc.norm[ColFG] = getcolor(normfgcolor); +	dc.sel[ColBG] = getcolor(selbgcolor); +	dc.sel[ColFG] = getcolor(selfgcolor); +	initfont(font); + +	/* pixmap */ +	dc.drawable = XCreatePixmap(dpy, parent, mw, mh, DefaultDepth(dpy, screen)); +	dc.gc = XCreateGC(dpy, parent, 0, NULL); +	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); +	if(!dc.font.set) +		XSetFont(dpy, dc.gc, dc.font.xfont->fid); +} + +void +drawtext(const char *text, unsigned long col[ColLast]) { +	char buf[256]; +	int i, x, y, h, len, olen; +	XRectangle r = { dc.x, dc.y, dc.w, dc.h }; + +	XSetForeground(dpy, dc.gc, col[ColBG]); +	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); +	if(!text) +		return; +	olen = strlen(text); +	h = dc.font.height; +	y = dc.y + ((h+2) / 2) - (h / 2) + dc.font.ascent; +	x = dc.x + (h / 2); +	/* shorten text if necessary */ +	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); +	if(!len) +		return; +	memcpy(buf, text, len); +	if(len < olen) +		for(i = len; i && i > len - 3; buf[--i] = '.'); +	XSetForeground(dpy, dc.gc, col[ColFG]); +	if(dc.font.set) +		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); +	else +		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); +} + +unsigned long +getcolor(const char *colstr) { +	Colormap cmap = DefaultColormap(dpy, screen); +	XColor color; + +	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) +		eprint("drawtext: cannot allocate color '%s'\n", colstr); +	return color.pixel; +} + +void +initfont(const char *fontstr) { +	char *def, **missing = NULL; +	int i, n; + +	if(!fontstr || fontstr[0] == '\0') +		eprint("drawtext: cannot load font: '%s'\n", fontstr); +	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); +	if(missing) +		XFreeStringList(missing); +	if(dc.font.set) { +		XFontStruct **xfonts; +		char **font_names; +		dc.font.ascent = dc.font.descent = 0; +		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); +		for(i = 0; i < n; i++) { +			dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); +			dc.font.descent = MAX(dc.font.descent, (*xfonts)->descent); +			xfonts++; +		} +	} +	else { +		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) +		&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) +			eprint("drawtext: cannot load font: '%s'\n", fontstr); +		dc.font.ascent = dc.font.xfont->ascent; +		dc.font.descent = dc.font.xfont->descent; +	} +	dc.font.height = dc.font.ascent + dc.font.descent; +} + +int +textnw(const char *text, unsigned int len) { +	XRectangle r; + +	if(dc.font.set) { +		XmbTextExtents(dc.font.set, text, len, NULL, &r); +		return r.width; +	} +	return XTextWidth(dc.font.xfont, text, len); +} + +int +textw(const char *text) { +	return textnw(text, strlen(text)) + dc.font.height; +}  | 
