xref: /netbsd-src/external/bsd/tmux/dist/input-keys.c (revision 901e7e84758515fbf39dfc064cb0b45ab146d8b0)
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 /* Translate a key code into an output key sequence. */
416 int
417 input_key(struct screen *s, struct bufferevent *bev, key_code key)
418 {
419 	struct input_key_entry	*ike;
420 	key_code		 justkey, newkey, outkey, modifiers;
421 	struct utf8_data	 ud;
422 	char			 tmp[64], modifier;
423 
424 	/* Mouse keys need a pane. */
425 	if (KEYC_IS_MOUSE(key))
426 		return (0);
427 
428 	/* Literal keys go as themselves (can't be more than eight bits). */
429 	if (key & KEYC_LITERAL) {
430 		ud.data[0] = (u_char)key;
431 		input_key_write(__func__, bev, (const char *)ud.data, 1);
432 		return (0);
433 	}
434 
435 	/* Is this backspace? */
436 	if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
437 		newkey = options_get_number(global_options, "backspace");
438 		if (newkey >= 0x7f)
439 			newkey = '\177';
440 		key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS));
441 	}
442 
443 	/*
444 	 * If this is a normal 7-bit key, just send it, with a leading escape
445 	 * if necessary. If it is a UTF-8 key, split it and send it.
446 	 */
447 	justkey = (key & ~(KEYC_META|KEYC_IMPLIED_META));
448 	if (justkey <= 0x7f) {
449 		if (key & KEYC_META)
450 			input_key_write(__func__, bev, "\033", 1);
451 		ud.data[0] = justkey;
452 		input_key_write(__func__, bev, (const char *)ud.data, 1);
453 		return (0);
454 	}
455 	if (KEYC_IS_UNICODE(justkey)) {
456 		if (key & KEYC_META)
457 			input_key_write(__func__, bev, "\033", 1);
458 		utf8_to_data(justkey, &ud);
459 		input_key_write(__func__, bev, (const char *)ud.data, ud.size);
460 		return (0);
461 	}
462 
463 	/*
464 	 * Look up in the tree. If not in application keypad or cursor mode,
465 	 * remove the flags from the key.
466 	 */
467 	if (~s->mode & MODE_KKEYPAD)
468 		key &= ~KEYC_KEYPAD;
469 	if (~s->mode & MODE_KCURSOR)
470 		key &= ~KEYC_CURSOR;
471 	ike = input_key_get(key);
472 	if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META))
473 		ike = input_key_get(key & ~KEYC_META);
474 	if (ike == NULL && (key & KEYC_CURSOR))
475 		ike = input_key_get(key & ~KEYC_CURSOR);
476 	if (ike == NULL && (key & KEYC_KEYPAD))
477 		ike = input_key_get(key & ~KEYC_KEYPAD);
478 	if (ike != NULL) {
479 		log_debug("found key 0x%llx: \"%s\"", key, ike->data);
480 		if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
481 			input_key_write(__func__, bev, "\033", 1);
482 		input_key_write(__func__, bev, ike->data, strlen(ike->data));
483 		return (0);
484 	}
485 
486 	/* No builtin key sequence; construct an extended key sequence. */
487 	if (~s->mode & MODE_KEXTENDED) {
488 		if ((key & KEYC_MASK_MODIFIERS) != KEYC_CTRL)
489 			goto missing;
490 		justkey = (key & KEYC_MASK_KEY);
491 		switch (justkey) {
492 		case ' ':
493 		case '2':
494 			key = 0|(key & ~KEYC_MASK_KEY);
495 			break;
496 		case '|':
497 			key = 28|(key & ~KEYC_MASK_KEY);
498 			break;
499 		case '6':
500 			key = 30|(key & ~KEYC_MASK_KEY);
501 			break;
502 		case '-':
503 		case '/':
504 			key = 31|(key & ~KEYC_MASK_KEY);
505 			break;
506 		case '?':
507 			key = 127|(key & ~KEYC_MASK_KEY);
508 			break;
509 		default:
510 			if (justkey >= 'A' && justkey <= '_')
511 				key = (justkey - 'A')|(key & ~KEYC_MASK_KEY);
512 			else if (justkey >= 'a' && justkey <= '~')
513 				key = (justkey - 96)|(key & ~KEYC_MASK_KEY);
514 			else
515 				return (0);
516 			break;
517 		}
518 		return (input_key(s, bev, key & ~KEYC_CTRL));
519 	}
520 	outkey = (key & KEYC_MASK_KEY);
521 	modifiers = (key & KEYC_MASK_MODIFIERS);
522 	if (outkey < 32 && outkey != 9 && outkey != 13 && outkey != 27) {
523 		outkey = 64 + outkey;
524 		modifiers |= KEYC_CTRL;
525 	}
526 	switch (modifiers) {
527 	case KEYC_SHIFT:
528 		modifier = '2';
529 		break;
530 	case KEYC_META:
531 		modifier = '3';
532 		break;
533 	case KEYC_SHIFT|KEYC_META:
534 		modifier = '4';
535 		break;
536 	case KEYC_CTRL:
537 		modifier = '5';
538 		break;
539 	case KEYC_SHIFT|KEYC_CTRL:
540 		modifier = '6';
541 		break;
542 	case KEYC_META|KEYC_CTRL:
543 		modifier = '7';
544 		break;
545 	case KEYC_SHIFT|KEYC_META|KEYC_CTRL:
546 		modifier = '8';
547 		break;
548 	default:
549 		goto missing;
550 	}
551 	xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier);
552 	input_key_write(__func__, bev, tmp, strlen(tmp));
553 	return (0);
554 
555 missing:
556 	log_debug("key 0x%llx missing", key);
557 	return (-1);
558 }
559 
560 /* Get mouse event string. */
561 int
562 input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
563     const char **rbuf, size_t *rlen)
564 {
565 	static char	 buf[40];
566 	size_t		 len;
567 
568 	*rbuf = NULL;
569 	*rlen = 0;
570 
571 	/* If this pane is not in button or all mode, discard motion events. */
572 	if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0)
573 		return (0);
574 	if ((s->mode & ALL_MOUSE_MODES) == 0)
575 		return (0);
576 
577 	/*
578 	 * If this event is a release event and not in all mode, discard it.
579 	 * In SGR mode we can tell absolutely because a release is normally
580 	 * shown by the last character. Without SGR, we check if the last
581 	 * buttons was also a release.
582 	 */
583 	if (m->sgr_type != ' ') {
584 		if (MOUSE_DRAG(m->sgr_b) &&
585 		    MOUSE_RELEASE(m->sgr_b) &&
586 		    (~s->mode & MODE_MOUSE_ALL))
587 			return (0);
588 	} else {
589 		if (MOUSE_DRAG(m->b) &&
590 		    MOUSE_RELEASE(m->b) &&
591 		    MOUSE_RELEASE(m->lb) &&
592 		    (~s->mode & MODE_MOUSE_ALL))
593 			return (0);
594 	}
595 
596 	/*
597 	 * Use the SGR (1006) extension only if the application requested it
598 	 * and the underlying terminal also sent the event in this format (this
599 	 * is because an old style mouse release event cannot be converted into
600 	 * the new SGR format, since the released button is unknown). Otherwise
601 	 * pretend that tmux doesn't speak this extension, and fall back to the
602 	 * UTF-8 (1005) extension if the application requested, or to the
603 	 * legacy format.
604 	 */
605 	if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
606 		len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
607 		    m->sgr_b, x + 1, y + 1, m->sgr_type);
608 	} else if (s->mode & MODE_MOUSE_UTF8) {
609 		if (m->b > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_BTN_OFF ||
610 		    x > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF ||
611 		    y > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF)
612 			return (0);
613 		len = xsnprintf(buf, sizeof buf, "\033[M");
614 		len += input_key_split2(m->b + MOUSE_PARAM_BTN_OFF, &buf[len]);
615 		len += input_key_split2(x + MOUSE_PARAM_POS_OFF, &buf[len]);
616 		len += input_key_split2(y + MOUSE_PARAM_POS_OFF, &buf[len]);
617 	} else {
618 		if (m->b + MOUSE_PARAM_BTN_OFF > MOUSE_PARAM_MAX)
619 			return (0);
620 
621 		len = xsnprintf(buf, sizeof buf, "\033[M");
622 		buf[len++] = m->b + MOUSE_PARAM_BTN_OFF;
623 
624 		/*
625 		 * The incoming x and y may be out of the range which can be
626 		 * supported by the "normal" mouse protocol. Clamp the
627 		 * coordinates to the supported range.
628 		 */
629 		if (x + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
630 			buf[len++] = MOUSE_PARAM_MAX;
631 		else
632 			buf[len++] = x + MOUSE_PARAM_POS_OFF;
633 		if (y + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
634 			buf[len++] = MOUSE_PARAM_MAX;
635 		else
636 			buf[len++] = y + MOUSE_PARAM_POS_OFF;
637 	}
638 
639 	*rbuf = buf;
640 	*rlen = len;
641 	return (1);
642 }
643 
644 /* Translate mouse and output. */
645 static void
646 input_key_mouse(struct window_pane *wp, struct mouse_event *m)
647 {
648 	struct screen	*s = wp->screen;
649 	u_int		 x, y;
650 	const char	*buf;
651 	size_t		 len;
652 
653 	/* Ignore events if no mouse mode or the pane is not visible. */
654 	if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0)
655 		return;
656 	if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
657 		return;
658 	if (!window_pane_visible(wp))
659 		return;
660 	if (!input_key_get_mouse(s, m, x, y, &buf, &len))
661 		return;
662 	log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
663 	input_key_write(__func__, wp->event, buf, len);
664 }
665