diff options
-rw-r--r-- | LICENSE | 18 | ||||
-rw-r--r-- | config.h | 4 | ||||
-rw-r--r-- | config.mk | 4 | ||||
-rw-r--r-- | dmenu.c | 130 |
4 files changed, 74 insertions, 82 deletions
@@ -8,16 +8,16 @@ Permission is hereby granted, free of charge, to any person obtaining a | |||
8 | copy of this software and associated documentation files (the "Software"), | 8 | copy of this software and associated documentation files (the "Software"), |
9 | to deal in the Software without restriction, including without limitation | 9 | to deal in the Software without restriction, including without limitation |
10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, | 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, |
11 | and/or sell copies of the Software, and to permit persons to whom the | 11 | and/or sell copies of the Software, and to permit persons to whom the |
12 | Software is furnished to do so, subject to the following conditions: | 12 | Software is furnished to do so, subject to the following conditions: |
13 | 13 | ||
14 | The above copyright notice and this permission notice shall be included in | 14 | The above copyright notice and this permission notice shall be included in |
15 | all copies or substantial portions of the Software. | 15 | all copies or substantial portions of the Software. |
16 | 16 | ||
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | DEALINGS IN THE SOFTWARE. | 23 | DEALINGS IN THE SOFTWARE. |
@@ -6,5 +6,5 @@ | |||
6 | #define NORMFGCOLOR "#000000" | 6 | #define NORMFGCOLOR "#000000" |
7 | #define SELBGCOLOR "#0066ff" | 7 | #define SELBGCOLOR "#0066ff" |
8 | #define SELFGCOLOR "#ffffff" | 8 | #define SELFGCOLOR "#ffffff" |
9 | /* next macro defines the space between menu items */ | 9 | |
10 | #define SPACE 30 /* px */ | 10 | static uint spaceitem = 30; /* px between menu items */ |
@@ -20,10 +20,8 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} | |||
20 | 20 | ||
21 | # flags | 21 | # flags |
22 | CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} | 22 | CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} |
23 | CFLAGS = -Os ${INCS} ${CPPFLAGS} | 23 | CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} |
24 | LDFLAGS = -s ${LIBS} | 24 | LDFLAGS = -s ${LIBS} |
25 | #CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" | ||
26 | #LDFLAGS = -g ${LIBS} | ||
27 | 25 | ||
28 | # Solaris | 26 | # Solaris |
29 | #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" | 27 | #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" |
@@ -2,13 +2,14 @@ | |||
2 | #include <ctype.h> | 2 | #include <ctype.h> |
3 | #include <locale.h> | 3 | #include <locale.h> |
4 | #include <stdarg.h> | 4 | #include <stdarg.h> |
5 | #include <stdlib.h> | ||
6 | #include <stdio.h> | 5 | #include <stdio.h> |
6 | #include <stdlib.h> | ||
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <strings.h> | ||
8 | #include <unistd.h> | 9 | #include <unistd.h> |
10 | #include <X11/keysym.h> | ||
9 | #include <X11/Xlib.h> | 11 | #include <X11/Xlib.h> |
10 | #include <X11/Xutil.h> | 12 | #include <X11/Xutil.h> |
11 | #include <X11/keysym.h> | ||
12 | #ifdef XINERAMA | 13 | #ifdef XINERAMA |
13 | #include <X11/extensions/Xinerama.h> | 14 | #include <X11/extensions/Xinerama.h> |
14 | #endif | 15 | #endif |
@@ -45,55 +46,54 @@ struct Item { | |||
45 | }; | 46 | }; |
46 | 47 | ||
47 | /* forward declarations */ | 48 | /* forward declarations */ |
48 | void appenditem(Item *i, Item **list, Item **last); | 49 | static void appenditem(Item *i, Item **list, Item **last); |
49 | void calcoffsets(void); | 50 | static void calcoffsets(void); |
50 | char *cistrstr(const char *s, const char *sub); | 51 | static char *cistrstr(const char *s, const char *sub); |
51 | void cleanup(void); | 52 | static void cleanup(void); |
52 | void drawmenu(void); | 53 | static void drawmenu(void); |
53 | void drawtext(const char *text, ulong col[ColLast]); | 54 | static void drawtext(const char *text, ulong col[ColLast]); |
54 | void *emalloc(uint size); | 55 | static void *emalloc(uint size); |
55 | void eprint(const char *errstr, ...); | 56 | static void eprint(const char *errstr, ...); |
56 | char *estrdup(const char *str); | 57 | static ulong getcolor(const char *colstr); |
57 | ulong getcolor(const char *colstr); | 58 | static Bool grabkeyboard(void); |
58 | Bool grabkeyboard(void); | 59 | static void initfont(const char *fontstr); |
59 | void initfont(const char *fontstr); | 60 | static void kpress(XKeyEvent * e); |
60 | void kpress(XKeyEvent * e); | 61 | static void match(char *pattern); |
61 | void match(char *pattern); | 62 | static void readstdin(void); |
62 | void readstdin(void); | 63 | static void run(void); |
63 | void run(void); | 64 | static void setup(Bool topbar); |
64 | void setup(Bool topbar); | 65 | static int textnw(const char *text, uint len); |
65 | uint textnw(const char *text, uint len); | 66 | static int textw(const char *text); |
66 | uint textw(const char *text); | ||
67 | 67 | ||
68 | #include "config.h" | 68 | #include "config.h" |
69 | 69 | ||
70 | /* variables */ | 70 | /* variables */ |
71 | char *font = FONT; | 71 | static char *font = FONT; |
72 | char *maxname = NULL; | 72 | static char *maxname = NULL; |
73 | char *normbg = NORMBGCOLOR; | 73 | static char *normbg = NORMBGCOLOR; |
74 | char *normfg = NORMFGCOLOR; | 74 | static char *normfg = NORMFGCOLOR; |
75 | char *prompt = NULL; | 75 | static char *prompt = NULL; |
76 | char *selbg = SELBGCOLOR; | 76 | static char *selbg = SELBGCOLOR; |
77 | char *selfg = SELFGCOLOR; | 77 | static char *selfg = SELFGCOLOR; |
78 | char text[4096]; | 78 | static char text[4096]; |
79 | int screen; | 79 | static int cmdw = 0; |
80 | int ret = 0; | 80 | static int promptw = 0; |
81 | uint cmdw = 0; | 81 | static int ret = 0; |
82 | uint mw, mh; | 82 | static int screen; |
83 | uint promptw = 0; | 83 | static uint mw, mh; |
84 | uint numlockmask = 0; | 84 | static uint numlockmask = 0; |
85 | Bool running = True; | 85 | static Bool running = True; |
86 | Display *dpy; | 86 | static Display *dpy; |
87 | DC dc = {0}; | 87 | static DC dc = {0}; |
88 | Item *allitems = NULL; /* first of all items */ | 88 | static Item *allitems = NULL; /* first of all items */ |
89 | Item *item = NULL; /* first of pattern matching items */ | 89 | static Item *item = NULL; /* first of pattern matching items */ |
90 | Item *sel = NULL; | 90 | static Item *sel = NULL; |
91 | Item *next = NULL; | 91 | static Item *next = NULL; |
92 | Item *prev = NULL; | 92 | static Item *prev = NULL; |
93 | Item *curr = NULL; | 93 | static Item *curr = NULL; |
94 | Window root, win; | 94 | static Window root, win; |
95 | int (*fstrncmp)(const char *, const char *, size_t n) = strncmp; | 95 | static int (*fstrncmp)(const char *, const char *, size_t n) = strncmp; |
96 | char *(*fstrstr)(const char *, const char *) = strstr; | 96 | static char *(*fstrstr)(const char *, const char *) = strstr; |
97 | 97 | ||
98 | void | 98 | void |
99 | appenditem(Item *i, Item **list, Item **last) { | 99 | appenditem(Item *i, Item **list, Item **last) { |
@@ -108,11 +108,12 @@ appenditem(Item *i, Item **list, Item **last) { | |||
108 | 108 | ||
109 | void | 109 | void |
110 | calcoffsets(void) { | 110 | calcoffsets(void) { |
111 | uint tw, w; | 111 | int tw; |
112 | uint w; | ||
112 | 113 | ||
113 | if(!curr) | 114 | if(!curr) |
114 | return; | 115 | return; |
115 | w = promptw + cmdw + 2 * SPACE; | 116 | w = promptw + cmdw + 2 * spaceitem; |
116 | for(next = curr; next; next=next->right) { | 117 | for(next = curr; next; next=next->right) { |
117 | tw = textw(next->text); | 118 | tw = textw(next->text); |
118 | if(tw > mw / 3) | 119 | if(tw > mw / 3) |
@@ -121,7 +122,7 @@ calcoffsets(void) { | |||
121 | if(w > mw) | 122 | if(w > mw) |
122 | break; | 123 | break; |
123 | } | 124 | } |
124 | w = promptw + cmdw + 2 * SPACE; | 125 | w = promptw + cmdw + 2 * spaceitem; |
125 | for(prev = curr; prev && prev->left; prev=prev->left) { | 126 | for(prev = curr; prev && prev->left; prev=prev->left) { |
126 | tw = textw(prev->left->text); | 127 | tw = textw(prev->left->text); |
127 | if(tw > mw / 3) | 128 | if(tw > mw / 3) |
@@ -197,7 +198,7 @@ drawmenu(void) { | |||
197 | drawtext(text[0] ? text : NULL, dc.norm); | 198 | drawtext(text[0] ? text : NULL, dc.norm); |
198 | dc.x += cmdw; | 199 | dc.x += cmdw; |
199 | if(curr) { | 200 | if(curr) { |
200 | dc.w = SPACE; | 201 | dc.w = spaceitem; |
201 | drawtext((curr && curr->left) ? "<" : NULL, dc.norm); | 202 | drawtext((curr && curr->left) ? "<" : NULL, dc.norm); |
202 | dc.x += dc.w; | 203 | dc.x += dc.w; |
203 | /* determine maximum items */ | 204 | /* determine maximum items */ |
@@ -208,8 +209,8 @@ drawmenu(void) { | |||
208 | drawtext(i->text, (sel == i) ? dc.sel : dc.norm); | 209 | drawtext(i->text, (sel == i) ? dc.sel : dc.norm); |
209 | dc.x += dc.w; | 210 | dc.x += dc.w; |
210 | } | 211 | } |
211 | dc.x = mw - SPACE; | 212 | dc.x = mw - spaceitem; |
212 | dc.w = SPACE; | 213 | dc.w = spaceitem; |
213 | drawtext(next ? ">" : NULL, dc.norm); | 214 | drawtext(next ? ">" : NULL, dc.norm); |
214 | } | 215 | } |
215 | XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0); | 216 | XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0); |
@@ -275,15 +276,6 @@ eprint(const char *errstr, ...) { | |||
275 | exit(EXIT_FAILURE); | 276 | exit(EXIT_FAILURE); |
276 | } | 277 | } |
277 | 278 | ||
278 | char * | ||
279 | estrdup(const char *str) { | ||
280 | void *res = strdup(str); | ||
281 | |||
282 | if(!res) | ||
283 | eprint("fatal: could not malloc() %u bytes\n", strlen(str)); | ||
284 | return res; | ||
285 | } | ||
286 | |||
287 | ulong | 279 | ulong |
288 | getcolor(const char *colstr) { | 280 | getcolor(const char *colstr) { |
289 | Colormap cmap = DefaultColormap(dpy, screen); | 281 | Colormap cmap = DefaultColormap(dpy, screen); |
@@ -358,14 +350,15 @@ kpress(XKeyEvent * e) { | |||
358 | len = strlen(text); | 350 | len = strlen(text); |
359 | buf[0] = 0; | 351 | buf[0] = 0; |
360 | num = XLookupString(e, buf, sizeof buf, &ksym, 0); | 352 | num = XLookupString(e, buf, sizeof buf, &ksym, 0); |
361 | if(IsKeypadKey(ksym)) | 353 | if(IsKeypadKey(ksym)) { |
362 | if(ksym == XK_KP_Enter) | 354 | if(ksym == XK_KP_Enter) |
363 | ksym = XK_Return; | 355 | ksym = XK_Return; |
364 | else if(ksym >= XK_KP_0 && ksym <= XK_KP_9) | 356 | else if(ksym >= XK_KP_0 && ksym <= XK_KP_9) |
365 | ksym = (ksym - XK_KP_0) + XK_0; | 357 | ksym = (ksym - XK_KP_0) + XK_0; |
358 | } | ||
366 | if(IsFunctionKey(ksym) || IsKeypadKey(ksym) | 359 | if(IsFunctionKey(ksym) || IsKeypadKey(ksym) |
367 | || IsMiscFunctionKey(ksym) || IsPFKey(ksym) | 360 | || IsMiscFunctionKey(ksym) || IsPFKey(ksym) |
368 | || IsPrivateKeypadKey(ksym)) | 361 | || IsPrivateKeypadKey(ksym)) |
369 | return; | 362 | return; |
370 | /* first check if a control mask is omitted */ | 363 | /* first check if a control mask is omitted */ |
371 | if(e->state & ControlMask) { | 364 | if(e->state & ControlMask) { |
@@ -569,7 +562,8 @@ readstdin(void) { | |||
569 | len = strlen(buf); | 562 | len = strlen(buf); |
570 | if (buf[len - 1] == '\n') | 563 | if (buf[len - 1] == '\n') |
571 | buf[len - 1] = 0; | 564 | buf[len - 1] = 0; |
572 | p = estrdup(buf); | 565 | if(!(p = strdup(buf))) |
566 | eprint("fatal: could not strdup() %u bytes\n", strlen(buf)); | ||
573 | if(max < len) { | 567 | if(max < len) { |
574 | maxname = p; | 568 | maxname = p; |
575 | max = len; | 569 | max = len; |
@@ -677,7 +671,7 @@ setup(Bool topbar) { | |||
677 | XMapRaised(dpy, win); | 671 | XMapRaised(dpy, win); |
678 | } | 672 | } |
679 | 673 | ||
680 | uint | 674 | int |
681 | textnw(const char *text, uint len) { | 675 | textnw(const char *text, uint len) { |
682 | XRectangle r; | 676 | XRectangle r; |
683 | 677 | ||
@@ -688,7 +682,7 @@ textnw(const char *text, uint len) { | |||
688 | return XTextWidth(dc.font.xfont, text, len); | 682 | return XTextWidth(dc.font.xfont, text, len); |
689 | } | 683 | } |
690 | 684 | ||
691 | uint | 685 | int |
692 | textw(const char *text) { | 686 | textw(const char *text) { |
693 | return textnw(text, strlen(text)) + dc.font.height; | 687 | return textnw(text, strlen(text)) + dc.font.height; |
694 | } | 688 | } |