commit 135dcf099a6ff35bce21a62ed2b792085aab36ae
Author: woland <[email protected]>
Date:   Fri Oct 27 20:22:36 2023 -0400

    calculator patch using qalculate

diff --git a/tools.suckless.org/dmenu/patches/qalc/dmenu-qalc-5.2.diff 
b/tools.suckless.org/dmenu/patches/qalc/dmenu-qalc-5.2.diff
new file mode 100644
index 00000000..37653f82
--- /dev/null
+++ b/tools.suckless.org/dmenu/patches/qalc/dmenu-qalc-5.2.diff
@@ -0,0 +1,259 @@
+diff -up dmenu-5.2/config.mk dmenu-qalc-5.2/config.mk
+--- dmenu-5.2/config.mk        2022-10-04 13:36:58.000000000 -0400
++++ dmenu-qalc-5.2/config.mk   2023-10-27 19:29:48.197693355 -0400
+@@ -24,7 +24,7 @@ INCS = -I$(X11INC) -I$(FREETYPEINC)
+ LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
+ 
+ # flags
+-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 
-D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
++CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 
-D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
+ CFLAGS   = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS)
+ LDFLAGS  = $(LIBS)
+ 
+diff -up dmenu-5.2/dmenu.1 dmenu-qalc-5.2/dmenu.1
+--- dmenu-5.2/dmenu.1  2022-10-04 13:36:58.000000000 -0400
++++ dmenu-qalc-5.2/dmenu.1     2023-10-27 19:28:48.676578875 -0400
+@@ -40,6 +40,9 @@ which lists programs in the user's $PATH
+ .B \-b
+ dmenu appears at the bottom of the screen.
+ .TP
++.B \-C
++dmenu becomes a calculator.
++.TP
+ .B \-f
+ dmenu grabs the keyboard before reading stdin if not reading from a tty. This
+ is faster, but will lock up X until stdin reaches end\-of\-file.
+diff -up dmenu-5.2/dmenu.c dmenu-qalc-5.2/dmenu.c
+--- dmenu-5.2/dmenu.c  2022-10-04 13:36:58.000000000 -0400
++++ dmenu-qalc-5.2/dmenu.c     2023-10-27 20:00:21.438467597 -0400
+@@ -7,6 +7,11 @@
+ #include <strings.h>
+ #include <time.h>
+ #include <unistd.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <sys/prctl.h>
++#include <sys/select.h>
+ 
+ #include <X11/Xlib.h>
+ #include <X11/Xatom.h>
+@@ -34,6 +39,12 @@ struct item {
+       int out;
+ };
+ 
++static struct {
++  pid_t pid;
++  int enable, in[2], out[2];
++  char buf[256];
++} qalc;
++
+ static char text[BUFSIZ] = "";
+ static char *embed;
+ static int bh, mw, mh;
+@@ -228,8 +239,81 @@ grabkeyboard(void)
+ }
+ 
+ static void
++init_qalc(void)
++{
++  pipe(qalc.in);
++  pipe2(qalc.out, O_NONBLOCK);
++  qalc.pid = fork();
++  if (qalc.pid == -1)
++    die("failed to fork for qalc");
++  if (qalc.pid == 0) {
++    dup2(qalc.in[0], STDIN_FILENO);
++    dup2(qalc.out[1], STDOUT_FILENO);
++    close(qalc.in[1]);
++    close(qalc.out[0]);
++    prctl(PR_SET_PDEATHSIG, SIGTERM);
++    execl("/usr/bin/qalc", "qalc", "-c0", "-t", NULL);
++    die ("execl qalc failed");
++  } else { // parent
++    close(qalc.in[0]);
++    close(qalc.out[1]);
++    items = malloc(sizeof(struct item)*2);
++    items[0].text = malloc(LENGTH(qalc.buf));
++    strcpy(items[0].text, "no result");
++    items[1].out = 0;
++    items[1].text = NULL;
++  }
++}
++
++static void
++recv_qalc(void)
++{
++  ssize_t r = read(qalc.out[0], qalc.buf, LENGTH(qalc.buf));
++
++  if (r < 0)
++    die("error reading qalc.out");
++
++  if (qalc.buf[0] == '
') {
++    int i;
++    for (i = 3; i < LENGTH(qalc.buf) && qalc.buf[i] != '
'; ++i)
++      items[0].text[i-3] = qalc.buf[i];
++    items[0].text[i-3] = 0;
++    if (r != LENGTH(qalc.buf))
++      return;
++  }
++
++  while (read(qalc.out[0], qalc.buf, LENGTH(qalc.buf)) != -1)
++    ; // empty the pipe
++  if (errno != EAGAIN && errno != EWOULDBLOCK)
++    die("error emptying qalc.out");
++}
++
++static void
++send_qalc(void)
++{
++  int s = strlen(text);
++  text[s] = '
';
++  write(qalc.in[1], text, s+1);
++  text[s] = 0;
++}
++
++static void
++match_qalc(void)
++{
++  matches = matchend = NULL;
++  appenditem(items, &matches, &matchend);
++  curr = sel = matches;
++  calcoffsets();
++}
++
++static void
+ match(void)
+ {
++  if (qalc.enable) {
++    match_qalc();
++    return;
++  }
++
+       static char **tokv = NULL;
+       static int tokn = 0;
+ 
+@@ -524,6 +608,9 @@ insert:
+               break;
+       }
+ 
++  if (qalc.enable)
++    send_qalc();
++
+ draw:
+       drawmenu();
+ }
+@@ -573,37 +660,52 @@ run(void)
+ {
+       XEvent ev;
+ 
+-      while (!XNextEvent(dpy, &ev)) {
+-              if (XFilterEvent(&ev, win))
+-                      continue;
+-              switch(ev.type) {
+-              case DestroyNotify:
+-                      if (ev.xdestroywindow.window != win)
+-                              break;
+-                      cleanup();
+-                      exit(1);
+-              case Expose:
+-                      if (ev.xexpose.count == 0)
+-                              drw_map(drw, win, 0, 0, mw, mh);
+-                      break;
+-              case FocusIn:
+-                      /* regrab focus from parent window */
+-                      if (ev.xfocus.window != win)
+-                              grabfocus();
+-                      break;
+-              case KeyPress:
+-                      keypress(&ev.xkey);
+-                      break;
+-              case SelectionNotify:
+-                      if (ev.xselection.property == utf8)
+-                              paste();
+-                      break;
+-              case VisibilityNotify:
+-                      if (ev.xvisibility.state != VisibilityUnobscured)
+-                              XRaiseWindow(dpy, win);
+-                      break;
+-              }
+-      }
++  fd_set rfds;
++  int xfd = ConnectionNumber(dpy);
++
++  for (;;) {
++    FD_ZERO(&rfds);
++    FD_SET(xfd, &rfds);
++    FD_SET(qalc.out[0], &rfds);
++
++    if (select(MAX(xfd, qalc.out[0])+1, &rfds, NULL, NULL, NULL) > 0) {
++      if (qalc.enable && FD_ISSET(qalc.out[0], &rfds)) {
++        recv_qalc();
++        drawmenu();
++      }
++      while (XPending(dpy) && !XNextEvent(dpy, &ev)) {
++        if (XFilterEvent(&ev, win))
++          continue;
++        switch(ev.type) {
++          case DestroyNotify:
++            if (ev.xdestroywindow.window != win)
++              break;
++            cleanup();
++            exit(1);
++          case Expose:
++            if (ev.xexpose.count == 0)
++              drw_map(drw, win, 0, 0, mw, mh);
++            break;
++          case FocusIn:
++            /* regrab focus from parent window */
++            if (ev.xfocus.window != win)
++              grabfocus();
++            break;
++          case KeyPress:
++            keypress(&ev.xkey);
++            break;
++          case SelectionNotify:
++            if (ev.xselection.property == utf8)
++              paste();
++            break;
++          case VisibilityNotify:
++            if (ev.xvisibility.state != VisibilityUnobscured)
++              XRaiseWindow(dpy, win);
++            break;
++        }
++      }
++    }
++  }
+ }
+ 
+ static void
+@@ -710,7 +812,7 @@ setup(void)
+ static void
+ usage(void)
+ {
+-      die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]
"
++      die("usage: dmenu [-bCfiv] [-l lines] [-p prompt] [-fn font] [-m 
monitor]
"
+           "             [-nb color] [-nf color] [-sb color] [-sf color] [-w 
windowid]");
+ }
+ 
+@@ -727,6 +829,8 @@ main(int argc, char *argv[])
+                       exit(0);
+               } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of 
the screen */
+                       topbar = 0;
++              else if (!strcmp(argv[i], "-C"))   /* grabs keyboard before 
reading stdin */
++                      qalc.enable = 1;
+               else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before 
reading stdin */
+                       fast = 1;
+               else if (!strcmp(argv[i], "-i")) { /* case-insensitive item 
matching */
+@@ -777,7 +881,10 @@ main(int argc, char *argv[])
+               die("pledge");
+ #endif
+ 
+-      if (fast && !isatty(0)) {
++      if (qalc.enable) {
++              init_qalc();
++              grabkeyboard();
++      } else if (fast && !isatty(0)) {
+               grabkeyboard();
+               readstdin();
+       } else {
diff --git a/tools.suckless.org/dmenu/patches/qalc/index.md 
b/tools.suckless.org/dmenu/patches/qalc/index.md
new file mode 100644
index 00000000..e224a292
--- /dev/null
+++ b/tools.suckless.org/dmenu/patches/qalc/index.md
@@ -0,0 +1,11 @@
+qalc
+==================
+This patch adds an additional flag to dmenu, -C, which turns the app into a 
calculator, à la rofi-calc. The feedback is very smooth and the result of the 
equation is updated every time a key is pressed. This patch requires the 
*qalculate* CLI tool to be installed in /usr/bin/. For more info on its 
capabilities and syntax, visit <https://qalculate.github.io/>.
+
+Download
+--------
+* [dmenu-qalc-5.2.diff](dmenu-qalc-5.2.diff)
+
+Author
+------
+* woland <[email protected]>


Reply via email to