Coverage Report

Created: 2025-07-11 06:20

/src/tmux/input-keys.c
Line
Count
Source (jump to first uncovered line)
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_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
0
{
339
0
  if (ike1->key < ike2->key)
340
0
    return (-1);
341
0
  if (ike1->key > ike2->key)
342
0
    return (1);
343
0
  return (0);
344
0
}
345
346
/* Look for key in tree. */
347
static struct input_key_entry *
348
input_key_get(key_code key)
349
0
{
350
0
  struct input_key_entry  entry = { .key = key };
351
352
0
  return (RB_FIND(input_key_tree, &input_key_tree, &entry));
353
0
}
354
355
/* Split a character into two UTF-8 bytes. */
356
static size_t
357
input_key_split2(u_int c, u_char *dst)
358
0
{
359
0
  if (c > 0x7f) {
360
0
    dst[0] = (c >> 6) | 0xc0;
361
0
    dst[1] = (c & 0x3f) | 0x80;
362
0
    return (2);
363
0
  }
364
0
  dst[0] = c;
365
0
  return (1);
366
0
}
367
368
/* Build input key tree. */
369
void
370
input_key_build(void)
371
0
{
372
0
  struct input_key_entry  *ike, *new;
373
0
  u_int      i, j;
374
0
  char      *data;
375
0
  key_code     key;
376
377
0
  for (i = 0; i < nitems(input_key_defaults); i++) {
378
0
    ike = &input_key_defaults[i];
379
0
    if (~ike->key & KEYC_BUILD_MODIFIERS) {
380
0
      RB_INSERT(input_key_tree, &input_key_tree, ike);
381
0
      continue;
382
0
    }
383
384
0
    for (j = 2; j < nitems(input_key_modifiers); j++) {
385
0
      key = (ike->key & ~KEYC_BUILD_MODIFIERS);
386
0
      data = xstrdup(ike->data);
387
0
      data[strcspn(data, "_")] = '0' + j;
388
389
0
      new = xcalloc(1, sizeof *new);
390
0
      new->key = key|input_key_modifiers[j];
391
0
      new->data = data;
392
0
      RB_INSERT(input_key_tree, &input_key_tree, new);
393
0
    }
394
0
  }
395
396
0
  RB_FOREACH(ike, input_key_tree, &input_key_tree) {
397
0
    log_debug("%s: 0x%llx (%s) is %s", __func__, ike->key,
398
0
        key_string_lookup_key(ike->key, 1), ike->data);
399
0
  }
400
0
}
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
0
{
406
0
  if (log_get_level() != 0) {
407
0
    log_debug("writing key 0x%llx (%s) to %%%u", key,
408
0
        key_string_lookup_key(key, 1), wp->id);
409
0
  }
410
411
0
  if (KEYC_IS_MOUSE(key)) {
412
0
    if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
413
0
      input_key_mouse(wp, m);
414
0
    return (0);
415
0
  }
416
0
  return (input_key(wp->screen, wp->event, key));
417
0
}
418
419
static void
420
input_key_write(const char *from, struct bufferevent *bev, const char *data,
421
    size_t size)
