all repos — dwm @ f78c16f8c6134262da3f07cd7c8c33ca6d62a261

fork of suckless dynamic window manager

draw.c (view raw)

  1/* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
  2 * See LICENSE file for license details.
  3 */
  4#include "dwm.h"
  5#include <stdio.h>
  6#include <string.h>
  7#include <X11/Xlocale.h>
  8
  9/* static */
 10
 11static unsigned int
 12textnw(const char *text, unsigned int len) {
 13	XRectangle r;
 14
 15	if(dc.font.set) {
 16		XmbTextExtents(dc.font.set, text, len, NULL, &r);
 17		return r.width;
 18	}
 19	return XTextWidth(dc.font.xfont, text, len);
 20}
 21
 22static void
 23drawtext(const char *text, unsigned long col[ColLast], Bool highlight) {
 24	int x, y, w, h;
 25	static char buf[256];
 26	unsigned int len, olen;
 27	XGCValues gcv;
 28	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
 29
 30	XSetForeground(dpy, dc.gc, col[ColBG]);
 31	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
 32	if(!text)
 33		return;
 34	w = 0;
 35	olen = len = strlen(text);
 36	if(len >= sizeof(buf))
 37		len = sizeof(buf) - 1;
 38	memcpy(buf, text, len);
 39	buf[len] = 0;
 40	h = dc.font.ascent + dc.font.descent;
 41	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
 42	x = dc.x + (h / 2);
 43	/* shorten text if necessary */
 44	while(len && (w = textnw(buf, len)) > dc.w - h)
 45		buf[--len] = 0;
 46	if(len < olen) {
 47		if(len > 1)
 48			buf[len - 1] = '.';
 49		if(len > 2)
 50			buf[len - 2] = '.';
 51		if(len > 3)
 52			buf[len - 3] = '.';
 53	}
 54	if(w > dc.w)
 55		return; /* too long */
 56	gcv.foreground = col[ColFG];
 57	if(dc.font.set) {
 58		XChangeGC(dpy, dc.gc, GCForeground, &gcv);
 59		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
 60	}
 61	else {
 62		gcv.font = dc.font.xfont->fid;
 63		XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
 64		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
 65	}
 66	if(highlight) {
 67		r.x = dc.x + 2;
 68		r.y = dc.y + 2;
 69		r.width = r.height = (h + 2) / 4;
 70		XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
 71	}
 72}
 73
 74/* extern */
 75
 76void
 77drawall(void) {
 78	Client *c;
 79
 80	for(c = clients; c; c = getnext(c->next))
 81		drawtitle(c);
 82	drawstatus();
 83}
 84
 85void
 86drawstatus(void) {
 87	int i, x;
 88
 89	dc.x = dc.y = 0;
 90	for(i = 0; i < ntags; i++) {
 91		dc.w = textw(tags[i]);
 92		if(seltag[i])
 93			drawtext(tags[i], dc.sel, sel && sel->tags[i]);
 94		else
 95			drawtext(tags[i], dc.norm, sel && sel->tags[i]);
 96		dc.x += dc.w;
 97	}
 98	dc.w = bmw;
 99	drawtext(arrange == dofloat ?  FLOATSYMBOL : TILESYMBOL, dc.status, False);
100	x = dc.x + dc.w;
101	dc.w = textw(stext);
102	dc.x = bx + bw - dc.w;
103	if(dc.x < x) {
104		dc.x = x;
105		dc.w = bw - x;
106	}
107	drawtext(stext, dc.status, False);
108	if((dc.w = dc.x - x) > bh) {
109		dc.x = x;
110		if(sel)
111			drawtext(sel->name, dc.sel, False);
112		else
113			drawtext(NULL, dc.norm, False);
114	}
115	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
116	XSync(dpy, False);
117}
118
119void
120drawtitle(Client *c) {
121	if(c == sel && issel) {
122		drawstatus();
123		XUnmapWindow(dpy, c->twin);
124		XSetWindowBorder(dpy, c->win, dc.sel[ColBG]);
125		return;
126	}
127	XSetWindowBorder(dpy, c->win, dc.norm[ColBG]);
128	XMapWindow(dpy, c->twin);
129	dc.x = dc.y = 0;
130	dc.w = c->tw;
131	drawtext(c->name, dc.norm, False);
132	XCopyArea(dpy, dc.drawable, c->twin, dc.gc, 0, 0, c->tw, c->th, 0, 0);
133	XSync(dpy, False);
134}
135
136unsigned long
137getcolor(const char *colstr) {
138	Colormap cmap = DefaultColormap(dpy, screen);
139	XColor color;
140
141	if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
142		eprint("error, cannot allocate color '%s'\n", colstr);
143	return color.pixel;
144}
145
146void
147setfont(const char *fontstr) {
148	char **missing, *def;
149	int i, n;
150
151	missing = NULL;
152	setlocale(LC_ALL, "");
153	if(dc.font.set)
154		XFreeFontSet(dpy, dc.font.set);
155	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
156	if(missing) {
157		while(n--)
158			fprintf(stderr, "missing fontset: %s\n", missing[n]);
159		XFreeStringList(missing);
160		if(dc.font.set) {
161			XFreeFontSet(dpy, dc.font.set);
162			dc.font.set = NULL;
163		}
164	}
165	if(dc.font.set) {
166		XFontSetExtents *font_extents;
167		XFontStruct **xfonts;
168		char **font_names;
169		dc.font.ascent = dc.font.descent = 0;
170		font_extents = XExtentsOfFontSet(dc.font.set);
171		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
172		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
173			if(dc.font.ascent < (*xfonts)->ascent)
174				dc.font.ascent = (*xfonts)->ascent;
175			if(dc.font.descent < (*xfonts)->descent)
176				dc.font.descent = (*xfonts)->descent;
177			xfonts++;
178		}
179	}
180	else {
181		if(dc.font.xfont)
182			XFreeFont(dpy, dc.font.xfont);
183		dc.font.xfont = NULL;
184		dc.font.xfont = XLoadQueryFont(dpy, fontstr);
185		if (!dc.font.xfont)
186			dc.font.xfont = XLoadQueryFont(dpy, "fixed");
187		if (!dc.font.xfont)
188			eprint("error, cannot init 'fixed' font\n");
189		dc.font.ascent = dc.font.xfont->ascent;
190		dc.font.descent = dc.font.xfont->descent;
191	}
192	dc.font.height = dc.font.ascent + dc.font.descent;
193}
194
195unsigned int
196textw(const char *text) {
197	return textnw(text, strlen(text)) + dc.font.height;
198}