From f52b28990b0663fdeb8ddc006542a322a7413a3b Mon Sep 17 00:00:00 2001 From: lucy Date: Thu, 11 Jun 2026 09:06:24 +0200 Subject: [PATCH] add config and patches --- config.h | 23 ++ dmenu | Bin 0 -> 42384 bytes dmenu.c | 99 +++++- dmenu.c.orig | 826 +++++++++++++++++++++++++++++++++++++++++++++++++++ dmenu.o | Bin 0 -> 35880 bytes drw.o | Bin 0 -> 10392 bytes stest | Bin 0 -> 16392 bytes stest.o | Bin 0 -> 5360 bytes util.o | Bin 0 -> 2288 bytes 9 files changed, 933 insertions(+), 15 deletions(-) create mode 100644 config.h create mode 100755 dmenu create mode 100644 dmenu.c.orig create mode 100644 dmenu.o create mode 100644 drw.o create mode 100755 stest create mode 100644 stest.o create mode 100644 util.o diff --git a/config.h b/config.h new file mode 100644 index 0000000..f235175 --- /dev/null +++ b/config.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "monospace:size=10" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 8; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/dmenu b/dmenu new file mode 100755 index 0000000000000000000000000000000000000000..20fe15b7f5a251f88bb151900d62b01214a7cb4c GIT binary patch literal 42384 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 r`R7Xt$W=$?6yIcuQmVeti8 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 literal 0 HcmV?d00001 diff --git a/dmenu.c b/dmenu.c index 6b8f51b..ff6e63c 100644 --- a/dmenu.c +++ b/dmenu.c @@ -15,6 +15,7 @@ #include #endif #include +#include #include "drw.h" #include "util.h" @@ -53,6 +54,10 @@ static XIC xic; static Drw *drw; static Clr *scheme[SchemeLast]; +/* Temporary arrays to allow overriding xresources values */ +static char *colortemp[4]; +static char *tempfonts; + #include "config.h" static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; @@ -89,6 +94,15 @@ calcoffsets(void) break; } +static int +max_textw(void) +{ + int len = 0; + for (struct item *item = items; item && item->text; item++) + len = MAX(TEXTW(item->text), len); + return len; +} + static void cleanup(void) { @@ -596,8 +610,13 @@ setup(void) int a, di, n, area = 0; #endif /* init appearance */ - for (j = 0; j < SchemeLast; j++) - scheme[j] = drw_scm_create(drw, colors[j], 2); + for (j = 0; j < SchemeLast; j++) { + scheme[j] = drw_scm_create(drw, (const char**)colors[j], 2); + } + for (j = 0; j < SchemeOut; ++j) { + for (i = 0; i < 2; ++i) + free(colors[j][i]); + } clip = XInternAtom(dpy, "CLIPBOARD", False); utf8 = XInternAtom(dpy, "UTF8_STRING", False); @@ -606,6 +625,7 @@ setup(void) bh = drw->fonts->h + 2; lines = MAX(lines, 0); mh = (lines + 1) * bh; + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; #ifdef XINERAMA i = 0; if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { @@ -632,9 +652,9 @@ setup(void) if (INTERSECT(x, y, 1, 1, info[i])) break; - x = info[i].x_org; - y = info[i].y_org + (topbar ? 0 : info[i].height - mh); - mw = info[i].width; + mw = MIN(MAX(max_textw() + promptw, 100), info[i].width); + x = info[i].x_org + ((info[i].width - mw) / 2); + y = info[i].y_org + ((info[i].height - mh) / 2); XFree(info); } else #endif @@ -642,11 +662,10 @@ setup(void) if (!XGetWindowAttributes(dpy, parentwin, &wa)) die("could not get embedding window attributes: 0x%lx", parentwin); - x = 0; - y = topbar ? 0 : wa.height - mh; - mw = wa.width; + mw = MIN(MAX(max_textw() + promptw, 100), wa.width); + x = (wa.width - mw) / 2; + y = (wa.height - mh) / 2; } - promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; inputw = MIN(inputw, mw/3); match(); @@ -687,6 +706,41 @@ usage(void) exit(1); } +void +readxresources(void) { + XrmInitialize(); + + char* xrm; + if ((xrm = XResourceManagerString(drw->dpy))) { + char *type; + XrmDatabase xdb = XrmGetStringDatabase(xrm); + XrmValue xval; + + if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval)) + fonts[0] = strdup(xval.addr); + else + fonts[0] = strdup(fonts[0]); + if (XrmGetResource(xdb, "color0", "*", &type, &xval)) + colors[SchemeNorm][ColBg] = strdup(xval.addr); + else + colors[SchemeNorm][ColBg] = strdup(colors[SchemeNorm][ColBg]); + if (XrmGetResource(xdb, "color12", "*", &type, &xval)) + colors[SchemeNorm][ColFg] = strdup(xval.addr); + else + colors[SchemeNorm][ColFg] = strdup(colors[SchemeNorm][ColFg]); + if (XrmGetResource(xdb, "color12", "*", &type, &xval)) + colors[SchemeSel][ColBg] = strdup(xval.addr); + else + colors[SchemeSel][ColBg] = strdup(colors[SchemeSel][ColBg]); + if (XrmGetResource(xdb, "color0", "*", &type, &xval)) + colors[SchemeSel][ColFg] = strdup(xval.addr); + else + colors[SchemeSel][ColFg] = strdup(colors[SchemeSel][ColFg]); + + XrmDestroyDatabase(xdb); + } +} + int main(int argc, char *argv[]) { @@ -715,15 +769,15 @@ main(int argc, char *argv[]) else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ prompt = argv[++i]; else if (!strcmp(argv[i], "-fn")) /* font or font set */ - fonts[0] = argv[++i]; + tempfonts = argv[++i]; else if (!strcmp(argv[i], "-nb")) /* normal background color */ - colors[SchemeNorm][ColBg] = argv[++i]; + colortemp[0] = argv[++i]; else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ - colors[SchemeNorm][ColFg] = argv[++i]; + colortemp[1] = argv[++i]; else if (!strcmp(argv[i], "-sb")) /* selected background color */ - colors[SchemeSel][ColBg] = argv[++i]; + colortemp[2] = argv[++i]; else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ - colors[SchemeSel][ColFg] = argv[++i]; + colortemp[3] = argv[++i]; else if (!strcmp(argv[i], "-w")) /* embedding window id */ embed = argv[++i]; else @@ -743,8 +797,23 @@ main(int argc, char *argv[]) die("could not get embedding window attributes: 0x%lx", parentwin); drw = drw_create(dpy, screen, root, wa.width, wa.height); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + readxresources(); + /* Now we check whether to override xresources with commandline parameters */ + if ( tempfonts ) + fonts[0] = strdup(tempfonts); + if ( colortemp[0]) + colors[SchemeNorm][ColBg] = strdup(colortemp[0]); + if ( colortemp[1]) + colors[SchemeNorm][ColFg] = strdup(colortemp[1]); + if ( colortemp[2]) + colors[SchemeSel][ColBg] = strdup(colortemp[2]); + if ( colortemp[3]) + colors[SchemeSel][ColFg] = strdup(colortemp[3]); + + if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts))) die("no fonts could be loaded."); + + free(fonts[0]); lrpad = drw->fonts->h; #ifdef __OpenBSD__ diff --git a/dmenu.c.orig b/dmenu.c.orig new file mode 100644 index 0000000..ab19c83 --- /dev/null +++ b/dmenu.c.orig @@ -0,0 +1,826 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef XINERAMA +#include +#endif +#include +#include + +#include "drw.h" +#include "util.h" + +/* macros */ +#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ + * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ + +struct item { + char *text; + struct item *left, *right; + int out; +}; + +static char text[BUFSIZ] = ""; +static char *embed; +static int bh, mw, mh; +static int inputw = 0, promptw; +static int lrpad; /* sum of left and right padding */ +static size_t cursor; +static struct item *items = NULL; +static struct item *matches, *matchend; +static struct item *prev, *curr, *next, *sel; +static int mon = -1, screen; + +static Atom clip, utf8; +static Display *dpy; +static Window root, parentwin, win; +static XIC xic; + +static Drw *drw; +static Clr *scheme[SchemeLast]; + +/* Temporary arrays to allow overriding xresources values */ +static char *colortemp[4]; +static char *tempfonts; + +#include "config.h" + +static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; +static char *(*fstrstr)(const char *, const char *) = strstr; + +static void +appenditem(struct item *item, struct item **list, struct item **last) +{ + if (*last) + (*last)->right = item; + else + *list = item; + + item->left = *last; + item->right = NULL; + *last = item; +} + +static void +calcoffsets(void) +{ + int i, n; + + if (lines > 0) + n = lines * bh; + else + n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); + /* calculate which items will begin the next page and previous page */ + for (i = 0, next = curr; next; next = next->right) + if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n) + break; + for (i = 0, prev = curr; prev && prev->left; prev = prev->left) + if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) + break; +} + +static void +cleanup(void) +{ + size_t i; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); + drw_free(drw); + XSync(dpy, False); + XCloseDisplay(dpy); +} + +static char * +cistrstr(const char *s, const char *sub) +{ + size_t len; + + for (len = strlen(sub); *s; s++) + if (!strncasecmp(s, sub, len)) + return (char *)s; + return NULL; +} + +static int +drawitem(struct item *item, int x, int y, int w) +{ + if (item == sel) + drw_setscheme(drw, scheme[SchemeSel]); + else if (item->out) + drw_setscheme(drw, scheme[SchemeOut]); + else + drw_setscheme(drw, scheme[SchemeNorm]); + + return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); +} + +static void +drawmenu(void) +{ + unsigned int curpos; + struct item *item; + int x = 0, y = 0, w; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, 0, 0, mw, mh, 1, 1); + + if (prompt && *prompt) { + drw_setscheme(drw, scheme[SchemeSel]); + x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); + } + /* draw input field */ + w = (lines > 0 || !matches) ? mw - x : inputw; + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); + + curpos = TEXTW(text) - TEXTW(&text[cursor]); + if ((curpos += lrpad / 2 - 1) < w) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); + } + + if (lines > 0) { + /* draw vertical list */ + for (item = curr; item != next; item = item->right) + drawitem(item, x, y += bh, mw - x); + } else if (matches) { + /* draw horizontal list */ + x += inputw; + w = TEXTW("<"); + if (curr->left) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0); + } + x += w; + for (item = curr; item != next; item = item->right) + x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">"))); + if (next) { + w = TEXTW(">"); + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); + } + } + drw_map(drw, win, 0, 0, mw, mh); +} + +static void +grabfocus(void) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; + Window focuswin; + int i, revertwin; + + for (i = 0; i < 100; ++i) { + XGetInputFocus(dpy, &focuswin, &revertwin); + if (focuswin == win) + return; + XSetInputFocus(dpy, win, RevertToParent, CurrentTime); + nanosleep(&ts, NULL); + } + die("cannot grab focus"); +} + +static void +grabkeyboard(void) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; + int i; + + if (embed) + return; + /* try to grab keyboard, we may have to wait for another process to ungrab */ + for (i = 0; i < 1000; i++) { + if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, + GrabModeAsync, CurrentTime) == GrabSuccess) + return; + nanosleep(&ts, NULL); + } + die("cannot grab keyboard"); +} + +static void +match(void) +{ + static char **tokv = NULL; + static int tokn = 0; + + char buf[sizeof text], *s; + int i, tokc = 0; + size_t len, textsize; + struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; + + strcpy(buf, text); + /* separate input text into tokens to be matched individually */ + for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) + if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) + die("cannot realloc %u bytes:", tokn * sizeof *tokv); + len = tokc ? strlen(tokv[0]) : 0; + + matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; + textsize = strlen(text) + 1; + for (item = items; item && item->text; item++) { + for (i = 0; i < tokc; i++) + if (!fstrstr(item->text, tokv[i])) + break; + if (i != tokc) /* not all tokens match */ + continue; + /* exact matches go first, then prefixes, then substrings */ + if (!tokc || !fstrncmp(text, item->text, textsize)) + appenditem(item, &matches, &matchend); + else if (!fstrncmp(tokv[0], item->text, len)) + appenditem(item, &lprefix, &prefixend); + else + appenditem(item, &lsubstr, &substrend); + } + if (lprefix) { + if (matches) { + matchend->right = lprefix; + lprefix->left = matchend; + } else + matches = lprefix; + matchend = prefixend; + } + if (lsubstr) { + if (matches) { + matchend->right = lsubstr; + lsubstr->left = matchend; + } else + matches = lsubstr; + matchend = substrend; + } + curr = sel = matches; + calcoffsets(); +} + +static void +insert(const char *str, ssize_t n) +{ + if (strlen(text) + n > sizeof text - 1) + return; + /* move existing text out of the way, insert new text, and update cursor */ + memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); + if (n > 0) + memcpy(&text[cursor], str, n); + cursor += n; + match(); +} + +static size_t +nextrune(int inc) +{ + ssize_t n; + + /* return location of next utf8 rune in the given direction (+1 or -1) */ + for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) + ; + return n; +} + +static void +movewordedge(int dir) +{ + if (dir < 0) { /* move cursor to the start of the word*/ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + } else { /* move cursor to the end of the word */ + while (text[cursor] && strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + while (text[cursor] && !strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + } +} + +static void +keypress(XKeyEvent *ev) +{ + char buf[32]; + int len; + KeySym ksym; + Status status; + + len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); + switch (status) { + default: /* XLookupNone, XBufferOverflow */ + return; + case XLookupChars: + goto insert; + case XLookupKeySym: + case XLookupBoth: + break; + } + + if (ev->state & ControlMask) { + switch(ksym) { + case XK_a: ksym = XK_Home; break; + case XK_b: ksym = XK_Left; break; + case XK_c: ksym = XK_Escape; break; + case XK_d: ksym = XK_Delete; break; + case XK_e: ksym = XK_End; break; + case XK_f: ksym = XK_Right; break; + case XK_g: ksym = XK_Escape; break; + case XK_h: ksym = XK_BackSpace; break; + case XK_i: ksym = XK_Tab; break; + case XK_j: /* fallthrough */ + case XK_J: /* fallthrough */ + case XK_m: /* fallthrough */ + case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; + case XK_n: ksym = XK_Down; break; + case XK_p: ksym = XK_Up; break; + + case XK_k: /* delete right */ + text[cursor] = '\0'; + match(); + break; + case XK_u: /* delete left */ + insert(NULL, 0 - cursor); + break; + case XK_w: /* delete word */ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + break; + case XK_y: /* paste selection */ + case XK_Y: + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + case XK_Left: + movewordedge(-1); + goto draw; + case XK_Right: + movewordedge(+1); + goto draw; + case XK_Return: + case XK_KP_Enter: + break; + case XK_bracketleft: + cleanup(); + exit(1); + default: + return; + } + } else if (ev->state & Mod1Mask) { + switch(ksym) { + case XK_b: + movewordedge(-1); + goto draw; + case XK_f: + movewordedge(+1); + goto draw; + case XK_g: ksym = XK_Home; break; + case XK_G: ksym = XK_End; break; + case XK_h: ksym = XK_Up; break; + case XK_j: ksym = XK_Next; break; + case XK_k: ksym = XK_Prior; break; + case XK_l: ksym = XK_Down; break; + default: + return; + } + } + + switch(ksym) { + default: +insert: + if (!iscntrl(*buf)) + insert(buf, len); + break; + case XK_Delete: + if (text[cursor] == '\0') + return; + cursor = nextrune(+1); + /* fallthrough */ + case XK_BackSpace: + if (cursor == 0) + return; + insert(NULL, nextrune(-1) - cursor); + break; + case XK_End: + if (text[cursor] != '\0') { + cursor = strlen(text); + break; + } + if (next) { + /* jump to end of list and position items in reverse */ + curr = matchend; + calcoffsets(); + curr = prev; + calcoffsets(); + while (next && (curr = curr->right)) + calcoffsets(); + } + sel = matchend; + break; + case XK_Escape: + cleanup(); + exit(1); + case XK_Home: + if (sel == matches) { + cursor = 0; + break; + } + sel = curr = matches; + calcoffsets(); + break; + case XK_Left: + if (cursor > 0 && (!sel || !sel->left || lines > 0)) { + cursor = nextrune(-1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Up: + if (sel && sel->left && (sel = sel->left)->right == curr) { + curr = prev; + calcoffsets(); + } + break; + case XK_Next: + if (!next) + return; + sel = curr = next; + calcoffsets(); + break; + case XK_Prior: + if (!prev) + return; + sel = curr = prev; + calcoffsets(); + break; + case XK_Return: + case XK_KP_Enter: + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + if (!(ev->state & ControlMask)) { + cleanup(); + exit(0); + } + if (sel) + sel->out = 1; + break; + case XK_Right: + if (text[cursor] != '\0') { + cursor = nextrune(+1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Down: + if (sel && sel->right && (sel = sel->right) == next) { + curr = next; + calcoffsets(); + } + break; + case XK_Tab: + if (!sel) + return; + strncpy(text, sel->text, sizeof text - 1); + text[sizeof text - 1] = '\0'; + cursor = strlen(text); + match(); + break; + } + +draw: + drawmenu(); +} + +static void +paste(void) +{ + char *p, *q; + int di; + unsigned long dl; + Atom da; + + /* we have been given the current selection, now insert it into input */ + if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, + utf8, &da, &di, &dl, &dl, (unsigned char **)&p) + == Success && p) { + insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); + XFree(p); + } + drawmenu(); +} + +static void +readstdin(void) +{ + char buf[sizeof text], *p; + size_t i, imax = 0, size = 0; + unsigned int tmpmax = 0; + + /* read each line from stdin and add it to the item list */ + for (i = 0; fgets(buf, sizeof buf, stdin); i++) { + if (i + 1 >= size / sizeof *items) + if (!(items = realloc(items, (size += BUFSIZ)))) + die("cannot realloc %u bytes:", size); + if ((p = strchr(buf, '\n'))) + *p = '\0'; + if (!(items[i].text = strdup(buf))) + die("cannot strdup %u bytes:", strlen(buf) + 1); + items[i].out = 0; + drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); + if (tmpmax > inputw) { + inputw = tmpmax; + imax = i; + } + } + if (items) + items[i].text = NULL; + inputw = items ? TEXTW(items[imax].text) : 0; + lines = MIN(lines, i); +} + +static void +run(void) +{ + XEvent ev; + + while (!XNextEvent(dpy, &ev)) { + if (XFilterEvent(&ev, None)) + continue; + switch(ev.type) { + case Expose: + if (ev.xexpose.count == 0) + drw_map(drw, win, 0, 0, mw, mh); + break; + case FocusIn: + /* regrab focus from parent window */ + if (ev.xfocus.window != win) + grabfocus(); + break; + case KeyPress: + keypress(&ev.xkey); + break; + case SelectionNotify: + if (ev.xselection.property == utf8) + paste(); + break; + case VisibilityNotify: + if (ev.xvisibility.state != VisibilityUnobscured) + XRaiseWindow(dpy, win); + break; + } + } +} + +static void +setup(void) +{ + int x, y, i, j; + unsigned int du; + XSetWindowAttributes swa; + XIM xim; + Window w, dw, *dws; + XWindowAttributes wa; + XClassHint ch = {"dmenu", "dmenu"}; +#ifdef XINERAMA + XineramaScreenInfo *info; + Window pw; + int a, di, n, area = 0; +#endif + /* init appearance */ + for (j = 0; j < SchemeLast; j++) { + scheme[j] = drw_scm_create(drw, (const char**)colors[j], 2); + } + for (j = 0; j < SchemeOut; ++j) { + for (i = 0; i < 2; ++i) + free(colors[j][i]); + } + + clip = XInternAtom(dpy, "CLIPBOARD", False); + utf8 = XInternAtom(dpy, "UTF8_STRING", False); + + /* calculate menu geometry */ + bh = drw->fonts->h + 2; + lines = MAX(lines, 0); + mh = (lines + 1) * bh; +#ifdef XINERAMA + i = 0; + if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { + XGetInputFocus(dpy, &w, &di); + if (mon >= 0 && mon < n) + i = mon; + else if (w != root && w != PointerRoot && w != None) { + /* find top-level window containing current input focus */ + do { + if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) + XFree(dws); + } while (w != root && w != pw); + /* find xinerama screen with which the window intersects most */ + if (XGetWindowAttributes(dpy, pw, &wa)) + for (j = 0; j < n; j++) + if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { + area = a; + i = j; + } + } + /* no focused window is on screen, so use pointer location instead */ + if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) + for (i = 0; i < n; i++) + if (INTERSECT(x, y, 1, 1, info[i])) + break; + + x = info[i].x_org; + y = info[i].y_org + (topbar ? 0 : info[i].height - mh); + mw = info[i].width; + XFree(info); + } else +#endif + { + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + x = 0; + y = topbar ? 0 : wa.height - mh; + mw = wa.width; + } + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; + inputw = MIN(inputw, mw/3); + match(); + + /* create menu window */ + swa.override_redirect = True; + swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; + win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + XSetClassHint(dpy, win, &ch); + + /* open input methods */ + xim = XOpenIM(dpy, NULL, NULL, NULL); + xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, win, XNFocusWindow, win, NULL); + + XMapRaised(dpy, win); + XSetInputFocus(dpy, win, RevertToParent, CurrentTime); + if (embed) { + XSelectInput(dpy, parentwin, FocusChangeMask); + if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { + for (i = 0; i < du && dws[i] != win; ++i) + XSelectInput(dpy, dws[i], FocusChangeMask); + XFree(dws); + } + grabfocus(); + } + drw_resize(drw, mw, mh); + drawmenu(); +} + +static void +usage(void) +{ + fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" + " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); + exit(1); +} + +void +readxresources(void) { + XrmInitialize(); + + char* xrm; + if ((xrm = XResourceManagerString(drw->dpy))) { + char *type; + XrmDatabase xdb = XrmGetStringDatabase(xrm); + XrmValue xval; + + if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval)) + fonts[0] = strdup(xval.addr); + else + fonts[0] = strdup(fonts[0]); + if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval)) + colors[SchemeNorm][ColBg] = strdup(xval.addr); + else + colors[SchemeNorm][ColBg] = strdup(colors[SchemeNorm][ColBg]); + if (XrmGetResource(xdb, "dmenu.foreground", "*", &type, &xval)) + colors[SchemeNorm][ColFg] = strdup(xval.addr); + else + colors[SchemeNorm][ColFg] = strdup(colors[SchemeNorm][ColFg]); + if (XrmGetResource(xdb, "dmenu.selbackground", "*", &type, &xval)) + colors[SchemeSel][ColBg] = strdup(xval.addr); + else + colors[SchemeSel][ColBg] = strdup(colors[SchemeSel][ColBg]); + if (XrmGetResource(xdb, "dmenu.selforeground", "*", &type, &xval)) + colors[SchemeSel][ColFg] = strdup(xval.addr); + else + colors[SchemeSel][ColFg] = strdup(colors[SchemeSel][ColFg]); + + XrmDestroyDatabase(xdb); + } +} + +int +main(int argc, char *argv[]) +{ + XWindowAttributes wa; + int i, fast = 0; + + for (i = 1; i < argc; i++) + /* these options take no arguments */ + if (!strcmp(argv[i], "-v")) { /* prints version information */ + puts("dmenu-"VERSION); + exit(0); + } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ + topbar = 0; + else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ + fast = 1; + else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ + fstrncmp = strncasecmp; + fstrstr = cistrstr; + } else if (i + 1 == argc) + usage(); + /* these options take one argument */ + else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ + lines = atoi(argv[++i]); + else if (!strcmp(argv[i], "-m")) + mon = atoi(argv[++i]); + else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ + prompt = argv[++i]; + else if (!strcmp(argv[i], "-fn")) /* font or font set */ + tempfonts = argv[++i]; + else if (!strcmp(argv[i], "-nb")) /* normal background color */ + colortemp[0] = argv[++i]; + else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ + colortemp[1] = argv[++i]; + else if (!strcmp(argv[i], "-sb")) /* selected background color */ + colortemp[2] = argv[++i]; + else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ + colortemp[3] = argv[++i]; + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; + else + usage(); + + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!XSetLocaleModifiers("")) + fputs("warning: no locale modifiers support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("cannot open display"); + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + if (!embed || !(parentwin = strtol(embed, NULL, 0))) + parentwin = root; + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + drw = drw_create(dpy, screen, root, wa.width, wa.height); + readxresources(); + /* Now we check whether to override xresources with commandline parameters */ + if ( tempfonts ) + fonts[0] = strdup(tempfonts); + if ( colortemp[0]) + colors[SchemeNorm][ColBg] = strdup(colortemp[0]); + if ( colortemp[1]) + colors[SchemeNorm][ColFg] = strdup(colortemp[1]); + if ( colortemp[2]) + colors[SchemeSel][ColBg] = strdup(colortemp[2]); + if ( colortemp[3]) + colors[SchemeSel][ColFg] = strdup(colortemp[3]); + + if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + + free(fonts[0]); + lrpad = drw->fonts->h; + +#ifdef __OpenBSD__ + if (pledge("stdio rpath", NULL) == -1) + die("pledge"); +#endif + + if (fast && !isatty(0)) { + grabkeyboard(); + readstdin(); + } else { + readstdin(); + grabkeyboard(); + } + setup(); + run(); + + return 1; /* unreachable */ +} diff --git a/dmenu.o b/dmenu.o new file mode 100644 index 0000000000000000000000000000000000000000..3c6745ad99c96c6fa0285f605b2a884b72fff014 GIT binary patch literal 35880 zcmb<-^>JfjWMqH=Mg}_u1P><4z_6kX!FB*M9T>zIL>WA~ML|4|;^9!5*EzJvzUGMLj!@G*~l~i2HOt^5}f$(Rm*%+Ipab-Q)k^*G~*@ zdvxB2j&+PV{QtOPh)=I7$jnfWUR@9!%-=eVfq}uJTNcFgXuVycv;Y79|NmcD{r~?T z>KI4SPYkqwKYKlkeZT^-C3=9kqz5o8f_44m4VP){>JPgxY zn(NUCw(9k1sOd175>JRf4}vszLIMrqD*k;XvJ4I_-%8KERz=fPDhJWjgQThRFkHh$ zu(v~l4Q~f}bc3Dj(fYQ;)}yR zoj0PQV-GuqI);P>2SFUzdb@;^e?7!o!B8_jdchG0Q2?=<8SDbEWvGf=Ao7l#N5GOU z5QQ$9uQgx0Xg=0F?9mN&o8emzXt=ZL6K{Z09 zJ-Q8$RUCTF21%uiS1n)HazoV`zI~kwWqNcw2)yp`=yu=$MS3pG!Wi5ZD#3Mv9S7Em zW+}+B8b!D|2M&avN~gT$fVk-O%?MD;ImRA#40jBJgtbTG8wLRe29IVQ6$TV`^BWDr zZ?1+M7urRdHU6$u3f2EzlLB`P8wy*VlpuuR$cejkGZ0|PiLU_sM* zfWPGl0|SFk=L4VKVn&aHFIYV-j}>WoHXZ?~_33;DQ4WuQQhuM#XUM5>9~aox_Yifh z2TGWaf$|l&9PsSC@6q|*^WbwV1PuQW1M6B;m}}@<~JHh5#ypFVR*psfCn@| zc^r395pZzgXYlBBQQ;_!-~ED_fdLd@98l-D8lH6A0V)G`f{0xp!Xvr;0Vuc+K4AA? zZU=oI7ZnK%S2rKgh>krR8oWCNWNh;r3l#Ti zfZf}hqrwAntU|-I8DPgsKpp7OTcRT1(fJB&KeXibuq;s#C^3YpFg&@7i2<7A48M8w z)~G-t@&D=4-I&hPz~Vd$NTJht)-lAf^GYbB1_f~U6pddQdlXEOEJ3)_D(Rv*Y)F2uq>9^XPmB)`(_s=TQ$vh=gO5V|3?1h{t9+e*fpxo1^hx^Q?>I z(_&|s8A#PWL?I*ydrh>%p-RBP0ZvU>3@*J6f53J+MmR=7yK%g}(#7T~wM>X$))o3HD(LCyC`L&+t;`O;}2fh;o5MShV3u!%I-rr~w@77~>f0821vC z(?UU|3fRZNhPQ(}AX;}ZG{B<~>@|<>n!5}h{~?a@X#UMy`W709P-$?C8-7FPMMTGf zZ6K;9w%7%#Euo?5YWO6@quT~r9q&;A)eE4aPXl5+q=Dqoc^ty+JPK-?U|=x3I&*k*dJ8}WUWdYr0XICljXk<8VERgBeOup_uz7aI3cP0a=)7xq$)_`$!?W|Q zM`y6WYZ*|2XZP%kQ4x5}?AdwW@PJQeGKXj99gj|D0gvXx3NM90{e{-IC7Q58q(l&A zS!afTN2e>tYj$Y2!3WZN@NNB%MYT_7g@9+LJI8BwpH6UU^y!2a1dy19wmu-#i_$Nk zva1E0v@j~o#v>M}EfGkC1uf7*Jv#sTbUqLE===c3U;ecuM4Q*_|T&l zl62r%3D(mBcmBF-R0LkLL-P-^zLy@I_tCY2Ed?tYMtVX1gr*cwk>Syez3Ha_ik-t8 z3=9mQt}jSsX>nqDs+B@YZfahsLbPsDT4q_SLbPs3o1)dP8g0qjTv2xVx*pj!r!)HTtwWYA4w&`o2|&1BHcVbING z&@EulP0M4@%}Zj?%}Zm@Ely(4Ely+5EoWdTPb|vI%uBaY$jevA$xlwqNmVE=Ehxw@ zD&fK=mz$rGnU zp&_M^SW;4ynN$i26a|9{)tm~3ynJxX6e~bF3S>4wrCn=rbheWTxhoKslLt1*IjyC6zg;49ZDhz@Tgd1`NunV8Ebk zU|?!$ZVsXi3=9lFbXrwVsffgab{Jjt)T$}xFiU7?ELQ-=C}{ksc{T- zHGB&iR`6(ibApM1A;qIx2U>ZqQQ5)7z~IsO)z$JJfA3pH1_s~cXV6;Bt2^c?17g&t zR1jJtfHU*UW^Pbt3Q}XiM~3)Y7J&*BSg`>cFye1%#U@+|@2*4g5^P8d!h0Fc$iU$E z|Cp=g_flvV5Z&BTQLpZrr;y?ds!0i}MVRV-foeev^8~%RU7o^54qjd(Ld_;3)bwFh z!-s6w>s)A{BZW7r0v|#Ov@sO$w;uiX|38W~Y>s=uDdPXJmt6n;|2O;()dY@HP$NMU z))a&^KEUFyIl)xxfs#kaNdTl=7>jaPO9c`mAXPjl+8`}4X!YTd+zje)L)C)2-OV7| zJi0-ZJGkNL(fYrX2U^8@biR8nVffAP5=adLY>21x7^us4$D?pQ9W1&XI3NynZGBrJ4viU*Ua&$i@tO-vfeC01G`tOM%Yd4i9`Npni%Nh; z=RIiffqRM`2cNO{Fv5ngT)=$*aP$8iJ9O3 zX&z+!32mr(K!&7Jt! z!^ptk%6Q0?@wAKO``UQ^{bKz4-B?`s_m?p-UU0Fz;K=WP$i?!IBfrlD%?rCgZ61D) zL;U;0*jyMtxmezE01u4kX8VbYAr6by3j?a0~&>Mfj*VfV^)5 z_Mu1f5rx(RC8gaZDl*+QDheLGzAPZmgsAAa^tv&+^!hWpSYECT<=-#Jzuyt$mq@T* z4mk4rAF%wy?{f{=CxL7(jJI4YPdW1YUv#wm?ZWSK-$nD5<8G)=F7vNH)Ow(l!=w2i z&;P@(mw{aX>9p?zjR7|QNU7sR66`z(>U(D2=J8;B&A&gG!}3&}5|Z>Tta=Xd?|0?^ zcl#kp+oSWn=7pKxfAa4SW?{V0>7pXTzu%cl8=OiY!faq+1+d94H-G{W8g8)kJVgbR z0KoFC2e6i#U^%=#fhHN^ywKeOPG3mA0DA%C`0f^PGK0In(?vz08|;~#%pj-t#;8Qh z{QeVCVp|^K_rCxM2CxgEdG~mW3dozF+73G40Uzsd5P+5%9>-f$7BDa{Fg7qUz>-s^ zi%LRp1``(pLlzWv`=|tThp6~KOm98{n-u}&a1W2pW6)B`2R=>-E6@QCABfwt z7<_ucC5Z=w+Qq>FYI+?vJm46BTIxYsRnVA$6k8C>A#rAS66#oR84QtuW|XK%{+3oy z5J6PJ)G;t9K&K^oeN+rQK=}t21Q1(%dVN$>Ksg3pVAvYI^=Ph9abPGh_UNuraj?!& zQ7KmT=r(!pVGVX)i5Rl!9{(ZJc&{NfGuTm(_<_2lca6#oP^km44=fKRUUN48;N)+a zh>(Mgd$k_mZ+*|szyKN`flOhv9w@!t-2yhJ`3DbwiwYwH1Ajkg0=4-EQ|Wf7dptXD zdUU??>D{6-gNcE`r?&;1vUe(gXJI~pE$wtsVd-{JiD>@8#NXn`$iUG2g1PwzBY%74 z|NsBHr>JOv3v-CZZ--d;Th4==*ZiZBzs(xNvJL*vz`)-U%FMvP-<}T^;RT7b27%b! z5RD$T;UKa0GoWb)TYoTnKA6o3Vz$0u%rJ|NrtRNZ>dm%t7j2R)frg3P}HF zV0f8@B=8?35c%)_|At2#{4HQ_H2-ktZ`}-vIjAO3yuCC<(gcd`mnujCAdkNkMiKx; z=}RUg0Z@!KKla1~_E+fvJPEdpufCmhOdy zG<0m&qxB?zizU$}^SAQ;{r?}$^w*oAg>b_oMrh#&?ubH@s0Y6*xCC(pwb~APK&KX8 z{{0R0&TCf4L4E?&LEuaUt0^D~eL(|o93Tat(IKz`!~Z^- z2Ru5DfjKWB?M-mK2Q3a7Y}gq}Ano;+O(3^Hi+xai4N(WFEnfD43ov9Mu#wPcfw}`C z1T~^$FHExAK>(@%)OWk}dI?Md(i-M(T?!g?J^)qoQW<0w%nfYt*g0+87oPMDlH zIIX@s%D}(?72zPz?oI^Z@332D#W8Vjn~^f9rja z7=!~h_2oH`0Fnt0e}KZtU>9f{8JZTr3Zd*{VB;W#1=P1->6f5oM6l%vmQ%pB0DtS0 zAOHV5hC&N{SHqKrCxab#Fmf<31cRE;5dj{(Eh+_!3=9E5U_(5bj~KKbD7EwHPEqjy zjn|uimn8UfK8HxR9w=e;(R}cl1193r`5cypK}`n_ure_5Qt}75HevwRMlIZ6UxCX4 zi1e@TAaAyS2c@tKyMqR=z!UbMaaGV1m1F#2P$4mjK_LKY;DBhVV0UL{D+LYr)Vz}X zd<8>OJtIBC_yQvXBQpadLlcDpQ%$I#0!$2IE2tkWz`(!&N{{Y-p`ds^01^W=+d(Qo zY>+z<@{C}4P;LXsGcus^ML>d}7J5|>17n2%qcjgY#{@_M~}pFj_jBcDVYvkRX>GfM%Vgd?AT6CY@-9;CJc zq=tck;X8sr3Mkq_>UDk^71ocI)+5Qc)>4eH5*oU|H5Al&W3=fJcG=5CO>7Lc6`3=H#8)p_y-FinK1 zvteLhSOZnp2vP_3pDW0JE+GFogZ$^hXHdgu;mPNajN!)?1_p*VQ2nz&i6wwfpbzB7 zUXUMqK;hE{@?$fbC!d8k$OMqLQu!==`5cn?ES&fZm;(4LKu-4n^Q!qQg83Z0!EC0v zU`yk`A;I*R&%%$-Arj2-;M0gg2^I#Be@j4x69WT7638FmaPi`kfW)US%)g*GnFCdK z7(^2rCm$S`CozF7$A}XT1_p)?AhQ@47(n5{;Dj0m9()>YtnPdU&1_7;T;LG&ghi+; zwbt~U;_$A1_p*%pm0T`cSlefcHwhi?qmd~GkCgR!N9;!0M+wOh=GB@4V2DY z`6T+7JwWNq6+N9burVKFfim1Ju)Ka?A{%(h60OlYxPO3CSE-*#inL zMg|s!8&Kt-as&j7pOVCpn!svSquyeexNdzfrSAy5)Lv4=6+C_ z26BG{NDx#GL1_>lBn}$82MNJKDh_J?L#X-SvW@{XmI4X~L^#9L7eMX(0y2bw0UqMT zQ1K6F;$={AaB~4keJxZRwA2!$1!g{IECl3E&`=Oa9Of_3svnRzD9s~__e0Iu0TM*= z?-Z!NJfU6ym%|JU4D+DkJkY2Fm!%903?Le0{tq;BHbTt@EzJf=!Q2BH-UP+tcBnbv zvX+5?A(RmmZY&HLAjL@T*$=fhj13|IE^`?e7(mk>AbUZhS|Ayi`M;PT<~V=^85kHq zbtQ-is*^zWUWb|kE_)dm7_LIy`39s2DV#y+8)QDHjt5D>%m+1KLE<3$k;R`w-B}1) z#0o1@85kJeL(PZPvoLc&=>X)O%TV>;vXy~>0W@6)G9RW67Qc+p@B!Hg!Z3MIeF;(z zS_qFUE(lf+H5@5CC86SQ{UA*Y3=E*@M38%?fd}rOCo8BlX!=J-R!LHP_M1v4iS zDh^s(k1QSs74HBEB85*fR6GGq9K>a2fSC&7AuuxoBAgMTpmL7~nG0s8gUbtO;s=XB zh#aUm%$*QX28KeY_#~JBlrDpcgYqj>2uxK&#X-{tU;!urT8{{7t%5qGP$4h{ny&_l z-vaXxL>JT?SiXSC^h3qp!33c66sS0?9D@oo%!G>nh6zCF`A~7tzynkWOf7|qbAf5F z5SUmE=Cd;Jf@!c2m;iN=LGBkv6Wu}j;}8$PAs&uHJf4|>L5P8oL5dHOKEQn<1_p*a9O`Ruh)>2Lz5<8% zb{yiT!0th`2f+O;1_p-nIMjRMh~H~C)W5+Y{t<`xZye&>EZEbJJPvUk9OA|}#656` z2jdV=!y%rFL%arucn1#gxj4iZ;}BnmLwpYo@l!a&Z{QGrfJ6Kh4)L!z#F<#J$0IKe zaS0sasyM_=afmzP5DE*aY~0Ef5`bSw~(s}UrqeS@w1fh^C|OJ>MRttcrf%}ZrS zE-fm~FJb^M%w05MWhb24)?OHzx98FCXV;!9F1 zO3E2BOHy--8B&VM8FGpW537;?)Qz{@+!86XRL%RyEa zfgQk5P?TE6P?VaOQe2Xfna2QHJPTh?3tolFkWx?y76vaJWk@MXEC*T2P@I|r=781_ zGvsDKjb_MAEJ@BtEoMm0NlnZvEnq0h&o6-pGL+grRJ5CXXb&HvlcLv zmZVuQRAeSI==nGsfCxhnVFV(KL4*m2Fa;52Ai^9(Sbzvi5Mc<>0@h;))?^6QWeC=0 z2-ar^)@TUUX$aP82-a%^)@uaTYXsJ71lDT=)@uaTYXsJ71lDT=)@uaTYYf(F4AyH5 z)@uybYYf(F4AyH5)@y9eP+XFdT2#c4R!~|}%#d1%7Fg{NkL{)B=VG_tX+k&$)B@6<}LP+C!HDnmqYWnMBvgmX@QajFY+ ztu)A4Macz~Aa{Y>UXq{9keiwd$}!-iTv3!-oL^d$oLbBfQIzYMmsygTn3GwR$`BC* zmGDi>OH5BK3N9(i%u5F;a!)ORa9k2g5|a{(Q=x(|4Ir*dYH>+XekEK*Zek`l&_UrH z@9yL8pUF_1S^`-n&JYm{StnlX170@H0174u(-*c# zoFT%$AT(c+S#l6+98r$U!$JHnTNgF`5}C^fMJ5~8qJh6-gCCzg~zg0VO`Hy$b) z;h9>9oHllAp^Ek(rlTl$e_sSejZ?84S)$#S9T{;4lY^g&>##`I#V%3=z&?3!zKK zLC$y1Nh~h*$jmE&INZ}0rpD8mA;LGYASf}jI5h?2)11^~ND=|NyeJj4R-7TiFSVk? zwJa5+-z_tzB((_2$xZUf&(AI`fJ6#Ie0*|AWkG6uQhZK6C^h8gm8BMy1gC-w&CCbK zLSAw~B{&^ITo+K3UyxcKAI95k;0 zVuHFUb_@&*e?U{^|Ns97jbp;ZK`Z27;+`Nu=y+8slKNmI@iZjyOeFDiB=LGAanRTs z%>21fagcjJV=ORtf~LelQt0BFL4x2hFv!>@%)cj*#H~T@h4$A#OU^-3AhSVkgW3BC zB#6bF*J$D}_pn0E1Gxv;d{BJ}(t>Wj9FlsF9L$~SNaD!m=s?9mYLVRu+D`;BA7n2` z4rY!gR6V*lYz_(}j%&|CpT4rb0PBy&J{0T#bsk;Fl6 zf{ho!`tdOL!0d&LM?lO6%>}^Bfs98$#6jl3#;G9V5eRYEI617}4>KP&o-YFu0HsUl z*gedA$an<89GH8wpz1*sXp9-A-Vh{!lx|_+UR%y=J0hun4;2TQlZPb!2T2^c+ynK)k;4b(9wm?g&@j$NGRGWA9JyYzgNlRP z>4c=-6Dkg(klhmi5SK&;}AfQV%Pa z`f!NvLKBCXzaJ_NqL9fy>DntrTb?8(E zD4aoZphaIG|9hf|*MI~W7#PZ-;vls}NanO6iG$`uVeXj#6$hE`jHG@#R2*auay+g< z5=VCDE2ucg9FQKEd%i=(L1HCH=Kq6=!_tm;xKb0pyD8NN|DS_K@vyy zmp)V+WDcl}2lKBPR2*auvcJ5M#F71#4HXBO1JW}G^9R2*bJvin`2;xO}J;T()64zo83O&k{fNoe9Qd$Z8QVeO?7 zs5rS6veK@*3WV~r*b3ugzYILLhDaC3u-!_0?; zPdJ)5%={dvILI92{89!L2bqJMej1R(L3&{Az%Dd#SUYeUnm8<7%|#Q3xpOC)I4pf0 zM-zv+{~VGya)0Csk~qknuylI|Dh?7uj^9U6agcvOaw#Og$`oxS`@8^O4h`AXFS(y&Rf2EF4tP#9`@E4^15A9y_Qw$X?|1=?)c# z*$b=pgVDrc_C}$J!`gv~XyPz?%hAMP;nsvE4r*(HS{i+5;;{DQWT-gE{Z&Zqp9M(b z)kxxNq2e%q!Q8V6Dh@ISWHzjQvJ)x}QxB2@x#s{>9Hbt!))1!tI8+>6JtH?r7oxoc zt7qk*;vjQCV~j9!)S%)Zb6kVCiSGdg8Uq8veKheSQ1SO@;;?x93l&GVR~Fi^gxL!VH+>{= zP}+xyhaicA%!0Wm4^13qZwZn($Q+O!kW(9x#6e;(_fJ9-hnYVcO&sQ)HAv#f=Kn(y z2bm9R4{$&S?qU9gnJOp%9VCF|7iG$Wm!^E?o;vjR}kjyVc5_d-u zuYrn#%m?i~gPGF@6$hCE+9jt0O0*0N43nYaAoa-OS4*MdAoa-hu0aw9?U#U=zZpp! z+58<)agh1Q?l}b&2bm9250VEt={!^%#7B0|L#Q}NJ+gaVAc=$Ko?z~Ik0g$4{uih? z$b4k?u!upr!?)(JR2NDPQ9cDgke+I}LQ2!bx&Vn=_ z2iofe6X$`7gUmq=H_&<`kQE?tWb0f~duBAWx-j{{Nz5+w6MaRPHs4OASY7TKI0 zs5s0V*j~&TNaCP62WHL!s5rVgp!0)4?u3~G+J6V)gU@${#(OA|zYgLs=OR=bW)7@= zxrHPihGY(Goi)09VC$)2=9qvS!@$7s8_68d9xRx@m_Z7$svU4JmJKsXZK@><1rXI9E5Tp+z2HML43kLyEVT9yQ!fJ*2bqH$ z4(RizuyC-1s)xA;<}Z6RaacIGK*d4kPe$^WH&h&E4k*uq`~zB_4WdEnn~>Cl)@Osn zVd`P!Pa@PDkb2~LJOe5YQV**4Vfi{ANgSjHR{m5%#X(}o<}^UXVdjA3LGEZr5(kOF z%Abi)agZ3YImq+KAosw+A9St{$UKnwAU!a5uEb%^2BJB3u;;?yhkQpEhGY5Iz9JI$37C!Ds=77QzCJtJ^4hkQT86YK~HVufM1mZy5 z31Y(hTMXhr%Sq5)UYI$cb?P8}Aajt-??qCN9G+94;xP44F2hVH14JRKUjPz-x(8%F zEd4Bnii0R*^=m)^Na|tfb|X|AL?Nr+0TO_!2Qgvg&p{9eDjts%kH?_mAZj|2_*swu zR6U3ZGv^wJ0~H7DO@xKpT_kZ36VxUHh2tX-2O7@E=D&oBgTf8OgvHAT5C>{LhzSdy zpCAsBIINw`22FP$b3jQA<{l9wagbKnIIR?#IBeWi6Dkf;i#*=04;2TQ50ZoB3pX@z zSb6S?CJw7dg3-ib^Oy-};;?Yef{KIe1ns$k`KuNx4s#Do{UoS3NIl3cF!eK_;vn^) z@BzgM2ya0Whv@-{--L>T#AYI;ho?|+kU1bZkR2fP-_XQi?%{*ZYlGCzLNZ4hDh@LT zrd}H=4pNU?FQ0>ogVclE4_#LF{}qxrNDs`Mk7(jBck)8#F+plUeJ)t|^h3o#=7Vr2 zwB0!sNgSjH7GFz{#F5pnLJ~(-e;7#|S^Y^Qab)#3ki?PI-$N2dRu4L_4-^j|wIFfW zd;vGwJRK~Z!{%W@YLVkt6HPrV-5Q{Y!@}7XDh@ISIlerg;xPBX%<)GOM{Y-jK*d4k zAlGY=P;rnsAPkF_cqDO<9$38OA&DcaFF_JVR^Nssj;y{1NgP@IY$S1H^$U^2k=1WS z6NkmiX*6+Iyxc$&hp9)OhlTaGzoDsziT_3t2e}hAZo-5%Uk0lmMbN}y?vX|lhq*@$ zO&k`#mT2OzbP@>_2Zar2tQVH=QlR1>H-h9~>Wk6DL46)j`mTnGgVci7gu~2ff{LS? z(+d>`sRx}I0aHH(Dh^W*Gk-3UIA|;grhW;MIOu#DnD}-i@nod(Z4Xo&WH0DU37GoB zP;qp7Poas!!r>yCI4IA6!r>ZJ9ArM|%n6wJccJ3w=08IdhnbH&-wGPbf|-Lp-wInt z#||BTgP9MDcRn<6nE4V=agaMf$H2kN*My3rn`3|`4l~CdDh@ISxgJS|io?u-#bXYd zILw?%s5rLAw?LiU;>4Ev{2vi&-1{yPjh4VEeanKqEnD`&4ILK^}9$30U zo+kzEt$?XN2%UF>sR!j@P&zz;CJvi_xds&nnTL{8xO#L||agZKZ z`F{&Z9NC;FNa7&%lc4+`P#Po#!Z3IKM-m6QA2x2wgEY^AypCD{Dh@IOgkk2ZBZ(us z#~4i<<}WKWaacG6A&G;`hq*HnNgUaoX;5*HoyhL2gNlR90AZLr+mXaUdSLyIiD=@m z^e`7q9F}g8=hr~y!1_n9c{GsNa-?$LB$7E`_kc1TXx8A`${4ywz85kHE(8OWpOhOU|_3vQob(i80-;5*<@-NJs3pm8Dqlv@9;RTvF zEd0NqiG%7+kQe@#*QQo zvIAD13L}Yw%!1VmT4>_1dcg-O4pO@kshrP75=X9&YLUc|-Pr*Z2e}1=Vddl`s5r=c z_+LE;CY;?U*~T)Ycv4m8`r#ZN-j!^S~j=AVU%!_L`*iC=_@!{#es z;#Z;K&}0EO|0Yx%HZK8Fe-|naI;$4hUk{<;uyJ>o`lnEF(7B+<>R&>|Ve3l# zpmS@H)qjMF!}{wm^#`E!J!lOrvihG;^~mcYK;f(etGJR-XtJhn4p*_03RwVdsFt#51AlVf80Wyb2m_uya6R z;)PK4uyz(q+yRk$g|%N`;;`}uc3vh-99I6o)~mwAk3#d&1(0W<^#Uj# zU51(us~=$M6`<|`o!1G{0uw(3^%rd3045GAe_-R6FmYR`Ik53Om^iE*4{N`}#9`|i zVf|g0crmo#gw1=v#J51jVe{}X@o;Fph`c@r3n~sP&tc+0P;rKn$gT!Iy3?rATAaT$d z7myz0at0(0nwtcPBj-DiIP5%O>Sz!XyUN*X1}0`!_Iwm05wvP%z>RFSArxC zN}r&x0b{-5%G{E~BnCauDKcO>1I8*!%}LY)pTVP-l30?+pqEr!%%E4458{B78|oP{ z=)o1~6_+Fym6R4hg&@kH9I%d})EqRf9{9u?2EF9`++5J%E_!+SC8>JuexbVH1BDnM z{Pet1y#m-dEfD)sGvd>V5_3Tdb-41TO;Q_P(B@8}Cm;rtQEi7NDLB*lb1K0iqYA+}+!UdsrA@f1)Cy*L+{osoS zKnfK>1OkKni{LRZ7((qwNfRIi&;kLrz6vA+!l1B1ra^lmKw{|OmjZ3~!p;i>=>cJo zS`ZDxpl}1Vc|kNx3`9QwE#d(6e?bR|GcYiK!VhEz$gd!ISone3O&~L&*#RU4#v$N4 zvl$rB&!Gj`1y%qhKx+s=V(9iKfHu#7?r8v73bh|(Hwc5Y!t4hnL6H6E;hzACSO(0q z>|pvqW`HoL9f!^S37|#tAp1dzp!S2RR+xU6{h;<3Hv0>p_QTr6P-8%s)5Dlx8ni|S zoBao%_QT3gQ22xT8tC?e+G`;DVdXp6PzDBu6;S(O>tJExAhjSij0UYCgt0;5Fnk-T zAI68#=xRZ8TA(Rj^!R@O)eoyLVESS1hw(w{e?exV>o-t`sE_~!4ulCN(e;DcX&@!& z=_dmeFrf4cG8`Izpei1w9~OTgX>_|m7I|ocNCpNAXg&n>+dyr5bp4=dD)h7m(%AqS pv}9mlfUSD~iGeW4J`fGVAU9#t{{pnRf`NenbbdQbEr>?f4*;^;HLL&t literal 0 HcmV?d00001 diff --git a/drw.o b/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..51a85f2fb2606a81148a66b7016045878c40b51d GIT binary patch literal 10392 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 literal 0 HcmV?d00001 diff --git a/stest b/stest new file mode 100755 index 0000000000000000000000000000000000000000..d45ab82c8480f0f0720b80645f2c5b4c7b3da514 GIT binary patch literal 16392 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 S{$taxYYtH%g{A?G%K!kcF*>OL literal 0 HcmV?d00001 diff --git a/stest.o b/stest.o new file mode 100644 index 0000000000000000000000000000000000000000..285b13f5140291a1a21079cbe75b32adef91b13e GIT binary patch literal 5360 zcmb<-^>JfjWMqH=Mg}_u1P><4!0r5qtvstWb>4p3Z|=z^mh5nB9H4)AX~@LFsiD7q2CC8u5*|NH;n66~!KC8!Z4 z?1ulrp?n-H4l>ZA^F3I^qq_y19#TBCS-=UTgcTy*cm$MgqGJy;Fff!BC#I)bDX11J zMC&FdC8wmOrDx<66c!bimX%k;Dn#q%DWqlQq=H!aFcwHaPfstFivdFigKDw9YB9rS zez{+c;f`UBp^hP;!5)oo7z7v?Jeqk_7(ANaXt)|4@afeB#ZHPxH^gZkoh>R70t^hG z1kdKv>7v5n(VNEsVhFhOrvLZo1pCgTyOzPD^*?_L6C(pdgS{?)>rVy-hAwx;mIM4P z?-&>uY;;S78tR!CN_jk*k8(KvKlAbiD4zZw_w0Occ)+8xmZ3|$KPeI`8>PhIXqf#mvTb_t~Z|XHM`^g zGoH=IIXrqzK|W~sl~>9RWqWkqcWi!_2v+Nx{H^r>Bqp6ZUA8imvV$Z0wE-+bU%z+h z{N~XM&XZsr9<2vTW`Oh?9`H^6=6u{`E4Tph?B@6Atz`7o}EWQPRa9uC8O2@r8001Bv?!0V9C$@^)Zj$2w|Vz5*3L6!vn!S z-M$PvL9x9HloWk>!SS{aB;eEe9c)`vr0sux28Qza9-a4KVy`EGqZa0@nT7|T=JQWE z;L$w=oHSBAv_;U8v4#KxLv*ZTjAN{0oMZf926ty?D+LYr)Vz}Xd<8>OJtIBC_yQvX zBQpadLlcDpQ%$I#0!)m70hEtHMKZ{p?tY;RObiSMKw`|G$Yp@YD=;uHAmkar@*v-V zlrS=&@}Ka&%mL?5#g zpF%H-6Q4#8t0SL58=E7aMKilQ-wp*&z6T1-HyQa}C^++dP)O!`q2S2(K!M4Z&%%+< zz>!bGiBG|aPr`{$z=@9oYBDAT@-GX+$N!iz3=GWRgo-J{3=UmXaZUyX1|}r+;ILp| zVBm*}!}#EEU|?VXg(o8e3qu0P0SpWb8BpUSL1E0m!T^dJkkAAW!N9;E3l%>A<-^1k zq2ec?=78cDs)T`=feprl)9PRrDAvIYIH3b(u`<|!X#`;iX0kE_fN2C_#=rnd{0IRk z3zY8#k-`TS^3FKa2jUQq!yz7qLp&CTcrp%gP&S}ug4+21BW<6aY<@%iC!|K!ejt(7}9bQ(;4zo%Ng=> zQW$a*OOi7f^n9ERK!hQPFk&b!Nl7g#Vn{4XFEe0>k54No%FHWCi%-tTW=O5bEMZ7Y zPEIW@X2>ZnNi1O~C@m>wh>tHWNleZLDTz-@%*8H^%t?oe??)5QhKip+6VHc=Ux$i=+%Jse z{$EgWn7zeN^?XnoCSDHZi$iIcct4b{1EoRcgUU8oID|mOVd`Q2Pel`-4CTYz3sWxw z6>osjF!AY7{#+;x6Q2*|FN4xB@x@R+xU~YU|B%DsGE^R>el?W;97@B)H$(X!pfpT; zJCx4~62M}<3=VN^s5poM#qS2FImRFXq*p32EF2vA_$!UV-=<5B=ydc`G)MJ1&L40_4=xw)x%B@B9b`6a1(?tY=V z;JOFOPtPmWD=5k@NG&RrK|BQBie@iN24n_| z4WdEqK#-YGYd}I^yaTHL44MXzf58f%1gO0TQep(5VLhPOlY!}u^7U2P5n0|PrW|G?CM=p9h~=2ySAfD1rUpcV1~EXi2Z(^CKTtahrXLo5ApfA- z4bpM~YQF?D9zks}5JuO}$$*)5LHZwnBp4VNj)OQz7-Sz3mjP5KLajg+W=H@v<`@_l N`cOm}ka}zo2>@33gGm4Y literal 0 HcmV?d00001 diff --git a/util.o b/util.o new file mode 100644 index 0000000000000000000000000000000000000000..3b3f2b7cce5bcc62950c033fd8306ddf246bae37 GIT binary patch literal 2288 zcmb<-^>JfjWMqH=Mg}_u1P><4z)--7U^{@B4h(z@ybPcD<$i?*dvyNxXnb>nfq}uJ zvqVM1qccRsz@yVg#lol4Ma99V(?`XlN&>%Th)My!<{Xs<1_lOx z%_S-m!1NlG1z>uM$_6mKN96zm14D{OH;bwU*l-sW3Bv;(-L@bXcyvDW=)C38+oJM; zfq`Kk$koSLR5+mOI6Qh?R1}W8sIVA7MFd`eb#?24s0M3>5>=1R`(Uw#8s`62rD7hP z@AfM&Fff3{4F7|v*SsK6E|}i_ zfEXA+>74oy2^K)}k^GX=>^72bk z_1yhJb&E?9le3}x^t@8Nf};F_)S{9~20gHWsTuKUMTxnoAlFciLH-2=1t@NjO@sMY z3?zvpfyQN!hL#;L^)RJ7K!MG`z`z03z|Ft_&V8V`1gQb#FA%K;6^AMZ34w7KR3Dgw zM4$`nfb3uZl?6zO7#J9c)o%#3-w0JZTtCdcFlm_mFdF1<5F1n}z|?@~IFKL%1A{S$ zgM^{N;IIG*dqV98v61mam_lShENUYe7#KkL43s93mCk_b4?q@#h840~q6#Xrazbh|