4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
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.
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.
19 #include <sys/types.h>
30 static enum cmd_retval
cmd_refresh_client_exec(struct cmd
*,
33 const struct cmd_entry cmd_refresh_client_entry
= {
34 .name
= "refresh-client",
37 .args
= { "A:B:cC:Df:F:l::LRSt:U", 0, 1, NULL
},
38 .usage
= "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
39 "[-C XxY] [-f flags] " CMD_TARGET_CLIENT_USAGE
" [adjustment]",
41 .flags
= CMD_AFTERHOOK
|CMD_CLIENT_TFLAG
,
42 .exec
= cmd_refresh_client_exec
46 cmd_refresh_client_update_subscription(struct client
*tc
, const char *value
)
48 char *copy
, *split
, *name
, *what
;
49 enum control_sub_type subtype
;
52 copy
= name
= xstrdup(value
);
53 if ((split
= strchr(copy
, ':')) == NULL
) {
54 control_remove_sub(tc
, copy
);
60 if ((split
= strchr(what
, ':')) == NULL
)
64 if (strcmp(what
, "%*") == 0)
65 subtype
= CONTROL_SUB_ALL_PANES
;
66 else if (sscanf(what
, "%%%d", &subid
) == 1 && subid
>= 0)
67 subtype
= CONTROL_SUB_PANE
;
68 else if (strcmp(what
, "@*") == 0)
69 subtype
= CONTROL_SUB_ALL_WINDOWS
;
70 else if (sscanf(what
, "@%d", &subid
) == 1 && subid
>= 0)
71 subtype
= CONTROL_SUB_WINDOW
;
73 subtype
= CONTROL_SUB_SESSION
;
74 control_add_sub(tc
, name
, subtype
, subid
, split
);
80 static enum cmd_retval
81 cmd_refresh_client_control_client_size(struct cmd
*self
, struct cmdq_item
*item
)
83 struct args
*args
= cmd_get_args(self
);
84 struct client
*tc
= cmdq_get_target_client(item
);
85 const char *size
= args_get(args
, 'C');
87 struct client_window
*cw
;
89 if (sscanf(size
, "@%u:%ux%u", &w
, &x
, &y
) == 3) {
90 if (x
< WINDOW_MINIMUM
|| x
> WINDOW_MAXIMUM
||
91 y
< WINDOW_MINIMUM
|| y
> WINDOW_MAXIMUM
) {
92 cmdq_error(item
, "size too small or too big");
93 return (CMD_RETURN_ERROR
);
95 log_debug("%s: client %s window @%u: size %ux%u", __func__
,
97 cw
= server_client_add_client_window(tc
, w
);
100 tc
->flags
|= CLIENT_WINDOWSIZECHANGED
;
101 recalculate_sizes_now(1);
102 return (CMD_RETURN_NORMAL
);
104 if (sscanf(size
, "@%u:", &w
) == 1) {
105 cw
= server_client_get_client_window(tc
, w
);
107 log_debug("%s: client %s window @%u: no size", __func__
,
111 recalculate_sizes_now(1);
113 return (CMD_RETURN_NORMAL
);
116 if (sscanf(size
, "%u,%u", &x
, &y
) != 2 &&
117 sscanf(size
, "%ux%u", &x
, &y
) != 2) {
118 cmdq_error(item
, "bad size argument");
119 return (CMD_RETURN_ERROR
);
121 if (x
< WINDOW_MINIMUM
|| x
> WINDOW_MAXIMUM
||
122 y
< WINDOW_MINIMUM
|| y
> WINDOW_MAXIMUM
) {
123 cmdq_error(item
, "size too small or too big");
124 return (CMD_RETURN_ERROR
);
126 tty_set_size(&tc
->tty
, x
, y
, 0, 0);
127 tc
->flags
|= CLIENT_SIZECHANGED
;
128 recalculate_sizes_now(1);
129 return (CMD_RETURN_NORMAL
);
133 cmd_refresh_client_update_offset(struct client
*tc
, const char *value
)
135 struct window_pane
*wp
;
141 copy
= xstrdup(value
);
142 if ((split
= strchr(copy
, ':')) == NULL
)
146 if (sscanf(copy
, "%%%u", &pane
) != 1)
148 wp
= window_pane_find_by_id(pane
);
152 if (strcmp(split
, "on") == 0)
153 control_set_pane_on(tc
, wp
);
154 else if (strcmp(split
, "off") == 0)
155 control_set_pane_off(tc
, wp
);
156 else if (strcmp(split
, "continue") == 0)
157 control_continue_pane(tc
, wp
);
158 else if (strcmp(split
, "pause") == 0)
159 control_pause_pane(tc
, wp
);
165 static enum cmd_retval
166 cmd_refresh_client_clipboard(struct cmd
*self
, struct cmdq_item
*item
)
168 struct args
*args
= cmd_get_args(self
);
169 struct client
*tc
= cmdq_get_target_client(item
);
172 struct cmd_find_state fs
;
174 p
= args_get(args
, 'l');
176 if (tc
->flags
& CLIENT_CLIPBOARDBUFFER
)
177 return (CMD_RETURN_NORMAL
);
178 tc
->flags
|= CLIENT_CLIPBOARDBUFFER
;
180 if (cmd_find_target(&fs
, item
, p
, CMD_FIND_PANE
, 0) != 0)
181 return (CMD_RETURN_ERROR
);
182 for (i
= 0; i
< tc
->clipboard_npanes
; i
++) {
183 if (tc
->clipboard_panes
[i
] == fs
.wp
->id
)
186 if (i
!= tc
->clipboard_npanes
)
187 return (CMD_RETURN_NORMAL
);
188 tc
->clipboard_panes
= xreallocarray(tc
->clipboard_panes
,
189 tc
->clipboard_npanes
+ 1, sizeof *tc
->clipboard_panes
);
190 tc
->clipboard_panes
[tc
->clipboard_npanes
++] = fs
.wp
->id
;
192 tty_clipboard_query(&tc
->tty
);
193 return (CMD_RETURN_NORMAL
);
196 static enum cmd_retval
197 cmd_refresh_client_exec(struct cmd
*self
, struct cmdq_item
*item
)
199 struct args
*args
= cmd_get_args(self
);
200 struct client
*tc
= cmdq_get_target_client(item
);
201 struct tty
*tty
= &tc
->tty
;
205 struct args_value
*av
;
207 if (args_has(args
, 'c') ||
208 args_has(args
, 'L') ||
209 args_has(args
, 'R') ||
210 args_has(args
, 'U') ||
213 if (args_count(args
) == 0)
216 adjust
= strtonum(args_string(args
, 0), 1, INT_MAX
,
218 if (errstr
!= NULL
) {
219 cmdq_error(item
, "adjustment %s", errstr
);
220 return (CMD_RETURN_ERROR
);
224 if (args_has(args
, 'c'))
225 tc
->pan_window
= NULL
;
227 w
= tc
->session
->curw
->window
;
228 if (tc
->pan_window
!= w
) {
230 tc
->pan_ox
= tty
->oox
;
231 tc
->pan_oy
= tty
->ooy
;
233 if (args_has(args
, 'L')) {
234 if (tc
->pan_ox
> adjust
)
235 tc
->pan_ox
-= adjust
;
238 } else if (args_has(args
, 'R')) {
239 tc
->pan_ox
+= adjust
;
240 if (tc
->pan_ox
> w
->sx
- tty
->osx
)
241 tc
->pan_ox
= w
->sx
- tty
->osx
;
242 } else if (args_has(args
, 'U')) {
243 if (tc
->pan_oy
> adjust
)
244 tc
->pan_oy
-= adjust
;
247 } else if (args_has(args
, 'D')) {
248 tc
->pan_oy
+= adjust
;
249 if (tc
->pan_oy
> w
->sy
- tty
->osy
)
250 tc
->pan_oy
= w
->sy
- tty
->osy
;
253 tty_update_client_offset(tc
);
254 server_redraw_client(tc
);
255 return (CMD_RETURN_NORMAL
);
258 if (args_has(args
, 'l'))
259 return (cmd_refresh_client_clipboard(self
, item
));
261 if (args_has(args
, 'F')) /* -F is an alias for -f */
262 server_client_set_flags(tc
, args_get(args
, 'F'));
263 if (args_has(args
, 'f'))
264 server_client_set_flags(tc
, args_get(args
, 'f'));
266 if (args_has(args
, 'A')) {
267 if (~tc
->flags
& CLIENT_CONTROL
)
268 goto not_control_client
;
269 av
= args_first_value(args
, 'A');
271 cmd_refresh_client_update_offset(tc
, av
->string
);
272 av
= args_next_value(av
);
274 return (CMD_RETURN_NORMAL
);
276 if (args_has(args
, 'B')) {
277 if (~tc
->flags
& CLIENT_CONTROL
)
278 goto not_control_client
;
279 av
= args_first_value(args
, 'B');
281 cmd_refresh_client_update_subscription(tc
, av
->string
);
282 av
= args_next_value(av
);
284 return (CMD_RETURN_NORMAL
);
286 if (args_has(args
, 'C')) {
287 if (~tc
->flags
& CLIENT_CONTROL
)
288 goto not_control_client
;
289 return (cmd_refresh_client_control_client_size(self
, item
));
292 if (args_has(args
, 'S')) {
293 tc
->flags
|= CLIENT_STATUSFORCE
;
294 server_status_client(tc
);
296 tc
->flags
|= CLIENT_STATUSFORCE
;
297 server_redraw_client(tc
);
299 return (CMD_RETURN_NORMAL
);
302 cmdq_error(item
, "not a control client");
303 return (CMD_RETURN_ERROR
);