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