aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConnor Lane Smith <cls@lubutu.com>2010-07-02 06:49:05 +0100
committerConnor Lane Smith <cls@lubutu.com>2010-07-02 06:49:05 +0100
commit855a56631916bdff1438e11c232b88450f973648 (patch)
treec7ed1e1ae2aac45b3e3980cfa36bc45b9580e39e
parent29e8faed6cf4b296382439651cf04596d276f080 (diff)
added dmenu.h, common.c
-rw-r--r--Makefile10
-rw-r--r--common.c129
-rw-r--r--config.def.h11
-rw-r--r--dinput.c150
-rw-r--r--dmenu.c188
-rw-r--r--dmenu.h30
6 files changed, 204 insertions, 314 deletions
diff --git a/Makefile b/Makefile
index 0f29652..7274923 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
3 3
4include config.mk 4include config.mk
5 5
6SRC = dinput.c dmenu.c 6SRC = dinput.c dmenu.c common.c
7OBJ = ${SRC:.c=.o} 7OBJ = ${SRC:.c=.o}
8 8
9all: options dinput dmenu 9all: options dinput dmenu
@@ -24,9 +24,13 @@ config.h:
24 @echo creating $@ from config.def.h 24 @echo creating $@ from config.def.h
25 @cp config.def.h $@ 25 @cp config.def.h $@
26 26
27.o: 27dinput: dinput.o common.o
28 @echo CC -o $@ 28 @echo CC -o $@
29 @${CC} -o $@ $< ${LDFLAGS} 29 @${CC} -o $@ $+ ${LDFLAGS}
30
31dmenu: dmenu.o common.o
32 @echo CC -o $@
33 @${CC} -o $@ $+ ${LDFLAGS}
30 34
31clean: 35clean:
32 @echo cleaning 36 @echo cleaning
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..2d19aee
--- /dev/null
+++ b/common.c
@@ -0,0 +1,129 @@
1/* See LICENSE file for copyright and license details. */
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <X11/keysym.h>
6#ifdef XINERAMA
7#include <X11/extensions/Xinerama.h>
8#endif
9#include "dmenu.h"
10
11/* variables */
12char *prompt = NULL;
13char text[4096] = "";
14int promptw = 0;
15int screen;
16unsigned int numlockmask = 0;
17unsigned int mw, mh;
18unsigned long normcol[ColLast];
19unsigned long selcol[ColLast];
20Bool topbar = True;
21DC dc;
22Display *dpy;
23Window win, root;
24
25void
26grabkeyboard(void) {
27 unsigned int len;
28
29 for(len = 1000; len; len--) {
30 if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
31 == GrabSuccess)
32 return;
33 usleep(1000);
34 }
35 exit(EXIT_FAILURE);
36}
37
38void
39run(void) {
40 XEvent ev;
41
42 /* main event loop */
43 XSync(dpy, False);
44 while(!XNextEvent(dpy, &ev))
45 switch(ev.type) {
46 case KeyPress:
47 kpress(&ev.xkey);
48 break;
49 case Expose:
50 if(ev.xexpose.count == 0)
51 drawbar();
52 break;
53 case VisibilityNotify:
54 if(ev.xvisibility.state != VisibilityUnobscured)
55 XRaiseWindow(dpy, win);
56 break;
57 }
58 exit(EXIT_FAILURE);
59}
60
61void
62setup(unsigned int lines) {
63 int i, j, x, y;
64#if XINERAMA
65 int n;
66 XineramaScreenInfo *info = NULL;
67#endif
68 XModifierKeymap *modmap;
69 XSetWindowAttributes wa;
70
71 /* init modifier map */
72 modmap = XGetModifierMapping(dpy);
73 for(i = 0; i < 8; i++)
74 for(j = 0; j < modmap->max_keypermod; j++) {
75 if(modmap->modifiermap[i * modmap->max_keypermod + j]
76 == XKeysymToKeycode(dpy, XK_Num_Lock))
77 numlockmask = (1 << i);
78 }
79 XFreeModifiermap(modmap);
80
81 dc.dpy = dpy;
82 normcol[ColBG] = getcolor(&dc, normbgcolor);
83 normcol[ColFG] = getcolor(&dc, normfgcolor);
84 selcol[ColBG] = getcolor(&dc, selbgcolor);
85 selcol[ColFG] = getcolor(&dc, selfgcolor);
86 initfont(&dc, font);
87
88 /* input window */
89 wa.override_redirect = True;
90 wa.background_pixmap = ParentRelative;
91 wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
92
93 /* input window geometry */
94 mh = (dc.font.height + 2) * (lines + 1);
95#if XINERAMA
96 if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
97 i = 0;
98 if(n > 1) {
99 int di;
100 unsigned int dui;
101 Window dummy;
102 if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
103 for(i = 0; i < n; i++)
104 if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
105 break;
106 }
107 x = info[i].x_org;
108 y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh;
109 mw = info[i].width;
110 XFree(info);
111 }
112 else
113#endif
114 {
115 x = 0;
116 y = topbar ? 0 : DisplayHeight(dpy, screen) - mh;
117 mw = DisplayWidth(dpy, screen);
118 }
119
120 win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
121 DefaultDepth(dpy, screen), CopyFromParent,
122 DefaultVisual(dpy, screen),
123 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
124
125 setupdraw(&dc, win);
126 if(prompt)
127 promptw = MIN(textw(&dc, prompt), mw / 5);
128 XMapRaised(dpy, win);
129}
diff --git a/config.def.h b/config.def.h
index cda3b2a..eae3f08 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,9 +1,8 @@
1/* See LICENSE file for copyright and license details. */ 1/* See LICENSE file for copyright and license details. */
2 2
3/* appearance */ 3/* appearance */
4const char *font = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*"; 4static const char *font = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*";
5const char *normbgcolor = "#cccccc"; 5static const char *normbgcolor = "#cccccc";
6const char *normfgcolor = "#000000"; 6static const char *normfgcolor = "#000000";
7const char *selbgcolor = "#0066ff"; 7static const char *selbgcolor = "#0066ff";
8const char *selfgcolor = "#ffffff"; 8static const char *selfgcolor = "#ffffff";
9unsigned int spaceitem = 30; /* px between menu items */
diff --git a/dinput.c b/dinput.c
index 0d0adeb..e22bc35 100644
--- a/dinput.c
+++ b/dinput.c
@@ -4,45 +4,16 @@
4#include <stdio.h> 4#include <stdio.h>
5#include <stdlib.h> 5#include <stdlib.h>
6#include <string.h> 6#include <string.h>
7#include <unistd.h>
8#include <X11/keysym.h> 7#include <X11/keysym.h>
9#include <X11/Xlib.h> 8#include <X11/Xlib.h>
10#include <X11/Xutil.h> 9#include <X11/Xutil.h>
11#ifdef XINERAMA 10#include "dmenu.h"
12#include <X11/extensions/Xinerama.h>
13#endif
14#include <draw.h>
15
16/* macros */
17#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
18#define MIN(a, b) ((a) < (b) ? (a) : (b))
19#define MAX(a, b) ((a) > (b) ? (a) : (b))
20#define IS_UTF8_1ST_CHAR(c) ((((c) & 0xc0) == 0xc0) || !((c) & 0x80))
21 11
22/* forward declarations */ 12/* forward declarations */
23static void cleanup(void); 13static void cleanup(void);
24static void drawinput(void);
25static void grabkeyboard(void);
26static void kpress(XKeyEvent *e);
27static void run(void);
28static void setup(void);
29
30#include "config.h"
31 14
32/* variables */ 15/* variables */
33static char *prompt = NULL;
34static char text[4096];
35static int promptw = 0;
36static int screen;
37static size_t cursor = 0; 16static size_t cursor = 0;
38static unsigned int numlockmask = 0;
39static unsigned int mw, mh;
40static unsigned long normcol[ColLast];
41static unsigned long selcol[ColLast];
42static Bool topbar = True;
43static DC dc;
44static Display *dpy;
45static Window win, root;
46 17
47void 18void
48cleanup(void) { 19cleanup(void) {
@@ -53,7 +24,7 @@ cleanup(void) {
53} 24}
54 25
55void 26void
56drawinput(void) 27drawbar(void)
57{ 28{
58 dc.x = 0; 29 dc.x = 0;
59 dc.y = 0; 30 dc.y = 0;
@@ -73,19 +44,6 @@ drawinput(void)
73} 44}
74 45
75void 46void
76grabkeyboard(void) {
77 unsigned int len;
78
79 for(len = 1000; len; len--) {
80 if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
81 == GrabSuccess)
82 return;
83 usleep(1000);
84 }
85 exit(EXIT_FAILURE);
86}
87
88void
89kpress(XKeyEvent *e) { 47kpress(XKeyEvent *e) {
90 char buf[sizeof text]; 48 char buf[sizeof text];
91 int num; 49 int num;
@@ -207,101 +165,7 @@ kpress(XKeyEvent *e) {
207 while(cursor++ < len && !IS_UTF8_1ST_CHAR(text[cursor])); 165 while(cursor++ < len && !IS_UTF8_1ST_CHAR(text[cursor]));
208 break; 166 break;
209 } 167 }
210 drawinput(); 168 drawbar();
211}
212
213void
214run(void) {
215 XEvent ev;
216
217 /* main event loop */
218 XSync(dpy, False);
219 while(!XNextEvent(dpy, &ev))
220 switch(ev.type) {
221 case KeyPress:
222 kpress(&ev.xkey);
223 break;
224 case Expose:
225 if(ev.xexpose.count == 0)
226 drawinput();
227 break;
228 case VisibilityNotify:
229 if(ev.xvisibility.state != VisibilityUnobscured)
230 XRaiseWindow(dpy, win);
231 break;
232 }
233 exit(EXIT_FAILURE);
234}
235
236void
237setup(void) {
238 int i, j, x, y;
239#if XINERAMA
240 int n;
241 XineramaScreenInfo *info = NULL;
242#endif
243 XModifierKeymap *modmap;
244 XSetWindowAttributes wa;
245
246 /* init modifier map */
247 modmap = XGetModifierMapping(dpy);
248 for(i = 0; i < 8; i++)
249 for(j = 0; j < modmap->max_keypermod; j++) {
250 if(modmap->modifiermap[i * modmap->max_keypermod + j]
251 == XKeysymToKeycode(dpy, XK_Num_Lock))
252 numlockmask = (1 << i);
253 }
254 XFreeModifiermap(modmap);
255
256 dc.dpy = dpy;
257 normcol[ColBG] = getcolor(&dc, normbgcolor);
258 normcol[ColFG] = getcolor(&dc, normfgcolor);
259 selcol[ColBG] = getcolor(&dc, selbgcolor);
260 selcol[ColFG] = getcolor(&dc, selfgcolor);
261 initfont(&dc, font);
262
263 /* input window */
264 wa.override_redirect = True;
265 wa.background_pixmap = ParentRelative;
266 wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
267
268 /* input window geometry */
269 mh = dc.font.height + 2;
270#if XINERAMA
271 if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
272 i = 0;
273 if(n > 1) {
274 int di;
275 unsigned int dui;
276 Window dummy;
277 if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
278 for(i = 0; i < n; i++)
279 if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
280 break;
281 }
282 x = info[i].x_org;
283 y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh;
284 mw = info[i].width;
285 XFree(info);
286 }
287 else
288#endif
289 {
290 x = 0;
291 y = topbar ? 0 : DisplayHeight(dpy, screen) - mh;
292 mw = DisplayWidth(dpy, screen);
293 }
294
295 win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
296 DefaultDepth(dpy, screen), CopyFromParent,
297 DefaultVisual(dpy, screen),
298 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
299
300 setupdraw(&dc, win);
301 if(prompt)
302 promptw = MIN(textw(&dc, prompt), mw / 5);
303 cursor = strlen(text);
304 XMapRaised(dpy, win);
305} 169}
306 170
307int 171int
@@ -336,11 +200,13 @@ main(int argc, char *argv[]) {
336 if(++i < argc) selfgcolor = argv[i]; 200 if(++i < argc) selfgcolor = argv[i];
337 } 201 }
338 else if(!strcmp(argv[i], "-v")) { 202 else if(!strcmp(argv[i], "-v")) {
339 printf("dinput-"VERSION", © 2006-2010 dinput engineers, see LICENSE for details\n"); 203 printf("dinput-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n");
340 exit(EXIT_SUCCESS); 204 exit(EXIT_SUCCESS);
341 } 205 }
342 else if(!*text) 206 else if(!*text) {
343 strncpy(text, argv[i], sizeof text); 207 strncpy(text, argv[i], sizeof text);
208 cursor = strlen(text);
209 }
344 else { 210 else {
345 fputs("usage: dinput [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n" 211 fputs("usage: dinput [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
346 " [-p <prompt>] [-sb <color>] [-sf <color>] [-v] [<text>]\n", stderr); 212 " [-p <prompt>] [-sb <color>] [-sf <color>] [-v] [<text>]\n", stderr);
@@ -356,7 +222,7 @@ main(int argc, char *argv[]) {
356 root = RootWindow(dpy, screen); 222 root = RootWindow(dpy, screen);
357 223
358 grabkeyboard(); 224 grabkeyboard();
359 setup(); 225 setup(0);
360 run(); 226 run();
361 return 0; 227 return 0;
362} 228}
diff --git a/dmenu.c b/dmenu.c
index c612dbe..6fc414c 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -8,16 +8,7 @@
8#include <X11/keysym.h> 8#include <X11/keysym.h>
9#include <X11/Xlib.h> 9#include <X11/Xlib.h>
10#include <X11/Xutil.h> 10#include <X11/Xutil.h>
11#ifdef XINERAMA 11#include "dmenu.h"
12#include <X11/extensions/Xinerama.h>
13#endif
14#include <draw.h>
15
16/* macros */
17#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
18#define MIN(a, b) ((a) < (b) ? (a) : (b))
19#define MAX(a, b) ((a) > (b) ? (a) : (b))
20#define IS_UTF8_1ST_CHAR(c) ((((c) & 0xc0) == 0xc0) || !((c) & 0x80))
21 12
22typedef struct Item Item; 13typedef struct Item Item;
23struct Item { 14struct Item {
@@ -33,41 +24,22 @@ static void calcoffsetsv(void);
33static char *cistrstr(const char *s, const char *sub); 24static char *cistrstr(const char *s, const char *sub);
34static void cleanup(void); 25static void cleanup(void);
35static void dinput(void); 26static void dinput(void);
36static void drawmenu(void);
37static void drawmenuh(void); 27static void drawmenuh(void);
38static void drawmenuv(void); 28static void drawmenuv(void);
39static void grabkeyboard(void); 29static void match(void);
40static void kpress(XKeyEvent *e);
41static void match(char *pattern);
42static void readstdin(void); 30static void readstdin(void);
43static void run(void);
44static void setup(void);
45
46#include "config.h"
47 31
48/* variables */ 32/* variables */
49static char **argp = NULL; 33static char **argp = NULL;
50static char *maxname = NULL; 34static char *maxname = NULL;
51static char *prompt = NULL; 35static unsigned int cmdw = 0;
52static char text[4096];
53static int cmdw = 0;
54static int promptw = 0;
55static int screen;
56static unsigned int lines = 0; 36static unsigned int lines = 0;
57static unsigned int numlockmask = 0;
58static unsigned int mw, mh;
59static unsigned long normcol[ColLast];
60static unsigned long selcol[ColLast];
61static Bool topbar = True;
62static DC dc;
63static Display *dpy;
64static Item *allitems = NULL; /* first of all items */ 37static Item *allitems = NULL; /* first of all items */
65static Item *item = NULL; /* first of pattern matching items */ 38static Item *item = NULL; /* first of pattern matching items */
66static Item *sel = NULL; 39static Item *sel = NULL;
67static Item *next = NULL; 40static Item *next = NULL;
68static Item *prev = NULL; 41static Item *prev = NULL;
69static Item *curr = NULL; 42static Item *curr = NULL;
70static Window win, root;
71static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; 43static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
72static char *(*fstrstr)(const char *, const char *) = strstr; 44static char *(*fstrstr)(const char *, const char *) = strstr;
73static void (*calcoffsets)(void) = calcoffsetsh; 45static void (*calcoffsets)(void) = calcoffsetsh;
@@ -85,14 +57,13 @@ appenditem(Item *i, Item **list, Item **last) {
85 57
86void 58void
87calcoffsetsh(void) { 59calcoffsetsh(void) {
88 unsigned int x; 60 unsigned int w, x;
89 61
90 x = promptw + cmdw + (2 * spaceitem); 62 w = promptw + cmdw + textw(&dc, "<") + textw(&dc, ">");
91 for(next = curr; next; next = next->right) 63 for(x = w, next = curr; next; next = next->right)
92 if((x += MIN(textw(&dc, next->text), mw / 3)) > mw) 64 if((x += MIN(textw(&dc, next->text), mw / 3)) > mw)
93 break; 65 break;
94 x = promptw + cmdw + (2 * spaceitem); 66 for(x = w, prev = curr; prev && prev->left; prev = prev->left)
95 for(prev = curr; prev && prev->left; prev = prev->left)
96 if((x += MIN(textw(&dc, prev->left->text), mw / 3)) > mw) 67 if((x += MIN(textw(&dc, prev->left->text), mw / 3)) > mw)
97 break; 68 break;
98} 69}
@@ -157,7 +128,7 @@ dinput(void) {
157} 128}
158 129
159void 130void
160drawmenu(void) { 131drawbar(void) {
161 dc.x = 0; 132 dc.x = 0;
162 dc.y = 0; 133 dc.y = 0;
163 dc.w = mw; 134 dc.w = mw;
@@ -188,7 +159,7 @@ drawmenuh(void) {
188 Item *i; 159 Item *i;
189 160
190 dc.x += cmdw; 161 dc.x += cmdw;
191 dc.w = spaceitem; 162 dc.w = textw(&dc, "<");
192 drawtext(&dc, curr->left ? "<" : NULL, normcol); 163 drawtext(&dc, curr->left ? "<" : NULL, normcol);
193 dc.x += dc.w; 164 dc.x += dc.w;
194 for(i = curr; i != next; i = i->right) { 165 for(i = curr; i != next; i = i->right) {
@@ -196,7 +167,7 @@ drawmenuh(void) {
196 drawtext(&dc, i->text, (sel == i) ? selcol : normcol); 167 drawtext(&dc, i->text, (sel == i) ? selcol : normcol);
197 dc.x += dc.w; 168 dc.x += dc.w;
198 } 169 }
199 dc.w = spaceitem; 170 dc.w = textw(&dc, ">");
200 dc.x = mw - dc.w; 171 dc.x = mw - dc.w;
201 drawtext(&dc, next ? ">" : NULL, normcol); 172 drawtext(&dc, next ? ">" : NULL, normcol);
202} 173}
@@ -218,19 +189,6 @@ drawmenuv(void) {
218} 189}
219 190
220void 191void
221grabkeyboard(void) {
222 unsigned int len;
223
224 for(len = 1000; len; len--) {
225 if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
226 == GrabSuccess)
227 return;
228 usleep(1000);
229 }
230 exit(EXIT_FAILURE);
231}
232
233void
234kpress(XKeyEvent *e) { 192kpress(XKeyEvent *e) {
235 char buf[sizeof text]; 193 char buf[sizeof text];
236 int num; 194 int num;
@@ -285,7 +243,7 @@ kpress(XKeyEvent *e) {
285 break; 243 break;
286 case XK_u: 244 case XK_u:
287 text[0] = '\0'; 245 text[0] = '\0';
288 match(text); 246 match();
289 break; 247 break;
290 case XK_w: 248 case XK_w:
291 if(len == 0) 249 if(len == 0)
@@ -294,7 +252,7 @@ kpress(XKeyEvent *e) {
294 while(i-- > 0 && text[i] == ' '); 252 while(i-- > 0 && text[i] == ' ');
295 while(i-- > 0 && text[i] != ' '); 253 while(i-- > 0 && text[i] != ' ');
296 text[++i] = '\0'; 254 text[++i] = '\0';
297 match(text); 255 match();
298 break; 256 break;
299 } 257 }
300 } 258 }
@@ -304,7 +262,7 @@ kpress(XKeyEvent *e) {
304 if(num && !iscntrl((int) buf[0])) { 262 if(num && !iscntrl((int) buf[0])) {
305 memcpy(text + len, buf, num + 1); 263 memcpy(text + len, buf, num + 1);
306 len += num; 264 len += num;
307 match(text); 265 match();
308 } 266 }
309 break; 267 break;
310 case XK_BackSpace: 268 case XK_BackSpace:
@@ -313,7 +271,7 @@ kpress(XKeyEvent *e) {
313 for(i = 1; len - i > 0 && !IS_UTF8_1ST_CHAR(text[len - i]); i++); 271 for(i = 1; len - i > 0 && !IS_UTF8_1ST_CHAR(text[len - i]); i++);
314 len -= i; 272 len -= i;
315 text[len] = '\0'; 273 text[len] = '\0';
316 match(text); 274 match();
317 break; 275 break;
318 case XK_End: 276 case XK_End:
319 while(next) { 277 while(next) {
@@ -373,24 +331,22 @@ kpress(XKeyEvent *e) {
373 dinput(); 331 dinput();
374 break; 332 break;
375 } 333 }
376 drawmenu(); 334 drawbar();
377} 335}
378 336
379void 337void
380match(char *pattern) { 338match(void) {
381 unsigned int plen; 339 unsigned int len;
382 Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend; 340 Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
383 341
384 if(!pattern) 342 len = strlen(text);
385 return;
386 plen = strlen(pattern);
387 item = lexact = lprefix = lsubstr = itemend = exactend = prefixend = substrend = NULL; 343 item = lexact = lprefix = lsubstr = itemend = exactend = prefixend = substrend = NULL;
388 for(i = allitems; i; i = i->next) 344 for(i = allitems; i; i = i->next)
389 if(!fstrncmp(pattern, i->text, plen + 1)) 345 if(!fstrncmp(text, i->text, len + 1))
390 appenditem(i, &lexact, &exactend); 346 appenditem(i, &lexact, &exactend);
391 else if(!fstrncmp(pattern, i->text, plen)) 347 else if(!fstrncmp(text, i->text, len))
392 appenditem(i, &lprefix, &prefixend); 348 appenditem(i, &lprefix, &prefixend);
393 else if(fstrstr(i->text, pattern)) 349 else if(fstrstr(i->text, text))
394 appenditem(i, &lsubstr, &substrend); 350 appenditem(i, &lsubstr, &substrend);
395 if(lexact) { 351 if(lexact) {
396 item = lexact; 352 item = lexact;
@@ -444,103 +400,6 @@ readstdin(void) {
444 } 400 }
445} 401}
446 402
447void
448run(void) {
449 XEvent ev;
450
451 /* main event loop */
452 XSync(dpy, False);
453 while(!XNextEvent(dpy, &ev))
454 switch(ev.type) {
455 case KeyPress:
456 kpress(&ev.xkey);
457 break;
458 case Expose:
459 if(ev.xexpose.count == 0)
460 drawmenu();
461 break;
462 case VisibilityNotify:
463 if(ev.xvisibility.state != VisibilityUnobscured)
464 XRaiseWindow(dpy, win);
465 break;
466 }
467 exit(EXIT_FAILURE);
468}
469
470void
471setup(void) {
472 int i, j, x, y;
473#if XINERAMA
474 int n;
475 XineramaScreenInfo *info = NULL;
476#endif
477 XModifierKeymap *modmap;
478 XSetWindowAttributes wa;
479
480 /* init modifier map */
481 modmap = XGetModifierMapping(dpy);
482 for(i = 0; i < 8; i++)
483 for(j = 0; j < modmap->max_keypermod; j++) {
484 if(modmap->modifiermap[i * modmap->max_keypermod + j]
485 == XKeysymToKeycode(dpy, XK_Num_Lock))
486 numlockmask = (1 << i);
487 }
488 XFreeModifiermap(modmap);
489
490 dc.dpy = dpy;
491 normcol[ColBG] = getcolor(&dc, normbgcolor);
492 normcol[ColFG] = getcolor(&dc, normfgcolor);
493 selcol[ColBG] = getcolor(&dc, selbgcolor);
494 selcol[ColFG] = getcolor(&dc, selfgcolor);
495 initfont(&dc, font);
496
497 /* menu window */
498 wa.override_redirect = True;
499 wa.background_pixmap = ParentRelative;
500 wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
501
502 /* menu window geometry */
503 mh = (dc.font.height + 2) * (lines + 1);
504#if XINERAMA
505 if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
506 i = 0;
507 if(n > 1) {
508 int di;
509 unsigned int dui;
510 Window dummy;
511 if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
512 for(i = 0; i < n; i++)
513 if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
514 break;
515 }
516 x = info[i].x_org;
517 y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh;
518 mw = info[i].width;
519 XFree(info);
520 }
521 else
522#endif
523 {
524 x = 0;
525 y = topbar ? 0 : mh - DisplayHeight(dpy, screen);
526 mw = DisplayWidth(dpy, screen);
527 }
528
529 win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
530 DefaultDepth(dpy, screen), CopyFromParent,
531 DefaultVisual(dpy, screen),
532 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
533
534 setupdraw(&dc, win);
535 if(maxname)
536 cmdw = MIN(textw(&dc, maxname), mw / 3);
537 if(prompt)
538 promptw = MIN(textw(&dc, prompt), mw / 5);
539 text[0] = '\0';
540 match(text);
541 XMapRaised(dpy, win);
542}
543
544int 403int
545main(int argc, char *argv[]) { 404main(int argc, char *argv[]) {
546 unsigned int i; 405 unsigned int i;
@@ -600,7 +459,10 @@ main(int argc, char *argv[]) {
600 459
601 readstdin(); 460 readstdin();
602 grabkeyboard(); 461 grabkeyboard();
603 setup(); 462 setup(lines);
463 if(maxname)
464 cmdw = MIN(textw(&dc, maxname), mw / 3);
465 match();
604 run(); 466 run();
605 return 0; 467 return 0;
606} 468}
diff --git a/dmenu.h b/dmenu.h
new file mode 100644
index 0000000..4cc13f4
--- /dev/null
+++ b/dmenu.h
@@ -0,0 +1,30 @@
1#include <X11/Xlib.h>
2#include <draw.h>
3#include "config.h"
4
5/* macros */
6#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
7#define MIN(a, b) ((a) < (b) ? (a) : (b))
8#define MAX(a, b) ((a) > (b) ? (a) : (b))
9#define IS_UTF8_1ST_CHAR(c) ((((c) & 0xc0) == 0xc0) || !((c) & 0x80))
10
11/* forward declarations */
12void drawbar(void);
13void grabkeyboard(void);
14void kpress(XKeyEvent *e);
15void run(void);
16void setup(unsigned int lines);
17
18/* variables */
19extern char *prompt;
20extern char text[4096];
21extern int promptw;
22extern int screen;
23extern unsigned int numlockmask;
24extern unsigned int mw, mh;
25extern unsigned long normcol[ColLast];
26extern unsigned long selcol[ColLast];
27extern Bool topbar;
28extern DC dc;
29extern Display *dpy;
30extern Window win, root;