diff options
| author | Connor Lane Smith <cls@lubutu.com> | 2010-07-02 06:49:05 +0100 |
|---|---|---|
| committer | Connor Lane Smith <cls@lubutu.com> | 2010-07-02 06:49:05 +0100 |
| commit | 855a56631916bdff1438e11c232b88450f973648 (patch) | |
| tree | c7ed1e1ae2aac45b3e3980cfa36bc45b9580e39e | |
| parent | 29e8faed6cf4b296382439651cf04596d276f080 (diff) | |
added dmenu.h, common.c
| -rw-r--r-- | Makefile | 10 | ||||
| -rw-r--r-- | common.c | 129 | ||||
| -rw-r--r-- | config.def.h | 11 | ||||
| -rw-r--r-- | dinput.c | 150 | ||||
| -rw-r--r-- | dmenu.c | 188 | ||||
| -rw-r--r-- | dmenu.h | 30 |
6 files changed, 204 insertions, 314 deletions
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | include config.mk | 4 | include config.mk |
| 5 | 5 | ||
| 6 | SRC = dinput.c dmenu.c | 6 | SRC = dinput.c dmenu.c common.c |
| 7 | OBJ = ${SRC:.c=.o} | 7 | OBJ = ${SRC:.c=.o} |
| 8 | 8 | ||
| 9 | all: options dinput dmenu | 9 | all: 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: | 27 | dinput: dinput.o common.o |
| 28 | @echo CC -o $@ | 28 | @echo CC -o $@ |
| 29 | @${CC} -o $@ $< ${LDFLAGS} | 29 | @${CC} -o $@ $+ ${LDFLAGS} |
| 30 | |||
| 31 | dmenu: dmenu.o common.o | ||
| 32 | @echo CC -o $@ | ||
| 33 | @${CC} -o $@ $+ ${LDFLAGS} | ||
| 30 | 34 | ||
| 31 | clean: | 35 | clean: |
| 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 */ | ||
| 12 | char *prompt = NULL; | ||
| 13 | char text[4096] = ""; | ||
| 14 | int promptw = 0; | ||
| 15 | int screen; | ||
| 16 | unsigned int numlockmask = 0; | ||
| 17 | unsigned int mw, mh; | ||
| 18 | unsigned long normcol[ColLast]; | ||
| 19 | unsigned long selcol[ColLast]; | ||
| 20 | Bool topbar = True; | ||
| 21 | DC dc; | ||
| 22 | Display *dpy; | ||
| 23 | Window win, root; | ||
| 24 | |||
| 25 | void | ||
| 26 | grabkeyboard(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 | |||
| 38 | void | ||
| 39 | run(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 | |||
| 61 | void | ||
| 62 | setup(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 */ |
| 4 | const char *font = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*"; | 4 | static const char *font = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*"; |
| 5 | const char *normbgcolor = "#cccccc"; | 5 | static const char *normbgcolor = "#cccccc"; |
| 6 | const char *normfgcolor = "#000000"; | 6 | static const char *normfgcolor = "#000000"; |
| 7 | const char *selbgcolor = "#0066ff"; | 7 | static const char *selbgcolor = "#0066ff"; |
| 8 | const char *selfgcolor = "#ffffff"; | 8 | static const char *selfgcolor = "#ffffff"; |
| 9 | unsigned int spaceitem = 30; /* px between menu items */ | ||
| @@ -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 */ |
| 23 | static void cleanup(void); | 13 | static void cleanup(void); |
| 24 | static void drawinput(void); | ||
| 25 | static void grabkeyboard(void); | ||
| 26 | static void kpress(XKeyEvent *e); | ||
| 27 | static void run(void); | ||
| 28 | static void setup(void); | ||
| 29 | |||
| 30 | #include "config.h" | ||
| 31 | 14 | ||
| 32 | /* variables */ | 15 | /* variables */ |
| 33 | static char *prompt = NULL; | ||
| 34 | static char text[4096]; | ||
| 35 | static int promptw = 0; | ||
| 36 | static int screen; | ||
| 37 | static size_t cursor = 0; | 16 | static size_t cursor = 0; |
| 38 | static unsigned int numlockmask = 0; | ||
| 39 | static unsigned int mw, mh; | ||
| 40 | static unsigned long normcol[ColLast]; | ||
| 41 | static unsigned long selcol[ColLast]; | ||
| 42 | static Bool topbar = True; | ||
| 43 | static DC dc; | ||
| 44 | static Display *dpy; | ||
| 45 | static Window win, root; | ||
| 46 | 17 | ||
| 47 | void | 18 | void |
| 48 | cleanup(void) { | 19 | cleanup(void) { |
| @@ -53,7 +24,7 @@ cleanup(void) { | |||
| 53 | } | 24 | } |
| 54 | 25 | ||
| 55 | void | 26 | void |
| 56 | drawinput(void) | 27 | drawbar(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 | ||
| 75 | void | 46 | void |
| 76 | grabkeyboard(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 | |||
| 88 | void | ||
| 89 | kpress(XKeyEvent *e) { | 47 | kpress(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 | |||
| 213 | void | ||
| 214 | run(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 | |||
| 236 | void | ||
| 237 | setup(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 | ||
| 307 | int | 171 | int |
| @@ -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 | } |
| @@ -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 | ||
| 22 | typedef struct Item Item; | 13 | typedef struct Item Item; |
| 23 | struct Item { | 14 | struct Item { |
| @@ -33,41 +24,22 @@ static void calcoffsetsv(void); | |||
| 33 | static char *cistrstr(const char *s, const char *sub); | 24 | static char *cistrstr(const char *s, const char *sub); |
| 34 | static void cleanup(void); | 25 | static void cleanup(void); |
| 35 | static void dinput(void); | 26 | static void dinput(void); |
| 36 | static void drawmenu(void); | ||
| 37 | static void drawmenuh(void); | 27 | static void drawmenuh(void); |
| 38 | static void drawmenuv(void); | 28 | static void drawmenuv(void); |
| 39 | static void grabkeyboard(void); | 29 | static void match(void); |
| 40 | static void kpress(XKeyEvent *e); | ||
| 41 | static void match(char *pattern); | ||
| 42 | static void readstdin(void); | 30 | static void readstdin(void); |
| 43 | static void run(void); | ||
| 44 | static void setup(void); | ||
| 45 | |||
| 46 | #include "config.h" | ||
| 47 | 31 | ||
| 48 | /* variables */ | 32 | /* variables */ |
| 49 | static char **argp = NULL; | 33 | static char **argp = NULL; |
| 50 | static char *maxname = NULL; | 34 | static char *maxname = NULL; |
| 51 | static char *prompt = NULL; | 35 | static unsigned int cmdw = 0; |
| 52 | static char text[4096]; | ||
| 53 | static int cmdw = 0; | ||
| 54 | static int promptw = 0; | ||
| 55 | static int screen; | ||
| 56 | static unsigned int lines = 0; | 36 | static unsigned int lines = 0; |
| 57 | static unsigned int numlockmask = 0; | ||
| 58 | static unsigned int mw, mh; | ||
| 59 | static unsigned long normcol[ColLast]; | ||
| 60 | static unsigned long selcol[ColLast]; | ||
| 61 | static Bool topbar = True; | ||
| 62 | static DC dc; | ||
| 63 | static Display *dpy; | ||
| 64 | static Item *allitems = NULL; /* first of all items */ | 37 | static Item *allitems = NULL; /* first of all items */ |
| 65 | static Item *item = NULL; /* first of pattern matching items */ | 38 | static Item *item = NULL; /* first of pattern matching items */ |
| 66 | static Item *sel = NULL; | 39 | static Item *sel = NULL; |
| 67 | static Item *next = NULL; | 40 | static Item *next = NULL; |
| 68 | static Item *prev = NULL; | 41 | static Item *prev = NULL; |
| 69 | static Item *curr = NULL; | 42 | static Item *curr = NULL; |
| 70 | static Window win, root; | ||
| 71 | static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; | 43 | static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; |
| 72 | static char *(*fstrstr)(const char *, const char *) = strstr; | 44 | static char *(*fstrstr)(const char *, const char *) = strstr; |
| 73 | static void (*calcoffsets)(void) = calcoffsetsh; | 45 | static void (*calcoffsets)(void) = calcoffsetsh; |
| @@ -85,14 +57,13 @@ appenditem(Item *i, Item **list, Item **last) { | |||
| 85 | 57 | ||
| 86 | void | 58 | void |
| 87 | calcoffsetsh(void) { | 59 | calcoffsetsh(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 | ||
| 159 | void | 130 | void |
| 160 | drawmenu(void) { | 131 | drawbar(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 | ||
| 220 | void | 191 | void |
| 221 | grabkeyboard(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 | |||
| 233 | void | ||
| 234 | kpress(XKeyEvent *e) { | 192 | kpress(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 | ||
| 379 | void | 337 | void |
| 380 | match(char *pattern) { | 338 | match(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 | ||
| 447 | void | ||
| 448 | run(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 | |||
| 470 | void | ||
| 471 | setup(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 | |||
| 544 | int | 403 | int |
| 545 | main(int argc, char *argv[]) { | 404 | main(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 | } |
| @@ -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 */ | ||
| 12 | void drawbar(void); | ||
| 13 | void grabkeyboard(void); | ||
| 14 | void kpress(XKeyEvent *e); | ||
| 15 | void run(void); | ||
| 16 | void setup(unsigned int lines); | ||
| 17 | |||
| 18 | /* variables */ | ||
| 19 | extern char *prompt; | ||
| 20 | extern char text[4096]; | ||
| 21 | extern int promptw; | ||
| 22 | extern int screen; | ||
| 23 | extern unsigned int numlockmask; | ||
| 24 | extern unsigned int mw, mh; | ||
| 25 | extern unsigned long normcol[ColLast]; | ||
| 26 | extern unsigned long selcol[ColLast]; | ||
| 27 | extern Bool topbar; | ||
| 28 | extern DC dc; | ||
| 29 | extern Display *dpy; | ||
| 30 | extern Window win, root; | ||
