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