xref: /minix/external/bsd/tmux/dist/cmd-find-window.c (revision e3b78ef1)
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