Annotation of src/usr.bin/tmux/input.c, Revision 1.151
1.151 ! nicm 1: /* $OpenBSD: input.c,v 1.150 2019/04/02 09:03:39 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.151 ! nicm 1188: if (s->mode & MODE_CRLF)
! 1189: screen_write_carriagereturn(sctx);
1.75 nicm 1190: break;
1.28 nicm 1191: case '\015': /* CR */
1192: screen_write_carriagereturn(sctx);
1.75 nicm 1193: break;
1.28 nicm 1194: case '\016': /* SO */
1.69 nicm 1195: ictx->cell.set = 1;
1.28 nicm 1196: break;
1197: case '\017': /* SI */
1.69 nicm 1198: ictx->cell.set = 0;
1.28 nicm 1199: break;
1200: default:
1201: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1202: break;
1203: }
1.1 nicm 1204:
1.127 nicm 1205: ictx->last = -1;
1.28 nicm 1206: return (0);
1.7 nicm 1207: }
1208:
1.28 nicm 1209: /* Execute escape sequence. */
1.104 nicm 1210: static int
1.28 nicm 1211: input_esc_dispatch(struct input_ctx *ictx)
1.7 nicm 1212: {
1.31 nicm 1213: struct screen_write_ctx *sctx = &ictx->ctx;
1214: struct screen *s = sctx->s;
1215: struct input_table_entry *entry;
1.7 nicm 1216:
1.28 nicm 1217: if (ictx->flags & INPUT_DISCARD)
1218: return (0);
1219: log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1.7 nicm 1220:
1.28 nicm 1221: entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
1222: sizeof input_esc_table[0], input_table_compare);
1223: if (entry == NULL) {
1224: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1225: return (0);
1226: }
1.7 nicm 1227:
1.28 nicm 1228: switch (entry->type) {
1229: case INPUT_ESC_RIS:
1.107 nicm 1230: window_pane_reset_palette(ictx->wp);
1.69 nicm 1231: input_reset_cell(ictx);
1.46 nicm 1232: screen_write_reset(sctx);
1.28 nicm 1233: break;
1234: case INPUT_ESC_IND:
1.121 nicm 1235: screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1.28 nicm 1236: break;
1237: case INPUT_ESC_NEL:
1238: screen_write_carriagereturn(sctx);
1.121 nicm 1239: screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
1.28 nicm 1240: break;
1241: case INPUT_ESC_HTS:
1242: if (s->cx < screen_size_x(s))
1243: bit_set(s->tabs, s->cx);
1244: break;
1245: case INPUT_ESC_RI:
1.121 nicm 1246: screen_write_reverseindex(sctx, ictx->cell.cell.bg);
1.28 nicm 1247: break;
1248: case INPUT_ESC_DECKPAM:
1.59 nicm 1249: screen_write_mode_set(sctx, MODE_KKEYPAD);
1.28 nicm 1250: break;
1251: case INPUT_ESC_DECKPNM:
1.59 nicm 1252: screen_write_mode_clear(sctx, MODE_KKEYPAD);
1.1 nicm 1253: break;
1.28 nicm 1254: case INPUT_ESC_DECSC:
1.146 nicm 1255: input_save_state(ictx);
1.28 nicm 1256: break;
1257: case INPUT_ESC_DECRC:
1.146 nicm 1258: input_restore_state(ictx);
1.28 nicm 1259: break;
1260: case INPUT_ESC_DECALN:
1261: screen_write_alignmenttest(sctx);
1262: break;
1.69 nicm 1263: case INPUT_ESC_SCSG0_ON:
1264: ictx->cell.g0set = 1;
1265: break;
1266: case INPUT_ESC_SCSG0_OFF:
1267: ictx->cell.g0set = 0;
1268: break;
1269: case INPUT_ESC_SCSG1_ON:
1270: ictx->cell.g1set = 1;
1.1 nicm 1271: break;
1.69 nicm 1272: case INPUT_ESC_SCSG1_OFF:
1273: ictx->cell.g1set = 0;
1.1 nicm 1274: break;
1.107 nicm 1275: case INPUT_ESC_ST:
1276: /* ST terminates OSC but the state transition already did it. */
1277: break;
1.1 nicm 1278: }
1.28 nicm 1279:
1.127 nicm 1280: ictx->last = -1;
1.28 nicm 1281: return (0);
1.1 nicm 1282: }
1283:
1.28 nicm 1284: /* Execute control sequence. */
1.104 nicm 1285: static int
1.28 nicm 1286: input_csi_dispatch(struct input_ctx *ictx)
1.1 nicm 1287: {
1.28 nicm 1288: struct screen_write_ctx *sctx = &ictx->ctx;
1289: struct screen *s = sctx->s;
1290: struct input_table_entry *entry;
1.127 nicm 1291: int i, n, m;
1.131 nicm 1292: u_int cx, bg = ictx->cell.cell.bg;
1.1 nicm 1293:
1.28 nicm 1294: if (ictx->flags & INPUT_DISCARD)
1295: return (0);
1.110 nicm 1296:
1297: log_debug("%s: '%c' \"%s\" \"%s\"",
1298: __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1299:
1.28 nicm 1300: if (input_split(ictx) != 0)
1301: return (0);
1.1 nicm 1302:
1.28 nicm 1303: entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1304: sizeof input_csi_table[0], input_table_compare);
1305: if (entry == NULL) {
1306: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1307: return (0);
1308: }
1.1 nicm 1309:
1.28 nicm 1310: switch (entry->type) {
1311: case INPUT_CSI_CBT:
1312: /* Find the previous tab point, n times. */
1.81 nicm 1313: cx = s->cx;
1314: if (cx > screen_size_x(s) - 1)
1315: cx = screen_size_x(s) - 1;
1.28 nicm 1316: n = input_get(ictx, 0, 1, 1);
1.131 nicm 1317: if (n == -1)
1318: break;
1.81 nicm 1319: while (cx > 0 && n-- > 0) {
1.28 nicm 1320: do
1.81 nicm 1321: cx--;
1322: while (cx > 0 && !bit_test(s->tabs, cx));
1.28 nicm 1323: }
1.81 nicm 1324: s->cx = cx;
1.28 nicm 1325: break;
1326: case INPUT_CSI_CUB:
1.131 nicm 1327: n = input_get(ictx, 0, 1, 1);
1328: if (n != -1)
1329: screen_write_cursorleft(sctx, n);
1.28 nicm 1330: break;
1331: case INPUT_CSI_CUD:
1.131 nicm 1332: n = input_get(ictx, 0, 1, 1);
1333: if (n != -1)
1334: screen_write_cursordown(sctx, n);
1.28 nicm 1335: break;
1336: case INPUT_CSI_CUF:
1.131 nicm 1337: n = input_get(ictx, 0, 1, 1);
1338: if (n != -1)
1339: screen_write_cursorright(sctx, n);
1.28 nicm 1340: break;
1341: case INPUT_CSI_CUP:
1342: n = input_get(ictx, 0, 1, 1);
1343: m = input_get(ictx, 1, 1, 1);
1.131 nicm 1344: if (n != -1 && m != -1)
1.146 nicm 1345: screen_write_cursormove(sctx, m - 1, n - 1, 1);
1.28 nicm 1346: break;
1.65 nicm 1347: case INPUT_CSI_WINOPS:
1348: input_csi_dispatch_winops(ictx);
1349: break;
1.28 nicm 1350: case INPUT_CSI_CUU:
1.131 nicm 1351: n = input_get(ictx, 0, 1, 1);
1352: if (n != -1)
1353: screen_write_cursorup(sctx, n);
1.43 nicm 1354: break;
1355: case INPUT_CSI_CNL:
1.131 nicm 1356: n = input_get(ictx, 0, 1, 1);
1357: if (n != -1) {
1358: screen_write_carriagereturn(sctx);
1359: screen_write_cursordown(sctx, n);
1360: }
1.43 nicm 1361: break;
1362: case INPUT_CSI_CPL:
1.131 nicm 1363: n = input_get(ictx, 0, 1, 1);
1364: if (n != -1) {
1365: screen_write_carriagereturn(sctx);
1366: screen_write_cursorup(sctx, n);
1367: }
1.28 nicm 1368: break;
1369: case INPUT_CSI_DA:
1370: switch (input_get(ictx, 0, 0, 0)) {
1.131 nicm 1371: case -1:
1372: break;
1.28 nicm 1373: case 0:
1374: input_reply(ictx, "\033[?1;2c");
1.50 nicm 1375: break;
1376: default:
1377: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1378: break;
1379: }
1380: break;
1381: case INPUT_CSI_DA_TWO:
1382: switch (input_get(ictx, 0, 0, 0)) {
1.131 nicm 1383: case -1:
1384: break;
1.50 nicm 1385: case 0:
1.66 nicm 1386: input_reply(ictx, "\033[>84;0;0c");
1.28 nicm 1387: break;
1388: default:
1389: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1390: break;
1391: }
1.56 nicm 1392: break;
1393: case INPUT_CSI_ECH:
1.131 nicm 1394: n = input_get(ictx, 0, 1, 1);
1395: if (n != -1)
1396: screen_write_clearcharacter(sctx, n, bg);
1.28 nicm 1397: break;
1398: case INPUT_CSI_DCH:
1.131 nicm 1399: n = input_get(ictx, 0, 1, 1);
1400: if (n != -1)
1401: screen_write_deletecharacter(sctx, n, bg);
1.28 nicm 1402: break;
1403: case INPUT_CSI_DECSTBM:
1404: n = input_get(ictx, 0, 1, 1);
1405: m = input_get(ictx, 1, 1, screen_size_y(s));
1.131 nicm 1406: if (n != -1 && m != -1)
1407: screen_write_scrollregion(sctx, n - 1, m - 1);
1.1 nicm 1408: break;
1.28 nicm 1409: case INPUT_CSI_DL:
1.131 nicm 1410: n = input_get(ictx, 0, 1, 1);
1411: if (n != -1)
1412: screen_write_deleteline(sctx, n, bg);
1.1 nicm 1413: break;
1.28 nicm 1414: case INPUT_CSI_DSR:
1415: switch (input_get(ictx, 0, 0, 0)) {
1.131 nicm 1416: case -1:
1417: break;
1.28 nicm 1418: case 5:
1419: input_reply(ictx, "\033[0n");
1420: break;
1421: case 6:
1422: input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1423: break;
1424: default:
1425: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1426: break;
1427: }
1428: break;
1429: case INPUT_CSI_ED:
1430: switch (input_get(ictx, 0, 0, 0)) {
1.131 nicm 1431: case -1:
1432: break;
1.28 nicm 1433: case 0:
1.131 nicm 1434: screen_write_clearendofscreen(sctx, bg);
1.28 nicm 1435: break;
1436: case 1:
1.131 nicm 1437: screen_write_clearstartofscreen(sctx, bg);
1.28 nicm 1438: break;
1439: case 2:
1.131 nicm 1440: screen_write_clearscreen(sctx, bg);
1.41 nicm 1441: break;
1442: case 3:
1.131 nicm 1443: if (input_get(ictx, 1, 0, 0) == 0) {
1.41 nicm 1444: /*
1445: * Linux console extension to clear history
1446: * (for example before locking the screen).
1447: */
1448: screen_write_clearhistory(sctx);
1449: }
1.28 nicm 1450: break;
1451: default:
1452: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1453: break;
1454: }
1455: break;
1456: case INPUT_CSI_EL:
1457: switch (input_get(ictx, 0, 0, 0)) {
1.131 nicm 1458: case -1:
1459: break;
1.28 nicm 1460: case 0:
1.131 nicm 1461: screen_write_clearendofline(sctx, bg);
1.28 nicm 1462: break;
1463: case 1:
1.131 nicm 1464: screen_write_clearstartofline(sctx, bg);
1.28 nicm 1465: break;
1466: case 2:
1.131 nicm 1467: screen_write_clearline(sctx, bg);
1.28 nicm 1468: break;
1469: default:
1470: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1471: break;
1472: }
1473: break;
1474: case INPUT_CSI_HPA:
1475: n = input_get(ictx, 0, 1, 1);
1.131 nicm 1476: if (n != -1)
1.148 nicm 1477: screen_write_cursormove(sctx, n - 1, -1, 1);
1.28 nicm 1478: break;
1479: case INPUT_CSI_ICH:
1.131 nicm 1480: n = input_get(ictx, 0, 1, 1);
1481: if (n != -1)
1482: screen_write_insertcharacter(sctx, n, bg);
1.28 nicm 1483: break;
1484: case INPUT_CSI_IL:
1.131 nicm 1485: n = input_get(ictx, 0, 1, 1);
1486: if (n != -1)
1487: screen_write_insertline(sctx, n, bg);
1.28 nicm 1488: break;
1.127 nicm 1489: case INPUT_CSI_REP:
1.131 nicm 1490: n = input_get(ictx, 0, 1, 1);
1491: if (n == -1)
1492: break;
1493:
1.127 nicm 1494: if (ictx->last == -1)
1495: break;
1496: ictx->ch = ictx->last;
1497:
1498: for (i = 0; i < n; i++)
1499: input_print(ictx);
1500: break;
1.42 nicm 1501: case INPUT_CSI_RCP:
1.146 nicm 1502: input_restore_state(ictx);
1.42 nicm 1503: break;
1.28 nicm 1504: case INPUT_CSI_RM:
1.64 nicm 1505: input_csi_dispatch_rm(ictx);
1506: break;
1507: case INPUT_CSI_RM_PRIVATE:
1508: input_csi_dispatch_rm_private(ictx);
1509: break;
1510: case INPUT_CSI_SCP:
1.146 nicm 1511: input_save_state(ictx);
1.64 nicm 1512: break;
1513: case INPUT_CSI_SGR:
1514: input_csi_dispatch_sgr(ictx);
1515: break;
1516: case INPUT_CSI_SM:
1517: input_csi_dispatch_sm(ictx);
1518: break;
1519: case INPUT_CSI_SM_PRIVATE:
1520: input_csi_dispatch_sm_private(ictx);
1.115 nicm 1521: break;
1522: case INPUT_CSI_SU:
1.131 nicm 1523: n = input_get(ictx, 0, 1, 1);
1524: if (n != -1)
1525: screen_write_scrollup(sctx, n, bg);
1.64 nicm 1526: break;
1527: case INPUT_CSI_TBC:
1528: switch (input_get(ictx, 0, 0, 0)) {
1.131 nicm 1529: case -1:
1530: break;
1.64 nicm 1531: case 0:
1532: if (s->cx < screen_size_x(s))
1533: bit_clear(s->tabs, s->cx);
1534: break;
1535: case 3:
1536: bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1537: break;
1538: default:
1539: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1540: break;
1541: }
1542: break;
1543: case INPUT_CSI_VPA:
1544: n = input_get(ictx, 0, 1, 1);
1.131 nicm 1545: if (n != -1)
1.148 nicm 1546: screen_write_cursormove(sctx, -1, n - 1, 1);
1.64 nicm 1547: break;
1548: case INPUT_CSI_DECSCUSR:
1549: n = input_get(ictx, 0, 0, 0);
1.131 nicm 1550: if (n != -1)
1551: screen_set_cursor_style(s, n);
1.64 nicm 1552: break;
1553: }
1554:
1.127 nicm 1555: ictx->last = -1;
1.64 nicm 1556: return (0);
1557: }
1558:
1559: /* Handle CSI RM. */
1.104 nicm 1560: static void
1.64 nicm 1561: input_csi_dispatch_rm(struct input_ctx *ictx)
1562: {
1.144 nicm 1563: struct screen_write_ctx *sctx = &ictx->ctx;
1564: u_int i;
1.64 nicm 1565:
1566: for (i = 0; i < ictx->param_list_len; i++) {
1567: switch (input_get(ictx, i, 0, -1)) {
1.131 nicm 1568: case -1:
1569: break;
1.28 nicm 1570: case 4: /* IRM */
1.144 nicm 1571: screen_write_mode_clear(sctx, MODE_INSERT);
1.28 nicm 1572: break;
1.72 nicm 1573: case 34:
1.144 nicm 1574: screen_write_mode_set(sctx, MODE_BLINKING);
1.72 nicm 1575: break;
1.28 nicm 1576: default:
1577: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1578: break;
1579: }
1.64 nicm 1580: }
1581: }
1582:
1583: /* Handle CSI private RM. */
1.104 nicm 1584: static void
1.64 nicm 1585: input_csi_dispatch_rm_private(struct input_ctx *ictx)
1586: {
1.144 nicm 1587: struct screen_write_ctx *sctx = &ictx->ctx;
1.69 nicm 1588: struct window_pane *wp = ictx->wp;
1589: u_int i;
1.64 nicm 1590:
1591: for (i = 0; i < ictx->param_list_len; i++) {
1592: switch (input_get(ictx, i, 0, -1)) {
1.131 nicm 1593: case -1:
1594: break;
1.64 nicm 1595: case 1: /* DECCKM */
1.144 nicm 1596: screen_write_mode_clear(sctx, MODE_KCURSOR);
1.1 nicm 1597: break;
1.17 nicm 1598: case 3: /* DECCOLM */
1.146 nicm 1599: screen_write_cursormove(sctx, 0, 0, 1);
1.144 nicm 1600: screen_write_clearscreen(sctx, ictx->cell.cell.bg);
1.17 nicm 1601: break;
1.141 nicm 1602: case 6: /* DECOM */
1.144 nicm 1603: screen_write_mode_clear(sctx, MODE_ORIGIN);
1.146 nicm 1604: screen_write_cursormove(sctx, 0, 0, 1);
1.141 nicm 1605: break;
1.61 nicm 1606: case 7: /* DECAWM */
1.144 nicm 1607: screen_write_mode_clear(sctx, MODE_WRAP);
1.61 nicm 1608: break;
1.72 nicm 1609: case 12:
1.144 nicm 1610: screen_write_mode_clear(sctx, MODE_BLINKING);
1.72 nicm 1611: break;
1.1 nicm 1612: case 25: /* TCEM */
1.144 nicm 1613: screen_write_mode_clear(sctx, MODE_CURSOR);
1.1 nicm 1614: break;
1615: case 1000:
1.32 nicm 1616: case 1001:
1617: case 1002:
1.109 nicm 1618: case 1003:
1.144 nicm 1619: screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1.1 nicm 1620: break;
1.62 nicm 1621: case 1004:
1.144 nicm 1622: screen_write_mode_clear(sctx, MODE_FOCUSON);
1.62 nicm 1623: break;
1.96 nicm 1624: case 1005:
1.144 nicm 1625: screen_write_mode_clear(sctx, MODE_MOUSE_UTF8);
1.96 nicm 1626: break;
1.60 nicm 1627: case 1006:
1.144 nicm 1628: screen_write_mode_clear(sctx, MODE_MOUSE_SGR);
1.60 nicm 1629: break;
1.55 nicm 1630: case 47:
1631: case 1047:
1.69 nicm 1632: window_pane_alternate_off(wp, &ictx->cell.cell, 0);
1.55 nicm 1633: break;
1.9 nicm 1634: case 1049:
1.69 nicm 1635: window_pane_alternate_off(wp, &ictx->cell.cell, 1);
1.9 nicm 1636: break;
1.49 nicm 1637: case 2004:
1.144 nicm 1638: screen_write_mode_clear(sctx, MODE_BRACKETPASTE);
1.49 nicm 1639: break;
1.1 nicm 1640: default:
1.28 nicm 1641: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1642: break;
1643: }
1.64 nicm 1644: }
1645: }
1646:
1647: /* Handle CSI SM. */
1.104 nicm 1648: static void
1.64 nicm 1649: input_csi_dispatch_sm(struct input_ctx *ictx)
1650: {
1.144 nicm 1651: struct screen_write_ctx *sctx = &ictx->ctx;
1652: u_int i;
1.64 nicm 1653:
1654: for (i = 0; i < ictx->param_list_len; i++) {
1655: switch (input_get(ictx, i, 0, -1)) {
1.131 nicm 1656: case -1:
1657: break;
1.1 nicm 1658: case 4: /* IRM */
1.144 nicm 1659: screen_write_mode_set(sctx, MODE_INSERT);
1.1 nicm 1660: break;
1.72 nicm 1661: case 34:
1.144 nicm 1662: screen_write_mode_clear(sctx, MODE_BLINKING);
1.72 nicm 1663: break;
1.1 nicm 1664: default:
1.28 nicm 1665: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1666: break;
1667: }
1.64 nicm 1668: }
1669: }
1670:
1671: /* Handle CSI private SM. */
1.104 nicm 1672: static void
1.64 nicm 1673: input_csi_dispatch_sm_private(struct input_ctx *ictx)
1674: {
1.144 nicm 1675: struct screen_write_ctx *sctx = &ictx->ctx;
1.69 nicm 1676: struct window_pane *wp = ictx->wp;
1677: u_int i;
1.64 nicm 1678:
1679: for (i = 0; i < ictx->param_list_len; i++) {
1680: switch (input_get(ictx, i, 0, -1)) {
1.131 nicm 1681: case -1:
1682: break;
1.64 nicm 1683: case 1: /* DECCKM */
1.144 nicm 1684: screen_write_mode_set(sctx, MODE_KCURSOR);
1.17 nicm 1685: break;
1686: case 3: /* DECCOLM */
1.146 nicm 1687: screen_write_cursormove(sctx, 0, 0, 1);
1.144 nicm 1688: screen_write_clearscreen(sctx, ictx->cell.cell.bg);
1.141 nicm 1689: break;
1690: case 6: /* DECOM */
1.144 nicm 1691: screen_write_mode_set(sctx, MODE_ORIGIN);
1.146 nicm 1692: screen_write_cursormove(sctx, 0, 0, 1);
1.61 nicm 1693: break;
1694: case 7: /* DECAWM */
1.144 nicm 1695: screen_write_mode_set(sctx, MODE_WRAP);
1.72 nicm 1696: break;
1697: case 12:
1.144 nicm 1698: screen_write_mode_set(sctx, MODE_BLINKING);
1.1 nicm 1699: break;
1700: case 25: /* TCEM */
1.144 nicm 1701: screen_write_mode_set(sctx, MODE_CURSOR);
1.1 nicm 1702: break;
1703: case 1000:
1.144 nicm 1704: screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1705: screen_write_mode_set(sctx, MODE_MOUSE_STANDARD);
1.32 nicm 1706: break;
1707: case 1002:
1.144 nicm 1708: screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1709: screen_write_mode_set(sctx, MODE_MOUSE_BUTTON);
1.109 nicm 1710: break;
1711: case 1003:
1.144 nicm 1712: screen_write_mode_clear(sctx, ALL_MOUSE_MODES);
1713: screen_write_mode_set(sctx, MODE_MOUSE_ALL);
1.62 nicm 1714: break;
1715: case 1004:
1.144 nicm 1716: if (sctx->s->mode & MODE_FOCUSON)
1.62 nicm 1717: break;
1.144 nicm 1718: screen_write_mode_set(sctx, MODE_FOCUSON);
1.69 nicm 1719: wp->flags |= PANE_FOCUSPUSH; /* force update */
1.96 nicm 1720: break;
1721: case 1005:
1.144 nicm 1722: screen_write_mode_set(sctx, MODE_MOUSE_UTF8);
1.60 nicm 1723: break;
1724: case 1006:
1.144 nicm 1725: screen_write_mode_set(sctx, MODE_MOUSE_SGR);
1.9 nicm 1726: break;
1.55 nicm 1727: case 47:
1728: case 1047:
1.69 nicm 1729: window_pane_alternate_on(wp, &ictx->cell.cell, 0);
1.55 nicm 1730: break;
1.9 nicm 1731: case 1049:
1.69 nicm 1732: window_pane_alternate_on(wp, &ictx->cell.cell, 1);
1.49 nicm 1733: break;
1734: case 2004:
1.144 nicm 1735: screen_write_mode_set(sctx, MODE_BRACKETPASTE);
1.1 nicm 1736: break;
1737: default:
1.28 nicm 1738: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1739: break;
1740: }
1.65 nicm 1741: }
1742: }
1743:
1744: /* Handle CSI window operations. */
1.104 nicm 1745: static void
1.65 nicm 1746: input_csi_dispatch_winops(struct input_ctx *ictx)
1747: {
1.144 nicm 1748: struct screen_write_ctx *sctx = &ictx->ctx;
1.65 nicm 1749: struct window_pane *wp = ictx->wp;
1750: int n, m;
1751:
1752: m = 0;
1753: while ((n = input_get(ictx, m, 0, -1)) != -1) {
1754: switch (n) {
1755: case 1:
1756: case 2:
1757: case 5:
1758: case 6:
1759: case 7:
1760: case 11:
1761: case 13:
1762: case 14:
1763: case 19:
1764: case 20:
1765: case 21:
1766: case 24:
1767: break;
1768: case 3:
1769: case 4:
1770: case 8:
1771: m++;
1772: if (input_get(ictx, m, 0, -1) == -1)
1773: return;
1774: /* FALLTHROUGH */
1775: case 9:
1776: case 10:
1.129 nicm 1777: m++;
1778: if (input_get(ictx, m, 0, -1) == -1)
1779: return;
1780: break;
1.65 nicm 1781: case 22:
1.129 nicm 1782: m++;
1783: switch (input_get(ictx, m, 0, -1)) {
1784: case -1:
1785: return;
1786: case 0:
1787: case 2:
1.144 nicm 1788: screen_push_title(sctx->s);
1.129 nicm 1789: break;
1790: }
1791: break;
1.65 nicm 1792: case 23:
1793: m++;
1.129 nicm 1794: switch (input_get(ictx, m, 0, -1)) {
1795: case -1:
1.65 nicm 1796: return;
1.129 nicm 1797: case 0:
1798: case 2:
1.144 nicm 1799: screen_pop_title(sctx->s);
1.129 nicm 1800: server_status_window(ictx->wp->window);
1801: break;
1802: }
1.65 nicm 1803: break;
1804: case 18:
1.76 nicm 1805: input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx);
1.65 nicm 1806: break;
1807: default:
1808: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1809: break;
1810: }
1811: m++;
1.1 nicm 1812: }
1813: }
1814:
1.131 nicm 1815: /* Helper for 256 colour SGR. */
1816: static int
1817: input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c)
1.78 nicm 1818: {
1819: struct grid_cell *gc = &ictx->cell.cell;
1820:
1.131 nicm 1821: if (c == -1 || c > 255) {
1.102 nicm 1822: if (fgbg == 38)
1.78 nicm 1823: gc->fg = 8;
1.102 nicm 1824: else if (fgbg == 48)
1.78 nicm 1825: gc->bg = 8;
1826: } else {
1.102 nicm 1827: if (fgbg == 38)
1828: gc->fg = c | COLOUR_FLAG_256;
1829: else if (fgbg == 48)
1830: gc->bg = c | COLOUR_FLAG_256;
1.78 nicm 1831: }
1.131 nicm 1832: return (1);
1.78 nicm 1833: }
1834:
1.131 nicm 1835: /* Handle CSI SGR for 256 colours. */
1.104 nicm 1836: static void
1.131 nicm 1837: input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
1838: {
1839: int c;
1840:
1841: c = input_get(ictx, (*i) + 1, 0, -1);
1842: if (input_csi_dispatch_sgr_256_do(ictx, fgbg, c))
1843: (*i)++;
1844: }
1845:
1846: /* Helper for RGB colour SGR. */
1847: static int
1848: input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g,
1849: int b)
1.78 nicm 1850: {
1851: struct grid_cell *gc = &ictx->cell.cell;
1852:
1853: if (r == -1 || r > 255)
1.131 nicm 1854: return (0);
1.78 nicm 1855: if (g == -1 || g > 255)
1.131 nicm 1856: return (0);
1.78 nicm 1857: if (b == -1 || b > 255)
1.131 nicm 1858: return (0);
1.78 nicm 1859:
1.102 nicm 1860: if (fgbg == 38)
1861: gc->fg = colour_join_rgb(r, g, b);
1862: else if (fgbg == 48)
1863: gc->bg = colour_join_rgb(r, g, b);
1.131 nicm 1864: return (1);
1865: }
1866:
1867: /* Handle CSI SGR for RGB colours. */
1868: static void
1869: input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
1870: {
1871: int r, g, b;
1872:
1873: r = input_get(ictx, (*i) + 1, 0, -1);
1874: g = input_get(ictx, (*i) + 2, 0, -1);
1875: b = input_get(ictx, (*i) + 3, 0, -1);
1876: if (input_csi_dispatch_sgr_rgb_do(ictx, fgbg, r, g, b))
1877: (*i) += 3;
1878: }
1879:
1880: /* Handle CSI SGR with a ISO parameter. */
1881: static void
1882: input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
1883: {
1.137 nicm 1884: struct grid_cell *gc = &ictx->cell.cell;
1885: char *s = ictx->param_list[i].str, *copy, *ptr, *out;
1886: int p[8];
1887: u_int n;
1888: const char *errstr;
1.131 nicm 1889:
1890: for (n = 0; n < nitems(p); n++)
1891: p[n] = -1;
1892: n = 0;
1893:
1894: ptr = copy = xstrdup(s);
1895: while ((out = strsep(&ptr, ":")) != NULL) {
1.134 nicm 1896: if (*out != '\0') {
1897: p[n++] = strtonum(out, 0, INT_MAX, &errstr);
1898: if (errstr != NULL || n == nitems(p)) {
1899: free(copy);
1900: return;
1901: }
1.140 nicm 1902: } else
1903: n++;
1.131 nicm 1904: log_debug("%s: %u = %d", __func__, n - 1, p[n - 1]);
1905: }
1906: free(copy);
1907:
1.137 nicm 1908: if (n == 0)
1909: return;
1910: if (p[0] == 4) {
1911: if (n != 2)
1912: return;
1913: switch (p[1]) {
1914: case 0:
1915: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1916: break;
1917: case 1:
1918: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1919: gc->attr |= GRID_ATTR_UNDERSCORE;
1920: break;
1921: case 2:
1922: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1923: gc->attr |= GRID_ATTR_UNDERSCORE_2;
1924: break;
1925: case 3:
1926: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1927: gc->attr |= GRID_ATTR_UNDERSCORE_3;
1928: break;
1929: case 4:
1930: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1931: gc->attr |= GRID_ATTR_UNDERSCORE_4;
1932: break;
1933: case 5:
1934: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1935: gc->attr |= GRID_ATTR_UNDERSCORE_5;
1936: break;
1937: }
1938: return;
1939: }
1940: if (p[0] != 38 && p[0] != 48)
1.131 nicm 1941: return;
1.134 nicm 1942: if (p[1] == -1)
1943: i = 2;
1944: else
1945: i = 1;
1946: switch (p[i]) {
1.131 nicm 1947: case 2:
1.134 nicm 1948: if (n < i + 4)
1.131 nicm 1949: break;
1.134 nicm 1950: input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[i + 1], p[i + 2],
1951: p[i + 3]);
1.131 nicm 1952: break;
1953: case 5:
1.134 nicm 1954: if (n < i + 2)
1.131 nicm 1955: break;
1.134 nicm 1956: input_csi_dispatch_sgr_256_do(ictx, p[0], p[i + 1]);
1.131 nicm 1957: break;
1958: }
1.78 nicm 1959: }
1960:
1.28 nicm 1961: /* Handle CSI SGR. */
1.104 nicm 1962: static void
1.28 nicm 1963: input_csi_dispatch_sgr(struct input_ctx *ictx)
1.1 nicm 1964: {
1.69 nicm 1965: struct grid_cell *gc = &ictx->cell.cell;
1.28 nicm 1966: u_int i;
1.78 nicm 1967: int n;
1.1 nicm 1968:
1.28 nicm 1969: if (ictx->param_list_len == 0) {
1.1 nicm 1970: memcpy(gc, &grid_default_cell, sizeof *gc);
1971: return;
1972: }
1973:
1.28 nicm 1974: for (i = 0; i < ictx->param_list_len; i++) {
1.131 nicm 1975: if (ictx->param_list[i].type == INPUT_STRING) {
1976: input_csi_dispatch_sgr_colon(ictx, i);
1977: continue;
1978: }
1.28 nicm 1979: n = input_get(ictx, i, 0, 0);
1.131 nicm 1980: if (n == -1)
1981: continue;
1.1 nicm 1982:
1.28 nicm 1983: if (n == 38 || n == 48) {
1.1 nicm 1984: i++;
1.78 nicm 1985: switch (input_get(ictx, i, 0, -1)) {
1986: case 2:
1987: input_csi_dispatch_sgr_rgb(ictx, n, &i);
1988: break;
1989: case 5:
1990: input_csi_dispatch_sgr_256(ictx, n, &i);
1991: break;
1.1 nicm 1992: }
1993: continue;
1994: }
1995:
1.28 nicm 1996: switch (n) {
1.1 nicm 1997: case 0:
1998: memcpy(gc, &grid_default_cell, sizeof *gc);
1999: break;
2000: case 1:
2001: gc->attr |= GRID_ATTR_BRIGHT;
2002: break;
2003: case 2:
2004: gc->attr |= GRID_ATTR_DIM;
2005: break;
2006: case 3:
2007: gc->attr |= GRID_ATTR_ITALICS;
2008: break;
2009: case 4:
1.137 nicm 2010: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1.1 nicm 2011: gc->attr |= GRID_ATTR_UNDERSCORE;
2012: break;
2013: case 5:
2014: gc->attr |= GRID_ATTR_BLINK;
2015: break;
2016: case 7:
2017: gc->attr |= GRID_ATTR_REVERSE;
2018: break;
2019: case 8:
2020: gc->attr |= GRID_ATTR_HIDDEN;
2021: break;
1.118 nicm 2022: case 9:
2023: gc->attr |= GRID_ATTR_STRIKETHROUGH;
2024: break;
1.1 nicm 2025: case 22:
2026: gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
2027: break;
2028: case 23:
2029: gc->attr &= ~GRID_ATTR_ITALICS;
2030: break;
2031: case 24:
1.137 nicm 2032: gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE;
1.1 nicm 2033: break;
2034: case 25:
2035: gc->attr &= ~GRID_ATTR_BLINK;
2036: break;
2037: case 27:
2038: gc->attr &= ~GRID_ATTR_REVERSE;
1.117 nicm 2039: break;
2040: case 28:
2041: gc->attr &= ~GRID_ATTR_HIDDEN;
1.118 nicm 2042: break;
2043: case 29:
2044: gc->attr &= ~GRID_ATTR_STRIKETHROUGH;
1.1 nicm 2045: break;
2046: case 30:
2047: case 31:
2048: case 32:
2049: case 33:
2050: case 34:
2051: case 35:
2052: case 36:
2053: case 37:
1.28 nicm 2054: gc->fg = n - 30;
1.1 nicm 2055: break;
2056: case 39:
2057: gc->fg = 8;
2058: break;
2059: case 40:
2060: case 41:
2061: case 42:
2062: case 43:
2063: case 44:
2064: case 45:
2065: case 46:
2066: case 47:
1.28 nicm 2067: gc->bg = n - 40;
1.1 nicm 2068: break;
2069: case 49:
2070: gc->bg = 8;
1.20 nicm 2071: break;
2072: case 90:
2073: case 91:
2074: case 92:
2075: case 93:
2076: case 94:
2077: case 95:
2078: case 96:
2079: case 97:
1.28 nicm 2080: gc->fg = n;
1.20 nicm 2081: break;
2082: case 100:
2083: case 101:
2084: case 102:
2085: case 103:
2086: case 104:
2087: case 105:
2088: case 106:
2089: case 107:
1.47 nicm 2090: gc->bg = n - 10;
1.1 nicm 2091: break;
2092: }
2093: }
1.28 nicm 2094: }
2095:
1.138 nicm 2096: /* End of input with BEL. */
2097: static int
2098: input_end_bel(struct input_ctx *ictx)
2099: {
2100: log_debug("%s", __func__);
2101:
2102: ictx->input_end = INPUT_END_BEL;
2103:
2104: return (0);
2105: }
2106:
1.125 nicm 2107: /* DCS string started. */
2108: static void
2109: input_enter_dcs(struct input_ctx *ictx)
2110: {
2111: log_debug("%s", __func__);
2112:
2113: input_clear(ictx);
2114: input_start_timer(ictx);
1.127 nicm 2115: ictx->last = -1;
1.125 nicm 2116: }
2117:
1.37 nicm 2118: /* DCS terminator (ST) received. */
1.104 nicm 2119: static int
1.37 nicm 2120: input_dcs_dispatch(struct input_ctx *ictx)
1.28 nicm 2121: {
1.144 nicm 2122: struct screen_write_ctx *sctx = &ictx->ctx;
2123: u_char *buf = ictx->input_buf;
2124: size_t len = ictx->input_len;
2125: const char prefix[] = "tmux;";
2126: const u_int prefixlen = (sizeof prefix) - 1;
1.37 nicm 2127:
2128: if (ictx->flags & INPUT_DISCARD)
2129: return (0);
2130:
1.144 nicm 2131: log_debug("%s: \"%s\"", __func__, buf);
1.28 nicm 2132:
1.144 nicm 2133: if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0)
2134: screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen);
1.28 nicm 2135:
1.37 nicm 2136: return (0);
1.28 nicm 2137: }
2138:
2139: /* OSC string started. */
1.104 nicm 2140: static void
1.28 nicm 2141: input_enter_osc(struct input_ctx *ictx)
2142: {
2143: log_debug("%s", __func__);
2144:
1.35 nicm 2145: input_clear(ictx);
1.125 nicm 2146: input_start_timer(ictx);
1.127 nicm 2147: ictx->last = -1;
1.28 nicm 2148: }
2149:
2150: /* OSC terminator (ST) received. */
1.104 nicm 2151: static void
1.28 nicm 2152: input_exit_osc(struct input_ctx *ictx)
2153: {
1.144 nicm 2154: struct screen_write_ctx *sctx = &ictx->ctx;
2155: u_char *p = ictx->input_buf;
2156: u_int option;
1.38 nicm 2157:
1.28 nicm 2158: if (ictx->flags & INPUT_DISCARD)
2159: return;
1.38 nicm 2160: if (ictx->input_len < 1 || *p < '0' || *p > '9')
2161: return;
1.28 nicm 2162:
1.138 nicm 2163: log_debug("%s: \"%s\" (end %s)", __func__, p,
2164: ictx->input_end == INPUT_END_ST ? "ST" : "BEL");
1.28 nicm 2165:
1.38 nicm 2166: option = 0;
2167: while (*p >= '0' && *p <= '9')
2168: option = option * 10 + *p++ - '0';
2169: if (*p == ';')
2170: p++;
2171:
2172: switch (option) {
2173: case 0:
2174: case 2:
1.124 nicm 2175: if (utf8_isvalid(p)) {
1.144 nicm 2176: screen_set_title(sctx->s, p);
1.124 nicm 2177: server_status_window(ictx->wp->window);
2178: }
1.38 nicm 2179: break;
1.107 nicm 2180: case 4:
1.138 nicm 2181: input_osc_4(ictx, p);
1.107 nicm 2182: break;
1.122 nicm 2183: case 10:
1.138 nicm 2184: input_osc_10(ictx, p);
1.122 nicm 2185: break;
2186: case 11:
1.138 nicm 2187: input_osc_11(ictx, p);
1.108 nicm 2188: break;
1.38 nicm 2189: case 12:
1.124 nicm 2190: if (utf8_isvalid(p) && *p != '?') /* ? is colour request */
1.144 nicm 2191: screen_set_cursor_colour(sctx->s, p);
1.38 nicm 2192: break;
1.122 nicm 2193: case 52:
1.138 nicm 2194: input_osc_52(ictx, p);
1.122 nicm 2195: break;
1.107 nicm 2196: case 104:
1.138 nicm 2197: input_osc_104(ictx, p);
1.107 nicm 2198: break;
1.38 nicm 2199: case 112:
1.57 nicm 2200: if (*p == '\0') /* no arguments allowed */
1.144 nicm 2201: screen_set_cursor_colour(sctx->s, "");
1.38 nicm 2202: break;
2203: default:
2204: log_debug("%s: unknown '%u'", __func__, option);
2205: break;
2206: }
1.28 nicm 2207: }
2208:
2209: /* APC string started. */
1.104 nicm 2210: static void
1.28 nicm 2211: input_enter_apc(struct input_ctx *ictx)
2212: {
2213: log_debug("%s", __func__);
2214:
1.35 nicm 2215: input_clear(ictx);
1.125 nicm 2216: input_start_timer(ictx);
1.127 nicm 2217: ictx->last = -1;
1.28 nicm 2218: }
2219:
2220: /* APC terminator (ST) received. */
1.104 nicm 2221: static void
1.28 nicm 2222: input_exit_apc(struct input_ctx *ictx)
2223: {
1.144 nicm 2224: struct screen_write_ctx *sctx = &ictx->ctx;
2225:
1.28 nicm 2226: if (ictx->flags & INPUT_DISCARD)
2227: return;
2228: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2229:
1.124 nicm 2230: if (!utf8_isvalid(ictx->input_buf))
2231: return;
1.144 nicm 2232: screen_set_title(sctx->s, ictx->input_buf);
1.28 nicm 2233: server_status_window(ictx->wp->window);
2234: }
2235:
2236: /* Rename string started. */
1.104 nicm 2237: static void
1.28 nicm 2238: input_enter_rename(struct input_ctx *ictx)
2239: {
2240: log_debug("%s", __func__);
2241:
1.35 nicm 2242: input_clear(ictx);
1.125 nicm 2243: input_start_timer(ictx);
1.127 nicm 2244: ictx->last = -1;
1.28 nicm 2245: }
2246:
2247: /* Rename terminator (ST) received. */
1.104 nicm 2248: static void
1.28 nicm 2249: input_exit_rename(struct input_ctx *ictx)
2250: {
2251: if (ictx->flags & INPUT_DISCARD)
1.44 nicm 2252: return;
1.87 nicm 2253: if (!options_get_number(ictx->wp->window->options, "allow-rename"))
1.28 nicm 2254: return;
2255: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
2256:
1.124 nicm 2257: if (!utf8_isvalid(ictx->input_buf))
2258: return;
1.48 nicm 2259: window_set_name(ictx->wp->window, ictx->input_buf);
1.87 nicm 2260: options_set_number(ictx->wp->window->options, "automatic-rename", 0);
1.28 nicm 2261: server_status_window(ictx->wp->window);
2262: }
2263:
2264: /* Open UTF-8 character. */
1.104 nicm 2265: static int
1.130 nicm 2266: input_top_bit_set(struct input_ctx *ictx)
1.28 nicm 2267: {
1.144 nicm 2268: struct screen_write_ctx *sctx = &ictx->ctx;
1.90 nicm 2269: struct utf8_data *ud = &ictx->utf8data;
2270:
1.127 nicm 2271: ictx->last = -1;
1.28 nicm 2272:
1.130 nicm 2273: if (!ictx->utf8started) {
2274: if (utf8_open(ud, ictx->ch) != UTF8_MORE)
2275: return (0);
2276: ictx->utf8started = 1;
2277: return (0);
2278: }
1.28 nicm 2279:
1.130 nicm 2280: switch (utf8_append(ud, ictx->ch)) {
2281: case UTF8_MORE:
2282: return (0);
2283: case UTF8_ERROR:
2284: ictx->utf8started = 0;
1.101 nicm 2285: return (0);
1.130 nicm 2286: case UTF8_DONE:
2287: break;
1.101 nicm 2288: }
1.130 nicm 2289: ictx->utf8started = 0;
1.28 nicm 2290:
1.90 nicm 2291: log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
2292: (int)ud->size, ud->data, ud->width);
1.28 nicm 2293:
1.90 nicm 2294: utf8_copy(&ictx->cell.cell.data, ud);
1.144 nicm 2295: screen_write_collect_add(sctx, &ictx->cell.cell);
1.28 nicm 2296:
2297: return (0);
1.107 nicm 2298: }
2299:
2300: /* Handle the OSC 4 sequence for setting (multiple) palette entries. */
2301: static void
1.138 nicm 2302: input_osc_4(struct input_ctx *ictx, const char *p)
1.107 nicm 2303: {
1.138 nicm 2304: struct window_pane *wp = ictx->wp;
2305: char *copy, *s, *next = NULL;
1.144 nicm 2306: long idx;
1.138 nicm 2307: u_int r, g, b;
1.107 nicm 2308:
2309: copy = s = xstrdup(p);
2310: while (s != NULL && *s != '\0') {
2311: idx = strtol(s, &next, 10);
2312: if (*next++ != ';')
2313: goto bad;
2314: if (idx < 0 || idx >= 0x100)
2315: goto bad;
2316:
2317: s = strsep(&next, ";");
2318: if (sscanf(s, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3) {
2319: s = next;
2320: continue;
2321: }
2322:
2323: window_pane_set_palette(wp, idx, colour_join_rgb(r, g, b));
2324: s = next;
2325: }
2326:
2327: free(copy);
2328: return;
2329:
2330: bad:
2331: log_debug("bad OSC 4: %s", p);
2332: free(copy);
1.122 nicm 2333: }
2334:
1.136 nicm 2335: /* Handle the OSC 10 sequence for setting foreground colour. */
1.122 nicm 2336: static void
1.138 nicm 2337: input_osc_10(struct input_ctx *ictx, const char *p)
1.122 nicm 2338: {
1.138 nicm 2339: struct window_pane *wp = ictx->wp;
2340: u_int r, g, b;
1.122 nicm 2341:
2342: if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2343: goto bad;
2344:
1.149 nicm 2345: wp->style.gc.fg = colour_join_rgb(r, g, b);
1.122 nicm 2346: wp->flags |= PANE_REDRAW;
2347:
2348: return;
2349:
2350: bad:
2351: log_debug("bad OSC 10: %s", p);
2352: }
2353:
2354: /* Handle the OSC 11 sequence for setting background colour. */
2355: static void
1.138 nicm 2356: input_osc_11(struct input_ctx *ictx, const char *p)
1.122 nicm 2357: {
1.138 nicm 2358: struct window_pane *wp = ictx->wp;
2359: u_int r, g, b;
1.122 nicm 2360:
2361: if (sscanf(p, "rgb:%2x/%2x/%2x", &r, &g, &b) != 3)
2362: goto bad;
2363:
1.149 nicm 2364: wp->style.gc.bg = colour_join_rgb(r, g, b);
1.122 nicm 2365: wp->flags |= PANE_REDRAW;
2366:
2367: return;
2368:
2369: bad:
2370: log_debug("bad OSC 11: %s", p);
1.108 nicm 2371: }
2372:
2373: /* Handle the OSC 52 sequence for setting the clipboard. */
2374: static void
1.138 nicm 2375: input_osc_52(struct input_ctx *ictx, const char *p)
1.108 nicm 2376: {
1.138 nicm 2377: struct window_pane *wp = ictx->wp;
1.108 nicm 2378: char *end;
1.138 nicm 2379: const char *buf;
1.108 nicm 2380: size_t len;
2381: u_char *out;
1.123 nicm 2382: int outlen, state;
1.108 nicm 2383: struct screen_write_ctx ctx;
1.138 nicm 2384: struct paste_buffer *pb;
1.108 nicm 2385:
1.123 nicm 2386: state = options_get_number(global_options, "set-clipboard");
2387: if (state != 2)
2388: return;
2389:
1.108 nicm 2390: if ((end = strchr(p, ';')) == NULL)
2391: return;
2392: end++;
2393: if (*end == '\0')
2394: return;
1.138 nicm 2395: log_debug("%s: %s", __func__, end);
2396:
2397: if (strcmp(end, "?") == 0) {
2398: if ((pb = paste_get_top(NULL)) != NULL) {
2399: buf = paste_buffer_data(pb, &len);
2400: outlen = 4 * ((len + 2) / 3) + 1;
2401: out = xmalloc(outlen);
2402: if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
2403: abort();
2404: free(out);
2405: return;
2406: }
2407: } else {
2408: outlen = 0;
2409: out = NULL;
2410: }
2411: bufferevent_write(wp->event, "\033]52;;", 6);
2412: if (outlen != 0)
2413: bufferevent_write(wp->event, out, outlen);
2414: if (ictx->input_end == INPUT_END_BEL)
2415: bufferevent_write(wp->event, "\007", 1);
2416: else
2417: bufferevent_write(wp->event, "\033\\", 2);
2418: free(out);
2419: return;
2420: }
1.108 nicm 2421:
2422: len = (strlen(end) / 4) * 3;
2423: if (len == 0)
2424: return;
2425:
2426: out = xmalloc(len);
2427: if ((outlen = b64_pton(end, out, len)) == -1) {
2428: free(out);
2429: return;
2430: }
2431:
1.123 nicm 2432: screen_write_start(&ctx, wp, NULL);
2433: screen_write_setselection(&ctx, out, outlen);
2434: screen_write_stop(&ctx);
1.126 nicm 2435: notify_pane("pane-set-clipboard", wp);
1.123 nicm 2436:
1.150 nicm 2437: paste_add(NULL, out, outlen);
1.107 nicm 2438: }
2439:
2440: /* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
2441: static void
1.138 nicm 2442: input_osc_104(struct input_ctx *ictx, const char *p)
1.107 nicm 2443: {
1.138 nicm 2444: struct window_pane *wp = ictx->wp;
2445: char *copy, *s;
1.144 nicm 2446: long idx;
1.107 nicm 2447:
2448: if (*p == '\0') {
2449: window_pane_reset_palette(wp);
2450: return;
2451: }
2452:
2453: copy = s = xstrdup(p);
2454: while (*s != '\0') {
2455: idx = strtol(s, &s, 10);
2456: if (*s != '\0' && *s != ';')
2457: goto bad;
2458: if (idx < 0 || idx >= 0x100)
2459: goto bad;
2460:
2461: window_pane_unset_palette(wp, idx);
2462: if (*s == ';')
2463: s++;
2464: }
2465: free(copy);
2466: return;
2467:
2468: bad:
2469: log_debug("bad OSC 104: %s", p);
2470: free(copy);
1.1 nicm 2471: }