422
0
{
423
0
  log_debug("%s: %.*s", from, (int)size, data);
424
0
  bufferevent_write(bev, data, size);
425
0
}
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
0
{
434
0
  char     tmp[64], modifier;
435
0
  struct utf8_data ud;
436
0
  wchar_t    wc;
437
438
0
  switch (key & KEYC_MASK_MODIFIERS) {
439
0
  case KEYC_SHIFT:
440
0
    modifier = '2';
441
0
    break;
442
0
  case KEYC_META:
443
0
    modifier = '3';
444
0
    break;
445
0
  case KEYC_SHIFT|KEYC_META:
446
0
    modifier = '4';
447
0
    break;
448
0
  case KEYC_CTRL:
449
0
    modifier = '5';
450
0
    break;
451
0
  case KEYC_SHIFT|KEYC_CTRL:
452
0
    modifier = '6';
453
0
    break;
454
0
  case KEYC_META|KEYC_CTRL:
455
0
    modifier = '7';
456
0
    break;
457
0
  case KEYC_SHIFT|KEYC_META|KEYC_CTRL:
458
0
    modifier = '8';
459
0
    break;
460
0
  default:
461
0
    return (-1);
462
0
  }
463
464
0
  if (KEYC_IS_UNICODE(key)) {
465
0
    utf8_to_data(key & KEYC_MASK_KEY, &ud);
466
0
    if (utf8_towc(&ud, &wc) == UTF8_DONE)
467
0
      key = wc;
468
0
    else
469
0
      return (-1);
470
0
  } else
471
0
    key &= KEYC_MASK_KEY;
472
473
0
  if (options_get_number(global_options, "extended-keys-format") == 1)
474
0
    xsnprintf(tmp, sizeof tmp, "\033[27;%c;%llu~", modifier, key);
475
0
  else
476
0
    xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", key, modifier);
477
478
0
  input_key_write(__func__, bev, tmp, strlen(tmp));
479
0
  return (0);
480
0
}
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
0
{
490
0
  struct utf8_data   ud;
491
0
  key_code     onlykey;
492
0
  char      *p;
493
0
  static const char *standard_map[2] = {
494
0
    "1!9(0)=+;:'\",<.>/-8? 2",
495
0
    "119900=+;;'',,..\x1f\x1f\x7f\x7f\0\0",
496
0
  };
497
498
0
  log_debug("%s: key in %llx", __func__, key);
499
500
0
  if (key & KEYC_META)
501
0
    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
0
  if (KEYC_IS_UNICODE(key)) {
508
0
    utf8_to_data(key, &ud);
509
0
                input_key_write(__func__, bev, ud.data, ud.size);
510
0
    return (0);
511
0
  }
512
513
  /*
514
   * Prevent TAB, CR and LF from being swallowed by the C0 remapping
515
   * logic.
516
   */
517
0
  onlykey = key & KEYC_MASK_KEY;
518
0
  if (onlykey == '\r' || onlykey == '\n' || onlykey == '\t')
519
0
    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
0
  if (key & KEYC_CTRL) {
531
0
    p = strchr(standard_map[0], onlykey);
532
0
    if (p != NULL)
533
0
      key = standard_map[1][p - standard_map[0]];
534
0
    else if (onlykey >= '3' && onlykey <= '7')
535
0
      key = onlykey - '\030';
536
0
    else if (onlykey >= '@' && onlykey <= '~')
537
0
      key = onlykey & 0x1f;
538
0
    else
539
0
      return (-1);
540
0
  }
541
542
0
  log_debug("%s: key out %llx", __func__, key);
543
544
0
  ud.data[0] = key & 0x7f;
545
0
  input_key_write(__func__, bev, &ud.data[0], 1);
546
0
  return (0);
547
0
}
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
0
{
553
0
  key_code   onlykey;
554
555
0
  log_debug("%s: key in %llx", __func__, key);
556
557
  /* A regular or shifted key + Meta. */
558
0
  if ((key & (KEYC_CTRL | KEYC_META)) == KEYC_META)
559
0
    return (input_key_vt10x(bev, key));
560
561
  /*
562
   * As per
563
   * https://invisible-island.net/xterm/modified-keys-us-pc105.html.
564
   */
565
0
  onlykey = key & KEYC_MASK_KEY;
566
0
  if ((key & KEYC_CTRL) &&
567
0
      (onlykey == ' ' ||
568
0
       onlykey == '/' ||
569
0
       onlykey == '@' ||
570
0
       onlykey == '^' ||
571
0
       (onlykey >= '2' && onlykey <= '8') ||
572
0
       (onlykey >= '@' && onlykey <= '~')))
573
0
    return (input_key_vt10x(bev, key));
574
575
0
  return (-1);
576
0
}
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
0
{
582
0
  struct input_key_entry  *ike = NULL;
583
0
  key_code     newkey;
584
0
  struct utf8_data   ud;
585
586
  /* Mouse keys need a pane. */
587
0
  if (KEYC_IS_MOUSE(key))
588
0
    return (0);
589
590
  /* Literal keys go as themselves (can't be more than eight bits). */
591
0
  if (key & KEYC_LITERAL) {
592
0
    ud.data[0] = (u_char)key;
593
0
    input_key_write(__func__, bev, &ud.data[0], 1);
594
0
    return (0);
595
0
  }
596
597
  /* Is this backspace? */
598
0
  if ((key & KEYC_MASK_KEY) == KEYC_BSPACE) {
599
0
    newkey = options_get_number(global_options, "backspace");
600
0
    log_debug("%s: key 0x%llx is backspace -> 0x%llx", __func__,
601
0
        key, newkey);
602
0
    if ((key & KEYC_MASK_MODIFIERS) == 0) {
603
0
      ud.data[0] = 255;
604
0
      if ((newkey & KEYC_MASK_MODIFIERS) == 0)
605
0
        ud.data[0] = newkey;
606
0
      else if ((newkey & KEYC_MASK_MODIFIERS) == KEYC_CTRL) {
607
0
        newkey &= KEYC_MASK_KEY;
608
0
        if (newkey >= 'A' && newkey <= 'Z')
609
0
          ud.data[0] = newkey - 0x40;
610
0
        else if (newkey >= 'a' && newkey <= 'z')
611
0
          ud.data[0] = newkey - 0x60;
612
0
      }
613
0
      if (ud.data[0] != 255)
614
0
        input_key_write(__func__, bev, &ud.data[0], 1);
615
0
      return (0);
616
0
    }
617
0
    key = newkey|(key & (KEYC_MASK_FLAGS|KEYC_MASK_MODIFIERS));
618
0
  }
619
620
  /* Is this backtab? */
621
0
  if ((key & KEYC_MASK_KEY) == KEYC_BTAB) {
622
0
    if (s->mode & MODE_KEYS_EXTENDED_2) {
623
      /* When in xterm extended mode, remap into S-Tab. */
624
0
      key = '\011' | (key & ~KEYC_MASK_KEY) | KEYC_SHIFT;
625
0
    } else {
626
      /* Otherwise clear modifiers. */
627
0
      key &= ~KEYC_MASK_MODIFIERS;
628
0
    }
629
0
  }
630
631
  /*
632
   * A trivial case, that is a 7-bit key, excluding C0 control characters
633
   * that can't be entered from the keyboard, and no modifiers; or a UTF-8
634
   * key and no modifiers.
635
   */
636
0
  if (!(key & ~KEYC_MASK_KEY)) {
637
0
    if (key == C0_HT ||
638
0
        key == C0_CR ||
639
0
        key == C0_ESC ||
640
0
        (key >= 0x20 && key <= 0x7f)) {
641
0
      ud.data[0] = key;
642
0
      input_key_write(__func__, bev, &ud.data[0], 1);
643
0
      return (0);
644
0
    }
645
0
    if (KEYC_IS_UNICODE(key)) {
646
0
      utf8_to_data(key, &ud);
647
0
      input_key_write(__func__, bev, ud.data, ud.size);
648
0
      return (0);
649
0
    }
650
0
  }
651
652
  /*
653
   * Look up the standard VT10x keys in the tree. If not in application
654
   * keypad or cursor mode, remove the respective flags from the key.
655
   */
656
0
  if (~s->mode & MODE_KKEYPAD)
657
0
    key &= ~KEYC_KEYPAD;
658
0
  if (~s->mode & MODE_KCURSOR)
659
0
    key &= ~KEYC_CURSOR;
660
0
  if (ike == NULL)
661
0
    ike = input_key_get(key);
662
0
  if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META))
