From 46fd4df719b1c3f3d84474c71da8b10e17601ffc Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 10 Jul 2015 14:05:10 +0200 Subject: patch 7.4.770 Problem: Background color response with transparency is not ignored. Solution: Change the way escape sequences are recognized. (partly by Hirohito Higashi) --- src/ascii.h | 16 ++++----- src/term.c | 111 +++++++++++++++++++++++++++++++++++++--------------------- src/version.c | 2 ++ 3 files changed, 80 insertions(+), 49 deletions(-) diff --git a/src/ascii.h b/src/ascii.h index a3cfecff71..7ed736a9f6 100644 --- a/src/ascii.h +++ b/src/ascii.h @@ -34,10 +34,6 @@ #define ESC_STR_nc "\033" #define DEL 0x7f #define DEL_STR (char_u *)"\177" -#define CSI 0x9b /* Control Sequence Introducer */ -#define CSI_STR "\233" -#define DCS 0x90 /* Device Control String */ -#define STERM 0x9c /* String Terminator */ #define POUND 0xA3 @@ -117,11 +113,6 @@ #define ESC_STR_nc "\x27" #define DEL 0x07 #define DEL_STR (char_u *)"\007" -/* TODO: EBCDIC Code page dependent (here 1047) */ -#define CSI 0x9b /* Control Sequence Introducer */ -#define CSI_STR "\233" -#define DCS 0x90 /* Device Control String */ -#define STERM 0x9c /* String Terminator */ #define POUND 0xB1 @@ -173,6 +164,13 @@ extern char MetaCharTable[]; #endif /* defined EBCDIC */ +/* TODO: EBCDIC Code page dependent (here 1047) */ +#define CSI 0x9b /* Control Sequence Introducer */ +#define CSI_STR "\233" +#define DCS 0x90 /* Device Control String */ +#define OSC 0x9d /* Operating System Command */ +#define STERM 0x9c /* String Terminator */ + /* * Character that separates dir names in a path. * For MS-DOS, WIN32 and OS/2 we use a backslash. A slash mostly works diff --git a/src/term.c b/src/term.c index 8d8ac407f7..d35a57e046 100644 --- a/src/term.c +++ b/src/term.c @@ -2364,7 +2364,7 @@ term_7to8bit(p) if (p[1] == '[') return CSI; if (p[1] == ']') - return 0x9d; + return OSC; if (p[1] == 'O') return 0x8f; } @@ -4261,18 +4261,11 @@ check_termcode(max_offset, buf, bufsize, buflen) * - Cursor position report: [{row};{col}R * The final byte must be 'R'. It is used for checking the * ambiguous-width character state. - * - * - Background color response: - * ]11;rgb:{rrrr}/{gggg}/{bbbb}\007 - * Or - * ]11;rgb:{rrrr}/{gggg}/{bbbb}ST - * The final byte must be '\007' or ST(0x9c or ESC\). */ - char_u *argp = tp[0] == CSI ? tp + 1 : tp + 2; + char_u *argp = tp[0] == ESC ? tp + 2 : tp + 1; - if ((*T_CRV != NUL || *T_U7 != NUL || *T_RBG != NUL) - && ((tp[0] == ESC && tp[1] == '[' && len >= 3) - || (tp[0] == ESC && tp[1] == ']' && len >= 24) + if ((*T_CRV != NUL || *T_U7 != NUL) + && ((tp[0] == ESC && len >= 3 && tp[1] == '[') || (tp[0] == CSI && len >= 2)) && (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?')) { @@ -4410,44 +4403,80 @@ check_termcode(max_offset, buf, bufsize, buflen) key_name[1] = (int)KE_IGNORE; slen = i + 1; } - else if (*T_RBG != NUL - && len >= 24 - (tp[0] == CSI) - && len >= 24 - (tp[0] == CSI) + (argp[21] == ESC) - && argp[0] == '1' && argp[1] == '1' - && argp[2] == ';' && argp[3] == 'r' && argp[4] == 'g' - && argp[5] == 'b' && argp[6] == ':' - && argp[11] == '/' && argp[16] == '/' - && (argp[21] == '\007' || argp[21] == STERM - || (argp[21] == ESC && argp[22] == '\\'))) - { - LOG_TR("Received RBG"); - rbg_status = RBG_GOT; - if (!option_was_set((char_u *)"bg")) + } + + /* Check for background color response from the terminal: + * + * {lead}11;rgb:{rrrr}/{gggg}/{bbbb}{tail} + * + * {lead} can be ] or OSC + * {tail} can be '\007', \ or STERM. + * + * Consume any code that starts with "{lead}11;", it's also + * possible that "rgba" is following. + */ + else if (*T_RBG != NUL + && ((tp[0] == ESC && len >= 2 && tp[1] == ']') + || tp[0] == OSC)) + { + j = 1 + (tp[0] == ESC); + if (len >= j + 3 && (argp[0] != '1' + || argp[1] != '1' || argp[2] != ';')) + i = 0; /* no match */ + else + for (i = j; i < len; ++i) + if (tp[i] == '\007' || (tp[0] == OSC ? tp[i] == STERM + : (tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\'))) { - set_option_value((char_u *)"bg", 0L, (char_u *)( - (3 * '6' < argp[7] + argp[12] + argp[17]) - ? "light" : "dark"), 0); - reset_option_was_set((char_u *)"bg"); - redraw_asap(CLEAR); + if (i - j >= 21 && STRNCMP(tp + j + 3, "rgb:", 4) == 0 + && tp[j + 11] == '/' && tp[j + 16] == '/' + && !option_was_set((char_u *)"bg")) + {/* TODO: don't set option when already the right value */ + LOG_TR("Received RBG"); + rbg_status = RBG_GOT; + set_option_value((char_u *)"bg", 0L, (char_u *)( + (3 * '6' < tp[j+7] + tp[j+12] + tp[j+17]) + ? "light" : "dark"), 0); + reset_option_was_set((char_u *)"bg"); + redraw_asap(CLEAR); + } + + /* got finished code: consume it */ + key_name[0] = (int)KS_EXTRA; + key_name[1] = (int)KE_IGNORE; + slen = i + 1 + (tp[i] == ESC); + break; } - key_name[0] = (int)KS_EXTRA; - key_name[1] = (int)KE_IGNORE; - slen = 24 - (tp[0] == CSI) + (argp[21] == ESC); + if (i == len) + { + LOG_TR("not enough characters for RB"); + return -1; } } - /* Check for 'P1+r\'. A "0" instead of the - * "1" means an invalid request. */ + /* Check for key code response from xterm: + * + * {lead}{flag}+r<{tail} + * + * {lead} can be P or DCS + * {flag} can be '0' or '1' + * {tail} can be Esc>\ or STERM + * + * Consume any code that starts with "{lead}.+r". + */ else if (check_for_codes - && ((tp[0] == ESC && tp[1] == 'P' && len >= 2) + && ((tp[0] == ESC && len >= 2 && tp[1] == 'P') || tp[0] == DCS)) { - j = 1 + (tp[0] != DCS); - for (i = j; i < len; ++i) - if ((tp[i] == ESC && tp[i + 1] == '\\' && i + 1 < len) + j = 1 + (tp[0] == ESC); + if (len >= j + 3 && (argp[1] != '+' || argp[2] != 'r')) + i = 0; /* no match */ + else + for (i = j; i < len; ++i) + if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\') || tp[i] == STERM) { - if (i - j >= 3 && tp[j + 1] == '+' && tp[j + 2] == 'r') + if (i - j >= 3) got_code_from_term(tp + j, i); key_name[0] = (int)KS_EXTRA; key_name[1] = (int)KE_IGNORE; @@ -4457,8 +4486,10 @@ check_termcode(max_offset, buf, bufsize, buflen) if (i == len) { + /* These codes arrive many together, each code can be + * truncated at any point. */ LOG_TR("not enough characters for XT"); - return -1; /* not enough characters */ + return -1; } } } diff --git a/src/version.c b/src/version.c index cd2604875e..3e09845856 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 770, /**/ 769, /**/ -- cgit v1.2.3