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

Reply via email to