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