diff --git a/mode-tree.c b/mode-tree.c index 1d929952..a3620b4f 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -82,6 +82,7 @@ struct mode_tree_data { char *filter; int no_matches; enum mode_tree_search_dir search_dir; + int search_icase; }; struct mode_tree_item { @@ -132,6 +133,17 @@ static const struct menu_item mode_tree_menu_items[] = { { NULL, KEYC_NONE, NULL } }; +static int +mode_tree_is_lowercase(const char *ptr) +{ + while (*ptr != '\0') { + if (*ptr != tolower((u_char)*ptr)) + return (0); + ++ptr; + } + return (1); +} + static struct mode_tree_item * mode_tree_find_item(struct mode_tree_list *mtl, uint64_t tag) { @@ -881,49 +893,57 @@ done: static struct mode_tree_item * mode_tree_search_backward(struct mode_tree_data *mtd) { - struct mode_tree_item *mti, *last, *prev; + struct mode_tree_item *mti, *last, *prev; + int icase = mtd->search_icase; - if (mtd->search == NULL) - return (NULL); + if (mtd->search == NULL) + return (NULL); - mti = last = mtd->line_list[mtd->current].item; - for (;;) { - if ((prev = TAILQ_PREV(mti, mode_tree_list, entry)) != NULL) { - /* Point to the last child in the previous subtree. */ - while (!TAILQ_EMPTY(&prev->children)) - prev = TAILQ_LAST(&prev->children, mode_tree_list); - mti = prev; - } else { - /* If prev is NULL, jump to the parent. */ - mti = mti->parent; - } + mti = last = mtd->line_list[mtd->current].item; + for (;;) { + if ((prev = TAILQ_PREV(mti, mode_tree_list, entry)) != NULL) { + /* Point to the last child in the previous subtree. */ + while (!TAILQ_EMPTY(&prev->children)) { + prev = TAILQ_LAST(&prev->children, + mode_tree_list); + } + mti = prev; + } else { + /* If prev is NULL, jump to the parent. */ + mti = mti->parent; + } - if (mti == NULL) { - /* Point to the last child in the last root subtree. */ - prev = TAILQ_LAST(&mtd->children, mode_tree_list); - while (!TAILQ_EMPTY(&prev->children)) - prev = TAILQ_LAST(&prev->children, mode_tree_list); - mti = prev; - } - if (mti == last) - break; + if (mti == NULL) { + /* Point to the last child in the last root subtree. */ + prev = TAILQ_LAST(&mtd->children, mode_tree_list); + while (!TAILQ_EMPTY(&prev->children)) { + prev = TAILQ_LAST(&prev->children, + mode_tree_list); + } + mti = prev; + } + if (mti == last) + break; - if (mtd->searchcb == NULL) { - if (strstr(mti->name, mtd->search) != NULL) + if (mtd->searchcb == NULL) { + if (!icase && strstr(mti->name, mtd->search) != NULL) + return (mti); + if (icase && strcasestr(mti->name, mtd->search) != NULL) + return (mti); + continue; + } + if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search, + icase)) return (mti); - continue; } - if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search)) - return (mti); - } - return (NULL); + return (NULL); } - static struct mode_tree_item * mode_tree_search_forward(struct mode_tree_data *mtd) { struct mode_tree_item *mti, *last, *next; + int icase = mtd->search_icase; if (mtd->search == NULL) return (NULL); @@ -951,11 +971,14 @@ mode_tree_search_forward(struct mode_tree_data *mtd) break; if (mtd->searchcb == NULL) { - if (strstr(mti->name, mtd->search) != NULL) + if (!icase && strstr(mti->name, mtd->search) != NULL) + return (mti); + if (icase && strcasestr(mti->name, mtd->search) != NULL) return (mti); continue; } - if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search)) + if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search, + icase)) return (mti); } return (NULL); @@ -1002,6 +1025,7 @@ mode_tree_search_callback(__unused struct client *c, void *data, const char *s, return (0); } mtd->search = xstrdup(s); + mtd->search_icase = mode_tree_is_lowercase(s); mode_tree_search_set(mtd); return (0); @@ -1309,6 +1333,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, case '/': case 's'|KEYC_CTRL: mtd->references++; + mtd->search_dir = MODE_TREE_SEARCH_FORWARD; status_prompt_set(c, NULL, "(search) ", "", mode_tree_search_callback, mode_tree_search_free, mtd, PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH); diff --git a/tmux.h b/tmux.h index 02d8d1fb..e386185c 100644 --- a/tmux.h +++ b/tmux.h @@ -3290,7 +3290,7 @@ typedef void (*mode_tree_build_cb)(void *, struct mode_tree_sort_criteria *, uint64_t *, const char *); typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *, u_int, u_int); -typedef int (*mode_tree_search_cb)(void *, void *, const char *); +typedef int (*mode_tree_search_cb)(void *, void *, const char *, int); typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code); typedef u_int (*mode_tree_height_cb)(void *, u_int); typedef key_code (*mode_tree_key_cb)(void *, void *, u_int); diff --git a/window-buffer.c b/window-buffer.c index a13193cd..782a7854 100644 --- a/window-buffer.c +++ b/window-buffer.c @@ -18,6 +18,7 @@ #include +#include #include #include #include @@ -255,7 +256,30 @@ window_buffer_draw(__unused void *modedata, void *itemdata, } static int -window_buffer_search(__unused void *modedata, void *itemdata, const char *ss) +window_buffer_find(const void *data, size_t datalen, const void *find, + size_t findlen, int icase) +{ + const u_char *udata = data, *ufind = find; + size_t i, j; + + if (findlen == 0 || datalen < findlen) + return (0); + for (i = 0; i + findlen <= datalen; i++) { + for (j = 0; j < findlen; j++) { + if (!icase && udata[i + j] != ufind[j]) + break; + if (icase && tolower(udata[i + j]) != tolower(ufind[j])) + break; + } + if (j == findlen) + return (1); + } + return (0); +} + +static int +window_buffer_search(__unused void *modedata, void *itemdata, const char *ss, + int icase) { struct window_buffer_itemdata *item = itemdata; struct paste_buffer *pb; @@ -264,10 +288,19 @@ window_buffer_search(__unused void *modedata, void *itemdata, const char *ss) if ((pb = paste_get_name(item->name)) == NULL) return (0); - if (strstr(item->name, ss) != NULL) - return (1); - bufdata = paste_buffer_data(pb, &bufsize); - return (memmem(bufdata, bufsize, ss, strlen(ss)) != NULL); + if (icase) { + if (strcasestr(item->name, ss) != NULL) + return (1); + bufdata = paste_buffer_data(pb, &bufsize); + return (window_buffer_find(bufdata, bufsize, ss, strlen(ss), + icase)); + } else { + if (strstr(item->name, ss) != NULL) + return (1); + bufdata = paste_buffer_data(pb, &bufsize); + return (window_buffer_find(bufdata, bufsize, ss, strlen(ss), + icase)); + } } static void diff --git a/window-tree.c b/window-tree.c index 78ed52be..0a2460f1 100644 --- a/window-tree.c +++ b/window-tree.c @@ -836,7 +836,8 @@ window_tree_draw(void *modedata, void *itemdata, struct screen_write_ctx *ctx, } static int -window_tree_search(__unused void *modedata, void *itemdata, const char *ss) +window_tree_search(__unused void *modedata, void *itemdata, const char *ss, + int icase) { struct window_tree_itemdata *item = itemdata; struct session *s; @@ -853,10 +854,14 @@ window_tree_search(__unused void *modedata, void *itemdata, const char *ss) case WINDOW_TREE_SESSION: if (s == NULL) return (0); - return (strstr(s->name, ss) != NULL); + if (icase) + return (strcasestr(s->name, ss) != NULL); + return (strstr(s->name, ss) != NULL); case WINDOW_TREE_WINDOW: if (s == NULL || wl == NULL) return (0); + if (icase) + return (strcasestr(wl->window->name, ss) != NULL); return (strstr(wl->window->name, ss) != NULL); case WINDOW_TREE_PANE: if (s == NULL || wl == NULL || wp == NULL) @@ -866,7 +871,10 @@ window_tree_search(__unused void *modedata, void *itemdata, const char *ss) free(cmd); return (0); } - retval = (strstr(cmd, ss) != NULL); + if (icase) + retval = (strcasestr(cmd, ss) != NULL); + else + retval = (strstr(cmd, ss) != NULL); free(cmd); return (retval); }