dmenu-qalc-5.3.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dmenu-qalc-5.3.diff (6137B)
       ---
            1 From 1e5ee55ff70ca7abcc8c223ae34ff5b94e0a647d Mon Sep 17 00:00:00 2001
            2 From: Justinas Grigas <dev@jstnas.com>
            3 Date: Sat, 15 Jun 2024 21:13:12 +0100
            4 Subject: [PATCH] qalc: calculator mode
            5 
            6 Updates over previous patch:
            7 - add flag to manpage synopsis.
            8 - uses poll instead of select (prevents hang when qalc is not installed).
            9 - follow suckless style.
           10 - qalc function names start with qalc.
           11 ---
           12  dmenu.1 |   5 +-
           13  dmenu.c | 160 +++++++++++++++++++++++++++++++++++++++++++++-----------
           14  2 files changed, 133 insertions(+), 32 deletions(-)
           15 
           16 diff --git a/dmenu.1 b/dmenu.1
           17 index 323f93c..ee5ca31 100644
           18 --- a/dmenu.1
           19 +++ b/dmenu.1
           20 @@ -3,7 +3,7 @@
           21  dmenu \- dynamic menu
           22  .SH SYNOPSIS
           23  .B dmenu
           24 -.RB [ \-bfiv ]
           25 +.RB [ \-bCfiv ]
           26  .RB [ \-l
           27  .IR lines ]
           28  .RB [ \-m
           29 @@ -40,6 +40,9 @@ which lists programs in the user's $PATH and runs the result in their $SHELL.
           30  .B \-b
           31  dmenu appears at the bottom of the screen.
           32  .TP
           33 +.B \-C
           34 +dmenu becomes a calculator.
           35 +.TP
           36  .B \-f
           37  dmenu grabs the keyboard before reading stdin if not reading from a tty. This
           38  is faster, but will lock up X until stdin reaches end\-of\-file.
           39 diff --git a/dmenu.c b/dmenu.c
           40 index 40f93e0..67b7f02 100644
           41 --- a/dmenu.c
           42 +++ b/dmenu.c
           43 @@ -7,6 +7,11 @@
           44  #include <strings.h>
           45  #include <time.h>
           46  #include <unistd.h>
           47 +#include <errno.h>
           48 +#include <fcntl.h>
           49 +#include <poll.h>
           50 +#include <signal.h>
           51 +#include <sys/prctl.h>
           52  
           53  #include <X11/Xlib.h>
           54  #include <X11/Xatom.h>
           55 @@ -33,6 +38,12 @@ struct item {
           56          int out;
           57  };
           58  
           59 +static struct {
           60 +        pid_t pid;
           61 +        int enable, in[2], out[2];
           62 +        char buf[256];
           63 +} qalc;
           64 +
           65  static char text[BUFSIZ] = "";
           66  static char *embed;
           67  static int bh, mw, mh;
           68 @@ -226,9 +237,78 @@ grabkeyboard(void)
           69          die("cannot grab keyboard");
           70  }
           71  
           72 +static void
           73 +qalc_init(void)
           74 +{
           75 +        pipe(qalc.in);
           76 +        pipe2(qalc.out, O_NONBLOCK);
           77 +        qalc.pid = fork();
           78 +        if (qalc.pid == -1)
           79 +                die("failed to fork for qalc");
           80 +        if (qalc.pid == 0) {
           81 +                dup2(qalc.in[0], STDIN_FILENO);
           82 +                dup2(qalc.out[1], STDOUT_FILENO);
           83 +                close(qalc.in[1]);
           84 +                close(qalc.out[0]);
           85 +                prctl(PR_SET_PDEATHSIG, SIGTERM);
           86 +                execl("/usr/bin/qalc", "qalc", "-c0", "-t", NULL);
           87 +                die("execl qalc failed");
           88 +        } else { /* parent */
           89 +                close(qalc.in[0]);
           90 +                close(qalc.out[1]);
           91 +                items = malloc(sizeof(struct item) * 2);
           92 +                items[0].text = malloc(LENGTH(qalc.buf));
           93 +                strcpy(items[0].text, "no result");
           94 +                items[1].out = 0;
           95 +                items[1].text = NULL;
           96 +        }
           97 +}
           98 +
           99 +static void
          100 +qalc_recv(void)
          101 +{
          102 +        ssize_t r = read(qalc.out[0], qalc.buf, LENGTH(qalc.buf));
          103 +        if (r < 0)
          104 +                die("error reading qalc.out");
          105 +        if (qalc.buf[0] == '\n') {
          106 +                int i;
          107 +                for (i = 3; i < LENGTH(qalc.buf) && qalc.buf[i] != '\n'; ++i)
          108 +                        items[0].text[i - 3] = qalc.buf[i];
          109 +                items[0].text[i - 3] = 0;
          110 +                if (r != LENGTH(qalc.buf))
          111 +                        return;
          112 +        }
          113 +        while (read(qalc.out[0], qalc.buf, LENGTH(qalc.buf)) != -1)
          114 +                ; /* empty the pipe */
          115 +        if (errno != EAGAIN && errno != EWOULDBLOCK)
          116 +                die("error emptying qalc.out");
          117 +}
          118 +
          119 +static void
          120 +qalc_send(void)
          121 +{
          122 +        int s = strlen(text);
          123 +        text[s] = '\n';
          124 +        write(qalc.in[1], text, s + 1);
          125 +        text[s] = 0;
          126 +}
          127 +
          128 +static void
          129 +qalc_match(void)
          130 +{
          131 +        matches = matchend = NULL;
          132 +        appenditem(items, &matches, &matchend);
          133 +        curr = sel = matches;
          134 +        calcoffsets();
          135 +}
          136 +
          137  static void
          138  match(void)
          139  {
          140 +        if (qalc.enable) {
          141 +                qalc_match();
          142 +                return;
          143 +        }
          144          static char **tokv = NULL;
          145          static int tokn = 0;
          146  
          147 @@ -523,6 +603,9 @@ insert:
          148                  break;
          149          }
          150  
          151 +  if (qalc.enable)
          152 +    qalc_send();
          153 +
          154  draw:
          155          drawmenu();
          156  }
          157 @@ -576,36 +659,46 @@ static void
          158  run(void)
          159  {
          160          XEvent ev;
          161 -
          162 -        while (!XNextEvent(dpy, &ev)) {
          163 -                if (XFilterEvent(&ev, win))
          164 -                        continue;
          165 -                switch(ev.type) {
          166 -                case DestroyNotify:
          167 -                        if (ev.xdestroywindow.window != win)
          168 +        int xfd = ConnectionNumber(dpy);
          169 +        struct pollfd fds[] = {
          170 +                {xfd, POLLIN, 0},
          171 +                {qalc.out[0], POLLIN, 0},
          172 +        };
          173 +        while (poll(fds, 2, -1) > 0) {
          174 +                if (qalc.enable && fds[1].revents & POLLIN) {
          175 +                        qalc_recv();
          176 +                        drawmenu();
          177 +                }
          178 +                while (XPending(dpy) && !XNextEvent(dpy, &ev)) {
          179 +                        if (XFilterEvent(&ev, win))
          180 +                                continue;
          181 +                        switch (ev.type) {
          182 +                        case DestroyNotify:
          183 +                                if (ev.xdestroywindow.window != win)
          184 +                                        break;
          185 +                                cleanup();
          186 +                                exit(1);
          187 +                        case Expose:
          188 +                                if (ev.xexpose.count == 0)
          189 +                                        drw_map(drw, win, 0, 0, mw, mh);
          190                                  break;
          191 -                        cleanup();
          192 -                        exit(1);
          193 -                case Expose:
          194 -                        if (ev.xexpose.count == 0)
          195 -                                drw_map(drw, win, 0, 0, mw, mh);
          196 -                        break;
          197 -                case FocusIn:
          198 -                        /* regrab focus from parent window */
          199 -                        if (ev.xfocus.window != win)
          200 -                                grabfocus();
          201 -                        break;
          202 -                case KeyPress:
          203 -                        keypress(&ev.xkey);
          204 -                        break;
          205 -                case SelectionNotify:
          206 -                        if (ev.xselection.property == utf8)
          207 -                                paste();
          208 -                        break;
          209 -                case VisibilityNotify:
          210 -                        if (ev.xvisibility.state != VisibilityUnobscured)
          211 -                                XRaiseWindow(dpy, win);
          212 -                        break;
          213 +                        case FocusIn:
          214 +                                /* regrab focus from parent window */
          215 +                                if (ev.xfocus.window != win)
          216 +                                        grabfocus();
          217 +                                break;
          218 +                        case KeyPress:
          219 +                                keypress(&ev.xkey);
          220 +                                break;
          221 +                        case SelectionNotify:
          222 +                                if (ev.xselection.property == utf8)
          223 +                                        paste();
          224 +                                break;
          225 +                        case VisibilityNotify:
          226 +                                if (ev.xvisibility.state != VisibilityUnobscured)
          227 +                                        XRaiseWindow(dpy, win);
          228 +                                break;
          229 +                        }
          230                  }
          231          }
          232  }
          233 @@ -715,7 +808,7 @@ setup(void)
          234  static void
          235  usage(void)
          236  {
          237 -        die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
          238 +        die("usage: dmenu [-bCfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
          239              "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");
          240  }
          241  
          242 @@ -732,6 +825,8 @@ main(int argc, char *argv[])
          243                          exit(0);
          244                  } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
          245                          topbar = 0;
          246 +                else if (!strcmp(argv[i], "-C"))   /* enable calculator */
          247 +                        qalc.enable = 1;
          248                  else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before reading stdin */
          249                          fast = 1;
          250                  else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
          251 @@ -782,7 +877,10 @@ main(int argc, char *argv[])
          252                  die("pledge");
          253  #endif
          254  
          255 -        if (fast && !isatty(0)) {
          256 +        if (qalc.enable) {
          257 +                qalc_init();
          258 +                grabkeyboard();
          259 +        } else if (fast && !isatty(0)) {
          260                  grabkeyboard();
          261                  readstdin();
          262          } else {
          263 -- 
          264 2.45.2
          265