X-Git-Url: https://git.armaanb.net/?p=dmenu.git;a=blobdiff_plain;f=dmenu.c;h=1c2e780efc766af060145563efa23c47fbda01ca;hp=cf5d97655d03db9cac670352dee971708813cb6f;hb=5a20b409c673a6736c3f9326cb54edc32908f717;hpb=b048eacc9ddc6ca995783411d4df84c23f3a0351 diff --git a/dmenu.c b/dmenu.c index cf5d976..1c2e780 100644 --- a/dmenu.c +++ b/dmenu.c @@ -7,6 +7,7 @@ #include #include #include + #include #include #include @@ -28,37 +29,20 @@ /* enums */ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ -typedef struct Item Item; -struct Item { +struct item { char *text; - Item *left, *right; + struct item *left, *right; bool out; }; -static void appenditem(Item *, Item **, Item **); -static void calcoffsets(void); -static char *cistrstr(const char *, const char *); -static void cleanup(void); -static void drawmenu(void); -static void grabkeyboard(void); -static void insert(const char *, ssize_t); -static void keypress(XKeyEvent *); -static void match(void); -static size_t nextrune(int); -static void paste(void); -static void readstdin(void); -static void run(void); -static void setup(void); -static void usage(void); - static char text[BUFSIZ] = ""; static int bh, mw, mh; static int sw, sh; /* X display screen geometry width, height */ static int inputw, promptw; static size_t cursor; -static Item *items = NULL; -static Item *matches, *matchend; -static Item *prev, *curr, *next, *sel; +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; @@ -75,7 +59,7 @@ static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; static char *(*fstrstr)(const char *, const char *) = strstr; static void -appenditem(Item *item, Item **list, Item **last) +appenditem(struct item *item, struct item **list, struct item **last) { if (*last) (*last)->right = item; @@ -108,13 +92,13 @@ calcoffsets(void) static void cleanup(void) { + size_t i; + XUngrabKey(dpy, AnyKey, AnyModifier, root); - drw_clr_free(scheme[SchemeNorm].bg); - drw_clr_free(scheme[SchemeNorm].fg); - drw_clr_free(scheme[SchemeSel].fg); - drw_clr_free(scheme[SchemeSel].bg); - drw_clr_free(scheme[SchemeOut].fg); - drw_clr_free(scheme[SchemeOut].bg); + for (i = 0; i < SchemeLast; i++) { + drw_clr_free(scheme[i].bg); + drw_clr_free(scheme[i].fg); + } drw_free(drw); XSync(dpy, False); XCloseDisplay(dpy); @@ -135,7 +119,7 @@ static void drawmenu(void) { int curpos; - Item *item; + struct item *item; int x = 0, y = 0, h = bh, w; drw_setscheme(drw, &scheme[SchemeNorm]); @@ -216,6 +200,60 @@ grabkeyboard(void) die("cannot grab keyboard\n"); } +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\n", tokn * sizeof *tokv); + len = tokc ? strlen(tokv[0]) : 0; + + matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; + textsize = strlen(text); + 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) { @@ -229,6 +267,17 @@ insert(const char *str, ssize_t 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 keypress(XKeyEvent *ev) { @@ -272,6 +321,7 @@ keypress(XKeyEvent *ev) 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; @@ -399,70 +449,6 @@ keypress(XKeyEvent *ev) drawmenu(); } -static void -match(void) -{ - static char **tokv = NULL; - static int tokn = 0; - - char buf[sizeof text], *s; - int i, tokc = 0; - size_t len; - 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\n", tokn * sizeof *tokv); - len = tokc ? strlen(tokv[0]) : 0; - - matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; - 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(tokv[0], item->text, len + 1)) - 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 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 paste(void) { @@ -639,7 +625,7 @@ main(int argc, char *argv[]) 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 */ + } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ topbar = false; else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ fast = true;