GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/tty-keys.c Lines: 0 296 0.0 %
Date: 2017-11-07 Branches: 0 217 0.0 %

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