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 /* Other (xterm) "cursor" keys. */
86 { "\033OH", KEYC_HOME
},
87 { "\033OF", KEYC_END
},
89 { "\033[H", KEYC_HOME
},
90 { "\033[F", KEYC_END
},
92 /* rxvt-style arrow + modifier keys. */
93 { "\033Oa", KEYC_UP
|KEYC_CTRL
},
94 { "\033Ob", KEYC_DOWN
|KEYC_CTRL
},
95 { "\033Oc", KEYC_RIGHT
|KEYC_CTRL
},
96 { "\033Od", KEYC_LEFT
|KEYC_CTRL
},
98 { "\033[a", KEYC_UP
|KEYC_SHIFT
},
99 { "\033[b", KEYC_DOWN
|KEYC_SHIFT
},
100 { "\033[c", KEYC_RIGHT
|KEYC_SHIFT
},
101 { "\033[d", KEYC_LEFT
|KEYC_SHIFT
},
103 /* rxvt-style function + modifier keys (C = ^, S = $, C-S = @). */
104 { "\033[11^", KEYC_F1
|KEYC_CTRL
},
105 { "\033[12^", KEYC_F2
|KEYC_CTRL
},
106 { "\033[13^", KEYC_F3
|KEYC_CTRL
},
107 { "\033[14^", KEYC_F4
|KEYC_CTRL
},
108 { "\033[15^", KEYC_F5
|KEYC_CTRL
},
109 { "\033[17^", KEYC_F6
|KEYC_CTRL
},
110 { "\033[18^", KEYC_F7
|KEYC_CTRL
},
111 { "\033[19^", KEYC_F8
|KEYC_CTRL
},
112 { "\033[20^", KEYC_F9
|KEYC_CTRL
},
113 { "\033[21^", KEYC_F10
|KEYC_CTRL
},
114 { "\033[23^", KEYC_F11
|KEYC_CTRL
},
115 { "\033[24^", KEYC_F12
|KEYC_CTRL
},
116 { "\033[25^", KEYC_F13
|KEYC_CTRL
},
117 { "\033[26^", KEYC_F14
|KEYC_CTRL
},
118 { "\033[28^", KEYC_F15
|KEYC_CTRL
},
119 { "\033[29^", KEYC_F16
|KEYC_CTRL
},
120 { "\033[31^", KEYC_F17
|KEYC_CTRL
},
121 { "\033[32^", KEYC_F18
|KEYC_CTRL
},
122 { "\033[33^", KEYC_F19
|KEYC_CTRL
},
123 { "\033[34^", KEYC_F20
|KEYC_CTRL
},
124 { "\033[2^", KEYC_IC
|KEYC_CTRL
},
125 { "\033[3^", KEYC_DC
|KEYC_CTRL
},
126 { "\033[7^", KEYC_HOME
|KEYC_CTRL
},
127 { "\033[8^", KEYC_END
|KEYC_CTRL
},
128 { "\033[6^", KEYC_NPAGE
|KEYC_CTRL
},
129 { "\033[5^", KEYC_PPAGE
|KEYC_CTRL
},
131 { "\033[11$", KEYC_F1
|KEYC_SHIFT
},
132 { "\033[12$", KEYC_F2
|KEYC_SHIFT
},
133 { "\033[13$", KEYC_F3
|KEYC_SHIFT
},
134 { "\033[14$", KEYC_F4
|KEYC_SHIFT
},
135 { "\033[15$", KEYC_F5
|KEYC_SHIFT
},
136 { "\033[17$", KEYC_F6
|KEYC_SHIFT
},
137 { "\033[18$", KEYC_F7
|KEYC_SHIFT
},
138 { "\033[19$", KEYC_F8
|KEYC_SHIFT
},
139 { "\033[20$", KEYC_F9
|KEYC_SHIFT
},
140 { "\033[21$", KEYC_F10
|KEYC_SHIFT
},
141 { "\033[23$", KEYC_F11
|KEYC_SHIFT
},
142 { "\033[24$", KEYC_F12
|KEYC_SHIFT
},
143 { "\033[25$", KEYC_F13
|KEYC_SHIFT
},
144 { "\033[26$", KEYC_F14
|KEYC_SHIFT
},
145 { "\033[28$", KEYC_F15
|KEYC_SHIFT
},
146 { "\033[29$", KEYC_F16
|KEYC_SHIFT
},
147 { "\033[31$", KEYC_F17
|KEYC_SHIFT
},
148 { "\033[32$", KEYC_F18
|KEYC_SHIFT
},
149 { "\033[33$", KEYC_F19
|KEYC_SHIFT
},
150 { "\033[34$", KEYC_F20
|KEYC_SHIFT
},
151 { "\033[2$", KEYC_IC
|KEYC_SHIFT
},
152 { "\033[3$", KEYC_DC
|KEYC_SHIFT
},
153 { "\033[7$", KEYC_HOME
|KEYC_SHIFT
},
154 { "\033[8$", KEYC_END
|KEYC_SHIFT
},
155 { "\033[6$", KEYC_NPAGE
|KEYC_SHIFT
},
156 { "\033[5$", KEYC_PPAGE
|KEYC_SHIFT
},
158 { "\033[11@", KEYC_F1
|KEYC_CTRL
|KEYC_SHIFT
},
159 { "\033[12@", KEYC_F2
|KEYC_CTRL
|KEYC_SHIFT
},
160 { "\033[13@", KEYC_F3
|KEYC_CTRL
|KEYC_SHIFT
},
161 { "\033[14@", KEYC_F4
|KEYC_CTRL
|KEYC_SHIFT
},
162 { "\033[15@", KEYC_F5
|KEYC_CTRL
|KEYC_SHIFT
},
163 { "\033[17@", KEYC_F6
|KEYC_CTRL
|KEYC_SHIFT
},
164 { "\033[18@", KEYC_F7
|KEYC_CTRL
|KEYC_SHIFT
},
165 { "\033[19@", KEYC_F8
|KEYC_CTRL
|KEYC_SHIFT
},
166 { "\033[20@", KEYC_F9
|KEYC_CTRL
|KEYC_SHIFT
},
167 { "\033[21@", KEYC_F10
|KEYC_CTRL
|KEYC_SHIFT
},
168 { "\033[23@", KEYC_F11
|KEYC_CTRL
|KEYC_SHIFT
},
169 { "\033[24@", KEYC_F12
|KEYC_CTRL
|KEYC_SHIFT
},
170 { "\033[25@", KEYC_F13
|KEYC_CTRL
|KEYC_SHIFT
},
171 { "\033[26@", KEYC_F14
|KEYC_CTRL
|KEYC_SHIFT
},
172 { "\033[28@", KEYC_F15
|KEYC_CTRL
|KEYC_SHIFT
},
173 { "\033[29@", KEYC_F16
|KEYC_CTRL
|KEYC_SHIFT
},
174 { "\033[31@", KEYC_F17
|KEYC_CTRL
|KEYC_SHIFT
},
175 { "\033[32@", KEYC_F18
|KEYC_CTRL
|KEYC_SHIFT
},
176 { "\033[33@", KEYC_F19
|KEYC_CTRL
|KEYC_SHIFT
},
177 { "\033[34@", KEYC_F20
|KEYC_CTRL
|KEYC_SHIFT
},
178 { "\033[2@", KEYC_IC
|KEYC_CTRL
|KEYC_SHIFT
},
179 { "\033[3@", KEYC_DC
|KEYC_CTRL
|KEYC_SHIFT
},
180 { "\033[7@", KEYC_HOME
|KEYC_CTRL
|KEYC_SHIFT
},
181 { "\033[8@", KEYC_END
|KEYC_CTRL
|KEYC_SHIFT
},
182 { "\033[6@", KEYC_NPAGE
|KEYC_CTRL
|KEYC_SHIFT
},
183 { "\033[5@", KEYC_PPAGE
|KEYC_CTRL
|KEYC_SHIFT
},
185 /* Focus tracking. */
186 { "\033[I", KEYC_FOCUS_IN
},
187 { "\033[O", KEYC_FOCUS_OUT
},
190 /* Default terminfo(5) keys. */
191 struct tty_default_key_code
{
192 enum tty_code_code code
;
195 const struct tty_default_key_code tty_default_code_keys
[] = {
197 { TTYC_KF1
, KEYC_F1
},
198 { TTYC_KF2
, KEYC_F2
},
199 { TTYC_KF3
, KEYC_F3
},
200 { TTYC_KF4
, KEYC_F4
},
201 { TTYC_KF5
, KEYC_F5
},
202 { TTYC_KF6
, KEYC_F6
},
203 { TTYC_KF7
, KEYC_F7
},
204 { TTYC_KF8
, KEYC_F8
},
205 { TTYC_KF9
, KEYC_F9
},
206 { TTYC_KF10
, KEYC_F10
},
207 { TTYC_KF11
, KEYC_F11
},
208 { TTYC_KF12
, KEYC_F12
},
209 { TTYC_KF13
, KEYC_F13
},
210 { TTYC_KF14
, KEYC_F14
},
211 { TTYC_KF15
, KEYC_F15
},
212 { TTYC_KF16
, KEYC_F16
},
213 { TTYC_KF17
, KEYC_F17
},
214 { TTYC_KF18
, KEYC_F18
},
215 { TTYC_KF19
, KEYC_F19
},
216 { TTYC_KF20
, KEYC_F20
},
217 { TTYC_KICH1
, KEYC_IC
},
218 { TTYC_KDCH1
, KEYC_DC
},
219 { TTYC_KHOME
, KEYC_HOME
},
220 { TTYC_KEND
, KEYC_END
},
221 { TTYC_KNP
, KEYC_NPAGE
},
222 { TTYC_KPP
, KEYC_PPAGE
},
223 { TTYC_KCBT
, KEYC_BTAB
},
225 /* Arrow keys from terminfo. */
226 { TTYC_KCUU1
, KEYC_UP
},
227 { TTYC_KCUD1
, KEYC_DOWN
},
228 { TTYC_KCUB1
, KEYC_LEFT
},
229 { TTYC_KCUF1
, KEYC_RIGHT
},
231 /* Key and modifier capabilities. */
232 { TTYC_KDC2
, KEYC_DC
|KEYC_SHIFT
},
233 { TTYC_KDC3
, KEYC_DC
|KEYC_ESCAPE
},
234 { TTYC_KDC4
, KEYC_DC
|KEYC_SHIFT
|KEYC_ESCAPE
},
235 { TTYC_KDC5
, KEYC_DC
|KEYC_CTRL
},
236 { TTYC_KDC6
, KEYC_DC
|KEYC_SHIFT
|KEYC_CTRL
},
237 { TTYC_KDC7
, KEYC_DC
|KEYC_ESCAPE
|KEYC_CTRL
},
238 { TTYC_KDN2
, KEYC_DOWN
|KEYC_SHIFT
},
239 { TTYC_KDN3
, KEYC_DOWN
|KEYC_ESCAPE
},
240 { TTYC_KDN4
, KEYC_DOWN
|KEYC_SHIFT
|KEYC_ESCAPE
},
241 { TTYC_KDN5
, KEYC_DOWN
|KEYC_CTRL
},
242 { TTYC_KDN6
, KEYC_DOWN
|KEYC_SHIFT
|KEYC_CTRL
},
243 { TTYC_KDN7
, KEYC_DOWN
|KEYC_ESCAPE
|KEYC_CTRL
},
244 { TTYC_KEND2
, KEYC_END
|KEYC_SHIFT
},
245 { TTYC_KEND3
, KEYC_END
|KEYC_ESCAPE
},
246 { TTYC_KEND4
, KEYC_END
|KEYC_SHIFT
|KEYC_ESCAPE
},
247 { TTYC_KEND5
, KEYC_END
|KEYC_CTRL
},
248 { TTYC_KEND6
, KEYC_END
|KEYC_SHIFT
|KEYC_CTRL
},
249 { TTYC_KEND7
, KEYC_END
|KEYC_ESCAPE
|KEYC_CTRL
},
250 { TTYC_KHOM2
, KEYC_HOME
|KEYC_SHIFT
},
251 { TTYC_KHOM3
, KEYC_HOME
|KEYC_ESCAPE
},
252 { TTYC_KHOM4
, KEYC_HOME
|KEYC_SHIFT
|KEYC_ESCAPE
},
253 { TTYC_KHOM5
, KEYC_HOME
|KEYC_CTRL
},
254 { TTYC_KHOM6
, KEYC_HOME
|KEYC_SHIFT
|KEYC_CTRL
},
255 { TTYC_KHOM7
, KEYC_HOME
|KEYC_ESCAPE
|KEYC_CTRL
},
256 { TTYC_KIC2
, KEYC_IC
|KEYC_SHIFT
},
257 { TTYC_KIC3
, KEYC_IC
|KEYC_ESCAPE
},
258 { TTYC_KIC4
, KEYC_IC
|KEYC_SHIFT
|KEYC_ESCAPE
},
259 { TTYC_KIC5
, KEYC_IC
|KEYC_CTRL
},
260 { TTYC_KIC6
, KEYC_IC
|KEYC_SHIFT
|KEYC_CTRL
},
261 { TTYC_KIC7
, KEYC_IC
|KEYC_ESCAPE
|KEYC_CTRL
},
262 { TTYC_KLFT2
, KEYC_LEFT
|KEYC_SHIFT
},
263 { TTYC_KLFT3
, KEYC_LEFT
|KEYC_ESCAPE
},
264 { TTYC_KLFT4
, KEYC_LEFT
|KEYC_SHIFT
|KEYC_ESCAPE
},
265 { TTYC_KLFT5
, KEYC_LEFT
|KEYC_CTRL
},
266 { TTYC_KLFT6
, KEYC_LEFT
|KEYC_SHIFT
|KEYC_CTRL
},
267 { TTYC_KLFT7
, KEYC_LEFT
|KEYC_ESCAPE
|KEYC_CTRL
},
268 { TTYC_KNXT2
, KEYC_NPAGE
|KEYC_SHIFT
},
269 { TTYC_KNXT3
, KEYC_NPAGE
|KEYC_ESCAPE
},
270 { TTYC_KNXT4
, KEYC_NPAGE
|KEYC_SHIFT
|KEYC_ESCAPE
},
271 { TTYC_KNXT5
, KEYC_NPAGE
|KEYC_CTRL
},
272 { TTYC_KNXT6
, KEYC_NPAGE
|KEYC_SHIFT
|KEYC_CTRL
},
273 { TTYC_KNXT7
, KEYC_NPAGE
|KEYC_ESCAPE
|KEYC_CTRL
},
274 { TTYC_KPRV2
, KEYC_PPAGE
|KEYC_SHIFT
},
275 { TTYC_KPRV3
, KEYC_PPAGE
|KEYC_ESCAPE
},
276 { TTYC_KPRV4
, KEYC_PPAGE
|KEYC_SHIFT
|KEYC_ESCAPE
},
277 { TTYC_KPRV5
, KEYC_PPAGE
|KEYC_CTRL
},
278 { TTYC_KPRV6
, KEYC_PPAGE
|KEYC_SHIFT
|KEYC_CTRL
},
279 { TTYC_KPRV7
, KEYC_PPAGE
|KEYC_ESCAPE
|KEYC_CTRL
},
280 { TTYC_KRIT2
, KEYC_RIGHT
|KEYC_SHIFT
},
281 { TTYC_KRIT3
, KEYC_RIGHT
|KEYC_ESCAPE
},
282 { TTYC_KRIT4
, KEYC_RIGHT
|KEYC_SHIFT
|KEYC_ESCAPE
},
283 { TTYC_KRIT5
, KEYC_RIGHT
|KEYC_CTRL
},
284 { TTYC_KRIT6
, KEYC_RIGHT
|KEYC_SHIFT
|KEYC_CTRL
},
285 { TTYC_KRIT7
, KEYC_RIGHT
|KEYC_ESCAPE
|KEYC_CTRL
},
286 { TTYC_KUP2
, KEYC_UP
|KEYC_SHIFT
},
287 { TTYC_KUP3
, KEYC_UP
|KEYC_ESCAPE
},
288 { TTYC_KUP4
, KEYC_UP
|KEYC_SHIFT
|KEYC_ESCAPE
},
289 { TTYC_KUP5
, KEYC_UP
|KEYC_CTRL
},
290 { TTYC_KUP6
, KEYC_UP
|KEYC_SHIFT
|KEYC_CTRL
},
291 { TTYC_KUP7
, KEYC_UP
|KEYC_ESCAPE
|KEYC_CTRL
},
294 /* Add key to tree. */
296 tty_keys_add(struct tty
*tty
, const char *s
, int key
)
302 keystr
= key_string_lookup_key(key
);
303 if ((tk
= tty_keys_find(tty
, s
, strlen(s
), &size
)) == NULL
) {
304 log_debug("new key %s: 0x%x (%s)", s
, key
, keystr
);
305 tty_keys_add1(&tty
->key_tree
, s
, key
);
307 log_debug("replacing key %s: 0x%x (%s)", s
, key
, keystr
);
312 /* Add next node to the tree. */
314 tty_keys_add1(struct tty_key
**tkp
, const char *s
, int key
)
318 /* Allocate a tree entry if there isn't one already. */
321 tk
= *tkp
= xcalloc(1, sizeof *tk
);
326 /* Find the next entry. */
328 /* Move forward in string. */
331 /* If this is the end of the string, no more is necessary. */
337 /* Use the child tree for the next character. */
342 else if (*s
> tk
->ch
)
346 /* And recurse to add it. */
347 tty_keys_add1(tkp
, s
, key
);
350 /* Initialise a key tree from the table. */
352 tty_keys_build(struct tty
*tty
)
354 const struct tty_default_key_raw
*tdkr
;
355 const struct tty_default_key_code
*tdkc
;
359 if (tty
->key_tree
!= NULL
)
361 tty
->key_tree
= NULL
;
363 for (i
= 0; i
< nitems(tty_default_raw_keys
); i
++) {
364 tdkr
= &tty_default_raw_keys
[i
];
368 tty_keys_add(tty
, s
, tdkr
->key
);
370 for (i
= 0; i
< nitems(tty_default_code_keys
); i
++) {
371 tdkc
= &tty_default_code_keys
[i
];
373 s
= tty_term_string(tty
->term
, tdkc
->code
);
375 tty_keys_add(tty
, s
, tdkc
->key
);
380 /* Free the entire key tree. */
382 tty_keys_free(struct tty
*tty
)
384 tty_keys_free1(tty
->key_tree
);
387 /* Free a single key. */
389 tty_keys_free1(struct tty_key
*tk
)
391 if (tk
->next
!= NULL
)
392 tty_keys_free1(tk
->next
);
393 if (tk
->left
!= NULL
)
394 tty_keys_free1(tk
->left
);
395 if (tk
->right
!= NULL
)
396 tty_keys_free1(tk
->right
);
400 /* Lookup a key in the tree. */
402 tty_keys_find(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
405 return (tty_keys_find1(tty
->key_tree
, buf
, len
, size
));
408 /* Find the next node. */
410 tty_keys_find1(struct tty_key
*tk
, const char *buf
, size_t len
, size_t *size
)
412 /* If the node is NULL, this is the end of the tree. No match. */
416 /* Pick the next in the sequence. */
417 if (tk
->ch
== *buf
) {
418 /* Move forward in the string. */
422 /* At the end of the string, return the current node. */
423 if (len
== 0 || (tk
->next
== NULL
&& tk
->key
!= KEYC_NONE
))
426 /* Move into the next tree for the following character. */
431 else if (*buf
> tk
->ch
)
435 /* Move to the next in the tree. */
436 return (tty_keys_find1(tk
, buf
, len
, size
));
440 * Process at least one key in the buffer and invoke tty->key_callback. Return
441 * 0 if there are no further keys, or 1 if there could be more in the buffer.
444 tty_keys_next(struct tty
*tty
)
451 int key
, delay
, expired
= 0;
453 /* Get key buffer. */
454 buf
= EVBUFFER_DATA(tty
->event
->input
);
455 len
= EVBUFFER_LENGTH(tty
->event
->input
);
458 log_debug("keys are %zu (%.*s)", len
, (int) len
, buf
);
460 /* Is this device attributes response? */
461 switch (tty_keys_device(tty
, buf
, len
, &size
)) {
465 case -1: /* no, or not valid */
467 case 1: /* partial */
471 /* Is this a mouse key press? */
472 switch (tty_keys_mouse(tty
, buf
, len
, &size
)) {
476 case -1: /* no, or not valid */
478 case 1: /* partial */
482 /* Try to parse a key with an xterm-style modifier. */
483 switch (xterm_keys_find(buf
, len
, &size
, &key
)) {
486 case -1: /* not found */
492 /* Look for matching key string and return if found. */
493 tk
= tty_keys_find(tty
, buf
, len
, &size
);
495 if (tk
->next
!= NULL
)
502 /* Is this a meta key? */
503 if (len
>= 2 && buf
[0] == '\033') {
504 if (buf
[1] != '\033') {
505 key
= buf
[1] | KEYC_ESCAPE
;
510 tk
= tty_keys_find(tty
, buf
+ 1, len
- 1, &size
);
511 if (tk
!= NULL
&& (!expired
|| tk
->next
== NULL
)) {
512 size
++; /* include escape */
513 if (tk
->next
!= NULL
)
516 if (key
!= KEYC_NONE
)
522 /* No key found, take first. */
527 * Check for backspace key using termios VERASE - the terminfo
528 * kbs entry is extremely unreliable, so cannot be safely
529 * used. termios should have a better idea.
531 bspace
= tty
->tio
.c_cc
[VERASE
];
532 if (bspace
!= _POSIX_VDISABLE
&& key
== bspace
)
538 log_debug("partial key %.*s", (int) len
, buf
);
540 /* If timer is going, check for expiration. */
541 if (tty
->flags
& TTY_TIMER
) {
542 if (evtimer_initialized(&tty
->key_timer
) &&
543 !evtimer_pending(&tty
->key_timer
, NULL
)) {
550 /* Get the time period. */
551 delay
= options_get_number(&global_options
, "escape-time");
552 tv
.tv_sec
= delay
/ 1000;
553 tv
.tv_usec
= (delay
% 1000) * 1000L;
555 /* Start the timer. */
556 if (event_initialized(&tty
->key_timer
))
557 evtimer_del(&tty
->key_timer
);
558 evtimer_set(&tty
->key_timer
, tty_keys_callback
, tty
);
559 evtimer_add(&tty
->key_timer
, &tv
);
561 tty
->flags
|= TTY_TIMER
;
565 log_debug("complete key %.*s %#x", (int) size
, buf
, key
);
567 /* Remove data from buffer. */
568 evbuffer_drain(tty
->event
->input
, size
);
570 /* Remove key timer. */
571 if (event_initialized(&tty
->key_timer
))
572 evtimer_del(&tty
->key_timer
);
573 tty
->flags
&= ~TTY_TIMER
;
575 /* Check for focus events. */
576 if (key
== KEYC_FOCUS_OUT
) {
577 tty
->client
->flags
&= ~CLIENT_FOCUSED
;
579 } else if (key
== KEYC_FOCUS_IN
) {
580 tty
->client
->flags
|= CLIENT_FOCUSED
;
585 if (key
!= KEYC_NONE
)
586 server_client_handle_key(tty
->client
, key
);
591 /* Key timer callback. */
593 tty_keys_callback(unused
int fd
, unused
short events
, void *data
)
595 struct tty
*tty
= data
;
597 if (tty
->flags
& TTY_TIMER
) {
598 while (tty_keys_next(tty
))
604 * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
605 * (probably a mouse sequence but need more data).
608 tty_keys_mouse(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
610 struct mouse_event
*m
= &tty
->mouse
;
611 struct utf8_data utf8data
;
612 u_int i
, value
, x
, y
, b
, sgr
, sgr_b
, sgr_rel
;
616 * Standard mouse sequences are \033[M followed by three characters
617 * indicating button, X and Y, all based at 32 with 1,1 top-left.
619 * UTF-8 mouse sequences are similar but the three are expressed as
622 * SGR extended mouse sequences are \033[< followed by three numbers in
623 * decimal and separated by semicolons indicating button, X and Y. A
624 * trailing 'M' is click or scroll and trailing 'm' release. All are
625 * based at 0 with 1,1 top-left.
629 x
= y
= b
= sgr
= sgr_b
= sgr_rel
= 0;
631 /* First two bytes are always \033[. */
632 if (buf
[0] != '\033')
642 * Third byte is M in old standard and UTF-8 extension, < in SGR
646 /* Read the three inputs. */
648 for (i
= 0; i
< 3; i
++) {
652 if (tty
->mode
& MODE_MOUSE_UTF8
) {
653 if (utf8_open(&utf8data
, buf
[*size
])) {
654 if (utf8data
.size
!= 2)
659 utf8_append(&utf8data
, buf
[*size
]);
660 value
= utf8_combine(&utf8data
);
662 value
= (u_char
) buf
[*size
];
665 value
= (u_char
) buf
[*size
];
676 log_debug("mouse input: %.*s", (int) *size
, buf
);
678 /* Check and return the mouse input. */
690 } else if (buf
[2] == '<') {
691 /* Read the three inputs. */
696 c
= (u_char
)buf
[(*size
)++];
699 if (c
< '0' || c
> '9')
701 sgr_b
= 10 * sgr_b
+ (c
- '0');
706 c
= (u_char
)buf
[(*size
)++];
709 if (c
< '0' || c
> '9')
711 x
= 10 * x
+ (c
- '0');
716 c
= (u_char
) buf
[(*size
)++];
717 if (c
== 'M' || c
== 'm')
719 if (c
< '0' || c
> '9')
721 y
= 10 * y
+ (c
- '0');
723 log_debug("mouse input (sgr): %.*s", (int) *size
, buf
);
725 /* Check and return the mouse input. */
731 sgr_rel
= (c
== 'm');
733 /* Figure out what b would be in old format. */
740 /* Fill in mouse structure. */
741 if (~m
->event
& MOUSE_EVENT_WHEEL
) {
748 m
->sgr_rel
= sgr_rel
;
749 if (b
& 64) { /* wheel button */
752 m
->wheel
= MOUSE_WHEEL_UP
;
754 m
->wheel
= MOUSE_WHEEL_DOWN
;
755 m
->event
= MOUSE_EVENT_WHEEL
;
756 } else if ((b
& 3) == 3) {
757 if (~m
->event
& MOUSE_EVENT_DRAG
&& x
== m
->x
&& y
== m
->y
) {
758 m
->event
= MOUSE_EVENT_CLICK
;
760 m
->event
= MOUSE_EVENT_DRAG
;
761 m
->event
|= MOUSE_EVENT_UP
;
763 if (b
& 32) /* drag motion */
764 m
->event
= MOUSE_EVENT_DRAG
;
766 if (m
->event
& MOUSE_EVENT_UP
&& x
== m
->x
&& y
== m
->y
)
767 m
->clicks
= (m
->clicks
+ 1) % 3;
772 m
->event
= MOUSE_EVENT_DOWN
;
783 * Handle device attributes input. Returns 0 for success, -1 for failure, 1 for
787 tty_keys_device(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
790 char tmp
[64], *endptr
;
793 * Primary device attributes are \033[?a;b and secondary are
799 /* First three bytes are always \033[?. */
800 if (buf
[0] != '\033')
808 if (buf
[2] != '>' && buf
[2] != '?')
813 /* Copy the rest up to a 'c'. */
814 for (i
= 0; i
< (sizeof tmp
) - 1 && buf
[3 + i
] != 'c'; i
++) {
819 if (i
== (sizeof tmp
) - 1)
824 /* Only primary is of interest. */
828 /* Convert service class. */
829 class = strtoul(tmp
, &endptr
, 10);
833 log_debug("received service class %u", class);
834 tty_set_class(tty
, class);