summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustaf Rydholm <gustaf.rydholm@gmail.com>2021-12-26 14:16:59 +0100
committerGustaf Rydholm <gustaf.rydholm@gmail.com>2021-12-26 14:16:59 +0100
commitf0da9217a70ae3a6a16c08056cc4d90eba740949 (patch)
tree61fe63e20cdf07436b132e808456035f750631b5
parent07d64a9a936fa917747437c4e05100415c9f72ea (diff)
Format dmenu.c, update colors
-rw-r--r--dmenu.c1744
1 files changed, 873 insertions, 871 deletions
diff --git a/dmenu.c b/dmenu.c
index bde0869..54e1bc2 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -8,8 +8,8 @@
#include <time.h>
#include <unistd.h>
-#include <X11/Xlib.h>
#include <X11/Xatom.h>
+#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
@@ -21,10 +21,11 @@
#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)
+#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)
/* define opaqueness */
#define OPAQUE 0xFFU
@@ -33,9 +34,9 @@
enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
struct item {
- char *text;
- struct item *left, *right;
- int out;
+ char *text;
+ struct item *left, *right;
+ int out;
};
static char text[BUFSIZ] = "";
@@ -67,929 +68,930 @@ static Clr *scheme[SchemeLast];
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
static char *(*fstrstr)(const char *, const char *) = strstr;
+static void xinitvisual() {
+ XVisualInfo *infos;
+ XRenderPictFormat *fmt;
+ int nitems;
+ int i;
+
+ XVisualInfo tpl = {.screen = screen, .depth = 32, .class = TrueColor};
+
+ long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
+
+ infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
+ visual = NULL;
+
+ for (i = 0; i < nitems; i++) {
+ fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
+ if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
+ visual = infos[i].visual;
+ depth = infos[i].depth;
+ cmap = XCreateColormap(dpy, root, visual, AllocNone);
+ usergb = 1;
+ break;
+ }
+ }
+
+ XFree(infos);
-static void
-xinitvisual()
-{
- XVisualInfo *infos;
- XRenderPictFormat *fmt;
- int nitems;
- int i;
-
- XVisualInfo tpl = {
- .screen = screen,
- .depth = 32,
- .class = TrueColor
- };
-
- long masks = VisualScreenMask | VisualDepthMask | VisualClassMask;
-
- infos = XGetVisualInfo(dpy, masks, &tpl, &nitems);
- visual = NULL;
-
- for (i = 0; i < nitems; i++){
- fmt = XRenderFindVisualFormat(dpy, infos[i].visual);
- if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) {
- visual = infos[i].visual;
- depth = infos[i].depth;
- cmap = XCreateColormap(dpy, root, visual, AllocNone);
- usergb = 1;
- break;
- }
- }
-
- XFree(infos);
-
- if (! visual) {
- visual = DefaultVisual(dpy, screen);
- depth = DefaultDepth(dpy, screen);
- cmap = DefaultColormap(dpy, screen);
- }
+ if (!visual) {
+ visual = DefaultVisual(dpy, screen);
+ depth = DefaultDepth(dpy, screen);
+ cmap = DefaultColormap(dpy, screen);
+ }
}
-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 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 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 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;
+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;
+ 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 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;
- char *censort;
-
- 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]);
- if (passwd) {
- censort = ecalloc(1, sizeof(text));
- memset(censort, '.', strlen(text));
- drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0);
- free(censort);
- } else 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 drawmenu(void) {
+ unsigned int curpos;
+ struct item *item;
+ int x = 0, y = 0, w;
+ char *censort;
+
+ 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]);
+ if (passwd) {
+ censort = ecalloc(1, sizeof(text));
+ memset(censort, '.', strlen(text));
+ drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0);
+ free(censort);
+ } else
+ 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 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 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 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;
-
- static char last[BUFSIZ] = "";
- if(reject_no_match) {
- /* store last text value in case we need to revert it */
- memcpy(last, text, BUFSIZ);
- }
-
- /* 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();
-
- if(!matches && reject_no_match) {
- /* revert to last text value if theres no match */
- memcpy(text, last, BUFSIZ);
- cursor -= n;
- match();
- }
+static void insert(const char *str, ssize_t n) {
+ if (strlen(text) + n > sizeof text - 1)
+ return;
+
+ static char last[BUFSIZ] = "";
+ if (reject_no_match) {
+ /* store last text value in case we need to revert it */
+ memcpy(last, text, BUFSIZ);
+ }
+
+ /* 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();
+
+ if (!matches && reject_no_match) {
+ /* revert to last text value if theres no match */
+ memcpy(text, last, BUFSIZ);
+ cursor -= n;
+ match();
+ }
}
-static size_t
-nextrune(int inc)
-{
- ssize_t n;
+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;
+ /* 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 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;
- }
+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();
+ drawmenu();
}
-static void
-buttonpress(XEvent *e)
-{
- struct item *item;
- XButtonPressedEvent *ev = &e->xbutton;
- int x = 0, y = 0, h = bh, w;
-
- if (ev->window != win)
- return;
-
- /* right-click: exit */
- if (ev->button == Button3)
- exit(1);
-
- if (prompt && *prompt)
- x += promptw;
-
- /* input field */
- w = (lines > 0 || !matches) ? mw - x : inputw;
-
- /* left-click on input: clear input,
- * NOTE: if there is no left-arrow the space for < is reserved so
- * add that to the input width */
- if (ev->button == Button1 &&
- ((lines <= 0 && ev->x >= 0 && ev->x <= x + w +
- ((!prev || !curr->left) ? TEXTW("<") : 0)) ||
- (lines > 0 && ev->y >= y && ev->y <= y + h))) {
- insert(NULL, -cursor);
- drawmenu();
- return;
- }
- /* middle-mouse click: paste selection */
- if (ev->button == Button2) {
- XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
- utf8, utf8, win, CurrentTime);
- drawmenu();
- return;
- }
- /* scroll up */
- if (ev->button == Button4 && prev) {
- sel = curr = prev;
- calcoffsets();
- drawmenu();
- return;
- }
- /* scroll down */
- if (ev->button == Button5 && next) {
- sel = curr = next;
- calcoffsets();
- drawmenu();
- return;
- }
- if (ev->button != Button1)
- return;
- if (ev->state & ~ControlMask)
- return;
- if (lines > 0) {
- /* vertical list: (ctrl)left-click on item */
- w = mw - x;
- for (item = curr; item != next; item = item->right) {
- y += h;
- if (ev->y >= y && ev->y <= (y + h)) {
- puts(item->text);
- if (!(ev->state & ControlMask))
- exit(0);
- sel = item;
- if (sel) {
- sel->out = 1;
- drawmenu();
- }
- return;
- }
- }
- } else if (matches) {
- /* left-click on left arrow */
- x += inputw;
- w = TEXTW("<");
- if (prev && curr->left) {
- if (ev->x >= x && ev->x <= x + w) {
- sel = curr = prev;
- calcoffsets();
- drawmenu();
- return;
- }
- }
- /* horizontal list: (ctrl)left-click on item */
- for (item = curr; item != next; item = item->right) {
- x += w;
- w = MIN(TEXTW(item->text), mw - x - TEXTW(">"));
- if (ev->x >= x && ev->x <= x + w) {
- puts(item->text);
- if (!(ev->state & ControlMask))
- exit(0);
- sel = item;
- if (sel) {
- sel->out = 1;
- drawmenu();
- }
- return;
- }
- }
- /* left-click on right arrow */
- w = TEXTW(">");
- x = mw - w;
- if (next && ev->x >= x && ev->x <= x + w) {
- sel = curr = next;
- calcoffsets();
- drawmenu();
- return;
- }
- }
+static void buttonpress(XEvent *e) {
+ struct item *item;
+ XButtonPressedEvent *ev = &e->xbutton;
+ int x = 0, y = 0, h = bh, w;
+
+ if (ev->window != win)
+ return;
+
+ /* right-click: exit */
+ if (ev->button == Button3)
+ exit(1);
+
+ if (prompt && *prompt)
+ x += promptw;
+
+ /* input field */
+ w = (lines > 0 || !matches) ? mw - x : inputw;
+
+ /* left-click on input: clear input,
+ * NOTE: if there is no left-arrow the space for < is reserved so
+ * add that to the input width */
+ if (ev->button == Button1 &&
+ ((lines <= 0 && ev->x >= 0 &&
+ ev->x <= x + w + ((!prev || !curr->left) ? TEXTW("<") : 0)) ||
+ (lines > 0 && ev->y >= y && ev->y <= y + h))) {
+ insert(NULL, -cursor);
+ drawmenu();
+ return;
+ }
+ /* middle-mouse click: paste selection */
+ if (ev->button == Button2) {
+ XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, utf8,
+ utf8, win, CurrentTime);
+ drawmenu();
+ return;
+ }
+ /* scroll up */
+ if (ev->button == Button4 && prev) {
+ sel = curr = prev;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ /* scroll down */
+ if (ev->button == Button5 && next) {
+ sel = curr = next;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ if (ev->button != Button1)
+ return;
+ if (ev->state & ~ControlMask)
+ return;
+ if (lines > 0) {
+ /* vertical list: (ctrl)left-click on item */
+ w = mw - x;
+ for (item = curr; item != next; item = item->right) {
+ y += h;
+ if (ev->y >= y && ev->y <= (y + h)) {
+ puts(item->text);
+ if (!(ev->state & ControlMask))
+ exit(0);
+ sel = item;
+ if (sel) {
+ sel->out = 1;
+ drawmenu();
+ }
+ return;
+ }
+ }
+ } else if (matches) {
+ /* left-click on left arrow */
+ x += inputw;
+ w = TEXTW("<");
+ if (prev && curr->left) {
+ if (ev->x >= x && ev->x <= x + w) {
+ sel = curr = prev;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ }
+ /* horizontal list: (ctrl)left-click on item */
+ for (item = curr; item != next; item = item->right) {
+ x += w;
+ w = MIN(TEXTW(item->text), mw - x - TEXTW(">"));
+ if (ev->x >= x && ev->x <= x + w) {
+ puts(item->text);
+ if (!(ev->state & ControlMask))
+ exit(0);
+ sel = item;
+ if (sel) {
+ sel->out = 1;
+ drawmenu();
+ }
+ return;
+ }
+ }
+ /* left-click on right arrow */
+ w = TEXTW(">");
+ x = mw - w;
+ if (next && ev->x >= x && ev->x <= x + w) {
+ sel = curr = next;
+ calcoffsets();
+ drawmenu();
+ return;
+ }
+ }
}
-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 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;
+static void readstdin(void) {
+ char buf[sizeof text], *p;
+ size_t i, imax = 0, size = 0;
+ unsigned int tmpmax = 0;
- if(passwd){
+ if (passwd) {
inputw = lines = 0;
return;
}
- /* 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);
+ /* 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, win))
- continue;
- switch(ev.type) {
- case ButtonPress:
- buttonpress(&ev);
- break;
- case DestroyNotify:
- if (ev.xdestroywindow.window != win)
- break;
- cleanup();
- exit(1);
- 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 run(void) {
+ XEvent ev;
+
+ while (!XNextEvent(dpy, &ev)) {
+ if (XFilterEvent(&ev, win))
+ continue;
+ switch (ev.type) {
+ case ButtonPress:
+ buttonpress(&ev);
+ break;
+ case DestroyNotify:
+ if (ev.xdestroywindow.window != win)
+ break;
+ cleanup();
+ exit(1);
+ 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"};
+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;
+ 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, colors[j], alphas[j], 2);
+ /* init appearance */
+ for (j = 0; j < SchemeLast; j++)
+ scheme[j] = drw_scm_create(drw, colors[j], alphas[j], 2);
- clip = XInternAtom(dpy, "CLIPBOARD", False);
- utf8 = XInternAtom(dpy, "UTF8_STRING", False);
+ 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;
+ /* 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
+ 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.border_pixel = 0;
- swa.colormap = cmap;
- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask |
- ButtonPressMask;
- win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
- depth, InputOutput, visual,
- CWOverrideRedirect | CWBackPixel | CWColormap | CWEventMask | CWBorderPixel, &swa);
- XSetClassHint(dpy, win, &ch);
-
-
- /* input methods */
- if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
- die("XOpenIM failed: could not open input device");
-
- xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- XNClientWindow, win, XNFocusWindow, win, NULL);
-
- XMapRaised(dpy, win);
- if (embed) {
- XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
- 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();
+ {
+ 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.border_pixel = 0;
+ swa.colormap = cmap;
+ swa.event_mask =
+ ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonPressMask;
+ win =
+ XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, depth, InputOutput, visual,
+ CWOverrideRedirect | CWBackPixel | CWColormap |
+ CWEventMask | CWBorderPixel,
+ &swa);
+ XSetClassHint(dpy, win, &ch);
+
+ /* input methods */
+ if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
+ die("XOpenIM failed: could not open input device");
+
+ xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+ XNClientWindow, win, XNFocusWindow, win, NULL);
+
+ XMapRaised(dpy, win);
+ if (embed) {
+ XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
+ 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 [-bfiPrv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
- exit(1);
+static void usage(void) {
+ fputs(
+ "usage: dmenu [-bfiPrv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
+ " [-nb color] [-nf color] [-sb color] [-sf color] [-w "
+ "windowid]\n",
+ stderr);
+ exit(1);
}
-void
-read_Xresources(void) {
- XrmInitialize();
-
- char* xrm;
- if ((xrm = XResourceManagerString(drw->dpy))) {
- char *type;
- XrmDatabase xdb = XrmGetStringDatabase(xrm);
- XrmValue xval;
-
- if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval) == True) /* font or font set */
- fonts[0] = strdup(xval.addr);
- if (XrmGetResource(xdb, "dmenu.color0", "*", &type, &xval) == True) /* normal background color */
- colors[SchemeNorm][ColBg] = strdup(xval.addr);
- if (XrmGetResource(xdb, "dmenu.color4", "*", &type, &xval) == True) /* normal foreground color */
- colors[SchemeNorm][ColFg] = strdup(xval.addr);
- if (XrmGetResource(xdb, "dmenu.color4", "*", &type, &xval) == True) /* selected background color */
- colors[SchemeSel][ColBg] = strdup(xval.addr);
- if (XrmGetResource(xdb, "dmenu.color0", "*", &type, &xval) == True) /* selected foreground color */
- colors[SchemeSel][ColFg] = strdup(xval.addr);
-
- XrmDestroyDatabase(xdb);
- }
+void read_Xresources(void) {
+ XrmInitialize();
+
+ char *xrm;
+ if ((xrm = XResourceManagerString(drw->dpy))) {
+ char *type;
+ XrmDatabase xdb = XrmGetStringDatabase(xrm);
+ XrmValue xval;
+
+ if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval) ==
+ True) /* font or font set */
+ fonts[0] = strdup(xval.addr);
+ if (XrmGetResource(xdb, "dmenu.color0", "*", &type, &xval) ==
+ True) /* normal background color */
+ colors[SchemeNorm][ColBg] = strdup(xval.addr);
+ if (XrmGetResource(xdb, "dmenu.color7", "*", &type, &xval) ==
+ True) /* normal foreground color */
+ colors[SchemeNorm][ColFg] = strdup(xval.addr);
+ if (XrmGetResource(xdb, "dmenu.color7", "*", &type, &xval) ==
+ True) /* selected background color */
+ colors[SchemeSel][ColBg] = strdup(xval.addr);
+ if (XrmGetResource(xdb, "dmenu.color0", "*", &type, &xval) ==
+ True) /* selected foreground color */
+ colors[SchemeSel][ColFg] = strdup(xval.addr);
+
+ 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 (!strcmp(argv[i], "-P")) /* is the input a password */
- passwd = 1;
- else if (!strcmp(argv[i], "-r")) /* reject input which results in no match */
- reject_no_match = 1;
- 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 */
- fonts[0] = argv[++i];
- else if (!strcmp(argv[i], "-nb")) /* normal background color */
- colors[SchemeNorm][ColBg] = argv[++i];
- else if (!strcmp(argv[i], "-nf")) /* normal foreground color */
- colors[SchemeNorm][ColFg] = argv[++i];
- else if (!strcmp(argv[i], "-sb")) /* selected background color */
- colors[SchemeSel][ColBg] = argv[++i];
- else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
- colors[SchemeSel][ColFg] = 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 (!(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);
- xinitvisual();
- drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap);
- read_Xresources();
- if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
- die("no fonts could be loaded.");
- lrpad = drw->fonts->h;
+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 (!strcmp(argv[i], "-P")) /* is the input a password */
+ passwd = 1;
+ else if (!strcmp(argv[i],
+ "-r")) /* reject input which results in no match */
+ reject_no_match = 1;
+ 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 */
+ fonts[0] = argv[++i];
+ else if (!strcmp(argv[i], "-nb")) /* normal background color */
+ colors[SchemeNorm][ColBg] = argv[++i];
+ else if (!strcmp(argv[i], "-nf")) /* normal foreground color */
+ colors[SchemeNorm][ColFg] = argv[++i];
+ else if (!strcmp(argv[i], "-sb")) /* selected background color */
+ colors[SchemeSel][ColBg] = argv[++i];
+ else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
+ colors[SchemeSel][ColFg] = 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 (!(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);
+ xinitvisual();
+ drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap);
+ read_Xresources();
+ if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
+ die("no fonts could be loaded.");
+ lrpad = drw->fonts->h;
#ifdef __OpenBSD__
- if (pledge("stdio rpath", NULL) == -1)
- die("pledge");
+ if (pledge("stdio rpath", NULL) == -1)
+ die("pledge");
#endif
- if (fast && !isatty(0)) {
- grabkeyboard();
- readstdin();
- } else {
- readstdin();
- grabkeyboard();
- }
- setup();
- run();
-
- return 1; /* unreachable */
+ if (fast && !isatty(0)) {
+ grabkeyboard();
+ readstdin();
+ } else {
+ readstdin();
+ grabkeyboard();
+ }
+ setup();
+ run();
+
+ return 1; /* unreachable */
}