4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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>
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.
36 void tty_keys_add1(struct tty_key
**, const char *, int);
37 void tty_keys_add(struct tty
*, const char *, int);
38 void tty_keys_free1(struct tty_key
*);
39 struct tty_key
*tty_keys_find1(
40 struct tty_key
*, const char *, size_t, 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 int tty_keys_device(struct tty
*, const char *, size_t, size_t *);
46 /* Default raw keys. */
47 struct tty_default_key_raw
{
51 const struct tty_default_key_raw tty_default_raw_keys
[] = {
53 * Numeric keypad. Just use the vt100 escape sequences here and always
54 * put the terminal into keypad_xmit mode. Translation of numbers
55 * mode/applications mode is done in input-keys.c.
57 { "\033Oo", KEYC_KP_SLASH
},
58 { "\033Oj", KEYC_KP_STAR
},
59 { "\033Om", KEYC_KP_MINUS
},
60 { "\033Ow", KEYC_KP_SEVEN
},
61 { "\033Ox", KEYC_KP_EIGHT
},
62 { "\033Oy", KEYC_KP_NINE
},
63 { "\033Ok", KEYC_KP_PLUS
},
64 { "\033Ot", KEYC_KP_FOUR
},
65 { "\033Ou", KEYC_KP_FIVE
},
66 { "\033Ov", KEYC_KP_SIX
},
67 { "\033Oq", KEYC_KP_ONE
},
68 { "\033Or", KEYC_KP_TWO
},
69 { "\033Os", KEYC_KP_THREE
},
70 { "\033OM", KEYC_KP_ENTER
},
71 { "\033Op", KEYC_KP_ZERO
},
72 { "\033On", KEYC_KP_PERIOD
},
75 { "\033OA", KEYC_UP
},
76 { "\033OB", KEYC_DOWN
},
77 { "\033OC", KEYC_RIGHT
},
78 { "\033OD", KEYC_LEFT
},
80 { "\033[A", KEYC_UP
},
81 { "\033[B", KEYC_DOWN
},
82 { "\033[C", KEYC_RIGHT
},
83 { "\033[D", KEYC_LEFT
},
85 /* rxvt-style arrow + modifier keys. */
86 { "\033Oa", KEYC_UP
|KEYC_CTRL
},
87 { "\033Ob", KEYC_DOWN
|KEYC_CTRL
},
88 { "\033Oc", KEYC_RIGHT
|KEYC_CTRL
},
89 { "\033Od", KEYC_LEFT
|KEYC_CTRL
},
91 { "\033[a", KEYC_UP
|KEYC_SHIFT
},
92 { "\033[b", KEYC_DOWN
|KEYC_SHIFT
},
93 { "\033[c", KEYC_RIGHT
|KEYC_SHIFT
},
94 { "\033[d", KEYC_LEFT
|KEYC_SHIFT
},
96 /* rxvt-style function + modifier keys (C = ^, S = $, C-S = @). */
97 { "\033[11^", KEYC_F1
|KEYC_CTRL
},
98 { "\033[12^", KEYC_F2
|KEYC_CTRL
},
99 { "\033[13^", KEYC_F3
|KEYC_CTRL
},
100 { "\033[14^", KEYC_F4
|KEYC_CTRL
},
101 { "\033[15^", KEYC_F5
|KEYC_CTRL
},
102 { "\033[17^", KEYC_F6
|KEYC_CTRL
},
103 { "\033[18^", KEYC_F7
|KEYC_CTRL
},
104 { "\033[19^", KEYC_F8
|KEYC_CTRL
},
105 { "\033[20^", KEYC_F9
|KEYC_CTRL
},
106 { "\033[21^", KEYC_F10
|KEYC_CTRL
},
107 { "\033[23^", KEYC_F11
|KEYC_CTRL
},
108 { "\033[24^", KEYC_F12
|KEYC_CTRL
},
109 { "\033[25^", KEYC_F13
|KEYC_CTRL
},
110 { "\033[26^", KEYC_F14
|KEYC_CTRL
},
111 { "\033[28^", KEYC_F15
|KEYC_CTRL
},
112 { "\033[29^", KEYC_F16
|KEYC_CTRL
},
113 { "\033[31^", KEYC_F17
|KEYC_CTRL
},
114 { "\033[32^", KEYC_F18
|KEYC_CTRL
},
115 { "\033[33^", KEYC_F19
|KEYC_CTRL
},
116 { "\033[34^", KEYC_F20
|KEYC_CTRL
},
117 { "\033[2^", KEYC_IC
|KEYC_CTRL
},
118 { "\033[3^", KEYC_DC
|KEYC_CTRL
},
119 { "\033[7^", KEYC_HOME
|KEYC_CTRL
},
120 { "\033[8^", KEYC_END
|KEYC_CTRL
},
121 { "\033[6^", KEYC_NPAGE
|KEYC_CTRL
},
122 { "\033[5^", KEYC_PPAGE
|KEYC_CTRL
},
124 { "\033[11$", KEYC_F1
|KEYC_SHIFT
},
125 { "\033[12$", KEYC_F2
|KEYC_SHIFT
},
126 { "\033[13$", KEYC_F3
|KEYC_SHIFT
},
127 { "\033[14$", KEYC_F4
|KEYC_SHIFT
},
128 { "\033[15$", KEYC_F5
|KEYC_SHIFT
},
129 { "\033[17$", KEYC_F6
|KEYC_SHIFT
},
130 { "\033[18$", KEYC_F7
|KEYC_SHIFT
},
131 { "\033[19$", KEYC_F8
|KEYC_SHIFT
},
132 { "\033[20$", KEYC_F9
|KEYC_SHIFT
},
133 { "\033[21$", KEYC_F10
|KEYC_SHIFT
},
134 { "\033[23$", KEYC_F11
|KEYC_SHIFT
},
135 { "\033[24$", KEYC_F12
|KEYC_SHIFT
},
136 { "\033[25$", KEYC_F13
|KEYC_SHIFT
},
137 { "\033[26$", KEYC_F14
|KEYC_SHIFT
},
138 { "\033[28$", KEYC_F15
|KEYC_SHIFT
},
139 { "\033[29$", KEYC_F16
|KEYC_SHIFT
},
140 { "\033[31$", KEYC_F17
|KEYC_SHIFT
},
141 { "\033[32$", KEYC_F18
|KEYC_SHIFT
},
142 { "\033[33$", KEYC_F19
|KEYC_SHIFT
},
143 { "\033[34$", KEYC_F20
|KEYC_SHIFT
},
144 { "\033[2$", KEYC_IC
|KEYC_SHIFT
},
145 { "\033[3$", KEYC_DC
|KEYC_SHIFT
},
146 { "\033[7$", KEYC_HOME
|KEYC_SHIFT
},
147 { "\033[8$", KEYC_END
|KEYC_SHIFT
},
148 { "\033[6$", KEYC_NPAGE
|KEYC_SHIFT
},
149 { "\033[5$", KEYC_PPAGE
|KEYC_SHIFT
},
151 { "\033[11@", KEYC_F1
|KEYC_CTRL
|KEYC_SHIFT
},
152 { "\033[12@", KEYC_F2
|KEYC_CTRL
|KEYC_SHIFT
},
153 { "\033[13@", KEYC_F3
|KEYC_CTRL
|KEYC_SHIFT
},
154 { "\033[14@", KEYC_F4
|KEYC_CTRL
|KEYC_SHIFT
},
155 { "\033[15@", KEYC_F5
|KEYC_CTRL
|KEYC_SHIFT
},
156 { "\033[17@", KEYC_F6
|KEYC_CTRL
|KEYC_SHIFT
},
157 { "\033[18@", KEYC_F7
|KEYC_CTRL
|KEYC_SHIFT
},
158 { "\033[19@", KEYC_F8
|KEYC_CTRL
|KEYC_SHIFT
},
159 { "\033[20@", KEYC_F9
|KEYC_CTRL
|KEYC_SHIFT
},
160 { "\033[21@", KEYC_F10
|KEYC_CTRL
|KEYC_SHIFT
},
161 { "\033[23@", KEYC_F11
|KEYC_CTRL
|KEYC_SHIFT
},
162 { "\033[24@", KEYC_F12
|KEYC_CTRL
|KEYC_SHIFT
},
163 { "\033[25@", KEYC_F13
|KEYC_CTRL
|KEYC_SHIFT
},
164 { "\033[26@", KEYC_F14
|KEYC_CTRL
|KEYC_SHIFT
},
165 { "\033[28@", KEYC_F15
|KEYC_CTRL
|KEYC_SHIFT
},
166 { "\033[29@", KEYC_F16
|KEYC_CTRL
|KEYC_SHIFT
},
167 { "\033[31@", KEYC_F17
|KEYC_CTRL
|KEYC_SHIFT
},
168 { "\033[32@", KEYC_F18
|KEYC_CTRL
|KEYC_SHIFT
},
169 { "\033[33@", KEYC_F19
|KEYC_CTRL
|KEYC_SHIFT
},
170 { "\033[34@", KEYC_F20
|KEYC_CTRL
|KEYC_SHIFT
},
171 { "\033[2@", KEYC_IC
|KEYC_CTRL
|KEYC_SHIFT
},
172 { "\033[3@", KEYC_DC
|KEYC_CTRL
|KEYC_SHIFT
},
173 { "\033[7@", KEYC_HOME
|KEYC_CTRL
|KEYC_SHIFT
},
174 { "\033[8@", KEYC_END
|KEYC_CTRL
|KEYC_SHIFT
},
175 { "\033[6@", KEYC_NPAGE
|KEYC_CTRL
|KEYC_SHIFT
},
176 { "\033[5@", KEYC_PPAGE
|KEYC_CTRL
|KEYC_SHIFT
},
178 /* Focus tracking. */
179 { "\033[I", KEYC_FOCUS_IN
},
180 { "\033[O", KEYC_FOCUS_OUT
},
183 /* Default terminfo(5) keys. */
184 struct tty_default_key_code
{
185 enum tty_code_code code
;
188 const struct tty_default_key_code tty_default_code_keys
[] = {
190 { TTYC_KF1
, KEYC_F1
},
191 { TTYC_KF2
, KEYC_F2
},
192 { TTYC_KF3
, KEYC_F3
},
193 { TTYC_KF4
, KEYC_F4
},
194 { TTYC_KF5
, KEYC_F5
},
195 { TTYC_KF6
, KEYC_F6
},
196 { TTYC_KF7
, KEYC_F7
},
197 { TTYC_KF8
, KEYC_F8
},
198 { TTYC_KF9
, KEYC_F9
},
199 { TTYC_KF10
, KEYC_F10
},
200 { TTYC_KF11
, KEYC_F11
},
201 { TTYC_KF12
, KEYC_F12
},
202 { TTYC_KF13
, KEYC_F13
},
203 { TTYC_KF14
, KEYC_F14
},
204 { TTYC_KF15
, KEYC_F15
},
205 { TTYC_KF16
, KEYC_F16
},
206 { TTYC_KF17
, KEYC_F17
},
207 { TTYC_KF18
, KEYC_F18
},
208 { TTYC_KF19
, KEYC_F19
},
209 { TTYC_KF20
, KEYC_F20
},
210 { TTYC_KICH1
, KEYC_IC
},
211 { TTYC_KDCH1
, KEYC_DC
},
212 { TTYC_KHOME
, KEYC_HOME
},
213 { TTYC_KEND
, KEYC_END
},
214 { TTYC_KNP
, KEYC_NPAGE
},
215 { TTYC_KPP
, KEYC_PPAGE
},
216 { TTYC_KCBT
, KEYC_BTAB
},
218 /* Arrow keys from terminfo. */
219 { TTYC_KCUU1
, KEYC_UP
},
220 { TTYC_KCUD1
, KEYC_DOWN
},
221 { TTYC_KCUB1
, KEYC_LEFT
},
222 { TTYC_KCUF1
, KEYC_RIGHT
},
224 /* Key and modifier capabilities. */
225 { TTYC_KDC2
, KEYC_DC
|KEYC_SHIFT
},
226 { TTYC_KDC3
, KEYC_DC
|KEYC_ESCAPE
},
227 { TTYC_KDC4
, KEYC_DC
|KEYC_SHIFT
|KEYC_ESCAPE
},
228 { TTYC_KDC5
, KEYC_DC
|KEYC_CTRL
},
229 { TTYC_KDC6
, KEYC_DC
|KEYC_SHIFT
|KEYC_CTRL
},
230 { TTYC_KDC7
, KEYC_DC
|KEYC_ESCAPE
|KEYC_CTRL
},
231 { TTYC_KDN2
, KEYC_DOWN
|KEYC_SHIFT
},
232 { TTYC_KDN3
, KEYC_DOWN
|KEYC_ESCAPE
},
233 { TTYC_KDN4
, KEYC_DOWN
|KEYC_SHIFT
|KEYC_ESCAPE
},
234 { TTYC_KDN5
, KEYC_DOWN
|KEYC_CTRL
},
235 { TTYC_KDN6
, KEYC_DOWN
|KEYC_SHIFT
|KEYC_CTRL
},
236 { TTYC_KDN7
, KEYC_DOWN
|KEYC_ESCAPE
|KEYC_CTRL
},
237 { TTYC_KEND2
, KEYC_END
|KEYC_SHIFT
},
238 { TTYC_KEND3
, KEYC_END
|KEYC_ESCAPE
},
239 { TTYC_KEND4
, KEYC_END
|KEYC_SHIFT
|KEYC_ESCAPE
},
240 { TTYC_KEND5
, KEYC_END
|KEYC_CTRL
},
241 { TTYC_KEND6
, KEYC_END
|KEYC_SHIFT
|KEYC_CTRL
},
242 { TTYC_KEND7
, KEYC_END
|KEYC_ESCAPE
|KEYC_CTRL
},
243 { TTYC_KHOM2
, KEYC_HOME
|KEYC_SHIFT
},
244 { TTYC_KHOM3
, KEYC_HOME
|KEYC_ESCAPE
},
245 { TTYC_KHOM4
, KEYC_HOME
|KEYC_SHIFT
|KEYC_ESCAPE
},
246 { TTYC_KHOM5
, KEYC_HOME
|KEYC_CTRL
},
247 { TTYC_KHOM6
, KEYC_HOME
|KEYC_SHIFT
|KEYC_CTRL
},
248 { TTYC_KHOM7
, KEYC_HOME
|KEYC_ESCAPE
|KEYC_CTRL
},
249 { TTYC_KIC2
, KEYC_IC
|KEYC_SHIFT
},
250 { TTYC_KIC3
, KEYC_IC
|KEYC_ESCAPE
},
251 { TTYC_KIC4
, KEYC_IC
|KEYC_SHIFT
|KEYC_ESCAPE
},
252 { TTYC_KIC5
, KEYC_IC
|KEYC_CTRL
},
253 { TTYC_KIC6
, KEYC_IC
|KEYC_SHIFT
|KEYC_CTRL
},
254 { TTYC_KIC7
, KEYC_IC
|KEYC_ESCAPE
|KEYC_CTRL
},
255 { TTYC_KLFT2
, KEYC_LEFT
|KEYC_SHIFT
},
256 { TTYC_KLFT3
, KEYC_LEFT
|KEYC_ESCAPE
},
257 { TTYC_KLFT4
, KEYC_LEFT
|KEYC_SHIFT
|KEYC_ESCAPE
},
258 { TTYC_KLFT5
, KEYC_LEFT
|KEYC_CTRL
},
259 { TTYC_KLFT6
, KEYC_LEFT
|KEYC_SHIFT
|KEYC_CTRL
},
260 { TTYC_KLFT7
, KEYC_LEFT
|KEYC_ESCAPE
|KEYC_CTRL
},
261 { TTYC_KNXT2
, KEYC_NPAGE
|KEYC_SHIFT
},
262 { TTYC_KNXT3
, KEYC_NPAGE
|KEYC_ESCAPE
},
263 { TTYC_KNXT4
, KEYC_NPAGE
|KEYC_SHIFT
|KEYC_ESCAPE
},
264 { TTYC_KNXT5
, KEYC_NPAGE
|KEYC_CTRL
},
265 { TTYC_KNXT6
, KEYC_NPAGE
|KEYC_SHIFT
|KEYC_CTRL
},
266 { TTYC_KNXT7
, KEYC_NPAGE
|KEYC_ESCAPE
|KEYC_CTRL
},
267 { TTYC_KPRV2
, KEYC_PPAGE
|KEYC_SHIFT
},
268 { TTYC_KPRV3
, KEYC_PPAGE
|KEYC_ESCAPE
},
269 { TTYC_KPRV4
, KEYC_PPAGE
|KEYC_SHIFT
|KEYC_ESCAPE
},
270 { TTYC_KPRV5
, KEYC_PPAGE
|KEYC_CTRL
},
271 { TTYC_KPRV6
, KEYC_PPAGE
|KEYC_SHIFT
|KEYC_CTRL
},
272 { TTYC_KPRV7
, KEYC_PPAGE
|KEYC_ESCAPE
|KEYC_CTRL
},
273 { TTYC_KRIT2
, KEYC_RIGHT
|KEYC_SHIFT
},
274 { TTYC_KRIT3
, KEYC_RIGHT
|KEYC_ESCAPE
},
275 { TTYC_KRIT4
, KEYC_RIGHT
|KEYC_SHIFT
|KEYC_ESCAPE
},
276 { TTYC_KRIT5
, KEYC_RIGHT
|KEYC_CTRL
},
277 { TTYC_KRIT6
, KEYC_RIGHT
|KEYC_SHIFT
|KEYC_CTRL
},
278 { TTYC_KRIT7
, KEYC_RIGHT
|KEYC_ESCAPE
|KEYC_CTRL
},
279 { TTYC_KUP2
, KEYC_UP
|KEYC_SHIFT
},
280 { TTYC_KUP3
, KEYC_UP
|KEYC_ESCAPE
},
281 { TTYC_KUP4
, KEYC_UP
|KEYC_SHIFT
|KEYC_ESCAPE
},
282 { TTYC_KUP5
, KEYC_UP
|KEYC_CTRL
},
283 { TTYC_KUP6
, KEYC_UP
|KEYC_SHIFT
|KEYC_CTRL
},
284 { TTYC_KUP7
, KEYC_UP
|KEYC_ESCAPE
|KEYC_CTRL
},
287 /* Add key to tree. */
289 tty_keys_add(struct tty
*tty
, const char *s
, int key
)
295 keystr
= key_string_lookup_key(key
);
296 if ((tk
= tty_keys_find(tty
, s
, strlen(s
), &size
)) == NULL
) {
297 log_debug("new key %s: 0x%x (%s)", s
, key
, keystr
);
298 tty_keys_add1(&tty
->key_tree
, s
, key
);
300 log_debug("replacing key %s: 0x%x (%s)", s
, key
, keystr
);
305 /* Add next node to the tree. */
307 tty_keys_add1(struct tty_key
**tkp
, const char *s
, int key
)
311 /* Allocate a tree entry if there isn't one already. */
314 tk
= *tkp
= xcalloc(1, sizeof *tk
);
319 /* Find the next entry. */
321 /* Move forward in string. */
324 /* If this is the end of the string, no more is necessary. */
330 /* Use the child tree for the next character. */
335 else if (*s
> tk
->ch
)
339 /* And recurse to add it. */
340 tty_keys_add1(tkp
, s
, key
);
343 /* Initialise a key tree from the table. */
345 tty_keys_build(struct tty
*tty
)
347 const struct tty_default_key_raw
*tdkr
;
348 const struct tty_default_key_code
*tdkc
;
352 if (tty
->key_tree
!= NULL
)
354 tty
->key_tree
= NULL
;
356 for (i
= 0; i
< nitems(tty_default_raw_keys
); i
++) {
357 tdkr
= &tty_default_raw_keys
[i
];
361 tty_keys_add(tty
, s
, tdkr
->key
);
363 for (i
= 0; i
< nitems(tty_default_code_keys
); i
++) {
364 tdkc
= &tty_default_code_keys
[i
];
366 s
= tty_term_string(tty
->term
, tdkc
->code
);
368 tty_keys_add(tty
, s
, tdkc
->key
);
373 /* Free the entire key tree. */
375 tty_keys_free(struct tty
*tty
)
377 tty_keys_free1(tty
->key_tree
);
380 /* Free a single key. */
382 tty_keys_free1(struct tty_key
*tk
)
384 if (tk
->next
!= NULL
)
385 tty_keys_free1(tk
->next
);
386 if (tk
->left
!= NULL
)
387 tty_keys_free1(tk
->left
);
388 if (tk
->right
!= NULL
)
389 tty_keys_free1(tk
->right
);
393 /* Lookup a key in the tree. */
395 tty_keys_find(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
398 return (tty_keys_find1(tty
->key_tree
, buf
, len
, size
));
401 /* Find the next node. */
403 tty_keys_find1(struct tty_key
*tk
, const char *buf
, size_t len
, size_t *size
)
405 /* If the node is NULL, this is the end of the tree. No match. */
409 /* Pick the next in the sequence. */
410 if (tk
->ch
== *buf
) {
411 /* Move forward in the string. */
415 /* At the end of the string, return the current node. */
416 if (len
== 0 || (tk
->next
== NULL
&& tk
->key
!= KEYC_NONE
))
419 /* Move into the next tree for the following character. */
424 else if (*buf
> tk
->ch
)
428 /* Move to the next in the tree. */
429 return (tty_keys_find1(tk
, buf
, len
, size
));
433 * Process at least one key in the buffer and invoke tty->key_callback. Return
434 * 0 if there are no further keys, or 1 if there could be more in the buffer.
437 tty_keys_next(struct tty
*tty
)
446 /* Get key buffer. */
447 buf
= EVBUFFER_DATA(tty
->event
->input
);
448 len
= EVBUFFER_LENGTH(tty
->event
->input
);
451 log_debug("keys are %zu (%.*s)", len
, (int) len
, buf
);
453 /* Is this device attributes response? */
454 switch (tty_keys_device(tty
, buf
, len
, &size
)) {
458 case -1: /* no, or not valid */
460 case 1: /* partial */
464 /* Is this a mouse key press? */
465 switch (tty_keys_mouse(tty
, buf
, len
, &size
)) {
469 case -1: /* no, or not valid */
471 case 1: /* partial */
475 /* Try to parse a key with an xterm-style modifier. */
476 switch (xterm_keys_find(buf
, len
, &size
, &key
)) {
479 case -1: /* not found */
485 /* Look for matching key string and return if found. */
486 tk
= tty_keys_find(tty
, buf
, len
, &size
);
488 if (tk
->next
!= NULL
)
494 /* Is this a meta key? */
495 if (len
>= 2 && buf
[0] == '\033') {
496 if (buf
[1] != '\033') {
497 key
= buf
[1] | KEYC_ESCAPE
;
502 tk
= tty_keys_find(tty
, buf
+ 1, len
- 1, &size
);
504 size
++; /* include escape */
505 if (tk
->next
!= NULL
)
508 if (key
!= KEYC_NONE
)
515 /* No key found, take first. */
520 * Check for backspace key using termios VERASE - the terminfo
521 * kbs entry is extremely unreliable, so cannot be safely
522 * used. termios should have a better idea.
524 bspace
= tty
->tio
.c_cc
[VERASE
];
525 if (bspace
!= _POSIX_VDISABLE
&& key
== bspace
)
531 log_debug("partial key %.*s", (int) len
, buf
);
533 /* If timer is going, check for expiration. */
534 if (tty
->flags
& TTY_TIMER
) {
535 if (evtimer_initialized(&tty
->key_timer
) &&
536 !evtimer_pending(&tty
->key_timer
, NULL
))
541 /* Get the time period. */
542 delay
= options_get_number(&global_options
, "escape-time");
543 tv
.tv_sec
= delay
/ 1000;
544 tv
.tv_usec
= (delay
% 1000) * 1000L;
546 /* Start the timer. */
547 if (event_initialized(&tty
->key_timer
))
548 evtimer_del(&tty
->key_timer
);
549 evtimer_set(&tty
->key_timer
, tty_keys_callback
, tty
);
550 evtimer_add(&tty
->key_timer
, &tv
);
552 tty
->flags
|= TTY_TIMER
;
556 log_debug("complete key %.*s %#x", (int) size
, buf
, key
);
558 /* Remove data from buffer. */
559 evbuffer_drain(tty
->event
->input
, size
);
561 /* Remove key timer. */
562 if (event_initialized(&tty
->key_timer
))
563 evtimer_del(&tty
->key_timer
);
564 tty
->flags
&= ~TTY_TIMER
;
566 /* Check for focus events. */
567 if (key
== KEYC_FOCUS_OUT
) {
568 tty
->client
->flags
&= ~CLIENT_FOCUSED
;
570 } else if (key
== KEYC_FOCUS_IN
) {
571 tty
->client
->flags
|= CLIENT_FOCUSED
;
576 if (key
!= KEYC_NONE
)
577 server_client_handle_key(tty
->client
, key
);
582 /* Key timer callback. */
584 tty_keys_callback(unused
int fd
, unused
short events
, void *data
)
586 struct tty
*tty
= data
;
588 if (tty
->flags
& TTY_TIMER
) {
589 while (tty_keys_next(tty
))
595 * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
596 * (probably a mouse sequence but need more data).
599 tty_keys_mouse(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
601 struct mouse_event
*m
= &tty
->mouse
;
602 struct utf8_data utf8data
;
603 u_int i
, value
, x
, y
, b
, sgr
, sgr_b
, sgr_rel
;
607 * Standard mouse sequences are \033[M followed by three characters
608 * indicating button, X and Y, all based at 32 with 1,1 top-left.
610 * UTF-8 mouse sequences are similar but the three are expressed as
613 * SGR extended mouse sequences are \033[< followed by three numbers in
614 * decimal and separated by semicolons indicating button, X and Y. A
615 * trailing 'M' is click or scroll and trailing 'm' release. All are
616 * based at 0 with 1,1 top-left.
620 x
= y
= b
= sgr
= sgr_b
= sgr_rel
= 0;
622 /* First two bytes are always \033[. */
623 if (buf
[0] != '\033')
633 * Third byte is M in old standard and UTF-8 extension, < in SGR
637 /* Read the three inputs. */
639 for (i
= 0; i
< 3; i
++) {
643 if (tty
->mode
& MODE_MOUSE_UTF8
) {
644 if (utf8_open(&utf8data
, buf
[*size
])) {
645 if (utf8data
.size
!= 2)
650 utf8_append(&utf8data
, buf
[*size
]);
651 value
= utf8_combine(&utf8data
);
653 value
= (u_char
) buf
[*size
];
656 value
= (u_char
) buf
[*size
];
667 log_debug("mouse input: %.*s", (int) *size
, buf
);
669 /* Check and return the mouse input. */
670 if (b
< 32 || x
< 33 || y
< 33)
675 } else if (buf
[2] == '<') {
676 /* Read the three inputs. */
681 c
= (u_char
)buf
[(*size
)++];
684 if (c
< '0' || c
> '9')
686 sgr_b
= 10 * sgr_b
+ (c
- '0');
691 c
= (u_char
)buf
[(*size
)++];
694 if (c
< '0' || c
> '9')
696 x
= 10 * x
+ (c
- '0');
701 c
= (u_char
) buf
[(*size
)++];
702 if (c
== 'M' || c
== 'm')
704 if (c
< '0' || c
> '9')
706 y
= 10 * y
+ (c
- '0');
708 log_debug("mouse input (sgr): %.*s", (int) *size
, buf
);
710 /* Check and return the mouse input. */
716 sgr_rel
= (c
== 'm');
718 /* Figure out what b would be in old format. */
725 /* Fill in mouse structure. */
726 if (~m
->event
& MOUSE_EVENT_WHEEL
) {
733 m
->sgr_rel
= sgr_rel
;
734 if (b
& 64) { /* wheel button */
737 m
->wheel
= MOUSE_WHEEL_UP
;
739 m
->wheel
= MOUSE_WHEEL_DOWN
;
740 m
->event
= MOUSE_EVENT_WHEEL
;
741 } else if ((b
& 3) == 3) {
742 if (~m
->event
& MOUSE_EVENT_DRAG
&& x
== m
->x
&& y
== m
->y
) {
743 m
->event
= MOUSE_EVENT_CLICK
;
745 m
->event
= MOUSE_EVENT_DRAG
;
746 m
->event
|= MOUSE_EVENT_UP
;
748 if (b
& 32) /* drag motion */
749 m
->event
= MOUSE_EVENT_DRAG
;
751 if (m
->event
& MOUSE_EVENT_UP
&& x
== m
->x
&& y
== m
->y
)
752 m
->clicks
= (m
->clicks
+ 1) % 3;
757 m
->event
= MOUSE_EVENT_DOWN
;
768 * Handle device attributes input. Returns 0 for success, -1 for failure, 1 for
772 tty_keys_device(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
775 char tmp
[64], *endptr
;
778 * Primary device attributes are \033[?a;b and secondary are
784 /* First three bytes are always \033[?. */
785 if (buf
[0] != '\033')
793 if (buf
[2] != '>' && buf
[2] != '?')
798 /* Copy the rest up to a 'c'. */
799 for (i
= 0; i
< (sizeof tmp
) - 1 && buf
[3 + i
] != 'c'; i
++) {
804 if (i
== (sizeof tmp
) - 1)
809 /* Only primary is of interest. */
813 /* Convert service class. */
814 class = strtoul(tmp
, &endptr
, 10);
818 log_debug("received service class %u", class);
819 tty_set_class(tty
, class);