1 /* $Id: cmd-find-window.c,v 1.1.1.1 2011/03/10 09:15:37 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 CMD_TARGET_WINDOW_USAGE " match-string", 38 CMD_ARG1, "", 39 cmd_target_init, 40 cmd_target_parse, 41 cmd_find_window_exec, 42 cmd_target_free, 43 cmd_target_print 44 }; 45 46 struct cmd_find_window_data { 47 struct session *session; 48 }; 49 50 int 51 cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) 52 { 53 struct cmd_target_data *data = self->data; 54 struct cmd_find_window_data *cdata; 55 struct session *s; 56 struct winlink *wl, *wm; 57 struct window *w; 58 struct window_pane *wp; 59 ARRAY_DECL(, u_int) list_idx; 60 ARRAY_DECL(, char *) list_ctx; 61 char *sres, *sctx, *searchstr; 62 u_int i, line; 63 64 if (ctx->curclient == NULL) { 65 ctx->error(ctx, "must be run interactively"); 66 return (-1); 67 } 68 s = ctx->curclient->session; 69 70 if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) 71 return (-1); 72 73 ARRAY_INIT(&list_idx); 74 ARRAY_INIT(&list_ctx); 75 76 xasprintf(&searchstr, "*%s*", data->arg); 77 RB_FOREACH(wm, winlinks, &s->windows) { 78 i = 0; 79 TAILQ_FOREACH(wp, &wm->window->panes, entry) { 80 i++; 81 82 if (fnmatch(searchstr, wm->window->name, 0) == 0) 83 sctx = xstrdup(""); 84 else { 85 sres = window_pane_search(wp, data->arg, &line); 86 if (sres == NULL && 87 fnmatch(searchstr, wp->base.title, 0) != 0) 88 continue; 89 90 if (sres == NULL) { 91 xasprintf(&sctx, 92 "pane %u title: \"%s\"", i - 1, 93 wp->base.title); 94 } else { 95 xasprintf(&sctx, 96 "pane %u line %u: \"%s\"", i - 1, 97 line + 1, sres); 98 xfree(sres); 99 } 100 } 101 102 ARRAY_ADD(&list_idx, wm->idx); 103 ARRAY_ADD(&list_ctx, sctx); 104 } 105 } 106 xfree(searchstr); 107 108 if (ARRAY_LENGTH(&list_idx) == 0) { 109 ctx->error(ctx, "no windows matching: %s", data->arg); 110 ARRAY_FREE(&list_idx); 111 ARRAY_FREE(&list_ctx); 112 return (-1); 113 } 114 115 if (ARRAY_LENGTH(&list_idx) == 1) { 116 if (session_select(s, ARRAY_FIRST(&list_idx)) == 0) 117 server_redraw_session(s); 118 recalculate_sizes(); 119 goto out; 120 } 121 122 if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) 123 goto out; 124 125 for (i = 0; i < ARRAY_LENGTH(&list_idx); i++) { 126 wm = winlink_find_by_index( 127 &s->windows, ARRAY_ITEM(&list_idx, i)); 128 w = wm->window; 129 130 sctx = ARRAY_ITEM(&list_ctx, i); 131 window_choose_add(wl->window->active, 132 wm->idx, "%3d: %s [%ux%u] (%u panes) %s", wm->idx, w->name, 133 w->sx, w->sy, window_count_panes(w), sctx); 134 xfree(sctx); 135 } 136 137 cdata = xmalloc(sizeof *cdata); 138 cdata->session = s; 139 cdata->session->references++; 140 141 window_choose_ready(wl->window->active, 142 0, cmd_find_window_callback, cmd_find_window_free, cdata); 143 144 out: 145 ARRAY_FREE(&list_idx); 146 ARRAY_FREE(&list_ctx); 147 148 return (0); 149 } 150 151 void 152 cmd_find_window_callback(void *data, int idx) 153 { 154 struct cmd_find_window_data *cdata = data; 155 struct session *s = cdata->session; 156 157 if (idx == -1) 158 return; 159 if (!session_alive(s)) 160 return; 161 162 if (session_select(s, idx) == 0) { 163 server_redraw_session(s); 164 recalculate_sizes(); 165 } 166 } 167 168 void 169 cmd_find_window_free(void *data) 170 { 171 struct cmd_find_window_data *cdata = data; 172 173 cdata->session->references--; 174 xfree(cdata); 175 } 176