Skip NULL entries in the sessions list when choosing the next session,
[tmux-openbsd.git] / input.c
blobf49591a78b471287d2002cad8cdfff5de9ef0d7c
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;
684 wp->window->flags |= WINDOW_ACTIVITY;
687 * Open the screen. Use NULL wp if there is a mode set as don't want to
688 * update the tty.
690 if (wp->mode == NULL)
691 screen_write_start(&ictx->ctx, wp, &wp->base);
692 else
693 screen_write_start(&ictx->ctx, NULL, &wp->base);
694 ictx->wp = wp;
696 buf = EVBUFFER_DATA(evb);
697 len = EVBUFFER_LENGTH(evb);
698 off = 0;
700 /* Parse the input. */
701 while (off < len) {
702 ictx->ch = buf[off++];
703 log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
705 /* Find the transition. */
706 itr = ictx->state->transitions;
707 while (itr->first != -1 && itr->last != -1) {
708 if (ictx->ch >= itr->first && ictx->ch <= itr->last)
709 break;
710 itr++;
712 if (itr->first == -1 || itr->last == -1) {
713 /* No transition? Eh? */
714 fatalx("No transition from state!");
718 * Execute the handler, if any. Don't switch state if it
719 * returns non-zero.
721 if (itr->handler && itr->handler(ictx) != 0)
722 continue;
724 /* And switch state, if necessary. */
725 if (itr->state) {
726 if (ictx->state->exit != NULL)
727 ictx->state->exit(ictx);
728 ictx->state = itr->state;
729 if (ictx->state->enter != NULL)
730 ictx->state->enter(ictx);
734 /* Close the screen. */
735 screen_write_stop(&ictx->ctx);
737 evbuffer_drain(evb, len);
740 /* Split the parameter list (if any). */
742 input_split(struct input_ctx *ictx)
745 const char *errstr;
746 char *ptr, *out;
747 int n;
749 ictx->param_list_len = 0;
750 if (ictx->param_len == 0)
751 return (0);
753 ptr = ictx->param_buf;
754 while ((out = strsep(&ptr, ";")) != NULL) {
755 if (*out == '\0')
756 n = -1;
757 else {
758 n = strtonum(out, 0, INT_MAX, &errstr);
759 if (errstr != NULL)
760 return (-1);
763 ictx->param_list[ictx->param_list_len++] = n;
764 if (ictx->param_list_len == nitems(ictx->param_list))
765 return (-1);
768 return (0);
771 /* Get an argument or return default value..*/
773 input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
775 int retval;
777 if (validx >= ictx->param_list_len)
778 return (defval);
780 retval = ictx->param_list[validx];
781 if (retval == -1)
782 return (defval);
783 if (retval < minval)
784 return (minval);
785 return (retval);
788 /* Reply to terminal query. */
789 void
790 input_reply(struct input_ctx *ictx, const char *fmt, ...)
792 va_list ap;
793 char *reply;
795 va_start(ap, fmt);
796 vasprintf(&reply, fmt, ap);
797 va_end(ap);
799 bufferevent_write(ictx->wp->event, reply, strlen(reply));
800 xfree(reply);
803 /* Clear saved state. */
804 void
805 input_clear(struct input_ctx *ictx)
807 *ictx->interm_buf = '\0';
808 ictx->interm_len = 0;
810 *ictx->param_buf = '\0';
811 ictx->param_len = 0;
813 ictx->flags &= ~INPUT_DISCARD;
816 /* Output this character to the screen. */
818 input_print(struct input_ctx *ictx)
820 ictx->cell.data = ictx->ch;
821 screen_write_cell(&ictx->ctx, &ictx->cell, NULL);
823 return (0);
826 /* Collect intermediate string. */
828 input_intermediate(struct input_ctx *ictx)
830 if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
831 ictx->flags |= INPUT_DISCARD;
832 else {
833 ictx->interm_buf[ictx->interm_len++] = ictx->ch;
834 ictx->interm_buf[ictx->interm_len] = '\0';
837 return (0);
840 /* Collect parameter string. */
842 input_parameter(struct input_ctx *ictx)
844 if (ictx->param_len == (sizeof ictx->param_buf) - 1)
845 ictx->flags |= INPUT_DISCARD;
846 else {
847 ictx->param_buf[ictx->param_len++] = ictx->ch;
848 ictx->param_buf[ictx->param_len] = '\0';
851 return (0);
854 /* Collect input string. */
856 input_input(struct input_ctx *ictx)
858 if (ictx->input_len == (sizeof ictx->input_buf) - 1)
859 ictx->flags |= INPUT_DISCARD;
860 else {
861 ictx->input_buf[ictx->input_len++] = ictx->ch;
862 ictx->input_buf[ictx->input_len] = '\0';
865 return (0);
868 /* Execute C0 control sequence. */
870 input_c0_dispatch(struct input_ctx *ictx)
872 struct screen_write_ctx *sctx = &ictx->ctx;
873 struct window_pane *wp = ictx->wp;
874 struct screen *s = sctx->s;
876 log_debug("%s: '%c", __func__, ictx->ch);
878 switch (ictx->ch) {
879 case '\000': /* NUL */
880 break;
881 case '\007': /* BEL */
882 wp->window->flags |= WINDOW_BELL;
883 break;
884 case '\010': /* BS */
885 screen_write_backspace(sctx);
886 break;
887 case '\011': /* HT */
888 /* Don't tab beyond the end of the line. */
889 if (s->cx >= screen_size_x(s) - 1)
890 break;
892 /* Find the next tab point, or use the last column if none. */
893 do {
894 s->cx++;
895 if (bit_test(s->tabs, s->cx))
896 break;
897 } while (s->cx < screen_size_x(s) - 1);
898 break;
899 case '\012': /* LF */
900 case '\013': /* VT */
901 case '\014': /* FF */
902 screen_write_linefeed(sctx, 0);
903 break;
904 case '\015': /* CR */
905 screen_write_carriagereturn(sctx);
906 break;
907 case '\016': /* SO */
908 ictx->cell.attr |= GRID_ATTR_CHARSET;
909 break;
910 case '\017': /* SI */
911 ictx->cell.attr &= ~GRID_ATTR_CHARSET;
912 break;
913 default:
914 log_debug("%s: unknown '%c'", __func__, ictx->ch);
915 break;
918 return (0);
921 /* Execute escape sequence. */
923 input_esc_dispatch(struct input_ctx *ictx)
925 struct screen_write_ctx *sctx = &ictx->ctx;
926 struct screen *s = sctx->s;
927 struct input_table_entry *entry;
929 if (ictx->flags & INPUT_DISCARD)
930 return (0);
931 log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
933 entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
934 sizeof input_esc_table[0], input_table_compare);
935 if (entry == NULL) {
936 log_debug("%s: unknown '%c'", __func__, ictx->ch);
937 return (0);
940 switch (entry->type) {
941 case INPUT_ESC_RIS:
942 memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
943 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
944 ictx->old_cx = 0;
945 ictx->old_cy = 0;
947 screen_reset_tabs(sctx->s);
949 screen_write_scrollregion(sctx, 0, screen_size_y(sctx->s) - 1);
951 screen_write_insertmode(sctx, 0);
952 screen_write_kcursormode(sctx, 0);
953 screen_write_kkeypadmode(sctx, 0);
954 screen_write_mousemode(sctx, 0);
956 screen_write_clearscreen(sctx);
957 screen_write_cursormove(sctx, 0, 0);
958 break;
959 case INPUT_ESC_IND:
960 screen_write_linefeed(sctx, 0);
961 break;
962 case INPUT_ESC_NEL:
963 screen_write_carriagereturn(sctx);
964 screen_write_linefeed(sctx, 0);
965 break;
966 case INPUT_ESC_HTS:
967 if (s->cx < screen_size_x(s))
968 bit_set(s->tabs, s->cx);
969 break;
970 case INPUT_ESC_RI:
971 screen_write_reverseindex(sctx);
972 break;
973 case INPUT_ESC_DECKPAM:
974 screen_write_kkeypadmode(sctx, 1);
975 break;
976 case INPUT_ESC_DECKPNM:
977 screen_write_kkeypadmode(sctx, 0);
978 break;
979 case INPUT_ESC_DECSC:
980 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
981 ictx->old_cx = s->cx;
982 ictx->old_cy = s->cy;
983 break;
984 case INPUT_ESC_DECRC:
985 memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
986 screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
987 break;
988 case INPUT_ESC_DECALN:
989 screen_write_alignmenttest(sctx);
990 break;
991 case INPUT_ESC_SCSON_G0:
993 * Not really supported, but fake it up enough for those that
994 * use it to switch character sets (by redefining G0 to
995 * graphics set, rather than switching to G1).
997 ictx->cell.attr &= ~GRID_ATTR_CHARSET;
998 break;
999 case INPUT_ESC_SCSOFF_G0:
1000 ictx->cell.attr |= GRID_ATTR_CHARSET;
1001 break;
1004 return (0);
1007 /* Execute control sequence. */
1009 input_csi_dispatch(struct input_ctx *ictx)
1011 struct screen_write_ctx *sctx = &ictx->ctx;
1012 struct window_pane *wp = ictx->wp;
1013 struct screen *s = sctx->s;
1014 struct input_table_entry *entry;
1015 int n, m;
1017 if (ictx->flags & INPUT_DISCARD)
1018 return (0);
1019 if (input_split(ictx) != 0)
1020 return (0);
1021 log_debug("%s: '%c' \"%s\" \"%s\"",
1022 __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1024 entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1025 sizeof input_csi_table[0], input_table_compare);
1026 if (entry == NULL) {
1027 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1028 return (0);
1031 switch (entry->type) {
1032 case INPUT_CSI_CBT:
1033 /* Find the previous tab point, n times. */
1034 n = input_get(ictx, 0, 1, 1);
1035 while (s->cx > 0 && n-- > 0) {
1037 s->cx--;
1038 while (s->cx > 0 && !bit_test(s->tabs, s->cx));
1040 break;
1041 case INPUT_CSI_CUB:
1042 screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
1043 break;
1044 case INPUT_CSI_CUD:
1045 screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1046 break;
1047 case INPUT_CSI_CUF:
1048 screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
1049 break;
1050 case INPUT_CSI_CUP:
1051 n = input_get(ictx, 0, 1, 1);
1052 m = input_get(ictx, 1, 1, 1);
1053 screen_write_cursormove(sctx, m - 1, n - 1);
1054 break;
1055 case INPUT_CSI_CUU:
1056 screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1057 break;
1058 case INPUT_CSI_DA:
1059 switch (input_get(ictx, 0, 0, 0)) {
1060 case 0:
1061 input_reply(ictx, "\033[?1;2c");
1062 break;
1063 default:
1064 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1065 break;
1067 break;
1068 case INPUT_CSI_DCH:
1069 screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1));
1070 break;
1071 case INPUT_CSI_DECSTBM:
1072 n = input_get(ictx, 0, 1, 1);
1073 m = input_get(ictx, 1, 1, screen_size_y(s));
1074 screen_write_scrollregion(sctx, n - 1, m - 1);
1075 break;
1076 case INPUT_CSI_DL:
1077 screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1));
1078 break;
1079 case INPUT_CSI_DSR:
1080 switch (input_get(ictx, 0, 0, 0)) {
1081 case 5:
1082 input_reply(ictx, "\033[0n");
1083 break;
1084 case 6:
1085 input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1086 break;
1087 default:
1088 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1089 break;
1091 break;
1092 case INPUT_CSI_ED:
1093 switch (input_get(ictx, 0, 0, 0)) {
1094 case 0:
1095 screen_write_clearendofscreen(sctx);
1096 break;
1097 case 1:
1098 screen_write_clearstartofscreen(sctx);
1099 break;
1100 case 2:
1101 screen_write_clearscreen(sctx);
1102 break;
1103 default:
1104 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1105 break;
1107 break;
1108 case INPUT_CSI_EL:
1109 switch (input_get(ictx, 0, 0, 0)) {
1110 case 0:
1111 screen_write_clearendofline(sctx);
1112 break;
1113 case 1:
1114 screen_write_clearstartofline(sctx);
1115 break;
1116 case 2:
1117 screen_write_clearline(sctx);
1118 break;
1119 default:
1120 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1121 break;
1123 break;
1124 case INPUT_CSI_HPA:
1125 n = input_get(ictx, 0, 1, 1);
1126 screen_write_cursormove(sctx, n - 1, s->cy);
1127 break;
1128 case INPUT_CSI_ICH:
1129 screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1));
1130 break;
1131 case INPUT_CSI_IL:
1132 screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
1133 break;
1134 case INPUT_CSI_RM:
1135 switch (input_get(ictx, 0, 0, -1)) {
1136 case 4: /* IRM */
1137 screen_write_insertmode(&ictx->ctx, 0);
1138 break;
1139 default:
1140 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1141 break;
1143 break;
1144 case INPUT_CSI_RM_PRIVATE:
1145 switch (input_get(ictx, 0, 0, -1)) {
1146 case 1: /* GATM */
1147 screen_write_kcursormode(&ictx->ctx, 0);
1148 break;
1149 case 3: /* DECCOLM */
1150 screen_write_cursormove(&ictx->ctx, 0, 0);
1151 screen_write_clearscreen(&ictx->ctx);
1152 break;
1153 case 25: /* TCEM */
1154 screen_write_cursormode(&ictx->ctx, 0);
1155 break;
1156 case 1000:
1157 screen_write_mousemode(&ictx->ctx, 0);
1158 break;
1159 case 1049:
1160 window_pane_alternate_off(wp, &ictx->cell);
1161 break;
1162 default:
1163 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1164 break;
1166 break;
1167 case INPUT_CSI_SGR:
1168 input_csi_dispatch_sgr(ictx);
1169 break;
1170 case INPUT_CSI_SM:
1171 switch (input_get(ictx, 0, 0, -1)) {
1172 case 4: /* IRM */
1173 screen_write_insertmode(&ictx->ctx, 1);
1174 break;
1175 default:
1176 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1177 break;
1179 break;
1180 case INPUT_CSI_SM_PRIVATE:
1181 switch (input_get(ictx, 0, 0, -1)) {
1182 case 1: /* GATM */
1183 screen_write_kcursormode(&ictx->ctx, 1);
1184 break;
1185 case 3: /* DECCOLM */
1186 screen_write_cursormove(&ictx->ctx, 0, 0);
1187 screen_write_clearscreen(&ictx->ctx);
1188 break;
1189 case 25: /* TCEM */
1190 screen_write_cursormode(&ictx->ctx, 1);
1191 break;
1192 case 1000:
1193 screen_write_mousemode(&ictx->ctx, 1);
1194 break;
1195 case 1049:
1196 window_pane_alternate_on(wp, &ictx->cell);
1197 break;
1198 default:
1199 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1200 break;
1202 break;
1203 case INPUT_CSI_TBC:
1204 switch (input_get(ictx, 0, 0, 0)) {
1205 case 0:
1206 if (s->cx < screen_size_x(s))
1207 bit_clear(s->tabs, s->cx);
1208 break;
1209 case 3:
1210 bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1211 break;
1212 default:
1213 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1214 break;
1216 break;
1217 case INPUT_CSI_VPA:
1218 n = input_get(ictx, 0, 1, 1);
1219 screen_write_cursormove(sctx, s->cx, n - 1);
1220 break;
1223 return (0);
1226 /* Handle CSI SGR. */
1227 void
1228 input_csi_dispatch_sgr(struct input_ctx *ictx)
1230 struct grid_cell *gc = &ictx->cell;
1231 u_int i;
1232 int n, m;
1233 u_char attr;
1235 if (ictx->param_list_len == 0) {
1236 attr = gc->attr;
1237 memcpy(gc, &grid_default_cell, sizeof *gc);
1238 gc->attr |= (attr & GRID_ATTR_CHARSET);
1239 return;
1242 for (i = 0; i < ictx->param_list_len; i++) {
1243 n = input_get(ictx, i, 0, 0);
1245 if (n == 38 || n == 48) {
1246 i++;
1247 if (input_get(ictx, i, 0, -1) != 5)
1248 continue;
1250 i++;
1251 m = input_get(ictx, i, 0, -1);
1252 if (m == -1) {
1253 if (n == 38) {
1254 gc->flags &= ~GRID_FLAG_FG256;
1255 gc->fg = 8;
1256 } else if (n == 48) {
1257 gc->flags &= ~GRID_FLAG_BG256;
1258 gc->fg = 8;
1261 } else {
1262 if (n == 38) {
1263 gc->flags |= GRID_FLAG_FG256;
1264 gc->fg = m;
1265 } else if (n == 48) {
1266 gc->flags |= GRID_FLAG_BG256;
1267 gc->bg = m;
1270 continue;
1273 switch (n) {
1274 case 0:
1275 case 10:
1276 attr = gc->attr;
1277 memcpy(gc, &grid_default_cell, sizeof *gc);
1278 gc->attr |= (attr & GRID_ATTR_CHARSET);
1279 break;
1280 case 1:
1281 gc->attr |= GRID_ATTR_BRIGHT;
1282 break;
1283 case 2:
1284 gc->attr |= GRID_ATTR_DIM;
1285 break;
1286 case 3:
1287 gc->attr |= GRID_ATTR_ITALICS;
1288 break;
1289 case 4:
1290 gc->attr |= GRID_ATTR_UNDERSCORE;
1291 break;
1292 case 5:
1293 gc->attr |= GRID_ATTR_BLINK;
1294 break;
1295 case 7:
1296 gc->attr |= GRID_ATTR_REVERSE;
1297 break;
1298 case 8:
1299 gc->attr |= GRID_ATTR_HIDDEN;
1300 break;
1301 case 22:
1302 gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1303 break;
1304 case 23:
1305 gc->attr &= ~GRID_ATTR_ITALICS;
1306 break;
1307 case 24:
1308 gc->attr &= ~GRID_ATTR_UNDERSCORE;
1309 break;
1310 case 25:
1311 gc->attr &= ~GRID_ATTR_BLINK;
1312 break;
1313 case 27:
1314 gc->attr &= ~GRID_ATTR_REVERSE;
1315 break;
1316 case 30:
1317 case 31:
1318 case 32:
1319 case 33:
1320 case 34:
1321 case 35:
1322 case 36:
1323 case 37:
1324 gc->flags &= ~GRID_FLAG_FG256;
1325 gc->fg = n - 30;
1326 break;
1327 case 39:
1328 gc->flags &= ~GRID_FLAG_FG256;
1329 gc->fg = 8;
1330 break;
1331 case 40:
1332 case 41:
1333 case 42:
1334 case 43:
1335 case 44:
1336 case 45:
1337 case 46:
1338 case 47:
1339 gc->flags &= ~GRID_FLAG_BG256;
1340 gc->bg = n - 40;
1341 break;
1342 case 49:
1343 gc->flags &= ~GRID_FLAG_BG256;
1344 gc->bg = 8;
1345 break;
1346 case 90:
1347 case 91:
1348 case 92:
1349 case 93:
1350 case 94:
1351 case 95:
1352 case 96:
1353 case 97:
1354 gc->flags &= ~GRID_FLAG_FG256;
1355 gc->fg = n;
1356 break;
1357 case 100:
1358 case 101:
1359 case 102:
1360 case 103:
1361 case 104:
1362 case 105:
1363 case 106:
1364 case 107:
1365 gc->flags &= ~GRID_FLAG_BG256;
1366 gc->bg = n;
1367 break;
1372 /* DCS string started. */
1373 void
1374 input_enter_dcs(struct input_ctx *ictx)
1376 log_debug("%s", __func__);
1378 ictx->input_len = 0;
1381 /* DCS terminator (ST) received. */
1382 void
1383 input_exit_dcs(unused struct input_ctx *ictx)
1385 log_debug("%s", __func__);
1388 /* OSC string started. */
1389 void
1390 input_enter_osc(struct input_ctx *ictx)
1392 log_debug("%s", __func__);
1394 ictx->input_len = 0;
1397 /* OSC terminator (ST) received. */
1398 void
1399 input_exit_osc(struct input_ctx *ictx)
1401 if (ictx->flags & INPUT_DISCARD)
1402 return;
1403 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1405 if (ictx->input_len < 2 || ictx->input_buf[1] != ';')
1406 return;
1407 if (ictx->input_buf[0] != '0' && ictx->input_buf[0] != '2')
1408 return;
1410 screen_set_title(ictx->ctx.s, ictx->input_buf + 2);
1411 server_status_window(ictx->wp->window);
1414 /* APC string started. */
1415 void
1416 input_enter_apc(struct input_ctx *ictx)
1418 log_debug("%s", __func__);
1420 ictx->input_len = 0;
1423 /* APC terminator (ST) received. */
1424 void
1425 input_exit_apc(struct input_ctx *ictx)
1427 if (ictx->flags & INPUT_DISCARD)
1428 return;
1429 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1431 screen_set_title(ictx->ctx.s, ictx->input_buf);
1432 server_status_window(ictx->wp->window);
1435 /* Rename string started. */
1436 void
1437 input_enter_rename(struct input_ctx *ictx)
1439 log_debug("%s", __func__);
1441 ictx->input_len = 0;
1444 /* Rename terminator (ST) received. */
1445 void
1446 input_exit_rename(struct input_ctx *ictx)
1448 if (ictx->flags & INPUT_DISCARD)
1449 return;
1450 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1452 xfree(ictx->wp->window->name);
1453 ictx->wp->window->name = xstrdup(ictx->input_buf);
1454 options_set_number(&ictx->wp->window->options, "automatic-rename", 0);
1456 server_status_window(ictx->wp->window);
1459 /* Open UTF-8 character. */
1461 input_utf8_open(struct input_ctx *ictx)
1463 if (!options_get_number(&ictx->wp->window->options, "utf8")) {
1464 /* Print, and do not switch state. */
1465 input_print(ictx);
1466 return (-1);
1468 log_debug("%s", __func__);
1470 utf8_open(&ictx->utf8data, ictx->ch);
1471 return (0);
1474 /* Append to UTF-8 character. */
1476 input_utf8_add(struct input_ctx *ictx)
1478 log_debug("%s", __func__);
1480 utf8_append(&ictx->utf8data, ictx->ch);
1481 return (0);
1484 /* Close UTF-8 string. */
1486 input_utf8_close(struct input_ctx *ictx)
1488 log_debug("%s", __func__);
1490 utf8_append(&ictx->utf8data, ictx->ch);
1492 ictx->cell.flags |= GRID_FLAG_UTF8;
1493 screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
1494 ictx->cell.flags &= ~GRID_FLAG_UTF8;
1496 return (0);