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