1 /* $OpenBSD: cmd-refresh-client.c,v 1.38 2020/06/11 09:55:47 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 = { "A:cC:Df:F:lLRSt:U", 0, 1 }, 38 .usage = "[-cDlLRSU] [-A pane:state] [-C XxY] [-f flags] " 39 CMD_TARGET_CLIENT_USAGE " [adjustment]", 40 41 .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG, 42 .exec = cmd_refresh_client_exec 43 }; 44 45 static void 46 cmd_refresh_client_update_offset(struct client *tc, const char *value) 47 { 48 struct window_pane *wp; 49 char *copy, *colon; 50 u_int pane; 51 52 if (*value != '%') 53 return; 54 copy = xstrdup(value); 55 if ((colon = strchr(copy, ':')) == NULL) 56 goto out; 57 *colon++ = '\0'; 58 59 if (sscanf(copy, "%%%u", &pane) != 1) 60 goto out; 61 wp = window_pane_find_by_id(pane); 62 if (wp == NULL) 63 goto out; 64 65 if (strcmp(colon, "on") == 0) 66 control_set_pane_on(tc, wp); 67 else if (strcmp(colon, "off") == 0) 68 control_set_pane_off(tc, wp); 69 else if (strcmp(colon, "continue") == 0) 70 control_continue_pane(tc, wp); 71 else if (strcmp(colon, "pause") == 0) 72 control_pause_pane(tc, wp); 73 74 out: 75 free(copy); 76 } 77 78 static enum cmd_retval 79 cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item) 80 { 81 struct args *args = cmd_get_args(self); 82 struct client *tc = cmdq_get_target_client(item); 83 struct tty *tty = &tc->tty; 84 struct window *w; 85 const char *size, *errstr, *value; 86 u_int x, y, adjust; 87 struct args_value *av; 88 89 if (args_has(args, 'c') || 90 args_has(args, 'L') || 91 args_has(args, 'R') || 92 args_has(args, 'U') || 93 args_has(args, 'D')) 94 { 95 if (args->argc == 0) 96 adjust = 1; 97 else { 98 adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); 99 if (errstr != NULL) { 100 cmdq_error(item, "adjustment %s", errstr); 101 return (CMD_RETURN_ERROR); 102 } 103 } 104 105 if (args_has(args, 'c')) 106 tc->pan_window = NULL; 107 else { 108 w = tc->session->curw->window; 109 if (tc->pan_window != w) { 110 tc->pan_window = w; 111 tc->pan_ox = tty->oox; 112 tc->pan_oy = tty->ooy; 113 } 114 if (args_has(args, 'L')) { 115 if (tc->pan_ox > adjust) 116 tc->pan_ox -= adjust; 117 else 118 tc->pan_ox = 0; 119 } else if (args_has(args, 'R')) { 120 tc->pan_ox += adjust; 121 if (tc->pan_ox > w->sx - tty->osx) 122 tc->pan_ox = w->sx - tty->osx; 123 } else if (args_has(args, 'U')) { 124 if (tc->pan_oy > adjust) 125 tc->pan_oy -= adjust; 126 else 127 tc->pan_oy = 0; 128 } else if (args_has(args, 'D')) { 129 tc->pan_oy += adjust; 130 if (tc->pan_oy > w->sy - tty->osy) 131 tc->pan_oy = w->sy - tty->osy; 132 } 133 } 134 tty_update_client_offset(tc); 135 server_redraw_client(tc); 136 return (CMD_RETURN_NORMAL); 137 } 138 139 if (args_has(args, 'l')) { 140 tty_putcode_ptr2(&tc->tty, TTYC_MS, "", "?"); 141 return (CMD_RETURN_NORMAL); 142 } 143 144 if (args_has(args, 'F')) /* -F is an alias for -f */ 145 server_client_set_flags(tc, args_get(args, 'F')); 146 if (args_has(args, 'f')) 147 server_client_set_flags(tc, args_get(args, 'f')); 148 149 if (args_has(args, 'A')) { 150 if (~tc->flags & CLIENT_CONTROL) 151 goto not_control_client; 152 value = args_first_value(args, 'A', &av); 153 while (value != NULL) { 154 cmd_refresh_client_update_offset(tc, value); 155 value = args_next_value(&av); 156 } 157 return (CMD_RETURN_NORMAL); 158 } 159 if (args_has(args, 'C')) { 160 if (~tc->flags & CLIENT_CONTROL) 161 goto not_control_client; 162 size = args_get(args, 'C'); 163 if (sscanf(size, "%u,%u", &x, &y) != 2 && 164 sscanf(size, "%ux%u", &x, &y) != 2) { 165 cmdq_error(item, "bad size argument"); 166 return (CMD_RETURN_ERROR); 167 } 168 if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM || 169 y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) { 170 cmdq_error(item, "size too small or too big"); 171 return (CMD_RETURN_ERROR); 172 } 173 tty_set_size(&tc->tty, x, y, 0, 0); 174 tc->flags |= CLIENT_SIZECHANGED; 175 recalculate_sizes_now(1); 176 return (CMD_RETURN_NORMAL); 177 } 178 179 if (args_has(args, 'S')) { 180 tc->flags |= CLIENT_STATUSFORCE; 181 server_status_client(tc); 182 } else { 183 tc->flags |= CLIENT_STATUSFORCE; 184 server_redraw_client(tc); 185 } 186 return (CMD_RETURN_NORMAL); 187 188 not_control_client: 189 cmdq_error(item, "not a control client"); 190 return (CMD_RETURN_ERROR); 191 } 192