Hey, On 29 November 2010 00:17, Christophe-Marie Duquesne <chm.duque...@gmail.com> wrote: > I rewrote my proposal with select(). Now readstdin() will return if it > cannot read data from stdin during more than 1 u_sec. It will set the > static flag 'eof' to 1 if it has read the end of file character. This > way while eof is 0, you know you should call readstdin() again.
Great, it's a lot cleaner this way. One problem with this approach, though, is that if data is written to stdin it isn't displayed until the next X event. This is likely fine for your use case, and dmenu_run, but perhaps not for other cases. To fix that we'd have to select between stdin and XConnectionNumber(dc->dpy). I've also attached a slightly neater version of your patch, plus a bugfix. Thanks, cls
diff -r a79e4a9cb167 dmenu.c --- a/dmenu.c Sat Nov 20 09:25:08 2010 +0000 +++ b/dmenu.c Mon Nov 29 01:40:44 2010 +0000 @@ -4,6 +4,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <sys/select.h> #include <X11/Xlib.h> #include <X11/Xatom.h> #include <X11/Xutil.h> @@ -54,11 +55,13 @@ static unsigned long normcol[ColLast]; static unsigned long selcol[ColLast]; static Atom utf8; +static Bool eof = False; static Bool topbar = True; static DC *dc; static Item *items = NULL; static Item *matches, *sel; static Item *prev, *curr, *next; +static Item **end = &items; static Window root, win; static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; @@ -102,7 +105,6 @@ dc = initdc(); initfont(dc, font); - readstdin(); setup(); run(); @@ -433,9 +435,20 @@ void readstdin(void) { char buf[sizeof text], *p; - Item *item, **end; + fd_set fds; + int n; + struct timeval tv; + Item *item; - for(end = &items; fgets(buf, sizeof buf, stdin); *end = item, end = &item->next) { + while(!eof) { + tv.tv_sec = 0; + tv.tv_usec = 1; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + if((n = select(1, &fds, NULL, NULL, &tv)) < 0) + eprintf("cannot select stdin\n"); + if(n == 0 || (eof = !fgets(buf, sizeof buf, stdin))) + break; if((p = strchr(buf, '\n'))) *p = '\0'; if(!(item = malloc(sizeof *item))) @@ -444,6 +457,9 @@ eprintf("cannot strdup %u bytes\n", strlen(buf)+1); item->next = item->left = item->right = NULL; inputw = MAX(inputw, textw(dc, item->text)); + *end = item; + end = &item->next; + match(); } } @@ -451,7 +467,7 @@ run(void) { XEvent ev; - while(!XNextEvent(dc->dpy, &ev)) + while(!XNextEvent(dc->dpy, &ev)) { switch(ev.type) { case Expose: if(ev.xexpose.count == 0) @@ -469,6 +485,8 @@ XRaiseWindow(dc->dpy, win); break; } + readstdin(); + } } void @@ -531,7 +549,7 @@ promptw = prompt ? textw(dc, prompt) : 0; XMapRaised(dc->dpy, win); text[0] = '\0'; - match(); + drawmenu(); } void