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