Merge branch 'obsd-master'
[tmux.git] / input-keys.c
blob80a477f9fa4b597b6823e8e1f8ab195997111785
1 /* $OpenBSD$ */
3 /*
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>
21 #include <stdlib.h>
22 #include <string.h>
24 #include "tmux.h"
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).
33 static void input_key_mouse(struct window_pane *, struct mouse_event *);
35 /* Entry in the key tree. */
36 struct input_key_entry {
37 key_code key;
38 const char *data;
40 RB_ENTRY(input_key_entry) entry;
42 RB_HEAD(input_key_tree, input_key_entry);
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);
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~"
56 { .key = KEYC_PASTE_END,
57 .data = "\033[201~"
60 /* Function keys. */
61 { .key = KEYC_F1,
62 .data = "\033OP"
64 { .key = KEYC_F2,
65 .data = "\033OQ"
67 { .key = KEYC_F3,
68 .data = "\033OR"
70 { .key = KEYC_F4,
71 .data = "\033OS"
73 { .key = KEYC_F5,
74 .data = "\033[15~"
76 { .key = KEYC_F6,
77 .data = "\033[17~"
79 { .key = KEYC_F7,
80 .data = "\033[18~"
82 { .key = KEYC_F8,
83 .data = "\033[19~"
85 { .key = KEYC_F9,
86 .data = "\033[20~"
88 { .key = KEYC_F10,
89 .data = "\033[21~"
91 { .key = KEYC_F11,
92 .data = "\033[23~"
94 { .key = KEYC_F12,
95 .data = "\033[24~"
97 { .key = KEYC_IC,
98 .data = "\033[2~"
100 { .key = KEYC_DC,
101 .data = "\033[3~"
103 { .key = KEYC_HOME,
104 .data = "\033[1~"
106 { .key = KEYC_END,
107 .data = "\033[4~"
109 { .key = KEYC_NPAGE,
110 .data = "\033[6~"
112 { .key = KEYC_PPAGE,
113 .data = "\033[5~"
115 { .key = KEYC_BTAB,
116 .data = "\033[Z"
119 /* Arrow keys. */
120 { .key = KEYC_UP|KEYC_CURSOR,
121 .data = "\033OA"
123 { .key = KEYC_DOWN|KEYC_CURSOR,
124 .data = "\033OB"
126 { .key = KEYC_RIGHT|KEYC_CURSOR,
127 .data = "\033OC"
129 { .key = KEYC_LEFT|KEYC_CURSOR,
130 .data = "\033OD"
132 { .key = KEYC_UP,
133 .data = "\033[A"
135 { .key = KEYC_DOWN,
136 .data = "\033[B"
138 { .key = KEYC_RIGHT,
139 .data = "\033[C"
141 { .key = KEYC_LEFT,
142 .data = "\033[D"
145 /* Keypad keys. */
146 { .key = KEYC_KP_SLASH|KEYC_KEYPAD,
147 .data = "\033Oo"
149 { .key = KEYC_KP_STAR|KEYC_KEYPAD,
150 .data = "\033Oj"
152 { .key = KEYC_KP_MINUS|KEYC_KEYPAD,
153 .data = "\033Om"
155 { .key = KEYC_KP_SEVEN|KEYC_KEYPAD,
156 .data = "\033Ow"
158 { .key = KEYC_KP_EIGHT|KEYC_KEYPAD,
159 .data = "\033Ox"
161 { .key = KEYC_KP_NINE|KEYC_KEYPAD,
162 .data = "\033Oy"
164 { .key = KEYC_KP_PLUS|KEYC_KEYPAD,
165 .data = "\033Ok"
167 { .key = KEYC_KP_FOUR|KEYC_KEYPAD,
168 .data = "\033Ot"
170 { .key = KEYC_KP_FIVE|KEYC_KEYPAD,
171 .data = "\033Ou"
173 { .key = KEYC_KP_SIX|KEYC_KEYPAD,
174 .data = "\033Ov"
176 { .key = KEYC_KP_ONE|KEYC_KEYPAD,
177 .data = "\033Oq"
179 { .key = KEYC_KP_TWO|KEYC_KEYPAD,
180 .data = "\033Or"
182 { .key = KEYC_KP_THREE|KEYC_KEYPAD,
183 .data = "\033Os"
185 { .key = KEYC_KP_ENTER|KEYC_KEYPAD,
186 .data = "\033OM"
188 { .key = KEYC_KP_ZERO|KEYC_KEYPAD,
189 .data = "\033Op"
191 { .key = KEYC_KP_PERIOD|KEYC_KEYPAD,
192 .data = "\033On"
194 { .key = KEYC_KP_SLASH,
195 .data = "/"
197 { .key = KEYC_KP_STAR,
198 .data = "*"
200 { .key = KEYC_KP_MINUS,
201 .data = "-"
203 { .key = KEYC_KP_SEVEN,
204 .data = "7"
206 { .key = KEYC_KP_EIGHT,
207 .data = "8"
209 { .key = KEYC_KP_NINE,
210 .data = "9"
212 { .key = KEYC_KP_PLUS,
213 .data = "+"
215 { .key = KEYC_KP_FOUR,
216 .data = "4"
218 { .key = KEYC_KP_FIVE,
219 .data = "5"
221 { .key = KEYC_KP_SIX,
222 .data = "6"
224 { .key = KEYC_KP_ONE,
225 .data = "1"
227 { .key = KEYC_KP_TWO,
228 .data = "2"
230 { .key = KEYC_KP_THREE,
231 .data = "3"
233 { .key = KEYC_KP_ENTER,
234 .data = "\n"
236 { .key = KEYC_KP_ZERO,
237 .data = "0"
239 { .key = KEYC_KP_PERIOD,
240 .data = "."
243 /* Keys with an embedded modifier. */
244 { .key = KEYC_F1|KEYC_BUILD_MODIFIERS,
245 .data = "\033[1;_P"
247 { .key = KEYC_F2|KEYC_BUILD_MODIFIERS,
248 .data = "\033[1;_Q"
250 { .key = KEYC_F3|KEYC_BUILD_MODIFIERS,
251 .data = "\033[1;_R"
253 { .key = KEYC_F4|KEYC_BUILD_MODIFIERS,
254 .data = "\033[1;_S"
256 { .key = KEYC_F5|KEYC_BUILD_MODIFIERS,
257 .data = "\033[15;_~"
259 { .key = KEYC_F6|KEYC_BUILD_MODIFIERS,
260 .data = "\033[17;_~"
262 { .key = KEYC_F7|KEYC_BUILD_MODIFIERS,
263 .data = "\033[18;_~"
265 { .key = KEYC_F8|KEYC_BUILD_MODIFIERS,
266 .data = "\033[19;_~"
268 { .key = KEYC_F9|KEYC_BUILD_MODIFIERS,
269 .data = "\033[20;_~"
271 { .key = KEYC_F10|KEYC_BUILD_MODIFIERS,
272 .data = "\033[21;_~"
274 { .key = KEYC_F11|KEYC_BUILD_MODIFIERS,
275 .data = "\033[23;_~"
277 { .key = KEYC_F12|KEYC_BUILD_MODIFIERS,
278 .data = "\033[24;_~"
280 { .key = KEYC_UP|KEYC_BUILD_MODIFIERS,
281 .data = "\033[1;_A"
283 { .key = KEYC_DOWN|KEYC_BUILD_MODIFIERS,
284 .data = "\033[1;_B"
286 { .key = KEYC_RIGHT|KEYC_BUILD_MODIFIERS,
287 .data = "\033[1;_C"
289 { .key = KEYC_LEFT|KEYC_BUILD_MODIFIERS,
290 .data = "\033[1;_D"
292 { .key = KEYC_HOME|KEYC_BUILD_MODIFIERS,
293 .data = "\033[1;_H"
295 { .key = KEYC_END|KEYC_BUILD_MODIFIERS,
296 .data = "\033[1;_F"
298 { .key = KEYC_PPAGE|KEYC_BUILD_MODIFIERS,
299 .data = "\033[5;_~"
301 { .key = KEYC_NPAGE|KEYC_BUILD_MODIFIERS,
302 .data = "\033[6;_~"
304 { .key = KEYC_IC|KEYC_BUILD_MODIFIERS,
305 .data = "\033[2;_~"
307 { .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
308 .data = "\033[3;_~"
311 static const key_code input_key_modifiers[] = {
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
323 /* Input key comparison function. */
324 static int
325 input_key_cmp(struct input_key_entry *ike1, struct input_key_entry *ike2)
327 if (ike1->key < ike2->key)
328 return (-1);
329 if (ike1->key > ike2->key)
330 return (1);
331 return (0);
334 /* Look for key in tree. */
335 static struct input_key_entry *
336 input_key_get(key_code key)
338 struct input_key_entry entry = { .key = key };
340 return (RB_FIND(input_key_tree, &input_key_tree, &entry));
343 /* Split a character into two UTF-8 bytes. */
344 static size_t
345 input_key_split2(u_int c, u_char *dst)
347 if (c > 0x7f) {
348 dst[0] = (c >> 6) | 0xc0;
349 dst[1] = (c & 0x3f) | 0x80;
350 return (2);
352 dst[0] = c;
353 return (1);
356 /* Build input key tree. */
357 void
358 input_key_build(void)
360 struct input_key_entry *ike, *new;
361 u_int i, j;
362 char *data;
363 key_code key;
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;
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;
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);
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);
390 /* Translate a key code into an output key sequence for a pane. */
392 input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
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);
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);
404 return (input_key(wp->screen, wp->event, key));
407 static void
408 input_key_write(const char *from, struct bufferevent *bev, const char *data,
409 size_t size)
411 log_debug("%s: %.*s", from, (int)size, data);
412 bufferevent_write(bev, data, size);
416 * Encode and write an extended key escape sequence in one of the two
417 * possible formats, depending on the configured output mode.
419 static int
420 input_key_extended(struct bufferevent *bev, key_code key)
422 char tmp[64], modifier;
423 struct utf8_data ud;
424 wchar_t wc;
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);
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;
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);
466 input_key_write(__func__, bev, tmp, strlen(tmp));
467 return (0);
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.
475 static int
476 input_key_vt10x(struct bufferevent *bev, key_code key)
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",
486 log_debug("%s: key in %llx", __func__, key);
488 if (key & KEYC_META)
489 input_key_write(__func__, bev, "\033", 1);
492 * There's no way to report modifiers for unicode keys in standard mode
493 * so lose the modifiers.
495 if (KEYC_IS_UNICODE(key)) {
496 utf8_to_data(key, &ud);
497 input_key_write(__func__, bev, ud.data, ud.size);
498 return (0);
502 * Prevent TAB, CR and LF from being swallowed by the C0 remapping
503 * logic.
505 onlykey = key & KEYC_MASK_KEY;
506 if (onlykey == '\r' || onlykey == '\n' || onlykey == '\t')
507 key &= ~KEYC_CTRL;
510 * Convert keys with Ctrl modifier into corresponding C0 control codes,
511 * with the exception of *some* keys, which are remapped into printable
512 * ASCII characters.
514 * There is no special handling for Shift modifier, which is pretty
515 * much redundant anyway, as no terminal will send <base key>|SHIFT,
516 * but only <shifted key>|SHIFT.
518 if (key & KEYC_CTRL) {
519 p = strchr(standard_map[0], onlykey);
520 if (p != NULL)
521 key = standard_map[1][p - standard_map[0]];
522 else if (onlykey >= '3' && onlykey <= '7')
523 key = onlykey - '\030';
524 else if (onlykey >= '@' && onlykey <= '~')
525 key = onlykey & 0x1f;
526 else
527 return (-1);
530 log_debug("%s: key out %llx", __func__, key);
532 ud.data[0] = key & 0x7f;
533 input_key_write(__func__, bev, &ud.data[0], 1);
534 return (0);
537 /* Pick keys that are reported as vt10x keys in modifyOtherKeys=1 mode. */
538 static int
539 input_key_mode1(struct bufferevent *bev, key_code key)
541 key_code onlykey;
543 log_debug("%s: key in %llx", __func__, key);
546 * As per
547 * https://invisible-island.net/xterm/modified-keys-us-pc105.html.
549 onlykey = key & KEYC_MASK_KEY;
550 if ((key & (KEYC_META | KEYC_CTRL)) == KEYC_CTRL &&
551 (onlykey == ' ' ||
552 onlykey == '/' ||
553 onlykey == '@' ||
554 onlykey == '^' ||
555 (onlykey >= '2' && onlykey <= '8') ||
556 (onlykey >= '@' && onlykey <= '~')))
557 return (input_key_vt10x(bev, key));
560 * A regular key + Meta. In the absence of a standard to back this, we
561 * mimic what iTerm 2 does.
563 if ((key & (KEYC_CTRL | KEYC_META)) == KEYC_META)
564 return (input_key_vt10x(bev, key));
566 return (-1);
569 /* Translate a key code into an output key sequence. */
571 input_key(struct screen *s, struct bufferevent *bev, key_code key)
573 struct input_key_entry *ike = NULL;
574 key_code newkey;
575 struct utf8_data ud;
577 /* Mouse keys need a pane. */
578 if (KEYC_IS_MOUSE(key))
579 return (0);
581 /* Literal keys go as themselves (can't be more than eight bits). */
582 if (key & KEYC_LITERAL) {
583 ud.data[0] = (u_char)key;
584 input_key_write(__func__, bev, &ud.data[0], 1);
585 return (0);
588 /* Is this backspace? */
589 if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
590 newkey = options_get_number(global_options, "backspace");
591 if (newkey >= 0x7f)
592 newkey = '\177';
593 key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS));
596 /* Is this backtab? */
597 if ((key & KEYC_MASK_KEY) == KEYC_BTAB) {
598 if ((s->mode & EXTENDED_KEY_MODES) != 0) {
599 /* When in xterm extended mode, remap into S-Tab. */
600 key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT;
601 } else {
602 /* Otherwise clear modifiers. */
603 key &= ~KEYC_MASK_MODIFIERS;
608 * A trivial case, that is a 7-bit key, excluding C0 control characters
609 * that can't be entered from the keyboard, and no modifiers; or a UTF-8
610 * key and no modifiers.
612 if (!(key & ~KEYC_MASK_KEY)) {
613 if (key == C0_HT ||
614 key == C0_CR ||
615 key == C0_ESC ||
616 (key >= 0x20 && key <= 0x7f)) {
617 ud.data[0] = key;
618 input_key_write(__func__, bev, &ud.data[0], 1);
619 return (0);
621 if (KEYC_IS_UNICODE(key)) {
622 utf8_to_data(key, &ud);
623 input_key_write(__func__, bev, ud.data, ud.size);
624 return (0);
629 * Look up the standard VT10x keys in the tree. If not in application
630 * keypad or cursor mode, remove the respective flags from the key.
632 if (~s->mode & MODE_KKEYPAD)
633 key &= ~KEYC_KEYPAD;
634 if (~s->mode & MODE_KCURSOR)
635 key &= ~KEYC_CURSOR;
636 if (ike == NULL)
637 ike = input_key_get(key);
638 if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META))
639 ike = input_key_get(key & ~KEYC_META);
640 if (ike == NULL && (key & KEYC_CURSOR))
641 ike = input_key_get(key & ~KEYC_CURSOR);
642 if (ike == NULL && (key & KEYC_KEYPAD))
643 ike = input_key_get(key & ~KEYC_KEYPAD);
644 if (ike != NULL) {
645 log_debug("%s: found key 0x%llx: \"%s\"", __func__, key,
646 ike->data);
647 if ((key == KEYC_PASTE_START || key == KEYC_PASTE_END) &&
648 (~s->mode & MODE_BRACKETPASTE))
649 return (0);
650 if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
651 input_key_write(__func__, bev, "\033", 1);
652 input_key_write(__func__, bev, ike->data, strlen(ike->data));
653 return (0);
656 /* Ignore internal function key codes. */
657 if ((key >= KEYC_BASE && key < KEYC_BASE_END) ||
658 (key >= KEYC_USER && key < KEYC_USER_END)) {
659 log_debug("%s: ignoring key 0x%llx", __func__, key);
660 return (0);
664 * No builtin key sequence; construct an extended key sequence
665 * depending on the client mode.
667 * If something invalid reaches here, an invalid output may be
668 * produced. For example Ctrl-Shift-2 is invalid (as there's
669 * no way to enter it). The correct form is Ctrl-Shift-@, at
670 * least in US English keyboard layout.
672 switch (s->mode & EXTENDED_KEY_MODES) {
673 case MODE_KEYS_EXTENDED_2:
675 * The simplest mode to handle - *all* modified keys are
676 * reported in the extended form.
678 return (input_key_extended(bev, key));
679 case MODE_KEYS_EXTENDED:
681 * Some keys are still reported in standard mode, to maintain
682 * compatibility with applications unaware of extended keys.
684 if (input_key_mode1(bev, key) == -1)
685 return (input_key_extended(bev, key));
686 return (0);
687 default:
688 /* The standard mode. */
689 return (input_key_vt10x(bev, key));
693 /* Get mouse event string. */
695 input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
696 const char **rbuf, size_t *rlen)
698 static char buf[40];
699 size_t len;
701 *rbuf = NULL;
702 *rlen = 0;
704 /* If this pane is not in button or all mode, discard motion events. */
705 if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0)
706 return (0);
707 if ((s->mode & ALL_MOUSE_MODES) == 0)
708 return (0);
711 * If this event is a release event and not in all mode, discard it.
712 * In SGR mode we can tell absolutely because a release is normally
713 * shown by the last character. Without SGR, we check if the last
714 * buttons was also a release.
716 if (m->sgr_type != ' ') {
717 if (MOUSE_DRAG(m->sgr_b) &&
718 MOUSE_RELEASE(m->sgr_b) &&
719 (~s->mode & MODE_MOUSE_ALL))
720 return (0);
721 } else {
722 if (MOUSE_DRAG(m->b) &&
723 MOUSE_RELEASE(m->b) &&
724 MOUSE_RELEASE(m->lb) &&
725 (~s->mode & MODE_MOUSE_ALL))
726 return (0);
730 * Use the SGR (1006) extension only if the application requested it
731 * and the underlying terminal also sent the event in this format (this
732 * is because an old style mouse release event cannot be converted into
733 * the new SGR format, since the released button is unknown). Otherwise
734 * pretend that tmux doesn't speak this extension, and fall back to the
735 * UTF-8 (1005) extension if the application requested, or to the
736 * legacy format.
738 if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
739 len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
740 m->sgr_b, x + 1, y + 1, m->sgr_type);
741 } else if (s->mode & MODE_MOUSE_UTF8) {
742 if (m->b > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_BTN_OFF ||
743 x > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF ||
744 y > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF)
745 return (0);
746 len = xsnprintf(buf, sizeof buf, "\033[M");
747 len += input_key_split2(m->b + MOUSE_PARAM_BTN_OFF, &buf[len]);
748 len += input_key_split2(x + MOUSE_PARAM_POS_OFF, &buf[len]);
749 len += input_key_split2(y + MOUSE_PARAM_POS_OFF, &buf[len]);
750 } else {
751 if (m->b + MOUSE_PARAM_BTN_OFF > MOUSE_PARAM_MAX)
752 return (0);
754 len = xsnprintf(buf, sizeof buf, "\033[M");
755 buf[len++] = m->b + MOUSE_PARAM_BTN_OFF;
758 * The incoming x and y may be out of the range which can be
759 * supported by the "normal" mouse protocol. Clamp the
760 * coordinates to the supported range.
762 if (x + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
763 buf[len++] = MOUSE_PARAM_MAX;
764 else
765 buf[len++] = x + MOUSE_PARAM_POS_OFF;
766 if (y + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
767 buf[len++] = MOUSE_PARAM_MAX;
768 else
769 buf[len++] = y + MOUSE_PARAM_POS_OFF;
772 *rbuf = buf;
773 *rlen = len;
774 return (1);
777 /* Translate mouse and output. */
778 static void
779 input_key_mouse(struct window_pane *wp, struct mouse_event *m)
781 struct screen *s = wp->screen;
782 u_int x, y;
783 const char *buf;
784 size_t len;
786 /* Ignore events if no mouse mode or the pane is not visible. */
787 if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0)
788 return;
789 if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
790 return;
791 if (!window_pane_visible(wp))
792 return;
793 if (!input_key_get_mouse(s, m, x, y, &buf, &len))
794 return;
795 log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
796 input_key_write(__func__, wp->event, buf, len);