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