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