Don't match items in insert - wmenu - 🔧 fork of wmenu
 (HTM) git clone git@git.drkhsh.at/wmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 7284f5958bea340e25598562821b73db3c26ee63
 (DIR) parent 48f4a1d2ed523ae8b0c0c6b97561d96a3d5ab369
 (HTM) Author: adnano <me@adnano.co>
       Date:   Mon, 26 Feb 2024 15:03:42 -0500
       
       Don't match items in insert
       
       Diffstat:
         M main.c                              |     209 ++++++++++++++++---------------
       
       1 file changed, 105 insertions(+), 104 deletions(-)
       ---
 (DIR) diff --git a/main.c b/main.c
       @@ -106,18 +106,6 @@ struct menu {
                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) {
                if (*last) {
                        (*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,
                        int x, int y, int width, int height,
                        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:
                                // Delete right
                                menu->text[menu->cursor] = '\0';
       -                        match(menu);
       +                        match_items(menu);
                                render_frame(menu);
                                return;
                        case XKB_KEY_u:
                                // Delete left
                                insert(menu, NULL, 0 - menu->cursor);
       +                        match_items(menu);
                                render_frame(menu);
                                return;
                        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)] != ' ') {
                                        insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
                                }
       +                        match_items(menu);
                                render_frame(menu);
                                return;
                        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);
                                menu->offer = NULL;
       +                        match_items(menu);
                                render_frame(menu);
                                return;
                        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:
                        if (menu->cursor > 0) {
                                insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
       +                        match_items(menu);
                                render_frame(menu);
                        }
                        break;
       @@ -697,6 +785,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                        }
                        menu->cursor = nextrune(menu, +1);
                        insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
       +                match_items(menu);
                        render_frame(menu);
                        break;
                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);
                        memcpy(menu->text, menu->sel->text, menu->cursor);
                        menu->text[menu->cursor] = '\0';
       -                match(menu);
       +                match_items(menu);
                        render_frame(menu);
                        break;
                case XKB_KEY_Escape:
       @@ -716,6 +805,7 @@ static void keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
                default:
                        if (xkb_keysym_to_utf8(sym, buf, 8)) {
                                insert(menu, buf, strnlen(buf, 8));
       +                        match_items(menu);
                                render_frame(menu);
                        }
                }
       @@ -842,95 +932,6 @@ static const struct wl_registry_listener registry_listener = {
                .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) {
                char buf[sizeof menu->text], *p;
                struct item *item, **end;
       @@ -1139,7 +1140,7 @@ int main(int argc, char **argv) {
                render_frame(&menu);
        
                read_stdin(&menu);
       -        match(&menu);
       +        match_items(&menu);
                render_frame(&menu);
        
                struct pollfd fds[] = {