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