xref: /netbsd-src/external/bsd/tmux/dist/input-keys.c (revision 890b6d91a44b7fcb2dfbcbc1e93463086e462d2d)
1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "tmux.h"
25 
26 /*
27  * This file is rather misleadingly named, it contains the code which takes a
28  * key code and translates it into something suitable to be sent to the
29  * application running in a pane (similar to input.c does in the other
30  * direction with output).
31  */
32 
33 static void	 input_key_mouse(struct window_pane *, struct mouse_event *);
34 
35 /* Entry in the key tree. */
36 struct input_key_entry {
37 	key_code			 key;
38 	const char			*data;
39 
40 	RB_ENTRY(input_key_entry)	 entry;
41 };
42 RB_HEAD(input_key_tree, input_key_entry);
43 
44 /* Tree of input keys. */
45 static int	input_key_cmp(struct input_key_entry *,
46 		    struct input_key_entry *);
47 RB_GENERATE_STATIC(input_key_tree, input_key_entry, entry, input_key_cmp);
48 struct input_key_tree input_key_tree = RB_INITIALIZER(&input_key_tree);
49 
50 /* List of default keys, the tree is built from this. */
51 static struct input_key_entry input_key_defaults[] = {
52 	/* Paste keys. */
53 	{ .key = KEYC_PASTE_START,
54 	  .data = "\033[200~"
55 	},
56 	{ .key = KEYC_PASTE_END,
57 	  .data = "\033[201~"
58 	},
59 
60 	/* Function keys. */
61 	{ .key = KEYC_F1,
62 	  .data = "\033OP"
63 	},
64 	{ .key = KEYC_F2,
65 	  .data = "\033OQ"
66 	},
67 	{ .key = KEYC_F3,
68 	  .data = "\033OR"
69 	},
70 	{ .key = KEYC_F4,
71 	  .data = "\033OS"
72 	},
73 	{ .key = KEYC_F5,
74 	  .data = "\033[15~"
75 	},
76 	{ .key = KEYC_F6,
77 	  .data = "\033[17~"
78 	},
79 	{ .key = KEYC_F7,
80 	  .data = "\033[18~"
81 	},
82 	{ .key = KEYC_F8,
83 	  .data = "\033[19~"
84 	},
85 	{ .key = KEYC_F9,
86 	  .data = "\033[20~"
87 	},
88 	{ .key = KEYC_F10,
89 	  .data = "\033[21~"
90 	},
91 	{ .key = KEYC_F11,
92 	  .data = "\033[23~"
93 	},
94 	{ .key = KEYC_F12,
95 	  .data = "\033[24~"
96 	},
97 	{ .key = KEYC_IC,
98 	  .data = "\033[2~"
99 	},
100 	{ .key = KEYC_DC,
101 	  .data = "\033[3~"
102 	},
103 	{ .key = KEYC_HOME,
104 	  .data = "\033[1~"
105 	},
106 	{ .key = KEYC_END,
107 	  .data = "\033[4~"
108 	},
109 	{ .key = KEYC_NPAGE,
110 	  .data = "\033[6~"
111 	},
112 	{ .key = KEYC_PPAGE,
113 	  .data = "\033[5~"
114 	},
115 	{ .key = KEYC_BTAB,
116 	  .data = "\033[Z"
117 	},
118 
119 	/* Arrow keys. */
120 	{ .key = KEYC_UP|KEYC_CURSOR,
121 	  .data = "\033OA"
122 	},
123 	{ .key = KEYC_DOWN|KEYC_CURSOR,
124 	  .data = "\033OB"
125 	},
126 	{ .key = KEYC_RIGHT|KEYC_CURSOR,
127 	  .data = "\033OC"
128 	},
129 	{ .key = KEYC_LEFT|KEYC_CURSOR,
130 	  .data = "\033OD"
131 	},
132 	{ .key = KEYC_UP,
133 	  .data = "\033[A"
134 	},
135 	{ .key = KEYC_DOWN,
136 	  .data = "\033[B"
137 	},
138 	{ .key = KEYC_RIGHT,
139 	  .data = "\033[C"
140 	},
141 	{ .key = KEYC_LEFT,
142 	  .data = "\033[D"
143 	},
144 
145 	/* Keypad keys. */
146 	{ .key = KEYC_KP_SLASH|KEYC_KEYPAD,
147 	  .data = "\033Oo"
148 	},
149 	{ .key = KEYC_KP_STAR|KEYC_KEYPAD,
150 	  .data = "\033Oj"
151 	},
152 	{ .key = KEYC_KP_MINUS|KEYC_KEYPAD,
153 	  .data = "\033Om"
154 	},
155 	{ .key = KEYC_KP_SEVEN|KEYC_KEYPAD,
156 	  .data = "\033Ow"
157 	},
158 	{ .key = KEYC_KP_EIGHT|KEYC_KEYPAD,
159 	  .data = "\033Ox"
160 	},
161 	{ .key = KEYC_KP_NINE|KEYC_KEYPAD,
162 	  .data = "\033Oy"
163 	},
164 	{ .key = KEYC_KP_PLUS|KEYC_KEYPAD,
165 	  .data = "\033Ok"
166 	},
167 	{ .key = KEYC_KP_FOUR|KEYC_KEYPAD,
168 	  .data = "\033Ot"
169 	},
170 	{ .key = KEYC_KP_FIVE|KEYC_KEYPAD,
171 	  .data = "\033Ou"
172 	},
173 	{ .key = KEYC_KP_SIX|KEYC_KEYPAD,
174 	  .data = "\033Ov"
175 	},
176 	{ .key = KEYC_KP_ONE|KEYC_KEYPAD,
177 	  .data = "\033Oq"
178 	},
179 	{ .key = KEYC_KP_TWO|KEYC_KEYPAD,
180 	  .data = "\033Or"
181 	},
182 	{ .key = KEYC_KP_THREE|KEYC_KEYPAD,
183 	  .data = "\033Os"
184 	},
185 	{ .key = KEYC_KP_ENTER|KEYC_KEYPAD,
186 	  .data = "\033OM"
187 	},
188 	{ .key = KEYC_KP_ZERO|KEYC_KEYPAD,
189 	  .data = "\033Op"
190 	},
191 	{ .key = KEYC_KP_PERIOD|KEYC_KEYPAD,
192 	  .data = "\033On"
193 	},
194 	{ .key = KEYC_KP_SLASH,
195 	  .data = "/"
196 	},
197 	{ .key = KEYC_KP_STAR,
198 	  .data = "*"
199 	},
200 	{ .key = KEYC_KP_MINUS,
201 	  .data = "-"
202 	},
203 	{ .key = KEYC_KP_SEVEN,
204 	  .data = "7"
205 	},
206 	{ .key = KEYC_KP_EIGHT,
207 	  .data = "8"
208 	},
209 	{ .key = KEYC_KP_NINE,
210 	  .data = "9"
211 	},
212 	{ .key = KEYC_KP_PLUS,
213 	  .data = "+"
214 	},
215 	{ .key = KEYC_KP_FOUR,
216 	  .data = "4"
217 	},
218 	{ .key = KEYC_KP_FIVE,
219 	  .data = "5"
220 	},
221 	{ .key = KEYC_KP_SIX,
222 	  .data = "6"
223 	},
224 	{ .key = KEYC_KP_ONE,
225 	  .data = "1"
226 	},
227 	{ .key = KEYC_KP_TWO,
228 	  .data = "2"
229 	},
230 	{ .key = KEYC_KP_THREE,
231 	  .data = "3"
232 	},
233 	{ .key = KEYC_KP_ENTER,
234 	  .data = "\n"
235 	},
236 	{ .key = KEYC_KP_ZERO,
237 	  .data = "0"
238 	},
239 	{ .key = KEYC_KP_PERIOD,
240 	  .data = "."
241 	},
242 
243 	/* Keys with an embedded modifier. */
244 	{ .key = KEYC_F1|KEYC_BUILD_MODIFIERS,
245 	  .data = "\033[1;_P"
246 	},
247 	{ .key = KEYC_F2|KEYC_BUILD_MODIFIERS,
248 	  .data = "\033[1;_Q"
249 	},
250 	{ .key = KEYC_F3|KEYC_BUILD_MODIFIERS,
251 	  .data = "\033[1;_R"
252 	},
253 	{ .key = KEYC_F4|KEYC_BUILD_MODIFIERS,
254 	  .data = "\033[1;_S"
255 	},
256 	{ .key = KEYC_F5|KEYC_BUILD_MODIFIERS,
257 	  .data = "\033[15;_~"
258 	},
259 	{ .key = KEYC_F6|KEYC_BUILD_MODIFIERS,
260 	  .data = "\033[17;_~"
261 	},
262 	{ .key = KEYC_F7|KEYC_BUILD_MODIFIERS,
263 	  .data = "\033[18;_~"
264 	},
265 	{ .key = KEYC_F8|KEYC_BUILD_MODIFIERS,
266 	  .data = "\033[19;_~"
267 	},
268 	{ .key = KEYC_F9|KEYC_BUILD_MODIFIERS,
269 	  .data = "\033[20;_~"
270 	},
271 	{ .key = KEYC_F10|KEYC_BUILD_MODIFIERS,
272 	  .data = "\033[21;_~"
273 	},
274 	{ .key = KEYC_F11|KEYC_BUILD_MODIFIERS,
275 	  .data = "\033[23;_~"
276 	},
277 	{ .key = KEYC_F12|KEYC_BUILD_MODIFIERS,
278 	  .data = "\033[24;_~"
279 	},
280 	{ .key = KEYC_UP|KEYC_BUILD_MODIFIERS,
281 	  .data = "\033[1;_A"
282 	},
283 	{ .key = KEYC_DOWN|KEYC_BUILD_MODIFIERS,
284 	  .data = "\033[1;_B"
285 	},
286 	{ .key = KEYC_RIGHT|KEYC_BUILD_MODIFIERS,
287 	  .data = "\033[1;_C"
288 	},
289 	{ .key = KEYC_LEFT|KEYC_BUILD_MODIFIERS,
290 	  .data = "\033[1;_D"
291 	},
292 	{ .key = KEYC_HOME|KEYC_BUILD_MODIFIERS,
293 	  .data = "\033[1;_H"
294 	},
295 	{ .key = KEYC_END|KEYC_BUILD_MODIFIERS,
296 	  .data = "\033[1;_F"
297 	},
298 	{ .key = KEYC_PPAGE|KEYC_BUILD_MODIFIERS,
299 	  .data = "\033[5;_~"
300 	},
301 	{ .key = KEYC_NPAGE|KEYC_BUILD_MODIFIERS,
302 	  .data = "\033[6;_~"
303 	},
304 	{ .key = KEYC_IC|KEYC_BUILD_MODIFIERS,
305 	  .data = "\033[2;_~"
306 	},
307 	{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
308 	  .data = "\033[3;_~"
309 	},
310 };
311 static const key_code input_key_modifiers[] = {
312 	0,
313 	0,
314 	KEYC_SHIFT,
315 	KEYC_META|KEYC_IMPLIED_META,
316 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META,
317 	KEYC_CTRL,
318 	KEYC_SHIFT|KEYC_CTRL,
319 	KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
320 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL
321 };
322 
323 /* Input key comparison function. */
324 static int
325 input_key_cmp(struct input_key_entry *ike1, struct input_key_entry *ike2)
326 {
327 	if (ike1->key < ike2->key)
328 		return (-1);
329 	if (ike1->key > ike2->key)
330 		return (1);
331 	return (0);
332 }
333 
334 /* Look for key in tree. */
335 static struct input_key_entry *
336 input_key_get(key_code key)
337 {
338 	struct input_key_entry	entry = { .key = key };
339 
340 	return (RB_FIND(input_key_tree, &input_key_tree, &entry));
341 }
342 
343 /* Split a character into two UTF-8 bytes. */
344 static size_t
345 input_key_split2(u_int c, char *dst)
346 {
347 	if (c > 0x7f) {
348 		dst[0] = (c >> 6) | 0xc0;
349 		dst[1] = (c & 0x3f) | 0x80;
350 		return (2);
351 	}
352 	dst[0] = c;
353 	return (1);
354 }
355 
356 /* Build input key tree. */
357 void
358 input_key_build(void)
359 {
360 	struct input_key_entry	*ike, *new;
361 	u_int			 i, j;
362 	char			*data;
363 	key_code		 key;
364 
365 	for (i = 0; i < nitems(input_key_defaults); i++) {
366 		ike = &input_key_defaults[i];
367 		if (~ike->key & KEYC_BUILD_MODIFIERS) {
368 			RB_INSERT(input_key_tree, &input_key_tree, ike);
369 			continue;
370 		}
371 
372 		for (j = 2; j < nitems(input_key_modifiers); j++) {
373 			key = (ike->key & ~KEYC_BUILD_MODIFIERS);
374 			data = xstrdup(ike->data);
375 			data[strcspn(data, "_")] = '0' + j;
376 
377 			new = xcalloc(1, sizeof *new);
378 			new->key = key|input_key_modifiers[j];
379 			new->data = data;
380 			RB_INSERT(input_key_tree, &input_key_tree, new);
381 		}
382 	}
383 
384 	RB_FOREACH(ike, input_key_tree, &input_key_tree) {
385 		log_debug("%s: 0x%llx (%s) is %s", __func__, ike->key,
386 		    key_string_lookup_key(ike->key, 1), ike->data);
387 	}
388 }
389 
390 /* Translate a key code into an output key sequence for a pane. */
391 int
392 input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
393 {
394 	if (log_get_level() != 0) {
395 		log_debug("writing key 0x%llx (%s) to %%%u", key,
396 		    key_string_lookup_key(key, 1), wp->id);
397 	}
398 
399 	if (KEYC_IS_MOUSE(key)) {
400 		if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
401 			input_key_mouse(wp, m);
402 		return (0);
403 	}
404 	return (input_key(wp->screen, wp->event, key));
405 }
406 
407 static void
408 input_key_write(const char *from, struct bufferevent *bev, const char *data,
409     size_t size)
410 {
411 	log_debug("%s: %.*s", from, (int)size, (const char *)data);
412 	bufferevent_write(bev, data, size);
413 }
414 
415 /*
416  * Encode and write an extended key escape sequence in one of the two
417  * possible formats, depending on the configured output mode.
418  */
419 static int
420 input_key_extended(struct bufferevent *bev, key_code key)
421 {
422 	char		 tmp[64], modifier;
423 	struct utf8_data ud;
424 	wchar_t		 wc;
425 
426 	switch (key & KEYC_MASK_MODIFIERS) {
427 	case KEYC_SHIFT:
428 		modifier = '2';
429 		break;
430 	case KEYC_META:
431 		modifier = '3';
432 		break;
433 	case KEYC_SHIFT|KEYC_META:
434 		modifier = '4';
435 		break;
436 	case KEYC_CTRL:
437 		modifier = '5';
438 		break;
439 	case KEYC_SHIFT|KEYC_CTRL:
440 		modifier = '6';
441 		break;
442 	case KEYC_META|KEYC_CTRL:
443 		modifier = '7';
444 		break;
445 	case KEYC_SHIFT|KEYC_META|KEYC_CTRL:
446 		modifier = '8';
447 		break;
448 	default:
449 		return (-1);
450 	}
451 
452 	if (KEYC_IS_UNICODE(key)) {
453 		utf8_to_data(key & KEYC_MASK_KEY, &ud);
454 		if (utf8_towc(&ud, &wc) == UTF8_DONE)
455 			key = wc;
456 		else
457 			return (-1);
458 	} else
459 		key &= KEYC_MASK_KEY;
460 
461 	if (options_get_number(global_options, "extended-keys-format") == 1)
462 		xsnprintf(tmp, sizeof tmp, "\033[27;%c;%llu~", modifier, key);
463 	else
464 		xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", key, modifier);
465 
466 	input_key_write(__func__, bev, tmp, strlen(tmp));
467 	return (0);
468 }
469 
470 /*
471  * Outputs the key in the "standard" mode. This is by far the most
472  * complicated output mode, with a lot of remapping in order to
473  * emulate quirks of terminals that today can be only found in museums.
474  */
475 static int
476 input_key_vt10x(struct bufferevent *bev, key_code key)
477 {
478 	struct utf8_data	 ud;
479 	key_code		 onlykey;
480 	char			*p;
481 	static const char	*standard_map[2] = {
482 		"1!9(0)=+;:'\",<.>/-8? 2",
483 		"119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0",
484 	};
485 
486 	log_debug("%s: key in %llx", __func__, key);
487 
488 	if (key & KEYC_META)
489 		input_key_write(__func__, bev, "\033", 1);
490 
491 	/*
492 	 * There's no way to report modifiers for unicode keys in standard mode
493 	 * so lose the modifiers.
494 	 */
495 	if (KEYC_IS_UNICODE(key)) {
496 		utf8_to_data(key, &ud);
497                 input_key_write(__func__, bev, (const char *)ud.data, ud.size);
498 		return (0);
499 	}
500 
501 	/* Prevent TAB and RET from being swallowed by C0 remapping logic. */
502 	onlykey = key & KEYC_MASK_KEY;
503 	if (onlykey == '\r' || onlykey == '\t')
504 		key &= ~KEYC_CTRL;
505 
506 	/*
507 	 * Convert keys with Ctrl modifier into corresponding C0 control codes,
508 	 * with the exception of *some* keys, which are remapped into printable
509 	 * ASCII characters.
510 	 *
511 	 * There is no special handling for Shift modifier, which is pretty
512 	 * much redundant anyway, as no terminal will send <base key>|SHIFT,
513 	 * but only <shifted key>|SHIFT.
514 	 */
515 	if (key & KEYC_CTRL) {
516 		p = strchr(standard_map[0], onlykey);
517 		if (p != NULL)
518 			key = standard_map[1][p - standard_map[0]];
519 		else if (onlykey >= '3' && onlykey <= '7')
520 			key = onlykey - '\030';
521 		else if (onlykey >= '@' && onlykey <= '~')
522 			key = onlykey & 0x1f;
523 		else
524 			return (-1);
525 	}
526 
527 	log_debug("%s: key out %llx", __func__, key);
528 
529 	ud.data[0] = key & 0x7f;
530 	input_key_write(__func__, bev, (const char *)&ud.data[0], 1);
531 	return (0);
532 }
533 
534 /* Pick keys that are reported as vt10x keys in modifyOtherKeys=1 mode. */
535 static int
536 input_key_mode1(struct bufferevent *bev, key_code key)
537 {
538 	key_code	 onlykey;
539 
540 	log_debug("%s: key in %llx", __func__, key);
541 
542 	/*
543 	 * As per
544 	 * https://invisible-island.net/xterm/modified-keys-us-pc105.html.
545 	 */
546 	onlykey = key & KEYC_MASK_KEY;
547 	if ((key & (KEYC_META | KEYC_CTRL)) == KEYC_CTRL &&
548 	    (onlykey == ' ' ||
549 	     onlykey == '/' ||
550 	     onlykey == '@' ||
551 	     onlykey == '^' ||
552 	     (onlykey >= '2' && onlykey <= '8') ||
553 	     (onlykey >= '@' && onlykey <= '~')))
554 		return (input_key_vt10x(bev, key));
555 
556 	/*
557 	 * A regular key + Meta. In the absence of a standard to back this, we
558 	 * mimic what iTerm 2 does.
559 	 */
560 	if ((key & (KEYC_CTRL | KEYC_META)) == KEYC_META)
561 		return (input_key_vt10x(bev, key));
562 
563 	return (-1);
564 }
565 
566 /* Translate a key code into an output key sequence. */
567 int
568 input_key(struct screen *s, struct bufferevent *bev, key_code key)
569 {
570 	struct input_key_entry	*ike = NULL;
571 	key_code		 newkey;
572 	struct utf8_data	 ud;
573 
574 	/* Mouse keys need a pane. */
575 	if (KEYC_IS_MOUSE(key))
576 		return (0);
577 
578 	/* Literal keys go as themselves (can't be more than eight bits). */
579 	if (key & KEYC_LITERAL) {
580 		ud.data[0] = (u_char)key;
581 		input_key_write(__func__, bev, (const char *)ud.data, 1);
582 		return (0);
583 	}
584 
585 	/* Is this backspace? */
586 	if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
587 		newkey = options_get_number(global_options, "backspace");
588 		if (newkey >= 0x7f)
589 			newkey = '\177';
590 		key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS));
591 	}
592 
593 	/* Is this backtab? */
594 	if ((key & KEYC_MASK_KEY) == KEYC_BTAB) {
595 		if ((s->mode & EXTENDED_KEY_MODES) != 0) {
596 			/* When in xterm extended mode, remap into S-Tab. */
597 			key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT;
598 		} else {
599 			/* Otherwise clear modifiers. */
600 			key &= ~KEYC_MASK_MODIFIERS;
601 		}
602 	}
603 
604 	/*
605 	 * A trivial case, that is a 7-bit key, excluding C0 control characters
606 	 * that can't be entered from the keyboard, and no modifiers; or a UTF-8
607 	 * key and no modifiers.
608 	 */
609 	if (!(key & ~KEYC_MASK_KEY)) {
610 		if (key == C0_HT ||
611 		    key == C0_CR ||
612 		    key == C0_ESC ||
613 		    (key >= 0x20 && key <= 0x7f)) {
614 			ud.data[0] = key;
615 			input_key_write(__func__, bev, (const char *)&ud.data[0], 1);
616 			return (0);
617 		}
618 		if (KEYC_IS_UNICODE(key)) {
619 			utf8_to_data(key, &ud);
620 			input_key_write(__func__, bev, (const char *)ud.data, ud.size);
621 			return (0);
622 		}
623 	}
624 
625 	/*
626 	 * Look up the standard VT10x keys in the tree. If not in application
627 	 * keypad or cursor mode, remove the respective flags from the key.
628 	 */
629 	if (~s->mode & MODE_KKEYPAD)
630 		key &= ~KEYC_KEYPAD;
631 	if (~s->mode & MODE_KCURSOR)
632 		key &= ~KEYC_CURSOR;
633 	if (ike == NULL)
634 		ike = input_key_get(key);
635 	if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META))
636 		ike = input_key_get(key & ~KEYC_META);
637 	if (ike == NULL && (key & KEYC_CURSOR))
638 		ike = input_key_get(key & ~KEYC_CURSOR);
639 	if (ike == NULL && (key & KEYC_KEYPAD))
640 		ike = input_key_get(key & ~KEYC_KEYPAD);
641 	if (ike != NULL) {
642 		log_debug("%s: found key 0x%llx: \"%s\"", __func__, key,
643 		    ike->data);
644 		if ((key == KEYC_PASTE_START || key == KEYC_PASTE_END) &&
645 		    (~s->mode & MODE_BRACKETPASTE))
646 			return (0);
647 		if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
648 			input_key_write(__func__, bev, "\033", 1);
649 		input_key_write(__func__, bev, ike->data, strlen(ike->data));
650 		return (0);
651 	}
652 
653 	/* Ignore internal function key codes. */
654 	if ((key >= KEYC_BASE && key < KEYC_BASE_END) ||
655 	    (key >= KEYC_USER && key < KEYC_USER_END)) {
656 		log_debug("%s: ignoring key 0x%llx", __func__, key);
657 		return (0);
658 	}
659 
660 	/*
661 	 * No builtin key sequence; construct an extended key sequence
662 	 * depending on the client mode.
663 	 *
664 	 * If something invalid reaches here, an invalid output may be
665 	 * produced. For example Ctrl-Shift-2 is invalid (as there's
666 	 * no way to enter it). The correct form is Ctrl-Shift-@, at
667 	 * least in US English keyboard layout.
668 	 */
669 	switch (s->mode & EXTENDED_KEY_MODES) {
670 	case MODE_KEYS_EXTENDED_2:
671 		/*
672 		 * The simplest mode to handle - *all* modified keys are
673 		 * reported in the extended form.
674 		 */
675 		return (input_key_extended(bev, key));
676         case MODE_KEYS_EXTENDED:
677 		/*
678 		 * Some keys are still reported in standard mode, to maintain
679 		 * compatibility with applications unaware of extended keys.
680 		 */
681 		if (input_key_mode1(bev, key) == -1)
682 			return (input_key_extended(bev, key));
683 		return (0);
684 	default:
685 		/* The standard mode. */
686 		return (input_key_vt10x(bev, key));
687 	}
688 }
689 
690 /* Get mouse event string. */
691 int
692 input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
693     const char **rbuf, size_t *rlen)
694 {
695 	static char	 buf[40];
696 	size_t		 len;
697 
698 	*rbuf = NULL;
699 	*rlen = 0;
700 
701 	/* If this pane is not in button or all mode, discard motion events. */
702 	if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0)
703 		return (0);
704 	if ((s->mode & ALL_MOUSE_MODES) == 0)
705 		return (0);
706 
707 	/*
708 	 * If this event is a release event and not in all mode, discard it.
709 	 * In SGR mode we can tell absolutely because a release is normally
710 	 * shown by the last character. Without SGR, we check if the last
711 	 * buttons was also a release.
712 	 */
713 	if (m->sgr_type != ' ') {
714 		if (MOUSE_DRAG(m->sgr_b) &&
715 		    MOUSE_RELEASE(m->sgr_b) &&
716 		    (~s->mode & MODE_MOUSE_ALL))
717 			return (0);
718 	} else {
719 		if (MOUSE_DRAG(m->b) &&
720 		    MOUSE_RELEASE(m->b) &&
721 		    MOUSE_RELEASE(m->lb) &&
722 		    (~s->mode & MODE_MOUSE_ALL))
723 			return (0);
724 	}
725 
726 	/*
727 	 * Use the SGR (1006) extension only if the application requested it
728 	 * and the underlying terminal also sent the event in this format (this
729 	 * is because an old style mouse release event cannot be converted into
730 	 * the new SGR format, since the released button is unknown). Otherwise
731 	 * pretend that tmux doesn't speak this extension, and fall back to the
732 	 * UTF-8 (1005) extension if the application requested, or to the
733 	 * legacy format.
734 	 */
735 	if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
736 		len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
737 		    m->sgr_b, x + 1, y + 1, m->sgr_type);
738 	} else if (s->mode & MODE_MOUSE_UTF8) {
739 		if (m->b > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_BTN_OFF ||
740 		    x > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF ||
741 		    y > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF)
742 			return (0);
743 		len = xsnprintf(buf, sizeof buf, "\033[M");
744 		len += input_key_split2(m->b + MOUSE_PARAM_BTN_OFF, &buf[len]);
745 		len += input_key_split2(x + MOUSE_PARAM_POS_OFF, &buf[len]);
746 		len += input_key_split2(y + MOUSE_PARAM_POS_OFF, &buf[len]);
747 	} else {
748 		if (m->b + MOUSE_PARAM_BTN_OFF > MOUSE_PARAM_MAX)
749 			return (0);
750 
751 		len = xsnprintf(buf, sizeof buf, "\033[M");
752 		buf[len++] = m->b + MOUSE_PARAM_BTN_OFF;
753 
754 		/*
755 		 * The incoming x and y may be out of the range which can be
756 		 * supported by the "normal" mouse protocol. Clamp the
757 		 * coordinates to the supported range.
758 		 */
759 		if (x + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
760 			buf[len++] = MOUSE_PARAM_MAX;
761 		else
762 			buf[len++] = x + MOUSE_PARAM_POS_OFF;
763 		if (y + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
764 			buf[len++] = MOUSE_PARAM_MAX;
765 		else
766 			buf[len++] = y + MOUSE_PARAM_POS_OFF;
767 	}
768 
769 	*rbuf = buf;
770 	*rlen = len;
771 	return (1);
772 }
773 
774 /* Translate mouse and output. */
775 static void
776 input_key_mouse(struct window_pane *wp, struct mouse_event *m)
777 {
778 	struct screen	*s = wp->screen;
779 	u_int		 x, y;
780 	const char	*buf;
781 	size_t		 len;
782 
783 	/* Ignore events if no mouse mode or the pane is not visible. */
784 	if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0)
785 		return;
786 	if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
787 		return;
788 	if (!window_pane_visible(wp))
789 		return;
790 	if (!input_key_get_mouse(s, m, x, y, &buf, &len))
791 		return;
792 	log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
793 	input_key_write(__func__, wp->event, buf, len);
794 }
795