sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | 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