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