removed libdc dependence a0a99d10
Connor Lane Smith · 2010-11-11 23:56 6 file(s) · +269 −34
Makefile +9 −5
3 3
4 4
include config.mk
5 5
6 -
all: options dmenu dmenu_path
6 +
all: options dmenu dmenu_path config.mk
7 7
8 8
options:
9 9
	@echo dmenu build options:
11 11
	@echo "LDFLAGS  = ${LDFLAGS}"
12 12
	@echo "CC       = ${CC}"
13 13
14 -
dmenu: dmenu.c config.mk
15 -
dmenu_path: dmenu_path.c
14 +
dmenu: dmenu.o draw.o
15 +
dmenu_path: dmenu_path.o
16 +
17 +
.c.o:
18 +
	@echo CC -c $<
19 +
	@${CC} -c $< ${CFLAGS}
16 20
17 21
dmenu dmenu_path:
18 22
	@echo CC -o $@
19 -
	@${CC} -o $@ $< ${CFLAGS} ${LDFLAGS}
23 +
	@${CC} -o $@ $+ ${LDFLAGS}
20 24
21 25
clean:
22 26
	@echo cleaning
23 -
	@rm -f dmenu dmenu_path dmenu-${VERSION}.tar.gz
27 +
	@rm -f dmenu dmenu.o draw.o dmenu_path dmenu_path.o dmenu-${VERSION}.tar.gz
24 28
25 29
dist: clean
26 30
	@echo creating dist tarball
README +0 −2
7 7
------------
8 8
In order to build dmenu you need the Xlib header files.
9 9
10 -
You also need libdc, available from http://hg.suckless.org/libdraw
11 -
12 10
13 11
Installation
14 12
------------
config.mk +1 −1
16 16
17 17
# includes and libs
18 18
INCS = -I${X11INC}
19 -
LIBS = -L${X11LIB} -ldc -lX11 ${XINERAMALIBS}
19 +
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS}
20 20
21 21
# flags
22 22
CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
dmenu.c +26 −26
10 10
#ifdef XINERAMA
11 11
#include <X11/extensions/Xinerama.h>
12 12
#endif
13 -
#include <dc.h>
13 +
#include "draw.h"
14 14
15 15
#define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh))
16 16
#define MIN(a,b)                ((a) < (b) ? (a) : (b))
81 81
	if(lines > 0)
82 82
		n = lines * bh;
83 83
	else
84 -
		n = mw - (promptw + inputw + dc_textw(dc, "<") + dc_textw(dc, ">"));
84 +
		n = mw - (promptw + inputw + textw(dc, "<") + textw(dc, ">"));
85 85
86 86
	for(i = 0, next = curr; next; next = next->right)
87 -
		if((i += (lines > 0) ? bh : MIN(dc_textw(dc, next->text), n)) > n)
87 +
		if((i += (lines > 0) ? bh : MIN(textw(dc, next->text), n)) > n)
88 88
			break;
89 89
	for(i = 0, prev = curr; prev && prev->left; prev = prev->left)
90 -
		if((i += (lines > 0) ? bh : MIN(dc_textw(dc, prev->left->text), n)) > n)
90 +
		if((i += (lines > 0) ? bh : MIN(textw(dc, prev->left->text), n)) > n)
91 91
			break;
92 92
}
93 93
99 99
	dc->x = 0;
100 100
	dc->y = 0;
101 101
	dc->h = bh;
102 -
	dc_drawrect(dc, 0, 0, mw, mh, True, BG(dc, normcol));
102 +
	drawrect(dc, 0, 0, mw, mh, True, BG(dc, normcol));
103 103
104 104
	if(prompt) {
105 105
		dc->w = promptw;
106 -
		dc_drawtext(dc, prompt, selcol);
106 +
		drawtext(dc, prompt, selcol);
107 107
		dc->x = dc->w;
108 108
	}
109 109
	dc->w = (lines > 0 || !matches) ? mw - dc->x : inputw;
110 -
	dc_drawtext(dc, text, normcol);
111 -
	if((curpos = dc_textnw(dc, text, cursor) + dc->h/2 - 2) < dc->w)
112 -
		dc_drawrect(dc, curpos, 2, 1, dc->h - 4, True, FG(dc, normcol));
110 +
	drawtext(dc, text, normcol);
111 +
	if((curpos = textnw(dc, text, cursor) + dc->h/2 - 2) < dc->w)
112 +
		drawrect(dc, curpos, 2, 1, dc->h - 4, True, FG(dc, normcol));
