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