Blame


1 15aae8ae 2023-05-28 aa #include <ctype.h>
2 15aae8ae 2023-05-28 aa #include <errno.h>
3 cb28fcb8 2023-05-26 aa #include <stdarg.h>
4 15aae8ae 2023-05-28 aa #include <stdbool.h>
5 cb28fcb8 2023-05-26 aa #include <stdio.h>
6 cb28fcb8 2023-05-26 aa #include <stdlib.h>
7 cb28fcb8 2023-05-26 aa #include <string.h>
8 15aae8ae 2023-05-28 aa #include <time.h>
9 cb28fcb8 2023-05-26 aa #include <unistd.h>
10 cb28fcb8 2023-05-26 aa
11 cb28fcb8 2023-05-26 aa #include <X11/Xlib.h>
12 cb28fcb8 2023-05-26 aa #include <X11/Xutil.h>
13 cb28fcb8 2023-05-26 aa #include <X11/Xos.h>
14 cb28fcb8 2023-05-26 aa #include <X11/Xatom.h>
15 77968eb5 2023-05-29 aa #include <X11/Xft/Xft.h>
16 cb28fcb8 2023-05-26 aa
17 7c7bbaee 2023-05-27 aa #define PROGNAME "xitems"
18 843ffc79 2023-05-28 aa #define MAXKS 32
19 7c7bbaee 2023-05-27 aa
20 15aae8ae 2023-05-28 aa /* usage -- print usage information and die. */
21 cb28fcb8 2023-05-26 aa static void
22 7c7bbaee 2023-05-27 aa usage(void)
23 7c7bbaee 2023-05-27 aa {
24 15aae8ae 2023-05-28 aa printf(
25 15aae8ae 2023-05-28 aa "usage: " PROGNAME " [-font font] [-bg colour] [-fg colour]\n"
26 f1adc4ca 2023-05-28 aa " [-sbg colour] [-sfg colour] [-bc colour] [-bw width]\n"
27 15aae8ae 2023-05-28 aa " [-hp padding] [-vp padding] [-x x] [-y y]\n");
28 7c7bbaee 2023-05-27 aa exit(1);
29 7c7bbaee 2023-05-27 aa }
30 7c7bbaee 2023-05-27 aa
31 15aae8ae 2023-05-28 aa /* die -- print formatted string, and exit with the status eval. */
32 7c7bbaee 2023-05-27 aa static void
33 15aae8ae 2023-05-28 aa die(int eval, const char *fmt, ...)
34 cb28fcb8 2023-05-26 aa {
35 7c7bbaee 2023-05-27 aa fputs(PROGNAME ": ", stderr);
36 cb28fcb8 2023-05-26 aa if (fmt) {
37 cb28fcb8 2023-05-26 aa va_list argp;
38 cb28fcb8 2023-05-26 aa va_start(argp, fmt);
39 cb28fcb8 2023-05-26 aa vfprintf(stderr, fmt, argp);
40 cb28fcb8 2023-05-26 aa va_end(argp);
41 cb28fcb8 2023-05-26 aa }
42 cb28fcb8 2023-05-26 aa fputc('\n', stderr);
43 cb28fcb8 2023-05-26 aa exit(eval);
44 cb28fcb8 2023-05-26 aa }
45 cb28fcb8 2023-05-26 aa
46 840c16f6 2023-05-30 aa /* edie -- same as die(), but also output a message via strerror(). */
47 840c16f6 2023-05-30 aa static void
48 840c16f6 2023-05-30 aa edie(int eval, const char *fmt, ...)
49 840c16f6 2023-05-30 aa {
50 840c16f6 2023-05-30 aa int xerrno = errno;
51 840c16f6 2023-05-30 aa
52 840c16f6 2023-05-30 aa fputs(PROGNAME ": ", stderr);
53 840c16f6 2023-05-30 aa if (fmt) {
54 840c16f6 2023-05-30 aa va_list argp;
55 840c16f6 2023-05-30 aa va_start(argp, fmt);
56 840c16f6 2023-05-30 aa vfprintf(stderr, fmt, argp);
57 840c16f6 2023-05-30 aa va_end(argp);
58 840c16f6 2023-05-30 aa }
59 840c16f6 2023-05-30 aa fprintf(stderr, ": %s", strerror(xerrno));
60 840c16f6 2023-05-30 aa
61 840c16f6 2023-05-30 aa fputc('\n', stderr);
62 840c16f6 2023-05-30 aa exit(eval);
63 840c16f6 2023-05-30 aa }
64 840c16f6 2023-05-30 aa
65 843ffc79 2023-05-28 aa /* warn -- print formatted string to stderr. */
66 843ffc79 2023-05-28 aa static void
67 843ffc79 2023-05-28 aa warn(const char *fmt, ...)
68 843ffc79 2023-05-28 aa {
69 843ffc79 2023-05-28 aa fputs(PROGNAME ": ", stderr);
70 843ffc79 2023-05-28 aa if (fmt) {
71 843ffc79 2023-05-28 aa va_list argp;
72 843ffc79 2023-05-28 aa va_start(argp, fmt);
73 843ffc79 2023-05-28 aa vfprintf(stderr, fmt, argp);
74 843ffc79 2023-05-28 aa va_end(argp);
75 843ffc79 2023-05-28 aa }
76 843ffc79 2023-05-28 aa fputc('\n', stderr);
77 843ffc79 2023-05-28 aa }
78 843ffc79 2023-05-28 aa
79 6cdc5a3d 2023-05-28 aa enum direction {
80 6cdc5a3d 2023-05-28 aa DIR_UP,
81 6cdc5a3d 2023-05-28 aa DIR_DOWN
82 6cdc5a3d 2023-05-28 aa };
83 6cdc5a3d 2023-05-28 aa
84 cb28fcb8 2023-05-26 aa /* doubly-linked cyclic list */
85 cb28fcb8 2023-05-26 aa struct item {
86 cb28fcb8 2023-05-26 aa struct item *prev;
87 cb28fcb8 2023-05-26 aa struct item *next;
88 843ffc79 2023-05-28 aa char *s;
89 843ffc79 2023-05-28 aa KeySym ks[MAXKS]; /* array of associated keysyms */
90 843ffc79 2023-05-28 aa size_t len; /* length of string */
91 843ffc79 2023-05-28 aa size_t nks; /* number of associated keysyms */
92 15aae8ae 2023-05-28 aa bool dirty; /* should be redrawn */
93 cb28fcb8 2023-05-26 aa };
94 cb28fcb8 2023-05-26 aa
95 15aae8ae 2023-05-28 aa static struct item *first = NULL; /* first member of the list */
96 cb28fcb8 2023-05-26 aa static struct item *selected = NULL;
97 15aae8ae 2023-05-28 aa
98 15aae8ae 2023-05-28 aa /* command-line options and X resources */
99 15aae8ae 2023-05-28 aa static char *o_font = NULL;
100 f1adc4ca 2023-05-28 aa static char *o_bg = NULL, *o_fg = NULL, *o_sbg = NULL, *o_sfg = NULL,
101 f1adc4ca 2023-05-28 aa *o_bc = NULL;
102 15aae8ae 2023-05-28 aa static int o_x = -1, o_y = -1;
103 15aae8ae 2023-05-28 aa static int o_bw = -1;
104 15aae8ae 2023-05-28 aa static int o_hp = -1, o_vp = -1;
105 15aae8ae 2023-05-28 aa
106 15aae8ae 2023-05-28 aa /* X globals */
107 2d5f9ee6 2023-05-29 aa enum {
108 2d5f9ee6 2023-05-29 aa PIXEL_BG = 0,
109 2d5f9ee6 2023-05-29 aa PIXEL_BC,
110 2d5f9ee6 2023-05-29 aa };
111 2d5f9ee6 2023-05-29 aa #define PIXEL_N 2
112 2d5f9ee6 2023-05-29 aa
113 15aae8ae 2023-05-28 aa static Display *dpy = NULL;
114 cb28fcb8 2023-05-26 aa static int screen;
115 15aae8ae 2023-05-28 aa static Window win;
116 15aae8ae 2023-05-28 aa static int height, width; /* height and width of one item */
117 77968eb5 2023-05-29 aa static XftFont *font;
118 77968eb5 2023-05-29 aa static XftColor c_fg, c_sfg, c_sbg;
119 2d5f9ee6 2023-05-29 aa static unsigned long pixels[PIXEL_N];
120 cb28fcb8 2023-05-26 aa
121 703f0cd0 2023-05-29 aa /*
122 703f0cd0 2023-05-29 aa * freeitems -- recursively free the list of items. First call should be
123 703f0cd0 2023-05-29 aa * freeitems(NULL).
124 703f0cd0 2023-05-29 aa */
125 703f0cd0 2023-05-29 aa static void
126 703f0cd0 2023-05-29 aa freeitems(struct item *it)
127 703f0cd0 2023-05-29 aa {
128 703f0cd0 2023-05-29 aa if (!it)
129 703f0cd0 2023-05-29 aa it = first;
130 703f0cd0 2023-05-29 aa else if (it == first)
131 703f0cd0 2023-05-29 aa return;
132 703f0cd0 2023-05-29 aa
133 703f0cd0 2023-05-29 aa freeitems(it->next);
134 703f0cd0 2023-05-29 aa free(it);
135 703f0cd0 2023-05-29 aa }
136 703f0cd0 2023-05-29 aa
137 843ffc79 2023-05-28 aa /* selpos -- mark the item at position y (from top) as selected. */
138 6cdc5a3d 2023-05-28 aa static void
139 843ffc79 2023-05-28 aa selpos(int y)
140 6cdc5a3d 2023-05-28 aa {
141 6cdc5a3d 2023-05-28 aa struct item *unselected = selected;
142 6cdc5a3d 2023-05-28 aa int top = 1;
143 6cdc5a3d 2023-05-28 aa
144 6cdc5a3d 2023-05-28 aa selected = first;
145 6cdc5a3d 2023-05-28 aa
146 6cdc5a3d 2023-05-28 aa if (y <= 0)
147 6cdc5a3d 2023-05-28 aa goto end;
148 6cdc5a3d 2023-05-28 aa
149 843ffc79 2023-05-28 aa for (selected = first; selected != first->prev;
150 843ffc79 2023-05-28 aa selected = selected->next) {
151 6cdc5a3d 2023-05-28 aa if (y >= top && y < top+height)
152 6cdc5a3d 2023-05-28 aa break;
153 6cdc5a3d 2023-05-28 aa top += height;
154 843ffc79 2023-05-28 aa }
155 6cdc5a3d 2023-05-28 aa
156 6cdc5a3d 2023-05-28 aa end:
157 6cdc5a3d 2023-05-28 aa if (unselected != selected)
158 6cdc5a3d 2023-05-28 aa unselected->dirty = selected->dirty = true;
159 6cdc5a3d 2023-05-28 aa }
160 6cdc5a3d 2023-05-28 aa
161 703f0cd0 2023-05-29 aa /* inbounds -- check if point y is within the bounds of line going from top. */
162 703f0cd0 2023-05-29 aa static bool
163 703f0cd0 2023-05-29 aa inbounds(int y, int top, int height)
164 703f0cd0 2023-05-29 aa {
165 703f0cd0 2023-05-29 aa return y >= top && y <= top+height;
166 703f0cd0 2023-05-29 aa }
167 703f0cd0 2023-05-29 aa
168 703f0cd0 2023-05-29 aa /* expose -- mark exposed items as dirty. */
169 703f0cd0 2023-05-29 aa static void
170 703f0cd0 2023-05-29 aa expose(XExposeEvent e)
171 703f0cd0 2023-05-29 aa {
172 703f0cd0 2023-05-29 aa struct item *it = first;
173 703f0cd0 2023-05-29 aa int y = 0;
174 703f0cd0 2023-05-29 aa
175 703f0cd0 2023-05-29 aa do {
176 703f0cd0 2023-05-29 aa /*
177 703f0cd0 2023-05-29 aa * If either end of e's vertical part is within the bounds
178 703f0cd0 2023-05-29 aa * of the item, there is at least some collision. Conversely,
179 703f0cd0 2023-05-29 aa * if either of the item's vertical ends is within e's bounds,
180 703f0cd0 2023-05-29 aa * they must collide.
181 703f0cd0 2023-05-29 aa */
182 703f0cd0 2023-05-29 aa int bot = y+height, e_bot = e.y+e.height;
183 703f0cd0 2023-05-29 aa if (inbounds(e.y, y, bot) || inbounds(e_bot, y, bot) ||
184 703f0cd0 2023-05-29 aa inbounds(y, e.y, e_bot) || inbounds(bot, e.y, e_bot))
185 703f0cd0 2023-05-29 aa it->dirty = true;
186 703f0cd0 2023-05-29 aa
187 703f0cd0 2023-05-29 aa y += height;
188 703f0cd0 2023-05-29 aa it = it->next;
189 703f0cd0 2023-05-29 aa } while (it != first);
190 703f0cd0 2023-05-29 aa }
191 703f0cd0 2023-05-29 aa
192 2d5f9ee6 2023-05-29 aa /* redraw -- redraw the entire window. */
193 15aae8ae 2023-05-28 aa static void
194 15aae8ae 2023-05-28 aa redraw(void)
195 15aae8ae 2023-05-28 aa {
196 15aae8ae 2023-05-28 aa struct item *it = first;
197 15aae8ae 2023-05-28 aa int y = 0;
198 15aae8ae 2023-05-28 aa
199 77968eb5 2023-05-29 aa static XftDraw *d = NULL;
200 77968eb5 2023-05-29 aa
201 77968eb5 2023-05-29 aa if (!d && !(d = XftDrawCreate(dpy, win, DefaultVisual(dpy, screen),
202 77968eb5 2023-05-29 aa DefaultColormap(dpy, screen))))
203 77968eb5 2023-05-29 aa die(1, "couldn't create XftDraw");
204 77968eb5 2023-05-29 aa
205 15aae8ae 2023-05-28 aa do {
206 15aae8ae 2023-05-28 aa if (it->dirty) {
207 2d5f9ee6 2023-05-29 aa XftColor *c;
208 77968eb5 2023-05-29 aa
209 b64495df 2023-05-29 aa XClearArea(dpy, win, 0, y, width, height, False);
210 15aae8ae 2023-05-28 aa
211 15aae8ae 2023-05-28 aa if (it == selected) {
212 2d5f9ee6 2023-05-29 aa c = &c_sfg;
213 77968eb5 2023-05-29 aa XftDrawRect(d, &c_sbg, 0, y, width, height);
214 b64495df 2023-05-29 aa } else
215 2d5f9ee6 2023-05-29 aa c = &c_fg;
216 15aae8ae 2023-05-28 aa
217 2d5f9ee6 2023-05-29 aa XftDrawStringUtf8(d, c, font,
218 77968eb5 2023-05-29 aa o_hp, y + o_vp+font->ascent,
219 77968eb5 2023-05-29 aa (FcChar8 *)it->s, it->len);
220 15aae8ae 2023-05-28 aa
221 15aae8ae 2023-05-28 aa it->dirty = false;
222 15aae8ae 2023-05-28 aa }
223 15aae8ae 2023-05-28 aa
224 15aae8ae 2023-05-28 aa y += height;
225 15aae8ae 2023-05-28 aa it = it->next;
226 15aae8ae 2023-05-28 aa } while (it != first);
227 15aae8ae 2023-05-28 aa }
228 15aae8ae 2023-05-28 aa
229 2d5f9ee6 2023-05-29 aa /* cleanup -- free allocated resources. */
230 2d5f9ee6 2023-05-29 aa static void
231 2d5f9ee6 2023-05-29 aa cleanup(void)
232 2d5f9ee6 2023-05-29 aa {
233 2d5f9ee6 2023-05-29 aa Colormap cmap = DefaultColormap(dpy, screen);
234 2d5f9ee6 2023-05-29 aa Visual *vis = DefaultVisual(dpy, screen);
235 2d5f9ee6 2023-05-29 aa
236 2d5f9ee6 2023-05-29 aa freeitems(NULL);
237 2d5f9ee6 2023-05-29 aa
238 2d5f9ee6 2023-05-29 aa XftFontClose(dpy, font);
239 2d5f9ee6 2023-05-29 aa
240 2d5f9ee6 2023-05-29 aa XFreeColors(dpy, cmap, pixels, PIXEL_N, 0);
241 2d5f9ee6 2023-05-29 aa XftColorFree(dpy, vis, cmap, &c_fg);
242 2d5f9ee6 2023-05-29 aa XftColorFree(dpy, vis, cmap, &c_sbg);
243 2d5f9ee6 2023-05-29 aa XftColorFree(dpy, vis, cmap, &c_sfg);
244 2d5f9ee6 2023-05-29 aa
245 2d5f9ee6 2023-05-29 aa XUngrabKeyboard(dpy, CurrentTime);
246 2d5f9ee6 2023-05-29 aa XUngrabPointer(dpy, CurrentTime);
247 2d5f9ee6 2023-05-29 aa
248 2d5f9ee6 2023-05-29 aa XCloseDisplay(dpy);
249 2d5f9ee6 2023-05-29 aa }
250 2d5f9ee6 2023-05-29 aa
251 6cdc5a3d 2023-05-28 aa /* succeed -- exit successfully. If print is true, also print selected item. */
252 6cdc5a3d 2023-05-28 aa static void
253 6cdc5a3d 2023-05-28 aa succeed(bool print)
254 6cdc5a3d 2023-05-28 aa {
255 6cdc5a3d 2023-05-28 aa if (print && selected)
256 6cdc5a3d 2023-05-28 aa puts(selected->s);
257 2d5f9ee6 2023-05-29 aa cleanup();
258 6cdc5a3d 2023-05-28 aa exit(0);
259 6cdc5a3d 2023-05-28 aa }
260 6cdc5a3d 2023-05-28 aa
261 6cdc5a3d 2023-05-28 aa /* scroll -- select the previous, or next item, depending on dir. */
262 6cdc5a3d 2023-05-28 aa static void
263 6cdc5a3d 2023-05-28 aa scroll(enum direction dir)
264 6cdc5a3d 2023-05-28 aa {
265 6cdc5a3d 2023-05-28 aa if (selected) {
266 6cdc5a3d 2023-05-28 aa selected->dirty = true;
267 6cdc5a3d 2023-05-28 aa selected = (dir == DIR_UP) ? selected->prev : selected->next;
268 6cdc5a3d 2023-05-28 aa } else
269 6cdc5a3d 2023-05-28 aa selected = (dir == DIR_UP) ? first->prev : first;
270 6cdc5a3d 2023-05-28 aa selected->dirty = true;
271 6cdc5a3d 2023-05-28 aa }
272 6cdc5a3d 2023-05-28 aa
273 843ffc79 2023-05-28 aa /*
274 843ffc79 2023-05-28 aa * keyselectd -- compare ks with keysyms stored in the items list, and mark
275 843ffc79 2023-05-28 aa * the first match as selected. Return true on match, and false otherwise.
276 843ffc79 2023-05-28 aa */
277 843ffc79 2023-05-28 aa static bool
278 843ffc79 2023-05-28 aa keyselect(KeySym ks)
279 843ffc79 2023-05-28 aa {
280 843ffc79 2023-05-28 aa struct item *it = first;
281 843ffc79 2023-05-28 aa KeySym k, dummy;
282 843ffc79 2023-05-28 aa
283 843ffc79 2023-05-28 aa XConvertCase(ks, &k, &dummy);
284 843ffc79 2023-05-28 aa
285 843ffc79 2023-05-28 aa do {
286 843ffc79 2023-05-28 aa size_t i;
287 843ffc79 2023-05-28 aa for (i = 0; i < it->nks; ++i)
288 843ffc79 2023-05-28 aa if (it->ks[i] == k) {
289 843ffc79 2023-05-28 aa selected->dirty = true;
290 843ffc79 2023-05-28 aa selected = it;
291 843ffc79 2023-05-28 aa selected->dirty = true;
292 843ffc79 2023-05-28 aa return true;
293 843ffc79 2023-05-28 aa }
294 843ffc79 2023-05-28 aa it = it->next;
295 843ffc79 2023-05-28 aa } while (it != first);
296 843ffc79 2023-05-28 aa
297 843ffc79 2023-05-28 aa return false;
298 843ffc79 2023-05-28 aa }
299 843ffc79 2023-05-28 aa
300 15aae8ae 2023-05-28 aa /* proc -- body of the main event-reading loop. */
301 15aae8ae 2023-05-28 aa static void
302 15aae8ae 2023-05-28 aa proc(void)
303 15aae8ae 2023-05-28 aa {
304 15aae8ae 2023-05-28 aa XKeyEvent ke;
305 15aae8ae 2023-05-28 aa KeySym ks;
306 15aae8ae 2023-05-28 aa char *dummy = "";
307 15aae8ae 2023-05-28 aa XEvent ev;
308 15aae8ae 2023-05-28 aa
309 6cdc5a3d 2023-05-28 aa static bool inwin = false;
310 6cdc5a3d 2023-05-28 aa
311 15aae8ae 2023-05-28 aa XNextEvent(dpy, &ev);
312 15aae8ae 2023-05-28 aa
313 15aae8ae 2023-05-28 aa switch (ev.type) {
314 6cdc5a3d 2023-05-28 aa case EnterNotify:
315 6cdc5a3d 2023-05-28 aa inwin = true;
316 4c35dce7 2023-05-30 aa redraw();
317 4c35dce7 2023-05-30 aa break;
318 6cdc5a3d 2023-05-28 aa case MotionNotify:
319 843ffc79 2023-05-28 aa selpos(ev.xbutton.y);
320 4c35dce7 2023-05-30 aa redraw();
321 4c35dce7 2023-05-30 aa break;
322 15aae8ae 2023-05-28 aa case Expose:
323 703f0cd0 2023-05-29 aa expose(ev.xexpose);
324 703f0cd0 2023-05-29 aa if (ev.xexpose.count)
325 703f0cd0 2023-05-29 aa break;
326 15aae8ae 2023-05-28 aa redraw();
327 15aae8ae 2023-05-28 aa break;
328 6cdc5a3d 2023-05-28 aa case LeaveNotify:
329 6cdc5a3d 2023-05-28 aa inwin = false;
330 6cdc5a3d 2023-05-28 aa break;
331 6cdc5a3d 2023-05-28 aa case ButtonPress:
332 6cdc5a3d 2023-05-28 aa if (ev.xbutton.button == Button4) {
333 6cdc5a3d 2023-05-28 aa scroll(DIR_UP);
334 6cdc5a3d 2023-05-28 aa redraw();
335 6cdc5a3d 2023-05-28 aa } else if (ev.xbutton.button == Button5) {
336 6cdc5a3d 2023-05-28 aa scroll(DIR_DOWN);
337 6cdc5a3d 2023-05-28 aa redraw();
338 6cdc5a3d 2023-05-28 aa } else if (inwin)
339 6cdc5a3d 2023-05-28 aa succeed(true);
340 6cdc5a3d 2023-05-28 aa else
341 6cdc5a3d 2023-05-28 aa succeed(false);
342 6cdc5a3d 2023-05-28 aa break;
343 15aae8ae 2023-05-28 aa case KeyPress:
344 15aae8ae 2023-05-28 aa ke = ev.xkey;
345 15aae8ae 2023-05-28 aa XLookupString(&ke, dummy, 0, &ks, NULL);
346 15aae8ae 2023-05-28 aa
347 15aae8ae 2023-05-28 aa if (ke.state & ControlMask) {
348 15aae8ae 2023-05-28 aa switch (ks) {
349 15aae8ae 2023-05-28 aa case XK_bracketleft:
350 15aae8ae 2023-05-28 aa case XK_C:
351 15aae8ae 2023-05-28 aa case XK_c:
352 15aae8ae 2023-05-28 aa ks = XK_Escape;
353 15aae8ae 2023-05-28 aa break;
354 15aae8ae 2023-05-28 aa case XK_M:
355 15aae8ae 2023-05-28 aa case XK_m:
356 15aae8ae 2023-05-28 aa case XK_J:
357 15aae8ae 2023-05-28 aa case XK_j:
358 15aae8ae 2023-05-28 aa ks = XK_Return;
359 15aae8ae 2023-05-28 aa break;
360 15aae8ae 2023-05-28 aa case XK_N:
361 15aae8ae 2023-05-28 aa case XK_n:
362 15aae8ae 2023-05-28 aa ks = XK_j;
363 15aae8ae 2023-05-28 aa return;
364 15aae8ae 2023-05-28 aa case XK_P:
365 15aae8ae 2023-05-28 aa case XK_p:
366 15aae8ae 2023-05-28 aa ks = XK_k;
367 15aae8ae 2023-05-28 aa return;
368 15aae8ae 2023-05-28 aa }
369 843ffc79 2023-05-28 aa } else if (keyselect(ks))
370 843ffc79 2023-05-28 aa succeed(true);
371 15aae8ae 2023-05-28 aa
372 15aae8ae 2023-05-28 aa switch (ks) {
373 15aae8ae 2023-05-28 aa case XK_j:
374 15aae8ae 2023-05-28 aa case XK_J:
375 15aae8ae 2023-05-28 aa case XK_Down:
376 6cdc5a3d 2023-05-28 aa scroll(DIR_DOWN);
377 15aae8ae 2023-05-28 aa redraw();
378 15aae8ae 2023-05-28 aa break;
379 15aae8ae 2023-05-28 aa case XK_k:
380 15aae8ae 2023-05-28 aa case XK_K:
381 15aae8ae 2023-05-28 aa case XK_Up:
382 6cdc5a3d 2023-05-28 aa scroll(DIR_UP);
383 15aae8ae 2023-05-28 aa redraw();
384 15aae8ae 2023-05-28 aa break;
385 15aae8ae 2023-05-28 aa case XK_Return:
386 6cdc5a3d 2023-05-28 aa succeed(true);
387 15aae8ae 2023-05-28 aa /* NOTREACHED */
388 15aae8ae 2023-05-28 aa case XK_Escape:
389 6cdc5a3d 2023-05-28 aa succeed(false);
390 15aae8ae 2023-05-28 aa /* NOTREACHED */
391 15aae8ae 2023-05-28 aa }
392 15aae8ae 2023-05-28 aa
393 15aae8ae 2023-05-28 aa break;
394 15aae8ae 2023-05-28 aa }
395 15aae8ae 2023-05-28 aa }
396 15aae8ae 2023-05-28 aa
397 6cdc5a3d 2023-05-28 aa /* grabptr -- try to grab pointer for a second */
398 6cdc5a3d 2023-05-28 aa static void
399 6cdc5a3d 2023-05-28 aa grabptr(void)
400 6cdc5a3d 2023-05-28 aa {
401 6cdc5a3d 2023-05-28 aa struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
402 6cdc5a3d 2023-05-28 aa int i;
403 6cdc5a3d 2023-05-28 aa
404 6cdc5a3d 2023-05-28 aa for (i = 0; i < 1000; ++i) {
405 6cdc5a3d 2023-05-28 aa if (XGrabPointer(dpy, RootWindow(dpy, screen), True,
406 6cdc5a3d 2023-05-28 aa ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None,
407 6cdc5a3d 2023-05-28 aa CurrentTime) == GrabSuccess)
408 6cdc5a3d 2023-05-28 aa return;
409 6cdc5a3d 2023-05-28 aa nanosleep(&ts, NULL);
410 6cdc5a3d 2023-05-28 aa }
411 6cdc5a3d 2023-05-28 aa die(1, "couldn't grab pointer");
412 6cdc5a3d 2023-05-28 aa }
413 6cdc5a3d 2023-05-28 aa
414 15aae8ae 2023-05-28 aa /* grabkb -- try to grab keyboard for a second */
415 15aae8ae 2023-05-28 aa static void
416 15aae8ae 2023-05-28 aa grabkb(void)
417 15aae8ae 2023-05-28 aa {
418 15aae8ae 2023-05-28 aa struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
419 15aae8ae 2023-05-28 aa int i;
420 15aae8ae 2023-05-28 aa
421 15aae8ae 2023-05-28 aa for (i = 0; i < 1000; ++i) {
422 15aae8ae 2023-05-28 aa if (XGrabKeyboard(dpy, RootWindow(dpy, screen), True,
423 15aae8ae 2023-05-28 aa GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
424 15aae8ae 2023-05-28 aa return;
425 15aae8ae 2023-05-28 aa nanosleep(&ts, NULL);
426 15aae8ae 2023-05-28 aa }
427 15aae8ae 2023-05-28 aa die(1, "couldn't grab keyboard");
428 15aae8ae 2023-05-28 aa }
429 15aae8ae 2023-05-28 aa
430 6cdc5a3d 2023-05-28 aa /* setfocus -- try setting focus to the menu for a second */
431 6cdc5a3d 2023-05-28 aa static void
432 6cdc5a3d 2023-05-28 aa setfocus(void)
433 6cdc5a3d 2023-05-28 aa {
434 6cdc5a3d 2023-05-28 aa struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
435 6cdc5a3d 2023-05-28 aa Window focuswin;
436 6cdc5a3d 2023-05-28 aa int i, dummy;
437 6cdc5a3d 2023-05-28 aa
438 6cdc5a3d 2023-05-28 aa for (i = 0; i < 1000; ++i) {
439 6cdc5a3d 2023-05-28 aa XGetInputFocus(dpy, &focuswin, &dummy);
440 6cdc5a3d 2023-05-28 aa if (focuswin == win)
441 6cdc5a3d 2023-05-28 aa return;
442 6cdc5a3d 2023-05-28 aa XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
443 6cdc5a3d 2023-05-28 aa nanosleep(&ts, NULL);
444 6cdc5a3d 2023-05-28 aa }
445 6cdc5a3d 2023-05-28 aa die(1, "couldn't grab keyboard");
446 6cdc5a3d 2023-05-28 aa }
447 6cdc5a3d 2023-05-28 aa
448 77968eb5 2023-05-29 aa /* alloccol_xft -- safely allocate new Xft colour c from string s. */
449 b64495df 2023-05-29 aa static void
450 77968eb5 2023-05-29 aa alloccol_xft(char *s, XftColor *c)
451 77968eb5 2023-05-29 aa {
452 77968eb5 2023-05-29 aa if (!(XftColorAllocName(dpy, DefaultVisual(dpy, screen),
453 77968eb5 2023-05-29 aa DefaultColormap(dpy, screen), s, c)))
454 703f0cd0 2023-05-29 aa die(1, "couldn't allocate Xft colour %s", s);
455 77968eb5 2023-05-29 aa }
456 77968eb5 2023-05-29 aa
457 77968eb5 2023-05-29 aa /* alloccol -- safely allocate new colour c from string s. */
458 77968eb5 2023-05-29 aa static void
459 b64495df 2023-05-29 aa alloccol(char *s, XColor *c)
460 b64495df 2023-05-29 aa {
461 b64495df 2023-05-29 aa XColor dummy;
462 b64495df 2023-05-29 aa if (!(XAllocNamedColor(dpy, DefaultColormap(dpy, screen), s, c, &dummy)))
463 703f0cd0 2023-05-29 aa die(1, "couldn't allocate colour %s", s);
464 b64495df 2023-05-29 aa }
465 b64495df 2023-05-29 aa
466 15aae8ae 2023-05-28 aa /*
467 15aae8ae 2023-05-28 aa * setupx -- create and map a window for n items; assign values to the X
468 15aae8ae 2023-05-28 aa * globals.
469 15aae8ae 2023-05-28 aa */
470 15aae8ae 2023-05-28 aa static void
471 15aae8ae 2023-05-28 aa setupx(int n)
472 15aae8ae 2023-05-28 aa {
473 15aae8ae 2023-05-28 aa struct item *it;
474 b64495df 2023-05-29 aa XColor col;
475 15aae8ae 2023-05-28 aa XClassHint ch = {PROGNAME, PROGNAME};
476 15aae8ae 2023-05-28 aa XSetWindowAttributes swa = {
477 15aae8ae 2023-05-28 aa .override_redirect = True,
478 15aae8ae 2023-05-28 aa .save_under = True,
479 6cdc5a3d 2023-05-28 aa .event_mask = ExposureMask | StructureNotifyMask |
480 6cdc5a3d 2023-05-28 aa KeyPressMask | ButtonPressMask | ButtonReleaseMask |
481 6cdc5a3d 2023-05-28 aa PointerMotionMask | LeaveWindowMask | EnterWindowMask,
482 15aae8ae 2023-05-28 aa };
483 15aae8ae 2023-05-28 aa
484 77968eb5 2023-05-29 aa if (!(font = XftFontOpenName(dpy, screen, o_font)))
485 15aae8ae 2023-05-28 aa die(1, "couldn't load font");
486 77968eb5 2023-05-29 aa height = font->height + o_vp;
487 15aae8ae 2023-05-28 aa
488 15aae8ae 2023-05-28 aa it = first;
489 15aae8ae 2023-05-28 aa do {
490 77968eb5 2023-05-29 aa XGlyphInfo gi;
491 77968eb5 2023-05-29 aa XftTextExtentsUtf8(dpy, font, (FcChar8 *)it->s, it->len, &gi);
492 77968eb5 2023-05-29 aa if (gi.xOff + o_hp*2 > width)
493 77968eb5 2023-05-29 aa width = gi.xOff + o_hp*2;
494 15aae8ae 2023-05-28 aa it = it->next;
495 15aae8ae 2023-05-28 aa } while (it != first);
496 15aae8ae 2023-05-28 aa
497 f0265770 2023-05-28 aa if (o_x + width > DisplayWidth(dpy, screen))
498 f0265770 2023-05-28 aa o_x = DisplayWidth(dpy, screen) - width;
499 f0265770 2023-05-28 aa if (o_y + height*n > DisplayHeight(dpy, screen))
500 f0265770 2023-05-28 aa o_y = DisplayHeight(dpy, screen) - height*n;
501 f0265770 2023-05-28 aa
502 b64495df 2023-05-29 aa alloccol(o_bg, &col);
503 2d5f9ee6 2023-05-29 aa pixels[PIXEL_BG] = swa.background_pixel = col.pixel;
504 2d5f9ee6 2023-05-29 aa alloccol(o_bc, &col);
505 2d5f9ee6 2023-05-29 aa pixels[PIXEL_BC] = swa.border_pixel = col.pixel;
506 f1adc4ca 2023-05-28 aa
507 15aae8ae 2023-05-28 aa win = XCreateWindow(dpy, RootWindow(dpy, screen), o_x, o_y,
508 15aae8ae 2023-05-28 aa width, n*height, o_bw, CopyFromParent, CopyFromParent,
509 f1adc4ca 2023-05-28 aa CopyFromParent, CWOverrideRedirect | CWBackPixel | CWBorderPixel |
510 f1adc4ca 2023-05-28 aa CWEventMask | CWSaveUnder, &swa);
511 15aae8ae 2023-05-28 aa XSetClassHint(dpy, win, &ch);
512 15aae8ae 2023-05-28 aa
513 77968eb5 2023-05-29 aa alloccol_xft(o_fg, &c_fg);
514 77968eb5 2023-05-29 aa alloccol_xft(o_sfg, &c_sfg);
515 77968eb5 2023-05-29 aa alloccol_xft(o_sbg, &c_sbg);
516 15aae8ae 2023-05-28 aa
517 15aae8ae 2023-05-28 aa grabkb();
518 6cdc5a3d 2023-05-28 aa grabptr();
519 15aae8ae 2023-05-28 aa
520 15aae8ae 2023-05-28 aa XMapRaised(dpy, win);
521 6cdc5a3d 2023-05-28 aa
522 6cdc5a3d 2023-05-28 aa setfocus();
523 15aae8ae 2023-05-28 aa }
524 15aae8ae 2023-05-28 aa
525 15aae8ae 2023-05-28 aa /*
526 15aae8ae 2023-05-28 aa * Create a new struct item, and insert it a after the it item. The rest of the
527 15aae8ae 2023-05-28 aa * arguments are values that the new item receives. On success return pointer
528 15aae8ae 2023-05-28 aa * to the new item. Return NULL otherwise.
529 15aae8ae 2023-05-28 aa */
530 15aae8ae 2023-05-28 aa static struct item *
531 843ffc79 2023-05-28 aa insitem(struct item *it, char *s) {
532 cb28fcb8 2023-05-26 aa struct item *new;
533 843ffc79 2023-05-28 aa char *p, *end;
534 843ffc79 2023-05-28 aa
535 cb28fcb8 2023-05-26 aa if (!(new = calloc(1, sizeof *new)))
536 cb28fcb8 2023-05-26 aa return NULL;
537 cb28fcb8 2023-05-26 aa if (it) {
538 cb28fcb8 2023-05-26 aa new->prev = it;
539 cb28fcb8 2023-05-26 aa new->next = it->next;
540 cb28fcb8 2023-05-26 aa it->next->prev = new;
541 cb28fcb8 2023-05-26 aa it->next = new;
542 cb28fcb8 2023-05-26 aa } else
543 cb28fcb8 2023-05-26 aa new->prev = new->next = new;
544 843ffc79 2023-05-28 aa new->nks = 0;
545 15aae8ae 2023-05-28 aa new->dirty = true;
546 843ffc79 2023-05-28 aa
547 843ffc79 2023-05-28 aa for (p = s; ; p = end) {
548 843ffc79 2023-05-28 aa size_t n;
549 843ffc79 2023-05-28 aa char c;
550 843ffc79 2023-05-28 aa KeySym ks;
551 843ffc79 2023-05-28 aa
552 843ffc79 2023-05-28 aa n = strspn(p, " ");
553 843ffc79 2023-05-28 aa p = p + n;
554 843ffc79 2023-05-28 aa if (!(n = strcspn(p, " \t"))) {
555 843ffc79 2023-05-28 aa p += strspn(p, " \t");
556 843ffc79 2023-05-28 aa break;
557 843ffc79 2023-05-28 aa }
558 843ffc79 2023-05-28 aa
559 843ffc79 2023-05-28 aa end = p + n;
560 843ffc79 2023-05-28 aa c = *end;
561 843ffc79 2023-05-28 aa *end = '\0';
562 843ffc79 2023-05-28 aa
563 843ffc79 2023-05-28 aa if ((ks = XStringToKeysym(p)) == NoSymbol)
564 703f0cd0 2023-05-29 aa warn("no such keysym: %s", p);
565 843ffc79 2023-05-28 aa else if (new->nks >= MAXKS)
566 703f0cd0 2023-05-29 aa warn("too many keysyms (%s)", p);
567 843ffc79 2023-05-28 aa else {
568 843ffc79 2023-05-28 aa KeySym k, dummy;
569 843ffc79 2023-05-28 aa XConvertCase(ks, &k, &dummy);
570 843ffc79 2023-05-28 aa new->ks[new->nks++] = k;
571 843ffc79 2023-05-28 aa }
572 843ffc79 2023-05-28 aa
573 843ffc79 2023-05-28 aa *end = c;
574 843ffc79 2023-05-28 aa }
575 843ffc79 2023-05-28 aa
576 843ffc79 2023-05-28 aa new->len = strlen(p);
577 843ffc79 2023-05-28 aa new->s = strdup(p);
578 843ffc79 2023-05-28 aa
579 cb28fcb8 2023-05-26 aa return new;
580 cb28fcb8 2023-05-26 aa }
581 cb28fcb8 2023-05-26 aa
582 15aae8ae 2023-05-28 aa /*
583 15aae8ae 2023-05-28 aa * mkitems -- create a list of items from stdin, and return pointer to the
584 15aae8ae 2023-05-28 aa * new list's first element. If np is not NULL, set its value to the number of
585 15aae8ae 2023-05-28 aa * elements in the list. Return NULL on error.
586 15aae8ae 2023-05-28 aa */
587 15aae8ae 2023-05-28 aa static struct item *
588 15aae8ae 2023-05-28 aa mkitems(int *np)
589 cb28fcb8 2023-05-26 aa {
590 15aae8ae 2023-05-28 aa struct item *last = NULL;
591 15aae8ae 2023-05-28 aa size_t n = 0;
592 15aae8ae 2023-05-28 aa char *line = NULL;
593 15aae8ae 2023-05-28 aa size_t linesize = 0;
594 15aae8ae 2023-05-28 aa ssize_t linelen;
595 cb28fcb8 2023-05-26 aa
596 15aae8ae 2023-05-28 aa while ((linelen = getline(&line, &linesize, stdin)) != -1) {
597 15aae8ae 2023-05-28 aa struct item *it;
598 f0265770 2023-05-28 aa if (line[linelen-1] == '\n')
599 f0265770 2023-05-28 aa line[--linelen] = '\0';
600 843ffc79 2023-05-28 aa if (!(it = insitem(last, line)))
601 15aae8ae 2023-05-28 aa die(1, "couldn't insert new item");
602 15aae8ae 2023-05-28 aa n++;
603 15aae8ae 2023-05-28 aa last = it;
604 15aae8ae 2023-05-28 aa }
605 15aae8ae 2023-05-28 aa free(line);
606 cb28fcb8 2023-05-26 aa
607 15aae8ae 2023-05-28 aa if (np)
608 15aae8ae 2023-05-28 aa *np = n;
609 cb28fcb8 2023-05-26 aa
610 15aae8ae 2023-05-28 aa return last ? last->next : NULL;
611 cb28fcb8 2023-05-26 aa }
612 cb28fcb8 2023-05-26 aa
613 15aae8ae 2023-05-28 aa /*
614 15aae8ae 2023-05-28 aa * {s,i}default -- return the {char *,int} value of the X default, or def
615 15aae8ae 2023-05-28 aa * otherwise.
616 15aae8ae 2023-05-28 aa */
617 15aae8ae 2023-05-28 aa static char *
618 f1adc4ca 2023-05-28 aa sdefault(const char *opt, const char *def)
619 7c7bbaee 2023-05-27 aa {
620 7c7bbaee 2023-05-27 aa char *val = XGetDefault(dpy, PROGNAME, opt);
621 f1adc4ca 2023-05-28 aa return val ? val : (char *)def;
622 7c7bbaee 2023-05-27 aa }
623 7c7bbaee 2023-05-27 aa
624 15aae8ae 2023-05-28 aa static int
625 f1adc4ca 2023-05-28 aa idefault(const char *opt, int def)
626 7c7bbaee 2023-05-27 aa {
627 7c7bbaee 2023-05-27 aa char *val = XGetDefault(dpy, PROGNAME, opt);
628 7c7bbaee 2023-05-27 aa return val ? atoi(val) : def;
629 7c7bbaee 2023-05-27 aa }
630 7c7bbaee 2023-05-27 aa
631 15aae8ae 2023-05-28 aa /* nextarg -- safely skip the current command-line option */
632 15aae8ae 2023-05-28 aa static void
633 15aae8ae 2023-05-28 aa nextarg(int *argcp, char **argvp[])
634 15aae8ae 2023-05-28 aa {
635 15aae8ae 2023-05-28 aa if (--*argcp <= 0)
636 15aae8ae 2023-05-28 aa usage();
637 15aae8ae 2023-05-28 aa ++*argvp;
638 15aae8ae 2023-05-28 aa }
639 15aae8ae 2023-05-28 aa
640 15aae8ae 2023-05-28 aa /*
641 15aae8ae 2023-05-28 aa * {s,i}arg -- return the {char *,int} argument of the current command-line
642 15aae8ae 2023-05-28 aa * option.
643 15aae8ae 2023-05-28 aa */
644 15aae8ae 2023-05-28 aa static char *
645 7c7bbaee 2023-05-27 aa sarg(int *argcp, char **argvp[])
646 7c7bbaee 2023-05-27 aa {
647 15aae8ae 2023-05-28 aa nextarg(argcp, argvp);
648 7c7bbaee 2023-05-27 aa return **argvp;
649 7c7bbaee 2023-05-27 aa }
650 7c7bbaee 2023-05-27 aa
651 15aae8ae 2023-05-28 aa static int
652 7c7bbaee 2023-05-27 aa iarg(int *argcp, char **argvp[])
653 7c7bbaee 2023-05-27 aa {
654 15aae8ae 2023-05-28 aa nextarg(argcp, argvp);
655 7c7bbaee 2023-05-27 aa return atoi(**argvp);
656 7c7bbaee 2023-05-27 aa }
657 7c7bbaee 2023-05-27 aa
658 15aae8ae 2023-05-28 aa /*
659 15aae8ae 2023-05-28 aa * xitems -- pop-up menu for X, constructed from stdin, and printing user choice
660 15aae8ae 2023-05-28 aa * to stdout.
661 15aae8ae 2023-05-28 aa */
662 7c7bbaee 2023-05-27 aa int
663 cb28fcb8 2023-05-26 aa main(int argc, char *argv[])
664 cb28fcb8 2023-05-26 aa {
665 15aae8ae 2023-05-28 aa int n = 0;
666 cb28fcb8 2023-05-26 aa
667 7c7bbaee 2023-05-27 aa for (--argc, ++argv; argc > 0; --argc, ++argv)
668 7c7bbaee 2023-05-27 aa if (argv[0][0] == '-')
669 7c7bbaee 2023-05-27 aa switch (argv[0][1]) {
670 7c7bbaee 2023-05-27 aa case 'b':
671 7c7bbaee 2023-05-27 aa switch (argv[0][2]) {
672 f1adc4ca 2023-05-28 aa case 'c': /* -bc */
673 f1adc4ca 2023-05-28 aa o_bc = sarg(&argc, &argv);
674 f1adc4ca 2023-05-28 aa break;
675 7c7bbaee 2023-05-27 aa case 'g': /* -bg */
676 15aae8ae 2023-05-28 aa o_bg = sarg(&argc, &argv);
677 7c7bbaee 2023-05-27 aa break;
678 7c7bbaee 2023-05-27 aa case 'w': /* -bw */
679 15aae8ae 2023-05-28 aa o_bw = iarg(&argc, &argv);
680 7c7bbaee 2023-05-27 aa break;
681 7c7bbaee 2023-05-27 aa default:
682 7c7bbaee 2023-05-27 aa usage();
683 7c7bbaee 2023-05-27 aa /* NOTREACHED */
684 7c7bbaee 2023-05-27 aa }
685 7c7bbaee 2023-05-27 aa break;
686 7c7bbaee 2023-05-27 aa case 'f':
687 7c7bbaee 2023-05-27 aa switch (argv[0][2]) {
688 7c7bbaee 2023-05-27 aa case 'g': /* -fg */
689 15aae8ae 2023-05-28 aa o_fg = sarg(&argc, &argv);
690 7c7bbaee 2023-05-27 aa break;
691 7c7bbaee 2023-05-27 aa case 'o': /* -font */
692 15aae8ae 2023-05-28 aa o_font = sarg(&argc, &argv);
693 7c7bbaee 2023-05-27 aa break;
694 7c7bbaee 2023-05-27 aa default:
695 7c7bbaee 2023-05-27 aa usage();
696 7c7bbaee 2023-05-27 aa /* NOTREACHED */
697 7c7bbaee 2023-05-27 aa }
698 7c7bbaee 2023-05-27 aa break;
699 15aae8ae 2023-05-28 aa case 'h': /* -hp */
700 15aae8ae 2023-05-28 aa o_hp = iarg(&argc, &argv);
701 15aae8ae 2023-05-28 aa break;
702 7c7bbaee 2023-05-27 aa case 's':
703 7c7bbaee 2023-05-27 aa switch (argv[0][2]) {
704 7c7bbaee 2023-05-27 aa case 'b': /* -sbg */
705 15aae8ae 2023-05-28 aa o_sbg = sarg(&argc, &argv);
706 7c7bbaee 2023-05-27 aa break;
707 7c7bbaee 2023-05-27 aa case 'f': /* -sfg */
708 15aae8ae 2023-05-28 aa o_sfg = sarg(&argc, &argv);
709 7c7bbaee 2023-05-27 aa break;
710 7c7bbaee 2023-05-27 aa default:
711 7c7bbaee 2023-05-27 aa usage();
712 7c7bbaee 2023-05-27 aa /* NOTREACHED */
713 7c7bbaee 2023-05-27 aa }
714 7c7bbaee 2023-05-27 aa break;
715 15aae8ae 2023-05-28 aa case 'v': /* -vp */
716 15aae8ae 2023-05-28 aa o_vp = iarg(&argc, &argv);
717 15aae8ae 2023-05-28 aa break;
718 7c7bbaee 2023-05-27 aa case 'x': /* -x */
719 15aae8ae 2023-05-28 aa o_x = iarg(&argc, &argv);
720 7c7bbaee 2023-05-27 aa break;
721 7c7bbaee 2023-05-27 aa case 'y': /* -y */
722 15aae8ae 2023-05-28 aa o_y = iarg(&argc, &argv);
723 7c7bbaee 2023-05-27 aa break;
724 7c7bbaee 2023-05-27 aa default:
725 7c7bbaee 2023-05-27 aa usage();
726 7c7bbaee 2023-05-27 aa /* NOTREACHED */
727 7c7bbaee 2023-05-27 aa }
728 7c7bbaee 2023-05-27 aa
729 7c7bbaee 2023-05-27 aa if (!(dpy = XOpenDisplay(NULL)))
730 15aae8ae 2023-05-28 aa die(1, "couldn't open display");
731 840c16f6 2023-05-30 aa
732 840c16f6 2023-05-30 aa #ifdef __OpenBSD__
733 840c16f6 2023-05-30 aa /* Xlib needs rpath at runtime. */
734 840c16f6 2023-05-30 aa if (pledge("stdio rpath", NULL) == -1)
735 840c16f6 2023-05-30 aa edie(1, "pledge");
736 840c16f6 2023-05-30 aa #endif
737 840c16f6 2023-05-30 aa
738 7c7bbaee 2023-05-27 aa screen = DefaultScreen(dpy);
739 7c7bbaee 2023-05-27 aa
740 15aae8ae 2023-05-28 aa if (!o_bg)
741 15aae8ae 2023-05-28 aa o_bg = sdefault("background", "white");
742 15aae8ae 2023-05-28 aa if (!o_fg)
743 15aae8ae 2023-05-28 aa o_fg = sdefault("foreground", "black");
744 15aae8ae 2023-05-28 aa if (!o_font)
745 77968eb5 2023-05-29 aa o_font = sdefault("font", "DejaVu Sans Mono-10");
746 15aae8ae 2023-05-28 aa if (!o_sbg)
747 15aae8ae 2023-05-28 aa o_sbg = sdefault("selectedBackground", "black");
748 15aae8ae 2023-05-28 aa if (!o_sfg)
749 15aae8ae 2023-05-28 aa o_sfg = sdefault("selectedForeground", "white");
750 f1adc4ca 2023-05-28 aa if (!o_bc)
751 f1adc4ca 2023-05-28 aa o_bc = sdefault("borderColour", "black");
752 15aae8ae 2023-05-28 aa if (o_bw == -1)
753 15aae8ae 2023-05-28 aa o_bw = idefault("borderWidth", 1);
754 15aae8ae 2023-05-28 aa if (o_hp == -1)
755 15aae8ae 2023-05-28 aa o_hp = idefault("horizontalPadding", 2);
756 15aae8ae 2023-05-28 aa if (o_vp == -1)
757 15aae8ae 2023-05-28 aa o_vp = idefault("verticalPadding", 1);
758 7c7bbaee 2023-05-27 aa
759 15aae8ae 2023-05-28 aa if (o_x == -1 || o_y == -1) {
760 7c7bbaee 2023-05-27 aa Window w;
761 7c7bbaee 2023-05-27 aa int i;
762 7c7bbaee 2023-05-27 aa unsigned int ui;
763 7c7bbaee 2023-05-27 aa int *xp, *yp;
764 7c7bbaee 2023-05-27 aa
765 15aae8ae 2023-05-28 aa xp = (o_x == -1) ? &o_x : &i;
766 15aae8ae 2023-05-28 aa yp = (o_y == -1) ? &o_y : &i;
767 7c7bbaee 2023-05-27 aa
768 7c7bbaee 2023-05-27 aa XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, xp, yp, &i,
769 7c7bbaee 2023-05-27 aa &i, &ui);
770 7c7bbaee 2023-05-27 aa }
771 7c7bbaee 2023-05-27 aa
772 15aae8ae 2023-05-28 aa if (!(first = selected = mkitems(&n))) {
773 15aae8ae 2023-05-28 aa if (n)
774 15aae8ae 2023-05-28 aa die(1, "coulnd't create items list");
775 15aae8ae 2023-05-28 aa else
776 15aae8ae 2023-05-28 aa exit(0);
777 cb28fcb8 2023-05-26 aa }
778 15aae8ae 2023-05-28 aa setupx(n);
779 cb28fcb8 2023-05-26 aa
780 15aae8ae 2023-05-28 aa for (;;)
781 15aae8ae 2023-05-28 aa proc();
782 cb28fcb8 2023-05-26 aa /* NOTREACHED */
783 cb28fcb8 2023-05-26 aa }