Don't match items in insert
This commit is contained in:
parent
48f4a1d2ed
commit
7284f5958b
1 changed files with 105 additions and 104 deletions
209
main.c
209
main.c
|
@ -106,18 +106,6 @@ struct menu {
|
||||||
struct page *pages; // list of pages
|
struct page *pages; // list of pages
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
|
|
||||||
cairo_set_source_rgba(cairo,
|
|
||||||
(color >> (3*8) & 0xFF) / 255.0,
|
|
||||||
(color >> (2*8) & 0xFF) / 255.0,
|
|
||||||
(color >> (1*8) & 0xFF) / 255.0,
|
|
||||||
(color >> (0*8) & 0xFF) / 255.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void insert(struct menu *menu, const char *s, ssize_t n);
|
|
||||||
static void match(struct menu *menu);
|
|
||||||
static size_t nextrune(struct menu *menu, int incr);
|
|
||||||
|
|
||||||
static void append_page(struct page *page, struct page **first, struct page **last) {
|
static void append_page(struct page *page, struct page **first, struct page **last) {
|
||||||
if (*last) {
|
if (*last) {
|
||||||
(*last)->next = page;
|
(*last)->next = page;
|
||||||
|
@ -183,6 +171,102 @@ static void page_items(struct menu *menu) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char * fstrstr(struct menu *menu, const char *s, const char *sub) {
|
||||||
|
for (size_t len = strlen(sub); *s; s++) {
|
||||||
|
if (!menu->strncmp(s, sub, len)) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void append_item(struct item *item, struct item **first, struct item **last) {
|
||||||
|
if (*last) {
|
||||||
|
(*last)->next_match = item;
|
||||||
|
} else {
|
||||||
|
*first = item;
|
||||||
|
}
|
||||||
|
item->prev_match = *last;
|
||||||
|
item->next_match = NULL;
|
||||||
|
*last = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void match_items(struct menu *menu) {
|
||||||
|
struct item *lexact = NULL, *exactend = NULL;
|
||||||
|
struct item *lprefix = NULL, *prefixend = NULL;
|
||||||
|
struct item *lsubstr = NULL, *substrend = NULL;
|
||||||
|
menu->matches = NULL;
|
||||||
|
menu->matches_end = NULL;
|
||||||
|
menu->sel = NULL;
|
||||||
|
|
||||||
|
size_t len = strlen(menu->text);
|
||||||
|
|
||||||
|
struct item *item;
|
||||||
|
for (item = menu->items; item; item = item->next) {
|
||||||
|
if (!menu->strncmp(menu->text, item->text, len + 1)) {
|
||||||
|
append_item(item, &lexact, &exactend);
|
||||||
|
} else if (!menu->strncmp(menu->text, item->text, len)) {
|
||||||
|
append_item(item, &lprefix, &prefixend);
|
||||||
|
} else if (fstrstr(menu, item->text, menu->text)) {
|
||||||
|
append_item(item, &lsubstr, &substrend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lexact) {
|
||||||
|
menu->matches = lexact;
|
||||||
|
menu->matches_end = exactend;
|
||||||
|
}
|
||||||
|
if (lprefix) {
|
||||||
|
if (menu->matches_end) {
|
||||||
|
menu->matches_end->next_match = lprefix;
|
||||||
|
lprefix->prev_match = menu->matches_end;
|
||||||
|
} else {
|
||||||
|
menu->matches = lprefix;
|
||||||
|
}
|
||||||
|
menu->matches_end = prefixend;
|
||||||
|
}
|
||||||
|
if (lsubstr) {
|
||||||
|
if (menu->matches_end) {
|
||||||
|
menu->matches_end->next_match = lsubstr;
|
||||||
|
lsubstr->prev_match = menu->matches_end;
|
||||||
|
} else {
|
||||||
|
menu->matches = lsubstr;
|
||||||
|
}
|
||||||
|
menu->matches_end = substrend;
|
||||||
|
}
|
||||||
|
|
||||||
|
page_items(menu);
|
||||||
|
menu->sel = menu->pages->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert(struct menu *menu, const char *s, ssize_t n) {
|
||||||
|
if (strlen(menu->text) + n > sizeof menu->text - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memmove(menu->text + menu->cursor + n, menu->text + menu->cursor,
|
||||||
|
sizeof menu->text - menu->cursor - MAX(n, 0));
|
||||||
|
if (n > 0 && s != NULL) {
|
||||||
|
memcpy(menu->text + menu->cursor, s, n);
|
||||||
|
}
|
||||||
|
menu->cursor += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t nextrune(struct menu *menu, int incr) {
|
||||||
|
size_t n, len;
|
||||||
|
|
||||||
|
len = strlen(menu->text);
|
||||||
|
for(n = menu->cursor + incr; n < len && (menu->text[n] & 0xc0) == 0x80; n += incr);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
|
||||||
|
cairo_set_source_rgba(cairo,
|
||||||
|
(color >> (3*8) & 0xFF) / 255.0,
|
||||||
|
(color >> (2*8) & 0xFF) / 255.0,
|
||||||
|
(color >> (1*8) & 0xFF) / 255.0,
|
||||||
|
(color >> (0*8) & 0xFF) / 255.0);
|
||||||
|
}
|
||||||
|
|
||||||
static int render_text(struct menu *menu, cairo_t *cairo, const char *str,
|
static int render_text(struct menu *menu, cairo_t *cairo, const char *str,
|
||||||
int x, int y, int width, int height,
|
int x, int y, int width, int height,
|
||||||
uint32_t foreground, uint32_t background,
|
uint32_t foreground, uint32_t background,
|
||||||
|
@ -530,12 +614,13 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
||||||
case XKB_KEY_k:
|
case XKB_KEY_k:
|
||||||
// Delete right
|
// Delete right
|
||||||
menu->text[menu->cursor] = '\0';
|
menu->text[menu->cursor] = '\0';
|
||||||
match(menu);
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
return;
|
return;
|
||||||
case XKB_KEY_u:
|
case XKB_KEY_u:
|
||||||
// Delete left
|
// Delete left
|
||||||
insert(menu, NULL, 0 - menu->cursor);
|
insert(menu, NULL, 0 - menu->cursor);
|
||||||
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
return;
|
return;
|
||||||
case XKB_KEY_w:
|
case XKB_KEY_w:
|
||||||
|
@ -546,6 +631,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
||||||
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] != ' ') {
|
while (menu->cursor > 0 && menu->text[nextrune(menu, -1)] != ' ') {
|
||||||
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
||||||
}
|
}
|
||||||
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
return;
|
return;
|
||||||
case XKB_KEY_Y:
|
case XKB_KEY_Y:
|
||||||
|
@ -576,6 +662,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
||||||
|
|
||||||
wl_data_offer_destroy(menu->offer);
|
wl_data_offer_destroy(menu->offer);
|
||||||
menu->offer = NULL;
|
menu->offer = NULL;
|
||||||
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
return;
|
return;
|
||||||
case XKB_KEY_Left:
|
case XKB_KEY_Left:
|
||||||
|
@ -687,6 +774,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
||||||
case XKB_KEY_BackSpace:
|
case XKB_KEY_BackSpace:
|
||||||
if (menu->cursor > 0) {
|
if (menu->cursor > 0) {
|
||||||
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
||||||
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -697,6 +785,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
||||||
}
|
}
|
||||||
menu->cursor = nextrune(menu, +1);
|
menu->cursor = nextrune(menu, +1);
|
||||||
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
|
||||||
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_Tab:
|
case XKB_KEY_Tab:
|
||||||
|
@ -706,7 +795,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
||||||
menu->cursor = strnlen(menu->sel->text, sizeof menu->text - 1);
|
menu->cursor = strnlen(menu->sel->text, sizeof menu->text - 1);
|
||||||
memcpy(menu->text, menu->sel->text, menu->cursor);
|
memcpy(menu->text, menu->sel->text, menu->cursor);
|
||||||
menu->text[menu->cursor] = '\0';
|
menu->text[menu->cursor] = '\0';
|
||||||
match(menu);
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
break;
|
break;
|
||||||
case XKB_KEY_Escape:
|
case XKB_KEY_Escape:
|
||||||
|
@ -716,6 +805,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
|
||||||
default:
|
default:
|
||||||
if (xkb_keysym_to_utf8(sym, buf, 8)) {
|
if (xkb_keysym_to_utf8(sym, buf, 8)) {
|
||||||
insert(menu, buf, strnlen(buf, 8));
|
insert(menu, buf, strnlen(buf, 8));
|
||||||
|
match_items(menu);
|
||||||
render_frame(menu);
|
render_frame(menu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,95 +932,6 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
.global_remove = noop,
|
.global_remove = noop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void insert(struct menu *menu, const char *s, ssize_t n) {
|
|
||||||
if (strlen(menu->text) + n > sizeof menu->text - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memmove(menu->text + menu->cursor + n, menu->text + menu->cursor,
|
|
||||||
sizeof menu->text - menu->cursor - MAX(n, 0));
|
|
||||||
if (n > 0 && s != NULL) {
|
|
||||||
memcpy(menu->text + menu->cursor, s, n);
|
|
||||||
}
|
|
||||||
menu->cursor += n;
|
|
||||||
match(menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char * fstrstr(struct menu *menu, const char *s, const char *sub) {
|
|
||||||
for (size_t len = strlen(sub); *s; s++) {
|
|
||||||
if (!menu->strncmp(s, sub, len)) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void append_item(struct item *item, struct item **first, struct item **last) {
|
|
||||||
if (*last) {
|
|
||||||
(*last)->next_match = item;
|
|
||||||
} else {
|
|
||||||
*first = item;
|
|
||||||
}
|
|
||||||
item->prev_match = *last;
|
|
||||||
item->next_match = NULL;
|
|
||||||
*last = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void match(struct menu *menu) {
|
|
||||||
struct item *lexact = NULL, *exactend = NULL;
|
|
||||||
struct item *lprefix = NULL, *prefixend = NULL;
|
|
||||||
struct item *lsubstr = NULL, *substrend = NULL;
|
|
||||||
menu->matches = NULL;
|
|
||||||
menu->matches_end = NULL;
|
|
||||||
menu->sel = NULL;
|
|
||||||
|
|
||||||
size_t len = strlen(menu->text);
|
|
||||||
|
|
||||||
struct item *item;
|
|
||||||
for (item = menu->items; item; item = item->next) {
|
|
||||||
if (!menu->strncmp(menu->text, item->text, len + 1)) {
|
|
||||||
append_item(item, &lexact, &exactend);
|
|
||||||
} else if (!menu->strncmp(menu->text, item->text, len)) {
|
|
||||||
append_item(item, &lprefix, &prefixend);
|
|
||||||
} else if (fstrstr(menu, item->text, menu->text)) {
|
|
||||||
append_item(item, &lsubstr, &substrend);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lexact) {
|
|
||||||
menu->matches = lexact;
|
|
||||||
menu->matches_end = exactend;
|
|
||||||
}
|
|
||||||
if (lprefix) {
|
|
||||||
if (menu->matches_end) {
|
|
||||||
menu->matches_end->next_match = lprefix;
|
|
||||||
lprefix->prev_match = menu->matches_end;
|
|
||||||
} else {
|
|
||||||
menu->matches = lprefix;
|
|
||||||
}
|
|
||||||
menu->matches_end = prefixend;
|
|
||||||
}
|
|
||||||
if (lsubstr) {
|
|
||||||
if (menu->matches_end) {
|
|
||||||
menu->matches_end->next_match = lsubstr;
|
|
||||||
lsubstr->prev_match = menu->matches_end;
|
|
||||||
} else {
|
|
||||||
menu->matches = lsubstr;
|
|
||||||
}
|
|
||||||
menu->matches_end = substrend;
|
|
||||||
}
|
|
||||||
|
|
||||||
page_items(menu);
|
|
||||||
menu->sel = menu->pages->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t nextrune(struct menu *menu, int incr) {
|
|
||||||
size_t n, len;
|
|
||||||
|
|
||||||
len = strlen(menu->text);
|
|
||||||
for(n = menu->cursor + incr; n < len && (menu->text[n] & 0xc0) == 0x80; n += incr);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_stdin(struct menu *menu) {
|
static void read_stdin(struct menu *menu) {
|
||||||
char buf[sizeof menu->text], *p;
|
char buf[sizeof menu->text], *p;
|
||||||
struct item *item, **end;
|
struct item *item, **end;
|
||||||
|
@ -1139,7 +1140,7 @@ int main(int argc, char **argv) {
|
||||||
render_frame(&menu);
|
render_frame(&menu);
|
||||||
|
|
||||||
read_stdin(&menu);
|
read_stdin(&menu);
|
||||||
match(&menu);
|
match_items(&menu);
|
||||||
render_frame(&menu);
|
render_frame(&menu);
|
||||||
|
|
||||||
struct pollfd fds[] = {
|
struct pollfd fds[] = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue