Coverage Report

Created: 2026-01-17 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tmux/input.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 <netinet/in.h>
22
23
#include <ctype.h>
24
#include <resolv.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <time.h>
28
29
#include "tmux.h"
30
31
/*
32
 * Based on the description by Paul Williams at:
33
 *
34
 * https://vt100.net/emu/dec_ansi_parser
35
 *
36
 * With the following changes:
37
 *
38
 * - 7-bit only.
39
 *
40
 * - Support for UTF-8.
41
 *
42
 * - OSC (but not APC) may be terminated by \007 as well as ST.
43
 *
44
 * - A state for APC similar to OSC. Some terminals appear to use this to set
45
 *   the title.
46
 *
47
 * - A state for the screen \033k...\033\\ sequence to rename a window. This is
48
 *   pretty stupid but not supporting it is more trouble than it is worth.
49
 *
50
 * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
51
 *   be passed to the underlying terminals.
52
 */
53
54
/* Type of terminator. */
55
enum input_end_type {
56
  INPUT_END_ST,
57
  INPUT_END_BEL
58
};
59
60
/* Request sent by a pane. */
61
struct input_request {
62
  struct client     *c;
63
  struct input_ctx    *ictx;
64
65
  enum input_request_type    type;
66
  uint64_t       t;
67
  enum input_end_type              end;
68
69
  int        idx;
70
  void        *data;
71
72
  TAILQ_ENTRY(input_request)   entry;
73
  TAILQ_ENTRY(input_request)   centry;
74
};
75
0
#define INPUT_REQUEST_TIMEOUT 500
76
77
/* Input parser cell. */
78
struct input_cell {
79
  struct grid_cell  cell;
80
  int     set;
81
  int     g0set;  /* 1 if ACS */
82
  int     g1set;  /* 1 if ACS */
83
};
84
85
/* Input parser argument. */
86
struct input_param {
87
  enum {
88
    INPUT_MISSING,
89
    INPUT_NUMBER,
90
    INPUT_STRING
91
  }     type;
92
  union {
93
    int   num;
94
    char         *str;
95
  };
96
};
97
98
/* Input parser context. */
99
struct input_ctx {
100
  struct window_pane         *wp;
101
  struct bufferevent         *event;
102
  struct screen_write_ctx   ctx;
103
  struct colour_palette        *palette;
104
105
  struct input_cell   cell;
106
  struct input_cell   old_cell;
107
  u_int       old_cx;
108
  u_int       old_cy;
109
  int       old_mode;
110
111
  u_char        interm_buf[4];
112
  size_t        interm_len;
113
114
  u_char        param_buf[64];
115
  size_t        param_len;
116
117
77.3k
#define INPUT_BUF_START 32
118
  u_char             *input_buf;
119
  size_t        input_len;
120
  size_t        input_space;
121
  enum input_end_type   input_end;
122
123
  struct input_param    param_list[24];
124
  u_int       param_list_len;
125
126
  struct utf8_data    utf8data;
127
  int       utf8started;
128
129
  int       ch;
130
  struct utf8_data    last;
131
132
  const struct input_state       *state;
133
  int       flags;
134
221k
#define INPUT_DISCARD 0x1
135
116k
#define INPUT_LAST 0x2
136
137
  struct input_requests    requests;
138
  u_int        request_count;
139
  struct event       request_timer;
140
141
  /*
142
   * All input received since we were last in the ground state. Sent to
143
   * control clients on connection.
144
   */
145
  struct evbuffer     *since_ground;
146
  struct event       ground_timer;
147
};
148
149
/* Helper functions. */
150
struct input_transition;
151
static void   input_request_timer_callback(int, short, void *);
152
static void input_start_request_timer(struct input_ctx *);
153
static struct input_request *input_make_request(struct input_ctx *,
154
        enum input_request_type);
155
static void input_free_request(struct input_request *);
156
static int  input_add_request(struct input_ctx *, enum input_request_type,
157
        int);
158
static int  input_split(struct input_ctx *);
159
static int  input_get(struct input_ctx *, u_int, int, int);
160
static void input_set_state(struct input_ctx *,
161
        const struct input_transition *);
