xref: /netbsd-src/external/bsd/tmux/dist/input-keys.c (revision 53d1339bf7f9c7367b35a9e1ebe693f9b047a47b)
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_F1|KEYC_SHIFT,
98 	  .data = "\033[25~"
99 	},
100 	{ .key = KEYC_F2|KEYC_SHIFT,
101 	  .data = "\033[26~"
102 	},
103 	{ .key = KEYC_F3|KEYC_SHIFT,
104 	  .data = "\033[28~"
105 	},
106 	{ .key = KEYC_F4|KEYC_SHIFT,
107 	  .data = "\033[29~"
108 	},
109 	{ .key = KEYC_F5|KEYC_SHIFT,
110 	  .data = "\033[31~"
111 	},
112 	{ .key = KEYC_F6|KEYC_SHIFT,
113 	  .data = "\033[32~"
114 	},
115 	{ .key = KEYC_F7|KEYC_SHIFT,
116 	  .data = "\033[33~"
117 	},
118 	{ .key = KEYC_F8|KEYC_SHIFT,
119 	  .data = "\033[34~"
120 	},
121 	{ .key = KEYC_IC,
122 	  .data = "\033[2~"
123 	},
124 	{ .key = KEYC_DC,
125 	  .data = "\033[3~"
126 	},
127 	{ .key = KEYC_HOME,
128 	  .data = "\033[1~"
129 	},
130 	{ .key = KEYC_END,
131 	  .data = "\033[4~"
132 	},
133 	{ .key = KEYC_NPAGE,
134 	  .data = "\033[6~"
135 	},
136 	{ .key = KEYC_PPAGE,
137 	  .data = "\033[5~"
138 	},
139 	{ .key = KEYC_BTAB,
140 	  .data = "\033[Z"
141 	},
142 
143 	/* Arrow keys. */
144 	{ .key = KEYC_UP|KEYC_CURSOR,
145 	  .data = "\033OA"
146 	},
147 	{ .key = KEYC_DOWN|KEYC_CURSOR,
148 	  .data = "\033OB"
149 	},
150 	{ .key = KEYC_RIGHT|KEYC_CURSOR,
151 	  .data = "\033OC"
152 	},
153 	{ .key = KEYC_LEFT|KEYC_CURSOR,
154 	  .data = "\033OD"
155 	},
156 	{ .key = KEYC_UP,
157 	  .data = "\033[A"
158 	},
159 	{ .key = KEYC_DOWN,
160 	  .data = "\033[B"
161 	},
162 	{ .key = KEYC_RIGHT,
163 	  .data = "\033[C"
164 	},
165 	{ .key = KEYC_LEFT,
166 	  .data = "\033[D"
167 	},
168 
169 	/* Keypad keys. */
170 	{ .key = KEYC_KP_SLASH|KEYC_KEYPAD,
171 	  .data = "\033Oo"
172 	},
173 	{ .key = KEYC_KP_STAR|KEYC_KEYPAD,
174 	  .data = "\033Oj"
175 	},
176 	{ .key = KEYC_KP_MINUS|KEYC_KEYPAD,
177 	  .data = "\033Om"
178 	},
179 	{ .key = KEYC_KP_SEVEN|KEYC_KEYPAD,
180 	  .data = "\033Ow"
181 	},
182 	{ .key = KEYC_KP_EIGHT|KEYC_KEYPAD,
183 	  .data = "\033Ox"
184 	},
185 	{ .key = KEYC_KP_NINE|KEYC_KEYPAD,
186 	  .data = "\033Oy"
187 	},
188 	{ .key = KEYC_KP_PLUS|KEYC_KEYPAD,
189 	  .data = "\033Ok"
190 	},
191 	{ .key = KEYC_KP_FOUR|KEYC_KEYPAD,
192 	  .data = "\033Ot"
193 	},
194 	{ .key = KEYC_KP_FIVE|KEYC_KEYPAD,
195 	  .data = "\033Ou"
196 	},
197 	{ .key = KEYC_KP_SIX|KEYC_KEYPAD,
198 	  .data = "\033Ov"
199 	},
200 	{ .key = KEYC_KP_ONE|KEYC_KEYPAD,
201 	  .data = "\033Oq"
202 	},
203 	{ .key = KEYC_KP_TWO|KEYC_KEYPAD,
204 	  .data = "\033Or"
205 	},
206 	{ .key = KEYC_KP_THREE|KEYC_KEYPAD,
207 	  .data = "\033Os"
208 	},
209 	{ .key = KEYC_KP_ENTER|KEYC_KEYPAD,
210 	  .data = "\033OM"
211 	},
212 	{ .key = KEYC_KP_ZERO|KEYC_KEYPAD,
213 	  .data = "\033Op"
214 	},
215 	{ .key = KEYC_KP_PERIOD|KEYC_KEYPAD,
216 	  .data = "\033On"
217 	},
218 	{ .key = KEYC_KP_SLASH,
219 	  .data = "/"
220 	},
221 	{ .key = KEYC_KP_STAR,
222 	  .data = "*"
223 	},
224 	{ .key = KEYC_KP_MINUS,
225 	  .data = "-"
226 	},
227 	{ .key = KEYC_KP_SEVEN,
228 	  .data = "7"
229 	},
230 	{ .key = KEYC_KP_EIGHT,
231 	  .data = "8"
232 	},
233 	{ .key = KEYC_KP_NINE,
234 	  .data = "9"
235 	},
236 	{ .key = KEYC_KP_PLUS,
237 	  .data = "+"
238 	},
239 	{ .key = KEYC_KP_FOUR,
240 	  .data = "4"
241 	},
242 	{ .key = KEYC_KP_FIVE,
243 	  .data = "5"
244 	},
245 	{ .key = KEYC_KP_SIX,
246 	  .data = "6"
247 	},
248 	{ .key = KEYC_KP_ONE,
249 	  .data = "1"
250 	},
251 	{ .key = KEYC_KP_TWO,
252 	  .data = "2"
253 	},
254 	{ .key = KEYC_KP_THREE,
255 	  .data = "3"
256 	},
257 	{ .key = KEYC_KP_ENTER,
258 	  .data = "\n"
259 	},
260 	{ .key = KEYC_KP_ZERO,
261 	  .data = "0"
262 	},
263 	{ .key = KEYC_KP_PERIOD,
264 	  .data = "."
265 	},
266 
267 	/* Keys with an embedded modifier. */
268 	{ .key = KEYC_F1|KEYC_BUILD_MODIFIERS,
269 	  .data = "\033[1;_P"
270 	},
271 	{ .key = KEYC_F2|KEYC_BUILD_MODIFIERS,
272 	  .data = "\033[1;_Q"
273 	},
274 	{ .key = KEYC_F3|KEYC_BUILD_MODIFIERS,
275 	  .data = "\033[1;_R"
276 	},
277 	{ .key = KEYC_F4|KEYC_BUILD_MODIFIERS,
278 	  .data = "\033[1;_S"
279 	},
280 	{ .key = KEYC_F5|KEYC_BUILD_MODIFIERS,
281 	  .data = "\033[15;_~"
282 	},
283 	{ .key = KEYC_F6|KEYC_BUILD_MODIFIERS,
284 	  .data = "\033[17;_~"
285 	},
286 	{ .key = KEYC_F7|KEYC_BUILD_MODIFIERS,
287 	  .data = "\033[18;_~"
288 	},
289 	{ .key = KEYC_F8|KEYC_BUILD_MODIFIERS,
290 	  .data = "\033[19;_~"
291 	},
292 	{ .key = KEYC_F9|KEYC_BUILD_MODIFIERS,
293 	  .data = "\033[20;_~"
294 	},
295 	{ .key = KEYC_F10|KEYC_BUILD_MODIFIERS,
296 	  .data = "\033[21;_~"
297 	},
298 	{ .key = KEYC_F11|KEYC_BUILD_MODIFIERS,
299 	  .data = "\033[23;_~"
300 	},
301 	{ .key = KEYC_F12|KEYC_BUILD_MODIFIERS,
302 	  .data = "\033[24;_~"
303 	},
304 	{ .key = KEYC_UP|KEYC_BUILD_MODIFIERS,
305 	  .data = "\033[1;_A"
306 	},
307 	{ .key = KEYC_DOWN|KEYC_BUILD_MODIFIERS,
308 	  .data = "\033[1;_B"
309 	},
310 	{ .key = KEYC_RIGHT|KEYC_BUILD_MODIFIERS,
311 	  .data = "\033[1;_C"
312 	},
313 	{ .key = KEYC_LEFT|KEYC_BUILD_MODIFIERS,
314 	  .data = "\033[1;_D"
315 	},
316 	{ .key = KEYC_HOME|KEYC_BUILD_MODIFIERS,
317 	  .data = "\033[1;_H"
318 	},
319 	{ .key = KEYC_END|KEYC_BUILD_MODIFIERS,
320 	  .data = "\033[1;_F"
321 	},
322 	{ .key = KEYC_PPAGE|KEYC_BUILD_MODIFIERS,
323 	  .data = "\033[5;_~"
324 	},
325 	{ .key = KEYC_NPAGE|KEYC_BUILD_MODIFIERS,
326 	  .data = "\033[6;_~"
327 	},
328 	{ .key = KEYC_IC|KEYC_BUILD_MODIFIERS,
329 	  .data = "\033[2;_~"
330 	},
331 	{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
332 	  .data = "\033[3;_~"
333 	}
334 };
335 static const key_code input_key_modifiers[] = {
336 	0,
337 	0,
338 	KEYC_SHIFT,
339 	KEYC_META|KEYC_IMPLIED_META,
340 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META,
341 	KEYC_CTRL,
342 	KEYC_SHIFT|KEYC_CTRL,
343 	KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
344 	KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL
345 };
346 
347 /* Input key comparison function. */
348 static int
349 input_key_cmp(struct input_key_entry *ike1, struct input_key_entry *ike2)
350 {
351 	if (ike1->key < ike2->key)
352 		return (-1);
353 	if (ike1->key > ike2->key)
354 		return (1);
355 	return (0);
356 }
357 
358 /* Look for key in tree. */
359 static struct input_key_entry *
360 input_key_get (key_code key)
361 {
362 	struct input_key_entry	entry = { .key = key };
363 
364 	return (RB_FIND(input_key_tree, &input_key_tree, &entry));
365 }
366 
367 /* Split a character into two UTF-8 bytes. */
368 static size_t
369 input_key_split2(u_int c, char *dst)
370 {
371 	if (c > 0x7f) {
372 		dst[0] = (c >> 6) | 0xc0;
373 		dst[1] = (c & 0x3f) | 0x80;
374 		return (2);
375 	}
376 	dst[0] = c;
377 	return (1);
378 }
379 
380 /* Build input key tree. */
381 void
382 input_key_build(void)
383 {
384 	struct input_key_entry	*ike, *new;
385 	u_int			 i, j;
386 	char			*data;
387 	key_code		 key;
388 
389 	for (i = 0; i < nitems(input_key_defaults); i++) {
390 		ike = &input_key_defaults[i];
391 		if (~ike->key & KEYC_BUILD_MODIFIERS) {
392 			RB_INSERT(input_key_tree, &input_key_tree, ike);
393 			continue;
394 		}
395 
396 		for (j = 2; j < nitems(input_key_modifiers); j++) {
397 			key = (ike->key & ~KEYC_BUILD_MODIFIERS);
398 			data = xstrdup(ike->data);
399 			data[strcspn(data, "_")] = '0' + j;
400 
401 			new = xcalloc(1, sizeof *new);
402 			new->key = key|input_key_modifiers[j];
403 			new->data = data;
404 			RB_INSERT(input_key_tree, &input_key_tree, new);
405 		}
406 	}
407 
408 	RB_FOREACH(ike, input_key_tree, &input_key_tree) {
409 		log_debug("%s: 0x%llx (%s) is %s", __func__, ike->key,
410 		    key_string_lookup_key(ike->key, 1), ike->data);
411 	}
412 }
413 
414 /* Translate a key code into an output key sequence for a pane. */
415 int
416 input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
417 {
418 	if (log_get_level() != 0) {
419 		log_debug("writing key 0x%llx (%s) to %%%u", key,
420 		    key_string_lookup_key(key, 1), wp->id);
421 	}
422 
423 	if (KEYC_IS_MOUSE(key)) {
424 		if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
425 			input_key_mouse(wp, m);
426 		return (0);
427 	}
428 	return (input_key(wp->screen, wp->event, key));
429 }
430 
431 static void
432 input_key_write(const char *from, struct bufferevent *bev, const char *data,
433     size_t size)
434 {
435 	log_debug("%s: %.*s", from, (int)size, (const char *)data);
436 	bufferevent_write(bev, data, size);
437 }
438 
439 /* Translate a key code into an output key sequence. */
440 int
441 input_key(struct screen *s, struct bufferevent *bev, key_code key)
442 {
443 	struct input_key_entry	*ike;
444 	key_code		 justkey, newkey, outkey;
445 	struct utf8_data	 ud;
446 	char			 tmp[64], modifier;
447 
448 	/* Mouse keys need a pane. */
449 	if (KEYC_IS_MOUSE(key))
450 		return (0);
451 
452 	/* Literal keys go as themselves (can't be more than eight bits). */
453 	if (key & KEYC_LITERAL) {
454 		ud.data[0] = (u_char)key;
455 		input_key_write(__func__, bev, (const char *)ud.data, 1);
456 		return (0);
457 	}
458 
459 	/* Is this backspace? */
460 	if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
461 		newkey = options_get_number(global_options, "backspace");
462 		if (newkey >= 0x7f)
463 			newkey = '\177';
464 		key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS));
465 	}
466 
467 	/*
468 	 * If this is a normal 7-bit key, just send it, with a leading escape
469 	 * if necessary. If it is a UTF-8 key, split it and send it.
470 	 */
471 	justkey = (key & ~(KEYC_META|KEYC_IMPLIED_META));
472 	if (justkey <= 0x7f) {
473 		if (key & KEYC_META)
474 			input_key_write(__func__, bev, "\033", 1);
475 		ud.data[0] = justkey;
476 		input_key_write(__func__, bev, (const char *)ud.data, 1);
477 		return (0);
478 	}
479 	if (justkey > 0x7f && justkey < KEYC_BASE) {
480 		if (key & KEYC_META)
481 			input_key_write(__func__, bev, "\033", 1);
482 		utf8_to_data(justkey, &ud);
483 		input_key_write(__func__, bev, (const char *)ud.data, ud.size);
484 		return (0);
485 	}
486 
487 	/*
488 	 * Look up in the tree. If not in application keypad or cursor mode,
489 	 * remove the flags from the key.
490 	 */
491 	if (~s->mode & MODE_KKEYPAD)
492 		key &= ~KEYC_KEYPAD;
493 	if (~s->mode & MODE_KCURSOR)
494 		key &= ~KEYC_CURSOR;
495 	ike = input_key_get(key);
496 	if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META))
497 		ike = input_key_get(key & ~KEYC_META);
498 	if (ike == NULL && (key & KEYC_CURSOR))
499 		ike = input_key_get(key & ~KEYC_CURSOR);
500 	if (ike == NULL && (key & KEYC_KEYPAD))
501 		ike = input_key_get(key & ~KEYC_KEYPAD);
502 	if (ike != NULL) {
503 		log_debug("found key 0x%llx: \"%s\"", key, ike->data);
504 		if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
505 			input_key_write(__func__, bev, "\033", 1);
506 		input_key_write(__func__, bev, ike->data, strlen(ike->data));
507 		return (0);
508 	}
509 
510 	/* No builtin key sequence; construct an extended key sequence. */
511 	if (~s->mode & MODE_KEXTENDED) {
512 		if ((key & KEYC_MASK_MODIFIERS) != KEYC_CTRL)
513 			goto missing;
514 		justkey = (key & KEYC_MASK_KEY);
515 		switch (justkey) {
516 		case ' ':
517 		case '2':
518 			key = 0|(key & ~KEYC_MASK_KEY);
519 			break;
520 		case '|':
521 			key = 28|(key & ~KEYC_MASK_KEY);
522 			break;
523 		case '6':
524 			key = 30|(key & ~KEYC_MASK_KEY);
525 			break;
526 		case '-':
527 		case '/':
528 			key = 31|(key & ~KEYC_MASK_KEY);
529 			break;
530 		case '?':
531 			key = 127|(key & ~KEYC_MASK_KEY);
532 			break;
533 		default:
534 			if (justkey >= 'A' && justkey <= '_')
535 				key = (justkey - 'A')|(key & ~KEYC_MASK_KEY);
536 			else if (justkey >= 'a' && justkey <= '~')
537 				key = (justkey - 96)|(key & ~KEYC_MASK_KEY);
538 			else
539 				return (0);
540 			break;
541 		}
542 		return (input_key(s, bev, key & ~KEYC_CTRL));
543 	}
544 	outkey = (key & KEYC_MASK_KEY);
545 	switch (key & KEYC_MASK_MODIFIERS) {
546 	case KEYC_SHIFT:
547 		modifier = '2';
548 		break;
549 	case KEYC_META:
550 		modifier = '3';
551 		break;
552 	case KEYC_SHIFT|KEYC_META:
553 		modifier = '4';
554 		break;
555 	case KEYC_CTRL:
556 		modifier = '5';
557 		break;
558 	case KEYC_SHIFT|KEYC_CTRL:
559 		modifier = '6';
560 		break;
561 	case KEYC_META|KEYC_CTRL:
562 		modifier = '7';
563 		break;
564 	case KEYC_SHIFT|KEYC_META|KEYC_CTRL:
565 		modifier = '8';
566 		break;
567 	default:
568 		goto missing;
569 	}
570 	xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier);
571 	input_key_write(__func__, bev, tmp, strlen(tmp));
572 	return (0);
573 
574 missing:
575 	log_debug("key 0x%llx missing", key);
576 	return (-1);
577 }
578 
579 /* Get mouse event string. */
580 int
581 input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
582     const char **rbuf, size_t *rlen)
583 {
584 	static char	 buf[40];
585 	size_t		 len;
586 
587 	*rbuf = NULL;
588 	*rlen = 0;
589 
590 	/* If this pane is not in button or all mode, discard motion events. */
591 	if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0)
592 		return (0);
593 	if ((s->mode & ALL_MOUSE_MODES) == 0)
594 		return (0);
595 
596 	/*
597 	 * If this event is a release event and not in all mode, discard it.
598 	 * In SGR mode we can tell absolutely because a release is normally
599 	 * shown by the last character. Without SGR, we check if the last
600 	 * buttons was also a release.
601 	 */
602 	if (m->sgr_type != ' ') {
603 		if (MOUSE_DRAG(m->sgr_b) &&
604 		    MOUSE_BUTTONS(m->sgr_b) == 3 &&
605 		    (~s->mode & MODE_MOUSE_ALL))
606 			return (0);
607 	} else {
608 		if (MOUSE_DRAG(m->b) &&
609 		    MOUSE_BUTTONS(m->b) == 3 &&
610 		    MOUSE_BUTTONS(m->lb) == 3 &&
611 		    (~s->mode & MODE_MOUSE_ALL))
612 			return (0);
613 	}
614 
615 	/*
616 	 * Use the SGR (1006) extension only if the application requested it
617 	 * and the underlying terminal also sent the event in this format (this
618 	 * is because an old style mouse release event cannot be converted into
619 	 * the new SGR format, since the released button is unknown). Otherwise
620 	 * pretend that tmux doesn't speak this extension, and fall back to the
621 	 * UTF-8 (1005) extension if the application requested, or to the
622 	 * legacy format.
623 	 */
624 	if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
625 		len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
626 		    m->sgr_b, x + 1, y + 1, m->sgr_type);
627 	} else if (s->mode & MODE_MOUSE_UTF8) {
628 		if (m->b > 0x7ff - 32 || x > 0x7ff - 33 || y > 0x7ff - 33)
629 			return (0);
630 		len = xsnprintf(buf, sizeof buf, "\033[M");
631 		len += input_key_split2(m->b + 32, &buf[len]);
632 		len += input_key_split2(x + 33, &buf[len]);
633 		len += input_key_split2(y + 33, &buf[len]);
634 	} else {
635 		if (m->b > 223)
636 			return (0);
637 		len = xsnprintf(buf, sizeof buf, "\033[M");
638 		buf[len++] = m->b + 32;
639 		buf[len++] = x + 33;
640 		buf[len++] = y + 33;
641 	}
642 
643 	*rbuf = buf;
644 	*rlen = len;
645 	return (1);
646 }
647 
648 /* Translate mouse and output. */
649 static void
650 input_key_mouse(struct window_pane *wp, struct mouse_event *m)
651 {
652 	struct screen	*s = wp->screen;
653 	u_int		 x, y;
654 	const char	*buf;
655 	size_t		 len;
656 
657 	/* Ignore events if no mouse mode or the pane is not visible. */
658 	if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0)
659 		return;
660 	if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
661 		return;
662 	if (!window_pane_visible(wp))
663 		return;
664 	if (!input_key_get_mouse(s, m, x, y, &buf, &len))
665 		return;
666 	log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
667 	input_key_write(__func__, wp->event, buf, len);
668 }
669