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