663
0
    ike = input_key_get(key & ~KEYC_META);
664
0
  if (ike == NULL && (key & KEYC_CURSOR))
665
0
    ike = input_key_get(key & ~KEYC_CURSOR);
666
0
  if (ike == NULL && (key & KEYC_KEYPAD))
667
0
    ike = input_key_get(key & ~KEYC_KEYPAD);
668
0
  if (ike != NULL) {
669
0
    log_debug("%s: found key 0x%llx: \"%s\"", __func__, key,
670
0
        ike->data);
671
0
    if (KEYC_IS_PASTE(key) && (~s->mode & MODE_BRACKETPASTE))
672
0
      return (0);
673
0
    if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META))
674
0
      input_key_write(__func__, bev, "\033", 1);
675
0
    input_key_write(__func__, bev, ike->data, strlen(ike->data));
676
0
    return (0);
677
0
  }
678
679
  /* Ignore internal function key codes. */
680
0
  if ((key >= KEYC_BASE && key < KEYC_BASE_END) ||
681
0
      (key >= KEYC_USER && key < KEYC_USER_END)) {
682
0
    log_debug("%s: ignoring key 0x%llx", __func__, key);
683
0
    return (0);
684
0
  }
685
686
  /*
687
   * No builtin key sequence; construct an extended key sequence
688
   * depending on the client mode.
689
   *
690
   * If something invalid reaches here, an invalid output may be
691
   * produced. For example Ctrl-Shift-2 is invalid (as there's
692
   * no way to enter it). The correct form is Ctrl-Shift-@, at
693
   * least in US English keyboard layout.
694
   */
695
0
  switch (s->mode & EXTENDED_KEY_MODES) {
696
0
  case MODE_KEYS_EXTENDED_2:
697
    /*
698
     * The simplest mode to handle - *all* modified keys are
699
     * reported in the extended form.
700
     */
701
0
    return (input_key_extended(bev, key));
702
0
        case MODE_KEYS_EXTENDED:
703
    /*
704
     * Some keys are still reported in standard mode, to maintain
705
     * compatibility with applications unaware of extended keys.
706
     */
707
0
    if (input_key_mode1(bev, key) == -1)
708
0
      return (input_key_extended(bev, key));
709
0
    return (0);
710
0
  default:
711
    /* The standard mode. */
712
0
    return (input_key_vt10x(bev, key));
713
0
  }
