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