all repos — dwm @ 29355bd38284ed9aec8d3ffabde61db73947c9f9

fork of suckless dynamic window manager

draw.c (view raw)

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