xref: /openbsd-src/usr.bin/tmux/cmd-refresh-client.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /* $OpenBSD: cmd-refresh-client.c,v 1.30 2019/11/28 09:05:34 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@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 #include <string.h>
23 
24 #include "tmux.h"
25 
26 /*
27  * Refresh client.
28  */
29 
30 static enum cmd_retval	cmd_refresh_client_exec(struct cmd *,
31 			    struct cmdq_item *);
32 
33 const struct cmd_entry cmd_refresh_client_entry = {
34 	.name = "refresh-client",
35 	.alias = "refresh",
36 
37 	.args = { "cC:DF:lLRSt:U", 0, 1 },
38 	.usage = "[-cDlLRSU] [-C XxY] [-F flags] " CMD_TARGET_CLIENT_USAGE
39 		" [adjustment]",
40 
41 	.flags = CMD_AFTERHOOK,
42 	.exec = cmd_refresh_client_exec
43 };
44 
45 static enum cmd_retval
46 cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
47 {
48 	struct args	*args = self->args;
49 	struct client	*c;
50 	struct tty	*tty;
51 	struct window	*w;
52 	const char	*size, *errstr;
53 	char		*copy, *next, *s;
54 	u_int		 x, y, adjust;
55 
56 	if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
57 		return (CMD_RETURN_ERROR);
58 	tty = &c->tty;
59 
60 	if (args_has(args, 'c') ||
61 	    args_has(args, 'L') ||
62 	    args_has(args, 'R') ||
63 	    args_has(args, 'U') ||
64 	    args_has(args, 'D'))
65 	{
66 		if (args->argc == 0)
67 			adjust = 1;
68 		else {
69 			adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
70 			if (errstr != NULL) {
71 				cmdq_error(item, "adjustment %s", errstr);
72 				return (CMD_RETURN_ERROR);
73 			}
74 		}
75 
76 		if (args_has(args, 'c'))
77 		    c->pan_window = NULL;
78 		else {
79 			w = c->session->curw->window;
80 			if (c->pan_window != w) {
81 				c->pan_window = w;
82 				c->pan_ox = tty->oox;
83 				c->pan_oy = tty->ooy;
84 			}
85 			if (args_has(args, 'L')) {
86 				if (c->pan_ox > adjust)
87 					c->pan_ox -= adjust;
88 				else
89 					c->pan_ox = 0;
90 			} else if (args_has(args, 'R')) {
91 				c->pan_ox += adjust;
92 				if (c->pan_ox > w->sx - tty->osx)
93 					c->pan_ox = w->sx - tty->osx;
94 			} else if (args_has(args, 'U')) {
95 				if (c->pan_oy > adjust)
96 					c->pan_oy -= adjust;
97 				else
98 					c->pan_oy = 0;
99 			} else if (args_has(args, 'D')) {
100 				c->pan_oy += adjust;
101 				if (c->pan_oy > w->sy - tty->osy)
102 					c->pan_oy = w->sy - tty->osy;
103 			}
104 		}
105 		tty_update_client_offset(c);
106 		server_redraw_client(c);
107 		return (CMD_RETURN_NORMAL);
108 	}
109 
110 	if (args_has(args, 'l')) {
111 		if (c->session != NULL)
112 			tty_putcode_ptr2(&c->tty, TTYC_MS, "", "?");
113 		return (CMD_RETURN_NORMAL);
114 	}
115 
116 	if (args_has(args, 'C') || args_has(args, 'F')) {
117 		if (args_has(args, 'C')) {
118 			if (!(c->flags & CLIENT_CONTROL)) {
119 				cmdq_error(item, "not a control client");
120 				return (CMD_RETURN_ERROR);
121 			}
122 			size = args_get(args, 'C');
123 			if (sscanf(size, "%u,%u", &x, &y) != 2 &&
124 			    sscanf(size, "%ux%u", &x, &y) != 2) {
125 				cmdq_error(item, "bad size argument");
126 				return (CMD_RETURN_ERROR);
127 			}
128 			if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
129 			    y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
130 				cmdq_error(item, "size too small or too big");
131 				return (CMD_RETURN_ERROR);
132 			}
133 			tty_set_size(&c->tty, x, y, 0, 0);
134 			c->flags |= CLIENT_SIZECHANGED;
135 			recalculate_sizes();
136 		}
137 		if (args_has(args, 'F')) {
138 			if (!(c->flags & CLIENT_CONTROL)) {
139 				cmdq_error(item, "not a control client");
140 				return (CMD_RETURN_ERROR);
141 			}
142 			s = copy = xstrdup(args_get(args, 'F'));
143 			while ((next = strsep(&s, ",")) != NULL) {
144 				/* Unknown flags are ignored. */
145 				if (strcmp(next, "no-output") == 0)
146 					c->flags |= CLIENT_CONTROL_NOOUTPUT;
147 			}
148 			free(copy);
149 		}
150 		return (CMD_RETURN_NORMAL);
151 	}
152 
153 	if (args_has(args, 'S')) {
154 		c->flags |= CLIENT_STATUSFORCE;
155 		server_status_client(c);
156 	} else {
157 		c->flags |= CLIENT_STATUSFORCE;
158 		server_redraw_client(c);
159 	}
160 	return (CMD_RETURN_NORMAL);
161 }
162