Coverage Report

Created: 2026-09-03 06:29

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