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(args
, 'N', 1, UINT_MAX
, &cause
);
156 cmdq_error(item
, "repeat count %s", cause
);
158 return (CMD_RETURN_ERROR
);
160 if (wme
!= NULL
&& (args_has(args
, 'X') || count
== 0)) {
161 if (wme
->mode
->command
== NULL
) {
162 cmdq_error(item
, "not in a mode");
163 return (CMD_RETURN_ERROR
);
169 if (args_has(args
, 'X')) {
170 if (wme
== NULL
|| wme
->mode
->command
== NULL
) {
171 cmdq_error(item
, "not in a mode");
172 return (CMD_RETURN_ERROR
);
176 wme
->mode
->command(wme
, tc
, s
, wl
, args
, m
);
177 return (CMD_RETURN_NORMAL
);
180 if (args_has(args
, 'M')) {
181 wp
= cmd_mouse_pane(m
, &s
, NULL
);
183 cmdq_error(item
, "no mouse target");
184 return (CMD_RETURN_ERROR
);
186 window_pane_key(wp
, tc
, s
, wl
, m
->key
, m
);
187 return (CMD_RETURN_NORMAL
);
190 if (cmd_get_entry(self
) == &cmd_send_prefix_entry
) {
191 if (args_has(args
, '2'))
192 key
= options_get_number(s
->options
, "prefix2");
194 key
= options_get_number(s
->options
, "prefix");
195 cmd_send_keys_inject_key(item
, item
, key
);
196 return (CMD_RETURN_NORMAL
);
199 if (args_has(args
, 'R')) {
200 colour_palette_clear(&wp
->palette
);
201 input_reset(wp
->ictx
, 1);
202 wp
->flags
|= (PANE_STYLECHANGED
|PANE_REDRAW
);
206 if (args_has(args
, 'N') || args_has(args
, 'R'))
207 return (CMD_RETURN_NORMAL
);
208 for (; np
!= 0; np
--)
209 cmd_send_keys_inject_key(item
, NULL
, event
->key
);
210 return (CMD_RETURN_NORMAL
);
213 for (; np
!= 0; np
--) {
214 for (i
= 0; i
< count
; i
++) {
215 after
= cmd_send_keys_inject_string(item
, after
, args
,
220 return (CMD_RETURN_NORMAL
);