GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/input.c Lines: 0 708 0.0 %
Date: 2017-11-07 Branches: 0 430 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: input.c,v 1.128 2017/09/10 08:01:23 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 <resolv.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <time.h>
27
28
#include "tmux.h"
29
30
/*
31
 * Based on the description by Paul Williams at:
32
 *
33
 * http://vt100.net/emu/dec_ansi_parser
34
 *
35
 * With the following changes:
36
 *
37
 * - 7-bit only.
38
 *
39
 * - Support for UTF-8.
40
 *
41
 * - OSC (but not APC) may be terminated by \007 as well as ST.
42
 *
43
 * - A state for APC similar to OSC. Some terminals appear to use this to set
44
 *   the title.
45
 *
46
 * - A state for the screen \033k...\033\\ sequence to rename a window. This is
47
 *   pretty stupid but not supporting it is more trouble than it is worth.
48
 *
49
 * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
50
 *   be passed to the underlying terminals.
51
 */
52
53
/* Input parser cell. */
54
struct input_cell {
55
	struct grid_cell	cell;
56
	int			set;
57
	int			g0set;	/* 1 if ACS */
58
	int			g1set;	/* 1 if ACS */
59
};
60
61
/* Input parser context. */
62
struct input_ctx {
63
	struct window_pane     *wp;
64
	struct screen_write_ctx ctx;
65
66
	struct input_cell	cell;
67
68
	struct input_cell	old_cell;
69
	u_int 			old_cx;
70
	u_int			old_cy;
71
72
	u_char			interm_buf[4];
73
	size_t			interm_len;
74
75
	u_char			param_buf[64];
76
	size_t			param_len;
77
78
#define INPUT_BUF_START 32
79
#define INPUT_BUF_LIMIT 1048576
80
	u_char		       *input_buf;
81
	size_t			input_len;
82
	size_t			input_space;
83
84
	int			param_list[24];	/* -1 not present */
85
	u_int			param_list_len;
86
87
	struct utf8_data	utf8data;
88
89
	int			ch;
90
	int			last;
91
92
	int			flags;
93
#define INPUT_DISCARD 0x1
94
95
	const struct input_state *state;
96
97
	struct event		timer;
98
99
	/*
100
	 * All input received since we were last in the ground state. Sent to
101
	 * control clients on connection.
102
	 */
103
	struct evbuffer	 	*since_ground;
104
};
105
106
/* Helper functions. */
107
struct input_transition;
108
static int	input_split(struct input_ctx *);
109
static int	input_get(struct input_ctx *, u_int, int, int);
110
static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
111
static void	input_set_state(struct window_pane *,
112
		    const struct input_transition *);
