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