Home | History | Annotate | Line # | Download | only in dist
      1 /* $OpenBSD$ */
      2 
      3 /*
      4  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott (at) gmail.com>
      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 <stdlib.h>
     22 
     23 #include "tmux.h"
     24 
     25 /*
     26  * Break pane off into a window.
     27  */
     28 
     29 #define BREAK_PANE_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
     30 
     31 static enum cmd_retval	cmd_break_pane_exec(struct cmd *, struct cmdq_item *);
     32 
     33 const struct cmd_entry cmd_break_pane_entry = {
     34 	.name = "break-pane",
     35 	.alias = "breakp",
     36 
     37 	.args = { "abdPF:n:s:t:", 0, 0, NULL },
     38 	.usage = "[-abdP] [-F format] [-n window-name] [-s src-pane] "
     39 		 "[-t dst-window]",
     40 
     41 	.source = { 's', CMD_FIND_PANE, 0 },
     42 	.target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
     43 
     44 	.flags = 0,
     45 	.exec = cmd_break_pane_exec
     46 };
     47 
     48 static enum cmd_retval
     49 cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
     50 {
     51 	struct args		*args = cmd_get_args(self);
     52 	struct cmd_find_state	*current = cmdq_get_current(item);
     53 	struct cmd_find_state	*target = cmdq_get_target(item);
     54 	struct cmd_find_state	*source = cmdq_get_source(item);
     55 	struct client		*tc = cmdq_get_target_client(item);
     56 	struct winlink		*wl = source->wl;
     57 	struct session		*src_s = source->s;
     58 	struct session		*dst_s = target->s;
     59 	struct window_pane	*wp = source->wp;
     60 	struct window		*w = wl->window;
     61 	char			*name, *cause, *cp;
     62 	int			 idx = target->idx, before;
     63 	const char		*template;
     64 
     65 	before = args_has(args, 'b');
     66 	if (args_has(args, 'a') || before) {
     67 		if (target->wl != NULL)
     68 			idx = winlink_shuffle_up(dst_s, target->wl, before);
     69 		else
     70 			idx = winlink_shuffle_up(dst_s, dst_s->curw, before);
     71 		if (idx == -1)
     72 			return (CMD_RETURN_ERROR);
     73 	}
     74 	server_unzoom_window(w);
     75 
     76 	if (window_count_panes(w) == 1) {
     77 		if (server_link_window(src_s, wl, dst_s, idx, 0,
     78 		    !args_has(args, 'd'), &cause) != 0) {
     79 			cmdq_error(item, "%s", cause);
     80 			free(cause);
     81 			return (CMD_RETURN_ERROR);
     82 		}
     83 		if (args_has(args, 'n')) {
     84 			window_set_name(w, args_get(args, 'n'));
     85 			options_set_number(w->options, "automatic-rename", 0);
     86 		}
     87 		server_unlink_window(src_s, wl);
     88 		wl = winlink_find_by_window(&dst_s->windows, w);
     89 		if (wl == NULL)
     90 			return (CMD_RETURN_ERROR);
     91 		goto out;
     92 	}
     93 	if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
     94 		cmdq_error(item, "index in use: %d", idx);
     95 		return (CMD_RETURN_ERROR);
     96 	}
     97 
     98 	TAILQ_REMOVE(&w->panes, wp, entry);
     99 	server_client_remove_pane(wp);
    100 	window_lost_pane(w, wp);
    101 	layout_close_pane(wp);
    102 
    103 	w = wp->window = window_create(w->sx, w->sy, w->xpixel, w->ypixel);
    104 	options_set_parent(wp->options, w->options);
    105 	wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
    106 	TAILQ_INSERT_HEAD(&w->panes, wp, entry);
    107 	w->active = wp;
    108 	w->latest = tc;
    109 
    110 	if (!args_has(args, 'n')) {
    111 		name = default_window_name(w);
    112 		window_set_name(w, name);
    113 		free(name);
    114 	} else {
    115 		window_set_name(w, args_get(args, 'n'));
    116 		options_set_number(w->options, "automatic-rename", 0);
    117 	}
    118 
    119 	layout_init(w, wp);
    120 	wp->flags |= PANE_CHANGED;
    121 	colour_palette_from_option(&wp->palette, wp->options);
    122 
    123 	if (idx == -1)
    124 		idx = -1 - options_get_number(dst_s->options, "base-index");
    125 	wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
    126 	if (!args_has(args, 'd')) {
    127 		session_select(dst_s, wl->idx);
    128 		cmd_find_from_session(current, dst_s, 0);
    129 	}
    130 
    131 	server_redraw_session(src_s);
    132 	if (src_s != dst_s)
    133 		server_redraw_session(dst_s);
    134 	server_status_session_group(src_s);
    135 	if (src_s != dst_s)
    136 		server_status_session_group(dst_s);
    137 
    138 out:
    139 	if (args_has(args, 'P')) {
    140 		if ((template = args_get(args, 'F')) == NULL)
    141 			template = BREAK_PANE_TEMPLATE;
    142 		cp = format_single(item, template, tc, dst_s, wl, wp);
    143 		cmdq_print(item, "%s", cp);
    144 		free(cp);
    145 	}
    146 	return (CMD_RETURN_NORMAL);
    147 }
    148