1 /* $Id: cmd-find-window.c,v 1.1.1.2 2011/08/17 18:40:04 jmmv Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 21 #include <fnmatch.h> 22 #include <string.h> 23 24 #include "tmux.h" 25 26 /* 27 * Find window containing text. 28 */ 29 30 int cmd_find_window_exec(struct cmd *, struct cmd_ctx *); 31 32 void cmd_find_window_callback(void *, int); 33 void cmd_find_window_free(void *); 34 35 const struct cmd_entry cmd_find_window_entry = { 36 "find-window", "findw", 37 "t:", 1, 1, 38 CMD_TARGET_WINDOW_USAGE " match-string", 39 0, 40 NULL, 41 NULL, 42 cmd_find_window_exec 43 }; 44 45 struct cmd_find_window_data { 46 struct session *session; 47 }; 48 49 int 50 cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) 51 { 52 struct args *args = self->args; 53 struct cmd_find_window_data *cdata; 54 struct session *s; 55 struct winlink *wl, *wm; 56 struct window *w; 57 struct window_pane *wp; 58 ARRAY_DECL(, u_int) list_idx; 59 ARRAY_DECL(, char *) list_ctx; 60 char *str, *sres, *sctx, *searchstr; 61 u_int i, line; 62 63 if (ctx->curclient == NULL) { 64 ctx->error(ctx, "must be run interactively"); 65 return (-1); 66 } 67 s = ctx->curclient->session; 68 69 if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) 70 return (-1); 71 72 str = args->argv[0]; 73 74 ARRAY_INIT(&list_idx); 75 ARRAY_INIT(&list_ctx); 76 77 xasprintf(&searchstr, "*%s*", str); 78 RB_FOREACH(wm, winlinks, &s->windows) { 79 i = 0; 80 TAILQ_FOREACH(wp, &wm->window->panes, entry) { 81 i++; 82 83 if (fnmatch(searchstr, wm->window->name, 0) == 0) 84 sctx = xstrdup(""); 85 else { 86 sres = window_pane_search(wp, str, &line); 87 if (sres == NULL && 88 fnmatch(searchstr, wp->base.title, 0) != 0) 89 continue; 90 91 if (sres == NULL) { 92 xasprintf(&sctx, 93 "pane %u title: \"%s\"", i - 1, 94 wp->base.title); 95 } else { 96 xasprintf(&sctx, 97 "pane %u line %u: \"%s\"", i - 1, 98 line + 1, sres); 99 xfree(sres); 100 } 101 } 102 103 ARRAY_ADD(&list_idx, wm->idx); 104 ARRAY_ADD(&list_ctx, sctx); 105 } 106 } 107 xfree(searchstr); 108 109 if (ARRAY_LENGTH(&list_idx) == 0) { 110 ctx->error(ctx, "no windows matching: %s", str); 111 ARRAY_FREE(&list_idx); 112 ARRAY_FREE(&list_ctx); 113 return (-1); 114 } 115 116 if (ARRAY_LENGTH(&list_idx) == 1) { 117 if (session_select(s, ARRAY_FIRST(&list_idx)) == 0) 118 server_redraw_session(s); 119 recalculate_sizes(); 120 goto out; 121 } 122 123 if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) 124 goto out; 125 126 for (i = 0; i < ARRAY_LENGTH(&list_idx); i++) { 127 wm = winlink_find_by_index( 128 &s->windows, ARRAY_ITEM(&list_idx, i)); 129 w = wm->window; 130 131 sctx = ARRAY_ITEM(&list_ctx, i); 132 window_choose_add(wl->window->active, 133 wm->idx, "%3d: %s [%ux%u] (%u panes) %s", wm->idx, w->name, 134 w->sx, w->sy, window_count_panes(w), sctx); 135 xfree(sctx); 136 } 137 138 cdata = xmalloc(sizeof *cdata); 139 cdata->session = s; 140 cdata->session->references++; 141 142 window_choose_ready(wl->window->active, 143 0, cmd_find_window_callback, cmd_find_window_free, cdata); 144 145 out: 146 ARRAY_FREE(&list_idx); 147 ARRAY_FREE(&list_ctx); 148 149 return (0); 150 } 151 152 void 153 cmd_find_window_callback(void *data, int idx) 154 { 155 struct cmd_find_window_data *cdata = data; 156 struct session *s = cdata->session; 157 158 if (idx == -1) 159 return; 160 if (!session_alive(s)) 161 return; 162 163 if (session_select(s, idx) == 0) { 164 server_redraw_session(s); 165 recalculate_sizes(); 166 } 167 } 168 169 void 170 cmd_find_window_free(void *data) 171 { 172 struct cmd_find_window_data *cdata = data; 173 174 cdata->session->references--; 175 xfree(cdata); 176 } 177