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