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 | } |
