4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
22 #include <netinet/in.h>
35 * Handle keys input from the outside terminal. tty_default_*_keys[] are a base
36 * table of supported keys which are looked up in terminfo(5) and translated
37 * into a ternary tree.
40 static void tty_keys_add1(struct tty_key
**, const char *, key_code
);
41 static void tty_keys_add(struct tty
*, const char *, key_code
);
42 static void tty_keys_free1(struct tty_key
*);
43 static struct tty_key
*tty_keys_find1(struct tty_key
*, const char *, size_t,
45 static struct tty_key
*tty_keys_find(struct tty
*, const char *, size_t,
47 static int tty_keys_next1(struct tty
*, const char *, size_t, key_code
*,
49 static void tty_keys_callback(int, short, void *);
50 static int tty_keys_extended_key(struct tty
*, const char *, size_t,
51 size_t *, key_code
*);
52 static int tty_keys_mouse(struct tty
*, const char *, size_t, size_t *,
53 struct mouse_event
*);
54 static int tty_keys_clipboard(struct tty
*, const char *, size_t,
56 static int tty_keys_device_attributes(struct tty
*, const char *, size_t,
58 static int tty_keys_device_attributes2(struct tty
*, const char *, size_t,
60 static int tty_keys_extended_device_attributes(struct tty
*, const char *,
63 /* A key tree entry. */
69 struct tty_key
*right
;
74 /* Default raw keys. */
75 struct tty_default_key_raw
{
79 static const struct tty_default_key_raw tty_default_raw_keys
[] = {
80 /* Application escape. */
84 * Numeric keypad. Just use the vt100 escape sequences here and always
85 * put the terminal into keypad_xmit mode. Translation of numbers
86 * mode/applications mode is done in input-keys.c.
88 { "\033Oo", KEYC_KP_SLASH
|KEYC_KEYPAD
},
89 { "\033Oj", KEYC_KP_STAR
|KEYC_KEYPAD
},
90 { "\033Om", KEYC_KP_MINUS
|KEYC_KEYPAD
},
91 { "\033Ow", KEYC_KP_SEVEN
|KEYC_KEYPAD
},
92 { "\033Ox", KEYC_KP_EIGHT
|KEYC_KEYPAD
},
93 { "\033Oy", KEYC_KP_NINE
|KEYC_KEYPAD
},
94 { "\033Ok", KEYC_KP_PLUS
|KEYC_KEYPAD
},
95 { "\033Ot", KEYC_KP_FOUR
|KEYC_KEYPAD
},
96 { "\033Ou", KEYC_KP_FIVE
|KEYC_KEYPAD
},
97 { "\033Ov", KEYC_KP_SIX
|KEYC_KEYPAD
},
98 { "\033Oq", KEYC_KP_ONE
|KEYC_KEYPAD
},
99 { "\033Or", KEYC_KP_TWO
|KEYC_KEYPAD
},
100 { "\033Os", KEYC_KP_THREE
|KEYC_KEYPAD
},
101 { "\033OM", KEYC_KP_ENTER
|KEYC_KEYPAD
},
102 { "\033Op", KEYC_KP_ZERO
|KEYC_KEYPAD
},
103 { "\033On", KEYC_KP_PERIOD
|KEYC_KEYPAD
},
106 { "\033OA", KEYC_UP
|KEYC_CURSOR
},
107 { "\033OB", KEYC_DOWN
|KEYC_CURSOR
},
108 { "\033OC", KEYC_RIGHT
|KEYC_CURSOR
},
109 { "\033OD", KEYC_LEFT
|KEYC_CURSOR
},
111 { "\033[A", KEYC_UP
|KEYC_CURSOR
},
112 { "\033[B", KEYC_DOWN
|KEYC_CURSOR
},
113 { "\033[C", KEYC_RIGHT
|KEYC_CURSOR
},
114 { "\033[D", KEYC_LEFT
|KEYC_CURSOR
},
117 * Meta arrow keys. These do not get the IMPLIED_META flag so they
118 * don't match the xterm-style meta keys in the output tree - Escape+Up
119 * should stay as Escape+Up and not become M-Up.
121 { "\033\033OA", KEYC_UP
|KEYC_CURSOR
|KEYC_META
},
122 { "\033\033OB", KEYC_DOWN
|KEYC_CURSOR
|KEYC_META
},
123 { "\033\033OC", KEYC_RIGHT
|KEYC_CURSOR
|KEYC_META
},
124 { "\033\033OD", KEYC_LEFT
|KEYC_CURSOR
|KEYC_META
},
126 { "\033\033[A", KEYC_UP
|KEYC_CURSOR
|KEYC_META
},
127 { "\033\033[B", KEYC_DOWN
|KEYC_CURSOR
|KEYC_META
},
128 { "\033\033[C", KEYC_RIGHT
|KEYC_CURSOR
|KEYC_META
},
129 { "\033\033[D", KEYC_LEFT
|KEYC_CURSOR
|KEYC_META
},
131 /* Other xterm keys. */
132 { "\033OH", KEYC_HOME
},
133 { "\033OF", KEYC_END
},
135 { "\033\033OH", KEYC_HOME
|KEYC_META
|KEYC_IMPLIED_META
},
136 { "\033\033OF", KEYC_END
|KEYC_META
|KEYC_IMPLIED_META
},
138 { "\033[H", KEYC_HOME
},
139 { "\033[F", KEYC_END
},
141 { "\033\033[H", KEYC_HOME
|KEYC_META
|KEYC_IMPLIED_META
},
142 { "\033\033[F", KEYC_END
|KEYC_META
|KEYC_IMPLIED_META
},
144 /* rxvt arrow keys. */
145 { "\033Oa", KEYC_UP
|KEYC_CTRL
},
146 { "\033Ob", KEYC_DOWN
|KEYC_CTRL
},
147 { "\033Oc", KEYC_RIGHT
|KEYC_CTRL
},
148 { "\033Od", KEYC_LEFT
|KEYC_CTRL
},
150 { "\033[a", KEYC_UP
|KEYC_SHIFT
},
151 { "\033[b", KEYC_DOWN
|KEYC_SHIFT
},
152 { "\033[c", KEYC_RIGHT
|KEYC_SHIFT
},
153 { "\033[d", KEYC_LEFT
|KEYC_SHIFT
},
155 /* rxvt function keys. */
156 { "\033[11~", KEYC_F1
},
157 { "\033[12~", KEYC_F2
},
158 { "\033[13~", KEYC_F3
},
159 { "\033[14~", KEYC_F4
},
160 { "\033[15~", KEYC_F5
},
161 { "\033[17~", KEYC_F6
},
162 { "\033[18~", KEYC_F7
},
163 { "\033[19~", KEYC_F8
},
164 { "\033[20~", KEYC_F9
},
165 { "\033[21~", KEYC_F10
},
167 { "\033[23~", KEYC_F1
|KEYC_SHIFT
},
168 { "\033[24~", KEYC_F2
|KEYC_SHIFT
},
169 { "\033[25~", KEYC_F3
|KEYC_SHIFT
},
170 { "\033[26~", KEYC_F4
|KEYC_SHIFT
},
171 { "\033[28~", KEYC_F5
|KEYC_SHIFT
},
172 { "\033[29~", KEYC_F6
|KEYC_SHIFT
},
173 { "\033[31~", KEYC_F7
|KEYC_SHIFT
},
174 { "\033[32~", KEYC_F8
|KEYC_SHIFT
},
175 { "\033[33~", KEYC_F9
|KEYC_SHIFT
},
176 { "\033[34~", KEYC_F10
|KEYC_SHIFT
},
177 { "\033[23$", KEYC_F11
|KEYC_SHIFT
},
178 { "\033[24$", KEYC_F12
|KEYC_SHIFT
},
180 { "\033[11^", KEYC_F1
|KEYC_CTRL
},
181 { "\033[12^", KEYC_F2
|KEYC_CTRL
},
182 { "\033[13^", KEYC_F3
|KEYC_CTRL
},
183 { "\033[14^", KEYC_F4
|KEYC_CTRL
},
184 { "\033[15^", KEYC_F5
|KEYC_CTRL
},
185 { "\033[17^", KEYC_F6
|KEYC_CTRL
},
186 { "\033[18^", KEYC_F7
|KEYC_CTRL
},
187 { "\033[19^", KEYC_F8
|KEYC_CTRL
},
188 { "\033[20^", KEYC_F9
|KEYC_CTRL
},
189 { "\033[21^", KEYC_F10
|KEYC_CTRL
},
190 { "\033[23^", KEYC_F11
|KEYC_CTRL
},
191 { "\033[24^", KEYC_F12
|KEYC_CTRL
},
193 { "\033[11@", KEYC_F1
|KEYC_CTRL
|KEYC_SHIFT
},
194 { "\033[12@", KEYC_F2
|KEYC_CTRL
|KEYC_SHIFT
},
195 { "\033[13@", KEYC_F3
|KEYC_CTRL
|KEYC_SHIFT
},
196 { "\033[14@", KEYC_F4
|KEYC_CTRL
|KEYC_SHIFT
},
197 { "\033[15@", KEYC_F5
|KEYC_CTRL
|KEYC_SHIFT
},
198 { "\033[17@", KEYC_F6
|KEYC_CTRL
|KEYC_SHIFT
},
199 { "\033[18@", KEYC_F7
|KEYC_CTRL
|KEYC_SHIFT
},
200 { "\033[19@", KEYC_F8
|KEYC_CTRL
|KEYC_SHIFT
},
201 { "\033[20@", KEYC_F9
|KEYC_CTRL
|KEYC_SHIFT
},
202 { "\033[21@", KEYC_F10
|KEYC_CTRL
|KEYC_SHIFT
},
203 { "\033[23@", KEYC_F11
|KEYC_CTRL
|KEYC_SHIFT
},
204 { "\033[24@", KEYC_F12
|KEYC_CTRL
|KEYC_SHIFT
},
206 /* Focus tracking. */
207 { "\033[I", KEYC_FOCUS_IN
},
208 { "\033[O", KEYC_FOCUS_OUT
},
211 { "\033[200~", KEYC_PASTE_START
},
212 { "\033[201~", KEYC_PASTE_END
},
215 { "\033[1;5Z", '\011'|KEYC_CTRL
|KEYC_SHIFT
},
218 /* Default xterm keys. */
219 struct tty_default_key_xterm
{
220 const char *template;
223 static const struct tty_default_key_xterm tty_default_xterm_keys
[] = {
224 { "\033[1;_P", KEYC_F1
},
225 { "\033O1;_P", KEYC_F1
},
226 { "\033O_P", KEYC_F1
},
227 { "\033[1;_Q", KEYC_F2
},
228 { "\033O1;_Q", KEYC_F2
},
229 { "\033O_Q", KEYC_F2
},
230 { "\033[1;_R", KEYC_F3
},
231 { "\033O1;_R", KEYC_F3
},
232 { "\033O_R", KEYC_F3
},
233 { "\033[1;_S", KEYC_F4
},
234 { "\033O1;_S", KEYC_F4
},
235 { "\033O_S", KEYC_F4
},
236 { "\033[15;_~", KEYC_F5
},
237 { "\033[17;_~", KEYC_F6
},
238 { "\033[18;_~", KEYC_F7
},
239 { "\033[19;_~", KEYC_F8
},
240 { "\033[20;_~", KEYC_F9
},
241 { "\033[21;_~", KEYC_F10
},
242 { "\033[23;_~", KEYC_F11
},
243 { "\033[24;_~", KEYC_F12
},
244 { "\033[1;_A", KEYC_UP
},
245 { "\033[1;_B", KEYC_DOWN
},
246 { "\033[1;_C", KEYC_RIGHT
},
247 { "\033[1;_D", KEYC_LEFT
},
248 { "\033[1;_H", KEYC_HOME
},
249 { "\033[1;_F", KEYC_END
},
250 { "\033[5;_~", KEYC_PPAGE
},
251 { "\033[6;_~", KEYC_NPAGE
},
252 { "\033[2;_~", KEYC_IC
},
253 { "\033[3;_~", KEYC_DC
},
255 static const key_code tty_default_xterm_modifiers
[] = {
259 KEYC_META
|KEYC_IMPLIED_META
,
260 KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
,
262 KEYC_SHIFT
|KEYC_CTRL
,
263 KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
,
264 KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
,
265 KEYC_META
|KEYC_IMPLIED_META
269 * Default terminfo(5) keys. Any keys that have builtin modifiers (that is,
270 * where the key itself contains the modifiers) has the KEYC_XTERM flag set so
271 * a leading escape is not treated as meta (and probably removed).
273 struct tty_default_key_code
{
274 enum tty_code_code code
;
277 static const struct tty_default_key_code tty_default_code_keys
[] = {
279 { TTYC_KF1
, KEYC_F1
},
280 { TTYC_KF2
, KEYC_F2
},
281 { TTYC_KF3
, KEYC_F3
},
282 { TTYC_KF4
, KEYC_F4
},
283 { TTYC_KF5
, KEYC_F5
},
284 { TTYC_KF6
, KEYC_F6
},
285 { TTYC_KF7
, KEYC_F7
},
286 { TTYC_KF8
, KEYC_F8
},
287 { TTYC_KF9
, KEYC_F9
},
288 { TTYC_KF10
, KEYC_F10
},
289 { TTYC_KF11
, KEYC_F11
},
290 { TTYC_KF12
, KEYC_F12
},
292 { TTYC_KF13
, KEYC_F1
|KEYC_SHIFT
},
293 { TTYC_KF14
, KEYC_F2
|KEYC_SHIFT
},
294 { TTYC_KF15
, KEYC_F3
|KEYC_SHIFT
},
295 { TTYC_KF16
, KEYC_F4
|KEYC_SHIFT
},
296 { TTYC_KF17
, KEYC_F5
|KEYC_SHIFT
},
297 { TTYC_KF18
, KEYC_F6
|KEYC_SHIFT
},
298 { TTYC_KF19
, KEYC_F7
|KEYC_SHIFT
},
299 { TTYC_KF20
, KEYC_F8
|KEYC_SHIFT
},
300 { TTYC_KF21
, KEYC_F9
|KEYC_SHIFT
},
301 { TTYC_KF22
, KEYC_F10
|KEYC_SHIFT
},
302 { TTYC_KF23
, KEYC_F11
|KEYC_SHIFT
},
303 { TTYC_KF24
, KEYC_F12
|KEYC_SHIFT
},
305 { TTYC_KF25
, KEYC_F1
|KEYC_CTRL
},
306 { TTYC_KF26
, KEYC_F2
|KEYC_CTRL
},
307 { TTYC_KF27
, KEYC_F3
|KEYC_CTRL
},
308 { TTYC_KF28
, KEYC_F4
|KEYC_CTRL
},
309 { TTYC_KF29
, KEYC_F5
|KEYC_CTRL
},
310 { TTYC_KF30
, KEYC_F6
|KEYC_CTRL
},
311 { TTYC_KF31
, KEYC_F7
|KEYC_CTRL
},
312 { TTYC_KF32
, KEYC_F8
|KEYC_CTRL
},
313 { TTYC_KF33
, KEYC_F9
|KEYC_CTRL
},
314 { TTYC_KF34
, KEYC_F10
|KEYC_CTRL
},
315 { TTYC_KF35
, KEYC_F11
|KEYC_CTRL
},
316 { TTYC_KF36
, KEYC_F12
|KEYC_CTRL
},
318 { TTYC_KF37
, KEYC_F1
|KEYC_SHIFT
|KEYC_CTRL
},
319 { TTYC_KF38
, KEYC_F2
|KEYC_SHIFT
|KEYC_CTRL
},
320 { TTYC_KF39
, KEYC_F3
|KEYC_SHIFT
|KEYC_CTRL
},
321 { TTYC_KF40
, KEYC_F4
|KEYC_SHIFT
|KEYC_CTRL
},
322 { TTYC_KF41
, KEYC_F5
|KEYC_SHIFT
|KEYC_CTRL
},
323 { TTYC_KF42
, KEYC_F6
|KEYC_SHIFT
|KEYC_CTRL
},
324 { TTYC_KF43
, KEYC_F7
|KEYC_SHIFT
|KEYC_CTRL
},
325 { TTYC_KF44
, KEYC_F8
|KEYC_SHIFT
|KEYC_CTRL
},
326 { TTYC_KF45
, KEYC_F9
|KEYC_SHIFT
|KEYC_CTRL
},
327 { TTYC_KF46
, KEYC_F10
|KEYC_SHIFT
|KEYC_CTRL
},
328 { TTYC_KF47
, KEYC_F11
|KEYC_SHIFT
|KEYC_CTRL
},
329 { TTYC_KF48
, KEYC_F12
|KEYC_SHIFT
|KEYC_CTRL
},
331 { TTYC_KF49
, KEYC_F1
|KEYC_META
|KEYC_IMPLIED_META
},
332 { TTYC_KF50
, KEYC_F2
|KEYC_META
|KEYC_IMPLIED_META
},
333 { TTYC_KF51
, KEYC_F3
|KEYC_META
|KEYC_IMPLIED_META
},
334 { TTYC_KF52
, KEYC_F4
|KEYC_META
|KEYC_IMPLIED_META
},
335 { TTYC_KF53
, KEYC_F5
|KEYC_META
|KEYC_IMPLIED_META
},
336 { TTYC_KF54
, KEYC_F6
|KEYC_META
|KEYC_IMPLIED_META
},
337 { TTYC_KF55
, KEYC_F7
|KEYC_META
|KEYC_IMPLIED_META
},
338 { TTYC_KF56
, KEYC_F8
|KEYC_META
|KEYC_IMPLIED_META
},
339 { TTYC_KF57
, KEYC_F9
|KEYC_META
|KEYC_IMPLIED_META
},
340 { TTYC_KF58
, KEYC_F10
|KEYC_META
|KEYC_IMPLIED_META
},
341 { TTYC_KF59
, KEYC_F11
|KEYC_META
|KEYC_IMPLIED_META
},
342 { TTYC_KF60
, KEYC_F12
|KEYC_META
|KEYC_IMPLIED_META
},
344 { TTYC_KF61
, KEYC_F1
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_SHIFT
},
345 { TTYC_KF62
, KEYC_F2
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_SHIFT
},
346 { TTYC_KF63
, KEYC_F3
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_SHIFT
},
348 { TTYC_KICH1
, KEYC_IC
},
349 { TTYC_KDCH1
, KEYC_DC
},
350 { TTYC_KHOME
, KEYC_HOME
},
351 { TTYC_KEND
, KEYC_END
},
352 { TTYC_KNP
, KEYC_NPAGE
},
353 { TTYC_KPP
, KEYC_PPAGE
},
354 { TTYC_KCBT
, KEYC_BTAB
},
356 /* Arrow keys from terminfo. */
357 { TTYC_KCUU1
, KEYC_UP
|KEYC_CURSOR
},
358 { TTYC_KCUD1
, KEYC_DOWN
|KEYC_CURSOR
},
359 { TTYC_KCUB1
, KEYC_LEFT
|KEYC_CURSOR
},
360 { TTYC_KCUF1
, KEYC_RIGHT
|KEYC_CURSOR
},
362 /* Key and modifier capabilities. */
363 { TTYC_KDC2
, KEYC_DC
|KEYC_SHIFT
},
364 { TTYC_KDC3
, KEYC_DC
|KEYC_META
|KEYC_IMPLIED_META
},
365 { TTYC_KDC4
, KEYC_DC
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
366 { TTYC_KDC5
, KEYC_DC
|KEYC_CTRL
},
367 { TTYC_KDC6
, KEYC_DC
|KEYC_SHIFT
|KEYC_CTRL
},
368 { TTYC_KDC7
, KEYC_DC
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
369 { TTYC_KIND
, KEYC_DOWN
|KEYC_SHIFT
},
370 { TTYC_KDN2
, KEYC_DOWN
|KEYC_SHIFT
},
371 { TTYC_KDN3
, KEYC_DOWN
|KEYC_META
|KEYC_IMPLIED_META
},
372 { TTYC_KDN4
, KEYC_DOWN
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
373 { TTYC_KDN5
, KEYC_DOWN
|KEYC_CTRL
},
374 { TTYC_KDN6
, KEYC_DOWN
|KEYC_SHIFT
|KEYC_CTRL
},
375 { TTYC_KDN7
, KEYC_DOWN
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
376 { TTYC_KEND2
, KEYC_END
|KEYC_SHIFT
},
377 { TTYC_KEND3
, KEYC_END
|KEYC_META
|KEYC_IMPLIED_META
},
378 { TTYC_KEND4
, KEYC_END
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
379 { TTYC_KEND5
, KEYC_END
|KEYC_CTRL
},
380 { TTYC_KEND6
, KEYC_END
|KEYC_SHIFT
|KEYC_CTRL
},
381 { TTYC_KEND7
, KEYC_END
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
382 { TTYC_KHOM2
, KEYC_HOME
|KEYC_SHIFT
},
383 { TTYC_KHOM3
, KEYC_HOME
|KEYC_META
|KEYC_IMPLIED_META
},
384 { TTYC_KHOM4
, KEYC_HOME
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
385 { TTYC_KHOM5
, KEYC_HOME
|KEYC_CTRL
},
386 { TTYC_KHOM6
, KEYC_HOME
|KEYC_SHIFT
|KEYC_CTRL
},
387 { TTYC_KHOM7
, KEYC_HOME
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
388 { TTYC_KIC2
, KEYC_IC
|KEYC_SHIFT
},
389 { TTYC_KIC3
, KEYC_IC
|KEYC_META
|KEYC_IMPLIED_META
},
390 { TTYC_KIC4
, KEYC_IC
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
391 { TTYC_KIC5
, KEYC_IC
|KEYC_CTRL
},
392 { TTYC_KIC6
, KEYC_IC
|KEYC_SHIFT
|KEYC_CTRL
},
393 { TTYC_KIC7
, KEYC_IC
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
394 { TTYC_KLFT2
, KEYC_LEFT
|KEYC_SHIFT
},
395 { TTYC_KLFT3
, KEYC_LEFT
|KEYC_META
|KEYC_IMPLIED_META
},
396 { TTYC_KLFT4
, KEYC_LEFT
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
397 { TTYC_KLFT5
, KEYC_LEFT
|KEYC_CTRL
},
398 { TTYC_KLFT6
, KEYC_LEFT
|KEYC_SHIFT
|KEYC_CTRL
},
399 { TTYC_KLFT7
, KEYC_LEFT
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
400 { TTYC_KNXT2
, KEYC_NPAGE
|KEYC_SHIFT
},
401 { TTYC_KNXT3
, KEYC_NPAGE
|KEYC_META
|KEYC_IMPLIED_META
},
402 { TTYC_KNXT4
, KEYC_NPAGE
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
403 { TTYC_KNXT5
, KEYC_NPAGE
|KEYC_CTRL
},
404 { TTYC_KNXT6
, KEYC_NPAGE
|KEYC_SHIFT
|KEYC_CTRL
},
405 { TTYC_KNXT7
, KEYC_NPAGE
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
406 { TTYC_KPRV2
, KEYC_PPAGE
|KEYC_SHIFT
},
407 { TTYC_KPRV3
, KEYC_PPAGE
|KEYC_META
|KEYC_IMPLIED_META
},
408 { TTYC_KPRV4
, KEYC_PPAGE
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
409 { TTYC_KPRV5
, KEYC_PPAGE
|KEYC_CTRL
},
410 { TTYC_KPRV6
, KEYC_PPAGE
|KEYC_SHIFT
|KEYC_CTRL
},
411 { TTYC_KPRV7
, KEYC_PPAGE
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
412 { TTYC_KRIT2
, KEYC_RIGHT
|KEYC_SHIFT
},
413 { TTYC_KRIT3
, KEYC_RIGHT
|KEYC_META
|KEYC_IMPLIED_META
},
414 { TTYC_KRIT4
, KEYC_RIGHT
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
415 { TTYC_KRIT5
, KEYC_RIGHT
|KEYC_CTRL
},
416 { TTYC_KRIT6
, KEYC_RIGHT
|KEYC_SHIFT
|KEYC_CTRL
},
417 { TTYC_KRIT7
, KEYC_RIGHT
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
418 { TTYC_KRI
, KEYC_UP
|KEYC_SHIFT
},
419 { TTYC_KUP2
, KEYC_UP
|KEYC_SHIFT
},
420 { TTYC_KUP3
, KEYC_UP
|KEYC_META
|KEYC_IMPLIED_META
},
421 { TTYC_KUP4
, KEYC_UP
|KEYC_SHIFT
|KEYC_META
|KEYC_IMPLIED_META
},
422 { TTYC_KUP5
, KEYC_UP
|KEYC_CTRL
},
423 { TTYC_KUP6
, KEYC_UP
|KEYC_SHIFT
|KEYC_CTRL
},
424 { TTYC_KUP7
, KEYC_UP
|KEYC_META
|KEYC_IMPLIED_META
|KEYC_CTRL
},
427 /* Add key to tree. */
429 tty_keys_add(struct tty
*tty
, const char *s
, key_code key
)
435 keystr
= key_string_lookup_key(key
, 1);
436 if ((tk
= tty_keys_find(tty
, s
, strlen(s
), &size
)) == NULL
) {
437 log_debug("new key %s: 0x%llx (%s)", s
, key
, keystr
);
438 tty_keys_add1(&tty
->key_tree
, s
, key
);
440 log_debug("replacing key %s: 0x%llx (%s)", s
, key
, keystr
);
445 /* Add next node to the tree. */
447 tty_keys_add1(struct tty_key
**tkp
, const char *s
, key_code key
)
451 /* Allocate a tree entry if there isn't one already. */
454 tk
= *tkp
= xcalloc(1, sizeof *tk
);
456 tk
->key
= KEYC_UNKNOWN
;
459 /* Find the next entry. */
461 /* Move forward in string. */
464 /* If this is the end of the string, no more is necessary. */
470 /* Use the child tree for the next character. */
475 else if (*s
> tk
->ch
)
479 /* And recurse to add it. */
480 tty_keys_add1(tkp
, s
, key
);
483 /* Initialise a key tree from the table. */
485 tty_keys_build(struct tty
*tty
)
487 const struct tty_default_key_raw
*tdkr
;
488 const struct tty_default_key_xterm
*tdkx
;
489 const struct tty_default_key_code
*tdkc
;
492 struct options_entry
*o
;
493 struct options_array_item
*a
;
494 union options_value
*ov
;
498 if (tty
->key_tree
!= NULL
)
500 tty
->key_tree
= NULL
;
502 for (i
= 0; i
< nitems(tty_default_xterm_keys
); i
++) {
503 tdkx
= &tty_default_xterm_keys
[i
];
504 for (j
= 2; j
< nitems(tty_default_xterm_modifiers
); j
++) {
505 strlcpy(copy
, tdkx
->template, sizeof copy
);
506 copy
[strcspn(copy
, "_")] = '0' + j
;
508 key
= tdkx
->key
|tty_default_xterm_modifiers
[j
];
509 tty_keys_add(tty
, copy
, key
);
512 for (i
= 0; i
< nitems(tty_default_raw_keys
); i
++) {
513 tdkr
= &tty_default_raw_keys
[i
];
517 tty_keys_add(tty
, s
, tdkr
->key
);
519 for (i
= 0; i
< nitems(tty_default_code_keys
); i
++) {
520 tdkc
= &tty_default_code_keys
[i
];
522 s
= tty_term_string(tty
->term
, tdkc
->code
);
524 tty_keys_add(tty
, s
, tdkc
->key
);
528 o
= options_get(global_options
, "user-keys");
530 a
= options_array_first(o
);
532 i
= options_array_item_index(a
);
533 ov
= options_array_item_value(a
);
534 tty_keys_add(tty
, ov
->string
, KEYC_USER
+ i
);
535 a
= options_array_next(a
);
540 /* Free the entire key tree. */
542 tty_keys_free(struct tty
*tty
)
544 tty_keys_free1(tty
->key_tree
);
547 /* Free a single key. */
549 tty_keys_free1(struct tty_key
*tk
)
551 if (tk
->next
!= NULL
)
552 tty_keys_free1(tk
->next
);
553 if (tk
->left
!= NULL
)
554 tty_keys_free1(tk
->left
);
555 if (tk
->right
!= NULL
)
556 tty_keys_free1(tk
->right
);
560 /* Lookup a key in the tree. */
561 static struct tty_key
*
562 tty_keys_find(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
565 return (tty_keys_find1(tty
->key_tree
, buf
, len
, size
));
568 /* Find the next node. */
569 static struct tty_key
*
570 tty_keys_find1(struct tty_key
*tk
, const char *buf
, size_t len
, size_t *size
)
572 /* If no data, no match. */
576 /* If the node is NULL, this is the end of the tree. No match. */
580 /* Pick the next in the sequence. */
581 if (tk
->ch
== *buf
) {
582 /* Move forward in the string. */
586 /* At the end of the string, return the current node. */
587 if (len
== 0 || (tk
->next
== NULL
&& tk
->key
!= KEYC_UNKNOWN
))
590 /* Move into the next tree for the following character. */
595 else if (*buf
> tk
->ch
)
599 /* Move to the next in the tree. */
600 return (tty_keys_find1(tk
, buf
, len
, size
));
603 /* Look up part of the next key. */
605 tty_keys_next1(struct tty
*tty
, const char *buf
, size_t len
, key_code
*key
,
606 size_t *size
, int expired
)
608 struct client
*c
= tty
->client
;
609 struct tty_key
*tk
, *tk1
;
611 enum utf8_state more
;
615 log_debug("%s: next key is %zu (%.*s) (expired=%d)", c
->name
, len
,
616 (int)len
, buf
, expired
);
618 /* Is this a known key? */
619 tk
= tty_keys_find(tty
, buf
, len
, size
);
620 if (tk
!= NULL
&& tk
->key
!= KEYC_UNKNOWN
) {
623 log_debug("%s: keys in list: %#llx", c
->name
, tk1
->key
);
624 while ((tk1
= tk1
->next
) != NULL
);
625 if (tk
->next
!= NULL
&& !expired
)
631 /* Is this valid UTF-8? */
632 more
= utf8_open(&ud
, (u_char
)*buf
);
633 if (more
== UTF8_MORE
) {
640 for (i
= 1; i
< ud
.size
; i
++)
641 more
= utf8_append(&ud
, (u_char
)buf
[i
]);
642 if (more
!= UTF8_DONE
)
645 if (utf8_from_data(&ud
, &uc
) != UTF8_DONE
)
649 log_debug("%s: UTF-8 key %.*s %#llx", c
->name
, (int)ud
.size
,
657 /* Process window size change escape sequences. */
659 tty_keys_winsz(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
661 struct client
*c
= tty
->client
;
664 u_int sx
, sy
, xpixel
, ypixel
, char_x
, char_y
;
668 /* If we did not request this, ignore it. */
669 if (!(tty
->flags
& TTY_WINSIZEQUERY
))
672 /* First two bytes are always \033[. */
673 if (buf
[0] != '\033')
683 * Stop at either 't' or anything that isn't a
686 for (end
= 2; end
< len
&& end
!= sizeof tmp
; end
++) {
689 if (!isdigit((u_char
)buf
[end
]) && buf
[end
] != ';')
694 if (end
== sizeof tmp
|| buf
[end
] != 't')
697 /* Copy to the buffer. */
698 memcpy(tmp
, buf
+ 2, end
- 2);
701 /* Try to parse the window size sequence. */
702 if (sscanf(tmp
, "8;%u;%u", &sy
, &sx
) == 2) {
703 /* Window size in characters. */
704 tty_set_size(tty
, sx
, sy
, tty
->xpixel
, tty
->ypixel
);
708 } else if (sscanf(tmp
, "4;%u;%u", &ypixel
, &xpixel
) == 2) {
709 /* Window size in pixels. */
710 char_x
= (xpixel
&& tty
->sx
) ? xpixel
/ tty
->sx
: 0;
711 char_y
= (ypixel
&& tty
->sy
) ? ypixel
/ tty
->sy
: 0;
712 tty_set_size(tty
, tty
->sx
, tty
->sy
, char_x
, char_y
);
715 tty
->flags
&= ~TTY_WINSIZEQUERY
;
720 log_debug("%s: unrecognized window size sequence: %s", c
->name
, tmp
);
725 /* Process at least one key in the buffer. Return 0 if no keys present. */
727 tty_keys_next(struct tty
*tty
)
729 struct client
*c
= tty
->client
;
734 int delay
, expired
= 0, n
;
735 key_code key
, onlykey
;
736 struct mouse_event m
= { 0 };
737 struct key_event
*event
;
739 /* Get key buffer. */
740 buf
= EVBUFFER_DATA(tty
->in
);
741 len
= EVBUFFER_LENGTH(tty
->in
);
744 log_debug("%s: keys are %zu (%.*s)", c
->name
, len
, (int)len
, buf
);
746 /* Is this a clipboard response? */
747 switch (tty_keys_clipboard(tty
, buf
, len
, &size
)) {
751 case -1: /* no, or not valid */
753 case 1: /* partial */
757 /* Is this a primary device attributes response? */
758 switch (tty_keys_device_attributes(tty
, buf
, len
, &size
)) {
762 case -1: /* no, or not valid */
764 case 1: /* partial */
768 /* Is this a secondary device attributes response? */
769 switch (tty_keys_device_attributes2(tty
, buf
, len
, &size
)) {
773 case -1: /* no, or not valid */
775 case 1: /* partial */
779 /* Is this an extended device attributes response? */
780 switch (tty_keys_extended_device_attributes(tty
, buf
, len
, &size
)) {
784 case -1: /* no, or not valid */
786 case 1: /* partial */
790 /* Is this a colours response? */
791 switch (tty_keys_colours(tty
, buf
, len
, &size
, &tty
->fg
, &tty
->bg
)) {
795 case -1: /* no, or not valid */
797 case 1: /* partial */
801 /* Is this a mouse key press? */
802 switch (tty_keys_mouse(tty
, buf
, len
, &size
, &m
)) {
806 case -1: /* no, or not valid */
808 case -2: /* yes, but we don't care. */
811 case 1: /* partial */
815 /* Is this an extended key press? */
816 switch (tty_keys_extended_key(tty
, buf
, len
, &size
, &key
)) {
819 case -1: /* no, or not valid */
821 case 1: /* partial */
825 /* Check for window size query */
826 switch (tty_keys_winsz(tty
, buf
, len
, &size
)) {
830 case -1: /* no, or not valid */
832 case 1: /* partial */
837 /* Try to lookup complete key. */
838 n
= tty_keys_next1(tty
, buf
, len
, &key
, &size
, expired
);
839 if (n
== 0) /* found */
845 * If not a complete key, look for key with an escape prefix (meta
848 if (*buf
== '\033' && len
> 1) {
849 /* Look for a key without the escape. */
850 n
= tty_keys_next1(tty
, buf
+ 1, len
- 1, &key
, &size
, expired
);
851 if (n
== 0) { /* found */
852 if (key
& KEYC_IMPLIED_META
) {
854 * We want the escape key as well as the xterm
855 * key, because the xterm sequence implicitly
856 * includes the escape (so if we see
857 * \033\033[1;3D we know it is an Escape
858 * followed by M-Left, not just M-Left).
868 if (n
== 1) /* partial */
873 * At this point, we know the key is not partial (with or without
874 * escape). So pass it through even if the timer has not expired.
876 if (*buf
== '\033' && len
>= 2) {
877 key
= (u_char
)buf
[1] | KEYC_META
;
880 key
= (u_char
)buf
[0];
884 /* C-Space is special. */
885 if ((key
& KEYC_MASK_KEY
) == C0_NUL
)
886 key
= ' ' | KEYC_CTRL
| (key
& KEYC_META
);
889 * Fix up all C0 control codes that don't have a dedicated key into
890 * corresponding Ctrl keys. Convert characters in the A-Z range into
891 * lowercase, so ^A becomes a|CTRL.
893 onlykey
= key
& KEYC_MASK_KEY
;
894 if (onlykey
< 0x20 &&
899 if (onlykey
>= 'A' && onlykey
<= 'Z')
901 key
= onlykey
| KEYC_CTRL
| (key
& KEYC_META
);
907 log_debug("%s: partial key %.*s", c
->name
, (int)len
, buf
);
909 /* If timer is going, check for expiration. */
910 if (tty
->flags
& TTY_TIMER
) {
911 if (evtimer_initialized(&tty
->key_timer
) &&
912 !evtimer_pending(&tty
->key_timer
, NULL
)) {
919 /* Get the time period. */
920 delay
= options_get_number(global_options
, "escape-time");
923 tv
.tv_sec
= delay
/ 1000;
924 tv
.tv_usec
= (delay
% 1000) * 1000L;
926 /* Start the timer. */
927 if (event_initialized(&tty
->key_timer
))
928 evtimer_del(&tty
->key_timer
);
929 evtimer_set(&tty
->key_timer
, tty_keys_callback
, tty
);
930 evtimer_add(&tty
->key_timer
, &tv
);
932 tty
->flags
|= TTY_TIMER
;
936 log_debug("%s: complete key %.*s %#llx", c
->name
, (int)size
, buf
, key
);
939 * Check for backspace key using termios VERASE - the terminfo
940 * kbs entry is extremely unreliable, so cannot be safely
941 * used. termios should have a better idea.
943 bspace
= tty
->tio
.c_cc
[VERASE
];
944 if (bspace
!= _POSIX_VDISABLE
&& (key
& KEYC_MASK_KEY
) == bspace
)
945 key
= (key
& KEYC_MASK_MODIFIERS
)|KEYC_BSPACE
;
947 /* Remove key timer. */
948 if (event_initialized(&tty
->key_timer
))
949 evtimer_del(&tty
->key_timer
);
950 tty
->flags
&= ~TTY_TIMER
;
952 /* Check for focus events. */
953 if (key
== KEYC_FOCUS_OUT
) {
954 c
->flags
&= ~CLIENT_FOCUSED
;
955 window_update_focus(c
->session
->curw
->window
);
956 notify_client("client-focus-out", c
);
957 } else if (key
== KEYC_FOCUS_IN
) {
958 c
->flags
|= CLIENT_FOCUSED
;
959 notify_client("client-focus-in", c
);
960 window_update_focus(c
->session
->curw
->window
);
964 if (key
!= KEYC_UNKNOWN
) {
965 event
= xcalloc(1, sizeof *event
);
967 memcpy(&event
->m
, &m
, sizeof event
->m
);
969 event
->buf
= xmalloc(size
);
971 memcpy (event
->buf
, buf
, event
->len
);
973 if (!server_client_handle_key(c
, event
)) {
979 /* Remove data from buffer. */
980 evbuffer_drain(tty
->in
, size
);
985 log_debug("%s: discard key %.*s %#llx", c
->name
, (int)size
, buf
, key
);
987 /* Remove data from buffer. */
988 evbuffer_drain(tty
->in
, size
);
993 /* Key timer callback. */
995 tty_keys_callback(__unused
int fd
, __unused
short events
, void *data
)
997 struct tty
*tty
= data
;
999 if (tty
->flags
& TTY_TIMER
) {
1000 while (tty_keys_next(tty
))
1006 * Handle extended key input. This has two forms: \033[27;m;k~ and \033[k;mu,
1007 * where k is key as a number and m is a modifier. Returns 0 for success, -1
1008 * for failure, 1 for partial;
1011 tty_keys_extended_key(struct tty
*tty
, const char *buf
, size_t len
,
1012 size_t *size
, key_code
*key
)
1014 struct client
*c
= tty
->client
;
1016 u_int number
, modifiers
;
1020 struct utf8_data ud
;
1025 /* First two bytes are always \033[. */
1026 if (buf
[0] != '\033')
1036 * Look for a terminator. Stop at either '~' or anything that isn't a
1039 for (end
= 2; end
< len
&& end
!= sizeof tmp
; end
++) {
1040 if (buf
[end
] == '~')
1042 if (!isdigit((u_char
)buf
[end
]) && buf
[end
] != ';')
1047 if (end
== sizeof tmp
|| (buf
[end
] != '~' && buf
[end
] != 'u'))
1050 /* Copy to the buffer. */
1051 memcpy(tmp
, buf
+ 2, end
);
1054 /* Try to parse either form of key. */
1055 if (buf
[end
] == '~') {
1056 if (sscanf(tmp
, "27;%u;%u", &modifiers
, &number
) != 2)
1059 if (sscanf(tmp
,"%u;%u", &number
, &modifiers
) != 2)
1064 /* Store the key. */
1065 bspace
= tty
->tio
.c_cc
[VERASE
];
1066 if (bspace
!= _POSIX_VDISABLE
&& number
== bspace
)
1071 /* Convert UTF-32 codepoint into internal representation. */
1073 if (utf8_fromwc(nkey
, &ud
) == UTF8_DONE
&&
1074 utf8_from_data(&ud
, &uc
) == UTF8_DONE
)
1080 /* Update the modifiers. */
1081 if (modifiers
> 0) {
1084 * The Shift modifier may not be reported in some input modes,
1085 * which is unfortunate, as in general case determining if a
1086 * character is shifted or not requires knowing the input
1087 * keyboard layout. So we only fix up the trivial case.
1089 if (modifiers
& 1 || (nkey
>= 'A' && nkey
<= 'Z'))
1092 nkey
|= (KEYC_META
|KEYC_IMPLIED_META
); /* Alt */
1096 nkey
|= (KEYC_META
|KEYC_IMPLIED_META
); /* Meta */
1099 /* Convert S-Tab into Backtab. */
1100 if ((nkey
& KEYC_MASK_KEY
) == '\011' && (nkey
& KEYC_SHIFT
))
1101 nkey
= KEYC_BTAB
| (nkey
& ~KEYC_MASK_KEY
& ~KEYC_SHIFT
);
1103 if (log_get_level() != 0) {
1104 log_debug("%s: extended key %.*s is %llx (%s)", c
->name
,
1105 (int)*size
, buf
, nkey
, key_string_lookup_key(nkey
, 1));
1113 * Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
1114 * (probably a mouse sequence but need more data), -2 if an invalid mouse
1118 tty_keys_mouse(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
,
1119 struct mouse_event
*m
)
1121 struct client
*c
= tty
->client
;
1122 u_int i
, x
, y
, b
, sgr_b
;
1123 u_char sgr_type
, ch
;
1126 * Standard mouse sequences are \033[M followed by three characters
1127 * indicating button, X and Y, all based at 32 with 1,1 top-left.
1129 * UTF-8 mouse sequences are similar but the three are expressed as
1132 * SGR extended mouse sequences are \033[< followed by three numbers in
1133 * decimal and separated by semicolons indicating button, X and Y. A
1134 * trailing 'M' is click or scroll and trailing 'm' release. All are
1135 * based at 0 with 1,1 top-left.
1139 x
= y
= b
= sgr_b
= 0;
1142 /* First two bytes are always \033[. */
1143 if (buf
[0] != '\033')
1153 * Third byte is M in old standard (and UTF-8 extension which we do not
1154 * support), < in SGR extension.
1156 if (buf
[2] == 'M') {
1157 /* Read the three inputs. */
1159 for (i
= 0; i
< 3; i
++) {
1162 ch
= (u_char
)buf
[(*size
)++];
1170 log_debug("%s: mouse input: %.*s", c
->name
, (int)*size
, buf
);
1172 /* Check and return the mouse input. */
1173 if (b
< MOUSE_PARAM_BTN_OFF
||
1174 x
< MOUSE_PARAM_POS_OFF
||
1175 y
< MOUSE_PARAM_POS_OFF
)
1177 b
-= MOUSE_PARAM_BTN_OFF
;
1178 x
-= MOUSE_PARAM_POS_OFF
;
1179 y
-= MOUSE_PARAM_POS_OFF
;
1180 } else if (buf
[2] == '<') {
1181 /* Read the three inputs. */
1186 ch
= (u_char
)buf
[(*size
)++];
1189 if (ch
< '0' || ch
> '9')
1191 sgr_b
= 10 * sgr_b
+ (ch
- '0');
1196 ch
= (u_char
)buf
[(*size
)++];
1199 if (ch
< '0' || ch
> '9')
1201 x
= 10 * x
+ (ch
- '0');
1206 ch
= (u_char
)buf
[(*size
)++];
1207 if (ch
== 'M' || ch
== 'm')
1209 if (ch
< '0' || ch
> '9')
1211 y
= 10 * y
+ (ch
- '0');
1213 log_debug("%s: mouse input (SGR): %.*s", c
->name
, (int)*size
,
1216 /* Check and return the mouse input. */
1223 /* Type is M for press, m for release. */
1225 if (sgr_type
== 'm')
1229 * Some terminals (like PuTTY 0.63) mistakenly send
1230 * button-release events for scroll-wheel button-press event.
1231 * Discard it before it reaches any program running inside
1234 if (sgr_type
== 'm' && MOUSE_WHEEL(sgr_b
))
1239 /* Fill mouse event. */
1240 m
->lx
= tty
->mouse_last_x
;
1242 m
->ly
= tty
->mouse_last_y
;
1244 m
->lb
= tty
->mouse_last_b
;
1246 m
->sgr_type
= sgr_type
;
1249 /* Update last mouse state. */
1250 tty
->mouse_last_x
= x
;
1251 tty
->mouse_last_y
= y
;
1252 tty
->mouse_last_b
= b
;
1258 * Handle OSC 52 clipboard input. Returns 0 for success, -1 for failure, 1 for
1262 tty_keys_clipboard(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
)
1264 struct client
*c
= tty
->client
;
1265 struct window_pane
*wp
;
1266 size_t end
, terminator
= 0, needed
;
1273 /* First five bytes are always \033]52;. */
1274 if (buf
[0] != '\033')
1295 /* Find the terminator if any. */
1296 for (end
= 5; end
< len
; end
++) {
1297 if (buf
[end
] == '\007') {
1301 if (end
> 5 && buf
[end
- 1] == '\033' && buf
[end
] == '\\') {
1310 /* Skip the initial part. */
1314 /* Adjust end so that it points to the start of the terminator. */
1315 end
-= terminator
- 1;
1317 /* Get the second argument. */
1318 while (end
!= 0 && *buf
!= ';') {
1322 if (end
== 0 || end
== 1)
1327 /* If we did not request this, ignore it. */
1328 if (~tty
->flags
& TTY_OSC52QUERY
)
1330 tty
->flags
&= ~TTY_OSC52QUERY
;
1331 evtimer_del(&tty
->clipboard_timer
);
1333 /* It has to be a string so copy it. */
1334 copy
= xmalloc(end
+ 1);
1335 memcpy(copy
, buf
, end
);
1338 /* Convert from base64. */
1339 needed
= (end
/ 4) * 3;
1340 out
= xmalloc(needed
);
1341 if ((outlen
= b64_pton(copy
, out
, len
)) == -1) {
1348 /* Create a new paste buffer and forward to panes. */
1349 log_debug("%s: %.*s", __func__
, outlen
, out
);
1350 if (c
->flags
& CLIENT_CLIPBOARDBUFFER
) {
1351 paste_add(NULL
, out
, outlen
);
1352 c
->flags
&= ~CLIENT_CLIPBOARDBUFFER
;
1354 for (i
= 0; i
< c
->clipboard_npanes
; i
++) {
1355 wp
= window_pane_find_by_id(c
->clipboard_panes
[i
]);
1357 input_reply_clipboard(wp
->event
, out
, outlen
, "\033\\");
1359 free(c
->clipboard_panes
);
1360 c
->clipboard_panes
= NULL
;
1361 c
->clipboard_npanes
= 0;
1367 * Handle primary device attributes input. Returns 0 for success, -1 for
1368 * failure, 1 for partial.
1371 tty_keys_device_attributes(struct tty
*tty
, const char *buf
, size_t len
,
1374 struct client
*c
= tty
->client
;
1375 int *features
= &c
->term_features
;
1377 char tmp
[128], *endptr
, p
[32] = { 0 }, *cp
, *next
;
1380 if (tty
->flags
& TTY_HAVEDA
)
1383 /* First three bytes are always \033[?. */
1384 if (buf
[0] != '\033')
1397 /* Copy the rest up to a c. */
1398 for (i
= 0; i
< (sizeof tmp
); i
++) {
1401 if (buf
[3 + i
] == 'c')
1403 tmp
[i
] = buf
[3 + i
];
1405 if (i
== (sizeof tmp
))
1410 /* Convert all arguments to numbers. */
1412 while ((next
= strsep(&cp
, ";")) != NULL
) {
1413 p
[n
] = strtoul(next
, &endptr
, 10);
1414 if (*endptr
!= '\0')
1416 if (++n
== nitems(p
))
1420 /* Add terminal features. */
1422 case 61: /* level 1 */
1423 case 62: /* level 2 */
1424 case 63: /* level 3 */
1425 case 64: /* level 4 */
1426 case 65: /* level 5 */
1427 for (i
= 1; i
< n
; i
++) {
1428 log_debug("%s: DA feature: %d", c
->name
, p
[i
]);
1430 tty_add_features(features
, "sixel", ",");
1432 tty_add_features(features
, "margins", ",");
1434 tty_add_features(features
, "rectfill", ",");
1438 log_debug("%s: received primary DA %.*s", c
->name
, (int)*size
, buf
);
1440 tty_update_features(tty
);
1441 tty
->flags
|= TTY_HAVEDA
;
1447 * Handle secondary device attributes input. Returns 0 for success, -1 for
1448 * failure, 1 for partial.
1451 tty_keys_device_attributes2(struct tty
*tty
, const char *buf
, size_t len
,
1454 struct client
*c
= tty
->client
;
1455 int *features
= &c
->term_features
;
1457 char tmp
[128], *endptr
, p
[32] = { 0 }, *cp
, *next
;
1460 if (tty
->flags
& TTY_HAVEDA2
)
1463 /* First three bytes are always \033[>. */
1464 if (buf
[0] != '\033')
1477 /* Copy the rest up to a c. */
1478 for (i
= 0; i
< (sizeof tmp
); i
++) {
1481 if (buf
[3 + i
] == 'c')
1483 tmp
[i
] = buf
[3 + i
];
1485 if (i
== (sizeof tmp
))
1490 /* Convert all arguments to numbers. */
1492 while ((next
= strsep(&cp
, ";")) != NULL
) {
1493 p
[n
] = strtoul(next
, &endptr
, 10);
1494 if (*endptr
!= '\0')
1496 if (++n
== nitems(p
))
1501 * Add terminal features. We add DECSLRM and DECFRA for some
1502 * identification codes here, notably 64 will catch VT520, even though
1503 * we can't use level 5 from DA because of VTE.
1506 case 'M': /* mintty */
1507 tty_default_features(features
, "mintty", 0);
1509 case 'T': /* tmux */
1510 tty_default_features(features
, "tmux", 0);
1512 case 'U': /* rxvt-unicode */
1513 tty_default_features(features
, "rxvt-unicode", 0);
1516 log_debug("%s: received secondary DA %.*s", c
->name
, (int)*size
, buf
);
1518 tty_update_features(tty
);
1519 tty
->flags
|= TTY_HAVEDA2
;
1525 * Handle extended device attributes input. Returns 0 for success, -1 for
1526 * failure, 1 for partial.
1529 tty_keys_extended_device_attributes(struct tty
*tty
, const char *buf
,
1530 size_t len
, size_t *size
)
1532 struct client
*c
= tty
->client
;
1533 int *features
= &c
->term_features
;
1538 if (tty
->flags
& TTY_HAVEXDA
)
1541 /* First four bytes are always \033P>|. */
1542 if (buf
[0] != '\033')
1559 /* Copy the rest up to \033\. */
1560 for (i
= 0; i
< (sizeof tmp
) - 1; i
++) {
1563 if (buf
[4 + i
- 1] == '\033' && buf
[4 + i
] == '\\')
1565 tmp
[i
] = buf
[4 + i
];
1567 if (i
== (sizeof tmp
) - 1)
1572 /* Add terminal features. */
1573 if (strncmp(tmp
, "iTerm2 ", 7) == 0)
1574 tty_default_features(features
, "iTerm2", 0);
1575 else if (strncmp(tmp
, "tmux ", 5) == 0)
1576 tty_default_features(features
, "tmux", 0);
1577 else if (strncmp(tmp
, "XTerm(", 6) == 0)
1578 tty_default_features(features
, "XTerm", 0);
1579 else if (strncmp(tmp
, "mintty ", 7) == 0)
1580 tty_default_features(features
, "mintty", 0);
1581 log_debug("%s: received extended DA %.*s", c
->name
, (int)*size
, buf
);
1584 c
->term_type
= xstrdup(tmp
);
1586 tty_update_features(tty
);
1587 tty
->flags
|= TTY_HAVEXDA
;
1593 * Handle foreground or background input. Returns 0 for success, -1 for
1594 * failure, 1 for partial.
1597 tty_keys_colours(struct tty
*tty
, const char *buf
, size_t len
, size_t *size
,
1600 struct client
*c
= tty
->client
;
1607 /* First four bytes are always \033]1 and 0 or 1 and ;. */
1608 if (buf
[0] != '\033')
1620 if (buf
[3] != '0' && buf
[3] != '1')
1629 /* Copy the rest up to \033\ or \007. */
1630 for (i
= 0; i
< (sizeof tmp
) - 1; i
++) {
1633 if (buf
[5 + i
- 1] == '\033' && buf
[5 + i
] == '\\')
1635 if (buf
[5 + i
] == '\007')
1637 tmp
[i
] = buf
[5 + i
];
1639 if (i
== (sizeof tmp
) - 1)
1641 if (tmp
[i
- 1] == '\033')
1647 n
= colour_parseX11(tmp
);
1648 if (n
!= -1 && buf
[3] == '0') {
1650 log_debug("%s fg is %s", c
->name
, colour_tostring(n
));
1652 log_debug("fg is %s", colour_tostring(n
));
1654 } else if (n
!= -1) {
1656 log_debug("%s bg is %s", c
->name
, colour_tostring(n
));
1658 log_debug("bg is %s", colour_tostring(n
));