Hey,
On 29 November 2010 00:17, Christophe-Marie Duquesne
<[email protected]> 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