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