fixed bugs, no more config.h, updated manpage, new libdraw a7aee433
Connor Lane Smith · 2010-08-02 14:22 7 file(s) · +162 −220
Makefile +8 −16
3 3
4 4
include config.mk
5 5
6 -
SRC = dmenu.c
7 -
OBJ = ${SRC:.c=.o}
8 -
9 6
all: options dmenu
10 7
11 8
options:
14 11
	@echo "LDFLAGS  = ${LDFLAGS}"
15 12
	@echo "CC       = ${CC}"
16 13
17 -
.c.o:
14 +
dmenu.o: dmenu.c config.mk
18 15
	@echo CC $<
19 16
	@${CC} -c ${CFLAGS} $<
20 17
21 -
${OBJ}: config.h config.mk
22 -
23 -
config.h:
24 -
	@echo creating $@ from config.def.h
25 -
	@cp config.def.h $@
26 -
27 -
dmenu: ${OBJ}
18 +
dmenu: dmenu.o
28 19
	@echo CC -o $@
29 20
	@${CC} -o $@ $+ ${LDFLAGS}
30 21
31 22
clean:
32 23
	@echo cleaning
33 -
	@rm -f dmenu ${OBJ} dmenu-${VERSION}.tar.gz
24 +
	@rm -f dmenu dmenu.o dmenu-${VERSION}.tar.gz
34 25
35 26
dist: clean
36 27
	@echo creating dist tarball
37 28
	@mkdir -p dmenu-${VERSION}
38 -
	@cp -R LICENSE Makefile README config.mk dmenu.1 config.def.h dmenu_path dmenu_run ${SRC} dmenu-${VERSION}
29 +
	@cp -R LICENSE Makefile README config.mk dmenu.1 dmenu.c dmenu_path dmenu_run dmenu-${VERSION}
39 30
	@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION}
40 31
	@gzip dmenu-${VERSION}.tar
41 32
	@rm -rf dmenu-${VERSION}
42 33
43 34
install: all
44 -
	@echo installing executable file to ${DESTDIR}${PREFIX}/bin
35 +
	@echo installing executables to ${DESTDIR}${PREFIX}/bin
45 36
	@mkdir -p ${DESTDIR}${PREFIX}/bin
46 37
	@cp -f dmenu dmenu_path dmenu_run ${DESTDIR}${PREFIX}/bin
47 38
	@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu
53 44
	@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1
54 45
55 46
uninstall:
56 -
	@echo removing executable file from ${DESTDIR}${PREFIX}/bin
57 -
	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu ${DESTDIR}${PREFIX}/bin/dmenu_path
47 +
	@echo removing executables from ${DESTDIR}${PREFIX}/bin
48 +
	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu
49 +
	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_path
58 50
	@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_run
59 51
	@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
60 52
	@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1
README +6 −5
1 1
dmenu - dynamic menu
2 2
====================
3 -
dmenu is a generic and efficient menu for X. 
3 +
dmenu is an efficient dynamic menu for X.
4 4
5 5
6 6
Requirements
7 7
------------
8 8
In order to build dmenu you need the Xlib header files.
9 +
9 10
You also need libdraw, available from http://hg.suckless.org/libdraw
10 11
11 12
12 13
Installation
13 14
------------
14 -
Edit config.mk to match your local setup (dmenu is installed into the
15 -
/usr/local namespace by default).
15 +
Edit config.mk to match your local setup (dmenu is installed into
16 +
the /usr/local namespace by default).
16 17
17 -
Afterwards enter the following command to build and install dmenu (if
18 -
necessary as root):
18 +
Afterwards enter the following command to build and install dmenu
19 +
(if necessary as root):
19 20
20 21
    make clean install
