4 * Copyright (c) 2008 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>
27 * Send keys to client.
30 static enum cmd_retval
cmd_send_keys_exec(struct cmd
*, struct cmdq_item
*);
32 const struct cmd_entry cmd_send_keys_entry
= {
36 .args
= { "FHlMN:Rt:X", 0, -1, NULL
},
37 .usage
= "[-FHlMRX] [-N repeat-count] " CMD_TARGET_PANE_USAGE
40 .target
= { 't', CMD_FIND_PANE
, 0 },
42 .flags
= CMD_AFTERHOOK
,
43 .exec
= cmd_send_keys_exec
46 const struct cmd_entry cmd_send_prefix_entry
= {
47 .name
= "send-prefix",
50 .args
= { "2t:", 0, 0, NULL
},
51 .usage
= "[-2] " CMD_TARGET_PANE_USAGE
,
53 .target
= { 't', CMD_FIND_PANE
, 0 },
55 .flags
= CMD_AFTERHOOK
,
56 .exec
= cmd_send_keys_exec
59 static struct cmdq_item
*
60 cmd_send_keys_inject_key(struct cmdq_item
*item
, struct cmdq_item
*after
,
63 struct cmd_find_state
*target
= cmdq_get_target(item
);
64 struct client
*tc
= cmdq_get_target_client(item
);
65 struct session
*s
= target
->s
;
66 struct winlink
*wl
= target
->wl
;
67 struct window_pane
*wp
= target
->wp
;
68 struct window_mode_entry
*wme
;
69 struct key_table
*table
;
70 struct key_binding
*bd
;
72 wme
= TAILQ_FIRST(&wp
->modes
);
73 if (wme
== NULL
|| wme
->mode
->key_table
== NULL
) {
74 if (window_pane_key(wp
, tc
, s
, wl
, key
, NULL
) != 0)
78 table
= key_bindings_get_table(wme
->mode
->key_table(wme
), 1);
80 bd
= key_bindings_get(table
, key
& ~KEYC_MASK_FLAGS
);
83 after
= key_bindings_dispatch(bd
, after
, tc
, NULL
, target
);
84 key_bindings_unref_table(table
);
89 static struct cmdq_item
*
90 cmd_send_keys_inject_string(struct cmdq_item
*item
, struct cmdq_item
*after
,
91 struct args
*args
, int i
)
93 const char *s
= args_string(args
, i
);
94 struct utf8_data
*ud
, *loop
;
101 if (args_has(args
, 'H')) {
102 n
= strtol(s
, &endptr
, 16);
103 if (*s
=='\0' || n
< 0 || n
> 0xff || *endptr
!= '\0')
105 return (cmd_send_keys_inject_key(item
, after
, KEYC_LITERAL
|n
));
108 literal
= args_has(args
, 'l');
110 key
= key_string_lookup_string(s
);
111 if (key
!= KEYC_NONE
&& key
!= KEYC_UNKNOWN
) {
112 after
= cmd_send_keys_inject_key(item
, after
, key
);
119 ud
= utf8_fromcstr(s
);
120 for (loop
= ud
; loop
->size
!= 0; loop
++) {
121 if (loop
->size
== 1 && loop
->data
[0] <= 0x7f)
124 if (utf8_from_data(loop
, &uc
) != UTF8_DONE
)
128 after
= cmd_send_keys_inject_key(item
, after
, key
);
135 static enum cmd_retval
136 cmd_send_keys_exec(struct cmd
*self
, struct cmdq_item
*item
)
138 struct args
*args
= cmd_get_args(self
);
139 struct cmd_find_state
*target
= cmdq_get_target(item
);
140 struct client
*tc
= cmdq_get_target_client(item
);
141 struct session
*s
= target
->s
;
142 struct winlink
*wl
= target
->wl
;
143 struct window_pane
*wp
= target
->wp
;
144 struct key_event
*event
= cmdq_get_event(item
);
145 struct mouse_event
*m
= &event
->m
;
146 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
147 struct cmdq_item
*after
= item
;
150 u_int count
= args_count(args
);
153 if (args_has(args
, 'N')) {
154 np
= args_strtonum_and_expand(args
, 'N', 1, UINT_MAX
, item
,
157 cmdq_error(item
, "repeat count %s", cause
);
159 return (CMD_RETURN_ERROR
);
161 if (wme
!= NULL
&& (args_has(args
, 'X') || count
== 0)) {
162 if (wme
->mode
->command
== NULL
) {
163 cmdq_error(item
, "not in a mode");
164 return (CMD_RETURN_ERROR
);
170 if (args_has(args
, 'X')) {
171 if (wme
== NULL
|| wme
->mode
->command
== NULL
) {
172 cmdq_error(item
, "not in a mode");
173 return (CMD_RETURN_ERROR
);
177 wme
->mode
->command(wme
, tc
, s
, wl
, args
, m
);
178 return (CMD_RETURN_NORMAL
);
181 if (args_has(args
, 'M')) {
182 wp
= cmd_mouse_pane(m
, &s
, NULL
);
184 cmdq_error(item
, "no mouse target");
185 return (CMD_RETURN_ERROR
);
187 window_pane_key(wp
, tc
, s
, wl
, m
->key
, m
);
188 return (CMD_RETURN_NORMAL
);
191 if (cmd_get_entry(self
) == &cmd_send_prefix_entry
) {
192 if (args_has(args
, '2'))
193 key
= options_get_number(s
->options
, "prefix2");
195 key
= options_get_number(s
->options
, "prefix");
196 cmd_send_keys_inject_key(item
, item
, key
);
197 return (CMD_RETURN_NORMAL
);
200 if (args_has(args
, 'R')) {
201 colour_palette_clear(&wp
->palette
);
202 input_reset(wp
->ictx
, 1);
203 wp
->flags
|= (PANE_STYLECHANGED
|PANE_REDRAW
);
207 if (args_has(args
, 'N') || args_has(args
, 'R'))
208 return (CMD_RETURN_NORMAL
);
209 for (; np
!= 0; np
--)
210 cmd_send_keys_inject_key(item
, NULL
, event
->key
);
211 return (CMD_RETURN_NORMAL
);
214 for (; np
!= 0; np
--) {
215 for (i
= 0; i
< count
; i
++) {
216 after
= cmd_send_keys_inject_string(item
, after
, args
,
221 return (CMD_RETURN_NORMAL
);