dmenu-nonblockingstdin-20160702-3c91eed.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) 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 result in their $SHELL.
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 will lock up
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 }; /* color schemes */
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 = NULL;
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 substrings */
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, NULL);
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 font] [-m monitor]\n"
212 + fputs("usage: dmenu [-b] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
213 " [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr);
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 bottom of the screen */
228 topbar = 0;
229 - else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
230 - fast = 1;
231 else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
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