|
|
@ -34,22 +34,6 @@ struct item { |
|
|
|
bool out; |
|
|
|
bool out; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void appenditem(struct item *, struct item **, struct 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 char text[BUFSIZ] = ""; |
|
|
|
static int bh, mw, mh; |
|
|
|
static int bh, mw, mh; |
|
|
|
static int sw, sh; /* X display screen geometry width, height */ |
|
|
|
static int sw, sh; /* X display screen geometry width, height */ |
|
|
@ -215,6 +199,59 @@ grabkeyboard(void) |
|
|
|
die("cannot grab keyboard\n"); |
|
|
|
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; |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
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 void |
|
|
|
static void |
|
|
|
insert(const char *str, ssize_t n) |
|
|
|
insert(const char *str, ssize_t n) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -228,6 +265,17 @@ insert(const char *str, ssize_t n) |
|
|
|
match(); |
|
|
|
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 |
|
|
|
static void |
|
|
|
keypress(XKeyEvent *ev) |
|
|
|
keypress(XKeyEvent *ev) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -398,70 +446,6 @@ keypress(XKeyEvent *ev) |
|
|
|
drawmenu(); |
|
|
|
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; |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
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 |
|
|
|
static void |
|
|
|
paste(void) |
|
|
|
paste(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|