Introduction
Introduction Statistics Contact Development Disclaimer Help
dmenu.c - dmenu - dynamic menu
git clone git://git.suckless.org/dmenu
Log
Files
Refs
README
LICENSE
---
dmenu.c (19477B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <ctype.h>
3 #include <locale.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <strings.h>
8 #include <time.h>
9 #include <unistd.h>
10
11 #include <X11/Xlib.h>
12 #include <X11/Xatom.h>
13 #include <X11/Xutil.h>
14 #ifdef XINERAMA
15 #include <X11/extensions/Xinerama.h>
16 #endif
17 #include <X11/Xft/Xft.h>
18
19 #include "drw.h"
20 #include "util.h"
21
22 /* macros */
23 #define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) …
24 * MAX(0, MIN((y)+(h),(r).y_org+(r).height) …
25 #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
26
27 /* enums */
28 enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes …
29
30 struct item {
31 char *text;
32 struct item *left, *right;
33 int out;
34 };
35
36 static char text[BUFSIZ] = "";
37 static char *embed;
38 static int bh, mw, mh;
39 static int inputw = 0, promptw;
40 static int lrpad; /* sum of left and right padding */
41 static size_t cursor;
42 static struct item *items = NULL;
43 static struct item *matches, *matchend;
44 static struct item *prev, *curr, *next, *sel;
45 static int mon = -1, screen;
46
47 static Atom clip, utf8;
48 static Display *dpy;
49 static Window root, parentwin, win;
50 static XIC xic;
51
52 static Drw *drw;
53 static Clr *scheme[SchemeLast];
54
55 #include "config.h"
56
57 static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
58 static char *(*fstrstr)(const char *, const char *) = strstr;
59
60 static unsigned int
61 textw_clamp(const char *str, unsigned int n)
62 {
63 unsigned int w = drw_fontset_getwidth_clamp(drw, str, n) + lrpad;
64 return MIN(w, n);
65 }
66
67 static void
68 appenditem(struct item *item, struct item **list, struct item **last)
69 {
70 if (*last)
71 (*last)->right = item;
72 else
73 *list = item;
74
75 item->left = *last;
76 item->right = NULL;
77 *last = item;
78 }
79
80 static void
81 calcoffsets(void)
82 {
83 int i, n;
84
85 if (lines > 0)
86 n = lines * bh;
87 else
88 n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
89 /* calculate which items will begin the next page and previous p…
90 for (i = 0, next = curr; next; next = next->right)
91 if ((i += (lines > 0) ? bh : textw_clamp(next->text, n))…
92 break;
93 for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
94 if ((i += (lines > 0) ? bh : textw_clamp(prev->left->tex…
95 break;
96 }
97
98 static void
99 cleanup(void)
100 {
101 size_t i;
102
103 XUngrabKeyboard(dpy, CurrentTime);
104 for (i = 0; i < SchemeLast; i++)
105 free(scheme[i]);
106 for (i = 0; items && items[i].text; ++i)
107 free(items[i].text);
108 free(items);
109 drw_free(drw);
110 XSync(dpy, False);
111 XCloseDisplay(dpy);
112 }
113
114 static char *
115 cistrstr(const char *h, const char *n)
116 {
117 size_t i;
118
119 if (!n[0])
120 return (char *)h;
121
122 for (; *h; ++h) {
123 for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
124 tolower((unsigned char)h[i]); ++i)
125 ;
126 if (n[i] == '\0')
127 return (char *)h;
128 }
129 return NULL;
130 }
131
132 static int
133 drawitem(struct item *item, int x, int y, int w)
134 {
135 if (item == sel)
136 drw_setscheme(drw, scheme[SchemeSel]);
137 else if (item->out)
138 drw_setscheme(drw, scheme[SchemeOut]);
139 else
140 drw_setscheme(drw, scheme[SchemeNorm]);
141
142 return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
143 }
144
145 static void
146 drawmenu(void)
147 {
148 unsigned int curpos;
149 struct item *item;
150 int x = 0, y = 0, w;
151
152 drw_setscheme(drw, scheme[SchemeNorm]);
153 drw_rect(drw, 0, 0, mw, mh, 1, 1);
154
155 if (prompt && *prompt) {
156 drw_setscheme(drw, scheme[SchemeSel]);
157 x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, …
158 }
159 /* draw input field */
160 w = (lines > 0 || !matches) ? mw - x : inputw;
161 drw_setscheme(drw, scheme[SchemeNorm]);
162 drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
163
164 curpos = TEXTW(text) - TEXTW(&text[cursor]);
165 if ((curpos += lrpad / 2 - 1) < w) {
166 drw_setscheme(drw, scheme[SchemeNorm]);
167 drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
168 }
169
170 if (lines > 0) {
171 /* draw vertical list */
172 for (item = curr; item != next; item = item->right)
173 drawitem(item, x, y += bh, mw - x);
174 } else if (matches) {
175 /* draw horizontal list */
176 x += inputw;
177 w = TEXTW("<");
178 if (curr->left) {
179 drw_setscheme(drw, scheme[SchemeNorm]);
180 drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0);
181 }
182 x += w;
183 for (item = curr; item != next; item = item->right)
184 x = drawitem(item, x, 0, textw_clamp(item->text,…
185 if (next) {
186 w = TEXTW(">");
187 drw_setscheme(drw, scheme[SchemeNorm]);
188 drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", …
189 }
190 }
191 drw_map(drw, win, 0, 0, mw, mh);
192 }
193
194 static void
195 grabfocus(void)
196 {
197 struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
198 Window focuswin;
199 int i, revertwin;
200
201 for (i = 0; i < 100; ++i) {
202 XGetInputFocus(dpy, &focuswin, &revertwin);
203 if (focuswin == win)
204 return;
205 XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
206 nanosleep(&ts, NULL);
207 }
208 die("cannot grab focus");
209 }
210
211 static void
212 grabkeyboard(void)
213 {
214 struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
215 int i;
216
217 if (embed)
218 return;
219 /* try to grab keyboard, we may have to wait for another process…
220 for (i = 0; i < 1000; i++) {
221 if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, Gra…
222 GrabModeAsync, CurrentTime) == GrabSuc…
223 return;
224 nanosleep(&ts, NULL);
225 }
226 die("cannot grab keyboard");
227 }
228
229 static void
230 match(void)
231 {
232 static char **tokv = NULL;
233 static int tokn = 0;
234
235 char buf[sizeof text], *s;
236 int i, tokc = 0;
237 size_t len, textsize;
238 struct item *item, *lprefix, *lsubstr, *prefixend, *substrend;
239
240 strcpy(buf, text);
241 /* separate input text into tokens to be matched individually */
242 for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NUL…
243 if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * siz…
244 die("cannot realloc %zu bytes:", tokn * sizeof *…
245 len = tokc ? strlen(tokv[0]) : 0;
246
247 matches = lprefix = lsubstr = matchend = prefixend = substrend =…
248 textsize = strlen(text) + 1;
249 for (item = items; item && item->text; item++) {
250 for (i = 0; i < tokc; i++)
251 if (!fstrstr(item->text, tokv[i]))
252 break;
253 if (i != tokc) /* not all tokens match */
254 continue;
255 /* exact matches go first, then prefixes, then substring…
256 if (!tokc || !fstrncmp(text, item->text, textsize))
257 appenditem(item, &matches, &matchend);
258 else if (!fstrncmp(tokv[0], item->text, len))
259 appenditem(item, &lprefix, &prefixend);
260 else
261 appenditem(item, &lsubstr, &substrend);
262 }
263 if (lprefix) {
264 if (matches) {
265 matchend->right = lprefix;
266 lprefix->left = matchend;
267 } else
268 matches = lprefix;
269 matchend = prefixend;
270 }
271 if (lsubstr) {
272 if (matches) {
273 matchend->right = lsubstr;
274 lsubstr->left = matchend;
275 } else
276 matches = lsubstr;
277 matchend = substrend;
278 }
279 curr = sel = matches;
280 calcoffsets();
281 }
282
283 static void
284 insert(const char *str, ssize_t n)
285 {
286 if (strlen(text) + n > sizeof text - 1)
287 return;
288 /* move existing text out of the way, insert new text, and updat…
289 memmove(&text[cursor + n], &text[cursor], sizeof text - cursor -…
290 if (n > 0)
291 memcpy(&text[cursor], str, n);
292 cursor += n;
293 match();
294 }
295
296 static size_t
297 nextrune(int inc)
298 {
299 ssize_t n;
300
301 /* return location of next utf8 rune in the given direction (+1 …
302 for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80;…
303 ;
304 return n;
305 }
306
307 static void
308 movewordedge(int dir)
309 {
310 if (dir < 0) { /* move cursor to the start of the word*/
311 while (cursor > 0 && strchr(worddelimiters, text[nextrun…
312 cursor = nextrune(-1);
313 while (cursor > 0 && !strchr(worddelimiters, text[nextru…
314 cursor = nextrune(-1);
315 } else { /* move cursor to the end of the word */
316 while (text[cursor] && strchr(worddelimiters, text[curso…
317 cursor = nextrune(+1);
318 while (text[cursor] && !strchr(worddelimiters, text[curs…
319 cursor = nextrune(+1);
320 }
321 }
322
323 static void
324 keypress(XKeyEvent *ev)
325 {
326 char buf[64];
327 int len;
328 KeySym ksym = NoSymbol;
329 Status status;
330
331 len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
332 switch (status) {
333 default: /* XLookupNone, XBufferOverflow */
334 return;
335 case XLookupChars: /* composed string from input method */
336 goto insert;
337 case XLookupKeySym:
338 case XLookupBoth: /* a KeySym and a string are returned: use key…
339 break;
340 }
341
342 if (ev->state & ControlMask) {
343 switch(ksym) {
344 case XK_a: ksym = XK_Home; break;
345 case XK_b: ksym = XK_Left; break;
346 case XK_c: ksym = XK_Escape; break;
347 case XK_d: ksym = XK_Delete; break;
348 case XK_e: ksym = XK_End; break;
349 case XK_f: ksym = XK_Right; break;
350 case XK_g: ksym = XK_Escape; break;
351 case XK_h: ksym = XK_BackSpace; break;
352 case XK_i: ksym = XK_Tab; break;
353 case XK_j: /* fallthrough */
354 case XK_J: /* fallthrough */
355 case XK_m: /* fallthrough */
356 case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; …
357 case XK_n: ksym = XK_Down; break;
358 case XK_p: ksym = XK_Up; break;
359
360 case XK_k: /* delete right */
361 text[cursor] = '\0';
362 match();
363 break;
364 case XK_u: /* delete left */
365 insert(NULL, 0 - cursor);
366 break;
367 case XK_w: /* delete word */
368 while (cursor > 0 && strchr(worddelimiters, text…
369 insert(NULL, nextrune(-1) - cursor);
370 while (cursor > 0 && !strchr(worddelimiters, tex…
371 insert(NULL, nextrune(-1) - cursor);
372 break;
373 case XK_y: /* paste selection */
374 case XK_Y:
375 XConvertSelection(dpy, (ev->state & ShiftMask) ?…
376 utf8, utf8, win, CurrentTime);
377 return;
378 case XK_Left:
379 case XK_KP_Left:
380 movewordedge(-1);
381 goto draw;
382 case XK_Right:
383 case XK_KP_Right:
384 movewordedge(+1);
385 goto draw;
386 case XK_Return:
387 case XK_KP_Enter:
388 break;
389 case XK_bracketleft:
390 cleanup();
391 exit(1);
392 default:
393 return;
394 }
395 } else if (ev->state & Mod1Mask) {
396 switch(ksym) {
397 case XK_b:
398 movewordedge(-1);
399 goto draw;
400 case XK_f:
401 movewordedge(+1);
402 goto draw;
403 case XK_g: ksym = XK_Home; break;
404 case XK_G: ksym = XK_End; break;
405 case XK_h: ksym = XK_Up; break;
406 case XK_j: ksym = XK_Next; break;
407 case XK_k: ksym = XK_Prior; break;
408 case XK_l: ksym = XK_Down; break;
409 default:
410 return;
411 }
412 }
413
414 switch(ksym) {
415 default:
416 insert:
417 if (!iscntrl((unsigned char)*buf))
418 insert(buf, len);
419 break;
420 case XK_Delete:
421 case XK_KP_Delete:
422 if (text[cursor] == '\0')
423 return;
424 cursor = nextrune(+1);
425 /* fallthrough */
426 case XK_BackSpace:
427 if (cursor == 0)
428 return;
429 insert(NULL, nextrune(-1) - cursor);
430 break;
431 case XK_End:
432 case XK_KP_End:
433 if (text[cursor] != '\0') {
434 cursor = strlen(text);
435 break;
436 }
437 if (next) {
438 /* jump to end of list and position items in rev…
439 curr = matchend;
440 calcoffsets();
441 curr = prev;
442 calcoffsets();
443 while (next && (curr = curr->right))
444 calcoffsets();
445 }
446 sel = matchend;
447 break;
448 case XK_Escape:
449 cleanup();
450 exit(1);
451 case XK_Home:
452 case XK_KP_Home:
453 if (sel == matches) {
454 cursor = 0;
455 break;
456 }
457 sel = curr = matches;
458 calcoffsets();
459 break;
460 case XK_Left:
461 case XK_KP_Left:
462 if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
463 cursor = nextrune(-1);
464 break;
465 }
466 if (lines > 0)
467 return;
468 /* fallthrough */
469 case XK_Up:
470 case XK_KP_Up:
471 if (sel && sel->left && (sel = sel->left)->right == curr…
472 curr = prev;
473 calcoffsets();
474 }
475 break;
476 case XK_Next:
477 case XK_KP_Next:
478 if (!next)
479 return;
480 sel = curr = next;
481 calcoffsets();
482 break;
483 case XK_Prior:
484 case XK_KP_Prior:
485 if (!prev)
486 return;
487 sel = curr = prev;
488 calcoffsets();
489 break;
490 case XK_Return:
491 case XK_KP_Enter:
492 puts((sel && !(ev->state & ShiftMask)) ? sel->text : tex…
493 if (!(ev->state & ControlMask)) {
494 cleanup();
495 exit(0);
496 }
497 if (sel)
498 sel->out = 1;
499 break;
500 case XK_Right:
501 case XK_KP_Right:
502 if (text[cursor] != '\0') {
503 cursor = nextrune(+1);
504 break;
505 }
506 if (lines > 0)
507 return;
508 /* fallthrough */
509 case XK_Down:
510 case XK_KP_Down:
511 if (sel && sel->right && (sel = sel->right) == next) {
512 curr = next;
513 calcoffsets();
514 }
515 break;
516 case XK_Tab:
517 if (!sel)
518 return;
519 cursor = strnlen(sel->text, sizeof text - 1);
520 memcpy(text, sel->text, cursor);
521 text[cursor] = '\0';
522 match();
523 break;
524 }
525
526 draw:
527 drawmenu();
528 }
529
530 static void
531 paste(void)
532 {
533 char *p, *q;
534 int di;
535 unsigned long dl;
536 Atom da;
537
538 /* we have been given the current selection, now insert it into …
539 if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1,…
540 utf8, &da, &di, &dl, &dl, (unsigned char **)&…
541 == Success && p) {
542 insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strle…
543 XFree(p);
544 }
545 drawmenu();
546 }
547
548 static void
549 readstdin(void)
550 {
551 char *line = NULL;
552 size_t i, itemsiz = 0, linesiz = 0;
553 ssize_t len;
554
555 /* read each line from stdin and add it to the item list */
556 for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) {
557 if (i + 1 >= itemsiz) {
558 itemsiz += 256;
559 if (!(items = realloc(items, itemsiz * sizeof(*i…
560 die("cannot realloc %zu bytes:", itemsiz…
561 }
562 if (line[len - 1] == '\n')
563 line[len - 1] = '\0';
564 if (!(items[i].text = strdup(line)))
565 die("strdup:");
566
567 items[i].out = 0;
568 }
569 free(line);
570 if (items)
571 items[i].text = NULL;
572 lines = MIN(lines, i);
573 }
574
575 static void
576 run(void)
577 {
578 XEvent ev;
579
580 while (!XNextEvent(dpy, &ev)) {
581 if (XFilterEvent(&ev, win))
582 continue;
583 switch(ev.type) {
584 case DestroyNotify:
585 if (ev.xdestroywindow.window != win)
586 break;
587 cleanup();
588 exit(1);
589 case Expose:
590 if (ev.xexpose.count == 0)
591 drw_map(drw, win, 0, 0, mw, mh);
592 break;
593 case FocusIn:
594 /* regrab focus from parent window */
595 if (ev.xfocus.window != win)
596 grabfocus();
597 break;
598 case KeyPress:
599 keypress(&ev.xkey);
600 break;
601 case SelectionNotify:
602 if (ev.xselection.property == utf8)
603 paste();
604 break;
605 case VisibilityNotify:
606 if (ev.xvisibility.state != VisibilityUnobscured)
607 XRaiseWindow(dpy, win);
608 break;
609 }
610 }
611 }
612
613 static void
614 setup(void)
615 {
616 int x, y, i, j;
617 unsigned int du;
618 XSetWindowAttributes swa;
619 XIM xim;
620 Window w, dw, *dws;
621 XWindowAttributes wa;
622 XClassHint ch = {"dmenu", "dmenu"};
623 #ifdef XINERAMA
624 XineramaScreenInfo *info;
625 Window pw;
626 int a, di, n, area = 0;
627 #endif
628 /* init appearance */
629 for (j = 0; j < SchemeLast; j++)
630 scheme[j] = drw_scm_create(drw, colors[j], 2);
631
632 clip = XInternAtom(dpy, "CLIPBOARD", False);
633 utf8 = XInternAtom(dpy, "UTF8_STRING", False);
634
635 /* calculate menu geometry */
636 bh = drw->fonts->h + 2;
637 lines = MAX(lines, 0);
638 mh = (lines + 1) * bh;
639 #ifdef XINERAMA
640 i = 0;
641 if (parentwin == root && (info = XineramaQueryScreens(dpy, &n)))…
642 XGetInputFocus(dpy, &w, &di);
643 if (mon >= 0 && mon < n)
644 i = mon;
645 else if (w != root && w != PointerRoot && w != None) {
646 /* find top-level window containing current inpu…
647 do {
648 if (XQueryTree(dpy, (pw = w), &dw, &w, &…
649 XFree(dws);
650 } while (w != root && w != pw);
651 /* find xinerama screen with which the window in…
652 if (XGetWindowAttributes(dpy, pw, &wa))
653 for (j = 0; j < n; j++)
654 if ((a = INTERSECT(wa.x, wa.y, w…
655 area = a;
656 i = j;
657 }
658 }
659 /* no focused window is on screen, so use pointer locati…
660 if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &d…
661 for (i = 0; i < n; i++)
662 if (INTERSECT(x, y, 1, 1, info[i]) != 0)
663 break;
664
665 x = info[i].x_org;
666 y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
667 mw = info[i].width;
668 XFree(info);
669 } else
670 #endif
671 {
672 if (!XGetWindowAttributes(dpy, parentwin, &wa))
673 die("could not get embedding window attributes: …
674 parentwin);
675 x = 0;
676 y = topbar ? 0 : wa.height - mh;
677 mw = wa.width;
678 }
679 promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
680 inputw = mw / 3; /* input width: ~33% of monitor width */
681 match();
682
683 /* create menu window */
684 swa.override_redirect = True;
685 swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
686 swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeM…
687 win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
688 CopyFromParent, CopyFromParent, CopyFromPare…
689 CWOverrideRedirect | CWBackPixel | CWEventMa…
690 XSetClassHint(dpy, win, &ch);
691
692 /* input methods */
693 if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
694 die("XOpenIM failed: could not open input device");
695
696 xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatus…
697 XNClientWindow, win, XNFocusWindow, win, NULL);
698
699 XMapRaised(dpy, win);
700 if (embed) {
701 XReparentWindow(dpy, win, parentwin, x, y);
702 XSelectInput(dpy, parentwin, FocusChangeMask | Substruct…
703 if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dw…
704 for (i = 0; i < du && dws[i] != win; ++i)
705 XSelectInput(dpy, dws[i], FocusChangeMas…
706 XFree(dws);
707 }
708 grabfocus();
709 }
710 drw_resize(drw, mw, mh);
711 drawmenu();
712 }
713
714 static void
715 usage(void)
716 {
717 die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m …
718 " [-nb color] [-nf color] [-sb color] [-sf color…
719 }
720
721 int
722 main(int argc, char *argv[])
723 {
724 XWindowAttributes wa;
725 int i, fast = 0;
726
727 for (i = 1; i < argc; i++)
728 /* these options take no arguments */
729 if (!strcmp(argv[i], "-v")) { /* prints version inf…
730 puts("dmenu-"VERSION);
731 exit(0);
732 } else if (!strcmp(argv[i], "-b")) /* appears at the bot…
733 topbar = 0;
734 else if (!strcmp(argv[i], "-f")) /* grabs keyboard bef…
735 fast = 1;
736 else if (!strcmp(argv[i], "-i")) { /* case-insensitive i…
737 fstrncmp = strncasecmp;
738 fstrstr = cistrstr;
739 } else if (i + 1 == argc)
740 usage();
741 /* these options take one argument */
742 else if (!strcmp(argv[i], "-l")) /* number of lines in…
743 lines = atoi(argv[++i]);
744 else if (!strcmp(argv[i], "-m"))
745 mon = atoi(argv[++i]);
746 else if (!strcmp(argv[i], "-p")) /* adds prompt to lef…
747 prompt = argv[++i];
748 else if (!strcmp(argv[i], "-fn")) /* font or font set */
749 fonts[0] = argv[++i];
750 else if (!strcmp(argv[i], "-nb")) /* normal background …
751 colors[SchemeNorm][ColBg] = argv[++i];
752 else if (!strcmp(argv[i], "-nf")) /* normal foreground …
753 colors[SchemeNorm][ColFg] = argv[++i];
754 else if (!strcmp(argv[i], "-sb")) /* selected backgroun…
755 colors[SchemeSel][ColBg] = argv[++i];
756 else if (!strcmp(argv[i], "-sf")) /* selected foregroun…
757 colors[SchemeSel][ColFg] = argv[++i];
758 else if (!strcmp(argv[i], "-w")) /* embedding window i…
759 embed = argv[++i];
760 else
761 usage();
762
763 if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
764 fputs("warning: no locale support\n", stderr);
765 if (!(dpy = XOpenDisplay(NULL)))
766 die("cannot open display");
767 screen = DefaultScreen(dpy);
768 root = RootWindow(dpy, screen);
769 if (!embed || !(parentwin = strtol(embed, NULL, 0)))
770 parentwin = root;
771 if (!XGetWindowAttributes(dpy, parentwin, &wa))
772 die("could not get embedding window attributes: 0x%lx",
773 parentwin);
774 drw = drw_create(dpy, screen, root, wa.width, wa.height);
775 if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
776 die("no fonts could be loaded.");
777 lrpad = drw->fonts->h;
778
779 #ifdef __OpenBSD__
780 if (pledge("stdio rpath", NULL) == -1)
781 die("pledge");
782 #endif
783
784 if (fast && !isatty(0)) {
785 grabkeyboard();
786 readstdin();
787 } else {
788 readstdin();
789 grabkeyboard();
790 }
791 setup();
792 run();
793
794 return 1; /* unreachable */
795 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.