changeset 6874:a89cff862dda v7.4.757

patch 7.4.757 Problem: Cannot detect the background color of a terminal. Solution: Add T_RBG to request the background color if possible. (Lubomir Rintel)
author Bram Moolenaar <bram@vim.org>
date Thu, 25 Jun 2015 17:03:36 +0200
parents 48ad20643c92
children e21db7bc04e2
files src/main.c src/proto/term.pro src/term.c src/term.h src/version.c
diffstat 5 files changed, 86 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/main.c
+++ b/src/main.c
@@ -837,8 +837,11 @@ vim_main2(int argc UNUSED, char **argv U
 
     starttermcap();	    /* start termcap if not done by wait_return() */
     TIME_MSG("start termcap");
-#if defined(FEAT_TERMRESPONSE) && defined(FEAT_MBYTE)
+#if defined(FEAT_TERMRESPONSE)
+# if defined(FEAT_MBYTE)
     may_req_ambiguous_char_width();
+# endif
+    may_req_bg_color();
 #endif
 
 #ifdef FEAT_MOUSE
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -36,6 +36,7 @@ void starttermcap __ARGS((void));
 void stoptermcap __ARGS((void));
 void may_req_termresponse __ARGS((void));
 void may_req_ambiguous_char_width __ARGS((void));
+void may_req_bg_color __ARGS((void));
 int swapping_screen __ARGS((void));
 void setmouse __ARGS((void));
 int mouse_has __ARGS((int c));
--- a/src/term.c
+++ b/src/term.c
@@ -124,6 +124,11 @@ static int crv_status = CRV_GET;
 #  define U7_SENT	2	/* did send T_U7, waiting for answer */
 #  define U7_GOT	3	/* received T_U7 response */
 static int u7_status = U7_GET;
+/* Request background color report: */
+#  define RBG_GET	1	/* send T_RBG when switched to RAW mode */
+#  define RBG_SENT	2	/* did send T_RBG, waiting for answer */
+#  define RBG_GOT	3	/* received T_RBG response */
+static int rbg_status = RBG_GET;
 # endif
 
 /*
@@ -949,6 +954,7 @@ static struct builtin_term builtin_termc
     {(int)KS_CWP,	IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")},
 #  endif
     {(int)KS_CRV,	IF_EB("\033[>c", ESC_STR "[>c")},
+    {(int)KS_RBG,	IF_EB("\033]11;?\007", ESC_STR "]11;?\007")},
     {(int)KS_U7,	IF_EB("\033[6n", ESC_STR "[6n")},
 
     {K_UP,		IF_EB("\033O*A", ESC_STR "O*A")},
@@ -1240,6 +1246,7 @@ static struct builtin_term builtin_termc
 #  endif
     {(int)KS_CRV,	"[CRV]"},
     {(int)KS_U7,	"[U7]"},
+    {(int)KS_RBG,	"[RBG]"},
     {K_UP,		"[KU]"},
     {K_DOWN,		"[KD]"},
     {K_LEFT,		"[KL]"},
@@ -3224,7 +3231,8 @@ settmode(tmode)
 		 * doesn't work in Cooked mode, an external program may get
 		 * them. */
 		if (tmode != TMODE_RAW && (crv_status == CRV_SENT
-					 || u7_status == U7_SENT))
+					 || u7_status == U7_SENT
+					 || rbg_status == RBG_SENT))
 		    (void)vpeekc_nomap();
 		check_for_codes_from_term();
 	    }
