input.c revision 1.141
1/* $OpenBSD: input.c,v 1.141 2019/03/12 07:39:27 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 (wp->mode == NULL)
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 (wp->mode == NULL)
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		screen_write_clearhistory(sctx);
1201		break;
1202	case INPUT_ESC_IND:
1203		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1204		break;
1205	case INPUT_ESC_NEL:
1206		screen_write_carriagereturn(sctx);
1207		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1208		break;
1209	case INPUT_ESC_HTS:
1210		if (s->cx < screen_size_x(s))
1211			bit_set(s->tabs, s->cx);
1212		break;
1213	case INPUT_ESC_RI:
1214		screen_write_reverseindex(sctx, ictx->cell.cell.bg);
1215		break;
1216	case INPUT_ESC_DECKPAM:
1217		screen_write_mode_set(sctx, MODE_KKEYPAD);
1218		break;
1219	case INPUT_ESC_DECKPNM:
1220		screen_write_mode_clear(sctx, MODE_KKEYPAD);
1221		break;
1222	case INPUT_ESC_DECSC:
1223		memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1224		ictx->old_cx = s->cx;
1225		ictx->old_cy = s->cy;
1226		break;
1227	case INPUT_ESC_DECRC:
1228		memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1229		screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1230		break;
1231	case INPUT_ESC_DECALN:
1232		screen_write_alignmenttest(sctx);
1233		break;
1234	case INPUT_ESC_SCSG0_ON:
1235		ictx->cell.g0set = 1;
1236		break;
1237	case INPUT_ESC_SCSG0_OFF:
1238		ictx->cell.g0set = 0;
1239		break;
1240	case INPUT_ESC_SCSG1_ON:
1241		ictx->cell.g1set = 1;
1242		break;
1243	case INPUT_ESC_SCSG1_OFF:
1244		ictx->cell.g1set = 0;
1245		break;
1246	case INPUT_ESC_ST:
1247		/* ST terminates OSC but the state transition already did it. */
1248		break;
1249	}
1250
1251	ictx->last = -1;
1252	return (0);
1253}
1254
1255/* Execute control sequence. */
1256static int
1257input_csi_dispatch(struct input_ctx *ictx)
1258{
1259	struct screen_write_ctx	       *sctx = &ictx->ctx;
1260	struct screen		       *s = sctx->s;
1261	struct input_table_entry       *entry;
1262	int				i, n, m;
1263	u_int				cx, bg = ictx->cell.cell.bg;
1264
1265	if (ictx->flags & INPUT_DISCARD)
1266		return (0);
1267
1268	log_debug("%s: '%c' \"%s\" \"%s\"",
1269	    __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1270
1271	if (input_split(ictx) != 0)
1272		return (0);
1273
1274	entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1275	    sizeof input_csi_table[0], input_table_compare);
1276	if (entry == NULL) {
1277		log_debug("%s: unknown '%c'", __func__, ictx->ch);
1278		return (0);
1279	}
1280
1281	switch (entry->type) {
1282	case INPUT_CSI_CBT:
1283		/* Find the previous tab point, n times. */
1284		cx = s->cx;
1285		if (cx > screen_size_x(s) - 1)
1286			cx = screen_size_x(s) - 1;
1287		n = input_get(ictx, 0, 1, 1);
1288		if (n == -1)
1289			break;
1290		while (cx > 0 && n-- > 0) {
1291			do
1292				cx--;
1293			while (cx > 0 && !bit_test(s->tabs, cx));
1294		}
1295		s->cx = cx;
1296		break;
1297	case INPUT_CSI_CUB:
1298		n = input_get(ictx, 0, 1, 1);
1299		if (n != -1)
1300			screen_write_cursorleft(sctx, n);
1301		break;
1302	case INPUT_CSI_CUD:
1303		n = input_get(ictx, 0, 1, 1);
1304		if (n != -1)
1305			screen_write_cursordown(sctx, n);
1306		break;
1307	case INPUT_CSI_CUF:
1308		n = input_get(ictx, 0, 1, 1);
1309		if (n != -1)
1310			screen_write_cursorright(sctx, n);
1311		break;
1312	case INPUT_CSI_CUP:
1313		n = input_get(ictx, 0, 1, 1);
1314		m = input_get(ictx, 1, 1, 1);
1315		if (n != -1 && m != -1)
1316			screen_write_cursormove(sctx, m - 1, n - 1);
1317		break;
1318	case INPUT_CSI_WINOPS:
1319		input_csi_dispatch_winops(ictx);
1320		break;
1321	case INPUT_CSI_CUU:
1322		n = input_get(ictx, 0, 1, 1);
1323		if (n != -1)
1324			screen_write_cursorup(sctx, n);
1325		break;
1326	case INPUT_CSI_CNL:
1327		n = input_get(ictx, 0, 1, 1);
1328		if (n != -1) {
1329			screen_write_carriagereturn(sctx);
1330			screen_write_cursordown(sctx, n);
1331		}
1332		break;
1333	case INPUT_CSI_CPL:
1334		n = input_get(ictx, 0, 1, 1);
1335		if (n != -1) {
1336			screen_write_carriagereturn(sctx);
1337			screen_write_cursorup(sctx, n);
1338		}
1339		break;
1340	case INPUT_CSI_DA:
1341		switch (input_get(ictx, 0, 0, 0)) {
1342		case -1:
1343			break;
1344		case 0:
1345			input_reply(ictx, "\033[?1;2c");
1346			break;
1347		default:
1348			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1349			break;
1350		}
1351		break;
1352	case INPUT_CSI_DA_TWO:
1353		switch (input_get(ictx, 0, 0, 0)) {
1354		case -1:
1355			break;
1356		case 0:
1357			input_reply(ictx, "\033[>84;0;0c");
1358			break;
1359		default:
1360			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1361			break;
1362		}
1363		break;
1364	case INPUT_CSI_ECH:
1365		n = input_get(ictx, 0, 1, 1);
1366		if (n != -1)
1367			screen_write_clearcharacter(sctx, n, bg);
1368		break;
1369	case INPUT_CSI_DCH:
1370		n = input_get(ictx, 0, 1, 1);
1371		if (n != -1)
1372			screen_write_deletecharacter(sctx, n, bg);
1373		break;
1374	case INPUT_CSI_DECSTBM:
1375		n = input_get(ictx, 0, 1, 1);
1376		m = input_get(ictx, 1, 1, screen_size_y(s));
1377		if (n != -1 && m != -1)
1378			screen_write_scrollregion(sctx, n - 1, m - 1);
1379		break;
1380	case INPUT_CSI_DL:
1381		n = input_get(ictx, 0, 1, 1);
1382		if (n != -1)
1383			screen_write_deleteline(sctx, n, bg);
1384		break;
1385	case INPUT_CSI_DSR:
1386		switch (input_get(ictx, 0, 0, 0)) {
1387		case -1:
1388			break;
1389		case 5:
1390			input_reply(ictx, "\033[0n");
1391			break;
1392		case 6:
1393			input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1394			break;
1395		default:
1396			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1397			break;
1398		}
1399		break;
1400	case INPUT_CSI_ED:
1401		switch (input_get(ictx, 0, 0, 0)) {
1402		case -1:
1403			break;
1404		case 0:
1405			screen_write_clearendofscreen(sctx, bg);
1406			break;
1407		case 1:
1408			screen_write_clearstartofscreen(sctx, bg);
1409			break;
1410		case 2:
1411			screen_write_clearscreen(sctx, bg);
1412			break;
1413		case 3:
1414			if (input_get(ictx, 1, 0, 0) == 0) {
1415				/*
1416				 * Linux console extension to clear history
1417				 * (for example before locking the screen).
1418				 */
1419				screen_write_clearhistory(sctx);
1420			}
1421			break;
1422		default:
1423			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1424			break;
1425		}
1426		break;
1427	case INPUT_CSI_EL:
1428		switch (input_get(ictx, 0, 0, 0)) {
1429		case -1:
1430			break;
1431		case 0:
1432			screen_write_clearendofline(sctx, bg);
1433			break;
1434		case 1:
1435			screen_write_clearstartofline(sctx, bg);
1436			break;
1437		case 2:
1438			screen_write_clearline(sctx, bg);
1439			break;
1440		default:
1441			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1442			break;
1443		}
1444		break;
1445	case INPUT_CSI_HPA:
1446		n = input_get(ictx, 0, 1, 1);
1447		if (n != -1)
1448			screen_write_cursormove(sctx, n - 1, s->cy);
1449		break;
1450	case INPUT_CSI_ICH:
1451		n = input_get(ictx, 0, 1, 1);
1452		if (n != -1)
1453			screen_write_insertcharacter(sctx, n, bg);
1454		break;
1455	case INPUT_CSI_IL:
1456		n = input_get(ictx, 0, 1, 1);
1457		if (n != -1)
1458			screen_write_insertline(sctx, n, bg);
1459		break;
1460	case INPUT_CSI_REP:
1461		n = input_get(ictx, 0, 1, 1);
1462		if (n == -1)
1463			break;
1464
1465		if (ictx->last == -1)
1466			break;
1467		ictx->ch = ictx->last;
1468
1469		for (i = 0; i < n; i++)
1470			input_print(ictx);
1471		break;
1472	case INPUT_CSI_RCP:
1473		memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1474		screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1475		break;
1476	case INPUT_CSI_RM:
1477		input_csi_dispatch_rm(ictx);
1478		break;
1479	case INPUT_CSI_RM_PRIVATE:
1480		input_csi_dispatch_rm_private(ictx);
1481		break;
1482	case INPUT_CSI_SCP:
1483		memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1484		ictx->old_cx = s->cx;
1485		ictx->old_cy = s->cy;
1486		break;
1487	case INPUT_CSI_SGR:
1488		input_csi_dispatch_sgr(ictx);
1489		break;
1490	case INPUT_CSI_SM:
1491		input_csi_dispatch_sm(ictx);
1492		break;
1493	case INPUT_CSI_SM_PRIVATE:
1494		input_csi_dispatch_sm_private(ictx);
1495		break;
1496	case INPUT_CSI_SU:
1497		n = input_get(ictx, 0, 1, 1);
1498		if (n != -1)
1499			screen_write_scrollup(sctx, n, bg);
1500		break;
1501	case INPUT_CSI_TBC:
1502		switch (input_get(ictx, 0, 0, 0)) {
1503		case -1:
1504			break;
1505		case 0:
1506			if (s->cx < screen_size_x(s))
1507				bit_clear(s->tabs, s->cx);
1508			break;
1509		case 3:
1510			bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1511			break;
1512		default:
1513			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1514			break;
1515		}
1516		break;
1517	case INPUT_CSI_VPA:
1518		n = input_get(ictx, 0, 1, 1);
1519		if (n != -1)
1520			screen_write_cursormove(sctx, s->cx, n - 1);
1521		break;
1522	case INPUT_CSI_DECSCUSR:
1523		n = input_get(ictx, 0, 0, 0);
1524		if (n != -1)
1525			screen_set_cursor_style(s, n);
1526		break;
1527	}
1528
1529	ictx->last = -1;
1530	return (0);
1531}
1532
1533/* Handle CSI RM. */
1534static void
1535input_csi_dispatch_rm(struct input_ctx *ictx)
1536{
1537	u_int	i;
1538
1539	for (i = 0; i < ictx->param_list_len; i++) {
1540		switch (input_get(ictx, i, 0, -1)) {
1541		case -1:
1542			break;
1543		case 4:		/* IRM */
1544			screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
1545			break;
1546		case 34:
1547			screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1548			break;
1549		default:
1550			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1551			break;
1552		}
1553	}
1554}
1555
1556/* Handle CSI private RM. */
1557static void
1558input_csi_dispatch_rm_private(struct input_ctx *ictx)
1559{
1560	struct window_pane	*wp = ictx->wp;
1561	u_int			 i;
1562
1563	for (i = 0; i < ictx->param_list_len; i++) {
1564		switch (input_get(ictx, i, 0, -1)) {
1565		case -1:
1566			break;
1567		case 1:		/* DECCKM */
1568			screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
1569			break;
1570		case 3:		/* DECCOLM */
1571			screen_write_cursormove(&ictx->ctx, 0, 0);
1572			screen_write_clearscreen(&ictx->ctx,
1573			    ictx->cell.cell.bg);
1574			break;
1575		case 6:		/* DECOM */
1576			screen_write_mode_clear(&ictx->ctx, MODE_ORIGIN);
1577			screen_write_cursormove(&ictx->ctx, 0, 0);
1578			break;
1579		case 7:		/* DECAWM */
1580			screen_write_mode_clear(&ictx->ctx, MODE_WRAP);
1581			break;
1582		case 12:
1583			screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1584			break;
1585		case 25:	/* TCEM */
1586			screen_write_mode_clear(&ictx->ctx, MODE_CURSOR);
1587			break;
1588		case 1000:
1589		case 1001:
1590		case 1002:
1591		case 1003:
1592			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1593			break;
1594		case 1004:
1595			screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON);
1596			break;
1597		case 1005:
1598			screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8);
1599			break;
1600		case 1006:
1601			screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR);
1602			break;
1603		case 47:
1604		case 1047:
1605			window_pane_alternate_off(wp, &ictx->cell.cell, 0);
1606			break;
1607		case 1049:
1608			window_pane_alternate_off(wp, &ictx->cell.cell, 1);
1609			break;
1610		case 2004:
1611			screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
1612			break;
1613		default:
1614			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1615			break;
1616		}
1617	}
1618}
1619
1620/* Handle CSI SM. */
1621static void
1622input_csi_dispatch_sm(struct input_ctx *ictx)
1623{
1624	u_int	i;
1625
1626	for (i = 0; i < ictx->param_list_len; i++) {
1627		switch (input_get(ictx, i, 0, -1)) {
1628		case -1:
1629			break;
1630		case 4:		/* IRM */
1631			screen_write_mode_set(&ictx->ctx, MODE_INSERT);
1632			break;
1633		case 34:
1634			screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1635			break;
1636		default:
1637			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1638			break;
1639		}
1640	}
1641}
1642
1643/* Handle CSI private SM. */
1644static void
1645input_csi_dispatch_sm_private(struct input_ctx *ictx)
1646{
1647	struct window_pane	*wp = ictx->wp;
1648	u_int			 i;
1649
1650	for (i = 0; i < ictx->param_list_len; i++) {
1651		switch (input_get(ictx, i, 0, -1)) {
1652		case -1:
1653			break;
1654		case 1:		/* DECCKM */
1655			screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
1656			break;
1657		case 3:		/* DECCOLM */
1658			screen_write_cursormove(&ictx->ctx, 0, 0);
1659			screen_write_clearscreen(&ictx->ctx,
1660			    ictx->cell.cell.bg);
1661			break;
1662		case 6:		/* DECOM */
1663			screen_write_mode_set(&ictx->ctx, MODE_ORIGIN);
1664			screen_write_cursormove(&ictx->ctx, 0, 0);
1665			break;
1666		case 7:		/* DECAWM */
1667			screen_write_mode_set(&ictx->ctx, MODE_WRAP);
1668			break;
1669		case 12:
1670			screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1671			break;
1672		case 25:	/* TCEM */
1673			screen_write_mode_set(&ictx->ctx, MODE_CURSOR);
1674			break;
1675		case 1000:
1676			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1677			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD);
1678			break;
1679		case 1002:
1680			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1681			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON);
1682			break;
1683		case 1003:
1684			screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1685			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ALL);
1686			break;
1687		case 1004:
1688			if (ictx->ctx.s->mode & MODE_FOCUSON)
1689				break;
1690			screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
1691			wp->flags |= PANE_FOCUSPUSH; /* force update */
1692			break;
1693		case 1005:
1694			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
1695			break;
1696		case 1006:
1697			screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR);
1698			break;
1699		case 47:
1700		case 1047:
1701			window_pane_alternate_on(wp, &ictx->cell.cell, 0);
1702			break;
1703		case 1049:
1704			window_pane_alternate_on(wp, &ictx->cell.cell, 1);
1705			break;
1706		case 2004:
1707			screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
1708			break;
1709		default:
1710			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1711			break;
1712		}
1713	}
1714}
1715
1716/* Handle CSI window operations. */
1717static void
1718input_csi_dispatch_winops(struct input_ctx *ictx)
1719{
1720	struct window_pane	*wp = ictx->wp;
1721	int			 n, m;
1722
1723	m = 0;
1724	while ((n = input_get(ictx, m, 0, -1)) != -1) {
1725		switch (n) {
1726		case 1:
1727		case 2:
1728		case 5:
1729		case 6:
1730		case 7:
1731		case 11:
1732		case 13:
1733		case 14:
1734		case 19:
1735		case 20:
1736		case 21:
1737		case 24:
1738			break;
1739		case 3:
1740		case 4:
1741		case 8:
1742			m++;
1743			if (input_get(ictx, m, 0, -1) == -1)
1744				return;
1745			/* FALLTHROUGH */
1746		case 9:
1747		case 10:
1748			m++;
1749			if (input_get(ictx, m, 0, -1) == -1)
1750				return;
1751			break;
1752		case 22:
1753			m++;
1754			switch (input_get(ictx, m, 0, -1)) {
1755			case -1:
1756				return;
1757			case 0:
1758			case 2:
1759				screen_push_title(ictx->ctx.s);
1760				break;
1761			}
1762			break;
1763		case 23:
1764			m++;
1765			switch (input_get(ictx, m, 0, -1)) {
1766			case -1:
1767				return;
1768			case 0:
1769			case 2:
1770				screen_pop_title(ictx->ctx.s);
1771				server_status_window(ictx->wp->window);
1772				break;
1773			}
1774			break;
1775		case 18:
1776			input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx);
1777			break;
1778		default:
1779			log_debug("%s: unknown '%c'", __func__, ictx->ch);
1780			break;
1781		}
1782		m++;
1783	}
1784}
1785
1786/* Helper for 256 colour SGR. */
1787static int
1788input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c)
1789{
1790	struct grid_cell	*gc = &ictx->cell.cell;
1791
1792	if (c == -1 || c > 255) {
1793		if (fgbg == 38)
1794			gc->fg = 8;
1795		else if (fgbg == 48)
1796			gc->bg = 8;
1797	} else {
1798		if (fgbg == 38)
1799			gc->fg = c | COLOUR_FLAG_256;
1800		else if (fgbg == 48)
1801			gc->bg = c | COLOUR_FLAG_256;
1802	}
1803	return (1);
1804}
1805
1806/* Handle CSI SGR for 256 colours. */
1807static void
1808input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
1809{
1810	int	c;
1811
1812	c = input_get(ictx, (*i) + 1, 0, -1);
1813	if (input_csi_dispatch_sgr_256_do(ictx, fgbg, c))
1814		(*i)++;
1815}
1816
1817/* Helper for RGB colour SGR. */
1818static int
1819input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g,
1820    int b)
1821{
1822	struct grid_cell	*gc = &ictx->cell.cell;
1823
1824	if (r == -1 || r > 255)
1825		return (0);
1826	if (g == -1 || g > 255)
1827		return (0);
1828	if (b == -1 || b > 255)
1829		return (0);
1830
1831	if (fgbg == 38)
1832		gc->fg = colour_join_rgb(r, g, b);
1833	else if (fgbg == 48)
1834		gc->bg = colour_join_rgb(r, g, b);
1835	return (1);
1836}
1837
1838/* Handle CSI SGR for RGB colours. */
1839static void
1840input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
1841{
1842	int	r, g, b;
1843
1844	r = input_get(ictx, (*i) + 1, 0, -1);
1845	g = input_get(ictx, (*i) + 2, 0, -1);
1846	b = input_get(ictx, (*i) + 3, 0, -1);
1847	if (input_csi_dispatch_sgr_rgb_do(ictx, fgbg, r, g, b))
1848		(*i) += 3;
1849}
1850
1851/* Handle CSI SGR with a ISO parameter. */
1852static void
1853input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
1854{
1855	struct grid_cell	*gc = &ictx->cell.cell;
1856	char			*s = ictx->param_list[i].str, *copy, *ptr, *out;
1857	int			 p[8];
1858	u_int			 n;
1859	const char		*errstr;
1860
1861	for (n = 0; n < nitems(p); n++)
1862		p[n] = -1;
1863	n = 0;
1864
1865	ptr = copy = xstrdup(s);
1866	while ((out = strsep(&ptr, ":")) != NULL) {
1867		if (*out != '\0') {
1868			p[n++] = strtonum(out, 0, INT_MAX, &errstr);
1869			if (errstr != NULL || n == nitems(p)) {
1870				free(copy);
1871				return;
1872			}
1873		} else
1874			n++;
1875		log_debug("%s: %u = %d", __func__, n - 1, p[n - 1]);
1876	}
1877	free(copy);
1878
1879	if (n == 0)
1880		return;
1881	if (p[0] == 4) {
1882		if (n != 2)
1883			return;
1884		switch (p[1]) {
1885		case 0:
1886			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1887			break;
1888		case 1:
1889			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1890			gc->attr |= GRID_ATTR_UNDERSCORE;
1891			break;
1892		case 2:
1893			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1894			gc->attr |= GRID_ATTR_UNDERSCORE_2;
1895			break;
1896		case 3:
1897			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1898			gc->attr |= GRID_ATTR_UNDERSCORE_3;
1899			break;
1900		case 4:
1901			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1902			gc->attr |= GRID_ATTR_UNDERSCORE_4;
1903			break;
1904		case 5:
1905			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1906			gc->attr |= GRID_ATTR_UNDERSCORE_5;
1907			break;
1908		}
1909		return;
1910	}
1911	if (p[0] != 38 && p[0] != 48)
1912		return;
1913	if (p[1] == -1)
1914		i = 2;
1915	else
1916		i = 1;
1917	switch (p[i]) {
1918	case 2:
1919		if (n < i + 4)
1920			break;
1921		input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[i + 1], p[i + 2],
1922		    p[i + 3]);
1923		break;
1924	case 5:
1925		if (n < i + 2)
1926			break;
1927		input_csi_dispatch_sgr_256_do(ictx, p[0], p[i + 1]);
1928		break;
1929	}
1930}
1931
1932/* Handle CSI SGR. */
1933static void
1934input_csi_dispatch_sgr(struct input_ctx *ictx)
1935{
1936	struct grid_cell	*gc = &ictx->cell.cell;
1937	u_int			 i;
1938	int			 n;
1939
1940	if (ictx->param_list_len == 0) {
1941		memcpy(gc, &grid_default_cell, sizeof *gc);
1942		return;
1943	}
1944
1945	for (i = 0; i < ictx->param_list_len; i++) {
1946		if (ictx->param_list[i].type == INPUT_STRING) {
1947			input_csi_dispatch_sgr_colon(ictx, i);
1948			continue;
1949		}
1950		n = input_get(ictx, i, 0, 0);
1951		if (n == -1)
1952			continue;
1953
1954		if (n == 38 || n == 48) {
1955			i++;
1956			switch (input_get(ictx, i, 0, -1)) {
1957			case 2:
1958				input_csi_dispatch_sgr_rgb(ictx, n, &i);
1959				break;
1960			case 5:
1961				input_csi_dispatch_sgr_256(ictx, n, &i);
1962				break;
1963			}
1964			continue;
1965		}
1966
1967		switch (n) {
1968		case 0:
1969			memcpy(gc, &grid_default_cell, sizeof *gc);
1970			break;
1971		case 1:
1972			gc->attr |= GRID_ATTR_BRIGHT;
1973			break;
1974		case 2:
1975			gc->attr |= GRID_ATTR_DIM;
1976			break;
1977		case 3:
1978			gc->attr |= GRID_ATTR_ITALICS;
1979			break;
1980		case 4:
1981			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1982			gc->attr |= GRID_ATTR_UNDERSCORE;
1983			break;
1984		case 5:
1985			gc->attr |= GRID_ATTR_BLINK;
1986			break;
1987		case 7:
1988			gc->attr |= GRID_ATTR_REVERSE;
1989			break;
1990		case 8:
1991			gc->attr |= GRID_ATTR_HIDDEN;
1992			break;
1993		case 9:
1994			gc->attr |= GRID_ATTR_STRIKETHROUGH;
1995			break;
1996		case 22:
1997			gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1998			break;
1999		case 23:
2000			gc->attr &= ~GRID_ATTR_ITALICS;
2001			break;
2002		case 24:
2003			gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2004			break;
2005		case 25:
2006			gc->attr &= ~GRID_ATTR_BLINK;
2007			break;
2008		case 27:
2009			gc->attr &= ~GRID_ATTR_REVERSE;
2010			break;
2011		case 28:
2012			gc->attr &= ~GRID_ATTR_HIDDEN;
2013			break;
2014		case 29:
2015			gc->attr &= ~GRID_ATTR_STRIKETHROUGH;
2016			break;
2017		case 30:
2018		case 31:
2019		case 32:
2020		case 33:
2021		case 34:
2022		case 35:
2023		case 36:
2024		case 37:
2025			gc->fg = n - 30;
2026			break;
2027		case 39:
2028			gc->fg = 8;
2029			break;
2030		case 40:
2031		case 41:
2032		case 42:
2033		case 43:
2034		case 44:
2035		case 45:
2036		case 46:
2037		case 47:
2038			gc->bg = n - 40;
2039			break;
2040		case 49:
2041			gc->bg = 8;
2042			break;
2043		case 90:
2044		case 91:
2045		case 92:
2046		case 93:
2047		case 94:
2048		case 95:
2049		case 96:
2050		case 97:
2051			gc->fg = n;
2052			break;
2053		case 100:
2054		case 101:
2055		case 102:
2056		case 103:
2057		case 104:
2058		case 105:
2059		case 106:
2060		case 107:
2061			gc->bg = n - 10;
2062			break;
2063		}
2064	}
2065}
2066
2067/* End of input with BEL. */
2068static int
2069input_end_bel(struct input_ctx *ictx)
2070{
2071	log_debug("%s", __func__);
2072
2073	ictx->input_end = INPUT_END_BEL;
2074
2075	return (0);
2076}
2077
2078/* DCS string started. */
2079static void
2080input_enter_dcs(struct input_ctx *ictx)
2081{
2082	log_debug("%s", __func__);
2083
2084	input_clear(ictx);
2085	input_start_timer(ictx);
2086	ictx->last = -1;
2087}
2088
2089/* DCS terminator (ST) received. */
2090static int
2091input_dcs_dispatch(struct input_ctx *ictx)
2092{
2093	const char	prefix[] = "tmux;";
2094	const u_int	prefix_len = (sizeof prefix) - 1;
2095
2096	if (ictx->flags & INPUT_DISCARD)
2097		return (0);
2098
2099	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2100
2101	/* Check for tmux prefix. */
2102	if (ictx->input_len >= prefix_len &&
2103	    strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
2104		screen_write_rawstring(&ictx->ctx,
2105		    ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
2106	}
2107
2108	return (0);
2109}
2110
2111/* OSC string started. */
2112static void
2113input_enter_osc(struct input_ctx *ictx)
2114{
2115	log_debug("%s", __func__);
2116
2117	input_clear(ictx);
2118	input_start_timer(ictx);
2119	ictx->last = -1;
2120}
2121
2122/* OSC terminator (ST) received. */
2123static void
2124input_exit_osc(struct input_ctx *ictx)
2125{
2126	u_char	*p = ictx->input_buf;
2127	u_int	 option;
2128
2129	if (ictx->flags & INPUT_DISCARD)
2130		return;
2131	if (ictx->input_len < 1 || *p < '0' || *p > '9')
2132		return;
2133
2134	log_debug("%s: \"%s\" (end %s)", __func__, p,
2135	    ictx->input_end == INPUT_END_ST ? "ST" : "BEL");
2136
2137	option = 0;
2138	while (*p >= '0' && *p <= '9')
2139		option = option * 10 + *p++ - '0';
2140	if (*p == ';')
2141		p++;
2142
2143	switch (option) {
2144	case 0:
2145	case 2:
2146		if (utf8_isvalid(p)) {
2147			screen_set_title(ictx->ctx.s, p);
2148			server_status_window(ictx->wp->window);
2149		}
2150		break;
2151	case 4:
2152		input_osc_4(ictx, p);
2153		break;
2154	case 10:
2155		input_osc_10(ictx, p);
2156		break;
2157	case 11:
2158		input_osc_11(ictx, p);
2159		break;
2160	case 12:
2161		if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
2162			screen_set_cursor_colour(ictx->ctx.s, p);
2163		break;
2164	case 52:
2165		input_osc_52(ictx, p);
2166		break;
2167	case 104:
2168		input_osc_104(ictx, p);
2169		break;
2170	case 112:
2171		if (*p == '\0') /* no arguments allowed */
2172			screen_set_cursor_colour(ictx->ctx.s, "");
2173		break;
2174	default:
2175		log_debug("%s: unknown '%u'", __func__, option);
2176		break;
2177	}
2178}
2179
2180/* APC string started. */
2181static void
2182input_enter_apc(struct input_ctx *ictx)
2183{
2184	log_debug("%s", __func__);
2185
2186	input_clear(ictx);
2187	input_start_timer(ictx);
2188	ictx->last = -1;
2189}
2190
2191/* APC terminator (ST) received. */
2192static void
2193input_exit_apc(struct input_ctx *ictx)
2194{
2195	if (ictx->flags & INPUT_DISCARD)
2196		return;
2197	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2198
2199	if (!utf8_isvalid(ictx->input_buf))
2200		return;
2201	screen_set_title(ictx->ctx.s, ictx->input_buf);
2202	server_status_window(ictx->wp->window);
2203}
2204
2205/* Rename string started. */
2206static void
2207input_enter_rename(struct input_ctx *ictx)
2208{
2209	log_debug("%s", __func__);
2210
2211	input_clear(ictx);
2212	input_start_timer(ictx);
2213	ictx->last = -1;
2214}
2215
2216/* Rename terminator (ST) received. */
2217static void
2218input_exit_rename(struct input_ctx *ictx)
2219{
2220	if (ictx->flags & INPUT_DISCARD)
2221		return;
2222	if (!options_get_number(ictx->wp->window->options, "allow-rename"))
2223		return;
2224	log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2225
2226	if (!utf8_isvalid(ictx->input_buf))
2227		return;
2228	window_set_name(ictx->wp->window, ictx->input_buf);
2229	options_set_number(ictx->wp->window->options, "automatic-rename", 0);
2230	server_status_window(ictx->wp->window);
2231}
2232
2233/* Open UTF-8 character. */
2234static int
2235input_top_bit_set(struct input_ctx *ictx)
2236{
2237	struct utf8_data	*ud = &ictx->utf8data;
2238
2239	ictx->last = -1;
2240
2241	if (!ictx->utf8started) {
2242		if (utf8_open(ud, ictx->ch) != UTF8_MORE)
2243			return (0);
2244		ictx->utf8started = 1;
2245		return (0);
2246	}
2247
2248	switch (utf8_append(ud, ictx->ch)) {
2249	case UTF8_MORE:
2250		return (0);
2251	case UTF8_ERROR:
2252		ictx->utf8started = 0;
2253		return (0);
2254	case UTF8_DONE:
2255		break;
2256	}
2257	ictx->utf8started = 0;
2258
2259	log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
2260	    (int)ud->size, ud->data, ud->width);
2261
2262	utf8_copy(&ictx->cell.cell.data, ud);
2263	screen_write_collect_add(&ictx->ctx, &ictx->cell.cell);
2264
2265	return (0);
2266}
2267
2268/* Handle the OSC 4 sequence for setting (multiple) palette entries. */
2269static void
2270input_osc_4(struct input_ctx *ictx, const char *p)
2271{
2272	struct window_pane	*wp = ictx->wp;
2273	char			*copy, *s, *next = NULL;
2274	long	 		idx;
2275	u_int			 r, g, b;
2276
2277	copy = s = xstrdup(p);
2278	while (s != NULL && *s != '\0') {
2279		idx = strtol(s, &next, 10);
2280		if (*next++ != ';')
2281			goto bad;
2282		if (idx < 0 || idx >= 0x100)
2283			goto bad;
2284
2285		s = strsep(&next, ";");
2286		if (sscanf(s, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) {
2287			s = next;
2288			continue;
2289		}
2290
2291		window_pane_set_palette(wp, idx, colour_join_rgb(r, g, b));
2292		s = next;
2293	}
2294
2295	free(copy);
2296	return;
2297
2298bad:
2299	log_debug("bad OSC 4: %s", p);
2300	free(copy);
2301}
2302
2303/* Handle the OSC 10 sequence for setting foreground colour. */
2304static void
2305input_osc_10(struct input_ctx *ictx, const char *p)
2306{
2307	struct window_pane	*wp = ictx->wp;
2308	u_int			 r, g, b;
2309
2310	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2311	    goto bad;
2312
2313	wp->colgc.fg = colour_join_rgb(r, g, b);
2314	wp->flags |= PANE_REDRAW;
2315
2316	return;
2317
2318bad:
2319	log_debug("bad OSC 10: %s", p);
2320}
2321
2322/* Handle the OSC 11 sequence for setting background colour. */
2323static void
2324input_osc_11(struct input_ctx *ictx, const char *p)
2325{
2326	struct window_pane	*wp = ictx->wp;
2327	u_int			 r, g, b;
2328
2329	if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2330	    goto bad;
2331
2332	wp->colgc.bg = colour_join_rgb(r, g, b);
2333	wp->flags |= PANE_REDRAW;
2334
2335	return;
2336
2337bad:
2338	log_debug("bad OSC 11: %s", p);
2339}
2340
2341/* Handle the OSC 52 sequence for setting the clipboard. */
2342static void
2343input_osc_52(struct input_ctx *ictx, const char *p)
2344{
2345	struct window_pane	*wp = ictx->wp;
2346	char			*end;
2347	const char		*buf;
2348	size_t			 len;
2349	u_char			*out;
2350	int			 outlen, state;
2351	struct screen_write_ctx	 ctx;
2352	struct paste_buffer	*pb;
2353
2354	state = options_get_number(global_options, "set-clipboard");
2355	if (state != 2)
2356		return;
2357
2358	if ((end = strchr(p, ';')) == NULL)
2359		return;
2360	end++;
2361	if (*end == '\0')
2362		return;
2363	log_debug("%s: %s", __func__, end);
2364
2365	if (strcmp(end, "?") == 0) {
2366		if ((pb = paste_get_top(NULL)) != NULL) {
2367			buf = paste_buffer_data(pb, &len);
2368			outlen = 4 * ((len + 2) / 3) + 1;
2369			out = xmalloc(outlen);
2370			if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
2371				abort();
2372				free(out);
2373				return;
2374			}
2375		} else {
2376			outlen = 0;
2377			out = NULL;
2378		}
2379		bufferevent_write(wp->event, "\033]52;;", 6);
2380		if (outlen != 0)
2381			bufferevent_write(wp->event, out, outlen);
2382		if (ictx->input_end == INPUT_END_BEL)
2383			bufferevent_write(wp->event, "\007", 1);
2384		else
2385			bufferevent_write(wp->event, "\033\\", 2);
2386		free(out);
2387		return;
2388	}
2389
2390	len = (strlen(end) / 4) * 3;
2391	if (len == 0)
2392		return;
2393
2394	out = xmalloc(len);
2395	if ((outlen = b64_pton(end, out, len)) == -1) {
2396		free(out);
2397		return;
2398	}
2399
2400	screen_write_start(&ctx, wp, NULL);
2401	screen_write_setselection(&ctx, out, outlen);
2402	screen_write_stop(&ctx);
2403	notify_pane("pane-set-clipboard", wp);
2404
2405	paste_add(out, outlen);
2406}
2407
2408/* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
2409static void
2410input_osc_104(struct input_ctx *ictx, const char *p)
2411{
2412	struct window_pane	*wp = ictx->wp;
2413	char			*copy, *s;
2414	long			idx;
2415
2416	if (*p == '\0') {
2417		window_pane_reset_palette(wp);
2418		return;
2419	}
2420
2421	copy = s = xstrdup(p);
2422	while (*s != '\0') {
2423		idx = strtol(s, &s, 10);
2424		if (*s != '\0' && *s != ';')
2425			goto bad;
2426		if (idx < 0 || idx >= 0x100)
2427			goto bad;
2428
2429		window_pane_unset_palette(wp, idx);
2430		if (*s == ';')
2431			s++;
2432	}
2433	free(copy);
2434	return;
2435
2436bad:
2437	log_debug("bad OSC 104: %s", p);
2438	free(copy);
2439}
2440