diff -r 56ee9af6dcea dmenu.c --- a/dmenu.c Sat Nov 19 21:31:18 2011 +0100 +++ b/dmenu.c Mon Nov 21 21:09:58 2011 +0100 @@ -1,10 +1,12 @@ /* See LICENSE file for copyright and license details. */ #include +#include #include #include #include #include #include +#include #include #include #include @@ -21,6 +23,7 @@ typedef struct Item Item; struct Item { char *text; + Item *next; Item *left, *right; }; @@ -34,6 +37,7 @@ static void match(void); static size_t nextrune(int inc); static void paste(void); +static void readevent(void); static void readstdin(void); static void run(void); static void setup(void); @@ -43,6 +47,7 @@ static int bh, mw, mh; static int inputw, promptw; static size_t cursor = 0; +static const char *maxstr; static const char *font = NULL; static const char *prompt = NULL; static const char *normbgcolor = "#222222"; @@ -66,7 +71,6 @@ int main(int argc, char *argv[]) { - Bool fast = False; int i; for(i = 1; i < argc; i++) @@ -77,8 +81,6 @@ } else if(!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ topbar = False; - else if(!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ - fast = True; else if(!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ fstrncmp = strncasecmp; fstrstr = cistrstr; @@ -105,15 +107,7 @@ dc = initdc(); initfont(dc, font); - - if(fast) { - grabkeyboard(); - readstdin(); - } - else { - readstdin(); - grabkeyboard(); - } + grabkeyboard(); setup(); run(); @@ -205,6 +199,7 @@ drawtext(dc, ">", normcol); } mapdc(dc, win, mw, mh); + XFlush(dc->dpy); } void @@ -396,7 +391,7 @@ len = tokc ? strlen(tokv[0]) : 0; matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; - for(item = items; item && item->text; item++) { + for(item = items; item; item = item->next) { for(i = 0; i < tokc; i++) if(!fstrstr(item->text, tokv[i])) break; @@ -457,33 +452,10 @@ } void -readstdin(void) { - char buf[sizeof text], *p, *maxstr = NULL; - size_t i, max = 0, size = 0; - - /* read each line from stdin and add it to the item list */ - for(i = 0; fgets(buf, sizeof buf, stdin); i++) { - if(i+1 >= size / sizeof *items) - if(!(items = realloc(items, (size += BUFSIZ)))) - eprintf("cannot realloc %u bytes:", size); - if((p = strchr(buf, '\n'))) - *p = '\0'; - if(!(items[i].text = strdup(buf))) - eprintf("cannot strdup %u bytes:", strlen(buf)+1); - if(strlen(items[i].text) > max) - max = strlen(maxstr = items[i].text); - } - if(items) - items[i].text = NULL; - inputw = maxstr ? textw(dc, maxstr) : 0; - lines = MIN(lines, i); -} - -void -run(void) { +readevent(void) { XEvent ev; - while(!XNextEvent(dc->dpy, &ev)) { + while(XPending(dc->dpy) && !XNextEvent(dc->dpy, &ev)) { if(XFilterEvent(&ev, win)) continue; switch(ev.type) { @@ -507,6 +479,57 @@ } void +readstdin(void) { + static size_t max = 0; + static Item **end = &items; + + char buf[sizeof text], *p; + Item *item; + + /* read each line from stdin and add it to the item list */ + while(fgets(buf, sizeof buf, stdin)) { + if(!(item = malloc(sizeof *item))) + eprintf("cannot malloc %u bytes:", sizeof *item); + if((p = strchr(buf, '\n'))) + *p = '\0'; + if(!(item->text = strdup(buf))) + eprintf("cannot strdup %u bytes:", strlen(buf)+1); + if(strlen(item->text) > max) { + max = strlen(maxstr = item->text); + inputw = textw(dc, maxstr); + } + *end = item; + end = &item->next; + item->next = NULL; + } + match(); + drawmenu(); +} + +void +run(void) { + fd_set fds; + int flags, xfd = XConnectionNumber(dc->dpy); + + if((flags = fcntl(STDIN_FILENO, F_GETFL)) == -1) + eprintf("cannot get stdin control flags:"); + if(fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK) == -1) + eprintf("cannot set stdin control flags:"); + for(;;) { + FD_ZERO(&fds); + FD_SET(xfd, &fds); + if(!feof(stdin)) + FD_SET(STDIN_FILENO, &fds); + if(select(MAX(STDIN_FILENO, xfd) + 1, &fds, NULL, NULL, NULL) == -1) + eprintf("cannot multiplex input:"); + if(FD_ISSET(xfd, &fds)) + readevent(); + if(FD_ISSET(STDIN_FILENO, &fds)) + readstdin(); + } +} + +void setup(void) { int x, y, screen = DefaultScreen(dc->dpy); Window root = RootWindow(dc->dpy, screen);