@@ -3285,8 +3293,9 @@ stoptermcap()
 	if (!gui.in_use && !gui.starting)
 # endif
 	{
-	    /* May need to discard T_CRV or T_U7 response. */
-	    if (crv_status == CRV_SENT || u7_status == U7_SENT)
+	    /* May need to discard T_CRV, T_U7 or T_RBG response. */
+	    if (crv_status == CRV_SENT || u7_status == U7_SENT
+						     || rbg_status == RBG_SENT)
 	    {
 # ifdef UNIX
 		/* Give the terminal a chance to respond. */
@@ -3398,6 +3407,41 @@ may_req_ambiguous_char_width()
 }
 # endif
 
+#if defined(FEAT_TERMRESPONSE) || defined(PROTO)
+/*
+ * Check how the terminal treats ambiguous character width (UAX #11).
+ * First, we move the cursor to (1, 0) and print a test ambiguous character
+ * \u25bd (WHITE DOWN-POINTING TRIANGLE) and query current cursor position.
+ * If the terminal treats \u25bd as single width, the position is (1, 1),
+ * or if it is treated as double width, that will be (1, 2).
+ * This function has the side effect that changes cursor position, so
+ * it must be called immediately after entering termcap mode.
+ */
+    void
+may_req_bg_color()
+{
+    if (rbg_status == RBG_GET
+	    && cur_tmode == TMODE_RAW
+	    && termcap_active
+	    && p_ek
+#  ifdef UNIX
+	    && isatty(1)
+	    && isatty(read_cmd_fd)
+#  endif
+	    && *T_RBG != NUL
+	    && !option_was_set((char_u *)"bg"))
+    {
+	LOG_TR("Sending BG request");
+	out_str(T_RBG);
+	rbg_status = RBG_SENT;
+	/* check for the characters now, otherwise they might be eaten by
+	 * get_keystroke() */
+	out_flush();
+	(void)vpeekc_nomap();
+    }
+}
+# endif
+
 # ifdef DEBUG_TERMRESPONSE
     static void
 log_tr(char *msg)
@@ -4222,12 +4266,18 @@ check_termcode(max_offset, buf, bufsize,
 	     * - Cursor position report: <Esc>[{row};{col}R
 	     *   The final byte must be 'R'. It is used for checking the
 	     *   ambiguous-width character state.
+	     *
+	     * - Background color response:
+	     *       <Esc>]11;rgb:{rrrr}/{gggg}/{bbbb}\007
+	     *   The final byte must be '\007'.
 	     */
-	    p = tp[0] == CSI ? tp + 1 : tp + 2;
-	    if ((*T_CRV != NUL || *T_U7 != NUL)
+	    char_u *argp = tp[0] == CSI ? tp + 1 : tp + 2;
+
+	    if ((*T_CRV != NUL || *T_U7 != NUL || *T_RBG != NUL)
 			&& ((tp[0] == ESC && tp[1] == '[' && len >= 3)
+			    || (tp[0] == ESC && tp[1] == ']' && len >= 24)
 			    || (tp[0] == CSI && len >= 2))
-			&& (VIM_ISDIGIT(*p) || *p == '>' || *p == '?'))
+			&& (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?'))
 	    {
 #ifdef FEAT_MBYTE
 		int col;
@@ -4363,6 +4413,27 @@ check_termcode(max_offset, buf, bufsize,
 		    key_name[1] = (int)KE_IGNORE;
 		    slen = i + 1;
 		}
+		else if (*T_RBG != NUL && len >= 24 - (tp[0] == CSI)
+			&& 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')
+		{
+		    LOG_TR("Received RBG");
+		    rbg_status = RBG_GOT;
+		    if (!option_was_set((char_u *)"bg"))
+		    {
+			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);
+		    }
+		    key_name[0] = (int)KS_EXTRA;
+		    key_name[1] = (int)KE_IGNORE;
+		    slen = 24;
+		}
 	    }
 
 	    /* Check for '<Esc>P1+r<hex bytes><Esc>\'.  A "0" instead of the
--- a/src/term.h
+++ b/src/term.h
@@ -79,6 +79,7 @@ enum SpecialKey
     KS_CWP,	/* set window position in pixels */
     KS_CWS,	/* set window size in characters */
     KS_CRV,	/* request version string */
+    KS_RBG,	/* request background color */
     KS_CSI,	/* start insert mode (bar cursor) */
     KS_CEI,	/* end insert mode (block cursor) */
     KS_CSR,	/* start replace mode (underline cursor) */
@@ -162,6 +163,7 @@ extern char_u *(term_strings[]);    /* c
 #define T_CEI	(term_str(KS_CEI))	/* end insert mode */
 #define T_CSR	(term_str(KS_CSR))	/* start replace mode */
 #define T_CRV	(term_str(KS_CRV))	/* request version string */
+#define T_RBG	(term_str(KS_RBG))	/* request background RGB */
 #define T_OP	(term_str(KS_OP))	/* original color pair */
 #define T_U7	(term_str(KS_U7))	/* request cursor position */
 
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    757,
+/**/
     756,
 /**/
     755,