dmenu-qalc-5.3.diff - 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 <[email protected]> | |
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 … | |
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… | |
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'… | |
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 != VisibilityUnobscure… | |
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 != VisibilityU… | |
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… | |
238 + die("usage: dmenu [-bCfiv] [-l lines] [-p prompt] [-fn font] [-… | |
239 " [-nb color] [-nf color] [-sb color] [-sf colo… | |
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 bo… | |
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 be… | |
249 fast = 1; | |
250 else if (!strcmp(argv[i], "-i")) { /* case-insensitive … | |
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 |