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
input_key_cmp(struct input_key_entry * ike1,struct input_key_entry * ike2)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 *
input_key_get(key_code key)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
input_key_split2(u_int c,char * dst)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
input_key_build(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
input_key_pane(struct window_pane * wp,key_code key,struct mouse_event * m)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
input_key_write(const char * from,struct bufferevent * bev,const char * data,size_t size)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
input_key_extended(struct bufferevent * bev,key_code key)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
input_key_vt10x(struct bufferevent * bev,key_code key)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
input_key_mode1(struct bufferevent * bev,key_code key)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
input_key(struct screen * s,struct bufferevent * bev,key_code key)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
input_key_get_mouse(struct screen * s,struct mouse_event * m,u_int x,u_int y,const char ** rbuf,size_t * rlen)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
input_key_mouse(struct window_pane * wp,struct mouse_event * m)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