113
static void	input_reset_cell(struct input_ctx *);
114
115
static void	input_osc_4(struct window_pane *, const char *);
116
static void	input_osc_10(struct window_pane *, const char *);
117
static void	input_osc_11(struct window_pane *, const char *);
118
static void	input_osc_52(struct window_pane *, const char *);
119
static void	input_osc_104(struct window_pane *, const char *);
120
121
/* Transition entry/exit handlers. */
122
static void	input_clear(struct input_ctx *);
123
static void	input_ground(struct input_ctx *);
124
static void	input_enter_dcs(struct input_ctx *);
125
static void	input_enter_osc(struct input_ctx *);
126
static void	input_exit_osc(struct input_ctx *);
127
static void	input_enter_apc(struct input_ctx *);
128
static void	input_exit_apc(struct input_ctx *);
129
static void	input_enter_rename(struct input_ctx *);
130
static void	input_exit_rename(struct input_ctx *);
131
132
/* Input state handlers. */
133
static int	input_print(struct input_ctx *);
134
static int	input_intermediate(struct input_ctx *);
135
static int	input_parameter(struct input_ctx *);
136
static int	input_input(struct input_ctx *);
137
static int	input_c0_dispatch(struct input_ctx *);
138
static int	input_esc_dispatch(struct input_ctx *);
139
static int	input_csi_dispatch(struct input_ctx *);
140
static void	input_csi_dispatch_rm(struct input_ctx *);
141
static void	input_csi_dispatch_rm_private(struct input_ctx *);
142
static void	input_csi_dispatch_sm(struct input_ctx *);
143
static void	input_csi_dispatch_sm_private(struct input_ctx *);
144
static void	input_csi_dispatch_winops(struct input_ctx *);
145
static void	input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
146
static void	input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
147
static void	input_csi_dispatch_sgr(struct input_ctx *);
148
static int	input_dcs_dispatch(struct input_ctx *);
149
static int	input_utf8_open(struct input_ctx *);
150
static int	input_utf8_add(struct input_ctx *);
151
static int	input_utf8_close(struct input_ctx *);
152
153
/* Command table comparison function. */
154
static int	input_table_compare(const void *, const void *);
155
156
/* Command table entry. */
157
struct input_table_entry {
158
	int		ch;
159
	const char     *interm;
160
	int		type;
161
};
162
163
/* Escape commands. */
164
enum input_esc_type {
165
	INPUT_ESC_DECALN,
166
	INPUT_ESC_DECKPAM,
167
	INPUT_ESC_DECKPNM,
168
	INPUT_ESC_DECRC,
169
	INPUT_ESC_DECSC,
170
	INPUT_ESC_HTS,
171
	INPUT_ESC_IND,
172
	INPUT_ESC_NEL,
173
	INPUT_ESC_RI,
174
	INPUT_ESC_RIS,
175
	INPUT_ESC_SCSG0_OFF,
176
	INPUT_ESC_SCSG0_ON,
177
	INPUT_ESC_SCSG1_OFF,
178
	INPUT_ESC_SCSG1_ON,
179
	INPUT_ESC_ST,
180
};
181
182
/* Escape command table. */
183
static const struct input_table_entry input_esc_table[] = {
184
	{ '0', "(", INPUT_ESC_SCSG0_ON },
185
	{ '0', ")", INPUT_ESC_SCSG1_ON },
186
	{ '7', "",  INPUT_ESC_DECSC },
187
	{ '8', "",  INPUT_ESC_DECRC },
188
	{ '8', "#", INPUT_ESC_DECALN },
189
	{ '=', "",  INPUT_ESC_DECKPAM },
190
	{ '>', "",  INPUT_ESC_DECKPNM },
191
	{ 'B', "(", INPUT_ESC_SCSG0_OFF },
192
	{ 'B', ")", INPUT_ESC_SCSG1_OFF },
193
	{ 'D', "",  INPUT_ESC_IND },
194
	{ 'E', "",  INPUT_ESC_NEL },
195
	{ 'H', "",  INPUT_ESC_HTS },
196
	{ 'M', "",  INPUT_ESC_RI },
197
	{ '\\', "", INPUT_ESC_ST },
198
	{ 'c', "",  INPUT_ESC_RIS },
199
};
200
201
/* Control (CSI) commands. */
202
enum input_csi_type {
203
	INPUT_CSI_CBT,
204
	INPUT_CSI_CNL,
205
	INPUT_CSI_CPL,
206
	INPUT_CSI_CUB,
207
	INPUT_CSI_CUD,
208
	INPUT_CSI_CUF,
209
	INPUT_CSI_CUP,
210
	INPUT_CSI_CUU,
211
	INPUT_CSI_DA,
212
	INPUT_CSI_DA_TWO,
213
	INPUT_CSI_DCH,
214
	INPUT_CSI_DECSCUSR,
215
	INPUT_CSI_DECSTBM,
216
	INPUT_CSI_DL,
217
	INPUT_CSI_DSR,
218
	INPUT_CSI_ECH,
219
	INPUT_CSI_ED,
220
	INPUT_CSI_EL,
221
	INPUT_CSI_HPA,
222
	INPUT_CSI_ICH,
223
	INPUT_CSI_IL,
224
	INPUT_CSI_RCP,
225
	INPUT_CSI_REP,
226
	INPUT_CSI_RM,
227
	INPUT_CSI_RM_PRIVATE,
228
	INPUT_CSI_SCP,
229
	INPUT_CSI_SGR,
230
	INPUT_CSI_SM,
231
	INPUT_CSI_SM_PRIVATE,
232
	INPUT_CSI_SU,
233
	INPUT_CSI_TBC,
234
	INPUT_CSI_VPA,
235
	INPUT_CSI_WINOPS,
236
};
237
238
/* Control (CSI) command table. */
239
static const struct input_table_entry input_csi_table[] = {
240
	{ '@', "",  INPUT_CSI_ICH },
241
	{ 'A', "",  INPUT_CSI_CUU },
242
	{ 'B', "",  INPUT_CSI_CUD },
243
	{ 'C', "",  INPUT_CSI_CUF },
244
	{ 'D', "",  INPUT_CSI_CUB },
245
	{ 'E', "",  INPUT_CSI_CNL },
246
	{ 'F', "",  INPUT_CSI_CPL },
247
	{ 'G', "",  INPUT_CSI_HPA },
248
	{ 'H', "",  INPUT_CSI_CUP },
249
	{ 'J', "",  INPUT_CSI_ED },
250
	{ 'K', "",  INPUT_CSI_EL },
251
	{ 'L', "",  INPUT_CSI_IL },
252
	{ 'M', "",  INPUT_CSI_DL },
253
	{ 'P', "",  INPUT_CSI_DCH },
254
	{ 'S', "",  INPUT_CSI_SU },
255
	{ 'X', "",  INPUT_CSI_ECH },
256
	{ 'Z', "",  INPUT_CSI_CBT },
257
	{ 'b', "",  INPUT_CSI_REP },
258
	{ 'c', "",  INPUT_CSI_DA },
259
	{ 'c', ">", INPUT_CSI_DA_TWO },
260
	{ 'd', "",  INPUT_CSI_VPA },
261
	{ 'f', "",  INPUT_CSI_CUP },
262
	{ 'g', "",  INPUT_CSI_TBC },
263
	{ 'h', "",  INPUT_CSI_SM },
264
	{ 'h', "?", INPUT_CSI_SM_PRIVATE },
265
	{ 'l', "",  INPUT_CSI_RM },
266
	{ 'l', "?", INPUT_CSI_RM_PRIVATE },
267
	{ 'm', "",  INPUT_CSI_SGR },
268
	{ 'n', "",  INPUT_CSI_DSR },
269
	{ 'q', " ", INPUT_CSI_DECSCUSR },
270
	{ 'r', "",  INPUT_CSI_DECSTBM },
271
	{ 's', "",  INPUT_CSI_SCP },
272
	{ 't', "",  INPUT_CSI_WINOPS },
273
	{ 'u', "",  INPUT_CSI_RCP },
274
};
275
276
/* Input transition. */
277
struct input_transition {
278
	int				first;
279
	int				last;
280
281
	int				(*handler)(struct input_ctx *);
282
	const struct input_state       *state;
283
};
284
285
/* Input state. */
286
struct input_state {
287
	const char			*name;
288
	void				(*enter)(struct input_ctx *);
289
	void				(*exit)(struct input_ctx *);
290
	const struct input_transition	*transitions;
291
};
292
293
/* State transitions available from all states. */
294
#define INPUT_STATE_ANYWHERE \
295
	{ 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
296
	{ 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
297
	{ 0x1b, 0x1b, NULL,		 &input_state_esc_enter }
298
299
/* Forward declarations of state tables. */
300
static const struct input_transition input_state_ground_table[];
301
static const struct input_transition input_state_esc_enter_table[];
302
static const struct input_transition input_state_esc_intermediate_table[];
303
static const struct input_transition input_state_csi_enter_table[];
304
static const struct input_transition input_state_csi_parameter_table[];
305
static const struct input_transition input_state_csi_intermediate_table[];
306
static const struct input_transition input_state_csi_ignore_table[];
307
static const struct input_transition input_state_dcs_enter_table[];
308
static const struct input_transition input_state_dcs_parameter_table[];
309
static const struct input_transition input_state_dcs_intermediate_table[];
310
static const struct input_transition input_state_dcs_handler_table[];
311
static const struct input_transition input_state_dcs_escape_table[];
312
static const struct input_transition input_state_dcs_ignore_table[];
313
static const struct input_transition input_state_osc_string_table[];
314
static const struct input_transition input_state_apc_string_table[];
315
static const struct input_transition input_state_rename_string_table[];
316
static const struct input_transition input_state_consume_st_table[];
317
static const struct input_transition input_state_utf8_three_table[];
318
static const struct input_transition input_state_utf8_two_table[];
319
static const struct input_transition input_state_utf8_one_table[];
320
321
/* ground state definition. */
322
static const struct input_state input_state_ground = {
323
	"ground",
324
	input_ground, NULL,
325
	input_state_ground_table
326
};
327
328
/* esc_enter state definition. */
329
static const struct input_state input_state_esc_enter = {
330
	"esc_enter",
331
	input_clear, NULL,
332
	input_state_esc_enter_table
333
};
334
335
/* esc_intermediate state definition. */
336
static const struct input_state input_state_esc_intermediate = {
337
	"esc_intermediate",
338
	NULL, NULL,
339
	input_state_esc_intermediate_table
340
};
341
342
/* csi_enter state definition. */
343
static const struct input_state input_state_csi_enter = {
344
	"csi_enter",
345
	input_clear, NULL,
346
	input_state_csi_enter_table
347
};
348
349
/* csi_parameter state definition. */
350
static const struct input_state input_state_csi_parameter = {
351
	"csi_parameter",
352
	NULL, NULL,
353
	input_state_csi_parameter_table
354
};
355
356
/* csi_intermediate state definition. */
357
static const struct input_state input_state_csi_intermediate = {
358
	"csi_intermediate",
359
	NULL, NULL,
360
	input_state_csi_intermediate_table
361
};
362
363
/* csi_ignore state definition. */
364
static const struct input_state input_state_csi_ignore = {
365
	"csi_ignore",
366
	NULL, NULL,
367
	input_state_csi_ignore_table
368
};
369
370
/* dcs_enter state definition. */
371
static const struct input_state input_state_dcs_enter = {
372
	"dcs_enter",
373
	input_enter_dcs, NULL,
374
	input_state_dcs_enter_table
375
};
376
377
/* dcs_parameter state definition. */
378
static const struct input_state input_state_dcs_parameter = {
379
	"dcs_parameter",
380
	NULL, NULL,
381
	input_state_dcs_parameter_table
382
};
383
384
/* dcs_intermediate state definition. */
385
static const struct input_state input_state_dcs_intermediate = {
386
	"dcs_intermediate",
387
	NULL, NULL,
388
	input_state_dcs_intermediate_table
389
};
390
391
/* dcs_handler state definition. */
392
static const struct input_state input_state_dcs_handler = {
393
	"dcs_handler",
394
	NULL, NULL,
395
	input_state_dcs_handler_table
396
};
397
398
/* dcs_escape state definition. */
399
static const struct input_state input_state_dcs_escape = {
400
	"dcs_escape",
401
	NULL, NULL,
402
	input_state_dcs_escape_table
403
};
404
405
/* dcs_ignore state definition. */
406
static const struct input_state input_state_dcs_ignore = {
407
	"dcs_ignore",
408
	NULL, NULL,
409
	input_state_dcs_ignore_table
410
};
411
412
/* osc_string state definition. */
413
static const struct input_state input_state_osc_string = {
414
	"osc_string",
415
	input_enter_osc, input_exit_osc,
416
	input_state_osc_string_table
417
};
418
419
/* apc_string state definition. */
420
static const struct input_state input_state_apc_string = {
421
	"apc_string",
422
	input_enter_apc, input_exit_apc,
423
	input_state_apc_string_table
424
};
425
426
/* rename_string state definition. */
427
static const struct input_state input_state_rename_string = {
428
	"rename_string",
429
	input_enter_rename, input_exit_rename,
430
	input_state_rename_string_table
431
};
432
433
/* consume_st state definition. */
434
static const struct input_state input_state_consume_st = {
435
	"consume_st",
436
	input_enter_rename, NULL, /* rename also waits for ST */
437
	input_state_consume_st_table
438
};
439
440
/* utf8_three state definition. */
441
static const struct input_state input_state_utf8_three = {
442
	"utf8_three",
443
	NULL, NULL,
444
	input_state_utf8_three_table
445
};
446
447
/* utf8_two state definition. */
448
static const struct input_state input_state_utf8_two = {
449
	"utf8_two",
450
	NULL, NULL,
451
	input_state_utf8_two_table
452
};
453
454
/* utf8_one state definition. */
455
static const struct input_state input_state_utf8_one = {
456
	"utf8_one",
457
	NULL, NULL,
458
	input_state_utf8_one_table
459
};
460
461
/* ground state table. */
462
static const struct input_transition input_state_ground_table[] = {
463
	INPUT_STATE_ANYWHERE,
464
465
	{ 0x00, 0x17, input_c0_dispatch, NULL },
466
	{ 0x19, 0x19, input_c0_dispatch, NULL },
467
	{ 0x1c, 0x1f, input_c0_dispatch, NULL },
468
	{ 0x20, 0x7e, input_print,	 NULL },
469
	{ 0x7f, 0x7f, NULL,		 NULL },
470
	{ 0x80, 0xc1, NULL,		 NULL },
471
	{ 0xc2, 0xdf, input_utf8_open,	 &input_state_utf8_one },
472
	{ 0xe0, 0xef, input_utf8_open,	 &input_state_utf8_two },
473
	{ 0xf0, 0xf4, input_utf8_open,	 &input_state_utf8_three },
474
	{ 0xf5, 0xff, NULL,		 NULL },
475
476
	{ -1, -1, NULL, NULL }
477
};
478
479
/* esc_enter state table. */
480
static const struct input_transition input_state_esc_enter_table[] = {
481
	INPUT_STATE_ANYWHERE,
482
483
	{ 0x00, 0x17, input_c0_dispatch,  NULL },
484
	{ 0x19, 0x19, input_c0_dispatch,  NULL },
485
	{ 0x1c, 0x1f, input_c0_dispatch,  NULL },
486
	{ 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
487
	{ 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
488
	{ 0x50, 0x50, NULL,		  &input_state_dcs_enter },
489
	{ 0x51, 0x57, input_esc_dispatch, &input_state_ground },
490
	{ 0x58, 0x58, NULL,		  &input_state_consume_st },
491
	{ 0x59, 0x59, input_esc_dispatch, &input_state_ground },
492
	{ 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
493
	{ 0x5b, 0x5b, NULL,		  &input_state_csi_enter },
494
	{ 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
495
	{ 0x5d, 0x5d, NULL,		  &input_state_osc_string },
496
	{ 0x5e, 0x5e, NULL,		  &input_state_consume_st },
497
	{ 0x5f, 0x5f, NULL,		  &input_state_apc_string },
498
	{ 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
499
	{ 0x6b, 0x6b, NULL,		  &input_state_rename_string },
500
	{ 0x6c, 0x7e, input_esc_dispatch, &input_state_ground },
501
	{ 0x7f, 0xff, NULL,		  NULL },
502
503
	{ -1, -1, NULL, NULL }
504
};
505
506
/* esc_interm state table. */
507
static const struct input_transition input_state_esc_intermediate_table[] = {
508
	INPUT_STATE_ANYWHERE,
509
510
	{ 0x00, 0x17, input_c0_dispatch,  NULL },
511
	{ 0x19, 0x19, input_c0_dispatch,  NULL },
512
	{ 0x1c, 0x1f, input_c0_dispatch,  NULL },
513
	{ 0x20, 0x2f, input_intermediate, NULL },
514
	{ 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
515
	{ 0x7f, 0xff, NULL,		  NULL },
516
517
	{ -1, -1, NULL, NULL }
518
};
519
520
/* csi_enter state table. */
521
static const struct input_transition input_state_csi_enter_table[] = {
522
	INPUT_STATE_ANYWHERE,
523
524
	{ 0x00, 0x17, input_c0_dispatch,  NULL },
525
	{ 0x19, 0x19, input_c0_dispatch,  NULL },
526
	{ 0x1c, 0x1f, input_c0_dispatch,  NULL },
527
	{ 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
528
	{ 0x30, 0x39, input_parameter,	  &input_state_csi_parameter },
529
	{ 0x3a, 0x3a, NULL,		  &input_state_csi_ignore },
530
	{ 0x3b, 0x3b, input_parameter,	  &input_state_csi_parameter },
531
	{ 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
532
	{ 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
533
	{ 0x7f, 0xff, NULL,		  NULL },
534
535
	{ -1, -1, NULL, NULL }
536
};
537
538
/* csi_parameter state table. */
539
static const struct input_transition input_state_csi_parameter_table[] = {
540
	INPUT_STATE_ANYWHERE,
541
542
	{ 0x00, 0x17, input_c0_dispatch,  NULL },
543
	{ 0x19, 0x19, input_c0_dispatch,  NULL },
544
	{ 0x1c, 0x1f, input_c0_dispatch,  NULL },
545
	{ 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
546
	{ 0x30, 0x39, input_parameter,	  NULL },
547
	{ 0x3a, 0x3a, NULL,		  &input_state_csi_ignore },
548
	{ 0x3b, 0x3b, input_parameter,	  NULL },
549
	{ 0x3c, 0x3f, NULL,		  &input_state_csi_ignore },
550
	{ 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
551
	{ 0x7f, 0xff, NULL,		  NULL },
552
553
	{ -1, -1, NULL, NULL }
554
};
555
556
/* csi_intermediate state table. */
557
static const struct input_transition input_state_csi_intermediate_table[] = {
558
	INPUT_STATE_ANYWHERE,
559
560
	{ 0x00, 0x17, input_c0_dispatch,  NULL },
561
	{ 0x19, 0x19, input_c0_dispatch,  NULL },
562
	{ 0x1c, 0x1f, input_c0_dispatch,  NULL },
563
	{ 0x20, 0x2f, input_intermediate, NULL },
564
	{ 0x30, 0x3f, NULL,		  &input_state_csi_ignore },
565
	{ 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
566
	{ 0x7f, 0xff, NULL,		  NULL },
567
568
	{ -1, -1, NULL, NULL }
569
};
570
571
/* csi_ignore state table. */
572
static const struct input_transition input_state_csi_ignore_table[] = {
573
	INPUT_STATE_ANYWHERE,
574
575
	{ 0x00, 0x17, input_c0_dispatch, NULL },
576
	{ 0x19, 0x19, input_c0_dispatch, NULL },
577
	{ 0x1c, 0x1f, input_c0_dispatch, NULL },
578
	{ 0x20, 0x3f, NULL,		 NULL },
579
	{ 0x40, 0x7e, NULL,		 &input_state_ground },
580
	{ 0x7f, 0xff, NULL,		 NULL },
581
582
	{ -1, -1, NULL, NULL }
583
};
584
585
/* dcs_enter state table. */
586
static const struct input_transition input_state_dcs_enter_table[] = {
587
	INPUT_STATE_ANYWHERE,
588
589
	{ 0x00, 0x17, NULL,		  NULL },
590
	{ 0x19, 0x19, NULL,		  NULL },
591
	{ 0x1c, 0x1f, NULL,		  NULL },
592
	{ 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
593
	{ 0x30, 0x39, input_parameter,	  &input_state_dcs_parameter },
594
	{ 0x3a, 0x3a, NULL,		  &input_state_dcs_ignore },
595
	{ 0x3b, 0x3b, input_parameter,	  &input_state_dcs_parameter },
596
	{ 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
597
	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler },
598
	{ 0x7f, 0xff, NULL,		  NULL },
599
600
	{ -1, -1, NULL, NULL }
601
};
602
603
/* dcs_parameter state table. */
604
static const struct input_transition input_state_dcs_parameter_table[] = {
605
	INPUT_STATE_ANYWHERE,
606
607
	{ 0x00, 0x17, NULL,		  NULL },
608
	{ 0x19, 0x19, NULL,		  NULL },
609
	{ 0x1c, 0x1f, NULL,		  NULL },
610
	{ 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
611
	{ 0x30, 0x39, input_parameter,	  NULL },
612
	{ 0x3a, 0x3a, NULL,		  &input_state_dcs_ignore },
613
	{ 0x3b, 0x3b, input_parameter,	  NULL },
614
	{ 0x3c, 0x3f, NULL,		  &input_state_dcs_ignore },
615
	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler },
616
	{ 0x7f, 0xff, NULL,		  NULL },
617
618
	{ -1, -1, NULL, NULL }
619
};
620
621
/* dcs_interm state table. */
622
static const struct input_transition input_state_dcs_intermediate_table[] = {
623
	INPUT_STATE_ANYWHERE,
624
625
	{ 0x00, 0x17, NULL,		  NULL },
626
	{ 0x19, 0x19, NULL,		  NULL },
627
	{ 0x1c, 0x1f, NULL,		  NULL },
628
	{ 0x20, 0x2f, input_intermediate, NULL },
629
	{ 0x30, 0x3f, NULL,		  &input_state_dcs_ignore },
630
	{ 0x40, 0x7e, input_input,	  &input_state_dcs_handler },
631
	{ 0x7f, 0xff, NULL,		  NULL },
632
633
	{ -1, -1, NULL, NULL }
634
};
635
636
/* dcs_handler state table. */
637
static const struct input_transition input_state_dcs_handler_table[] = {
638
	/* No INPUT_STATE_ANYWHERE */
639
640
	{ 0x00, 0x1a, input_input,  NULL },
641
	{ 0x1b, 0x1b, NULL,	    &input_state_dcs_escape },
642
	{ 0x1c, 0xff, input_input,  NULL },
643
644
	{ -1, -1, NULL, NULL }
645
};
646
647
/* dcs_escape state table. */
648
static const struct input_transition input_state_dcs_escape_table[] = {
649
	/* No INPUT_STATE_ANYWHERE */
650
651
	{ 0x00, 0x5b, input_input,	  &input_state_dcs_handler },
652
	{ 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
653
	{ 0x5d, 0xff, input_input,	  &input_state_dcs_handler },
654
655
	{ -1, -1, NULL, NULL }
656
};
657
658
/* dcs_ignore state table. */
659
static const struct input_transition input_state_dcs_ignore_table[] = {
660
	INPUT_STATE_ANYWHERE,
661
662
	{ 0x00, 0x17, NULL,	    NULL },
663
	{ 0x19, 0x19, NULL,	    NULL },
664
	{ 0x1c, 0x1f, NULL,	    NULL },
665
	{ 0x20, 0xff, NULL,	    NULL },
666
667
	{ -1, -1, NULL, NULL }
668
};
669
670
/* osc_string state table. */
671
static const struct input_transition input_state_osc_string_table[] = {
672
	INPUT_STATE_ANYWHERE,
673
674
	{ 0x00, 0x06, NULL,	    NULL },
675
	{ 0x07, 0x07, NULL,	    &input_state_ground },
676
	{ 0x08, 0x17, NULL,	    NULL },
677
	{ 0x19, 0x19, NULL,	    NULL },
678
	{ 0x1c, 0x1f, NULL,	    NULL },
679
	{ 0x20, 0xff, input_input,  NULL },
680
681
	{ -1, -1, NULL, NULL }
682
};
683
684
/* apc_string state table. */
685
static const struct input_transition input_state_apc_string_table[] = {
686
	INPUT_STATE_ANYWHERE,
687
688
	{ 0x00, 0x17, NULL,	    NULL },
689
	{ 0x19, 0x19, NULL,	    NULL },
690
	{ 0x1c, 0x1f, NULL,	    NULL },
691
	{ 0x20, 0xff, input_input,  NULL },
692
693
	{ -1, -1, NULL, NULL }
694
};
695
696
/* rename_string state table. */
697
static const struct input_transition input_state_rename_string_table[] = {
698
	INPUT_STATE_ANYWHERE,
699
700
	{ 0x00, 0x17, NULL,	    NULL },
701
	{ 0x19, 0x19, NULL,	    NULL },
702
	{ 0x1c, 0x1f, NULL,	    NULL },
703
	{ 0x20, 0xff, input_input,  NULL },
704
705
	{ -1, -1, NULL, NULL }
706
};
707
708
/* consume_st state table. */
709
static const struct input_transition input_state_consume_st_table[] = {
710
	INPUT_STATE_ANYWHERE,
711
712
	{ 0x00, 0x17, NULL,	    NULL },
713
	{ 0x19, 0x19, NULL,	    NULL },
714
	{ 0x1c, 0x1f, NULL,	    NULL },
715
	{ 0x20, 0xff, NULL,	    NULL },
716
717
	{ -1, -1, NULL, NULL }
718
};
719
720
/* utf8_three state table. */
721
static const struct input_transition input_state_utf8_three_table[] = {
722
	/* No INPUT_STATE_ANYWHERE */
723
724
	{ 0x00, 0x7f, NULL,		&input_state_ground },
725
	{ 0x80, 0xbf, input_utf8_add,	&input_state_utf8_two },
726
	{ 0xc0, 0xff, NULL,		&input_state_ground },
727
728
	{ -1, -1, NULL, NULL }
729
};
730
731
/* utf8_two state table. */
732
static const struct input_transition input_state_utf8_two_table[] = {
733
	/* No INPUT_STATE_ANYWHERE */
734
735
	{ 0x00, 0x7f, NULL,	      &input_state_ground },
736
	{ 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
737
	{ 0xc0, 0xff, NULL,	      &input_state_ground },
738
739
	{ -1, -1, NULL, NULL }
740
};
741
742
/* utf8_one state table. */
743
static const struct input_transition input_state_utf8_one_table[] = {
744
	/* No INPUT_STATE_ANYWHERE */
745
746
	{ 0x00, 0x7f, NULL,		&input_state_ground },
747
	{ 0x80, 0xbf, input_utf8_close, &input_state_ground },
748
	{ 0xc0, 0xff, NULL,		&input_state_ground },
749
750
	{ -1, -1, NULL, NULL }
751
};
752
753
/* Input table compare. */
754
static int
755
input_table_compare(const void *key, const void *value)
756
{
757
	const struct input_ctx		*ictx = key;
758
	const struct input_table_entry	*entry = value;
759
760
	if (ictx->ch != entry->ch)
761
		return (ictx->ch - entry->ch);
762
	return (strcmp(ictx->interm_buf, entry->interm));
763
}
764
765
/*
766
 * Timer - if this expires then have been waiting for a terminator for too
767
 * long, so reset to ground.
768
 */
769
static void
770
input_timer_callback(__unused int fd, __unused short events, void *arg)
771
{
772
	struct input_ctx	*ictx = arg;
773
	struct window_pane	*wp = ictx->wp;
774
775
	log_debug("%s: %%%u %s expired" , __func__, wp->id, ictx->state->name);
776
	input_reset(wp, 0);
777
}
778
779
/* Start the timer. */
780
static void
781
input_start_timer(struct input_ctx *ictx)
782
{
783
	struct timeval	tv = { .tv_usec = 100000 };
784
785
	event_del(&ictx->timer);
786
	event_add(&ictx->timer, &tv);
787
}
788
789
/* Reset cell state to default. */
790
static void
791
input_reset_cell(struct input_ctx *ictx)
792
{
793
	memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell);
794
	ictx->cell.set = 0;
795
	ictx->cell.g0set = ictx->cell.g1set = 0;
796
797
	memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
798
	ictx->old_cx = 0;
799
	ictx->old_cy = 0;
800
}
801
802
/* Initialise input parser. */
803
void
804
input_init(struct window_pane *wp)
805
{
806
	struct input_ctx	*ictx;
807
808
	ictx = wp->ictx = xcalloc(1, sizeof *ictx);
809
810
	ictx->input_space = INPUT_BUF_START;
811
	ictx->input_buf = xmalloc(INPUT_BUF_START);
812
813
	ictx->since_ground = evbuffer_new();
814
815
	evtimer_set(&ictx->timer, input_timer_callback, ictx);
816
817
	input_reset(wp, 0);
818
}
819
820
/* Destroy input parser. */
821
void
822
input_free(struct window_pane *wp)
823
{
824
	struct input_ctx	*ictx = wp->ictx;
825
826
	event_del(&ictx->timer);
827
828
	free(ictx->input_buf);
829
	evbuffer_free(ictx->since_ground);
830
831
	free(ictx);
832
	wp->ictx = NULL;
833
}
834
835
/* Reset input state and clear screen. */
836
void
837
input_reset(struct window_pane *wp, int clear)
838
{
839
	struct input_ctx	*ictx = wp->ictx;
840
841
	input_reset_cell(ictx);
842
843
	if (clear) {
844
		if (wp->mode == NULL)
845
			screen_write_start(&ictx->ctx, wp, &wp->base);
846
		else
847
			screen_write_start(&ictx->ctx, NULL, &wp->base);
848
		screen_write_reset(&ictx->ctx);
849
		screen_write_stop(&ictx->ctx);
850
	}
851
852
	input_clear(ictx);
853
854
	ictx->last = -1;
855
856
	ictx->state = &input_state_ground;
857
	ictx->flags = 0;
858
}
859
860
/* Return pending data. */
861
struct evbuffer *
862
input_pending(struct window_pane *wp)
863
{
864
	return (wp->ictx->since_ground);
865
}
866
867
/* Change input state. */
868
static void
869
input_set_state(struct window_pane *wp, const struct input_transition *itr)
870
{
871
	struct input_ctx	*ictx = wp->ictx;
872
873
	if (ictx->state->exit != NULL)
874
		ictx->state->exit(ictx);
875
	ictx->state = itr->state;
876
	if (ictx->state->enter != NULL)
877
		ictx->state->enter(ictx);
878
}
879
880
/* Parse input. */
881
void
882
input_parse(struct window_pane *wp)
883
{
884
	struct input_ctx		*ictx = wp->ictx;
885
	const struct input_transition	*itr;
886
	struct evbuffer			*evb = wp->event->input;
887
	u_char				*buf;
888
	size_t				 len, off;
889
890
	if (EVBUFFER_LENGTH(evb) == 0)
891
		return;
892
893
	window_update_activity(wp->window);
894
	wp->flags |= PANE_CHANGED;
895
896
	/*
897
	 * Open the screen. Use NULL wp if there is a mode set as don't want to
898
	 * update the tty.
899
	 */
900
	if (wp->mode == NULL)
901
		screen_write_start(&ictx->ctx, wp, &wp->base);
902
	else
903
		screen_write_start(&ictx->ctx, NULL, &wp->base);
904
	ictx->wp = wp;
905
906
	buf = EVBUFFER_DATA(evb);
907
	len = EVBUFFER_LENGTH(evb);
908
	off = 0;
909
910
	notify_input(wp, evb);
911
912
	log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
913
	    ictx->state->name, len, (int)len, buf);
914
915
	/* Parse the input. */
916
	while (off < len) {
917
		ictx->ch = buf[off++];
918
919
		/* Find the transition. */
920
		itr = ictx->state->transitions;
921
		while (itr->first != -1 && itr->last != -1) {
922
			if (ictx->ch >= itr->first && ictx->ch <= itr->last)
923
				break;
924
			itr++;
925
		}
926
		if (itr->first == -1 || itr->last == -1) {
927
			/* No transition? Eh? */
928
			fatalx("no transition from state");
929
		}
930
931
		/*
932
		 * Any state except print stops the current collection. This is
933
		 * an optimization to avoid checking if the attributes have
934
		 * changed for every character. It will stop unnecessarily for
935
		 * sequences that don't make a terminal change, but they should
936
		 * be the minority.
937
		 */
938
		if (itr->handler != input_print)
939
			screen_write_collect_end(&ictx->ctx);
940
941
		/*
942
		 * Execute the handler, if any. Don't switch state if it
943
		 * returns non-zero.
944
		 */
945
		if (itr->handler != NULL && itr->handler(ictx) != 0)
946
			continue;
947
948
		/* And switch state, if necessary. */
949
		if (itr->state != NULL)
950
			input_set_state(wp, itr);
951
952
		/* If not in ground state, save input. */
953
		if (ictx->state != &input_state_ground)
954
			evbuffer_add(ictx->since_ground, &ictx->ch, 1);
955
	}
956
957
	/* Close the screen. */
958
	screen_write_stop(&ictx->ctx);
959
960
	evbuffer_drain(evb, len);
961
}
962
963
/* Split the parameter list (if any). */
964
static int
965
input_split(struct input_ctx *ictx)
966
{
967
	const char	*errstr;
968
	char		*ptr, *out;
969
	int		 n;
970
971
	ictx->param_list_len = 0;
972
	if (ictx->param_len == 0)
973
		return (0);
974
975
	ptr = ictx->param_buf;
976
	while ((out = strsep(&ptr, ";")) != NULL) {
977
		if (*out == '\0')
978
			n = -1;
979
		else {
980
			n = strtonum(out, 0, INT_MAX, &errstr);
981
			if (errstr != NULL)
982
				return (-1);
983
		}
984
985
		ictx->param_list[ictx->param_list_len++] = n;
986
		if (ictx->param_list_len == nitems(ictx->param_list))
987
			return (-1);
988
	}
989
990
	return (0);
991
}
992
993
/* Get an argument or return default value. */
994
static int
995
input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
996
{
997
	int	retval;
998
999
	if (validx >= ictx->param_list_len)
1000
	    return (defval);
1001
1002
	retval = ictx->param_list[validx];
1003
	if (retval == -1)
1004
		return (defval);
1005
	if (retval < minval)
1006
		return (minval);
1007
	return (retval);
1008
}
1009
1010
/* Reply to terminal query. */
1011
static void
1012
input_reply(struct input_ctx *ictx, const char *fmt, ...)
1013
{
1014
	va_list	ap;
1015
	char   *reply;
1016
1017
	va_start(ap, fmt);
1018
	xvasprintf(&reply, fmt, ap);
1019
	va_end(ap);
1020
1021
	bufferevent_write(ictx->wp->event, reply, strlen(reply));
1022
	free(reply);
1023
}
1024
1025
/* Clear saved state. */
1026
static void
1027
input_clear(struct input_ctx *ictx)
1028
{
1029
	event_del(&ictx->timer);
1030
1031
	*ictx->interm_buf = '\0';
1032
	ictx->interm_len = 0;
1033
1034
	*ictx->param_buf = '\0';
1035
	ictx->param_len = 0;
1036
1037
	*ictx->input_buf = '\0';
1038
	ictx->input_len = 0;
1039
1040
	ictx->flags &= ~INPUT_DISCARD;
1041
}
1042
1043
/* Reset for ground state. */
1044
static void
1045
input_ground(struct input_ctx *ictx)
1046
{
1047
	event_del(&ictx->timer);
1048
	evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
1049
1050
	if (ictx->input_space > INPUT_BUF_START) {
1051
		ictx->input_space = INPUT_BUF_START;
1052
		ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START);
1053
	}
1054
}
1055
1056
/* Output this character to the screen. */
1057
static int
1058
input_print(struct input_ctx *ictx)
1059
{
1060
	int	set;
1061
1062
	set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
1063
	if (set == 1)
1064
		ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
1065
	else
1066
		ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1067
1068
	utf8_set(&ictx->cell.cell.data, ictx->ch);
1069
	screen_write_collect_add(&ictx->ctx, &ictx->cell.cell);
1070
	ictx->last = ictx->ch;
1071
1072
	ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1073
1074
	return (0);
1075
}
1076
1077
/* Collect intermediate string. */
1078
static int
1079
input_intermediate(struct input_ctx *ictx)
1080
{
1081
	if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
1082
		ictx->flags |= INPUT_DISCARD;
1083
	else {
1084
		ictx->interm_buf[ictx->interm_len++] = ictx->ch;
1085
		ictx->interm_buf[ictx->interm_len] = '\0';
1086
	}
1087
1088
	return (0);
1089
}
1090
1091
/* Collect parameter string. */
1092
static int
1093
input_parameter(struct input_ctx *ictx)
1094
{
1095
	if (ictx->param_len == (sizeof ictx->param_buf) - 1)
1096
		ictx->flags |= INPUT_DISCARD;
1097
	else {
1098
		ictx->param_buf[ictx->param_len++] = ictx->ch;
1099
		ictx->param_buf[ictx->param_len] = '\0';
1100
	}
1101
1102
	return (0);
1103
}
1104
1105
/* Collect input string. */
1106
static int
1107
input_input(struct input_ctx *ictx)
1108
{
1109
	size_t available;
1110
1111
	available = ictx->input_space;
1112
	while (ictx->input_len + 1 >= available) {
1113
		available *= 2;
1114
		if (available > INPUT_BUF_LIMIT) {
1115
			ictx->flags |= INPUT_DISCARD;
1116
			return (0);
1117
		}
1118
		ictx->input_buf = xrealloc(ictx->input_buf, available);
1119
		ictx->input_space = available;
1120
	}
1121
	ictx->input_buf[ictx->input_len++] = ictx->ch;
1122
	ictx->input_buf[ictx->input_len] = '\0';
1123
1124
	return (0);
1125
}
1126
1127
/* Execute C0 control sequence. */
1128
static int
1129
input_c0_dispatch(struct input_ctx *ictx)
1130
{
1131
	struct screen_write_ctx	*sctx = &ictx->ctx;
1132
	struct window_pane	*wp = ictx->wp;
1133
	struct screen		*s = sctx->s;
1134
1135
	log_debug("%s: '%c'", __func__, ictx->ch);
1136
1137
	switch (ictx->ch) {
1138
	case '\000':	/* NUL */
1139
		break;
1140
	case '\007':	/* BEL */
1141
		alerts_queue(wp->window, WINDOW_BELL);
1142
		break;
1143
	case '\010':	/* BS */
1144
		screen_write_backspace(sctx);
1145
		break;
1146
	case '\011':	/* HT */
1147
		/* Don't tab beyond the end of the line. */
1148
		if (s->cx >= screen_size_x(s) - 1)
1149
			break;
1150
1151
		/* Find the next tab point, or use the last column if none. */
1152
		do {
1153
			s->cx++;
1154
			if (bit_test(s->tabs, s->cx))
1155
				break;
1156
		} while (s->cx < screen_size_x(s) - 1);
1157
		break;
1158
	case '\012':	/* LF */
1159
	case '\013':	/* VT */
1160
	case '\014':	/* FF */
1161
		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1162
		break;
1163
	case '\015':	/* CR */
1164
		screen_write_carriagereturn(sctx);
1165
		break;
1166
	case '\016':	/* SO */
1167
		ictx->cell.set = 1;
1168
		break;
1169
	case '\017':	/* SI */
1170
		ictx->cell.set = 0;
1171
		break;
1172
	default:
1173
		log_debug("%s: unknown '%c'", __func__, ictx->ch);
1174
		break;
1175
	}
1176
1177
	ictx->last = -1;
1178
	return (0);
1179
}
1180
1181
/* Execute escape sequence. */
1182
static int
1183
input_esc_dispatch(struct input_ctx *ictx)
1184
{
1185
	struct screen_write_ctx		*sctx = &ictx->ctx;
1186
	struct screen			*s = sctx->s;
1187
	struct input_table_entry	*entry;
1188
1189
	if (ictx->flags & INPUT_DISCARD)
1190
		return (0);
1191
	log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1192
1193
	entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
1194
	    sizeof input_esc_table[0], input_table_compare);
1195
	if (entry == NULL) {
1196
		log_debug("%s: unknown '%c'", __func__, ictx->ch);
1197
		return (0);
1198
	}
1199
1200
	switch (entry->type) {
1201
	case INPUT_ESC_RIS:
1202
		window_pane_reset_palette(ictx->wp);
1203
		input_reset_cell(ictx);
1204
		screen_write_reset(sctx);
1205
		break;
1206
	case INPUT_ESC_IND:
1207
		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1208
		break;
1209
	case INPUT_ESC_NEL:
1210
		screen_write_carriagereturn(sctx);
1211
		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1212
		break;
1213
	case INPUT_ESC_HTS:
1214
		if (s->cx < screen_size_x(s))
1215
			bit_set(s->tabs, s->cx);
1216
		break;
1217
	case INPUT_ESC_RI:
1218
		screen_write_reverseindex(sctx, ictx->cell.cell.bg);
1219
		break;
1220
	case INPUT_ESC_DECKPAM:
1221
		screen_write_mode_set(sctx, MODE_KKEYPAD);
1222
		break;
1223
	case INPUT_ESC_DECKPNM:
1224
		screen_write_mode_clear(sctx, MODE_KKEYPAD);
1225
		break;
1226
	case INPUT_ESC_DECSC:
1227
		memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1228
		ictx->old_cx = s->cx;
1229
		ictx->old_cy = s->cy;
1230
		break;
1231
	case INPUT_ESC_DECRC:
1232
		memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1233
		screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1234
		break;
1235
	case INPUT_ESC_DECALN:
1236
		screen_write_alignmenttest(sctx);
1237
		break;
1238
	case INPUT_ESC_SCSG0_ON:
1239
		ictx->cell.g0set = 1;
1240
		break;
1241
	case INPUT_ESC_SCSG0_OFF:
1242
		ictx->cell.g0set = 0;
1243
		break;
1244
	case INPUT_ESC_SCSG1_ON:
1245
		ictx->cell.g1set = 1;
1246
		break;
1247
	case INPUT_ESC_SCSG1_OFF:
1248
		ictx->cell.g1set = 0;
1249
		break;
1250
	case INPUT_ESC_ST:
1251
		/* ST terminates OSC but the state transition already did it. */
1252
		break;
1253
	}
1254
1255
	ictx->last = -1;
1256
	return (0);
1257
}
1258
1259
/* Execute control sequence. */
1260
static int
1261
input_csi_dispatch(struct input_ctx *ictx)
1262
{
1263
	struct screen_write_ctx	       *sctx = &ictx->ctx;
1264
	struct screen		       *s = sctx->s;
1265
	struct input_table_entry       *entry;
1266
	int				i, n, m;
1267
	u_int				cx;
1268
1269
	if (ictx->flags & INPUT_DISCARD)
1270
		return (0);
1271
1272
	log_debug("%s: '%c' \"%s\" \"%s\"",
1273
	    __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1274
1275
	if (input_split(ictx) != 0)
1276
		return (0);
1277
1278
	entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1279
	    sizeof input_csi_table[0], input_table_compare);
1280
	if (entry == NULL) {
1281
		log_debug("%s: unknown '%c'", __func__, ictx->ch);
1282
		return (0);
1283
	}
1284
1285
	switch (entry->type) {
1286
	case INPUT_CSI_CBT:
1287
		/* Find the previous tab point, n times. */
1288
		cx = s->cx;
1289
		if (cx > screen_size_x(s) - 1)
1290
			cx = screen_size_x(s) - 1;
1291
		n = input_get(ictx, 0, 1, 1);
1292
		while (cx > 0 && n-- > 0) {
1293
			do
1294
				cx--;
1295
			while (cx > 0 && !bit_test(s->tabs, cx));
1296
		}
1297
		s->cx = cx;
1298
		break;
1299
	case INPUT_CSI_CUB:
1300
		screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
1301
		break;
1302
	case INPUT_CSI_CUD:
1303
		screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1304
		break;
1305
	case INPUT_CSI_CUF:
1306
		screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
1307
		break;
1308
	case INPUT_CSI_CUP:
1309
		n = input_get(ictx, 0, 1, 1);
1310
		m = input_get(ictx, 1, 1, 1);
1311
		screen_write_cursormove(sctx, m - 1, n - 1);
1312
		break;
1313
	case INPUT_CSI_WINOPS:
1314
		input_csi_dispatch_winops(ictx);
1315
		break;
1316
	case INPUT_CSI_CUU:
1317
		screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1318
		break;
1319
	case INPUT_CSI_CNL:
1320
		screen_write_carriagereturn(sctx);
1321
		screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1322
		break;
1323
	case INPUT_CSI_CPL:
1324
		screen_write_carriagereturn(sctx);
1325
		screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1326
		break;
1327
	case INPUT_CSI_DA:
1328
		switch (input_get(ictx, 0, 0, 0)) {
1329
		case 0:
1330
			input_reply(ictx, "\033[?1;2c");
1331
			break;
1332
		default:
1333
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1334
			break;
1335
		}
1336
		break;
1337
	case INPUT_CSI_DA_TWO:
1338
		switch (input_get(ictx, 0, 0, 0)) {
1339
		case 0:
1340
			input_reply(ictx, "\033[>84;0;0c");
1341
			break;
1342
		default:
1343
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1344
			break;
1345
		}
1346
		break;
1347
	case INPUT_CSI_ECH:
1348
		screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1),
1349
		    ictx->cell.cell.bg);
1350
		break;
1351
	case INPUT_CSI_DCH:
1352
		screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1),
1353
		    ictx->cell.cell.bg);
1354
		break;
1355
	case INPUT_CSI_DECSTBM:
1356
		n = input_get(ictx, 0, 1, 1);
1357
		m = input_get(ictx, 1, 1, screen_size_y(s));
1358
		screen_write_scrollregion(sctx, n - 1, m - 1);
1359
		break;
1360
	case INPUT_CSI_DL:
1361
		screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1),
1362
		    ictx->cell.cell.bg);
1363
		break;
1364
	case INPUT_CSI_DSR:
1365
		switch (input_get(ictx, 0, 0, 0)) {
1366
		case 5:
1367
			input_reply(ictx, "\033[0n");
1368
			break;
1369
		case 6:
1370
			input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1371
			break;
1372
		default:
1373
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1374
			break;
1375
		}
1376
		break;
1377
	case INPUT_CSI_ED:
1378
		switch (input_get(ictx, 0, 0, 0)) {
1379
		case 0:
1380
			screen_write_clearendofscreen(sctx, ictx->cell.cell.bg);
1381
			break;
1382
		case 1:
1383
			screen_write_clearstartofscreen(sctx, ictx->cell.cell.bg);
1384
			break;
1385
		case 2:
1386
			screen_write_clearscreen(sctx, ictx->cell.cell.bg);
1387
			break;
1388
		case 3:
1389
			switch (input_get(ictx, 1, 0, 0)) {
1390
			case 0:
1391
				/*
1392
				 * Linux console extension to clear history
1393
				 * (for example before locking the screen).
1394
				 */
1395
				screen_write_clearhistory(sctx);
1396
				break;
1397
			}
1398
			break;
1399
		default:
1400
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1401
			break;
1402
		}
1403
		break;
1404
	case INPUT_CSI_EL:
1405
		switch (input_get(ictx, 0, 0, 0)) {
1406
		case 0:
1407
			screen_write_clearendofline(sctx, ictx->cell.cell.bg);
1408
			break;
1409
		case 1:
1410
			screen_write_clearstartofline(sctx, ictx->cell.cell.bg);
1411
			break;
1412
		case 2:
1413
			screen_write_clearline(sctx, ictx->cell.cell.bg);
1414
			break;
1415
		default:
1416
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1417
			break;
1418
		}
1419
		break;
1420
	case INPUT_CSI_HPA:
1421
		n = input_get(ictx, 0, 1, 1);
1422
		screen_write_cursormove(sctx, n - 1, s->cy);
1423
		break;
1424
	case INPUT_CSI_ICH:
1425
		screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1),
1426
		    ictx->cell.cell.bg);
1427
		break;
1428
	case INPUT_CSI_IL:
1429
		screen_write_insertline(sctx, input_get(ictx, 0, 1, 1),
1430
		    ictx->cell.cell.bg);
1431
		break;
1432
	case INPUT_CSI_REP:
1433
		if (ictx->last == -1)
1434
			break;
1435
		ictx->ch = ictx->last;
1436
1437
		n = input_get(ictx, 0, 1, 1);
1438
		for (i = 0; i < n; i++)
1439
			input_print(ictx);
1440
		break;
1441
	case INPUT_CSI_RCP:
1442
		memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1443
		screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1444
		break;
1445
	case INPUT_CSI_RM:
1446
		input_csi_dispatch_rm(ictx);
1447
		break;
1448
	case INPUT_CSI_RM_PRIVATE:
1449
		input_csi_dispatch_rm_private(ictx);
1450
		break;
1451
	case INPUT_CSI_SCP:
1452
		memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1453
		ictx->old_cx = s->cx;
1454
		ictx->old_cy = s->cy;
1455
		break;
1456
	case INPUT_CSI_SGR:
1457
		input_csi_dispatch_sgr(ictx);
1458
		break;
1459
	case INPUT_CSI_SM:
1460
		input_csi_dispatch_sm(ictx);
1461
		break;
1462
	case INPUT_CSI_SM_PRIVATE:
1463
		input_csi_dispatch_sm_private(ictx);
1464
		break;
1465
	case INPUT_CSI_SU:
1466
		screen_write_scrollup(sctx, input_get(ictx, 0, 1, 1),
1467
		    ictx->cell.cell.bg);
1468
		break;
1469
	case INPUT_CSI_TBC:
1470
		switch (input_get(ictx, 0, 0, 0)) {
1471
		case 0:
1472
			if (s->cx < screen_size_x(s))
1473
				bit_clear(s->tabs, s->cx);
1474
			break;
1475
		case 3:
1476
			bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1477
			break;
1478
		default:
1479
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1480
			break;
1481
		}
1482
		break;
1483
	case INPUT_CSI_VPA:
1484
		n = input_get(ictx, 0, 1, 1);
1485
		screen_write_cursormove(sctx, s->cx, n - 1);
1486
		break;
1487
	case INPUT_CSI_DECSCUSR:
1488
		n = input_get(ictx, 0, 0, 0);
1489
		screen_set_cursor_style(s, n);
1490
		break;
1491
	}
1492
1493
	ictx->last = -1;
1494
	return (0);
1495
}
1496
1497
/* Handle CSI RM. */
1498
static void
1499
input_csi_dispatch_rm(struct input_ctx *ictx)
1500
{
1501
	u_int	i;
1502
1503
	for (i = 0; i < ictx->param_list_len; i++) {
1504
		switch (input_get(ictx, i, 0, -1)) {
1505
		case 4:		/* IRM */
1506
			screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
1507
			break;
1508
		case 34:
1509
			screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1510
			break;
1511
		default:
1512
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1513
			break;
1514
		}
1515
	}
1516
}
1517
1518
/* Handle CSI private RM. */
1519
static void
1520
input_csi_dispatch_rm_private(struct input_ctx *ictx)
1521
{
1522
	struct window_pane	*wp = ictx->wp;
1523
	u_int			 i;
1524
1525
	for (i = 0; i < ictx->param_list_len; i++) {
1526
		switch (input_get(ictx, i, 0, -1)) {
1527
		case 1:		/* DECCKM */
1528
			screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
1529
			break;
1530
		case 3:		/* DECCOLM */
1531
			screen_write_cursormove(&ictx->ctx, 0, 0);
1532
			screen_write_clearscreen(&ictx->ctx,
1533
			    ictx->cell.cell.bg);
1534
			break;
1535
		case 7:		/* DECAWM */
1536
			screen_write_mode_clear(&ictx->ctx, MODE_WRAP);
1537
			break;
1538
		case 12:
1539
			screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1540
			break;
1541
		case 25:	/* TCEM */
1542
			screen_write_mode_clear(&ictx->ctx, MODE_CURSOR);
1543
			break;
1544
		case 1000:
1545
		case 1001:
1546
		case 1002:
1547
		case 1003:
1548
			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1549
			break;
1550
		case 1004:
1551
			screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON);
1552
			break;
1553
		case 1005:
1554
			screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8);
1555
			break;
1556
		case 1006:
1557
			screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR);
1558
			break;
1559
		case 47:
1560
		case 1047:
1561
			window_pane_alternate_off(wp, &ictx->cell.cell, 0);
1562
			break;
1563
		case 1049:
1564
			window_pane_alternate_off(wp, &ictx->cell.cell, 1);
1565
			break;
1566
		case 2004:
1567
			screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
1568
			break;
1569
		default:
1570
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1571
			break;
1572
		}
1573
	}
1574
}
1575
1576
/* Handle CSI SM. */
1577
static void
1578
input_csi_dispatch_sm(struct input_ctx *ictx)
1579
{
1580
	u_int	i;
1581
1582
	for (i = 0; i < ictx->param_list_len; i++) {
1583
		switch (input_get(ictx, i, 0, -1)) {
1584
		case 4:		/* IRM */
1585
			screen_write_mode_set(&ictx->ctx, MODE_INSERT);
1586
			break;
1587
		case 34:
1588
			screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1589
			break;
1590
		default:
1591
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1592
			break;
1593
		}
1594
	}
1595
}
1596
1597
/* Handle CSI private SM. */
1598
static void
1599
input_csi_dispatch_sm_private(struct input_ctx *ictx)
1600
{
1601
	struct window_pane	*wp = ictx->wp;
1602
	u_int			 i;
1603
1604
	for (i = 0; i < ictx->param_list_len; i++) {
1605
		switch (input_get(ictx, i, 0, -1)) {
1606
		case 1:		/* DECCKM */
1607
			screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
1608
			break;
1609
		case 3:		/* DECCOLM */
1610
			screen_write_cursormove(&ictx->ctx, 0, 0);
1611
			screen_write_clearscreen(&ictx->ctx,
1612
			    ictx->cell.cell.bg);
1613
			break;
1614
		case 7:		/* DECAWM */
1615
			screen_write_mode_set(&ictx->ctx, MODE_WRAP);
1616
			break;
1617
		case 12:
1618
			screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1619
			break;
1620
		case 25:	/* TCEM */
1621
			screen_write_mode_set(&ictx->ctx, MODE_CURSOR);
1622
			break;
1623
		case 1000:
1624
			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1625
			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD);
1626
			break;
1627
		case 1002:
1628
			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1629
			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON);
1630
			break;
1631
		case 1003:
1632
			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1633
			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ALL);
1634
			break;
1635
		case 1004:
1636
			if (ictx->ctx.s->mode & MODE_FOCUSON)
1637
				break;
1638
			screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
1639
			wp->flags |= PANE_FOCUSPUSH; /* force update */
1640
			break;
1641
		case 1005:
1642
			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
1643
			break;
1644
		case 1006:
1645
			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR);
1646
			break;
1647
		case 47:
1648
		case 1047:
1649
			window_pane_alternate_on(wp, &ictx->cell.cell, 0);
1650
			break;
1651
		case 1049:
1652
			window_pane_alternate_on(wp, &ictx->cell.cell, 1);
1653
			break;
1654
		case 2004:
1655
			screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
1656
			break;
1657
		default:
1658
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1659
			break;
1660
		}
