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