Coverage Report

Created: 2026-10-05 06:03

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