sites

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