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