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