113 113
114 114
	if(lines > 0) {
115 115
		dc->w = mw - dc->x;
116 116
		for(item = curr; item != next; item = item->right) {
117 117
			dc->y += dc->h;
118 -
			dc_drawtext(dc, item->text, (item == sel) ? selcol : normcol);
118 +
			drawtext(dc, item->text, (item == sel) ? selcol : normcol);
119 119
		}
120 120
	}
121 121
	else if(matches) {
122 122
		dc->x += inputw;
123 -
		dc->w = dc_textw(dc, "<");
123 +
		dc->w = textw(dc, "<");
124 124
		if(curr->left)
125 -
			dc_drawtext(dc, "<", normcol);
125 +
			drawtext(dc, "<", normcol);
126 126
		for(item = curr; item != next; item = item->right) {
127 127
			dc->x += dc->w;
128 -
			dc->w = MIN(dc_textw(dc, item->text), mw - dc->x - dc_textw(dc, ">"));
129 -
			dc_drawtext(dc, item->text, (item == sel) ? selcol : normcol);
128 +
			dc->w = MIN(textw(dc, item->text), mw - dc->x - textw(dc, ">"));
129 +
			drawtext(dc, item->text, (item == sel) ? selcol : normcol);
130 130
		}
131 -
		dc->w = dc_textw(dc, ">");
131 +
		dc->w = textw(dc, ">");
132 132
		dc->x = mw - dc->w;
133 133
		if(next)
134 -
			dc_drawtext(dc, ">", normcol);
134 +
			drawtext(dc, ">", normcol);
135 135
	}
136 -
	dc_map(dc, win, mw, mh);
136 +
	mapdc(dc, win, mw, mh);
137 137
}
138 138
139 139
char *
398 398
		if(!(item->text = strdup(buf)))
399 399
			eprintf("cannot strdup %u bytes\n", strlen(buf)+1);
400 400
		item->next = item->left = item->right = NULL;
401 -
		inputw = MAX(inputw, dc_textw(dc, item->text));
401 +
		inputw = MAX(inputw, textw(dc, item->text));
402 402
	}
403 403
}
404 404
439 439
	root = RootWindow(dc->dpy, screen);
440 440
	utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False);
441 441
442 -
	normcol[ColBG] = dc_color(dc, normbgcolor);
443 -
	normcol[ColFG] = dc_color(dc, normfgcolor);
444 -
	selcol[ColBG] = dc_color(dc, selbgcolor);
445 -
	selcol[ColFG] = dc_color(dc, selfgcolor);
442 +
	normcol[ColBG] = getcolor(dc, normbgcolor);
443 +
	normcol[ColFG] = getcolor(dc, normfgcolor);
444 +
	selcol[ColBG] = getcolor(dc, selbgcolor);
445 +
	selcol[ColFG] = getcolor(dc, selfgcolor);
446 446
447 447
	/* menu geometry */
448 448
	bh = dc->font.height + 2;
481 481
	                    CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
482 482
483 483
	grabkeyboard();
484 -
	dc_resize(dc, mw, mh);
484 +
	resizedc(dc, mw, mh);
485 485
	inputw = MIN(inputw, mw/3);
486 -
	promptw = prompt ? dc_textw(dc, prompt) : 0;
486 +
	promptw = prompt ? textw(dc, prompt) : 0;
487 487
	XMapRaised(dc->dpy, win);
488 488
	text[0] = '\0';
489 489
	match();
533 533
		else
534 534
			usage();
535 535
536 -
	dc = dc_init();
537 -
	dc_font(dc, font);
536 +
	dc = initdc();
537 +
	initfont(dc, font);
538 538
	readstdin();
539 539
	setup();
540 540
	run();
