Coverage Report

Created: 2026-04-12 06:58

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