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