Coverage Report

Created: 2025-08-08 06:46

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