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