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