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