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