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