1 /* $OpenBSD: input.c,v 1.232 2024/11/11 08:41:05 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 <ctype.h> 24 #include <resolv.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <time.h> 28 29 #include "tmux.h" 30 31 /* 32 * Based on the description by Paul Williams at: 33 * 34 * https://vt100.net/emu/dec_ansi_parser 35 * 36 * With the following changes: 37 * 38 * - 7-bit only. 39 * 40 * - Support for UTF-8. 41 * 42 * - OSC (but not APC) may be terminated by \007 as well as ST. 43 * 44 * - A state for APC similar to OSC. Some terminals appear to use this to set 45 * the title. 46 * 47 * - A state for the screen \033k...\033\\ sequence to rename a window. This is 48 * pretty stupid but not supporting it is more trouble than it is worth. 49 * 50 * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to 51 * be passed to the underlying terminals. 52 */ 53 54 /* Input parser cell. */ 55 struct input_cell { 56 struct grid_cell cell; 57 int set; 58 int g0set; /* 1 if ACS */ 59 int g1set; /* 1 if ACS */ 60 }; 61 62 /* Input parser argument. */ 63 struct input_param { 64 enum { 65 INPUT_MISSING, 66 INPUT_NUMBER, 67 INPUT_STRING 68 } type; 69 union { 70 int num; 71 char *str; 72 }; 73 }; 74 75 /* Input parser context. */ 76 struct input_ctx { 77 struct window_pane *wp; 78 struct bufferevent *event; 79 struct screen_write_ctx ctx; 80 struct colour_palette *palette; 81 82 struct input_cell cell; 83 84 struct input_cell old_cell; 85 u_int old_cx; 86 u_int old_cy; 87 int old_mode; 88 89 u_char interm_buf[4]; 90 size_t interm_len; 91 92 u_char param_buf[64]; 93 size_t param_len; 94 95 #define INPUT_BUF_START 32 96 u_char *input_buf; 97 size_t input_len; 98 size_t input_space; 99 enum { 100 INPUT_END_ST, 101 INPUT_END_BEL 102 } input_end; 103 104 struct input_param param_list[24]; 105 u_int param_list_len; 106 107 struct utf8_data utf8data; 108 int utf8started; 109 110 int ch; 111 struct utf8_data last; 112 113 int flags; 114 #define INPUT_DISCARD 0x1 115 #define INPUT_LAST 0x2 116 117 const struct input_state *state; 118 119 struct event timer; 120 121 /* 122 * All input received since we were last in the ground state. Sent to 123 * control clients on connection. 124 */ 125 struct evbuffer *since_ground; 126 }; 127 128 /* Helper functions. */ 129 struct input_transition; 130 static int input_split(struct input_ctx *); 131 static int input_get(struct input_ctx *, u_int, int, int); 132 static void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...); 133 static void input_set_state(struct input_ctx *, 134 const struct input_transition *); 135 static void input_reset_cell(struct input_ctx *); 136 137 static void input_osc_4(struct input_ctx *, const char *); 138 static void input_osc_8(struct input_ctx *, const char *); 139 static void input_osc_10(struct input_ctx *, const char *); 140 static void input_osc_11(struct input_ctx *, const char *); 141 static void input_osc_12(struct input_ctx *, const char *); 142 static void input_osc_52(struct input_ctx *, const char *); 143 static void input_osc_104(struct input_ctx *, const char *); 144 static void input_osc_110(struct input_ctx *, const char *); 145 static void input_osc_111(struct input_ctx *, const char *); 146 static void input_osc_112(struct input_ctx *, const char *); 147 static void input_osc_133(struct input_ctx *, const char *); 148 149 /* Transition entry/exit handlers. */ 150 static void input_clear(struct input_ctx *); 151 static void input_ground(struct input_ctx *); 152 static void input_enter_dcs(struct input_ctx *); 153 static void input_enter_osc(struct input_ctx *); 154 static void input_exit_osc(struct input_ctx *); 155 static void input_enter_apc(struct input_ctx *); 156 static void input_exit_apc(struct input_ctx *); 157 static void input_enter_rename(struct input_ctx *); 158 static void input_exit_rename(struct input_ctx *); 159 160 /* Input state handlers. */ 161 static int input_print(struct input_ctx *); 162 static int input_intermediate(struct input_ctx *); 163 static int input_parameter(struct input_ctx *); 164 static int input_input(struct input_ctx *); 165 static int input_c0_dispatch(struct input_ctx *); 166 static int input_esc_dispatch(struct input_ctx *); 167 static int input_csi_dispatch(struct input_ctx *); 168 static void input_csi_dispatch_rm(struct input_ctx *); 169 static void input_csi_dispatch_rm_private(struct input_ctx *); 170 static void input_csi_dispatch_sm(struct input_ctx *); 171 static void input_csi_dispatch_sm_private(struct input_ctx *); 172 static void input_csi_dispatch_sm_graphics(struct input_ctx *); 173 static void input_csi_dispatch_winops(struct input_ctx *); 174 static void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *); 175 static void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *); 176 static void input_csi_dispatch_sgr(struct input_ctx *); 177 static int input_dcs_dispatch(struct input_ctx *); 178 static int input_top_bit_set(struct input_ctx *); 179 static int input_end_bel(struct input_ctx *); 180 181 /* Command table comparison function. */ 182 static int input_table_compare(const void *, const void *); 183 184 /* Command table entry. */ 185 struct input_table_entry { 186 int ch; 187 const char *interm; 188 int type; 189 }; 190 191 /* Escape commands. */ 192 enum input_esc_type { 193 INPUT_ESC_DECALN, 194 INPUT_ESC_DECKPAM, 195 INPUT_ESC_DECKPNM, 196 INPUT_ESC_DECRC, 197 INPUT_ESC_DECSC, 198 INPUT_ESC_HTS, 199 INPUT_ESC_IND, 200 INPUT_ESC_NEL, 201 INPUT_ESC_RI, 202 INPUT_ESC_RIS, 203 INPUT_ESC_SCSG0_OFF, 204 INPUT_ESC_SCSG0_ON, 205 INPUT_ESC_SCSG1_OFF, 206 INPUT_ESC_SCSG1_ON, 207 INPUT_ESC_ST 208 }; 209 210 /* Escape command table. */ 211 static const struct input_table_entry input_esc_table[] = { 212 { '0', "(", INPUT_ESC_SCSG0_ON }, 213 { '0', ")", INPUT_ESC_SCSG1_ON }, 214 { '7', "", INPUT_ESC_DECSC }, 215 { '8', "", INPUT_ESC_DECRC }, 216 { '8', "#", INPUT_ESC_DECALN }, 217 { '=', "", INPUT_ESC_DECKPAM }, 218 { '>', "", INPUT_ESC_DECKPNM }, 219 { 'B', "(", INPUT_ESC_SCSG0_OFF }, 220 { 'B', ")", INPUT_ESC_SCSG1_OFF }, 221 { 'D', "", INPUT_ESC_IND }, 222 { 'E', "", INPUT_ESC_NEL }, 223 { 'H', "", INPUT_ESC_HTS }, 224 { 'M', "", INPUT_ESC_RI }, 225 { '\\', "", INPUT_ESC_ST }, 226 { 'c', "", INPUT_ESC_RIS }, 227 }; 228 229 /* Control (CSI) commands. */ 230 enum input_csi_type { 231 INPUT_CSI_CBT, 232 INPUT_CSI_CNL, 233 INPUT_CSI_CPL, 234 INPUT_CSI_CUB, 235 INPUT_CSI_CUD, 236 INPUT_CSI_CUF, 237 INPUT_CSI_CUP, 238 INPUT_CSI_CUU, 239 INPUT_CSI_DA, 240 INPUT_CSI_DA_TWO, 241 INPUT_CSI_DCH, 242 INPUT_CSI_DECSCUSR, 243 INPUT_CSI_DECSTBM, 244 INPUT_CSI_DL, 245 INPUT_CSI_DSR, 246 INPUT_CSI_ECH, 247 INPUT_CSI_ED, 248 INPUT_CSI_EL, 249 INPUT_CSI_HPA, 250 INPUT_CSI_ICH, 251 INPUT_CSI_IL, 252 INPUT_CSI_MODOFF, 253 INPUT_CSI_MODSET, 254 INPUT_CSI_RCP, 255 INPUT_CSI_REP, 256 INPUT_CSI_RM, 257 INPUT_CSI_RM_PRIVATE, 258 INPUT_CSI_SCP, 259 INPUT_CSI_SD, 260 INPUT_CSI_SGR, 261 INPUT_CSI_SM, 262 INPUT_CSI_SM_PRIVATE, 263 INPUT_CSI_SM_GRAPHICS, 264 INPUT_CSI_SU, 265 INPUT_CSI_TBC, 266 INPUT_CSI_VPA, 267 INPUT_CSI_WINOPS, 268 INPUT_CSI_XDA 269 }; 270 271 /* Control (CSI) command table. */ 272 static const struct input_table_entry input_csi_table[] = { 273 { '@', "", INPUT_CSI_ICH }, 274 { 'A', "", INPUT_CSI_CUU }, 275 { 'B', "", INPUT_CSI_CUD }, 276 { 'C', "", INPUT_CSI_CUF }, 277 { 'D', "", INPUT_CSI_CUB }, 278 { 'E', "", INPUT_CSI_CNL }, 279 { 'F', "", INPUT_CSI_CPL }, 280 { 'G', "", INPUT_CSI_HPA }, 281 { 'H', "", INPUT_CSI_CUP }, 282 { 'J', "", INPUT_CSI_ED }, 283 { 'K', "", INPUT_CSI_EL }, 284 { 'L', "", INPUT_CSI_IL }, 285 { 'M', "", INPUT_CSI_DL }, 286 { 'P', "", INPUT_CSI_DCH }, 287 { 'S', "", INPUT_CSI_SU }, 288 { 'S', "?", INPUT_CSI_SM_GRAPHICS }, 289 { 'T', "", INPUT_CSI_SD }, 290 { 'X', "", INPUT_CSI_ECH }, 291 { 'Z', "", INPUT_CSI_CBT }, 292 { '`', "", INPUT_CSI_HPA }, 293 { 'b', "", INPUT_CSI_REP }, 294 { 'c', "", INPUT_CSI_DA }, 295 { 'c', ">", INPUT_CSI_DA_TWO }, 296 { 'd', "", INPUT_CSI_VPA }, 297 { 'f', "", INPUT_CSI_CUP }, 298 { 'g', "", INPUT_CSI_TBC }, 299 { 'h', "", INPUT_CSI_SM }, 300 { 'h', "?", INPUT_CSI_SM_PRIVATE }, 301 { 'l', "", INPUT_CSI_RM }, 302 { 'l', "?", INPUT_CSI_RM_PRIVATE }, 303 { 'm', "", INPUT_CSI_SGR }, 304 { 'm', ">", INPUT_CSI_MODSET }, 305 { 'n', "", INPUT_CSI_DSR }, 306 { 'n', ">", INPUT_CSI_MODOFF }, 307 { 'q', " ", INPUT_CSI_DECSCUSR }, 308 { 'q', ">", INPUT_CSI_XDA }, 309 { 'r', "", INPUT_CSI_DECSTBM }, 310 { 's', "", INPUT_CSI_SCP }, 311 { 't', "", INPUT_CSI_WINOPS }, 312 { 'u', "", INPUT_CSI_RCP } 313 }; 314 315 /* Input transition. */ 316 struct input_transition { 317 int first; 318 int last; 319 320 int (*handler)(struct input_ctx *); 321 const struct input_state *state; 322 }; 323 324 /* Input state. */ 325 struct input_state { 326 const char *name; 327 void (*enter)(struct input_ctx *); 328 void (*exit)(struct input_ctx *); 329 const struct input_transition *transitions; 330 }; 331 332 /* State transitions available from all states. */ 333 #define INPUT_STATE_ANYWHERE \ 334 { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \ 335 { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \ 336 { 0x1b, 0x1b, NULL, &input_state_esc_enter } 337 338 /* Forward declarations of state tables. */ 339 static const struct input_transition input_state_ground_table[]; 340 static const struct input_transition input_state_esc_enter_table[]; 341 static const struct input_transition input_state_esc_intermediate_table[]; 342 static const struct input_transition input_state_csi_enter_table[]; 343 static const struct input_transition input_state_csi_parameter_table[]; 344 static const struct input_transition input_state_csi_intermediate_table[]; 345 static const struct input_transition input_state_csi_ignore_table[]; 346 static const struct input_transition input_state_dcs_enter_table[]; 347 static const struct input_transition input_state_dcs_parameter_table[]; 348 static const struct input_transition input_state_dcs_intermediate_table[]; 349 static const struct input_transition input_state_dcs_handler_table[]; 350 static const struct input_transition input_state_dcs_escape_table[]; 351 static const struct input_transition input_state_dcs_ignore_table[]; 352 static const struct input_transition input_state_osc_string_table[]; 353 static const struct input_transition input_state_apc_string_table[]; 354 static const struct input_transition input_state_rename_string_table[]; 355 static const struct input_transition input_state_consume_st_table[]; 356 357 /* ground state definition. */ 358 static const struct input_state input_state_ground = { 359 "ground", 360 input_ground, NULL, 361 input_state_ground_table 362 }; 363 364 /* esc_enter state definition. */ 365 static const struct input_state input_state_esc_enter = { 366 "esc_enter", 367 input_clear, NULL, 368 input_state_esc_enter_table 369 }; 370 371 /* esc_intermediate state definition. */ 372 static const struct input_state input_state_esc_intermediate = { 373 "esc_intermediate", 374 NULL, NULL, 375 input_state_esc_intermediate_table 376 }; 377 378 /* csi_enter state definition. */ 379 static const struct input_state input_state_csi_enter = { 380 "csi_enter", 381 input_clear, NULL, 382 input_state_csi_enter_table 383 }; 384 385 /* csi_parameter state definition. */ 386 static const struct input_state input_state_csi_parameter = { 387 "csi_parameter", 388 NULL, NULL, 389 input_state_csi_parameter_table 390 }; 391 392 /* csi_intermediate state definition. */ 393 static const struct input_state input_state_csi_intermediate = { 394 "csi_intermediate", 395 NULL, NULL, 396 input_state_csi_intermediate_table 397 }; 398 399 /* csi_ignore state definition. */ 400 static const struct input_state input_state_csi_ignore = { 401 "csi_ignore", 402 NULL, NULL, 403 input_state_csi_ignore_table 404 }; 405 406 /* dcs_enter state definition. */ 407 static const struct input_state input_state_dcs_enter = { 408 "dcs_enter", 409 input_enter_dcs, NULL, 410 input_state_dcs_enter_table 411 }; 412 413 /* dcs_parameter state definition. */ 414 static const struct input_state input_state_dcs_parameter = { 415 "dcs_parameter", 416 NULL, NULL, 417 input_state_dcs_parameter_table 418 }; 419 420 /* dcs_intermediate state definition. */ 421 static const struct input_state input_state_dcs_intermediate = { 422 "dcs_intermediate", 423 NULL, NULL, 424 input_state_dcs_intermediate_table 425 }; 426 427 /* dcs_handler state definition. */ 428 static const struct input_state input_state_dcs_handler = { 429 "dcs_handler", 430 NULL, NULL, 431 input_state_dcs_handler_table 432 }; 433 434 /* dcs_escape state definition. */ 435 static const struct input_state input_state_dcs_escape = { 436 "dcs_escape", 437 NULL, NULL, 438 input_state_dcs_escape_table 439 }; 440 441 /* dcs_ignore state definition. */ 442 static const struct input_state input_state_dcs_ignore = { 443 "dcs_ignore", 444 NULL, NULL, 445 input_state_dcs_ignore_table 446 }; 447 448 /* osc_string state definition. */ 449 static const struct input_state input_state_osc_string = { 450 "osc_string", 451 input_enter_osc, input_exit_osc, 452 input_state_osc_string_table 453 }; 454 455 /* apc_string state definition. */ 456 static const struct input_state input_state_apc_string = { 457 "apc_string", 458 input_enter_apc, input_exit_apc, 459 input_state_apc_string_table 460 }; 461 462 /* rename_string state definition. */ 463 static const struct input_state input_state_rename_string = { 464 "rename_string", 465 input_enter_rename, input_exit_rename, 466 input_state_rename_string_table 467 }; 468 469 /* consume_st state definition. */ 470 static const struct input_state input_state_consume_st = { 471 "consume_st", 472 input_enter_rename, NULL, /* rename also waits for ST */ 473 input_state_consume_st_table 474 }; 475 476 /* ground state table. */ 477 static const struct input_transition input_state_ground_table[] = { 478 INPUT_STATE_ANYWHERE, 479 480 { 0x00, 0x17, input_c0_dispatch, NULL }, 481 { 0x19, 0x19, input_c0_dispatch, NULL }, 482 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 483 { 0x20, 0x7e, input_print, NULL }, 484 { 0x7f, 0x7f, NULL, NULL }, 485 { 0x80, 0xff, input_top_bit_set, NULL }, 486 487 { -1, -1, NULL, NULL } 488 }; 489 490 /* esc_enter state table. */ 491 static const struct input_transition input_state_esc_enter_table[] = { 492 INPUT_STATE_ANYWHERE, 493 494 { 0x00, 0x17, input_c0_dispatch, NULL }, 495 { 0x19, 0x19, input_c0_dispatch, NULL }, 496 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 497 { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate }, 498 { 0x30, 0x4f, input_esc_dispatch, &input_state_ground }, 499 { 0x50, 0x50, NULL, &input_state_dcs_enter }, 500 { 0x51, 0x57, input_esc_dispatch, &input_state_ground }, 501 { 0x58, 0x58, NULL, &input_state_consume_st }, 502 { 0x59, 0x59, input_esc_dispatch, &input_state_ground }, 503 { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground }, 504 { 0x5b, 0x5b, NULL, &input_state_csi_enter }, 505 { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground }, 506 { 0x5d, 0x5d, NULL, &input_state_osc_string }, 507 { 0x5e, 0x5e, NULL, &input_state_consume_st }, 508 { 0x5f, 0x5f, NULL, &input_state_apc_string }, 509 { 0x60, 0x6a, input_esc_dispatch, &input_state_ground }, 510 { 0x6b, 0x6b, NULL, &input_state_rename_string }, 511 { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground }, 512 { 0x7f, 0xff, NULL, NULL }, 513 514 { -1, -1, NULL, NULL } 515 }; 516 517 /* esc_intermediate state table. */ 518 static const struct input_transition input_state_esc_intermediate_table[] = { 519 INPUT_STATE_ANYWHERE, 520 521 { 0x00, 0x17, input_c0_dispatch, NULL }, 522 { 0x19, 0x19, input_c0_dispatch, NULL }, 523 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 524 { 0x20, 0x2f, input_intermediate, NULL }, 525 { 0x30, 0x7e, input_esc_dispatch, &input_state_ground }, 526 { 0x7f, 0xff, NULL, NULL }, 527 528 { -1, -1, NULL, NULL } 529 }; 530 531 /* csi_enter state table. */ 532 static const struct input_transition input_state_csi_enter_table[] = { 533 INPUT_STATE_ANYWHERE, 534 535 { 0x00, 0x17, input_c0_dispatch, NULL }, 536 { 0x19, 0x19, input_c0_dispatch, NULL }, 537 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 538 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate }, 539 { 0x30, 0x39, input_parameter, &input_state_csi_parameter }, 540 { 0x3a, 0x3a, input_parameter, &input_state_csi_parameter }, 541 { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter }, 542 { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter }, 543 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, 544 { 0x7f, 0xff, NULL, NULL }, 545 546 { -1, -1, NULL, NULL } 547 }; 548 549 /* csi_parameter state table. */ 550 static const struct input_transition input_state_csi_parameter_table[] = { 551 INPUT_STATE_ANYWHERE, 552 553 { 0x00, 0x17, input_c0_dispatch, NULL }, 554 { 0x19, 0x19, input_c0_dispatch, NULL }, 555 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 556 { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate }, 557 { 0x30, 0x39, input_parameter, NULL }, 558 { 0x3a, 0x3a, input_parameter, NULL }, 559 { 0x3b, 0x3b, input_parameter, NULL }, 560 { 0x3c, 0x3f, NULL, &input_state_csi_ignore }, 561 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, 562 { 0x7f, 0xff, NULL, NULL }, 563 564 { -1, -1, NULL, NULL } 565 }; 566 567 /* csi_intermediate state table. */ 568 static const struct input_transition input_state_csi_intermediate_table[] = { 569 INPUT_STATE_ANYWHERE, 570 571 { 0x00, 0x17, input_c0_dispatch, NULL }, 572 { 0x19, 0x19, input_c0_dispatch, NULL }, 573 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 574 { 0x20, 0x2f, input_intermediate, NULL }, 575 { 0x30, 0x3f, NULL, &input_state_csi_ignore }, 576 { 0x40, 0x7e, input_csi_dispatch, &input_state_ground }, 577 { 0x7f, 0xff, NULL, NULL }, 578 579 { -1, -1, NULL, NULL } 580 }; 581 582 /* csi_ignore state table. */ 583 static const struct input_transition input_state_csi_ignore_table[] = { 584 INPUT_STATE_ANYWHERE, 585 586 { 0x00, 0x17, input_c0_dispatch, NULL }, 587 { 0x19, 0x19, input_c0_dispatch, NULL }, 588 { 0x1c, 0x1f, input_c0_dispatch, NULL }, 589 { 0x20, 0x3f, NULL, NULL }, 590 { 0x40, 0x7e, NULL, &input_state_ground }, 591 { 0x7f, 0xff, NULL, NULL }, 592 593 { -1, -1, NULL, NULL } 594 }; 595 596 /* dcs_enter state table. */ 597 static const struct input_transition input_state_dcs_enter_table[] = { 598 INPUT_STATE_ANYWHERE, 599 600 { 0x00, 0x17, NULL, NULL }, 601 { 0x19, 0x19, NULL, NULL }, 602 { 0x1c, 0x1f, NULL, NULL }, 603 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate }, 604 { 0x30, 0x39, input_parameter, &input_state_dcs_parameter }, 605 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore }, 606 { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter }, 607 { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter }, 608 { 0x40, 0x7e, input_input, &input_state_dcs_handler }, 609 { 0x7f, 0xff, NULL, NULL }, 610 611 { -1, -1, NULL, NULL } 612 }; 613 614 /* dcs_parameter state table. */ 615 static const struct input_transition input_state_dcs_parameter_table[] = { 616 INPUT_STATE_ANYWHERE, 617 618 { 0x00, 0x17, NULL, NULL }, 619 { 0x19, 0x19, NULL, NULL }, 620 { 0x1c, 0x1f, NULL, NULL }, 621 { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate }, 622 { 0x30, 0x39, input_parameter, NULL }, 623 { 0x3a, 0x3a, NULL, &input_state_dcs_ignore }, 624 { 0x3b, 0x3b, input_parameter, NULL }, 625 { 0x3c, 0x3f, NULL, &input_state_dcs_ignore }, 626 { 0x40, 0x7e, input_input, &input_state_dcs_handler }, 627 { 0x7f, 0xff, NULL, NULL }, 628 629 { -1, -1, NULL, NULL } 630 }; 631 632 /* dcs_intermediate state table. */ 633 static const struct input_transition input_state_dcs_intermediate_table[] = { 634 INPUT_STATE_ANYWHERE, 635 636 { 0x00, 0x17, NULL, NULL }, 637 { 0x19, 0x19, NULL, NULL }, 638 { 0x1c, 0x1f, NULL, NULL }, 639 { 0x20, 0x2f, input_intermediate, NULL }, 640 { 0x30, 0x3f, NULL, &input_state_dcs_ignore }, 641 { 0x40, 0x7e, input_input, &input_state_dcs_handler }, 642 { 0x7f, 0xff, NULL, NULL }, 643 644 { -1, -1, NULL, NULL } 645 }; 646 647 /* dcs_handler state table. */ 648 static const struct input_transition input_state_dcs_handler_table[] = { 649 /* No INPUT_STATE_ANYWHERE */ 650 651 { 0x00, 0x1a, input_input, NULL }, 652 { 0x1b, 0x1b, NULL, &input_state_dcs_escape }, 653 { 0x1c, 0xff, input_input, NULL }, 654 655 { -1, -1, NULL, NULL } 656 }; 657 658 /* dcs_escape state table. */ 659 static const struct input_transition input_state_dcs_escape_table[] = { 660 /* No INPUT_STATE_ANYWHERE */ 661 662 { 0x00, 0x5b, input_input, &input_state_dcs_handler }, 663 { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground }, 664 { 0x5d, 0xff, input_input, &input_state_dcs_handler }, 665 666 { -1, -1, NULL, NULL } 667 }; 668 669 /* dcs_ignore state table. */ 670 static const struct input_transition input_state_dcs_ignore_table[] = { 671 INPUT_STATE_ANYWHERE, 672 673 { 0x00, 0x17, NULL, NULL }, 674 { 0x19, 0x19, NULL, NULL }, 675 { 0x1c, 0x1f, NULL, NULL }, 676 { 0x20, 0xff, NULL, NULL }, 677 678 { -1, -1, NULL, NULL } 679 }; 680 681 /* osc_string state table. */ 682 static const struct input_transition input_state_osc_string_table[] = { 683 INPUT_STATE_ANYWHERE, 684 685 { 0x00, 0x06, NULL, NULL }, 686 { 0x07, 0x07, input_end_bel, &input_state_ground }, 687 { 0x08, 0x17, NULL, NULL }, 688 { 0x19, 0x19, NULL, NULL }, 689 { 0x1c, 0x1f, NULL, NULL }, 690 { 0x20, 0xff, input_input, NULL }, 691 692 { -1, -1, NULL, NULL } 693 }; 694 695 /* apc_string state table. */ 696 static const struct input_transition input_state_apc_string_table[] = { 697 INPUT_STATE_ANYWHERE, 698 699 { 0x00, 0x17, NULL, NULL }, 700 { 0x19, 0x19, NULL, NULL }, 701 { 0x1c, 0x1f, NULL, NULL }, 702 { 0x20, 0xff, input_input, NULL }, 703 704 { -1, -1, NULL, NULL } 705 }; 706 707 /* rename_string state table. */ 708 static const struct input_transition input_state_rename_string_table[] = { 709 INPUT_STATE_ANYWHERE, 710 711 { 0x00, 0x17, NULL, NULL }, 712 { 0x19, 0x19, NULL, NULL }, 713 { 0x1c, 0x1f, NULL, NULL }, 714 { 0x20, 0xff, input_input, NULL }, 715 716 { -1, -1, NULL, NULL } 717 }; 718 719 /* consume_st state table. */ 720 static const struct input_transition input_state_consume_st_table[] = { 721 INPUT_STATE_ANYWHERE, 722 723 { 0x00, 0x17, NULL, NULL }, 724 { 0x19, 0x19, NULL, NULL }, 725 { 0x1c, 0x1f, NULL, NULL }, 726 { 0x20, 0xff, NULL, NULL }, 727 728 { -1, -1, NULL, NULL } 729 }; 730 731 /* Maximum of bytes allowed to read in a single input. */ 732 static size_t input_buffer_size = INPUT_BUF_DEFAULT_SIZE; 733 734 /* Input table compare. */ 735 static int 736 input_table_compare(const void *key, const void *value) 737 { 738 const struct input_ctx *ictx = key; 739 const struct input_table_entry *entry = value; 740 741 if (ictx->ch != entry->ch) 742 return (ictx->ch - entry->ch); 743 return (strcmp(ictx->interm_buf, entry->interm)); 744 } 745 746 /* 747 * Timer - if this expires then have been waiting for a terminator for too 748 * long, so reset to ground. 749 */ 750 static void 751 input_timer_callback(__unused int fd, __unused short events, void *arg) 752 { 753 struct input_ctx *ictx = arg; 754 755 log_debug("%s: %s expired" , __func__, ictx->state->name); 756 input_reset(ictx, 0); 757 } 758 759 /* Start the timer. */ 760 static void 761 input_start_timer(struct input_ctx *ictx) 762 { 763 struct timeval tv = { .tv_sec = 5, .tv_usec = 0 }; 764 765 event_del(&ictx->timer); 766 event_add(&ictx->timer, &tv); 767 } 768 769 /* Reset cell state to default. */ 770 static void 771 input_reset_cell(struct input_ctx *ictx) 772 { 773 memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell); 774 ictx->cell.set = 0; 775 ictx->cell.g0set = ictx->cell.g1set = 0; 776 777 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); 778 ictx->old_cx = 0; 779 ictx->old_cy = 0; 780 } 781 782 /* Save screen state. */ 783 static void 784 input_save_state(struct input_ctx *ictx) 785 { 786 struct screen_write_ctx *sctx = &ictx->ctx; 787 struct screen *s = sctx->s; 788 789 memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell); 790 ictx->old_cx = s->cx; 791 ictx->old_cy = s->cy; 792 ictx->old_mode = s->mode; 793 } 794 795 /* Restore screen state. */ 796 static void 797 input_restore_state(struct input_ctx *ictx) 798 { 799 struct screen_write_ctx *sctx = &ictx->ctx; 800 801 memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell); 802 if (ictx->old_mode & MODE_ORIGIN) 803 screen_write_mode_set(sctx, MODE_ORIGIN); 804 else 805 screen_write_mode_clear(sctx, MODE_ORIGIN); 806 screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy, 0); 807 } 808 809 /* Initialise input parser. */ 810 struct input_ctx * 811 input_init(struct window_pane *wp, struct bufferevent *bev, 812 struct colour_palette *palette) 813 { 814 struct input_ctx *ictx; 815 816 ictx = xcalloc(1, sizeof *ictx); 817 ictx->wp = wp; 818 ictx->event = bev; 819 ictx->palette = palette; 820 821 ictx->input_space = INPUT_BUF_START; 822 ictx->input_buf = xmalloc(INPUT_BUF_START); 823 824 ictx->since_ground = evbuffer_new(); 825 if (ictx->since_ground == NULL) 826 fatalx("out of memory"); 827 828 evtimer_set(&ictx->timer, input_timer_callback, ictx); 829 830 input_reset(ictx, 0); 831 return (ictx); 832 } 833 834 /* Destroy input parser. */ 835 void 836 input_free(struct input_ctx *ictx) 837 { 838 u_int i; 839 840 for (i = 0; i < ictx->param_list_len; i++) { 841 if (ictx->param_list[i].type == INPUT_STRING) 842 free(ictx->param_list[i].str); 843 } 844 845 event_del(&ictx->timer); 846 847 free(ictx->input_buf); 848 evbuffer_free(ictx->since_ground); 849 850 free(ictx); 851 } 852 853 /* Reset input state and clear screen. */ 854 void 855 input_reset(struct input_ctx *ictx, int clear) 856 { 857 struct screen_write_ctx *sctx = &ictx->ctx; 858 struct window_pane *wp = ictx->wp; 859 860 input_reset_cell(ictx); 861 862 if (clear && wp != NULL) { 863 if (TAILQ_EMPTY(&wp->modes)) 864 screen_write_start_pane(sctx, wp, &wp->base); 865 else 866 screen_write_start(sctx, &wp->base); 867 screen_write_reset(sctx); 868 screen_write_stop(sctx); 869 } 870 871 input_clear(ictx); 872 873 ictx->state = &input_state_ground; 874 ictx->flags = 0; 875 } 876 877 /* Return pending data. */ 878 struct evbuffer * 879 input_pending(struct input_ctx *ictx) 880 { 881 return (ictx->since_ground); 882 } 883 884 /* Change input state. */ 885 static void 886 input_set_state(struct input_ctx *ictx, const struct input_transition *itr) 887 { 888 if (ictx->state->exit != NULL) 889 ictx->state->exit(ictx); 890 ictx->state = itr->state; 891 if (ictx->state->enter != NULL) 892 ictx->state->enter(ictx); 893 } 894 895 /* Parse data. */ 896 static void 897 input_parse(struct input_ctx *ictx, u_char *buf, size_t len) 898 { 899 struct screen_write_ctx *sctx = &ictx->ctx; 900 const struct input_state *state = NULL; 901 const struct input_transition *itr = NULL; 902 size_t off = 0; 903 904 /* Parse the input. */ 905 while (off < len) { 906 ictx->ch = buf[off++]; 907 908 /* Find the transition. */ 909 if (ictx->state != state || 910 itr == NULL || 911 ictx->ch < itr->first || 912 ictx->ch > itr->last) { 913 itr = ictx->state->transitions; 914 while (itr->first != -1 && itr->last != -1) { 915 if (ictx->ch >= itr->first && 916 ictx->ch <= itr->last) 917 break; 918 itr++; 919 } 920 if (itr->first == -1 || itr->last == -1) { 921 /* No transition? Eh? */ 922 fatalx("no transition from state"); 923 } 924 } 925 state = ictx->state; 926 927 /* 928 * Any state except print stops the current collection. This is 929 * an optimization to avoid checking if the attributes have 930 * changed for every character. It will stop unnecessarily for 931 * sequences that don't make a terminal change, but they should 932 * be the minority. 933 */ 934 if (itr->handler != input_print) 935 screen_write_collect_end(sctx); 936 937 /* 938 * Execute the handler, if any. Don't switch state if it 939 * returns non-zero. 940 */ 941 if (itr->handler != NULL && itr->handler(ictx) != 0) 942 continue; 943 944 /* And switch state, if necessary. */ 945 if (itr->state != NULL) 946 input_set_state(ictx, itr); 947 948 /* If not in ground state, save input. */ 949 if (ictx->state != &input_state_ground) 950 evbuffer_add(ictx->since_ground, &ictx->ch, 1); 951 } 952 } 953 954 /* Parse input from pane. */ 955 void 956 input_parse_pane(struct window_pane *wp) 957 { 958 void *new_data; 959 size_t new_size; 960 961 new_data = window_pane_get_new_data(wp, &wp->offset, &new_size); 962 input_parse_buffer(wp, new_data, new_size); 963 window_pane_update_used_data(wp, &wp->offset, new_size); 964 } 965 966 /* Parse given input. */ 967 void 968 input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len) 969 { 970 struct input_ctx *ictx = wp->ictx; 971 struct screen_write_ctx *sctx = &ictx->ctx; 972 973 if (len == 0) 974 return; 975 976 window_update_activity(wp->window); 977 wp->flags |= PANE_CHANGED; 978 979 /* Flag new input while in a mode. */ 980 if (!TAILQ_EMPTY(&wp->modes)) 981 wp->flags |= PANE_UNSEENCHANGES; 982 983 /* NULL wp if there is a mode set as don't want to update the tty. */ 984 if (TAILQ_EMPTY(&wp->modes)) 985 screen_write_start_pane(sctx, wp, &wp->base); 986 else 987 screen_write_start(sctx, &wp->base); 988 989 log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id, 990 ictx->state->name, len, (int)len, buf); 991 992 input_parse(ictx, buf, len); 993 screen_write_stop(sctx); 994 } 995 996 /* Parse given input for screen. */ 997 void 998 input_parse_screen(struct input_ctx *ictx, struct screen *s, 999 screen_write_init_ctx_cb cb, void *arg, u_char *buf, size_t len) 1000 { 1001 struct screen_write_ctx *sctx = &ictx->ctx; 1002 1003 if (len == 0) 1004 return; 1005 1006 screen_write_start_callback(sctx, s, cb, arg); 1007 input_parse(ictx, buf, len); 1008 screen_write_stop(sctx); 1009 } 1010 1011 /* Split the parameter list (if any). */ 1012 static int 1013 input_split(struct input_ctx *ictx) 1014 { 1015 const char *errstr; 1016 char *ptr, *out; 1017 struct input_param *ip; 1018 u_int i; 1019 1020 for (i = 0; i < ictx->param_list_len; i++) { 1021 if (ictx->param_list[i].type == INPUT_STRING) 1022 free(ictx->param_list[i].str); 1023 } 1024 ictx->param_list_len = 0; 1025 1026 if (ictx->param_len == 0) 1027 return (0); 1028 ip = &ictx->param_list[0]; 1029 1030 ptr = ictx->param_buf; 1031 while ((out = strsep(&ptr, ";")) != NULL) { 1032 if (*out == '\0') 1033 ip->type = INPUT_MISSING; 1034 else { 1035 if (strchr(out, ':') != NULL) { 1036 ip->type = INPUT_STRING; 1037 ip->str = xstrdup(out); 1038 } else { 1039 ip->type = INPUT_NUMBER; 1040 ip->num = strtonum(out, 0, INT_MAX, &errstr); 1041 if (errstr != NULL) 1042 return (-1); 1043 } 1044 } 1045 ip = &ictx->param_list[++ictx->param_list_len]; 1046 if (ictx->param_list_len == nitems(ictx->param_list)) 1047 return (-1); 1048 } 1049 1050 for (i = 0; i < ictx->param_list_len; i++) { 1051 ip = &ictx->param_list[i]; 1052 if (ip->type == INPUT_MISSING) 1053 log_debug("parameter %u: missing", i); 1054 else if (ip->type == INPUT_STRING) 1055 log_debug("parameter %u: string %s", i, ip->str); 1056 else if (ip->type == INPUT_NUMBER) 1057 log_debug("parameter %u: number %d", i, ip->num); 1058 } 1059 1060 return (0); 1061 } 1062 1063 /* Get an argument or return default value. */ 1064 static int 1065 input_get(struct input_ctx *ictx, u_int validx, int minval, int defval) 1066 { 1067 struct input_param *ip; 1068 int retval; 1069 1070 if (validx >= ictx->param_list_len) 1071 return (defval); 1072 ip = &ictx->param_list[validx]; 1073 if (ip->type == INPUT_MISSING) 1074 return (defval); 1075 if (ip->type == INPUT_STRING) 1076 return (-1); 1077 retval = ip->num; 1078 if (retval < minval) 1079 return (minval); 1080 return (retval); 1081 } 1082 1083 /* Reply to terminal query. */ 1084 static void 1085 input_reply(struct input_ctx *ictx, const char *fmt, ...) 1086 { 1087 struct bufferevent *bev = ictx->event; 1088 va_list ap; 1089 char *reply; 1090 1091 if (bev == NULL) 1092 return; 1093 1094 va_start(ap, fmt); 1095 xvasprintf(&reply, fmt, ap); 1096 va_end(ap); 1097 1098 log_debug("%s: %s", __func__, reply); 1099 bufferevent_write(bev, reply, strlen(reply)); 1100 free(reply); 1101 } 1102 1103 /* Clear saved state. */ 1104 static void 1105 input_clear(struct input_ctx *ictx) 1106 { 1107 event_del(&ictx->timer); 1108 1109 *ictx->interm_buf = '\0'; 1110 ictx->interm_len = 0; 1111 1112 *ictx->param_buf = '\0'; 1113 ictx->param_len = 0; 1114 1115 *ictx->input_buf = '\0'; 1116 ictx->input_len = 0; 1117 1118 ictx->input_end = INPUT_END_ST; 1119 1120 ictx->flags &= ~INPUT_DISCARD; 1121 } 1122 1123 /* Reset for ground state. */ 1124 static void 1125 input_ground(struct input_ctx *ictx) 1126 { 1127 event_del(&ictx->timer); 1128 evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground)); 1129 1130 if (ictx->input_space > INPUT_BUF_START) { 1131 ictx->input_space = INPUT_BUF_START; 1132 ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START); 1133 } 1134 } 1135 1136 /* Output this character to the screen. */ 1137 static int 1138 input_print(struct input_ctx *ictx) 1139 { 1140 struct screen_write_ctx *sctx = &ictx->ctx; 1141 int set; 1142 1143 ictx->utf8started = 0; /* can't be valid UTF-8 */ 1144 1145 set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set; 1146 if (set == 1) 1147 ictx->cell.cell.attr |= GRID_ATTR_CHARSET; 1148 else 1149 ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET; 1150 utf8_set(&ictx->cell.cell.data, ictx->ch); 1151 screen_write_collect_add(sctx, &ictx->cell.cell); 1152 1153 utf8_copy(&ictx->last, &ictx->cell.cell.data); 1154 ictx->flags |= INPUT_LAST; 1155 1156 ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET; 1157 1158 return (0); 1159 } 1160 1161 /* Collect intermediate string. */ 1162 static int 1163 input_intermediate(struct input_ctx *ictx) 1164 { 1165 if (ictx->interm_len == (sizeof ictx->interm_buf) - 1) 1166 ictx->flags |= INPUT_DISCARD; 1167 else { 1168 ictx->interm_buf[ictx->interm_len++] = ictx->ch; 1169 ictx->interm_buf[ictx->interm_len] = '\0'; 1170 } 1171 1172 return (0); 1173 } 1174 1175 /* Collect parameter string. */ 1176 static int 1177 input_parameter(struct input_ctx *ictx) 1178 { 1179 if (ictx->param_len == (sizeof ictx->param_buf) - 1) 1180 ictx->flags |= INPUT_DISCARD; 1181 else { 1182 ictx->param_buf[ictx->param_len++] = ictx->ch; 1183 ictx->param_buf[ictx->param_len] = '\0'; 1184 } 1185 1186 return (0); 1187 } 1188 1189 /* Collect input string. */ 1190 static int 1191 input_input(struct input_ctx *ictx) 1192 { 1193 size_t available; 1194 1195 available = ictx->input_space; 1196 while (ictx->input_len + 1 >= available) { 1197 available *= 2; 1198 if (available > input_buffer_size) { 1199 ictx->flags |= INPUT_DISCARD; 1200 return (0); 1201 } 1202 ictx->input_buf = xrealloc(ictx->input_buf, available); 1203 ictx->input_space = available; 1204 } 1205 ictx->input_buf[ictx->input_len++] = ictx->ch; 1206 ictx->input_buf[ictx->input_len] = '\0'; 1207 1208 return (0); 1209 } 1210 1211 /* Execute C0 control sequence. */ 1212 static int 1213 input_c0_dispatch(struct input_ctx *ictx) 1214 { 1215 struct screen_write_ctx *sctx = &ictx->ctx; 1216 struct window_pane *wp = ictx->wp; 1217 struct screen *s = sctx->s; 1218 struct grid_cell gc, first_gc; 1219 u_int cx = s->cx, line = s->cy + s->grid->hsize; 1220 u_int width; 1221 int has_content = 0; 1222 1223 ictx->utf8started = 0; /* can't be valid UTF-8 */ 1224 1225 log_debug("%s: '%c'", __func__, ictx->ch); 1226 1227 switch (ictx->ch) { 1228 case '\000': /* NUL */ 1229 break; 1230 case '\007': /* BEL */ 1231 if (wp != NULL) 1232 alerts_queue(wp->window, WINDOW_BELL); 1233 break; 1234 case '\010': /* BS */ 1235 screen_write_backspace(sctx); 1236 break; 1237 case '\011': /* HT */ 1238 /* Don't tab beyond the end of the line. */ 1239 if (s->cx >= screen_size_x(s) - 1) 1240 break; 1241 1242 /* Find the next tab point, or use the last column if none. */ 1243 grid_get_cell(s->grid, s->cx, line, &first_gc); 1244 do { 1245 if (!has_content) { 1246 grid_get_cell(s->grid, cx, line, &gc); 1247 if (gc.data.size != 1 || 1248 *gc.data.data != ' ' || 1249 !grid_cells_look_equal(&gc, &first_gc)) 1250 has_content = 1; 1251 } 1252 cx++; 1253 if (bit_test(s->tabs, cx)) 1254 break; 1255 } while (cx < screen_size_x(s) - 1); 1256 1257 width = cx - s->cx; 1258 if (has_content || width > sizeof gc.data.data) 1259 s->cx = cx; 1260 else { 1261 grid_get_cell(s->grid, s->cx, line, &gc); 1262 grid_set_tab(&gc, width); 1263 screen_write_collect_add(sctx, &gc); 1264 } 1265 break; 1266 case '\012': /* LF */ 1267 case '\013': /* VT */ 1268 case '\014': /* FF */ 1269 screen_write_linefeed(sctx, 0, ictx->cell.cell.bg); 1270 if (s->mode & MODE_CRLF) 1271 screen_write_carriagereturn(sctx); 1272 break; 1273 case '\015': /* CR */ 1274 screen_write_carriagereturn(sctx); 1275 break; 1276 case '\016': /* SO */ 1277 ictx->cell.set = 1; 1278 break; 1279 case '\017': /* SI */ 1280 ictx->cell.set = 0; 1281 break; 1282 default: 1283 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1284 break; 1285 } 1286 1287 ictx->flags &= ~INPUT_LAST; 1288 return (0); 1289 } 1290 1291 /* Execute escape sequence. */ 1292 static int 1293 input_esc_dispatch(struct input_ctx *ictx) 1294 { 1295 struct screen_write_ctx *sctx = &ictx->ctx; 1296 struct screen *s = sctx->s; 1297 struct input_table_entry *entry; 1298 1299 if (ictx->flags & INPUT_DISCARD) 1300 return (0); 1301 log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf); 1302 1303 entry = bsearch(ictx, input_esc_table, nitems(input_esc_table), 1304 sizeof input_esc_table[0], input_table_compare); 1305 if (entry == NULL) { 1306 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1307 return (0); 1308 } 1309 1310 switch (entry->type) { 1311 case INPUT_ESC_RIS: 1312 colour_palette_clear(ictx->palette); 1313 input_reset_cell(ictx); 1314 screen_write_reset(sctx); 1315 screen_write_fullredraw(sctx); 1316 break; 1317 case INPUT_ESC_IND: 1318 screen_write_linefeed(sctx, 0, ictx->cell.cell.bg); 1319 break; 1320 case INPUT_ESC_NEL: 1321 screen_write_carriagereturn(sctx); 1322 screen_write_linefeed(sctx, 0, ictx->cell.cell.bg); 1323 break; 1324 case INPUT_ESC_HTS: 1325 if (s->cx < screen_size_x(s)) 1326 bit_set(s->tabs, s->cx); 1327 break; 1328 case INPUT_ESC_RI: 1329 screen_write_reverseindex(sctx, ictx->cell.cell.bg); 1330 break; 1331 case INPUT_ESC_DECKPAM: 1332 screen_write_mode_set(sctx, MODE_KKEYPAD); 1333 break; 1334 case INPUT_ESC_DECKPNM: 1335 screen_write_mode_clear(sctx, MODE_KKEYPAD); 1336 break; 1337 case INPUT_ESC_DECSC: 1338 input_save_state(ictx); 1339 break; 1340 case INPUT_ESC_DECRC: 1341 input_restore_state(ictx); 1342 break; 1343 case INPUT_ESC_DECALN: 1344 screen_write_alignmenttest(sctx); 1345 break; 1346 case INPUT_ESC_SCSG0_ON: 1347 ictx->cell.g0set = 1; 1348 break; 1349 case INPUT_ESC_SCSG0_OFF: 1350 ictx->cell.g0set = 0; 1351 break; 1352 case INPUT_ESC_SCSG1_ON: 1353 ictx->cell.g1set = 1; 1354 break; 1355 case INPUT_ESC_SCSG1_OFF: 1356 ictx->cell.g1set = 0; 1357 break; 1358 case INPUT_ESC_ST: 1359 /* ST terminates OSC but the state transition already did it. */ 1360 break; 1361 } 1362 1363 ictx->flags &= ~INPUT_LAST; 1364 return (0); 1365 } 1366 1367 /* Execute control sequence. */ 1368 static int 1369 input_csi_dispatch(struct input_ctx *ictx) 1370 { 1371 struct screen_write_ctx *sctx = &ictx->ctx; 1372 struct screen *s = sctx->s; 1373 struct input_table_entry *entry; 1374 int i, n, m, ek, set; 1375 u_int cx, bg = ictx->cell.cell.bg; 1376 1377 if (ictx->flags & INPUT_DISCARD) 1378 return (0); 1379 1380 log_debug("%s: '%c' \"%s\" \"%s\"", __func__, ictx->ch, 1381 ictx->interm_buf, ictx->param_buf); 1382 1383 if (input_split(ictx) != 0) 1384 return (0); 1385 1386 entry = bsearch(ictx, input_csi_table, nitems(input_csi_table), 1387 sizeof input_csi_table[0], input_table_compare); 1388 if (entry == NULL) { 1389 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1390 return (0); 1391 } 1392 1393 switch (entry->type) { 1394 case INPUT_CSI_CBT: 1395 /* Find the previous tab point, n times. */ 1396 cx = s->cx; 1397 if (cx > screen_size_x(s) - 1) 1398 cx = screen_size_x(s) - 1; 1399 n = input_get(ictx, 0, 1, 1); 1400 if (n == -1) 1401 break; 1402 while (cx > 0 && n-- > 0) { 1403 do 1404 cx--; 1405 while (cx > 0 && !bit_test(s->tabs, cx)); 1406 } 1407 s->cx = cx; 1408 break; 1409 case INPUT_CSI_CUB: 1410 n = input_get(ictx, 0, 1, 1); 1411 if (n != -1) 1412 screen_write_cursorleft(sctx, n); 1413 break; 1414 case INPUT_CSI_CUD: 1415 n = input_get(ictx, 0, 1, 1); 1416 if (n != -1) 1417 screen_write_cursordown(sctx, n); 1418 break; 1419 case INPUT_CSI_CUF: 1420 n = input_get(ictx, 0, 1, 1); 1421 if (n != -1) 1422 screen_write_cursorright(sctx, n); 1423 break; 1424 case INPUT_CSI_CUP: 1425 n = input_get(ictx, 0, 1, 1); 1426 m = input_get(ictx, 1, 1, 1); 1427 if (n != -1 && m != -1) 1428 screen_write_cursormove(sctx, m - 1, n - 1, 1); 1429 break; 1430 case INPUT_CSI_MODSET: 1431 n = input_get(ictx, 0, 0, 0); 1432 if (n != 4) 1433 break; 1434 m = input_get(ictx, 1, 0, 0); 1435 1436 /* 1437 * Set the extended key reporting mode as per the client 1438 * request, unless "extended-keys" is set to "off". 1439 */ 1440 ek = options_get_number(global_options, "extended-keys"); 1441 if (ek == 0) 1442 break; 1443 screen_write_mode_clear(sctx, EXTENDED_KEY_MODES); 1444 if (m == 2) 1445 screen_write_mode_set(sctx, MODE_KEYS_EXTENDED_2); 1446 else if (m == 1 || ek == 2) 1447 screen_write_mode_set(sctx, MODE_KEYS_EXTENDED); 1448 break; 1449 case INPUT_CSI_MODOFF: 1450 n = input_get(ictx, 0, 0, 0); 1451 if (n != 4) 1452 break; 1453 1454 /* 1455 * Clear the extended key reporting mode as per the client 1456 * request, unless "extended-keys always" forces into mode 1. 1457 */ 1458 screen_write_mode_clear(sctx, 1459 MODE_KEYS_EXTENDED|MODE_KEYS_EXTENDED_2); 1460 if (options_get_number(global_options, "extended-keys") == 2) 1461 screen_write_mode_set(sctx, MODE_KEYS_EXTENDED); 1462 break; 1463 case INPUT_CSI_WINOPS: 1464 input_csi_dispatch_winops(ictx); 1465 break; 1466 case INPUT_CSI_CUU: 1467 n = input_get(ictx, 0, 1, 1); 1468 if (n != -1) 1469 screen_write_cursorup(sctx, n); 1470 break; 1471 case INPUT_CSI_CNL: 1472 n = input_get(ictx, 0, 1, 1); 1473 if (n != -1) { 1474 screen_write_carriagereturn(sctx); 1475 screen_write_cursordown(sctx, n); 1476 } 1477 break; 1478 case INPUT_CSI_CPL: 1479 n = input_get(ictx, 0, 1, 1); 1480 if (n != -1) { 1481 screen_write_carriagereturn(sctx); 1482 screen_write_cursorup(sctx, n); 1483 } 1484 break; 1485 case INPUT_CSI_DA: 1486 switch (input_get(ictx, 0, 0, 0)) { 1487 case -1: 1488 break; 1489 case 0: 1490 input_reply(ictx, "\033[?1;2c"); 1491 break; 1492 default: 1493 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1494 break; 1495 } 1496 break; 1497 case INPUT_CSI_DA_TWO: 1498 switch (input_get(ictx, 0, 0, 0)) { 1499 case -1: 1500 break; 1501 case 0: 1502 input_reply(ictx, "\033[>84;0;0c"); 1503 break; 1504 default: 1505 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1506 break; 1507 } 1508 break; 1509 case INPUT_CSI_ECH: 1510 n = input_get(ictx, 0, 1, 1); 1511 if (n != -1) 1512 screen_write_clearcharacter(sctx, n, bg); 1513 break; 1514 case INPUT_CSI_DCH: 1515 n = input_get(ictx, 0, 1, 1); 1516 if (n != -1) 1517 screen_write_deletecharacter(sctx, n, bg); 1518 break; 1519 case INPUT_CSI_DECSTBM: 1520 n = input_get(ictx, 0, 1, 1); 1521 m = input_get(ictx, 1, 1, screen_size_y(s)); 1522 if (n != -1 && m != -1) 1523 screen_write_scrollregion(sctx, n - 1, m - 1); 1524 break; 1525 case INPUT_CSI_DL: 1526 n = input_get(ictx, 0, 1, 1); 1527 if (n != -1) 1528 screen_write_deleteline(sctx, n, bg); 1529 break; 1530 case INPUT_CSI_DSR: 1531 switch (input_get(ictx, 0, 0, 0)) { 1532 case -1: 1533 break; 1534 case 5: 1535 input_reply(ictx, "\033[0n"); 1536 break; 1537 case 6: 1538 input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1); 1539 break; 1540 default: 1541 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1542 break; 1543 } 1544 break; 1545 case INPUT_CSI_ED: 1546 switch (input_get(ictx, 0, 0, 0)) { 1547 case -1: 1548 break; 1549 case 0: 1550 screen_write_clearendofscreen(sctx, bg); 1551 break; 1552 case 1: 1553 screen_write_clearstartofscreen(sctx, bg); 1554 break; 1555 case 2: 1556 screen_write_clearscreen(sctx, bg); 1557 break; 1558 case 3: 1559 if (input_get(ictx, 1, 0, 0) == 0) { 1560 /* 1561 * Linux console extension to clear history 1562 * (for example before locking the screen). 1563 */ 1564 screen_write_clearhistory(sctx); 1565 } 1566 break; 1567 default: 1568 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1569 break; 1570 } 1571 break; 1572 case INPUT_CSI_EL: 1573 switch (input_get(ictx, 0, 0, 0)) { 1574 case -1: 1575 break; 1576 case 0: 1577 screen_write_clearendofline(sctx, bg); 1578 break; 1579 case 1: 1580 screen_write_clearstartofline(sctx, bg); 1581 break; 1582 case 2: 1583 screen_write_clearline(sctx, bg); 1584 break; 1585 default: 1586 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1587 break; 1588 } 1589 break; 1590 case INPUT_CSI_HPA: 1591 n = input_get(ictx, 0, 1, 1); 1592 if (n != -1) 1593 screen_write_cursormove(sctx, n - 1, -1, 1); 1594 break; 1595 case INPUT_CSI_ICH: 1596 n = input_get(ictx, 0, 1, 1); 1597 if (n != -1) 1598 screen_write_insertcharacter(sctx, n, bg); 1599 break; 1600 case INPUT_CSI_IL: 1601 n = input_get(ictx, 0, 1, 1); 1602 if (n != -1) 1603 screen_write_insertline(sctx, n, bg); 1604 break; 1605 case INPUT_CSI_REP: 1606 n = input_get(ictx, 0, 1, 1); 1607 if (n == -1) 1608 break; 1609 1610 m = screen_size_x(s) - s->cx; 1611 if (n > m) 1612 n = m; 1613 1614 if (~ictx->flags & INPUT_LAST) 1615 break; 1616 1617 set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set; 1618 if (set == 1) 1619 ictx->cell.cell.attr |= GRID_ATTR_CHARSET; 1620 else 1621 ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET; 1622 utf8_copy(&ictx->cell.cell.data, &ictx->last); 1623 for (i = 0; i < n; i++) 1624 screen_write_collect_add(sctx, &ictx->cell.cell); 1625 break; 1626 case INPUT_CSI_RCP: 1627 input_restore_state(ictx); 1628 break; 1629 case INPUT_CSI_RM: 1630 input_csi_dispatch_rm(ictx); 1631 break; 1632 case INPUT_CSI_RM_PRIVATE: 1633 input_csi_dispatch_rm_private(ictx); 1634 break; 1635 case INPUT_CSI_SCP: 1636 input_save_state(ictx); 1637 break; 1638 case INPUT_CSI_SGR: 1639 input_csi_dispatch_sgr(ictx); 1640 break; 1641 case INPUT_CSI_SM: 1642 input_csi_dispatch_sm(ictx); 1643 break; 1644 case INPUT_CSI_SM_PRIVATE: 1645 input_csi_dispatch_sm_private(ictx); 1646 break; 1647 case INPUT_CSI_SM_GRAPHICS: 1648 input_csi_dispatch_sm_graphics(ictx); 1649 break; 1650 case INPUT_CSI_SU: 1651 n = input_get(ictx, 0, 1, 1); 1652 if (n != -1) 1653 screen_write_scrollup(sctx, n, bg); 1654 break; 1655 case INPUT_CSI_SD: 1656 n = input_get(ictx, 0, 1, 1); 1657 if (n != -1) 1658 screen_write_scrolldown(sctx, n, bg); 1659 break; 1660 case INPUT_CSI_TBC: 1661 switch (input_get(ictx, 0, 0, 0)) { 1662 case -1: 1663 break; 1664 case 0: 1665 if (s->cx < screen_size_x(s)) 1666 bit_clear(s->tabs, s->cx); 1667 break; 1668 case 3: 1669 bit_nclear(s->tabs, 0, screen_size_x(s) - 1); 1670 break; 1671 default: 1672 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1673 break; 1674 } 1675 break; 1676 case INPUT_CSI_VPA: 1677 n = input_get(ictx, 0, 1, 1); 1678 if (n != -1) 1679 screen_write_cursormove(sctx, -1, n - 1, 1); 1680 break; 1681 case INPUT_CSI_DECSCUSR: 1682 n = input_get(ictx, 0, 0, 0); 1683 if (n != -1) 1684 screen_set_cursor_style(n, &s->cstyle, &s->mode); 1685 break; 1686 case INPUT_CSI_XDA: 1687 n = input_get(ictx, 0, 0, 0); 1688 if (n == 0) 1689 input_reply(ictx, "\033P>|tmux %s\033\\", getversion()); 1690 break; 1691 1692 } 1693 1694 ictx->flags &= ~INPUT_LAST; 1695 return (0); 1696 } 1697 1698 /* Handle CSI RM. */ 1699 static void 1700 input_csi_dispatch_rm(struct input_ctx *ictx) 1701 { 1702 struct screen_write_ctx *sctx = &ictx->ctx; 1703 u_int i; 1704 1705 for (i = 0; i < ictx->param_list_len; i++) { 1706 switch (input_get(ictx, i, 0, -1)) { 1707 case -1: 1708 break; 1709 case 4: /* IRM */ 1710 screen_write_mode_clear(sctx, MODE_INSERT); 1711 break; 1712 case 34: 1713 screen_write_mode_set(sctx, MODE_CURSOR_VERY_VISIBLE); 1714 break; 1715 default: 1716 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1717 break; 1718 } 1719 } 1720 } 1721 1722 /* Handle CSI private RM. */ 1723 static void 1724 input_csi_dispatch_rm_private(struct input_ctx *ictx) 1725 { 1726 struct screen_write_ctx *sctx = &ictx->ctx; 1727 struct grid_cell *gc = &ictx->cell.cell; 1728 u_int i; 1729 1730 for (i = 0; i < ictx->param_list_len; i++) { 1731 switch (input_get(ictx, i, 0, -1)) { 1732 case -1: 1733 break; 1734 case 1: /* DECCKM */ 1735 screen_write_mode_clear(sctx, MODE_KCURSOR); 1736 break; 1737 case 3: /* DECCOLM */ 1738 screen_write_cursormove(sctx, 0, 0, 1); 1739 screen_write_clearscreen(sctx, gc->bg); 1740 break; 1741 case 6: /* DECOM */ 1742 screen_write_mode_clear(sctx, MODE_ORIGIN); 1743 screen_write_cursormove(sctx, 0, 0, 1); 1744 break; 1745 case 7: /* DECAWM */ 1746 screen_write_mode_clear(sctx, MODE_WRAP); 1747 break; 1748 case 12: 1749 screen_write_mode_clear(sctx, MODE_CURSOR_BLINKING); 1750 screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET); 1751 break; 1752 case 25: /* TCEM */ 1753 screen_write_mode_clear(sctx, MODE_CURSOR); 1754 break; 1755 case 1000: 1756 case 1001: 1757 case 1002: 1758 case 1003: 1759 screen_write_mode_clear(sctx, ALL_MOUSE_MODES); 1760 break; 1761 case 1004: 1762 screen_write_mode_clear(sctx, MODE_FOCUSON); 1763 break; 1764 case 1005: 1765 screen_write_mode_clear(sctx, MODE_MOUSE_UTF8); 1766 break; 1767 case 1006: 1768 screen_write_mode_clear(sctx, MODE_MOUSE_SGR); 1769 break; 1770 case 47: 1771 case 1047: 1772 screen_write_alternateoff(sctx, gc, 0); 1773 break; 1774 case 1049: 1775 screen_write_alternateoff(sctx, gc, 1); 1776 break; 1777 case 2004: 1778 screen_write_mode_clear(sctx, MODE_BRACKETPASTE); 1779 break; 1780 default: 1781 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1782 break; 1783 } 1784 } 1785 } 1786 1787 /* Handle CSI SM. */ 1788 static void 1789 input_csi_dispatch_sm(struct input_ctx *ictx) 1790 { 1791 struct screen_write_ctx *sctx = &ictx->ctx; 1792 u_int i; 1793 1794 for (i = 0; i < ictx->param_list_len; i++) { 1795 switch (input_get(ictx, i, 0, -1)) { 1796 case -1: 1797 break; 1798 case 4: /* IRM */ 1799 screen_write_mode_set(sctx, MODE_INSERT); 1800 break; 1801 case 34: 1802 screen_write_mode_clear(sctx, MODE_CURSOR_VERY_VISIBLE); 1803 break; 1804 default: 1805 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1806 break; 1807 } 1808 } 1809 } 1810 1811 /* Handle CSI private SM. */ 1812 static void 1813 input_csi_dispatch_sm_private(struct input_ctx *ictx) 1814 { 1815 struct screen_write_ctx *sctx = &ictx->ctx; 1816 struct grid_cell *gc = &ictx->cell.cell; 1817 u_int i; 1818 1819 for (i = 0; i < ictx->param_list_len; i++) { 1820 switch (input_get(ictx, i, 0, -1)) { 1821 case -1: 1822 break; 1823 case 1: /* DECCKM */ 1824 screen_write_mode_set(sctx, MODE_KCURSOR); 1825 break; 1826 case 3: /* DECCOLM */ 1827 screen_write_cursormove(sctx, 0, 0, 1); 1828 screen_write_clearscreen(sctx, ictx->cell.cell.bg); 1829 break; 1830 case 6: /* DECOM */ 1831 screen_write_mode_set(sctx, MODE_ORIGIN); 1832 screen_write_cursormove(sctx, 0, 0, 1); 1833 break; 1834 case 7: /* DECAWM */ 1835 screen_write_mode_set(sctx, MODE_WRAP); 1836 break; 1837 case 12: 1838 screen_write_mode_set(sctx, MODE_CURSOR_BLINKING); 1839 screen_write_mode_set(sctx, MODE_CURSOR_BLINKING_SET); 1840 break; 1841 case 25: /* TCEM */ 1842 screen_write_mode_set(sctx, MODE_CURSOR); 1843 break; 1844 case 1000: 1845 screen_write_mode_clear(sctx, ALL_MOUSE_MODES); 1846 screen_write_mode_set(sctx, MODE_MOUSE_STANDARD); 1847 break; 1848 case 1002: 1849 screen_write_mode_clear(sctx, ALL_MOUSE_MODES); 1850 screen_write_mode_set(sctx, MODE_MOUSE_BUTTON); 1851 break; 1852 case 1003: 1853 screen_write_mode_clear(sctx, ALL_MOUSE_MODES); 1854 screen_write_mode_set(sctx, MODE_MOUSE_ALL); 1855 break; 1856 case 1004: 1857 screen_write_mode_set(sctx, MODE_FOCUSON); 1858 break; 1859 case 1005: 1860 screen_write_mode_set(sctx, MODE_MOUSE_UTF8); 1861 break; 1862 case 1006: 1863 screen_write_mode_set(sctx, MODE_MOUSE_SGR); 1864 break; 1865 case 47: 1866 case 1047: 1867 screen_write_alternateon(sctx, gc, 0); 1868 break; 1869 case 1049: 1870 screen_write_alternateon(sctx, gc, 1); 1871 break; 1872 case 2004: 1873 screen_write_mode_set(sctx, MODE_BRACKETPASTE); 1874 break; 1875 default: 1876 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1877 break; 1878 } 1879 } 1880 } 1881 1882 /* Handle CSI graphics SM. */ 1883 static void 1884 input_csi_dispatch_sm_graphics(__unused struct input_ctx *ictx) 1885 { 1886 } 1887 1888 /* Handle CSI window operations. */ 1889 static void 1890 input_csi_dispatch_winops(struct input_ctx *ictx) 1891 { 1892 struct screen_write_ctx *sctx = &ictx->ctx; 1893 struct screen *s = sctx->s; 1894 struct window_pane *wp = ictx->wp; 1895 struct window *w = NULL; 1896 u_int x = screen_size_x(s), y = screen_size_y(s); 1897 int n, m; 1898 1899 if (wp != NULL) 1900 w = wp->window; 1901 1902 m = 0; 1903 while ((n = input_get(ictx, m, 0, -1)) != -1) { 1904 switch (n) { 1905 case 1: 1906 case 2: 1907 case 5: 1908 case 6: 1909 case 7: 1910 case 11: 1911 case 13: 1912 case 20: 1913 case 21: 1914 case 24: 1915 break; 1916 case 3: 1917 case 4: 1918 case 8: 1919 m++; 1920 if (input_get(ictx, m, 0, -1) == -1) 1921 return; 1922 /* FALLTHROUGH */ 1923 case 9: 1924 case 10: 1925 m++; 1926 if (input_get(ictx, m, 0, -1) == -1) 1927 return; 1928 break; 1929 case 14: 1930 if (w == NULL) 1931 break; 1932 input_reply(ictx, "\033[4;%u;%ut", y * w->ypixel, 1933 x * w->xpixel); 1934 break; 1935 case 15: 1936 if (w == NULL) 1937 break; 1938 input_reply(ictx, "\033[5;%u;%ut", y * w->ypixel, 1939 x * w->xpixel); 1940 break; 1941 case 16: 1942 if (w == NULL) 1943 break; 1944 input_reply(ictx, "\033[6;%u;%ut", w->ypixel, 1945 w->xpixel); 1946 break; 1947 case 18: 1948 input_reply(ictx, "\033[8;%u;%ut", y, x); 1949 break; 1950 case 19: 1951 input_reply(ictx, "\033[9;%u;%ut", y, x); 1952 break; 1953 case 22: 1954 m++; 1955 switch (input_get(ictx, m, 0, -1)) { 1956 case -1: 1957 return; 1958 case 0: 1959 case 2: 1960 screen_push_title(sctx->s); 1961 break; 1962 } 1963 break; 1964 case 23: 1965 m++; 1966 switch (input_get(ictx, m, 0, -1)) { 1967 case -1: 1968 return; 1969 case 0: 1970 case 2: 1971 screen_pop_title(sctx->s); 1972 if (wp == NULL) 1973 break; 1974 notify_pane("pane-title-changed", wp); 1975 server_redraw_window_borders(w); 1976 server_status_window(w); 1977 break; 1978 } 1979 break; 1980 default: 1981 log_debug("%s: unknown '%c'", __func__, ictx->ch); 1982 break; 1983 } 1984 m++; 1985 } 1986 } 1987 1988 /* Helper for 256 colour SGR. */ 1989 static int 1990 input_csi_dispatch_sgr_256_do(struct input_ctx *ictx, int fgbg, int c) 1991 { 1992 struct grid_cell *gc = &ictx->cell.cell; 1993 1994 if (c == -1 || c > 255) { 1995 if (fgbg == 38) 1996 gc->fg = 8; 1997 else if (fgbg == 48) 1998 gc->bg = 8; 1999 } else { 2000 if (fgbg == 38) 2001 gc->fg = c | COLOUR_FLAG_256; 2002 else if (fgbg == 48) 2003 gc->bg = c | COLOUR_FLAG_256; 2004 else if (fgbg == 58) 2005 gc->us = c | COLOUR_FLAG_256; 2006 } 2007 return (1); 2008 } 2009 2010 /* Handle CSI SGR for 256 colours. */ 2011 static void 2012 input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i) 2013 { 2014 int c; 2015 2016 c = input_get(ictx, (*i) + 1, 0, -1); 2017 if (input_csi_dispatch_sgr_256_do(ictx, fgbg, c)) 2018 (*i)++; 2019 } 2020 2021 /* Helper for RGB colour SGR. */ 2022 static int 2023 input_csi_dispatch_sgr_rgb_do(struct input_ctx *ictx, int fgbg, int r, int g, 2024 int b) 2025 { 2026 struct grid_cell *gc = &ictx->cell.cell; 2027 2028 if (r == -1 || r > 255) 2029 return (0); 2030 if (g == -1 || g > 255) 2031 return (0); 2032 if (b == -1 || b > 255) 2033 return (0); 2034 2035 if (fgbg == 38) 2036 gc->fg = colour_join_rgb(r, g, b); 2037 else if (fgbg == 48) 2038 gc->bg = colour_join_rgb(r, g, b); 2039 else if (fgbg == 58) 2040 gc->us = colour_join_rgb(r, g, b); 2041 return (1); 2042 } 2043 2044 /* Handle CSI SGR for RGB colours. */ 2045 static void 2046 input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i) 2047 { 2048 int r, g, b; 2049 2050 r = input_get(ictx, (*i) + 1, 0, -1); 2051 g = input_get(ictx, (*i) + 2, 0, -1); 2052 b = input_get(ictx, (*i) + 3, 0, -1); 2053 if (input_csi_dispatch_sgr_rgb_do(ictx, fgbg, r, g, b)) 2054 (*i) += 3; 2055 } 2056 2057 /* Handle CSI SGR with a ISO parameter. */ 2058 static void 2059 input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i) 2060 { 2061 struct grid_cell *gc = &ictx->cell.cell; 2062 char *s = ictx->param_list[i].str, *copy, *ptr, *out; 2063 int p[8]; 2064 u_int n; 2065 const char *errstr; 2066 2067 for (n = 0; n < nitems(p); n++) 2068 p[n] = -1; 2069 n = 0; 2070 2071 ptr = copy = xstrdup(s); 2072 while ((out = strsep(&ptr, ":")) != NULL) { 2073 if (*out != '\0') { 2074 p[n++] = strtonum(out, 0, INT_MAX, &errstr); 2075 if (errstr != NULL || n == nitems(p)) { 2076 free(copy); 2077 return; 2078 } 2079 } else { 2080 n++; 2081 if (n == nitems(p)) { 2082 free(copy); 2083 return; 2084 } 2085 } 2086 log_debug("%s: %u = %d", __func__, n - 1, p[n - 1]); 2087 } 2088 free(copy); 2089 2090 if (n == 0) 2091 return; 2092 if (p[0] == 4) { 2093 if (n != 2) 2094 return; 2095 switch (p[1]) { 2096 case 0: 2097 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2098 break; 2099 case 1: 2100 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2101 gc->attr |= GRID_ATTR_UNDERSCORE; 2102 break; 2103 case 2: 2104 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2105 gc->attr |= GRID_ATTR_UNDERSCORE_2; 2106 break; 2107 case 3: 2108 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2109 gc->attr |= GRID_ATTR_UNDERSCORE_3; 2110 break; 2111 case 4: 2112 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2113 gc->attr |= GRID_ATTR_UNDERSCORE_4; 2114 break; 2115 case 5: 2116 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2117 gc->attr |= GRID_ATTR_UNDERSCORE_5; 2118 break; 2119 } 2120 return; 2121 } 2122 if (n < 2 || (p[0] != 38 && p[0] != 48 && p[0] != 58)) 2123 return; 2124 switch (p[1]) { 2125 case 2: 2126 if (n < 3) 2127 break; 2128 if (n == 5) 2129 i = 2; 2130 else 2131 i = 3; 2132 if (n < i + 3) 2133 break; 2134 input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[i], p[i + 1], 2135 p[i + 2]); 2136 break; 2137 case 5: 2138 if (n < 3) 2139 break; 2140 input_csi_dispatch_sgr_256_do(ictx, p[0], p[2]); 2141 break; 2142 } 2143 } 2144 2145 /* Handle CSI SGR. */ 2146 static void 2147 input_csi_dispatch_sgr(struct input_ctx *ictx) 2148 { 2149 struct grid_cell *gc = &ictx->cell.cell; 2150 u_int i, link; 2151 int n; 2152 2153 if (ictx->param_list_len == 0) { 2154 memcpy(gc, &grid_default_cell, sizeof *gc); 2155 return; 2156 } 2157 2158 for (i = 0; i < ictx->param_list_len; i++) { 2159 if (ictx->param_list[i].type == INPUT_STRING) { 2160 input_csi_dispatch_sgr_colon(ictx, i); 2161 continue; 2162 } 2163 n = input_get(ictx, i, 0, 0); 2164 if (n == -1) 2165 continue; 2166 2167 if (n == 38 || n == 48 || n == 58) { 2168 i++; 2169 switch (input_get(ictx, i, 0, -1)) { 2170 case 2: 2171 input_csi_dispatch_sgr_rgb(ictx, n, &i); 2172 break; 2173 case 5: 2174 input_csi_dispatch_sgr_256(ictx, n, &i); 2175 break; 2176 } 2177 continue; 2178 } 2179 2180 switch (n) { 2181 case 0: 2182 link = gc->link; 2183 memcpy(gc, &grid_default_cell, sizeof *gc); 2184 gc->link = link; 2185 break; 2186 case 1: 2187 gc->attr |= GRID_ATTR_BRIGHT; 2188 break; 2189 case 2: 2190 gc->attr |= GRID_ATTR_DIM; 2191 break; 2192 case 3: 2193 gc->attr |= GRID_ATTR_ITALICS; 2194 break; 2195 case 4: 2196 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2197 gc->attr |= GRID_ATTR_UNDERSCORE; 2198 break; 2199 case 5: 2200 case 6: 2201 gc->attr |= GRID_ATTR_BLINK; 2202 break; 2203 case 7: 2204 gc->attr |= GRID_ATTR_REVERSE; 2205 break; 2206 case 8: 2207 gc->attr |= GRID_ATTR_HIDDEN; 2208 break; 2209 case 9: 2210 gc->attr |= GRID_ATTR_STRIKETHROUGH; 2211 break; 2212 case 21: 2213 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2214 gc->attr |= GRID_ATTR_UNDERSCORE_2; 2215 break; 2216 case 22: 2217 gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM); 2218 break; 2219 case 23: 2220 gc->attr &= ~GRID_ATTR_ITALICS; 2221 break; 2222 case 24: 2223 gc->attr &= ~GRID_ATTR_ALL_UNDERSCORE; 2224 break; 2225 case 25: 2226 gc->attr &= ~GRID_ATTR_BLINK; 2227 break; 2228 case 27: 2229 gc->attr &= ~GRID_ATTR_REVERSE; 2230 break; 2231 case 28: 2232 gc->attr &= ~GRID_ATTR_HIDDEN; 2233 break; 2234 case 29: 2235 gc->attr &= ~GRID_ATTR_STRIKETHROUGH; 2236 break; 2237 case 30: 2238 case 31: 2239 case 32: 2240 case 33: 2241 case 34: 2242 case 35: 2243 case 36: 2244 case 37: 2245 gc->fg = n - 30; 2246 break; 2247 case 39: 2248 gc->fg = 8; 2249 break; 2250 case 40: 2251 case 41: 2252 case 42: 2253 case 43: 2254 case 44: 2255 case 45: 2256 case 46: 2257 case 47: 2258 gc->bg = n - 40; 2259 break; 2260 case 49: 2261 gc->bg = 8; 2262 break; 2263 case 53: 2264 gc->attr |= GRID_ATTR_OVERLINE; 2265 break; 2266 case 55: 2267 gc->attr &= ~GRID_ATTR_OVERLINE; 2268 break; 2269 case 59: 2270 gc->us = 8; 2271 break; 2272 case 90: 2273 case 91: 2274 case 92: 2275 case 93: 2276 case 94: 2277 case 95: 2278 case 96: 2279 case 97: 2280 gc->fg = n; 2281 break; 2282 case 100: 2283 case 101: 2284 case 102: 2285 case 103: 2286 case 104: 2287 case 105: 2288 case 106: 2289 case 107: 2290 gc->bg = n - 10; 2291 break; 2292 } 2293 } 2294 } 2295 2296 /* End of input with BEL. */ 2297 static int 2298 input_end_bel(struct input_ctx *ictx) 2299 { 2300 log_debug("%s", __func__); 2301 2302 ictx->input_end = INPUT_END_BEL; 2303 2304 return (0); 2305 } 2306 2307 /* DCS string started. */ 2308 static void 2309 input_enter_dcs(struct input_ctx *ictx) 2310 { 2311 log_debug("%s", __func__); 2312 2313 input_clear(ictx); 2314 input_start_timer(ictx); 2315 ictx->flags &= ~INPUT_LAST; 2316 } 2317 2318 /* DCS terminator (ST) received. */ 2319 static int 2320 input_dcs_dispatch(struct input_ctx *ictx) 2321 { 2322 struct window_pane *wp = ictx->wp; 2323 struct screen_write_ctx *sctx = &ictx->ctx; 2324 u_char *buf = ictx->input_buf; 2325 size_t len = ictx->input_len; 2326 const char prefix[] = "tmux;"; 2327 const u_int prefixlen = (sizeof prefix) - 1; 2328 long long allow_passthrough = 0; 2329 2330 if (wp == NULL) 2331 return (0); 2332 if (ictx->flags & INPUT_DISCARD) { 2333 log_debug("%s: %zu bytes (discard)", __func__, len); 2334 return (0); 2335 } 2336 log_debug("%s: %zu bytes", __func__, len); 2337 2338 allow_passthrough = options_get_number(wp->options, "allow-passthrough"); 2339 if (!allow_passthrough) 2340 return (0); 2341 log_debug("%s: \"%s\"", __func__, buf); 2342 2343 if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) { 2344 screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen, 2345 allow_passthrough == 2); 2346 } 2347 2348 return (0); 2349 } 2350 2351 /* OSC string started. */ 2352 static void 2353 input_enter_osc(struct input_ctx *ictx) 2354 { 2355 log_debug("%s", __func__); 2356 2357 input_clear(ictx); 2358 input_start_timer(ictx); 2359 ictx->flags &= ~INPUT_LAST; 2360 } 2361 2362 /* OSC terminator (ST) received. */ 2363 static void 2364 input_exit_osc(struct input_ctx *ictx) 2365 { 2366 struct screen_write_ctx *sctx = &ictx->ctx; 2367 struct window_pane *wp = ictx->wp; 2368 u_char *p = ictx->input_buf; 2369 u_int option; 2370 2371 if (ictx->flags & INPUT_DISCARD) 2372 return; 2373 if (ictx->input_len < 1 || *p < '0' || *p > '9') 2374 return; 2375 2376 log_debug("%s: \"%s\" (end %s)", __func__, p, 2377 ictx->input_end == INPUT_END_ST ? "ST" : "BEL"); 2378 2379 option = 0; 2380 while (*p >= '0' && *p <= '9') 2381 option = option * 10 + *p++ - '0'; 2382 if (*p != ';' && *p != '\0') 2383 return; 2384 if (*p == ';') 2385 p++; 2386 2387 switch (option) { 2388 case 0: 2389 case 2: 2390 if (wp != NULL && 2391 options_get_number(wp->options, "allow-set-title") && 2392 screen_set_title(sctx->s, p)) { 2393 notify_pane("pane-title-changed", wp); 2394 server_redraw_window_borders(wp->window); 2395 server_status_window(wp->window); 2396 } 2397 break; 2398 case 4: 2399 input_osc_4(ictx, p); 2400 break; 2401 case 7: 2402 if (utf8_isvalid(p)) { 2403 screen_set_path(sctx->s, p); 2404 if (wp != NULL) { 2405 server_redraw_window_borders(wp->window); 2406 server_status_window(wp->window); 2407 } 2408 } 2409 break; 2410 case 8: 2411 input_osc_8(ictx, p); 2412 break; 2413 case 10: 2414 input_osc_10(ictx, p); 2415 break; 2416 case 11: 2417 input_osc_11(ictx, p); 2418 break; 2419 case 12: 2420 input_osc_12(ictx, p); 2421 break; 2422 case 52: 2423 input_osc_52(ictx, p); 2424 break; 2425 case 104: 2426 input_osc_104(ictx, p); 2427 break; 2428 case 110: 2429 input_osc_110(ictx, p); 2430 break; 2431 case 111: 2432 input_osc_111(ictx, p); 2433 break; 2434 case 112: 2435 input_osc_112(ictx, p); 2436 break; 2437 case 133: 2438 input_osc_133(ictx, p); 2439 break; 2440 default: 2441 log_debug("%s: unknown '%u'", __func__, option); 2442 break; 2443 } 2444 } 2445 2446 /* APC string started. */ 2447 static void 2448 input_enter_apc(struct input_ctx *ictx) 2449 { 2450 log_debug("%s", __func__); 2451 2452 input_clear(ictx); 2453 input_start_timer(ictx); 2454 ictx->flags &= ~INPUT_LAST; 2455 } 2456 2457 /* APC terminator (ST) received. */ 2458 static void 2459 input_exit_apc(struct input_ctx *ictx) 2460 { 2461 struct screen_write_ctx *sctx = &ictx->ctx; 2462 struct window_pane *wp = ictx->wp; 2463 2464 if (ictx->flags & INPUT_DISCARD) 2465 return; 2466 log_debug("%s: \"%s\"", __func__, ictx->input_buf); 2467 2468 if (screen_set_title(sctx->s, ictx->input_buf) && wp != NULL) { 2469 notify_pane("pane-title-changed", wp); 2470 server_redraw_window_borders(wp->window); 2471 server_status_window(wp->window); 2472 } 2473 } 2474 2475 /* Rename string started. */ 2476 static void 2477 input_enter_rename(struct input_ctx *ictx) 2478 { 2479 log_debug("%s", __func__); 2480 2481 input_clear(ictx); 2482 input_start_timer(ictx); 2483 ictx->flags &= ~INPUT_LAST; 2484 } 2485 2486 /* Rename terminator (ST) received. */ 2487 static void 2488 input_exit_rename(struct input_ctx *ictx) 2489 { 2490 struct window_pane *wp = ictx->wp; 2491 struct window *w; 2492 struct options_entry *o; 2493 2494 if (wp == NULL) 2495 return; 2496 if (ictx->flags & INPUT_DISCARD) 2497 return; 2498 if (!options_get_number(ictx->wp->options, "allow-rename")) 2499 return; 2500 log_debug("%s: \"%s\"", __func__, ictx->input_buf); 2501 2502 if (!utf8_isvalid(ictx->input_buf)) 2503 return; 2504 w = wp->window; 2505 2506 if (ictx->input_len == 0) { 2507 o = options_get_only(w->options, "automatic-rename"); 2508 if (o != NULL) 2509 options_remove_or_default(o, -1, NULL); 2510 if (!options_get_number(w->options, "automatic-rename")) 2511 window_set_name(w, ""); 2512 } else { 2513 options_set_number(w->options, "automatic-rename", 0); 2514 window_set_name(w, ictx->input_buf); 2515 } 2516 server_redraw_window_borders(w); 2517 server_status_window(w); 2518 } 2519 2520 /* Open UTF-8 character. */ 2521 static int 2522 input_top_bit_set(struct input_ctx *ictx) 2523 { 2524 struct screen_write_ctx *sctx = &ictx->ctx; 2525 struct utf8_data *ud = &ictx->utf8data; 2526 2527 ictx->flags &= ~INPUT_LAST; 2528 2529 if (!ictx->utf8started) { 2530 if (utf8_open(ud, ictx->ch) != UTF8_MORE) 2531 return (0); 2532 ictx->utf8started = 1; 2533 return (0); 2534 } 2535 2536 switch (utf8_append(ud, ictx->ch)) { 2537 case UTF8_MORE: 2538 return (0); 2539 case UTF8_ERROR: 2540 ictx->utf8started = 0; 2541 return (0); 2542 case UTF8_DONE: 2543 break; 2544 } 2545 ictx->utf8started = 0; 2546 2547 log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size, 2548 (int)ud->size, ud->data, ud->width); 2549 2550 utf8_copy(&ictx->cell.cell.data, ud); 2551 screen_write_collect_add(sctx, &ictx->cell.cell); 2552 2553 utf8_copy(&ictx->last, &ictx->cell.cell.data); 2554 ictx->flags |= INPUT_LAST; 2555 2556 return (0); 2557 } 2558 2559 /* Reply to a colour request. */ 2560 static void 2561 input_osc_colour_reply(struct input_ctx *ictx, u_int n, int c) 2562 { 2563 u_char r, g, b; 2564 const char *end; 2565 2566 if (c != -1) 2567 c = colour_force_rgb(c); 2568 if (c == -1) 2569 return; 2570 colour_split_rgb(c, &r, &g, &b); 2571 2572 if (ictx->input_end == INPUT_END_BEL) 2573 end = "\007"; 2574 else 2575 end = "\033\\"; 2576 input_reply(ictx, "\033]%u;rgb:%02hhx%02hhx/%02hhx%02hhx/%02hhx%02hhx%s", 2577 n, r, r, g, g, b, b, end); 2578 } 2579 2580 /* Handle the OSC 4 sequence for setting (multiple) palette entries. */ 2581 static void 2582 input_osc_4(struct input_ctx *ictx, const char *p) 2583 { 2584 char *copy, *s, *next = NULL; 2585 long idx; 2586 int c, bad = 0, redraw = 0; 2587 2588 copy = s = xstrdup(p); 2589 while (s != NULL && *s != '\0') { 2590 idx = strtol(s, &next, 10); 2591 if (*next++ != ';') { 2592 bad = 1; 2593 break; 2594 } 2595 if (idx < 0 || idx >= 256) { 2596 bad = 1; 2597 break; 2598 } 2599 2600 s = strsep(&next, ";"); 2601 if (strcmp(s, "?") == 0) { 2602 c = colour_palette_get(ictx->palette, idx); 2603 if (c != -1) 2604 input_osc_colour_reply(ictx, 4, c); 2605 continue; 2606 } 2607 if ((c = colour_parseX11(s)) == -1) { 2608 s = next; 2609 continue; 2610 } 2611 if (colour_palette_set(ictx->palette, idx, c)) 2612 redraw = 1; 2613 s = next; 2614 } 2615 if (bad) 2616 log_debug("bad OSC 4: %s", p); 2617 if (redraw) 2618 screen_write_fullredraw(&ictx->ctx); 2619 free(copy); 2620 } 2621 2622 /* Handle the OSC 8 sequence for embedding hyperlinks. */ 2623 static void 2624 input_osc_8(struct input_ctx *ictx, const char *p) 2625 { 2626 struct hyperlinks *hl = ictx->ctx.s->hyperlinks; 2627 struct grid_cell *gc = &ictx->cell.cell; 2628 const char *start, *end, *uri; 2629 char *id = NULL; 2630 2631 for (start = p; (end = strpbrk(start, ":;")) != NULL; start = end + 1) { 2632 if (end - start >= 4 && strncmp(start, "id=", 3) == 0) { 2633 if (id != NULL) 2634 goto bad; 2635 id = xstrndup(start + 3, end - start - 3); 2636 } 2637 2638 /* The first ; is the end of parameters and start of the URI. */ 2639 if (*end == ';') 2640 break; 2641 } 2642 if (end == NULL || *end != ';') 2643 goto bad; 2644 uri = end + 1; 2645 if (*uri == '\0') { 2646 gc->link = 0; 2647 free(id); 2648 return; 2649 } 2650 gc->link = hyperlinks_put(hl, uri, id); 2651 if (id == NULL) 2652 log_debug("hyperlink (anonymous) %s = %u", uri, gc->link); 2653 else 2654 log_debug("hyperlink (id=%s) %s = %u", id, uri, gc->link); 2655 free(id); 2656 return; 2657 2658 bad: 2659 log_debug("bad OSC 8 %s", p); 2660 free(id); 2661 } 2662 2663 /* 2664 * Get a client with a foreground for the pane. There isn't much to choose 2665 * between them so just use the first. 2666 */ 2667 static int 2668 input_get_fg_client(struct window_pane *wp) 2669 { 2670 struct window *w = wp->window; 2671 struct client *loop; 2672 2673 TAILQ_FOREACH(loop, &clients, entry) { 2674 if (loop->flags & CLIENT_UNATTACHEDFLAGS) 2675 continue; 2676 if (loop->session == NULL || !session_has(loop->session, w)) 2677 continue; 2678 if (loop->tty.fg == -1) 2679 continue; 2680 return (loop->tty.fg); 2681 } 2682 return (-1); 2683 } 2684 2685 /* Get a client with a background for the pane. */ 2686 static int 2687 input_get_bg_client(struct window_pane *wp) 2688 { 2689 struct window *w = wp->window; 2690 struct client *loop; 2691 2692 TAILQ_FOREACH(loop, &clients, entry) { 2693 if (loop->flags & CLIENT_UNATTACHEDFLAGS) 2694 continue; 2695 if (loop->session == NULL || !session_has(loop->session, w)) 2696 continue; 2697 if (loop->tty.bg == -1) 2698 continue; 2699 return (loop->tty.bg); 2700 } 2701 return (-1); 2702 } 2703 2704 /* 2705 * If any control mode client exists that has provided a bg color, return it. 2706 * Otherwise, return -1. 2707 */ 2708 static int 2709 input_get_bg_control_client(struct window_pane *wp) 2710 { 2711 struct client *c; 2712 2713 if (wp->control_bg == -1) 2714 return (-1); 2715 2716 TAILQ_FOREACH(c, &clients, entry) { 2717 if (c->flags & CLIENT_CONTROL) 2718 return (wp->control_bg); 2719 } 2720 return (-1); 2721 } 2722 2723 /* 2724 * If any control mode client exists that has provided a fg color, return it. 2725 * Otherwise, return -1. 2726 */ 2727 static int 2728 input_get_fg_control_client(struct window_pane *wp) 2729 { 2730 struct client *c; 2731 2732 if (wp->control_fg == -1) 2733 return (-1); 2734 2735 TAILQ_FOREACH(c, &clients, entry) { 2736 if (c->flags & CLIENT_CONTROL) 2737 return (wp->control_fg); 2738 } 2739 return (-1); 2740 } 2741 2742 /* Handle the OSC 10 sequence for setting and querying foreground colour. */ 2743 static void 2744 input_osc_10(struct input_ctx *ictx, const char *p) 2745 { 2746 struct window_pane *wp = ictx->wp; 2747 struct grid_cell defaults; 2748 int c; 2749 2750 if (strcmp(p, "?") == 0) { 2751 if (wp == NULL) 2752 return; 2753 c = input_get_fg_control_client(wp); 2754 if (c == -1) { 2755 tty_default_colours(&defaults, wp); 2756 if (COLOUR_DEFAULT(defaults.fg)) 2757 c = input_get_fg_client(wp); 2758 else 2759 c = defaults.fg; 2760 } 2761 input_osc_colour_reply(ictx, 10, c); 2762 return; 2763 } 2764 2765 if ((c = colour_parseX11(p)) == -1) { 2766 log_debug("bad OSC 10: %s", p); 2767 return; 2768 } 2769 if (ictx->palette != NULL) { 2770 ictx->palette->fg = c; 2771 if (wp != NULL) 2772 wp->flags |= PANE_STYLECHANGED; 2773 screen_write_fullredraw(&ictx->ctx); 2774 } 2775 } 2776 2777 /* Handle the OSC 110 sequence for resetting foreground colour. */ 2778 static void 2779 input_osc_110(struct input_ctx *ictx, const char *p) 2780 { 2781 struct window_pane *wp = ictx->wp; 2782 2783 if (*p != '\0') 2784 return; 2785 if (ictx->palette != NULL) { 2786 ictx->palette->fg = 8; 2787 if (wp != NULL) 2788 wp->flags |= PANE_STYLECHANGED; 2789 screen_write_fullredraw(&ictx->ctx); 2790 } 2791 } 2792 2793 /* Handle the OSC 11 sequence for setting and querying background colour. */ 2794 static void 2795 input_osc_11(struct input_ctx *ictx, const char *p) 2796 { 2797 struct window_pane *wp = ictx->wp; 2798 struct grid_cell defaults; 2799 int c; 2800 2801 if (strcmp(p, "?") == 0) { 2802 if (wp == NULL) 2803 return; 2804 c = input_get_bg_control_client(wp); 2805 if (c == -1) { 2806 tty_default_colours(&defaults, wp); 2807 if (COLOUR_DEFAULT(defaults.bg)) 2808 c = input_get_bg_client(wp); 2809 else 2810 c = defaults.bg; 2811 } 2812 input_osc_colour_reply(ictx, 11, c); 2813 return; 2814 } 2815 2816 if ((c = colour_parseX11(p)) == -1) { 2817 log_debug("bad OSC 11: %s", p); 2818 return; 2819 } 2820 if (ictx->palette != NULL) { 2821 ictx->palette->bg = c; 2822 if (wp != NULL) 2823 wp->flags |= PANE_STYLECHANGED; 2824 screen_write_fullredraw(&ictx->ctx); 2825 } 2826 } 2827 2828 /* Handle the OSC 111 sequence for resetting background colour. */ 2829 static void 2830 input_osc_111(struct input_ctx *ictx, const char *p) 2831 { 2832 struct window_pane *wp = ictx->wp; 2833 2834 if (*p != '\0') 2835 return; 2836 if (ictx->palette != NULL) { 2837 ictx->palette->bg = 8; 2838 if (wp != NULL) 2839 wp->flags |= PANE_STYLECHANGED; 2840 screen_write_fullredraw(&ictx->ctx); 2841 } 2842 } 2843 2844 /* Handle the OSC 12 sequence for setting and querying cursor colour. */ 2845 static void 2846 input_osc_12(struct input_ctx *ictx, const char *p) 2847 { 2848 struct window_pane *wp = ictx->wp; 2849 int c; 2850 2851 if (strcmp(p, "?") == 0) { 2852 if (wp != NULL) { 2853 c = ictx->ctx.s->ccolour; 2854 if (c == -1) 2855 c = ictx->ctx.s->default_ccolour; 2856 input_osc_colour_reply(ictx, 12, c); 2857 } 2858 return; 2859 } 2860 2861 if ((c = colour_parseX11(p)) == -1) { 2862 log_debug("bad OSC 12: %s", p); 2863 return; 2864 } 2865 screen_set_cursor_colour(ictx->ctx.s, c); 2866 } 2867 2868 /* Handle the OSC 112 sequence for resetting cursor colour. */ 2869 static void 2870 input_osc_112(struct input_ctx *ictx, const char *p) 2871 { 2872 if (*p == '\0') /* no arguments allowed */ 2873 screen_set_cursor_colour(ictx->ctx.s, -1); 2874 } 2875 2876 /* Handle the OSC 133 sequence. */ 2877 static void 2878 input_osc_133(struct input_ctx *ictx, const char *p) 2879 { 2880 struct grid *gd = ictx->ctx.s->grid; 2881 u_int line = ictx->ctx.s->cy + gd->hsize; 2882 struct grid_line *gl; 2883 2884 if (line > gd->hsize + gd->sy - 1) 2885 return; 2886 gl = grid_get_line(gd, line); 2887 2888 switch (*p) { 2889 case 'A': 2890 gl->flags |= GRID_LINE_START_PROMPT; 2891 break; 2892 case 'C': 2893 gl->flags |= GRID_LINE_START_OUTPUT; 2894 break; 2895 } 2896 } 2897 2898 /* Handle the OSC 52 sequence for setting the clipboard. */ 2899 static void 2900 input_osc_52(struct input_ctx *ictx, const char *p) 2901 { 2902 struct window_pane *wp = ictx->wp; 2903 char *end; 2904 const char *buf = NULL; 2905 size_t len = 0; 2906 u_char *out; 2907 int outlen, state; 2908 struct screen_write_ctx ctx; 2909 struct paste_buffer *pb; 2910 const char* allow = "cpqs01234567"; 2911 char flags[sizeof "cpqs01234567"] = ""; 2912 u_int i, j = 0; 2913 2914 if (wp == NULL) 2915 return; 2916 state = options_get_number(global_options, "set-clipboard"); 2917 if (state != 2) 2918 return; 2919 2920 if ((end = strchr(p, ';')) == NULL) 2921 return; 2922 end++; 2923 if (*end == '\0') 2924 return; 2925 log_debug("%s: %s", __func__, end); 2926 2927 for (i = 0; p + i != end; i++) { 2928 if (strchr(allow, p[i]) != NULL && strchr(flags, p[i]) == NULL) 2929 flags[j++] = p[i]; 2930 } 2931 log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, flags); 2932 2933 if (strcmp(end, "?") == 0) { 2934 if ((pb = paste_get_top(NULL)) != NULL) 2935 buf = paste_buffer_data(pb, &len); 2936 if (ictx->input_end == INPUT_END_BEL) 2937 input_reply_clipboard(ictx->event, buf, len, "\007"); 2938 else 2939 input_reply_clipboard(ictx->event, buf, len, "\033\\"); 2940 return; 2941 } 2942 2943 len = (strlen(end) / 4) * 3; 2944 if (len == 0) 2945 return; 2946 2947 out = xmalloc(len); 2948 if ((outlen = b64_pton(end, out, len)) == -1) { 2949 free(out); 2950 return; 2951 } 2952 2953 screen_write_start_pane(&ctx, wp, NULL); 2954 screen_write_setselection(&ctx, flags, out, outlen); 2955 screen_write_stop(&ctx); 2956 notify_pane("pane-set-clipboard", wp); 2957 2958 paste_add(NULL, out, outlen); 2959 } 2960 2961 /* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */ 2962 static void 2963 input_osc_104(struct input_ctx *ictx, const char *p) 2964 { 2965 char *copy, *s; 2966 long idx; 2967 int bad = 0, redraw = 0; 2968 2969 if (*p == '\0') { 2970 colour_palette_clear(ictx->palette); 2971 screen_write_fullredraw(&ictx->ctx); 2972 return; 2973 } 2974 2975 copy = s = xstrdup(p); 2976 while (*s != '\0') { 2977 idx = strtol(s, &s, 10); 2978 if (*s != '\0' && *s != ';') { 2979 bad = 1; 2980 break; 2981 } 2982 if (idx < 0 || idx >= 256) { 2983 bad = 1; 2984 break; 2985 } 2986 if (colour_palette_set(ictx->palette, idx, -1)) 2987 redraw = 1; 2988 if (*s == ';') 2989 s++; 2990 } 2991 if (bad) 2992 log_debug("bad OSC 104: %s", p); 2993 if (redraw) 2994 screen_write_fullredraw(&ictx->ctx); 2995 free(copy); 2996 } 2997 2998 void 2999 input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len, 3000 const char *end) 3001 { 3002 char *out = NULL; 3003 int outlen = 0; 3004 3005 if (buf != NULL && len != 0) { 3006 if (len >= ((size_t)INT_MAX * 3 / 4) - 1) 3007 return; 3008 outlen = 4 * ((len + 2) / 3) + 1; 3009 out = xmalloc(outlen); 3010 if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) { 3011 free(out); 3012 return; 3013 } 3014 } 3015 3016 bufferevent_write(bev, "\033]52;;", 6); 3017 if (outlen != 0) 3018 bufferevent_write(bev, out, outlen); 3019 bufferevent_write(bev, end, strlen(end)); 3020 free(out); 3021 } 3022 3023 /* Set input buffer size. */ 3024 void 3025 input_set_buffer_size(size_t buffer_size) 3026 { 3027 log_debug("%s: %lu -> %lu", __func__, input_buffer_size, buffer_size); 3028 input_buffer_size = buffer_size; 3029 } 3030