xref: /openbsd-src/usr.bin/tmux/cmd-resize-pane.c (revision cb39b41371628601fbe4c618205356d538b9d08a)
1 /* $OpenBSD: cmd-resize-pane.c,v 1.18 2015/04/19 21:34:21 nicm 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 <stdlib.h>
22 
23 #include "tmux.h"
24 
25 /*
26  * Increase or decrease pane size.
27  */
28 
29 enum cmd_retval	 cmd_resize_pane_exec(struct cmd *, struct cmd_q *);
30 
31 void	cmd_resize_pane_mouse_update(struct client *, struct mouse_event *);
32 
33 const struct cmd_entry cmd_resize_pane_entry = {
34 	"resize-pane", "resizep",
35 	"DLMRt:Ux:y:Z", 0, 1,
36 	"[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE
37 	" [adjustment]",
38 	0,
39 	cmd_resize_pane_exec
40 };
41 
42 enum cmd_retval
43 cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
44 {
45 	struct args		*args = self->args;
46 	struct client		*c = cmdq->client;
47 	struct session		*s;
48 	struct winlink		*wl;
49 	struct window		*w;
50 	const char	       	*errstr;
51 	char			*cause;
52 	struct window_pane	*wp;
53 	u_int			 adjust;
54 	int			 x, y;
55 
56 	if (args_has(args, 'M')) {
57 		if (cmd_mouse_window(&cmdq->item->mouse, &s) == NULL)
58 			return (CMD_RETURN_NORMAL);
59 		if (c == NULL || c->session != s)
60 			return (CMD_RETURN_NORMAL);
61 		c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
62 		cmd_resize_pane_mouse_update(c, &cmdq->item->mouse);
63 		return (CMD_RETURN_NORMAL);
64 	}
65 
66 	if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
67 		return (CMD_RETURN_ERROR);
68 	w = wl->window;
69 
70 	if (args_has(args, 'Z')) {
71 		if (w->flags & WINDOW_ZOOMED)
72 			window_unzoom(w);
73 		else
74 			window_zoom(wp);
75 		server_redraw_window(w);
76 		server_status_window(w);
77 		return (CMD_RETURN_NORMAL);
78 	}
79 	server_unzoom_window(w);
80 
81 	if (args->argc == 0)
82 		adjust = 1;
83 	else {
84 		adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
85 		if (errstr != NULL) {
86 			cmdq_error(cmdq, "adjustment %s", errstr);
87 			return (CMD_RETURN_ERROR);
88 		}
89 	}
90 
91 	if (args_has(self->args, 'x')) {
92 		x = args_strtonum(self->args, 'x', PANE_MINIMUM, INT_MAX,
93 		    &cause);
94 		if (cause != NULL) {
95 			cmdq_error(cmdq, "width %s", cause);
96 			free(cause);
97 			return (CMD_RETURN_ERROR);
98 		}
99 		layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x);
100 	}
101 	if (args_has(self->args, 'y')) {
102 		y = args_strtonum(self->args, 'y', PANE_MINIMUM, INT_MAX,
103 		    &cause);
104 		if (cause != NULL) {
105 			cmdq_error(cmdq, "height %s", cause);
106 			free(cause);
107 			return (CMD_RETURN_ERROR);
108 		}
109 		layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
110 	}
111 
112 	if (args_has(self->args, 'L'))
113 		layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust);
114 	else if (args_has(self->args, 'R'))
115 		layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust);
116 	else if (args_has(self->args, 'U'))
117 		layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust);
118 	else if (args_has(self->args, 'D'))
119 		layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust);
120 	server_redraw_window(wl->window);
121 
122 	return (CMD_RETURN_NORMAL);
123 }
124 
125 void
126 cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
127 {
128 	struct winlink		*wl;
129 	struct window_pane	*wp;
130 	int			 found;
131 	u_int			 y, ly;
132 
133 	wl = cmd_mouse_window(m, NULL);
134 	if (wl == NULL) {
135 		c->tty.mouse_drag_update = NULL;
136 		return;
137 	}
138 
139 	y = m->y;
140 	if (m->statusat == 0 && y > 0)
141 		y--;
142 	else if (m->statusat > 0 && y >= (u_int)m->statusat)
143 		y = m->statusat - 1;
144 	ly = m->ly;
145 	if (m->statusat == 0 && ly > 0)
146 		ly--;
147 	else if (m->statusat > 0 && ly >= (u_int)m->statusat)
148 		ly = m->statusat - 1;
149 
150 	found = 0;
151 	TAILQ_FOREACH(wp, &wl->window->panes, entry) {
152 		if (!window_pane_visible(wp))
153 			continue;
154 
155 		if (wp->xoff + wp->sx == m->lx &&
156 		    wp->yoff <= 1 + ly && wp->yoff + wp->sy >= ly) {
157 			layout_resize_pane(wp, LAYOUT_LEFTRIGHT, m->x - m->lx);
158 			found = 1;
159 		}
160 		if (wp->yoff + wp->sy == ly &&
161 		    wp->xoff <= 1 + m->lx && wp->xoff + wp->sx >= m->lx) {
162 			layout_resize_pane(wp, LAYOUT_TOPBOTTOM, y - ly);
163 			found = 1;
164 		}
165 	}
166 	if (found)
167 		server_redraw_window(wl->window);
168 	else
169 		c->tty.mouse_drag_update = NULL;
170 }
171