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