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