Annotation of src/usr.bin/tmux/input.c, Revision 1.37
1.37 ! nicm 1: /* $OpenBSD: input.c,v 1.36 2011/03/03 08:53:14 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20:
21: #include <stdlib.h>
22: #include <string.h>
23:
24: #include "tmux.h"
25:
1.28 nicm 26: /*
27: * Based on the description by Paul Williams at:
28: *
29: * http://vt100.net/emu/dec_ansi_parser
30: *
31: * With the following changes:
32: *
33: * - 7-bit only.
34: *
35: * - Support for UTF-8.
36: *
37: * - OSC (but not APC) may be terminated by \007 as well as ST.
38: *
39: * - A state for APC similar to OSC. Some terminals appear to use this to set
40: * the title.
41: *
42: * - A state for the screen \033k...\033\\ sequence to rename a window. This is
43: * pretty stupid but not supporting it is more trouble than it is worth.
1.37 ! nicm 44: *
! 45: * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
! 46: * be passed to the underlying teminal(s).
1.28 nicm 47: */
48:
49: /* Helper functions. */
50: int input_split(struct input_ctx *);
51: int input_get(struct input_ctx *, u_int, int, int);
52: void input_reply(struct input_ctx *, const char *, ...);
53:
54: /* Transition entry/exit handlers. */
55: void input_clear(struct input_ctx *);
56: void input_enter_osc(struct input_ctx *);
57: void input_exit_osc(struct input_ctx *);
58: void input_enter_apc(struct input_ctx *);
59: void input_exit_apc(struct input_ctx *);
60: void input_enter_rename(struct input_ctx *);
61: void input_exit_rename(struct input_ctx *);
62:
63: /* Input state handlers. */
64: int input_print(struct input_ctx *);
65: int input_intermediate(struct input_ctx *);
66: int input_parameter(struct input_ctx *);
67: int input_input(struct input_ctx *);
68: int input_c0_dispatch(struct input_ctx *);
69: int input_esc_dispatch(struct input_ctx *);
70: int input_csi_dispatch(struct input_ctx *);
71: void input_csi_dispatch_sgr(struct input_ctx *);
1.37 ! nicm 72: int input_dcs_dispatch(struct input_ctx *);
1.28 nicm 73: int input_utf8_open(struct input_ctx *);
74: int input_utf8_add(struct input_ctx *);
75: int input_utf8_close(struct input_ctx *);
76:
77: /* Command table comparison function. */
78: int input_table_compare(const void *, const void *);
79:
80: /* Command table entry. */
81: struct input_table_entry {
82: int ch;
83: const char *interm;
84: int type;
1.1 nicm 85: };
86:
1.28 nicm 87: /* Escape commands. */
88: enum input_esc_type {
89: INPUT_ESC_DECALN,
90: INPUT_ESC_DECKPAM,
91: INPUT_ESC_DECKPNM,
92: INPUT_ESC_DECRC,
93: INPUT_ESC_DECSC,
94: INPUT_ESC_HTS,
95: INPUT_ESC_IND,
96: INPUT_ESC_NEL,
97: INPUT_ESC_RI,
98: INPUT_ESC_RIS,
99: INPUT_ESC_SCSOFF_G0,
100: INPUT_ESC_SCSON_G0,
101: };
1.1 nicm 102:
1.28 nicm 103: /* Escape command table. */
104: const struct input_table_entry input_esc_table[] = {
105: { '0', "(", INPUT_ESC_SCSOFF_G0 },
106: { '7', "", INPUT_ESC_DECSC },
107: { '8', "", INPUT_ESC_DECRC },
108: { '8', "#", INPUT_ESC_DECALN },
109: { '=', "", INPUT_ESC_DECKPAM },
110: { '>', "", INPUT_ESC_DECKPNM },
111: { 'B', "(", INPUT_ESC_SCSON_G0 },
112: { 'D', "", INPUT_ESC_IND },
113: { 'E', "", INPUT_ESC_NEL },
114: { 'H', "", INPUT_ESC_HTS },
115: { 'M', "", INPUT_ESC_RI },
116: { 'c', "", INPUT_ESC_RIS },
117: };
1.1 nicm 118:
1.28 nicm 119: /* Control (CSI) commands. */
120: enum input_csi_type {
121: INPUT_CSI_CBT,
122: INPUT_CSI_CUB,
123: INPUT_CSI_CUD,
124: INPUT_CSI_CUF,
125: INPUT_CSI_CUP,
126: INPUT_CSI_CUU,
127: INPUT_CSI_DA,
128: INPUT_CSI_DCH,
129: INPUT_CSI_DECSTBM,
130: INPUT_CSI_DL,
131: INPUT_CSI_DSR,
132: INPUT_CSI_ED,
133: INPUT_CSI_EL,
134: INPUT_CSI_HPA,
135: INPUT_CSI_ICH,
136: INPUT_CSI_IL,
137: INPUT_CSI_RM,
138: INPUT_CSI_RM_PRIVATE,
139: INPUT_CSI_SGR,
140: INPUT_CSI_SM,
141: INPUT_CSI_SM_PRIVATE,
142: INPUT_CSI_TBC,
143: INPUT_CSI_VPA,
144: };
1.1 nicm 145:
1.28 nicm 146: /* Control (CSI) command table. */
147: const struct input_table_entry input_csi_table[] = {
148: { '@', "", INPUT_CSI_ICH },
149: { 'A', "", INPUT_CSI_CUU },
150: { 'B', "", INPUT_CSI_CUD },
151: { 'C', "", INPUT_CSI_CUF },
152: { 'D', "", INPUT_CSI_CUB },
153: { 'G', "", INPUT_CSI_HPA },
154: { 'H', "", INPUT_CSI_CUP },
155: { 'J', "", INPUT_CSI_ED },
156: { 'K', "", INPUT_CSI_EL },
157: { 'L', "", INPUT_CSI_IL },
158: { 'M', "", INPUT_CSI_DL },
159: { 'P', "", INPUT_CSI_DCH },
160: { 'Z', "", INPUT_CSI_CBT },
161: { 'c', "", INPUT_CSI_DA },
162: { 'd', "", INPUT_CSI_VPA },
163: { 'f', "", INPUT_CSI_CUP },
164: { 'g', "", INPUT_CSI_TBC },
165: { 'h', "", INPUT_CSI_SM },
166: { 'h', "?", INPUT_CSI_SM_PRIVATE },
167: { 'l', "", INPUT_CSI_RM },
168: { 'l', "?", INPUT_CSI_RM_PRIVATE },
169: { 'm', "", INPUT_CSI_SGR },
170: { 'n', "", INPUT_CSI_DSR },
171: { 'r', "", INPUT_CSI_DECSTBM },
172: };
1.1 nicm 173:
1.28 nicm 174: /* Input transition. */
175: struct input_transition {
176: int first;
177: int last;
1.1 nicm 178:
1.28 nicm 179: int (*handler)(struct input_ctx *);
180: const struct input_state *state;
181: };
1.1 nicm 182:
1.28 nicm 183: /* Input state. */
184: struct input_state {
185: const char *name;
186: void (*enter)(struct input_ctx *);
187: void (*exit)(struct input_ctx *);
188: const struct input_transition *transitions;
189: };
1.1 nicm 190:
1.28 nicm 191: /* State transitions available from all states. */
192: #define INPUT_STATE_ANYWHERE \
193: { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
194: { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
195: { 0x1b, 0x1b, NULL, &input_state_esc_enter }
196:
197: /* Forward declarations of state tables. */
198: const struct input_transition input_state_ground_table[];
199: const struct input_transition input_state_esc_enter_table[];
200: const struct input_transition input_state_esc_intermediate_table[];
201: const struct input_transition input_state_csi_enter_table[];
202: const struct input_transition input_state_csi_parameter_table[];
203: const struct input_transition input_state_csi_intermediate_table[];
204: const struct input_transition input_state_csi_ignore_table[];
205: const struct input_transition input_state_dcs_enter_table[];
206: const struct input_transition input_state_dcs_parameter_table[];
207: const struct input_transition input_state_dcs_intermediate_table[];
208: const struct input_transition input_state_dcs_handler_table[];
1.37 ! nicm 209: const struct input_transition input_state_dcs_escape_table[];
1.28 nicm 210: const struct input_transition input_state_dcs_ignore_table[];
211: const struct input_transition input_state_osc_string_table[];
212: const struct input_transition input_state_apc_string_table[];
213: const struct input_transition input_state_rename_string_table[];
214: const struct input_transition input_state_consume_st_table[];
215: const struct input_transition input_state_utf8_three_table[];
216: const struct input_transition input_state_utf8_two_table[];
217: const struct input_transition input_state_utf8_one_table[];
218:
219: /* ground state definition. */
220: const struct input_state input_state_ground = {
221: "ground",
222: NULL, NULL,
223: input_state_ground_table
224: };
1.1 nicm 225:
1.28 nicm 226: /* esc_enter state definition. */
227: const struct input_state input_state_esc_enter = {
228: "esc_enter",
229: input_clear, NULL,
230: input_state_esc_enter_table
231: };
1.1 nicm 232:
1.28 nicm 233: /* esc_intermediate state definition. */
234: const struct input_state input_state_esc_intermediate = {
235: "esc_intermediate",
236: NULL, NULL,
237: input_state_esc_intermediate_table
238: };
1.1 nicm 239:
1.28 nicm 240: /* csi_enter state definition. */
241: const struct input_state input_state_csi_enter = {
242: "csi_enter",
243: input_clear, NULL,
244: input_state_csi_enter_table
245: };
1.1 nicm 246:
1.28 nicm 247: /* csi_parameter state definition. */
248: const struct input_state input_state_csi_parameter = {
249: "csi_parameter",
250: NULL, NULL,
251: input_state_csi_parameter_table
252: };
1.1 nicm 253:
1.28 nicm 254: /* csi_intermediate state definition. */
255: const struct input_state input_state_csi_intermediate = {
256: "csi_intermediate",
257: NULL, NULL,
258: input_state_csi_intermediate_table
259: };
1.1 nicm 260:
1.28 nicm 261: /* csi_ignore state definition. */
262: const struct input_state input_state_csi_ignore = {
263: "csi_ignore",
264: NULL, NULL,
265: input_state_csi_ignore_table
266: };
1.1 nicm 267:
1.28 nicm 268: /* dcs_enter state definition. */
269: const struct input_state input_state_dcs_enter = {
270: "dcs_enter",
271: input_clear, NULL,
272: input_state_dcs_enter_table
273: };
1.1 nicm 274:
1.28 nicm 275: /* dcs_parameter state definition. */
276: const struct input_state input_state_dcs_parameter = {
277: "dcs_parameter",
278: NULL, NULL,
279: input_state_dcs_parameter_table
280: };
1.1 nicm 281:
1.28 nicm 282: /* dcs_intermediate state definition. */
283: const struct input_state input_state_dcs_intermediate = {
284: "dcs_intermediate",
285: NULL, NULL,
286: input_state_dcs_intermediate_table
287: };
1.1 nicm 288:
1.28 nicm 289: /* dcs_handler state definition. */
290: const struct input_state input_state_dcs_handler = {
291: "dcs_handler",
1.37 ! nicm 292: NULL, NULL,
1.28 nicm 293: input_state_dcs_handler_table
294: };
1.1 nicm 295:
1.37 ! nicm 296: /* dcs_escape state definition. */
! 297: const struct input_state input_state_dcs_escape = {
! 298: "dcs_escape",
! 299: NULL, NULL,
! 300: input_state_dcs_escape_table
! 301: };
! 302:
1.28 nicm 303: /* dcs_ignore state definition. */
304: const struct input_state input_state_dcs_ignore = {
305: "dcs_ignore",
306: NULL, NULL,
307: input_state_dcs_ignore_table
308: };
1.1 nicm 309:
1.28 nicm 310: /* osc_string state definition. */
311: const struct input_state input_state_osc_string = {
312: "osc_string",
313: input_enter_osc, input_exit_osc,
314: input_state_osc_string_table
315: };
1.1 nicm 316:
1.28 nicm 317: /* apc_string state definition. */
318: const struct input_state input_state_apc_string = {
319: "apc_string",
320: input_enter_apc, input_exit_apc,
321: input_state_apc_string_table
322: };
1.1 nicm 323:
1.28 nicm 324: /* rename_string state definition. */
325: const struct input_state input_state_rename_string = {
326: "rename_string",
327: input_enter_rename, input_exit_rename,
328: input_state_rename_string_table
329: };
1.1 nicm 330:
1.28 nicm 331: /* consume_st state definition. */
332: const struct input_state input_state_consume_st = {
333: "consume_st",
334: NULL, NULL,
335: input_state_consume_st_table
336: };
1.1 nicm 337:
1.28 nicm 338: /* utf8_three state definition. */
339: const struct input_state input_state_utf8_three = {
340: "utf8_three",
341: NULL, NULL,
342: input_state_utf8_three_table
343: };
1.1 nicm 344:
1.28 nicm 345: /* utf8_two state definition. */
346: const struct input_state input_state_utf8_two = {
347: "utf8_two",
348: NULL, NULL,
349: input_state_utf8_two_table
350: };
1.1 nicm 351:
1.28 nicm 352: /* utf8_one state definition. */
353: const struct input_state input_state_utf8_one = {
354: "utf8_one",
355: NULL, NULL,
356: input_state_utf8_one_table
357: };
1.1 nicm 358:
1.28 nicm 359: /* ground state table. */
360: const struct input_transition input_state_ground_table[] = {
361: INPUT_STATE_ANYWHERE,
362:
363: { 0x00, 0x17, input_c0_dispatch, NULL },
364: { 0x19, 0x19, input_c0_dispatch, NULL },
365: { 0x1c, 0x1f, input_c0_dispatch, NULL },
366: { 0x20, 0x7e, input_print, NULL },
367: { 0x7f, 0x7f, NULL, NULL },
368: { 0x80, 0xc1, input_print, NULL },
369: { 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one },
370: { 0xe0, 0xef, input_utf8_open, &input_state_utf8_two },
371: { 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three },
372: { 0xf5, 0xff, input_print, NULL },
1.1 nicm 373:
1.28 nicm 374: { -1, -1, NULL, NULL }
375: };
1.13 nicm 376:
1.28 nicm 377: /* esc_enter state table. */
378: const struct input_transition input_state_esc_enter_table[] = {
379: INPUT_STATE_ANYWHERE,
380:
381: { 0x00, 0x17, input_c0_dispatch, NULL },
382: { 0x19, 0x19, input_c0_dispatch, NULL },
383: { 0x1c, 0x1f, input_c0_dispatch, NULL },
384: { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
385: { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
386: { 0x50, 0x50, NULL, &input_state_dcs_enter },
387: { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
388: { 0x58, 0x58, NULL, &input_state_consume_st },
389: { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
390: { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
391: { 0x5b, 0x5b, NULL, &input_state_csi_enter },
392: { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
393: { 0x5d, 0x5d, NULL, &input_state_osc_string },
394: { 0x5e, 0x5e, NULL, &input_state_consume_st },
395: { 0x5f, 0x5f, NULL, &input_state_apc_string },
396: { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
397: { 0x6b, 0x6b, NULL, &input_state_rename_string },
1.29 nicm 398: { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground },
1.28 nicm 399: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 400:
1.28 nicm 401: { -1, -1, NULL, NULL }
402: };
1.1 nicm 403:
1.28 nicm 404: /* esc_interm state table. */
405: const struct input_transition input_state_esc_intermediate_table[] = {
406: INPUT_STATE_ANYWHERE,
407:
408: { 0x00, 0x17, input_c0_dispatch, NULL },
409: { 0x19, 0x19, input_c0_dispatch, NULL },
410: { 0x1c, 0x1f, input_c0_dispatch, NULL },
411: { 0x20, 0x2f, input_intermediate, NULL },
412: { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
413: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 414:
1.28 nicm 415: { -1, -1, NULL, NULL }
416: };
1.1 nicm 417:
1.28 nicm 418: /* csi_enter state table. */
419: const struct input_transition input_state_csi_enter_table[] = {
420: INPUT_STATE_ANYWHERE,
421:
422: { 0x00, 0x17, input_c0_dispatch, NULL },
423: { 0x19, 0x19, input_c0_dispatch, NULL },
424: { 0x1c, 0x1f, input_c0_dispatch, NULL },
425: { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
426: { 0x30, 0x39, input_parameter, &input_state_csi_parameter },
427: { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
428: { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter },
429: { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
430: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
431: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 432:
1.28 nicm 433: { -1, -1, NULL, NULL }
434: };
1.1 nicm 435:
1.28 nicm 436: /* csi_parameter state table. */
437: const struct input_transition input_state_csi_parameter_table[] = {
438: INPUT_STATE_ANYWHERE,
439:
440: { 0x00, 0x17, input_c0_dispatch, NULL },
441: { 0x19, 0x19, input_c0_dispatch, NULL },
442: { 0x1c, 0x1f, input_c0_dispatch, NULL },
443: { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
444: { 0x30, 0x39, input_parameter, NULL },
445: { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
446: { 0x3b, 0x3b, input_parameter, NULL },
447: { 0x3c, 0x3f, NULL, &input_state_csi_ignore },
448: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
449: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 450:
1.28 nicm 451: { -1, -1, NULL, NULL }
452: };
1.1 nicm 453:
1.28 nicm 454: /* csi_intermediate state table. */
455: const struct input_transition input_state_csi_intermediate_table[] = {
456: INPUT_STATE_ANYWHERE,
457:
458: { 0x00, 0x17, input_c0_dispatch, NULL },
459: { 0x19, 0x19, input_c0_dispatch, NULL },
460: { 0x1c, 0x1f, input_c0_dispatch, NULL },
461: { 0x20, 0x2f, input_intermediate, NULL },
462: { 0x30, 0x3f, NULL, &input_state_csi_ignore },
463: { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
464: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 465:
1.28 nicm 466: { -1, -1, NULL, NULL }
467: };
1.1 nicm 468:
1.28 nicm 469: /* csi_ignore state table. */
470: const struct input_transition input_state_csi_ignore_table[] = {
471: INPUT_STATE_ANYWHERE,
472:
473: { 0x00, 0x17, input_c0_dispatch, NULL },
474: { 0x19, 0x19, input_c0_dispatch, NULL },
475: { 0x1c, 0x1f, input_c0_dispatch, NULL },
476: { 0x20, 0x3f, NULL, NULL },
477: { 0x40, 0x7e, NULL, &input_state_ground },
478: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 479:
1.28 nicm 480: { -1, -1, NULL, NULL }
481: };
1.1 nicm 482:
1.28 nicm 483: /* dcs_enter state table. */
484: const struct input_transition input_state_dcs_enter_table[] = {
485: INPUT_STATE_ANYWHERE,
486:
487: { 0x00, 0x17, NULL, NULL },
488: { 0x19, 0x19, NULL, NULL },
489: { 0x1c, 0x1f, NULL, NULL },
490: { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
491: { 0x30, 0x39, input_parameter, &input_state_dcs_parameter },
492: { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
493: { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
494: { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
1.37 ! nicm 495: { 0x40, 0x7e, input_input, &input_state_dcs_handler },
1.28 nicm 496: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 497:
1.28 nicm 498: { -1, -1, NULL, NULL }
499: };
1.1 nicm 500:
1.28 nicm 501: /* dcs_parameter state table. */
502: const struct input_transition input_state_dcs_parameter_table[] = {
503: INPUT_STATE_ANYWHERE,
504:
505: { 0x00, 0x17, NULL, NULL },
506: { 0x19, 0x19, NULL, NULL },
507: { 0x1c, 0x1f, NULL, NULL },
508: { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
509: { 0x30, 0x39, input_parameter, NULL },
510: { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
511: { 0x3b, 0x3b, input_parameter, NULL },
512: { 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
1.37 ! nicm 513: { 0x40, 0x7e, input_input, &input_state_dcs_handler },
1.28 nicm 514: { 0x7f, 0xff, NULL, NULL },
1.1 nicm 515:
1.28 nicm 516: { -1, -1, NULL, NULL }
517: };
1.1 nicm 518:
1.28 nicm 519: /* dcs_interm state table. */
520: const struct input_transition input_state_dcs_intermediate_table[] = {
521: INPUT_STATE_ANYWHERE,
522:
523: { 0x00, 0x17, NULL, NULL },
524: { 0x19, 0x19, NULL, NULL },
525: { 0x1c, 0x1f, NULL, NULL },
526: { 0x20, 0x2f, input_intermediate, NULL },
527: { 0x30, 0x3f, NULL, &input_state_dcs_ignore },
1.37 ! nicm 528: { 0x40, 0x7e, input_input, &input_state_dcs_handler },
1.28 nicm 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: /* dcs_handler state table. */
535: const struct input_transition input_state_dcs_handler_table[] = {
1.37 ! nicm 536: /* No INPUT_STATE_ANYWHERE */
! 537:
! 538: { 0x00, 0x1a, input_input, NULL },
! 539: { 0x1b, 0x1b, NULL, &input_state_dcs_escape },
! 540: { 0x1c, 0xff, input_input, NULL },
! 541:
! 542: { -1, -1, NULL, NULL }
! 543: };
! 544:
! 545: /* dcs_escape state table. */
! 546: const struct input_transition input_state_dcs_escape_table[] = {
! 547: /* No INPUT_STATE_ANYWHERE */
1.28 nicm 548:
1.37 ! nicm 549: { 0x00, 0x5b, input_input, &input_state_dcs_handler },
! 550: { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
! 551: { 0x5d, 0xff, input_input, &input_state_dcs_handler },
1.1 nicm 552:
1.28 nicm 553: { -1, -1, NULL, NULL }
554: };
1.1 nicm 555:
1.28 nicm 556: /* device_ignore state table. */
557: const struct input_transition input_state_dcs_ignore_table[] = {
558: INPUT_STATE_ANYWHERE,
559:
560: { 0x00, 0x17, NULL, NULL },
561: { 0x19, 0x19, NULL, NULL },
562: { 0x1c, 0x1f, NULL, NULL },
563: { 0x20, 0xff, NULL, NULL },
1.1 nicm 564:
1.28 nicm 565: { -1, -1, NULL, NULL }
566: };
1.1 nicm 567:
1.28 nicm 568: /* osc_string state table. */
569: const struct input_transition input_state_osc_string_table[] = {
570: INPUT_STATE_ANYWHERE,
571:
572: { 0x00, 0x06, NULL, NULL },
573: { 0x07, 0x07, NULL, &input_state_ground },
574: { 0x08, 0x17, NULL, NULL },
575: { 0x19, 0x19, NULL, NULL },
576: { 0x1c, 0x1f, NULL, NULL },
577: { 0x20, 0xff, input_input, NULL },
1.1 nicm 578:
1.28 nicm 579: { -1, -1, NULL, NULL }
580: };
1.1 nicm 581:
1.28 nicm 582: /* apc_string state table. */
583: const struct input_transition input_state_apc_string_table[] = {
584: INPUT_STATE_ANYWHERE,
585:
586: { 0x00, 0x17, NULL, NULL },
587: { 0x19, 0x19, NULL, NULL },
588: { 0x1c, 0x1f, NULL, NULL },
589: { 0x20, 0xff, input_input, NULL },
1.1 nicm 590:
1.28 nicm 591: { -1, -1, NULL, NULL }
592: };
1.1 nicm 593:
1.28 nicm 594: /* rename_string state table. */
595: const struct input_transition input_state_rename_string_table[] = {
596: INPUT_STATE_ANYWHERE,
597:
598: { 0x00, 0x17, NULL, NULL },
599: { 0x19, 0x19, NULL, NULL },
600: { 0x1c, 0x1f, NULL, NULL },
601: { 0x20, 0xff, input_input, NULL },
1.1 nicm 602:
1.28 nicm 603: { -1, -1, NULL, NULL }
604: };
1.1 nicm 605:
1.28 nicm 606: /* consume_st state table. */
607: const struct input_transition input_state_consume_st_table[] = {
608: INPUT_STATE_ANYWHERE,
609:
610: { 0x00, 0x17, NULL, NULL },
611: { 0x19, 0x19, NULL, NULL },
612: { 0x1c, 0x1f, NULL, NULL },
613: { 0x20, 0xff, NULL, NULL },
1.6 nicm 614:
1.28 nicm 615: { -1, -1, NULL, NULL }
616: };
1.6 nicm 617:
1.28 nicm 618: /* utf8_three state table. */
619: const struct input_transition input_state_utf8_three_table[] = {
620: /* No INPUT_STATE_ANYWHERE */
621:
622: { 0x00, 0x7f, NULL, &input_state_ground },
623: { 0x80, 0xbf, input_utf8_add, &input_state_utf8_two },
624: { 0xc0, 0xff, NULL, &input_state_ground },
1.4 nicm 625:
1.28 nicm 626: { -1, -1, NULL, NULL }
627: };
1.1 nicm 628:
1.28 nicm 629: /* utf8_two state table. */
630: const struct input_transition input_state_utf8_two_table[] = {
631: /* No INPUT_STATE_ANYWHERE */
632:
633: { 0x00, 0x7f, NULL, &input_state_ground },
634: { 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
635: { 0xc0, 0xff, NULL, &input_state_ground },
1.1 nicm 636:
1.28 nicm 637: { -1, -1, NULL, NULL }
638: };
1.1 nicm 639:
1.28 nicm 640: /* utf8_one state table. */
641: const struct input_transition input_state_utf8_one_table[] = {
642: /* No INPUT_STATE_ANYWHERE */
643:
644: { 0x00, 0x7f, NULL, &input_state_ground },
645: { 0x80, 0xbf, input_utf8_close, &input_state_ground },
646: { 0xc0, 0xff, NULL, &input_state_ground },
1.1 nicm 647:
1.28 nicm 648: { -1, -1, NULL, NULL }
649: };
1.1 nicm 650:
1.28 nicm 651: /* Input table compare. */
652: int
653: input_table_compare(const void *key, const void *value)
1.1 nicm 654: {
1.28 nicm 655: const struct input_ctx *ictx = key;
656: const struct input_table_entry *entry = value;
1.1 nicm 657:
1.28 nicm 658: if (ictx->ch != entry->ch)
659: return (ictx->ch - entry->ch);
660: return (strcmp(ictx->interm_buf, entry->interm));
1.1 nicm 661: }
662:
1.28 nicm 663: /* Initialise input parser. */
1.1 nicm 664: void
1.28 nicm 665: input_init(struct window_pane *wp)
1.1 nicm 666: {
1.28 nicm 667: struct input_ctx *ictx = &wp->ictx;
1.1 nicm 668:
1.28 nicm 669: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
1.1 nicm 670:
1.28 nicm 671: memcpy(&ictx->old_cell, &grid_default_cell, sizeof ictx->old_cell);
672: ictx->old_cx = 0;
673: ictx->old_cy = 0;
1.1 nicm 674:
1.28 nicm 675: *ictx->interm_buf = '\0';
676: ictx->interm_len = 0;
1.1 nicm 677:
1.28 nicm 678: *ictx->param_buf = '\0';
679: ictx->param_len = 0;
1.1 nicm 680:
1.28 nicm 681: ictx->state = &input_state_ground;
682: ictx->flags = 0;
1.1 nicm 683: }
684:
1.28 nicm 685: /* Destroy input parser. */
1.1 nicm 686: void
1.28 nicm 687: input_free(unused struct window_pane *wp)
1.1 nicm 688: {
689: }
690:
1.28 nicm 691: /* Parse input. */
1.1 nicm 692: void
1.28 nicm 693: input_parse(struct window_pane *wp)
1.1 nicm 694: {
1.28 nicm 695: struct input_ctx *ictx = &wp->ictx;
696: const struct input_transition *itr;
697: struct evbuffer *evb = wp->event->input;
698: u_char *buf;
699: size_t len, off;
1.1 nicm 700:
1.28 nicm 701: if (EVBUFFER_LENGTH(evb) == 0)
702: return;
1.30 nicm 703:
1.28 nicm 704: wp->window->flags |= WINDOW_ACTIVITY;
1.30 nicm 705: wp->window->flags &= ~WINDOW_SILENCE;
1.1 nicm 706:
1.28 nicm 707: /*
708: * Open the screen. Use NULL wp if there is a mode set as don't want to
709: * update the tty.
710: */
711: if (wp->mode == NULL)
712: screen_write_start(&ictx->ctx, wp, &wp->base);
713: else
714: screen_write_start(&ictx->ctx, NULL, &wp->base);
715: ictx->wp = wp;
1.7 nicm 716:
1.28 nicm 717: buf = EVBUFFER_DATA(evb);
718: len = EVBUFFER_LENGTH(evb);
719: off = 0;
720:
721: /* Parse the input. */
722: while (off < len) {
723: ictx->ch = buf[off++];
724: log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
725:
726: /* Find the transition. */
727: itr = ictx->state->transitions;
728: while (itr->first != -1 && itr->last != -1) {
729: if (ictx->ch >= itr->first && ictx->ch <= itr->last)
1.7 nicm 730: break;
1.28 nicm 731: itr++;
1.1 nicm 732: }
1.28 nicm 733: if (itr->first == -1 || itr->last == -1) {
734: /* No transition? Eh? */
735: fatalx("No transition from state!");
1.3 nicm 736: }
1.1 nicm 737:
738: /*
1.28 nicm 739: * Execute the handler, if any. Don't switch state if it
740: * returns non-zero.
1.1 nicm 741: */
1.31 nicm 742: if (itr->handler != NULL && itr->handler(ictx) != 0)
1.28 nicm 743: continue;
744:
745: /* And switch state, if necessary. */
1.31 nicm 746: if (itr->state != NULL) {
1.28 nicm 747: if (ictx->state->exit != NULL)
748: ictx->state->exit(ictx);
749: ictx->state = itr->state;
750: if (ictx->state->enter != NULL)
751: ictx->state->enter(ictx);
1.1 nicm 752: }
753: }
754:
1.28 nicm 755: /* Close the screen. */
756: screen_write_stop(&ictx->ctx);
1.1 nicm 757:
1.28 nicm 758: evbuffer_drain(evb, len);
1.1 nicm 759: }
760:
1.28 nicm 761: /* Split the parameter list (if any). */
762: int
763: input_split(struct input_ctx *ictx)
1.1 nicm 764:
765: {
1.28 nicm 766: const char *errstr;
767: char *ptr, *out;
768: int n;
1.1 nicm 769:
1.28 nicm 770: ictx->param_list_len = 0;
771: if (ictx->param_len == 0)
772: return (0);
1.1 nicm 773:
1.28 nicm 774: ptr = ictx->param_buf;
775: while ((out = strsep(&ptr, ";")) != NULL) {
776: if (*out == '\0')
777: n = -1;
778: else {
779: n = strtonum(out, 0, INT_MAX, &errstr);
780: if (errstr != NULL)
781: return (-1);
782: }
1.1 nicm 783:
1.28 nicm 784: ictx->param_list[ictx->param_list_len++] = n;
785: if (ictx->param_list_len == nitems(ictx->param_list))
786: return (-1);
787: }
1.1 nicm 788:
1.28 nicm 789: return (0);
1.1 nicm 790: }
791:
1.28 nicm 792: /* Get an argument or return default value..*/
793: int
794: input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
1.1 nicm 795: {
1.28 nicm 796: int retval;
1.1 nicm 797:
1.28 nicm 798: if (validx >= ictx->param_list_len)
799: return (defval);
1.1 nicm 800:
1.28 nicm 801: retval = ictx->param_list[validx];
802: if (retval == -1)
803: return (defval);
804: if (retval < minval)
805: return (minval);
806: return (retval);
1.1 nicm 807: }
808:
1.28 nicm 809: /* Reply to terminal query. */
1.1 nicm 810: void
1.28 nicm 811: input_reply(struct input_ctx *ictx, const char *fmt, ...)
1.1 nicm 812: {
1.28 nicm 813: va_list ap;
814: char *reply;
1.1 nicm 815:
1.28 nicm 816: va_start(ap, fmt);
817: vasprintf(&reply, fmt, ap);
818: va_end(ap);
1.1 nicm 819:
1.28 nicm 820: bufferevent_write(ictx->wp->event, reply, strlen(reply));
821: xfree(reply);
1.8 nicm 822: }
823:
1.28 nicm 824: /* Clear saved state. */
1.8 nicm 825: void
1.28 nicm 826: input_clear(struct input_ctx *ictx)
1.8 nicm 827: {
1.28 nicm 828: *ictx->interm_buf = '\0';
829: ictx->interm_len = 0;
1.8 nicm 830:
1.28 nicm 831: *ictx->param_buf = '\0';
832: ictx->param_len = 0;
1.8 nicm 833:
1.35 nicm 834: *ictx->input_buf = '\0';
835: ictx->input_len = 0;
836:
1.28 nicm 837: ictx->flags &= ~INPUT_DISCARD;
1.14 nicm 838: }
839:
1.28 nicm 840: /* Output this character to the screen. */
841: int
842: input_print(struct input_ctx *ictx)
1.14 nicm 843: {
1.28 nicm 844: ictx->cell.data = ictx->ch;
845: screen_write_cell(&ictx->ctx, &ictx->cell, NULL);
1.14 nicm 846:
1.28 nicm 847: return (0);
1.1 nicm 848: }
849:
1.28 nicm 850: /* Collect intermediate string. */
851: int
852: input_intermediate(struct input_ctx *ictx)
1.1 nicm 853: {
1.28 nicm 854: if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
855: ictx->flags |= INPUT_DISCARD;
856: else {
857: ictx->interm_buf[ictx->interm_len++] = ictx->ch;
858: ictx->interm_buf[ictx->interm_len] = '\0';
859: }
1.1 nicm 860:
1.28 nicm 861: return (0);
1.1 nicm 862: }
863:
1.28 nicm 864: /* Collect parameter string. */
865: int
866: input_parameter(struct input_ctx *ictx)
1.1 nicm 867: {
1.28 nicm 868: if (ictx->param_len == (sizeof ictx->param_buf) - 1)
869: ictx->flags |= INPUT_DISCARD;
870: else {
871: ictx->param_buf[ictx->param_len++] = ictx->ch;
872: ictx->param_buf[ictx->param_len] = '\0';
873: }
1.1 nicm 874:
1.28 nicm 875: return (0);
1.1 nicm 876: }
877:
1.28 nicm 878: /* Collect input string. */
879: int
880: input_input(struct input_ctx *ictx)
1.1 nicm 881: {
1.28 nicm 882: if (ictx->input_len == (sizeof ictx->input_buf) - 1)
883: ictx->flags |= INPUT_DISCARD;
884: else {
885: ictx->input_buf[ictx->input_len++] = ictx->ch;
886: ictx->input_buf[ictx->input_len] = '\0';
887: }
1.1 nicm 888:
1.28 nicm 889: return (0);
1.1 nicm 890: }
891:
1.28 nicm 892: /* Execute C0 control sequence. */
893: int
894: input_c0_dispatch(struct input_ctx *ictx)
1.1 nicm 895: {
1.28 nicm 896: struct screen_write_ctx *sctx = &ictx->ctx;
897: struct window_pane *wp = ictx->wp;
898: struct screen *s = sctx->s;
1.1 nicm 899:
1.28 nicm 900: log_debug("%s: '%c", __func__, ictx->ch);
1.1 nicm 901:
1.28 nicm 902: switch (ictx->ch) {
903: case '\000': /* NUL */
904: break;
905: case '\007': /* BEL */
906: wp->window->flags |= WINDOW_BELL;
907: break;
908: case '\010': /* BS */
909: screen_write_backspace(sctx);
910: break;
911: case '\011': /* HT */
912: /* Don't tab beyond the end of the line. */
913: if (s->cx >= screen_size_x(s) - 1)
914: break;
1.1 nicm 915:
1.28 nicm 916: /* Find the next tab point, or use the last column if none. */
917: do {
918: s->cx++;
919: if (bit_test(s->tabs, s->cx))
920: break;
921: } while (s->cx < screen_size_x(s) - 1);
922: break;
923: case '\012': /* LF */
924: case '\013': /* VT */
925: case '\014': /* FF */
926: screen_write_linefeed(sctx, 0);
927: break;
928: case '\015': /* CR */
929: screen_write_carriagereturn(sctx);
930: break;
931: case '\016': /* SO */
932: ictx->cell.attr |= GRID_ATTR_CHARSET;
933: break;
934: case '\017': /* SI */
935: ictx->cell.attr &= ~GRID_ATTR_CHARSET;
936: break;
937: default:
938: log_debug("%s: unknown '%c'", __func__, ictx->ch);
939: break;
940: }
1.1 nicm 941:
1.28 nicm 942: return (0);
1.7 nicm 943: }
944:
1.28 nicm 945: /* Execute escape sequence. */
946: int
947: input_esc_dispatch(struct input_ctx *ictx)
1.7 nicm 948: {
1.31 nicm 949: struct screen_write_ctx *sctx = &ictx->ctx;
950: struct screen *s = sctx->s;
951: struct input_table_entry *entry;
1.7 nicm 952:
1.28 nicm 953: if (ictx->flags & INPUT_DISCARD)
954: return (0);
955: log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
1.7 nicm 956:
1.28 nicm 957: entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
958: sizeof input_esc_table[0], input_table_compare);
959: if (entry == NULL) {
960: log_debug("%s: unknown '%c'", __func__, ictx->ch);
961: return (0);
962: }
1.7 nicm 963:
1.28 nicm 964: switch (entry->type) {
965: case INPUT_ESC_RIS:
966: memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
967: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
968: ictx->old_cx = 0;
969: ictx->old_cy = 0;
1.1 nicm 970:
1.28 nicm 971: screen_reset_tabs(sctx->s);
1.1 nicm 972:
1.28 nicm 973: screen_write_scrollregion(sctx, 0, screen_size_y(sctx->s) - 1);
1.1 nicm 974:
1.28 nicm 975: screen_write_insertmode(sctx, 0);
976: screen_write_kcursormode(sctx, 0);
977: screen_write_kkeypadmode(sctx, 0);
1.32 nicm 978: screen_write_mousemode_off(sctx);
1.1 nicm 979:
1.28 nicm 980: screen_write_clearscreen(sctx);
981: screen_write_cursormove(sctx, 0, 0);
982: break;
983: case INPUT_ESC_IND:
984: screen_write_linefeed(sctx, 0);
985: break;
986: case INPUT_ESC_NEL:
987: screen_write_carriagereturn(sctx);
988: screen_write_linefeed(sctx, 0);
989: break;
990: case INPUT_ESC_HTS:
991: if (s->cx < screen_size_x(s))
992: bit_set(s->tabs, s->cx);
993: break;
994: case INPUT_ESC_RI:
995: screen_write_reverseindex(sctx);
996: break;
997: case INPUT_ESC_DECKPAM:
998: screen_write_kkeypadmode(sctx, 1);
999: break;
1000: case INPUT_ESC_DECKPNM:
1001: screen_write_kkeypadmode(sctx, 0);
1.1 nicm 1002: break;
1.28 nicm 1003: case INPUT_ESC_DECSC:
1004: memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1005: ictx->old_cx = s->cx;
1006: ictx->old_cy = s->cy;
1007: break;
1008: case INPUT_ESC_DECRC:
1009: memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1010: screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1011: break;
1012: case INPUT_ESC_DECALN:
1013: screen_write_alignmenttest(sctx);
1014: break;
1015: case INPUT_ESC_SCSON_G0:
1016: /*
1017: * Not really supported, but fake it up enough for those that
1018: * use it to switch character sets (by redefining G0 to
1019: * graphics set, rather than switching to G1).
1020: */
1021: ictx->cell.attr &= ~GRID_ATTR_CHARSET;
1.1 nicm 1022: break;
1.28 nicm 1023: case INPUT_ESC_SCSOFF_G0:
1024: ictx->cell.attr |= GRID_ATTR_CHARSET;
1.1 nicm 1025: break;
1026: }
1.28 nicm 1027:
1028: return (0);
1.1 nicm 1029: }
1030:
1.28 nicm 1031: /* Execute control sequence. */
1032: int
1033: input_csi_dispatch(struct input_ctx *ictx)
1.1 nicm 1034: {
1.28 nicm 1035: struct screen_write_ctx *sctx = &ictx->ctx;
1036: struct window_pane *wp = ictx->wp;
1037: struct screen *s = sctx->s;
1038: struct input_table_entry *entry;
1039: int n, m;
1.1 nicm 1040:
1.28 nicm 1041: if (ictx->flags & INPUT_DISCARD)
1042: return (0);
1043: if (input_split(ictx) != 0)
1044: return (0);
1045: log_debug("%s: '%c' \"%s\" \"%s\"",
1046: __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1.1 nicm 1047:
1.28 nicm 1048: entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1049: sizeof input_csi_table[0], input_table_compare);
1050: if (entry == NULL) {
1051: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1052: return (0);
1053: }
1.1 nicm 1054:
1.28 nicm 1055: switch (entry->type) {
1056: case INPUT_CSI_CBT:
1057: /* Find the previous tab point, n times. */
1058: n = input_get(ictx, 0, 1, 1);
1059: while (s->cx > 0 && n-- > 0) {
1060: do
1061: s->cx--;
1062: while (s->cx > 0 && !bit_test(s->tabs, s->cx));
1063: }
1064: break;
1065: case INPUT_CSI_CUB:
1066: screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
1067: break;
1068: case INPUT_CSI_CUD:
1069: screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1070: break;
1071: case INPUT_CSI_CUF:
1072: screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
1073: break;
1074: case INPUT_CSI_CUP:
1075: n = input_get(ictx, 0, 1, 1);
1076: m = input_get(ictx, 1, 1, 1);
1077: screen_write_cursormove(sctx, m - 1, n - 1);
1078: break;
1079: case INPUT_CSI_CUU:
1080: screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1081: break;
1082: case INPUT_CSI_DA:
1083: switch (input_get(ictx, 0, 0, 0)) {
1084: case 0:
1085: input_reply(ictx, "\033[?1;2c");
1086: break;
1087: default:
1088: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1089: break;
1090: }
1091: break;
1092: case INPUT_CSI_DCH:
1093: screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1));
1094: break;
1095: case INPUT_CSI_DECSTBM:
1096: n = input_get(ictx, 0, 1, 1);
1097: m = input_get(ictx, 1, 1, screen_size_y(s));
1098: screen_write_scrollregion(sctx, n - 1, m - 1);
1.1 nicm 1099: break;
1.28 nicm 1100: case INPUT_CSI_DL:
1101: screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1));
1.1 nicm 1102: break;
1.28 nicm 1103: case INPUT_CSI_DSR:
1104: switch (input_get(ictx, 0, 0, 0)) {
1105: case 5:
1106: input_reply(ictx, "\033[0n");
1107: break;
1108: case 6:
1109: input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1110: break;
1111: default:
1112: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1113: break;
1114: }
1115: break;
1116: case INPUT_CSI_ED:
1117: switch (input_get(ictx, 0, 0, 0)) {
1118: case 0:
1119: screen_write_clearendofscreen(sctx);
1120: break;
1121: case 1:
1122: screen_write_clearstartofscreen(sctx);
1123: break;
1124: case 2:
1125: screen_write_clearscreen(sctx);
1126: break;
1127: default:
1128: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1129: break;
1130: }
1131: break;
1132: case INPUT_CSI_EL:
1133: switch (input_get(ictx, 0, 0, 0)) {
1134: case 0:
1135: screen_write_clearendofline(sctx);
1136: break;
1137: case 1:
1138: screen_write_clearstartofline(sctx);
1139: break;
1140: case 2:
1141: screen_write_clearline(sctx);
1142: break;
1143: default:
1144: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1145: break;
1146: }
1147: break;
1148: case INPUT_CSI_HPA:
1149: n = input_get(ictx, 0, 1, 1);
1150: screen_write_cursormove(sctx, n - 1, s->cy);
1151: break;
1152: case INPUT_CSI_ICH:
1153: screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1));
1154: break;
1155: case INPUT_CSI_IL:
1156: screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
1157: break;
1158: case INPUT_CSI_RM:
1159: switch (input_get(ictx, 0, 0, -1)) {
1160: case 4: /* IRM */
1161: screen_write_insertmode(&ictx->ctx, 0);
1162: break;
1163: default:
1164: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1165: break;
1166: }
1.1 nicm 1167: break;
1.28 nicm 1168: case INPUT_CSI_RM_PRIVATE:
1169: switch (input_get(ictx, 0, 0, -1)) {
1.1 nicm 1170: case 1: /* GATM */
1.28 nicm 1171: screen_write_kcursormode(&ictx->ctx, 0);
1.1 nicm 1172: break;
1.17 nicm 1173: case 3: /* DECCOLM */
1.24 nicm 1174: screen_write_cursormove(&ictx->ctx, 0, 0);
1.17 nicm 1175: screen_write_clearscreen(&ictx->ctx);
1176: break;
1.1 nicm 1177: case 25: /* TCEM */
1.28 nicm 1178: screen_write_cursormode(&ictx->ctx, 0);
1.1 nicm 1179: break;
1180: case 1000:
1.32 nicm 1181: case 1001:
1182: case 1002:
1183: case 1003:
1184: screen_write_mousemode_off(&ictx->ctx);
1.1 nicm 1185: break;
1.33 nicm 1186: case 1005:
1187: screen_write_utf8mousemode(&ictx->ctx, 0);
1188: break;
1.9 nicm 1189: case 1049:
1.28 nicm 1190: window_pane_alternate_off(wp, &ictx->cell);
1.9 nicm 1191: break;
1.1 nicm 1192: default:
1.28 nicm 1193: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1194: break;
1195: }
1.28 nicm 1196: break;
1197: case INPUT_CSI_SGR:
1198: input_csi_dispatch_sgr(ictx);
1199: break;
1200: case INPUT_CSI_SM:
1201: switch (input_get(ictx, 0, 0, -1)) {
1.1 nicm 1202: case 4: /* IRM */
1203: screen_write_insertmode(&ictx->ctx, 1);
1204: break;
1205: default:
1.28 nicm 1206: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1207: break;
1208: }
1.28 nicm 1209: break;
1210: case INPUT_CSI_SM_PRIVATE:
1211: switch (input_get(ictx, 0, 0, -1)) {
1.1 nicm 1212: case 1: /* GATM */
1.28 nicm 1213: screen_write_kcursormode(&ictx->ctx, 1);
1.17 nicm 1214: break;
1215: case 3: /* DECCOLM */
1.24 nicm 1216: screen_write_cursormove(&ictx->ctx, 0, 0);
1.17 nicm 1217: screen_write_clearscreen(&ictx->ctx);
1.1 nicm 1218: break;
1219: case 25: /* TCEM */
1.28 nicm 1220: screen_write_cursormode(&ictx->ctx, 1);
1.1 nicm 1221: break;
1222: case 1000:
1.32 nicm 1223: screen_write_mousemode_on(
1224: &ictx->ctx, MODE_MOUSE_STANDARD);
1225: break;
1226: case 1002:
1227: screen_write_mousemode_on(
1228: &ictx->ctx, MODE_MOUSE_BUTTON);
1229: break;
1230: case 1003:
1231: screen_write_mousemode_on(&ictx->ctx, MODE_MOUSE_ANY);
1.33 nicm 1232: break;
1233: case 1005:
1234: screen_write_utf8mousemode(&ictx->ctx, 1);
1.9 nicm 1235: break;
1236: case 1049:
1.28 nicm 1237: window_pane_alternate_on(wp, &ictx->cell);
1.1 nicm 1238: break;
1239: default:
1.28 nicm 1240: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1241: break;
1242: }
1.28 nicm 1243: break;
1244: case INPUT_CSI_TBC:
1245: switch (input_get(ictx, 0, 0, 0)) {
1246: case 0:
1247: if (s->cx < screen_size_x(s))
1248: bit_clear(s->tabs, s->cx);
1.1 nicm 1249: break;
1.28 nicm 1250: case 3:
1251: bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1.1 nicm 1252: break;
1253: default:
1.28 nicm 1254: log_debug("%s: unknown '%c'", __func__, ictx->ch);
1.1 nicm 1255: break;
1256: }
1.28 nicm 1257: break;
1258: case INPUT_CSI_VPA:
1259: n = input_get(ictx, 0, 1, 1);
1260: screen_write_cursormove(sctx, s->cx, n - 1);
1261: break;
1.1 nicm 1262: }
1263:
1.28 nicm 1264: return (0);
1.1 nicm 1265: }
1266:
1.28 nicm 1267: /* Handle CSI SGR. */
1.1 nicm 1268: void
1.28 nicm 1269: input_csi_dispatch_sgr(struct input_ctx *ictx)
1.1 nicm 1270: {
1.28 nicm 1271: struct grid_cell *gc = &ictx->cell;
1272: u_int i;
1273: int n, m;
1274: u_char attr;
1.1 nicm 1275:
1.28 nicm 1276: if (ictx->param_list_len == 0) {
1.1 nicm 1277: attr = gc->attr;
1278: memcpy(gc, &grid_default_cell, sizeof *gc);
1.24 nicm 1279: gc->attr |= (attr & GRID_ATTR_CHARSET);
1.1 nicm 1280: return;
1281: }
1282:
1.28 nicm 1283: for (i = 0; i < ictx->param_list_len; i++) {
1284: n = input_get(ictx, i, 0, 0);
1.1 nicm 1285:
1.28 nicm 1286: if (n == 38 || n == 48) {
1.1 nicm 1287: i++;
1.28 nicm 1288: if (input_get(ictx, i, 0, -1) != 5)
1.1 nicm 1289: continue;
1290:
1291: i++;
1.28 nicm 1292: m = input_get(ictx, i, 0, -1);
1293: if (m == -1) {
1294: if (n == 38) {
1295: gc->flags &= ~GRID_FLAG_FG256;
1296: gc->fg = 8;
1297: } else if (n == 48) {
1298: gc->flags &= ~GRID_FLAG_BG256;
1.36 nicm 1299: gc->bg = 8;
1.28 nicm 1300: }
1301:
1302: } else {
1303: if (n == 38) {
1304: gc->flags |= GRID_FLAG_FG256;
1305: gc->fg = m;
1306: } else if (n == 48) {
1307: gc->flags |= GRID_FLAG_BG256;
1308: gc->bg = m;
1309: }
1.1 nicm 1310: }
1311: continue;
1312: }
1313:
1.28 nicm 1314: switch (n) {
1.1 nicm 1315: case 0:
1316: case 10:
1317: attr = gc->attr;
1318: memcpy(gc, &grid_default_cell, sizeof *gc);
1319: gc->attr |= (attr & GRID_ATTR_CHARSET);
1320: break;
1321: case 1:
1322: gc->attr |= GRID_ATTR_BRIGHT;
1323: break;
1324: case 2:
1325: gc->attr |= GRID_ATTR_DIM;
1326: break;
1327: case 3:
1328: gc->attr |= GRID_ATTR_ITALICS;
1329: break;
1330: case 4:
1331: gc->attr |= GRID_ATTR_UNDERSCORE;
1332: break;
1333: case 5:
1334: gc->attr |= GRID_ATTR_BLINK;
1335: break;
1336: case 7:
1337: gc->attr |= GRID_ATTR_REVERSE;
1338: break;
1339: case 8:
1340: gc->attr |= GRID_ATTR_HIDDEN;
1341: break;
1342: case 22:
1343: gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1344: break;
1345: case 23:
1346: gc->attr &= ~GRID_ATTR_ITALICS;
1347: break;
1348: case 24:
1349: gc->attr &= ~GRID_ATTR_UNDERSCORE;
1350: break;
1351: case 25:
1352: gc->attr &= ~GRID_ATTR_BLINK;
1353: break;
1354: case 27:
1355: gc->attr &= ~GRID_ATTR_REVERSE;
1356: break;
1357: case 30:
1358: case 31:
1359: case 32:
1360: case 33:
1361: case 34:
1362: case 35:
1363: case 36:
1364: case 37:
1365: gc->flags &= ~GRID_FLAG_FG256;
1.28 nicm 1366: gc->fg = n - 30;
1.1 nicm 1367: break;
1368: case 39:
1369: gc->flags &= ~GRID_FLAG_FG256;
1370: gc->fg = 8;
1371: break;
1372: case 40:
1373: case 41:
1374: case 42:
1375: case 43:
1376: case 44:
1377: case 45:
1378: case 46:
1379: case 47:
1380: gc->flags &= ~GRID_FLAG_BG256;
1.28 nicm 1381: gc->bg = n - 40;
1.1 nicm 1382: break;
1383: case 49:
1384: gc->flags &= ~GRID_FLAG_BG256;
1385: gc->bg = 8;
1.20 nicm 1386: break;
1387: case 90:
1388: case 91:
1389: case 92:
1390: case 93:
1391: case 94:
1392: case 95:
1393: case 96:
1394: case 97:
1.26 nicm 1395: gc->flags &= ~GRID_FLAG_FG256;
1.28 nicm 1396: gc->fg = n;
1.20 nicm 1397: break;
1398: case 100:
1399: case 101:
1400: case 102:
1401: case 103:
1402: case 104:
1403: case 105:
1404: case 106:
1405: case 107:
1.26 nicm 1406: gc->flags &= ~GRID_FLAG_BG256;
1.28 nicm 1407: gc->bg = n;
1.1 nicm 1408: break;
1409: }
1410: }
1.28 nicm 1411: }
1412:
1.37 ! nicm 1413: /* DCS terminator (ST) received. */
! 1414: int
! 1415: input_dcs_dispatch(struct input_ctx *ictx)
1.28 nicm 1416: {
1.37 ! nicm 1417: const char prefix[] = "tmux;";
! 1418: const u_int prefix_len = (sizeof prefix) - 1;
! 1419:
! 1420: if (ictx->flags & INPUT_DISCARD)
! 1421: return (0);
! 1422:
! 1423: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1.28 nicm 1424:
1.37 ! nicm 1425: /* Check for tmux prefix. */
! 1426: if (ictx->input_len >= prefix_len &&
! 1427: strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
! 1428: screen_write_rawstring(&ictx->ctx,
! 1429: ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
! 1430: }
1.28 nicm 1431:
1.37 ! nicm 1432: return (0);
1.28 nicm 1433: }
1434:
1435: /* OSC string started. */
1436: void
1437: input_enter_osc(struct input_ctx *ictx)
1438: {
1439: log_debug("%s", __func__);
1440:
1.35 nicm 1441: input_clear(ictx);
1.28 nicm 1442: }
1443:
1444: /* OSC terminator (ST) received. */
1445: void
1446: input_exit_osc(struct input_ctx *ictx)
1447: {
1448: if (ictx->flags & INPUT_DISCARD)
1449: return;
1450: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1451:
1452: if (ictx->input_len < 2 || ictx->input_buf[1] != ';')
1453: return;
1454: if (ictx->input_buf[0] != '0' && ictx->input_buf[0] != '2')
1455: return;
1456:
1457: screen_set_title(ictx->ctx.s, ictx->input_buf + 2);
1458: server_status_window(ictx->wp->window);
1459: }
1460:
1461: /* APC string started. */
1462: void
1463: input_enter_apc(struct input_ctx *ictx)
1464: {
1465: log_debug("%s", __func__);
1466:
1.35 nicm 1467: input_clear(ictx);
1.28 nicm 1468: }
1469:
1470: /* APC terminator (ST) received. */
1471: void
1472: input_exit_apc(struct input_ctx *ictx)
1473: {
1474: if (ictx->flags & INPUT_DISCARD)
1475: return;
1476: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1477:
1478: screen_set_title(ictx->ctx.s, ictx->input_buf);
1479: server_status_window(ictx->wp->window);
1480: }
1481:
1482: /* Rename string started. */
1483: void
1484: input_enter_rename(struct input_ctx *ictx)
1485: {
1486: log_debug("%s", __func__);
1487:
1.35 nicm 1488: input_clear(ictx);
1.28 nicm 1489: }
1490:
1491: /* Rename terminator (ST) received. */
1492: void
1493: input_exit_rename(struct input_ctx *ictx)
1494: {
1495: if (ictx->flags & INPUT_DISCARD)
1496: return;
1497: log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1498:
1499: xfree(ictx->wp->window->name);
1500: ictx->wp->window->name = xstrdup(ictx->input_buf);
1501: options_set_number(&ictx->wp->window->options, "automatic-rename", 0);
1502:
1503: server_status_window(ictx->wp->window);
1504: }
1505:
1506: /* Open UTF-8 character. */
1507: int
1508: input_utf8_open(struct input_ctx *ictx)
1509: {
1510: if (!options_get_number(&ictx->wp->window->options, "utf8")) {
1511: /* Print, and do not switch state. */
1512: input_print(ictx);
1513: return (-1);
1514: }
1515: log_debug("%s", __func__);
1516:
1517: utf8_open(&ictx->utf8data, ictx->ch);
1518: return (0);
1519: }
1520:
1521: /* Append to UTF-8 character. */
1522: int
1523: input_utf8_add(struct input_ctx *ictx)
1524: {
1525: log_debug("%s", __func__);
1526:
1527: utf8_append(&ictx->utf8data, ictx->ch);
1528: return (0);
1529: }
1530:
1531: /* Close UTF-8 string. */
1532: int
1533: input_utf8_close(struct input_ctx *ictx)
1534: {
1535: log_debug("%s", __func__);
1536:
1537: utf8_append(&ictx->utf8data, ictx->ch);
1538:
1539: ictx->cell.flags |= GRID_FLAG_UTF8;
1540: screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
1541: ictx->cell.flags &= ~GRID_FLAG_UTF8;
1542:
1543: return (0);
1.1 nicm 1544: }