Annotation of src/usr.bin/tmux/input-keys.c, Revision 1.89
1.89 ! nicm 1: /* $OpenBSD: input-keys.c,v 1.88 2022/02/28 09:24:22 nicm Exp $ */
1.1 nicm 2:
3: /*
1.53 nicm 4: * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 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:
1.8 nicm 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:
1.56 nicm 34: static void input_key_mouse(struct window_pane *, struct mouse_event *);
1.42 nicm 35:
1.72 nicm 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;
1.1 nicm 42: };
1.72 nicm 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);
1.1 nicm 50:
1.72 nicm 51: /* List of default keys, the tree is built from this. */
52: static struct input_key_entry input_key_defaults[] = {
1.61 nicm 53: /* Paste keys. */
1.72 nicm 54: { .key = KEYC_PASTE_START,
55: .data = "\033[200~"
56: },
57: { .key = KEYC_PASTE_END,
58: .data = "\033[201~"
59: },
1.3 nicm 60:
1.1 nicm 61: /* Function keys. */
1.72 nicm 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. */
1.74 nicm 245: { .key = KEYC_F1|KEYC_BUILD_MODIFIERS,
1.72 nicm 246: .data = "\033[1;_P"
247: },
1.74 nicm 248: { .key = KEYC_F2|KEYC_BUILD_MODIFIERS,
1.72 nicm 249: .data = "\033[1;_Q"
250: },
1.74 nicm 251: { .key = KEYC_F3|KEYC_BUILD_MODIFIERS,
1.72 nicm 252: .data = "\033[1;_R"
253: },
1.74 nicm 254: { .key = KEYC_F4|KEYC_BUILD_MODIFIERS,
1.72 nicm 255: .data = "\033[1;_S"
256: },
1.74 nicm 257: { .key = KEYC_F5|KEYC_BUILD_MODIFIERS,
1.72 nicm 258: .data = "\033[15;_~"
259: },
1.74 nicm 260: { .key = KEYC_F6|KEYC_BUILD_MODIFIERS,
1.72 nicm 261: .data = "\033[17;_~"
262: },
1.74 nicm 263: { .key = KEYC_F7|KEYC_BUILD_MODIFIERS,
1.72 nicm 264: .data = "\033[18;_~"
265: },
1.74 nicm 266: { .key = KEYC_F8|KEYC_BUILD_MODIFIERS,
1.72 nicm 267: .data = "\033[19;_~"
268: },
1.74 nicm 269: { .key = KEYC_F9|KEYC_BUILD_MODIFIERS,
1.72 nicm 270: .data = "\033[20;_~"
271: },
1.74 nicm 272: { .key = KEYC_F10|KEYC_BUILD_MODIFIERS,
1.72 nicm 273: .data = "\033[21;_~"
274: },
1.74 nicm 275: { .key = KEYC_F11|KEYC_BUILD_MODIFIERS,
1.72 nicm 276: .data = "\033[23;_~"
277: },
1.74 nicm 278: { .key = KEYC_F12|KEYC_BUILD_MODIFIERS,
1.72 nicm 279: .data = "\033[24;_~"
280: },
1.74 nicm 281: { .key = KEYC_UP|KEYC_BUILD_MODIFIERS,
1.72 nicm 282: .data = "\033[1;_A"
283: },
1.74 nicm 284: { .key = KEYC_DOWN|KEYC_BUILD_MODIFIERS,
1.72 nicm 285: .data = "\033[1;_B"
286: },
1.74 nicm 287: { .key = KEYC_RIGHT|KEYC_BUILD_MODIFIERS,
1.72 nicm 288: .data = "\033[1;_C"
289: },
1.74 nicm 290: { .key = KEYC_LEFT|KEYC_BUILD_MODIFIERS,
1.72 nicm 291: .data = "\033[1;_D"
292: },
1.74 nicm 293: { .key = KEYC_HOME|KEYC_BUILD_MODIFIERS,
1.72 nicm 294: .data = "\033[1;_H"
295: },
1.74 nicm 296: { .key = KEYC_END|KEYC_BUILD_MODIFIERS,
1.72 nicm 297: .data = "\033[1;_F"
298: },
1.74 nicm 299: { .key = KEYC_PPAGE|KEYC_BUILD_MODIFIERS,
1.72 nicm 300: .data = "\033[5;_~"
301: },
1.74 nicm 302: { .key = KEYC_NPAGE|KEYC_BUILD_MODIFIERS,
1.72 nicm 303: .data = "\033[6;_~"
304: },
1.74 nicm 305: { .key = KEYC_IC|KEYC_BUILD_MODIFIERS,
1.72 nicm 306: .data = "\033[2;_~"
307: },
1.74 nicm 308: { .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
1.81 nicm 309: .data = "\033[3;_~"
310: }
1.72 nicm 311: };
312: static const key_code input_key_modifiers[] = {
313: 0,
314: 0,
1.74 nicm 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
1.72 nicm 322: };
1.7 nicm 323:
1.72 nicm 324: /* Input key comparison function. */
325: static int
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: }
1.1 nicm 334:
1.74 nicm 335: /* Look for key in tree. */
336: static struct input_key_entry *
1.86 nicm 337: input_key_get(key_code key)
1.74 nicm 338: {
339: struct input_key_entry entry = { .key = key };
340:
341: return (RB_FIND(input_key_tree, &input_key_tree, &entry));
342: }
343:
1.54 nicm 344: /* Split a character into two UTF-8 bytes. */
345: static size_t
1.72 nicm 346: input_key_split2(u_int c, u_char *dst)
1.54 nicm 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:
1.72 nicm 357: /* Build input key tree. */
358: void
359: input_key_build(void)
360: {
361: struct input_key_entry *ike, *new;
362: u_int i, j;
363: char *data;
1.74 nicm 364: key_code key;
1.72 nicm 365:
366: for (i = 0; i < nitems(input_key_defaults); i++) {
367: ike = &input_key_defaults[i];
1.74 nicm 368: if (~ike->key & KEYC_BUILD_MODIFIERS) {
1.72 nicm 369: RB_INSERT(input_key_tree, &input_key_tree, ike);
370: continue;
371: }
372:
373: for (j = 2; j < nitems(input_key_modifiers); j++) {
1.74 nicm 374: key = (ike->key & ~KEYC_BUILD_MODIFIERS);
1.72 nicm 375: data = xstrdup(ike->data);
376: data[strcspn(data, "_")] = '0' + j;
377:
378: new = xcalloc(1, sizeof *new);
1.74 nicm 379: new->key = key|input_key_modifiers[j];
1.72 nicm 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,
1.74 nicm 387: key_string_lookup_key(ike->key, 1), ike->data);
1.72 nicm 388: }
389: }
390:
1.69 nicm 391: /* Translate a key code into an output key sequence for a pane. */
392: int
393: input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
394: {
1.72 nicm 395: if (log_get_level() != 0) {
396: log_debug("writing key 0x%llx (%s) to %%%u", key,
1.74 nicm 397: key_string_lookup_key(key, 1), wp->id);
1.72 nicm 398: }
1.69 nicm 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: }
1.72 nicm 405: return (input_key(wp->screen, wp->event, key));
1.69 nicm 406: }
407:
1.82 nicm 408: static void
1.83 nicm 409: input_key_write(const char *from, struct bufferevent *bev, const char *data,
1.82 nicm 410: size_t size)
411: {
412: log_debug("%s: %.*s", from, (int)size, data);
413: bufferevent_write(bev, data, size);
414: }
415:
1.8 nicm 416: /* Translate a key code into an output key sequence. */
1.67 nicm 417: int
1.72 nicm 418: input_key(struct screen *s, struct bufferevent *bev, key_code key)
1.1 nicm 419: {
1.74 nicm 420: struct input_key_entry *ike;
1.88 nicm 421: key_code justkey, newkey, outkey, modifiers;
1.72 nicm 422: struct utf8_data ud;
1.75 nicm 423: char tmp[64], modifier;
1.1 nicm 424:
1.69 nicm 425: /* Mouse keys need a pane. */
426: if (KEYC_IS_MOUSE(key))
1.67 nicm 427: return (0);
1.64 nicm 428:
429: /* Literal keys go as themselves (can't be more than eight bits). */
430: if (key & KEYC_LITERAL) {
431: ud.data[0] = (u_char)key;
1.82 nicm 432: input_key_write(__func__, bev, &ud.data[0], 1);
1.67 nicm 433: return (0);
1.65 nicm 434: }
435:
436: /* Is this backspace? */
437: if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
1.66 nicm 438: newkey = options_get_number(global_options, "backspace");
439: if (newkey >= 0x7f)
440: newkey = '\177';
1.74 nicm 441: key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS));
1.42 nicm 442: }
1.1 nicm 443:
1.8 nicm 444: /*
445: * If this is a normal 7-bit key, just send it, with a leading escape
1.46 nicm 446: * if necessary. If it is a UTF-8 key, split it and send it.
1.8 nicm 447: */
1.75 nicm 448: justkey = (key & ~(KEYC_META|KEYC_IMPLIED_META));
1.52 nicm 449: if (justkey <= 0x7f) {
1.73 nicm 450: if (key & KEYC_META)
1.82 nicm 451: input_key_write(__func__, bev, "\033", 1);
1.47 nicm 452: ud.data[0] = justkey;
1.82 nicm 453: input_key_write(__func__, bev, &ud.data[0], 1);
1.67 nicm 454: return (0);
1.46 nicm 455: }
1.84 nicm 456: if (KEYC_IS_UNICODE(justkey)) {
1.73 nicm 457: if (key & KEYC_META)
1.82 nicm 458: input_key_write(__func__, bev, "\033", 1);
1.78 nicm 459: utf8_to_data(justkey, &ud);
1.82 nicm 460: input_key_write(__func__, bev, ud.data, ud.size);
1.67 nicm 461: return (0);
1.12 nicm 462: }
463:
1.18 nicm 464: /*
1.72 nicm 465: * Look up in the tree. If not in application keypad or cursor mode,
466: * remove the flags from the key.
1.12 nicm 467: */
1.72 nicm 468: if (~s->mode & MODE_KKEYPAD)
469: key &= ~KEYC_KEYPAD;
470: if (~s->mode & MODE_KCURSOR)
471: key &= ~KEYC_CURSOR;
1.74 nicm 472: ike = input_key_get(key);
473: if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META))
474: ike = input_key_get(key & ~KEYC_META);
1.79 nicm 475: if (ike == NULL && (key & KEYC_CURSOR))
476: ike = input_key_get(key & ~KEYC_CURSOR);
477: if (ike == NULL && (key & KEYC_KEYPAD))
478: ike = input_key_get(key & ~KEYC_KEYPAD);
1.75 nicm 479: if (ike != NULL) {
480: log_debug("found key 0x%llx: \"%s\"", key, ike->data);
1.79 nicm 481: if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
1.82 nicm 482: input_key_write(__func__, bev, "\033", 1);
483: input_key_write(__func__, bev, ike->data, strlen(ike->data));
1.75 nicm 484: return (0);
1.1 nicm 485: }
486:
1.75 nicm 487: /* No builtin key sequence; construct an extended key sequence. */
1.76 nicm 488: if (~s->mode & MODE_KEXTENDED) {
1.77 nicm 489: if ((key & KEYC_MASK_MODIFIERS) != KEYC_CTRL)
490: goto missing;
1.79 nicm 491: justkey = (key & KEYC_MASK_KEY);
1.77 nicm 492: switch (justkey) {
493: case ' ':
494: case '2':
1.79 nicm 495: key = 0|(key & ~KEYC_MASK_KEY);
1.77 nicm 496: break;
497: case '|':
498: key = 28|(key & ~KEYC_MASK_KEY);
499: break;
500: case '6':
501: key = 30|(key & ~KEYC_MASK_KEY);
502: break;
503: case '-':
504: case '/':
505: key = 31|(key & ~KEYC_MASK_KEY);
506: break;
507: case '?':
508: key = 127|(key & ~KEYC_MASK_KEY);
509: break;
510: default:
511: if (justkey >= 'A' && justkey <= '_')
512: key = (justkey - 'A')|(key & ~KEYC_MASK_KEY);
513: else if (justkey >= 'a' && justkey <= '~')
514: key = (justkey - 96)|(key & ~KEYC_MASK_KEY);
1.79 nicm 515: else
516: return (0);
1.77 nicm 517: break;
518: }
519: return (input_key(s, bev, key & ~KEYC_CTRL));
1.76 nicm 520: }
1.75 nicm 521: outkey = (key & KEYC_MASK_KEY);
1.88 nicm 522: modifiers = (key & KEYC_MASK_MODIFIERS);
1.89 ! nicm 523: if (outkey < 32 && outkey != 9 && outkey != 13 && outkey != 27) {
1.88 nicm 524: outkey = 64 + outkey;
525: modifiers |= KEYC_CTRL;
526: }
527: switch (modifiers) {
1.75 nicm 528: case KEYC_SHIFT:
529: modifier = '2';
530: break;
531: case KEYC_META:
532: modifier = '3';
533: break;
534: case KEYC_SHIFT|KEYC_META:
535: modifier = '4';
536: break;
537: case KEYC_CTRL:
538: modifier = '5';
539: break;
540: case KEYC_SHIFT|KEYC_CTRL:
541: modifier = '6';
542: break;
543: case KEYC_META|KEYC_CTRL:
544: modifier = '7';
545: break;
546: case KEYC_SHIFT|KEYC_META|KEYC_CTRL:
547: modifier = '8';
548: break;
1.80 nicm 549: default:
1.81 nicm 550: goto missing;
1.75 nicm 551: }
552: xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier);
1.82 nicm 553: input_key_write(__func__, bev, tmp, strlen(tmp));
1.67 nicm 554: return (0);
1.75 nicm 555:
556: missing:
557: log_debug("key 0x%llx missing", key);
558: return (-1);
1.1 nicm 559: }
560:
1.70 nicm 561: /* Get mouse event string. */
562: int
563: input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
564: const char **rbuf, size_t *rlen)
1.1 nicm 565: {
1.70 nicm 566: static char buf[40];
1.59 nicm 567: size_t len;
1.42 nicm 568:
1.70 nicm 569: *rbuf = NULL;
570: *rlen = 0;
1.24 nicm 571:
1.59 nicm 572: /* If this pane is not in button or all mode, discard motion events. */
1.68 nicm 573: if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0)
1.71 nicm 574: return (0);
575: if ((s->mode & ALL_MOUSE_MODES) == 0)
1.70 nicm 576: return (0);
1.59 nicm 577:
578: /*
579: * If this event is a release event and not in all mode, discard it.
580: * In SGR mode we can tell absolutely because a release is normally
581: * shown by the last character. Without SGR, we check if the last
582: * buttons was also a release.
583: */
584: if (m->sgr_type != ' ') {
585: if (MOUSE_DRAG(m->sgr_b) &&
1.87 nicm 586: MOUSE_RELEASE(m->sgr_b) &&
1.68 nicm 587: (~s->mode & MODE_MOUSE_ALL))
1.70 nicm 588: return (0);
1.59 nicm 589: } else {
590: if (MOUSE_DRAG(m->b) &&
1.87 nicm 591: MOUSE_RELEASE(m->b) &&
592: MOUSE_RELEASE(m->lb) &&
1.68 nicm 593: (~s->mode & MODE_MOUSE_ALL))
1.70 nicm 594: return (0);
1.59 nicm 595: }
1.42 nicm 596:
597: /*
598: * Use the SGR (1006) extension only if the application requested it
599: * and the underlying terminal also sent the event in this format (this
600: * is because an old style mouse release event cannot be converted into
601: * the new SGR format, since the released button is unknown). Otherwise
602: * pretend that tmux doesn't speak this extension, and fall back to the
1.51 nicm 603: * UTF-8 (1005) extension if the application requested, or to the
1.42 nicm 604: * legacy format.
605: */
1.59 nicm 606: if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
1.42 nicm 607: len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
608: m->sgr_b, x + 1, y + 1, m->sgr_type);
1.59 nicm 609: } else if (s->mode & MODE_MOUSE_UTF8) {
1.55 nicm 610: if (m->b > 0x7ff - 32 || x > 0x7ff - 33 || y > 0x7ff - 33)
1.70 nicm 611: return (0);
1.51 nicm 612: len = xsnprintf(buf, sizeof buf, "\033[M");
1.72 nicm 613: len += input_key_split2(m->b + 32, &buf[len]);
614: len += input_key_split2(x + 33, &buf[len]);
615: len += input_key_split2(y + 33, &buf[len]);
1.42 nicm 616: } else {
617: if (m->b > 223)
1.70 nicm 618: return (0);
1.42 nicm 619: len = xsnprintf(buf, sizeof buf, "\033[M");
620: buf[len++] = m->b + 32;
621: buf[len++] = x + 33;
622: buf[len++] = y + 33;
1.1 nicm 623: }
1.70 nicm 624:
625: *rbuf = buf;
626: *rlen = len;
627: return (1);
628: }
629:
630: /* Translate mouse and output. */
631: static void
632: input_key_mouse(struct window_pane *wp, struct mouse_event *m)
633: {
634: struct screen *s = wp->screen;
635: u_int x, y;
636: const char *buf;
637: size_t len;
638:
639: /* Ignore events if no mouse mode or the pane is not visible. */
640: if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0)
641: return;
642: if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
643: return;
644: if (!window_pane_visible(wp))
645: return;
646: if (!input_key_get_mouse(s, m, x, y, &buf, &len))
647: return;
1.44 nicm 648: log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
1.82 nicm 649: input_key_write(__func__, wp->event, buf, len);
1.1 nicm 650: }