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