162
static void input_reset_cell(struct input_ctx *);
163
static void input_report_current_theme(struct input_ctx *);
164
static void input_osc_4(struct input_ctx *, const char *);
165
static void input_osc_8(struct input_ctx *, const char *);
166
static void input_osc_10(struct input_ctx *, const char *);
167
static void input_osc_11(struct input_ctx *, const char *);
168
static void input_osc_12(struct input_ctx *, const char *);
169
static void input_osc_52(struct input_ctx *, const char *);
170
static void input_osc_104(struct input_ctx *, const char *);
171
static void input_osc_110(struct input_ctx *, const char *);
172
static void input_osc_111(struct input_ctx *, const char *);
173
static void input_osc_112(struct input_ctx *, const char *);
174
static void input_osc_133(struct input_ctx *, const char *);
175
176
/* Transition entry/exit handlers. */
177
static void input_clear(struct input_ctx *);
178
static void input_ground(struct input_ctx *);
179
static void input_enter_dcs(struct input_ctx *);
180
static void input_enter_osc(struct input_ctx *);
181
static void input_exit_osc(struct input_ctx *);
182
static void input_enter_apc(struct input_ctx *);
183
static void input_exit_apc(struct input_ctx *);
184
static void input_enter_rename(struct input_ctx *);
185
static void input_exit_rename(struct input_ctx *);
186
187
/* Input state handlers. */
188
static int  input_print(struct input_ctx *);
189
static int  input_intermediate(struct input_ctx *);
190
static int  input_parameter(struct input_ctx *);
191
static int  input_input(struct input_ctx *);
192
static int  input_c0_dispatch(struct input_ctx *);
193
static int  input_esc_dispatch(struct input_ctx *);
194
static int  input_csi_dispatch(struct input_ctx *);
195
static void input_csi_dispatch_rm(struct input_ctx *);
196
static void input_csi_dispatch_rm_private(struct input_ctx *);
197
static void input_csi_dispatch_sm(struct input_ctx *);
198
static void input_csi_dispatch_sm_private(struct input_ctx *);
199
static void input_csi_dispatch_sm_graphics(struct input_ctx *);
200
static void input_csi_dispatch_winops(struct input_ctx *);
201
static void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
202
static void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
203
static void input_csi_dispatch_sgr(struct input_ctx *);
204
static int  input_dcs_dispatch(struct input_ctx *);
205
static int  input_top_bit_set(struct input_ctx *);
206
static int  input_end_bel(struct input_ctx *);
207
208
/* Command table comparison function. */
209
static int  input_table_compare(const void *, const void *);
210
211
/* Command table entry. */
212
struct input_table_entry {
213
  int   ch;
214
  const char     *interm;
215
  int   type;
216
};
217
218
/* Escape commands. */
219
enum input_esc_type {
220
  INPUT_ESC_DECALN,
221
  INPUT_ESC_DECKPAM,
222
  INPUT_ESC_DECKPNM,
223
  INPUT_ESC_DECRC,
224
  INPUT_ESC_DECSC,
225
  INPUT_ESC_HTS,
226
  INPUT_ESC_IND,
227
  INPUT_ESC_NEL,
228
  INPUT_ESC_RI,
229
  INPUT_ESC_RIS,
230
  INPUT_ESC_SCSG0_OFF,
231
  INPUT_ESC_SCSG0_ON,
232
  INPUT_ESC_SCSG1_OFF,
233
  INPUT_ESC_SCSG1_ON,
234
  INPUT_ESC_ST
235
};
236
237
/* Escape command table. */
238
static const struct input_table_entry input_esc_table[] = {
239
  { '0', "(", INPUT_ESC_SCSG0_ON },
240
  { '0', ")", INPUT_ESC_SCSG1_ON },
241
  { '7', "",  INPUT_ESC_DECSC },
242
  { '8', "",  INPUT_ESC_DECRC },
243
  { '8', "#", INPUT_ESC_DECALN },
244
  { '=', "",  INPUT_ESC_DECKPAM },
245
  { '>', "",  INPUT_ESC_DECKPNM },
246
  { 'B', "(", INPUT_ESC_SCSG0_OFF },
247
  { 'B', ")", INPUT_ESC_SCSG1_OFF },
248
  { 'D', "",  INPUT_ESC_IND },
249
  { 'E', "",  INPUT_ESC_NEL },
250
  { 'H', "",  INPUT_ESC_HTS },
251
  { 'M', "",  INPUT_ESC_RI },
252
  { '\\', "", INPUT_ESC_ST },
253
  { 'c', "",  INPUT_ESC_RIS },
254
};
255
256
/* Control (CSI) commands. */
257
enum input_csi_type {
258
  INPUT_CSI_CBT,
259
  INPUT_CSI_CNL,
260
  INPUT_CSI_CPL,
261
  INPUT_CSI_CUB,
262
  INPUT_CSI_CUD,
263
  INPUT_CSI_CUF,
264
  INPUT_CSI_CUP,
265
  INPUT_CSI_CUU,
266
  INPUT_CSI_DA,
267
  INPUT_CSI_DA_TWO,
268
  INPUT_CSI_DCH,
269
  INPUT_CSI_DECSCUSR,
270
  INPUT_CSI_DECSTBM,
271
  INPUT_CSI_DL,
272
  INPUT_CSI_DSR,
273
  INPUT_CSI_DSR_PRIVATE,
274
  INPUT_CSI_ECH,
275
  INPUT_CSI_ED,
276
  INPUT_CSI_EL,
277
  INPUT_CSI_HPA,
278
  INPUT_CSI_ICH,
279
  INPUT_CSI_IL,
280
  INPUT_CSI_MODOFF,
281
  INPUT_CSI_MODSET,
282
  INPUT_CSI_QUERY_PRIVATE,
283
  INPUT_CSI_RCP,
284
  INPUT_CSI_REP,
285
  INPUT_CSI_RM,
286
  INPUT_CSI_RM_PRIVATE,
287
  INPUT_CSI_SCP,
288
  INPUT_CSI_SD,
289
  INPUT_CSI_SGR,
290
  INPUT_CSI_SM,
291
  INPUT_CSI_SM_GRAPHICS,
292
  INPUT_CSI_SM_PRIVATE,
293
  INPUT_CSI_SU,
294
  INPUT_CSI_TBC,
295
  INPUT_CSI_VPA,
296
  INPUT_CSI_WINOPS,
297
  INPUT_CSI_XDA
298
};
299
300
/* Control (CSI) command table. */
301
static const struct input_table_entry input_csi_table[] = {
302
  { '@', "",  INPUT_CSI_ICH },
303
  { 'A', "",  INPUT_CSI_CUU },
304
  { 'B', "",  INPUT_CSI_CUD },
305
  { 'C', "",  INPUT_CSI_CUF },
306
  { 'D', "",  INPUT_CSI_CUB },
307
  { 'E', "",  INPUT_CSI_CNL },
308
  { 'F', "",  INPUT_CSI_CPL },
309
  { 'G', "",  INPUT_CSI_HPA },
310
  { 'H', "",  INPUT_CSI_CUP },
311
  { 'J', "",  INPUT_CSI_ED },
312
  { 'K', "",  INPUT_CSI_EL },
313
  { 'L', "",  INPUT_CSI_IL },
314
  { 'M', "",  INPUT_CSI_DL },
315
  { 'P', "",  INPUT_CSI_DCH },
316
  { 'S', "",  INPUT_CSI_SU },
317
  { 'S', "?", INPUT_CSI_SM_GRAPHICS },
318
  { 'T', "",  INPUT_CSI_SD },
319
  { 'X', "",  INPUT_CSI_ECH },
320
  { 'Z', "",  INPUT_CSI_CBT },
321
  { '`', "",  INPUT_CSI_HPA },
322
  { 'b', "",  INPUT_CSI_REP },
323
  { 'c', "",  INPUT_CSI_DA },
324
  { 'c', ">", INPUT_CSI_DA_TWO },
325
  { 'd', "",  INPUT_CSI_VPA },
326
  { 'f', "",  INPUT_CSI_CUP },
327
  { 'g', "",  INPUT_CSI_TBC },
328
  { 'h', "",  INPUT_CSI_SM },
329
  { 'h', "?", INPUT_CSI_SM_PRIVATE },
330
  { 'l', "",  INPUT_CSI_RM },
331
  { 'l', "?", INPUT_CSI_RM_PRIVATE },
332
  { 'm', "",  INPUT_CSI_SGR },
333
  { 'm', ">", INPUT_CSI_MODSET },
334
  { 'n', "",  INPUT_CSI_DSR },
335
  { 'n', ">", INPUT_CSI_MODOFF },
336
  { 'n', "?", INPUT_CSI_DSR_PRIVATE },
337
  { 'p', "?$", INPUT_CSI_QUERY_PRIVATE },
338
  { 'q', " ", INPUT_CSI_DECSCUSR },
339
  { 'q', ">", INPUT_CSI_XDA },
340
  { 'r', "",  INPUT_CSI_DECSTBM },
341
  { 's', "",  INPUT_CSI_SCP },
342
  { 't', "",  INPUT_CSI_WINOPS },
343
  { 'u', "",  INPUT_CSI_RCP }
344
};
345
346
/* Input transition. */
347
struct input_transition {
348
  int       first;
349
  int       last;
350
351
  int       (*handler)(struct input_ctx *);
352
  const struct input_state       *state;
353
};
354
355
/* Input state. */
356
struct input_state {
357
  const char      *name;
358
  void        (*enter)(struct input_ctx *);
359
  void        (*exit)(struct input_ctx *);
360
  const struct input_transition *transitions;
361
};
362
363
/* State transitions available from all states. */
364
#define INPUT_STATE_ANYWHERE \
365
  { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
366
  { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
367
  { 0x1b, 0x1b, NULL,    &input_state_esc_enter }
368
369
/* Forward declarations of state tables. */
370
static const struct input_transition input_state_ground_table[];
371
static const struct input_transition input_state_esc_enter_table[];
372
static const struct input_transition input_state_esc_intermediate_table[];
373
static const struct input_transition input_state_csi_enter_table[];
374
static const struct input_transition input_state_csi_parameter_table[];
375
static const struct input_transition input_state_csi_intermediate_table[];
376
static const struct input_transition input_state_csi_ignore_table[];
377
static const struct input_transition input_state_dcs_enter_table[];
378
static const struct input_transition input_state_dcs_parameter_table[];
379
static const struct input_transition input_state_dcs_intermediate_table[];
380
static const struct input_transition input_state_dcs_handler_table[];
381
static const struct input_transition input_state_dcs_escape_table[];
382
static const struct input_transition input_state_dcs_ignore_table[];
383
static const struct input_transition input_state_osc_string_table[];
384
static const struct input_transition input_state_apc_string_table[];
385
static const struct input_transition input_state_rename_string_table[];
386
static const struct input_transition input_state_consume_st_table[];
387
388
/* ground state definition. */
389
static const struct input_state input_state_ground = {
390
  "ground",
391
  input_ground, NULL,
392
  input_state_ground_table
393
};
394
395
/* esc_enter state definition. */
396
static const struct input_state input_state_esc_enter = {
397
  "esc_enter",
398
  input_clear, NULL,
399
  input_state_esc_enter_table
400
};
401
402
/* esc_intermediate state definition. */
403
static const struct input_state input_state_esc_intermediate = {
404
  "esc_intermediate",
405
  NULL, NULL,
406
  input_state_esc_intermediate_table
407
};
408
409
/* csi_enter state definition. */
410
static const struct input_state input_state_csi_enter = {
411
  "csi_enter",
412
  input_clear, NULL,
413
  input_state_csi_enter_table
414
};
415
416
/* csi_parameter state definition. */
417
static const struct input_state input_state_csi_parameter = {
418
  "csi_parameter",
419
  NULL, NULL,
420
  input_state_csi_parameter_table
421
};
422
423
/* csi_intermediate state definition. */
424
static const struct input_state input_state_csi_intermediate = {
425
  "csi_intermediate",
426
  NULL, NULL,
427
  input_state_csi_intermediate_table
428
};
429
430
/* csi_ignore state definition. */
431
static const struct input_state input_state_csi_ignore = {
432
  "csi_ignore",
433
  NULL, NULL,
434
  input_state_csi_ignore_table
435
};
436
437
/* dcs_enter state definition. */
438
static const struct input_state input_state_dcs_enter = {
439
  "dcs_enter",
440
  input_enter_dcs, NULL,
441
  input_state_dcs_enter_table
442
};
443
444
/* dcs_parameter state definition. */
445
static const struct input_state input_state_dcs_parameter = {
446
  "dcs_parameter",
447
  NULL, NULL,
448
  input_state_dcs_parameter_table
449
};
450
451
/* dcs_intermediate state definition. */
452
static const struct input_state input_state_dcs_intermediate = {
453
  "dcs_intermediate",
454
  NULL, NULL,
455
  input_state_dcs_intermediate_table
456
};
457
458
/* dcs_handler state definition. */
459
static const struct input_state input_state_dcs_handler = {
460
  "dcs_handler",
461
  NULL, NULL,
462
  input_state_dcs_handler_table
463
};
464
465
/* dcs_escape state definition. */
466
static const struct input_state input_state_dcs_escape = {
467
  "dcs_escape",
468
  NULL, NULL,
469
  input_state_dcs_escape_table
470
};
471
472
/* dcs_ignore state definition. */
473
static const struct input_state input_state_dcs_ignore = {
474
  "dcs_ignore",
475
  NULL, NULL,
476
  input_state_dcs_ignore_table
477
};
478
479
/* osc_string state definition. */
480
static const struct input_state input_state_osc_string = {
481
  "osc_string",
482
  input_enter_osc, input_exit_osc,
483
  input_state_osc_string_table
484
};
485
486
/* apc_string state definition. */
487
static const struct input_state input_state_apc_string = {
488
  "apc_string",
489
  input_enter_apc, input_exit_apc,
490
  input_state_apc_string_table
491
};
492
493
/* rename_string state definition. */
494
static const struct input_state input_state_rename_string = {
495
  "rename_string",
496
  input_enter_rename, input_exit_rename,
497
  input_state_rename_string_table
498
};
499
500
/* consume_st state definition. */
501
static const struct input_state input_state_consume_st = {
502
  "consume_st",
503
  input_enter_rename, NULL, /* rename also waits for ST */
504
  input_state_consume_st_table
505
};
506
507
/* ground state table. */
508
static const struct input_transition input_state_ground_table[] = {
509
  INPUT_STATE_ANYWHERE,
510
511
  { 0x00, 0x17, input_c0_dispatch, NULL },
512
  { 0x19, 0x19, input_c0_dispatch, NULL },
513
  { 0x1c, 0x1f, input_c0_dispatch, NULL },
514
  { 0x20, 0x7e, input_print,   NULL },
515
  { 0x7f, 0x7f, NULL,    NULL },
516
  { 0x80, 0xff, input_top_bit_set, NULL },
517
518
  { -1, -1, NULL, NULL }
519
};
520
521
/* esc_enter state table. */
522
static const struct input_transition input_state_esc_enter_table[] = {
523
  INPUT_STATE_ANYWHERE,
524
525
  { 0x00, 0x17, input_c0_dispatch,  NULL },
526
  { 0x19, 0x19, input_c0_dispatch,  NULL },
527
  { 0x1c, 0x1f, input_c0_dispatch,  NULL },
528
  { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
529
  { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
530
  { 0x50, 0x50, NULL,     &input_state_dcs_enter },
531
  { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
532
  { 0x58, 0x58, NULL,     &input_state_consume_st },
533
  { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
534
  { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
535
  { 0x5b, 0x5b, NULL,     &input_state_csi_enter },
536
  { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
537
  { 0x5d, 0x5d, NULL,     &input_state_osc_string },
538
  { 0x5e, 0x5e, NULL,     &input_state_consume_st },
539
  { 0x5f, 0x5f, NULL,     &input_state_apc_string },
540
  { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
541
  { 0x6b, 0x6b, NULL,     &input_state_rename_string },
542
  { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground },
543
  { 0x7f, 0xff, NULL,     NULL },
544
545
  { -1, -1, NULL, NULL }
546
};
547
548
/* esc_intermediate state table. */
549
static const struct input_transition input_state_esc_intermediate_table[] = {
550
  INPUT_STATE_ANYWHERE,
551
552
  { 0x00, 0x17, input_c0_dispatch,  NULL },
553
  { 0x19, 0x19, input_c0_dispatch,  NULL },
554
  { 0x1c, 0x1f, input_c0_dispatch,  NULL },
555
  { 0x20, 0x2f, input_intermediate, NULL },
556
  { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
557
  { 0x7f, 0xff, NULL,     NULL },
558
559
  { -1, -1, NULL, NULL }
560
};
561
562
/* csi_enter state table. */
563
static const struct input_transition input_state_csi_enter_table[] = {
564
  INPUT_STATE_ANYWHERE,
565
566
  { 0x00, 0x17, input_c0_dispatch,  NULL },
567
  { 0x19, 0x19, input_c0_dispatch,  NULL },
568
  { 0x1c, 0x1f, input_c0_dispatch,  NULL },
569
  { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
570
  { 0x30, 0x39, input_parameter,    &input_state_csi_parameter },
571
  { 0x3a, 0x3a, input_parameter,    &input_state_csi_parameter },
572
  { 0x3b, 0x3b, input_parameter,    &input_state_csi_parameter },
573
  { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
574
  { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
575
  { 0x7f, 0xff, NULL,     NULL },
576
577
  { -1, -1, NULL, NULL }
578
};
579
580
/* csi_parameter state table. */
581
static const struct input_transition input_state_csi_parameter_table[] = {
582
  INPUT_STATE_ANYWHERE,
583
584
  { 0x00, 0x17, input_c0_dispatch,  NULL },
585
  { 0x19, 0x19, input_c0_dispatch,  NULL },
586
  { 0x1c, 0x1f, input_c0_dispatch,  NULL },
587
  { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
588
  { 0x30, 0x39, input_parameter,    NULL },
589
  { 0x3a, 0x3a, input_parameter,    NULL },
590
  { 0x3b, 0x3b, input_parameter,    NULL },
591
  { 0x3c, 0x3f, NULL,     &input_state_csi_ignore },
592
  { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
593
  { 0x7f, 0xff, NULL,     NULL },
594
595
  { -1, -1, NULL, NULL }
596
};
597
598
/* csi_intermediate state table. */
599
static const struct input_transition input_state_csi_intermediate_table[] = {
600
  INPUT_STATE_ANYWHERE,
601
602
  { 0x00, 0x17, input_c0_dispatch,  NULL },
603
  { 0x19, 0x19, input_c0_dispatch,  NULL },
604
  { 0x1c, 0x1f, input_c0_dispatch,  NULL },
605
  { 0x20, 0x2f, input_intermediate, NULL },
606
  { 0x30, 0x3f, NULL,     &input_state_csi_ignore },
607
  { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
608
  { 0x7f, 0xff, NULL,     NULL },
609
610
  { -1, -1, NULL, NULL }
611
};
612
613
/* csi_ignore state table. */
614
static const struct input_transition input_state_csi_ignore_table[] = {
615
  INPUT_STATE_ANYWHERE,
616
617
  { 0x00, 0x17, input_c0_dispatch, NULL },
618
  { 0x19, 0x19, input_c0_dispatch, NULL },
619
  { 0x1c, 0x1f, input_c0_dispatch, NULL },
620
  { 0x20, 0x3f, NULL,    NULL },
621
  { 0x40, 0x7e, NULL,    &input_state_ground },
622
  { 0x7f, 0xff, NULL,    NULL },
623
624
  { -1, -1, NULL, NULL }
625
};
626
627
/* dcs_enter state table. */
628
static const struct input_transition input_state_dcs_enter_table[] = {
629
  INPUT_STATE_ANYWHERE,
630
631
  { 0x00, 0x17, NULL,     NULL },
632
  { 0x19, 0x19, NULL,     NULL },
633
  { 0x1c, 0x1f, NULL,     NULL },
634
  { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
635
  { 0x30, 0x39, input_parameter,    &input_state_dcs_parameter },
636
  { 0x3a, 0x3a, NULL,     &input_state_dcs_ignore },
637
  { 0x3b, 0x3b, input_parameter,    &input_state_dcs_parameter },
638
  { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
639
  { 0x40, 0x7e, input_input,    &input_state_dcs_handler },
640
  { 0x7f, 0xff, NULL,     NULL },
641
642
  { -1, -1, NULL, NULL }
643
};
644
645
/* dcs_parameter state table. */
646
static const struct input_transition input_state_dcs_parameter_table[] = {
647
  INPUT_STATE_ANYWHERE,
648
649
  { 0x00, 0x17, NULL,     NULL },
650
  { 0x19, 0x19, NULL,     NULL },
651
  { 0x1c, 0x1f, NULL,     NULL },
652
  { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
653
  { 0x30, 0x39, input_parameter,    NULL },
654
  { 0x3a, 0x3a, NULL,     &input_state_dcs_ignore },
655
  { 0x3b, 0x3b, input_parameter,    NULL },
656
  { 0x3c, 0x3f, NULL,     &input_state_dcs_ignore },
657
  { 0x40, 0x7e, input_input,    &input_state_dcs_handler },
658
  { 0x7f, 0xff, NULL,     NULL },
659
660
  { -1, -1, NULL, NULL }
661
};
662
663
/* dcs_intermediate state table. */
664
static const struct input_transition input_state_dcs_intermediate_table[] = {
665
  INPUT_STATE_ANYWHERE,
666
667
  { 0x00, 0x17, NULL,     NULL },
668
  { 0x19, 0x19, NULL,     NULL },
669
  { 0x1c, 0x1f, NULL,     NULL },
670
  { 0x20, 0x2f, input_intermediate, NULL },
671
  { 0x30, 0x3f, NULL,     &input_state_dcs_ignore },
672
  { 0x40, 0x7e, input_input,    &input_state_dcs_handler },
673
  { 0x7f, 0xff, NULL,     NULL },
674
675
  { -1, -1, NULL, NULL }
676
};
677
678
/* dcs_handler state table. */
679
static const struct input_transition input_state_dcs_handler_table[] = {
680
  /* No INPUT_STATE_ANYWHERE */
681
682
  { 0x00, 0x1a, input_input,  NULL },
683
  { 0x1b, 0x1b, NULL,     &input_state_dcs_escape },
684
  { 0x1c, 0xff, input_input,  NULL },
685
686
  { -1, -1, NULL, NULL }
687
};
688
689
/* dcs_escape state table. */
690
static const struct input_transition input_state_dcs_escape_table[] = {
691
  /* No INPUT_STATE_ANYWHERE */
692
693
  { 0x00, 0x5b, input_input,    &input_state_dcs_handler },
694
  { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
695
  { 0x5d, 0xff, input_input,    &input_state_dcs_handler },
696
697
  { -1, -1, NULL, NULL }
698
};
699
700
/* dcs_ignore state table. */
701
static const struct input_transition input_state_dcs_ignore_table[] = {
702
  INPUT_STATE_ANYWHERE,
703
704
  { 0x00, 0x17, NULL,     NULL },
705
  { 0x19, 0x19, NULL,     NULL },
706
  { 0x1c, 0x1f, NULL,     NULL },
707
  { 0x20, 0xff, NULL,     NULL },
708
709
  { -1, -1, NULL, NULL }
710
};
711
712
/* osc_string state table. */
713
static const struct input_transition input_state_osc_string_table[] = {
714
  INPUT_STATE_ANYWHERE,
715
716
  { 0x00, 0x06, NULL,      NULL },
717
  { 0x07, 0x07, input_end_bel, &input_state_ground },
718
  { 0x08, 0x17, NULL,      NULL },
719
  { 0x19, 0x19, NULL,      NULL },
720
  { 0x1c, 0x1f, NULL,      NULL },
721
  { 0x20, 0xff, input_input,   NULL },
722
723
  { -1, -1, NULL, NULL }
724
};
725
726
/* apc_string state table. */
727
static const struct input_transition input_state_apc_string_table[] = {
728
  INPUT_STATE_ANYWHERE,
729
730
  { 0x00, 0x17, NULL,     NULL },
731
  { 0x19, 0x19, NULL,     NULL },
732
  { 0x1c, 0x1f, NULL,     NULL },
733
  { 0x20, 0xff, input_input,  NULL },
734
735
  { -1, -1, NULL, NULL }
736
};
737
738
/* rename_string state table. */
739
static const struct input_transition input_state_rename_string_table[] = {
740
  INPUT_STATE_ANYWHERE,
741
742
  { 0x00, 0x17, NULL,     NULL },
743
  { 0x19, 0x19, NULL,     NULL },
744
  { 0x1c, 0x1f, NULL,     NULL },
745
  { 0x20, 0xff, input_input,  NULL },
746
747
  { -1, -1, NULL, NULL }
748
};
749
750
/* consume_st state table. */
751
static const struct input_transition input_state_consume_st_table[] = {
752
  INPUT_STATE_ANYWHERE,
753
754
  { 0x00, 0x17, NULL,     NULL },
755
  { 0x19, 0x19, NULL,     NULL },
756
  { 0x1c, 0x1f, NULL,     NULL },
757
  { 0x20, 0xff, NULL,     NULL },
758
759
  { -1, -1, NULL, NULL }
760
};
761
762
/* Maximum of bytes allowed to read in a single input. */
763
static size_t input_buffer_size = INPUT_BUF_DEFAULT_SIZE;
764
765
/* Input table compare. */
766
static int
767
input_table_compare(const void *key, const void *value)
768
226k
{
769
226k
  const struct input_ctx    *ictx = key;
770
226k
  const struct input_table_entry  *entry = value;
771
772
226k
  if (ictx->ch != entry->ch)
773
168k
    return (ictx->ch - entry->ch);
774
57.4k
  return (strcmp(ictx->interm_buf, entry->interm));
775
226k
}
776
777
/* Stop UTF-8 and enter an invalid character. */
778
static void
779
input_stop_utf8(struct input_ctx *ictx)
780
43.5k
{
781
43.5k
  struct screen_write_ctx *sctx = &ictx->ctx;
782
43.5k
  static struct utf8_data  rc = { "\357\277\275", 3, 3, 1 };
783
784
43.5k
  if (ictx->utf8started) {
785
5.63k
    utf8_copy(&ictx->cell.cell.data, &rc);
786
5.63k
    screen_write_collect_add(sctx, &ictx->cell.cell);
787
5.63k
  }
788
43.5k
  ictx->utf8started = 0;
789
43.5k
}
790
791
/*
792
 * Timer - if this expires then have been waiting for a terminator for too
793
 * long, so reset to ground.
794
 */
795
static void
796
input_ground_timer_callback(__unused int fd, __unused short events, void *arg)
797
0
{
798
0
  struct input_ctx  *ictx = arg;
799
800
0
  log_debug("%s: %s expired" , __func__, ictx->state->name);
801
0
  input_reset(ictx, 0);
802
0
}
803
804
/* Start the timer. */
805
static void
806
input_start_ground_timer(struct input_ctx *ictx)
807
19.4k
{
808
19.4k
  struct timeval  tv = { .tv_sec = 5, .tv_usec = 0 };
809
810
19.4k
  event_del(&ictx->ground_timer);
811
19.4k
  event_add(&ictx->ground_timer, &tv);
812
19.4k
}
813
814
/* Reset cell state to default. */
815
static void
816
input_reset_cell(struct input_ctx *ictx)
817
13.0k
{
818
13.0k
  memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell);
819
13.0k
  ictx->cell.set = 0;
820
13.0k
  ictx->cell.g0set = ictx->cell.g1set = 0;
821
822
13.0k
  memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
823
13.0k
  ictx->old_cx = 0;
824
13.0k
  ictx->old_cy = 0;
825
13.0k
}
826
827
/* Save screen state. */
828
static void
829
input_save_state(struct input_ctx *ictx)
830
424
{
831
424
  struct screen_write_ctx *sctx = &ictx->ctx;
832
424
  struct screen   *s = sctx->s;
833
834
424
  memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
835
424
  ictx->old_cx = s->cx;
836
424
  ictx->old_cy = s->cy;
837
424
  ictx->old_mode = s->mode;
838
424
}
839
840
/* Restore screen state. */
841
static void
842
input_restore_state(struct input_ctx *ictx)
843
1.03k
{
844
1.03k
  struct screen_write_ctx *sctx = &ictx->ctx;
845
846
1.03k
  memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
847
1.03k
  if (ictx->old_mode & MODE_ORIGIN)
848
388
    screen_write_mode_set(sctx, MODE_ORIGIN);
849
643
  else
850
643
    screen_write_mode_clear(sctx, MODE_ORIGIN);
851
1.03k
  screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy, 0);
852
1.03k
}
853
854
/* Initialise input parser. */
855
struct input_ctx *
856
input_init(struct window_pane *wp, struct bufferevent *bev,
857
    struct colour_palette *palette)
858
12.2k
{
859
12.2k
  struct input_ctx  *ictx;
860
861
12.2k
  ictx = xcalloc(1, sizeof *ictx);
862
12.2k
  ictx->wp = wp;
863
12.2k
  ictx->event = bev;
864
12.2k
  ictx->palette = palette;
865
866
12.2k
  ictx->input_space = INPUT_BUF_START;
867
12.2k
  ictx->input_buf = xmalloc(INPUT_BUF_START);
868
869
12.2k
  ictx->since_ground = evbuffer_new();
870
12.2k
  if (ictx->since_ground == NULL)
871
0
    fatalx("out of memory");
872
12.2k
  evtimer_set(&ictx->ground_timer, input_ground_timer_callback, ictx);
873
874
12.2k
  TAILQ_INIT(&ictx->requests);
875
12.2k
  evtimer_set(&ictx->request_timer, input_request_timer_callback, ictx);
876
877
12.2k
  input_reset(ictx, 0);
878
12.2k
  return (ictx);
879
12.2k
}
880
881
/* Destroy input parser. */
882
void
883
input_free(struct input_ctx *ictx)
884
12.2k
{
885
12.2k
  struct input_request  *ir, *ir1;
886
12.2k
  u_int      i;
887
888
32.9k
  for (i = 0; i < ictx->param_list_len; i++) {
889
20.6k
    if (ictx->param_list[i].type == INPUT_STRING)
890
2.13k
      free(ictx->param_list[i].str);
891
20.6k
  }
892
893
12.2k
  TAILQ_FOREACH_SAFE(ir, &ictx->requests, entry, ir1)
894
0
    input_free_request(ir);
895
12.2k
  event_del(&ictx->request_timer);
896
897
12.2k
  free(ictx->input_buf);
898
12.2k
  evbuffer_free(ictx->since_ground);
899
12.2k
  event_del(&ictx->ground_timer);
900
901
12.2k
  screen_write_stop_sync(ictx->wp);
902
903
12.2k
  free(ictx);
904
12.2k
}
905
906
/* Reset input state and clear screen. */
907
void
908
input_reset(struct input_ctx *ictx, int clear)
909
12.2k
{
910
12.2k
  struct screen_write_ctx *sctx = &ictx->ctx;
911
12.2k
  struct window_pane  *wp = ictx->wp;
912
913
12.2k
  input_reset_cell(ictx);
914
915
12.2k
  if (clear && wp != NULL) {
916
0
    if (TAILQ_EMPTY(&wp->modes))
917
0
      screen_write_start_pane(sctx, wp, &wp->base);
918
0
    else
919
0
      screen_write_start(sctx, &wp->base);
920
0
    screen_write_reset(sctx);
921
0
    screen_write_stop(sctx);
922
0
  }
923
924
12.2k
  input_clear(ictx);
925
926
12.2k
  ictx->state = &input_state_ground;
927
12.2k
  ictx->flags = 0;
928
12.2k
}
929
930
/* Return pending data. */
931
struct evbuffer *
932
input_pending(struct input_ctx *ictx)
933
0
{
934
0
  return (ictx->since_ground);
935
0
}
936
937
/* Change input state. */
938
static void
939
input_set_state(struct input_ctx *ictx, const struct input_transition *itr)
940
225k
{
941
225k
  if (ictx->state->exit != NULL)
942
18.4k
    ictx->state->exit(ictx);
943
225k
  ictx->state = itr->state;
944
225k
  if (ictx->state->enter != NULL)
945
190k
    ictx->state->enter(ictx);
946
225k
}
947
948
/* Parse data. */
949
static void
950
input_parse(struct input_ctx *ictx, u_char *buf, size_t len)
951
12.2k
{
952
12.2k
  struct screen_write_ctx   *sctx = &ictx->ctx;
953
12.2k
  const struct input_state  *state = NULL;
954
12.2k
  const struct input_transition *itr = NULL;
955
12.2k
  size_t         off = 0;
956
957
  /* Parse the input. */
958
521k
  while (off < len) {
959
509k
    ictx->ch = buf[off++];
960
961
    /* Find the transition. */
962
509k
    if (ictx->state != state ||
963
282k
        itr == NULL ||
964
282k
        ictx->ch < itr->first ||
965
348k
        ictx->ch > itr->last) {
966
348k
      itr = ictx->state->transitions;
967
3.07M
      while (itr->first != -1 && itr->last != -1) {
968
3.07M
        if (ictx->ch >= itr->first &&
969
3.04M
            ictx->ch <= itr->last)
970
348k
          break;
971
2.72M
        itr++;
972
2.72M
      }
973
348k
      if (itr->first == -1 || itr->last == -1) {
974
        /* No transition? Eh? */
975
0
        fatalx("no transition from state");
976
0
      }
977
348k
    }
978
509k
    state = ictx->state;
979
980
    /*
981
     * Any state except print stops the current collection. This is
982
     * an optimization to avoid checking if the attributes have
983
     * changed for every character. It will stop unnecessarily for
984
     * sequences that don't make a terminal change, but they should
985
     * be the minority.
986
     */
987
509k
    if (itr->handler != input_print)
988
495k
      screen_write_collect_end(sctx);
989
990
    /*
991
     * Execute the handler, if any. Don't switch state if it
992
     * returns non-zero.
993
     */
994
509k
    if (itr->handler != NULL && itr->handler(ictx) != 0)
995
0
      continue;
996
997
    /* And switch state, if necessary. */
998
509k
    if (itr->state != NULL)
999
225k
      input_set_state(ictx, itr);
1000
1001
    /* If not in ground state, save input. */
1002
509k
    if (ictx->state != &input_state_ground)
1003
414k
      evbuffer_add(ictx->since_ground, &ictx->ch, 1);
1004
509k
  }
1005
12.2k
}
1006
1007
/* Parse input from pane. */
1008
void
1009
input_parse_pane(struct window_pane *wp)
1010
0
{
1011
0
  void  *new_data;
1012
0
  size_t   new_size;
1013
1014
0
  new_data = window_pane_get_new_data(wp, &wp->offset, &new_size);
1015
0
  input_parse_buffer(wp, new_data, new_size);
1016
0
  window_pane_update_used_data(wp, &wp->offset, new_size);
1017
0
}
1018
1019
/* Parse given input. */
1020
void
1021
input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
1022
12.2k
{
1023
12.2k
  struct input_ctx  *ictx = wp->ictx;
1024
12.2k
  struct screen_write_ctx *sctx = &ictx->ctx;
1025
1026
12.2k
  if (len == 0)
1027
0
    return;
1028
1029
12.2k
  window_update_activity(wp->window);
1030
12.2k
  wp->flags |= PANE_CHANGED;
1031
1032
  /* Flag new input while in a mode. */
1033
12.2k
  if (!TAILQ_EMPTY(&wp->modes))
1034
0
    wp->flags |= PANE_UNSEENCHANGES;
1035
1036
  /* NULL wp if there is a mode set as don't want to update the tty. */
1037
12.2k
  if (TAILQ_EMPTY(&wp->modes))
1038
12.2k
    screen_write_start_pane(sctx, wp, &wp->base);
1039
0
  else
1040
0
    screen_write_start(sctx, &wp->base);
1041
1042
12.2k
  log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
1043
12.2k
      ictx->state->name, len, (int)len, buf);
1044
1045
12.2k
  input_parse(ictx, buf, len);
1046
12.2k
  screen_write_stop(sctx);
1047
12.2k
}
1048
1049
/* Parse given input for screen. */
1050
void
1051
input_parse_screen(struct input_ctx *ictx, struct screen *s,
1052
    screen_write_init_ctx_cb cb, void *arg, u_char *buf, size_t len)
1053
0
{
1054
0
  struct screen_write_ctx *sctx = &ictx->ctx;
1055
1056
0
  if (len == 0)
1057
0
    return;
1058
1059
0
  screen_write_start_callback(sctx, s, cb, arg);
1060
0
  input_parse(ictx, buf, len);
1061
0
  screen_write_stop(sctx);
1062
0
}
1063
1064
/* Split the parameter list (if any). */
1065
static int
1066
input_split(struct input_ctx *ictx)
1067
44.3k
{
1068
44.3k
  const char    *errstr;
1069
44.3k
  char      *ptr, *out;
1070
44.3k
  struct input_param  *ip;
1071
44.3k
  u_int      i;
1072
1073
90.6k
  for (i = 0; i < ictx->param_list_len; i++) {
1074
46.3k
    if (ictx->param_list[i].type == INPUT_STRING)
1075
6.23k
      free(ictx->param_list[i].str);
1076
46.3k
  }
1077
44.3k
  ictx->param_list_len = 0;
1078
1079
44.3k
  if (ictx->param_len == 0)
1080
16.1k
    return (0);
1081
28.1k
  ip = &ictx->param_list[0];
1082
1083
28.1k
  ptr = ictx->param_buf;
1084
95.1k
  while ((out = strsep(&ptr, ";")) != NULL) {
1085
67.2k
    if (*out == '\0')
1086
13.9k
      ip->type = INPUT_MISSING;
1087
53.3k
    else {
1088
53.3k
      if (strchr(out, ':') != NULL) {
1089
8.37k
        ip->type = INPUT_STRING;
1090
8.37k
        ip->str = xstrdup(out);
1091
44.9k
      } else {
1092
44.9k
        ip->type = INPUT_NUMBER;
1093
44.9k
        ip->num = strtonum(out, 0, INT_MAX, &errstr);
1094
44.9k
        if (errstr != NULL)
1095
295
          return (-1);
1096
44.9k
      }
1097
53.3k
    }
1098
66.9k
    ip = &ictx->param_list[++ictx->param_list_len];
1099
66.9k
    if (ictx->param_list_len == nitems(ictx->param_list))
1100
37
      return (-1);
1101
66.9k
  }
1102
1103
93.9k
  for (i = 0; i < ictx->param_list_len; i++) {
1104
66.1k
    ip = &ictx->param_list[i];
1105
66.1k
    if (ip->type == INPUT_MISSING)
1106
13.0k
      log_debug("parameter %u: missing", i);
1107
53.0k
    else if (ip->type == INPUT_STRING)
1108
8.37k
      log_debug("parameter %u: string %s", i, ip->str);
1109
44.6k
    else if (ip->type == INPUT_NUMBER)
1110
44.6k
      log_debug("parameter %u: number %d", i, ip->num);
1111
66.1k
  }
1112
1113
27.8k
  return (0);
1114
28.1k
}
1115
1116
/* Get an argument or return default value. */
1117
static int
1118
input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
1119
80.4k
{
1120
80.4k
  struct input_param  *ip;
1121
80.4k
  int      retval;
1122
1123
80.4k
  if (validx >= ictx->param_list_len)
1124
18.4k
      return (defval);
1125
61.9k
  ip = &ictx->param_list[validx];
1126
61.9k
  if (ip->type == INPUT_MISSING)
1127
10.0k
    return (defval);
1128
51.9k
  if (ip->type == INPUT_STRING)
1129
5.28k
    return (-1);
1130
46.6k
  retval = ip->num;
1131
46.6k
  if (retval < minval)
1132
1.80k
    return (minval);
1133
44.8k
  return (retval);
1134
46.6k
}
1135
1136
/* Send reply. */
1137
static void
1138
input_send_reply(struct input_ctx *ictx, const char *reply)
1139
2.76k
{
1140
2.76k
  struct bufferevent  *bev = ictx->event;
1141
1142
2.76k
  if (bev != NULL) {
1143
2.76k
    log_debug("%s: %s", __func__, reply);
1144
2.76k
    bufferevent_write(bev, reply, strlen(reply));
1145
2.76k
  }
1146
2.76k
}
1147
1148
/* Reply to terminal query. */
1149
static void printflike(3, 4)
1150
input_reply(struct input_ctx *ictx, int add, const char *fmt, ...)
1151
2.76k
{
1152
2.76k
  struct input_request  *ir;
1153
2.76k
  va_list      ap;
1154
2.76k
  char      *reply;
1155
1156
2.76k
  va_start(ap, fmt);
1157
2.76k
  xvasprintf(&reply, fmt, ap);
1158
2.76k
  va_end(ap);
1159
1160
2.76k
  if (add && !TAILQ_EMPTY(&ictx->requests)) {
1161
0
    ir = input_make_request(ictx, INPUT_REQUEST_QUEUE);
1162
0
    ir->data = reply;
1163
2.76k
  } else {
1164
2.76k
    input_send_reply(ictx, reply);
1165
2.76k
    free(reply);
1166
2.76k
  }
1167
2.76k
}
1168
1169
/* Clear saved state. */
1170
static void
1171
input_clear(struct input_ctx *ictx)
1172
149k
{
1173
149k
  event_del(&ictx->ground_timer);
1174
1175
149k
  *ictx->interm_buf = '\0';
1176
149k
  ictx->interm_len = 0;
1177
1178
149k
  *ictx->param_buf = '\0';
1179
149k
  ictx->param_len = 0;
1180
1181
149k
  *ictx->input_buf = '\0';
1182
149k
  ictx->input_len = 0;
1183
1184
149k
  ictx->input_end = INPUT_END_ST;
1185
1186
149k
  ictx->flags &= ~INPUT_DISCARD;
1187
149k
}
1188
1189
/* Reset for ground state. */
1190
static void
1191
input_ground(struct input_ctx *ictx)
1192
52.6k
{
1193
52.6k
  event_del(&ictx->ground_timer);
1194
52.6k
  evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
1195
1196
52.6k
  if (ictx->input_space > INPUT_BUF_START) {
1197
49
    ictx->input_space = INPUT_BUF_START;
1198
49
    ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START);
1199
49
  }
1200
52.6k
}
1201
1202
/* Output this character to the screen. */
1203
static int
1204
input_print(struct input_ctx *ictx)
1205
13.6k
{
1206
13.6k
  struct screen_write_ctx *sctx = &ictx->ctx;
1207
13.6k
  int      set;
1208
1209
13.6k
  input_stop_utf8(ictx); /* can't be valid UTF-8 */
1210
1211
13.6k
  set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
1212
13.6k
  if (set == 1)
1213
2.11k
    ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
1214
11.5k
  else
1215
11.5k
    ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1216
13.6k
  utf8_set(&ictx->cell.cell.data, ictx->ch);
1217
13.6k
  screen_write_collect_add(sctx, &ictx->cell.cell);
1218
1219
13.6k
  utf8_copy(&ictx->last, &ictx->cell.cell.data);
1220
13.6k
  ictx->flags |= INPUT_LAST;
1221
1222
13.6k
  ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1223
1224
13.6k
  return (0);
1225
13.6k
}
1226
1227
/* Collect intermediate string. */
1228
static int
1229
input_intermediate(struct input_ctx *ictx)
1230
11.1k
{
1231
11.1k
  if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
1232
572
    ictx->flags |= INPUT_DISCARD;
1233
10.5k
  else {
1234
10.5k
    ictx->interm_buf[ictx->interm_len++] = ictx->ch;
1235
10.5k
    ictx->interm_buf[ictx->interm_len] = '\0';
1236
10.5k
  }
1237
1238
11.1k
  return (0);
1239
11.1k
}
1240
1241
/* Collect parameter string. */
1242
static int
1243
input_parameter(struct input_ctx *ictx)
1244
154k
{
1245
154k
  if (ictx->param_len == (sizeof ictx->param_buf) - 1)
1246
395
    ictx->flags |= INPUT_DISCARD;
1247
154k
  else {
1248
154k
    ictx->param_buf[ictx->param_len++] = ictx->ch;
1249
154k
    ictx->param_buf[ictx->param_len] = '\0';
1250
154k
  }
1251
1252
154k
  return (0);
1253
154k
}
1254
1255
/* Collect input string. */
1256
static int
1257
input_input(struct input_ctx *ictx)
1258
106k
{
1259
106k
  size_t available;
1260
1261
106k
  available = ictx->input_space;
1262
106k
  while (ictx->input_len + 1 >= available) {
1263
497
    available *= 2;
1264
497
    if (available > input_buffer_size) {
1265
0
      ictx->flags |= INPUT_DISCARD;
1266
0
      return (0);
1267
0
    }
1268
497
    ictx->input_buf = xrealloc(ictx->input_buf, available);
1269
497
    ictx->input_space = available;
1270
497
  }
1271
106k
  ictx->input_buf[ictx->input_len++] = ictx->ch;
1272
106k
  ictx->input_buf[ictx->input_len] = '\0';
1273
1274
106k
  return (0);
1275
106k
}
1276
1277
/* Execute C0 control sequence. */
1278
static int
1279
input_c0_dispatch(struct input_ctx *ictx)
1280
25.2k
{
1281
25.2k
  struct screen_write_ctx *sctx = &ictx->ctx;
1282
25.2k
  struct window_pane  *wp = ictx->wp;
1283
25.2k
  struct screen   *s = sctx->s;
1284
25.2k
  struct grid_cell   gc, first_gc;
1285
25.2k
  u_int      cx, line;
1286
25.2k
  u_int      width;
1287
25.2k
  int      has_content = 0;
1288
1289
25.2k
  input_stop_utf8(ictx); /* can't be valid UTF-8 */
1290
1291
25.2k
  log_debug("%s: '%c'", __func__, ictx->ch);
1292
1293
25.2k
  switch (ictx->ch) {
1294
932
  case '\000':  /* NUL */
1295
932
    break;
1296
3.78k
  case '\007':  /* BEL */
1297
3.78k
    if (wp != NULL)
1298
3.78k
      alerts_queue(wp->window, WINDOW_BELL);
1299
3.78k
    break;
1300
3.91k
  case '\010':  /* BS */
1301
3.91k
    screen_write_backspace(sctx);
1302
3.91k
    break;
1303
7.64k
  case '\011':  /* HT */
1304
    /* Don't tab beyond the end of the line. */
1305
7.64k
    cx = s->cx;
1306
7.64k
    if (cx >= screen_size_x(s) - 1)
1307
217
      break;
1308
1309
    /* Find the next tab point, or use the last column if none. */
1310
7.43k
    line = s->cy + s->grid->hsize;
1311
7.43k
    grid_get_cell(s->grid, cx, line, &first_gc);
1312
173k
    do {
1313
173k
      if (!has_content) {
1314
163k
        grid_get_cell(s->grid, cx, line, &gc);
1315
163k
        if (gc.data.size != 1 ||
1316
163k
            *gc.data.data != ' ' ||
1317
163k
            !grid_cells_look_equal(&gc, &first_gc))
1318
1.72k
          has_content = 1;
1319
163k
      }
1320
173k
      cx++;
1321
173k
      if (bit_test(s->tabs, cx))
1322
5.42k
        break;
1323
173k
    } while (cx < screen_size_x(s) - 1);
1324
1325
7.43k
    width = cx - s->cx;
1326
7.43k
    if (has_content || width > sizeof gc.data.data)
1327
3.27k
      s->cx = cx;
1328
4.16k
    else {
1329
4.16k
      grid_get_cell(s->grid, s->cx, line, &gc);
1330
4.16k
      grid_set_tab(&gc, width);
1331
4.16k
      screen_write_collect_add(sctx, &gc);
1332
4.16k
    }
1333
7.43k
    break;
1334
1.79k
  case '\012':  /* LF */
1335
2.48k
  case '\013':  /* VT */
1336
5.59k
  case '\014':  /* FF */
1337
5.59k
    screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1338
5.59k
    if (s->mode & MODE_CRLF)
1339
0
      screen_write_carriagereturn(sctx);
1340
5.59k
    break;
1341
1.87k
  case '\015':  /* CR */
1342
1.87k
    screen_write_carriagereturn(sctx);
1343
1.87k
    break;
1344
259
  case '\016':  /* SO */
1345
259
    ictx->cell.set = 1;
1346
259
    break;
1347
207
  case '\017':  /* SI */
1348
207
    ictx->cell.set = 0;
1349
207
    break;
1350
988
  default:
1351
988
    log_debug("%s: unknown '%c'", __func__, ictx->ch);
1352
988
    break;
1353
25.2k
  }
1354
1355
25.2k
  ictx->flags &= ~INPUT_LAST;
1356
25.2k
  return (0);
1357
25.2k
}
1358
1359
/* Execute escape sequence. */
1360
static int
1361
input_esc_dispatch(struct input_ctx *ictx)
1362
6.72k
{
1363
6.72k
  struct screen_write_ctx   *sctx = &ictx->ctx;
1364
6.72k
  struct screen     *s = sctx->s;
1365
6.72k
  struct input_table_entry  *entry;
1366
1367
6.72k
  if (ictx->flags & INPUT_DISCARD)
1368
66
    return (0);
1369
6.65k
  log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1370
1371
6.65k
  entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
1372
6.65k
      sizeof input_esc_table[0], input_table_compare);
1373
6.65k
  if (entry == NULL) {
1374
518
    log_debug("%s: unknown '%c'", __func__, ictx->ch);
1375
518
    return (0);
1376
518
  }
1377
1378
6.13k
  switch (entry->type) {
1379
763
  case INPUT_ESC_RIS:
1380
763
    colour_palette_clear(ictx->palette);
1381
763
    input_reset_cell(ictx);
1382
763
    screen_write_reset(sctx);
1383
763
    screen_write_fullredraw(sctx);
1384
763
    break;
1385
196
  case INPUT_ESC_IND:
1386
196
    screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1387
196
    break;
1388
453
  case INPUT_ESC_NEL:
1389
453
    screen_write_carriagereturn(sctx);
1390
453
    screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1391
453
    break;
1392
410
  case INPUT_ESC_HTS:
1393
410
    if (s->cx < screen_size_x(s))
1394
216
      bit_set(s->tabs, s->cx);
1395
410
    break;
1396
683
  case INPUT_ESC_RI:
1397
683
    screen_write_reverseindex(sctx, ictx->cell.cell.bg);
1398
683
    break;
1399
198
  case INPUT_ESC_DECKPAM:
1400
198
    screen_write_mode_set(sctx, MODE_KKEYPAD);
1401
198
    break;
1402
238
  case INPUT_ESC_DECKPNM:
1403
238
    screen_write_mode_clear(sctx, MODE_KKEYPAD);
1404
238
    break;
1405
229
  case INPUT_ESC_DECSC:
1406
229
    input_save_state(ictx);
1407
229
    break;
1408
642
  case INPUT_ESC_DECRC:
1409
642
    input_restore_state(ictx);
1410
642
    break;
1411
1.15k
  case INPUT_ESC_DECALN:
1412
1.15k
    screen_write_alignmenttest(sctx);
1413
1.15k
    break;
1414
389
  case INPUT_ESC_SCSG0_ON:
1415
389
    ictx->cell.g0set = 1;
1416
389
    break;
1417
194
  case INPUT_ESC_SCSG0_OFF:
1418
194
    ictx->cell.g0set = 0;
1419
194
    break;
1420
194
  case INPUT_ESC_SCSG1_ON:
1421
194
    ictx->cell.g1set = 1;
1422
194
    break;
1423
194
  case INPUT_ESC_SCSG1_OFF:
1424
194
    ictx->cell.g1set = 0;
1425
194
    break;
1426
198
  case INPUT_ESC_ST:
1427
    /* ST terminates OSC but the state transition already did it. */
1428
198
    break;
1429
6.13k
  }
1430
1431
6.13k
  ictx->flags &= ~INPUT_LAST;
1432
6.13k
  return (0);
1433
6.13k
}
1434
1435
/* Execute control sequence. */
1436
static int
1437
input_csi_dispatch(struct input_ctx *ictx)
1438
44.3k
{
1439
44.3k
  struct screen_write_ctx        *sctx = &ictx->ctx;
1440
44.3k
  struct screen          *s = sctx->s;
1441
44.3k
  struct input_table_entry       *entry;
1442
44.3k
  struct options           *oo;
1443
44.3k
  int       i, n, m, ek, set, p;
1444
44.3k
  u_int       cx, bg = ictx->cell.cell.bg;
1445
1446
44.3k
  if (ictx->flags & INPUT_DISCARD)
1447
67
    return (0);
1448
1449
44.3k
  log_debug("%s: '%c' \"%s\" \"%s\"", __func__, ictx->ch,
1450
44.3k
      ictx->interm_buf, ictx->param_buf);
1451
1452
44.3k
  if (input_split(ictx) != 0)
1453
332
    return (0);
1454
1455
43.9k
  entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1456
43.9k
      sizeof input_csi_table[0], input_table_compare);
1457
43.9k
  if (entry == NULL) {
1458
310
    log_debug("%s: unknown '%c'", __func__, ictx->ch);
1459
310
    return (0);
1460
310
  }
1461
1462
43.6k
  switch (entry->type) {
1463
845
  case INPUT_CSI_CBT:
1464
    /* Find the previous tab point, n times. */
1465
845
    cx = s->cx;
1466
845
    if (cx > screen_size_x(s) - 1)
1467
66
      cx = screen_size_x(s) - 1;
1468
845
    n = input_get(ictx, 0, 1, 1);
1469
845
    if (n == -1)
1470
125
      break;
1471
1.14k
    while (cx > 0 && n-- > 0) {
1472
426
      do
1473
2.95k
        cx--;
1474
2.95k
      while (cx > 0 && !bit_test(s->tabs, cx));
1475
426
    }
1476
720
    s->cx = cx;
1477
720
    break;
1478
976
  case INPUT_CSI_CUB:
1479
976
    n = input_get(ictx, 0, 1, 1);
1480
976
    if (n != -1)
1481
782
      screen_write_cursorleft(sctx, n);
1482
976
    break;
1483
1.06k
  case INPUT_CSI_CUD:
1484
1.06k
    n = input_get(ictx, 0, 1, 1);
1485
1.06k
    if (n != -1)
1486
994
      screen_write_cursordown(sctx, n);
1487
1.06k
    break;
1488
1.49k
  case INPUT_CSI_CUF:
1489
1.49k
    n = input_get(ictx, 0, 1, 1);
1490
1.49k
    if (n != -1)
1491
1.42k
      screen_write_cursorright(sctx, n);
1492
1.49k
    break;
1493
1.11k
  case INPUT_CSI_CUP:
1494
1.11k
    n = input_get(ictx, 0, 1, 1);
1495
1.11k
    m = input_get(ictx, 1, 1, 1);
1496
1.11k
    if (n != -1 && m != -1)
1497
853
      screen_write_cursormove(sctx, m - 1, n - 1, 1);
1498
1.11k
    break;
1499
694
  case INPUT_CSI_MODSET:
1500
694
    n = input_get(ictx, 0, 0, 0);
1501
694
    if (n != 4)
1502
369
      break;
1503
325
    m = input_get(ictx, 1, 0, 0);
1504
1505
    /*
1506
     * Set the extended key reporting mode as per the client
1507
     * request, unless "extended-keys" is set to "off".
1508
     */
1509
325
    ek = options_get_number(global_options, "extended-keys");
1510
325
    if (ek == 0)
1511
325
      break;
1512
0
    screen_write_mode_clear(sctx, EXTENDED_KEY_MODES);
1513
0
    if (m == 2)
1514
0
      screen_write_mode_set(sctx, MODE_KEYS_EXTENDED_2);
1515
0
    else if (m == 1 || ek == 2)
1516
0
      screen_write_mode_set(sctx, MODE_KEYS_EXTENDED);
1517
0
    break;
1518
409
  case INPUT_CSI_MODOFF:
1519
409
    n = input_get(ictx, 0, 0, 0);
1520
409
    if (n != 4)
1521
306
      break;
1522
1523
    /*
1524
     * Clear the extended key reporting mode as per the client
1525
     * request, unless "extended-keys always" forces into mode 1.
1526
     */
1527
103
    screen_write_mode_clear(sctx,
1528
103
        MODE_KEYS_EXTENDED|MODE_KEYS_EXTENDED_2);
1529
103
    if (options_get_number(global_options, "extended-keys") == 2)
1530
0
      screen_write_mode_set(sctx, MODE_KEYS_EXTENDED);
1531
103
    break;
1532
2.25k
  case INPUT_CSI_WINOPS:
1533
2.25k
    input_csi_dispatch_winops(ictx);
1534
2.25k
    break;
1535
844
  case INPUT_CSI_CUU:
1536
844
    n = input_get(ictx, 0, 1, 1);
1537
844
    if (n != -1)
1538
778
      screen_write_cursorup(sctx, n);
1539
844
    break;
1540
1.15k
  case INPUT_CSI_CNL:
1541
1.15k
    n = input_get(ictx, 0, 1, 1);
1542
1.15k
    if (n != -1) {
1543
965
      screen_write_carriagereturn(sctx);
1544
965
      screen_write_cursordown(sctx, n);
1545
965
    }
1546
1.15k
    break;
1547
752
  case INPUT_CSI_CPL:
1548
752
    n = input_get(ictx, 0, 1, 1);
1549
752
    if (n != -1) {
1550
686
      screen_write_carriagereturn(sctx);
1551
686
      screen_write_cursorup(sctx, n);
1552
686
    }
1553
752
    break;
1554
443
  case INPUT_CSI_DA:
1555
443
    switch (input_get(ictx, 0, 0, 0)) {
1556
67
    case -1:
1557
67
      break;
1558
260
    case 0:
1559
#ifdef ENABLE_SIXEL
1560
      input_reply(ictx, 1, "\033[?1;2;4c");
1561
#else
1562
260
      input_reply(ictx, 1, "\033[?1;2c");
1563
260
#endif
1564
260
      break;
1565
116
    default:
1566
116
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1567
116
      break;
1568
443
    }
1569
443
    break;
1570
443
  case INPUT_CSI_DA_TWO:
1571
325
    switch (input_get(ictx, 0, 0, 0)) {
1572
66
    case -1:
1573
66
      break;
1574
134
    case 0:
1575
134
      input_reply(ictx, 1, "\033[>84;0;0c");
1576
134
      break;
1577
125
    default:
1578
125
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1579
125
      break;
1580
325
    }
1581
325
    break;
1582
1.11k
  case INPUT_CSI_ECH:
1583
1.11k
    n = input_get(ictx, 0, 1, 1);
1584
1.11k
    if (n != -1)
1585
1.04k
      screen_write_clearcharacter(sctx, n, bg);
1586
1.11k
    break;
1587
1.33k
  case INPUT_CSI_DCH:
1588
1.33k
    n = input_get(ictx, 0, 1, 1);
1589
1.33k
    if (n != -1)
1590
1.13k
      screen_write_deletecharacter(sctx, n, bg);
1591
1.33k
    break;
1592
1.30k
  case INPUT_CSI_DECSTBM:
1593
1.30k
    n = input_get(ictx, 0, 1, 1);
1594
1.30k
    m = input_get(ictx, 1, 1, screen_size_y(s));
1595
1.30k
    if (n != -1 && m != -1)
1596
1.17k
      screen_write_scrollregion(sctx, n - 1, m - 1);
1597
1.30k
    break;
1598
1.27k
  case INPUT_CSI_DL:
1599
1.27k
    n = input_get(ictx, 0, 1, 1);
1600
1.27k
    if (n != -1)
1601
1.08k
      screen_write_deleteline(sctx, n, bg);
1602
1.27k
    break;
1603
384
  case INPUT_CSI_DSR_PRIVATE:
1604
384
    switch (input_get(ictx, 0, 0, 0)) {
1605
66
    case 996:
1606
66
      input_report_current_theme(ictx);
1607
66
      break;
1608
384
    }
1609
384
    break;
1610
825
  case INPUT_CSI_QUERY_PRIVATE:
1611
825
    switch (input_get(ictx, 0, 0, 0)) {
1612
198
    case 12: /* cursor blink: 1 = blink, 2 = steady */
1613
198
      if (s->cstyle != SCREEN_CURSOR_DEFAULT ||
1614
132
          s->mode & MODE_CURSOR_BLINKING_SET)
1615
132
        n = (s->mode & MODE_CURSOR_BLINKING) ? 1 : 2;
1616
66
      else {
1617
66
        if (ictx->wp != NULL)
1618
66
          oo = ictx->wp->options;
1619
0
        else
1620
0
          oo = global_options;
1621
66
        p = options_get_number(oo, "cursor-style");
1622
1623
        /* blink for 1,3,5; steady for 0,2,4,6 */
1624
66
        n = (p == 1 || p == 3 || p == 5) ? 1 : 2;
1625
66
      }
1626
198
      input_reply(ictx, 1, "\033[?12;%d$y", n);
1627
198
      break;
1628
66
    case 2004: /* bracketed paste */
1629
66
      n = (s->mode & MODE_BRACKETPASTE) ? 1 : 2;
1630
66
      input_reply(ictx, 1, "\033[?2004;%d$y", n);
1631
66
      break;
1632
67
    case 1004: /* focus reporting */
1633
67
      n = (s->mode & MODE_FOCUSON) ? 1 : 2;
1634
67
      input_reply(ictx, 1, "\033[?1004;%d$y", n);
1635
67
      break;
1636
66
    case 1006: /* SGR mouse */
1637
66
      n = (s->mode & MODE_MOUSE_SGR) ? 1 : 2;
1638
66
      input_reply(ictx, 1, "\033[?1006;%d$y", n);
1639
66
      break;
1640
66
    case 2031:
1641
66
      input_reply(ictx, 1, "\033[?2031;2$y");
1642
66
      break;
1643
825
    }
1644
825
    break;
1645
825
  case INPUT_CSI_DSR:
1646
695
    switch (input_get(ictx, 0, 0, 0)) {
1647
66
    case -1:
1648
66
      break;
1649
225
    case 5:
1650
225
      input_reply(ictx, 1, "\033[0n");
1651
225
      break;
1652
69
    case 6:
1653
69
      input_reply(ictx, 1, "\033[%u;%uR", s->cy + 1,
1654
69
          s->cx + 1);
1655
69
      break;
1656
335
    default:
1657
335
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1658
335
      break;
1659
695
    }
1660
695
    break;
1661
3.54k
  case INPUT_CSI_ED:
1662
3.54k
    switch (input_get(ictx, 0, 0, 0)) {
1663
74
    case -1:
1664
74
      break;
1665
2.47k
    case 0:
1666
2.47k
      screen_write_clearendofscreen(sctx, bg);
1667
2.47k
      break;
1668
233
    case 1:
1669
233
      screen_write_clearstartofscreen(sctx, bg);
1670
233
      break;
1671
85
    case 2:
1672
85
      screen_write_clearscreen(sctx, bg);
1673
85
      break;
1674
551
    case 3:
1675
551
      if (input_get(ictx, 1, 0, 0) == 0) {
1676
        /*
1677
         * Linux console extension to clear history
1678
         * (for example before locking the screen).
1679
         */
1680
390
        screen_write_clearhistory(sctx);
1681
390
      }
1682
551
      break;
1683
134
    default:
1684
134
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1685
134
      break;
1686
3.54k
    }
1687
3.54k
    break;
1688
3.54k
  case INPUT_CSI_EL:
1689
2.13k
    switch (input_get(ictx, 0, 0, 0)) {
1690
194
    case -1:
1691
194
      break;
1692
1.59k
    case 0:
1693
1.59k
      screen_write_clearendofline(sctx, bg);
1694
1.59k
      break;
1695
148
    case 1:
1696
148
      screen_write_clearstartofline(sctx, bg);
1697
148
      break;
1698
77
    case 2:
1699
77
      screen_write_clearline(sctx, bg);
1700
77
      break;
1701
124
    default:
1702
124
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1703
124
      break;
1704
2.13k
    }
1705
2.13k
    break;
1706
2.13k
  case INPUT_CSI_HPA:
1707
771
    n = input_get(ictx, 0, 1, 1);
1708
771
    if (n != -1)
1709
705
      screen_write_cursormove(sctx, n - 1, -1, 1);
1710
771
    break;
1711
1.53k
  case INPUT_CSI_ICH:
1712
1.53k
    n = input_get(ictx, 0, 1, 1);
1713
1.53k
    if (n != -1)
1714
1.46k
      screen_write_insertcharacter(sctx, n, bg);
1715
1.53k
    break;
1716
1.40k
  case INPUT_CSI_IL:
1717
1.40k
    n = input_get(ictx, 0, 1, 1);
1718
1.40k
    if (n != -1)
1719
1.21k
      screen_write_insertline(sctx, n, bg);
1720
1.40k
    break;
1721
1.44k
  case INPUT_CSI_REP:
1722
1.44k
    n = input_get(ictx, 0, 1, 1);
1723
1.44k
    if (n == -1)
1724
66
      break;
1725
1726
1.38k
    m = screen_size_x(s) - s->cx;
1727
1.38k
    if (n > m)
1728
376
      n = m;
1729
1730
1.38k
    if (~ictx->flags & INPUT_LAST)
1731
907
      break;
1732
1733
474
    set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
1734
474
    if (set == 1)
1735
167
      ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
1736
307
    else
1737
307
      ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1738
474
    utf8_copy(&ictx->cell.cell.data, &ictx->last);
1739
12.7k
    for (i = 0; i < n; i++)
1740
12.2k
      screen_write_collect_add(sctx, &ictx->cell.cell);
1741
474
    break;
1742
389
  case INPUT_CSI_RCP:
1743
389
    input_restore_state(ictx);
1744
389
    break;
1745
590
  case INPUT_CSI_RM:
1746
590
    input_csi_dispatch_rm(ictx);
1747
590
    break;
1748
1.06k
  case INPUT_CSI_RM_PRIVATE:
1749
1.06k
    input_csi_dispatch_rm_private(ictx);
1750
1.06k
    break;
1751
195
  case INPUT_CSI_SCP:
1752
195
    input_save_state(ictx);
1753
195
    break;
1754
3.94k
  case INPUT_CSI_SGR:
1755
3.94k
    input_csi_dispatch_sgr(ictx);
1756
3.94k
    break;
1757
476
  case INPUT_CSI_SM:
1758
476
    input_csi_dispatch_sm(ictx);
1759
476
    break;
1760
1.08k
  case INPUT_CSI_SM_PRIVATE:
1761
1.08k
    input_csi_dispatch_sm_private(ictx);
1762
1.08k
    break;
1763
66
  case INPUT_CSI_SM_GRAPHICS:
1764
66
    input_csi_dispatch_sm_graphics(ictx);
1765
66
    break;
1766
1.26k
  case INPUT_CSI_SU:
1767
1.26k
    n = input_get(ictx, 0, 1, 1);
1768
1.26k
    if (n != -1)
1769
1.19k
      screen_write_scrollup(sctx, n, bg);
1770
1.26k
    break;
1771
765
  case INPUT_CSI_SD:
1772
765
    n = input_get(ictx, 0, 1, 1);
1773
765
    if (n != -1)
1774
571
      screen_write_scrolldown(sctx, n, bg);
1775
765
    break;
1776
1.24k
  case INPUT_CSI_TBC:
1777
1.24k
    switch (input_get(ictx, 0, 0, 0)) {
1778
194
    case -1:
1779
194
      break;
1780
485
    case 0:
1781
485
      if (s->cx < screen_size_x(s))
1782
291
        bit_clear(s->tabs, s->cx);
1783
485
      break;
1784
433
    case 3:
1785
433
      bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1786
433
      break;
1787
131
    default:
1788
131
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1789
131
      break;
1790
1.24k
    }
1791
1.24k
    break;
1792
1.24k
  case INPUT_CSI_VPA:
1793
1.17k
    n = input_get(ictx, 0, 1, 1);
1794
1.17k
    if (n != -1)
1795
984
      screen_write_cursormove(sctx, -1, n - 1, 1);
1796
1.17k
    break;
1797
847
  case INPUT_CSI_DECSCUSR:
1798
847
    n = input_get(ictx, 0, 0, 0);
1799
847
    if (n == -1)
1800
66
      break;
1801
781
    screen_set_cursor_style(n, &s->cstyle, &s->mode);
1802
781
    if (n == 0) {
1803
      /* Go back to default blinking state. */
1804
261
      screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING_SET);
1805
261
    }
1806
781
    break;
1807
422
  case INPUT_CSI_XDA:
1808
422
    n = input_get(ictx, 0, 0, 0);
1809
422
    if (n == 0) {
1810
273
      input_reply(ictx, 1, "\033P>|tmux %s\033\\",
1811
273
          getversion());
1812
273
    }
1813
422
    break;
1814
1815
43.6k
  }
1816
1817
43.6k
  ictx->flags &= ~INPUT_LAST;
1818
43.6k
  return (0);
1819
43.6k
}
1820
1821
/* Handle CSI RM. */
1822
static void
1823
input_csi_dispatch_rm(struct input_ctx *ictx)
1824
590
{
1825
590
  struct screen_write_ctx *sctx = &ictx->ctx;
1826
590
  u_int      i;
1827
1828
2.58k
  for (i = 0; i < ictx->param_list_len; i++) {
1829
1.99k
    switch (input_get(ictx, i, 0, -1)) {
1830
1.32k
    case -1:
1831
1.32k
      break;
1832
196
    case 4:   /* IRM */
1833
196
      screen_write_mode_clear(sctx, MODE_INSERT);
1834
196
      break;
1835
194
    case 34:
1836
194
      screen_write_mode_set(sctx, MODE_CURSOR_VERY_VISIBLE);
1837
194
      break;
1838
280
    default:
1839
280
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1840
280
      break;
1841
1.99k
    }
1842
1.99k
  }
1843
590
}
1844
1845
/* Handle CSI private RM. */
1846
static void
1847
input_csi_dispatch_rm_private(struct input_ctx *ictx)
1848
1.06k
{
1849
1.06k
  struct screen_write_ctx *sctx = &ictx->ctx;
1850
1.06k
  struct grid_cell  *gc = &ictx->cell.cell;
1851
1.06k
  u_int      i;
1852
1853
5.01k
  for (i = 0; i < ictx->param_list_len; i++) {
1854
3.95k
    switch (input_get(ictx, i, 0, -1)) {
1855
651
    case -1:
1856
651
      break;
1857
199
    case 1:   /* DECCKM */
1858
199
      screen_write_mode_clear(sctx, MODE_KCURSOR);
1859
199
      break;
1860
246
    case 3:   /* DECCOLM */
1861
246
      screen_write_cursormove(sctx, 0, 0, 1);
1862
246
      screen_write_clearscreen(sctx, gc->bg);
1863
246
      break;
1864
217
    case 6:   /* DECOM */
1865
217
      screen_write_mode_clear(sctx, MODE_ORIGIN);
1866
217
      screen_write_cursormove(sctx, 0, 0, 1);
1867
217
      break;
1868
316
    case 7:   /* DECAWM */
1869
316
      screen_write_mode_clear(sctx, MODE_WRAP);
1870
316
      break;
1871
197
    case 12:
1872
197
      screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING);
1873
197
      screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
1874
197
      break;
1875
194
    case 25:  /* TCEM */
1876
194
      screen_write_mode_clear(sctx, MODE_CURSOR);
1877
194
      break;
1878
66
    case 1000:
1879
132
    case 1001:
1880
198
    case 1002:
1881
264
    case 1003:
1882
264
      screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1883
264
      break;
1884
66
    case 1004:
1885
66
      screen_write_mode_clear(sctx, MODE_FOCUSON);
1886
66
      break;
1887
66
    case 1005:
1888
66
      screen_write_mode_clear(sctx, MODE_MOUSE_UTF8);
1889
66
      break;
1890
66
    case 1006:
1891
66
      screen_write_mode_clear(sctx, MODE_MOUSE_SGR);
1892
66
      break;
1893
543
    case 47:
1894
609
    case 1047:
1895
609
      screen_write_alternateoff(sctx, gc, 0);
1896
609
      break;
1897
194
    case 1049:
1898
194
      screen_write_alternateoff(sctx, gc, 1);
1899
194
      break;
1900
66
    case 2004:
1901
66
      screen_write_mode_clear(sctx, MODE_BRACKETPASTE);
1902
66
      break;
1903
66
    case 2031:
1904
66
      screen_write_mode_clear(sctx, MODE_THEME_UPDATES);
1905
66
      if (ictx->wp != NULL)
1906
66
        ictx->wp->flags &= ~PANE_THEMECHANGED;
1907
66
      break;
1908
180
    case 2026:  /* synchronized output */
1909
180
      screen_write_stop_sync(ictx->wp);
1910
180
      if (ictx->wp != NULL)
1911
180
        ictx->wp->flags |= PANE_REDRAW;
1912
180
      break;
1913
357
    default:
1914
357
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1915
357
      break;
1916
3.95k
    }
1917
3.95k
  }
1918
1.06k
}
1919
1920
/* Handle CSI SM. */
1921
static void
1922
input_csi_dispatch_sm(struct input_ctx *ictx)
1923
476
{
1924
476
  struct screen_write_ctx *sctx = &ictx->ctx;
1925
476
  u_int      i;
1926
1927
1.96k
  for (i = 0; i < ictx->param_list_len; i++) {
1928
1.49k
    switch (input_get(ictx, i, 0, -1)) {
1929
744
    case -1:
1930
744
      break;
1931
239
    case 4:   /* IRM */
1932
239
      screen_write_mode_set(sctx, MODE_INSERT);
1933
239
      break;
1934
194
    case 34:
1935
194
      screen_write_mode_clear(sctx, MODE_CURSOR_VERY_VISIBLE);
1936
194
      break;
1937
315
    default:
1938
315
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
1939
315
      break;
1940
1.49k
    }
1941
1.49k
  }
1942
476
}
1943
1944
/* Handle CSI private SM. */
1945
static void
1946
input_csi_dispatch_sm_private(struct input_ctx *ictx)
1947
1.08k
{
1948
1.08k
  struct screen_write_ctx *sctx = &ictx->ctx;
1949
1.08k
  struct grid_cell  *gc = &ictx->cell.cell;
1950
1.08k
  u_int      i;
1951
1952
5.22k
  for (i = 0; i < ictx->param_list_len; i++) {
1953
4.14k
    switch (input_get(ictx, i, 0, -1)) {
1954
619
    case -1:
1955
619
      break;
1956
222
    case 1:   /* DECCKM */
1957
222
      screen_write_mode_set(sctx, MODE_KCURSOR);
1958
222
      break;
1959
225
    case 3:   /* DECCOLM */
1960
225
      screen_write_cursormove(sctx, 0, 0, 1);
1961
225
      screen_write_clearscreen(sctx, ictx->cell.cell.bg);
1962
225
      break;
1963
244
    case 6:   /* DECOM */
1964
244
      screen_write_mode_set(sctx, MODE_ORIGIN);
1965
244
      screen_write_cursormove(sctx, 0, 0, 1);
1966
244
      break;
1967
197
    case 7:   /* DECAWM */
1968
197
      screen_write_mode_set(sctx, MODE_WRAP);
1969
197
      break;
1970
286
    case 12:
1971
286
      screen_write_mode_set(sctx, MODE_CURSOR_BLINKING);
1972
286
      screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
1973
286
      break;
1974
194
    case 25:  /* TCEM */
1975
194
      screen_write_mode_set(sctx, MODE_CURSOR);
1976
194
      break;
1977
66
    case 1000:
1978
66
      screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1979
66
      screen_write_mode_set(sctx, MODE_MOUSE_STANDARD);
1980
66
      break;
1981
66
    case 1002:
1982
66
      screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1983
66
      screen_write_mode_set(sctx, MODE_MOUSE_BUTTON);
1984
66
      break;
1985
81
    case 1003:
1986
81
      screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1987
81
      screen_write_mode_set(sctx, MODE_MOUSE_ALL);
1988
81
      break;
1989
68
    case 1004:
1990
68
      screen_write_mode_set(sctx, MODE_FOCUSON);
1991
68
      break;
1992
66
    case 1005:
1993
66
      screen_write_mode_set(sctx, MODE_MOUSE_UTF8);
1994
66
      break;
1995
66
    case 1006:
1996
66
      screen_write_mode_set(sctx, MODE_MOUSE_SGR);
1997
66
      break;
1998
915
    case 47:
1999
981
    case 1047:
2000
981
      screen_write_alternateon(sctx, gc, 0);
2001
981
      break;
2002
152
    case 1049:
2003
152
      screen_write_alternateon(sctx, gc, 1);
2004
152
      break;
2005
66
    case 2004:
2006
66
      screen_write_mode_set(sctx, MODE_BRACKETPASTE);
2007
66
      break;
2008
66
    case 2031:
2009
66
      screen_write_mode_set(sctx, MODE_THEME_UPDATES);
2010
66
      if (ictx->wp != NULL) {
2011
66
        ictx->wp->last_theme = window_pane_get_theme(ictx->wp);
2012
66
        ictx->wp->flags &= ~PANE_THEMECHANGED;
2013
66
      }
2014
66
      break;
2015
136
    case 2026:  /* synchronized output */
2016
136
      screen_write_start_sync(ictx->wp);
2017
136
      break;
2018
344
    default:
2019
344
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
2020
344
      break;
2021
4.14k
    }
2022
4.14k
  }
2023
1.08k
}
2024
2025
/* Handle CSI graphics SM. */
2026
static void
2027
input_csi_dispatch_sm_graphics(__unused struct input_ctx *ictx)
2028
66
{
2029
#ifdef ENABLE_SIXEL
2030
  int n, m, o;
2031
2032
  if (ictx->param_list_len > 3)
2033
    return;
2034
  n = input_get(ictx, 0, 0, 0);
2035
  m = input_get(ictx, 1, 0, 0);
2036
  o = input_get(ictx, 2, 0, 0);
2037
2038
  if (n == 1 && (m == 1 || m == 2 || m == 4)) {
2039
    input_reply(ictx, 1, "\033[?%d;0;%uS", n,
2040
        SIXEL_COLOUR_REGISTERS);
2041
  } else
2042
    input_reply(ictx, 1, "\033[?%d;3;%dS", n, o);
2043
#endif
2044
66
}
2045
2046
/* Handle CSI window operations. */
2047
static void
2048
input_csi_dispatch_winops(struct input_ctx *ictx)
2049
2.25k
{
2050
2.25k
  struct screen_write_ctx *sctx = &ictx->ctx;
2051
2.25k
  struct screen   *s = sctx->s;
2052
2.25k
  struct window_pane  *wp = ictx->wp;
2053
2.25k
  struct window   *w = NULL;
2054
2.25k
  u_int      x = screen_size_x(s), y = screen_size_y(s);
2055
2.25k
  int      n, m;
2056
2057
2.25k
  if (wp != NULL)
2058
2.25k
    w = wp->window;
2059
2060
2.25k
  m = 0;
2061
6.19k
  while ((n = input_get(ictx, m, 0, -1)) != -1) {
2062
5.12k
    switch (n) {
2063
206
    case 1:
2064
426
    case 2:
2065
621
    case 5:
2066
817
    case 6:
2067
1.01k
    case 7:
2068
1.07k
    case 11:
2069
1.27k
    case 13:
2070
1.46k
    case 20:
2071
1.66k
    case 21:
2072
1.85k
    case 24:
2073
1.85k
      break;
2074
148
    case 3:
2075
370
    case 4:
2076
531
    case 8:
2077
531
      m++;
2078
531
      if (input_get(ictx, m, 0, -1) == -1)
2079
465
        return;
2080
      /* FALLTHROUGH */
2081
334
    case 9:
2082
400
    case 10:
2083
400
      m++;
2084
400
      if (input_get(ictx, m, 0, -1) == -1)
2085
328
        return;
2086
72
      break;
2087
194
    case 14:
2088
194
      if (w == NULL)
2089
0
        break;
2090
194
      input_reply(ictx, 1, "\033[4;%u;%ut", y * w->ypixel,
2091
194
          x * w->xpixel);
2092
194
      break;
2093
66
    case 15:
2094
66
      if (w == NULL)
2095
0
        break;
2096
66
      input_reply(ictx, 1, "\033[5;%u;%ut", y * w->ypixel,
2097
66
          x * w->xpixel);
2098
66
      break;
2099
194
    case 16:
2100
194
      if (w == NULL)
2101
0
        break;
2102
194
      input_reply(ictx, 1, "\033[6;%u;%ut", w->ypixel,
2103
194
          w->xpixel);
2104
194
      break;
2105
194
    case 18:
2106
194
      input_reply(ictx, 1, "\033[8;%u;%ut", y, x);
2107
194
      break;
2108
66
    case 19:
2109
66
      input_reply(ictx, 1, "\033[9;%u;%ut", y, x);
2110
66
      break;
2111
731
    case 22:
2112
731
      m++;
2113
731
      switch (input_get(ictx, m, 0, -1)) {
2114
201
      case -1:
2115
201
        return;
2116
272
      case 0:
2117
403
      case 2:
2118
403
        screen_push_title(sctx->s);
2119
403
        break;
2120
731
      }
2121
530
      break;
2122
705
    case 23:
2123
705
      m++;
2124
705
      switch (input_get(ictx, m, 0, -1)) {
2125
198
      case -1:
2126
198
        return;
2127
108
      case 0:
2128
393
      case 2:
2129
393
        screen_pop_title(sctx->s);
2130
393
        if (wp == NULL)
2131
0
          break;
2132
393
        notify_pane("pane-title-changed", wp);
2133
393
        server_redraw_window_borders(w);
2134
393
        server_status_window(w);
2135
393
        break;
2136
705
      }
2137
507
      break;
2138
507
    default:
2139
258
      log_debug("%s: unknown '%c'", __func__, ictx->ch);
2140
258
      break;
2141
5.12k
    }
2142
3.93k
    m++;
2143
3.93k
  }
2144
2.25k
}
2145
2146
/* Helper for 256 colour SGR. */
2147
static int
2148
input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c)
2149
1.23k
{
2150
1.23k
  struct grid_cell  *gc = &ictx->cell.cell;
2151
2152
1.23k
  if (c == -1 || c > 255) {
2153
686
    if (fgbg == 38)
2154
157
      gc->fg = 8;
2155
529
    else if (fgbg == 48)
2156
305
      gc->bg = 8;
2157
686
  } else {
2158
545
    if (fgbg == 38)
2159
169
      gc->fg = c | COLOUR_FLAG_256;
2160
376
    else if (fgbg == 48)
2161
215
      gc->bg = c | COLOUR_FLAG_256;
2162
161
    else if (fgbg == 58)
2163
161
      gc->us = c | COLOUR_FLAG_256;
2164
545
  }
2165
1.23k
  return (1);
2166
1.23k
}
2167
2168
/* Handle CSI SGR for 256 colours. */
2169
static void
2170
input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
2171
707
{
2172
707
  int c;
2173
2174
707
  c = input_get(ictx, (*i) + 1, 0, -1);
2175
707
  if (input_csi_dispatch_sgr_256_do(ictx, fgbg, c))
2176
707
    (*i)++;
2177
707
}
2178
2179
/* Helper for RGB colour SGR. */
2180
static int
2181
input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g,
2182
    int b)
2183
2.56k
{
2184
2.56k
  struct grid_cell  *gc = &ictx->cell.cell;
2185
2186
2.56k
  if (r == -1 || r > 255)
2187
907
    return (0);
2188
1.65k
  if (g == -1 || g > 255)
2189
378
    return (0);
2190
1.27k
  if (b == -1 || b > 255)
2191
492
    return (0);
2192
2193
783
  if (fgbg == 38)
2194
229
    gc->fg = colour_join_rgb(r, g, b);
2195
554
  else if (fgbg == 48)
2196
382
    gc->bg = colour_join_rgb(r, g, b);
2197
172
  else if (fgbg == 58)
2198
172
    gc->us = colour_join_rgb(r, g, b);
2199
783
  return (1);
2200
1.27k
}
2201
2202
/* Handle CSI SGR for RGB colours. */
2203
static void
2204
input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
2205
1.70k
{
2206
1.70k
  int r, g, b;
2207
2208
1.70k
  r = input_get(ictx, (*i) + 1, 0, -1);
2209
1.70k
  g = input_get(ictx, (*i) + 2, 0, -1);
2210
1.70k
  b = input_get(ictx, (*i) + 3, 0, -1);
2211
1.70k
  if (input_csi_dispatch_sgr_rgb_do(ictx, fgbg, r, g, b))
2212
449
    (*i) += 3;
2213
1.70k
}
2214
2215
/* Handle CSI SGR with a ISO parameter. */
2216
static void
2217
input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
2218
3.31k
{
2219
3.31k
  struct grid_cell  *gc = &ictx->cell.cell;
2220
3.31k
  char      *s = ictx->param_list[i].str, *copy, *ptr, *out;
2221
3.31k
  int      p[8];
2222
3.31k
  u_int      n;
2223
3.31k
  const char    *errstr;
2224
2225
29.8k
  for (n = 0; n < nitems(p); n++)
2226
26.5k
    p[n] = -1;
2227
3.31k
  n = 0;
2228
2229
3.31k
  ptr = copy = xstrdup(s);
2230
13.9k
  while ((out = strsep(&ptr, ":")) != NULL) {
2231
10.8k
    if (*out != '\0') {
2232
6.91k
      p[n++] = strtonum(out, 0, INT_MAX, &errstr);
2233
6.91k
      if (errstr != NULL || n == nitems(p)) {
2234
132
        free(copy);
2235
132
        return;
2236
132
      }
2237
6.91k
    } else {
2238
3.89k
      n++;
2239
3.89k
      if (n == nitems(p)) {
2240
87
        free(copy);
2241
87
        return;
2242
87
      }
2243
3.89k
    }
2244
10.5k
    log_debug("%s: %u = %d", __func__, n - 1, p[n - 1]);
2245
10.5k
  }
2246
3.09k
  free(copy);
2247
2248
3.09k
  if (n == 0)
2249
0
    return;
2250
3.09k
  if (p[0] == 4) {
2251
731
    if (n != 2)
2252
67
      return;
2253
664
    switch (p[1]) {
2254
130
    case 0:
2255
130
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2256
130
      break;
2257
66
    case 1:
2258
66
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2259
66
      gc->attr |= GRID_ATTR_UNDERSCORE;
2260
66
      break;
2261
66
    case 2:
2262
66
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2263
66
      gc->attr |= GRID_ATTR_UNDERSCORE_2;
2264
66
      break;
2265
69
    case 3:
2266
69
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2267
69
      gc->attr |= GRID_ATTR_UNDERSCORE_3;
2268
69
      break;
2269
69
    case 4:
2270
69
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2271
69
      gc->attr |= GRID_ATTR_UNDERSCORE_4;
2272
69
      break;
2273
69
    case 5:
2274
69
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2275
69
      gc->attr |= GRID_ATTR_UNDERSCORE_5;
2276
69
      break;
2277
664
    }
2278
664
    return;
2279
664
  }
2280
2.36k
  if (n < 2 || (p[0] != 38 && p[0] != 48 && p[0] != 58))
2281
581
    return;
2282
1.78k
  switch (p[1]) {
2283
1.00k
  case 2:
2284
1.00k
    if (n < 3)
2285
78
      break;
2286
926
    if (n == 5)
2287
846
      i = 2;
2288
80
    else
2289
80
      i = 3;
2290
926
    if (n < i + 3)
2291
66
      break;
2292
860
    input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[i], p[i + 1],
2293
860
        p[i + 2]);
2294
860
    break;
2295
590
  case 5:
2296
590
    if (n < 3)
2297
66
      break;
2298
524
    input_csi_dispatch_sgr_256_do(ictx, p[0], p[2]);
2299
524
    break;
2300
1.78k
  }
2301
1.78k
}
2302
2303
/* Handle CSI SGR. */
2304
static void
2305
input_csi_dispatch_sgr(struct input_ctx *ictx)
2306
3.94k
{
2307
3.94k
  struct grid_cell  *gc = &ictx->cell.cell;
2308
3.94k
  u_int      i, link;
2309
3.94k
  int      n;
2310
2311
3.94k
  if (ictx->param_list_len == 0) {
2312
197
    memcpy(gc, &grid_default_cell, sizeof *gc);
2313
197
    return;
2314
197
  }
2315
2316
21.8k
  for (i = 0; i < ictx->param_list_len; i++) {
2317
18.1k
    if (ictx->param_list[i].type == INPUT_STRING) {
2318
3.31k
      input_csi_dispatch_sgr_colon(ictx, i);
2319
3.31k
      continue;
2320
3.31k
    }
2321
14.7k
    n = input_get(ictx, i, 0, 0);
2322
14.7k
    if (n == -1)
2323
0
      continue;
2324
2325
14.7k
    if (n == 38 || n == 48 || n == 58) {
2326
2.84k
      i++;
2327
2.84k
      switch (input_get(ictx, i, 0, -1)) {
2328
1.70k
      case 2:
2329
1.70k
        input_csi_dispatch_sgr_rgb(ictx, n, &i);
2330
1.70k
        break;
2331
707
      case 5:
2332
707
        input_csi_dispatch_sgr_256(ictx, n, &i);
2333
707
        break;
2334
2.84k
      }
2335
2.84k
      continue;
2336
2.84k
    }
2337
2338
11.9k
    switch (n) {
2339
1.50k
    case 0:
2340
1.50k
      link = gc->link;
2341
1.50k
      memcpy(gc, &grid_default_cell, sizeof *gc);
2342
1.50k
      gc->link = link;
2343
1.50k
      break;
2344
284
    case 1:
2345
284
      gc->attr |= GRID_ATTR_BRIGHT;
2346
284
      break;
2347
379
    case 2:
2348
379
      gc->attr |= GRID_ATTR_DIM;
2349
379
      break;
2350
316
    case 3:
2351
316
      gc->attr |= GRID_ATTR_ITALICS;
2352
316
      break;
2353
265
    case 4:
2354
265
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2355
265
      gc->attr |= GRID_ATTR_UNDERSCORE;
2356
265
      break;
2357
290
    case 5:
2358
554
    case 6:
2359
554
      gc->attr |= GRID_ATTR_BLINK;
2360
554
      break;
2361
228
    case 7:
2362
228
      gc->attr |= GRID_ATTR_REVERSE;
2363
228
      break;
2364
266
    case 8:
2365
266
      gc->attr |= GRID_ATTR_HIDDEN;
2366
266
      break;
2367
274
    case 9:
2368
274
      gc->attr |= GRID_ATTR_STRIKETHROUGH;
2369
274
      break;
2370
207
    case 21:
2371
207
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2372
207
      gc->attr |= GRID_ATTR_UNDERSCORE_2;
2373
207
      break;
2374
196
    case 22:
2375
196
      gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
2376
196
      break;
2377
194
    case 23:
2378
194
      gc->attr &= ~GRID_ATTR_ITALICS;
2379
194
      break;
2380
194
    case 24:
2381
194
      gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2382
194
      break;
2383
195
    case 25:
2384
195
      gc->attr &= ~GRID_ATTR_BLINK;
2385
195
      break;
2386
194
    case 27:
2387
194
      gc->attr &= ~GRID_ATTR_REVERSE;
2388
194
      break;
2389
196
    case 28:
2390
196
      gc->attr &= ~GRID_ATTR_HIDDEN;
2391
196
      break;
2392
66
    case 29:
2393
66
      gc->attr &= ~GRID_ATTR_STRIKETHROUGH;
2394
66
      break;
2395
199
    case 30:
2396
268
    case 31:
2397
465
    case 32:
2398
659
    case 33:
2399
855
    case 34:
2400
1.05k
    case 35:
2401
1.24k
    case 36:
2402
1.44k
    case 37:
2403
1.44k
      gc->fg = n - 30;
2404
1.44k
      break;
2405
66
    case 39:
2406
66
      gc->fg = 8;
2407
66
      break;
2408
246
    case 40:
2409
454
    case 41:
2410
679
    case 42:
2411
891
    case 43:
2412
1.10k
    case 44:
2413
1.31k
    case 45:
2414
1.53k
    case 46:
2415
1.73k
    case 47:
2416
1.73k
      gc->bg = n - 40;
2417
1.73k
      break;
2418
194
    case 49:
2419
194
      gc->bg = 8;
2420
194
      break;
2421
207
    case 53:
2422
207
      gc->attr |= GRID_ATTR_OVERLINE;
2423
207
      break;
2424
195
    case 55:
2425
195
      gc->attr &= ~GRID_ATTR_OVERLINE;
2426
195
      break;
2427
69
    case 59:
2428
69
      gc->us = 8;
2429
69
      break;
2430
74
    case 90:
2431
272
    case 91:
2432
468
    case 92:
2433
664
    case 93:
2434
861
    case 94:
2435
1.06k
    case 95:
2436
1.26k
    case 96:
2437
1.45k
    case 97:
2438
1.45k
      gc->fg = n;
2439
1.45k
      break;
2440
67
    case 100:
2441
134
    case 101:
2442
201
    case 102:
2443
267
    case 103:
2444
335
    case 104:
2445
407
    case 105:
2446
474
    case 106:
2447
540
    case 107:
2448
540
      gc->bg = n - 10;
2449
540
      break;
2450
11.9k
    }
2451
11.9k
  }
2452
3.74k
}
2453
2454
/* End of input with BEL. */
2455
static int
2456
input_end_bel(struct input_ctx *ictx)
2457
416
{
2458
416
  log_debug("%s", __func__);
2459
2460
416
  ictx->input_end = INPUT_END_BEL;
2461
2462
416
  return (0);
2463
416
}
2464
2465
/* DCS string started. */
2466
static void
2467
input_enter_dcs(struct input_ctx *ictx)
2468
961
{
2469
961
  log_debug("%s", __func__);
2470
2471
961
  input_clear(ictx);
2472
961
  input_start_ground_timer(ictx);
2473
961
  ictx->flags &= ~INPUT_LAST;
2474
961
}
2475
2476
/* Handle DECRQSS query. */
2477
static int
2478
input_handle_decrqss(struct input_ctx *ictx)
2479
475
{
2480
475
  struct window_pane  *wp = ictx->wp;
2481
475
  struct options    *oo;
2482
475
  struct screen_write_ctx *sctx = &ictx->ctx;
2483
475
  u_char      *buf = ictx->input_buf;
2484
475
  size_t       len = ictx->input_len;
2485
475
  struct screen   *s = sctx->s;
2486
475
  int      ps, opt_ps, blinking;
2487
2488
475
  if (len < 3 || buf[1] != ' ' || buf[2] != 'q')
2489
211
    goto not_recognized;
2490
2491
  /*
2492
   * Cursor style query: DCS $ q SP q
2493
   * Reply: DCS 1 $ r SP q <Ps> SP q ST
2494
   */
2495
264
  if (s->cstyle == SCREEN_CURSOR_BLOCK ||
2496
198
      s->cstyle == SCREEN_CURSOR_UNDERLINE ||
2497
198
      s->cstyle == SCREEN_CURSOR_BAR) {
2498
198
    blinking = (s->mode & MODE_CURSOR_BLINKING) != 0;
2499
198
    switch (s->cstyle) {
2500
66
    case SCREEN_CURSOR_BLOCK:
2501
66
      ps = blinking ? 1 : 2;
2502
66
      break;
2503
66
    case SCREEN_CURSOR_UNDERLINE:
2504
66
      ps = blinking ? 3 : 4;
2505
66
      break;
2506
66
    case SCREEN_CURSOR_BAR:
2507
66
      ps = blinking ? 5 : 6;
2508
66
      break;
2509
0
    default:
2510
0
      ps = 0;
2511
0
      break;
2512
198
    }
2513
198
  } else {
2514
    /*
2515
     * No explicit runtime style: fall back to the configured
2516
     * cursor-style option (integer Ps 0..6). Pane options inherit.
2517
     */
2518
66
    if (wp != NULL)
2519
66
      oo = wp->options;
2520
0
    else
2521
0
      oo = global_options;
2522
66
    opt_ps = options_get_number(oo, "cursor-style");
2523
2524
    /* Sanity clamp: valid Ps are 0..6 per DECSCUSR. */
2525
66
    if (opt_ps < 0 || opt_ps > 6)
2526
0
      opt_ps = 0;
2527
66
    ps = opt_ps;
2528
66
  }
2529
2530
264
  log_debug("%s: DECRQSS cursor -> Ps=%d (cstyle=%d mode=%#x)", __func__,
2531
264
      ps, s->cstyle, s->mode);
2532
2533
264
  input_reply(ictx, 1, "\033P1$r q%d q\033\\", ps);
2534
264
  return (0);
2535
2536
211
not_recognized:
2537
  /* Unrecognized DECRQSS: send DCS 0 $ r Pt ST. */
2538
211
  input_reply(ictx, 1, "\033P0$r\033\\");
2539
211
  return (0);
2540
264
}
2541
2542
/* DCS terminator (ST) received. */
2543
static int
2544
input_dcs_dispatch(struct input_ctx *ictx)
2545
756
{
2546
756
  struct window_pane  *wp = ictx->wp;
2547
756
  struct options    *oo;
2548
756
  struct screen_write_ctx *sctx = &ictx->ctx;
2549
756
  u_char      *buf = ictx->input_buf;
2550
756
  size_t       len = ictx->input_len;
2551
756
  const char     prefix[] = "tmux;";
2552
756
  const u_int    prefixlen = (sizeof prefix) - 1;
2553
756
  long long    allow_passthrough = 0;
2554
#ifdef ENABLE_SIXEL
2555
  struct window   *w;
2556
  struct sixel_image  *si;
2557
  int      p2;
2558
#endif
2559
2560
756
  if (wp == NULL)
2561
0
    return (0);
2562
756
  oo = wp->options;
2563
2564
756
  if (ictx->flags & INPUT_DISCARD) {
2565
66
    log_debug("%s: %zu bytes (discard)", __func__, len);
2566
66
    return (0);
2567
66
  }
2568
2569
#ifdef ENABLE_SIXEL
2570
  w = wp->window;
2571
  if (buf[0] == 'q' && ictx->interm_len == 0) {
2572
    if (input_split(ictx) != 0)
2573
      return (0);
2574
    p2 = input_get(ictx, 1, 0, 0);
2575
    if (p2 == -1)
2576
      p2 = 0;
2577
    si = sixel_parse(buf, len, p2, w->xpixel, w->ypixel);
2578
    if (si != NULL)
2579
      screen_write_sixelimage(sctx, si, ictx->cell.cell.bg);
2580
  }
2581
#endif
2582
2583
  /* DCS sequences with intermediate byte '$' (includes DECRQSS). */
2584
690
  if (ictx->interm_len == 1 && ictx->interm_buf[0] == '$') {
2585
    /* DECRQSS is DCS $ q Pt ST. */
2586
551
    if (len >= 1 && buf[0] == 'q')
2587
475
      return (input_handle_decrqss(ictx));
2588
2589
    /*
2590
     * Not DECRQSS. DCS '$' is currently only used by DECRQSS, but
2591
     * leave other '$' DCS (if any appear in future) to existing
2592
     * handlers.
2593
     */
2594
551
  }
2595
2596
215
  allow_passthrough = options_get_number(oo, "allow-passthrough");
2597
215
  if (!allow_passthrough)
2598
215
    return (0);
2599
0
  log_debug("%s: \"%s\"", __func__, buf);
2600
2601
0
  if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) {
2602
0
    screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen,
2603
0
        allow_passthrough == 2);
2604
0
  }
2605
2606
0
  return (0);
2607
215
}
2608
2609
/* OSC string started. */
2610
static void
2611
input_enter_osc(struct input_ctx *ictx)
2612
14.0k
{
2613
14.0k
  log_debug("%s", __func__);
2614
2615
14.0k
  input_clear(ictx);
2616
14.0k
  input_start_ground_timer(ictx);
2617
14.0k
  ictx->flags &= ~INPUT_LAST;
2618
14.0k
}
2619
2620
/* OSC terminator (ST) received. */
2621
static void
2622
input_exit_osc(struct input_ctx *ictx)
2623
14.0k
{
2624
14.0k
  struct screen_write_ctx *sctx = &ictx->ctx;
2625
14.0k
  struct window_pane  *wp = ictx->wp;
2626
14.0k
  u_char      *p = ictx->input_buf;
2627
14.0k
  u_int      option;
2628
2629
14.0k
  if (ictx->flags & INPUT_DISCARD)
2630
0
    return;
2631
14.0k
  if (ictx->input_len < 1 || *p < '0' || *p > '9')
2632
1.00k
    return;
2633
2634
13.0k
  log_debug("%s: \"%s\" (end %s)", __func__, p,
2635
13.0k
      ictx->input_end == INPUT_END_ST ? "ST" : "BEL");
2636
2637
13.0k
  option = 0;
2638
30.9k
  while (*p >= '0' && *p <= '9')
2639
17.9k
    option = option * 10 + *p++ - '0';
2640
13.0k
  if (*p != ';' && *p != '\0')
2641
109
    return;
2642
12.9k
  if (*p == ';')
2643
11.1k
    p++;
2644
2645
12.9k
  switch (option) {
2646
303
  case 0:
2647
508
  case 2:
2648
508
    if (wp != NULL &&
2649
508
        options_get_number(wp->options, "allow-set-title") &&
2650
508
        screen_set_title(sctx->s, p)) {
2651
441
      notify_pane("pane-title-changed", wp);
2652
441
      server_redraw_window_borders(wp->window);
2653
441
      server_status_window(wp->window);
2654
441
    }
2655
508
    break;
2656
762
  case 4:
2657
762
    input_osc_4(ictx, p);
2658
762
    break;
2659
261
  case 7:
2660
261
    if (utf8_isvalid(p)) {
2661
195
      screen_set_path(sctx->s, p);
2662
195
      if (wp != NULL) {
2663
195
        server_redraw_window_borders(wp->window);
2664
195
        server_status_window(wp->window);
2665
195
      }
2666
195
    }
2667
261
    break;
2668
7.41k
  case 8:
2669
7.41k
    input_osc_8(ictx, p);
2670
7.41k
    break;
2671
228
  case 10:
2672
228
    input_osc_10(ictx, p);
2673
228
    break;
2674
289
  case 11:
2675
289
    input_osc_11(ictx, p);
2676
289
    break;
2677
490
  case 12:
2678
490
    input_osc_12(ictx, p);
2679
490
    break;
2680
1.83k
  case 52:
2681
1.83k
    input_osc_52(ictx, p);
2682
1.83k
    break;
2683
281
  case 104:
2684
281
    input_osc_104(ictx, p);
2685
281
    break;
2686
138
  case 110:
2687
138
    input_osc_110(ictx, p);
2688
138
    break;
2689
134
  case 111:
2690
134
    input_osc_111(ictx, p);
2691
134
    break;
2692
133
  case 112:
2693
133
    input_osc_112(ictx, p);
2694
133
    break;
2695
198
  case 133:
2696
198
    input_osc_133(ictx, p);
2697
198
    break;
2698
244
  default:
2699
244
    log_debug("%s: unknown '%u'", __func__, option);
2700
244
    break;
2701
12.9k
  }
2702
12.9k
}
2703
2704
/* APC string started. */
2705
static void
2706
input_enter_apc(struct input_ctx *ictx)
2707
2.54k
{
2708
2.54k
  log_debug("%s", __func__);
2709
2710
2.54k
  input_clear(ictx);
2711
2.54k
  input_start_ground_timer(ictx);
2712
2.54k
  ictx->flags &= ~INPUT_LAST;
2713
2.54k
}
2714
2715
/* APC terminator (ST) received. */
2716
static void
2717
input_exit_apc(struct input_ctx *ictx)
2718
2.53k
{
2719
2.53k
  struct screen_write_ctx *sctx = &ictx->ctx;
2720
2.53k
  struct window_pane  *wp = ictx->wp;
2721
2722
2.53k
  if (ictx->flags & INPUT_DISCARD)
2723
0
    return;
2724
2.53k
  log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2725
2726
2.53k
  if (wp != NULL &&
2727
2.53k
      options_get_number(wp->options, "allow-set-title") &&
2728
2.53k
      screen_set_title(sctx->s, ictx->input_buf)) {
2729
1.98k
    notify_pane("pane-title-changed", wp);
2730
1.98k
    server_redraw_window_borders(wp->window);
2731
1.98k
    server_status_window(wp->window);
2732
1.98k
  }
2733
2.53k
}
2734
2735
/* Rename string started. */
2736
static void
2737
input_enter_rename(struct input_ctx *ictx)
2738
1.91k
{
2739
1.91k
  log_debug("%s", __func__);
2740
2741
1.91k
  input_clear(ictx);
2742
1.91k
  input_start_ground_timer(ictx);
2743
1.91k
  ictx->flags &= ~INPUT_LAST;
2744
1.91k
}
2745
2746
/* Rename terminator (ST) received. */
2747
static void
2748
input_exit_rename(struct input_ctx *ictx)
2749
1.90k
{
2750
1.90k
  struct window_pane  *wp = ictx->wp;
2751
1.90k
  struct window   *w;
2752
1.90k
  struct options_entry  *o;
2753
2754
1.90k
  if (wp == NULL)
2755
0
    return;
2756
1.90k
  if (ictx->flags & INPUT_DISCARD)
2757
0
    return;
2758
1.90k
  if (!options_get_number(ictx->wp->options, "allow-rename"))
2759
0
    return;
2760
1.90k
  log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2761
2762
1.90k
  if (!utf8_isvalid(ictx->input_buf))
2763
471
    return;
2764
1.43k
  w = wp->window;
2765
2766
1.43k
  if (ictx->input_len == 0) {
2767
459
    o = options_get_only(w->options, "automatic-rename");
2768
459
    if (o != NULL)
2769
79
      options_remove_or_default(o, -1, NULL);
2770
459
    if (!options_get_number(w->options, "automatic-rename"))
2771
0
      window_set_name(w, "");
2772
971
  } else {
2773
971
    options_set_number(w->options, "automatic-rename", 0);
2774
971
    window_set_name(w, ictx->input_buf);
2775
971
  }
2776
1.43k
  server_redraw_window_borders(w);
2777
1.43k
  server_status_window(w);
2778
1.43k
}
2779
2780
/* Open UTF-8 character. */
2781
static int
2782
input_top_bit_set(struct input_ctx *ictx)
2783
6.85k
{
2784
6.85k
  struct screen_write_ctx *sctx = &ictx->ctx;
2785
6.85k
  struct utf8_data  *ud = &ictx->utf8data;
2786
2787
6.85k
  ictx->flags &= ~INPUT_LAST;
2788
2789
6.85k
  if (!ictx->utf8started) {
2790
5.68k
    ictx->utf8started = 1;
2791
5.68k
    if (utf8_open(ud, ictx->ch) != UTF8_MORE)
2792
3.95k
      input_stop_utf8(ictx);
2793
5.68k
    return (0);
2794
5.68k
  }
2795
2796
1.16k
  switch (utf8_append(ud, ictx->ch)) {
2797
466
  case UTF8_MORE:
2798
466
    return (0);
2799
698
  case UTF8_ERROR:
2800
698
    input_stop_utf8(ictx);
2801
698
    return (0);
2802
0
  case UTF8_DONE:
2803
0
    break;
2804
1.16k
  }
2805
0
  ictx->utf8started = 0;
2806
2807
0
  log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
2808
0
      (int)ud->size, ud->data, ud->width);
2809
2810
0
  utf8_copy(&ictx->cell.cell.data, ud);
2811
0
  screen_write_collect_add(sctx, &ictx->cell.cell);
2812
2813
0
  utf8_copy(&ictx->last, &ictx->cell.cell.data);
2814
0
  ictx->flags |= INPUT_LAST;
2815
2816
0
  return (0);
2817
1.16k
}
2818
2819
/* Reply to a colour request. */
2820
static void
2821
input_osc_colour_reply(struct input_ctx *ictx, int add, u_int n, int idx, int c,
2822
    enum input_end_type end_type)
2823
362
{
2824
362
  u_char     r, g, b;
2825
362
  const char  *end;
2826
2827
362
  if (c != -1)
2828
155
    c = colour_force_rgb(c);
2829
362
  if (c == -1)
2830
207
      return;
2831
155
  colour_split_rgb(c, &r, &g, &b);
2832
2833
155
  if (end_type == INPUT_END_BEL)
2834
77
    end = "\007";
2835
78
  else
2836
78
    end = "\033\\";
2837
2838
155
  if (n == 4) {
2839
0
    input_reply(ictx, add,
2840
0
        "\033]%u;%d;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
2841
0
        n, idx, r, r, g, g, b, b, end);
2842
155
  } else {
2843
155
    input_reply(ictx, add,
2844
155
        "\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
2845
155
        n, r, r, g, g, b, b, end);
2846
155
  }
2847
155
}
2848
2849
/* Handle the OSC 4 sequence for setting (multiple) palette entries. */
2850
static void
2851
input_osc_4(struct input_ctx *ictx, const char *p)
2852
762
{
2853
762
  char      *copy, *s, *next = NULL;
2854
762
  long       idx;
2855
762
  int      c, bad = 0, redraw = 0;
2856
762
  struct colour_palette *palette = ictx->palette;
2857
2858
762
  copy = s = xstrdup(p);
2859
3.18k
  while (s != NULL && *s != '\0') {
2860
2.60k
    idx = strtol(s, &next, 10);
2861
2.60k
    if (*next++ != ';') {
2862
176
      bad = 1;
2863
176
      break;
2864
176
    }
2865
2.42k
    if (idx < 0 || idx >= 256) {
2866
0
      bad = 1;
2867
0
      break;
2868
0
    }
2869
2870
2.42k
    s = strsep(&next, ";");
2871
2.42k
    if (strcmp(s, "?") == 0) {
2872
197
      c = colour_palette_get(palette, idx|COLOUR_FLAG_256);
2873
197
      if (c != -1) {
2874
0
        input_osc_colour_reply(ictx, 1, 4, idx, c,
2875
0
            ictx->input_end);
2876
0
        s = next;
2877
0
        continue;
2878
0
      }
2879
197
      input_add_request(ictx, INPUT_REQUEST_PALETTE, idx);
2880
197
      s = next;
2881
197
      continue;
2882
197
    }
2883
2.22k
    if ((c = colour_parseX11(s)) == -1) {
2884
1.56k
      s = next;
2885
1.56k
      continue;
2886
1.56k
    }
2887
660
    if (colour_palette_set(palette, idx, c))
2888
0
      redraw = 1;
2889
660
    s = next;
2890
660
  }
2891
762
  if (bad)
2892
176
    log_debug("bad OSC 4: %s", p);
2893
762
  if (redraw)
2894
0
    screen_write_fullredraw(&ictx->ctx);
2895
762
  free(copy);
2896
762
}
2897
2898
/* Handle the OSC 8 sequence for embedding hyperlinks. */
2899
static void
2900
input_osc_8(struct input_ctx *ictx, const char *p)
2901
7.41k
{
2902
7.41k
  struct hyperlinks *hl = ictx->ctx.s->hyperlinks;
2903
7.41k
  struct grid_cell  *gc = &ictx->cell.cell;
2904
7.41k
  const char    *start, *end, *uri;
2905
7.41k
  char      *id = NULL;
2906
2907
7.84k
  for (start = p; (end = strpbrk(start, ":;")) != NULL; start = end + 1) {
2908
7.55k
    if (end - start >= 4 && strncmp(start, "id=", 3) == 0) {
2909
2.61k
      if (id != NULL)
2910
66
        goto bad;
2911
2.54k
      id = xstrndup(start + 3, end - start - 3);
2912
2.54k
    }
2913
2914
    /* The first ; is the end of parameters and start of the URI. */
2915
7.49k
    if (*end == ';')
2916
7.05k
      break;
2917
7.49k
  }
2918
7.34k
  if (end == NULL || *end != ';')
2919
287
    goto bad;
2920
7.05k
  uri = end + 1;
2921
7.05k
  if (*uri == '\0') {
2922
95
    gc->link = 0;
2923
95
    free(id);
2924
95
    return;
2925
95
  }
2926
6.96k
  gc->link = hyperlinks_put(hl, uri, id);
2927
6.96k
  if (id == NULL)
2928
4.48k
    log_debug("hyperlink (anonymous) %s = %u", uri, gc->link);
2929
2.47k
  else
2930
2.47k
    log_debug("hyperlink (id=%s) %s = %u", id, uri, gc->link);
2931
6.96k
  free(id);
2932
6.96k
  return;
2933
2934
353
bad:
2935
353
  log_debug("bad OSC 8 %s", p);
2936
353
  free(id);
2937
353
}
2938
2939
2940
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
2941
static void
2942
input_osc_10(struct input_ctx *ictx, const char *p)
2943
228
{
2944
228
  struct window_pane  *wp = ictx->wp;
2945
228
  struct grid_cell   defaults;
2946
228
  int      c;
2947
2948
228
  if (strcmp(p, "?") == 0) {
2949
66
    if (wp == NULL)
2950
0
      return;
2951
66
    c = window_pane_get_fg_control_client(wp);
2952
66
    if (c == -1) {
2953
66
      tty_default_colours(&defaults, wp);
2954
66
      if (COLOUR_DEFAULT(defaults.fg))
2955
66
        c = window_pane_get_fg(wp);
2956
0
      else
2957
0
        c = defaults.fg;
2958
66
    }
2959
66
    input_osc_colour_reply(ictx, 1, 10, 0, c, ictx->input_end);
2960
66
    return;
2961
66
  }
2962
2963
162
  if ((c = colour_parseX11(p)) == -1) {
2964
86
    log_debug("bad OSC 10: %s", p);
2965
86
    return;
2966
86
  }
2967
76
  if (ictx->palette != NULL) {
2968
0
    ictx->palette->fg = c;
2969
0
    if (wp != NULL)
2970
0
      wp->flags |= PANE_STYLECHANGED;
2971
0
    screen_write_fullredraw(&ictx->ctx);
2972
0
  }
2973
76
}
2974
2975
/* Handle the OSC 110 sequence for resetting foreground colour. */
2976
static void
2977
input_osc_110(struct input_ctx *ictx, const char *p)
2978
138
{
2979
138
  struct window_pane  *wp = ictx->wp;
2980
2981
138
  if (*p != '\0')
2982
72
    return;
2983
66
  if (ictx->palette != NULL) {
2984
0
    ictx->palette->fg = 8;
2985
0
    if (wp != NULL)
2986
0
      wp->flags |= PANE_STYLECHANGED;
2987
0
    screen_write_fullredraw(&ictx->ctx);
2988
0
  }
2989
66
}
2990
2991
/* Handle the OSC 11 sequence for setting and querying background colour. */
2992
static void
2993
input_osc_11(struct input_ctx *ictx, const char *p)
2994
289
{
2995
289
  struct window_pane  *wp = ictx->wp;
2996
289
  int      c;
2997
2998
289
  if (strcmp(p, "?") == 0) {
2999
75
    if (wp == NULL)
3000
0
      return;
3001
75
    c = window_pane_get_bg(wp);
3002
75
    input_osc_colour_reply(ictx, 1, 11, 0, c, ictx->input_end);
3003
75
    return;
3004
75
  }
3005
3006
214
  if ((c = colour_parseX11(p)) == -1) {
3007
119
    log_debug("bad OSC 11: %s", p);
3008
119
    return;
3009
119
  }
3010
95
  if (ictx->palette != NULL) {
3011
0
    ictx->palette->bg = c;
3012
0
    if (wp != NULL)
3013
0
      wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
3014
0
    screen_write_fullredraw(&ictx->ctx);
3015
0
  }
3016
95
}
3017
3018
/* Handle the OSC 111 sequence for resetting background colour. */
3019
static void
3020
input_osc_111(struct input_ctx *ictx, const char *p)
3021
134
{
3022
134
  struct window_pane  *wp = ictx->wp;
3023
3024
134
  if (*p != '\0')
3025
66
    return;
3026
68
  if (ictx->palette != NULL) {
3027
0
    ictx->palette->bg = 8;
3028
0
    if (wp != NULL)
3029
0
      wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
3030
0
    screen_write_fullredraw(&ictx->ctx);
3031
0
  }
3032
68
}
3033
3034
/* Handle the OSC 12 sequence for setting and querying cursor colour. */
3035
static void
3036
input_osc_12(struct input_ctx *ictx, const char *p)
3037
490
{
3038
490
  struct window_pane  *wp = ictx->wp;
3039
490
  int      c;
3040
3041
490
  if (strcmp(p, "?") == 0) {
3042
221
    if (wp != NULL) {
3043
221
      c = ictx->ctx.s->ccolour;
3044
221
      if (c == -1)
3045
66
        c = ictx->ctx.s->default_ccolour;
3046
221
      input_osc_colour_reply(ictx, 1, 12, 0, c, ictx->input_end);
3047
221
    }
3048
221
    return;
3049
221
  }
3050
3051
269
  if ((c = colour_parseX11(p)) == -1) {
3052
141
    log_debug("bad OSC 12: %s", p);
3053
141
    return;
3054
141
  }
3055
128
  screen_set_cursor_colour(ictx->ctx.s, c);
3056
128
}
3057
3058
/* Handle the OSC 112 sequence for resetting cursor colour. */
3059
static void
3060
input_osc_112(struct input_ctx *ictx, const char *p)
3061
133
{
3062
133
  if (*p == '\0') /* no arguments allowed */
3063
66
    screen_set_cursor_colour(ictx->ctx.s, -1);
3064
133
}
3065
3066
/* Handle the OSC 133 sequence. */
3067
static void
3068
input_osc_133(struct input_ctx *ictx, const char *p)
3069
198
{
3070
198
  struct grid   *gd = ictx->ctx.s->grid;
3071
198
  u_int      line = ictx->ctx.s->cy + gd->hsize;
3072
198
  struct grid_line  *gl;
3073
3074
198
  if (line > gd->hsize + gd->sy - 1)
3075
0
    return;
3076
198
  gl = grid_get_line(gd, line);
3077
3078
198
  switch (*p) {
3079
66
  case 'A':
3080
66
    gl->flags |= GRID_LINE_START_PROMPT;
3081
66
    break;
3082
66
  case 'C':
3083
66
    gl->flags |= GRID_LINE_START_OUTPUT;
3084
66
    break;
3085
198
  }
3086
198
}
3087
3088
/* Handle OSC 52 reply. */
3089
static void
3090
input_osc_52_reply(struct input_ctx *ictx)
3091
246
{
3092
246
  struct paste_buffer *pb;
3093
246
  int      state;
3094
246
  const char    *buf;
3095
246
  size_t       len;
3096
3097
246
  state = options_get_number(global_options, "get-clipboard");
3098
246
  if (state == 0)
3099
0
    return;
3100
246
  if (state == 1) {
3101
246
    if ((pb = paste_get_top(NULL)) == NULL)
3102
3
      return;
3103
243
    buf = paste_buffer_data(pb, &len);
3104
243
    if (ictx->input_end == INPUT_END_BEL)
3105
69
      input_reply_clipboard(ictx->event, buf, len, "\007");
3106
174
    else
3107
174
      input_reply_clipboard(ictx->event, buf, len, "\033\\");
3108
243
    return;
3109
246
  }
3110
0
  input_add_request(ictx, INPUT_REQUEST_CLIPBOARD, ictx->input_end);
3111
0
}
3112
3113
/* Handle the OSC 52 sequence for setting the clipboard. */
3114
static void
3115
input_osc_52(struct input_ctx *ictx, const char *p)
3116
1.83k
{
3117
1.83k
  struct window_pane  *wp = ictx->wp;
3118
1.83k
  size_t       len;
3119
1.83k
  char      *end;
3120
1.83k
  u_char      *out;
3121
1.83k
  int      outlen, state;
3122
1.83k
  struct screen_write_ctx  ctx;
3123
1.83k
  const char*    allow = "cpqs01234567";
3124
1.83k
  char       flags[sizeof "cpqs01234567"] = "";
3125
1.83k
  u_int      i, j = 0;
3126
3127
1.83k
  if (wp == NULL)
3128
0
    return;
3129
1.83k
  state = options_get_number(global_options, "set-clipboard");
3130
1.83k
  if (state != 2)
3131
0
    return;
3132
3133
1.83k
  if ((end = strchr(p, ';')) == NULL)
3134
71
    return;
3135
1.76k
  end++;
3136
1.76k
  if (*end == '\0')
3137
67
    return;
3138
1.70k
  log_debug("%s: %s", __func__, end);
3139
3140
4.20k
  for (i = 0; p + i != end; i++) {
3141
2.50k
    if (strchr(allow, p[i]) != NULL && strchr(flags, p[i]) == NULL)
3142
239
      flags[j++] = p[i];
3143
2.50k
  }
3144
1.70k
  log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, flags);
3145
3146
1.70k
  if (strcmp(end, "?") == 0) {
3147
246
    input_osc_52_reply(ictx);
3148
246
    return;
3149
246
  }
3150
3151
1.45k
  len = (strlen(end) / 4) * 3;
3152
1.45k
  if (len == 0)
3153
126
    return;
3154
3155
1.32k
  out = xmalloc(len);
3156
1.32k
  if ((outlen = b64_pton(end, out, len)) == -1) {
3157
86
    free(out);
3158
86
    return;
3159
86
  }
3160
3161
1.24k
  screen_write_start_pane(&ctx, wp, NULL);
3162
1.24k
  screen_write_setselection(&ctx, flags, out, outlen);
3163
1.24k
  screen_write_stop(&ctx);
3164
1.24k
  notify_pane("pane-set-clipboard", wp);
3165
3166
1.24k
  paste_add(NULL, out, outlen);
3167
1.24k
}
3168
3169
/* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
3170
static void
3171
input_osc_104(struct input_ctx *ictx, const char *p)
3172
281
{
3173
281
  char  *copy, *s;
3174
281
  long   idx;
3175
281
  int  bad = 0, redraw = 0;
3176
3177
281
  if (*p == '\0') {
3178
66
    colour_palette_clear(ictx->palette);
3179
66
    screen_write_fullredraw(&ictx->ctx);
3180
66
    return;
3181
66
  }
3182
3183
215
  copy = s = xstrdup(p);
3184
680
  while (*s != '\0') {
3185
594
    idx = strtol(s, &s, 10);
3186
594
    if (*s != '\0' && *s != ';') {
3187
77
      bad = 1;
3188
77
      break;
3189
77
    }
3190
517
    if (idx < 0 || idx >= 256) {
3191
52
      bad = 1;
3192
52
      break;
3193
52
    }
3194
465
    if (colour_palette_set(ictx->palette, idx, -1))
3195
0
      redraw = 1;
3196
465
    if (*s == ';')
3197
391
      s++;
3198
465
  }
3199
215
  if (bad)
3200
129
    log_debug("bad OSC 104: %s", p);
3201
215
  if (redraw)
3202
0
    screen_write_fullredraw(&ictx->ctx);
3203
215
  free(copy);
3204
215
}
3205
3206
/* Send a clipboard reply. */
3207
void
3208
input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
3209
    const char *end)
3210
243
{
3211
243
  char  *out = NULL;
3212
243
  int  outlen = 0;
3213
3214
243
  if (buf != NULL && len != 0) {
3215
243
    if (len >= ((size_t)INT_MAX * 3 / 4) - 1)
3216
0
      return;
3217
243
    outlen = 4 * ((len + 2) / 3) + 1;
3218
243
    out = xmalloc(outlen);
3219
243
    if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
3220
0
      free(out);
3221
0
      return;
3222
0
    }
3223
243
  }
3224
3225
243
  bufferevent_write(bev, "\033]52;;", 6);
3226
243
  if (outlen != 0)
3227
243
    bufferevent_write(bev, out, outlen);
3228
243
  bufferevent_write(bev, end, strlen(end));
3229
243
  free(out);
3230
243
}
3231
3232
/* Set input buffer size. */
3233
void
3234
input_set_buffer_size(size_t buffer_size)
3235
0
{
3236
0
  log_debug("%s: %lu -> %lu", __func__, input_buffer_size, buffer_size);
3237
0
  input_buffer_size = buffer_size;
3238
0
}
3239
3240
/* Request timer. Remove any requests that are too old. */
3241
static void
3242
input_request_timer_callback(__unused int fd, __unused short events, void *arg)
3243
0
{
3244
0
  struct input_ctx  *ictx = arg;
3245
0
  struct input_request  *ir, *ir1;
3246
0
  uint64_t     t = get_timer();
3247
3248
0
  TAILQ_FOREACH_SAFE(ir, &ictx->requests, entry, ir1) {
3249
0
    if (ir->t >= t - INPUT_REQUEST_TIMEOUT)
3250
0
      continue;
3251
0
    if (ir->type == INPUT_REQUEST_QUEUE)
3252
0
      input_send_reply(ir->ictx, ir->data);
3253
0
    input_free_request(ir);
3254
0
  }
3255
0
  if (ictx->request_count != 0)
3256
0
    input_start_request_timer(ictx);
3257
0
}
3258
3259
/* Start the request timer. */
3260
static void
3261
input_start_request_timer(struct input_ctx *ictx)
3262
0
{
3263
0
  struct timeval  tv = { .tv_sec = 0, .tv_usec = 100000 };
3264
3265
0
  event_del(&ictx->request_timer);
3266
0
  event_add(&ictx->request_timer, &tv);
3267
0
}
3268
3269
/* Create a request. */
3270
static struct input_request *
3271
input_make_request(struct input_ctx *ictx, enum input_request_type type)
3272
0
{
3273
0
  struct input_request  *ir;
3274
3275
0
  ir = xcalloc (1, sizeof *ir);
3276
0
  ir->type = type;
3277
0
  ir->ictx = ictx;
3278
0
  ir->t = get_timer();
3279
3280
0
  if (++ictx->request_count == 1)
3281
0
    input_start_request_timer(ictx);
3282
0
  TAILQ_INSERT_TAIL(&ictx->requests, ir, entry);
3283
3284
0
  return (ir);
3285
0
}
3286
3287
/* Free a request. */
3288
static void
3289
input_free_request(struct input_request *ir)
3290
0
{
3291
0
  struct input_ctx  *ictx = ir->ictx;
3292
3293
0
  if (ir->c != NULL)
3294
0
    TAILQ_REMOVE(&ir->c->input_requests, ir, centry);
3295
3296
0
  ictx->request_count--;
3297
0
  TAILQ_REMOVE(&ictx->requests, ir, entry);
3298
3299
0
  free(ir->data);
3300
0
  free(ir);
3301
0
}
3302
3303
/* Add a request. */
3304
static int
3305
input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx)
3306
197
{
3307
197
  struct window_pane  *wp = ictx->wp;
3308
197
  struct window   *w;
3309
197
  struct client   *c = NULL, *loop;
3310
197
  struct input_request  *ir;
3311
197
  char       s[64];
3312
3313
197
  if (wp == NULL)
3314
0
    return (-1);
3315
197
  w = wp->window;
3316
3317
197
  TAILQ_FOREACH(loop, &clients, entry) {
3318
0
    if (loop->flags & CLIENT_UNATTACHEDFLAGS)
3319
0
      continue;
3320
0
    if (loop->session == NULL || !session_has(loop->session, w))
3321
0
      continue;
3322
0
    if (~loop->tty.flags & TTY_STARTED)
3323
0
      continue;
3324
0
    if (c == NULL)
3325
0
      c = loop;
3326
0
    else if (timercmp(&loop->activity_time, &c->activity_time, >))
3327
0
      c = loop;
3328
0
  }
3329
197
  if (c == NULL)
3330
197
    return (-1);
3331
3332
0
  ir = input_make_request(ictx, type);
3333
0
  ir->c = c;
3334
0
  ir->idx = idx;
3335
0
  ir->end = ictx->input_end;
3336
0
  TAILQ_INSERT_TAIL(&c->input_requests, ir, centry);
3337
3338
0
  switch (type) {
3339
0
  case INPUT_REQUEST_PALETTE:
3340
0
    xsnprintf(s, sizeof s, "\033]4;%d;?\033\\", idx);
3341
0
    tty_puts(&c->tty, s);
3342
0
    break;
3343
0
  case INPUT_REQUEST_CLIPBOARD:
3344
0
    tty_putcode_ss(&c->tty, TTYC_MS, "", "?");
3345
0
    break;
3346
0
  case INPUT_REQUEST_QUEUE:
3347
0
    break;
3348
0
  }
3349
3350
0
  return (0);
3351
0
}
3352
3353
/* Handle a palette reply. */
3354
static void
3355
input_request_palette_reply(struct input_request *ir, void *data)
3356
0
{
3357
0
  struct input_request_palette_data *pd = data;
3358
3359
0
  input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c, ir->end);
3360
0
}
3361
3362
/* Handle a clipboard reply. */
3363
static void
3364
input_request_clipboard_reply(struct input_request *ir, void *data)
3365
0
{
3366
0
  struct input_ctx      *ictx = ir->ictx;
3367
0
  struct input_request_clipboard_data *cd = data;
3368
0
  int          state;
3369
0
  char          *copy;
3370
3371
0
  state = options_get_number(global_options, "get-clipboard");
3372
0
  if (state == 0 || state == 1)
3373
0
    return;
3374
0
  if (state == 3) {
3375
0
    copy = xmalloc(cd->len);
3376
0
    memcpy(copy, cd->buf, cd->len);
3377
0
    paste_add(NULL, copy, cd->len);
3378
0
  }
3379
3380
0
  if (ir->idx == INPUT_END_BEL)
3381
0
    input_reply_clipboard(ictx->event, cd->buf, cd->len, "\007");
3382
0
  else
3383
0
    input_reply_clipboard(ictx->event, cd->buf, cd->len, "\033\\");
3384
0
}
3385
3386
/* Handle a reply to a request. */
3387
void
3388
input_request_reply(struct client *c, enum input_request_type type, void *data)
3389
0
{
3390
0
  struct input_request      *ir, *ir1, *found = NULL;
3391
0
  struct input_request_palette_data *pd = data;
3392
0
  int          complete = 0;
3393
3394
0
  TAILQ_FOREACH_SAFE(ir, &c->input_requests, centry, ir1) {
3395
0
    if (ir->type != type) {
3396
0
      input_free_request(ir);
3397
0
      continue;
3398
0
    }
3399
0
    if (type == INPUT_REQUEST_PALETTE) {
3400
0
      if (pd->idx != ir->idx) {
3401
0
        input_free_request(ir);
3402
0
        continue;
3403
0
      }
3404
0
      found = ir;
3405
0
      break;
3406
0
    }
3407
0
    if (type == INPUT_REQUEST_CLIPBOARD) {
3408
0
      found = ir;
3409
0
      break;
3410
0
    }
3411
0
  }
3412
0
  if (found == NULL)
3413
0
    return;
3414
3415
0
  TAILQ_FOREACH_SAFE(ir, &found->ictx->requests, entry, ir1) {
3416
0
    if (complete && ir->type != INPUT_REQUEST_QUEUE)
3417
0
      break;
3418
0
    if (ir->type == INPUT_REQUEST_QUEUE)
3419
0
      input_send_reply(ir->ictx, ir->data);
3420
0
    else if (ir == found) {
3421
0
      if (ir->type == INPUT_REQUEST_PALETTE)
3422
0
        input_request_palette_reply(ir, data);
3423
0
      else if (ir->type == INPUT_REQUEST_CLIPBOARD)
3424
0
        input_request_clipboard_reply(ir, data);
3425
0
      complete = 1;
3426
0
    }
3427
0
    input_free_request(ir);
3428
0
  }
3429
0
}
3430
3431
/* Cancel pending requests for client. */
3432
void
3433
input_cancel_requests(struct client *c)
3434
0
{
3435
0
  struct input_request  *ir, *ir1;
3436
3437
0
  TAILQ_FOREACH_SAFE(ir, &c->input_requests, entry, ir1)
3438
0
    input_free_request(ir);
3439
0
}
3440
3441
/* Report current theme. */
3442
static void
3443
input_report_current_theme(struct input_ctx *ictx)
3444
66
{
3445
66
  struct window_pane  *wp = ictx->wp;
3446
3447
66
  if (wp != NULL) {
3448
66
    wp->last_theme = window_pane_get_theme(wp);
3449
66
    wp->flags &= ~PANE_THEMECHANGED;
3450
3451
66
    switch (wp->last_theme) {
3452
0
    case THEME_DARK:
3453
0
      log_debug("%s: %%%u dark theme", __func__, wp->id);
3454
0
      input_reply(ictx, 0, "\033[?997;1n");
3455
0
      break;
3456
0
    case THEME_LIGHT:
3457
0
      log_debug("%s: %%%u light theme", __func__, wp->id);
3458
0
      input_reply(ictx, 0, "\033[?997;2n");
3459
0
      break;
3460
66
    case THEME_UNKNOWN:
3461
66
      log_debug("%s: %%%u unknown theme", __func__, wp->id);
3462
66
      break;
3463
66
    }
3464
66
  }
3465
66
}