1 /* $OpenBSD: input.c,v 1.83 2015/08/29 08:30:54 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 #include <time.h> 24 25 #include "tmux.h" 26 27 /* 28 * Based on the description by Paul Williams at: 29 * 30 * http://vt100.net/emu/dec_ansi_parser 31 * 32 * With the following changes: 33 * 34 * - 7-bit only. 35 * 36 * - Support for UTF-8. 37 * 38 * - OSC (but not APC) may be terminated by \007 as well as ST. 39 * 40 * - A state for APC similar to OSC. Some terminals appear to use this to set 41 * the title. 42 * 43 * - A state for the screen \033k...\033\\ sequence to rename a window. This is 44 * pretty stupid but not supporting it is more trouble than it is worth. 45 * 46 * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to 47 * be passed to the underlying terminals. 48 */ 49 50 /* Input parser cell. */ 51 struct input_cell { 52 struct grid_cell cell; 53 int set; 54 int g0set; /* 1 if ACS */ 55 int g1set; /* 1 if ACS */ 56 }; 57 58 /* Input parser context. */ 59 struct input_ctx { 60 struct window_pane *wp; 61 struct screen_write_ctx ctx; 62 63 struct input_cell cell; 64 65 struct input_cell old_cell; 66 u_int old_cx; 67 u_int old_cy; 68 69 u_char interm_buf[4]; 70 size_t interm_len; 71 72 u_char param_buf[64]; 73 size_t param_len; 74 75 #define INPUT_BUF_START 32 76 #define INPUT_BUF_LIMIT 1048576 77 u_char *input_buf; 78 size_t input_len; 79 size_t input_space; 80 81 int param_list[24]; /* -1 not present */ 82 u_int param_list_len; 83 84 struct utf8_data utf8data; 85 86 int ch; 87 int flags; 88 #define INPUT_DISCARD 0x1 89 90 const struct input_state *state; 91 92 /* 93 * All input received since we were last in the ground state. Sent to 94 * control clients on connection. 95 */ 96 struct evbuffer *since_ground; 97 }; 98 99 /* Helper functions. */ 100 struct input_transition; 101 int input_split(struct input_ctx *); 102 int input_get(struct input_ctx *, u_int, int, int); 103 void input_reply(struct input_ctx *, const char *, ...); 104 void input_set_state(struct window_pane *, const struct input_transition *); 105 void input_reset_cell(struct input_ctx *); 106 107 /* Transition entry/exit handlers. */ 108 void input_clear(struct input_ctx *); 109 void input_ground(struct input_ctx *); 110 void input_enter_osc(struct input_ctx *); 111 void input_exit_osc(struct input_ctx *); 112 void input_enter_apc(struct input_ctx *); 113 void input_exit_apc(struct input_ctx *); 114 void input_enter_rename(struct input_ctx *); 115 void input_exit_rename(struct input_ctx *); 116 117 /* Input state handlers. */ 118 int input_print(struct input_ctx *); 119 int input_intermediate(struct input_ctx *); 120 int input_parameter(struct input_ctx *); 121 int input_input(struct input_ctx *); 122 int input_c0_dispatch(struct input_ctx *); 123 int input_esc_dispatch(struct input_ctx *); 124 int input_csi_dispatch(struct input_ctx *); 125 void input_csi_dispatch_rm(struct input_ctx *); 126 void input_csi_dispatch_rm_private(struct input_ctx *); 127 void input_csi_dispatch_sm(struct input_ctx *); 128 void input_csi_dispatch_sm_private(struct input_ctx *); 129 void input_csi_dispatch_winops(struct input_ctx *); 130 void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *); 131 void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *); 132 void input_csi_dispatch_sgr(struct input_ctx *); 133 int input_dcs_dispatch(struct input_ctx *); 134 int input_utf8_open(struct input_ctx *); 135 int input_utf8_add(struct input_ctx *); 136 int input_utf8_close(struct input_ctx *); 137 138 /* Command table comparison function. */ 139 int input_table_compare(const void *, const void *); 140 141 /* Command table entry. */ 142 struct input_table_entry { 143 int ch; 144 const char *interm; 145 int type; 146 }; 147 148 /* Escape commands. */ 149 enum input_esc_type { 150 INPUT_ESC_DECALN, 151 INPUT_ESC_DECKPAM, 152 INPUT_ESC_DECKPNM, 153 INPUT_ESC_DECRC, 154 INPUT_ESC_DECSC, 155 INPUT_ESC_HTS, 156 INPUT_ESC_IND, 157 INPUT_ESC_NEL, 158 INPUT_ESC_RI, 159 INPUT_ESC_RIS, 160 INPUT_ESC_SCSG0_OFF, 161 INPUT_ESC_SCSG0_ON, 162 INPUT_ESC_SCSG1_OFF, 163 INPUT_ESC_SCSG1_ON, 164 }; 165 166 /* Escape command table. */ 167 const struct input_table_entry input_esc_table[] = { 168 { '0', "(", INPUT_ESC_SCSG0_ON }, 169 { '0', ")", INPUT_ESC_SCSG1_ON }, 170 { '7', "", INPUT_ESC_DECSC }, 171 { '8', "", INPUT_ESC_DECRC }, 172 { '8', "#", INPUT_ESC_DECALN }, 173 { '=', "", INPUT_ESC_DECKPAM }, 174 { '>', "", INPUT_ESC_DECKPNM }, 175 { 'B', "(", INPUT_ESC_SCSG0_OFF }, 176 { 'B', ")", INPUT_ESC_SCSG1_OFF }, 177 { 'D', "", INPUT_ESC_IND }, 178 { 'E', "", INPUT_ESC_NEL }, 179 { 'H', "", INPUT_ESC_HTS }, 180 { 'M', "", INPUT_ESC_RI }, 181 { 'c', "", INPUT_ESC_RIS }, 182 }; 183 184 /* Control (CSI) commands. */ 185 enum input_csi_type { 186 INPUT_CSI_CBT, 187 INPUT_CSI_CNL, 188 INPUT_CSI_CPL, 189 INPUT_CSI_CUB, 190 INPUT_CSI_CUD, 191 INPUT_CSI_CUF, 192 INPUT_CSI_CUP, 193 INPUT_CSI_CUU, 194 INPUT_CSI_DA, 195 INPUT_CSI_DA_TWO, 196 INPUT_CSI_DCH, 197 INPUT_CSI_DECSCUSR, 198 INPUT_CSI_DECSTBM, 199 INPUT_CSI_DL, 200 INPUT_CSI_DSR, 201 INPUT_CSI_ECH, 202 INPUT_CSI_ED, 203 INPUT_CSI_EL, 204 INPUT_CSI_HPA, 205 INPUT_CSI_ICH, 206 INPUT_CSI_IL, 207 INPUT_CSI_RCP, 208 INPUT_CSI_RM, 209 INPUT_CSI_RM_PRIVATE, 210 INPUT_CSI_SCP, 211 INPUT_CSI_SGR, 212 INPUT_CSI_SM, 213 INPUT_CSI_SM_PRIVATE, 214 INPUT_CSI_TBC, 215 INPUT_CSI_VPA, 216 INPUT_CSI_WINOPS, 217 }; 218 219 /* Control (CSI) command table. */ 220 const struct input_table_entry input_csi_table[] = { 221 { '@', "", INPUT_CSI_ICH }, 222 { 'A', "", INPUT_CSI_CUU }, 223 { 'B', "", INPUT_CSI_CUD }, 224 { 'C', "", INPUT_CSI_CUF }, 225 { 'D', "", INPUT_CSI_CUB }, 226 { 'E', "", INPUT_CSI_CNL }, 227 { 'F', "", INPUT_CSI_CPL }, 228 { 'G', "", INPUT_CSI_HPA }, 229 { 'H', "", INPUT_CSI_CUP }, 230 { 'J', "", INPUT_CSI_ED }, 231 { 'K', "", INPUT_CSI_EL }, 232 { 'L', "", INPUT_CSI_IL }, 233 { 'M', "", INPUT_CSI_DL }, 234 { 'P', "", INPUT_CSI_DCH }, 235 { 'X', "", INPUT_CSI_ECH }, 236 { 'Z', "", INPUT_CSI_CBT }, 237 { 'c', "", INPUT_CSI_DA }, 238 { 'c', ">", INPUT_CSI_DA_TWO }, 239 { 'd', "", INPUT_CSI_VPA }, 240 { 'f', "", INPUT_CSI_CUP }, 241 { 'g', "", INPUT_CSI_TBC }, 242 { 'h', "", INPUT_CSI_SM }, 243 { 'h', "?", INPUT_CSI_SM_PRIVATE }, 244 { 'l', "", INPUT_CSI_RM }, 245 { 'l', "?", INPUT_CSI_RM_PRIVATE }, 246 { 'm', "", INPUT_CSI_SGR }, 247 { 'n', "", INPUT_CSI_DSR }, 248 { 'q', " ", INPUT_CSI_DECSCUSR }, 249 { 'r', "", INPUT_CSI_DECSTBM }, 250 { 's', "", INPUT_CSI_SCP }, 251 { 't', "", INPUT_CSI_WINOPS }, 252 { 'u', "", INPUT_CSI_RCP }, 253 }; 254 255 /* Input transition. */ 256 struct input_transition { 257 int first; 258 int last; 259 260 int (*handler)(struct input_ctx *); 261 const struct input_state *state; 262 }; 263 264 /* Input state. */ 265 struct input_state { 266 const char *name; 267 void (*enter)(struct input_ctx *); 268 void (*exit)(struct input_ctx *); 269 const struct input_transition *transitions; 270 }; 271 272 /* State transitions available from all states. */ 273 #define INPUT_STATE_ANYWHERE \ 274 { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \ 275 { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \ 276 { 0x1b, 0x1b, NULL, &input_state_esc_enter } 277 278 /* Forward declarations of state tables. */ 279 const struct input_transition input_state_ground_table[]; 280 const struct input_transition input_state_esc_enter_table[]; 281 const struct input_transition input_state_esc_intermediate_table[]; 282 const struct input_transition input_state_csi_enter_table[]; 283 const struct input_transition input_state_csi_parameter_table[]; 284 const struct input_transition input_state_csi_intermediate_table[]; 285 const struct input_transition input_state_csi_ignore_table[]; 286 const struct input_transition input_state_dcs_enter_table[]; 287 const struct input_transition input_state_dcs_parameter_table[]; 288 const struct input_transition input_state_dcs_intermediate_table[]; 289 const struct input_transition input_state_dcs_handler_table[]; 290 const struct input_transition input_state_dcs_escape_table[]; 291 const struct input_transition input_state_dcs_ignore_table[]; 292 const struct input_transition input_state_osc_string_table[]; 293 const struct input_transition input_state_apc_string_table[]; 294 const struct input_transition input_state_rename_string_table[]; 295 const struct input_transition input_state_consume_st_table[]; 296 const struct input_transition input_state_utf8_three_table[]; 297 const struct input_transition input_state_utf8_two_table[]; 298 const struct input_transition input_state_utf8_one_table[]; 299 300 /* ground state definition. */ 301 const struct input_state input_state_ground = { 302 "ground", 303 input_ground, NULL, 304 input_state_ground_table 305 }; 306 307 /* esc_enter state definition. */ 308 const struct input_state input_state_esc_enter = { 309 "esc_enter", 310 input_clear, NULL, 311 input_state_esc_enter_table 312 }; 313 314 /* esc_intermediate state definition. */ 315 const struct input_state input_state_esc_intermediate = { 316 "esc_intermediate", 317 NULL, NULL, 318 input_state_esc_intermediate_table 319 }; 320 321 /* csi_enter state definition. */ 322 const struct input_state input_state_csi_enter = { 323 "csi_enter", 324 input_clear, NULL, 325 input_state_csi_enter_table 326 }; 327 328 /* csi_parameter state definition. */ 329 const struct input_state input_state_csi_parameter = { 330 "csi_parameter", 331 NULL, NULL, 332 input_state_csi_parameter_table 333 }; 334 335 /* csi_intermediate state definition. */ 336 const struct input_state input_state_csi_intermediate = { 337 "csi_intermediate", 338 NULL, NULL, 339 input_state_csi_intermediate_table 340 }; 341 342 /* csi_ignore state definition. */ 343 const struct input_state input_state_csi_ignore = { 344 "csi_ignore", 345 NULL, NULL, 346 input_state_csi_ignore_table 347 }; 348 349 /* dcs_enter state definition. */ 350 const struct input_state input_state_dcs_enter = { 351 "dcs_enter", 352 input_clear, NULL, 353 input_state_dcs_enter_table 354 }; 355 356 /* dcs_parameter state definition. */ 357 const struct input_state input_state_dcs_parameter = { 358 "dcs_parameter", 359 NULL, NULL, 360 input_state_dcs_parameter_table 361 }; 362 363 /* dcs_intermediate state definition. */ 364 const struct input_state input_state_dcs_intermediate = { 365 "dcs_intermediate", 366 NULL, NULL, 367 input_state_dcs_intermediate_table 368 }; 369 370 /* dcs_handler state definition. */ 371 const struct input_state input_state_dcs_handler = { 372 "dcs_handler", 373 NULL, NULL, 374 input_state_dcs_handler_table 375 }; 376 377 /* dcs_escape state definition. */ 378 const struct input_state input_state_dcs_escape = { 379 "dcs_escape", 380 NULL, NULL, 381 input_state_dcs_escape_table 382 }; 383 384 /* dcs_ignore state definition. */ 385 const struct input_state input_state_dcs_ignore = { 386 "dcs_ignore", 387 NULL, NULL, 388 input_state_dcs_ignore_table 389 }; 390 391 /* osc_string state definition. */ 392 const struct input_state input_state_osc_string = { 393 "osc_string", 394 input_enter_osc, input_exit_osc, 395 input_state_osc_string_table 396 }; 397 398 /* apc_string state definition. */ 399 const struct input_state input_state_apc_string = { 400 "apc_string", 401 input_enter_apc, input_exit_apc, 402 input_state_apc_string_table 403 }; 404 405 /* rename_string state definition. */ 406 const struct input_state input_state_rename_string = { 407 "rename_string", 408 input_enter_rename, input_exit_rename, 409 input_state_rename_string_table 410 }; 411 412 /* consume_st state definition. */ 413 const struct input_state input_state_consume_st = { 414 "consume_st", 415 NULL, NULL, 416 input_state_consume_st_table 417 }; 418 419 /* utf8_three state definition. */ 420 const struct input_state input_state_utf8_three = { 421 "utf8_three", 422 NULL, NULL, 423 input_state_utf8_three_table 424 }; 425 426 /* utf8_two state definition. */ 427 const struct input_state input_state_utf8_two = { 428 "utf8_two", 429 NULL, NULL, 430 input_state_utf8_two_table 431 }; 432 433 /* utf8_one state definition. */ 434 const struct input_state input_state_utf8_one = { 435 "utf8_one", 436 NULL, NULL, 437 input_state_utf8_one_table 438 }; 439 440 /* ground state table. */ 441 const struct input_transition input_state_ground_table[] = { 442 INPUT_STATE_ANYWHERE, 443 444 { 0x00, 0x17, input_c0_dispatch, NULL }, 445 { 0x19, 0x19, input_c0_dispatch, NULL }, 446 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 447 { 0x20, 0x7e, input_print, NULL }, 448 { 0x7f, 0x7f, NULL, NULL }, 449 { 0x80, 0xc1, input_print, NULL }, 450 { 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one }, 451 { 0xe0, 0xef, input_utf8_open, &input_state_utf8_two }, 452 { 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three }, 453 { 0xf5, 0xff, input_print, NULL }, 454 455 { -1, -1, NULL, NULL } 456 }; 457 458 /* esc_enter state table. */ 459 const struct input_transition input_state_esc_enter_table[] = { 460 INPUT_STATE_ANYWHERE, 461 462 { 0x00, 0x17, input_c0_dispatch, NULL }, 463 { 0x19, 0x19, input_c0_dispatch, NULL }, 464 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 465 { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate }, 466 { 0x30, 0x4f, input_esc_dispatch, &input_state_ground }, 467 { 0x50, 0x50, NULL, &input_state_dcs_enter }, 468 { 0x51, 0x57, input_esc_dispatch, &input_state_ground }, 469 { 0x58, 0x58, NULL, &input_state_consume_st }, 470 { 0x59, 0x59, input_esc_dispatch, &input_state_ground }, 471 { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground }, 472 { 0x5b, 0x5b, NULL, &input_state_csi_enter }, 473 { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground }, 474 { 0x5d, 0x5d, NULL, &input_state_osc_string }, 475 { 0x5e, 0x5e, NULL, &input_state_consume_st }, 476 { 0x5f, 0x5f, NULL, &input_state_apc_string }, 477 { 0x60, 0x6a, input_esc_dispatch, &input_state_ground }, 478 { 0x6b, 0x6b, NULL, &input_state_rename_string }, 479 { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground }, 480 { 0x7f, 0xff, NULL, NULL }, 481 482 { -1, -1, NULL, NULL } 483 }; 484 485 /* esc_interm state table. */ 486 const struct input_transition input_state_esc_intermediate_table[] = { 487 INPUT_STATE_ANYWHERE, 488 489 { 0x00, 0x17, input_c0_dispatch, NULL }, 490 { 0x19, 0x19, input_c0_dispatch, NULL }, 491 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 492 { 0x20, 0x2f, input_intermediate, NULL }, 493 { 0x30, 0x7e, input_esc_dispatch, &input_state_ground }, 494 { 0x7f, 0xff, NULL, NULL }, 495 496 { -1, -1, NULL, NULL } 497 }; 498 499 /* csi_enter state table. */ 500 const struct input_transition input_state_csi_enter_table[] = { 501 INPUT_STATE_ANYWHERE, 502 503 { 0x00, 0x17, input_c0_dispatch, NULL }, 504 { 0x19, 0x19, input_c0_dispatch, NULL }, 505 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 506 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate }, 507 { 0x30, 0x39, input_parameter, &input_state_csi_parameter }, 508 { 0x3a, 0x3a, NULL, &input_state_csi_ignore }, 509 { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter }, 510 { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter }, 511 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, 512 { 0x7f, 0xff, NULL, NULL }, 513 514 { -1, -1, NULL, NULL } 515 }; 516 517 /* csi_parameter state table. */ 518 const struct input_transition input_state_csi_parameter_table[] = { 519 INPUT_STATE_ANYWHERE, 520 521 { 0x00, 0x17, input_c0_dispatch, NULL }, 522 { 0x19, 0x19, input_c0_dispatch, NULL }, 523 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 524 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate }, 525 { 0x30, 0x39, input_parameter, NULL }, 526 { 0x3a, 0x3a, NULL, &input_state_csi_ignore }, 527 { 0x3b, 0x3b, input_parameter, NULL }, 528 { 0x3c, 0x3f, NULL, &input_state_csi_ignore }, 529 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, 530 { 0x7f, 0xff, NULL, NULL }, 531 532 { -1, -1, NULL, NULL } 533 }; 534 535 /* csi_intermediate state table. */ 536 const struct input_transition input_state_csi_intermediate_table[] = { 537 INPUT_STATE_ANYWHERE, 538 539 { 0x00, 0x17, input_c0_dispatch, NULL }, 540 { 0x19, 0x19, input_c0_dispatch, NULL }, 541 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 542 { 0x20, 0x2f, input_intermediate, NULL }, 543 { 0x30, 0x3f, NULL, &input_state_csi_ignore }, 544 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, 545 { 0x7f, 0xff, NULL, NULL }, 546 547 { -1, -1, NULL, NULL } 548 }; 549 550 /* csi_ignore state table. */ 551 const struct input_transition input_state_csi_ignore_table[] = { 552 INPUT_STATE_ANYWHERE, 553 554 { 0x00, 0x17, input_c0_dispatch, NULL }, 555 { 0x19, 0x19, input_c0_dispatch, NULL }, 556 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 557 { 0x20, 0x3f, NULL, NULL }, 558 { 0x40, 0x7e, NULL, &input_state_ground }, 559 { 0x7f, 0xff, NULL, NULL }, 560 561 { -1, -1, NULL, NULL } 562 }; 563 564 /* dcs_enter state table. */ 565 const struct input_transition input_state_dcs_enter_table[] = { 566 INPUT_STATE_ANYWHERE, 567 568 { 0x00, 0x17, NULL, NULL }, 569 { 0x19, 0x19, NULL, NULL }, 570 { 0x1c, 0x1f, NULL, NULL }, 571 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate }, 572 { 0x30, 0x39, input_parameter, &input_state_dcs_parameter }, 573 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore }, 574 { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter }, 575 { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter }, 576 { 0x40, 0x7e, input_input, &input_state_dcs_handler }, 577 { 0x7f, 0xff, NULL, NULL }, 578 579 { -1, -1, NULL, NULL } 580 }; 581 582 /* dcs_parameter state table. */ 583 const struct input_transition input_state_dcs_parameter_table[] = { 584 INPUT_STATE_ANYWHERE, 585 586 { 0x00, 0x17, NULL, NULL }, 587 { 0x19, 0x19, NULL, NULL }, 588 { 0x1c, 0x1f, NULL, NULL }, 589 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate }, 590 { 0x30, 0x39, input_parameter, NULL }, 591 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore }, 592 { 0x3b, 0x3b, input_parameter, NULL }, 593 { 0x3c, 0x3f, NULL, &input_state_dcs_ignore }, 594 { 0x40, 0x7e, input_input, &input_state_dcs_handler }, 595 { 0x7f, 0xff, NULL, NULL }, 596 597 { -1, -1, NULL, NULL } 598 }; 599 600 /* dcs_interm state table. */ 601 const struct input_transition input_state_dcs_intermediate_table[] = { 602 INPUT_STATE_ANYWHERE, 603 604 { 0x00, 0x17, NULL, NULL }, 605 { 0x19, 0x19, NULL, NULL }, 606 { 0x1c, 0x1f, NULL, NULL }, 607 { 0x20, 0x2f, input_intermediate, NULL }, 608 { 0x30, 0x3f, NULL, &input_state_dcs_ignore }, 609 { 0x40, 0x7e, input_input, &input_state_dcs_handler }, 610 { 0x7f, 0xff, NULL, NULL }, 611 612 { -1, -1, NULL, NULL } 613 }; 614 615 /* dcs_handler state table. */ 616 const struct input_transition input_state_dcs_handler_table[] = { 617 /* No INPUT_STATE_ANYWHERE */ 618 619 { 0x00, 0x1a, input_input, NULL }, 620 { 0x1b, 0x1b, NULL, &input_state_dcs_escape }, 621 { 0x1c, 0xff, input_input, NULL }, 622 623 { -1, -1, NULL, NULL } 624 }; 625 626 /* dcs_escape state table. */ 627 const struct input_transition input_state_dcs_escape_table[] = { 628 /* No INPUT_STATE_ANYWHERE */ 629 630 { 0x00, 0x5b, input_input, &input_state_dcs_handler }, 631 { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground }, 632 { 0x5d, 0xff, input_input, &input_state_dcs_handler }, 633 634 { -1, -1, NULL, NULL } 635 }; 636 637 /* dcs_ignore state table. */ 638 const struct input_transition input_state_dcs_ignore_table[] = { 639 INPUT_STATE_ANYWHERE, 640 641 { 0x00, 0x17, NULL, NULL }, 642 { 0x19, 0x19, NULL, NULL }, 643 { 0x1c, 0x1f, NULL, NULL }, 644 { 0x20, 0xff, NULL, NULL }, 645 646 { -1, -1, NULL, NULL } 647 }; 648 649 /* osc_string state table. */ 650 const struct input_transition input_state_osc_string_table[] = { 651 INPUT_STATE_ANYWHERE, 652 653 { 0x00, 0x06, NULL, NULL }, 654 { 0x07, 0x07, NULL, &input_state_ground }, 655 { 0x08, 0x17, NULL, NULL }, 656 { 0x19, 0x19, NULL, NULL }, 657 { 0x1c, 0x1f, NULL, NULL }, 658 { 0x20, 0xff, input_input, NULL }, 659 660 { -1, -1, NULL, NULL } 661 }; 662 663 /* apc_string state table. */ 664 const struct input_transition input_state_apc_string_table[] = { 665 INPUT_STATE_ANYWHERE, 666 667 { 0x00, 0x17, NULL, NULL }, 668 { 0x19, 0x19, NULL, NULL }, 669 { 0x1c, 0x1f, NULL, NULL }, 670 { 0x20, 0xff, input_input, NULL }, 671 672 { -1, -1, NULL, NULL } 673 }; 674 675 /* rename_string state table. */ 676 const struct input_transition input_state_rename_string_table[] = { 677 INPUT_STATE_ANYWHERE, 678 679 { 0x00, 0x17, NULL, NULL }, 680 { 0x19, 0x19, NULL, NULL }, 681 { 0x1c, 0x1f, NULL, NULL }, 682 { 0x20, 0xff, input_input, NULL }, 683 684 { -1, -1, NULL, NULL } 685 }; 686 687 /* consume_st state table. */ 688 const struct input_transition input_state_consume_st_table[] = { 689 INPUT_STATE_ANYWHERE, 690 691 { 0x00, 0x17, NULL, NULL }, 692 { 0x19, 0x19, NULL, NULL }, 693 { 0x1c, 0x1f, NULL, NULL }, 694 { 0x20, 0xff, NULL, NULL }, 695 696 { -1, -1, NULL, NULL } 697 }; 698 699 /* utf8_three state table. */ 700 const struct input_transition input_state_utf8_three_table[] = { 701 /* No INPUT_STATE_ANYWHERE */ 702 703 { 0x00, 0x7f, NULL, &input_state_ground }, 704 { 0x80, 0xbf, input_utf8_add, &input_state_utf8_two }, 705 { 0xc0, 0xff, NULL, &input_state_ground }, 706 707 { -1, -1, NULL, NULL } 708 }; 709 710 /* utf8_two state table. */ 711 const struct input_transition input_state_utf8_two_table[] = { 712 /* No INPUT_STATE_ANYWHERE */ 713 714 { 0x00, 0x7f, NULL, &input_state_ground }, 715 { 0x80, 0xbf, input_utf8_add, &input_state_utf8_one }, 716 { 0xc0, 0xff, NULL, &input_state_ground }, 717 718 { -1, -1, NULL, NULL } 719 }; 720 721 /* utf8_one state table. */ 722 const struct input_transition input_state_utf8_one_table[] = { 723 /* No INPUT_STATE_ANYWHERE */ 724 725 { 0x00, 0x7f, NULL, &input_state_ground }, 726 { 0x80, 0xbf, input_utf8_close, &input_state_ground }, 727 { 0xc0, 0xff, NULL, &input_state_ground }, 728 729 { -1, -1, NULL, NULL } 730 }; 731 732 /* Input table compare. */ 733 int 734 input_table_compare(const void *key, const void *value) 735 { 736 const struct input_ctx *ictx = key; 737 const struct input_table_entry *entry = value; 738 739 if (ictx->ch != entry->ch) 740 return (ictx->ch - entry->ch); 741 return (strcmp(ictx->interm_buf, entry->interm)); 742 } 743 744 /* Reset cell state to default. */ 745 void 746 input_reset_cell(struct input_ctx *ictx) 747 { 748 memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell); 749 ictx->cell.set = 0; 750 ictx->cell.g0set = ictx->cell.g1set = 0; 751 752 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); 753 ictx->old_cx = 0; 754 ictx->old_cy = 0; 755 } 756 757 /* Initialise input parser. */ 758 void 759 input_init(struct window_pane *wp) 760 { 761 struct input_ctx *ictx; 762 763 ictx = wp->ictx = xcalloc(1, sizeof *ictx); 764 765 input_reset_cell(ictx); 766 767 *ictx->interm_buf = '\0'; 768 ictx->interm_len = 0; 769 770 *ictx->param_buf = '\0'; 771 ictx->param_len = 0; 772 773 ictx->input_space = INPUT_BUF_START; 774 ictx->input_buf = xmalloc(INPUT_BUF_START); 775 776 *ictx->input_buf = '\0'; 777 ictx->input_len = 0; 778 779 ictx->state = &input_state_ground; 780 ictx->flags = 0; 781 782 ictx->since_ground = evbuffer_new(); 783 } 784 785 /* Destroy input parser. */ 786 void 787 input_free(struct window_pane *wp) 788 { 789 struct input_ctx *ictx = wp->ictx; 790 791 free(ictx->input_buf); 792 evbuffer_free(ictx->since_ground); 793 794 free (ictx); 795 wp->ictx = NULL; 796 } 797 798 /* Reset input state and clear screen. */ 799 void 800 input_reset(struct window_pane *wp) 801 { 802 struct input_ctx *ictx = wp->ictx; 803 804 input_reset_cell(ictx); 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. */ 815 struct evbuffer * 816 input_pending(struct window_pane *wp) 817 { 818 return (wp->ictx->since_ground); 819 } 820 821 /* Change input state. */ 822 void 823 input_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. */ 835 void 836 input_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 window_update_activity(wp->window); 848 wp->flags |= PANE_CHANGED; 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). */ 905 int 906 input_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. */ 936 int 937 input_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. */ 953 void 954 input_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. */ 968 void 969 input_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. */ 984 void 985 input_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. */ 996 int 997 input_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. */ 1016 int 1017 input_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. */ 1030 int 1031 input_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. */ 1044 int 1045 input_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. */ 1066 int 1067 input_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 alerts_queue(wp->window, 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. */ 1119 int 1120 input_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. */ 1192 int 1193 input_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 u_int cx; 1200 1201 if (ictx->flags & INPUT_DISCARD) 1202 return (0); 1203 if (input_split(ictx) != 0) 1204 return (0); 1205 log_debug("%s: '%c' \"%s\" \"%s\"", 1206 __func__, ictx->ch, ictx->interm_buf, ictx->param_buf); 1207 1208 entry = bsearch(ictx, input_csi_table, nitems(input_csi_table), 1209 sizeof input_csi_table[0], input_table_compare); 1210 if (entry == NULL) { 1211 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1212 return (0); 1213 } 1214 1215 switch (entry->type) { 1216 case INPUT_CSI_CBT: 1217 /* Find the previous tab point, n times. */ 1218 cx = s->cx; 1219 if (cx > screen_size_x(s) - 1) 1220 cx = screen_size_x(s) - 1; 1221 n = input_get(ictx, 0, 1, 1); 1222 while (cx > 0 && n-- > 0) { 1223 do 1224 cx--; 1225 while (cx > 0 && !bit_test(s->tabs, cx)); 1226 } 1227 s->cx = cx; 1228 break; 1229 case INPUT_CSI_CUB: 1230 screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1)); 1231 break; 1232 case INPUT_CSI_CUD: 1233 screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); 1234 break; 1235 case INPUT_CSI_CUF: 1236 screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1)); 1237 break; 1238 case INPUT_CSI_CUP: 1239 n = input_get(ictx, 0, 1, 1); 1240 m = input_get(ictx, 1, 1, 1); 1241 screen_write_cursormove(sctx, m - 1, n - 1); 1242 break; 1243 case INPUT_CSI_WINOPS: 1244 input_csi_dispatch_winops(ictx); 1245 break; 1246 case INPUT_CSI_CUU: 1247 screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); 1248 break; 1249 case INPUT_CSI_CNL: 1250 screen_write_carriagereturn(sctx); 1251 screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1)); 1252 break; 1253 case INPUT_CSI_CPL: 1254 screen_write_carriagereturn(sctx); 1255 screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1)); 1256 break; 1257 case INPUT_CSI_DA: 1258 switch (input_get(ictx, 0, 0, 0)) { 1259 case 0: 1260 input_reply(ictx, "\033[?1;2c"); 1261 break; 1262 default: 1263 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1264 break; 1265 } 1266 break; 1267 case INPUT_CSI_DA_TWO: 1268 switch (input_get(ictx, 0, 0, 0)) { 1269 case 0: 1270 input_reply(ictx, "\033[>84;0;0c"); 1271 break; 1272 default: 1273 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1274 break; 1275 } 1276 break; 1277 case INPUT_CSI_ECH: 1278 screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1)); 1279 break; 1280 case INPUT_CSI_DCH: 1281 screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1)); 1282 break; 1283 case INPUT_CSI_DECSTBM: 1284 n = input_get(ictx, 0, 1, 1); 1285 m = input_get(ictx, 1, 1, screen_size_y(s)); 1286 screen_write_scrollregion(sctx, n - 1, m - 1); 1287 break; 1288 case INPUT_CSI_DL: 1289 screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1)); 1290 break; 1291 case INPUT_CSI_DSR: 1292 switch (input_get(ictx, 0, 0, 0)) { 1293 case 5: 1294 input_reply(ictx, "\033[0n"); 1295 break; 1296 case 6: 1297 input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1); 1298 break; 1299 default: 1300 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1301 break; 1302 } 1303 break; 1304 case INPUT_CSI_ED: 1305 switch (input_get(ictx, 0, 0, 0)) { 1306 case 0: 1307 screen_write_clearendofscreen(sctx); 1308 break; 1309 case 1: 1310 screen_write_clearstartofscreen(sctx); 1311 break; 1312 case 2: 1313 screen_write_clearscreen(sctx); 1314 break; 1315 case 3: 1316 switch (input_get(ictx, 1, 0, 0)) { 1317 case 0: 1318 /* 1319 * Linux console extension to clear history 1320 * (for example before locking the screen). 1321 */ 1322 screen_write_clearhistory(sctx); 1323 break; 1324 } 1325 break; 1326 default: 1327 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1328 break; 1329 } 1330 break; 1331 case INPUT_CSI_EL: 1332 switch (input_get(ictx, 0, 0, 0)) { 1333 case 0: 1334 screen_write_clearendofline(sctx); 1335 break; 1336 case 1: 1337 screen_write_clearstartofline(sctx); 1338 break; 1339 case 2: 1340 screen_write_clearline(sctx); 1341 break; 1342 default: 1343 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1344 break; 1345 } 1346 break; 1347 case INPUT_CSI_HPA: 1348 n = input_get(ictx, 0, 1, 1); 1349 screen_write_cursormove(sctx, n - 1, s->cy); 1350 break; 1351 case INPUT_CSI_ICH: 1352 screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1)); 1353 break; 1354 case INPUT_CSI_IL: 1355 screen_write_insertline(sctx, input_get(ictx, 0, 1, 1)); 1356 break; 1357 case INPUT_CSI_RCP: 1358 memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); 1359 screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy); 1360 break; 1361 case INPUT_CSI_RM: 1362 input_csi_dispatch_rm(ictx); 1363 break; 1364 case INPUT_CSI_RM_PRIVATE: 1365 input_csi_dispatch_rm_private(ictx); 1366 break; 1367 case INPUT_CSI_SCP: 1368 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); 1369 ictx->old_cx = s->cx; 1370 ictx->old_cy = s->cy; 1371 break; 1372 case INPUT_CSI_SGR: 1373 input_csi_dispatch_sgr(ictx); 1374 break; 1375 case INPUT_CSI_SM: 1376 input_csi_dispatch_sm(ictx); 1377 break; 1378 case INPUT_CSI_SM_PRIVATE: 1379 input_csi_dispatch_sm_private(ictx); 1380 break; 1381 case INPUT_CSI_TBC: 1382 switch (input_get(ictx, 0, 0, 0)) { 1383 case 0: 1384 if (s->cx < screen_size_x(s)) 1385 bit_clear(s->tabs, s->cx); 1386 break; 1387 case 3: 1388 bit_nclear(s->tabs, 0, screen_size_x(s) - 1); 1389 break; 1390 default: 1391 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1392 break; 1393 } 1394 break; 1395 case INPUT_CSI_VPA: 1396 n = input_get(ictx, 0, 1, 1); 1397 screen_write_cursormove(sctx, s->cx, n - 1); 1398 break; 1399 case INPUT_CSI_DECSCUSR: 1400 n = input_get(ictx, 0, 0, 0); 1401 screen_set_cursor_style(s, n); 1402 break; 1403 } 1404 1405 return (0); 1406 } 1407 1408 /* Handle CSI RM. */ 1409 void 1410 input_csi_dispatch_rm(struct input_ctx *ictx) 1411 { 1412 u_int i; 1413 1414 for (i = 0; i < ictx->param_list_len; i++) { 1415 switch (input_get(ictx, i, 0, -1)) { 1416 case 4: /* IRM */ 1417 screen_write_mode_clear(&ictx->ctx, MODE_INSERT); 1418 break; 1419 case 34: 1420 screen_write_mode_set(&ictx->ctx, MODE_BLINKING); 1421 break; 1422 default: 1423 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1424 break; 1425 } 1426 } 1427 } 1428 1429 /* Handle CSI private RM. */ 1430 void 1431 input_csi_dispatch_rm_private(struct input_ctx *ictx) 1432 { 1433 struct window_pane *wp = ictx->wp; 1434 u_int i; 1435 1436 for (i = 0; i < ictx->param_list_len; i++) { 1437 switch (input_get(ictx, i, 0, -1)) { 1438 case 1: /* DECCKM */ 1439 screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR); 1440 break; 1441 case 3: /* DECCOLM */ 1442 screen_write_cursormove(&ictx->ctx, 0, 0); 1443 screen_write_clearscreen(&ictx->ctx); 1444 break; 1445 case 7: /* DECAWM */ 1446 screen_write_mode_clear(&ictx->ctx, MODE_WRAP); 1447 break; 1448 case 12: 1449 screen_write_mode_clear(&ictx->ctx, MODE_BLINKING); 1450 break; 1451 case 25: /* TCEM */ 1452 screen_write_mode_clear(&ictx->ctx, MODE_CURSOR); 1453 break; 1454 case 1000: 1455 case 1001: 1456 case 1002: 1457 screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); 1458 break; 1459 case 1004: 1460 screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON); 1461 break; 1462 case 1005: 1463 screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8); 1464 break; 1465 case 1006: 1466 screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR); 1467 break; 1468 case 47: 1469 case 1047: 1470 window_pane_alternate_off(wp, &ictx->cell.cell, 0); 1471 break; 1472 case 1049: 1473 window_pane_alternate_off(wp, &ictx->cell.cell, 1); 1474 break; 1475 case 2004: 1476 screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE); 1477 break; 1478 default: 1479 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1480 break; 1481 } 1482 } 1483 } 1484 1485 /* Handle CSI SM. */ 1486 void 1487 input_csi_dispatch_sm(struct input_ctx *ictx) 1488 { 1489 u_int i; 1490 1491 for (i = 0; i < ictx->param_list_len; i++) { 1492 switch (input_get(ictx, i, 0, -1)) { 1493 case 4: /* IRM */ 1494 screen_write_mode_set(&ictx->ctx, MODE_INSERT); 1495 break; 1496 case 34: 1497 screen_write_mode_clear(&ictx->ctx, MODE_BLINKING); 1498 break; 1499 default: 1500 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1501 break; 1502 } 1503 } 1504 } 1505 1506 /* Handle CSI private SM. */ 1507 void 1508 input_csi_dispatch_sm_private(struct input_ctx *ictx) 1509 { 1510 struct window_pane *wp = ictx->wp; 1511 u_int i; 1512 1513 for (i = 0; i < ictx->param_list_len; i++) { 1514 switch (input_get(ictx, i, 0, -1)) { 1515 case 1: /* DECCKM */ 1516 screen_write_mode_set(&ictx->ctx, MODE_KCURSOR); 1517 break; 1518 case 3: /* DECCOLM */ 1519 screen_write_cursormove(&ictx->ctx, 0, 0); 1520 screen_write_clearscreen(&ictx->ctx); 1521 break; 1522 case 7: /* DECAWM */ 1523 screen_write_mode_set(&ictx->ctx, MODE_WRAP); 1524 break; 1525 case 12: 1526 screen_write_mode_set(&ictx->ctx, MODE_BLINKING); 1527 break; 1528 case 25: /* TCEM */ 1529 screen_write_mode_set(&ictx->ctx, MODE_CURSOR); 1530 break; 1531 case 1000: 1532 screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); 1533 screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD); 1534 break; 1535 case 1002: 1536 screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES); 1537 screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON); 1538 break; 1539 case 1004: 1540 if (ictx->ctx.s->mode & MODE_FOCUSON) 1541 break; 1542 screen_write_mode_set(&ictx->ctx, MODE_FOCUSON); 1543 wp->flags |= PANE_FOCUSPUSH; /* force update */ 1544 break; 1545 case 1005: 1546 screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8); 1547 break; 1548 case 1006: 1549 screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR); 1550 break; 1551 case 47: 1552 case 1047: 1553 window_pane_alternate_on(wp, &ictx->cell.cell, 0); 1554 break; 1555 case 1049: 1556 window_pane_alternate_on(wp, &ictx->cell.cell, 1); 1557 break; 1558 case 2004: 1559 screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE); 1560 break; 1561 default: 1562 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1563 break; 1564 } 1565 } 1566 } 1567 1568 /* Handle CSI window operations. */ 1569 void 1570 input_csi_dispatch_winops(struct input_ctx *ictx) 1571 { 1572 struct window_pane *wp = ictx->wp; 1573 int n, m; 1574 1575 m = 0; 1576 while ((n = input_get(ictx, m, 0, -1)) != -1) { 1577 switch (n) { 1578 case 1: 1579 case 2: 1580 case 5: 1581 case 6: 1582 case 7: 1583 case 11: 1584 case 13: 1585 case 14: 1586 case 19: 1587 case 20: 1588 case 21: 1589 case 24: 1590 break; 1591 case 3: 1592 case 4: 1593 case 8: 1594 m++; 1595 if (input_get(ictx, m, 0, -1) == -1) 1596 return; 1597 /* FALLTHROUGH */ 1598 case 9: 1599 case 10: 1600 case 22: 1601 case 23: 1602 m++; 1603 if (input_get(ictx, m, 0, -1) == -1) 1604 return; 1605 break; 1606 case 18: 1607 input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx); 1608 break; 1609 default: 1610 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1611 break; 1612 } 1613 m++; 1614 } 1615 } 1616 1617 /* Handle CSI SGR for 256 colours. */ 1618 void 1619 input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i) 1620 { 1621 struct grid_cell *gc = &ictx->cell.cell; 1622 int c; 1623 1624 (*i)++; 1625 c = input_get(ictx, *i, 0, -1); 1626 if (c == -1) { 1627 if (fgbg == 38) { 1628 gc->flags &= ~GRID_FLAG_FG256; 1629 gc->fg = 8; 1630 } else if (fgbg == 48) { 1631 gc->flags &= ~GRID_FLAG_BG256; 1632 gc->bg = 8; 1633 } 1634 } else { 1635 if (fgbg == 38) { 1636 gc->flags |= GRID_FLAG_FG256; 1637 gc->fg = c; 1638 } else if (fgbg == 48) { 1639 gc->flags |= GRID_FLAG_BG256; 1640 gc->bg = c; 1641 } 1642 } 1643 } 1644 1645 /* Handle CSI SGR for RGB colours. */ 1646 void 1647 input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i) 1648 { 1649 struct grid_cell *gc = &ictx->cell.cell; 1650 int c, r, g, b; 1651 1652 (*i)++; 1653 r = input_get(ictx, *i, 0, -1); 1654 if (r == -1 || r > 255) 1655 return; 1656 (*i)++; 1657 g = input_get(ictx, *i, 0, -1); 1658 if (g == -1 || g > 255) 1659 return; 1660 (*i)++; 1661 b = input_get(ictx, *i, 0, -1); 1662 if (b == -1 || b > 255) 1663 return; 1664 1665 c = colour_find_rgb(r, g, b); 1666 if (fgbg == 38) { 1667 gc->flags |= GRID_FLAG_FG256; 1668 gc->fg = c; 1669 } else if (fgbg == 48) { 1670 gc->flags |= GRID_FLAG_BG256; 1671 gc->bg = c; 1672 } 1673 } 1674 1675 /* Handle CSI SGR. */ 1676 void 1677 input_csi_dispatch_sgr(struct input_ctx *ictx) 1678 { 1679 struct grid_cell *gc = &ictx->cell.cell; 1680 u_int i; 1681 int n; 1682 1683 if (ictx->param_list_len == 0) { 1684 memcpy(gc, &grid_default_cell, sizeof *gc); 1685 return; 1686 } 1687 1688 for (i = 0; i < ictx->param_list_len; i++) { 1689 n = input_get(ictx, i, 0, 0); 1690 1691 if (n == 38 || n == 48) { 1692 i++; 1693 switch (input_get(ictx, i, 0, -1)) { 1694 case 2: 1695 input_csi_dispatch_sgr_rgb(ictx, n, &i); 1696 break; 1697 case 5: 1698 input_csi_dispatch_sgr_256(ictx, n, &i); 1699 break; 1700 } 1701 continue; 1702 } 1703 1704 switch (n) { 1705 case 0: 1706 case 10: 1707 memcpy(gc, &grid_default_cell, sizeof *gc); 1708 break; 1709 case 1: 1710 gc->attr |= GRID_ATTR_BRIGHT; 1711 break; 1712 case 2: 1713 gc->attr |= GRID_ATTR_DIM; 1714 break; 1715 case 3: 1716 gc->attr |= GRID_ATTR_ITALICS; 1717 break; 1718 case 4: 1719 gc->attr |= GRID_ATTR_UNDERSCORE; 1720 break; 1721 case 5: 1722 gc->attr |= GRID_ATTR_BLINK; 1723 break; 1724 case 7: 1725 gc->attr |= GRID_ATTR_REVERSE; 1726 break; 1727 case 8: 1728 gc->attr |= GRID_ATTR_HIDDEN; 1729 break; 1730 case 22: 1731 gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM); 1732 break; 1733 case 23: 1734 gc->attr &= ~GRID_ATTR_ITALICS; 1735 break; 1736 case 24: 1737 gc->attr &= ~GRID_ATTR_UNDERSCORE; 1738 break; 1739 case 25: 1740 gc->attr &= ~GRID_ATTR_BLINK; 1741 break; 1742 case 27: 1743 gc->attr &= ~GRID_ATTR_REVERSE; 1744 break; 1745 case 30: 1746 case 31: 1747 case 32: 1748 case 33: 1749 case 34: 1750 case 35: 1751 case 36: 1752 case 37: 1753 gc->flags &= ~GRID_FLAG_FG256; 1754 gc->fg = n - 30; 1755 break; 1756 case 39: 1757 gc->flags &= ~GRID_FLAG_FG256; 1758 gc->fg = 8; 1759 break; 1760 case 40: 1761 case 41: 1762 case 42: 1763 case 43: 1764 case 44: 1765 case 45: 1766 case 46: 1767 case 47: 1768 gc->flags &= ~GRID_FLAG_BG256; 1769 gc->bg = n - 40; 1770 break; 1771 case 49: 1772 gc->flags &= ~GRID_FLAG_BG256; 1773 gc->bg = 8; 1774 break; 1775 case 90: 1776 case 91: 1777 case 92: 1778 case 93: 1779 case 94: 1780 case 95: 1781 case 96: 1782 case 97: 1783 gc->flags &= ~GRID_FLAG_FG256; 1784 gc->fg = n; 1785 break; 1786 case 100: 1787 case 101: 1788 case 102: 1789 case 103: 1790 case 104: 1791 case 105: 1792 case 106: 1793 case 107: 1794 gc->flags &= ~GRID_FLAG_BG256; 1795 gc->bg = n - 10; 1796 break; 1797 } 1798 } 1799 } 1800 1801 /* DCS terminator (ST) received. */ 1802 int 1803 input_dcs_dispatch(struct input_ctx *ictx) 1804 { 1805 const char prefix[] = "tmux;"; 1806 const u_int prefix_len = (sizeof prefix) - 1; 1807 1808 if (ictx->flags & INPUT_DISCARD) 1809 return (0); 1810 1811 log_debug("%s: \"%s\"", __func__, ictx->input_buf); 1812 1813 /* Check for tmux prefix. */ 1814 if (ictx->input_len >= prefix_len && 1815 strncmp(ictx->input_buf, prefix, prefix_len) == 0) { 1816 screen_write_rawstring(&ictx->ctx, 1817 ictx->input_buf + prefix_len, ictx->input_len - prefix_len); 1818 } 1819 1820 return (0); 1821 } 1822 1823 /* OSC string started. */ 1824 void 1825 input_enter_osc(struct input_ctx *ictx) 1826 { 1827 log_debug("%s", __func__); 1828 1829 input_clear(ictx); 1830 } 1831 1832 /* OSC terminator (ST) received. */ 1833 void 1834 input_exit_osc(struct input_ctx *ictx) 1835 { 1836 u_char *p = ictx->input_buf; 1837 u_int option; 1838 1839 if (ictx->flags & INPUT_DISCARD) 1840 return; 1841 if (ictx->input_len < 1 || *p < '0' || *p > '9') 1842 return; 1843 1844 log_debug("%s: \"%s\"", __func__, p); 1845 1846 option = 0; 1847 while (*p >= '0' && *p <= '9') 1848 option = option * 10 + *p++ - '0'; 1849 if (*p == ';') 1850 p++; 1851 1852 switch (option) { 1853 case 0: 1854 case 2: 1855 screen_set_title(ictx->ctx.s, p); 1856 server_status_window(ictx->wp->window); 1857 break; 1858 case 12: 1859 if (*p != '?') /* ? is colour request */ 1860 screen_set_cursor_colour(ictx->ctx.s, p); 1861 break; 1862 case 112: 1863 if (*p == '\0') /* no arguments allowed */ 1864 screen_set_cursor_colour(ictx->ctx.s, ""); 1865 break; 1866 default: 1867 log_debug("%s: unknown '%u'", __func__, option); 1868 break; 1869 } 1870 } 1871 1872 /* APC string started. */ 1873 void 1874 input_enter_apc(struct input_ctx *ictx) 1875 { 1876 log_debug("%s", __func__); 1877 1878 input_clear(ictx); 1879 } 1880 1881 /* APC terminator (ST) received. */ 1882 void 1883 input_exit_apc(struct input_ctx *ictx) 1884 { 1885 if (ictx->flags & INPUT_DISCARD) 1886 return; 1887 log_debug("%s: \"%s\"", __func__, ictx->input_buf); 1888 1889 screen_set_title(ictx->ctx.s, ictx->input_buf); 1890 server_status_window(ictx->wp->window); 1891 } 1892 1893 /* Rename string started. */ 1894 void 1895 input_enter_rename(struct input_ctx *ictx) 1896 { 1897 log_debug("%s", __func__); 1898 1899 input_clear(ictx); 1900 } 1901 1902 /* Rename terminator (ST) received. */ 1903 void 1904 input_exit_rename(struct input_ctx *ictx) 1905 { 1906 if (ictx->flags & INPUT_DISCARD) 1907 return; 1908 if (!options_get_number(&ictx->wp->window->options, "allow-rename")) 1909 return; 1910 log_debug("%s: \"%s\"", __func__, ictx->input_buf); 1911 1912 window_set_name(ictx->wp->window, ictx->input_buf); 1913 options_set_number(&ictx->wp->window->options, "automatic-rename", 0); 1914 1915 server_status_window(ictx->wp->window); 1916 } 1917 1918 /* Open UTF-8 character. */ 1919 int 1920 input_utf8_open(struct input_ctx *ictx) 1921 { 1922 if (!options_get_number(&ictx->wp->window->options, "utf8")) { 1923 /* Print, and do not switch state. */ 1924 input_print(ictx); 1925 return (-1); 1926 } 1927 log_debug("%s", __func__); 1928 1929 utf8_open(&ictx->utf8data, ictx->ch); 1930 return (0); 1931 } 1932 1933 /* Append to UTF-8 character. */ 1934 int 1935 input_utf8_add(struct input_ctx *ictx) 1936 { 1937 log_debug("%s", __func__); 1938 1939 utf8_append(&ictx->utf8data, ictx->ch); 1940 return (0); 1941 } 1942 1943 /* Close UTF-8 string. */ 1944 int 1945 input_utf8_close(struct input_ctx *ictx) 1946 { 1947 log_debug("%s", __func__); 1948 1949 utf8_append(&ictx->utf8data, ictx->ch); 1950 1951 grid_cell_set(&ictx->cell.cell, &ictx->utf8data); 1952 screen_write_cell(&ictx->ctx, &ictx->cell.cell); 1953 1954 return (0); 1955 } 1956