1661
	}
1662
}
1663
1664
/* Handle CSI window operations. */
1665
static void
1666
input_csi_dispatch_winops(struct input_ctx *ictx)
1667
{
1668
	struct window_pane	*wp = ictx->wp;
1669
	int			 n, m;
1670
1671
	m = 0;
1672
	while ((n = input_get(ictx, m, 0, -1)) != -1) {
1673
		switch (n) {
1674
		case 1:
1675
		case 2:
1676
		case 5:
1677
		case 6:
1678
		case 7:
1679
		case 11:
1680
		case 13:
1681
		case 14:
1682
		case 19:
1683
		case 20:
1684
		case 21:
1685
		case 24:
1686
			break;
1687
		case 3:
1688
		case 4:
1689
		case 8:
1690
			m++;
1691
			if (input_get(ictx, m, 0, -1) == -1)
1692
				return;
1693
			/* FALLTHROUGH */
1694
		case 9:
1695
		case 10:
1696
		case 22:
1697
		case 23:
1698
			m++;
1699
			if (input_get(ictx, m, 0, -1) == -1)
1700
				return;
1701
			break;
1702
		case 18:
1703
			input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx);
1704
			break;
1705
		default:
1706
			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1707
			break;
1708
		}
1709
		m++;
1710
	}
