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_F1|KEYC_SHIFT, 98 .data = "\033[25~" 99 }, 100 { .key = KEYC_F2|KEYC_SHIFT, 101 .data = "\033[26~" 102 }, 103 { .key = KEYC_F3|KEYC_SHIFT, 104 .data = "\033[28~" 105 }, 106 { .key = KEYC_F4|KEYC_SHIFT, 107 .data = "\033[29~" 108 }, 109 { .key = KEYC_F5|KEYC_SHIFT, 110 .data = "\033[31~" 111 }, 112 { .key = KEYC_F6|KEYC_SHIFT, 113 .data = "\033[32~" 114 }, 115 { .key = KEYC_F7|KEYC_SHIFT, 116 .data = "\033[33~" 117 }, 118 { .key = KEYC_F8|KEYC_SHIFT, 119 .data = "\033[34~" 120 }, 121 { .key = KEYC_IC, 122 .data = "\033[2~" 123 }, 124 { .key = KEYC_DC, 125 .data = "\033[3~" 126 }, 127 { .key = KEYC_HOME, 128 .data = "\033[1~" 129 }, 130 { .key = KEYC_END, 131 .data = "\033[4~" 132 }, 133 { .key = KEYC_NPAGE, 134 .data = "\033[6~" 135 }, 136 { .key = KEYC_PPAGE, 137 .data = "\033[5~" 138 }, 139 { .key = KEYC_BTAB, 140 .data = "\033[Z" 141 }, 142 143 /* Arrow keys. */ 144 { .key = KEYC_UP|KEYC_CURSOR, 145 .data = "\033OA" 146 }, 147 { .key = KEYC_DOWN|KEYC_CURSOR, 148 .data = "\033OB" 149 }, 150 { .key = KEYC_RIGHT|KEYC_CURSOR, 151 .data = "\033OC" 152 }, 153 { .key = KEYC_LEFT|KEYC_CURSOR, 154 .data = "\033OD" 155 }, 156 { .key = KEYC_UP, 157 .data = "\033[A" 158 }, 159 { .key = KEYC_DOWN, 160 .data = "\033[B" 161 }, 162 { .key = KEYC_RIGHT, 163 .data = "\033[C" 164 }, 165 { .key = KEYC_LEFT, 166 .data = "\033[D" 167 }, 168 169 /* Keypad keys. */ 170 { .key = KEYC_KP_SLASH|KEYC_KEYPAD, 171 .data = "\033Oo" 172 }, 173 { .key = KEYC_KP_STAR|KEYC_KEYPAD, 174 .data = "\033Oj" 175 }, 176 { .key = KEYC_KP_MINUS|KEYC_KEYPAD, 177 .data = "\033Om" 178 }, 179 { .key = KEYC_KP_SEVEN|KEYC_KEYPAD, 180 .data = "\033Ow" 181 }, 182 { .key = KEYC_KP_EIGHT|KEYC_KEYPAD, 183 .data = "\033Ox" 184 }, 185 { .key = KEYC_KP_NINE|KEYC_KEYPAD, 186 .data = "\033Oy" 187 }, 188 { .key = KEYC_KP_PLUS|KEYC_KEYPAD, 189 .data = "\033Ok" 190 }, 191 { .key = KEYC_KP_FOUR|KEYC_KEYPAD, 192 .data = "\033Ot" 193 }, 194 { .key = KEYC_KP_FIVE|KEYC_KEYPAD, 195 .data = "\033Ou" 196 }, 197 { .key = KEYC_KP_SIX|KEYC_KEYPAD, 198 .data = "\033Ov" 199 }, 200 { .key = KEYC_KP_ONE|KEYC_KEYPAD, 201 .data = "\033Oq" 202 }, 203 { .key = KEYC_KP_TWO|KEYC_KEYPAD, 204 .data = "\033Or" 205 }, 206 { .key = KEYC_KP_THREE|KEYC_KEYPAD, 207 .data = "\033Os" 208 }, 209 { .key = KEYC_KP_ENTER|KEYC_KEYPAD, 210 .data = "\033OM" 211 }, 212 { .key = KEYC_KP_ZERO|KEYC_KEYPAD, 213 .data = "\033Op" 214 }, 215 { .key = KEYC_KP_PERIOD|KEYC_KEYPAD, 216 .data = "\033On" 217 }, 218 { .key = KEYC_KP_SLASH, 219 .data = "/" 220 }, 221 { .key = KEYC_KP_STAR, 222 .data = "*" 223 }, 224 { .key = KEYC_KP_MINUS, 225 .data = "-" 226 }, 227 { .key = KEYC_KP_SEVEN, 228 .data = "7" 229 }, 230 { .key = KEYC_KP_EIGHT, 231 .data = "8" 232 }, 233 { .key = KEYC_KP_NINE, 234 .data = "9" 235 }, 236 { .key = KEYC_KP_PLUS, 237 .data = "+" 238 }, 239 { .key = KEYC_KP_FOUR, 240 .data = "4" 241 }, 242 { .key = KEYC_KP_FIVE, 243 .data = "5" 244 }, 245 { .key = KEYC_KP_SIX, 246 .data = "6" 247 }, 248 { .key = KEYC_KP_ONE, 249 .data = "1" 250 }, 251 { .key = KEYC_KP_TWO, 252 .data = "2" 253 }, 254 { .key = KEYC_KP_THREE, 255 .data = "3" 256 }, 257 { .key = KEYC_KP_ENTER, 258 .data = "\n" 259 }, 260 { .key = KEYC_KP_ZERO, 261 .data = "0" 262 }, 263 { .key = KEYC_KP_PERIOD, 264 .data = "." 265 }, 266 267 /* Keys with an embedded modifier. */ 268 { .key = KEYC_F1|KEYC_BUILD_MODIFIERS, 269 .data = "\033[1;_P" 270 }, 271 { .key = KEYC_F2|KEYC_BUILD_MODIFIERS, 272 .data = "\033[1;_Q" 273 }, 274 { .key = KEYC_F3|KEYC_BUILD_MODIFIERS, 275 .data = "\033[1;_R" 276 }, 277 { .key = KEYC_F4|KEYC_BUILD_MODIFIERS, 278 .data = "\033[1;_S" 279 }, 280 { .key = KEYC_F5|KEYC_BUILD_MODIFIERS, 281 .data = "\033[15;_~" 282 }, 283 { .key = KEYC_F6|KEYC_BUILD_MODIFIERS, 284 .data = "\033[17;_~" 285 }, 286 { .key = KEYC_F7|KEYC_BUILD_MODIFIERS, 287 .data = "\033[18;_~" 288 }, 289 { .key = KEYC_F8|KEYC_BUILD_MODIFIERS, 290 .data = "\033[19;_~" 291 }, 292 { .key = KEYC_F9|KEYC_BUILD_MODIFIERS, 293 .data = "\033[20;_~" 294 }, 295 { .key = KEYC_F10|KEYC_BUILD_MODIFIERS, 296 .data = "\033[21;_~" 297 }, 298 { .key = KEYC_F11|KEYC_BUILD_MODIFIERS, 299 .data = "\033[23;_~" 300 }, 301 { .key = KEYC_F12|KEYC_BUILD_MODIFIERS, 302 .data = "\033[24;_~" 303 }, 304 { .key = KEYC_UP|KEYC_BUILD_MODIFIERS, 305 .data = "\033[1;_A" 306 }, 307 { .key = KEYC_DOWN|KEYC_BUILD_MODIFIERS, 308 .data = "\033[1;_B" 309 }, 310 { .key = KEYC_RIGHT|KEYC_BUILD_MODIFIERS, 311 .data = "\033[1;_C" 312 }, 313 { .key = KEYC_LEFT|KEYC_BUILD_MODIFIERS, 314 .data = "\033[1;_D" 315 }, 316 { .key = KEYC_HOME|KEYC_BUILD_MODIFIERS, 317 .data = "\033[1;_H" 318 }, 319 { .key = KEYC_END|KEYC_BUILD_MODIFIERS, 320 .data = "\033[1;_F" 321 }, 322 { .key = KEYC_PPAGE|KEYC_BUILD_MODIFIERS, 323 .data = "\033[5;_~" 324 }, 325 { .key = KEYC_NPAGE|KEYC_BUILD_MODIFIERS, 326 .data = "\033[6;_~" 327 }, 328 { .key = KEYC_IC|KEYC_BUILD_MODIFIERS, 329 .data = "\033[2;_~" 330 }, 331 { .key = KEYC_DC|KEYC_BUILD_MODIFIERS, 332 .data = "\033[3;_~" 333 } 334 }; 335 static const key_code input_key_modifiers[] = { 336 0, 337 0, 338 KEYC_SHIFT, 339 KEYC_META|KEYC_IMPLIED_META, 340 KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META, 341 KEYC_CTRL, 342 KEYC_SHIFT|KEYC_CTRL, 343 KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL, 344 KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL 345 }; 346 347 /* Input key comparison function. */ 348 static int 349 input_key_cmp(struct input_key_entry *ike1, struct input_key_entry *ike2) 350 { 351 if (ike1->key < ike2->key) 352 return (-1); 353 if (ike1->key > ike2->key) 354 return (1); 355 return (0); 356 } 357 358 /* Look for key in tree. */ 359 static struct input_key_entry * 360 input_key_get (key_code key) 361 { 362 struct input_key_entry entry = { .key = key }; 363 364 return (RB_FIND(input_key_tree, &input_key_tree, &entry)); 365 } 366 367 /* Split a character into two UTF-8 bytes. */ 368 static size_t 369 input_key_split2(u_int c, char *dst) 370 { 371 if (c > 0x7f) { 372 dst[0] = (c >> 6) | 0xc0; 373 dst[1] = (c & 0x3f) | 0x80; 374 return (2); 375 } 376 dst[0] = c; 377 return (1); 378 } 379 380 /* Build input key tree. */ 381 void 382 input_key_build(void) 383 { 384 struct input_key_entry *ike, *new; 385 u_int i, j; 386 char *data; 387 key_code key; 388 389 for (i = 0; i < nitems(input_key_defaults); i++) { 390 ike = &input_key_defaults[i]; 391 if (~ike->key & KEYC_BUILD_MODIFIERS) { 392 RB_INSERT(input_key_tree, &input_key_tree, ike); 393 continue; 394 } 395 396 for (j = 2; j < nitems(input_key_modifiers); j++) { 397 key = (ike->key & ~KEYC_BUILD_MODIFIERS); 398 data = xstrdup(ike->data); 399 data[strcspn(data, "_")] = '0' + j; 400 401 new = xcalloc(1, sizeof *new); 402 new->key = key|input_key_modifiers[j]; 403 new->data = data; 404 RB_INSERT(input_key_tree, &input_key_tree, new); 405 } 406 } 407 408 RB_FOREACH(ike, input_key_tree, &input_key_tree) { 409 log_debug("%s: 0x%llx (%s) is %s", __func__, ike->key, 410 key_string_lookup_key(ike->key, 1), ike->data); 411 } 412 } 413 414 /* Translate a key code into an output key sequence for a pane. */ 415 int 416 input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m) 417 { 418 if (log_get_level() != 0) { 419 log_debug("writing key 0x%llx (%s) to %%%u", key, 420 key_string_lookup_key(key, 1), wp->id); 421 } 422 423 if (KEYC_IS_MOUSE(key)) { 424 if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id) 425 input_key_mouse(wp, m); 426 return (0); 427 } 428 return (input_key(wp->screen, wp->event, key)); 429 } 430 431 static void 432 input_key_write(const char *from, struct bufferevent *bev, const char *data, 433 size_t size) 434 { 435 log_debug("%s: %.*s", from, (int)size, (const char *)data); 436 bufferevent_write(bev, data, size); 437 } 438 439 /* Translate a key code into an output key sequence. */ 440 int 441 input_key(struct screen *s, struct bufferevent *bev, key_code key) 442 { 443 struct input_key_entry *ike; 444 key_code justkey, newkey, outkey; 445 struct utf8_data ud; 446 char tmp[64], modifier; 447 448 /* Mouse keys need a pane. */ 449 if (KEYC_IS_MOUSE(key)) 450 return (0); 451 452 /* Literal keys go as themselves (can't be more than eight bits). */ 453 if (key & KEYC_LITERAL) { 454 ud.data[0] = (u_char)key; 455 input_key_write(__func__, bev, (const char *)ud.data, 1); 456 return (0); 457 } 458 459 /* Is this backspace? */ 460 if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) { 461 newkey = options_get_number(global_options, "backspace"); 462 if (newkey >= 0x7f) 463 newkey = '\177'; 464 key = newkey|(key & (KEYC_MASK_MODIFIERS|KEYC_MASK_FLAGS)); 465 } 466 467 /* 468 * If this is a normal 7-bit key, just send it, with a leading escape 469 * if necessary. If it is a UTF-8 key, split it and send it. 470 */ 471 justkey = (key & ~(KEYC_META|KEYC_IMPLIED_META)); 472 if (justkey <= 0x7f) { 473 if (key & KEYC_META) 474 input_key_write(__func__, bev, "\033", 1); 475 ud.data[0] = justkey; 476 input_key_write(__func__, bev, (const char *)ud.data, 1); 477 return (0); 478 } 479 if (justkey > 0x7f && justkey < KEYC_BASE) { 480 if (key & KEYC_META) 481 input_key_write(__func__, bev, "\033", 1); 482 utf8_to_data(justkey, &ud); 483 input_key_write(__func__, bev, (const char *)ud.data, ud.size); 484 return (0); 485 } 486 487 /* 488 * Look up in the tree. If not in application keypad or cursor mode, 489 * remove the flags from the key. 490 */ 491 if (~s->mode & MODE_KKEYPAD) 492 key &= ~KEYC_KEYPAD; 493 if (~s->mode & MODE_KCURSOR) 494 key &= ~KEYC_CURSOR; 495 ike = input_key_get(key); 496 if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META)) 497 ike = input_key_get(key & ~KEYC_META); 498 if (ike == NULL && (key & KEYC_CURSOR)) 499 ike = input_key_get(key & ~KEYC_CURSOR); 500 if (ike == NULL && (key & KEYC_KEYPAD)) 501 ike = input_key_get(key & ~KEYC_KEYPAD); 502 if (ike != NULL) { 503 log_debug("found key 0x%llx: \"%s\"", key, ike->data); 504 if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META)) 505 input_key_write(__func__, bev, "\033", 1); 506 input_key_write(__func__, bev, ike->data, strlen(ike->data)); 507 return (0); 508 } 509 510 /* No builtin key sequence; construct an extended key sequence. */ 511 if (~s->mode & MODE_KEXTENDED) { 512 if ((key & KEYC_MASK_MODIFIERS) != KEYC_CTRL) 513 goto missing; 514 justkey = (key & KEYC_MASK_KEY); 515 switch (justkey) { 516 case ' ': 517 case '2': 518 key = 0|(key & ~KEYC_MASK_KEY); 519 break; 520 case '|': 521 key = 28|(key & ~KEYC_MASK_KEY); 522 break; 523 case '6': 524 key = 30|(key & ~KEYC_MASK_KEY); 525 break; 526 case '-': 527 case '/': 528 key = 31|(key & ~KEYC_MASK_KEY); 529 break; 530 case '?': 531 key = 127|(key & ~KEYC_MASK_KEY); 532 break; 533 default: 534 if (justkey >= 'A' && justkey <= '_') 535 key = (justkey - 'A')|(key & ~KEYC_MASK_KEY); 536 else if (justkey >= 'a' && justkey <= '~') 537 key = (justkey - 96)|(key & ~KEYC_MASK_KEY); 538 else 539 return (0); 540 break; 541 } 542 return (input_key(s, bev, key & ~KEYC_CTRL)); 543 } 544 outkey = (key & KEYC_MASK_KEY); 545 switch (key & KEYC_MASK_MODIFIERS) { 546 case KEYC_SHIFT: 547 modifier = '2'; 548 break; 549 case KEYC_META: 550 modifier = '3'; 551 break; 552 case KEYC_SHIFT|KEYC_META: 553 modifier = '4'; 554 break; 555 case KEYC_CTRL: 556 modifier = '5'; 557 break; 558 case KEYC_SHIFT|KEYC_CTRL: 559 modifier = '6'; 560 break; 561 case KEYC_META|KEYC_CTRL: 562 modifier = '7'; 563 break; 564 case KEYC_SHIFT|KEYC_META|KEYC_CTRL: 565 modifier = '8'; 566 break; 567 default: 568 goto missing; 569 } 570 xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier); 571 input_key_write(__func__, bev, tmp, strlen(tmp)); 572 return (0); 573 574 missing: 575 log_debug("key 0x%llx missing", key); 576 return (-1); 577 } 578 579 /* Get mouse event string. */ 580 int 581 input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y, 582 const char **rbuf, size_t *rlen) 583 { 584 static char buf[40]; 585 size_t len; 586 587 *rbuf = NULL; 588 *rlen = 0; 589 590 /* If this pane is not in button or all mode, discard motion events. */ 591 if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0) 592 return (0); 593 if ((s->mode & ALL_MOUSE_MODES) == 0) 594 return (0); 595 596 /* 597 * If this event is a release event and not in all mode, discard it. 598 * In SGR mode we can tell absolutely because a release is normally 599 * shown by the last character. Without SGR, we check if the last 600 * buttons was also a release. 601 */ 602 if (m->sgr_type != ' ') { 603 if (MOUSE_DRAG(m->sgr_b) && 604 MOUSE_BUTTONS(m->sgr_b) == 3 && 605 (~s->mode & MODE_MOUSE_ALL)) 606 return (0); 607 } else { 608 if (MOUSE_DRAG(m->b) && 609 MOUSE_BUTTONS(m->b) == 3 && 610 MOUSE_BUTTONS(m->lb) == 3 && 611 (~s->mode & MODE_MOUSE_ALL)) 612 return (0); 613 } 614 615 /* 616 * Use the SGR (1006) extension only if the application requested it 617 * and the underlying terminal also sent the event in this format (this 618 * is because an old style mouse release event cannot be converted into 619 * the new SGR format, since the released button is unknown). Otherwise 620 * pretend that tmux doesn't speak this extension, and fall back to the 621 * UTF-8 (1005) extension if the application requested, or to the 622 * legacy format. 623 */ 624 if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) { 625 len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c", 626 m->sgr_b, x + 1, y + 1, m->sgr_type); 627 } else if (s->mode & MODE_MOUSE_UTF8) { 628 if (m->b > 0x7ff - 32 || x > 0x7ff - 33 || y > 0x7ff - 33) 629 return (0); 630 len = xsnprintf(buf, sizeof buf, "\033[M"); 631 len += input_key_split2(m->b + 32, &buf[len]); 632 len += input_key_split2(x + 33, &buf[len]); 633 len += input_key_split2(y + 33, &buf[len]); 634 } else { 635 if (m->b > 223) 636 return (0); 637 len = xsnprintf(buf, sizeof buf, "\033[M"); 638 buf[len++] = m->b + 32; 639 buf[len++] = x + 33; 640 buf[len++] = y + 33; 641 } 642 643 *rbuf = buf; 644 *rlen = len; 645 return (1); 646 } 647 648 /* Translate mouse and output. */ 649 static void 650 input_key_mouse(struct window_pane *wp, struct mouse_event *m) 651 { 652 struct screen *s = wp->screen; 653 u_int x, y; 654 const char *buf; 655 size_t len; 656 657 /* Ignore events if no mouse mode or the pane is not visible. */ 658 if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0) 659 return; 660 if (cmd_mouse_at(wp, m, &x, &y, 0) != 0) 661 return; 662 if (!window_pane_visible(wp)) 663 return; 664 if (!input_key_get_mouse(s, m, x, y, &buf, &len)) 665 return; 666 log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id); 667 input_key_write(__func__, wp->event, buf, len); 668 } 669