xref: /openbsd-src/usr.bin/tmux/cmd-join-pane.c (revision bf31d21b53c34d82f0b2275e5dd5913ba58ceef3)
1*bf31d21bSnicm /* $OpenBSD: cmd-join-pane.c,v 1.51 2023/01/17 06:50:55 nicm Exp $ */
2572cd943Snicm 
3572cd943Snicm /*
49c03dbf0Snicm  * Copyright (c) 2011 George Nachman <tmux@georgester.com>
598ca8272Snicm  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
6572cd943Snicm  *
7572cd943Snicm  * Permission to use, copy, modify, and distribute this software for any
8572cd943Snicm  * purpose with or without fee is hereby granted, provided that the above
9572cd943Snicm  * copyright notice and this permission notice appear in all copies.
10572cd943Snicm  *
11572cd943Snicm  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12572cd943Snicm  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13572cd943Snicm  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14572cd943Snicm  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15572cd943Snicm  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16572cd943Snicm  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17572cd943Snicm  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18572cd943Snicm  */
19572cd943Snicm 
20572cd943Snicm #include <sys/types.h>
21572cd943Snicm 
22572cd943Snicm #include <paths.h>
23572cd943Snicm #include <stdlib.h>
2428988ef6Snicm #include <string.h>
25572cd943Snicm #include <unistd.h>
26572cd943Snicm 
27572cd943Snicm #include "tmux.h"
28572cd943Snicm 
29572cd943Snicm /*
309c03dbf0Snicm  * Join or move a pane into another (like split/swap/kill).
31572cd943Snicm  */
32572cd943Snicm 
3368e0a7f2Snicm static enum cmd_retval	cmd_join_pane_exec(struct cmd *, struct cmdq_item *);
349c03dbf0Snicm 
35572cd943Snicm const struct cmd_entry cmd_join_pane_entry = {
36c057646bSnicm 	.name = "join-pane",
37c057646bSnicm 	.alias = "joinp",
38c057646bSnicm 
39a51dead1Snicm 	.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
40b9f4fd46Snicm 	.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
41c057646bSnicm 
42bf0d297eSnicm 	.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
43bf0d297eSnicm 	.target = { 't', CMD_FIND_PANE, 0 },
448d471e80Snicm 
458d471e80Snicm 	.flags = 0,
46c057646bSnicm 	.exec = cmd_join_pane_exec
47572cd943Snicm };
48572cd943Snicm 
499c03dbf0Snicm const struct cmd_entry cmd_move_pane_entry = {
50c057646bSnicm 	.name = "move-pane",
51c057646bSnicm 	.alias = "movep",
52c057646bSnicm 
53a51dead1Snicm 	.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
54b196a1a7Snicm 	.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
55c057646bSnicm 
56b8e51ba2Snicm 	.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
57bf0d297eSnicm 	.target = { 't', CMD_FIND_PANE, 0 },
588d471e80Snicm 
598d471e80Snicm 	.flags = 0,
60c057646bSnicm 	.exec = cmd_join_pane_exec
619c03dbf0Snicm };
629c03dbf0Snicm 
63dc1f0f5fSnicm static enum cmd_retval
cmd_join_pane_exec(struct cmd * self,struct cmdq_item * item)6468e0a7f2Snicm cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
65572cd943Snicm {
6690d7ba38Snicm 	struct args		*args = cmd_get_args(self);
67823b6d6dSnicm 	struct cmd_find_state	*current = cmdq_get_current(item);
68040343aeSnicm 	struct cmd_find_state	*target = cmdq_get_target(item);
69040343aeSnicm 	struct cmd_find_state	*source = cmdq_get_source(item);
70572cd943Snicm 	struct session		*dst_s;
71572cd943Snicm 	struct winlink		*src_wl, *dst_wl;
72572cd943Snicm 	struct window		*src_w, *dst_w;
73572cd943Snicm 	struct window_pane	*src_wp, *dst_wp;
7494300b02Snicm 	char			*cause = NULL;
75113211eaSnicm 	int			 size, dst_idx;
7628988ef6Snicm 	int			 flags;
77572cd943Snicm 	enum layout_type	 type;
78572cd943Snicm 	struct layout_cell	*lc;
79113211eaSnicm 	u_int			 curval = 0;
80dc1f0f5fSnicm 
81040343aeSnicm 	dst_s = target->s;
82040343aeSnicm 	dst_wl = target->wl;
83040343aeSnicm 	dst_wp = target->wp;
84572cd943Snicm 	dst_w = dst_wl->window;
857139e011Snicm 	dst_idx = dst_wl->idx;
86b4a3311eSnicm 	server_unzoom_window(dst_w);
87572cd943Snicm 
88040343aeSnicm 	src_wl = source->wl;
89040343aeSnicm 	src_wp = source->wp;
90572cd943Snicm 	src_w = src_wl->window;
91b4a3311eSnicm 	server_unzoom_window(src_w);
92572cd943Snicm 
93b196a1a7Snicm 	if (src_wp == dst_wp) {
9468e0a7f2Snicm 		cmdq_error(item, "source and target panes must be different");
95a224d0d3Snicm 		return (CMD_RETURN_ERROR);
969c03dbf0Snicm 	}
97572cd943Snicm 
98572cd943Snicm 	type = LAYOUT_TOPBOTTOM;
99ca7befccSnicm 	if (args_has(args, 'h'))
100572cd943Snicm 		type = LAYOUT_LEFTRIGHT;
101572cd943Snicm 
102113211eaSnicm 	/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
103113211eaSnicm 	if (args_has(args, 'l') || args_has(args, 'p')) {
104113211eaSnicm 		if (args_has(args, 'f')) {
105113211eaSnicm 			if (type == LAYOUT_TOPBOTTOM)
106113211eaSnicm 				curval = dst_w->sy;
107113211eaSnicm 			else
108113211eaSnicm 				curval = dst_w->sx;
109113211eaSnicm 		} else {
110113211eaSnicm 			if (type == LAYOUT_TOPBOTTOM)
111113211eaSnicm 				curval = dst_wp->sy;
112113211eaSnicm 			else
113113211eaSnicm 				curval = dst_wp->sx;
114113211eaSnicm 		}
115113211eaSnicm 	}
116113211eaSnicm 
117572cd943Snicm 	size = -1;
11894300b02Snicm 	if (args_has(args, 'l')) {
119113211eaSnicm 		size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
120113211eaSnicm 			   item, &cause);
12194300b02Snicm 	} else if (args_has(args, 'p')) {
122113211eaSnicm 		size = args_strtonum_and_expand(args, 'l', 0, 100, item,
123113211eaSnicm 			   &cause);
124113211eaSnicm 		if (cause == NULL)
125113211eaSnicm 			size = curval * size / 100;
12694300b02Snicm 	}
127ca7befccSnicm 	if (cause != NULL) {
12868e0a7f2Snicm 		cmdq_error(item, "size %s", cause);
1297d053cf9Snicm 		free(cause);
130a224d0d3Snicm 		return (CMD_RETURN_ERROR);
131ca7befccSnicm 	}
132b9f4fd46Snicm 
133c26c4f79Snicm 	flags = 0;
134b9f4fd46Snicm 	if (args_has(args, 'b'))
135b9f4fd46Snicm 		flags |= SPAWN_BEFORE;
136b9f4fd46Snicm 	if (args_has(args, 'f'))
137b9f4fd46Snicm 		flags |= SPAWN_FULLSIZE;
138b9f4fd46Snicm 
139c26c4f79Snicm 	lc = layout_split_pane(dst_wp, type, size, flags);
1409c03dbf0Snicm 	if (lc == NULL) {
14168e0a7f2Snicm 		cmdq_error(item, "create pane failed: pane too small");
142a224d0d3Snicm 		return (CMD_RETURN_ERROR);
143572cd943Snicm 	}
144572cd943Snicm 
145572cd943Snicm 	layout_close_pane(src_wp);
146572cd943Snicm 
147249e1654Snicm 	server_client_remove_pane(src_wp);
148e2f09fc8Snicm 	window_lost_pane(src_w, src_wp);
149572cd943Snicm 	TAILQ_REMOVE(&src_w->panes, src_wp, entry);
150572cd943Snicm 
151572cd943Snicm 	src_wp->window = dst_w;
1526e0f28f8Snicm 	options_set_parent(src_wp->options, dst_w->options);
1536e0f28f8Snicm 	src_wp->flags |= PANE_STYLECHANGED;
154d189c051Snicm 	if (flags & SPAWN_BEFORE)
155d189c051Snicm 		TAILQ_INSERT_BEFORE(dst_wp, src_wp, entry);
156d189c051Snicm 	else
157572cd943Snicm 		TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
158baddd6b2Snicm 	layout_assign_pane(lc, src_wp, 0);
159*bf31d21bSnicm 	colour_palette_from_option(&src_wp->palette, src_wp->options);
160572cd943Snicm 
161572cd943Snicm 	recalculate_sizes();
162572cd943Snicm 
163572cd943Snicm 	server_redraw_window(src_w);
164572cd943Snicm 	server_redraw_window(dst_w);
165572cd943Snicm 
166ca7befccSnicm 	if (!args_has(args, 'd')) {
167c26c4f79Snicm 		window_set_active_pane(dst_w, src_wp, 1);
1687139e011Snicm 		session_select(dst_s, dst_idx);
1690772530eSnicm 		cmd_find_from_session(current, dst_s, 0);
170572cd943Snicm 		server_redraw_session(dst_s);
171572cd943Snicm 	} else
172572cd943Snicm 		server_status_session(dst_s);
173572cd943Snicm 
174b0f51586Snicm 	if (window_count_panes(src_w) == 0)
175fedaf9c8Snicm 		server_kill_window(src_w, 1);
176b0f51586Snicm 	else
1772ae124feSnicm 		notify_window("window-layout-changed", src_w);
1782ae124feSnicm 	notify_window("window-layout-changed", dst_w);
179b0f51586Snicm 
180a224d0d3Snicm 	return (CMD_RETURN_NORMAL);
181572cd943Snicm }
182