Mercurial > vim
comparison src/term.c @ 20774:10535993e913 v8.2.0939
patch 8.2.0939: checking for term escape sequences is long and confusing
Commit: https://github.com/vim/vim/commit/218cb0fb62d29fba552281c2e8ffeb4046d540c4
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Jun 9 21:26:36 2020 +0200
patch 8.2.0939: checking for term escape sequences is long and confusing
Problem: checking for term escape sequences is long and confusing
Solution: Refactor code into separate functions.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 09 Jun 2020 21:30:03 +0200 |
parents | 1e2e81dbb958 |
children | 7728e309e013 |
comparison
equal
deleted
inserted
replaced
20773:764cb6c1e56c | 20774:10535993e913 |
---|---|
4382 } | 4382 } |
4383 } | 4383 } |
4384 return new_slen; | 4384 return new_slen; |
4385 } | 4385 } |
4386 | 4386 |
4387 static void | |
4388 handle_u7_response(int *arg, char_u *tp, int csi_len) | |
4389 { | |
4390 if (arg[0] == 2 && arg[1] >= 2) | |
4391 { | |
4392 char *aw = NULL; | |
4393 | |
4394 LOG_TR(("Received U7 status: %s", tp)); | |
4395 u7_status.tr_progress = STATUS_GOT; | |
4396 did_cursorhold = TRUE; | |
4397 if (arg[1] == 2) | |
4398 aw = "single"; | |
4399 else if (arg[1] == 3) | |
4400 aw = "double"; | |
4401 if (aw != NULL && STRCMP(aw, p_ambw) != 0) | |
4402 { | |
4403 // Setting the option causes a screen redraw. Do | |
4404 // that right away if possible, keeping any | |
4405 // messages. | |
4406 set_option_value((char_u *)"ambw", 0L, | |
4407 (char_u *)aw, 0); | |
4408 # ifdef DEBUG_TERMRESPONSE | |
4409 { | |
4410 int r = redraw_asap(CLEAR); | |
4411 | |
4412 log_tr("set 'ambiwidth', redraw_asap(): %d", r); | |
4413 } | |
4414 # else | |
4415 redraw_asap(CLEAR); | |
4416 # endif | |
4417 # ifdef FEAT_EVAL | |
4418 set_vim_var_string(VV_TERMU7RESP, tp, csi_len); | |
4419 # endif | |
4420 } | |
4421 } | |
4422 else if (arg[0] == 3) | |
4423 { | |
4424 LOG_TR(("Received compatibility test result: %s", tp)); | |
4425 // Third row: xterm compatibility test. | |
4426 // If the cursor is not on the first column then the | |
4427 // terminal is not xterm compatible. | |
4428 if (arg[1] != 1) | |
4429 xcc_test_failed = TRUE; | |
4430 xcc_status.tr_progress = STATUS_GOT; | |
4431 } | |
4432 } | |
4433 | |
4434 /* | |
4435 * Handle a response to T_CRV. | |
4436 */ | |
4437 static void | |
4438 handle_version_response(int first, int *arg, int argc, char_u *tp) | |
4439 { | |
4440 int version = arg[1]; | |
4441 | |
4442 LOG_TR(("Received CRV response: %s", tp)); | |
4443 crv_status.tr_progress = STATUS_GOT; | |
4444 did_cursorhold = TRUE; | |
4445 | |
4446 // If this code starts with CSI, you can bet that the | |
4447 // terminal uses 8-bit codes. | |
4448 if (tp[0] == CSI) | |
4449 switch_to_8bit(); | |
4450 | |
4451 // Screen sends 40500. | |
4452 // rxvt sends its version number: "20703" is 2.7.3. | |
4453 // Ignore it for when the user has set 'term' to xterm, | |
4454 // even though it's an rxvt. | |
4455 if (version > 20000) | |
4456 version = 0; | |
4457 | |
4458 if (first == '>' && argc == 3) | |
4459 { | |
4460 int need_flush = FALSE; | |
4461 int is_iterm2 = FALSE; | |
4462 int is_mintty = FALSE; | |
4463 int is_screen = FALSE; | |
4464 | |
4465 // mintty 2.9.5 sends 77;20905;0c. | |
4466 // (77 is ASCII 'M' for mintty.) | |
4467 if (arg[0] == 77) | |
4468 is_mintty = TRUE; | |
4469 | |
4470 // if xterm version >= 141 try to get termcap codes | |
4471 if (version >= 141) | |
4472 { | |
4473 LOG_TR(("Enable checking for XT codes")); | |
4474 check_for_codes = TRUE; | |
4475 need_gather = TRUE; | |
4476 req_codes_from_term(); | |
4477 } | |
4478 | |
4479 // libvterm sends 0;100;0 | |
4480 if (version == 100 && arg[0] == 0 && arg[2] == 0) | |
4481 { | |
4482 // If run from Vim $COLORS is set to the number of | |
4483 // colors the terminal supports. Otherwise assume | |
4484 // 256, libvterm supports even more. | |
4485 if (mch_getenv((char_u *)"COLORS") == NULL) | |
4486 may_adjust_color_count(256); | |
4487 // Libvterm can handle SGR mouse reporting. | |
4488 if (!option_was_set((char_u *)"ttym")) | |
4489 set_option_value((char_u *)"ttym", 0L, | |
4490 (char_u *)"sgr", 0); | |
4491 } | |
4492 | |
4493 if (version == 95) | |
4494 { | |
4495 // Mac Terminal.app sends 1;95;0 | |
4496 if (arg[0] == 1 && arg[2] == 0) | |
4497 { | |
4498 is_not_xterm = TRUE; | |
4499 is_mac_terminal = TRUE; | |
4500 } | |
4501 // iTerm2 sends 0;95;0 | |
4502 else if (arg[0] == 0 && arg[2] == 0) | |
4503 is_iterm2 = TRUE; | |
4504 // old iTerm2 sends 0;95; | |
4505 else if (arg[0] == 0 && arg[2] == -1) | |
4506 is_not_xterm = TRUE; | |
4507 } | |
4508 | |
4509 // screen sends 83;40500;0 83 is 'S' in ASCII. | |
4510 if (arg[0] == 83) | |
4511 is_screen = TRUE; | |
4512 | |
4513 // Only set 'ttymouse' automatically if it was not set | |
4514 // by the user already. | |
4515 if (!option_was_set((char_u *)"ttym")) | |
4516 { | |
4517 // Xterm version 277 supports SGR. Also support | |
4518 // Terminal.app, iTerm2, mintty, and screen 4.7+. | |
4519 if ((!is_screen && version >= 277) | |
4520 || is_iterm2 | |
4521 || is_mac_terminal | |
4522 || is_mintty | |
4523 || (is_screen && arg[1] >= 40700)) | |
4524 set_option_value((char_u *)"ttym", 0L, | |
4525 (char_u *)"sgr", 0); | |
4526 // For xterm version >= 95 mouse dragging works. | |
4527 else if (version >= 95) | |
4528 set_option_value((char_u *)"ttym", 0L, | |
4529 (char_u *)"xterm2", 0); | |
4530 } | |
4531 | |
4532 // Detect terminals that set $TERM to something like | |
4533 // "xterm-256color" but are not fully xterm compatible. | |
4534 | |
4535 // Gnome terminal sends 1;3801;0, 1;4402;0 or 1;2501;0. | |
4536 // xfce4-terminal sends 1;2802;0. | |
4537 // screen sends 83;40500;0 | |
4538 // Assuming any version number over 2500 is not an | |
4539 // xterm (without the limit for rxvt and screen). | |
4540 if (arg[1] >= 2500) | |
4541 is_not_xterm = TRUE; | |
4542 | |
4543 // PuTTY sends 0;136;0 | |
4544 // vandyke SecureCRT sends 1;136;0 | |
4545 else if (version == 136 && arg[2] == 0) | |
4546 { | |
4547 is_not_xterm = TRUE; | |
4548 | |
4549 // PuTTY supports sgr-like mouse reporting, but | |
4550 // only set 'ttymouse' if it was not set by the | |
4551 // user already. | |
4552 if (arg[0] == 0 | |
4553 && !option_was_set((char_u *)"ttym")) | |
4554 set_option_value((char_u *)"ttym", 0L, | |
4555 (char_u *)"sgr", 0); | |
4556 } | |
4557 | |
4558 // Konsole sends 0;115;0 | |
4559 else if (version == 115 && arg[0] == 0 && arg[2] == 0) | |
4560 is_not_xterm = TRUE; | |
4561 | |
4562 // GNU screen sends 83;30600;0, 83;40500;0, etc. | |
4563 // 30600/40500 is a version number of GNU screen. DA2 | |
4564 // support is added on 3.6. DCS string has a special | |
4565 // meaning to GNU screen, but xterm compatibility | |
4566 // checking does not detect GNU screen. | |
4567 if (version >= 30600 && arg[0] == 83) | |
4568 xcc_test_failed = TRUE; | |
4569 | |
4570 // Xterm first responded to this request at patch level | |
4571 // 95, so assume anything below 95 is not xterm. | |
4572 if (version < 95) | |
4573 is_not_xterm = TRUE; | |
4574 | |
4575 // With the real Xterm setting the underline RGB color | |
4576 // clears the background color, disable "t_8u". | |
4577 if (!is_not_xterm && *T_8U != NUL) | |
4578 T_8U = empty_option; | |
4579 | |
4580 // Only request the cursor style if t_SH and t_RS are | |
4581 // set. Only supported properly by xterm since version | |
4582 // 279 (otherwise it returns 0x18). | |
4583 // Only when the xcc_status was set, the test finished, | |
4584 // and xcc_test_failed is FALSE; | |
4585 // Not for Terminal.app, it can't handle t_RS, it | |
4586 // echoes the characters to the screen. | |
4587 if (rcs_status.tr_progress == STATUS_GET | |
4588 && xcc_status.tr_progress == STATUS_GOT | |
4589 && !xcc_test_failed | |
4590 && version >= 279 | |
4591 && *T_CSH != NUL | |
4592 && *T_CRS != NUL) | |
4593 { | |
4594 LOG_TR(("Sending cursor style request")); | |
4595 out_str(T_CRS); | |
4596 termrequest_sent(&rcs_status); | |
4597 need_flush = TRUE; | |
4598 } | |
4599 | |
4600 // Only request the cursor blink mode if t_RC set. Not | |
4601 // for Gnome terminal, it can't handle t_RC, it | |
4602 // echoes the characters to the screen. | |
4603 // Only when the xcc_status was set, the test finished, | |
4604 // and xcc_test_failed is FALSE; | |
4605 if (rbm_status.tr_progress == STATUS_GET | |
4606 && xcc_status.tr_progress == STATUS_GOT | |
4607 && !xcc_test_failed | |
4608 && *T_CRC != NUL) | |
4609 { | |
4610 LOG_TR(("Sending cursor blink mode request")); | |
4611 out_str(T_CRC); | |
4612 termrequest_sent(&rbm_status); | |
4613 need_flush = TRUE; | |
4614 } | |
4615 | |
4616 if (need_flush) | |
4617 out_flush(); | |
4618 } | |
4619 } | |
4620 | |
4621 /* | |
4622 * Handle a sequence with key and modifier, one of: | |
4623 * {lead}27;{modifier};{key}~ | |
4624 * {lead}{key};{modifier}u | |
4625 * Returns the difference in length. | |
4626 */ | |
4627 static int | |
4628 handle_key_with_modifier( | |
4629 int *arg, | |
4630 int trail, | |
4631 int csi_len, | |
4632 int offset, | |
4633 char_u *buf, | |
4634 int bufsize, | |
4635 int *buflen) | |
4636 { | |
4637 int key; | |
4638 int modifiers; | |
4639 int new_slen; | |
4640 char_u string[MAX_KEY_CODE_LEN + 1]; | |
4641 | |
4642 seenModifyOtherKeys = TRUE; | |
4643 if (trail == 'u') | |
4644 key = arg[0]; | |
4645 else | |
4646 key = arg[2]; | |
4647 | |
4648 modifiers = decode_modifiers(arg[1]); | |
4649 | |
4650 // Some keys already have Shift included, pass them as | |
4651 // normal keys. Not when Ctrl is also used, because <C-H> | |
4652 // and <C-S-H> are different. | |
4653 if (modifiers == MOD_MASK_SHIFT | |
4654 && ((key >= '@' && key <= 'Z') | |
4655 || key == '^' || key == '_' | |
4656 || (key >= '{' && key <= '~'))) | |
4657 modifiers = 0; | |
4658 | |
4659 // When used with Ctrl we always make a letter upper case, | |
4660 // so that mapping <C-H> and <C-h> are the same. Typing | |
4661 // <C-S-H> also uses "H" but modifier is different. | |
4662 if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) | |
4663 key = TOUPPER_ASC(key); | |
4664 | |
4665 // insert modifiers with KS_MODIFIER | |
4666 new_slen = modifiers2keycode(modifiers, &key, string); | |
4667 | |
4668 if (has_mbyte) | |
4669 new_slen += (*mb_char2bytes)(key, string + new_slen); | |
4670 else | |
4671 string[new_slen++] = key; | |
4672 | |
4673 if (put_string_in_typebuf(offset, csi_len, string, new_slen, | |
4674 buf, bufsize, buflen) == FAIL) | |
4675 return -1; | |
4676 return new_slen - csi_len + offset; | |
4677 } | |
4678 | |
4679 /* | |
4680 * Handle a CSI escape sequence. | |
4681 * - Xterm version string: {lead}>{x};{vers};{y}c | |
4682 * Also eat other possible responses to t_RV, rxvt returns | |
4683 * "{lead}?1;2c". | |
4684 * | |
4685 * - Cursor position report: {lead}{row};{col}R | |
4686 * The final byte must be 'R'. It is used for checking the | |
4687 * ambiguous-width character state. | |
4688 * | |
4689 * - window position reply: {lead}3;{x};{y}t | |
4690 * | |
4691 * - key with modifiers when modifyOtherKeys is enabled: | |
4692 * {lead}27;{modifier};{key}~ | |
4693 * {lead}{key};{modifier}u | |
4694 * Return 0 for no match, -1 for partial match, > 0 for full match. | |
4695 */ | |
4696 static int | |
4697 handle_csi( | |
4698 char_u *tp, | |
4699 int len, | |
4700 char_u *argp, | |
4701 int offset, | |
4702 char_u *buf, | |
4703 int bufsize, | |
4704 int *buflen, | |
4705 char_u *key_name, | |
4706 int *slen) | |
4707 { | |
4708 int first = -1; // optional char right after {lead} | |
4709 int trail; // char that ends CSI sequence | |
4710 int arg[3] = {-1, -1, -1}; // argument numbers | |
4711 int argc; // number of arguments | |
4712 char_u *ap = argp; | |
4713 int csi_len; | |
4714 | |
4715 // Check for non-digit after CSI. | |
4716 if (!VIM_ISDIGIT(*ap)) | |
4717 first = *ap++; | |
4718 | |
4719 // Find up to three argument numbers. | |
4720 for (argc = 0; argc < 3; ) | |
4721 { | |
4722 if (ap >= tp + len) | |
4723 return -1; | |
4724 if (*ap == ';') | |
4725 arg[argc++] = -1; // omitted number | |
4726 else if (VIM_ISDIGIT(*ap)) | |
4727 { | |
4728 arg[argc] = 0; | |
4729 for (;;) | |
4730 { | |
4731 if (ap >= tp + len) | |
4732 return -1; | |
4733 if (!VIM_ISDIGIT(*ap)) | |
4734 break; | |
4735 arg[argc] = arg[argc] * 10 + (*ap - '0'); | |
4736 ++ap; | |
4737 } | |
4738 ++argc; | |
4739 } | |
4740 if (*ap == ';') | |
4741 ++ap; | |
4742 else | |
4743 break; | |
4744 } | |
4745 | |
4746 // mrxvt has been reported to have "+" in the version. Assume | |
4747 // the escape sequence ends with a letter or one of "{|}~". | |
4748 while (ap < tp + len | |
4749 && !(*ap >= '{' && *ap <= '~') | |
4750 && !ASCII_ISALPHA(*ap)) | |
4751 ++ap; | |
4752 if (ap >= tp + len) | |
4753 return -1; | |
4754 trail = *ap; | |
4755 csi_len = (int)(ap - tp) + 1; | |
4756 | |
4757 // Cursor position report: Eat it when there are 2 arguments | |
4758 // and it ends in 'R'. Also when u7_status is not "sent", it | |
4759 // may be from a previous Vim that just exited. But not for | |
4760 // <S-F3>, it sends something similar, check for row and column | |
4761 // to make sense. | |
4762 if (first == -1 && argc == 2 && trail == 'R') | |
4763 { | |
4764 handle_u7_response(arg, tp, csi_len); | |
4765 | |
4766 key_name[0] = (int)KS_EXTRA; | |
4767 key_name[1] = (int)KE_IGNORE; | |
4768 *slen = csi_len; | |
4769 } | |
4770 | |
4771 // Version string: Eat it when there is at least one digit and | |
4772 // it ends in 'c' | |
4773 else if (*T_CRV != NUL && ap > argp + 1 && trail == 'c') | |
4774 { | |
4775 handle_version_response(first, arg, argc, tp); | |
4776 | |
4777 *slen = csi_len; | |
4778 # ifdef FEAT_EVAL | |
4779 set_vim_var_string(VV_TERMRESPONSE, tp, *slen); | |
4780 # endif | |
4781 apply_autocmds(EVENT_TERMRESPONSE, | |
4782 NULL, NULL, FALSE, curbuf); | |
4783 key_name[0] = (int)KS_EXTRA; | |
4784 key_name[1] = (int)KE_IGNORE; | |
4785 } | |
4786 | |
4787 // Check blinking cursor from xterm: | |
4788 // {lead}?12;1$y set | |
4789 // {lead}?12;2$y not set | |
4790 // | |
4791 // {lead} can be <Esc>[ or CSI | |
4792 else if (rbm_status.tr_progress == STATUS_SENT | |
4793 && first == '?' | |
4794 && ap == argp + 6 | |
4795 && arg[0] == 12 | |
4796 && ap[-1] == '$' | |
4797 && trail == 'y') | |
4798 { | |
4799 initial_cursor_blink = (arg[1] == '1'); | |
4800 rbm_status.tr_progress = STATUS_GOT; | |
4801 LOG_TR(("Received cursor blinking mode response: %s", tp)); | |
4802 key_name[0] = (int)KS_EXTRA; | |
4803 key_name[1] = (int)KE_IGNORE; | |
4804 *slen = csi_len; | |
4805 # ifdef FEAT_EVAL | |
4806 set_vim_var_string(VV_TERMBLINKRESP, tp, *slen); | |
4807 # endif | |
4808 } | |
4809 | |
4810 // Check for a window position response from the terminal: | |
4811 // {lead}3;{x};{y}t | |
4812 else if (did_request_winpos && argc == 3 && arg[0] == 3 | |
4813 && trail == 't') | |
4814 { | |
4815 winpos_x = arg[1]; | |
4816 winpos_y = arg[2]; | |
4817 // got finished code: consume it | |
4818 key_name[0] = (int)KS_EXTRA; | |
4819 key_name[1] = (int)KE_IGNORE; | |
4820 *slen = csi_len; | |
4821 | |
4822 if (--did_request_winpos <= 0) | |
4823 winpos_status.tr_progress = STATUS_GOT; | |
4824 } | |
4825 | |
4826 // Key with modifier: | |
4827 // {lead}27;{modifier};{key}~ | |
4828 // {lead}{key};{modifier}u | |
4829 else if ((arg[0] == 27 && argc == 3 && trail == '~') | |
4830 || (argc == 2 && trail == 'u')) | |
4831 { | |
4832 return len + handle_key_with_modifier(arg, trail, | |
4833 csi_len, offset, buf, bufsize, buflen); | |
4834 } | |
4835 | |
4836 // else: Unknown CSI sequence. We could drop it, but then the | |
4837 // user can't create a map for it. | |
4838 return 0; | |
4839 } | |
4840 | |
4841 /* | |
4842 * Handle an OSC sequence, fore/background color response from the terminal: | |
4843 * | |
4844 * {lead}{code};rgb:{rrrr}/{gggg}/{bbbb}{tail} | |
4845 * or {lead}{code};rgb:{rr}/{gg}/{bb}{tail} | |
4846 * | |
4847 * {code} is 10 for foreground, 11 for background | |
4848 * {lead} can be <Esc>] or OSC | |
4849 * {tail} can be '\007', <Esc>\ or STERM. | |
4850 * | |
4851 * Consume any code that starts with "{lead}11;", it's also | |
4852 * possible that "rgba" is following. | |
4853 */ | |
4854 static int | |
4855 handle_osc(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen) | |
4856 { | |
4857 int i, j; | |
4858 | |
4859 j = 1 + (tp[0] == ESC); | |
4860 if (len >= j + 3 && (argp[0] != '1' | |
4861 || (argp[1] != '1' && argp[1] != '0') | |
4862 || argp[2] != ';')) | |
4863 i = 0; // no match | |
4864 else | |
4865 for (i = j; i < len; ++i) | |
4866 if (tp[i] == '\007' || (tp[0] == OSC ? tp[i] == STERM | |
4867 : (tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\'))) | |
4868 { | |
4869 int is_bg = argp[1] == '1'; | |
4870 int is_4digit = i - j >= 21 && tp[j + 11] == '/' | |
4871 && tp[j + 16] == '/'; | |
4872 | |
4873 if (i - j >= 15 && STRNCMP(tp + j + 3, "rgb:", 4) == 0 | |
4874 && (is_4digit | |
4875 || (tp[j + 9] == '/' && tp[i + 12 == '/']))) | |
4876 { | |
4877 char_u *tp_r = tp + j + 7; | |
4878 char_u *tp_g = tp + j + (is_4digit ? 12 : 10); | |
4879 char_u *tp_b = tp + j + (is_4digit ? 17 : 13); | |
4880 # ifdef FEAT_TERMINAL | |
4881 int rval, gval, bval; | |
4882 | |
4883 rval = hexhex2nr(tp_r); | |
4884 gval = hexhex2nr(tp_b); | |
4885 bval = hexhex2nr(tp_g); | |
4886 # endif | |
4887 if (is_bg) | |
4888 { | |
4889 char *new_bg_val = (3 * '6' < *tp_r + *tp_g + | |
4890 *tp_b) ? "light" : "dark"; | |
4891 | |
4892 LOG_TR(("Received RBG response: %s", tp)); | |
4893 rbg_status.tr_progress = STATUS_GOT; | |
4894 # ifdef FEAT_TERMINAL | |
4895 bg_r = rval; | |
4896 bg_g = gval; | |
4897 bg_b = bval; | |
4898 # endif | |
4899 if (!option_was_set((char_u *)"bg") | |
4900 && STRCMP(p_bg, new_bg_val) != 0) | |
4901 { | |
4902 // value differs, apply it | |
4903 set_option_value((char_u *)"bg", 0L, | |
4904 (char_u *)new_bg_val, 0); | |
4905 reset_option_was_set((char_u *)"bg"); | |
4906 redraw_asap(CLEAR); | |
4907 } | |
4908 } | |
4909 # ifdef FEAT_TERMINAL | |
4910 else | |
4911 { | |
4912 LOG_TR(("Received RFG response: %s", tp)); | |
4913 rfg_status.tr_progress = STATUS_GOT; | |
4914 fg_r = rval; | |
4915 fg_g = gval; | |
4916 fg_b = bval; | |
4917 } | |
4918 # endif | |
4919 } | |
4920 | |
4921 // got finished code: consume it | |
4922 key_name[0] = (int)KS_EXTRA; | |
4923 key_name[1] = (int)KE_IGNORE; | |
4924 *slen = i + 1 + (tp[i] == ESC); | |
4925 # ifdef FEAT_EVAL | |
4926 set_vim_var_string(is_bg ? VV_TERMRBGRESP | |
4927 : VV_TERMRFGRESP, tp, *slen); | |
4928 # endif | |
4929 break; | |
4930 } | |
4931 if (i == len) | |
4932 { | |
4933 LOG_TR(("not enough characters for RB")); | |
4934 return FAIL; | |
4935 } | |
4936 return OK; | |
4937 } | |
4938 | |
4939 /* | |
4940 * Check for key code response from xterm: | |
4941 * {lead}{flag}+r<hex bytes><{tail} | |
4942 * | |
4943 * {lead} can be <Esc>P or DCS | |
4944 * {flag} can be '0' or '1' | |
4945 * {tail} can be Esc>\ or STERM | |
4946 * | |
4947 * Check for cursor shape response from xterm: | |
4948 * {lead}1$r<digit> q{tail} | |
4949 * | |
4950 * {lead} can be <Esc>P or DCS | |
4951 * {tail} can be <Esc>\ or STERM | |
4952 * | |
4953 * Consume any code that starts with "{lead}.+r" or "{lead}.$r". | |
4954 */ | |
4955 static int | |
4956 handle_dcs(char_u *tp, char_u *argp, int len, char_u *key_name, int *slen) | |
4957 { | |
4958 int i, j; | |
4959 | |
4960 j = 1 + (tp[0] == ESC); | |
4961 if (len < j + 3) | |
4962 i = len; // need more chars | |
4963 else if ((argp[1] != '+' && argp[1] != '$') || argp[2] != 'r') | |
4964 i = 0; // no match | |
4965 else if (argp[1] == '+') | |
4966 // key code response | |
4967 for (i = j; i < len; ++i) | |
4968 { | |
4969 if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\') | |
4970 || tp[i] == STERM) | |
4971 { | |
4972 if (i - j >= 3) | |
4973 got_code_from_term(tp + j, i); | |
4974 key_name[0] = (int)KS_EXTRA; | |
4975 key_name[1] = (int)KE_IGNORE; | |
4976 *slen = i + 1 + (tp[i] == ESC); | |
4977 break; | |
4978 } | |
4979 } | |
4980 else | |
4981 { | |
4982 // Probably the cursor shape response. Make sure that "i" | |
4983 // is equal to "len" when there are not sufficient | |
4984 // characters. | |
4985 for (i = j + 3; i < len; ++i) | |
4986 { | |
4987 if (i - j == 3 && !isdigit(tp[i])) | |
4988 break; | |
4989 if (i - j == 4 && tp[i] != ' ') | |
4990 break; | |
4991 if (i - j == 5 && tp[i] != 'q') | |
4992 break; | |
4993 if (i - j == 6 && tp[i] != ESC && tp[i] != STERM) | |
4994 break; | |
4995 if ((i - j == 6 && tp[i] == STERM) | |
4996 || (i - j == 7 && tp[i] == '\\')) | |
4997 { | |
4998 int number = argp[3] - '0'; | |
4999 | |
5000 // 0, 1 = block blink, 2 = block | |
5001 // 3 = underline blink, 4 = underline | |
5002 // 5 = vertical bar blink, 6 = vertical bar | |
5003 number = number == 0 ? 1 : number; | |
5004 initial_cursor_shape = (number + 1) / 2; | |
5005 // The blink flag is actually inverted, compared to | |
5006 // the value set with T_SH. | |
5007 initial_cursor_shape_blink = | |
5008 (number & 1) ? FALSE : TRUE; | |
5009 rcs_status.tr_progress = STATUS_GOT; | |
5010 LOG_TR(("Received cursor shape response: %s", tp)); | |
5011 | |
5012 key_name[0] = (int)KS_EXTRA; | |
5013 key_name[1] = (int)KE_IGNORE; | |
5014 *slen = i + 1; | |
5015 # ifdef FEAT_EVAL | |
5016 set_vim_var_string(VV_TERMSTYLERESP, tp, *slen); | |
5017 # endif | |
5018 break; | |
5019 } | |
5020 } | |
5021 } | |
5022 | |
5023 if (i == len) | |
5024 { | |
5025 // These codes arrive many together, each code can be | |
5026 // truncated at any point. | |
5027 LOG_TR(("not enough characters for XT")); | |
5028 return FAIL; | |
5029 } | |
5030 return OK; | |
5031 } | |
5032 | |
4387 /* | 5033 /* |
4388 * Check if typebuf.tb_buf[] contains a terminal key code. | 5034 * Check if typebuf.tb_buf[] contains a terminal key code. |
4389 * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off | 5035 * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off |
4390 * + "max_offset"]. | 5036 * + "max_offset"]. |
4391 * Return 0 for no match, -1 for partial match, > 0 for full match. | 5037 * Return 0 for no match, -1 for partial match, > 0 for full match. |
4635 */ | 5281 */ |
4636 if (((tp[0] == ESC && len >= 3 && tp[1] == '[') | 5282 if (((tp[0] == ESC && len >= 3 && tp[1] == '[') |
4637 || (tp[0] == CSI && len >= 2)) | 5283 || (tp[0] == CSI && len >= 2)) |
4638 && (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?')) | 5284 && (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?')) |
4639 { | 5285 { |
4640 int first = -1; // optional char right after {lead} | 5286 int resp = handle_csi(tp, len, argp, offset, buf, |
4641 int trail; // char that ends CSI sequence | 5287 bufsize, buflen, key_name, &slen); |
4642 int arg[3] = {-1, -1, -1}; // argument numbers | 5288 if (resp != 0) |
4643 int argc; // number of arguments | |
4644 char_u *ap = argp; | |
4645 int csi_len; | |
4646 | |
4647 // Check for non-digit after CSI. | |
4648 if (!VIM_ISDIGIT(*ap)) | |
4649 first = *ap++; | |
4650 | |
4651 // Find up to three argument numbers. | |
4652 for (argc = 0; argc < 3; ) | |
4653 { | 5289 { |
4654 if (ap >= tp + len) | 5290 # ifdef DEBUG_TERMRESPONSE |
4655 { | 5291 if (resp == -1) |
4656 not_enough: | |
4657 LOG_TR(("Not enough characters for CSI sequence")); | 5292 LOG_TR(("Not enough characters for CSI sequence")); |
4658 return -1; | 5293 # endif |
4659 } | 5294 return resp; |
4660 if (*ap == ';') | |
4661 arg[argc++] = -1; // omitted number | |
4662 else if (VIM_ISDIGIT(*ap)) | |
4663 { | |
4664 arg[argc] = 0; | |
4665 for (;;) | |
4666 { | |
4667 if (ap >= tp + len) | |
4668 goto not_enough; | |
4669 if (!VIM_ISDIGIT(*ap)) | |
4670 break; | |
4671 arg[argc] = arg[argc] * 10 + (*ap - '0'); | |
4672 ++ap; | |
4673 } | |
4674 ++argc; | |
4675 } | |
4676 if (*ap == ';') | |
4677 ++ap; | |
4678 else | |
4679 break; | |
4680 } | 5295 } |
4681 // mrxvt has been reported to have "+" in the version. Assume | |
4682 // the escape sequence ends with a letter or one of "{|}~". | |
4683 while (ap < tp + len | |
4684 && !(*ap >= '{' && *ap <= '~') | |
4685 && !ASCII_ISALPHA(*ap)) | |
4686 ++ap; | |
4687 if (ap >= tp + len) | |
4688 goto not_enough; | |
4689 trail = *ap; | |
4690 csi_len = (int)(ap - tp) + 1; | |
4691 | |
4692 // Cursor position report: Eat it when there are 2 arguments | |
4693 // and it ends in 'R'. Also when u7_status is not "sent", it | |
4694 // may be from a previous Vim that just exited. But not for | |
4695 // <S-F3>, it sends something similar, check for row and column | |
4696 // to make sense. | |
4697 if (first == -1 && argc == 2 && trail == 'R') | |
4698 { | |
4699 if (arg[0] == 2 && arg[1] >= 2) | |
4700 { | |
4701 char *aw = NULL; | |
4702 | |
4703 LOG_TR(("Received U7 status: %s", tp)); | |
4704 u7_status.tr_progress = STATUS_GOT; | |
4705 did_cursorhold = TRUE; | |
4706 if (arg[1] == 2) | |
4707 aw = "single"; | |
4708 else if (arg[1] == 3) | |
4709 aw = "double"; | |
4710 if (aw != NULL && STRCMP(aw, p_ambw) != 0) | |
4711 { | |
4712 // Setting the option causes a screen redraw. Do | |
4713 // that right away if possible, keeping any | |
4714 // messages. | |
4715 set_option_value((char_u *)"ambw", 0L, | |
4716 (char_u *)aw, 0); | |
4717 # ifdef DEBUG_TERMRESPONSE | |
4718 { | |
4719 int r = redraw_asap(CLEAR); | |
4720 | |
4721 log_tr("set 'ambiwidth', redraw_asap(): %d", r); | |
4722 } | |
4723 # else | |
4724 redraw_asap(CLEAR); | |
4725 # endif | |
4726 } | |
4727 } | |
4728 else if (arg[0] == 3) | |
4729 { | |
4730 // Third row: xterm compatibility test. | |
4731 // If the cursor is not on the first column then the | |
4732 // terminal is not xterm compatible. | |
4733 if (arg[1] != 1) | |
4734 xcc_test_failed = TRUE; | |
4735 xcc_status.tr_progress = STATUS_GOT; | |
4736 } | |
4737 | |
4738 key_name[0] = (int)KS_EXTRA; | |
4739 key_name[1] = (int)KE_IGNORE; | |
4740 slen = csi_len; | |
4741 # ifdef FEAT_EVAL | |
4742 set_vim_var_string(VV_TERMU7RESP, tp, slen); | |
4743 # endif | |
4744 } | |
4745 | |
4746 // Version string: Eat it when there is at least one digit and | |
4747 // it ends in 'c' | |
4748 else if (*T_CRV != NUL && ap > argp + 1 && trail == 'c') | |
4749 { | |
4750 int version = arg[1]; | |
4751 | |
4752 LOG_TR(("Received CRV response: %s", tp)); | |
4753 crv_status.tr_progress = STATUS_GOT; | |
4754 did_cursorhold = TRUE; | |
4755 | |
4756 // If this code starts with CSI, you can bet that the | |
4757 // terminal uses 8-bit codes. | |
4758 if (tp[0] == CSI) | |
4759 switch_to_8bit(); | |
4760 | |
4761 // Screen sends 40500. | |
4762 // rxvt sends its version number: "20703" is 2.7.3. | |
4763 // Ignore it for when the user has set 'term' to xterm, | |
4764 // even though it's an rxvt. | |
4765 if (version > 20000) | |
4766 version = 0; | |
4767 | |
4768 if (first == '>' && argc == 3) | |
4769 { | |
4770 int need_flush = FALSE; | |
4771 int is_iterm2 = FALSE; | |
4772 int is_mintty = FALSE; | |
4773 int is_screen = FALSE; | |
4774 | |
4775 // mintty 2.9.5 sends 77;20905;0c. | |
4776 // (77 is ASCII 'M' for mintty.) | |
4777 if (arg[0] == 77) | |
4778 is_mintty = TRUE; | |
4779 | |
4780 // if xterm version >= 141 try to get termcap codes | |
4781 if (version >= 141) | |
4782 { | |
4783 LOG_TR(("Enable checking for XT codes")); | |
4784 check_for_codes = TRUE; | |
4785 need_gather = TRUE; | |
4786 req_codes_from_term(); | |
4787 } | |
4788 | |
4789 // libvterm sends 0;100;0 | |
4790 if (version == 100 && arg[0] == 0 && arg[2] == 0) | |
4791 { | |
4792 // If run from Vim $COLORS is set to the number of | |
4793 // colors the terminal supports. Otherwise assume | |
4794 // 256, libvterm supports even more. | |
4795 if (mch_getenv((char_u *)"COLORS") == NULL) | |
4796 may_adjust_color_count(256); | |
4797 // Libvterm can handle SGR mouse reporting. | |
4798 if (!option_was_set((char_u *)"ttym")) | |
4799 set_option_value((char_u *)"ttym", 0L, | |
4800 (char_u *)"sgr", 0); | |
4801 } | |
4802 | |
4803 if (version == 95) | |
4804 { | |
4805 // Mac Terminal.app sends 1;95;0 | |
4806 if (arg[0] == 1 && arg[2] == 0) | |
4807 { | |
4808 is_not_xterm = TRUE; | |
4809 is_mac_terminal = TRUE; | |
4810 } | |
4811 // iTerm2 sends 0;95;0 | |
4812 else if (arg[0] == 0 && arg[2] == 0) | |
4813 is_iterm2 = TRUE; | |
4814 // old iTerm2 sends 0;95; | |
4815 else if (arg[0] == 0 && arg[2] == -1) | |
4816 is_not_xterm = TRUE; | |
4817 } | |
4818 | |
4819 // screen sends 83;40500;0 83 is 'S' in ASCII. | |
4820 if (arg[0] == 83) | |
4821 is_screen = TRUE; | |
4822 | |
4823 // Only set 'ttymouse' automatically if it was not set | |
4824 // by the user already. | |
4825 if (!option_was_set((char_u *)"ttym")) | |
4826 { | |
4827 // Xterm version 277 supports SGR. Also support | |
4828 // Terminal.app, iTerm2, mintty, and screen 4.7+. | |
4829 if ((!is_screen && version >= 277) | |
4830 || is_iterm2 | |
4831 || is_mac_terminal | |
4832 || is_mintty | |
4833 || (is_screen && arg[1] >= 40700)) | |
4834 set_option_value((char_u *)"ttym", 0L, | |
4835 (char_u *)"sgr", 0); | |
4836 // For xterm version >= 95 mouse dragging works. | |
4837 else if (version >= 95) | |
4838 set_option_value((char_u *)"ttym", 0L, | |
4839 (char_u *)"xterm2", 0); | |
4840 } | |
4841 | |
4842 // Detect terminals that set $TERM to something like | |
4843 // "xterm-256color" but are not fully xterm compatible. | |
4844 | |
4845 // Gnome terminal sends 1;3801;0, 1;4402;0 or 1;2501;0. | |
4846 // xfce4-terminal sends 1;2802;0. | |
4847 // screen sends 83;40500;0 | |
4848 // Assuming any version number over 2500 is not an | |
4849 // xterm (without the limit for rxvt and screen). | |
4850 if (arg[1] >= 2500) | |
4851 is_not_xterm = TRUE; | |
4852 | |
4853 // PuTTY sends 0;136;0 | |
4854 // vandyke SecureCRT sends 1;136;0 | |
4855 else if (version == 136 && arg[2] == 0) | |
4856 { | |
4857 is_not_xterm = TRUE; | |
4858 | |
4859 // PuTTY supports sgr-like mouse reporting, but | |
4860 // only set 'ttymouse' if it was not set by the | |
4861 // user already. | |
4862 if (arg[0] == 0 | |
4863 && !option_was_set((char_u *)"ttym")) | |
4864 set_option_value((char_u *)"ttym", 0L, | |
4865 (char_u *)"sgr", 0); | |
4866 } | |
4867 | |
4868 // Konsole sends 0;115;0 | |
4869 else if (version == 115 && arg[0] == 0 && arg[2] == 0) | |
4870 is_not_xterm = TRUE; | |
4871 | |
4872 // GNU screen sends 83;30600;0, 83;40500;0, etc. | |
4873 // 30600/40500 is a version number of GNU screen. DA2 | |
4874 // support is added on 3.6. DCS string has a special | |
4875 // meaning to GNU screen, but xterm compatibility | |
4876 // checking does not detect GNU screen. | |
4877 if (version >= 30600 && arg[0] == 83) | |
4878 xcc_test_failed = TRUE; | |
4879 | |
4880 // Xterm first responded to this request at patch level | |
4881 // 95, so assume anything below 95 is not xterm. | |
4882 if (version < 95) | |
4883 is_not_xterm = TRUE; | |
4884 | |
4885 // With the real Xterm setting the underline RGB color | |
4886 // clears the background color, disable "t_8u". | |
4887 if (!is_not_xterm && *T_8U != NUL) | |
4888 T_8U = empty_option; | |
4889 | |
4890 // Only request the cursor style if t_SH and t_RS are | |
4891 // set. Only supported properly by xterm since version | |
4892 // 279 (otherwise it returns 0x18). | |
4893 // Only when the xcc_status was set, the test finished, | |
4894 // and xcc_test_failed is FALSE; | |
4895 // Not for Terminal.app, it can't handle t_RS, it | |
4896 // echoes the characters to the screen. | |
4897 if (rcs_status.tr_progress == STATUS_GET | |
4898 && xcc_status.tr_progress == STATUS_GOT | |
4899 && !xcc_test_failed | |
4900 && version >= 279 | |
4901 && *T_CSH != NUL | |
4902 && *T_CRS != NUL) | |
4903 { | |
4904 LOG_TR(("Sending cursor style request")); | |
4905 out_str(T_CRS); | |
4906 termrequest_sent(&rcs_status); | |
4907 need_flush = TRUE; | |
4908 } | |
4909 | |
4910 // Only request the cursor blink mode if t_RC set. Not | |
4911 // for Gnome terminal, it can't handle t_RC, it | |
4912 // echoes the characters to the screen. | |
4913 // Only when the xcc_status was set, the test finished, | |
4914 // and xcc_test_failed is FALSE; | |
4915 if (rbm_status.tr_progress == STATUS_GET | |
4916 && xcc_status.tr_progress == STATUS_GOT | |
4917 && !xcc_test_failed | |
4918 && *T_CRC != NUL) | |
4919 { | |
4920 LOG_TR(("Sending cursor blink mode request")); | |
4921 out_str(T_CRC); | |
4922 termrequest_sent(&rbm_status); | |
4923 need_flush = TRUE; | |
4924 } | |
4925 | |
4926 if (need_flush) | |
4927 out_flush(); | |
4928 } | |
4929 slen = csi_len; | |
4930 # ifdef FEAT_EVAL | |
4931 set_vim_var_string(VV_TERMRESPONSE, tp, slen); | |
4932 # endif | |
4933 apply_autocmds(EVENT_TERMRESPONSE, | |
4934 NULL, NULL, FALSE, curbuf); | |
4935 key_name[0] = (int)KS_EXTRA; | |
4936 key_name[1] = (int)KE_IGNORE; | |
4937 } | |
4938 | |
4939 // Check blinking cursor from xterm: | |
4940 // {lead}?12;1$y set | |
4941 // {lead}?12;2$y not set | |
4942 // | |
4943 // {lead} can be <Esc>[ or CSI | |
4944 else if (rbm_status.tr_progress == STATUS_SENT | |
4945 && first == '?' | |
4946 && ap == argp + 6 | |
4947 && arg[0] == 12 | |
4948 && ap[-1] == '$' | |
4949 && trail == 'y') | |
4950 { | |
4951 initial_cursor_blink = (arg[1] == '1'); | |
4952 rbm_status.tr_progress = STATUS_GOT; | |
4953 LOG_TR(("Received cursor blinking mode response: %s", tp)); | |
4954 key_name[0] = (int)KS_EXTRA; | |
4955 key_name[1] = (int)KE_IGNORE; | |
4956 slen = csi_len; | |
4957 # ifdef FEAT_EVAL | |
4958 set_vim_var_string(VV_TERMBLINKRESP, tp, slen); | |
4959 # endif | |
4960 } | |
4961 | |
4962 // Check for a window position response from the terminal: | |
4963 // {lead}3;{x};{y}t | |
4964 else if (did_request_winpos && argc == 3 && arg[0] == 3 | |
4965 && trail == 't') | |
4966 { | |
4967 winpos_x = arg[1]; | |
4968 winpos_y = arg[2]; | |
4969 // got finished code: consume it | |
4970 key_name[0] = (int)KS_EXTRA; | |
4971 key_name[1] = (int)KE_IGNORE; | |
4972 slen = csi_len; | |
4973 | |
4974 if (--did_request_winpos <= 0) | |
4975 winpos_status.tr_progress = STATUS_GOT; | |
4976 } | |
4977 | |
4978 // Key with modifier: | |
4979 // {lead}27;{modifier};{key}~ | |
4980 // {lead}{key};{modifier}u | |
4981 else if ((arg[0] == 27 && argc == 3 && trail == '~') | |
4982 || (argc == 2 && trail == 'u')) | |
4983 { | |
4984 seenModifyOtherKeys = TRUE; | |
4985 if (trail == 'u') | |
4986 key = arg[0]; | |
4987 else | |
4988 key = arg[2]; | |
4989 | |
4990 modifiers = decode_modifiers(arg[1]); | |
4991 | |
4992 // Some keys already have Shift included, pass them as | |
4993 // normal keys. Not when Ctrl is also used, because <C-H> | |
4994 // and <C-S-H> are different. | |
4995 if (modifiers == MOD_MASK_SHIFT | |
4996 && ((key >= '@' && key <= 'Z') | |
4997 || key == '^' || key == '_' | |
4998 || (key >= '{' && key <= '~'))) | |
4999 modifiers = 0; | |
5000 | |
5001 // When used with Ctrl we always make a letter upper case, | |
5002 // so that mapping <C-H> and <C-h> are the same. Typing | |
5003 // <C-S-H> also uses "H" but modifier is different. | |
5004 if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) | |
5005 key = TOUPPER_ASC(key); | |
5006 | |
5007 // insert modifiers with KS_MODIFIER | |
5008 new_slen = modifiers2keycode(modifiers, &key, string); | |
5009 slen = csi_len; | |
5010 | |
5011 if (has_mbyte) | |
5012 new_slen += (*mb_char2bytes)(key, string + new_slen); | |
5013 else | |
5014 string[new_slen++] = key; | |
5015 | |
5016 if (put_string_in_typebuf(offset, slen, string, new_slen, | |
5017 buf, bufsize, buflen) == FAIL) | |
5018 return -1; | |
5019 return len + new_slen - slen + offset; | |
5020 } | |
5021 | |
5022 // else: Unknown CSI sequence. We could drop it, but then the | |
5023 // user can't create a map for it. | |
5024 } | 5296 } |
5025 | 5297 |
5026 // Check for fore/background color response from the terminal: | 5298 // Check for fore/background color response from the terminal, |
5027 // | 5299 // starting} with <Esc>] or OSC |
5028 // {lead}{code};rgb:{rrrr}/{gggg}/{bbbb}{tail} | |
5029 // or {lead}{code};rgb:{rr}/{gg}/{bb}{tail} | |
5030 // | |
5031 // {code} is 10 for foreground, 11 for background | |
5032 // {lead} can be <Esc>] or OSC | |
5033 // {tail} can be '\007', <Esc>\ or STERM. | |
5034 // | |
5035 // Consume any code that starts with "{lead}11;", it's also | |
5036 // possible that "rgba" is following. | |
5037 else if ((*T_RBG != NUL || *T_RFG != NUL) | 5300 else if ((*T_RBG != NUL || *T_RFG != NUL) |
5038 && ((tp[0] == ESC && len >= 2 && tp[1] == ']') | 5301 && ((tp[0] == ESC && len >= 2 && tp[1] == ']') |
5039 || tp[0] == OSC)) | 5302 || tp[0] == OSC)) |
5040 { | 5303 { |
5041 j = 1 + (tp[0] == ESC); | 5304 if (handle_osc(tp, argp, len, key_name, &slen) == FAIL) |
5042 if (len >= j + 3 && (argp[0] != '1' | |
5043 || (argp[1] != '1' && argp[1] != '0') | |
5044 || argp[2] != ';')) | |
5045 i = 0; // no match | |
5046 else | |
5047 for (i = j; i < len; ++i) | |
5048 if (tp[i] == '\007' || (tp[0] == OSC ? tp[i] == STERM | |
5049 : (tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\'))) | |
5050 { | |
5051 int is_bg = argp[1] == '1'; | |
5052 int is_4digit = i - j >= 21 && tp[j + 11] == '/' | |
5053 && tp[j + 16] == '/'; | |
5054 | |
5055 if (i - j >= 15 && STRNCMP(tp + j + 3, "rgb:", 4) == 0 | |
5056 && (is_4digit | |
5057 || (tp[j + 9] == '/' && tp[i + 12 == '/']))) | |
5058 { | |
5059 char_u *tp_r = tp + j + 7; | |
5060 char_u *tp_g = tp + j + (is_4digit ? 12 : 10); | |
5061 char_u *tp_b = tp + j + (is_4digit ? 17 : 13); | |
5062 # ifdef FEAT_TERMINAL | |
5063 int rval, gval, bval; | |
5064 | |
5065 rval = hexhex2nr(tp_r); | |
5066 gval = hexhex2nr(tp_b); | |
5067 bval = hexhex2nr(tp_g); | |
5068 # endif | |
5069 if (is_bg) | |
5070 { | |
5071 char *new_bg_val = (3 * '6' < *tp_r + *tp_g + | |
5072 *tp_b) ? "light" : "dark"; | |
5073 | |
5074 LOG_TR(("Received RBG response: %s", tp)); | |
5075 rbg_status.tr_progress = STATUS_GOT; | |
5076 # ifdef FEAT_TERMINAL | |
5077 bg_r = rval; | |
5078 bg_g = gval; | |
5079 bg_b = bval; | |
5080 # endif | |
5081 if (!option_was_set((char_u *)"bg") | |
5082 && STRCMP(p_bg, new_bg_val) != 0) | |
5083 { | |
5084 // value differs, apply it | |
5085 set_option_value((char_u *)"bg", 0L, | |
5086 (char_u *)new_bg_val, 0); | |
5087 reset_option_was_set((char_u *)"bg"); | |
5088 redraw_asap(CLEAR); | |
5089 } | |
5090 } | |
5091 # ifdef FEAT_TERMINAL | |
5092 else | |
5093 { | |
5094 LOG_TR(("Received RFG response: %s", tp)); | |
5095 rfg_status.tr_progress = STATUS_GOT; | |
5096 fg_r = rval; | |
5097 fg_g = gval; | |
5098 fg_b = bval; | |
5099 } | |
5100 # endif | |
5101 } | |
5102 | |
5103 // got finished code: consume it | |
5104 key_name[0] = (int)KS_EXTRA; | |
5105 key_name[1] = (int)KE_IGNORE; | |
5106 slen = i + 1 + (tp[i] == ESC); | |
5107 # ifdef FEAT_EVAL | |
5108 set_vim_var_string(is_bg ? VV_TERMRBGRESP | |
5109 : VV_TERMRFGRESP, tp, slen); | |
5110 # endif | |
5111 break; | |
5112 } | |
5113 if (i == len) | |
5114 { | |
5115 LOG_TR(("not enough characters for RB")); | |
5116 return -1; | 5305 return -1; |
5117 } | |
5118 } | 5306 } |
5119 | 5307 |
5120 // Check for key code response from xterm: | 5308 // Check for key code response from xterm, |
5121 // {lead}{flag}+r<hex bytes><{tail} | 5309 // starting with <Esc>P or DCS |
5122 // | |
5123 // {lead} can be <Esc>P or DCS | |
5124 // {flag} can be '0' or '1' | |
5125 // {tail} can be Esc>\ or STERM | |
5126 // | |
5127 // Check for cursor shape response from xterm: | |
5128 // {lead}1$r<digit> q{tail} | |
5129 // | |
5130 // {lead} can be <Esc>P or DCS | |
5131 // {tail} can be <Esc>\ or STERM | |
5132 // | |
5133 // Consume any code that starts with "{lead}.+r" or "{lead}.$r". | |
5134 else if ((check_for_codes || rcs_status.tr_progress == STATUS_SENT) | 5310 else if ((check_for_codes || rcs_status.tr_progress == STATUS_SENT) |
5135 && ((tp[0] == ESC && len >= 2 && tp[1] == 'P') | 5311 && ((tp[0] == ESC && len >= 2 && tp[1] == 'P') |
5136 || tp[0] == DCS)) | 5312 || tp[0] == DCS)) |
5137 { | 5313 { |
5138 j = 1 + (tp[0] == ESC); | 5314 if (handle_dcs(tp, argp, len, key_name, &slen) == FAIL) |
5139 if (len < j + 3) | |
5140 i = len; // need more chars | |
5141 else if ((argp[1] != '+' && argp[1] != '$') || argp[2] != 'r') | |
5142 i = 0; // no match | |
5143 else if (argp[1] == '+') | |
5144 // key code response | |
5145 for (i = j; i < len; ++i) | |
5146 { | |
5147 if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\') | |
5148 || tp[i] == STERM) | |
5149 { | |
5150 if (i - j >= 3) | |
5151 got_code_from_term(tp + j, i); | |
5152 key_name[0] = (int)KS_EXTRA; | |
5153 key_name[1] = (int)KE_IGNORE; | |
5154 slen = i + 1 + (tp[i] == ESC); | |
5155 break; | |
5156 } | |
5157 } | |
5158 else | |
5159 { | |
5160 // Probably the cursor shape response. Make sure that "i" | |
5161 // is equal to "len" when there are not sufficient | |
5162 // characters. | |
5163 for (i = j + 3; i < len; ++i) | |
5164 { | |
5165 if (i - j == 3 && !isdigit(tp[i])) | |
5166 break; | |
5167 if (i - j == 4 && tp[i] != ' ') | |
5168 break; | |
5169 if (i - j == 5 && tp[i] != 'q') | |
5170 break; | |
5171 if (i - j == 6 && tp[i] != ESC && tp[i] != STERM) | |
5172 break; | |
5173 if ((i - j == 6 && tp[i] == STERM) | |
5174 || (i - j == 7 && tp[i] == '\\')) | |
5175 { | |
5176 int number = argp[3] - '0'; | |
5177 | |
5178 // 0, 1 = block blink, 2 = block | |
5179 // 3 = underline blink, 4 = underline | |
5180 // 5 = vertical bar blink, 6 = vertical bar | |
5181 number = number == 0 ? 1 : number; | |
5182 initial_cursor_shape = (number + 1) / 2; | |
5183 // The blink flag is actually inverted, compared to | |
5184 // the value set with T_SH. | |
5185 initial_cursor_shape_blink = | |
5186 (number & 1) ? FALSE : TRUE; | |
5187 rcs_status.tr_progress = STATUS_GOT; | |
5188 LOG_TR(("Received cursor shape response: %s", tp)); | |
5189 | |
5190 key_name[0] = (int)KS_EXTRA; | |
5191 key_name[1] = (int)KE_IGNORE; | |
5192 slen = i + 1; | |
5193 # ifdef FEAT_EVAL | |
5194 set_vim_var_string(VV_TERMSTYLERESP, tp, slen); | |
5195 # endif | |
5196 break; | |
5197 } | |
5198 } | |
5199 } | |
5200 | |
5201 if (i == len) | |
5202 { | |
5203 // These codes arrive many together, each code can be | |
5204 // truncated at any point. | |
5205 LOG_TR(("not enough characters for XT")); | |
5206 return -1; | 5315 return -1; |
5207 } | |
5208 } | 5316 } |
5209 } | 5317 } |
5210 #endif | 5318 #endif |
5211 | 5319 |
5212 if (key_name[0] == NUL) | 5320 if (key_name[0] == NUL) |