xref: /netbsd-src/external/bsd/tmux/dist/cmd-select-pane.c (revision c23f9150cad51fdd442fa1806fac769ae26a1fdd)
15494e770Schristos /* $OpenBSD$ */
2698d5317Sjmmv 
3698d5317Sjmmv /*
4ed4e6cd4Schristos  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5698d5317Sjmmv  *
6698d5317Sjmmv  * Permission to use, copy, modify, and distribute this software for any
7698d5317Sjmmv  * purpose with or without fee is hereby granted, provided that the above
8698d5317Sjmmv  * copyright notice and this permission notice appear in all copies.
9698d5317Sjmmv  *
10698d5317Sjmmv  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11698d5317Sjmmv  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12698d5317Sjmmv  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13698d5317Sjmmv  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14698d5317Sjmmv  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15698d5317Sjmmv  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16698d5317Sjmmv  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17698d5317Sjmmv  */
18698d5317Sjmmv 
19698d5317Sjmmv #include <sys/types.h>
20698d5317Sjmmv 
218f3b9483Schristos #include <stdlib.h>
22ef36e747Schristos #include <string.h>
238f3b9483Schristos 
24698d5317Sjmmv #include "tmux.h"
25698d5317Sjmmv 
26698d5317Sjmmv /*
27698d5317Sjmmv  * Select pane.
28698d5317Sjmmv  */
29698d5317Sjmmv 
304e179ddaSchristos static enum cmd_retval	cmd_select_pane_exec(struct cmd *, struct cmdq_item *);
31698d5317Sjmmv 
32698d5317Sjmmv const struct cmd_entry cmd_select_pane_entry = {
33ed4e6cd4Schristos 	.name = "select-pane",
34ed4e6cd4Schristos 	.alias = "selectp",
35ed4e6cd4Schristos 
366db26757Swiz 	.args = { "DdegLlMmP:RT:t:UZ", 0, 0, NULL }, /* -P and -g deprecated */
37aa83ff61Schristos 	.usage = "[-DdeLlMmRUZ] [-T title] " CMD_TARGET_PANE_USAGE,
38ed4e6cd4Schristos 
39c9ad075bSchristos 	.target = { 't', CMD_FIND_PANE, 0 },
40ed4e6cd4Schristos 
41ed4e6cd4Schristos 	.flags = 0,
42ed4e6cd4Schristos 	.exec = cmd_select_pane_exec
43d530c4d0Sjmmv };
44d530c4d0Sjmmv 
45d530c4d0Sjmmv const struct cmd_entry cmd_last_pane_entry = {
46ed4e6cd4Schristos 	.name = "last-pane",
47ed4e6cd4Schristos 	.alias = "lastp",
48ed4e6cd4Schristos 
496db26757Swiz 	.args = { "det:Z", 0, 0, NULL },
50aa83ff61Schristos 	.usage = "[-deZ] " CMD_TARGET_WINDOW_USAGE,
51ed4e6cd4Schristos 
52c9ad075bSchristos 	.target = { 't', CMD_FIND_WINDOW, 0 },
53ed4e6cd4Schristos 
54ed4e6cd4Schristos 	.flags = 0,
55ed4e6cd4Schristos 	.exec = cmd_select_pane_exec
56698d5317Sjmmv };
57698d5317Sjmmv 
58ef36e747Schristos static void
cmd_select_pane_redraw(struct window * w)59ef36e747Schristos cmd_select_pane_redraw(struct window *w)
60ef36e747Schristos {
61ef36e747Schristos 	struct client	*c;
62ef36e747Schristos 
63ef36e747Schristos 	/*
64ef36e747Schristos 	 * Redraw entire window if it is bigger than the client (the
65ef36e747Schristos 	 * offset may change), otherwise just draw borders.
66ef36e747Schristos 	 */
67ef36e747Schristos 
68ef36e747Schristos 	TAILQ_FOREACH(c, &clients, entry) {
69ef36e747Schristos 		if (c->session == NULL || (c->flags & CLIENT_CONTROL))
70ef36e747Schristos 			continue;
71ef36e747Schristos 		if (c->session->curw->window == w && tty_window_bigger(&c->tty))
72ef36e747Schristos 			server_redraw_client(c);
73ef36e747Schristos 		else {
74ef36e747Schristos 			if (c->session->curw->window == w)
75ef36e747Schristos 				c->flags |= CLIENT_REDRAWBORDERS;
76ef36e747Schristos 			if (session_has(c->session, w))
77ef36e747Schristos 				c->flags |= CLIENT_REDRAWSTATUS;
78ef36e747Schristos 		}
79ef36e747Schristos 
80ef36e747Schristos 	}
81ef36e747Schristos }
82ef36e747Schristos 
834e179ddaSchristos static enum cmd_retval
cmd_select_pane_exec(struct cmd * self,struct cmdq_item * item)844e179ddaSchristos cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
85698d5317Sjmmv {
869fb66d81Schristos 	struct args		*args = cmd_get_args(self);
879fb66d81Schristos 	const struct cmd_entry	*entry = cmd_get_entry(self);
889fb66d81Schristos 	struct cmd_find_state	*current = cmdq_get_current(item);
899fb66d81Schristos 	struct cmd_find_state	*target = cmdq_get_target(item);
909fb66d81Schristos 	struct client		*c = cmdq_get_client(item);
919fb66d81Schristos 	struct winlink		*wl = target->wl;
92ed4e6cd4Schristos 	struct window		*w = wl->window;
939fb66d81Schristos 	struct session		*s = target->s;
949fb66d81Schristos 	struct window_pane	*wp = target->wp, *activewp, *lastwp, *markedwp;
959fb66d81Schristos 	struct options		*oo = wp->options;
969fb66d81Schristos 	char			*title;
975494e770Schristos 	const char		*style;
986483eba0Schristos 	struct options_entry	*o;
99698d5317Sjmmv 
1009fb66d81Schristos 	if (entry == &cmd_last_pane_entry || args_has(args, 'l')) {
101*c23f9150Swiz 		/*
102*c23f9150Swiz 		 * Check for no last pane found in case the other pane was
103*c23f9150Swiz 		 * spawned without being visited (for example split-window -d).
104*c23f9150Swiz 		 */
105*c23f9150Swiz 		lastwp = TAILQ_FIRST(&w->last_panes);
1068f3b9483Schristos 		if (lastwp == NULL && window_count_panes(w) == 2) {
1078f3b9483Schristos 			lastwp = TAILQ_PREV(w->active, window_panes, entry);
1088f3b9483Schristos 			if (lastwp == NULL)
1098f3b9483Schristos 				lastwp = TAILQ_NEXT(w->active, entry);
1108f3b9483Schristos 		}
111c9ad075bSchristos 		if (lastwp == NULL) {
1124e179ddaSchristos 			cmdq_error(item, "no last pane");
113928fc495Schristos 			return (CMD_RETURN_ERROR);
114698d5317Sjmmv 		}
1159fb66d81Schristos 		if (args_has(args, 'e')) {
116c9ad075bSchristos 			lastwp->flags &= ~PANE_INPUTOFF;
1179fb66d81Schristos 			server_redraw_window_borders(lastwp->window);
1189fb66d81Schristos 			server_status_window(lastwp->window);
1199fb66d81Schristos 		} else if (args_has(args, 'd')) {
120c9ad075bSchristos 			lastwp->flags |= PANE_INPUTOFF;
1219fb66d81Schristos 			server_redraw_window_borders(lastwp->window);
1229fb66d81Schristos 			server_status_window(lastwp->window);
1239fb66d81Schristos 		} else {
1249fb66d81Schristos 			if (window_push_zoom(w, 0, args_has(args, 'Z')))
125aa83ff61Schristos 				server_redraw_window(w);
126c9ad075bSchristos 			window_redraw_active_switch(w, lastwp);
1276483eba0Schristos 			if (window_set_active_pane(w, lastwp, 1)) {
128c9ad075bSchristos 				cmd_find_from_winlink(current, wl, 0);
129ef36e747Schristos 				cmd_select_pane_redraw(w);
1305494e770Schristos 			}
131aa83ff61Schristos 			if (window_pop_zoom(w))
132aa83ff61Schristos 				server_redraw_window(w);
1335494e770Schristos 		}
134928fc495Schristos 		return (CMD_RETURN_NORMAL);
135d530c4d0Sjmmv 	}
136d530c4d0Sjmmv 
1375494e770Schristos 	if (args_has(args, 'm') || args_has(args, 'M')) {
1385494e770Schristos 		if (args_has(args, 'm') && !window_pane_visible(wp))
1395494e770Schristos 			return (CMD_RETURN_NORMAL);
1409fb66d81Schristos 		if (server_check_marked())
141ed4e6cd4Schristos 			lastwp = marked_pane.wp;
1429fb66d81Schristos 		else
1439fb66d81Schristos 			lastwp = NULL;
1445494e770Schristos 
1455494e770Schristos 		if (args_has(args, 'M') || server_is_marked(s, wl, wp))
1465494e770Schristos 			server_clear_marked();
1475494e770Schristos 		else
1485494e770Schristos 			server_set_marked(s, wl, wp);
149ed4e6cd4Schristos 		markedwp = marked_pane.wp;
1505494e770Schristos 
1515494e770Schristos 		if (lastwp != NULL) {
1526db26757Swiz 			lastwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
1535494e770Schristos 			server_redraw_window_borders(lastwp->window);
1545494e770Schristos 			server_status_window(lastwp->window);
1555494e770Schristos 		}
1565494e770Schristos 		if (markedwp != NULL) {
1576db26757Swiz 			markedwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
1585494e770Schristos 			server_redraw_window_borders(markedwp->window);
1595494e770Schristos 			server_status_window(markedwp->window);
1605494e770Schristos 		}
1615494e770Schristos 		return (CMD_RETURN_NORMAL);
1625494e770Schristos 	}
1635494e770Schristos 
1649fb66d81Schristos 	style = args_get(args, 'P');
1659fb66d81Schristos 	if (style != NULL) {
1669fb66d81Schristos 		o = options_set_string(oo, "window-style", 0, "%s", style);
1676483eba0Schristos 		if (o == NULL) {
1684e179ddaSchristos 			cmdq_error(item, "bad style: %s", style);
169928fc495Schristos 			return (CMD_RETURN_ERROR);
170d530c4d0Sjmmv 		}
1719fb66d81Schristos 		options_set_string(oo, "window-active-style", 0, "%s", style);
1726483eba0Schristos 		wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
1735494e770Schristos 	}
1749fb66d81Schristos 	if (args_has(args, 'g')) {
1759fb66d81Schristos 		cmdq_print(item, "%s", options_get_string(oo, "window-style"));
1765494e770Schristos 		return (CMD_RETURN_NORMAL);
1775494e770Schristos 	}
178d530c4d0Sjmmv 
1799fb66d81Schristos 	if (args_has(args, 'L')) {
1809fb66d81Schristos 		window_push_zoom(w, 0, 1);
181698d5317Sjmmv 		wp = window_pane_find_left(wp);
182aa83ff61Schristos 		window_pop_zoom(w);
1839fb66d81Schristos 	} else if (args_has(args, 'R')) {
1849fb66d81Schristos 		window_push_zoom(w, 0, 1);
185698d5317Sjmmv 		wp = window_pane_find_right(wp);
186aa83ff61Schristos 		window_pop_zoom(w);
1879fb66d81Schristos 	} else if (args_has(args, 'U')) {
1889fb66d81Schristos 		window_push_zoom(w, 0, 1);
189698d5317Sjmmv 		wp = window_pane_find_up(wp);
190aa83ff61Schristos 		window_pop_zoom(w);
1919fb66d81Schristos 	} else if (args_has(args, 'D')) {
1929fb66d81Schristos 		window_push_zoom(w, 0, 1);
193698d5317Sjmmv 		wp = window_pane_find_down(wp);
194aa83ff61Schristos 		window_pop_zoom(w);
195ed4e6cd4Schristos 	}
1965494e770Schristos 	if (wp == NULL)
1975494e770Schristos 		return (CMD_RETURN_NORMAL);
1985494e770Schristos 
1999fb66d81Schristos 	if (args_has(args, 'e')) {
2005494e770Schristos 		wp->flags &= ~PANE_INPUTOFF;
2019fb66d81Schristos 		server_redraw_window_borders(wp->window);
202c9ad075bSchristos 		server_status_window(wp->window);
2039fb66d81Schristos 		return (CMD_RETURN_NORMAL);
2049fb66d81Schristos 	}
2059fb66d81Schristos 	if (args_has(args, 'd')) {
2069fb66d81Schristos 		wp->flags |= PANE_INPUTOFF;
2079fb66d81Schristos 		server_redraw_window_borders(wp->window);
2089fb66d81Schristos 		server_status_window(wp->window);
2098f3b9483Schristos 		return (CMD_RETURN_NORMAL);
210c9ad075bSchristos 	}
211c9ad075bSchristos 
2129fb66d81Schristos 	if (args_has(args, 'T')) {
2139fb66d81Schristos 		title = format_single_from_target(item, args_get(args, 'T'));
2149fb66d81Schristos 		if (screen_set_title(&wp->base, title)) {
2159fb66d81Schristos 			notify_pane("pane-title-changed", wp);
2169fb66d81Schristos 			server_redraw_window_borders(wp->window);
2179fb66d81Schristos 			server_status_window(wp->window);
2189fb66d81Schristos 		}
2199fb66d81Schristos 		free(title);
2205494e770Schristos 		return (CMD_RETURN_NORMAL);
2219fb66d81Schristos 	}
2229fb66d81Schristos 
2239fb66d81Schristos 	if (c != NULL && c->session != NULL && (c->flags & CLIENT_ACTIVEPANE))
2249fb66d81Schristos 		activewp = server_client_get_pane(c);
2259fb66d81Schristos 	else
2269fb66d81Schristos 		activewp = w->active;
2279fb66d81Schristos 	if (wp == activewp)
2289fb66d81Schristos 		return (CMD_RETURN_NORMAL);
2299fb66d81Schristos 	if (window_push_zoom(w, 0, args_has(args, 'Z')))
230aa83ff61Schristos 		server_redraw_window(w);
2315494e770Schristos 	window_redraw_active_switch(w, wp);
2329fb66d81Schristos 	if (c != NULL && c->session != NULL && (c->flags & CLIENT_ACTIVEPANE))
2339fb66d81Schristos 		server_client_set_pane(c, wp);
2349fb66d81Schristos 	else if (window_set_active_pane(w, wp, 1))
235c9ad075bSchristos 		cmd_find_from_winlink_pane(current, wl, wp, 0);
2366483eba0Schristos 	cmdq_insert_hook(s, item, current, "after-select-pane");
237ef36e747Schristos 	cmd_select_pane_redraw(w);
238aa83ff61Schristos 	if (window_pop_zoom(w))
239aa83ff61Schristos 		server_redraw_window(w);
240698d5317Sjmmv 
241928fc495Schristos 	return (CMD_RETURN_NORMAL);
242698d5317Sjmmv }
243