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