21 22
config.def.h (deleted) +0 −8
1 -
/* See LICENSE file for copyright and license details. */
2 -
3 -
/* appearance */
4 -
static const char *font        = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*";
5 -
static const char *normbgcolor = "#cccccc";
6 -
static const char *normfgcolor = "#000000";
7 -
static const char *selbgcolor  = "#0066ff";
8 -
static const char *selfgcolor  = "#ffffff";
config.mk +7 −10
1 1
# dmenu version
2 -
VERSION = 4.1.1
2 +
VERSION = 4.2
3 3
4 4
# Customize below to fit your system
5 5
7 7
PREFIX = /usr/local
8 8
MANPREFIX = ${PREFIX}/share/man
9 9
10 +
# Xlib
10 11
X11INC = /usr/X11R6/include
11 12
X11LIB = /usr/X11R6/lib
12 13
13 14
# Xinerama, comment if you don't want it
14 -
XINERAMALIBS = -L${X11LIB} -lXinerama
15 +
XINERAMALIBS  = -lXinerama
15 16
XINERAMAFLAGS = -DXINERAMA
16 17
17 18
# includes and libs
18 -
INCS = -I. -I/usr/include -I${X11INC}
19 -
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -ldraw ${XINERAMALIBS}
19 +
INCS = -I${X11INC}
20 +
LIBS = -L${X11LIB} -ldraw -lX11 ${XINERAMALIBS}
20 21
21 22
# flags
22 23
CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
23 -
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
24 -
LDFLAGS = -s ${LIBS}
25 -
26 -
# Solaris
27 -
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
28 -
#LDFLAGS = ${LIBS}
24 +
CFLAGS   = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
25 +
LDFLAGS  = -s ${LIBS}
29 26
30 27
# compiler and linker
31 28
CC = cc
dmenu.1 +46 −52
5 5
.B dmenu
6 6
.RB [ \-b ]
7 7
.RB [ \-i ]
8 -
.RB [ \-l " <lines>]"
9 -
.RB [ \-p " <prompt>]"
10 -
.RB [ \-fn " <font>]"
11 -
.RB [ \-nb " <color>]"
12 -
.RB [ \-nf " <color>]"
13 -
.RB [ \-sb " <color>]"
14 -
.RB [ \-sf " <color>]"
8 +
.RB [ \-l
9 +
.IR lines ]
10 +
.RB [ \-p
11 +
.IR prompt ]
12 +
.RB [ \-fn
13 +
.IR font ]
14 +
.RB [ \-nb
15 +
.IR color ]
16 +
.RB [ \-nf
17 +
.IR color ]
18 +
.RB [ \-sb
19 +
.IR color ]
20 +
.RB [ \-sf
21 +
.IR color ]
15 22
.RB [ \-v ]
16 -
17 -
.B dmenu_run
18 -
.RB [ \-b ]
19 -
.RB [ \-i ]
20 -
.RB [ \-l " <lines>]"
21 -
.RB [ \-p " <prompt>]"
22 -
.RB [ \-fn " <font>]"
23 -
.RB [ \-nb " <color>]"
24 -
.RB [ \-nf " <color>]"
25 -
.RB [ \-sb " <color>]"
26 -
.RB [ \-sf " <color>]"
27 -
.RB [ \-v ]
28 -
23 +
.P
24 +
.BR dmenu_run " ..."
25 +
.P
29 26
.B dmenu_path
30 27
.SH DESCRIPTION
31 -
.SS Overview
32 28
.B dmenu
33 -
is a generic menu for X, originally designed for
29 +
is a dynamic menu for X, originally designed for
34 30
.BR dwm (1).
35 -
It manages huge amounts (10000 and more) of user defined menu items efficiently.
31 +
It manages huge numbers of user-defined menu items efficiently.
32 +
.P
33 +
dmenu reads a list of newline-separated items from standard input and creates a
34 +
menu.  When the user selects an item or enters any text and presses Return,
35 +
their choice is printed to standard output and dmenu terminates.
36 36
.P
37 37
.B dmenu_run
38 -
is a dmenu script which lists programs in the user's PATH and executes
39 -
the selected item.
38 +
is a dmenu script used by dwm which lists programs in the user's PATH and
39 +
executes the selected item.
40 40
.P
41 41
.B dmenu_path
42 -
is a script used by
43 -
.I dmenu_run
44 -
to find and cache a list of programs.
45 -
.SS Options
42 +
is a script used by dmenu_run to find and cache a list of programs.
43 +
.SH OPTIONS
46 44
.TP
47 45
.B \-b
48 46
dmenu appears at the bottom of the screen.
49 47
.TP
50 48
.B \-i
51 -
dmenu matches menu entries case insensitively.
49 +
dmenu matches menu items case insensitively.
52 50
.TP
53 -
.B \-l <lines>
51 +
.BI \-l " lines"
54 52
dmenu lists items vertically, with the given number of lines.
55 53
.TP
56 -
.B \-p <prompt>
57 -
sets the prompt to be displayed to the left of the input area.
54 +
.BI \-p " prompt"
55 +
defines the prompt to be displayed to the left of the input area.
58 56
.TP
59 -
.B \-fn <font>
60 -
sets the font.
57 +
.BI \-fn " font"
58 +
defines the font set used.
61 59
.TP
62 -
.B \-nb <color>
63 -
sets the background color (#RGB, #RRGGBB, and color names are supported).
60 +
.BI \-nb " color"
61 +
defines the normal background color.
62 +
.IR #RGB ,
63 +
.IR #RRGGBB ,
64 +
and color names are supported.
64 65
.TP
65 -
.B \-nf <color>
66 -
sets the foreground color (#RGB, #RRGGBB, and color names are supported).
66 +
.BI \-nf " color"
67 +
defines the normal foreground color.
67 68
.TP
68 -
.B \-sb <color>
69 -
sets the background color of selected items (#RGB, #RRGGBB, and color names are
70 -
supported).
69 +
.BI \-sb " color"
70 +
defines the selected background color.
71 71
.TP
72 -
.B \-sf <color>
73 -
sets the foreground color of selected items (#RGB, #RRGGBB, and color names are
74 -
supported).
72 +
.BI \-sf " color"
73 +
defines the selected foreground color.
75 74
.TP
76 75
.B \-v
77 76
prints version information to standard output, then exits.
78 77
.SH USAGE
79 -
dmenu reads a list of newline-separated items from standard input and creates a
80 -
menu.  When the user selects an item or enters any text and presses Return,
81 -
their choice is printed to standard output and dmenu terminates.
82 -
.P
83 78
dmenu is completely controlled by the keyboard.  Besides standard Unix line
84 79
editing and item selection (Up/Down/Left/Right, PageUp/PageDown, Home/End), the
85 80
following keys are recognized:
96 91
success.
97 92
.TP
98 93
.B Escape (Control\-c)
99 -
Quit without selecting an item, returning failure.
94 +
Exit without selecting an item, returning failure.
100 95
.TP
101 96
.B Control\-y
102 97
Paste the current X selection into the input field.
103 98
.SH SEE ALSO
104 -
.BR dwm (1),
105 -
.BR wmii (1).
99 +
.BR dwm (1)
dmenu.c +94 −128
1 1
/* See LICENSE file for copyright and license details. */
2 2
#include <ctype.h>
3 -
#include <locale.h>
4 3
#include <stdio.h>
5 4
#include <stdlib.h>
6 5
#include <string.h>
7 6
#include <unistd.h>
8 -
#include <X11/keysym.h>
9 7
#include <X11/Xatom.h>
10 8
#include <X11/Xlib.h>
11 9
#include <X11/Xutil.h>
13 11
#include <X11/extensions/Xinerama.h>
14 12
#endif
15 13
#include <draw.h>
16 -
#include "config.h"
17 14
18 15
#define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh))
19 16
#define MIN(a,b)                ((a) < (b) ? (a) : (b))
38 35
static void insert(const char *s, ssize_t n);
39 36
static void keypress(XKeyEvent *e);
40 37
static void match(void);
41 -
static void paste(Atom atom);
38 +
static void paste(void);
42 39
static void readstdin(void);
43 40
static void run(void);
44 41
static void setup(void);
45 42
static void usage(void);
46 43
47 -
static char *prompt;
48 44
static char text[4096];
49 -
static int screen;
50 45
static size_t cursor = 0;
46 +
static const char *prompt = NULL;
47 +
static const char *normbgcolor = "#cccccc";
48 +
static const char *normfgcolor = "#000000";
49 +
static const char *selbgcolor  = "#0066ff";
50 +
static const char *selfgcolor  = "#ffffff";
51 51
static unsigned int inputw = 0;
52 52
static unsigned int lines = 0;
53 53
static unsigned int mw, mh;
54 -
static unsigned int promptw = 0;
55 54
static unsigned long normcol[ColLast];
56 55
static unsigned long selcol[ColLast];
57 56
static Atom utf8;
58 57
static Bool topbar = True;
59 -
static DC dc;
58 +
static DC *dc;
60 59
static Item *allitems, *matches;
61 60
static Item *curr, *prev, *next, *sel;
62 61
static Window root, win;
67 66
68 67
void
69 68
appenditem(Item *item, Item **list, Item **last) {
70 -
	if(!(*last))
69 +
	if(!*last)
71 70
		*list = item;
72 71
	else
73 72
		(*last)->right = item;
80 79
calcoffsetsh(void) {
81 80
	unsigned int w, x;
82 81
83 -
	w = promptw + inputw + textw(&dc, "<") + textw(&dc, ">");
82 +
	w = (prompt ? textw(dc, prompt) : 0) + inputw + textw(dc, "<") + textw(dc, ">");
84 83
	for(x = w, next = curr; next; next = next->right)
85 -
		if((x += MIN(textw(&dc, next->text), mw / 3)) > mw)
84 +
		if((x += MIN(textw(dc, next->text), mw / 3)) > mw)
86 85
			break;
87 86
	for(x = w, prev = curr; prev && prev->left; prev = prev->left)
88 -
		if((x += MIN(textw(&dc, prev->left->text), mw / 3)) > mw)
87 +
		if((x += MIN(textw(dc, prev->left->text), mw / 3)) > mw)
89 88
			break;
90 89
}
91 90
96 95
	next = prev = curr;
97 96
	for(i = 0; i < lines && next; i++)
98 97
		next = next->right;
99 -
	mh = (dc.font.height + 2) * (i + 1);
100 98
	for(i = 0; i < lines && prev && prev->left; i++)
101 99
		prev = prev->left;
102 100
}
103 101
104 102
char *
105 103
cistrstr(const char *s, const char *sub) {
106 -
	int c, csub;
107 -
	unsigned int len;
104 +
	size_t len;
108 105
109 -
	if(!sub)
110 -
		return (char *)s;
111 -
	if((c = tolower(*sub++)) != '\0') {
112 -
		len = strlen(sub);
113 -
		do {
114 -
			do {
115 -
				if((csub = *s++) == '\0')
116 -
					return NULL;
117 -
			}
118 -
			while(tolower(csub) != c);
119 -
		}
120 -
		while(strncasecmp(s, sub, len) != 0);
121 -
		s--;
122 -
	}
123 -
	return (char *)s;
106 +
	for(len = strlen(sub); *s; s++)
107 +
		if(!strncasecmp(s, sub, len))
108 +
			return (char *)s;
109 +
	return NULL;
124 110
}
125 111
126 112
void
127 113
drawmenu(void) {
128 -
	dc.x = 0;
129 -
	dc.y = 0;
130 -
	dc.w = mw;
131 -
	dc.h = mh;
132 -
	drawbox(&dc, normcol);
133 -
	dc.h = dc.font.height + 2;
134 -
	dc.y = topbar ? 0 : mh - dc.h;
114 +
	dc->x = 0;
115 +
	dc->y = 0;
116 +
	drawrect(dc, 0, 0, mw, mh, BG(dc, normcol));
117 +
	dc->h = dc->font.height + 2;
118 +
	dc->y = topbar ? 0 : mh - dc->h;
135 119
	/* print prompt? */
136 120
	if(prompt) {
137 -
		dc.w = promptw;
138 -
		drawbox(&dc, selcol);
139 -
		drawtext(&dc, prompt, selcol);
140 -
		dc.x += dc.w;
121 +
		dc->w = textw(dc, prompt);
122 +
		drawtext(dc, prompt, selcol);
123 +
		dc->x = dc->w;
141 124
	}
142 -
	dc.w = mw - dc.x;
125 +
	dc->w = mw - dc->x;
143 126
	/* print input area */
144 -
	if(matches && lines == 0 && textw(&dc, text) <= inputw)
145 -
		dc.w = inputw;
146 -
	drawtext(&dc, text, normcol);
147 -
	drawline(&dc, textnw(&dc, text, cursor) + dc.h/2 - 2, 2, 1, dc.h-4, normcol);
127 +
	if(matches && lines == 0 && textw(dc, text) <= inputw)
128 +
		dc->w = inputw;
129 +
	drawtext(dc, text, normcol);
130 +
	drawrect(dc, textnw(dc, text, cursor) + dc->h/2 - 2, 2, 1, dc->h - 4, FG(dc, normcol));
148 131
	if(lines > 0)
149 132
		drawmenuv();
150 -
	else if(curr && (dc.w == inputw || curr->next))
133 +
	else if(curr && (dc->w == inputw || curr->next))
151 134
		drawmenuh();
152 -
	commitdraw(&dc, win);
135 +
	commitdraw(dc, win);
153 136
}
154 137
155 138
void
156 139
drawmenuh(void) {
157 140
	Item *item;
158 141
159 -
	dc.x += inputw;
160 -
	dc.w = textw(&dc, "<");
142 +
	dc->x += inputw;
143 +
	dc->w = textw(dc, "<");
161 144
	if(curr->left)
162 -
		drawtext(&dc, "<", normcol);
163 -
	dc.x += dc.w;
145 +
		drawtext(dc, "<", normcol);
164 146
	for(item = curr; item != next; item = item->right) {
165 -
		dc.w = MIN(textw(&dc, item->text), mw / 3);
166 -
		if(item == sel)
167 -
			drawbox(&dc, selcol);
168 -
		drawtext(&dc, item->text, (item == sel) ? selcol : normcol);
169 -
		dc.x += dc.w;
147 +
		dc->x += dc->w;
148 +
		dc->w = MIN(textw(dc, item->text), mw / 3);
149 +
		drawtext(dc, item->text, (item == sel) ? selcol : normcol);
170 150
	}
171 -
	dc.w = textw(&dc, ">");
172 -
	dc.x = mw - dc.w;
151 +
	dc->w = textw(dc, ">");
152 +
	dc->x = mw - dc->w;
173 153
	if(next)
174 -
		drawtext(&dc, ">", normcol);
154 +
		drawtext(dc, ">", normcol);
175 155
}
176 156
177 157
void
178 158
drawmenuv(void) {
179 159
	Item *item;
180 -
	XWindowAttributes wa;
181 160
182 -
	dc.y = topbar ? dc.h : 0;
183 -
	dc.w = mw - dc.x;
161 +
	dc->y = topbar ? dc->h : 0;
162 +
	dc->w = mw - dc->x;
184 163
	for(item = curr; item != next; item = item->right) {
185 -
		if(item == sel)
186 -
			drawbox(&dc, selcol);
187 -
		drawtext(&dc, item->text, (item == sel) ? selcol : normcol);
188 -
		dc.y += dc.h;
164 +
		drawtext(dc, item->text, (item == sel) ? selcol : normcol);
165 +
		dc->y += dc->h;
189 166
	}
190 -
	if(!XGetWindowAttributes(dc.dpy, win, &wa))
191 -
		eprintf("cannot get window attributes\n");
192 -
	if(wa.height != mh)
193 -
		XMoveResizeWindow(dc.dpy, win, wa.x, wa.y + (topbar ? 0 : wa.height - mh), mw, mh);
194 167
}
195 168
196 169
void
198 171
	int i;
199 172
200 173
	for(i = 0; i < 1000; i++) {
201 -
		if(!XGrabKeyboard(dc.dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime))
174 +
		if(!XGrabKeyboard(dc->dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime))
202 175
			return;
203 176
		usleep(1000);
204 177
	}
254 227
			break;
255 228
		case XK_k:  /* delete right */
256 229
			text[cursor] = '\0';
230 +
			match();
257 231
			break;
258 232
		case XK_n:
259 233
			ksym = XK_Down;
270 244
			n = 0;
271 245
			while(cursor - n++ > 0 && text[cursor - n] == ' ');
272 246
			while(cursor - n++ > 0 && text[cursor - n] != ' ');
273 -
			insert(NULL, -(--n));
247 +
			insert(NULL, 1-n);
274 248
			break;
275 249
		case XK_y:  /* paste selection */
276 -
			XConvertSelection(dc.dpy, XA_PRIMARY, utf8, None, win, CurrentTime);
250 +
			XConvertSelection(dc->dpy, XA_PRIMARY, utf8, None, win, CurrentTime);
277 251
			/* causes SelectionNotify event */
278 252
			return;
279 253
		}
348 322
		break;
349 323
	case XK_Return:
350 324
	case XK_KP_Enter:
351 -
		fputs(((e->state & ShiftMask) || sel) ? sel->text : text, stdout);
325 +
		fputs((sel && !(e->state & ShiftMask)) ? sel->text : text, stdout);
352 326
		fflush(stdout);
353 327
		exit(EXIT_SUCCESS);
354 328
	case XK_Right:
418 392
}
419 393
420 394
void
421 -
paste(Atom atom)
422 -
{
395 +
paste(void) {
423 396
	char *p, *q;
424 397
	int di;
425 398
	unsigned long dl;
426 399
	Atom da;
427 400
428 -
	XGetWindowProperty(dc.dpy, win, atom, 0, sizeof text - cursor, True,
429 -
			utf8, &da, &di, &dl, &dl, (unsigned char **)&p);
401 +
	XGetWindowProperty(dc->dpy, win, utf8, 0, sizeof text - cursor, True,
402 +
	                   utf8, &da, &di, &dl, &dl, (unsigned char **)&p);
430 403
	insert(p, (q = strchr(p, '\n')) ? q-p : strlen(p));
431 404
	XFree(p);
432 405
	drawmenu();
434 407
435 408
void
436 409
readstdin(void) {
437 -
	char buf[sizeof text];
438 -
	size_t len;
410 +
	char buf[sizeof text], *p;
439 411
	Item *item, *new;
440 412
441 413
	allitems = NULL;
442 414
	for(item = NULL; fgets(buf, sizeof buf, stdin); item = new) {
443 -
		len = strlen(buf);
444 -
		if(buf[len-1] == '\n')
445 -
			buf[--len] = '\0';
415 +
		if((p = strchr(buf, '\n')))
416 +
			*p = '\0';
446 417
		if(!(new = malloc(sizeof *new)))
447 418
			eprintf("cannot malloc %u bytes\n", sizeof *new);
448 419
		if(!(new->text = strdup(buf)))
449 -
			eprintf("cannot strdup %u bytes\n", len);
450 -
		inputw = MAX(inputw, textw(&dc, new->text));
420 +
			eprintf("cannot strdup %u bytes\n", strlen(buf));
421 +
		inputw = MAX(inputw, textw(dc, new->text));
451 422
		new->next = new->left = new->right = NULL;
452 423
		if(item)
453 424
			item->next = new;
454 -
		else 
425 +
		else
455 426
			allitems = new;
456 427
	}
457 428
}
460 431
run(void) {
461 432
	XEvent ev;
462 433
463 -
	while(!XNextEvent(dc.dpy, &ev))
434 +
	while(!XNextEvent(dc->dpy, &ev))
464 435
		switch(ev.type) {
465 436
		case Expose:
466 437
			if(ev.xexpose.count == 0)
470 441
			keypress(&ev.xkey);
471 442
			break;
472 443
		case SelectionNotify:
473 -
			if(ev.xselection.property != None)
474 -
				paste(ev.xselection.property);
444 +
			if(ev.xselection.property == utf8)
445 +
				paste();
475 446
			break;
476 447
		case VisibilityNotify:
477 448
			if(ev.xvisibility.state != VisibilityUnobscured)
478 -
				XRaiseWindow(dc.dpy, win);
449 +
				XRaiseWindow(dc->dpy, win);
479 450
			break;
480 451
		}
481 452
}
482 453
483 454
void
484 455
setup(void) {
485 -
	int x, y;
456 +
	int x, y, screen;
457 +
	XSetWindowAttributes wa;
486 458
#ifdef XINERAMA
487 -
	int i, n;
459 +
	int n;
488 460
	XineramaScreenInfo *info;
489 461
#endif
490 -
	XSetWindowAttributes wa;
491 462
492 -
	normcol[ColBG] = getcolor(&dc, normbgcolor);
493 -
	normcol[ColFG] = getcolor(&dc, normfgcolor);
494 -
	selcol[ColBG] = getcolor(&dc, selbgcolor);
495 -
	selcol[ColFG] = getcolor(&dc, selfgcolor);
463 +
	screen = DefaultScreen(dc->dpy);
464 +
	root = RootWindow(dc->dpy, screen);
465 +
	utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False);
466 +
467 +
	normcol[ColBG] = getcolor(dc, normbgcolor);
468 +
	normcol[ColFG] = getcolor(dc, normfgcolor);
469 +
	selcol[ColBG] = getcolor(dc, selbgcolor);
470 +
	selcol[ColFG] = getcolor(dc, selfgcolor);
496 471
497 472
	/* input window geometry */
498 -
	mh = (dc.font.height + 2) * (lines + 1);
473 +
	mh = (dc->font.height + 2) * (lines + 1);
499 474
#ifdef XINERAMA
500 -
	if((info = XineramaQueryScreens(dc.dpy, &n))) {
501 -
		int di;
475 +
	if((info = XineramaQueryScreens(dc->dpy, &n))) {
476 +
		int i, di;
502 477
		unsigned int du;
503 478
		Window dw;
504 479
505 -
		XQueryPointer(dc.dpy, root, &dw, &dw, &x, &y, &di, &di, &du);
480 +
		XQueryPointer(dc->dpy, root, &dw, &dw, &x, &y, &di, &di, &du);
506 481
		for(i = 0; i < n; i++)
507 482
			if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
508 483
				break;
515 490
#endif
516 491
	{
517 492
		x = 0;
518 -
		y = topbar ? 0 : DisplayHeight(dc.dpy, screen) - mh;
519 -
		mw = DisplayWidth(dc.dpy, screen);
493 +
		y = topbar ? 0 : DisplayHeight(dc->dpy, screen) - mh;
494 +
		mw = DisplayWidth(dc->dpy, screen);
520 495
	}
521 496
522 497
	/* input window */
523 498
	wa.override_redirect = True;
524 499
	wa.background_pixmap = ParentRelative;
525 500
	wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
526 -
	win = XCreateWindow(dc.dpy, root, x, y, mw, mh, 0,
527 -
			DefaultDepth(dc.dpy, screen), CopyFromParent,
528 -
			DefaultVisual(dc.dpy, screen),
501 +
	win = XCreateWindow(dc->dpy, root, x, y, mw, mh, 0,
502 +
			DefaultDepth(dc->dpy, screen), CopyFromParent,
503 +
			DefaultVisual(dc->dpy, screen),
529 504
			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
530 505
506 +
	grabkeyboard();
507 +
	setcanvas(dc, win, mw, mh);
508 +
	inputw = MIN(inputw, mw/3);
509 +
	XMapRaised(dc->dpy, win);
531 510
	match();
532 -
	grabkeyboard();
533 -
	setupdraw(&dc, win);
534 -
	inputw = MIN(inputw, mw / 3);
535 -
	utf8 = XInternAtom(dc.dpy, "UTF8_STRING", False);
536 -
	XMapRaised(dc.dpy, win);
537 511
}
538 512
539 513
void
540 514
usage(void) {
541 -
	fputs("usage: dmenu [-b] [-i] [-l <lines>] [-p <prompt>] [-fn <font>] [-nb <color>]\n"
542 -
		      "             [-nf <color>] [-sb <color>] [-sf <color>] [-v]\n", stderr);
515 +
	fputs("usage: dmenu [-b] [-i] [-l lines] [-p prompt] [-fn font] [-nb color]\n"
516 +
	      "             [-nf color] [-sb color] [-sf color] [-v]\n", stderr);
543 517
	exit(EXIT_FAILURE);
544 518
}
545 519
548 522
	int i;
549 523
550 524
	progname = "dmenu";
525 +
	dc = initdraw();
526 +
551 527
	for(i = 1; i < argc; i++)
552 -
		/* 1-arg flags */
528 +
		/* single flags */
553 529
		if(!strcmp(argv[i], "-v")) {
554 530
			fputs("dmenu-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n", stdout);
555 531
			exit(EXIT_SUCCESS);
562 538
		}
563 539
		else if(i == argc-1)
564 540
			usage();
565 -
		/* 2-arg flags */
541 +
		/* double flags */
566 542
		else if(!strcmp(argv[i], "-l")) {
567 543
			if((lines = atoi(argv[++i])) > 0)
568 544
				calcoffsets = calcoffsetsv;
569 545
		}
570 -
		else if(!strcmp(argv[i], "-p")) {
546 +
		else if(!strcmp(argv[i], "-p"))
571 547
			prompt = argv[++i];
572 -
			promptw = MIN(textw(&dc, prompt), mw/5);
573 -
		}
574 548
		else if(!strcmp(argv[i], "-fn"))
575 -
			font = argv[++i];
549 +
			initfont(dc, argv[i++]);
576 550
		else if(!strcmp(argv[i], "-nb"))
577 551
			normbgcolor = argv[++i];
578 552
		else if(!strcmp(argv[i], "-nf"))
583 557
			selfgcolor = argv[++i];
584 558
		else
585 559
			usage();
586 -
587 -
	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
588 -
		fputs("dmenu: warning: no locale support\n", stderr);
589 -
	if(!(dc.dpy = XOpenDisplay(NULL)))
590 -
		eprintf("cannot open display\n");
591 -
	screen = DefaultScreen(dc.dpy);
592 -
	root = RootWindow(dc.dpy, screen);
593 -
	initfont(&dc, font);
594 560
595 561
	readstdin();
596 562
	setup();
dmenu_path +1 −1
19 19
		do
20 20
			test -x "$file" && echo "$file"
21 21
		done
22 -
	done | sort | uniq > "$CACHE".$$ &&
22 +
	done | sort -u > "$CACHE".$$ &&
23 23
	mv "$CACHE".$$ "$CACHE"
24 24
fi
25 25