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:r:F:l::LRSt:U", 0, 1, NULL
},
38 .usage
= "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
39 "[-C XxY] [-f flags] [-r pane:report]" CMD_TARGET_CLIENT_USAGE
42 .flags
= CMD_AFTERHOOK
|CMD_CLIENT_TFLAG
,
43 .exec
= cmd_refresh_client_exec
47 cmd_refresh_client_update_subscription(struct client
*tc
, const char *value
)
49 char *copy
, *split
, *name
, *what
;
50 enum control_sub_type subtype
;
53 copy
= name
= xstrdup(value
);
54 if ((split
= strchr(copy
, ':')) == NULL
) {
55 control_remove_sub(tc
, copy
);
61 if ((split
= strchr(what
, ':')) == NULL
)
65 if (strcmp(what
, "%*") == 0)
66 subtype
= CONTROL_SUB_ALL_PANES
;
67 else if (sscanf(what
, "%%%d", &subid
) == 1 && subid
>= 0)
68 subtype
= CONTROL_SUB_PANE
;
69 else if (strcmp(what
, "@*") == 0)
70 subtype
= CONTROL_SUB_ALL_WINDOWS
;
71 else if (sscanf(what
, "@%d", &subid
) == 1 && subid
>= 0)
72 subtype
= CONTROL_SUB_WINDOW
;
74 subtype
= CONTROL_SUB_SESSION
;
75 control_add_sub(tc
, name
, subtype
, subid
, split
);
81 static enum cmd_retval
82 cmd_refresh_client_control_client_size(struct cmd
*self
, struct cmdq_item
*item
)
84 struct args
*args
= cmd_get_args(self
);
85 struct client
*tc
= cmdq_get_target_client(item
);
86 const char *size
= args_get(args
, 'C');
88 struct client_window
*cw
;
90 if (sscanf(size
, "@%u:%ux%u", &w
, &x
, &y
) == 3) {
91 if (x
< WINDOW_MINIMUM
|| x
> WINDOW_MAXIMUM
||
92 y
< WINDOW_MINIMUM
|| y
> WINDOW_MAXIMUM
) {
93 cmdq_error(item
, "size too small or too big");
94 return (CMD_RETURN_ERROR
);
96 log_debug("%s: client %s window @%u: size %ux%u", __func__
,
98 cw
= server_client_add_client_window(tc
, w
);
101 tc
->flags
|= CLIENT_WINDOWSIZECHANGED
;
102 recalculate_sizes_now(1);
103 return (CMD_RETURN_NORMAL
);
105 if (sscanf(size
, "@%u:", &w
) == 1) {
106 cw
= server_client_get_client_window(tc
, w
);
108 log_debug("%s: client %s window @%u: no size", __func__
,
112 recalculate_sizes_now(1);
114 return (CMD_RETURN_NORMAL
);
117 if (sscanf(size
, "%u,%u", &x
, &y
) != 2 &&
118 sscanf(size
, "%ux%u", &x
, &y
) != 2) {
119 cmdq_error(item
, "bad size argument");
120 return (CMD_RETURN_ERROR
);
122 if (x
< WINDOW_MINIMUM
|| x
> WINDOW_MAXIMUM
||
123 y
< WINDOW_MINIMUM
|| y
> WINDOW_MAXIMUM
) {
124 cmdq_error(item
, "size too small or too big");
125 return (CMD_RETURN_ERROR
);
127 tty_set_size(&tc
->tty
, x
, y
, 0, 0);
128 tc
->flags
|= CLIENT_SIZECHANGED
;
129 recalculate_sizes_now(1);
130 return (CMD_RETURN_NORMAL
);
134 cmd_refresh_client_update_offset(struct client
*tc
, const char *value
)
136 struct window_pane
*wp
;
142 copy
= xstrdup(value
);
143 if ((split
= strchr(copy
, ':')) == NULL
)
147 if (sscanf(copy
, "%%%u", &pane
) != 1)
149 wp
= window_pane_find_by_id(pane
);
153 if (strcmp(split
, "on") == 0)
154 control_set_pane_on(tc
, wp
);
155 else if (strcmp(split
, "off") == 0)
156 control_set_pane_off(tc
, wp
);
157 else if (strcmp(split
, "continue") == 0)
158 control_continue_pane(tc
, wp
);
159 else if (strcmp(split
, "pause") == 0)
160 control_pause_pane(tc
, wp
);
166 static enum cmd_retval
167 cmd_refresh_client_clipboard(struct cmd
*self
, struct cmdq_item
*item
)
169 struct args
*args
= cmd_get_args(self
);
170 struct client
*tc
= cmdq_get_target_client(item
);
173 struct cmd_find_state fs
;
175 p
= args_get(args
, 'l');
177 if (tc
->flags
& CLIENT_CLIPBOARDBUFFER
)
178 return (CMD_RETURN_NORMAL
);
179 tc
->flags
|= CLIENT_CLIPBOARDBUFFER
;
181 if (cmd_find_target(&fs
, item
, p
, CMD_FIND_PANE
, 0) != 0)
182 return (CMD_RETURN_ERROR
);
183 for (i
= 0; i
< tc
->clipboard_npanes
; i
++) {
184 if (tc
->clipboard_panes
[i
] == fs
.wp
->id
)
187 if (i
!= tc
->clipboard_npanes
)
188 return (CMD_RETURN_NORMAL
);
189 tc
->clipboard_panes
= xreallocarray(tc
->clipboard_panes
,
190 tc
->clipboard_npanes
+ 1, sizeof *tc
->clipboard_panes
);
191 tc
->clipboard_panes
[tc
->clipboard_npanes
++] = fs
.wp
->id
;
193 tty_clipboard_query(&tc
->tty
);
194 return (CMD_RETURN_NORMAL
);
198 cmd_refresh_report(struct tty
*tty
, const char *value
)
200 struct window_pane
*wp
;
207 copy
= xstrdup(value
);
208 if ((split
= strchr(copy
, ':')) == NULL
)
212 if (sscanf(copy
, "%%%u", &pane
) != 1)
214 wp
= window_pane_find_by_id(pane
);
218 tty_keys_colours(tty
, split
, strlen(split
), &size
, &wp
->control_fg
,
225 static enum cmd_retval
226 cmd_refresh_client_exec(struct cmd
*self
, struct cmdq_item
*item
)
228 struct args
*args
= cmd_get_args(self
);
229 struct client
*tc
= cmdq_get_target_client(item
);
230 struct tty
*tty
= &tc
->tty
;
234 struct args_value
*av
;
236 if (args_has(args
, 'c') ||
237 args_has(args
, 'L') ||
238 args_has(args
, 'R') ||
239 args_has(args
, 'U') ||
242 if (args_count(args
) == 0)
245 adjust
= strtonum(args_string(args
, 0), 1, INT_MAX
,
247 if (errstr
!= NULL
) {
248 cmdq_error(item
, "adjustment %s", errstr
);
249 return (CMD_RETURN_ERROR
);
253 if (args_has(args
, 'c'))
254 tc
->pan_window
= NULL
;
256 w
= tc
->session
->curw
->window
;
257 if (tc
->pan_window
!= w
) {
259 tc
->pan_ox
= tty
->oox
;
260 tc
->pan_oy
= tty
->ooy
;
262 if (args_has(args
, 'L')) {
263 if (tc
->pan_ox
> adjust
)
264 tc
->pan_ox
-= adjust
;
267 } else if (args_has(args
, 'R')) {
268 tc
->pan_ox
+= adjust
;
269 if (tc
->pan_ox
> w
->sx
- tty
->osx
)
270 tc
->pan_ox
= w
->sx
- tty
->osx
;
271 } else if (args_has(args
, 'U')) {
272 if (tc
->pan_oy
> adjust
)
273 tc
->pan_oy
-= adjust
;
276 } else if (args_has(args
, 'D')) {
277 tc
->pan_oy
+= adjust
;
278 if (tc
->pan_oy
> w
->sy
- tty
->osy
)
279 tc
->pan_oy
= w
->sy
- tty
->osy
;
282 tty_update_client_offset(tc
);
283 server_redraw_client(tc
);
284 return (CMD_RETURN_NORMAL
);
287 if (args_has(args
, 'l'))
288 return (cmd_refresh_client_clipboard(self
, item
));
290 if (args_has(args
, 'F')) /* -F is an alias for -f */
291 server_client_set_flags(tc
, args_get(args
, 'F'));
292 if (args_has(args
, 'f'))
293 server_client_set_flags(tc
, args_get(args
, 'f'));
294 if (args_has(args
, 'r'))
295 cmd_refresh_report(tty
, args_get(args
, 'r'));
297 if (args_has(args
, 'A')) {
298 if (~tc
->flags
& CLIENT_CONTROL
)
299 goto not_control_client
;
300 av
= args_first_value(args
, 'A');
302 cmd_refresh_client_update_offset(tc
, av
->string
);
303 av
= args_next_value(av
);
305 return (CMD_RETURN_NORMAL
);
307 if (args_has(args
, 'B')) {
308 if (~tc
->flags
& CLIENT_CONTROL
)
309 goto not_control_client
;
310 av
= args_first_value(args
, 'B');
312 cmd_refresh_client_update_subscription(tc
, av
->string
);
313 av
= args_next_value(av
);
315 return (CMD_RETURN_NORMAL
);
317 if (args_has(args
, 'C')) {
318 if (~tc
->flags
& CLIENT_CONTROL
)
319 goto not_control_client
;
320 return (cmd_refresh_client_control_client_size(self
, item
));
323 if (args_has(args
, 'S')) {
324 tc
->flags
|= CLIENT_STATUSFORCE
;
325 server_status_client(tc
);
327 tc
->flags
|= CLIENT_STATUSFORCE
;
328 server_redraw_client(tc
);
330 return (CMD_RETURN_NORMAL
);
333 cmdq_error(item
, "not a control client");
334 return (CMD_RETURN_ERROR
);