nonblockingstdin-nodoc.patch (5299B)
1 diff --git a/dmenu.c b/dmenu.c 2 index 6b8f51b..479a4c8 100644 3 --- a/dmenu.c 4 +++ b/dmenu.c 5 @@ -1,5 +1,6 @@ 6 /* See LICENSE file for copyright and license details. */ 7 #include <ctype.h> 8 +#include <fcntl.h> 9 #include <locale.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 @@ -8,6 +9,7 @@ 13 #include <time.h> 14 #include <unistd.h> 15 16 +#include <sys/select.h> 17 #include <X11/Xlib.h> 18 #include <X11/Xatom.h> 19 #include <X11/Xutil.h> 20 @@ -31,6 +33,7 @@ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ 21 struct item { 22 char *text; 23 struct item *left, *right; 24 + struct item *next; 25 int out; 26 }; 27 28 @@ -173,6 +176,7 @@ drawmenu(void) 29 } 30 } 31 drw_map(drw, win, 0, 0, mw, mh); 32 + XFlush(dpy); 33 } 34 35 static void 36 @@ -220,6 +224,7 @@ match(void) 37 int i, tokc = 0; 38 size_t len, textsize; 39 struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; 40 + int preserve = 0; 41 42 strcpy(buf, text); 43 /* separate input text into tokens to be matched individually */ 44 @@ -230,19 +235,23 @@ match(void) 45 46 matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; 47 textsize = strlen(text) + 1; 48 - for (item = items; item && item->text; item++) { 49 + for (item = items; item; item = item->next) { 50 for (i = 0; i < tokc; i++) 51 if (!fstrstr(item->text, tokv[i])) 52 break; 53 if (i != tokc) /* not all tokens match */ 54 continue; 55 /* exact matches go first, then prefixes, then substrings */ 56 - if (!tokc || !fstrncmp(text, item->text, textsize)) 57 + if (!tokc || !fstrncmp(text, item->text, textsize)) { 58 appenditem(item, &matches, &matchend); 59 - else if (!fstrncmp(tokv[0], item->text, len)) 60 + if (sel == item) preserve = 1; 61 + } else if (!fstrncmp(tokv[0], item->text, len)) { 62 appenditem(item, &lprefix, &prefixend); 63 - else 64 + if (sel == item) preserve = 1; 65 + } else { 66 appenditem(item, &lsubstr, &substrend); 67 + if (sel == item) preserve = 1; 68 + } 69 } 70 if (lprefix) { 71 if (matches) { 72 @@ -260,7 +269,9 @@ match(void) 73 matches = lsubstr; 74 matchend = substrend; 75 } 76 - curr = sel = matches; 77 + if (!preserve) 78 + curr = sel = matches; 79 + 80 calcoffsets(); 81 } 82 83 @@ -519,40 +530,11 @@ paste(void) 84 } 85 86 static void 87 -readstdin(void) 88 -{ 89 - char buf[sizeof text], *p; 90 - size_t i, imax = 0, size = 0; 91 - unsigned int tmpmax = 0; 92 - 93 - /* read each line from stdin and add it to the item list */ 94 - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { 95 - if (i + 1 >= size / sizeof *items) 96 - if (!(items = realloc(items, (size += BUFSIZ)))) 97 - die("cannot realloc %u bytes:", size); 98 - if ((p = strchr(buf, '\n'))) 99 - *p = '\0'; 100 - if (!(items[i].text = strdup(buf))) 101 - die("cannot strdup %u bytes:", strlen(buf) + 1); 102 - items[i].out = 0; 103 - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); 104 - if (tmpmax > inputw) { 105 - inputw = tmpmax; 106 - imax = i; 107 - } 108 - } 109 - if (items) 110 - items[i].text = NULL; 111 - inputw = items ? TEXTW(items[imax].text) : 0; 112 - lines = MIN(lines, i); 113 -} 114 - 115 -static void 116 -run(void) 117 +readevent(void) 118 { 119 XEvent ev; 120 121 - while (!XNextEvent(dpy, &ev)) { 122 + while (XPending(dpy) && !XNextEvent(dpy, &ev)) { 123 if (XFilterEvent(&ev, win)) 124 continue; 125 switch(ev.type) { 126 @@ -580,6 +562,60 @@ run(void) 127 } 128 } 129 130 +static void 131 +readstdin(void) 132 +{ 133 + static size_t max = 0; 134 + static struct item **end = &items; 135 + 136 + char buf[sizeof text], *p, *maxstr; 137 + struct item *item; 138 + 139 + /* read each line from stdin and add it to the item list */ 140 + while (fgets(buf, sizeof buf, stdin)) { 141 + if (!(item = malloc(sizeof *item))) 142 + die("cannot malloc %u bytes:", sizeof *item); 143 + if ((p = strchr(buf, '\n'))) 144 + *p = '\0'; 145 + if (!(item->text = strdup(buf))) 146 + die("cannot strdup %u bytes:", strlen(buf)+1); 147 + if (strlen(item->text) > max) { 148 + max = strlen(maxstr = item->text); 149 + inputw = maxstr ? TEXTW(maxstr) : 0; 150 + } 151 + *end = item; 152 + end = &item->next; 153 + item->next = NULL; 154 + item->out = 0; 155 + } 156 + match(); 157 + drawmenu(); 158 +} 159 + 160 +static void 161 +run(void) 162 +{ 163 + fd_set fds; 164 + int flags, xfd = XConnectionNumber(dpy); 165 + 166 + if ((flags = fcntl(0, F_GETFL)) == -1) 167 + die("cannot get stdin control flags:"); 168 + if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1) 169 + die("cannot set stdin control flags:"); 170 + for (;;) { 171 + FD_ZERO(&fds); 172 + FD_SET(xfd, &fds); 173 + if (!feof(stdin)) 174 + FD_SET(0, &fds); 175 + if (select(xfd + 1, &fds, NULL, NULL, NULL) == -1) 176 + die("cannot multiplex input:"); 177 + if (FD_ISSET(xfd, &fds)) 178 + readevent(); 179 + if (FD_ISSET(0, &fds)) 180 + readstdin(); 181 + } 182 +} 183 + 184 static void 185 setup(void) 186 { 187 @@ -691,7 +727,7 @@ int 188 main(int argc, char *argv[]) 189 { 190 XWindowAttributes wa; 191 - int i, fast = 0; 192 + int i; 193 194 for (i = 1; i < argc; i++) 195 /* these options take no arguments */ 196 @@ -700,8 +736,6 @@ main(int argc, char *argv[]) 197 exit(0); 198 } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ 199 topbar = 0; 200 - else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ 201 - fast = 1; 202 else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ 203 fstrncmp = strncasecmp; 204 fstrstr = cistrstr; 205 @@ -752,13 +786,7 @@ main(int argc, char *argv[]) 206 die("no fonts could be loaded."); 207 lrpad = drw->fonts->h; 208 209 - if (fast) { 210 - grabkeyboard(); 211 - readstdin(); 212 - } else { 213 - readstdin(); 214 - grabkeyboard(); 215 - } 216 + grabkeyboard(); 217 setup(); 218 run(); 219 220 -- 221 2.19.2 222