draw.c (added) +196 −0
1 +
/* See LICENSE file for copyright and license details. */
2 +
#include <locale.h>
3 +
#include <stdarg.h>
4 +
#include <stdio.h>
5 +
#include <stdlib.h>
6 +
#include <string.h>
7 +
#include <X11/Xlib.h>
8 +
#include "draw.h"
9 +
10 +
#define MAX(a, b)   ((a) > (b) ? (a) : (b))
11 +
#define MIN(a, b)   ((a) < (b) ? (a) : (b))
12 +
#define FG(dc, col) ((col)[(dc)->invert ? ColBG : ColFG])
13 +
#define BG(dc, col) ((col)[(dc)->invert ? ColFG : ColBG])
14 +
#define DEFFONT     "fixed"
15 +
16 +
static Bool loadfont(DC *dc, const char *fontstr);
17 +
18 +
void
19 +
drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color) {
20 +
	XRectangle r = { dc->x + x, dc->y + y, w, h };
21 +
22 +
	if(!fill) {
23 +
		r.width -= 1;
24 +
		r.height -= 1;
25 +
	}
26 +
	XSetForeground(dc->dpy, dc->gc, color);
27 +
	(fill ? XFillRectangles : XDrawRectangles)(dc->dpy, dc->canvas, dc->gc, &r, 1);
28 +
}
29 +
30 +
31 +
void
32 +
drawtext(DC *dc, const char *text, unsigned long col[ColLast]) {
33 +
	char buf[256];
34 +
	size_t n, mn;
35 +
36 +
	/* shorten text if necessary */
37 +
	n = strlen(text);
38 +
	for(mn = MIN(n, sizeof buf); textnw(dc, text, mn) > dc->w - dc->font.height/2; mn--)
39 +
		if(mn == 0)
40 +
			return;
41 +
	memcpy(buf, text, mn);
42 +
	if(mn < n)
43 +
		for(n = MAX(mn-3, 0); n < mn; buf[n++] = '.');
44 +
45 +
	drawrect(dc, 0, 0, dc->w, dc->h, True, BG(dc, col));
46 +
	drawtextn(dc, buf, mn, col);
47 +
}
48 +
49 +
void
50 +
drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]) {
51 +
	int x, y;
52 +
53 +
	x = dc->x + dc->font.height/2;
54 +
	y = dc->y + dc->font.ascent+1;
55 +
56 +
	XSetForeground(dc->dpy, dc->gc, FG(dc, col));
57 +
	if(dc->font.set)
58 +
		XmbDrawString(dc->dpy, dc->canvas, dc->font.set, dc->gc, x, y, text, n);
59 +
	else {
60 +
		XSetFont(dc->dpy, dc->gc, dc->font.xfont->fid);
61 +
		XDrawString(dc->dpy, dc->canvas, dc->gc, x, y, text, n);
62 +
	}
63 +
}
64 +
65 +
void
66 +
eprintf(const char *fmt, ...) {
67 +
	va_list ap;
68 +
69 +
	fprintf(stderr, "%s: ", progname);
70 +
	va_start(ap, fmt);
71 +
	vfprintf(stderr, fmt, ap);
72 +
	va_end(ap);
73 +
	exit(EXIT_FAILURE);
74 +
}
75 +
76 +
void
77 +
freedc(DC *dc) {
78 +
	if(dc->font.set)
79 +
		XFreeFontSet(dc->dpy, dc->font.set);
80 +
	if(dc->font.xfont)
81 +
		XFreeFont(dc->dpy, dc->font.xfont);
82 +
	if(dc->canvas)
83 +
		XFreePixmap(dc->dpy, dc->canvas);
84 +
	XFreeGC(dc->dpy, dc->gc);
85 +
	XCloseDisplay(dc->dpy);
86 +
	free(dc);
87 +
}
88 +
89 +
unsigned long
90 +
getcolor(DC *dc, const char *colstr) {
91 +
	Colormap cmap = DefaultColormap(dc->dpy, DefaultScreen(dc->dpy));
92 +
	XColor color;
93 +
94 +
	if(!XAllocNamedColor(dc->dpy, cmap, colstr, &color, &color))
95 +
		eprintf("cannot allocate color '%s'\n", colstr);
96 +
	return color.pixel;
97 +
}
98 +
99 +
DC *
100 +
initdc(void) {
101 +
	DC *dc;
102 +
103 +
	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
104 +
		weprintf("no locale support\n");
105 +
	if(!(dc = malloc(sizeof *dc)))
106 +
		eprintf("cannot malloc %u bytes\n", sizeof *dc);
107 +
	if(!(dc->dpy = XOpenDisplay(NULL)))
108 +
		eprintf("cannot open display\n");
109 +
110 +
	dc->gc = XCreateGC(dc->dpy, DefaultRootWindow(dc->dpy), 0, NULL);
111 +
	XSetLineAttributes(dc->dpy, dc->gc, 1, LineSolid, CapButt, JoinMiter);
112 +
	dc->font.xfont = NULL;
113 +
	dc->font.set = NULL;
114 +
	dc->canvas = None;
115 +
	return dc;
116 +
}
117 +
118 +
void
119 +
initfont(DC *dc, const char *fontstr) {
120 +
	if(!loadfont(dc, fontstr ? fontstr : DEFFONT)) {
121 +
		if(fontstr != NULL)
122 +
			weprintf("cannot load font '%s'\n", fontstr);
123 +
		if(fontstr == NULL || !loadfont(dc, DEFFONT))
124 +
			eprintf("cannot load font '%s'\n", DEFFONT);
125 +
	}
126 +
	dc->font.height = dc->font.ascent + dc->font.descent;
127 +
}
128 +
129 +
Bool
130 +
loadfont(DC *dc, const char *fontstr) {
131 +
	char *def, **missing;
132 +
	int i, n;
133 +
134 +
	if(!*fontstr)
135 +
		return False;
136 +
	if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) {
137 +
		char **names;
138 +
		XFontStruct **xfonts;
139 +
140 +
		n = XFontsOfFontSet(dc->font.set, &xfonts, &names);
141 +
		for(i = dc->font.ascent = dc->font.descent = 0; i < n; i++) {
142 +
			dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent);
143 +
			dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent);
