Size on split-window is -l not -s. Doh.
[tmux-openbsd.git] / input.c
blob73e0209999fb554e5449dff0e3fd741509382929
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->input_buf = '\0';
816 ictx->input_len = 0;
818 ictx->flags &= ~INPUT_DISCARD;
821 /* Output this character to the screen. */
823 input_print(struct input_ctx *ictx)
825 ictx->cell.data = ictx->ch;
826 screen_write_cell(&ictx->ctx, &ictx->cell, NULL);
828 return (0);
831 /* Collect intermediate string. */
833 input_intermediate(struct input_ctx *ictx)
835 if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
836 ictx->flags |= INPUT_DISCARD;
837 else {
838 ictx->interm_buf[ictx->interm_len++] = ictx->ch;
839 ictx->interm_buf[ictx->interm_len] = '\0';
842 return (0);
845 /* Collect parameter string. */
847 input_parameter(struct input_ctx *ictx)
849 if (ictx->param_len == (sizeof ictx->param_buf) - 1)
850 ictx->flags |= INPUT_DISCARD;
851 else {
852 ictx->param_buf[ictx->param_len++] = ictx->ch;
853 ictx->param_buf[ictx->param_len] = '\0';
856 return (0);
859 /* Collect input string. */
861 input_input(struct input_ctx *ictx)
863 if (ictx->input_len == (sizeof ictx->input_buf) - 1)
864 ictx->flags |= INPUT_DISCARD;
865 else {
866 ictx->input_buf[ictx->input_len++] = ictx->ch;
867 ictx->input_buf[ictx->input_len] = '\0';
870 return (0);
873 /* Execute C0 control sequence. */
875 input_c0_dispatch(struct input_ctx *ictx)
877 struct screen_write_ctx *sctx = &ictx->ctx;
878 struct window_pane *wp = ictx->wp;
879 struct screen *s = sctx->s;
881 log_debug("%s: '%c", __func__, ictx->ch);
883 switch (ictx->ch) {
884 case '\000': /* NUL */
885 break;
886 case '\007': /* BEL */
887 wp->window->flags |= WINDOW_BELL;
888 break;
889 case '\010': /* BS */
890 screen_write_backspace(sctx);
891 break;
892 case '\011': /* HT */
893 /* Don't tab beyond the end of the line. */
894 if (s->cx >= screen_size_x(s) - 1)
895 break;
897 /* Find the next tab point, or use the last column if none. */
898 do {
899 s->cx++;
900 if (bit_test(s->tabs, s->cx))
901 break;
902 } while (s->cx < screen_size_x(s) - 1);
903 break;
904 case '\012': /* LF */
905 case '\013': /* VT */
906 case '\014': /* FF */
907 screen_write_linefeed(sctx, 0);
908 break;
909 case '\015': /* CR */
910 screen_write_carriagereturn(sctx);
911 break;
912 case '\016': /* SO */
913 ictx->cell.attr |= GRID_ATTR_CHARSET;
914 break;
915 case '\017': /* SI */
916 ictx->cell.attr &= ~GRID_ATTR_CHARSET;
917 break;
918 default:
919 log_debug("%s: unknown '%c'", __func__, ictx->ch);
920 break;
923 return (0);
926 /* Execute escape sequence. */
928 input_esc_dispatch(struct input_ctx *ictx)
930 struct screen_write_ctx *sctx = &ictx->ctx;
931 struct screen *s = sctx->s;
932 struct input_table_entry *entry;
934 if (ictx->flags & INPUT_DISCARD)
935 return (0);
936 log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
938 entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
939 sizeof input_esc_table[0], input_table_compare);
940 if (entry == NULL) {
941 log_debug("%s: unknown '%c'", __func__, ictx->ch);
942 return (0);
945 switch (entry->type) {
946 case INPUT_ESC_RIS:
947 memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
948 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
949 ictx->old_cx = 0;
950 ictx->old_cy = 0;
952 screen_reset_tabs(sctx->s);
954 screen_write_scrollregion(sctx, 0, screen_size_y(sctx->s) - 1);
956 screen_write_insertmode(sctx, 0);
957 screen_write_kcursormode(sctx, 0);
958 screen_write_kkeypadmode(sctx, 0);
959 screen_write_mousemode_off(sctx);
961 screen_write_clearscreen(sctx);
962 screen_write_cursormove(sctx, 0, 0);
963 break;
964 case INPUT_ESC_IND:
965 screen_write_linefeed(sctx, 0);
966 break;
967 case INPUT_ESC_NEL:
968 screen_write_carriagereturn(sctx);
969 screen_write_linefeed(sctx, 0);
970 break;
971 case INPUT_ESC_HTS:
972 if (s->cx < screen_size_x(s))
973 bit_set(s->tabs, s->cx);
974 break;
975 case INPUT_ESC_RI:
976 screen_write_reverseindex(sctx);
977 break;
978 case INPUT_ESC_DECKPAM:
979 screen_write_kkeypadmode(sctx, 1);
980 break;
981 case INPUT_ESC_DECKPNM:
982 screen_write_kkeypadmode(sctx, 0);
983 break;
984 case INPUT_ESC_DECSC:
985 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
986 ictx->old_cx = s->cx;
987 ictx->old_cy = s->cy;
988 break;
989 case INPUT_ESC_DECRC:
990 memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
991 screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
992 break;
993 case INPUT_ESC_DECALN:
994 screen_write_alignmenttest(sctx);
995 break;
996 case INPUT_ESC_SCSON_G0:
998 * Not really supported, but fake it up enough for those that
999 * use it to switch character sets (by redefining G0 to
1000 * graphics set, rather than switching to G1).
1002 ictx->cell.attr &= ~GRID_ATTR_CHARSET;
1003 break;
1004 case INPUT_ESC_SCSOFF_G0:
1005 ictx->cell.attr |= GRID_ATTR_CHARSET;
1006 break;
1009 return (0);
1012 /* Execute control sequence. */
1014 input_csi_dispatch(struct input_ctx *ictx)
1016 struct screen_write_ctx *sctx = &ictx->ctx;
1017 struct window_pane *wp = ictx->wp;
1018 struct screen *s = sctx->s;
1019 struct input_table_entry *entry;
1020 int n, m;
1022 if (ictx->flags & INPUT_DISCARD)
1023 return (0);
1024 if (input_split(ictx) != 0)
1025 return (0);
1026 log_debug("%s: '%c' \"%s\" \"%s\"",
1027 __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1029 entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1030 sizeof input_csi_table[0], input_table_compare);
1031 if (entry == NULL) {
1032 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1033 return (0);
1036 switch (entry->type) {
1037 case INPUT_CSI_CBT:
1038 /* Find the previous tab point, n times. */
1039 n = input_get(ictx, 0, 1, 1);
1040 while (s->cx > 0 && n-- > 0) {
1042 s->cx--;
1043 while (s->cx > 0 && !bit_test(s->tabs, s->cx));
1045 break;
1046 case INPUT_CSI_CUB:
1047 screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
1048 break;
1049 case INPUT_CSI_CUD:
1050 screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1051 break;
1052 case INPUT_CSI_CUF:
1053 screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
1054 break;
1055 case INPUT_CSI_CUP:
1056 n = input_get(ictx, 0, 1, 1);
1057 m = input_get(ictx, 1, 1, 1);
1058 screen_write_cursormove(sctx, m - 1, n - 1);
1059 break;
1060 case INPUT_CSI_CUU:
1061 screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1062 break;
1063 case INPUT_CSI_DA:
1064 switch (input_get(ictx, 0, 0, 0)) {
1065 case 0:
1066 input_reply(ictx, "\033[?1;2c");
1067 break;
1068 default:
1069 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1070 break;
1072 break;
1073 case INPUT_CSI_DCH:
1074 screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1));
1075 break;
1076 case INPUT_CSI_DECSTBM:
1077 n = input_get(ictx, 0, 1, 1);
1078 m = input_get(ictx, 1, 1, screen_size_y(s));
1079 screen_write_scrollregion(sctx, n - 1, m - 1);
1080 break;
1081 case INPUT_CSI_DL:
1082 screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1));
1083 break;
1084 case INPUT_CSI_DSR:
1085 switch (input_get(ictx, 0, 0, 0)) {
1086 case 5:
1087 input_reply(ictx, "\033[0n");
1088 break;
1089 case 6:
1090 input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1091 break;
1092 default:
1093 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1094 break;
1096 break;
1097 case INPUT_CSI_ED:
1098 switch (input_get(ictx, 0, 0, 0)) {
1099 case 0:
1100 screen_write_clearendofscreen(sctx);
1101 break;
1102 case 1:
1103 screen_write_clearstartofscreen(sctx);
1104 break;
1105 case 2:
1106 screen_write_clearscreen(sctx);
1107 break;
1108 default:
1109 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1110 break;
1112 break;
1113 case INPUT_CSI_EL:
1114 switch (input_get(ictx, 0, 0, 0)) {
1115 case 0:
1116 screen_write_clearendofline(sctx);
1117 break;
1118 case 1:
1119 screen_write_clearstartofline(sctx);
1120 break;
1121 case 2:
1122 screen_write_clearline(sctx);
1123 break;
1124 default:
1125 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1126 break;
1128 break;
1129 case INPUT_CSI_HPA:
1130 n = input_get(ictx, 0, 1, 1);
1131 screen_write_cursormove(sctx, n - 1, s->cy);
1132 break;
1133 case INPUT_CSI_ICH:
1134 screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1));
1135 break;
1136 case INPUT_CSI_IL:
1137 screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
1138 break;
1139 case INPUT_CSI_RM:
1140 switch (input_get(ictx, 0, 0, -1)) {
1141 case 4: /* IRM */
1142 screen_write_insertmode(&ictx->ctx, 0);
1143 break;
1144 default:
1145 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1146 break;
1148 break;
1149 case INPUT_CSI_RM_PRIVATE:
1150 switch (input_get(ictx, 0, 0, -1)) {
1151 case 1: /* GATM */
1152 screen_write_kcursormode(&ictx->ctx, 0);
1153 break;
1154 case 3: /* DECCOLM */
1155 screen_write_cursormove(&ictx->ctx, 0, 0);
1156 screen_write_clearscreen(&ictx->ctx);
1157 break;
1158 case 25: /* TCEM */
1159 screen_write_cursormode(&ictx->ctx, 0);
1160 break;
1161 case 1000:
1162 case 1001:
1163 case 1002:
1164 case 1003:
1165 screen_write_mousemode_off(&ictx->ctx);
1166 break;
1167 case 1005:
1168 screen_write_utf8mousemode(&ictx->ctx, 0);
1169 break;
1170 case 1049:
1171 window_pane_alternate_off(wp, &ictx->cell);
1172 break;
1173 default:
1174 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1175 break;
1177 break;
1178 case INPUT_CSI_SGR:
1179 input_csi_dispatch_sgr(ictx);
1180 break;
1181 case INPUT_CSI_SM:
1182 switch (input_get(ictx, 0, 0, -1)) {
1183 case 4: /* IRM */
1184 screen_write_insertmode(&ictx->ctx, 1);
1185 break;
1186 default:
1187 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1188 break;
1190 break;
1191 case INPUT_CSI_SM_PRIVATE:
1192 switch (input_get(ictx, 0, 0, -1)) {
1193 case 1: /* GATM */
1194 screen_write_kcursormode(&ictx->ctx, 1);
1195 break;
1196 case 3: /* DECCOLM */
1197 screen_write_cursormove(&ictx->ctx, 0, 0);
1198 screen_write_clearscreen(&ictx->ctx);
1199 break;
1200 case 25: /* TCEM */
1201 screen_write_cursormode(&ictx->ctx, 1);
1202 break;
1203 case 1000:
1204 screen_write_mousemode_on(
1205 &ictx->ctx, MODE_MOUSE_STANDARD);
1206 break;
1207 case 1002:
1208 screen_write_mousemode_on(
1209 &ictx->ctx, MODE_MOUSE_BUTTON);
1210 break;
1211 case 1003:
1212 screen_write_mousemode_on(&ictx->ctx, MODE_MOUSE_ANY);
1213 break;
1214 case 1005:
1215 screen_write_utf8mousemode(&ictx->ctx, 1);
1216 break;
1217 case 1049:
1218 window_pane_alternate_on(wp, &ictx->cell);
1219 break;
1220 default:
1221 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1222 break;
1224 break;
1225 case INPUT_CSI_TBC:
1226 switch (input_get(ictx, 0, 0, 0)) {
1227 case 0:
1228 if (s->cx < screen_size_x(s))
1229 bit_clear(s->tabs, s->cx);
1230 break;
1231 case 3:
1232 bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1233 break;
1234 default:
1235 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1236 break;
1238 break;
1239 case INPUT_CSI_VPA:
1240 n = input_get(ictx, 0, 1, 1);
1241 screen_write_cursormove(sctx, s->cx, n - 1);
1242 break;
1245 return (0);
1248 /* Handle CSI SGR. */
1249 void
1250 input_csi_dispatch_sgr(struct input_ctx *ictx)
1252 struct grid_cell *gc = &ictx->cell;
1253 u_int i;
1254 int n, m;
1255 u_char attr;
1257 if (ictx->param_list_len == 0) {
1258 attr = gc->attr;
1259 memcpy(gc, &grid_default_cell, sizeof *gc);
1260 gc->attr |= (attr & GRID_ATTR_CHARSET);
1261 return;
1264 for (i = 0; i < ictx->param_list_len; i++) {
1265 n = input_get(ictx, i, 0, 0);
1267 if (n == 38 || n == 48) {
1268 i++;
1269 if (input_get(ictx, i, 0, -1) != 5)
1270 continue;
1272 i++;
1273 m = input_get(ictx, i, 0, -1);
1274 if (m == -1) {
1275 if (n == 38) {
1276 gc->flags &= ~GRID_FLAG_FG256;
1277 gc->fg = 8;
1278 } else if (n == 48) {
1279 gc->flags &= ~GRID_FLAG_BG256;
1280 gc->fg = 8;
1283 } else {
1284 if (n == 38) {
1285 gc->flags |= GRID_FLAG_FG256;
1286 gc->fg = m;
1287 } else if (n == 48) {
1288 gc->flags |= GRID_FLAG_BG256;
1289 gc->bg = m;
1292 continue;
1295 switch (n) {
1296 case 0:
1297 case 10:
1298 attr = gc->attr;
1299 memcpy(gc, &grid_default_cell, sizeof *gc);
1300 gc->attr |= (attr & GRID_ATTR_CHARSET);
1301 break;
1302 case 1:
1303 gc->attr |= GRID_ATTR_BRIGHT;
1304 break;
1305 case 2:
1306 gc->attr |= GRID_ATTR_DIM;
1307 break;
1308 case 3:
1309 gc->attr |= GRID_ATTR_ITALICS;
1310 break;
1311 case 4:
1312 gc->attr |= GRID_ATTR_UNDERSCORE;
1313 break;
1314 case 5:
1315 gc->attr |= GRID_ATTR_BLINK;
1316 break;
1317 case 7:
1318 gc->attr |= GRID_ATTR_REVERSE;
1319 break;
1320 case 8:
1321 gc->attr |= GRID_ATTR_HIDDEN;
1322 break;
1323 case 22:
1324 gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1325 break;
1326 case 23:
1327 gc->attr &= ~GRID_ATTR_ITALICS;
1328 break;
1329 case 24:
1330 gc->attr &= ~GRID_ATTR_UNDERSCORE;
1331 break;
1332 case 25:
1333 gc->attr &= ~GRID_ATTR_BLINK;
1334 break;
1335 case 27:
1336 gc->attr &= ~GRID_ATTR_REVERSE;
1337 break;
1338 case 30:
1339 case 31:
1340 case 32:
1341 case 33:
1342 case 34:
1343 case 35:
1344 case 36:
1345 case 37:
1346 gc->flags &= ~GRID_FLAG_FG256;
1347 gc->fg = n - 30;
1348 break;
1349 case 39:
1350 gc->flags &= ~GRID_FLAG_FG256;
1351 gc->fg = 8;
1352 break;
1353 case 40:
1354 case 41:
1355 case 42:
1356 case 43:
1357 case 44:
1358 case 45:
1359 case 46:
1360 case 47:
1361 gc->flags &= ~GRID_FLAG_BG256;
1362 gc->bg = n - 40;
1363 break;
1364 case 49:
1365 gc->flags &= ~GRID_FLAG_BG256;
1366 gc->bg = 8;
1367 break;
1368 case 90:
1369 case 91:
1370 case 92:
1371 case 93:
1372 case 94:
1373 case 95:
1374 case 96:
1375 case 97:
1376 gc->flags &= ~GRID_FLAG_FG256;
1377 gc->fg = n;
1378 break;
1379 case 100:
1380 case 101:
1381 case 102:
1382 case 103:
1383 case 104:
1384 case 105:
1385 case 106:
1386 case 107:
1387 gc->flags &= ~GRID_FLAG_BG256;
1388 gc->bg = n;
1389 break;
1394 /* DCS string started. */
1395 void
1396 input_enter_dcs(struct input_ctx *ictx)
1398 log_debug("%s", __func__);
1400 input_clear(ictx);
1403 /* DCS terminator (ST) received. */
1404 void
1405 input_exit_dcs(unused struct input_ctx *ictx)
1407 log_debug("%s", __func__);
1410 /* OSC string started. */
1411 void
1412 input_enter_osc(struct input_ctx *ictx)
1414 log_debug("%s", __func__);
1416 input_clear(ictx);
1419 /* OSC terminator (ST) received. */
1420 void
1421 input_exit_osc(struct input_ctx *ictx)
1423 if (ictx->flags & INPUT_DISCARD)
1424 return;
1425 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1427 if (ictx->input_len < 2 || ictx->input_buf[1] != ';')
1428 return;
1429 if (ictx->input_buf[0] != '0' && ictx->input_buf[0] != '2')
1430 return;
1432 screen_set_title(ictx->ctx.s, ictx->input_buf + 2);
1433 server_status_window(ictx->wp->window);
1436 /* APC string started. */
1437 void
1438 input_enter_apc(struct input_ctx *ictx)
1440 log_debug("%s", __func__);
1442 input_clear(ictx);
1445 /* APC terminator (ST) received. */
1446 void
1447 input_exit_apc(struct input_ctx *ictx)
1449 if (ictx->flags & INPUT_DISCARD)
1450 return;
1451 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1453 screen_set_title(ictx->ctx.s, ictx->input_buf);
1454 server_status_window(ictx->wp->window);
1457 /* Rename string started. */
1458 void
1459 input_enter_rename(struct input_ctx *ictx)
1461 log_debug("%s", __func__);
1463 input_clear(ictx);
1466 /* Rename terminator (ST) received. */
1467 void
1468 input_exit_rename(struct input_ctx *ictx)
1470 if (ictx->flags & INPUT_DISCARD)
1471 return;
1472 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1474 xfree(ictx->wp->window->name);
1475 ictx->wp->window->name = xstrdup(ictx->input_buf);
1476 options_set_number(&ictx->wp->window->options, "automatic-rename", 0);
1478 server_status_window(ictx->wp->window);
1481 /* Open UTF-8 character. */
1483 input_utf8_open(struct input_ctx *ictx)
1485 if (!options_get_number(&ictx->wp->window->options, "utf8")) {
1486 /* Print, and do not switch state. */
1487 input_print(ictx);
1488 return (-1);
1490 log_debug("%s", __func__);
1492 utf8_open(&ictx->utf8data, ictx->ch);
1493 return (0);
1496 /* Append to UTF-8 character. */
1498 input_utf8_add(struct input_ctx *ictx)
1500 log_debug("%s", __func__);
1502 utf8_append(&ictx->utf8data, ictx->ch);
1503 return (0);
1506 /* Close UTF-8 string. */
1508 input_utf8_close(struct input_ctx *ictx)
1510 log_debug("%s", __func__);
1512 utf8_append(&ictx->utf8data, ictx->ch);
1514 ictx->cell.flags |= GRID_FLAG_UTF8;
1515 screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
1516 ictx->cell.flags &= ~GRID_FLAG_UTF8;
1518 return (0);