For initial session, use size of command client even if detached.
[tmux-openbsd.git] / cmd-find-window.c
blob6c3c48ce56a12affd91f7657e582fddb6f1ae5aa
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
21 #include <fnmatch.h>
22 #include <string.h>
24 #include "tmux.h"
27 * Find window containing text.
30 int cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
32 void cmd_find_window_callback(void *, int);
33 void cmd_find_window_free(void *);
35 const struct cmd_entry cmd_find_window_entry = {
36 "find-window", "findw",
37 "t:", 1, 1,
38 CMD_TARGET_WINDOW_USAGE " match-string",
40 NULL,
41 NULL,
42 cmd_find_window_exec
45 struct cmd_find_window_data {
46 struct session *session;
49 int
50 cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
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;
63 if (ctx->curclient == NULL) {
64 ctx->error(ctx, "must be run interactively");
65 return (-1);
67 s = ctx->curclient->session;
69 if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
70 return (-1);
72 str = args->argv[0];
74 ARRAY_INIT(&list_idx);
75 ARRAY_INIT(&list_ctx);
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++;
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;
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);
103 ARRAY_ADD(&list_idx, wm->idx);
104 ARRAY_ADD(&list_ctx, sctx);
107 xfree(searchstr);
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);
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;
123 if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
124 goto out;
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;
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);
138 cdata = xmalloc(sizeof *cdata);
139 cdata->session = s;
140 cdata->session->references++;
142 window_choose_ready(wl->window->active,
143 0, cmd_find_window_callback, cmd_find_window_free, cdata);
145 out:
146 ARRAY_FREE(&list_idx);
147 ARRAY_FREE(&list_ctx);
149 return (0);
152 void
153 cmd_find_window_callback(void *data, int idx)
155 struct cmd_find_window_data *cdata = data;
156 struct session *s = cdata->session;
158 if (idx == -1)
159 return;
160 if (!session_alive(s))
161 return;
163 if (session_select(s, idx) == 0) {
164 server_redraw_session(s);
165 recalculate_sizes();
169 void
170 cmd_find_window_free(void *data)
172 struct cmd_find_window_data *cdata = data;
174 cdata->session->references--;
175 xfree(cdata);