input.c revision 1.143
1/* $OpenBSD: input.c,v 1.143 2019/03/12 12:58:40 nicm Exp $ */
2
3/*
4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <netinet/in.h>
22
23#include <resolv.h>
24#include <stdlib.h>
25#include <string.h>
26#include <time.h>
27
28#include "tmux.h"
29
30/*
31 * Based on the description by Paul Williams at:
32 *
33 * https://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 argument. */
62struct input_param {
63	enum {
64		INPUT_MISSING,
65		INPUT_NUMBER,
66		INPUT_STRING
67	}                       type;
68	union {
69		int		num;
70		char	       *str;
71	};
72};
73
74/* Input parser context. */
75struct input_ctx {
76	struct window_pane     *wp;
77	struct screen_write_ctx ctx;
78
79	struct input_cell	cell;
80
81	struct input_cell	old_cell;
82	u_int 			old_cx;
83	u_int			old_cy;
84
85	u_char			interm_buf[4];
86	size_t			interm_len;
87
88	u_char			param_buf[64];
89	size_t			param_len;
90
91#define INPUT_BUF_START 32
92#define INPUT_BUF_LIMIT 1048576
93	u_char		       *input_buf;
94	size_t			input_len;
95	size_t			input_space;
96	enum {
97		INPUT_END_ST,
98		INPUT_END_BEL
99	}			input_end;
100
101	struct input_param	param_list[24];
102	u_int			param_list_len;
103
104	struct utf8_data	utf8data;
105	int			utf8started;
106
107	int			ch;
108	int			last;
109
110	int			flags;
111#define INPUT_DISCARD 0x1
112
113	const struct input_state *state;
114
115	struct event		timer;
116
117	/*
118	 * All input received since we were last in the ground state. Sent to
119	 * control clients on connection.
120	 */
121	struct evbuffer	 	*since_ground;
122};
123
124/* Helper functions. */
125struct input_transition;
126static int	input_split(struct input_ctx *);
127static int	input_get(struct input_ctx *, u_int, int, int);
128static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
129static void	input_set_state(struct window_pane *,
130		    const struct input_transition *);
131static void	input_reset_cell(struct input_ctx *);
132
133static void	input_osc_4(struct input_ctx *, const char *);
134static void	input_osc_10(struct input_ctx *, const char *);
135static void	input_osc_11(struct input_ctx *, const char *);
136static void	input_osc_52(struct input_ctx *, const char *);
137static void	input_osc_104(struct input_ctx *, const char *);
138
139/* Transition entry/exit handlers. */
140static void	input_clear(struct input_ctx *);
141static void	input_ground(struct input_ctx *);
142static void	input_enter_dcs(struct input_ctx *);
143static void	input_enter_osc(struct input_ctx *);
144static void	input_exit_osc(struct input_ctx *);
145static void	input_enter_apc(struct input_ctx *);
146static void	input_exit_apc(struct input_ctx *);
147static void	input_enter_rename(struct input_ctx *);
148static void	input_exit_rename(struct input_ctx *);
149
150/* Input state handlers. */
151static int	input_print(struct input_ctx *);
152static int	input_intermediate(struct input_ctx *);
153static int	input_parameter(struct input_ctx *);
154static int	input_input(struct input_ctx *);
155static int	input_c0_dispatch(struct input_ctx *);
156static int	input_esc_dispatch(struct input_ctx *);
157static int	input_csi_dispatch(struct input_ctx *);
158static void	input_csi_dispatch_rm(struct input_ctx *);
159static void	input_csi_dispatch_rm_private(struct input_ctx *);
160static void	input_csi_dispatch_sm(struct input_ctx *);
161static void	input_csi_dispatch_sm_private(struct input_ctx *);
162static void	input_csi_dispatch_winops(struct input_ctx *);
163static void	input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
164static void	input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
165static void	input_csi_dispatch_sgr(struct input_ctx *);
166static int	input_dcs_dispatch(struct input_ctx *);
167static int	input_top_bit_set(struct input_ctx *);
168static int	input_end_bel(struct input_ctx *);
169
170/* Command table comparison function. */
171static int	input_table_compare(const void *, const void *);
172
173/* Command table entry. */
174struct input_table_entry {
175	int		ch;
176	const char     *interm;
177	int		type;
178};
179
180/* Escape commands. */
181enum input_esc_type {
182	INPUT_ESC_DECALN,
183	INPUT_ESC_DECKPAM,
184	INPUT_ESC_DECKPNM,
185	INPUT_ESC_DECRC,
186	INPUT_ESC_DECSC,
187	INPUT_ESC_HTS,
188	INPUT_ESC_IND,
189	INPUT_ESC_NEL,
190	INPUT_ESC_RI,
191	INPUT_ESC_RIS,
192	INPUT_ESC_SCSG0_OFF,
193	INPUT_ESC_SCSG0_ON,
194	INPUT_ESC_SCSG1_OFF,
195	INPUT_ESC_SCSG1_ON,
196	INPUT_ESC_ST,
197};
198
199/* Escape command table. */
200static const struct input_table_entry input_esc_table[] = {
201	{ '0', "(", INPUT_ESC_SCSG0_ON },
202	{ '0', ")", INPUT_ESC_SCSG1_ON },
203	{ '7', "",  INPUT_ESC_DECSC },
204	{ '8', "",  INPUT_ESC_DECRC },
205	{ '8', "#", INPUT_ESC_DECALN },
206	{ '=', "",  INPUT_ESC_DECKPAM },
207	{ '>', "",  INPUT_ESC_DECKPNM },
208	{ 'B', "(", INPUT_ESC_SCSG0_OFF },
209	{ 'B', ")", INPUT_ESC_SCSG1_OFF },
210	{ 'D', "",  INPUT_ESC_IND },
211	{ 'E', "",  INPUT_ESC_NEL },
212	{ 'H', "",  INPUT_ESC_HTS },
213	{ 'M', "",  INPUT_ESC_RI },
214	{ '\\', "", INPUT_ESC_ST },
215	{ 'c', "",  INPUT_ESC_RIS },
216};
217
218/* Control (CSI) commands. */
219enum input_csi_type {
220	INPUT_CSI_CBT,
221	INPUT_CSI_CNL,
222	INPUT_CSI_CPL,
223	INPUT_CSI_CUB,
224	INPUT_CSI_CUD,
225	INPUT_CSI_CUF,
226	INPUT_CSI_CUP,
227	INPUT_CSI_CUU,
228	INPUT_CSI_DA,
229	INPUT_CSI_DA_TWO,
230	INPUT_CSI_DCH,
231	INPUT_CSI_DECSCUSR,
232	INPUT_CSI_DECSTBM,
233	INPUT_CSI_DL,
234	INPUT_CSI_DSR,
235	INPUT_CSI_ECH,
236	INPUT_CSI_ED,
237	INPUT_CSI_EL,
238	INPUT_CSI_HPA,
239	INPUT_CSI_ICH,
240	INPUT_CSI_IL,
241	INPUT_CSI_RCP,
242	INPUT_CSI_REP,
243	INPUT_CSI_RM,
244	INPUT_CSI_RM_PRIVATE,
245	INPUT_CSI_SCP,
246	INPUT_CSI_SGR,
247	INPUT_CSI_SM,
248	INPUT_CSI_SM_PRIVATE,
249	INPUT_CSI_SU,
250	INPUT_CSI_TBC,
251	INPUT_CSI_VPA,
252	INPUT_CSI_WINOPS,
253};
254
255/* Control (CSI) command table. */
256static const struct input_table_entry input_csi_table[] = {
257	{ '@', "",  INPUT_CSI_ICH },
258	{ 'A', "",  INPUT_CSI_CUU },
259	{ 'B', "",  INPUT_CSI_CUD },
260	{ 'C', "",  INPUT_CSI_CUF },
261	{ 'D', "",  INPUT_CSI_CUB },
262	{ 'E', "",  INPUT_CSI_CNL },
263	{ 'F', "",  INPUT_CSI_CPL },
264	{ 'G', "",  INPUT_CSI_HPA },
265	{ 'H', "",  INPUT_CSI_CUP },
266	{ 'J', "",  INPUT_CSI_ED },
267	{ 'K', "",  INPUT_CSI_EL },
268	{ 'L', "",  INPUT_CSI_IL },
269	{ 'M', "",  INPUT_CSI_DL },
270	{ 'P', "",  INPUT_CSI_DCH },
271	{ 'S', "",  INPUT_CSI_SU },
272	{ 'X', "",  INPUT_CSI_ECH },
273	{ 'Z', "",  INPUT_CSI_CBT },
274	{ 'b', "",  INPUT_CSI_REP },
275	{ 'c', "",  INPUT_CSI_DA },
276	{ 'c', ">", INPUT_CSI_DA_TWO },
277	{ 'd', "",  INPUT_CSI_VPA },
278	{ 'f', "",  INPUT_CSI_CUP },
279	{ 'g', "",  INPUT_CSI_TBC },
280	{ 'h', "",  INPUT_CSI_SM },
281	{ 'h', "?", INPUT_CSI_SM_PRIVATE },
282	{ 'l', "",  INPUT_CSI_RM },
283	{ 'l', "?", INPUT_CSI_RM_PRIVATE },
284	{ 'm', "",  INPUT_CSI_SGR },
285	{ 'n', "",  INPUT_CSI_DSR },
286	{ 'q', " ", INPUT_CSI_DECSCUSR },
287	{ 'r', "",  INPUT_CSI_DECSTBM },
288	{ 's', "",  INPUT_CSI_SCP },
289	{ 't', "",  INPUT_CSI_WINOPS },
290	{ 'u', "",  INPUT_CSI_RCP },
291};
292
293/* Input transition. */
294struct input_transition {
295	int				first;
296	int				last;
297
298	int				(*handler)(struct input_ctx *);
299	const struct input_state       *state;
300};
301
302/* Input state. */
303struct input_state {
304	const char			*name;
305	void				(*enter)(struct input_ctx *);
306	void				(*exit)(struct input_ctx *);
307	const struct input_transition	*transitions;
308};
309
310/* State transitions available from all states. */
311#define INPUT_STATE_ANYWHERE \
312	{ 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
313	{ 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
314	{ 0x1b, 0x1b, NULL,		 &input_state_esc_enter }
315
316/* Forward declarations of state tables. */
317static const struct input_transition input_state_ground_table[];
318static const struct input_transition input_state_esc_enter_table[];
319static const struct input_transition input_state_esc_intermediate_table[];
320static const struct input_transition input_state_csi_enter_table[];
321static const struct input_transition input_state_csi_parameter_table[];
322static const struct input_transition input_state_csi_intermediate_table[];
323static const struct input_transition input_state_csi_ignore_table[];
324static const struct input_transition input_state_dcs_enter_table[];
325static const struct input_transition input_state_dcs_parameter_table[];
326static const struct input_transition input_state_dcs_intermediate_table[];
327static const struct input_transition input_state_dcs_handler_table[];
328static const struct input_transition input_state_dcs_escape_table[];
329static const struct input_transition input_state_dcs_ignore_table[];
330static const struct input_transition input_state_osc_string_table[];
331static const struct input_transition input_state_apc_string_table[];
332static const struct input_transition input_state_rename_string_table[];
333static const struct input_transition input_state_consume_st_table[];
334
335/* ground state definition. */
336static const struct input_state input_state_ground = {
337	"ground",
338	input_ground, NULL,
339	input_state_ground_table
340};
341
342/* esc_enter state definition. */
343static const struct input_state input_state_esc_enter = {
344	"esc_enter",
345	input_clear, NULL,
346	input_state_esc_enter_table
347};
348
349/* esc_intermediate state definition. */
350static const struct input_state input_state_esc_intermediate = {
351	"esc_intermediate",
352	NULL, NULL,
353	input_state_esc_intermediate_table
354};
355
356/* csi_enter state definition. */
357static const struct input_state input_state_csi_enter = {
358	"csi_enter",
359	input_clear, NULL,
360	input_state_csi_enter_table
361};
362
363/* csi_parameter state definition. */
364static const struct input_state input_state_csi_parameter = {
365	"csi_parameter",
366	NULL, NULL,
367	input_state_csi_parameter_table
368};
369
370/* csi_intermediate state definition. */
371static const struct input_state input_state_csi_intermediate = {
372	"csi_intermediate",
373	NULL, NULL,
374	input_state_csi_intermediate_table
375};
376
377/* csi_ignore state definition. */
378static const struct input_state input_state_csi_ignore = {
379	"csi_ignore",
380	NULL, NULL,
381	input_state_csi_ignore_table
382};
383
384/* dcs_enter state definition. */
385static const struct input_state input_state_dcs_enter = {
386	"dcs_enter",
387	input_enter_dcs, NULL,
388	input_state_dcs_enter_table
389};
390
391/* dcs_parameter state definition. */
392static const struct input_state input_state_dcs_parameter = {
393	"dcs_parameter",
394	NULL, NULL,
395	input_state_dcs_parameter_table
396};
397
398/* dcs_intermediate state definition. */
399static const struct input_state input_state_dcs_intermediate = {
400	"dcs_intermediate",
401	NULL, NULL,
402	input_state_dcs_intermediate_table
403};
404
405/* dcs_handler state definition. */
406static const struct input_state input_state_dcs_handler = {
407	"dcs_handler",
408	NULL, NULL,
409	input_state_dcs_handler_table
410};
411
412/* dcs_escape state definition. */
413static const struct input_state input_state_dcs_escape = {
414	"dcs_escape",
415	NULL, NULL,
416	input_state_dcs_escape_table
417};
418
419/* dcs_ignore state definition. */
420static const struct input_state input_state_dcs_ignore = {
421	"dcs_ignore",
422	NULL, NULL,
423	input_state_dcs_ignore_table
424};
425
426/* osc_string state definition. */
427static const struct input_state input_state_osc_string = {
428	"osc_string",
429	input_enter_osc, input_exit_osc,
430	input_state_osc_string_table
431};
432
433/* apc_string state definition. */
434static const struct input_state input_state_apc_string = {
435	"apc_string",
436	input_enter_apc, input_exit_apc,
437	input_state_apc_string_table
438};
439
440/* rename_string state definition. */
441static const struct input_state input_state_rename_string = {
442	"rename_string",
443	input_enter_rename, input_exit_rename,
444	input_state_rename_string_table
445};
446
447/* consume_st state definition. */
448static const struct input_state input_state_consume_st = {
449	"consume_st",
450	input_enter_rename, NULL, /* rename also waits for ST */
451	input_state_consume_st_table
452};
453
454/* ground state table. */
455static const struct input_transition input_state_ground_table[] = {
456	INPUT_STATE_ANYWHERE,
457
458	{ 0x00, 0x17, input_c0_dispatch, NULL },
459	{ 0x19, 0x19, input_c0_dispatch, NULL },
460	{ 0x1c, 0x1f, input_c0_dispatch, NULL },
461	{ 0x20, 0x7e, input_print,	 NULL },
462	{ 0x7f, 0x7f, NULL,		 NULL },
463	{ 0x80, 0xff, input_top_bit_set, 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_intermediate 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, input_parameter,	  &input_state_csi_parameter },
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, input_parameter,	  NULL },
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_intermediate 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, input_end_bel, &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/* Input table compare. */
710static int
711input_table_compare(const void *key, const void *value)
712{
713	const struct input_ctx		*ictx = key;
714	const struct input_table_entry	*entry = value;
715
716	if (ictx->ch != entry->ch)
717		return (ictx->ch - entry->ch);
718	return (strcmp(ictx->interm_buf, entry->interm));
719}
720
721/*
722 * Timer - if this expires then have been waiting for a terminator for too
723 * long, so reset to ground.
724 */
725static void
726input_timer_callback(__unused int fd, __unused short events, void *arg)
727{
728	struct input_ctx	*ictx = arg;
729	struct window_pane	*wp = ictx->wp;
730
731	log_debug("%s: %%%u %s expired" , __func__, wp->id, ictx->state->name);
732	input_reset(wp, 0);
733}
734
735/* Start the timer. */
736static void
737input_start_timer(struct input_ctx *ictx)
738{
739	struct timeval	tv = { .tv_usec = 100000 };
740
741	event_del(&ictx->timer);
742	event_add(&ictx->timer, &tv);
743}
744
745/* Reset cell state to default. */
746static void
747input_reset_cell(struct input_ctx *ictx)
748{
749	memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell);
750	ictx->cell.set = 0;
751	ictx->cell.g0set = ictx->cell.g1set = 0;
752
753	memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
754	ictx->old_cx = 0;
755	ictx->old_cy = 0;
756}
757
758/* Initialise input parser. */
759void
760input_init(struct window_pane *wp)
761{
762	struct input_ctx	*ictx;
763
764	ictx = wp->ictx = xcalloc(1, sizeof *ictx);
765
766	ictx->input_space = INPUT_BUF_START;
767	ictx->input_buf = xmalloc(INPUT_BUF_START);
768
769	ictx->since_ground = evbuffer_new();
770	if (ictx->since_ground == NULL)
771		fatalx("out of memory");
772
773	evtimer_set(&ictx->timer, input_timer_callback, ictx);
774
775	input_reset(wp, 0);
776}
777
778/* Destroy input parser. */
779void
780input_free(struct window_pane *wp)
781{
782	struct input_ctx	*ictx = wp->ictx;
783	u_int			 i;
784
785	for (i = 0; i < ictx->param_list_len; i++) {
786		if (ictx->param_list[i].type == INPUT_STRING)
787			free(ictx->param_list[i].str);
788	}
789
790	event_del(&ictx->timer);
791
792	free(ictx->input_buf);
793	evbuffer_free(ictx->since_ground);
794
795	free(ictx);
796	wp->ictx = NULL;
797}
798
799/* Reset input state and clear screen. */
800void
801input_reset(struct window_pane *wp, int clear)
802{
803	struct input_ctx	*ictx = wp->ictx;
804
805	input_reset_cell(ictx);
806
807	if (clear) {
808		if (TAILQ_EMPTY(&wp->modes))
809			screen_write_start(&ictx->ctx, wp, &wp->base);
810		else
811			screen_write_start(&ictx->ctx, NULL, &wp->base);
812		screen_write_reset(&ictx->ctx);
813		screen_write_stop(&ictx->ctx);
814	}
815
816	input_clear(ictx);
817
818	ictx->last = -1;
819
820	ictx->state = &input_state_ground;
821	ictx->flags = 0;
822}
823
824/* Return pending data. */
825struct evbuffer *
826input_pending(struct window_pane *wp)
827{
828	return (wp->ictx->since_ground);
829}
830
831/* Change input state. */
832static void
833input_set_state(struct window_pane *wp, const struct input_transition *itr)
834{
835	struct input_ctx	*ictx = wp->ictx;
836
837	if (ictx->state->exit != NULL)
838		ictx->state->exit(ictx);
839	ictx->state = itr->state;
840	if (ictx->state->enter != NULL)
841		ictx->state->enter(ictx);
842}
843
844/* Parse input. */
845void
846input_parse(struct window_pane *wp)
847{
848	struct input_ctx		*ictx = wp->ictx;
849	const struct input_transition	*itr;
850	struct evbuffer			*evb = wp->event->input;
851	u_char				*buf;
852	size_t				 len, off;
853
854	if (EVBUFFER_LENGTH(evb) == 0)
855		return;
856
857	window_update_activity(wp->window);
858	wp->flags |= PANE_CHANGED;
859
860	/*
861	 * Open the screen. Use NULL wp if there is a mode set as don't want to
862	 * update the tty.
863	 */
864	if (TAILQ_EMPTY(&wp->modes))
865		screen_write_start(&ictx->ctx, wp, &wp->base);
866	else
867		screen_write_start(&ictx->ctx, NULL, &wp->base);
868	ictx->wp = wp;
869
870	buf = EVBUFFER_DATA(evb);
871	len = EVBUFFER_LENGTH(evb);
872	off = 0;
873
874	notify_input(wp, evb);
875
876	log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
877	    ictx->state->name, len, (int)len, buf);
878
879	/* Parse the input. */
880	while (off < len) {
881		ictx->ch = buf[off++];
882
883		/* Find the transition. */
884		itr = ictx->state->transitions;
885		while (itr->first != -1 && itr->last != -1) {
886			if (ictx->ch >= itr->first && ictx->ch <= itr->last)
887				break;
888			itr++;
889		}
890		if (itr->first == -1 || itr->last == -1) {
891			/* No transition? Eh? */
892			fatalx("no transition from state");
893		}
894
895		/*
896		 * Any state except print stops the current collection. This is
897		 * an optimization to avoid checking if the attributes have
898		 * changed for every character. It will stop unnecessarily for
899		 * sequences that don't make a terminal change, but they should
900		 * be the minority.
901		 */
902		if (itr->handler != input_print)
903			screen_write_collect_end(&ictx->ctx);
904
905		/*
906		 * Execute the handler, if any. Don't switch state if it
907		 * returns non-zero.
908		 */
909		if (itr->handler != NULL && itr->handler(ictx) != 0)
910			continue;
911
912		/* And switch state, if necessary. */
913		if (itr->state != NULL)
914			input_set_state(wp, itr);
915
916		/* If not in ground state, save input. */
917		if (ictx->state != &input_state_ground)
918			evbuffer_add(ictx->since_ground, &ictx->ch, 1);
919	}
920
921	/* Close the screen. */
922	screen_write_stop(&ictx->ctx);
923
924	evbuffer_drain(evb, len);
925}
926
927/* Split the parameter list (if any). */
928static int
929input_split(struct input_ctx *ictx)
930{
931	const char		*errstr;
932	char			*ptr, *out;
933	struct input_param	*ip;
934	u_int			 i;
935
936	for (i = 0; i < ictx->param_list_len; i++) {
937		if (ictx->param_list[i].type == INPUT_STRING)
938			free(ictx->param_list[i].str);
939	}
940	ictx->param_list_len = 0;
941
942	if (ictx->param_len == 0)
943		return (0);
944	ip = &ictx->param_list[0];
945
946	ptr = ictx->param_buf;
947	while ((out = strsep(&ptr, ";")) != NULL) {
948		if (*out == '\0')
949			ip->type = INPUT_MISSING;
950		else {
951			if (strchr(out, ':') != NULL) {
952				ip->type = INPUT_STRING;
953				ip->str = xstrdup(out);
954			} else {
955				ip->type = INPUT_NUMBER;
956				ip->num = strtonum(out, 0, INT_MAX, &errstr);
957				if (errstr != NULL)
958					return (-1);
959			}
960		}
961		ip = &ictx->param_list[++ictx->param_list_len];
962		if (ictx->param_list_len == nitems(ictx->param_list))
963			return (-1);
964	}
965
966	for (i = 0; i < ictx->param_list_len; i++) {
967		ip = &ictx->param_list[i];
968		if (ip->type == INPUT_MISSING)
969			log_debug("parameter %u: missing", i);
970		else if (ip->type == INPUT_STRING)
971			log_debug("parameter %u: string %s", i, ip->str);
972		else if (ip->type == INPUT_NUMBER)
973			log_debug("parameter %u: number %d", i, ip->num);
974	}
975
976	return (0);
977}
978
979/* Get an argument or return default value. */
980static int
981input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
982{
983	struct input_param	*ip;
984	int			 retval;
985
986	if (validx >= ictx->param_list_len)
987	    return (defval);
988	ip = &ictx->param_list[validx];
989	if (ip->type == INPUT_MISSING)
990		return (defval);
991	if (ip->type == INPUT_STRING)
992		return (-1);
993	retval = ip->num;
994	if (retval < minval)
995		return (minval);
996	return (retval);
997}
998
999/* Reply to terminal query. */
1000static void
1001input_reply(struct input_ctx *ictx, const char *fmt, ...)
1002{
1003	va_list	 ap;
1004	char	*reply;
1005
1006	va_start(ap, fmt);
1007	xvasprintf(&reply, fmt, ap);
1008	va_end(ap);
1009
1010	bufferevent_write(ictx->wp->event, reply, strlen(reply));
1011	free(reply);
1012}
1013
1014/* Clear saved state. */
1015static void
1016input_clear(struct input_ctx *ictx)
1017{
1018	event_del(&ictx->timer);
1019
1020	*ictx->interm_buf = '\0';
1021	ictx->interm_len = 0;
1022
1023	*ictx->param_buf = '\0';
1024	ictx->param_len = 0;
1025
1026	*ictx->input_buf = '\0';
1027	ictx->input_len = 0;
1028
1029	ictx->input_end = INPUT_END_ST;
1030
1031	ictx->flags &= ~INPUT_DISCARD;
1032}
1033
1034/* Reset for ground state. */
1035static void
1036input_ground(struct input_ctx *ictx)
1037{
1038	event_del(&ictx->timer);
1039	evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
1040
1041	if (ictx->input_space > INPUT_BUF_START) {
1042		ictx->input_space = INPUT_BUF_START;
1043		ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START);
1044	}
1045}
1046
1047/* Output this character to the screen. */
1048static int
1049input_print(struct input_ctx *ictx)
1050{
1051	int	set;
1052
1053	ictx->utf8started = 0; /* can't be valid UTF-8 */
1054
1055	set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
1056	if (set == 1)
1057		ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
1058	else
1059		ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1060
1061	utf8_set(&ictx->cell.cell.data, ictx->ch);
1062	screen_write_collect_add(&ictx->ctx, &ictx->cell.cell);
1063	ictx->last = ictx->ch;
1064
1065	ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1066
1067	return (0);
1068}
1069
1070/* Collect intermediate string. */
1071static int
1072input_intermediate(struct input_ctx *ictx)
1073{
1074	if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
1075		ictx->flags |= INPUT_DISCARD;
1076	else {
1077		ictx->interm_buf[ictx->interm_len++] = ictx->ch;
1078		ictx->interm_buf[ictx->interm_len] = '\0';
1079	}
1080
1081	return (0);
1082}
1083
1084/* Collect parameter string. */
1085static int
1086input_parameter(struct input_ctx *ictx)
1087{
1088	if (ictx->param_len == (sizeof ictx->param_buf) - 1)
1089		ictx->flags |= INPUT_DISCARD;
1090	else {
1091		ictx->param_buf[ictx->param_len++] = ictx->ch;
1092		ictx->param_buf[ictx->param_len] = '\0';
1093	}
1094
1095	return (0);
1096}
1097
1098/* Collect input string. */
1099static int
1100input_input(struct input_ctx *ictx)
1101{
1102	size_t available;
1103
1104	available = ictx->input_space;
1105	while (ictx->input_len + 1 >= available) {
1106		available *= 2;
1107		if (available > INPUT_BUF_LIMIT) {
1108			ictx->flags |= INPUT_DISCARD;
1109			return (0);
1110		}
1111		ictx->input_buf = xrealloc(ictx->input_buf, available);
1112		ictx->input_space = available;
1113	}
1114	ictx->input_buf[ictx->input_len++] = ictx->ch;
1115	ictx->input_buf[ictx->input_len] = '\0';
1116
1117	return (0);
1118}
1119
1120/* Execute C0 control sequence. */
1121static int
1122input_c0_dispatch(struct input_ctx *ictx)
1123{
1124	struct screen_write_ctx	*sctx = &ictx->ctx;
1125	struct window_pane	*wp = ictx->wp;
1126	struct screen		*s = sctx->s;
1127
1128	ictx->utf8started = 0; /* can't be valid UTF-8 */
1129
1130	log_debug("%s: '%c'", __func__, ictx->ch);
1131
1132	switch (ictx->ch) {
1133	case '\000':	/* NUL */
1134		break;
1135	case '\007':	/* BEL */
1136		alerts_queue(wp->window, WINDOW_BELL);
1137		break;
1138	case '\010':	/* BS */
1139		screen_write_backspace(sctx);
1140		break;
1141	case '\011':	/* HT */
1142		/* Don't tab beyond the end of the line. */
1143		if (s->cx >= screen_size_x(s) - 1)
1144			break;
1145
1146		/* Find the next tab point, or use the last column if none. */
1147		do {
1148			s->cx++;
1149			if (bit_test(s->tabs, s->cx))
1150				break;
1151		} while (s->cx < screen_size_x(s) - 1);
1152		break;
1153	case '\012':	/* LF */
1154	case '\013':	/* VT */
1155	case '\014':	/* FF */
1156		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1157		break;
1158	case '\015':	/* CR */
1159		screen_write_carriagereturn(sctx);
1160		break;
1161	case '\016':	/* SO */
1162		ictx->cell.set = 1;
1163		break;
1164	case '\017':	/* SI */
1165		ictx->cell.set = 0;
1166		break;
1167	default:
1168		log_debug("%s: unknown '%c'", __func__, ictx->ch);
1169		break;
1170	}
1171
1172	ictx->last = -1;
1173	return (0);
1174}
1175
1176/* Execute escape sequence. */
1177static int
1178input_esc_dispatch(struct input_ctx *ictx)
1179{
1180	struct screen_write_ctx		*sctx = &ictx->ctx;
1181	struct screen			*s = sctx->s;
1182	struct input_table_entry	*entry;
1183
1184	if (ictx->flags & INPUT_DISCARD)
1185		return (0);
1186	log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1187
1188	entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
1189	    sizeof input_esc_table[0], input_table_compare);
1190	if (entry == NULL) {
1191		log_debug("%s: unknown '%c'", __func__, ictx->ch);
1192		return (0);
1193	}
1194
1195	switch (entry->type) {
1196	case INPUT_ESC_RIS:
1197		window_pane_reset_palette(ictx->wp);
1198		input_reset_cell(ictx);
1199		screen_write_reset(sctx);
1200		break;
1201	case INPUT_ESC_IND:
1202		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1203		break;
1204	case INPUT_ESC_NEL:
1205		screen_write_carriagereturn(sctx);
1206		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1207		break;
1208	case INPUT_ESC_HTS:
1209		if (s->cx < screen_size_x(s))
1210			bit_set(s->tabs, s->cx);
1211		break;
1212	case INPUT_ESC_RI:
1213		screen_write_reverseindex(sctx, ictx->cell.cell.bg);
1214		break;
1215	case INPUT_ESC_DECKPAM:
1216		screen_write_mode_set(sctx, MODE_KKEYPAD);
1217		break;
1218	case INPUT_ESC_DECKPNM:
1219		screen_write_mode_clear(sctx, MODE_KKEYPAD);
1220		break;
1221	case INPUT_ESC_DECSC:
1222		memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1223		ictx->old_cx = s->cx;
1224		ictx->old_cy = s->cy;
1225		break;
1226	case INPUT_ESC_DECRC:
1227		memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1228		screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1229		break;
1230	case INPUT_ESC_DECALN:
1231		screen_write_alignmenttest(sctx);
1232		break;
1233	case INPUT_ESC_SCSG0_ON:
1234		ictx->cell.g0set = 1;
1235		break;
1236	case INPUT_ESC_SCSG0_OFF:
1237		ictx->cell.g0set = 0;
1238		break;
1239	case INPUT_ESC_SCSG1_ON:
1240		ictx->cell.g1set = 1;
1241		break;
1242	case INPUT_ESC_SCSG1_OFF:
1243		ictx->cell.g1set = 0;
1244		break;
1245	case INPUT_ESC_ST:
1246		/* ST terminates OSC but the state transition already did it. */
1247		break;
1248	}
1249
1250	ictx->last = -1;
1251	return (0);
1252}
1253
1254/* Execute control sequence. */
1255static int
1256input_csi_dispatch(struct input_ctx *ictx)
1257{
1258	struct screen_write_ctx	       *sctx = &ictx->ctx;
1259	struct screen		       *s = sctx->s;
1260	struct input_table_entry       *entry;
1261	int				i, n, m;
1262	u_int				cx, bg = ictx->cell.cell.bg;
1263
1264	if (ictx->flags & INPUT_DISCARD)
1265		return (0);
1266
1267	log_debug("%s: '%c' \"%s\" \"%s\"",
1268	    __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1269
1270	if (input_split(ictx) != 0)
1271		return (0);
1272
1273	entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1274	    sizeof input_csi_table[0], input_table_compare);
1275	if (entry == NULL) {
1276		log_debug("%s: unknown '%c'", __func__, ictx->ch);
1277		return (0);
1278	}
1279
1280	switch (entry->type) {
1281	case INPUT_CSI_CBT:
1282		/* Find the previous tab point, n times. */
1283		cx = s->cx;
1284		if (cx > screen_size_x(s) - 1)
1285			cx = screen_size_x(s) - 1;
1286		n = input_get(ictx, 0, 1, 1);
1287		if (n == -1)
1288			break;
1289		while (cx > 0 && n-- > 0) {
1290			do
1291				cx--;
1292			while (cx > 0 && !bit_test(s->tabs, cx));
1293		}
1294		s->cx = cx;
1295		break;
1296	case INPUT_CSI_CUB:
1297		n = input_get(ictx, 0, 1, 1);
1298		if (n != -1)
1299			screen_write_cursorleft(sctx, n);
1300		break;
1301	case INPUT_CSI_CUD:
1302		n = input_get(ictx, 0, 1, 1);
1303		if (n != -1)
1304			screen_write_cursordown(sctx, n);
1305		break;
1306	case INPUT_CSI_CUF:
1307		n = input_get(ictx, 0, 1, 1);
1308		if (n != -1)
1309			screen_write_cursorright(sctx, n);
1310		break;
1311	case INPUT_CSI_CUP:
1312		n = input_get(ictx, 0, 1, 1);
1313		m = input_get(ictx, 1, 1, 1);
1314		if (n != -1 && m != -1)
1315			screen_write_cursormove(sctx, m - 1, n - 1);
1316		break;
1317	case INPUT_CSI_WINOPS:
1318		input_csi_dispatch_winops(ictx);
1319		break;
1320	case INPUT_CSI_CUU:
1321		n = input_get(ictx, 0, 1, 1);
1322		if (n != -1)
1323			screen_write_cursorup(sctx, n);
1324		break;
1325	case INPUT_CSI_CNL:
1326		n = input_get(ictx, 0, 1, 1);
1327		if (n != -1) {
1328			screen_write_carriagereturn(sctx);
1329			screen_write_cursordown(sctx, n);
1330		}
1331		break;
1332	case INPUT_CSI_CPL:
1333		n = input_get(ictx, 0, 1, 1);
1334		if (n != -1) {
1335			screen_write_carriagereturn(sctx);
1336			screen_write_cursorup(sctx, n);
1337		}
1338		break;
1339	case INPUT_CSI_DA:
1340		switch (input_get(ictx, 0, 0, 0)) {
1341		case -1:
1342			break;
1343		case 0:
1344			input_reply(ictx, "\033[?1;2c");
1345			break;
1346		default:
1347			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1348			break;
1349		}
1350		break;
1351	case INPUT_CSI_DA_TWO:
1352		switch (input_get(ictx, 0, 0, 0)) {
1353		case -1:
1354			break;
1355		case 0:
1356			input_reply(ictx, "\033[>84;0;0c");
1357			break;
1358		default:
1359			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1360			break;
1361		}
1362		break;
1363	case INPUT_CSI_ECH:
1364		n = input_get(ictx, 0, 1, 1);
1365		if (n != -1)
1366			screen_write_clearcharacter(sctx, n, bg);
1367		break;
1368	case INPUT_CSI_DCH:
1369		n = input_get(ictx, 0, 1, 1);
1370		if (n != -1)
1371			screen_write_deletecharacter(sctx, n, bg);
1372		break;
1373	case INPUT_CSI_DECSTBM:
1374		n = input_get(ictx, 0, 1, 1);
1375		m = input_get(ictx, 1, 1, screen_size_y(s));
1376		if (n != -1 && m != -1)
1377			screen_write_scrollregion(sctx, n - 1, m - 1);
1378		break;
1379	case INPUT_CSI_DL:
1380		n = input_get(ictx, 0, 1, 1);
1381		if (n != -1)
1382			screen_write_deleteline(sctx, n, bg);
1383		break;
1384	case INPUT_CSI_DSR:
1385		switch (input_get(ictx, 0, 0, 0)) {
1386		case -1:
1387			break;
1388		case 5:
1389			input_reply(ictx, "\033[0n");
1390			break;
1391		case 6:
1392			input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1393			break;
1394		default:
1395			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1396			break;
1397		}
1398		break;
1399	case INPUT_CSI_ED:
1400		switch (input_get(ictx, 0, 0, 0)) {
1401		case -1:
1402			break;
1403		case 0:
1404			screen_write_clearendofscreen(sctx, bg);
1405			break;
1406		case 1:
1407			screen_write_clearstartofscreen(sctx, bg);
1408			break;
1409		case 2:
1410			screen_write_clearscreen(sctx, bg);
1411			break;
1412		case 3:
1413			if (input_get(ictx, 1, 0, 0) == 0) {
1414				/*
1415				 * Linux console extension to clear history
1416				 * (for example before locking the screen).
1417				 */
1418				screen_write_clearhistory(sctx);
1419			}
1420			break;
1421		default:
1422			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1423			break;
1424		}
1425		break;
1426	case INPUT_CSI_EL:
1427		switch (input_get(ictx, 0, 0, 0)) {
1428		case -1:
1429			break;
1430		case 0:
1431			screen_write_clearendofline(sctx, bg);
1432			break;
1433		case 1:
1434			screen_write_clearstartofline(sctx, bg);
1435			break;
1436		case 2:
1437			screen_write_clearline(sctx, bg);
1438			break;
1439		default:
1440			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1441			break;
1442		}
1443		break;
1444	case INPUT_CSI_HPA:
1445		n = input_get(ictx, 0, 1, 1);
1446		if (n != -1)
1447			screen_write_cursormove(sctx, n - 1, s->cy);
1448		break;
1449	case INPUT_CSI_ICH:
1450		n = input_get(ictx, 0, 1, 1);
1451		if (n != -1)
1452			screen_write_insertcharacter(sctx, n, bg);
1453		break;
1454	case INPUT_CSI_IL:
1455		n = input_get(ictx, 0, 1, 1);
1456		if (n != -1)
1457			screen_write_insertline(sctx, n, bg);
1458		break;
1459	case INPUT_CSI_REP:
1460		n = input_get(ictx, 0, 1, 1);
1461		if (n == -1)
1462			break;
1463
1464		if (ictx->last == -1)
1465			break;
1466		ictx->ch = ictx->last;
1467
1468		for (i = 0; i < n; i++)
1469			input_print(ictx);
1470		break;
1471	case INPUT_CSI_RCP:
1472		memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1473		screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1474		break;
1475	case INPUT_CSI_RM:
1476		input_csi_dispatch_rm(ictx);
1477		break;
1478	case INPUT_CSI_RM_PRIVATE:
1479		input_csi_dispatch_rm_private(ictx);
1480		break;
1481	case INPUT_CSI_SCP:
1482		memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1483		ictx->old_cx = s->cx;
1484		ictx->old_cy = s->cy;
1485		break;
1486	case INPUT_CSI_SGR:
1487		input_csi_dispatch_sgr(ictx);
1488		break;
1489	case INPUT_CSI_SM:
1490		input_csi_dispatch_sm(ictx);
1491		break;
1492	case INPUT_CSI_SM_PRIVATE:
1493		input_csi_dispatch_sm_private(ictx);
1494		break;
1495	case INPUT_CSI_SU:
1496		n = input_get(ictx, 0, 1, 1);
1497		if (n != -1)
1498			screen_write_scrollup(sctx, n, bg);
1499		break;
1500	case INPUT_CSI_TBC:
1501		switch (input_get(ictx, 0, 0, 0)) {
1502		case -1:
1503			break;
1504		case 0:
1505			if (s->cx < screen_size_x(s))
1506				bit_clear(s->tabs, s->cx);
1507			break;
1508		case 3:
1509			bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1510			break;
1511		default:
1512			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1513			break;
1514		}
1515		break;
1516	case INPUT_CSI_VPA:
1517		n = input_get(ictx, 0, 1, 1);
1518		if (n != -1)
1519			screen_write_cursormove(sctx, s->cx, n - 1);
1520		break;
1521	case INPUT_CSI_DECSCUSR:
1522		n = input_get(ictx, 0, 0, 0);
1523		if (n != -1)
1524			screen_set_cursor_style(s, n);
1525		break;
1526	}
1527
1528	ictx->last = -1;
1529	return (0);
1530}
1531
1532/* Handle CSI RM. */
1533static void
1534input_csi_dispatch_rm(struct input_ctx *ictx)
1535{
1536	u_int	i;
1537
1538	for (i = 0; i < ictx->param_list_len; i++) {
1539		switch (input_get(ictx, i, 0, -1)) {
1540		case -1:
1541			break;
1542		case 4:		/* IRM */
1543			screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
1544			break;
1545		case 34:
1546			screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1547			break;
1548		default:
1549			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1550			break;
1551		}
1552	}
1553}
1554
1555/* Handle CSI private RM. */
1556static void
1557input_csi_dispatch_rm_private(struct input_ctx *ictx)
1558{
1559	struct window_pane	*wp = ictx->wp;
1560	u_int			 i;
1561
1562	for (i = 0; i < ictx->param_list_len; i++) {
1563		switch (input_get(ictx, i, 0, -1)) {
1564		case -1:
1565			break;
1566		case 1:		/* DECCKM */
1567			screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
1568			break;
1569		case 3:		/* DECCOLM */
1570			screen_write_cursormove(&ictx->ctx, 0, 0);
1571			screen_write_clearscreen(&ictx->ctx,
1572			    ictx->cell.cell.bg);
1573			break;
1574		case 6:		/* DECOM */
1575			screen_write_mode_clear(&ictx->ctx, MODE_ORIGIN);
1576			screen_write_cursormove(&ictx->ctx, 0, 0);
1577			break;
1578		case 7:		/* DECAWM */
1579			screen_write_mode_clear(&ictx->ctx, MODE_WRAP);
1580			break;
1581		case 12:
1582			screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1583			break;
1584		case 25:	/* TCEM */
1585			screen_write_mode_clear(&ictx->ctx, MODE_CURSOR);
1586			break;
1587		case 1000:
1588		case 1001:
1589		case 1002:
1590		case 1003:
1591			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1592			break;
1593		case 1004:
1594			screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON);
1595			break;
1596		case 1005:
1597			screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8);
1598			break;
1599		case 1006:
1600			screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR);
1601			break;
1602		case 47:
1603		case 1047:
1604			window_pane_alternate_off(wp, &ictx->cell.cell, 0);
1605			break;
1606		case 1049:
1607			window_pane_alternate_off(wp, &ictx->cell.cell, 1);
1608			break;
1609		case 2004:
1610			screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
1611			break;
1612		default:
1613			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1614			break;
1615		}
1616	}
1617}
1618
1619/* Handle CSI SM. */
1620static void
1621input_csi_dispatch_sm(struct input_ctx *ictx)
1622{
1623	u_int	i;
1624
1625	for (i = 0; i < ictx->param_list_len; i++) {
1626		switch (input_get(ictx, i, 0, -1)) {
1627		case -1:
1628			break;
1629		case 4:		/* IRM */
1630			screen_write_mode_set(&ictx->ctx, MODE_INSERT);
1631			break;
1632		case 34:
1633			screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1634			break;
1635		default:
1636			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1637			break;
1638		}
1639	}
1640}
1641
1642/* Handle CSI private SM. */
1643static void
1644input_csi_dispatch_sm_private(struct input_ctx *ictx)
1645{
1646	struct window_pane	*wp = ictx->wp;
1647	u_int			 i;
1648
1649	for (i = 0; i < ictx->param_list_len; i++) {
1650		switch (input_get(ictx, i, 0, -1)) {
1651		case -1:
1652			break;
1653		case 1:		/* DECCKM */
1654			screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
1655			break;
1656		case 3:		/* DECCOLM */
1657			screen_write_cursormove(&ictx->ctx, 0, 0);
1658			screen_write_clearscreen(&ictx->ctx,
1659			    ictx->cell.cell.bg);
1660			break;
1661		case 6:		/* DECOM */
1662			screen_write_mode_set(&ictx->ctx, MODE_ORIGIN);
1663			screen_write_cursormove(&ictx->ctx, 0, 0);
1664			break;
1665		case 7:		/* DECAWM */
1666			screen_write_mode_set(&ictx->ctx, MODE_WRAP);
1667			break;
1668		case 12:
1669			screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1670			break;
1671		case 25:	/* TCEM */
1672			screen_write_mode_set(&ictx->ctx, MODE_CURSOR);
1673			break;
1674		case 1000:
1675			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1676			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD);
1677			break;
1678		case 1002:
1679			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1680			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON);
1681			break;
1682		case 1003:
1683			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1684			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ALL);
1685			break;
1686		case 1004:
1687			if (ictx->ctx.s->mode & MODE_FOCUSON)
1688				break;
1689			screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
1690			wp->flags |= PANE_FOCUSPUSH; /* force update */
1691			break;
1692		case 1005:
1693			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
1694			break;
1695		case 1006:
1696			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR);
1697			break;
1698		case 47:
1699		case 1047:
1700			window_pane_alternate_on(wp, &ictx->cell.cell, 0);
1701			break;
1702		case 1049:
1703			window_pane_alternate_on(wp, &ictx->cell.cell, 1);
1704			break;
1705		case 2004:
1706			screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
1707			break;
1708		default:
1709			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1710			break;
1711		}
1712	}
1713}
1714
1715/* Handle CSI window operations. */
1716static void
1717input_csi_dispatch_winops(struct input_ctx *ictx)
1718{
1719	struct window_pane	*wp = ictx->wp;
1720	int			 n, m;
1721
1722	m = 0;
1723	while ((n = input_get(ictx, m, 0, -1)) != -1) {
1724		switch (n) {
1725		case 1:
1726		case 2:
1727		case 5:
1728		case 6:
1729		case 7:
1730		case 11:
1731		case 13:
1732		case 14:
1733		case 19:
1734		case 20:
1735		case 21:
1736		case 24:
1737			break;
1738		case 3:
1739		case 4:
1740		case 8:
1741			m++;
1742			if (input_get(ictx, m, 0, -1) == -1)
1743				return;
1744			/* FALLTHROUGH */
1745		case 9:
1746		case 10:
1747			m++;
1748			if (input_get(ictx, m, 0, -1) == -1)
1749				return;
1750			break;
1751		case 22:
1752			m++;
1753			switch (input_get(ictx, m, 0, -1)) {
1754			case -1:
1755				return;
1756			case 0:
1757			case 2:
1758				screen_push_title(ictx->ctx.s);
1759				break;
1760			}
1761			break;
1762		case 23:
1763			m++;
1764			switch (input_get(ictx, m, 0, -1)) {
1765			case -1:
1766				return;
1767			case 0:
1768			case 2:
1769				screen_pop_title(ictx->ctx.s);
1770				server_status_window(ictx->wp->window);
1771				break;
1772			}
1773			break;
1774		case 18:
1775			input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx);
1776			break;
1777		default:
1778			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1779			break;
1780		}
1781		m++;
1782	}
1783}
1784
1785/* Helper for 256 colour SGR. */
1786static int
1787input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c)
1788{
1789	struct grid_cell	*gc = &ictx->cell.cell;
1790
1791	if (c == -1 || c > 255) {
1792		if (fgbg == 38)
1793			gc->fg = 8;
1794		else if (fgbg == 48)
1795			gc->bg = 8;
1796	} else {
1797		if (fgbg == 38)
1798			gc->fg = c | COLOUR_FLAG_256;
1799		else if (fgbg == 48)
1800			gc->bg = c | COLOUR_FLAG_256;
1801	}
1802	return (1);
1803}
1804
1805/* Handle CSI SGR for 256 colours. */
1806static void
1807input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
1808{
1809	int	c;
1810
1811	c = input_get(ictx, (*i) + 1, 0, -1);
1812	if (input_csi_dispatch_sgr_256_do(ictx, fgbg, c))
1813		(*i)++;
1814}
1815
1816/* Helper for RGB colour SGR. */
1817static int
1818input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g,
1819    int b)
1820{
1821	struct grid_cell	*gc = &ictx->cell.cell;
1822
1823	if (r == -1 || r > 255)
1824		return (0);
1825	if (g == -1 || g > 255)
1826		return (0);
1827	if (b == -1 || b > 255)
1828		return (0);
1829
1830	if (fgbg == 38)
1831		gc->fg = colour_join_rgb(r, g, b);
1832	else if (fgbg == 48)
1833		gc->bg = colour_join_rgb(r, g, b);
1834	return (1);
1835}
1836
1837/* Handle CSI SGR for RGB colours. */
1838static void
1839input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
1840{
1841	int	r, g, b;
1842
1843	r = input_get(ictx, (*i) + 1, 0, -1);
1844	g = input_get(ictx, (*i) + 2, 0, -1);
1845	b = input_get(ictx, (*i) + 3, 0, -1);
1846	if (input_csi_dispatch_sgr_rgb_do(ictx, fgbg, r, g, b))
1847		(*i) += 3;
1848}
1849
1850/* Handle CSI SGR with a ISO parameter. */
1851static void
1852input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
1853{
1854	struct grid_cell	*gc = &ictx->cell.cell;
1855	char			*s = ictx->param_list[i].str, *copy, *ptr, *out;
1856	int			 p[8];
1857	u_int			 n;
1858	const char		*errstr;
1859
1860	for (n = 0; n < nitems(p); n++)
1861		p[n] = -1;
1862	n = 0;
1863
1864	ptr = copy = xstrdup(s);
1865	while ((out = strsep(&ptr, ":")) != NULL) {
1866		if (*out != '\0') {
1867			p[n++] = strtonum(out, 0, INT_MAX, &errstr);
1868			if (errstr != NULL || n == nitems(p)) {
1869				free(copy);
1870				return;
1871			}
1872		} else
1873			n++;
1874		log_debug("%s: %u = %d", __func__, n - 1, p[n - 1]);
1875	}
1876	free(copy);
1877
1878	if (n == 0)
1879		return;
1880	if (p[0] == 4) {
1881		if (n != 2)
1882			return;
1883		switch (p[1]) {
1884		case 0:
1885			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1886			break;
1887		case 1:
1888			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1889			gc->attr |= GRID_ATTR_UNDERSCORE;
1890			break;
1891		case 2:
1892			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1893			gc->attr |= GRID_ATTR_UNDERSCORE_2;
1894			break;
1895		case 3:
1896			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1897			gc->attr |= GRID_ATTR_UNDERSCORE_3;
1898			break;
1899		case 4:
1900			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1901			gc->attr |= GRID_ATTR_UNDERSCORE_4;
1902			break;
1903		case 5:
1904			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1905			gc->attr |= GRID_ATTR_UNDERSCORE_5;
1906			break;
1907		}
1908		return;
1909	}
1910	if (p[0] != 38 && p[0] != 48)
1911		return;
1912	if (p[1] == -1)
1913		i = 2;
1914	else
1915		i = 1;
1916	switch (p[i]) {
1917	case 2:
1918		if (n < i + 4)
1919			break;
1920		input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[i + 1], p[i + 2],
1921		    p[i + 3]);
1922		break;
1923	case 5:
1924		if (n < i + 2)
1925			break;
1926		input_csi_dispatch_sgr_256_do(ictx, p[0], p[i + 1]);
1927		break;
1928	}
1929}
1930
1931/* Handle CSI SGR. */
1932static void
1933input_csi_dispatch_sgr(struct input_ctx *ictx)
1934{
1935	struct grid_cell	*gc = &ictx->cell.cell;
1936	u_int			 i;
1937	int			 n;
1938
1939	if (ictx->param_list_len == 0) {
1940		memcpy(gc, &grid_default_cell, sizeof *gc);
1941		return;
1942	}
1943
1944	for (i = 0; i < ictx->param_list_len; i++) {
1945		if (ictx->param_list[i].type == INPUT_STRING) {
1946			input_csi_dispatch_sgr_colon(ictx, i);
1947			continue;
1948		}
1949		n = input_get(ictx, i, 0, 0);
1950		if (n == -1)
1951			continue;
1952
1953		if (n == 38 || n == 48) {
1954			i++;
1955			switch (input_get(ictx, i, 0, -1)) {
1956			case 2:
1957				input_csi_dispatch_sgr_rgb(ictx, n, &i);
1958				break;
1959			case 5:
1960				input_csi_dispatch_sgr_256(ictx, n, &i);
1961				break;
1962			}
1963			continue;
1964		}
1965
1966		switch (n) {
1967		case 0:
1968			memcpy(gc, &grid_default_cell, sizeof *gc);
1969			break;
1970		case 1:
1971			gc->attr |= GRID_ATTR_BRIGHT;
1972			break;
1973		case 2:
1974			gc->attr |= GRID_ATTR_DIM;
1975			break;
1976		case 3:
1977			gc->attr |= GRID_ATTR_ITALICS;
1978			break;
1979		case 4:
1980			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1981			gc->attr |= GRID_ATTR_UNDERSCORE;
1982			break;
1983		case 5:
1984			gc->attr |= GRID_ATTR_BLINK;
1985			break;
1986		case 7:
1987			gc->attr |= GRID_ATTR_REVERSE;
1988			break;
1989		case 8:
1990			gc->attr |= GRID_ATTR_HIDDEN;
1991			break;
1992		case 9:
1993			gc->attr |= GRID_ATTR_STRIKETHROUGH;
1994			break;
1995		case 22:
1996			gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1997			break;
1998		case 23:
1999			gc->attr &= ~GRID_ATTR_ITALICS;
2000			break;
2001		case 24:
2002			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2003			break;
2004		case 25:
2005			gc->attr &= ~GRID_ATTR_BLINK;
2006			break;
2007		case 27:
2008			gc->attr &= ~GRID_ATTR_REVERSE;
2009			break;
2010		case 28:
2011			gc->attr &= ~GRID_ATTR_HIDDEN;
2012			break;
2013		case 29:
2014			gc->attr &= ~GRID_ATTR_STRIKETHROUGH;
2015			break;
2016		case 30:
2017		case 31:
2018		case 32:
2019		case 33:
2020		case 34:
2021		case 35:
2022		case 36:
2023		case 37:
2024			gc->fg = n - 30;
2025			break;
2026		case 39:
2027			gc->fg = 8;
2028			break;
2029		case 40:
2030		case 41:
2031		case 42:
2032		case 43:
2033		case 44:
2034		case 45:
2035		case 46:
2036		case 47:
2037			gc->bg = n - 40;
2038			break;
2039		case 49:
2040			gc->bg = 8;
2041			break;
2042		case 90:
2043		case 91:
2044		case 92:
2045		case 93:
2046		case 94:
2047		case 95:
2048		case 96:
2049		case 97:
2050			gc->fg = n;
2051			break;
2052		case 100:
2053		case 101:
2054		case 102:
2055		case 103:
2056		case 104:
2057		case 105:
2058		case 106:
2059		case 107:
2060			gc->bg = n - 10;
2061			break;
2062		}
2063	}
2064}
2065
2066/* End of input with BEL. */
2067static int
2068input_end_bel(struct input_ctx *ictx)
2069{
2070	log_debug("%s", __func__);
2071
2072	ictx->input_end = INPUT_END_BEL;
2073
2074	return (0);
2075}
2076
2077/* DCS string started. */
2078static void
2079input_enter_dcs(struct input_ctx *ictx)
2080{
2081	log_debug("%s", __func__);
2082
2083	input_clear(ictx);
2084	input_start_timer(ictx);
2085	ictx->last = -1;
2086}
2087
2088/* DCS terminator (ST) received. */
2089static int
2090input_dcs_dispatch(struct input_ctx *ictx)
2091{
2092	const char	prefix[] = "tmux;";
2093	const u_int	prefix_len = (sizeof prefix) - 1;
2094
2095	if (ictx->flags & INPUT_DISCARD)
2096		return (0);
2097
2098	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2099
2100	/* Check for tmux prefix. */
2101	if (ictx->input_len >= prefix_len &&
2102	    strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
2103		screen_write_rawstring(&ictx->ctx,
2104		    ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
2105	}
2106
2107	return (0);
2108}
2109
2110/* OSC string started. */
2111static void
2112input_enter_osc(struct input_ctx *ictx)
2113{
2114	log_debug("%s", __func__);
2115
2116	input_clear(ictx);
2117	input_start_timer(ictx);
2118	ictx->last = -1;
2119}
2120
2121/* OSC terminator (ST) received. */
2122static void
2123input_exit_osc(struct input_ctx *ictx)
2124{
2125	u_char	*p = ictx->input_buf;
2126	u_int	 option;
2127
2128	if (ictx->flags & INPUT_DISCARD)
2129		return;
2130	if (ictx->input_len < 1 || *p < '0' || *p > '9')
2131		return;
2132
2133	log_debug("%s: \"%s\" (end %s)", __func__, p,
2134	    ictx->input_end == INPUT_END_ST ? "ST" : "BEL");
2135
2136	option = 0;
2137	while (*p >= '0' && *p <= '9')
2138		option = option * 10 + *p++ - '0';
2139	if (*p == ';')
2140		p++;
2141
2142	switch (option) {
2143	case 0:
2144	case 2:
2145		if (utf8_isvalid(p)) {
2146			screen_set_title(ictx->ctx.s, p);
2147			server_status_window(ictx->wp->window);
2148		}
2149		break;
2150	case 4:
2151		input_osc_4(ictx, p);
2152		break;
2153	case 10:
2154		input_osc_10(ictx, p);
2155		break;
2156	case 11:
2157		input_osc_11(ictx, p);
2158		break;
2159	case 12:
2160		if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
2161			screen_set_cursor_colour(ictx->ctx.s, p);
2162		break;
2163	case 52:
2164		input_osc_52(ictx, p);
2165		break;
2166	case 104:
2167		input_osc_104(ictx, p);
2168		break;
2169	case 112:
2170		if (*p == '\0') /* no arguments allowed */
2171			screen_set_cursor_colour(ictx->ctx.s, "");
2172		break;
2173	default:
2174		log_debug("%s: unknown '%u'", __func__, option);
2175		break;
2176	}
2177}
2178
2179/* APC string started. */
2180static void
2181input_enter_apc(struct input_ctx *ictx)
2182{
2183	log_debug("%s", __func__);
2184
2185	input_clear(ictx);
2186	input_start_timer(ictx);
2187	ictx->last = -1;
2188}
2189
2190/* APC terminator (ST) received. */
2191static void
2192input_exit_apc(struct input_ctx *ictx)
2193{
2194	if (ictx->flags & INPUT_DISCARD)
2195		return;
2196	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2197
2198	if (!utf8_isvalid(ictx->input_buf))
2199		return;
2200	screen_set_title(ictx->ctx.s, ictx->input_buf);
2201	server_status_window(ictx->wp->window);
2202}
2203
2204/* Rename string started. */
2205static void
2206input_enter_rename(struct input_ctx *ictx)
2207{
2208	log_debug("%s", __func__);
2209
2210	input_clear(ictx);
2211	input_start_timer(ictx);
2212	ictx->last = -1;
2213}
2214
2215/* Rename terminator (ST) received. */
2216static void
2217input_exit_rename(struct input_ctx *ictx)
2218{
2219	if (ictx->flags & INPUT_DISCARD)
2220		return;
2221	if (!options_get_number(ictx->wp->window->options, "allow-rename"))
2222		return;
2223	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2224
2225	if (!utf8_isvalid(ictx->input_buf))
2226		return;
2227	window_set_name(ictx->wp->window, ictx->input_buf);
2228	options_set_number(ictx->wp->window->options, "automatic-rename", 0);
2229	server_status_window(ictx->wp->window);
2230}
2231
2232/* Open UTF-8 character. */
2233static int
2234input_top_bit_set(struct input_ctx *ictx)
2235{
2236	struct utf8_data	*ud = &ictx->utf8data;
2237
2238	ictx->last = -1;
2239
2240	if (!ictx->utf8started) {
2241		if (utf8_open(ud, ictx->ch) != UTF8_MORE)
2242			return (0);
2243		ictx->utf8started = 1;
2244		return (0);
2245	}
2246
2247	switch (utf8_append(ud, ictx->ch)) {
2248	case UTF8_MORE:
2249		return (0);
2250	case UTF8_ERROR:
2251		ictx->utf8started = 0;
2252		return (0);
2253	case UTF8_DONE:
2254		break;
2255	}
2256	ictx->utf8started = 0;
2257
2258	log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
2259	    (int)ud->size, ud->data, ud->width);
2260
2261	utf8_copy(&ictx->cell.cell.data, ud);
2262	screen_write_collect_add(&ictx->ctx, &ictx->cell.cell);
2263
2264	return (0);
2265}
2266
2267/* Handle the OSC 4 sequence for setting (multiple) palette entries. */
2268static void
2269input_osc_4(struct input_ctx *ictx, const char *p)
2270{
2271	struct window_pane	*wp = ictx->wp;
2272	char			*copy, *s, *next = NULL;
2273	long	 		idx;
2274	u_int			 r, g, b;
2275
2276	copy = s = xstrdup(p);
2277	while (s != NULL && *s != '\0') {
2278		idx = strtol(s, &next, 10);
2279		if (*next++ != ';')
2280			goto bad;
2281		if (idx < 0 || idx >= 0x100)
2282			goto bad;
2283
2284		s = strsep(&next, ";");
2285		if (sscanf(s, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) {
2286			s = next;
2287			continue;
2288		}
2289
2290		window_pane_set_palette(wp, idx, colour_join_rgb(r, g, b));
2291		s = next;
2292	}
2293
2294	free(copy);
2295	return;
2296
2297bad:
2298	log_debug("bad OSC 4: %s", p);
2299	free(copy);
2300}
2301
2302/* Handle the OSC 10 sequence for setting foreground colour. */
2303static void
2304input_osc_10(struct input_ctx *ictx, const char *p)
2305{
2306	struct window_pane	*wp = ictx->wp;
2307	u_int			 r, g, b;
2308
2309	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2310	    goto bad;
2311
2312	wp->colgc.fg = colour_join_rgb(r, g, b);
2313	wp->flags |= PANE_REDRAW;
2314
2315	return;
2316
2317bad:
2318	log_debug("bad OSC 10: %s", p);
2319}
2320
2321/* Handle the OSC 11 sequence for setting background colour. */
2322static void
2323input_osc_11(struct input_ctx *ictx, const char *p)
2324{
2325	struct window_pane	*wp = ictx->wp;
2326	u_int			 r, g, b;
2327
2328	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2329	    goto bad;
2330
2331	wp->colgc.bg = colour_join_rgb(r, g, b);
2332	wp->flags |= PANE_REDRAW;
2333
2334	return;
2335
2336bad:
2337	log_debug("bad OSC 11: %s", p);
2338}
2339
2340/* Handle the OSC 52 sequence for setting the clipboard. */
2341static void
2342input_osc_52(struct input_ctx *ictx, const char *p)
2343{
2344	struct window_pane	*wp = ictx->wp;
2345	char			*end;
2346	const char		*buf;
2347	size_t			 len;
2348	u_char			*out;
2349	int			 outlen, state;
2350	struct screen_write_ctx	 ctx;
2351	struct paste_buffer	*pb;
2352
2353	state = options_get_number(global_options, "set-clipboard");
2354	if (state != 2)
2355		return;
2356
2357	if ((end = strchr(p, ';')) == NULL)
2358		return;
2359	end++;
2360	if (*end == '\0')
2361		return;
2362	log_debug("%s: %s", __func__, end);
2363
2364	if (strcmp(end, "?") == 0) {
2365		if ((pb = paste_get_top(NULL)) != NULL) {
2366			buf = paste_buffer_data(pb, &len);
2367			outlen = 4 * ((len + 2) / 3) + 1;
2368			out = xmalloc(outlen);
2369			if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
2370				abort();
2371				free(out);
2372				return;
2373			}
2374		} else {
2375			outlen = 0;
2376			out = NULL;
2377		}
2378		bufferevent_write(wp->event, "\033]52;;", 6);
2379		if (outlen != 0)
2380			bufferevent_write(wp->event, out, outlen);
2381		if (ictx->input_end == INPUT_END_BEL)
2382			bufferevent_write(wp->event, "\007", 1);
2383		else
2384			bufferevent_write(wp->event, "\033\\", 2);
2385		free(out);
2386		return;
2387	}
2388
2389	len = (strlen(end) / 4) * 3;
2390	if (len == 0)
2391		return;
2392
2393	out = xmalloc(len);
2394	if ((outlen = b64_pton(end, out, len)) == -1) {
2395		free(out);
2396		return;
2397	}
2398
2399	screen_write_start(&ctx, wp, NULL);
2400	screen_write_setselection(&ctx, out, outlen);
2401	screen_write_stop(&ctx);
2402	notify_pane("pane-set-clipboard", wp);
2403
2404	paste_add(out, outlen);
2405}
2406
2407/* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
2408static void
2409input_osc_104(struct input_ctx *ictx, const char *p)
2410{
2411	struct window_pane	*wp = ictx->wp;
2412	char			*copy, *s;
2413	long			idx;
2414
2415	if (*p == '\0') {
2416		window_pane_reset_palette(wp);
2417		return;
2418	}
2419
2420	copy = s = xstrdup(p);
2421	while (*s != '\0') {
2422		idx = strtol(s, &s, 10);
2423		if (*s != '\0' && *s != ';')
2424			goto bad;
2425		if (idx < 0 || idx >= 0x100)
2426			goto bad;
2427
2428		window_pane_unset_palette(wp, idx);
2429		if (*s == ';')
2430			s++;
2431	}
2432	free(copy);
2433	return;
2434
2435bad:
2436	log_debug("bad OSC 104: %s", p);
2437	free(copy);
2438}
2439