dmenu-nonblockingstdin-20160702-3c91eed.diff - sites - public wiki contents of … | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dmenu-nonblockingstdin-20160702-3c91eed.diff (6044B) | |
--- | |
1 diff --git a/dmenu.1 b/dmenu.1 | |
2 index d3ab805..00958cf 100644 | |
3 --- a/dmenu.1 | |
4 +++ b/dmenu.1 | |
5 @@ -4,7 +4,6 @@ dmenu \- dynamic menu | |
6 .SH SYNOPSIS | |
7 .B dmenu | |
8 .RB [ \-b ] | |
9 -.RB [ \-f ] | |
10 .RB [ \-i ] | |
11 .RB [ \-l | |
12 .RB [ \-m | |
13 @@ -41,10 +40,6 @@ which lists programs in the user's $PATH and runs the… | |
14 .B \-b | |
15 dmenu appears at the bottom of the screen. | |
16 .TP | |
17 -.B \-f | |
18 -dmenu grabs the keyboard before reading stdin. This is faster, but wil… | |
19 -X until stdin reaches end\-of\-file. | |
20 -.TP | |
21 .B \-i | |
22 dmenu matches menu items case insensitively. | |
23 .TP | |
24 diff --git a/dmenu.c b/dmenu.c | |
25 index e926eca..dc81ef2 100644 | |
26 --- a/dmenu.c | |
27 +++ b/dmenu.c | |
28 @@ -1,12 +1,15 @@ | |
29 /* See LICENSE file for copyright and license details. */ | |
30 #include <ctype.h> | |
31 +#include <fcntl.h> | |
32 #include <locale.h> | |
33 #include <stdio.h> | |
34 #include <stdlib.h> | |
35 #include <string.h> | |
36 #include <strings.h> | |
37 #include <time.h> | |
38 +#include <unistd.h> | |
39 | |
40 +#include <sys/select.h> | |
41 #include <X11/Xlib.h> | |
42 #include <X11/Xatom.h> | |
43 #include <X11/Xutil.h> | |
44 @@ -30,6 +33,7 @@ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast };… | |
45 struct item { | |
46 char *text; | |
47 struct item *left, *right; | |
48 + struct item *next; | |
49 int out; | |
50 }; | |
51 | |
52 @@ -172,6 +176,7 @@ drawmenu(void) | |
53 } | |
54 } | |
55 drw_map(drw, win, 0, 0, mw, mh); | |
56 + XFlush(dpy); | |
57 } | |
58 | |
59 static void | |
60 @@ -200,6 +205,7 @@ match(void) | |
61 int i, tokc = 0; | |
62 size_t len, textsize; | |
63 struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; | |
64 + int preserve = 0; | |
65 | |
66 strcpy(buf, text); | |
67 /* separate input text into tokens to be matched individually */ | |
68 @@ -210,19 +216,24 @@ match(void) | |
69 | |
70 matches = lprefix = lsubstr = matchend = prefixend = substrend … | |
71 textsize = strlen(text); | |
72 - for (item = items; item && item->text; item++) { | |
73 + | |
74 + for (item = items; item; item = item->next) { | |
75 for (i = 0; i < tokc; i++) | |
76 if (!fstrstr(item->text, tokv[i])) | |
77 break; | |
78 if (i != tokc) /* not all tokens match */ | |
79 continue; | |
80 /* exact matches go first, then prefixes, then substrin… | |
81 - if (!tokc || !fstrncmp(text, item->text, textsize)) | |
82 + if (!tokc || !fstrncmp(text, item->text, textsize)) { | |
83 appenditem(item, &matches, &matchend); | |
84 - else if (!fstrncmp(tokv[0], item->text, len)) | |
85 + if (sel == item) preserve = 1; | |
86 + } else if (!fstrncmp(tokv[0], item->text, len)) { | |
87 appenditem(item, &lprefix, &prefixend); | |
88 - else | |
89 + if (sel == item) preserve = 1; | |
90 + } else { | |
91 appenditem(item, &lsubstr, &substrend); | |
92 + if (sel == item) preserve = 1; | |
93 + } | |
94 } | |
95 if (lprefix) { | |
96 if (matches) { | |
97 @@ -240,7 +251,9 @@ match(void) | |
98 matches = lsubstr; | |
99 matchend = substrend; | |
100 } | |
101 - curr = sel = matches; | |
102 + if (!preserve) | |
103 + curr = sel = matches; | |
104 + | |
105 calcoffsets(); | |
106 } | |
107 | |
108 @@ -456,36 +469,7 @@ paste(void) | |
109 } | |
110 | |
111 static void | |
112 -readstdin(void) | |
113 -{ | |
114 - char buf[sizeof text], *p; | |
115 - size_t i, imax = 0, size = 0; | |
116 - unsigned int tmpmax = 0; | |
117 - | |
118 - /* read each line from stdin and add it to the item list */ | |
119 - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { | |
120 - if (i + 1 >= size / sizeof *items) | |
121 - if (!(items = realloc(items, (size += BUFSIZ)))) | |
122 - die("cannot realloc %u bytes:", size); | |
123 - if ((p = strchr(buf, '\n'))) | |
124 - *p = '\0'; | |
125 - if (!(items[i].text = strdup(buf))) | |
126 - die("cannot strdup %u bytes:", strlen(buf) + 1); | |
127 - items[i].out = 0; | |
128 - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax,… | |
129 - if (tmpmax > inputw) { | |
130 - inputw = tmpmax; | |
131 - imax = i; | |
132 - } | |
133 - } | |
134 - if (items) | |
135 - items[i].text = NULL; | |
136 - inputw = items ? TEXTW(items[imax].text) : 0; | |
137 - lines = MIN(lines, i); | |
138 -} | |
139 - | |
140 -static void | |
141 -run(void) | |
142 +readevent(void) | |
143 { | |
144 XEvent ev; | |
145 | |
146 @@ -513,6 +497,60 @@ run(void) | |
147 } | |
148 | |
149 static void | |
150 +readstdin(void) | |
151 +{ | |
152 + static size_t max = 0; | |
153 + static struct item **end = &items; | |
154 + | |
155 + char buf[sizeof text], *p, *maxstr; | |
156 + struct item *item; | |
157 + | |
158 + /* read each line from stdin and add it to the item list */ | |
159 + while (fgets(buf, sizeof buf, stdin)) { | |
160 + if (!(item = malloc(sizeof *item))) | |
161 + die("cannot malloc %u bytes:", sizeof *item); | |
162 + if ((p = strchr(buf, '\n'))) | |
163 + *p = '\0'; | |
164 + if (!(item->text = strdup(buf))) | |
165 + die("cannot strdup %u bytes:", strlen(buf)+1); | |
166 + if (strlen(item->text) > max) { | |
167 + max = strlen(maxstr = item->text); | |
168 + inputw = maxstr ? TEXTW(maxstr) : 0; | |
169 + } | |
170 + *end = item; | |
171 + end = &item->next; | |
172 + item->next = NULL; | |
173 + item->out = 0; | |
174 + } | |
175 + match(); | |
176 + drawmenu(); | |
177 +} | |
178 + | |
179 +static void | |
180 +run(void) | |
181 +{ | |
182 + fd_set fds; | |
183 + int flags, xfd = XConnectionNumber(dpy); | |
184 + | |
185 + if ((flags = fcntl(0, F_GETFL)) == -1) | |
186 + die("cannot get stdin control flags:"); | |
187 + if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1) | |
188 + die("cannot set stdin control flags:"); | |
189 + for (;;) { | |
190 + FD_ZERO(&fds); | |
191 + FD_SET(xfd, &fds); | |
192 + if (!feof(stdin)) | |
193 + FD_SET(0, &fds); | |
194 + if (select(xfd + 1, &fds, NULL, NULL, NULL) == -1) | |
195 + die("cannot multiplex input:"); | |
196 + if (FD_ISSET(xfd, &fds)) | |
197 + readevent(); | |
198 + if (FD_ISSET(0, &fds)) | |
199 + readstdin(); | |
200 + } | |
201 +} | |
202 + | |
203 +static void | |
204 setup(void) | |
205 { | |
206 int x, y; | |
207 @@ -600,7 +638,7 @@ setup(void) | |
208 static void | |
209 usage(void) | |
210 { | |
211 - fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn … | |
212 + fputs("usage: dmenu [-b] [-i] [-l lines] [-p prompt] [-fn font]… | |
213 " [-nb color] [-nf color] [-sb color] [-sf co… | |
214 exit(1); | |
215 } | |
216 @@ -608,7 +646,7 @@ usage(void) | |
217 int | |
218 main(int argc, char *argv[]) | |
219 { | |
220 - int i, fast = 0; | |
221 + int i; | |
222 | |
223 for (i = 1; i < argc; i++) | |
224 /* these options take no arguments */ | |
225 @@ -617,8 +655,6 @@ main(int argc, char *argv[]) | |
226 exit(0); | |
227 } else if (!strcmp(argv[i], "-b")) /* appears at the bo… | |
228 topbar = 0; | |
229 - else if (!strcmp(argv[i], "-f")) /* grabs keyboard be… | |
230 - fast = 1; | |
231 else if (!strcmp(argv[i], "-i")) { /* case-insensitive … | |
232 fstrncmp = strncasecmp; | |
233 fstrstr = cistrstr; | |
234 @@ -657,13 +693,7 @@ main(int argc, char *argv[]) | |
235 die("no fonts could be loaded.\n"); | |
236 lrpad = drw->fonts->h; | |
237 | |
238 - if (fast) { | |
239 - grabkeyboard(); | |
240 - readstdin(); | |
241 - } else { | |
242 - readstdin(); | |
243 - grabkeyboard(); | |
244 - } | |
245 + grabkeyboard(); | |
246 setup(); | |
247 run(); | |
248 |