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