144 +
		}
145 +
	}
146 +
	else if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))) {
147 +
		dc->font.ascent = dc->font.xfont->ascent;
148 +
		dc->font.descent = dc->font.xfont->descent;
149 +
	}
150 +
	if(missing)
151 +
		XFreeStringList(missing);
152 +
	return (dc->font.set || dc->font.xfont);
153 +
}
154 +
155 +
void
156 +
mapdc(DC *dc, Window win, unsigned int w, unsigned int h) {
157 +
	XCopyArea(dc->dpy, dc->canvas, win, dc->gc, 0, 0, w, h, 0, 0);
158 +
}
159 +
160 +
void
161 +
resizedc(DC *dc, unsigned int w, unsigned int h) {
162 +
	if(dc->canvas)
163 +
		XFreePixmap(dc->dpy, dc->canvas);
164 +
	dc->canvas = XCreatePixmap(dc->dpy, DefaultRootWindow(dc->dpy), w, h,
165 +
	                           DefaultDepth(dc->dpy, DefaultScreen(dc->dpy)));
166 +
	dc->x = dc->y = 0;
167 +
	dc->w = w;
168 +
	dc->h = h;
169 +
	dc->invert = False;
170 +
}
171 +
172 +
int
173 +
textnw(DC *dc, const char *text, size_t len) {
174 +
	if(dc->font.set) {
175 +
		XRectangle r;
176 +
177 +
		XmbTextExtents(dc->font.set, text, len, NULL, &r);
178 +
		return r.width;
179 +
	}
180 +
	return XTextWidth(dc->font.xfont, text, len);
181 +
}
182 +
183 +
int
184 +
textw(DC *dc, const char *text) {
185 +
	return textnw(dc, text, strlen(text)) + dc->font.height;
186 +
}
187 +
188 +
void
189 +
weprintf(const char *fmt, ...) {
190 +
	va_list ap;
191 +
192 +
	fprintf(stderr, "%s: warning: ", progname);
193 +
	va_start(ap, fmt);
194 +
	vfprintf(stderr, fmt, ap);
195 +
	va_end(ap);
196 +
}
draw.h (added) +37 −0
1 +
/* See LICENSE file for copyright and license details. */
2 +
3 +
#define FG(dc, col)  ((col)[(dc)->invert ? ColBG : ColFG])
4 +
#define BG(dc, col)  ((col)[(dc)->invert ? ColFG : ColBG])
5 +
6 +
enum { ColBG, ColFG, ColBorder, ColLast };
7 +
8 +
typedef struct {
9 +
	int x, y, w, h;
10 +
	Bool invert;
11 +
	Display *dpy;
12 +
	GC gc;
13 +
	Pixmap canvas;
14 +
	struct {
15 +
		int ascent;
16 +
		int descent;
17 +
		int height;
18 +
		XFontSet set;
19 +
		XFontStruct *xfont;
20 +
	} font;
21 +
} DC;  /* draw context */
22 +
23 +
unsigned long getcolor(DC *dc, const char *colstr);
24 +
void drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color);
25 +
void drawtext(DC *dc, const char *text, unsigned long col[ColLast]);
26 +
void drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]);
27 +
void initfont(DC *dc, const char *fontstr);
28 +
void freedc(DC *dc);
29 +
DC *initdc(void);
30 +
void mapdc(DC *dc, Window win, unsigned int w, unsigned int h);
31 +
void resizedc(DC *dc, unsigned int w, unsigned int h);
32 +
int textnw(DC *dc, const char *text, size_t len);
33 +
int textw(DC *dc, const char *text);
34 +
void eprintf(const char *fmt, ...);
35 +
void weprintf(const char *fmt, ...);
36 +
37 +
const char *progname;