Annotation of src/usr.bin/tmux/input.c, Revision 1.74
1.74 ! nicm 1: /* $OpenBSD: input.c,v 1.73 2015/03/31 17:45:10 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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:
21: #include <stdlib.h>
22: #include <string.h>
23:
24: #include "tmux.h"
25:
1.28 nicm 26: /*
27: * Based on the description by Paul Williams at:
28: *
29: * http://vt100.net/emu/dec_ansi_parser
30: *
31: * With the following changes:
32: *
33: * - 7-bit only.
34: *
35: * - Support for UTF-8.
36: *
37: * - OSC (but not APC) may be terminated by \007 as well as ST.
38: *
39: * - A state for APC similar to OSC. Some terminals appear to use this to set
40: * the title.
41: *
42: * - A state for the screen \033k...\033\\ sequence to rename a window. This is
43: * pretty stupid but not supporting it is more trouble than it is worth.
1.37 nicm 44: *
45: * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
46: * be passed to the underlying teminal(s).
1.28 nicm 47: */
48:
1.74 ! nicm 49: /* Input parser cell. */
! 50: struct input_cell {
! 51: struct grid_cell cell;
! 52: int set;
! 53: int g0set; /* 1 if ACS */
! 54: int g1set; /* 1 if ACS */
! 55: };
! 56:
! 57: /* Input parser context. */
! 58: struct input_ctx {
! 59: struct window_pane *wp;
! 60: struct screen_write_ctx ctx;
! 61:
! 62: struct input_cell cell;
! 63:
! 64: struct input_cell old_cell;
! 65: u_int old_cx;
! 66: u_int old_cy;
! 67:
! 68: u_char interm_buf[4];
! 69: size_t interm_len;
! 70:
! 71: u_char param_buf[64];
! 72: size_t param_len;
! 73:
! 74: #define INPUT_BUF_START 32
! 75: #define INPUT_BUF_LIMIT 1048576
! 76: u_char *input_buf;
! 77: size_t input_len;
! 78: size_t input_space;
! 79:
! 80: int param_list[24]; /* -1 not present */
! 81: u_int param_list_len;
! 82:
! 83: struct utf8_data utf8data;
! 84:
! 85: int ch;
! 86: int flags;
! 87: #define INPUT_DISCARD 0x1
! 88:
! 89: const struct input_state *state;
! 90:
! 91: /*
! 92: * All input received since we were last in the ground state. Sent to
! 93: * control clients on connection.
! 94: */
! 95: struct evbuffer *since_ground;
! 96: };
! 97:
1.28 nicm 98: /* Helper functions. */
1.52 nicm 99: struct input_transition;
1.28 nicm 100: int input_split(struct input_ctx *);
101: int input_get(struct input_ctx *, u_int, int, int);
102: void input_reply(struct input_ctx *, const char *, ...);
1.52 nicm 103: void input_set_state(struct window_pane *, const struct input_transition *);
1.69 nicm 104: void input_reset_cell(struct input_ctx *);
1.28 nicm 105:
106: /* Transition entry/exit handlers. */
107: void input_clear(struct input_ctx *);
1.67 nicm 108: void input_ground(struct input_ctx *);
1.28 nicm 109: void input_enter_osc(struct input_ctx *);
110: void input_exit_osc(struct input_ctx *);
111: void input_enter_apc(struct input_ctx *);
112: void input_exit_apc(struct input_ctx *);
113: void input_enter_rename(struct input_ctx *);
114: void input_exit_rename(struct input_ctx *);
115:
116: /* Input state handlers. */
117: int input_print(struct input_ctx *);
118: int input_intermediate(struct input_ctx *);
119: int input_parameter(struct input_ctx *);
120: int input_input(struct input_ctx *);
121: int input_c0_dispatch(struct input_ctx *);
122: int input_esc_dispatch(struct input_ctx *);
123: int input_csi_dispatch(struct input_ctx *);
1.64 nicm 124: void input_csi_dispatch_rm(struct input_ctx *);
125: void input_csi_dispatch_rm_private(struct input_ctx *);
126: void input_csi_dispatch_sm(struct input_ctx *);
127: void input_csi_dispatch_sm_private(struct input_ctx *);
1.65 nicm 128: void input_csi_dispatch_winops(struct input_ctx *);
1.28 nicm 129: void input_csi_dispatch_sgr(struct input_ctx *);
1.37 nicm 130: int input_dcs_dispatch(struct input_ctx *);
1.28 nicm 131: int input_utf8_open(struct input_ctx *);
132: int input_utf8_add(struct input_ctx *);
133: int input_utf8_close(struct input_ctx *);
134:
135: /* Command table comparison function. */
136: int input_table_compare(const void *, const void *);
137:
138: /* Command table entry. */
139: struct input_table_entry {
140: int ch;
141: const char *interm;
142: int type;
1.1 nicm 143: };
144:
1.28 nicm 145: /* Escape commands. */
146: enum input_esc_type {
147: INPUT_ESC_DECALN,
148: INPUT_ESC_DECKPAM,
149: INPUT_ESC_DECKPNM,
150: INPUT_ESC_DECRC,
151: INPUT_ESC_DECSC,
152: INPUT_ESC_HTS,
153: INPUT_ESC_IND,
154: INPUT_ESC_NEL,
155: INPUT_ESC_RI,
156: INPUT_ESC_RIS,
1.69 nicm 157: INPUT_ESC_SCSG0_OFF,
158: INPUT_ESC_SCSG0_ON,
159: INPUT_ESC_SCSG1_OFF,
160: INPUT_ESC_SCSG1_ON,
1.28 nicm 161: };
1.1 nicm 162:
1.28 nicm 163: /* Escape command table. */
164: const struct input_table_entry input_esc_table[] = {
1.69 nicm 165: { '0', "(", INPUT_ESC_SCSG0_ON },
166: { '0', ")", INPUT_ESC_SCSG1_ON },
1.28 nicm 167: { '7', "", INPUT_ESC_DECSC },
168: { '8', "", INPUT_ESC_DECRC },
169: { '8', "#", INPUT_ESC_DECALN },
170: { '=', "", INPUT_ESC_DECKPAM },
171: { '>', "", INPUT_ESC_DECKPNM },
1.69 nicm 172: { 'B', "(", INPUT_ESC_SCSG0_OFF },
173: { 'B', ")", INPUT_ESC_SCSG1_OFF },
1.28 nicm 174: { 'D', "", INPUT_ESC_IND },
175: { 'E', "", INPUT_ESC_NEL },
176: { 'H', "", INPUT_ESC_HTS },
177: { 'M', "", INPUT_ESC_RI },
178: { 'c', "", INPUT_ESC_RIS },
179: };
1.1 nicm 180:
1.28 nicm 181: /* Control (CSI) commands. */
182: enum input_csi_type {
183: INPUT_CSI_CBT,
1.43 nicm 184: INPUT_CSI_CNL,
185: INPUT_CSI_CPL,
1.28 nicm 186: INPUT_CSI_CUB,
187: INPUT_CSI_CUD,
188: INPUT_CSI_CUF,
189: INPUT_CSI_CUP,
190: INPUT_CSI_CUU,
191: INPUT_CSI_DA,
1.50 nicm 192: INPUT_CSI_DA_TWO,
1.28 nicm 193: INPUT_CSI_DCH,
1.39 nicm 194: INPUT_CSI_DECSCUSR,
1.28 nicm 195: INPUT_CSI_DECSTBM,
196: INPUT_CSI_DL,
197: INPUT_CSI_DSR,
1.56 nicm 198: INPUT_CSI_ECH,
1.28 nicm 199: INPUT_CSI_ED,
200: INPUT_CSI_EL,
201: INPUT_CSI_HPA,
202: INPUT_CSI_ICH,
203: INPUT_CSI_IL,
1.42 nicm 204: INPUT_CSI_RCP,
1.28 nicm 205: INPUT_CSI_RM,
206: INPUT_CSI_RM_PRIVATE,
1.42 nicm 207: INPUT_CSI_SCP,
1.28 nicm 208: INPUT_CSI_SGR,
209: INPUT_CSI_SM,
210: INPUT_CSI_SM_PRIVATE,
211: INPUT_CSI_TBC,
212: INPUT_CSI_VPA,
1.65 nicm 213: INPUT_CSI_WINOPS,
1.28 nicm 214: };
1.1 nicm 215:
1.28 nicm 216: /* Control (CSI) command table. */
217: const struct input_table_entry input_csi_table[] = {
218: { '@', "", INPUT_CSI_ICH },
219: { 'A', "", INPUT_CSI_CUU },
220: { 'B', "", INPUT_CSI_CUD },
221: { 'C', "", INPUT_CSI_CUF },
222: { 'D', "", INPUT_CSI_CUB },
1.43 nicm 223: { 'E', "", INPUT_CSI_CNL },
224: { 'F', "", INPUT_CSI_CPL },
1.28 nicm 225: { 'G', "", INPUT_CSI_HPA },
226: { 'H', "", INPUT_CSI_CUP },
227: { 'J', "", INPUT_CSI_ED },
228: { 'K', "", INPUT_CSI_EL },
229: { 'L', "", INPUT_CSI_IL },
230: { 'M', "", INPUT_CSI_DL },
231: { 'P', "", INPUT_CSI_DCH },
1.56 nicm 232: { 'X', "", INPUT_CSI_ECH },
1.28 nicm 233: { 'Z', "", INPUT_CSI_CBT },
234: { 'c', "", INPUT_CSI_DA },
1.50 nicm 235: { 'c', ">", INPUT_CSI_DA_TWO },
1.28 nicm 236: { 'd', "", INPUT_CSI_VPA },
237: { 'f', "", INPUT_CSI_CUP },
238: { 'g', "", INPUT_CSI_TBC },
239: { 'h', "", INPUT_CSI_SM },
240: { 'h', "?", INPUT_CSI_SM_PRIVATE },
241: { 'l', "", INPUT_CSI_RM },
242: { 'l', "?", INPUT_CSI_RM_PRIVATE },
243: { 'm', "", INPUT_CSI_SGR },
244: { 'n', "", INPUT_CSI_DSR },
1.39 nicm 245: { 'q', " ", INPUT_CSI_DECSCUSR },
1.28 nicm 246: { 'r', "", INPUT_CSI_DECSTBM },
1.42 nicm 247: { 's', "", INPUT_CSI_SCP },
1.65 nicm 248: { 't', "", INPUT_CSI_WINOPS },
1.42 nicm 249: { 'u', "", INPUT_CSI_RCP },
1.28 nicm 250: };
1.1 nicm 251:
1.28 nicm 252: /* Input transition. */
253: struct input_transition {
254: int first;
255: int last;
1.1 nicm 256:
1.28 nicm 257: int (*handler)(struct input_ctx *);
258: const struct input_state *state;
259: };
1.1 nicm 260:
1.28 nicm 261: /* Input state. */
262: struct input_state {
263: const char *name;
264: void (*enter)(struct input_ctx *);
265: void (*exit)(struct input_ctx *);
266: const struct input_transition *transitions;
267: };
1.1 nicm 268:
1.28 nicm 269: /* State transitions available from all states. */
270: #define INPUT_STATE_ANYWHERE \
271: { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
272: { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
273: { 0x1b, 0x1b, NULL, &input_state_esc_enter }
274:
275: /* Forward declarations of state tables. */
276: const struct input_transition input_state_ground_table[];
277: const struct input_transition input_state_esc_enter_table[];
278: const struct input_transition input_state_esc_intermediate_table[];
279: const struct input_transition input_state_csi_enter_table[];
280: const struct input_transition input_state_csi_parameter_table[];
281: const struct input_transition input_state_csi_intermediate_table[];
282: const struct input_transition input_state_csi_ignore_table[];
283: const struct input_transition input_state_dcs_enter_table[];
284: const struct input_transition input_state_dcs_parameter_table[];
285: const struct input_transition input_state_dcs_intermediate_table[];
286: const struct input_transition input_state_dcs_handler_table[];
1.37 nicm 287: const struct input_transition input_state_dcs_escape_table[];
1.28 nicm 288: const struct input_transition input_state_dcs_ignore_table[];
289: const struct input_transition input_state_osc_string_table[];
290: const struct input_transition input_state_apc_string_table[];
291: const struct input_transition input_state_rename_string_table[];
292: const struct input_transition input_state_consume_st_table[];
293: const struct input_transition input_state_utf8_three_table[];
294: const struct input_transition input_state_utf8_two_table[];
295: const struct input_transition input_state_utf8_one_table[];
296:
297: /* ground state definition. */
298: const struct input_state input_state_ground = {
299: "ground",
1.67 nicm 300: input_ground, NULL,
1.28 nicm 301: input_state_ground_table
302: };
1.1 nicm 303:
1.28 nicm 304: /* esc_enter state definition. */
305: const struct input_state input_state_esc_enter = {
306: "esc_enter",
307: input_clear, NULL,
308: input_state_esc_enter_table
309: };
1.1 nicm 310:
1.28 nicm 311: /* esc_intermediate state definition. */
312: const struct input_state input_state_esc_intermediate = {
313: "esc_intermediate",
314: NULL, NULL,
315: input_state_esc_intermediate_table
316: };
1.1 nicm 317:
1.28 nicm 318: /* csi_enter state definition. */
319: const struct input_state input_state_csi_enter = {
320: "csi_enter",
321: input_clear, NULL,
322: input_state_csi_enter_table
323: };
1.1 nicm 324:
1.28 nicm 325: /* csi_parameter state definition. */
326: const struct input_state input_state_csi_parameter = {
327: "csi_parameter",
328: NULL, NULL,
329: input_state_csi_parameter_table
330: };
1.1 nicm 331:
1.28 nicm 332: /* csi_intermediate state definition. */
333: const struct input_state input_state_csi_intermediate = {
334: "csi_intermediate",
335: NULL, NULL,
336: input_state_csi_intermediate_table
337: };
1.1 nicm 338:
1.28 nicm 339: /* csi_ignore state definition. */
340: const struct input_state input_state_csi_ignore = {
341: "csi_ignore",
342: NULL, NULL,
343: input_state_csi_ignore_table
344: };
1.1 nicm 345:
1.28 nicm 346: /* dcs_enter state definition. */
347: const struct input_state input_state_dcs_enter = {
348: "dcs_enter",
349: input_clear, NULL,
350: input_state_dcs_enter_table
351: };
1.1 nicm 352:
1.28 nicm 353: /* dcs_parameter state definition. */
354: const struct input_state input_state_dcs_parameter = {
355: "dcs_parameter",
356: NULL, NULL,
357: input_state_dcs_parameter_table
358: };
1.1 nicm 359:
1.28 nicm 360: /* dcs_intermediate state definition. */
361: const struct input_state input_state_dcs_intermediate = {
362: "dcs_intermediate",
363: NULL, NULL,
364: input_state_dcs_intermediate_table
365: };
1.1 nicm 366:
1.28 nicm 367: /* dcs_handler state definition. */
368: const struct input_state input_state_dcs_handler = {
369: "dcs_handler",
1.37 nicm 370: NULL, NULL,
1.28 nicm 371: input_state_dcs_handler_table
372: };
1.1 nicm 373:
1.37 nicm 374: /* dcs_escape state definition. */
375: const struct input_state input_state_dcs_escape = {
376: "dcs_escape",
377: NULL, NULL,
378: input_state_dcs_escape_table
379: };
380:
1.28 nicm 381: /* dcs_ignore state definition. */
382: const struct input_state input_state_dcs_ignore = {
383: "dcs_ignore",
384: NULL, NULL,
385: input_state_dcs_ignore_table
386: };
1.1 nicm 387:
1.28 nicm 388: /* osc_string state definition. */
389: const struct input_state input_state_osc_string = {
390: "osc_string",
391: input_enter_osc, input_exit_osc,
392: input_state_osc_string_table
393: };
1.1 nicm 394:
1.28 nicm 395: /* apc_string state definition. */
396: const struct input_state input_state_apc_string = {
397: "apc_string",
398: input_enter_apc, input_exit_apc,
399: input_state_apc_string_table
400: };
1.1 nicm 401:
1.28 nicm 402: /* rename_string state definition. */
403: const struct input_state input_state_rename_string = {
404: "rename_string",
405: input_enter_rename, input_exit_rename,
406: input_state_rename_string_table
407: };
1.1 nicm 408:
1.28 nicm 409: /* consume_st state definition. */
410: const struct input_state input_state_consume_st = {
411: "consume_st",
412: NULL, NULL,
413: input_state_consume_st_table
414: };
1.1 nicm 415:
1.28 nicm 416: /* utf8_three state definition. */
417: const struct input_state input_state_utf8_three = {
418: "utf8_three",
419: NULL, NULL,
420: input_state_utf8_three_table
421: };
1.1 nicm 422:
1.28 nicm 423: /* utf8_two state definition. */
424: const struct input_state input_state_utf8_two = {
425: "utf8_two",
426: NULL, NULL,
427: input_state_utf8_two_table
428: };
1.1 nicm 429:
1.28 nicm 430: /* utf8_one state definition. */
431: const struct input_state input_state_utf8_one = {
432: "utf8_one",
433: NULL, NULL,
434: input_state_utf8_one_table
435: };
1.1 nicm 436:
1.28 nicm 437: /* ground state table. */
438: const struct input_transition input_state_ground_table[] = {
439: INPUT_STATE_ANYWHERE,
440:
441: { 0x00, 0x17, input_c0_dispatch, NULL },
442: { 0x19, 0x19, input_c0_dispatch, NULL },
443: { 0x1c, 0x1f, input_c0_dispatch, NULL },
444: { 0x20, 0x7e, input_print, NULL },
445: { 0x7f, 0x7f, NULL, NULL },
446: { 0x80, 0xc1, input_print, NULL },
447: { 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one },
448: { 0xe0, 0xef, input_utf8_open, &input_state_utf8_two },
449: { 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three },
450: { 0xf5, 0xff, input_print, NULL },
1.1 nicm 451:
1.28 nicm 452: { -1, -1, NULL, NULL }
453: };
1.13 nicm 454:
1.28 nicm 455: /* esc_enter state table. */
456: const struct input_transition input_state_esc_enter_table[] = {
457: INPUT_STATE_ANYWHERE,
458:
459: { 0x00, 0x17, input_c0_dispatch, NULL },
460: { 0x19, 0x19, input_c0_dispatch, NULL },
461: { 0x1c, 0x1f, input_c0_dispatch, NULL },
462: { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
463: { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
464: { 0x50, 0x50, NULL, &input_state_dcs_enter },
465: { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
466: { 0x58, 0x58, NULL, &input_state_consume_st },
467: { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
468: { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
469: { 0x5b, 0x5b, NULL, &input_state_csi_enter },
470: { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
471: { 0x5d, 0x5d, NULL, &input_state_osc_string },
472: { 0x5e, 0x5e, NULL, &input_state_consume_st },
473: { 0x5f, 0x5f, NULL, &input_state_apc_string },
474: { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
475: { 0x6b, 0x6b, NULL, &input_state_rename_string },
1.29 nicm 476: { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground },
1.28 nicm 477: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 478:
1.28 nicm 479: { -1, -1, NULL, NULL }
480: };
1.1 nicm 481:
1.28 nicm 482: /* esc_interm state table. */
483: const struct input_transition input_state_esc_intermediate_table[] = {
484: INPUT_STATE_ANYWHERE,
485:
486: { 0x00, 0x17, input_c0_dispatch, NULL },
487: { 0x19, 0x19, input_c0_dispatch, NULL },
488: { 0x1c, 0x1f, input_c0_dispatch, NULL },
489: { 0x20, 0x2f, input_intermediate, NULL },
490: { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
491: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 492:
1.28 nicm 493: { -1, -1, NULL, NULL }
494: };
1.1 nicm 495:
1.28 nicm 496: /* csi_enter state table. */
497: const struct input_transition input_state_csi_enter_table[] = {
498: INPUT_STATE_ANYWHERE,
499:
500: { 0x00, 0x17, input_c0_dispatch, NULL },
501: { 0x19, 0x19, input_c0_dispatch, NULL },
502: { 0x1c, 0x1f, input_c0_dispatch, NULL },
503: { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
504: { 0x30, 0x39, input_parameter, &input_state_csi_parameter },
505: { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
506: { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter },
507: { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
508: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
509: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 510:
1.28 nicm 511: { -1, -1, NULL, NULL }
512: };
1.1 nicm 513:
1.28 nicm 514: /* csi_parameter state table. */
515: const struct input_transition input_state_csi_parameter_table[] = {
516: INPUT_STATE_ANYWHERE,
517:
518: { 0x00, 0x17, input_c0_dispatch, NULL },
519: { 0x19, 0x19, input_c0_dispatch, NULL },
520: { 0x1c, 0x1f, input_c0_dispatch, NULL },
521: { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
522: { 0x30, 0x39, input_parameter, NULL },
523: { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
524: { 0x3b, 0x3b, input_parameter, NULL },
525: { 0x3c, 0x3f, NULL, &input_state_csi_ignore },
526: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
527: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 528:
1.28 nicm 529: { -1, -1, NULL, NULL }
530: };
1.1 nicm 531:
1.28 nicm 532: /* csi_intermediate state table. */
533: const struct input_transition input_state_csi_intermediate_table[] = {
534: INPUT_STATE_ANYWHERE,
535:
536: { 0x00, 0x17, input_c0_dispatch, NULL },
537: { 0x19, 0x19, input_c0_dispatch, NULL },
538: { 0x1c, 0x1f, input_c0_dispatch, NULL },
539: { 0x20, 0x2f, input_intermediate, NULL },
540: { 0x30, 0x3f, NULL, &input_state_csi_ignore },
541: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
542: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 543:
1.28 nicm 544: { -1, -1, NULL, NULL }
545: };
1.1 nicm 546:
1.28 nicm 547: /* csi_ignore state table. */
548: const struct input_transition input_state_csi_ignore_table[] = {
549: INPUT_STATE_ANYWHERE,
550:
551: { 0x00, 0x17, input_c0_dispatch, NULL },
552: { 0x19, 0x19, input_c0_dispatch, NULL },
553: { 0x1c, 0x1f, input_c0_dispatch, NULL },
554: { 0x20, 0x3f, NULL, NULL },
555: { 0x40, 0x7e, NULL, &input_state_ground },
556: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 557:
1.28 nicm 558: { -1, -1, NULL, NULL }
559: };
1.1 nicm 560:
1.28 nicm 561: /* dcs_enter state table. */
562: const struct input_transition input_state_dcs_enter_table[] = {
563: INPUT_STATE_ANYWHERE,
564:
565: { 0x00, 0x17, NULL, NULL },
566: { 0x19, 0x19, NULL, NULL },
567: { 0x1c, 0x1f, NULL, NULL },
568: { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
569: { 0x30, 0x39, input_parameter, &input_state_dcs_parameter },
570: { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
571: { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
572: { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
1.37 nicm 573: { 0x40, 0x7e, input_input, &input_state_dcs_handler },
1.28 nicm 574: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 575:
1.28 nicm 576: { -1, -1, NULL, NULL }
577: };
1.1 nicm 578:
1.28 nicm 579: /* dcs_parameter state table. */
580: const struct input_transition input_state_dcs_parameter_table[] = {
581: INPUT_STATE_ANYWHERE,
582:
583: { 0x00, 0x17, NULL, NULL },
584: { 0x19, 0x19, NULL, NULL },
585: { 0x1c, 0x1f, NULL, NULL },
586: { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
587: { 0x30, 0x39, input_parameter, NULL },
588: { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
589: { 0x3b, 0x3b, input_parameter, NULL },
590: { 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
1.37 nicm 591: { 0x40, 0x7e, input_input, &input_state_dcs_handler },
1.28 nicm 592: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 593:
1.28 nicm 594: { -1, -1, NULL, NULL }
595: };
1.1 nicm 596:
1.28 nicm 597: /* dcs_interm state table. */
598: const struct input_transition input_state_dcs_intermediate_table[] = {
599: INPUT_STATE_ANYWHERE,
600:
601: { 0x00, 0x17, NULL, NULL },
602: { 0x19, 0x19, NULL, NULL },
603: { 0x1c, 0x1f, NULL, NULL },
604: { 0x20, 0x2f, input_intermediate, NULL },
605: { 0x30, 0x3f, NULL, &input_state_dcs_ignore },
1.37 nicm 606: { 0x40, 0x7e, input_input, &input_state_dcs_handler },
1.28 nicm 607: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 608:
1.28 nicm 609: { -1, -1, NULL, NULL }
610: };
1.1 nicm 611:
1.28 nicm 612: /* dcs_handler state table. */
613: const struct input_transition input_state_dcs_handler_table[] = {
1.37 nicm 614: /* No INPUT_STATE_ANYWHERE */
615:
616: { 0x00, 0x1a, input_input, NULL },
617: { 0x1b, 0x1b, NULL, &input_state_dcs_escape },
618: { 0x1c, 0xff, input_input, NULL },
619:
620: { -1, -1, NULL, NULL }
621: };
622:
623: /* dcs_escape state table. */
624: const struct input_transition input_state_dcs_escape_table[] = {
625: /* No INPUT_STATE_ANYWHERE */
1.28 nicm 626:
1.37 nicm 627: { 0x00, 0x5b, input_input, &input_state_dcs_handler },
628: { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
629: { 0x5d, 0xff, input_input, &input_state_dcs_handler },
1.1 nicm 630:
1.28 nicm 631: { -1, -1, NULL, NULL }
632: };
1.1 nicm 633:
1.40 nicm 634: /* dcs_ignore state table. */
1.28 nicm 635: const struct input_transition input_state_dcs_ignore_table[] = {
636: INPUT_STATE_ANYWHERE,
637:
638: { 0x00, 0x17, NULL, NULL },
639: { 0x19, 0x19, NULL, NULL },
640: { 0x1c, 0x1f, NULL, NULL },
641: { 0x20, 0xff, NULL, NULL },
1.1 nicm 642:
1.28 nicm 643: { -1, -1, NULL, NULL }
644: };
1.1 nicm 645:
1.28 nicm 646: /* osc_string state table. */
647: const struct input_transition input_state_osc_string_table[] = {
648: INPUT_STATE_ANYWHERE,
649:
650: { 0x00, 0x06, NULL, NULL },
651: { 0x07, 0x07, NULL, &input_state_ground },
652: { 0x08, 0x17, NULL, NULL },
653: { 0x19, 0x19, NULL, NULL },
654: { 0x1c, 0x1f, NULL, NULL },
655: { 0x20, 0xff, input_input, NULL },
1.1 nicm 656:
1.28 nicm 657: { -1, -1, NULL, NULL }
658: };
1.1 nicm 659:
1.28 nicm 660: /* apc_string state table. */
661: const struct input_transition input_state_apc_string_table[] = {
662: INPUT_STATE_ANYWHERE,
663:
664: { 0x00, 0x17, NULL, NULL },
665: { 0x19, 0x19, NULL, NULL },
666: { 0x1c, 0x1f, NULL, NULL },
667: { 0x20, 0xff, input_input, NULL },
1.1 nicm 668:
1.28 nicm 669: { -1, -1, NULL, NULL }
670: };
1.1 nicm 671:
1.28 nicm 672: /* rename_string state table. */
673: const struct input_transition input_state_rename_string_table[] = {
674: INPUT_STATE_ANYWHERE,
675:
676: { 0x00, 0x17, NULL, NULL },
677: { 0x19, 0x19, NULL, NULL },
678: { 0x1c, 0x1f, NULL, NULL },
679: { 0x20, 0xff, input_input, NULL },
1.1 nicm 680:
1.28 nicm 681: { -1, -1, NULL, NULL }
682: };
1.1 nicm 683:
1.28 nicm 684: /* consume_st state table. */
685: const struct input_transition input_state_consume_st_table[] = {
686: INPUT_STATE_ANYWHERE,
687:
688: { 0x00, 0x17, NULL, NULL },
689: { 0x19, 0x19, NULL, NULL },
690: { 0x1c, 0x1f, NULL, NULL },
691: { 0x20, 0xff, NULL, NULL },
1.6 nicm 692:
1.28 nicm 693: { -1, -1, NULL, NULL }
694: };
1.6 nicm 695:
1.28 nicm 696: /* utf8_three state table. */
697: const struct input_transition input_state_utf8_three_table[] = {
698: /* No INPUT_STATE_ANYWHERE */
699:
700: { 0x00, 0x7f, NULL, &input_state_ground },
701: { 0x80, 0xbf, input_utf8_add, &input_state_utf8_two },
702: { 0xc0, 0xff, NULL, &input_state_ground },
1.4 nicm 703:
1.28 nicm 704: { -1, -1, NULL, NULL }
705: };
1.1 nicm 706:
1.28 nicm 707: /* utf8_two state table. */
708: const struct input_transition input_state_utf8_two_table[] = {
709: /* No INPUT_STATE_ANYWHERE */
710:
711: { 0x00, 0x7f, NULL, &input_state_ground },
712: { 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
713: { 0xc0, 0xff, NULL, &input_state_ground },
1.1 nicm 714:
1.28 nicm 715: { -1, -1, NULL, NULL }
716: };
1.1 nicm 717:
1.28 nicm 718: /* utf8_one state table. */
719: const struct input_transition input_state_utf8_one_table[] = {
720: /* No INPUT_STATE_ANYWHERE */
721:
722: { 0x00, 0x7f, NULL, &input_state_ground },
723: { 0x80, 0xbf, input_utf8_close, &input_state_ground },
724: { 0xc0, 0xff, NULL, &input_state_ground },
1.1 nicm 725:
1.28 nicm 726: { -1, -1, NULL, NULL }
727: };
1.1 nicm 728:
1.28 nicm 729: /* Input table compare. */
730: int
731: input_table_compare(const void *key, const void *value)
1.1 nicm 732: {
1.28 nicm 733: const struct input_ctx *ictx = key;
734: const struct input_table_entry *entry = value;
1.1 nicm 735:
1.28 nicm 736: if (ictx->ch != entry->ch)
737: return (ictx->ch - entry->ch);
738: return (strcmp(ictx->interm_buf, entry->interm));
1.1 nicm 739: }
740:
1.69 nicm 741: /* Reset cell state to default. */
742: void
743: input_reset_cell(struct input_ctx *ictx)
744: {
745: memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell);
746: ictx->cell.set = 0;
747: ictx->cell.g0set = ictx->cell.g1set = 0;
748:
749: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
750: ictx->old_cx = 0;
751: ictx->old_cy = 0;
752: }
753:
1.28 nicm 754: /* Initialise input parser. */
1.1 nicm 755: void
1.28 nicm 756: input_init(struct window_pane *wp)
1.1 nicm 757: {
1.74 ! nicm 758: struct input_ctx *ictx;
! 759:
! 760: ictx = wp->ictx = xcalloc(1, sizeof *ictx);
1.1 nicm 761:
1.69 nicm 762: input_reset_cell(ictx);
1.1 nicm 763:
1.28 nicm 764: *ictx->interm_buf = '\0';
765: ictx->interm_len = 0;
1.1 nicm 766:
1.28 nicm 767: *ictx->param_buf = '\0';
768: ictx->param_len = 0;
1.1 nicm 769:
1.67 nicm 770: ictx->input_space = INPUT_BUF_START;
771: ictx->input_buf = xmalloc(INPUT_BUF_START);
772:
773: *ictx->input_buf = '\0';
774: ictx->input_len = 0;
775:
1.28 nicm 776: ictx->state = &input_state_ground;
777: ictx->flags = 0;
1.52 nicm 778:
779: ictx->since_ground = evbuffer_new();
1.1 nicm 780: }
781:
1.28 nicm 782: /* Destroy input parser. */
1.1 nicm 783: void
1.52 nicm 784: input_free(struct window_pane *wp)
1.1 nicm 785: {
1.74 ! nicm 786: struct input_ctx *ictx = wp->ictx;
! 787:
! 788: free(ictx->input_buf);
! 789: evbuffer_free(ictx->since_ground);
! 790:
! 791: free (ictx);
! 792: wp->ictx = NULL;
! 793: }
! 794:
! 795: /* Reset input state and clear screen. */
! 796: void
! 797: input_reset(struct window_pane *wp)
! 798: {
! 799: struct input_ctx *ictx = wp->ictx;
1.67 nicm 800:
1.74 ! nicm 801: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
! 802: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
! 803: ictx->old_cx = 0;
! 804: ictx->old_cy = 0;
! 805:
! 806: if (wp->mode == NULL)
! 807: screen_write_start(&ictx->ctx, wp, &wp->base);
! 808: else
! 809: screen_write_start(&ictx->ctx, NULL, &wp->base);
! 810: screen_write_reset(&ictx->ctx);
! 811: screen_write_stop(&ictx->ctx);
! 812: }
! 813:
! 814: /* Return pending data. */
! 815: struct evbuffer *
! 816: input_pending(struct window_pane *wp)
! 817: {
! 818: return (wp->ictx->since_ground);
1.52 nicm 819: }
820:
821: /* Change input state. */
822: void
823: input_set_state(struct window_pane *wp, const struct input_transition *itr)
824: {
1.74 ! nicm 825: struct input_ctx *ictx = wp->ictx;
1.52 nicm 826:
827: if (ictx->state->exit != NULL)
828: ictx->state->exit(ictx);
829: ictx->state = itr->state;
830: if (ictx->state->enter != NULL)
831: ictx->state->enter(ictx);
1.1 nicm 832: }
833:
1.28 nicm 834: /* Parse input. */
1.1 nicm 835: void
1.28 nicm 836: input_parse(struct window_pane *wp)
1.1 nicm 837: {
1.74 ! nicm 838: struct input_ctx *ictx = wp->ictx;
1.28 nicm 839: const struct input_transition *itr;
840: struct evbuffer *evb = wp->event->input;
841: u_char *buf;
842: size_t len, off;
1.1 nicm 843:
1.28 nicm 844: if (EVBUFFER_LENGTH(evb) == 0)
845: return;
1.30 nicm 846:
1.28 nicm 847: wp->window->flags |= WINDOW_ACTIVITY;
1.30 nicm 848: wp->window->flags &= ~WINDOW_SILENCE;
1.1 nicm 849:
1.28 nicm 850: /*
851: * Open the screen. Use NULL wp if there is a mode set as don't want to
852: * update the tty.
853: */
854: if (wp->mode == NULL)
855: screen_write_start(&ictx->ctx, wp, &wp->base);
856: else
857: screen_write_start(&ictx->ctx, NULL, &wp->base);
858: ictx->wp = wp;
1.7 nicm 859:
1.28 nicm 860: buf = EVBUFFER_DATA(evb);
861: len = EVBUFFER_LENGTH(evb);
1.54 nicm 862: notify_input(wp, evb);
1.28 nicm 863: off = 0;
864:
865: /* Parse the input. */
866: while (off < len) {
867: ictx->ch = buf[off++];
868: log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
869:
870: /* Find the transition. */
871: itr = ictx->state->transitions;
872: while (itr->first != -1 && itr->last != -1) {
873: if (ictx->ch >= itr->first && ictx->ch <= itr->last)
1.7 nicm 874: break;
1.28 nicm 875: itr++;
1.1 nicm 876: }
1.28 nicm 877: if (itr->first == -1 || itr->last == -1) {
878: /* No transition? Eh? */
879: fatalx("No transition from state!");
1.3 nicm 880: }
1.1 nicm 881:
882: /*
1.28 nicm 883: * Execute the handler, if any. Don't switch state if it
884: * returns non-zero.
1.1 nicm 885: */
1.31 nicm 886: if (itr->handler != NULL && itr->handler(ictx) != 0)
1.28 nicm 887: continue;
888:
889: /* And switch state, if necessary. */
1.52 nicm 890: if (itr->state != NULL)
891: input_set_state(wp, itr);
892:
893: /* If not in ground state, save input. */
894: if (ictx->state != &input_state_ground)
895: evbuffer_add(ictx->since_ground, &ictx->ch, 1);
1.1 nicm 896: }
897:
1.28 nicm 898: /* Close the screen. */
899: screen_write_stop(&ictx->ctx);
1.1 nicm 900:
1.28 nicm 901: evbuffer_drain(evb, len);
1.1 nicm 902: }
903:
1.28 nicm 904: /* Split the parameter list (if any). */
905: int
906: input_split(struct input_ctx *ictx)
1.1 nicm 907:
908: {
1.28 nicm 909: const char *errstr;
910: char *ptr, *out;
911: int n;
1.1 nicm 912:
1.28 nicm 913: ictx->param_list_len = 0;
914: if (ictx->param_len == 0)
915: return (0);
1.1 nicm 916:
1.28 nicm 917: ptr = ictx->param_buf;
918: while ((out = strsep(&ptr, ";")) != NULL) {
919: if (*out == '\0')
920: n = -1;
921: else {
922: n = strtonum(out, 0, INT_MAX, &errstr);
923: if (errstr != NULL)
924: return (-1);
925: }
1.1 nicm 926:
1.28 nicm 927: ictx->param_list[ictx->param_list_len++] = n;
928: if (ictx->param_list_len == nitems(ictx->param_list))
929: return (-1);
930: }
1.1 nicm 931:
1.28 nicm 932: return (0);
1.1 nicm 933: }
934:
1.40 nicm 935: /* Get an argument or return default value. */
1.28 nicm 936: int
937: input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
1.1 nicm 938: {
1.28 nicm 939: int retval;
1.1 nicm 940:
1.28 nicm 941: if (validx >= ictx->param_list_len)
942: return (defval);
1.1 nicm 943:
1.28 nicm 944: retval = ictx->param_list[validx];
945: if (retval == -1)
946: return (defval);
947: if (retval < minval)
948: return (minval);
949: return (retval);
1.1 nicm 950: }
951:
1.28 nicm 952: /* Reply to terminal query. */
1.1 nicm 953: void
1.28 nicm 954: input_reply(struct input_ctx *ictx, const char *fmt, ...)
1.1 nicm 955: {
1.28 nicm 956: va_list ap;
957: char *reply;
1.1 nicm 958:
1.28 nicm 959: va_start(ap, fmt);
960: vasprintf(&reply, fmt, ap);
961: va_end(ap);
1.1 nicm 962:
1.28 nicm 963: bufferevent_write(ictx->wp->event, reply, strlen(reply));
1.53 nicm 964: free(reply);
1.8 nicm 965: }
966:
1.28 nicm 967: /* Clear saved state. */
1.8 nicm 968: void
1.28 nicm 969: input_clear(struct input_ctx *ictx)
1.8 nicm 970: {
1.28 nicm 971: *ictx->interm_buf = '\0';
972: ictx->interm_len = 0;
1.8 nicm 973:
1.28 nicm 974: *ictx->param_buf = '\0';
975: ictx->param_len = 0;
1.8 nicm 976:
1.35 nicm 977: *ictx->input_buf = '\0';
978: ictx->input_len = 0;
979:
1.28 nicm 980: ictx->flags &= ~INPUT_DISCARD;
1.14 nicm 981: }
982:
1.67 nicm 983: /* Reset for ground state. */
984: void
985: input_ground(struct input_ctx *ictx)
986: {
987: evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
988:
989: if (ictx->input_space > INPUT_BUF_START) {
990: ictx->input_space = INPUT_BUF_START;
1.71 nicm 991: ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START);
1.67 nicm 992: }
993: }
994:
1.28 nicm 995: /* Output this character to the screen. */
996: int
997: input_print(struct input_ctx *ictx)
1.14 nicm 998: {
1.69 nicm 999: int set;
1000:
1001: set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
1002: if (set == 1)
1003: ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
1004: else
1005: ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1006:
1007: grid_cell_one(&ictx->cell.cell, ictx->ch);
1008: screen_write_cell(&ictx->ctx, &ictx->cell.cell);
1009:
1010: ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
1.14 nicm 1011:
1.28 nicm 1012: return (0);
1.1 nicm 1013: }
1014:
1.28 nicm 1015: /* Collect intermediate string. */
1016: int
1017: input_intermediate(struct input_ctx *ictx)
1.1 nicm 1018: {
1.28 nicm 1019: if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
1020: ictx->flags |= INPUT_DISCARD;
1021: else {
1022: ictx->interm_buf[ictx->interm_len++] = ictx->ch;
1023: ictx->interm_buf[ictx->interm_len] = '\0';
1024: }
1.1 nicm 1025:
1.28 nicm 1026: return (0);
1.1 nicm 1027: }
1028:
1.28 nicm 1029: /* Collect parameter string. */
1030: int
1031: input_parameter(struct input_ctx *ictx)
1.1 nicm 1032: {
1.28 nicm 1033: if (ictx->param_len == (sizeof ictx->param_buf) - 1)
1034: ictx->flags |= INPUT_DISCARD;
1035: else {
1036: ictx->param_buf[ictx->param_len++] = ictx->ch;
1037: ictx->param_buf[ictx->param_len] = '\0';
1038: }
1.1 nicm 1039:
1.28 nicm 1040: return (0);
1.1 nicm 1041: }
1042:
1.28 nicm 1043: /* Collect input string. */
1044: int
1045: input_input(struct input_ctx *ictx)
1.1 nicm 1046: {
1.67 nicm 1047: size_t available;
1048:
1049: available = ictx->input_space;
1050: while (ictx->input_len + 1 >= available) {
1051: available *= 2;
1052: if (available > INPUT_BUF_LIMIT) {
1053: ictx->flags |= INPUT_DISCARD;
1054: return (0);
1055: }
1.71 nicm 1056: ictx->input_buf = xrealloc(ictx->input_buf, available);
1.67 nicm 1057: ictx->input_space = available;
1.28 nicm 1058: }
1.67 nicm 1059: ictx->input_buf[ictx->input_len++] = ictx->ch;
1060: ictx->input_buf[ictx->input_len] = '\0';
1.1 nicm 1061:
1.28 nicm 1062: return (0);
1.1 nicm 1063: }
1064:
1.28 nicm 1065: /* Execute C0 control sequence. */
1066: int
1067: input_c0_dispatch(struct input_ctx *ictx)
1.1 nicm 1068: {
1.28 nicm 1069: struct screen_write_ctx *sctx = &ictx->ctx;
1070: struct window_pane *wp = ictx->wp;
1071: struct screen *s = sctx->s;
1.51 nicm 1072: u_int trigger;
1.1 nicm 1073:
1.28 nicm 1074: log_debug("%s: '%c", __func__, ictx->ch);
1.1 nicm 1075:
1.28 nicm 1076: switch (ictx->ch) {
1077: case '\000': /* NUL */
1078: break;
1079: case '\007': /* BEL */
1080: wp->window->flags |= WINDOW_BELL;
1081: break;
1082: case '\010': /* BS */
1083: screen_write_backspace(sctx);
1.51 nicm 1084: goto count_c0;
1.28 nicm 1085: case '\011': /* HT */
1086: /* Don't tab beyond the end of the line. */
1087: if (s->cx >= screen_size_x(s) - 1)
1088: break;
1.1 nicm 1089:
1.28 nicm 1090: /* Find the next tab point, or use the last column if none. */
1091: do {
1092: s->cx++;
1093: if (bit_test(s->tabs, s->cx))
1094: break;
1095: } while (s->cx < screen_size_x(s) - 1);
1096: break;
1097: case '\012': /* LF */
1098: case '\013': /* VT */
1099: case '\014': /* FF */
1100: screen_write_linefeed(sctx, 0);
1.51 nicm 1101: goto count_c0;
1.28 nicm 1102: case '\015': /* CR */
1103: screen_write_carriagereturn(sctx);
1.51 nicm 1104: goto count_c0;
1.28 nicm 1105: case '\016': /* SO */
1.69 nicm 1106: ictx->cell.set = 1;
1.28 nicm 1107: break;
1108: case '\017': /* SI */
1.69 nicm 1109: ictx->cell.set = 0;
1.28 nicm 1110: break;
1111: default:
1112: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1113: break;
1.51 nicm 1114: }
1115:
1116: return (0);
1117:
1118: count_c0:
1119: trigger = options_get_number(&wp->window->options, "c0-change-trigger");
1.68 nicm 1120: if (trigger != 0 && ++wp->changes >= trigger) {
1.51 nicm 1121: wp->flags |= PANE_DROP;
1122: window_pane_timer_start(wp);
1.28 nicm 1123: }
1.1 nicm 1124:
1.28 nicm 1125: return (0);
1.7 nicm 1126: }
1127:
1.28 nicm 1128: /* Execute escape sequence. */
1129: int
1130: input_esc_dispatch(struct input_ctx *ictx)
1.7 nicm 1131: {
1.31 nicm 1132: struct screen_write_ctx *sctx = &ictx->ctx;
1133: struct screen *s = sctx->s;
1134: struct input_table_entry *entry;
1.7 nicm 1135:
1.28 nicm 1136: if (ictx->flags & INPUT_DISCARD)
1137: return (0);
1138: log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1.7 nicm 1139:
1.28 nicm 1140: entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
1141: sizeof input_esc_table[0], input_table_compare);
1142: if (entry == NULL) {
1143: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1144: return (0);
1145: }
1.7 nicm 1146:
1.28 nicm 1147: switch (entry->type) {
1148: case INPUT_ESC_RIS:
1.69 nicm 1149: input_reset_cell(ictx);
1.46 nicm 1150: screen_write_reset(sctx);
1.28 nicm 1151: break;
1152: case INPUT_ESC_IND:
1153: screen_write_linefeed(sctx, 0);
1154: break;
1155: case INPUT_ESC_NEL:
1156: screen_write_carriagereturn(sctx);
1157: screen_write_linefeed(sctx, 0);
1158: break;
1159: case INPUT_ESC_HTS:
1160: if (s->cx < screen_size_x(s))
1161: bit_set(s->tabs, s->cx);
1162: break;
1163: case INPUT_ESC_RI:
1164: screen_write_reverseindex(sctx);
1165: break;
1166: case INPUT_ESC_DECKPAM:
1.59 nicm 1167: screen_write_mode_set(sctx, MODE_KKEYPAD);
1.28 nicm 1168: break;
1169: case INPUT_ESC_DECKPNM:
1.59 nicm 1170: screen_write_mode_clear(sctx, MODE_KKEYPAD);
1.1 nicm 1171: break;
1.28 nicm 1172: case INPUT_ESC_DECSC:
1173: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1174: ictx->old_cx = s->cx;
1175: ictx->old_cy = s->cy;
1176: break;
1177: case INPUT_ESC_DECRC:
1178: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1179: screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1180: break;
1181: case INPUT_ESC_DECALN:
1182: screen_write_alignmenttest(sctx);
1183: break;
1.69 nicm 1184: case INPUT_ESC_SCSG0_ON:
1185: ictx->cell.g0set = 1;
1186: break;
1187: case INPUT_ESC_SCSG0_OFF:
1188: ictx->cell.g0set = 0;
1189: break;
1190: case INPUT_ESC_SCSG1_ON:
1191: ictx->cell.g1set = 1;
1.1 nicm 1192: break;
1.69 nicm 1193: case INPUT_ESC_SCSG1_OFF:
1194: ictx->cell.g1set = 0;
1.1 nicm 1195: break;
1196: }
1.28 nicm 1197:
1198: return (0);
1.1 nicm 1199: }
1200:
1.28 nicm 1201: /* Execute control sequence. */
1202: int
1203: input_csi_dispatch(struct input_ctx *ictx)
1.1 nicm 1204: {
1.28 nicm 1205: struct screen_write_ctx *sctx = &ictx->ctx;
1206: struct screen *s = sctx->s;
1207: struct input_table_entry *entry;
1.65 nicm 1208: int n, m;
1.1 nicm 1209:
1.28 nicm 1210: if (ictx->flags & INPUT_DISCARD)
1211: return (0);
1212: if (input_split(ictx) != 0)
1213: return (0);
1214: log_debug("%s: '%c' \"%s\" \"%s\"",
1215: __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1.1 nicm 1216:
1.28 nicm 1217: entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1218: sizeof input_csi_table[0], input_table_compare);
1219: if (entry == NULL) {
1220: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1221: return (0);
1222: }
1.1 nicm 1223:
1.28 nicm 1224: switch (entry->type) {
1225: case INPUT_CSI_CBT:
1226: /* Find the previous tab point, n times. */
1227: n = input_get(ictx, 0, 1, 1);
1228: while (s->cx > 0 && n-- > 0) {
1229: do
1230: s->cx--;
1231: while (s->cx > 0 && !bit_test(s->tabs, s->cx));
1232: }
1233: break;
1234: case INPUT_CSI_CUB:
1235: screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
1236: break;
1237: case INPUT_CSI_CUD:
1238: screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1239: break;
1240: case INPUT_CSI_CUF:
1241: screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
1242: break;
1243: case INPUT_CSI_CUP:
1244: n = input_get(ictx, 0, 1, 1);
1245: m = input_get(ictx, 1, 1, 1);
1246: screen_write_cursormove(sctx, m - 1, n - 1);
1247: break;
1.65 nicm 1248: case INPUT_CSI_WINOPS:
1249: input_csi_dispatch_winops(ictx);
1250: break;
1.28 nicm 1251: case INPUT_CSI_CUU:
1.43 nicm 1252: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1253: break;
1254: case INPUT_CSI_CNL:
1255: screen_write_carriagereturn(sctx);
1256: screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1257: break;
1258: case INPUT_CSI_CPL:
1259: screen_write_carriagereturn(sctx);
1.28 nicm 1260: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1261: break;
1262: case INPUT_CSI_DA:
1263: switch (input_get(ictx, 0, 0, 0)) {
1264: case 0:
1265: input_reply(ictx, "\033[?1;2c");
1.50 nicm 1266: break;
1267: default:
1268: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1269: break;
1270: }
1271: break;
1272: case INPUT_CSI_DA_TWO:
1273: switch (input_get(ictx, 0, 0, 0)) {
1274: case 0:
1.66 nicm 1275: input_reply(ictx, "\033[>84;0;0c");
1.28 nicm 1276: break;
1277: default:
1278: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1279: break;
1280: }
1.56 nicm 1281: break;
1282: case INPUT_CSI_ECH:
1283: screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1));
1.28 nicm 1284: break;
1285: case INPUT_CSI_DCH:
1286: screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1));
1287: break;
1288: case INPUT_CSI_DECSTBM:
1289: n = input_get(ictx, 0, 1, 1);
1290: m = input_get(ictx, 1, 1, screen_size_y(s));
1291: screen_write_scrollregion(sctx, n - 1, m - 1);
1.1 nicm 1292: break;
1.28 nicm 1293: case INPUT_CSI_DL:
1294: screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1));
1.1 nicm 1295: break;
1.28 nicm 1296: case INPUT_CSI_DSR:
1297: switch (input_get(ictx, 0, 0, 0)) {
1298: case 5:
1299: input_reply(ictx, "\033[0n");
1300: break;
1301: case 6:
1302: input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1303: break;
1304: default:
1305: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1306: break;
1307: }
1308: break;
1309: case INPUT_CSI_ED:
1310: switch (input_get(ictx, 0, 0, 0)) {
1311: case 0:
1312: screen_write_clearendofscreen(sctx);
1313: break;
1314: case 1:
1315: screen_write_clearstartofscreen(sctx);
1316: break;
1317: case 2:
1318: screen_write_clearscreen(sctx);
1.41 nicm 1319: break;
1320: case 3:
1321: switch (input_get(ictx, 1, 0, 0)) {
1322: case 0:
1323: /*
1324: * Linux console extension to clear history
1325: * (for example before locking the screen).
1326: */
1327: screen_write_clearhistory(sctx);
1328: break;
1329: }
1.28 nicm 1330: break;
1331: default:
1332: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1333: break;
1334: }
1335: break;
1336: case INPUT_CSI_EL:
1337: switch (input_get(ictx, 0, 0, 0)) {
1338: case 0:
1339: screen_write_clearendofline(sctx);
1340: break;
1341: case 1:
1342: screen_write_clearstartofline(sctx);
1343: break;
1344: case 2:
1345: screen_write_clearline(sctx);
1346: break;
1347: default:
1348: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1349: break;
1350: }
1351: break;
1352: case INPUT_CSI_HPA:
1353: n = input_get(ictx, 0, 1, 1);
1354: screen_write_cursormove(sctx, n - 1, s->cy);
1355: break;
1356: case INPUT_CSI_ICH:
1357: screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1));
1358: break;
1359: case INPUT_CSI_IL:
1360: screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
1361: break;
1.42 nicm 1362: case INPUT_CSI_RCP:
1363: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1364: screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1365: break;
1.28 nicm 1366: case INPUT_CSI_RM:
1.64 nicm 1367: input_csi_dispatch_rm(ictx);
1368: break;
1369: case INPUT_CSI_RM_PRIVATE:
1370: input_csi_dispatch_rm_private(ictx);
1371: break;
1372: case INPUT_CSI_SCP:
1373: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1374: ictx->old_cx = s->cx;
1375: ictx->old_cy = s->cy;
1376: break;
1377: case INPUT_CSI_SGR:
1378: input_csi_dispatch_sgr(ictx);
1379: break;
1380: case INPUT_CSI_SM:
1381: input_csi_dispatch_sm(ictx);
1382: break;
1383: case INPUT_CSI_SM_PRIVATE:
1384: input_csi_dispatch_sm_private(ictx);
1385: break;
1386: case INPUT_CSI_TBC:
1387: switch (input_get(ictx, 0, 0, 0)) {
1388: case 0:
1389: if (s->cx < screen_size_x(s))
1390: bit_clear(s->tabs, s->cx);
1391: break;
1392: case 3:
1393: bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1394: break;
1395: default:
1396: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1397: break;
1398: }
1399: break;
1400: case INPUT_CSI_VPA:
1401: n = input_get(ictx, 0, 1, 1);
1402: screen_write_cursormove(sctx, s->cx, n - 1);
1403: break;
1404: case INPUT_CSI_DECSCUSR:
1405: n = input_get(ictx, 0, 0, 0);
1406: screen_set_cursor_style(s, n);
1407: break;
1408: }
1409:
1410: return (0);
1411: }
1412:
1413: /* Handle CSI RM. */
1414: void
1415: input_csi_dispatch_rm(struct input_ctx *ictx)
1416: {
1417: u_int i;
1418:
1419: for (i = 0; i < ictx->param_list_len; i++) {
1420: switch (input_get(ictx, i, 0, -1)) {
1.28 nicm 1421: case 4: /* IRM */
1.59 nicm 1422: screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
1.28 nicm 1423: break;
1.72 nicm 1424: case 34:
1425: screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1426: break;
1.28 nicm 1427: default:
1428: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1429: break;
1430: }
1.64 nicm 1431: }
1432: }
1433:
1434: /* Handle CSI private RM. */
1435: void
1436: input_csi_dispatch_rm_private(struct input_ctx *ictx)
1437: {
1.69 nicm 1438: struct window_pane *wp = ictx->wp;
1439: u_int i;
1.64 nicm 1440:
1441: for (i = 0; i < ictx->param_list_len; i++) {
1442: switch (input_get(ictx, i, 0, -1)) {
1443: case 1: /* DECCKM */
1.59 nicm 1444: screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
1.1 nicm 1445: break;
1.17 nicm 1446: case 3: /* DECCOLM */
1.24 nicm 1447: screen_write_cursormove(&ictx->ctx, 0, 0);
1.17 nicm 1448: screen_write_clearscreen(&ictx->ctx);
1449: break;
1.61 nicm 1450: case 7: /* DECAWM */
1451: screen_write_mode_clear(&ictx->ctx, MODE_WRAP);
1452: break;
1.72 nicm 1453: case 12:
1454: screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1455: break;
1.1 nicm 1456: case 25: /* TCEM */
1.59 nicm 1457: screen_write_mode_clear(&ictx->ctx, MODE_CURSOR);
1.1 nicm 1458: break;
1459: case 1000:
1.32 nicm 1460: case 1001:
1461: case 1002:
1.59 nicm 1462: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1.1 nicm 1463: break;
1.62 nicm 1464: case 1004:
1465: screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON);
1466: break;
1.33 nicm 1467: case 1005:
1.59 nicm 1468: screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8);
1.33 nicm 1469: break;
1.60 nicm 1470: case 1006:
1471: screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR);
1472: break;
1.55 nicm 1473: case 47:
1474: case 1047:
1.69 nicm 1475: window_pane_alternate_off(wp, &ictx->cell.cell, 0);
1.55 nicm 1476: break;
1.9 nicm 1477: case 1049:
1.69 nicm 1478: window_pane_alternate_off(wp, &ictx->cell.cell, 1);
1.9 nicm 1479: break;
1.49 nicm 1480: case 2004:
1.59 nicm 1481: screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
1.49 nicm 1482: break;
1.1 nicm 1483: default:
1.28 nicm 1484: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1485: break;
1486: }
1.64 nicm 1487: }
1488: }
1489:
1490: /* Handle CSI SM. */
1491: void
1492: input_csi_dispatch_sm(struct input_ctx *ictx)
1493: {
1494: u_int i;
1495:
1496: for (i = 0; i < ictx->param_list_len; i++) {
1497: switch (input_get(ictx, i, 0, -1)) {
1.1 nicm 1498: case 4: /* IRM */
1.59 nicm 1499: screen_write_mode_set(&ictx->ctx, MODE_INSERT);
1.1 nicm 1500: break;
1.72 nicm 1501: case 34:
1502: screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
1503: break;
1.1 nicm 1504: default:
1.28 nicm 1505: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1506: break;
1507: }
1.64 nicm 1508: }
1509: }
1510:
1511: /* Handle CSI private SM. */
1512: void
1513: input_csi_dispatch_sm_private(struct input_ctx *ictx)
1514: {
1.69 nicm 1515: struct window_pane *wp = ictx->wp;
1516: u_int i;
1.64 nicm 1517:
1518: for (i = 0; i < ictx->param_list_len; i++) {
1519: switch (input_get(ictx, i, 0, -1)) {
1520: case 1: /* DECCKM */
1.59 nicm 1521: screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
1.17 nicm 1522: break;
1523: case 3: /* DECCOLM */
1.24 nicm 1524: screen_write_cursormove(&ictx->ctx, 0, 0);
1.17 nicm 1525: screen_write_clearscreen(&ictx->ctx);
1.61 nicm 1526: break;
1527: case 7: /* DECAWM */
1528: screen_write_mode_set(&ictx->ctx, MODE_WRAP);
1.72 nicm 1529: break;
1530: case 12:
1531: screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
1.1 nicm 1532: break;
1533: case 25: /* TCEM */
1.59 nicm 1534: screen_write_mode_set(&ictx->ctx, MODE_CURSOR);
1.1 nicm 1535: break;
1536: case 1000:
1.59 nicm 1537: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1538: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD);
1.32 nicm 1539: break;
1540: case 1002:
1.59 nicm 1541: screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
1542: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON);
1.62 nicm 1543: break;
1544: case 1004:
1.64 nicm 1545: if (ictx->ctx.s->mode & MODE_FOCUSON)
1.62 nicm 1546: break;
1547: screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
1.69 nicm 1548: wp->flags |= PANE_FOCUSPUSH; /* force update */
1.33 nicm 1549: break;
1550: case 1005:
1.59 nicm 1551: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
1.60 nicm 1552: break;
1553: case 1006:
1554: screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR);
1.9 nicm 1555: break;
1.55 nicm 1556: case 47:
1557: case 1047:
1.69 nicm 1558: window_pane_alternate_on(wp, &ictx->cell.cell, 0);
1.55 nicm 1559: break;
1.9 nicm 1560: case 1049:
1.69 nicm 1561: window_pane_alternate_on(wp, &ictx->cell.cell, 1);
1.49 nicm 1562: break;
1563: case 2004:
1.59 nicm 1564: screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
1.1 nicm 1565: break;
1566: default:
1.28 nicm 1567: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1568: break;
1569: }
1.65 nicm 1570: }
1571: }
1572:
1573: /* Handle CSI window operations. */
1574: void
1575: input_csi_dispatch_winops(struct input_ctx *ictx)
1576: {
1577: struct window_pane *wp = ictx->wp;
1578: int n, m;
1579:
1580: m = 0;
1581: while ((n = input_get(ictx, m, 0, -1)) != -1) {
1582: switch (n) {
1583: case 1:
1584: case 2:
1585: case 5:
1586: case 6:
1587: case 7:
1588: case 11:
1589: case 13:
1590: case 14:
1591: case 19:
1592: case 20:
1593: case 21:
1594: case 24:
1595: break;
1596: case 3:
1597: case 4:
1598: case 8:
1599: m++;
1600: if (input_get(ictx, m, 0, -1) == -1)
1601: return;
1602: /* FALLTHROUGH */
1603: case 9:
1604: case 10:
1605: case 22:
1606: case 23:
1607: m++;
1608: if (input_get(ictx, m, 0, -1) == -1)
1609: return;
1610: break;
1611: case 18:
1612: input_reply(ictx, "\033[8;%u;%u", wp->sy, wp->sx);
1613: break;
1614: default:
1615: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1616: break;
1617: }
1618: m++;
1.1 nicm 1619: }
1620: }
1621:
1.28 nicm 1622: /* Handle CSI SGR. */
1.1 nicm 1623: void
1.28 nicm 1624: input_csi_dispatch_sgr(struct input_ctx *ictx)
1.1 nicm 1625: {
1.69 nicm 1626: struct grid_cell *gc = &ictx->cell.cell;
1.28 nicm 1627: u_int i;
1628: int n, m;
1.1 nicm 1629:
1.28 nicm 1630: if (ictx->param_list_len == 0) {
1.1 nicm 1631: memcpy(gc, &grid_default_cell, sizeof *gc);
1632: return;
1633: }
1634:
1.28 nicm 1635: for (i = 0; i < ictx->param_list_len; i++) {
1636: n = input_get(ictx, i, 0, 0);
1.1 nicm 1637:
1.28 nicm 1638: if (n == 38 || n == 48) {
1.1 nicm 1639: i++;
1.28 nicm 1640: if (input_get(ictx, i, 0, -1) != 5)
1.1 nicm 1641: continue;
1642:
1643: i++;
1.28 nicm 1644: m = input_get(ictx, i, 0, -1);
1645: if (m == -1) {
1646: if (n == 38) {
1647: gc->flags &= ~GRID_FLAG_FG256;
1648: gc->fg = 8;
1649: } else if (n == 48) {
1650: gc->flags &= ~GRID_FLAG_BG256;
1.36 nicm 1651: gc->bg = 8;
1.28 nicm 1652: }
1653:
1654: } else {
1655: if (n == 38) {
1656: gc->flags |= GRID_FLAG_FG256;
1657: gc->fg = m;
1658: } else if (n == 48) {
1659: gc->flags |= GRID_FLAG_BG256;
1660: gc->bg = m;
1661: }
1.1 nicm 1662: }
1663: continue;
1664: }
1665:
1.28 nicm 1666: switch (n) {
1.1 nicm 1667: case 0:
1668: case 10:
1669: memcpy(gc, &grid_default_cell, sizeof *gc);
1670: break;
1671: case 1:
1672: gc->attr |= GRID_ATTR_BRIGHT;
1673: break;
1674: case 2:
1675: gc->attr |= GRID_ATTR_DIM;
1676: break;
1677: case 3:
1678: gc->attr |= GRID_ATTR_ITALICS;
1679: break;
1680: case 4:
1681: gc->attr |= GRID_ATTR_UNDERSCORE;
1682: break;
1683: case 5:
1684: gc->attr |= GRID_ATTR_BLINK;
1685: break;
1686: case 7:
1687: gc->attr |= GRID_ATTR_REVERSE;
1688: break;
1689: case 8:
1690: gc->attr |= GRID_ATTR_HIDDEN;
1691: break;
1692: case 22:
1693: gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1694: break;
1695: case 23:
1696: gc->attr &= ~GRID_ATTR_ITALICS;
1697: break;
1698: case 24:
1699: gc->attr &= ~GRID_ATTR_UNDERSCORE;
1700: break;
1701: case 25:
1702: gc->attr &= ~GRID_ATTR_BLINK;
1703: break;
1704: case 27:
1705: gc->attr &= ~GRID_ATTR_REVERSE;
1706: break;
1707: case 30:
1708: case 31:
1709: case 32:
1710: case 33:
1711: case 34:
1712: case 35:
1713: case 36:
1714: case 37:
1715: gc->flags &= ~GRID_FLAG_FG256;
1.28 nicm 1716: gc->fg = n - 30;
1.1 nicm 1717: break;
1718: case 39:
1719: gc->flags &= ~GRID_FLAG_FG256;
1720: gc->fg = 8;
1721: break;
1722: case 40:
1723: case 41:
1724: case 42:
1725: case 43:
1726: case 44:
1727: case 45:
1728: case 46:
1729: case 47:
1730: gc->flags &= ~GRID_FLAG_BG256;
1.28 nicm 1731: gc->bg = n - 40;
1.1 nicm 1732: break;
1733: case 49:
1734: gc->flags &= ~GRID_FLAG_BG256;
1735: gc->bg = 8;
1.20 nicm 1736: break;
1737: case 90:
1738: case 91:
1739: case 92:
1740: case 93:
1741: case 94:
1742: case 95:
1743: case 96:
1744: case 97:
1.26 nicm 1745: gc->flags &= ~GRID_FLAG_FG256;
1.28 nicm 1746: gc->fg = n;
1.20 nicm 1747: break;
1748: case 100:
1749: case 101:
1750: case 102:
1751: case 103:
1752: case 104:
1753: case 105:
1754: case 106:
1755: case 107:
1.26 nicm 1756: gc->flags &= ~GRID_FLAG_BG256;
1.47 nicm 1757: gc->bg = n - 10;
1.1 nicm 1758: break;
1759: }
1760: }
1.28 nicm 1761: }
1762:
1.37 nicm 1763: /* DCS terminator (ST) received. */
1764: int
1765: input_dcs_dispatch(struct input_ctx *ictx)
1.28 nicm 1766: {
1.37 nicm 1767: const char prefix[] = "tmux;";
1768: const u_int prefix_len = (sizeof prefix) - 1;
1769:
1770: if (ictx->flags & INPUT_DISCARD)
1771: return (0);
1772:
1773: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1.28 nicm 1774:
1.37 nicm 1775: /* Check for tmux prefix. */
1776: if (ictx->input_len >= prefix_len &&
1777: strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
1778: screen_write_rawstring(&ictx->ctx,
1779: ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
1780: }
1.28 nicm 1781:
1.37 nicm 1782: return (0);
1.28 nicm 1783: }
1784:
1785: /* OSC string started. */
1786: void
1787: input_enter_osc(struct input_ctx *ictx)
1788: {
1789: log_debug("%s", __func__);
1790:
1.35 nicm 1791: input_clear(ictx);
1.28 nicm 1792: }
1793:
1794: /* OSC terminator (ST) received. */
1795: void
1796: input_exit_osc(struct input_ctx *ictx)
1797: {
1.67 nicm 1798: u_char *p = ictx->input_buf;
1.73 nicm 1799: u_int option;
1.38 nicm 1800:
1.28 nicm 1801: if (ictx->flags & INPUT_DISCARD)
1802: return;
1.38 nicm 1803: if (ictx->input_len < 1 || *p < '0' || *p > '9')
1804: return;
1.28 nicm 1805:
1.38 nicm 1806: log_debug("%s: \"%s\"", __func__, p);
1.28 nicm 1807:
1.38 nicm 1808: option = 0;
1809: while (*p >= '0' && *p <= '9')
1810: option = option * 10 + *p++ - '0';
1811: if (*p == ';')
1812: p++;
1813:
1814: switch (option) {
1815: case 0:
1816: case 2:
1817: screen_set_title(ictx->ctx.s, p);
1818: server_status_window(ictx->wp->window);
1819: break;
1820: case 12:
1.57 nicm 1821: if (*p != '?') /* ? is colour request */
1822: screen_set_cursor_colour(ictx->ctx.s, p);
1.38 nicm 1823: break;
1824: case 112:
1.57 nicm 1825: if (*p == '\0') /* no arguments allowed */
1.38 nicm 1826: screen_set_cursor_colour(ictx->ctx.s, "");
1827: break;
1828: default:
1829: log_debug("%s: unknown '%u'", __func__, option);
1830: break;
1831: }
1.28 nicm 1832: }
1833:
1834: /* APC string started. */
1835: void
1836: input_enter_apc(struct input_ctx *ictx)
1837: {
1838: log_debug("%s", __func__);
1839:
1.35 nicm 1840: input_clear(ictx);
1.28 nicm 1841: }
1842:
1843: /* APC terminator (ST) received. */
1844: void
1845: input_exit_apc(struct input_ctx *ictx)
1846: {
1847: if (ictx->flags & INPUT_DISCARD)
1848: return;
1849: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1850:
1851: screen_set_title(ictx->ctx.s, ictx->input_buf);
1852: server_status_window(ictx->wp->window);
1853: }
1854:
1855: /* Rename string started. */
1856: void
1857: input_enter_rename(struct input_ctx *ictx)
1858: {
1859: log_debug("%s", __func__);
1860:
1.35 nicm 1861: input_clear(ictx);
1.28 nicm 1862: }
1863:
1864: /* Rename terminator (ST) received. */
1865: void
1866: input_exit_rename(struct input_ctx *ictx)
1867: {
1868: if (ictx->flags & INPUT_DISCARD)
1.44 nicm 1869: return;
1870: if (!options_get_number(&ictx->wp->window->options, "allow-rename"))
1.28 nicm 1871: return;
1872: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1873:
1.48 nicm 1874: window_set_name(ictx->wp->window, ictx->input_buf);
1.28 nicm 1875: options_set_number(&ictx->wp->window->options, "automatic-rename", 0);
1876:
1877: server_status_window(ictx->wp->window);
1878: }
1879:
1880: /* Open UTF-8 character. */
1881: int
1882: input_utf8_open(struct input_ctx *ictx)
1883: {
1884: if (!options_get_number(&ictx->wp->window->options, "utf8")) {
1885: /* Print, and do not switch state. */
1886: input_print(ictx);
1887: return (-1);
1888: }
1889: log_debug("%s", __func__);
1890:
1891: utf8_open(&ictx->utf8data, ictx->ch);
1892: return (0);
1893: }
1894:
1895: /* Append to UTF-8 character. */
1896: int
1897: input_utf8_add(struct input_ctx *ictx)
1898: {
1899: log_debug("%s", __func__);
1900:
1901: utf8_append(&ictx->utf8data, ictx->ch);
1902: return (0);
1903: }
1904:
1905: /* Close UTF-8 string. */
1906: int
1907: input_utf8_close(struct input_ctx *ictx)
1908: {
1909: log_debug("%s", __func__);
1910:
1911: utf8_append(&ictx->utf8data, ictx->ch);
1912:
1.69 nicm 1913: grid_cell_set(&ictx->cell.cell, &ictx->utf8data);
1914: screen_write_cell(&ictx->ctx, &ictx->cell.cell);
1.28 nicm 1915:
1916: return (0);
1.1 nicm 1917: }