blob: 88e633fe83df4f2a1ff2b336e9f247e999ced83d [file] [log] [blame] [raw]
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
Nicholas Marriott35876ea2009-06-01 22:58:49 +000021#include <stdlib.h>
22#include <string.h>
23
24#include "tmux.h"
25
Nicholas Marriott4baafd82010-03-22 19:02:54 +000026/*
27 * Based on the description by Paul Williams at:
28 *
29 * http://vt100.net/emu/dec_ansi_parser
30 *
31 * With the following changes:
32 *
33 * - 7-bit only.
34 *
35 * - Support for UTF-8.
36 *
37 * - OSC (but not APC) may be terminated by \007 as well as ST.
38 *
39 * - A state for APC similar to OSC. Some terminals appear to use this to set
40 * the title.
41 *
42 * - A state for the screen \033k...\033\\ sequence to rename a window. This is
43 * pretty stupid but not supporting it is more trouble than it is worth.
Nicholas Marriott79e30da2011-03-07 23:46:27 +000044 *
45 * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
46 * be passed to the underlying teminal(s).
Nicholas Marriott4baafd82010-03-22 19:02:54 +000047 */
Nicholas Marriott35876ea2009-06-01 22:58:49 +000048
Nicholas Marriott4baafd82010-03-22 19:02:54 +000049/* Helper functions. */
50int input_split(struct input_ctx *);
51int input_get(struct input_ctx *, u_int, int, int);
52void input_reply(struct input_ctx *, const char *, ...);
Nicholas Marriott35876ea2009-06-01 22:58:49 +000053
Nicholas Marriott4baafd82010-03-22 19:02:54 +000054/* Transition entry/exit handlers. */
55void input_clear(struct input_ctx *);
Nicholas Marriott4baafd82010-03-22 19:02:54 +000056void input_enter_osc(struct input_ctx *);
57void input_exit_osc(struct input_ctx *);
58void input_enter_apc(struct input_ctx *);
59void input_exit_apc(struct input_ctx *);
60void input_enter_rename(struct input_ctx *);
61void input_exit_rename(struct input_ctx *);
Nicholas Marriott35876ea2009-06-01 22:58:49 +000062
Nicholas Marriott4baafd82010-03-22 19:02:54 +000063/* Input state handlers. */
64int input_print(struct input_ctx *);
65int input_intermediate(struct input_ctx *);
66int input_parameter(struct input_ctx *);
67int input_input(struct input_ctx *);
68int input_c0_dispatch(struct input_ctx *);
69int input_esc_dispatch(struct input_ctx *);
70int input_csi_dispatch(struct input_ctx *);
71void input_csi_dispatch_sgr(struct input_ctx *);
Nicholas Marriott79e30da2011-03-07 23:46:27 +000072int input_dcs_dispatch(struct input_ctx *);
Nicholas Marriott4baafd82010-03-22 19:02:54 +000073int input_utf8_open(struct input_ctx *);
74int input_utf8_add(struct input_ctx *);
75int input_utf8_close(struct input_ctx *);
Nicholas Marriott35876ea2009-06-01 22:58:49 +000076
Nicholas Marriott4baafd82010-03-22 19:02:54 +000077/* Command table comparison function. */
78int input_table_compare(const void *, const void *);
Nicholas Marriott35876ea2009-06-01 22:58:49 +000079
Nicholas Marriott4baafd82010-03-22 19:02:54 +000080/* Command table entry. */
81struct input_table_entry {
82 int ch;
83 const char *interm;
84 int type;
Nicholas Marriott35876ea2009-06-01 22:58:49 +000085};
86
Nicholas Marriott4baafd82010-03-22 19:02:54 +000087/* Escape commands. */
88enum input_esc_type {
89 INPUT_ESC_DECALN,
90 INPUT_ESC_DECKPAM,
91 INPUT_ESC_DECKPNM,
92 INPUT_ESC_DECRC,
93 INPUT_ESC_DECSC,
94 INPUT_ESC_HTS,
95 INPUT_ESC_IND,
96 INPUT_ESC_NEL,
97 INPUT_ESC_RI,
98 INPUT_ESC_RIS,
99 INPUT_ESC_SCSOFF_G0,
100 INPUT_ESC_SCSON_G0,
101};
102
103/* Escape command table. */
104const struct input_table_entry input_esc_table[] = {
105 { '0', "(", INPUT_ESC_SCSOFF_G0 },
106 { '7', "", INPUT_ESC_DECSC },
107 { '8', "", INPUT_ESC_DECRC },
108 { '8', "#", INPUT_ESC_DECALN },
109 { '=', "", INPUT_ESC_DECKPAM },
110 { '>', "", INPUT_ESC_DECKPNM },
111 { 'B', "(", INPUT_ESC_SCSON_G0 },
112 { 'D', "", INPUT_ESC_IND },
113 { 'E', "", INPUT_ESC_NEL },
114 { 'H', "", INPUT_ESC_HTS },
115 { 'M', "", INPUT_ESC_RI },
116 { 'c', "", INPUT_ESC_RIS },
117};
118
119/* Control (CSI) commands. */
120enum input_csi_type {
121 INPUT_CSI_CBT,
Nicholas Marriott92aef642011-12-29 08:06:24 +0000122 INPUT_CSI_CNL,
123 INPUT_CSI_CPL,
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000124 INPUT_CSI_CUB,
125 INPUT_CSI_CUD,
126 INPUT_CSI_CUF,
127 INPUT_CSI_CUP,
128 INPUT_CSI_CUU,
129 INPUT_CSI_DA,
Nicholas Marriott523ed382012-03-15 10:05:49 +0000130 INPUT_CSI_DA_TWO,
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000131 INPUT_CSI_DCH,
Nicholas Marriott3ea5e062011-05-20 19:17:39 +0000132 INPUT_CSI_DECSCUSR,
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000133 INPUT_CSI_DECSTBM,
134 INPUT_CSI_DL,
135 INPUT_CSI_DSR,
136 INPUT_CSI_ED,
137 INPUT_CSI_EL,
138 INPUT_CSI_HPA,
139 INPUT_CSI_ICH,
140 INPUT_CSI_IL,
Nicholas Marriottd377a682011-12-27 14:06:19 +0000141 INPUT_CSI_RCP,
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000142 INPUT_CSI_RM,
143 INPUT_CSI_RM_PRIVATE,
Nicholas Marriottd377a682011-12-27 14:06:19 +0000144 INPUT_CSI_SCP,
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000145 INPUT_CSI_SGR,
146 INPUT_CSI_SM,
147 INPUT_CSI_SM_PRIVATE,
148 INPUT_CSI_TBC,
149 INPUT_CSI_VPA,
150};
151
152/* Control (CSI) command table. */
153const struct input_table_entry input_csi_table[] = {
154 { '@', "", INPUT_CSI_ICH },
155 { 'A', "", INPUT_CSI_CUU },
156 { 'B', "", INPUT_CSI_CUD },
157 { 'C', "", INPUT_CSI_CUF },
158 { 'D', "", INPUT_CSI_CUB },
Nicholas Marriott92aef642011-12-29 08:06:24 +0000159 { 'E', "", INPUT_CSI_CNL },
160 { 'F', "", INPUT_CSI_CPL },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000161 { 'G', "", INPUT_CSI_HPA },
162 { 'H', "", INPUT_CSI_CUP },
163 { 'J', "", INPUT_CSI_ED },
164 { 'K', "", INPUT_CSI_EL },
165 { 'L', "", INPUT_CSI_IL },
166 { 'M', "", INPUT_CSI_DL },
167 { 'P', "", INPUT_CSI_DCH },
168 { 'Z', "", INPUT_CSI_CBT },
169 { 'c', "", INPUT_CSI_DA },
Nicholas Marriott523ed382012-03-15 10:05:49 +0000170 { 'c', ">", INPUT_CSI_DA_TWO },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000171 { 'd', "", INPUT_CSI_VPA },
172 { 'f', "", INPUT_CSI_CUP },
173 { 'g', "", INPUT_CSI_TBC },
174 { 'h', "", INPUT_CSI_SM },
175 { 'h', "?", INPUT_CSI_SM_PRIVATE },
176 { 'l', "", INPUT_CSI_RM },
177 { 'l', "?", INPUT_CSI_RM_PRIVATE },
178 { 'm', "", INPUT_CSI_SGR },
179 { 'n', "", INPUT_CSI_DSR },
Nicholas Marriott3ea5e062011-05-20 19:17:39 +0000180 { 'q', " ", INPUT_CSI_DECSCUSR },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000181 { 'r', "", INPUT_CSI_DECSTBM },
Nicholas Marriottd377a682011-12-27 14:06:19 +0000182 { 's', "", INPUT_CSI_SCP },
183 { 'u', "", INPUT_CSI_RCP },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000184};
185
186/* Input transition. */
187struct input_transition {
188 int first;
189 int last;
190
191 int (*handler)(struct input_ctx *);
192 const struct input_state *state;
193};
194
195/* Input state. */
196struct input_state {
197 const char *name;
198 void (*enter)(struct input_ctx *);
199 void (*exit)(struct input_ctx *);
200 const struct input_transition *transitions;
201};
202
203/* State transitions available from all states. */
204#define INPUT_STATE_ANYWHERE \
205 { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
206 { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
207 { 0x1b, 0x1b, NULL, &input_state_esc_enter }
208
209/* Forward declarations of state tables. */
210const struct input_transition input_state_ground_table[];
211const struct input_transition input_state_esc_enter_table[];
212const struct input_transition input_state_esc_intermediate_table[];
213const struct input_transition input_state_csi_enter_table[];
214const struct input_transition input_state_csi_parameter_table[];
215const struct input_transition input_state_csi_intermediate_table[];
216const struct input_transition input_state_csi_ignore_table[];
217const struct input_transition input_state_dcs_enter_table[];
218const struct input_transition input_state_dcs_parameter_table[];
219const struct input_transition input_state_dcs_intermediate_table[];
220const struct input_transition input_state_dcs_handler_table[];
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000221const struct input_transition input_state_dcs_escape_table[];
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000222const struct input_transition input_state_dcs_ignore_table[];
223const struct input_transition input_state_osc_string_table[];
224const struct input_transition input_state_apc_string_table[];
225const struct input_transition input_state_rename_string_table[];
226const struct input_transition input_state_consume_st_table[];
227const struct input_transition input_state_utf8_three_table[];
228const struct input_transition input_state_utf8_two_table[];
229const struct input_transition input_state_utf8_one_table[];
230
231/* ground state definition. */
232const struct input_state input_state_ground = {
233 "ground",
234 NULL, NULL,
235 input_state_ground_table
236};
237
238/* esc_enter state definition. */
239const struct input_state input_state_esc_enter = {
240 "esc_enter",
241 input_clear, NULL,
242 input_state_esc_enter_table
243};
244
245/* esc_intermediate state definition. */
246const struct input_state input_state_esc_intermediate = {
247 "esc_intermediate",
248 NULL, NULL,
249 input_state_esc_intermediate_table
250};
251
252/* csi_enter state definition. */
253const struct input_state input_state_csi_enter = {
254 "csi_enter",
255 input_clear, NULL,
256 input_state_csi_enter_table
257};
258
259/* csi_parameter state definition. */
260const struct input_state input_state_csi_parameter = {
261 "csi_parameter",
262 NULL, NULL,
263 input_state_csi_parameter_table
264};
265
266/* csi_intermediate state definition. */
267const struct input_state input_state_csi_intermediate = {
268 "csi_intermediate",
269 NULL, NULL,
270 input_state_csi_intermediate_table
271};
272
273/* csi_ignore state definition. */
274const struct input_state input_state_csi_ignore = {
275 "csi_ignore",
276 NULL, NULL,
277 input_state_csi_ignore_table
278};
279
280/* dcs_enter state definition. */
281const struct input_state input_state_dcs_enter = {
282 "dcs_enter",
283 input_clear, NULL,
284 input_state_dcs_enter_table
285};
286
287/* dcs_parameter state definition. */
288const struct input_state input_state_dcs_parameter = {
289 "dcs_parameter",
290 NULL, NULL,
291 input_state_dcs_parameter_table
292};
293
294/* dcs_intermediate state definition. */
295const struct input_state input_state_dcs_intermediate = {
296 "dcs_intermediate",
297 NULL, NULL,
298 input_state_dcs_intermediate_table
299};
300
301/* dcs_handler state definition. */
302const struct input_state input_state_dcs_handler = {
303 "dcs_handler",
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000304 NULL, NULL,
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000305 input_state_dcs_handler_table
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000306};
307
308/* dcs_escape state definition. */
309const struct input_state input_state_dcs_escape = {
310 "dcs_escape",
311 NULL, NULL,
312 input_state_dcs_escape_table
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000313};
314
315/* dcs_ignore state definition. */
316const struct input_state input_state_dcs_ignore = {
317 "dcs_ignore",
318 NULL, NULL,
319 input_state_dcs_ignore_table
320};
321
322/* osc_string state definition. */
323const struct input_state input_state_osc_string = {
324 "osc_string",
325 input_enter_osc, input_exit_osc,
326 input_state_osc_string_table
327};
328
329/* apc_string state definition. */
330const struct input_state input_state_apc_string = {
331 "apc_string",
332 input_enter_apc, input_exit_apc,
333 input_state_apc_string_table
334};
335
336/* rename_string state definition. */
337const struct input_state input_state_rename_string = {
338 "rename_string",
339 input_enter_rename, input_exit_rename,
340 input_state_rename_string_table
341};
342
343/* consume_st state definition. */
344const struct input_state input_state_consume_st = {
345 "consume_st",
346 NULL, NULL,
347 input_state_consume_st_table
348};
349
350/* utf8_three state definition. */
351const struct input_state input_state_utf8_three = {
352 "utf8_three",
353 NULL, NULL,
354 input_state_utf8_three_table
355};
356
357/* utf8_two state definition. */
358const struct input_state input_state_utf8_two = {
359 "utf8_two",
360 NULL, NULL,
361 input_state_utf8_two_table
362};
363
364/* utf8_one state definition. */
365const struct input_state input_state_utf8_one = {
366 "utf8_one",
367 NULL, NULL,
368 input_state_utf8_one_table
369};
370
371/* ground state table. */
372const struct input_transition input_state_ground_table[] = {
373 INPUT_STATE_ANYWHERE,
374
375 { 0x00, 0x17, input_c0_dispatch, NULL },
376 { 0x19, 0x19, input_c0_dispatch, NULL },
377 { 0x1c, 0x1f, input_c0_dispatch, NULL },
378 { 0x20, 0x7e, input_print, NULL },
379 { 0x7f, 0x7f, NULL, NULL },
380 { 0x80, 0xc1, input_print, NULL },
381 { 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one },
382 { 0xe0, 0xef, input_utf8_open, &input_state_utf8_two },
383 { 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three },
384 { 0xf5, 0xff, input_print, NULL },
385
386 { -1, -1, NULL, NULL }
387};
388
389/* esc_enter state table. */
390const struct input_transition input_state_esc_enter_table[] = {
391 INPUT_STATE_ANYWHERE,
392
393 { 0x00, 0x17, input_c0_dispatch, NULL },
394 { 0x19, 0x19, input_c0_dispatch, NULL },
395 { 0x1c, 0x1f, input_c0_dispatch, NULL },
396 { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
397 { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
398 { 0x50, 0x50, NULL, &input_state_dcs_enter },
399 { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
400 { 0x58, 0x58, NULL, &input_state_consume_st },
401 { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
402 { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
403 { 0x5b, 0x5b, NULL, &input_state_csi_enter },
404 { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
405 { 0x5d, 0x5d, NULL, &input_state_osc_string },
406 { 0x5e, 0x5e, NULL, &input_state_consume_st },
407 { 0x5f, 0x5f, NULL, &input_state_apc_string },
408 { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
409 { 0x6b, 0x6b, NULL, &input_state_rename_string },
Nicholas Marriott622593a2010-04-17 23:31:09 +0000410 { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000411 { 0x7f, 0xff, NULL, NULL },
412
413 { -1, -1, NULL, NULL }
414};
415
416/* esc_interm state table. */
417const struct input_transition input_state_esc_intermediate_table[] = {
418 INPUT_STATE_ANYWHERE,
419
420 { 0x00, 0x17, input_c0_dispatch, NULL },
421 { 0x19, 0x19, input_c0_dispatch, NULL },
422 { 0x1c, 0x1f, input_c0_dispatch, NULL },
423 { 0x20, 0x2f, input_intermediate, NULL },
424 { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
425 { 0x7f, 0xff, NULL, NULL },
426
427 { -1, -1, NULL, NULL }
428};
429
430/* csi_enter state table. */
431const struct input_transition input_state_csi_enter_table[] = {
432 INPUT_STATE_ANYWHERE,
433
434 { 0x00, 0x17, input_c0_dispatch, NULL },
435 { 0x19, 0x19, input_c0_dispatch, NULL },
436 { 0x1c, 0x1f, input_c0_dispatch, NULL },
437 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
438 { 0x30, 0x39, input_parameter, &input_state_csi_parameter },
439 { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
440 { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter },
441 { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
442 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
443 { 0x7f, 0xff, NULL, NULL },
444
445 { -1, -1, NULL, NULL }
446};
447
448/* csi_parameter state table. */
449const struct input_transition input_state_csi_parameter_table[] = {
450 INPUT_STATE_ANYWHERE,
451
452 { 0x00, 0x17, input_c0_dispatch, NULL },
453 { 0x19, 0x19, input_c0_dispatch, NULL },
454 { 0x1c, 0x1f, input_c0_dispatch, NULL },
455 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
456 { 0x30, 0x39, input_parameter, NULL },
457 { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
458 { 0x3b, 0x3b, input_parameter, NULL },
459 { 0x3c, 0x3f, NULL, &input_state_csi_ignore },
460 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
461 { 0x7f, 0xff, NULL, NULL },
462
463 { -1, -1, NULL, NULL }
464};
465
466/* csi_intermediate state table. */
467const struct input_transition input_state_csi_intermediate_table[] = {
468 INPUT_STATE_ANYWHERE,
469
470 { 0x00, 0x17, input_c0_dispatch, NULL },
471 { 0x19, 0x19, input_c0_dispatch, NULL },
472 { 0x1c, 0x1f, input_c0_dispatch, NULL },
473 { 0x20, 0x2f, input_intermediate, NULL },
474 { 0x30, 0x3f, NULL, &input_state_csi_ignore },
475 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
476 { 0x7f, 0xff, NULL, NULL },
477
478 { -1, -1, NULL, NULL }
479};
480
481/* csi_ignore state table. */
482const struct input_transition input_state_csi_ignore_table[] = {
483 INPUT_STATE_ANYWHERE,
484
485 { 0x00, 0x17, input_c0_dispatch, NULL },
486 { 0x19, 0x19, input_c0_dispatch, NULL },
487 { 0x1c, 0x1f, input_c0_dispatch, NULL },
488 { 0x20, 0x3f, NULL, NULL },
489 { 0x40, 0x7e, NULL, &input_state_ground },
490 { 0x7f, 0xff, NULL, NULL },
491
492 { -1, -1, NULL, NULL }
493};
494
495/* dcs_enter state table. */
496const struct input_transition input_state_dcs_enter_table[] = {
497 INPUT_STATE_ANYWHERE,
498
499 { 0x00, 0x17, NULL, NULL },
500 { 0x19, 0x19, NULL, NULL },
501 { 0x1c, 0x1f, NULL, NULL },
502 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
503 { 0x30, 0x39, input_parameter, &input_state_dcs_parameter },
504 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
505 { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
506 { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000507 { 0x40, 0x7e, input_input, &input_state_dcs_handler },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000508 { 0x7f, 0xff, NULL, NULL },
509
510 { -1, -1, NULL, NULL }
511};
512
513/* dcs_parameter state table. */
514const struct input_transition input_state_dcs_parameter_table[] = {
515 INPUT_STATE_ANYWHERE,
516
517 { 0x00, 0x17, NULL, NULL },
518 { 0x19, 0x19, NULL, NULL },
519 { 0x1c, 0x1f, NULL, NULL },
520 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
521 { 0x30, 0x39, input_parameter, NULL },
522 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
523 { 0x3b, 0x3b, input_parameter, NULL },
524 { 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000525 { 0x40, 0x7e, input_input, &input_state_dcs_handler },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000526 { 0x7f, 0xff, NULL, NULL },
527
528 { -1, -1, NULL, NULL }
529};
530
531/* dcs_interm state table. */
532const struct input_transition input_state_dcs_intermediate_table[] = {
533 INPUT_STATE_ANYWHERE,
534
535 { 0x00, 0x17, NULL, NULL },
536 { 0x19, 0x19, NULL, NULL },
537 { 0x1c, 0x1f, NULL, NULL },
538 { 0x20, 0x2f, input_intermediate, NULL },
539 { 0x30, 0x3f, NULL, &input_state_dcs_ignore },
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000540 { 0x40, 0x7e, input_input, &input_state_dcs_handler },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000541 { 0x7f, 0xff, NULL, NULL },
542
543 { -1, -1, NULL, NULL }
544};
545
546/* dcs_handler state table. */
547const struct input_transition input_state_dcs_handler_table[] = {
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000548 /* No INPUT_STATE_ANYWHERE */
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000549
Nicholas Marriott79e30da2011-03-07 23:46:27 +0000550 { 0x00, 0x1a, input_input, NULL },
551 { 0x1b, 0x1b, NULL, &input_state_dcs_escape },
552 { 0x1c, 0xff, input_input, NULL },
553
554 { -1, -1, NULL, NULL }
555};
556
557/* dcs_escape state table. */
558const struct input_transition input_state_dcs_escape_table[] = {
559 /* No INPUT_STATE_ANYWHERE */
560
561 { 0x00, 0x5b, input_input, &input_state_dcs_handler },
562 { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
563 { 0x5d, 0xff, input_input, &input_state_dcs_handler },
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000564
565 { -1, -1, NULL, NULL }
566};
567
Nicholas Marriottb4b3d9c2011-07-08 06:28:05 +0000568/* dcs_ignore state table. */
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000569const struct input_transition input_state_dcs_ignore_table[] = {
570 INPUT_STATE_ANYWHERE,
571
572 { 0x00, 0x17, NULL, NULL },
573 { 0x19, 0x19, NULL, NULL },
574 { 0x1c, 0x1f, NULL, NULL },
575 { 0x20, 0xff, NULL, NULL },
576
577 { -1, -1, NULL, NULL }
578};
579
580/* osc_string state table. */
581const struct input_transition input_state_osc_string_table[] = {
582 INPUT_STATE_ANYWHERE,
583
584 { 0x00, 0x06, NULL, NULL },
585 { 0x07, 0x07, NULL, &input_state_ground },
586 { 0x08, 0x17, NULL, NULL },
587 { 0x19, 0x19, NULL, NULL },
588 { 0x1c, 0x1f, NULL, NULL },
589 { 0x20, 0xff, input_input, NULL },
590
591 { -1, -1, NULL, NULL }
592};
593
594/* apc_string state table. */
595const struct input_transition input_state_apc_string_table[] = {
596 INPUT_STATE_ANYWHERE,
597
598 { 0x00, 0x17, NULL, NULL },
599 { 0x19, 0x19, NULL, NULL },
600 { 0x1c, 0x1f, NULL, NULL },
601 { 0x20, 0xff, input_input, NULL },
602
603 { -1, -1, NULL, NULL }
604};
605
606/* rename_string state table. */
607const struct input_transition input_state_rename_string_table[] = {
608 INPUT_STATE_ANYWHERE,
609
610 { 0x00, 0x17, NULL, NULL },
611 { 0x19, 0x19, NULL, NULL },
612 { 0x1c, 0x1f, NULL, NULL },
613 { 0x20, 0xff, input_input, NULL },
614
615 { -1, -1, NULL, NULL }
616};
617
618/* consume_st state table. */
619const struct input_transition input_state_consume_st_table[] = {
620 INPUT_STATE_ANYWHERE,
621
622 { 0x00, 0x17, NULL, NULL },
623 { 0x19, 0x19, NULL, NULL },
624 { 0x1c, 0x1f, NULL, NULL },
625 { 0x20, 0xff, NULL, NULL },
626
627 { -1, -1, NULL, NULL }
628};
629
630/* utf8_three state table. */
631const struct input_transition input_state_utf8_three_table[] = {
632 /* No INPUT_STATE_ANYWHERE */
633
634 { 0x00, 0x7f, NULL, &input_state_ground },
635 { 0x80, 0xbf, input_utf8_add, &input_state_utf8_two },
636 { 0xc0, 0xff, NULL, &input_state_ground },
637
638 { -1, -1, NULL, NULL }
639};
640
641/* utf8_two state table. */
642const struct input_transition input_state_utf8_two_table[] = {
643 /* No INPUT_STATE_ANYWHERE */
644
645 { 0x00, 0x7f, NULL, &input_state_ground },
646 { 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
647 { 0xc0, 0xff, NULL, &input_state_ground },
648
649 { -1, -1, NULL, NULL }
650};
651
652/* utf8_one state table. */
653const struct input_transition input_state_utf8_one_table[] = {
654 /* No INPUT_STATE_ANYWHERE */
655
656 { 0x00, 0x7f, NULL, &input_state_ground },
657 { 0x80, 0xbf, input_utf8_close, &input_state_ground },
658 { 0xc0, 0xff, NULL, &input_state_ground },
659
660 { -1, -1, NULL, NULL }
661};
662
663/* Input table compare. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000664int
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000665input_table_compare(const void *key, const void *value)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000666{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000667 const struct input_ctx *ictx = key;
668 const struct input_table_entry *entry = value;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000669
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000670 if (ictx->ch != entry->ch)
671 return (ictx->ch - entry->ch);
672 return (strcmp(ictx->interm_buf, entry->interm));
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000673}
674
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000675/* Initialise input parser. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000676void
677input_init(struct window_pane *wp)
678{
679 struct input_ctx *ictx = &wp->ictx;
680
Nicholas Marriott15a64b82009-12-03 22:50:09 +0000681 memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000682
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000683 memcpy(&ictx->old_cell, &grid_default_cell, sizeof ictx->old_cell);
684 ictx->old_cx = 0;
685 ictx->old_cy = 0;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000686
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000687 *ictx->interm_buf = '\0';
688 ictx->interm_len = 0;
Nicholas Marriott036de0c2009-08-18 21:41:13 +0000689
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000690 *ictx->param_buf = '\0';
691 ictx->param_len = 0;
692
693 ictx->state = &input_state_ground;
694 ictx->flags = 0;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000695}
696
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000697/* Destroy input parser. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000698void
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000699input_free(unused struct window_pane *wp)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000700{
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000701}
702
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000703/* Parse input. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000704void
705input_parse(struct window_pane *wp)
706{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000707 struct input_ctx *ictx = &wp->ictx;
708 const struct input_transition *itr;
709 struct evbuffer *evb = wp->event->input;
710 u_char *buf;
711 size_t len, off;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000712
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000713 if (EVBUFFER_LENGTH(evb) == 0)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000714 return;
Nicholas Marriotte26a3512010-12-06 22:51:02 +0000715
Nicholas Marriott036de0c2009-08-18 21:41:13 +0000716 wp->window->flags |= WINDOW_ACTIVITY;
Nicholas Marriotte26a3512010-12-06 22:51:02 +0000717 wp->window->flags &= ~WINDOW_SILENCE;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000718
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000719 /*
720 * Open the screen. Use NULL wp if there is a mode set as don't want to
721 * update the tty.
722 */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000723 if (wp->mode == NULL)
724 screen_write_start(&ictx->ctx, wp, &wp->base);
725 else
726 screen_write_start(&ictx->ctx, NULL, &wp->base);
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000727 ictx->wp = wp;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000728
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000729 buf = EVBUFFER_DATA(evb);
730 len = EVBUFFER_LENGTH(evb);
731 off = 0;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000732
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000733 /* Parse the input. */
734 while (off < len) {
735 ictx->ch = buf[off++];
736 log_debug("%s: '%c' %s", __func__, ictx->ch, ictx->state->name);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000737
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000738 /* Find the transition. */
739 itr = ictx->state->transitions;
740 while (itr->first != -1 && itr->last != -1) {
741 if (ictx->ch >= itr->first && ictx->ch <= itr->last)
742 break;
743 itr++;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000744 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000745 if (itr->first == -1 || itr->last == -1) {
746 /* No transition? Eh? */
747 fatalx("No transition from state!");
Nicholas Marriott8dd2f0d2009-06-04 14:15:50 +0000748 }
Nicholas Marriottd6015822009-06-04 14:42:14 +0000749
Nicholas Marriott8dd2f0d2009-06-04 14:15:50 +0000750 /*
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000751 * Execute the handler, if any. Don't switch state if it
752 * returns non-zero.
Nicholas Marriott8dd2f0d2009-06-04 14:15:50 +0000753 */
Nicholas Marriott6fd2b5b2010-12-23 20:18:39 +0000754 if (itr->handler != NULL && itr->handler(ictx) != 0)
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000755 continue;
756
757 /* And switch state, if necessary. */
Nicholas Marriott6fd2b5b2010-12-23 20:18:39 +0000758 if (itr->state != NULL) {
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000759 if (ictx->state->exit != NULL)
760 ictx->state->exit(ictx);
761 ictx->state = itr->state;
762 if (ictx->state->enter != NULL)
763 ictx->state->enter(ictx);
764 }
Nicholas Marriott8dd2f0d2009-06-04 14:15:50 +0000765 }
766
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000767 /* Close the screen. */
768 screen_write_stop(&ictx->ctx);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000769
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000770 evbuffer_drain(evb, len);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000771}
772
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000773/* Split the parameter list (if any). */
774int
775input_split(struct input_ctx *ictx)
776
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000777{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000778 const char *errstr;
779 char *ptr, *out;
780 int n;
781
782 ictx->param_list_len = 0;
783 if (ictx->param_len == 0)
784 return (0);
785
786 ptr = ictx->param_buf;
787 while ((out = strsep(&ptr, ";")) != NULL) {
788 if (*out == '\0')
789 n = -1;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000790 else {
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000791 n = strtonum(out, 0, INT_MAX, &errstr);
792 if (errstr != NULL)
793 return (-1);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000794 }
Nicholas Marriottd6015822009-06-04 14:42:14 +0000795
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000796 ictx->param_list[ictx->param_list_len++] = n;
797 if (ictx->param_list_len == nitems(ictx->param_list))
798 return (-1);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000799 }
800
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000801 return (0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000802}
803
Nicholas Marriottb4b3d9c2011-07-08 06:28:05 +0000804/* Get an argument or return default value. */
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000805int
806input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000807{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000808 int retval;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000809
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000810 if (validx >= ictx->param_list_len)
811 return (defval);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000812
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000813 retval = ictx->param_list[validx];
814 if (retval == -1)
815 return (defval);
816 if (retval < minval)
817 return (minval);
818 return (retval);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000819}
820
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000821/* Reply to terminal query. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000822void
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000823input_reply(struct input_ctx *ictx, const char *fmt, ...)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000824{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000825 va_list ap;
826 char *reply;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000827
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000828 va_start(ap, fmt);
829 vasprintf(&reply, fmt, ap);
830 va_end(ap);
831
832 bufferevent_write(ictx->wp->event, reply, strlen(reply));
833 xfree(reply);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000834}
835
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000836/* Clear saved state. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000837void
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000838input_clear(struct input_ctx *ictx)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000839{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000840 *ictx->interm_buf = '\0';
841 ictx->interm_len = 0;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000842
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000843 *ictx->param_buf = '\0';
844 ictx->param_len = 0;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000845
Nicholas Marriottb6bb3502011-01-28 20:39:22 +0000846 *ictx->input_buf = '\0';
847 ictx->input_len = 0;
848
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000849 ictx->flags &= ~INPUT_DISCARD;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000850}
851
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000852/* Output this character to the screen. */
853int
854input_print(struct input_ctx *ictx)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000855{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000856 ictx->cell.data = ictx->ch;
Nicholas Marriott1af09d62009-10-20 19:18:28 +0000857 screen_write_cell(&ictx->ctx, &ictx->cell, NULL);
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000858
859 return (0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000860}
861
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000862/* Collect intermediate string. */
863int
864input_intermediate(struct input_ctx *ictx)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000865{
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000866 if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
867 ictx->flags |= INPUT_DISCARD;
868 else {
869 ictx->interm_buf[ictx->interm_len++] = ictx->ch;
870 ictx->interm_buf[ictx->interm_len] = '\0';
871 }
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000872
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000873 return (0);
874}
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000875
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000876/* Collect parameter string. */
877int
878input_parameter(struct input_ctx *ictx)
879{
880 if (ictx->param_len == (sizeof ictx->param_buf) - 1)
881 ictx->flags |= INPUT_DISCARD;
882 else {
883 ictx->param_buf[ictx->param_len++] = ictx->ch;
884 ictx->param_buf[ictx->param_len] = '\0';
885 }
886
887 return (0);
888}
889
890/* Collect input string. */
891int
892input_input(struct input_ctx *ictx)
893{
894 if (ictx->input_len == (sizeof ictx->input_buf) - 1)
895 ictx->flags |= INPUT_DISCARD;
896 else {
897 ictx->input_buf[ictx->input_len++] = ictx->ch;
898 ictx->input_buf[ictx->input_len] = '\0';
899 }
900
901 return (0);
902}
903
904/* Execute C0 control sequence. */
905int
906input_c0_dispatch(struct input_ctx *ictx)
907{
908 struct screen_write_ctx *sctx = &ictx->ctx;
909 struct window_pane *wp = ictx->wp;
910 struct screen *s = sctx->s;
911
912 log_debug("%s: '%c", __func__, ictx->ch);
913
914 switch (ictx->ch) {
915 case '\000': /* NUL */
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000916 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000917 case '\007': /* BEL */
918 wp->window->flags |= WINDOW_BELL;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000919 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000920 case '\010': /* BS */
921 screen_write_backspace(sctx);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000922 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000923 case '\011': /* HT */
Nicholas Marriottd42fb432009-06-04 18:48:24 +0000924 /* Don't tab beyond the end of the line. */
925 if (s->cx >= screen_size_x(s) - 1)
926 break;
927
928 /* Find the next tab point, or use the last column if none. */
929 do {
930 s->cx++;
931 if (bit_test(s->tabs, s->cx))
932 break;
933 } while (s->cx < screen_size_x(s) - 1);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000934 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000935 case '\012': /* LF */
Nicholas Marriott8dd2f0d2009-06-04 14:15:50 +0000936 case '\013': /* VT */
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000937 case '\014': /* FF */
938 screen_write_linefeed(sctx, 0);
939 break;
940 case '\015': /* CR */
941 screen_write_carriagereturn(sctx);
Nicholas Marriott8dd2f0d2009-06-04 14:15:50 +0000942 break;
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000943 case '\016': /* SO */
944 ictx->cell.attr |= GRID_ATTR_CHARSET;
945 break;
946 case '\017': /* SI */
947 ictx->cell.attr &= ~GRID_ATTR_CHARSET;
948 break;
949 default:
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000950 log_debug("%s: unknown '%c'", __func__, ictx->ch);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000951 break;
952 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000953
954 return (0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000955}
956
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000957/* Execute escape sequence. */
958int
959input_esc_dispatch(struct input_ctx *ictx)
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000960{
Nicholas Marriott6fd2b5b2010-12-23 20:18:39 +0000961 struct screen_write_ctx *sctx = &ictx->ctx;
962 struct screen *s = sctx->s;
963 struct input_table_entry *entry;
Nicholas Marriottd42fb432009-06-04 18:48:24 +0000964
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000965 if (ictx->flags & INPUT_DISCARD)
966 return (0);
967 log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000968
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000969 entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
970 sizeof input_esc_table[0], input_table_compare);
971 if (entry == NULL) {
972 log_debug("%s: unknown '%c'", __func__, ictx->ch);
973 return (0);
974 }
975
976 switch (entry->type) {
977 case INPUT_ESC_RIS:
978 memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
979 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
980 ictx->old_cx = 0;
981 ictx->old_cy = 0;
982
Nicholas Marriottbe7b56a2012-01-21 08:12:03 +0000983 screen_write_reset(sctx);
Nicholas Marriott52ec9b92009-06-03 23:30:40 +0000984 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000985 case INPUT_ESC_IND:
986 screen_write_linefeed(sctx, 0);
Nicholas Marriottd42fb432009-06-04 18:48:24 +0000987 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000988 case INPUT_ESC_NEL:
989 screen_write_carriagereturn(sctx);
990 screen_write_linefeed(sctx, 0);
991 break;
992 case INPUT_ESC_HTS:
Nicholas Marriottd42fb432009-06-04 18:48:24 +0000993 if (s->cx < screen_size_x(s))
994 bit_set(s->tabs, s->cx);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000995 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000996 case INPUT_ESC_RI:
997 screen_write_reverseindex(sctx);
Nicholas Marriott35876ea2009-06-01 22:58:49 +0000998 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +0000999 case INPUT_ESC_DECKPAM:
1000 screen_write_kkeypadmode(sctx, 1);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001001 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001002 case INPUT_ESC_DECKPNM:
1003 screen_write_kkeypadmode(sctx, 0);
1004 break;
1005 case INPUT_ESC_DECSC:
1006 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1007 ictx->old_cx = s->cx;
1008 ictx->old_cy = s->cy;
1009 break;
1010 case INPUT_ESC_DECRC:
1011 memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1012 screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1013 break;
1014 case INPUT_ESC_DECALN:
1015 screen_write_alignmenttest(sctx);
1016 break;
1017 case INPUT_ESC_SCSON_G0:
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001018 /*
1019 * Not really supported, but fake it up enough for those that
1020 * use it to switch character sets (by redefining G0 to
1021 * graphics set, rather than switching to G1).
1022 */
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001023 ictx->cell.attr &= ~GRID_ATTR_CHARSET;
1024 break;
1025 case INPUT_ESC_SCSOFF_G0:
1026 ictx->cell.attr |= GRID_ATTR_CHARSET;
1027 break;
1028 }
1029
1030 return (0);
1031}
1032
1033/* Execute control sequence. */
1034int
1035input_csi_dispatch(struct input_ctx *ictx)
1036{
1037 struct screen_write_ctx *sctx = &ictx->ctx;
1038 struct window_pane *wp = ictx->wp;
1039 struct screen *s = sctx->s;
1040 struct input_table_entry *entry;
1041 int n, m;
1042
1043 if (ictx->flags & INPUT_DISCARD)
1044 return (0);
1045 if (input_split(ictx) != 0)
1046 return (0);
1047 log_debug("%s: '%c' \"%s\" \"%s\"",
1048 __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
1049
1050 entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
1051 sizeof input_csi_table[0], input_table_compare);
1052 if (entry == NULL) {
1053 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1054 return (0);
1055 }
1056
1057 switch (entry->type) {
1058 case INPUT_CSI_CBT:
1059 /* Find the previous tab point, n times. */
1060 n = input_get(ictx, 0, 1, 1);
1061 while (s->cx > 0 && n-- > 0) {
1062 do
1063 s->cx--;
1064 while (s->cx > 0 && !bit_test(s->tabs, s->cx));
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001065 }
1066 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001067 case INPUT_CSI_CUB:
1068 screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001069 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001070 case INPUT_CSI_CUD:
1071 screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001072 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001073 case INPUT_CSI_CUF:
1074 screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001075 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001076 case INPUT_CSI_CUP:
1077 n = input_get(ictx, 0, 1, 1);
1078 m = input_get(ictx, 1, 1, 1);
1079 screen_write_cursormove(sctx, m - 1, n - 1);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001080 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001081 case INPUT_CSI_CUU:
1082 screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001083 break;
Nicholas Marriott92aef642011-12-29 08:06:24 +00001084 case INPUT_CSI_CNL:
1085 screen_write_carriagereturn(sctx);
1086 screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
1087 break;
1088 case INPUT_CSI_CPL:
1089 screen_write_carriagereturn(sctx);
1090 screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
1091 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001092 case INPUT_CSI_DA:
1093 switch (input_get(ictx, 0, 0, 0)) {
1094 case 0:
1095 input_reply(ictx, "\033[?1;2c");
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001096 break;
1097 default:
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001098 log_debug("%s: unknown '%c'", __func__, ictx->ch);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001099 break;
1100 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001101 break;
Nicholas Marriott523ed382012-03-15 10:05:49 +00001102 case INPUT_CSI_DA_TWO:
1103 switch (input_get(ictx, 0, 0, 0)) {
1104 case 0:
1105 input_reply(ictx, "\033[>0;95;0c");
1106 break;
1107 default:
1108 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1109 break;
1110 }
1111 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001112 case INPUT_CSI_DCH:
1113 screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1));
1114 break;
1115 case INPUT_CSI_DECSTBM:
1116 n = input_get(ictx, 0, 1, 1);
1117 m = input_get(ictx, 1, 1, screen_size_y(s));
1118 screen_write_scrollregion(sctx, n - 1, m - 1);
1119 break;
1120 case INPUT_CSI_DL:
1121 screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1));
1122 break;
1123 case INPUT_CSI_DSR:
1124 switch (input_get(ictx, 0, 0, 0)) {
1125 case 5:
1126 input_reply(ictx, "\033[0n");
1127 break;
1128 case 6:
1129 input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
1130 break;
1131 default:
1132 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1133 break;
1134 }
1135 break;
1136 case INPUT_CSI_ED:
1137 switch (input_get(ictx, 0, 0, 0)) {
1138 case 0:
1139 screen_write_clearendofscreen(sctx);
1140 break;
1141 case 1:
1142 screen_write_clearstartofscreen(sctx);
1143 break;
1144 case 2:
1145 screen_write_clearscreen(sctx);
1146 break;
Nicholas Marriottf0aad682011-10-23 10:16:14 +00001147 case 3:
1148 switch (input_get(ictx, 1, 0, 0)) {
1149 case 0:
1150 /*
1151 * Linux console extension to clear history
1152 * (for example before locking the screen).
1153 */
1154 screen_write_clearhistory(sctx);
1155 break;
1156 }
1157 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001158 default:
1159 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1160 break;
1161 }
1162 break;
1163 case INPUT_CSI_EL:
1164 switch (input_get(ictx, 0, 0, 0)) {
1165 case 0:
1166 screen_write_clearendofline(sctx);
1167 break;
1168 case 1:
1169 screen_write_clearstartofline(sctx);
1170 break;
1171 case 2:
1172 screen_write_clearline(sctx);
1173 break;
1174 default:
1175 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1176 break;
1177 }
1178 break;
1179 case INPUT_CSI_HPA:
1180 n = input_get(ictx, 0, 1, 1);
1181 screen_write_cursormove(sctx, n - 1, s->cy);
1182 break;
1183 case INPUT_CSI_ICH:
1184 screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1));
1185 break;
1186 case INPUT_CSI_IL:
1187 screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
1188 break;
Nicholas Marriottd377a682011-12-27 14:06:19 +00001189 case INPUT_CSI_RCP:
1190 memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
1191 screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
1192 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001193 case INPUT_CSI_RM:
1194 switch (input_get(ictx, 0, 0, -1)) {
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001195 case 4: /* IRM */
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001196 screen_write_insertmode(&ictx->ctx, 0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001197 break;
1198 default:
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001199 log_debug("%s: unknown '%c'", __func__, ictx->ch);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001200 break;
1201 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001202 break;
1203 case INPUT_CSI_RM_PRIVATE:
1204 switch (input_get(ictx, 0, 0, -1)) {
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001205 case 1: /* GATM */
1206 screen_write_kcursormode(&ictx->ctx, 0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001207 break;
Nicholas Marriott71dc6e02009-10-13 15:23:13 +00001208 case 3: /* DECCOLM */
Nicholas Marriott15a64b82009-12-03 22:50:09 +00001209 screen_write_cursormove(&ictx->ctx, 0, 0);
Nicholas Marriott71dc6e02009-10-13 15:23:13 +00001210 screen_write_clearscreen(&ictx->ctx);
1211 break;
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001212 case 25: /* TCEM */
1213 screen_write_cursormode(&ictx->ctx, 0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001214 break;
1215 case 1000:
Nicholas Marriottf7c42c22010-12-29 21:49:06 +00001216 case 1001:
1217 case 1002:
1218 case 1003:
1219 screen_write_mousemode_off(&ictx->ctx);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001220 break;
Nicholas Marriottac3b78a2011-01-03 23:35:21 +00001221 case 1005:
1222 screen_write_utf8mousemode(&ictx->ctx, 0);
1223 break;
Nicholas Marriott35928592009-07-13 10:43:52 +00001224 case 1049:
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001225 window_pane_alternate_off(wp, &ictx->cell);
Nicholas Marriott35928592009-07-13 10:43:52 +00001226 break;
Nicholas Marriottf4fdddc2012-03-03 09:43:22 +00001227 case 2004:
1228 screen_write_bracketpaste(&ictx->ctx, 0);
1229 break;
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001230 default:
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001231 log_debug("%s: unknown '%c'", __func__, ictx->ch);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001232 break;
1233 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001234 break;
Nicholas Marriottd377a682011-12-27 14:06:19 +00001235 case INPUT_CSI_SCP:
1236 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
1237 ictx->old_cx = s->cx;
1238 ictx->old_cy = s->cy;
1239 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001240 case INPUT_CSI_SGR:
1241 input_csi_dispatch_sgr(ictx);
1242 break;
1243 case INPUT_CSI_SM:
1244 switch (input_get(ictx, 0, 0, -1)) {
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001245 case 4: /* IRM */
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001246 screen_write_insertmode(&ictx->ctx, 1);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001247 break;
1248 default:
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001249 log_debug("%s: unknown '%c'", __func__, ictx->ch);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001250 break;
1251 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001252 break;
1253 case INPUT_CSI_SM_PRIVATE:
1254 switch (input_get(ictx, 0, 0, -1)) {
1255 case 1: /* GATM */
1256 screen_write_kcursormode(&ictx->ctx, 1);
1257 break;
1258 case 3: /* DECCOLM */
1259 screen_write_cursormove(&ictx->ctx, 0, 0);
1260 screen_write_clearscreen(&ictx->ctx);
1261 break;
1262 case 25: /* TCEM */
1263 screen_write_cursormode(&ictx->ctx, 1);
1264 break;
1265 case 1000:
Nicholas Marriottf7c42c22010-12-29 21:49:06 +00001266 screen_write_mousemode_on(
1267 &ictx->ctx, MODE_MOUSE_STANDARD);
1268 break;
Nicholas Marriottf7c42c22010-12-29 21:49:06 +00001269 case 1002:
1270 screen_write_mousemode_on(
1271 &ictx->ctx, MODE_MOUSE_BUTTON);
1272 break;
1273 case 1003:
1274 screen_write_mousemode_on(&ictx->ctx, MODE_MOUSE_ANY);
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001275 break;
Nicholas Marriottac3b78a2011-01-03 23:35:21 +00001276 case 1005:
1277 screen_write_utf8mousemode(&ictx->ctx, 1);
1278 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001279 case 1049:
1280 window_pane_alternate_on(wp, &ictx->cell);
1281 break;
Nicholas Marriottf4fdddc2012-03-03 09:43:22 +00001282 case 2004:
1283 screen_write_bracketpaste(&ictx->ctx, 1);
1284 break;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001285 default:
1286 log_debug("%s: unknown '%c'", __func__, ictx->ch);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001287 break;
1288 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001289 break;
1290 case INPUT_CSI_TBC:
1291 switch (input_get(ictx, 0, 0, 0)) {
1292 case 0:
1293 if (s->cx < screen_size_x(s))
1294 bit_clear(s->tabs, s->cx);
1295 break;
1296 case 3:
1297 bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
1298 break;
1299 default:
1300 log_debug("%s: unknown '%c'", __func__, ictx->ch);
1301 break;
1302 }
1303 break;
1304 case INPUT_CSI_VPA:
1305 n = input_get(ictx, 0, 1, 1);
1306 screen_write_cursormove(sctx, s->cx, n - 1);
1307 break;
Nicholas Marriott3ea5e062011-05-20 19:17:39 +00001308 case INPUT_CSI_DECSCUSR:
1309 n = input_get(ictx, 0, 0, 0);
1310 screen_set_cursor_style(s, n);
1311 break;
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001312 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001313
1314 return (0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001315}
1316
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001317/* Handle CSI SGR. */
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001318void
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001319input_csi_dispatch_sgr(struct input_ctx *ictx)
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001320{
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001321 struct grid_cell *gc = &ictx->cell;
1322 u_int i;
1323 int n, m;
1324 u_char attr;
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001325
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001326 if (ictx->param_list_len == 0) {
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001327 attr = gc->attr;
1328 memcpy(gc, &grid_default_cell, sizeof *gc);
Nicholas Marriott15a64b82009-12-03 22:50:09 +00001329 gc->attr |= (attr & GRID_ATTR_CHARSET);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001330 return;
1331 }
1332
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001333 for (i = 0; i < ictx->param_list_len; i++) {
1334 n = input_get(ictx, i, 0, 0);
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001335
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001336 if (n == 38 || n == 48) {
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001337 i++;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001338 if (input_get(ictx, i, 0, -1) != 5)
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001339 continue;
1340
1341 i++;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001342 m = input_get(ictx, i, 0, -1);
1343 if (m == -1) {
1344 if (n == 38) {
1345 gc->flags &= ~GRID_FLAG_FG256;
1346 gc->fg = 8;
1347 } else if (n == 48) {
1348 gc->flags &= ~GRID_FLAG_BG256;
Nicholas Marriottc36f67a2011-03-03 08:53:14 +00001349 gc->bg = 8;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001350 }
1351
1352 } else {
1353 if (n == 38) {
1354 gc->flags |= GRID_FLAG_FG256;
1355 gc->fg = m;
1356 } else if (n == 48) {
1357 gc->flags |= GRID_FLAG_BG256;
1358 gc->bg = m;
1359 }
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001360 }
1361 continue;
1362 }
1363
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001364 switch (n) {
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001365 case 0:
1366 case 10:
1367 attr = gc->attr;
1368 memcpy(gc, &grid_default_cell, sizeof *gc);
1369 gc->attr |= (attr & GRID_ATTR_CHARSET);
1370 break;
1371 case 1:
1372 gc->attr |= GRID_ATTR_BRIGHT;
1373 break;
1374 case 2:
1375 gc->attr |= GRID_ATTR_DIM;
1376 break;
1377 case 3:
1378 gc->attr |= GRID_ATTR_ITALICS;
1379 break;
1380 case 4:
1381 gc->attr |= GRID_ATTR_UNDERSCORE;
1382 break;
1383 case 5:
1384 gc->attr |= GRID_ATTR_BLINK;
1385 break;
1386 case 7:
1387 gc->attr |= GRID_ATTR_REVERSE;
1388 break;
1389 case 8:
1390 gc->attr |= GRID_ATTR_HIDDEN;
1391 break;
1392 case 22:
1393 gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
1394 break;
1395 case 23:
1396 gc->attr &= ~GRID_ATTR_ITALICS;
1397 break;
1398 case 24:
1399 gc->attr &= ~GRID_ATTR_UNDERSCORE;
1400 break;
1401 case 25:
1402 gc->attr &= ~GRID_ATTR_BLINK;
1403 break;
1404 case 27:
1405 gc->attr &= ~GRID_ATTR_REVERSE;
1406 break;
1407 case 30:
1408 case 31:
1409 case 32:
1410 case 33:
1411 case 34:
1412 case 35:
1413 case 36:
1414 case 37:
1415 gc->flags &= ~GRID_FLAG_FG256;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001416 gc->fg = n - 30;
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001417 break;
1418 case 39:
1419 gc->flags &= ~GRID_FLAG_FG256;
1420 gc->fg = 8;
1421 break;
1422 case 40:
1423 case 41:
1424 case 42:
1425 case 43:
1426 case 44:
1427 case 45:
1428 case 46:
1429 case 47:
1430 gc->flags &= ~GRID_FLAG_BG256;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001431 gc->bg = n - 40;
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001432 break;
1433 case 49:
1434 gc->flags &= ~GRID_FLAG_BG256;
1435 gc->bg = 8;
1436 break;
Nicholas Marriottc2b8f3b2009-10-23 15:48:39 +00001437 case 90:
1438 case 91:
1439 case 92:
1440 case 93:
1441 case 94:
1442 case 95:
1443 case 96:
1444 case 97:
Nicholas Marriottad8509f2010-01-06 23:13:52 +00001445 gc->flags &= ~GRID_FLAG_FG256;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001446 gc->fg = n;
Nicholas Marriottc2b8f3b2009-10-23 15:48:39 +00001447 break;
1448 case 100:
1449 case 101:
1450 case 102:
1451 case 103:
1452 case 104:
1453 case 105:
1454 case 106:
1455 case 107:
Nicholas Marriottad8509f2010-01-06 23:13:52 +00001456 gc->flags &= ~GRID_FLAG_BG256;
Nicholas Marriott7f240202012-01-21 08:23:12 +00001457 gc->bg = n - 10;
Nicholas Marriottc2b8f3b2009-10-23 15:48:39 +00001458 break;
Nicholas Marriott35876ea2009-06-01 22:58:49 +00001459 }
1460 }
1461}
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001462
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001463/* DCS terminator (ST) received. */
Nicholas Marriott79e30da2011-03-07 23:46:27 +00001464int
1465input_dcs_dispatch(struct input_ctx *ictx)
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001466{
Nicholas Marriott79e30da2011-03-07 23:46:27 +00001467 const char prefix[] = "tmux;";
1468 const u_int prefix_len = (sizeof prefix) - 1;
1469
1470 if (ictx->flags & INPUT_DISCARD)
1471 return (0);
1472
1473 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1474
1475 /* Check for tmux prefix. */
1476 if (ictx->input_len >= prefix_len &&
1477 strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
1478 screen_write_rawstring(&ictx->ctx,
1479 ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
1480 }
1481
1482 return (0);
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001483}
1484
1485/* OSC string started. */
1486void
1487input_enter_osc(struct input_ctx *ictx)
1488{
1489 log_debug("%s", __func__);
1490
Nicholas Marriottb6bb3502011-01-28 20:39:22 +00001491 input_clear(ictx);
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001492}
1493
1494/* OSC terminator (ST) received. */
1495void
1496input_exit_osc(struct input_ctx *ictx)
1497{
Nicholas Marriott944b5e62011-05-20 19:03:58 +00001498 u_char *p = ictx->input_buf;
1499 int option;
1500
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001501 if (ictx->flags & INPUT_DISCARD)
1502 return;
Nicholas Marriott944b5e62011-05-20 19:03:58 +00001503 if (ictx->input_len < 1 || *p < '0' || *p > '9')
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001504 return;
1505
Nicholas Marriott944b5e62011-05-20 19:03:58 +00001506 log_debug("%s: \"%s\"", __func__, p);
1507
1508 option = 0;
1509 while (*p >= '0' && *p <= '9')
1510 option = option * 10 + *p++ - '0';
1511 if (*p == ';')
1512 p++;
1513
1514 switch (option) {
1515 case 0:
1516 case 2:
1517 screen_set_title(ictx->ctx.s, p);
1518 server_status_window(ictx->wp->window);
1519 break;
1520 case 12:
1521 screen_set_cursor_colour(ictx->ctx.s, p);
1522 break;
1523 case 112:
1524 if (*p == '\0') /* No arguments allowed. */
1525 screen_set_cursor_colour(ictx->ctx.s, "");
1526 break;
1527 default:
1528 log_debug("%s: unknown '%u'", __func__, option);
1529 break;
1530 }
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001531}
1532
1533/* APC string started. */
1534void
1535input_enter_apc(struct input_ctx *ictx)
1536{
1537 log_debug("%s", __func__);
1538
Nicholas Marriottb6bb3502011-01-28 20:39:22 +00001539 input_clear(ictx);
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001540}
1541
1542/* APC terminator (ST) received. */
1543void
1544input_exit_apc(struct input_ctx *ictx)
1545{
1546 if (ictx->flags & INPUT_DISCARD)
1547 return;
1548 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1549
1550 screen_set_title(ictx->ctx.s, ictx->input_buf);
1551 server_status_window(ictx->wp->window);
1552}
1553
1554/* Rename string started. */
1555void
1556input_enter_rename(struct input_ctx *ictx)
1557{
1558 log_debug("%s", __func__);
1559
Nicholas Marriottb6bb3502011-01-28 20:39:22 +00001560 input_clear(ictx);
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001561}
1562
1563/* Rename terminator (ST) received. */
1564void
1565input_exit_rename(struct input_ctx *ictx)
1566{
1567 if (ictx->flags & INPUT_DISCARD)
1568 return;
Nicholas Marriottdcad1312012-01-20 19:15:40 +00001569 if (!options_get_number(&ictx->wp->window->options, "allow-rename"))
1570 return;
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001571 log_debug("%s: \"%s\"", __func__, ictx->input_buf);
1572
Nicholas Marriott8363d192012-02-02 00:10:11 +00001573 window_set_name(ictx->wp->window, ictx->input_buf);
Nicholas Marriott4baafd82010-03-22 19:02:54 +00001574 options_set_number(&ictx->wp->window->options, "automatic-rename", 0);
1575
1576 server_status_window(ictx->wp->window);
1577}
1578
1579/* Open UTF-8 character. */
1580int
1581input_utf8_open(struct input_ctx *ictx)
1582{
1583 if (!options_get_number(&ictx->wp->window->options, "utf8")) {
1584 /* Print, and do not switch state. */
1585 input_print(ictx);
1586 return (-1);
1587 }
1588 log_debug("%s", __func__);
1589
1590 utf8_open(&ictx->utf8data, ictx->ch);
1591 return (0);
1592}
1593
1594/* Append to UTF-8 character. */
1595int
1596input_utf8_add(struct input_ctx *ictx)
1597{
1598 log_debug("%s", __func__);
1599
1600 utf8_append(&ictx->utf8data, ictx->ch);
1601 return (0);
1602}
1603
1604/* Close UTF-8 string. */
1605int
1606input_utf8_close(struct input_ctx *ictx)
1607{
1608 log_debug("%s", __func__);
1609
1610 utf8_append(&ictx->utf8data, ictx->ch);
1611
1612 ictx->cell.flags |= GRID_FLAG_UTF8;
1613 screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
1614 ictx->cell.flags &= ~GRID_FLAG_UTF8;
1615
1616 return (0);
1617}