1711
}
1712
1713
/* Handle CSI SGR for 256 colours. */
1714
static void
1715
input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
1716
{
1717
	struct grid_cell	*gc = &ictx->cell.cell;
1718
	int			 c;
1719
1720
	(*i)++;
1721
	c = input_get(ictx, *i, 0, -1);
1722
	if (c == -1) {
1723
		if (fgbg == 38)
1724
			gc->fg = 8;
1725
		else if (fgbg == 48)
1726
			gc->bg = 8;
1727
	} else {
1728
		if (fgbg == 38)
1729
			gc->fg = c | COLOUR_FLAG_256;
1730
		else if (fgbg == 48)
1731
			gc->bg = c | COLOUR_FLAG_256;
1732
	}
1733
}
1734
1735
/* Handle CSI SGR for RGB colours. */
1736
static void
1737
input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
1738
{
1739
	struct grid_cell	*gc = &ictx->cell.cell;
1740
	int			 r, g, b;
1741
1742
	(*i)++;
1743
	r = input_get(ictx, *i, 0, -1);
1744
	if (r == -1 || r > 255)
1745
		return;
1746
	(*i)++;
1747
	g = input_get(ictx, *i, 0, -1);
1748
	if (g == -1 || g > 255)
1749
		return;
1750
	(*i)++;
1751
	b = input_get(ictx, *i, 0, -1);
1752
	if (b == -1 || b > 255)
1753
		return;
1754
1755
	if (fgbg == 38)
1756
		gc->fg = colour_join_rgb(r, g, b);
1757
	else if (fgbg == 48)
1758
		gc->bg = colour_join_rgb(r, g, b);
1759
}
1760
1761
/* Handle CSI SGR. */
1762
static void
1763
input_csi_dispatch_sgr(struct input_ctx *ictx)
1764
{
1765
	struct grid_cell	*gc = &ictx->cell.cell;
1766
	u_int			 i;
1767
	int			 n;
1768
1769
	if (ictx->param_list_len == 0) {
1770
		memcpy(gc, &grid_default_cell, sizeof *gc);
1771
		return;
1772
	}
1773
1774
	for (i = 0; i < ictx->param_list_len; i++) {
1775
		n = input_get(ictx, i, 0, 0);
1776
1777
		if (n == 38 || n == 48) {
1778
			i++;
1779
			switch (input_get(ictx, i, 0, -1)) {
1780
			case 2:
1781
				input_csi_dispatch_sgr_rgb(ictx, n, &i);
1782
				break;
1783
			case 5:
1784
				input_csi_dispatch_sgr_256(ictx, n, &i);
1785
				break;
1786
			}
1787
			continue;
1788
		}
1789
1790
		switch (n) {
1791
		case 0:
1792
		case 10:
1793
			memcpy(gc, &grid_default_cell, sizeof *gc);
1794
			break;
1795
		case 1:
1796
			gc->attr |= GRID_ATTR_BRIGHT;
1797
			break;
1798
		case 2:
1799
			gc->attr |= GRID_ATTR_DIM;
1800
			break;
1801
		case 3:
1802
			gc->attr |= GRID_ATTR_ITALICS;
1803
			break;
1804
		case 4:
1805
			gc->attr |= GRID_ATTR_UNDERSCORE;
1806
			break;
1807
		case 5:
1808
			gc->attr |= GRID_ATTR_BLINK;
1809
			break;
1810
		case 7:
1811
			gc->attr |= GRID_ATTR_REVERSE;
1812
			break;
1813
		case 8:
1814
			gc->attr |= GRID_ATTR_HIDDEN;
1815
			break;
1816
		case 9:
1817
			gc->attr |= GRID_ATTR_STRIKETHROUGH;
1818
			break;
1819
		case 22:
1820
			gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1821
			break;
1822
		case 23:
1823
			gc->attr &= ~GRID_ATTR_ITALICS;
1824
			break;
1825
		case 24:
1826
			gc->attr &= ~GRID_ATTR_UNDERSCORE;
1827
			break;
1828
		case 25:
1829
			gc->attr &= ~GRID_ATTR_BLINK;
1830
			break;
1831
		case 27:
1832
			gc->attr &= ~GRID_ATTR_REVERSE;
1833
			break;
1834
		case 28:
1835
			gc->attr &= ~GRID_ATTR_HIDDEN;
1836
			break;
1837
		case 29:
1838
			gc->attr &= ~GRID_ATTR_STRIKETHROUGH;
1839
			break;
1840
		case 30:
1841
		case 31:
1842
		case 32:
1843
		case 33:
1844
		case 34:
1845
		case 35:
1846
		case 36:
1847
		case 37:
1848
			gc->fg = n - 30;
1849
			break;
1850
		case 39:
1851
			gc->fg = 8;
1852
			break;
1853
		case 40:
1854
		case 41:
1855
		case 42:
1856
		case 43:
1857
		case 44:
1858
		case 45:
1859
		case 46:
1860
		case 47:
1861
			gc->bg = n - 40;
1862
			break;
1863
		case 49:
1864
			gc->bg = 8;
1865
			break;
1866
		case 90:
1867
		case 91:
1868
		case 92:
1869
		case 93:
1870
		case 94:
1871
		case 95:
1872
		case 96:
1873
		case 97:
1874
			gc->fg = n;
1875
			break;
1876
		case 100:
1877
		case 101:
1878
		case 102:
1879
		case 103:
1880
		case 104:
1881
		case 105:
1882
		case 106:
1883
		case 107:
1884
			gc->bg = n - 10;
1885
			break;
1886
		}
1887
	}
1888
}
1889
1890
/* DCS string started. */
1891
static void
1892
input_enter_dcs(struct input_ctx *ictx)
1893
{
1894
	log_debug("%s", __func__);
1895
1896
	input_clear(ictx);
1897
	input_start_timer(ictx);
1898
	ictx->last = -1;
1899
}
1900
1901
/* DCS terminator (ST) received. */
1902
static int
1903
input_dcs_dispatch(struct input_ctx *ictx)
1904
{
1905
	const char	prefix[] = "tmux;";
1906
	const u_int	prefix_len = (sizeof prefix) - 1;
1907
1908
	if (ictx->flags & INPUT_DISCARD)
1909
		return (0);
1910
1911
	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1912
1913
	/* Check for tmux prefix. */
1914
	if (ictx->input_len >= prefix_len &&
1915
	    strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
1916
		screen_write_rawstring(&ictx->ctx,
1917
		    ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
1918
	}
1919
1920
	return (0);
1921
}
1922
1923
/* OSC string started. */
1924
static void
1925
input_enter_osc(struct input_ctx *ictx)
1926
{
1927
	log_debug("%s", __func__);
1928
1929
	input_clear(ictx);
1930
	input_start_timer(ictx);
1931
	ictx->last = -1;
1932
}
1933
1934
/* OSC terminator (ST) received. */
1935
static void
1936
input_exit_osc(struct input_ctx *ictx)
1937
{
1938
	u_char	*p = ictx->input_buf;
1939
	u_int	 option;
1940
1941
	if (ictx->flags & INPUT_DISCARD)
1942
		return;
1943
	if (ictx->input_len < 1 || *p < '0' || *p > '9')
1944
		return;
1945
1946
	log_debug("%s: \"%s\"", __func__, p);
1947
1948
	option = 0;
1949
	while (*p >= '0' && *p <= '9')
1950
		option = option * 10 + *p++ - '0';
1951
	if (*p == ';')
1952
		p++;
1953
1954
	switch (option) {
1955
	case 0:
1956
	case 2:
1957
		if (utf8_isvalid(p)) {
1958
			screen_set_title(ictx->ctx.s, p);
1959
			server_status_window(ictx->wp->window);
1960
		}
1961
		break;
1962
	case 4:
1963
		input_osc_4(ictx->wp, p);
1964
		break;
1965
	case 10:
1966
		input_osc_10(ictx->wp, p);
1967
		break;
1968
	case 11:
1969
		input_osc_11(ictx->wp, p);
1970
		break;
1971
	case 12:
1972
		if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
1973
			screen_set_cursor_colour(ictx->ctx.s, p);
1974
		break;
1975
	case 52:
1976
		input_osc_52(ictx->wp, p);
1977
		break;
1978
	case 104:
1979
		input_osc_104(ictx->wp, p);
1980
		break;
1981
	case 112:
1982
		if (*p == '\0') /* no arguments allowed */
1983
			screen_set_cursor_colour(ictx->ctx.s, "");
1984
		break;
1985
	default:
1986
		log_debug("%s: unknown '%u'", __func__, option);
1987
		break;
1988
	}
1989
}
1990
1991
/* APC string started. */
1992
static void
1993
input_enter_apc(struct input_ctx *ictx)
1994
{
1995
	log_debug("%s", __func__);
1996
1997
	input_clear(ictx);
1998
	input_start_timer(ictx);
1999
	ictx->last = -1;
2000
}
2001
2002
/* APC terminator (ST) received. */
2003
static void
2004
input_exit_apc(struct input_ctx *ictx)
2005
{
2006
	if (ictx->flags & INPUT_DISCARD)
2007
		return;
2008
	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2009
2010
	if (!utf8_isvalid(ictx->input_buf))
2011
		return;
2012
	screen_set_title(ictx->ctx.s, ictx->input_buf);
2013
	server_status_window(ictx->wp->window);
2014
}
2015
2016
/* Rename string started. */
2017
static void
2018
input_enter_rename(struct input_ctx *ictx)
2019
{
2020
	log_debug("%s", __func__);
2021
2022
	input_clear(ictx);
2023
	input_start_timer(ictx);
2024
	ictx->last = -1;
2025
}
2026
2027
/* Rename terminator (ST) received. */
2028
static void
2029
input_exit_rename(struct input_ctx *ictx)
2030
{
2031
	if (ictx->flags & INPUT_DISCARD)
2032
		return;
2033
	if (!options_get_number(ictx->wp->window->options, "allow-rename"))
2034
		return;
2035
	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2036
2037
	if (!utf8_isvalid(ictx->input_buf))
2038
		return;
2039
	window_set_name(ictx->wp->window, ictx->input_buf);
2040
	options_set_number(ictx->wp->window->options, "automatic-rename", 0);
2041
	server_status_window(ictx->wp->window);
2042
}
2043
2044
/* Open UTF-8 character. */
2045
static int
2046
input_utf8_open(struct input_ctx *ictx)
2047
{
2048
	struct utf8_data	*ud = &ictx->utf8data;
2049
2050
	if (utf8_open(ud, ictx->ch) != UTF8_MORE)
2051
		fatalx("UTF-8 open invalid %#x", ictx->ch);
2052
2053
	log_debug("%s %hhu", __func__, ud->size);
2054
	ictx->last = -1;
2055
2056
	return (0);
2057
}
2058
2059
/* Append to UTF-8 character. */
2060
static int
2061
input_utf8_add(struct input_ctx *ictx)
2062
{
2063
	struct utf8_data	*ud = &ictx->utf8data;
2064
2065
	if (utf8_append(ud, ictx->ch) != UTF8_MORE)
2066
		fatalx("UTF-8 add invalid %#x", ictx->ch);
2067
2068
	log_debug("%s", __func__);
2069
2070
	return (0);
2071
}
2072
2073
/* Close UTF-8 string. */
2074
static int
2075
input_utf8_close(struct input_ctx *ictx)
2076
{
2077
	struct utf8_data	*ud = &ictx->utf8data;
2078
2079
	if (utf8_append(ud, ictx->ch) != UTF8_DONE) {
2080
		/*
2081
		 * An error here could be invalid UTF-8 or it could be a
2082
		 * nonprintable character for which we can't get the
2083
		 * width. Drop it.
2084
		 */
2085
		return (0);
2086
	}
2087
2088
	log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
2089
	    (int)ud->size, ud->data, ud->width);
2090
2091
	utf8_copy(&ictx->cell.cell.data, ud);
2092
	screen_write_collect_add(&ictx->ctx, &ictx->cell.cell);
2093
2094
	return (0);
2095
}
2096
2097
/* Handle the OSC 4 sequence for setting (multiple) palette entries. */
2098
static void
2099
input_osc_4(struct window_pane *wp, const char *p)
2100
{
2101
	char	*copy, *s, *next = NULL;
2102
	long	 idx;
2103
	u_int	 r, g, b;
2104
2105
	copy = s = xstrdup(p);
2106
	while (s != NULL && *s != '\0') {
2107
		idx = strtol(s, &next, 10);
2108
		if (*next++ != ';')
2109
			goto bad;
2110
		if (idx < 0 || idx >= 0x100)
2111
			goto bad;
2112
2113
		s = strsep(&next, ";");
2114
		if (sscanf(s, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) {
2115
			s = next;
2116
			continue;
2117
		}
2118
2119
		window_pane_set_palette(wp, idx, colour_join_rgb(r, g, b));
2120
		s = next;
2121
	}
2122
2123
	free(copy);
2124
	return;
2125
2126
bad:
2127
	log_debug("bad OSC 4: %s", p);
2128
	free(copy);
2129
}
2130
2131
/* Handle the OSC 10 sequence for setting background colour. */
2132
static void
2133
input_osc_10(struct window_pane *wp, const char *p)
2134
{
2135
	u_int	 r, g, b;
2136
2137
	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2138
	    goto bad;
2139
2140
	wp->colgc.fg = colour_join_rgb(r, g, b);
2141
	wp->flags |= PANE_REDRAW;
2142
2143
	return;
2144
2145
bad:
2146
	log_debug("bad OSC 10: %s", p);
2147
}
2148
2149
/* Handle the OSC 11 sequence for setting background colour. */
2150
static void
2151
input_osc_11(struct window_pane *wp, const char *p)
2152
{
2153
	u_int	 r, g, b;
2154
2155
	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2156
	    goto bad;
2157
2158
	wp->colgc.bg = colour_join_rgb(r, g, b);
2159
	wp->flags |= PANE_REDRAW;
2160
2161
	return;
2162
2163
bad:
2164
	log_debug("bad OSC 11: %s", p);
2165
}
2166
2167
/* Handle the OSC 52 sequence for setting the clipboard. */
2168
static void
2169
input_osc_52(struct window_pane *wp, const char *p)
2170
{
2171
	char			*end;
2172
	size_t			 len;
2173
	u_char			*out;
2174
	int			 outlen, state;
2175
	struct screen_write_ctx	 ctx;
2176
2177
	state = options_get_number(global_options, "set-clipboard");
2178
	if (state != 2)
2179
		return;
2180
2181
	if ((end = strchr(p, ';')) == NULL)
2182
		return;
2183
	end++;
2184
	if (*end == '\0')
2185
		return;
2186
2187
	len = (strlen(end) / 4) * 3;
2188
	if (len == 0)
2189
		return;
2190
2191
	out = xmalloc(len);
2192
	if ((outlen = b64_pton(end, out, len)) == -1) {
2193
		free(out);
2194
		return;
2195
	}
2196
2197
	screen_write_start(&ctx, wp, NULL);
2198
	screen_write_setselection(&ctx, out, outlen);
2199
	screen_write_stop(&ctx);
2200
	notify_pane("pane-set-clipboard", wp);
2201
2202
	paste_add(out, outlen);
2203
}
2204
2205
/* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
2206
static void
2207
input_osc_104(struct window_pane *wp, const char *p)
2208
{
2209
	char	*copy, *s;
2210
	long	idx;
2211
2212
	if (*p == '\0') {
2213
		window_pane_reset_palette(wp);
2214
		return;
2215
	}
2216
2217
	copy = s = xstrdup(p);
2218
	while (*s != '\0') {
2219
		idx = strtol(s, &s, 10);
2220
		if (*s != '\0' && *s != ';')
2221
			goto bad;
2222
		if (idx < 0 || idx >= 0x100)
2223
			goto bad;
2224
2225
		window_pane_unset_palette(wp, idx);
2226
		if (*s == ';')
2227
			s++;
2228
	}
2229
	free(copy);
2230
	return;
2231
2232
bad:
2233
	log_debug("bad OSC 104: %s", p);
2234
	free(copy);
2235
}