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