1 /* $OpenBSD$ */
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 #include <sys/time.h>
21
22 #include <limits.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <termios.h>
26 #include <unistd.h>
27
28 #include "tmux.h"
29
30 /*
31 * Handle keys input from the outside terminal. tty_default_*_keys[] are a base
32 * table of supported keys which are looked up in terminfo(5) and translated
33 * into a ternary tree.
34 */
35
36 void tty_keys_add1(struct tty_key **, const char *, key_code);
37 void tty_keys_add(struct tty *, const char *, key_code);
38 void tty_keys_free1(struct tty_key *);
39 struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t,
40 size_t *);
41 struct tty_key *tty_keys_find(struct tty *, const char *, size_t, size_t *);
42 void tty_keys_callback(int, short, void *);
43 int tty_keys_mouse(struct tty *, const char *, size_t, size_t *);
44
45 /* Default raw keys. */
46 struct tty_default_key_raw {
47 const char *string;
48 key_code key;
49 };
50 const struct tty_default_key_raw tty_default_raw_keys[] = {
51 /*
52 * Numeric keypad. Just use the vt100 escape sequences here and always
53 * put the terminal into keypad_xmit mode. Translation of numbers
54 * mode/applications mode is done in input-keys.c.
55 */
56 { "\033Oo", KEYC_KP_SLASH },
57 { "\033Oj", KEYC_KP_STAR },
58 { "\033Om", KEYC_KP_MINUS },
59 { "\033Ow", KEYC_KP_SEVEN },
60 { "\033Ox", KEYC_KP_EIGHT },
61 { "\033Oy", KEYC_KP_NINE },
62 { "\033Ok", KEYC_KP_PLUS },
63 { "\033Ot", KEYC_KP_FOUR },
64 { "\033Ou", KEYC_KP_FIVE },
65 { "\033Ov", KEYC_KP_SIX },
66 { "\033Oq", KEYC_KP_ONE },
67 { "\033Or", KEYC_KP_TWO },
68 { "\033Os", KEYC_KP_THREE },
69 { "\033OM", KEYC_KP_ENTER },
70 { "\033Op", KEYC_KP_ZERO },
71 { "\033On", KEYC_KP_PERIOD },
72
73 /* Arrow keys. */
74 { "\033OA", KEYC_UP },
75 { "\033OB", KEYC_DOWN },
76 { "\033OC", KEYC_RIGHT },
77 { "\033OD", KEYC_LEFT },
78
79 { "\033[A", KEYC_UP },
80 { "\033[B", KEYC_DOWN },
81 { "\033[C", KEYC_RIGHT },
82 { "\033[D", KEYC_LEFT },
83
84 /* Other (xterm) "cursor" keys. */
85 { "\033OH", KEYC_HOME },
86 { "\033OF", KEYC_END },
87
88 { "\033[H", KEYC_HOME },
89 { "\033[F", KEYC_END },
90
91 /* rxvt-style arrow + modifier keys. */
92 { "\033Oa", KEYC_UP|KEYC_CTRL },
93 { "\033Ob", KEYC_DOWN|KEYC_CTRL },
94 { "\033Oc", KEYC_RIGHT|KEYC_CTRL },
95 { "\033Od", KEYC_LEFT|KEYC_CTRL },
96
97 { "\033[a", KEYC_UP|KEYC_SHIFT },
98 { "\033[b", KEYC_DOWN|KEYC_SHIFT },
99 { "\033[c", KEYC_RIGHT|KEYC_SHIFT },
100 { "\033[d", KEYC_LEFT|KEYC_SHIFT },
101
102 /* rxvt-style function + modifier keys (C = ^, S = $, C-S = @). */
103 { "\033[11^", KEYC_F1|KEYC_CTRL },
104 { "\033[12^", KEYC_F2|KEYC_CTRL },
105 { "\033[13^", KEYC_F3|KEYC_CTRL },
106 { "\033[14^", KEYC_F4|KEYC_CTRL },
107 { "\033[15^", KEYC_F5|KEYC_CTRL },
108 { "\033[17^", KEYC_F6|KEYC_CTRL },
109 { "\033[18^", KEYC_F7|KEYC_CTRL },
110 { "\033[19^", KEYC_F8|KEYC_CTRL },
111 { "\033[20^", KEYC_F9|KEYC_CTRL },
112 { "\033[21^", KEYC_F10|KEYC_CTRL },
113 { "\033[23^", KEYC_F11|KEYC_CTRL },
114 { "\033[24^", KEYC_F12|KEYC_CTRL },
115 { "\033[2^", KEYC_IC|KEYC_CTRL },
116 { "\033[3^", KEYC_DC|KEYC_CTRL },
117 { "\033[7^", KEYC_HOME|KEYC_CTRL },
118 { "\033[8^", KEYC_END|KEYC_CTRL },
119 { "\033[6^", KEYC_NPAGE|KEYC_CTRL },
120 { "\033[5^", KEYC_PPAGE|KEYC_CTRL },
121
122 { "\033[11$", KEYC_F1|KEYC_SHIFT },
123 { "\033[12$", KEYC_F2|KEYC_SHIFT },
124 { "\033[13$", KEYC_F3|KEYC_SHIFT },
125 { "\033[14$", KEYC_F4|KEYC_SHIFT },
126 { "\033[15$", KEYC_F5|KEYC_SHIFT },
127 { "\033[17$", KEYC_F6|KEYC_SHIFT },
128 { "\033[18$", KEYC_F7|KEYC_SHIFT },
129 { "\033[19$", KEYC_F8|KEYC_SHIFT },
130 { "\033[20$", KEYC_F9|KEYC_SHIFT },
131 { "\033[21$", KEYC_F10|KEYC_SHIFT },
132 { "\033[23$", KEYC_F11|KEYC_SHIFT },
133 { "\033[24$", KEYC_F12|KEYC_SHIFT },
134 { "\033[2$", KEYC_IC|KEYC_SHIFT },
135 { "\033[3$", KEYC_DC|KEYC_SHIFT },
136 { "\033[7$", KEYC_HOME|KEYC_SHIFT },
137 { "\033[8$", KEYC_END|KEYC_SHIFT },
138 { "\033[6$", KEYC_NPAGE|KEYC_SHIFT },
139 { "\033[5$", KEYC_PPAGE|KEYC_SHIFT },
140
141 { "\033[11@", KEYC_F1|KEYC_CTRL|KEYC_SHIFT },
142 { "\033[12@", KEYC_F2|KEYC_CTRL|KEYC_SHIFT },
143 { "\033[13@", KEYC_F3|KEYC_CTRL|KEYC_SHIFT },
144 { "\033[14@", KEYC_F4|KEYC_CTRL|KEYC_SHIFT },
145 { "\033[15@", KEYC_F5|KEYC_CTRL|KEYC_SHIFT },
146 { "\033[17@", KEYC_F6|KEYC_CTRL|KEYC_SHIFT },
147 { "\033[18@", KEYC_F7|KEYC_CTRL|KEYC_SHIFT },
148 { "\033[19@", KEYC_F8|KEYC_CTRL|KEYC_SHIFT },
149 { "\033[20@", KEYC_F9|KEYC_CTRL|KEYC_SHIFT },
150 { "\033[21@", KEYC_F10|KEYC_CTRL|KEYC_SHIFT },
151 { "\033[23@", KEYC_F11|KEYC_CTRL|KEYC_SHIFT },
152 { "\033[24@", KEYC_F12|KEYC_CTRL|KEYC_SHIFT },
153 { "\033[2@", KEYC_IC|KEYC_CTRL|KEYC_SHIFT },
154 { "\033[3@", KEYC_DC|KEYC_CTRL|KEYC_SHIFT },
155 { "\033[7@", KEYC_HOME|KEYC_CTRL|KEYC_SHIFT },
156 { "\033[8@", KEYC_END|KEYC_CTRL|KEYC_SHIFT },
157 { "\033[6@", KEYC_NPAGE|KEYC_CTRL|KEYC_SHIFT },
158 { "\033[5@", KEYC_PPAGE|KEYC_CTRL|KEYC_SHIFT },
159
160 /* Focus tracking. */
161 { "\033[I", KEYC_FOCUS_IN },
162 { "\033[O", KEYC_FOCUS_OUT },
163 };
164
165 /* Default terminfo(5) keys. */
166 struct tty_default_key_code {
167 enum tty_code_code code;
168 key_code key;
169 };
170 const struct tty_default_key_code tty_default_code_keys[] = {
171 /* Function keys. */
172 { TTYC_KF1, KEYC_F1 },
173 { TTYC_KF2, KEYC_F2 },
174 { TTYC_KF3, KEYC_F3 },
175 { TTYC_KF4, KEYC_F4 },
176 { TTYC_KF5, KEYC_F5 },
177 { TTYC_KF6, KEYC_F6 },
178 { TTYC_KF7, KEYC_F7 },
179 { TTYC_KF8, KEYC_F8 },
180 { TTYC_KF9, KEYC_F9 },
181 { TTYC_KF10, KEYC_F10 },
182 { TTYC_KF11, KEYC_F11 },
183 { TTYC_KF12, KEYC_F12 },
184
185 { TTYC_KF13, KEYC_F1|KEYC_SHIFT },
186 { TTYC_KF14, KEYC_F2|KEYC_SHIFT },
187 { TTYC_KF15, KEYC_F3|KEYC_SHIFT },
188 { TTYC_KF16, KEYC_F4|KEYC_SHIFT },
189 { TTYC_KF17, KEYC_F5|KEYC_SHIFT },
190 { TTYC_KF18, KEYC_F6|KEYC_SHIFT },
191 { TTYC_KF19, KEYC_F7|KEYC_SHIFT },
192 { TTYC_KF20, KEYC_F8|KEYC_SHIFT },
193 { TTYC_KF21, KEYC_F9|KEYC_SHIFT },
194 { TTYC_KF22, KEYC_F10|KEYC_SHIFT },
195 { TTYC_KF23, KEYC_F11|KEYC_SHIFT },
196 { TTYC_KF24, KEYC_F12|KEYC_SHIFT },
197
198 { TTYC_KF25, KEYC_F1|KEYC_CTRL },
199 { TTYC_KF26, KEYC_F2|KEYC_CTRL },
200 { TTYC_KF27, KEYC_F3|KEYC_CTRL },
201 { TTYC_KF28, KEYC_F4|KEYC_CTRL },
202 { TTYC_KF29, KEYC_F5|KEYC_CTRL },
203 { TTYC_KF30, KEYC_F6|KEYC_CTRL },
204 { TTYC_KF31, KEYC_F7|KEYC_CTRL },
205 { TTYC_KF32, KEYC_F8|KEYC_CTRL },
206 { TTYC_KF33, KEYC_F9|KEYC_CTRL },
207 { TTYC_KF34, KEYC_F10|KEYC_CTRL },
208 { TTYC_KF35, KEYC_F11|KEYC_CTRL },
209 { TTYC_KF36, KEYC_F12|KEYC_CTRL },
210
211 { TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL },
212 { TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL },
213 { TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL },
214 { TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL },
215 { TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL },
216 { TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL },
217 { TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL },
218 { TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL },
219 { TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL },
220 { TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL },
221 { TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL },
222 { TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL },
223
224 { TTYC_KF49, KEYC_F1|KEYC_ESCAPE },
225 { TTYC_KF50, KEYC_F2|KEYC_ESCAPE },
226 { TTYC_KF51, KEYC_F3|KEYC_ESCAPE },
227 { TTYC_KF52, KEYC_F4|KEYC_ESCAPE },
228 { TTYC_KF53, KEYC_F5|KEYC_ESCAPE },
229 { TTYC_KF54, KEYC_F6|KEYC_ESCAPE },
230 { TTYC_KF55, KEYC_F7|KEYC_ESCAPE },
231 { TTYC_KF56, KEYC_F8|KEYC_ESCAPE },
232 { TTYC_KF57, KEYC_F9|KEYC_ESCAPE },
233 { TTYC_KF58, KEYC_F10|KEYC_ESCAPE },
234 { TTYC_KF59, KEYC_F11|KEYC_ESCAPE },
235 { TTYC_KF60, KEYC_F12|KEYC_ESCAPE },
236
237 { TTYC_KF61, KEYC_F1|KEYC_ESCAPE|KEYC_SHIFT },
238 { TTYC_KF62, KEYC_F2|KEYC_ESCAPE|KEYC_SHIFT },
239 { TTYC_KF63, KEYC_F3|KEYC_ESCAPE|KEYC_SHIFT },
240
241 { TTYC_KICH1, KEYC_IC },
242 { TTYC_KDCH1, KEYC_DC },
243 { TTYC_KHOME, KEYC_HOME },
244 { TTYC_KEND, KEYC_END },
245 { TTYC_KNP, KEYC_NPAGE },
246 { TTYC_KPP, KEYC_PPAGE },
247 { TTYC_KCBT, KEYC_BTAB },
248
249 /* Arrow keys from terminfo. */
250 { TTYC_KCUU1, KEYC_UP },
251 { TTYC_KCUD1, KEYC_DOWN },
252 { TTYC_KCUB1, KEYC_LEFT },
253 { TTYC_KCUF1, KEYC_RIGHT },
254
255 /* Key and modifier capabilities. */
256 { TTYC_KDC2, KEYC_DC|KEYC_SHIFT },
257 { TTYC_KDC3, KEYC_DC|KEYC_ESCAPE },
258 { TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_ESCAPE },
259 { TTYC_KDC5, KEYC_DC|KEYC_CTRL },
260 { TTYC_KDC6, KEYC_DC|KEYC_SHIFT|KEYC_CTRL },
261 { TTYC_KDC7, KEYC_DC|KEYC_ESCAPE|KEYC_CTRL },
262 { TTYC_KDN2, KEYC_DOWN|KEYC_SHIFT },
263 { TTYC_KDN3, KEYC_DOWN|KEYC_ESCAPE },
264 { TTYC_KDN4, KEYC_DOWN|KEYC_SHIFT|KEYC_ESCAPE },
265 { TTYC_KDN5, KEYC_DOWN|KEYC_CTRL },
266 { TTYC_KDN6, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL },
267 { TTYC_KDN7, KEYC_DOWN|KEYC_ESCAPE|KEYC_CTRL },
268 { TTYC_KEND2, KEYC_END|KEYC_SHIFT },
269 { TTYC_KEND3, KEYC_END|KEYC_ESCAPE },
270 { TTYC_KEND4, KEYC_END|KEYC_SHIFT|KEYC_ESCAPE },
271 { TTYC_KEND5, KEYC_END|KEYC_CTRL },
272 { TTYC_KEND6, KEYC_END|KEYC_SHIFT|KEYC_CTRL },
273 { TTYC_KEND7, KEYC_END|KEYC_ESCAPE|KEYC_CTRL },
274 { TTYC_KHOM2, KEYC_HOME|KEYC_SHIFT },
275 { TTYC_KHOM3, KEYC_HOME|KEYC_ESCAPE },
276 { TTYC_KHOM4, KEYC_HOME|KEYC_SHIFT|KEYC_ESCAPE },
277 { TTYC_KHOM5, KEYC_HOME|KEYC_CTRL },
278 { TTYC_KHOM6, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL },
279 { TTYC_KHOM7, KEYC_HOME|KEYC_ESCAPE|KEYC_CTRL },
280 { TTYC_KIC2, KEYC_IC|KEYC_SHIFT },
281 { TTYC_KIC3, KEYC_IC|KEYC_ESCAPE },
282 { TTYC_KIC4, KEYC_IC|KEYC_SHIFT|KEYC_ESCAPE },
283 { TTYC_KIC5, KEYC_IC|KEYC_CTRL },
284 { TTYC_KIC6, KEYC_IC|KEYC_SHIFT|KEYC_CTRL },
285 { TTYC_KIC7, KEYC_IC|KEYC_ESCAPE|KEYC_CTRL },
286 { TTYC_KLFT2, KEYC_LEFT|KEYC_SHIFT },
287 { TTYC_KLFT3, KEYC_LEFT|KEYC_ESCAPE },
288 { TTYC_KLFT4, KEYC_LEFT|KEYC_SHIFT|KEYC_ESCAPE },
289 { TTYC_KLFT5, KEYC_LEFT|KEYC_CTRL },
290 { TTYC_KLFT6, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL },
291 { TTYC_KLFT7, KEYC_LEFT|KEYC_ESCAPE|KEYC_CTRL },
292 { TTYC_KNXT2, KEYC_NPAGE|KEYC_SHIFT },
293 { TTYC_KNXT3, KEYC_NPAGE|KEYC_ESCAPE },
294 { TTYC_KNXT4, KEYC_NPAGE|KEYC_SHIFT|KEYC_ESCAPE },
295 { TTYC_KNXT5, KEYC_NPAGE|KEYC_CTRL },
296 { TTYC_KNXT6, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL },
297 { TTYC_KNXT7, KEYC_NPAGE|KEYC_ESCAPE|KEYC_CTRL },
298 { TTYC_KPRV2, KEYC_PPAGE|KEYC_SHIFT },
299 { TTYC_KPRV3, KEYC_PPAGE|KEYC_ESCAPE },
300 { TTYC_KPRV4, KEYC_PPAGE|KEYC_SHIFT|KEYC_ESCAPE },
301 { TTYC_KPRV5, KEYC_PPAGE|KEYC_CTRL },
302 { TTYC_KPRV6, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL },
303 { TTYC_KPRV7, KEYC_PPAGE|KEYC_ESCAPE|KEYC_CTRL },
304 { TTYC_KRIT2, KEYC_RIGHT|KEYC_SHIFT },
305 { TTYC_KRIT3, KEYC_RIGHT|KEYC_ESCAPE },
306 { TTYC_KRIT4, KEYC_RIGHT|KEYC_SHIFT|KEYC_ESCAPE },
307 { TTYC_KRIT5, KEYC_RIGHT|KEYC_CTRL },
308 { TTYC_KRIT6, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL },
309 { TTYC_KRIT7, KEYC_RIGHT|KEYC_ESCAPE|KEYC_CTRL },
310 { TTYC_KUP2, KEYC_UP|KEYC_SHIFT },
311 { TTYC_KUP3, KEYC_UP|KEYC_ESCAPE },
312 { TTYC_KUP4, KEYC_UP|KEYC_SHIFT|KEYC_ESCAPE },
313 { TTYC_KUP5, KEYC_UP|KEYC_CTRL },
314 { TTYC_KUP6, KEYC_UP|KEYC_SHIFT|KEYC_CTRL },
315 { TTYC_KUP7, KEYC_UP|KEYC_ESCAPE|KEYC_CTRL },
316 };
317
318 /* Add key to tree. */
319 void
tty_keys_add(struct tty * tty,const char * s,key_code key)320 tty_keys_add(struct tty *tty, const char *s, key_code key)
321 {
322 struct tty_key *tk;
323 size_t size;
324 const char *keystr;
325
326 keystr = key_string_lookup_key(key);
327 if ((tk = tty_keys_find(tty, s, strlen(s), &size)) == NULL) {
328 log_debug("new key %s: 0x%llx (%s)", s, key, keystr);
329 tty_keys_add1(&tty->key_tree, s, key);
330 } else {
331 log_debug("replacing key %s: 0x%llx (%s)", s, key, keystr);
332 tk->key = key;
333 }
334 }
335
336 /* Add next node to the tree. */
337 void
tty_keys_add1(struct tty_key ** tkp,const char * s,key_code key)338 tty_keys_add1(struct tty_key **tkp, const char *s, key_code key)
339 {
340 struct tty_key *tk;
341
342 /* Allocate a tree entry if there isn't one already. */
343 tk = *tkp;
344 if (tk == NULL) {
345 tk = *tkp = xcalloc(1, sizeof *tk);
346 tk->ch = *s;
347 tk->key = KEYC_UNKNOWN;
348 }
349
350 /* Find the next entry. */
351 if (*s == tk->ch) {
352 /* Move forward in string. */
353 s++;
354
355 /* If this is the end of the string, no more is necessary. */
356 if (*s == '\0') {
357 tk->key = key;
358 return;
359 }
360
361 /* Use the child tree for the next character. */
362 tkp = &tk->next;
363 } else {
364 if (*s < tk->ch)
365 tkp = &tk->left;
366 else if (*s > tk->ch)
367 tkp = &tk->right;
368 }
369
370 /* And recurse to add it. */
371 tty_keys_add1(tkp, s, key);
372 }
373
374 /* Initialise a key tree from the table. */
375 void
tty_keys_build(struct tty * tty)376 tty_keys_build(struct tty *tty)
377 {
378 const struct tty_default_key_raw *tdkr;
379 const struct tty_default_key_code *tdkc;
380 u_int i;
381 const char *s;
382
383 if (tty->key_tree != NULL)
384 tty_keys_free(tty);
385 tty->key_tree = NULL;
386
387 for (i = 0; i < nitems(tty_default_raw_keys); i++) {
388 tdkr = &tty_default_raw_keys[i];
389
390 s = tdkr->string;
391 if (*s != '\0')
392 tty_keys_add(tty, s, tdkr->key);
393 }
394 for (i = 0; i < nitems(tty_default_code_keys); i++) {
395 tdkc = &tty_default_code_keys[i];
396
397 s = tty_term_string(tty->term, tdkc->code);
398 if (*s != '\0')
399 tty_keys_add(tty, s, tdkc->key);
400
401 }
402 }
403
404 /* Free the entire key tree. */
405 void
tty_keys_free(struct tty * tty)406 tty_keys_free(struct tty *tty)
407 {
408 tty_keys_free1(tty->key_tree);
409 }
410
411 /* Free a single key. */
412 void
tty_keys_free1(struct tty_key * tk)413 tty_keys_free1(struct tty_key *tk)
414 {
415 if (tk->next != NULL)
416 tty_keys_free1(tk->next);
417 if (tk->left != NULL)
418 tty_keys_free1(tk->left);
419 if (tk->right != NULL)
420 tty_keys_free1(tk->right);
421 free(tk);
422 }
423
424 /* Lookup a key in the tree. */
425 struct tty_key *
tty_keys_find(struct tty * tty,const char * buf,size_t len,size_t * size)426 tty_keys_find(struct tty *tty, const char *buf, size_t len, size_t *size)
427 {
428 *size = 0;
429 return (tty_keys_find1(tty->key_tree, buf, len, size));
430 }
431
432 /* Find the next node. */
433 struct tty_key *
tty_keys_find1(struct tty_key * tk,const char * buf,size_t len,size_t * size)434 tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
435 {
436 /* If the node is NULL, this is the end of the tree. No match. */
437 if (tk == NULL)
438 return (NULL);
439
440 /* Pick the next in the sequence. */
441 if (tk->ch == *buf) {
442 /* Move forward in the string. */
443 buf++; len--;
444 (*size)++;
445
446 /* At the end of the string, return the current node. */
447 if (len == 0 || (tk->next == NULL && tk->key != KEYC_UNKNOWN))
448 return (tk);
449
450 /* Move into the next tree for the following character. */
451 tk = tk->next;
452 } else {
453 if (*buf < tk->ch)
454 tk = tk->left;
455 else if (*buf > tk->ch)
456 tk = tk->right;
457 }
458
459 /* Move to the next in the tree. */
460 return (tty_keys_find1(tk, buf, len, size));
461 }
462
463 /*
464 * Process at least one key in the buffer and invoke tty->key_callback. Return
465 * 0 if there are no further keys, or 1 if there could be more in the buffer.
466 */
467 key_code
tty_keys_next(struct tty * tty)468 tty_keys_next(struct tty *tty)
469 {
470 struct tty_key *tk;
471 struct timeval tv;
472 const char *buf;
473 size_t len, size;
474 cc_t bspace;
475 int delay, expired = 0;
476 key_code key;
477 struct utf8_data ud;
478 enum utf8_state more;
479 u_int i;
480 wchar_t wc;
481
482 /* Get key buffer. */
483 buf = EVBUFFER_DATA(tty->event->input);
484 len = EVBUFFER_LENGTH(tty->event->input);
485
486 if (len == 0)
487 return (0);
488 log_debug("keys are %zu (%.*s)", len, (int) len, buf);
489
490 /* Is this a mouse key press? */
491 switch (tty_keys_mouse(tty, buf, len, &size)) {
492 case 0: /* yes */
493 key = KEYC_MOUSE;
494 goto complete_key;
495 case -1: /* no, or not valid */
496 break;
497 case -2: /* yes, but we don't care. */
498 key = KEYC_MOUSE;
499 goto discard_key;
500 case 1: /* partial */
501 goto partial_key;
502 }
503
504 /* Look for matching key string and return if found. */
505 tk = tty_keys_find(tty, buf, len, &size);
506 if (tk != NULL) {
507 if (tk->next != NULL)
508 goto partial_key;
509 key = tk->key;
510 goto complete_key;
511 }
512
513 /* Try to parse a key with an xterm-style modifier. */
514 switch (xterm_keys_find(buf, len, &size, &key)) {
515 case 0: /* found */
516 goto complete_key;
517 case -1: /* not found */
518 break;
519 case 1:
520 goto partial_key;
521 }
522
523 first_key:
524 /* Is this a meta key? */
525 if (len >= 2 && buf[0] == '\033') {
526 if (buf[1] != '\033') {
527 key = buf[1] | KEYC_ESCAPE;
528 size = 2;
529 goto complete_key;
530 }
531
532 tk = tty_keys_find(tty, buf + 1, len - 1, &size);
533 if (tk != NULL && (!expired || tk->next == NULL)) {
534 size++; /* include escape */
535 if (tk->next != NULL)
536 goto partial_key;
537 key = tk->key;
538 if (key != KEYC_UNKNOWN)
539 key |= KEYC_ESCAPE;
540 goto complete_key;
541 }
542 }
543
544 /* Is this valid UTF-8? */
545 if ((more = utf8_open(&ud, (u_char)*buf) == UTF8_MORE)) {
546 size = ud.size;
547 if (len < size) {
548 if (expired)
549 goto discard_key;
550 goto partial_key;
551 }
552 for (i = 1; i < size; i++)
553 more = utf8_append(&ud, (u_char)buf[i]);
554 if (more != UTF8_DONE)
555 goto discard_key;
556
557 if (utf8_combine(&ud, &wc) != UTF8_DONE)
558 goto discard_key;
559 key = wc;
560
561 log_debug("UTF-8 key %.*s %#llx", (int)size, buf, key);
562 goto complete_key;
563 }
564
565 /* No key found, take first. */
566 key = (u_char)*buf;
567 size = 1;
568
569 /*
570 * Check for backspace key using termios VERASE - the terminfo
571 * kbs entry is extremely unreliable, so cannot be safely
572 * used. termios should have a better idea.
573 */
574 bspace = tty->tio.c_cc[VERASE];
575 if (bspace != _POSIX_VDISABLE && key == bspace)
576 key = KEYC_BSPACE;
577
578 goto complete_key;
579
580 partial_key:
581 log_debug("partial key %.*s", (int) len, buf);
582
583 /* If timer is going, check for expiration. */
584 if (tty->flags & TTY_TIMER) {
585 if (evtimer_initialized(&tty->key_timer) &&
586 !evtimer_pending(&tty->key_timer, NULL)) {
587 expired = 1;
588 goto first_key;
589 }
590 return (0);
591 }
592
593 /* Get the time period. */
594 delay = options_get_number(global_options, "escape-time");
595 tv.tv_sec = delay / 1000;
596 tv.tv_usec = (delay % 1000) * 1000L;
597
598 /* Start the timer. */
599 if (event_initialized(&tty->key_timer))
600 evtimer_del(&tty->key_timer);
601 evtimer_set(&tty->key_timer, tty_keys_callback, tty);
602 evtimer_add(&tty->key_timer, &tv);
603
604 tty->flags |= TTY_TIMER;
605 return (0);
606
607 complete_key:
608 log_debug("complete key %.*s %#llx", (int)size, buf, key);
609
610 /* Remove data from buffer. */
611 evbuffer_drain(tty->event->input, size);
612
613 /* Remove key timer. */
614 if (event_initialized(&tty->key_timer))
615 evtimer_del(&tty->key_timer);
616 tty->flags &= ~TTY_TIMER;
617
618 /* Check for focus events. */
619 if (key == KEYC_FOCUS_OUT) {
620 tty->client->flags &= ~CLIENT_FOCUSED;
621 return (1);
622 } else if (key == KEYC_FOCUS_IN) {
623 tty->client->flags |= CLIENT_FOCUSED;
624 return (1);
625 }
626
627 /* Fire the key. */
628 if (key != KEYC_UNKNOWN)
629 server_client_handle_key(tty->client, key);
630
631 return (1);
632
633 discard_key:
634 log_debug("discard key %.*s %#llx", (int)size, buf, key);
635
636 /* Remove data from buffer. */
637 evbuffer_drain(tty->event->input, size);
638
639 return (1);
640 }
641
642 /* Key timer callback. */
643 void
tty_keys_callback(__unused int fd,__unused short events,void * data)644 tty_keys_callback(__unused int fd, __unused short events, void *data)
645 {
646 struct tty *tty = data;
647
648 if (tty->flags & TTY_TIMER) {
649 while (tty_keys_next(tty))
650 ;
651 }
652 }
653
654 /*
655 * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
656 * (probably a mouse sequence but need more data).
657 */
658 int
tty_keys_mouse(struct tty * tty,const char * buf,size_t len,size_t * size)659 tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
660 {
661 struct mouse_event *m = &tty->mouse;
662 u_int i, x, y, b, sgr_b;
663 u_char sgr_type, c;
664
665 /*
666 * Standard mouse sequences are \033[M followed by three characters
667 * indicating button, X and Y, all based at 32 with 1,1 top-left.
668 *
669 * UTF-8 mouse sequences are similar but the three are expressed as
670 * UTF-8 characters.
671 *
672 * SGR extended mouse sequences are \033[< followed by three numbers in
673 * decimal and separated by semicolons indicating button, X and Y. A
674 * trailing 'M' is click or scroll and trailing 'm' release. All are
675 * based at 0 with 1,1 top-left.
676 */
677
678 *size = 0;
679 x = y = b = sgr_b = 0;
680 sgr_type = ' ';
681
682 /* First two bytes are always \033[. */
683 if (buf[0] != '\033')
684 return (-1);
685 if (len == 1)
686 return (1);
687 if (buf[1] != '[')
688 return (-1);
689 if (len == 2)
690 return (1);
691
692 /*
693 * Third byte is M in old standard (and UTF-8 extension which we do not
694 * support), < in SGR extension.
695 */
696 if (buf[2] == 'M') {
697 /* Read the three inputs. */
698 *size = 3;
699 for (i = 0; i < 3; i++) {
700 if (len <= *size)
701 return (1);
702 c = (u_char)buf[(*size)++];
703 if (i == 0)
704 b = c;
705 else if (i == 1)
706 x = c;
707 else
708 y = c;
709 }
710 log_debug("mouse input: %.*s", (int)*size, buf);
711
712 /* Check and return the mouse input. */
713 if (b < 32)
714 return (-1);
715 b -= 32;
716 if (x >= 33)
717 x -= 33;
718 else
719 x = 256 - x;
720 if (y >= 33)
721 y -= 33;
722 else
723 y = 256 - y;
724 } else if (buf[2] == '<') {
725 /* Read the three inputs. */
726 *size = 3;
727 while (1) {
728 if (len <= *size)
729 return (1);
730 c = (u_char)buf[(*size)++];
731 if (c == ';')
732 break;
733 if (c < '0' || c > '9')
734 return (-1);
735 sgr_b = 10 * sgr_b + (c - '0');
736 }
737 while (1) {
738 if (len <= *size)
739 return (1);
740 c = (u_char)buf[(*size)++];
741 if (c == ';')
742 break;
743 if (c < '0' || c > '9')
744 return (-1);
745 x = 10 * x + (c - '0');
746 }
747 while (1) {
748 if (len <= *size)
749 return (1);
750 c = (u_char)buf[(*size)++];
751 if (c == 'M' || c == 'm')
752 break;
753 if (c < '0' || c > '9')
754 return (-1);
755 y = 10 * y + (c - '0');
756 }
757 log_debug("mouse input (SGR): %.*s", (int)*size, buf);
758
759 /* Check and return the mouse input. */
760 if (x < 1 || y < 1)
761 return (-1);
762 x--;
763 y--;
764 b = sgr_b;
765
766 /* Type is M for press, m for release. */
767 sgr_type = c;
768 if (sgr_type == 'm')
769 b |= 3;
770
771 /*
772 * Some terminals (like PuTTY 0.63) mistakenly send
773 * button-release events for scroll-wheel button-press event.
774 * Discard it before it reaches any program running inside
775 * tmux.
776 */
777 if (sgr_type == 'm' && (sgr_b & 64))
778 return (-2);
779 } else
780 return (-1);
781
782 /* Fill mouse event. */
783 m->lx = m->x;
784 m->x = x;
785 m->ly = m->y;
786 m->y = y;
787 m->lb = m->b;
788 m->b = b;
789 m->sgr_type = sgr_type;
790 m->sgr_b = sgr_b;
791
792 return (0);
793 }
794