Fix cursor position after zero width space, GitHub issue 3469.
[tmux-openbsd.git] / input.c
blobadbea1790feecee2739f48d3945c96d644d4bf03
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
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.
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.
19 #include <sys/types.h>
21 #include <netinet/in.h>
23 #include <ctype.h>
24 #include <resolv.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
29 #include "tmux.h"
32 * Based on the description by Paul Williams at:
34 * https://vt100.net/emu/dec_ansi_parser
36 * With the following changes:
38 * - 7-bit only.
40 * - Support for UTF-8.
42 * - OSC (but not APC) may be terminated by \007 as well as ST.
44 * - A state for APC similar to OSC. Some terminals appear to use this to set
45 * the title.
47 * - A state for the screen \033k...\033\\ sequence to rename a window. This is
48 * pretty stupid but not supporting it is more trouble than it is worth.
50 * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
51 * be passed to the underlying terminals.
54 /* Input parser cell. */
55 struct input_cell {
56 struct grid_cell cell;
57 int set;
58 int g0set; /* 1 if ACS */
59 int g1set; /* 1 if ACS */
62 /* Input parser argument. */
63 struct input_param {
64 enum {
65 INPUT_MISSING,
66 INPUT_NUMBER,
67 INPUT_STRING
68 } type;
69 union {
70 int num;
71 char *str;
75 /* Input parser context. */
76 struct input_ctx {
77 struct window_pane *wp;
78 struct bufferevent *event;
79 struct screen_write_ctx ctx;
80 struct colour_palette *palette;
82 struct input_cell cell;
84 struct input_cell old_cell;
85 u_int old_cx;
86 u_int old_cy;
87 int old_mode;
89 u_char interm_buf[4];
90 size_t interm_len;
92 u_char param_buf[64];
93 size_t param_len;
95 #define INPUT_BUF_START 32
96 #define INPUT_BUF_LIMIT 1048576
97 u_char *input_buf;
98 size_t input_len;
99 size_t input_space;
100 enum {
101 INPUT_END_ST,
102 INPUT_END_BEL
103 } input_end;
105 struct input_param param_list[24];
106 u_int param_list_len;
108 struct utf8_data utf8data;
109 int utf8started;
111 int ch;
112 int last;
114 int flags;
115 #define INPUT_DISCARD 0x1
117 const struct input_state *state;
119 struct event timer;
122 * All input received since we were last in the ground state. Sent to
123 * control clients on connection.
125 struct evbuffer *since_ground;
128 /* Helper functions. */
129 struct input_transition;
130 static int input_split(struct input_ctx *);
131 static int input_get(struct input_ctx *, u_int, int, int);
132 static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
133 static void input_set_state(struct input_ctx *,
134 const struct input_transition *);
135 static void input_reset_cell(struct input_ctx *);
137 static void input_osc_4(struct input_ctx *, const char *);
138 static void input_osc_8(struct input_ctx *, const char *);
139 static void input_osc_10(struct input_ctx *, const char *);
140 static void input_osc_11(struct input_ctx *, const char *);
141 static void input_osc_12(struct input_ctx *, const char *);
142 static void input_osc_52(struct input_ctx *, const char *);
143 static void input_osc_104(struct input_ctx *, const char *);
144 static void input_osc_110(struct input_ctx *, const char *);
145 static void input_osc_111(struct input_ctx *, const char *);
146 static void input_osc_112(struct input_ctx *, const char *);
148 /* Transition entry/exit handlers. */
149 static void input_clear(struct input_ctx *);
150 static void input_ground(struct input_ctx *);
151 static void input_enter_dcs(struct input_ctx *);
152 static void input_enter_osc(struct input_ctx *);
153 static void input_exit_osc(struct input_ctx *);
154 static void input_enter_apc(struct input_ctx *);
155 static void input_exit_apc(struct input_ctx *);
156 static void input_enter_rename(struct input_ctx *);
157 static void input_exit_rename(struct input_ctx *);
159 /* Input state handlers. */
160 static int input_print(struct input_ctx *);
161 static int input_intermediate(struct input_ctx *);
162 static int input_parameter(struct input_ctx *);
163 static int input_input(struct input_ctx *);
164 static int input_c0_dispatch(struct input_ctx *);
165 static int input_esc_dispatch(struct input_ctx *);
166 static int input_csi_dispatch(struct input_ctx *);
167 static void input_csi_dispatch_rm(struct input_ctx *);
168 static void input_csi_dispatch_rm_private(struct input_ctx *);
169 static void input_csi_dispatch_sm(struct input_ctx *);
170 static void input_csi_dispatch_sm_private(struct input_ctx *);
171 static void input_csi_dispatch_winops(struct input_ctx *);
172 static void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
173 static void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
174 static void input_csi_dispatch_sgr(struct input_ctx *);
175 static int input_dcs_dispatch(struct input_ctx *);
176 static int input_top_bit_set(struct input_ctx *);
177 static int input_end_bel(struct input_ctx *);
179 /* Command table comparison function. */
180 static int input_table_compare(const void *, const void *);
182 /* Command table entry. */
183 struct input_table_entry {
184 int ch;
185 const char *interm;
186 int type;
189 /* Escape commands. */
190 enum input_esc_type {
191 INPUT_ESC_DECALN,
192 INPUT_ESC_DECKPAM,
193 INPUT_ESC_DECKPNM,
194 INPUT_ESC_DECRC,
195 INPUT_ESC_DECSC,
196 INPUT_ESC_HTS,
197 INPUT_ESC_IND,
198 INPUT_ESC_NEL,
199 INPUT_ESC_RI,
200 INPUT_ESC_RIS,
201 INPUT_ESC_SCSG0_OFF,
202 INPUT_ESC_SCSG0_ON,
203 INPUT_ESC_SCSG1_OFF,
204 INPUT_ESC_SCSG1_ON,
205 INPUT_ESC_ST,
208 /* Escape command table. */
209 static const struct input_table_entry input_esc_table[] = {
210 { '0', "(", INPUT_ESC_SCSG0_ON },
211 { '0', ")", INPUT_ESC_SCSG1_ON },
212 { '7', "", INPUT_ESC_DECSC },
213 { '8', "", INPUT_ESC_DECRC },
214 { '8', "#", INPUT_ESC_DECALN },
215 { '=', "", INPUT_ESC_DECKPAM },
216 { '>', "", INPUT_ESC_DECKPNM },
217 { 'B', "(", INPUT_ESC_SCSG0_OFF },
218 { 'B', ")", INPUT_ESC_SCSG1_OFF },
219 { 'D', "", INPUT_ESC_IND },
220 { 'E', "", INPUT_ESC_NEL },
221 { 'H', "", INPUT_ESC_HTS },
222 { 'M', "", INPUT_ESC_RI },
223 { '\\', "", INPUT_ESC_ST },
224 { 'c', "", INPUT_ESC_RIS },
227 /* Control (CSI) commands. */
228 enum input_csi_type {
229 INPUT_CSI_CBT,
230 INPUT_CSI_CNL,
231 INPUT_CSI_CPL,
232 INPUT_CSI_CUB,
233 INPUT_CSI_CUD,
234 INPUT_CSI_CUF,
235 INPUT_CSI_CUP,
236 INPUT_CSI_CUU,
237 INPUT_CSI_DA,
238 INPUT_CSI_DA_TWO,
239 INPUT_CSI_DCH,
240 INPUT_CSI_DECSCUSR,
241 INPUT_CSI_DECSTBM,
242 INPUT_CSI_DL,
243 INPUT_CSI_DSR,
244 INPUT_CSI_ECH,
245 INPUT_CSI_ED,
246 INPUT_CSI_EL,
247 INPUT_CSI_HPA,
248 INPUT_CSI_ICH,
249 INPUT_CSI_IL,
250 INPUT_CSI_MODOFF,
251 INPUT_CSI_MODSET,
252 INPUT_CSI_RCP,
253 INPUT_CSI_REP,
254 INPUT_CSI_RM,
255 INPUT_CSI_RM_PRIVATE,
256 INPUT_CSI_SCP,
257 INPUT_CSI_SD,
258 INPUT_CSI_SGR,
259 INPUT_CSI_SM,
260 INPUT_CSI_SM_PRIVATE,
261 INPUT_CSI_SU,
262 INPUT_CSI_TBC,
263 INPUT_CSI_VPA,
264 INPUT_CSI_WINOPS,
265 INPUT_CSI_XDA,
268 /* Control (CSI) command table. */
269 static const struct input_table_entry input_csi_table[] = {
270 { '@', "", INPUT_CSI_ICH },
271 { 'A', "", INPUT_CSI_CUU },
272 { 'B', "", INPUT_CSI_CUD },
273 { 'C', "", INPUT_CSI_CUF },
274 { 'D', "", INPUT_CSI_CUB },
275 { 'E', "", INPUT_CSI_CNL },
276 { 'F', "", INPUT_CSI_CPL },
277 { 'G', "", INPUT_CSI_HPA },
278 { 'H', "", INPUT_CSI_CUP },
279 { 'J', "", INPUT_CSI_ED },
280 { 'K', "", INPUT_CSI_EL },
281 { 'L', "", INPUT_CSI_IL },
282 { 'M', "", INPUT_CSI_DL },
283 { 'P', "", INPUT_CSI_DCH },
284 { 'S', "", INPUT_CSI_SU },
285 { 'T', "", INPUT_CSI_SD },
286 { 'X', "", INPUT_CSI_ECH },
287 { 'Z', "", INPUT_CSI_CBT },
288 { '`', "", INPUT_CSI_HPA },
289 { 'b', "", INPUT_CSI_REP },
290 { 'c', "", INPUT_CSI_DA },
291 { 'c', ">", INPUT_CSI_DA_TWO },
292 { 'd', "", INPUT_CSI_VPA },
293 { 'f', "", INPUT_CSI_CUP },
294 { 'g', "", INPUT_CSI_TBC },
295 { 'h', "", INPUT_CSI_SM },
296 { 'h', "?", INPUT_CSI_SM_PRIVATE },
297 { 'l', "", INPUT_CSI_RM },
298 { 'l', "?", INPUT_CSI_RM_PRIVATE },
299 { 'm', "", INPUT_CSI_SGR },
300 { 'm', ">", INPUT_CSI_MODSET },
301 { 'n', "", INPUT_CSI_DSR },
302 { 'n', ">", INPUT_CSI_MODOFF },
303 { 'q', " ", INPUT_CSI_DECSCUSR },
304 { 'q', ">", INPUT_CSI_XDA },
305 { 'r', "", INPUT_CSI_DECSTBM },
306 { 's', "", INPUT_CSI_SCP },
307 { 't', "", INPUT_CSI_WINOPS },
308 { 'u', "", INPUT_CSI_RCP },
311 /* Input transition. */
312 struct input_transition {
313 int first;
314 int last;
316 int (*handler)(struct input_ctx *);
317 const struct input_state *state;
320 /* Input state. */
321 struct input_state {
322 const char *name;
323 void (*enter)(struct input_ctx *);
324 void (*exit)(struct input_ctx *);
325 const struct input_transition *transitions;
328 /* State transitions available from all states. */
329 #define INPUT_STATE_ANYWHERE \
330 { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
331 { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
332 { 0x1b, 0x1b, NULL, &input_state_esc_enter }
334 /* Forward declarations of state tables. */
335 static const struct input_transition input_state_ground_table[];
336 static const struct input_transition input_state_esc_enter_table[];
337 static const struct input_transition input_state_esc_intermediate_table[];
338 static const struct input_transition input_state_csi_enter_table[];
339 static const struct input_transition input_state_csi_parameter_table[];
340 static const struct input_transition input_state_csi_intermediate_table[];
341 static const struct input_transition input_state_csi_ignore_table[];
342 static const struct input_transition input_state_dcs_enter_table[];
343 static const struct input_transition input_state_dcs_parameter_table[];
344 static const struct input_transition input_state_dcs_intermediate_table[];
345 static const struct input_transition input_state_dcs_handler_table[];
346 static const struct input_transition input_state_dcs_escape_table[];
347 static const struct input_transition input_state_dcs_ignore_table[];
348 static const struct input_transition input_state_osc_string_table[];
349 static const struct input_transition input_state_apc_string_table[];
350 static const struct input_transition input_state_rename_string_table[];
351 static const struct input_transition input_state_consume_st_table[];
353 /* ground state definition. */
354 static const struct input_state input_state_ground = {
355 "ground",
356 input_ground, NULL,
357 input_state_ground_table
360 /* esc_enter state definition. */
361 static const struct input_state input_state_esc_enter = {
362 "esc_enter",
363 input_clear, NULL,
364 input_state_esc_enter_table
367 /* esc_intermediate state definition. */
368 static const struct input_state input_state_esc_intermediate = {
369 "esc_intermediate",
370 NULL, NULL,
371 input_state_esc_intermediate_table
374 /* csi_enter state definition. */
375 static const struct input_state input_state_csi_enter = {
376 "csi_enter",
377 input_clear, NULL,
378 input_state_csi_enter_table
381 /* csi_parameter state definition. */
382 static const struct input_state input_state_csi_parameter = {
383 "csi_parameter",
384 NULL, NULL,
385 input_state_csi_parameter_table
388 /* csi_intermediate state definition. */
389 static const struct input_state input_state_csi_intermediate = {
390 "csi_intermediate",
391 NULL, NULL,
392 input_state_csi_intermediate_table
395 /* csi_ignore state definition. */
396 static const struct input_state input_state_csi_ignore = {
397 "csi_ignore",
398 NULL, NULL,
399 input_state_csi_ignore_table
402 /* dcs_enter state definition. */
403 static const struct input_state input_state_dcs_enter = {
404 "dcs_enter",
405 input_enter_dcs, NULL,
406 input_state_dcs_enter_table
409 /* dcs_parameter state definition. */
410 static const struct input_state input_state_dcs_parameter = {
411 "dcs_parameter",
412 NULL, NULL,
413 input_state_dcs_parameter_table
416 /* dcs_intermediate state definition. */
417 static const struct input_state input_state_dcs_intermediate = {
418 "dcs_intermediate",
419 NULL, NULL,
420 input_state_dcs_intermediate_table
423 /* dcs_handler state definition. */
424 static const struct input_state input_state_dcs_handler = {
425 "dcs_handler",
426 NULL, NULL,
427 input_state_dcs_handler_table
430 /* dcs_escape state definition. */
431 static const struct input_state input_state_dcs_escape = {
432 "dcs_escape",
433 NULL, NULL,
434 input_state_dcs_escape_table
437 /* dcs_ignore state definition. */
438 static const struct input_state input_state_dcs_ignore = {
439 "dcs_ignore",
440 NULL, NULL,
441 input_state_dcs_ignore_table
444 /* osc_string state definition. */
445 static const struct input_state input_state_osc_string = {
446 "osc_string",
447 input_enter_osc, input_exit_osc,
448 input_state_osc_string_table
451 /* apc_string state definition. */
452 static const struct input_state input_state_apc_string = {
453 "apc_string",
454 input_enter_apc, input_exit_apc,
455 input_state_apc_string_table
458 /* rename_string state definition. */
459 static const struct input_state input_state_rename_string = {
460 "rename_string",
461 input_enter_rename, input_exit_rename,
462 input_state_rename_string_table
465 /* consume_st state definition. */
466 static const struct input_state input_state_consume_st = {
467 "consume_st",
468 input_enter_rename, NULL, /* rename also waits for ST */
469 input_state_consume_st_table
472 /* ground state table. */
473 static const struct input_transition input_state_ground_table[] = {
474 INPUT_STATE_ANYWHERE,
476 { 0x00, 0x17, input_c0_dispatch, NULL },
477 { 0x19, 0x19, input_c0_dispatch, NULL },
478 { 0x1c, 0x1f, input_c0_dispatch, NULL },
479 { 0x20, 0x7e, input_print, NULL },
480 { 0x7f, 0x7f, NULL, NULL },
481 { 0x80, 0xff, input_top_bit_set, NULL },
483 { -1, -1, NULL, NULL }
486 /* esc_enter state table. */
487 static const struct input_transition input_state_esc_enter_table[] = {
488 INPUT_STATE_ANYWHERE,
490 { 0x00, 0x17, input_c0_dispatch, NULL },
491 { 0x19, 0x19, input_c0_dispatch, NULL },
492 { 0x1c, 0x1f, input_c0_dispatch, NULL },
493 { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
494 { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
495 { 0x50, 0x50, NULL, &input_state_dcs_enter },
496 { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
497 { 0x58, 0x58, NULL, &input_state_consume_st },
498 { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
499 { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
500 { 0x5b, 0x5b, NULL, &input_state_csi_enter },
501 { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
502 { 0x5d, 0x5d, NULL, &input_state_osc_string },
503 { 0x5e, 0x5e, NULL, &input_state_consume_st },
504 { 0x5f, 0x5f, NULL, &input_state_apc_string },
505 { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
506 { 0x6b, 0x6b, NULL, &input_state_rename_string },
507 { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground },
508 { 0x7f, 0xff, NULL, NULL },
510 { -1, -1, NULL, NULL }
513 /* esc_intermediate state table. */
514 static const struct input_transition input_state_esc_intermediate_table[] = {
515 INPUT_STATE_ANYWHERE,
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, NULL },
521 { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
522 { 0x7f, 0xff, NULL, NULL },
524 { -1, -1, NULL, NULL }
527 /* csi_enter state table. */
528 static const struct input_transition input_state_csi_enter_table[] = {
529 INPUT_STATE_ANYWHERE,
531 { 0x00, 0x17, input_c0_dispatch, NULL },
532 { 0x19, 0x19, input_c0_dispatch, NULL },
533 { 0x1c, 0x1f, input_c0_dispatch, NULL },
534 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
535 { 0x30, 0x39, input_parameter, &input_state_csi_parameter },
536 { 0x3a, 0x3a, input_parameter, &input_state_csi_parameter },
537 { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter },
538 { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
539 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
540 { 0x7f, 0xff, NULL, NULL },
542 { -1, -1, NULL, NULL }
545 /* csi_parameter state table. */
546 static const struct input_transition input_state_csi_parameter_table[] = {
547 INPUT_STATE_ANYWHERE,
549 { 0x00, 0x17, input_c0_dispatch, NULL },
550 { 0x19, 0x19, input_c0_dispatch, NULL },
551 { 0x1c, 0x1f, input_c0_dispatch, NULL },
552 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
553 { 0x30, 0x39, input_parameter, NULL },
554 { 0x3a, 0x3a, input_parameter, NULL },
555 { 0x3b, 0x3b, input_parameter, NULL },
556 { 0x3c, 0x3f, NULL, &input_state_csi_ignore },
557 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
558 { 0x7f, 0xff, NULL, NULL },
560 { -1, -1, NULL, NULL }
563 /* csi_intermediate state table. */
564 static const struct input_transition input_state_csi_intermediate_table[] = {
565 INPUT_STATE_ANYWHERE,
567 { 0x00, 0x17, input_c0_dispatch, NULL },
568 { 0x19, 0x19, input_c0_dispatch, NULL },
569 { 0x1c, 0x1f, input_c0_dispatch, NULL },
570 { 0x20, 0x2f, input_intermediate, NULL },
571 { 0x30, 0x3f, NULL, &input_state_csi_ignore },
572 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
573 { 0x7f, 0xff, NULL, NULL },
575 { -1, -1, NULL, NULL }
578 /* csi_ignore state table. */
579 static const struct input_transition input_state_csi_ignore_table[] = {
580 INPUT_STATE_ANYWHERE,
582 { 0x00, 0x17, input_c0_dispatch, NULL },
583 { 0x19, 0x19, input_c0_dispatch, NULL },
584 { 0x1c, 0x1f, input_c0_dispatch, NULL },
585 { 0x20, 0x3f, NULL, NULL },
586 { 0x40, 0x7e, NULL, &input_state_ground },
587 { 0x7f, 0xff, NULL, NULL },
589 { -1, -1, NULL, NULL }
592 /* dcs_enter state table. */
593 static const struct input_transition input_state_dcs_enter_table[] = {
594 INPUT_STATE_ANYWHERE,
596 { 0x00, 0x17, NULL, NULL },
597 { 0x19, 0x19, NULL, NULL },
598 { 0x1c, 0x1f, NULL, NULL },
599 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
600 { 0x30, 0x39, input_parameter, &input_state_dcs_parameter },
601 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
602 { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
603 { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
604 { 0x40, 0x7e, input_input, &input_state_dcs_handler },
605 { 0x7f, 0xff, NULL, NULL },
607 { -1, -1, NULL, NULL }
610 /* dcs_parameter state table. */
611 static const struct input_transition input_state_dcs_parameter_table[] = {
612 INPUT_STATE_ANYWHERE,
614 { 0x00, 0x17, NULL, NULL },
615 { 0x19, 0x19, NULL, NULL },
616 { 0x1c, 0x1f, NULL, NULL },
617 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
618 { 0x30, 0x39, input_parameter, NULL },
619 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
620 { 0x3b, 0x3b, input_parameter, NULL },
621 { 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
622 { 0x40, 0x7e, input_input, &input_state_dcs_handler },
623 { 0x7f, 0xff, NULL, NULL },
625 { -1, -1, NULL, NULL }
628 /* dcs_intermediate state table. */
629 static const struct input_transition input_state_dcs_intermediate_table[] = {
630 INPUT_STATE_ANYWHERE,
632 { 0x00, 0x17, NULL, NULL },
633 { 0x19, 0x19, NULL, NULL },
634 { 0x1c, 0x1f, NULL, NULL },
635 { 0x20, 0x2f, input_intermediate, NULL },
636 { 0x30, 0x3f, NULL, &input_state_dcs_ignore },
637 { 0x40, 0x7e, input_input, &input_state_dcs_handler },
638 { 0x7f, 0xff, NULL, NULL },
640 { -1, -1, NULL, NULL }
643 /* dcs_handler state table. */
644 static const struct input_transition input_state_dcs_handler_table[] = {
645 /* No INPUT_STATE_ANYWHERE */
647 { 0x00, 0x1a, input_input, NULL },
648 { 0x1b, 0x1b, NULL, &input_state_dcs_escape },
649 { 0x1c, 0xff, input_input, NULL },
651 { -1, -1, NULL, NULL }
654 /* dcs_escape state table. */
655 static const struct input_transition input_state_dcs_escape_table[] = {
656 /* No INPUT_STATE_ANYWHERE */
658 { 0x00, 0x5b, input_input, &input_state_dcs_handler },
659 { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
660 { 0x5d, 0xff, input_input, &input_state_dcs_handler },
662 { -1, -1, NULL, NULL }
665 /* dcs_ignore state table. */
666 static const struct input_transition input_state_dcs_ignore_table[] = {
667 INPUT_STATE_ANYWHERE,
669 { 0x00, 0x17, NULL, NULL },
670 { 0x19, 0x19, NULL, NULL },
671 { 0x1c, 0x1f, NULL, NULL },
672 { 0x20, 0xff, NULL, NULL },
674 { -1, -1, NULL, NULL }
677 /* osc_string state table. */
678 static const struct input_transition input_state_osc_string_table[] = {
679 INPUT_STATE_ANYWHERE,
681 { 0x00, 0x06, NULL, NULL },
682 { 0x07, 0x07, input_end_bel, &input_state_ground },
683 { 0x08, 0x17, NULL, NULL },
684 { 0x19, 0x19, NULL, NULL },
685 { 0x1c, 0x1f, NULL, NULL },
686 { 0x20, 0xff, input_input, NULL },
688 { -1, -1, NULL, NULL }
691 /* apc_string state table. */
692 static const struct input_transition input_state_apc_string_table[] = {
693 INPUT_STATE_ANYWHERE,
695 { 0x00, 0x17, NULL, NULL },
696 { 0x19, 0x19, NULL, NULL },
697 { 0x1c, 0x1f, NULL, NULL },
698 { 0x20, 0xff, input_input, NULL },
700 { -1, -1, NULL, NULL }
703 /* rename_string state table. */
704 static const struct input_transition input_state_rename_string_table[] = {
705 INPUT_STATE_ANYWHERE,
707 { 0x00, 0x17, NULL, NULL },
708 { 0x19, 0x19, NULL, NULL },
709 { 0x1c, 0x1f, NULL, NULL },
710 { 0x20, 0xff, input_input, NULL },
712 { -1, -1, NULL, NULL }
715 /* consume_st state table. */
716 static const struct input_transition input_state_consume_st_table[] = {
717 INPUT_STATE_ANYWHERE,
719 { 0x00, 0x17, NULL, NULL },
720 { 0x19, 0x19, NULL, NULL },
721 { 0x1c, 0x1f, NULL, NULL },
722 { 0x20, 0xff, NULL, NULL },
724 { -1, -1, NULL, NULL }
727 /* Input table compare. */
728 static int
729 input_table_compare(const void *key, const void *value)
731 const struct input_ctx *ictx = key;
732 const struct input_table_entry *entry = value;
734 if (ictx->ch != entry->ch)
735 return (ictx->ch - entry->ch);
736 return (strcmp(ictx->interm_buf, entry->interm));
740 * Timer - if this expires then have been waiting for a terminator for too
741 * long, so reset to ground.
743 static void
744 input_timer_callback(__unused int fd, __unused short events, void *arg)
746 struct input_ctx *ictx = arg;
748 log_debug("%s: %s expired" , __func__, ictx->state->name);
749 input_reset(ictx, 0);
752 /* Start the timer. */
753 static void
754 input_start_timer(struct input_ctx *ictx)
756 struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
758 event_del(&ictx->timer);
759 event_add(&ictx->timer, &tv);
762 /* Reset cell state to default. */
763 static void
764 input_reset_cell(struct input_ctx *ictx)
766 memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell);
767 ictx->cell.set = 0;
768 ictx->cell.g0set = ictx->cell.g1set = 0;
770 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
771 ictx->old_cx = 0;
772 ictx->old_cy = 0;
775 /* Save screen state. */
776 static void
777 input_save_state(struct input_ctx *ictx)
779 struct screen_write_ctx *sctx = &ictx->ctx;
780 struct screen *s = sctx->s;
782 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
783 ictx->old_cx = s->cx;
784 ictx->old_cy = s->cy;
785 ictx->old_mode = s->mode;
788 /* Restore screen state. */
789 static void
790 input_restore_state(struct input_ctx *ictx)
792 struct screen_write_ctx *sctx = &ictx->ctx;
794 memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
795 if (ictx->old_mode & MODE_ORIGIN)
796 screen_write_mode_set(sctx, MODE_ORIGIN);
797 else
798 screen_write_mode_clear(sctx, MODE_ORIGIN);
799 screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy, 0);
802 /* Initialise input parser. */
803 struct input_ctx *
804 input_init(struct window_pane *wp, struct bufferevent *bev,
805 struct colour_palette *palette)
807 struct input_ctx *ictx;
809 ictx = xcalloc(1, sizeof *ictx);
810 ictx->wp = wp;
811 ictx->event = bev;
812 ictx->palette = palette;
814 ictx->input_space = INPUT_BUF_START;
815 ictx->input_buf = xmalloc(INPUT_BUF_START);
817 ictx->since_ground = evbuffer_new();
818 if (ictx->since_ground == NULL)
819 fatalx("out of memory");
821 evtimer_set(&ictx->timer, input_timer_callback, ictx);
823 input_reset(ictx, 0);
824 return (ictx);
827 /* Destroy input parser. */
828 void
829 input_free(struct input_ctx *ictx)
831 u_int i;
833 for (i = 0; i < ictx->param_list_len; i++) {
834 if (ictx->param_list[i].type == INPUT_STRING)
835 free(ictx->param_list[i].str);
838 event_del(&ictx->timer);
840 free(ictx->input_buf);
841 evbuffer_free(ictx->since_ground);
843 free(ictx);
846 /* Reset input state and clear screen. */
847 void
848 input_reset(struct input_ctx *ictx, int clear)
850 struct screen_write_ctx *sctx = &ictx->ctx;
851 struct window_pane *wp = ictx->wp;
853 input_reset_cell(ictx);
855 if (clear && wp != NULL) {
856 if (TAILQ_EMPTY(&wp->modes))
857 screen_write_start_pane(sctx, wp, &wp->base);
858 else
859 screen_write_start(sctx, &wp->base);
860 screen_write_reset(sctx);
861 screen_write_stop(sctx);
864 input_clear(ictx);
866 ictx->last = -1;
868 ictx->state = &input_state_ground;
869 ictx->flags = 0;
872 /* Return pending data. */
873 struct evbuffer *
874 input_pending(struct input_ctx *ictx)
876 return (ictx->since_ground);
879 /* Change input state. */
880 static void
881 input_set_state(struct input_ctx *ictx, const struct input_transition *itr)
883 if (ictx->state->exit != NULL)
884 ictx->state->exit(ictx);
885 ictx->state = itr->state;
886 if (ictx->state->enter != NULL)
887 ictx->state->enter(ictx);
890 /* Parse data. */
891 static void
892 input_parse(struct input_ctx *ictx, u_char *buf, size_t len)
894 struct screen_write_ctx *sctx = &ictx->ctx;
895 const struct input_state *state = NULL;
896 const struct input_transition *itr = NULL;
897 size_t off = 0;
899 /* Parse the input. */
900 while (off < len) {
901 ictx->ch = buf[off++];
903 /* Find the transition. */
904 if (ictx->state != state ||
905 itr == NULL ||
906 ictx->ch < itr->first ||
907 ictx->ch > itr->last) {
908 itr = ictx->state->transitions;
909 while (itr->first != -1 && itr->last != -1) {
910 if (ictx->ch >= itr->first &&
911 ictx->ch <= itr->last)
912 break;
913 itr++;
915 if (itr->first == -1 || itr->last == -1) {
916 /* No transition? Eh? */
917 fatalx("no transition from state");
920 state = ictx->state;
923 * Any state except print stops the current collection. This is
924 * an optimization to avoid checking if the attributes have
925 * changed for every character. It will stop unnecessarily for
926 * sequences that don't make a terminal change, but they should
927 * be the minority.
929 if (itr->handler != input_print)
930 screen_write_collect_end(sctx);
933 * Execute the handler, if any. Don't switch state if it
934 * returns non-zero.
936 if (itr->handler != NULL && itr->handler(ictx) != 0)
937 continue;
939 /* And switch state, if necessary. */
940 if (itr->state != NULL)
941 input_set_state(ictx, itr);
943 /* If not in ground state, save input. */
944 if (ictx->state != &input_state_ground)
945 evbuffer_add(ictx->since_ground, &ictx->ch, 1);
949 /* Parse input from pane. */
950 void
951 input_parse_pane(struct window_pane *wp)
953 void *new_data;
954 size_t new_size;
956 new_data = window_pane_get_new_data(wp, &wp->offset, &new_size);
957 input_parse_buffer(wp, new_data, new_size);
958 window_pane_update_used_data(wp, &wp->offset, new_size);
961 /* Parse given input. */
962 void
963 input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
965 struct input_ctx *ictx = wp->ictx;
966 struct screen_write_ctx *sctx = &ictx->ctx;
968 if (len == 0)
969 return;
971 window_update_activity(wp->window);
972 wp->flags |= PANE_CHANGED;
974 /* NULL wp if there is a mode set as don't want to update the tty. */
975 if (TAILQ_EMPTY(&wp->modes))
976 screen_write_start_pane(sctx, wp, &wp->base);
977 else
978 screen_write_start(sctx, &wp->base);
980 log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
981 ictx->state->name, len, (int)len, buf);
983 input_parse(ictx, buf, len);
984 screen_write_stop(sctx);
987 /* Parse given input for screen. */
988 void
989 input_parse_screen(struct input_ctx *ictx, struct screen *s,
990 screen_write_init_ctx_cb cb, void *arg, u_char *buf, size_t len)
992 struct screen_write_ctx *sctx = &ictx->ctx;
994 if (len == 0)
995 return;
997 screen_write_start_callback(sctx, s, cb, arg);
998 input_parse(ictx, buf, len);
999 screen_write_stop(sctx);
1002 /* Split the parameter list (if any). */
1003 static int
1004 input_split(struct input_ctx *ictx)
1006 const char *errstr;
1007 char *ptr, *out;
1008 struct input_param *ip;
1009 u_int i;
1011 for (i = 0; i < ictx->param_list_len; i++) {
1012 if (ictx->param_list[i].type == INPUT_STRING)
1013 free(ictx->param_list[i].str);
1015 ictx->param_list_len = 0;
1017 if (ictx->param_len == 0)
1018 return (0);
1019 ip = &ictx->param_list[0];
1021 ptr = ictx->param_buf;
1022 while ((out = strsep(&ptr, ";")) != NULL) {
1023 if (*out == '\0')
1024 ip->type = INPUT_MISSING;
1025 else {
1026 if (strchr(out, ':') != NULL) {
1027 ip->type = INPUT_STRING;
1028 ip->str = xstrdup(out);
1029 } else {
1030 ip->type = INPUT_NUMBER;
1031 ip->num = strtonum(out, 0, INT_MAX, &errstr);
1032 if (errstr != NULL)
1033 return (-1);
1036 ip = &ictx->param_list[++ictx->param_list_len];
1037 if (ictx->param_list_len == nitems(ictx->param_list))
1038 return (-1);
1041 for (i = 0; i < ictx->param_list_len; i++) {
1042 ip = &ictx->param_list[i];
1043 if (ip->type == INPUT_MISSING)
1044 log_debug("parameter %u: missing", i);
1045 else if (ip->type == INPUT_STRING)
1046 log_debug("parameter %u: string %s", i, ip->str);
1047 else if (ip->type == INPUT_NUMBER)
1048 log_debug("parameter %u: number %d", i, ip->num);
1051 return (0);
1054 /* Get an argument or return default value. */
1055 static int
1056 input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
1058 struct input_param *ip;
1059 int retval;
1061 if (validx >= ictx->param_list_len)
1062 return (defval);
1063 ip = &ictx->param_list[validx];
1064 if (ip->type == INPUT_MISSING)
1065 return (defval);
1066 if (ip->type == INPUT_STRING)
1067 return (-1);
1068 retval = ip->num;
1069 if (retval < minval)
1070 return (minval);
1071 return (retval);
1074 /* Reply to terminal query. */
1075 static void
1076 input_reply(struct input_ctx *ictx, const char *fmt, ...)
1078 struct bufferevent *bev = ictx->event;
1079 va_list ap;
1080 char *reply;
1082 if (bev == NULL)
1083 return;
1085 va_start(ap, fmt);
1086 xvasprintf(&reply, fmt, ap);
1087 va_end(ap);
1089 log_debug("%s: %s", __func__, reply);
1090 bufferevent_write(bev, reply, strlen(reply));
1091 free(reply);
1094 /* Clear saved state. */
1095 static void
1096 input_clear(struct input_ctx *ictx)
1098 event_del(&ictx->timer);
1100 *ictx->interm_buf = '\0';
1101 ictx->interm_len = 0;
1103 *ictx->param_buf = '\0';
1104 ictx->param_len = 0;
1106 *ictx->input_buf = '\0';
1107 ictx->input_len = 0;
1109 ictx->input_end = INPUT_END_ST;
1111 ictx->flags &= ~INPUT_DISCARD;
1114 /* Reset for ground state. */
1115 static void
1116 input_ground(struct input_ctx *ictx)
1118 event_del(&ictx->timer);
1119 evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
1121 if (ictx->input_space > INPUT_BUF_START) {
1122 ictx->input_space = INPUT_BUF_START;
1123 ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START);
1127 /* Output this character to the screen. */
1128 static int
1129 input_print(struct input_ctx *ictx)
1131 struct screen_write_ctx *sctx = &ictx->ctx;
1132 int set;
1134 ictx->utf8started = 0; /* can't be valid UTF-8 */
1136 set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
1137 if (set == 1)
1138 ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
1139 else
1140 ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1142 utf8_set(&ictx->cell.cell.data, ictx->ch);
1143 screen_write_collect_add(sctx, &ictx->cell.cell);
1144 ictx->last = ictx->ch;
1146 ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1148 return (0);
1151 /* Collect intermediate string. */
1152 static int
1153 input_intermediate(struct input_ctx *ictx)
1155 if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
1156 ictx->flags |= INPUT_DISCARD;
1157 else {
1158 ictx->interm_buf[ictx->interm_len++] = ictx->ch;
1159 ictx->interm_buf[ictx->interm_len] = '\0';
1162 return (0);
1165 /* Collect parameter string. */
1166 static int
1167 input_parameter(struct input_ctx *ictx)
1169 if (ictx->param_len == (sizeof ictx->param_buf) - 1)
1170 ictx->flags |= INPUT_DISCARD;
1171 else {
1172 ictx->param_buf[ictx->param_len++] = ictx->ch;
1173 ictx->param_buf[ictx->param_len] = '\0';
1176 return (0);
1179 /* Collect input string. */
1180 static int
1181 input_input(struct input_ctx *ictx)
1183 size_t available;
1185 available = ictx->input_space;
1186 while (ictx->input_len + 1 >= available) {
1187 available *= 2;
1188 if (available > INPUT_BUF_LIMIT) {
1189 ictx->flags |= INPUT_DISCARD;
1190 return (0);
1192 ictx->input_buf = xrealloc(ictx->input_buf, available);
1193 ictx->input_space = available;
1195 ictx->input_buf[ictx->input_len++] = ictx->ch;
1196 ictx->input_buf[ictx->input_len] = '\0';
1198 return (0);
1201 /* Execute C0 control sequence. */
1202 static int
1203 input_c0_dispatch(struct input_ctx *ictx)
1205 struct screen_write_ctx *sctx = &ictx->ctx;
1206 struct window_pane *wp = ictx->wp;
1207 struct screen *s = sctx->s;
1209 ictx->utf8started = 0; /* can't be valid UTF-8 */
1211 log_debug("%s: '%c'", __func__, ictx->ch);
1213 switch (ictx->ch) {
1214 case '\000': /* NUL */
1215 break;
1216 case '\007': /* BEL */
1217 if (wp != NULL)
1218 alerts_queue(wp->window, WINDOW_BELL);
1219 break;
1220 case '\010': /* BS */
1221 screen_write_backspace(sctx);
1222 break;
1223 case '\011': /* HT */
1224 /* Don't tab beyond the end of the line. */
1225 if (s->cx >= screen_size_x(s) - 1)
1226 break;
1228 /* Find the next tab point, or use the last column if none. */
1229 do {
1230 s->cx++;
1231 if (bit_test(s->tabs, s->cx))
1232 break;
1233 } while (s->cx < screen_size_x(s) - 1);
1234 break;
1235 case '\012': /* LF */
1236 case '\013': /* VT */
1237 case '\014': /* FF */
1238 screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1239 if (s->mode & MODE_CRLF)
1240 screen_write_carriagereturn(sctx);
1241 break;
1242 case '\015': /* CR */
1243 screen_write_carriagereturn(sctx);
1244 break;
1245 case '\016': /* SO */
1246 ictx->cell.set = 1;
1247 break;
1248 case '\017': /* SI */
1249 ictx->cell.set = 0;
1250 break;
1251 default:
1252 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1253 break;
1256 ictx->last = -1;
1257 return (0);
1260 /* Execute escape sequence. */
1261 static int
1262 input_esc_dispatch(struct input_ctx *ictx)
1264 struct screen_write_ctx *sctx = &ictx->ctx;
1265 struct screen *s = sctx->s;
1266 struct input_table_entry *entry;
1268 if (ictx->flags & INPUT_DISCARD)
1269 return (0);
1270 log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1272 entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
1273 sizeof input_esc_table[0], input_table_compare);
1274 if (entry == NULL) {
1275 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1276 return (0);
1279 switch (entry->type) {
1280 case INPUT_ESC_RIS:
1281 colour_palette_clear(ictx->palette);
1282 input_reset_cell(ictx);
1283 screen_write_reset(sctx);
1284 screen_write_fullredraw(sctx);
1285 break;
1286 case INPUT_ESC_IND:
1287 screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1288 break;
1289 case INPUT_ESC_NEL:
1290 screen_write_carriagereturn(sctx);
1291 screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1292 break;
1293 case INPUT_ESC_HTS:
1294 if (s->cx < screen_size_x(s))
1295 bit_set(s->tabs, s->cx);
1296 break;
1297 case INPUT_ESC_RI:
1298 screen_write_reverseindex(sctx, ictx->cell.cell.bg);
1299 break;
1300 case INPUT_ESC_DECKPAM:
1301 screen_write_mode_set(sctx, MODE_KKEYPAD);
1302 break;
1303 case INPUT_ESC_DECKPNM:
1304 screen_write_mode_clear(sctx, MODE_KKEYPAD);
1305 break;
1306 case INPUT_ESC_DECSC:
1307 input_save_state(ictx);
1308 break;
1309 case INPUT_ESC_DECRC:
1310 input_restore_state(ictx);
1311 break;
1312 case INPUT_ESC_DECALN:
1313 screen_write_alignmenttest(sctx);
1314 break;
1315 case INPUT_ESC_SCSG0_ON:
1316 ictx->cell.g0set = 1;
1317 break;
1318 case INPUT_ESC_SCSG0_OFF:
1319 ictx->cell.g0set = 0;
1320 break;
1321 case INPUT_ESC_SCSG1_ON:
1322 ictx->cell.g1set = 1;
1323 break;
1324 case INPUT_ESC_SCSG1_OFF:
1325 ictx->cell.g1set = 0;
1326 break;
1327 case INPUT_ESC_ST:
1328 /* ST terminates OSC but the state transition already did it. */
1329 break;
1332 ictx->last = -1;
1333 return (0);
1336 /* Execute control sequence. */
1337 static int
1338 input_csi_dispatch(struct input_ctx *ictx)
1340 struct screen_write_ctx *sctx = &ictx->ctx;
1341 struct screen *s = sctx->s;
1342 struct input_table_entry *entry;
1343 int i, n, m;
1344 u_int cx, bg = ictx->cell.cell.bg;
1346 if (ictx->flags & INPUT_DISCARD)
1347 return (0);
1349 log_debug("%s: '%c' \"%s\" \"%s\"", __func__, ictx->ch,
1350 ictx->interm_buf, ictx->param_buf);
1352 if (input_split(ictx) != 0)
1353 return (0);
1355 entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1356 sizeof input_csi_table[0], input_table_compare);
1357 if (entry == NULL) {
1358 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1359 return (0);
1362 switch (entry->type) {
1363 case INPUT_CSI_CBT:
1364 /* Find the previous tab point, n times. */
1365 cx = s->cx;
1366 if (cx > screen_size_x(s) - 1)
1367 cx = screen_size_x(s) - 1;
1368 n = input_get(ictx, 0, 1, 1);
1369 if (n == -1)
1370 break;
1371 while (cx > 0 && n-- > 0) {
1373 cx--;
1374 while (cx > 0 && !bit_test(s->tabs, cx));
1376 s->cx = cx;
1377 break;
1378 case INPUT_CSI_CUB:
1379 n = input_get(ictx, 0, 1, 1);
1380 if (n != -1)
1381 screen_write_cursorleft(sctx, n);
1382 break;
1383 case INPUT_CSI_CUD:
1384 n = input_get(ictx, 0, 1, 1);
1385 if (n != -1)
1386 screen_write_cursordown(sctx, n);
1387 break;
1388 case INPUT_CSI_CUF:
1389 n = input_get(ictx, 0, 1, 1);
1390 if (n != -1)
1391 screen_write_cursorright(sctx, n);
1392 break;
1393 case INPUT_CSI_CUP:
1394 n = input_get(ictx, 0, 1, 1);
1395 m = input_get(ictx, 1, 1, 1);
1396 if (n != -1 && m != -1)
1397 screen_write_cursormove(sctx, m - 1, n - 1, 1);
1398 break;
1399 case INPUT_CSI_MODSET:
1400 n = input_get(ictx, 0, 0, 0);
1401 m = input_get(ictx, 1, 0, 0);
1402 if (options_get_number(global_options, "extended-keys") == 2)
1403 break;
1404 if (n == 0 || (n == 4 && m == 0))
1405 screen_write_mode_clear(sctx, MODE_KEXTENDED);
1406 else if (n == 4 && (m == 1 || m == 2))
1407 screen_write_mode_set(sctx, MODE_KEXTENDED);
1408 break;
1409 case INPUT_CSI_MODOFF:
1410 n = input_get(ictx, 0, 0, 0);
1411 if (n == 4)
1412 screen_write_mode_clear(sctx, MODE_KEXTENDED);
1413 break;
1414 case INPUT_CSI_WINOPS:
1415 input_csi_dispatch_winops(ictx);
1416 break;
1417 case INPUT_CSI_CUU:
1418 n = input_get(ictx, 0, 1, 1);
1419 if (n != -1)
1420 screen_write_cursorup(sctx, n);
1421 break;
1422 case INPUT_CSI_CNL:
1423 n = input_get(ictx, 0, 1, 1);
1424 if (n != -1) {
1425 screen_write_carriagereturn(sctx);
1426 screen_write_cursordown(sctx, n);
1428 break;
1429 case INPUT_CSI_CPL:
1430 n = input_get(ictx, 0, 1, 1);
1431 if (n != -1) {
1432 screen_write_carriagereturn(sctx);
1433 screen_write_cursorup(sctx, n);
1435 break;
1436 case INPUT_CSI_DA:
1437 switch (input_get(ictx, 0, 0, 0)) {
1438 case -1:
1439 break;
1440 case 0:
1441 input_reply(ictx, "\033[?1;2c");
1442 break;
1443 default:
1444 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1445 break;
1447 break;
1448 case INPUT_CSI_DA_TWO:
1449 switch (input_get(ictx, 0, 0, 0)) {
1450 case -1:
1451 break;
1452 case 0:
1453 input_reply(ictx, "\033[>84;0;0c");
1454 break;
1455 default:
1456 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1457 break;
1459 break;
1460 case INPUT_CSI_ECH:
1461 n = input_get(ictx, 0, 1, 1);
1462 if (n != -1)
1463 screen_write_clearcharacter(sctx, n, bg);
1464 break;
1465 case INPUT_CSI_DCH:
1466 n = input_get(ictx, 0, 1, 1);
1467 if (n != -1)
1468 screen_write_deletecharacter(sctx, n, bg);
1469 break;
1470 case INPUT_CSI_DECSTBM:
1471 n = input_get(ictx, 0, 1, 1);
1472 m = input_get(ictx, 1, 1, screen_size_y(s));
1473 if (n != -1 && m != -1)
1474 screen_write_scrollregion(sctx, n - 1, m - 1);
1475 break;
1476 case INPUT_CSI_DL:
1477 n = input_get(ictx, 0, 1, 1);
1478 if (n != -1)
1479 screen_write_deleteline(sctx, n, bg);
1480 break;
1481 case INPUT_CSI_DSR:
1482 switch (input_get(ictx, 0, 0, 0)) {
1483 case -1:
1484 break;
1485 case 5:
1486 input_reply(ictx, "\033[0n");
1487 break;
1488 case 6:
1489 input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1490 break;
1491 default:
1492 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1493 break;
1495 break;
1496 case INPUT_CSI_ED:
1497 switch (input_get(ictx, 0, 0, 0)) {
1498 case -1:
1499 break;
1500 case 0:
1501 screen_write_clearendofscreen(sctx, bg);
1502 break;
1503 case 1:
1504 screen_write_clearstartofscreen(sctx, bg);
1505 break;
1506 case 2:
1507 screen_write_clearscreen(sctx, bg);
1508 break;
1509 case 3:
1510 if (input_get(ictx, 1, 0, 0) == 0) {
1512 * Linux console extension to clear history
1513 * (for example before locking the screen).
1515 screen_write_clearhistory(sctx);
1517 break;
1518 default:
1519 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1520 break;
1522 break;
1523 case INPUT_CSI_EL:
1524 switch (input_get(ictx, 0, 0, 0)) {
1525 case -1:
1526 break;
1527 case 0:
1528 screen_write_clearendofline(sctx, bg);
1529 break;
1530 case 1:
1531 screen_write_clearstartofline(sctx, bg);
1532 break;
1533 case 2:
1534 screen_write_clearline(sctx, bg);
1535 break;
1536 default:
1537 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1538 break;
1540 break;
1541 case INPUT_CSI_HPA:
1542 n = input_get(ictx, 0, 1, 1);
1543 if (n != -1)
1544 screen_write_cursormove(sctx, n - 1, -1, 1);
1545 break;
1546 case INPUT_CSI_ICH:
1547 n = input_get(ictx, 0, 1, 1);
1548 if (n != -1)
1549 screen_write_insertcharacter(sctx, n, bg);
1550 break;
1551 case INPUT_CSI_IL:
1552 n = input_get(ictx, 0, 1, 1);
1553 if (n != -1)
1554 screen_write_insertline(sctx, n, bg);
1555 break;
1556 case INPUT_CSI_REP:
1557 n = input_get(ictx, 0, 1, 1);
1558 if (n == -1)
1559 break;
1561 m = screen_size_x(s) - s->cx;
1562 if (n > m)
1563 n = m;
1565 if (ictx->last == -1)
1566 break;
1567 ictx->ch = ictx->last;
1569 for (i = 0; i < n; i++)
1570 input_print(ictx);
1571 break;
1572 case INPUT_CSI_RCP:
1573 input_restore_state(ictx);
1574 break;
1575 case INPUT_CSI_RM:
1576 input_csi_dispatch_rm(ictx);
1577 break;
1578 case INPUT_CSI_RM_PRIVATE:
1579 input_csi_dispatch_rm_private(ictx);
1580 break;
1581 case INPUT_CSI_SCP:
1582 input_save_state(ictx);
1583 break;
1584 case INPUT_CSI_SGR:
1585 input_csi_dispatch_sgr(ictx);
1586 break;
1587 case INPUT_CSI_SM:
1588 input_csi_dispatch_sm(ictx);
1589 break;
1590 case INPUT_CSI_SM_PRIVATE:
1591 input_csi_dispatch_sm_private(ictx);
1592 break;
1593 case INPUT_CSI_SU:
1594 n = input_get(ictx, 0, 1, 1);
1595 if (n != -1)
1596 screen_write_scrollup(sctx, n, bg);
1597 break;
1598 case INPUT_CSI_SD:
1599 n = input_get(ictx, 0, 1, 1);
1600 if (n != -1)
1601 screen_write_scrolldown(sctx, n, bg);
1602 break;
1603 case INPUT_CSI_TBC:
1604 switch (input_get(ictx, 0, 0, 0)) {
1605 case -1:
1606 break;
1607 case 0:
1608 if (s->cx < screen_size_x(s))
1609 bit_clear(s->tabs, s->cx);
1610 break;
1611 case 3:
1612 bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1613 break;
1614 default:
1615 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1616 break;
1618 break;
1619 case INPUT_CSI_VPA:
1620 n = input_get(ictx, 0, 1, 1);
1621 if (n != -1)
1622 screen_write_cursormove(sctx, -1, n - 1, 1);
1623 break;
1624 case INPUT_CSI_DECSCUSR:
1625 n = input_get(ictx, 0, 0, 0);
1626 if (n != -1)
1627 screen_set_cursor_style(n, &s->cstyle, &s->mode);
1628 break;
1629 case INPUT_CSI_XDA:
1630 n = input_get(ictx, 0, 0, 0);
1631 if (n == 0)
1632 input_reply(ictx, "\033P>|tmux %s\033\\", getversion());
1633 break;
1637 ictx->last = -1;
1638 return (0);
1641 /* Handle CSI RM. */
1642 static void
1643 input_csi_dispatch_rm(struct input_ctx *ictx)
1645 struct screen_write_ctx *sctx = &ictx->ctx;
1646 u_int i;
1648 for (i = 0; i < ictx->param_list_len; i++) {
1649 switch (input_get(ictx, i, 0, -1)) {
1650 case -1:
1651 break;
1652 case 4: /* IRM */
1653 screen_write_mode_clear(sctx, MODE_INSERT);
1654 break;
1655 case 34:
1656 screen_write_mode_set(sctx, MODE_CURSOR_VERY_VISIBLE);
1657 break;
1658 default:
1659 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1660 break;
1665 /* Handle CSI private RM. */
1666 static void
1667 input_csi_dispatch_rm_private(struct input_ctx *ictx)
1669 struct screen_write_ctx *sctx = &ictx->ctx;
1670 struct grid_cell *gc = &ictx->cell.cell;
1671 u_int i;
1673 for (i = 0; i < ictx->param_list_len; i++) {
1674 switch (input_get(ictx, i, 0, -1)) {
1675 case -1:
1676 break;
1677 case 1: /* DECCKM */
1678 screen_write_mode_clear(sctx, MODE_KCURSOR);
1679 break;
1680 case 3: /* DECCOLM */
1681 screen_write_cursormove(sctx, 0, 0, 1);
1682 screen_write_clearscreen(sctx, gc->bg);
1683 break;
1684 case 6: /* DECOM */
1685 screen_write_mode_clear(sctx, MODE_ORIGIN);
1686 screen_write_cursormove(sctx, 0, 0, 1);
1687 break;
1688 case 7: /* DECAWM */
1689 screen_write_mode_clear(sctx, MODE_WRAP);
1690 break;
1691 case 12:
1692 screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING);
1693 screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
1694 break;
1695 case 25: /* TCEM */
1696 screen_write_mode_clear(sctx, MODE_CURSOR);
1697 break;
1698 case 1000:
1699 case 1001:
1700 case 1002:
1701 case 1003:
1702 screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1703 break;
1704 case 1004:
1705 screen_write_mode_clear(sctx, MODE_FOCUSON);
1706 break;
1707 case 1005:
1708 screen_write_mode_clear(sctx, MODE_MOUSE_UTF8);
1709 break;
1710 case 1006:
1711 screen_write_mode_clear(sctx, MODE_MOUSE_SGR);
1712 break;
1713 case 47:
1714 case 1047:
1715 screen_write_alternateoff(sctx, gc, 0);
1716 break;
1717 case 1049:
1718 screen_write_alternateoff(sctx, gc, 1);
1719 break;
1720 case 2004:
1721 screen_write_mode_clear(sctx, MODE_BRACKETPASTE);
1722 break;
1723 default:
1724 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1725 break;
1730 /* Handle CSI SM. */
1731 static void
1732 input_csi_dispatch_sm(struct input_ctx *ictx)
1734 struct screen_write_ctx *sctx = &ictx->ctx;
1735 u_int i;
1737 for (i = 0; i < ictx->param_list_len; i++) {
1738 switch (input_get(ictx, i, 0, -1)) {
1739 case -1:
1740 break;
1741 case 4: /* IRM */
1742 screen_write_mode_set(sctx, MODE_INSERT);
1743 break;
1744 case 34:
1745 screen_write_mode_clear(sctx, MODE_CURSOR_VERY_VISIBLE);
1746 break;
1747 default:
1748 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1749 break;
1754 /* Handle CSI private SM. */
1755 static void
1756 input_csi_dispatch_sm_private(struct input_ctx *ictx)
1758 struct screen_write_ctx *sctx = &ictx->ctx;
1759 struct grid_cell *gc = &ictx->cell.cell;
1760 u_int i;
1762 for (i = 0; i < ictx->param_list_len; i++) {
1763 switch (input_get(ictx, i, 0, -1)) {
1764 case -1:
1765 break;
1766 case 1: /* DECCKM */
1767 screen_write_mode_set(sctx, MODE_KCURSOR);
1768 break;
1769 case 3: /* DECCOLM */
1770 screen_write_cursormove(sctx, 0, 0, 1);
1771 screen_write_clearscreen(sctx, ictx->cell.cell.bg);
1772 break;
1773 case 6: /* DECOM */
1774 screen_write_mode_set(sctx, MODE_ORIGIN);
1775 screen_write_cursormove(sctx, 0, 0, 1);
1776 break;
1777 case 7: /* DECAWM */
1778 screen_write_mode_set(sctx, MODE_WRAP);
1779 break;
1780 case 12:
1781 screen_write_mode_set(sctx, MODE_CURSOR_BLINKING);
1782 screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET);
1783 break;
1784 case 25: /* TCEM */
1785 screen_write_mode_set(sctx, MODE_CURSOR);
1786 break;
1787 case 1000:
1788 screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1789 screen_write_mode_set(sctx, MODE_MOUSE_STANDARD);
1790 break;
1791 case 1002:
1792 screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1793 screen_write_mode_set(sctx, MODE_MOUSE_BUTTON);
1794 break;
1795 case 1003:
1796 screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1797 screen_write_mode_set(sctx, MODE_MOUSE_ALL);
1798 break;
1799 case 1004:
1800 screen_write_mode_set(sctx, MODE_FOCUSON);
1801 break;
1802 case 1005:
1803 screen_write_mode_set(sctx, MODE_MOUSE_UTF8);
1804 break;
1805 case 1006:
1806 screen_write_mode_set(sctx, MODE_MOUSE_SGR);
1807 break;
1808 case 47:
1809 case 1047:
1810 screen_write_alternateon(sctx, gc, 0);
1811 break;
1812 case 1049:
1813 screen_write_alternateon(sctx, gc, 1);
1814 break;
1815 case 2004:
1816 screen_write_mode_set(sctx, MODE_BRACKETPASTE);
1817 break;
1818 default:
1819 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1820 break;
1825 /* Handle CSI window operations. */
1826 static void
1827 input_csi_dispatch_winops(struct input_ctx *ictx)
1829 struct screen_write_ctx *sctx = &ictx->ctx;
1830 struct screen *s = sctx->s;
1831 struct window_pane *wp = ictx->wp;
1832 u_int x = screen_size_x(s), y = screen_size_y(s);
1833 int n, m;
1835 m = 0;
1836 while ((n = input_get(ictx, m, 0, -1)) != -1) {
1837 switch (n) {
1838 case 1:
1839 case 2:
1840 case 5:
1841 case 6:
1842 case 7:
1843 case 11:
1844 case 13:
1845 case 14:
1846 case 19:
1847 case 20:
1848 case 21:
1849 case 24:
1850 break;
1851 case 3:
1852 case 4:
1853 case 8:
1854 m++;
1855 if (input_get(ictx, m, 0, -1) == -1)
1856 return;
1857 /* FALLTHROUGH */
1858 case 9:
1859 case 10:
1860 m++;
1861 if (input_get(ictx, m, 0, -1) == -1)
1862 return;
1863 break;
1864 case 22:
1865 m++;
1866 switch (input_get(ictx, m, 0, -1)) {
1867 case -1:
1868 return;
1869 case 0:
1870 case 2:
1871 screen_push_title(sctx->s);
1872 break;
1874 break;
1875 case 23:
1876 m++;
1877 switch (input_get(ictx, m, 0, -1)) {
1878 case -1:
1879 return;
1880 case 0:
1881 case 2:
1882 screen_pop_title(sctx->s);
1883 if (wp == NULL)
1884 break;
1885 notify_pane("pane-title-changed", wp);
1886 server_redraw_window_borders(wp->window);
1887 server_status_window(wp->window);
1888 break;
1890 break;
1891 case 18:
1892 input_reply(ictx, "\033[8;%u;%ut", y, x);
1893 break;
1894 default:
1895 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1896 break;
1898 m++;
1902 /* Helper for 256 colour SGR. */
1903 static int
1904 input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c)
1906 struct grid_cell *gc = &ictx->cell.cell;
1908 if (c == -1 || c > 255) {
1909 if (fgbg == 38)
1910 gc->fg = 8;
1911 else if (fgbg == 48)
1912 gc->bg = 8;
1913 } else {
1914 if (fgbg == 38)
1915 gc->fg = c | COLOUR_FLAG_256;
1916 else if (fgbg == 48)
1917 gc->bg = c | COLOUR_FLAG_256;
1918 else if (fgbg == 58)
1919 gc->us = c | COLOUR_FLAG_256;
1921 return (1);
1924 /* Handle CSI SGR for 256 colours. */
1925 static void
1926 input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
1928 int c;
1930 c = input_get(ictx, (*i) + 1, 0, -1);
1931 if (input_csi_dispatch_sgr_256_do(ictx, fgbg, c))
1932 (*i)++;
1935 /* Helper for RGB colour SGR. */
1936 static int
1937 input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g,
1938 int b)
1940 struct grid_cell *gc = &ictx->cell.cell;
1942 if (r == -1 || r > 255)
1943 return (0);
1944 if (g == -1 || g > 255)
1945 return (0);
1946 if (b == -1 || b > 255)
1947 return (0);
1949 if (fgbg == 38)
1950 gc->fg = colour_join_rgb(r, g, b);
1951 else if (fgbg == 48)
1952 gc->bg = colour_join_rgb(r, g, b);
1953 else if (fgbg == 58)
1954 gc->us = colour_join_rgb(r, g, b);
1955 return (1);
1958 /* Handle CSI SGR for RGB colours. */
1959 static void
1960 input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
1962 int r, g, b;
1964 r = input_get(ictx, (*i) + 1, 0, -1);
1965 g = input_get(ictx, (*i) + 2, 0, -1);
1966 b = input_get(ictx, (*i) + 3, 0, -1);
1967 if (input_csi_dispatch_sgr_rgb_do(ictx, fgbg, r, g, b))
1968 (*i) += 3;
1971 /* Handle CSI SGR with a ISO parameter. */
1972 static void
1973 input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
1975 struct grid_cell *gc = &ictx->cell.cell;
1976 char *s = ictx->param_list[i].str, *copy, *ptr, *out;
1977 int p[8];
1978 u_int n;
1979 const char *errstr;
1981 for (n = 0; n < nitems(p); n++)
1982 p[n] = -1;
1983 n = 0;
1985 ptr = copy = xstrdup(s);
1986 while ((out = strsep(&ptr, ":")) != NULL) {
1987 if (*out != '\0') {
1988 p[n++] = strtonum(out, 0, INT_MAX, &errstr);
1989 if (errstr != NULL || n == nitems(p)) {
1990 free(copy);
1991 return;
1993 } else {
1994 n++;
1995 if (n == nitems(p)) {
1996 free(copy);
1997 return;
2000 log_debug("%s: %u = %d", __func__, n - 1, p[n - 1]);
2002 free(copy);
2004 if (n == 0)
2005 return;
2006 if (p[0] == 4) {
2007 if (n != 2)
2008 return;
2009 switch (p[1]) {
2010 case 0:
2011 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2012 break;
2013 case 1:
2014 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2015 gc->attr |= GRID_ATTR_UNDERSCORE;
2016 break;
2017 case 2:
2018 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2019 gc->attr |= GRID_ATTR_UNDERSCORE_2;
2020 break;
2021 case 3:
2022 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2023 gc->attr |= GRID_ATTR_UNDERSCORE_3;
2024 break;
2025 case 4:
2026 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2027 gc->attr |= GRID_ATTR_UNDERSCORE_4;
2028 break;
2029 case 5:
2030 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2031 gc->attr |= GRID_ATTR_UNDERSCORE_5;
2032 break;
2034 return;
2036 if (n < 2 || (p[0] != 38 && p[0] != 48 && p[0] != 58))
2037 return;
2038 switch (p[1]) {
2039 case 2:
2040 if (n < 3)
2041 break;
2042 if (n == 5)
2043 i = 2;
2044 else
2045 i = 3;
2046 if (n < i + 3)
2047 break;
2048 input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[i], p[i + 1],
2049 p[i + 2]);
2050 break;
2051 case 5:
2052 if (n < 3)
2053 break;
2054 input_csi_dispatch_sgr_256_do(ictx, p[0], p[2]);
2055 break;
2059 /* Handle CSI SGR. */
2060 static void
2061 input_csi_dispatch_sgr(struct input_ctx *ictx)
2063 struct grid_cell *gc = &ictx->cell.cell;
2064 u_int i;
2065 int n;
2067 if (ictx->param_list_len == 0) {
2068 memcpy(gc, &grid_default_cell, sizeof *gc);
2069 return;
2072 for (i = 0; i < ictx->param_list_len; i++) {
2073 if (ictx->param_list[i].type == INPUT_STRING) {
2074 input_csi_dispatch_sgr_colon(ictx, i);
2075 continue;
2077 n = input_get(ictx, i, 0, 0);
2078 if (n == -1)
2079 continue;
2081 if (n == 38 || n == 48 || n == 58) {
2082 i++;
2083 switch (input_get(ictx, i, 0, -1)) {
2084 case 2:
2085 input_csi_dispatch_sgr_rgb(ictx, n, &i);
2086 break;
2087 case 5:
2088 input_csi_dispatch_sgr_256(ictx, n, &i);
2089 break;
2091 continue;
2094 switch (n) {
2095 case 0:
2096 memcpy(gc, &grid_default_cell, sizeof *gc);
2097 break;
2098 case 1:
2099 gc->attr |= GRID_ATTR_BRIGHT;
2100 break;
2101 case 2:
2102 gc->attr |= GRID_ATTR_DIM;
2103 break;
2104 case 3:
2105 gc->attr |= GRID_ATTR_ITALICS;
2106 break;
2107 case 4:
2108 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2109 gc->attr |= GRID_ATTR_UNDERSCORE;
2110 break;
2111 case 5:
2112 case 6:
2113 gc->attr |= GRID_ATTR_BLINK;
2114 break;
2115 case 7:
2116 gc->attr |= GRID_ATTR_REVERSE;
2117 break;
2118 case 8:
2119 gc->attr |= GRID_ATTR_HIDDEN;
2120 break;
2121 case 9:
2122 gc->attr |= GRID_ATTR_STRIKETHROUGH;
2123 break;
2124 case 21:
2125 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2126 gc->attr |= GRID_ATTR_UNDERSCORE_2;
2127 break;
2128 case 22:
2129 gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
2130 break;
2131 case 23:
2132 gc->attr &= ~GRID_ATTR_ITALICS;
2133 break;
2134 case 24:
2135 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
2136 break;
2137 case 25:
2138 gc->attr &= ~GRID_ATTR_BLINK;
2139 break;
2140 case 27:
2141 gc->attr &= ~GRID_ATTR_REVERSE;
2142 break;
2143 case 28:
2144 gc->attr &= ~GRID_ATTR_HIDDEN;
2145 break;
2146 case 29:
2147 gc->attr &= ~GRID_ATTR_STRIKETHROUGH;
2148 break;
2149 case 30:
2150 case 31:
2151 case 32:
2152 case 33:
2153 case 34:
2154 case 35:
2155 case 36:
2156 case 37:
2157 gc->fg = n - 30;
2158 break;
2159 case 39:
2160 gc->fg = 8;
2161 break;
2162 case 40:
2163 case 41:
2164 case 42:
2165 case 43:
2166 case 44:
2167 case 45:
2168 case 46:
2169 case 47:
2170 gc->bg = n - 40;
2171 break;
2172 case 49:
2173 gc->bg = 8;
2174 break;
2175 case 53:
2176 gc->attr |= GRID_ATTR_OVERLINE;
2177 break;
2178 case 55:
2179 gc->attr &= ~GRID_ATTR_OVERLINE;
2180 break;
2181 case 59:
2182 gc->us = 0;
2183 break;
2184 case 90:
2185 case 91:
2186 case 92:
2187 case 93:
2188 case 94:
2189 case 95:
2190 case 96:
2191 case 97:
2192 gc->fg = n;
2193 break;
2194 case 100:
2195 case 101:
2196 case 102:
2197 case 103:
2198 case 104:
2199 case 105:
2200 case 106:
2201 case 107:
2202 gc->bg = n - 10;
2203 break;
2208 /* End of input with BEL. */
2209 static int
2210 input_end_bel(struct input_ctx *ictx)
2212 log_debug("%s", __func__);
2214 ictx->input_end = INPUT_END_BEL;
2216 return (0);
2219 /* DCS string started. */
2220 static void
2221 input_enter_dcs(struct input_ctx *ictx)
2223 log_debug("%s", __func__);
2225 input_clear(ictx);
2226 input_start_timer(ictx);
2227 ictx->last = -1;
2230 /* DCS terminator (ST) received. */
2231 static int
2232 input_dcs_dispatch(struct input_ctx *ictx)
2234 struct window_pane *wp = ictx->wp;
2235 struct screen_write_ctx *sctx = &ictx->ctx;
2236 u_char *buf = ictx->input_buf;
2237 size_t len = ictx->input_len;
2238 const char prefix[] = "tmux;";
2239 const u_int prefixlen = (sizeof prefix) - 1;
2240 long long allow_passthrough = 0;
2242 if (wp == NULL)
2243 return (0);
2244 if (ictx->flags & INPUT_DISCARD)
2245 return (0);
2246 allow_passthrough = options_get_number(wp->options,
2247 "allow-passthrough");
2248 if (!allow_passthrough)
2249 return (0);
2250 log_debug("%s: \"%s\"", __func__, buf);
2252 if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) {
2253 screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen,
2254 allow_passthrough == 2);
2257 return (0);
2260 /* OSC string started. */
2261 static void
2262 input_enter_osc(struct input_ctx *ictx)
2264 log_debug("%s", __func__);
2266 input_clear(ictx);
2267 input_start_timer(ictx);
2268 ictx->last = -1;
2271 /* OSC terminator (ST) received. */
2272 static void
2273 input_exit_osc(struct input_ctx *ictx)
2275 struct screen_write_ctx *sctx = &ictx->ctx;
2276 struct window_pane *wp = ictx->wp;
2277 u_char *p = ictx->input_buf;
2278 u_int option;
2280 if (ictx->flags & INPUT_DISCARD)
2281 return;
2282 if (ictx->input_len < 1 || *p < '0' || *p > '9')
2283 return;
2285 log_debug("%s: \"%s\" (end %s)", __func__, p,
2286 ictx->input_end == INPUT_END_ST ? "ST" : "BEL");
2288 option = 0;
2289 while (*p >= '0' && *p <= '9')
2290 option = option * 10 + *p++ - '0';
2291 if (*p != ';' && *p != '\0')
2292 return;
2293 if (*p == ';')
2294 p++;
2296 switch (option) {
2297 case 0:
2298 case 2:
2299 if (screen_set_title(sctx->s, p) && wp != NULL) {
2300 notify_pane("pane-title-changed", wp);
2301 server_redraw_window_borders(wp->window);
2302 server_status_window(wp->window);
2304 break;
2305 case 4:
2306 input_osc_4(ictx, p);
2307 break;
2308 case 7:
2309 if (utf8_isvalid(p)) {
2310 screen_set_path(sctx->s, p);
2311 if (wp != NULL) {
2312 server_redraw_window_borders(wp->window);
2313 server_status_window(wp->window);
2316 break;
2317 case 8:
2318 input_osc_8(ictx, p);
2319 break;
2320 case 10:
2321 input_osc_10(ictx, p);
2322 break;
2323 case 11:
2324 input_osc_11(ictx, p);
2325 break;
2326 case 12:
2327 input_osc_12(ictx, p);
2328 break;
2329 case 52:
2330 input_osc_52(ictx, p);
2331 break;
2332 case 104:
2333 input_osc_104(ictx, p);
2334 break;
2335 case 110:
2336 input_osc_110(ictx, p);
2337 break;
2338 case 111:
2339 input_osc_111(ictx, p);
2340 break;
2341 case 112:
2342 input_osc_112(ictx, p);
2343 break;
2344 default:
2345 log_debug("%s: unknown '%u'", __func__, option);
2346 break;
2350 /* APC string started. */
2351 static void
2352 input_enter_apc(struct input_ctx *ictx)
2354 log_debug("%s", __func__);
2356 input_clear(ictx);
2357 input_start_timer(ictx);
2358 ictx->last = -1;
2361 /* APC terminator (ST) received. */
2362 static void
2363 input_exit_apc(struct input_ctx *ictx)
2365 struct screen_write_ctx *sctx = &ictx->ctx;
2366 struct window_pane *wp = ictx->wp;
2368 if (ictx->flags & INPUT_DISCARD)
2369 return;
2370 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2372 if (screen_set_title(sctx->s, ictx->input_buf) && wp != NULL) {
2373 notify_pane("pane-title-changed", wp);
2374 server_redraw_window_borders(wp->window);
2375 server_status_window(wp->window);
2379 /* Rename string started. */
2380 static void
2381 input_enter_rename(struct input_ctx *ictx)
2383 log_debug("%s", __func__);
2385 input_clear(ictx);
2386 input_start_timer(ictx);
2387 ictx->last = -1;
2390 /* Rename terminator (ST) received. */
2391 static void
2392 input_exit_rename(struct input_ctx *ictx)
2394 struct window_pane *wp = ictx->wp;
2395 struct window *w;
2396 struct options_entry *o;
2398 if (wp == NULL)
2399 return;
2400 if (ictx->flags & INPUT_DISCARD)
2401 return;
2402 if (!options_get_number(ictx->wp->options, "allow-rename"))
2403 return;
2404 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2406 if (!utf8_isvalid(ictx->input_buf))
2407 return;
2408 w = wp->window;
2410 if (ictx->input_len == 0) {
2411 o = options_get_only(w->options, "automatic-rename");
2412 if (o != NULL)
2413 options_remove_or_default(o, -1, NULL);
2414 if (!options_get_number(w->options, "automatic-rename"))
2415 window_set_name(w, "");
2416 } else {
2417 options_set_number(w->options, "automatic-rename", 0);
2418 window_set_name(w, ictx->input_buf);
2420 server_redraw_window_borders(w);
2421 server_status_window(w);
2424 /* Open UTF-8 character. */
2425 static int
2426 input_top_bit_set(struct input_ctx *ictx)
2428 struct screen_write_ctx *sctx = &ictx->ctx;
2429 struct utf8_data *ud = &ictx->utf8data;
2431 ictx->last = -1;
2433 if (!ictx->utf8started) {
2434 if (utf8_open(ud, ictx->ch) != UTF8_MORE)
2435 return (0);
2436 ictx->utf8started = 1;
2437 return (0);
2440 switch (utf8_append(ud, ictx->ch)) {
2441 case UTF8_MORE:
2442 return (0);
2443 case UTF8_ERROR:
2444 ictx->utf8started = 0;
2445 return (0);
2446 case UTF8_DONE:
2447 break;
2449 ictx->utf8started = 0;
2451 log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
2452 (int)ud->size, ud->data, ud->width);
2454 utf8_copy(&ictx->cell.cell.data, ud);
2455 screen_write_collect_add(sctx, &ictx->cell.cell);
2457 return (0);
2460 /* Reply to a colour request. */
2461 static void
2462 input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c)
2464 u_char r, g, b;
2465 const char *end;
2467 if (c != -1)
2468 c = colour_force_rgb(c);
2469 if (c == -1)
2470 return;
2471 colour_split_rgb(c, &r, &g, &b);
2473 if (ictx->input_end == INPUT_END_BEL)
2474 end = "\007";
2475 else
2476 end = "\033\\";
2477 input_reply(ictx, "\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s",
2478 n, r, r, g, g, b, b, end);
2481 /* Handle the OSC 4 sequence for setting (multiple) palette entries. */
2482 static void
2483 input_osc_4(struct input_ctx *ictx, const char *p)
2485 char *copy, *s, *next = NULL;
2486 long idx;
2487 int c, bad = 0, redraw = 0;
2489 copy = s = xstrdup(p);
2490 while (s != NULL && *s != '\0') {
2491 idx = strtol(s, &next, 10);
2492 if (*next++ != ';') {
2493 bad = 1;
2494 break;
2496 if (idx < 0 || idx >= 256) {
2497 bad = 1;
2498 break;
2501 s = strsep(&next, ";");
2502 if (strcmp(s, "?") == 0) {
2503 c = colour_palette_get(ictx->palette, idx);
2504 if (c != -1)
2505 input_osc_colour_reply(ictx, 4, c);
2506 continue;
2508 if ((c = colour_parseX11(s)) == -1) {
2509 s = next;
2510 continue;
2512 if (colour_palette_set(ictx->palette, idx, c))
2513 redraw = 1;
2514 s = next;
2516 if (bad)
2517 log_debug("bad OSC 4: %s", p);
2518 if (redraw)
2519 screen_write_fullredraw(&ictx->ctx);
2520 free(copy);
2523 /* Handle the OSC 8 sequence for embedding hyperlinks. */
2524 static void
2525 input_osc_8(struct input_ctx *ictx, const char *p)
2527 struct hyperlinks *hl = ictx->ctx.s->hyperlinks;
2528 struct grid_cell *gc = &ictx->cell.cell;
2529 const char *start, *end, *uri;
2530 char *id = NULL;
2532 for (start = p; (end = strpbrk(start, ":;")) != NULL; start = end + 1) {
2533 if (end - start >= 4 && strncmp(start, "id=", 3) == 0) {
2534 if (id != NULL)
2535 goto bad;
2536 id = xstrndup(start + 3, end - start - 3);
2539 /* The first ; is the end of parameters and start of the URI. */
2540 if (*end == ';')
2541 break;
2543 if (end == NULL || *end != ';')
2544 goto bad;
2545 uri = end + 1;
2546 if (*uri == '\0') {
2547 gc->link = 0;
2548 free(id);
2549 return;
2551 gc->link = hyperlinks_put(hl, uri, id);
2552 if (id == NULL)
2553 log_debug("hyperlink (anonymous) %s = %u", uri, gc->link);
2554 else
2555 log_debug("hyperlink (id=%s) %s = %u", id, uri, gc->link);
2556 free(id);
2557 return;
2559 bad:
2560 log_debug("bad OSC 8 %s", p);
2561 free(id);
2565 * Get a client with a foreground for the pane. There isn't much to choose
2566 * between them so just use the first.
2568 static int
2569 input_get_fg_client(struct window_pane *wp)
2571 struct window *w = wp->window;
2572 struct client *loop;
2574 TAILQ_FOREACH(loop, &clients, entry) {
2575 if (loop->flags & CLIENT_UNATTACHEDFLAGS)
2576 continue;
2577 if (loop->session == NULL || !session_has(loop->session, w))
2578 continue;
2579 if (loop->tty.fg == -1)
2580 continue;
2581 return (loop->tty.fg);
2583 return (-1);
2586 /* Get a client with a background for the pane. */
2587 static int
2588 input_get_bg_client(struct window_pane *wp)
2590 struct window *w = wp->window;
2591 struct client *loop;
2593 TAILQ_FOREACH(loop, &clients, entry) {
2594 if (loop->flags & CLIENT_UNATTACHEDFLAGS)
2595 continue;
2596 if (loop->session == NULL || !session_has(loop->session, w))
2597 continue;
2598 if (loop->tty.bg == -1)
2599 continue;
2600 return (loop->tty.bg);
2602 return (-1);
2605 /* Handle the OSC 10 sequence for setting and querying foreground colour. */
2606 static void
2607 input_osc_10(struct input_ctx *ictx, const char *p)
2609 struct window_pane *wp = ictx->wp;
2610 struct grid_cell defaults;
2611 int c;
2613 if (strcmp(p, "?") == 0) {
2614 if (wp == NULL)
2615 return;
2616 tty_default_colours(&defaults, wp);
2617 if (COLOUR_DEFAULT(defaults.fg))
2618 c = input_get_fg_client(wp);
2619 else
2620 c = defaults.fg;
2621 input_osc_colour_reply(ictx, 10, c);
2622 return;
2625 if ((c = colour_parseX11(p)) == -1) {
2626 log_debug("bad OSC 10: %s", p);
2627 return;
2629 if (ictx->palette != NULL) {
2630 ictx->palette->fg = c;
2631 if (wp != NULL)
2632 wp->flags |= PANE_STYLECHANGED;
2633 screen_write_fullredraw(&ictx->ctx);
2637 /* Handle the OSC 110 sequence for resetting foreground colour. */
2638 static void
2639 input_osc_110(struct input_ctx *ictx, const char *p)
2641 struct window_pane *wp = ictx->wp;
2643 if (*p != '\0')
2644 return;
2645 if (ictx->palette != NULL) {
2646 ictx->palette->fg = 8;
2647 if (wp != NULL)
2648 wp->flags |= PANE_STYLECHANGED;
2649 screen_write_fullredraw(&ictx->ctx);
2653 /* Handle the OSC 11 sequence for setting and querying background colour. */
2654 static void
2655 input_osc_11(struct input_ctx *ictx, const char *p)
2657 struct window_pane *wp = ictx->wp;
2658 struct grid_cell defaults;
2659 int c;
2661 if (strcmp(p, "?") == 0) {
2662 if (wp == NULL)
2663 return;
2664 tty_default_colours(&defaults, wp);
2665 if (COLOUR_DEFAULT(defaults.bg))
2666 c = input_get_bg_client(wp);
2667 else
2668 c = defaults.bg;
2669 input_osc_colour_reply(ictx, 11, c);
2670 return;
2673 if ((c = colour_parseX11(p)) == -1) {
2674 log_debug("bad OSC 11: %s", p);
2675 return;
2677 if (ictx->palette != NULL) {
2678 ictx->palette->bg = c;
2679 if (wp != NULL)
2680 wp->flags |= PANE_STYLECHANGED;
2681 screen_write_fullredraw(&ictx->ctx);
2685 /* Handle the OSC 111 sequence for resetting background colour. */
2686 static void
2687 input_osc_111(struct input_ctx *ictx, const char *p)
2689 struct window_pane *wp = ictx->wp;
2691 if (*p != '\0')
2692 return;
2693 if (ictx->palette != NULL) {
2694 ictx->palette->bg = 8;
2695 if (wp != NULL)
2696 wp->flags |= PANE_STYLECHANGED;
2697 screen_write_fullredraw(&ictx->ctx);
2701 /* Handle the OSC 12 sequence for setting and querying cursor colour. */
2702 static void
2703 input_osc_12(struct input_ctx *ictx, const char *p)
2705 struct window_pane *wp = ictx->wp;
2706 int c;
2708 if (strcmp(p, "?") == 0) {
2709 if (wp != NULL) {
2710 c = ictx->ctx.s->ccolour;
2711 if (c == -1)
2712 c = ictx->ctx.s->default_ccolour;
2713 input_osc_colour_reply(ictx, 12, c);
2715 return;
2718 if ((c = colour_parseX11(p)) == -1) {
2719 log_debug("bad OSC 12: %s", p);
2720 return;
2722 screen_set_cursor_colour(ictx->ctx.s, c);
2725 /* Handle the OSC 112 sequence for resetting cursor colour. */
2726 static void
2727 input_osc_112(struct input_ctx *ictx, const char *p)
2729 if (*p == '\0') /* no arguments allowed */
2730 screen_set_cursor_colour(ictx->ctx.s, -1);
2734 /* Handle the OSC 52 sequence for setting the clipboard. */
2735 static void
2736 input_osc_52(struct input_ctx *ictx, const char *p)
2738 struct window_pane *wp = ictx->wp;
2739 char *end;
2740 const char *buf = NULL;
2741 size_t len = 0;
2742 u_char *out;
2743 int outlen, state;
2744 struct screen_write_ctx ctx;
2745 struct paste_buffer *pb;
2746 const char* allow = "cpqs01234567";
2747 char flags[sizeof "cpqs01234567"] = "";
2748 u_int i, j = 0;
2750 if (wp == NULL)
2751 return;
2752 state = options_get_number(global_options, "set-clipboard");
2753 if (state != 2)
2754 return;
2756 if ((end = strchr(p, ';')) == NULL)
2757 return;
2758 end++;
2759 if (*end == '\0')
2760 return;
2761 log_debug("%s: %s", __func__, end);
2763 for (i = 0; p + i != end; i++) {
2764 if (strchr(allow, p[i]) != NULL && strchr(flags, p[i]) == NULL)
2765 flags[j++] = p[i];
2767 log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, flags);
2769 if (strcmp(end, "?") == 0) {
2770 if ((pb = paste_get_top(NULL)) != NULL)
2771 buf = paste_buffer_data(pb, &len);
2772 if (ictx->input_end == INPUT_END_BEL)
2773 input_reply_clipboard(ictx->event, buf, len, "\007");
2774 else
2775 input_reply_clipboard(ictx->event, buf, len, "\033\\");
2776 return;
2779 len = (strlen(end) / 4) * 3;
2780 if (len == 0)
2781 return;
2783 out = xmalloc(len);
2784 if ((outlen = b64_pton(end, out, len)) == -1) {
2785 free(out);
2786 return;
2789 screen_write_start_pane(&ctx, wp, NULL);
2790 screen_write_setselection(&ctx, flags, out, outlen);
2791 screen_write_stop(&ctx);
2792 notify_pane("pane-set-clipboard", wp);
2794 paste_add(NULL, out, outlen);
2797 /* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
2798 static void
2799 input_osc_104(struct input_ctx *ictx, const char *p)
2801 char *copy, *s;
2802 long idx;
2803 int bad = 0, redraw = 0;
2805 if (*p == '\0') {
2806 colour_palette_clear(ictx->palette);
2807 screen_write_fullredraw(&ictx->ctx);
2808 return;
2811 copy = s = xstrdup(p);
2812 while (*s != '\0') {
2813 idx = strtol(s, &s, 10);
2814 if (*s != '\0' && *s != ';') {
2815 bad = 1;
2816 break;
2818 if (idx < 0 || idx >= 256) {
2819 bad = 1;
2820 break;
2822 if (colour_palette_set(ictx->palette, idx, -1))
2823 redraw = 1;
2824 if (*s == ';')
2825 s++;
2827 if (bad)
2828 log_debug("bad OSC 104: %s", p);
2829 if (redraw)
2830 screen_write_fullredraw(&ictx->ctx);
2831 free(copy);
2834 void
2835 input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
2836 const char *end)
2838 char *out = NULL;
2839 size_t outlen = 0;
2841 if (buf != NULL && len != 0) {
2842 outlen = 4 * ((len + 2) / 3) + 1;
2843 out = xmalloc(outlen);
2844 if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
2845 free(out);
2846 return;
2850 bufferevent_write(bev, "\033]52;;", 6);
2851 if (outlen != 0)
2852 bufferevent_write(bev, out, outlen);
2853 bufferevent_write(bev, end, strlen(end));
2854 free(out);