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