714
0
}
715
716
/* Get mouse event string. */
717
int
718
input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
719
    const char **rbuf, size_t *rlen)
720
0
{
721
0
  static char  buf[40];
722
0
  size_t     len;
723
724
0
  *rbuf = NULL;
725
0
  *rlen = 0;
726
727
  /* If this pane is not in button or all mode, discard motion events. */
728
0
  if (MOUSE_DRAG(m->b) && (s->mode & MOTION_MOUSE_MODES) == 0)
729
0
    return (0);
730
0
  if ((s->mode & ALL_MOUSE_MODES) == 0)
731
0
    return (0);
732
733
  /*
734
   * If this event is a release event and not in all mode, discard it.
735
   * In SGR mode we can tell absolutely because a release is normally
736
   * shown by the last character. Without SGR, we check if the last
737
   * buttons was also a release.
738
   */
739
0
  if (m->sgr_type != ' ') {
740
0
    if (MOUSE_DRAG(m->sgr_b) &&
741
0
        MOUSE_RELEASE(m->sgr_b) &&
742
0
        (~s->mode & MODE_MOUSE_ALL))
743
0
      return (0);
744
0
  } else {
745
0
    if (MOUSE_DRAG(m->b) &&
746
0
        MOUSE_RELEASE(m->b) &&
747
0
        MOUSE_RELEASE(m->lb) &&
748
0
        (~s->mode & MODE_MOUSE_ALL))
749
0
      return (0);
750
0
  }
751
752
  /*
753
   * Use the SGR (1006) extension only if the application requested it
754
   * and the underlying terminal also sent the event in this format (this
755
   * is because an old style mouse release event cannot be converted into
756
   * the new SGR format, since the released button is unknown). Otherwise
757
   * pretend that tmux doesn't speak this extension, and fall back to the
758
   * UTF-8 (1005) extension if the application requested, or to the
759
   * legacy format.
760
   */
761
0
  if (m->sgr_type != ' ' && (s->mode & MODE_MOUSE_SGR)) {
762
0
    len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
763
0
        m->sgr_b, x + 1, y + 1, m->sgr_type);
764
0
  } else if (s->mode & MODE_MOUSE_UTF8) {
765
0
    if (m->b > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_BTN_OFF ||
766
0
        x > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF ||
767
0
        y > MOUSE_PARAM_UTF8_MAX - MOUSE_PARAM_POS_OFF)
768
0
      return (0);
769
0
    len = xsnprintf(buf, sizeof buf, "\033[M");
770
0
    len += input_key_split2(m->b + MOUSE_PARAM_BTN_OFF, &buf[len]);
771
0
    len += input_key_split2(x + MOUSE_PARAM_POS_OFF, &buf[len]);
772
0
    len += input_key_split2(y + MOUSE_PARAM_POS_OFF, &buf[len]);
773
0
  } else {
774
0
    if (m->b + MOUSE_PARAM_BTN_OFF > MOUSE_PARAM_MAX)
775
0
      return (0);
776
777
0
    len = xsnprintf(buf, sizeof buf, "\033[M");
778
0
    buf[len++] = m->b + MOUSE_PARAM_BTN_OFF;
779
780
    /*
781
     * The incoming x and y may be out of the range which can be
782
     * supported by the "normal" mouse protocol. Clamp the
783
     * coordinates to the supported range.
784
     */
785
0
    if (x + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
786
0
      buf[len++] = MOUSE_PARAM_MAX;
787
0
    else
788
0
      buf[len++] = x + MOUSE_PARAM_POS_OFF;
789
0
    if (y + MOUSE_PARAM_POS_OFF > MOUSE_PARAM_MAX)
790
0
      buf[len++] = MOUSE_PARAM_MAX;
791
0
    else
792
0
      buf[len++] = y + MOUSE_PARAM_POS_OFF;
793
0
  }
794
795
0
  *rbuf = buf;
796
0
  *rlen = len;
797
0
  return (1);
798
0
}
799
800
/* Translate mouse and output. */
801
static void
802
input_key_mouse(struct window_pane *wp, struct mouse_event *m)
803
0
{
804
0
  struct screen *s = wp->screen;
805
0
  u_int    x, y;
806
0
  const char  *buf;
807
0
  size_t     len;
808
809
  /* Ignore events if no mouse mode or the pane is not visible. */
810
0
  if (m->ignore || (s->mode & ALL_MOUSE_MODES) == 0)
811
0
    return;
812
0
  if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
813
0
    return;
814
0
  if (!window_pane_visible(wp))
815
0
    return;
816
0
  if (!input_key_get_mouse(s, m, x, y, &buf, &len))
817
0
    return;
818
0
  log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id);
819
0
  input_key_write(__func__, wp->event, buf, len);
820
0
}