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