diff src/term.c @ 13823:d0d8125ba692 v8.0.1783

patch 8.0.1783: cannot use 256 colors in a MS-Windows console commit https://github.com/vim/vim/commit/c5cd88554f1e0b2e9ff08d9a0748238dd8340ce1 Author: Bram Moolenaar <Bram@vim.org> Date: Tue May 1 15:47:38 2018 +0200 patch 8.0.1783: cannot use 256 colors in a MS-Windows console Problem: Cannot use 256 colors in a MS-Windows console. Solution: Add 256 color support. (Nobuhiro Takasaki, closes https://github.com/vim/vim/issues/2821)
author Christian Brabandt <cb@256bit.org>
date Tue, 01 May 2018 16:00:07 +0200
parents 5cf4a504bcc0
children 27e09f1a8e5c
line wrap: on
line diff
--- a/src/term.c
+++ b/src/term.c
@@ -2009,11 +2009,6 @@ set_termname(char_u *term)
     may_req_termresponse();
 #endif
 
-#if defined(WIN3264) && !defined(FEAT_GUI) && defined(FEAT_TERMGUICOLORS)
-    if (STRCMP(term, "win32") == 0)
-	set_color_count((p_tgc) ? 256 : 16);
-#endif
-
     return OK;
 }
 
@@ -2851,7 +2846,11 @@ term_color(char_u *s, int n)
     /* Also accept "\e[3%dm" for TERMINFO, it is sometimes used */
     /* Also accept CSI instead of <Esc>[ */
     if (n >= 8 && t_colors >= 16
-	      && ((s[0] == ESC && s[1] == '[') || (s[0] == CSI && (i = 1) == 1))
+	      && ((s[0] == ESC && s[1] == '[')
+#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
+		  || (s[0] == ESC && s[1] == '|')
+#endif
+	          || (s[0] == CSI && (i = 1) == 1))
 	      && s[i] != NUL
 	      && (STRCMP(s + i + 1, "%p1%dm") == 0
 		  || STRCMP(s + i + 1, "%dm") == 0)
@@ -2863,7 +2862,11 @@ term_color(char_u *s, int n)
 	char *format = "%s%s%%dm";
 #endif
 	sprintf(buf, format,
-		i == 2 ? IF_EB("\033[", ESC_STR "[") : "\233",
+		i == 2 ?
+#if defined(FEAT_VTP) && defined(FEAT_TERMGUICOLORS)
+		s[1] == '|' ? IF_EB("\033|", ESC_STR "|") :
+#endif
+		IF_EB("\033[", ESC_STR "[") : "\233",
 		s[i] == '3' ? (n >= 16 ? "38;5;" : "9")
 			    : (n >= 16 ? "48;5;" : "10"));
 	OUT_STR(tgoto(buf, 0, n >= 16 ? n : n - 8));
@@ -6640,26 +6643,38 @@ update_tcap(int attr)
 }
 
 # ifdef FEAT_TERMGUICOLORS
+#  define KSSIZE 20
 struct ks_tbl_s
 {
-    int  code;	    /* value of KS_ */
-    char *vtp;	    /* code in vtp mode */
-    char *buf;	    /* buffer in non-vtp mode */
-    char *vbuf;	    /* buffer in vtp mode */
+    int  code;		/* value of KS_ */
+    char *vtp;		/* code in vtp mode */
+    char *vtp2;		/* code in vtp2 mode */
+    char buf[KSSIZE];   /* save buffer in non-vtp mode */
+    char vbuf[KSSIZE];  /* save buffer in vtp mode */
+    char v2buf[KSSIZE]; /* save buffer in vtp2 mode */
+    char arr[KSSIZE];   /* real buffer */
 };
 
 static struct ks_tbl_s ks_tbl[] =
 {
-    {(int)KS_ME,  "\033|0m" },	/* normal */
-    {(int)KS_MR,  "\033|7m" },	/* reverse */
-    {(int)KS_MD,  "\033|1m" },	/* bold */
-    {(int)KS_SO,  "\033|91m"},	/* standout: bright red text */
-    {(int)KS_SE,  "\033|39m"},	/* standout end: default color */
-    {(int)KS_CZH, "\033|95m"},	/* italic: bright magenta text */
-    {(int)KS_CZR, "\033|0m",},	/* italic end */
-    {(int)KS_US,  "\033|4m",},	/* underscore */
-    {(int)KS_UE,  "\033|24m"},	/* underscore end */
-    {(int)KS_NAME, NULL}
+    {(int)KS_ME,  "\033|0m",  "\033|0m"},   /* normal */
+    {(int)KS_MR,  "\033|7m",  "\033|7m"},   /* reverse */
+    {(int)KS_MD,  "\033|1m",  "\033|1m"},   /* bold */
+    {(int)KS_SO,  "\033|91m", "\033|91m"},  /* standout: bright red text */
+    {(int)KS_SE,  "\033|39m", "\033|39m"},  /* standout end: default color */
+    {(int)KS_CZH, "\033|95m", "\033|95m"},  /* italic: bright magenta text */
+    {(int)KS_CZR, "\033|0m",  "\033|0m"},   /* italic end */
+    {(int)KS_US,  "\033|4m",  "\033|4m"},   /* underscore */
+    {(int)KS_UE,  "\033|24m", "\033|24m"},  /* underscore end */
+#  ifdef TERMINFO
+    {(int)KS_CAB, "\033|%p1%db", "\033|%p14%dm"}, /* set background color */
+    {(int)KS_CAF, "\033|%p1%df", "\033|%p13%dm"}, /* set foreground color */
+#  else
+    {(int)KS_CAB, "\033|%db", "\033|4%dm"}, /* set background color */
+    {(int)KS_CAF, "\033|%df", "\033|3%dm"}, /* set foreground color */
+#  endif
+    {(int)KS_CCO, "16", "256"},     /* colors */
+    {(int)KS_NAME}		    /* terminator */
 };
 
     static struct builtin_term *
@@ -6684,57 +6699,85 @@ swap_tcap(void)
 {
 # ifdef FEAT_TERMGUICOLORS
     static int		init_done = FALSE;
-    static int		last_tgc;
+    static int		curr_mode;
     struct ks_tbl_s	*ks;
     struct builtin_term *bt;
+    int			mode;
+    enum
+    {
+	CMODEINDEX,
+	CMODE24,
+	CMODE256
+    };
 
     /* buffer initialization */
     if (!init_done)
     {
-	for (ks = ks_tbl; ks->vtp != NULL; ks++)
+	for (ks = ks_tbl; ks->code != (int)KS_NAME; ks++)
 	{
 	    bt = find_first_tcap(DEFAULT_TERM, ks->code);
 	    if (bt != NULL)
 	    {
-		ks->buf = bt->bt_string;
-		ks->vbuf = ks->vtp;
+		STRNCPY(ks->buf, bt->bt_string, KSSIZE);
+		STRNCPY(ks->vbuf, ks->vtp, KSSIZE);
+		STRNCPY(ks->v2buf, ks->vtp2, KSSIZE);
+
+		STRNCPY(ks->arr, bt->bt_string, KSSIZE);
+		bt->bt_string = &ks->arr[0];
 	    }
 	}
 	init_done = TRUE;
-	last_tgc = p_tgc;
-	return;
+	curr_mode = CMODEINDEX;
     }
 
-    if (last_tgc != p_tgc)
+    if (p_tgc)
+	mode = CMODE24;
+    else if (t_colors >= 256)
+	mode = CMODE256;
+    else
+	mode = CMODEINDEX;
+
+    for (ks = ks_tbl; ks->code != (int)KS_NAME; ks++)
     {
-	if (p_tgc)
+	bt = find_first_tcap(DEFAULT_TERM, ks->code);
+	if (bt != NULL)
 	{
-	    /* switch to special character sequence */
-	    for (ks = ks_tbl; ks->vtp != NULL; ks++)
+	    switch (curr_mode)
 	    {
-		bt = find_first_tcap(DEFAULT_TERM, ks->code);
-		if (bt != NULL)
+	    case CMODEINDEX:
+		STRNCPY(&ks->buf[0], bt->bt_string, KSSIZE);
+		break;
+	    case CMODE24:
+		STRNCPY(&ks->vbuf[0], bt->bt_string, KSSIZE);
+		break;
+	    default:
+		STRNCPY(&ks->v2buf[0], bt->bt_string, KSSIZE);
+	    }
+	}
+    }
+
+    if (mode != curr_mode)
+    {
+	for (ks = ks_tbl; ks->code != (int)KS_NAME; ks++)
+	{
+	    bt = find_first_tcap(DEFAULT_TERM, ks->code);
+	    if (bt != NULL)
+	    {
+		switch (mode)
 		{
-		    ks->buf = bt->bt_string;
-		    bt->bt_string = ks->vbuf;
+		case CMODEINDEX:
+		    STRNCPY(bt->bt_string, &ks->buf[0], KSSIZE);
+		    break;
+		case CMODE24:
+		    STRNCPY(bt->bt_string, &ks->vbuf[0], KSSIZE);
+		    break;
+		default:
+		    STRNCPY(bt->bt_string, &ks->v2buf[0], KSSIZE);
 		}
 	    }
 	}
-	else
-	{
-	    /* switch to index color */
-	    for (ks = ks_tbl; ks->vtp != NULL; ks++)
-	    {
-		bt = find_first_tcap(DEFAULT_TERM, ks->code);
-		if (bt != NULL)
-		{
-		    ks->vbuf = bt->bt_string;
-		    bt->bt_string = ks->buf;
-		}
-	    }
-	}
-
-	last_tgc = p_tgc;
+
+	curr_mode = mode;
     }
 # endif
 }
@@ -6920,3 +6963,79 @@ gui_get_rgb_color_cmn(int r, int g, int 
     return color;
 }
 #endif
+
+#if (defined(WIN3264) && !defined(FEAT_GUI_W32)) || defined(FEAT_TERMINAL) \
+	|| defined(PROTO)
+static int cube_value[] = {
+    0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF
+};
+
+static int grey_ramp[] = {
+    0x08, 0x12, 0x1C, 0x26, 0x30, 0x3A, 0x44, 0x4E, 0x58, 0x62, 0x6C, 0x76,
+    0x80, 0x8A, 0x94, 0x9E, 0xA8, 0xB2, 0xBC, 0xC6, 0xD0, 0xDA, 0xE4, 0xEE
+};
+
+# ifdef FEAT_TERMINAL
+#  include "libvterm/include/vterm.h"  // for VTERM_ANSI_INDEX_NONE
+# endif
+
+static uint8_t ansi_table[16][4] = {
+//   R    G    B   idx
+  {  0,   0,   0,  1}, // black
+  {224,   0,   0,  2}, // dark red
+  {  0, 224,   0,  3}, // dark green
+  {224, 224,   0,  4}, // dark yellow / brown
+  {  0,   0, 224,  5}, // dark blue
+  {224,   0, 224,  6}, // dark magenta
+  {  0, 224, 224,  7}, // dark cyan
+  {224, 224, 224,  8}, // light grey
+
+  {128, 128, 128,  9}, // dark grey
+  {255,  64,  64, 10}, // light red
+  { 64, 255,  64, 11}, // light green
+  {255, 255,  64, 12}, // yellow
+  { 64,  64, 255, 13}, // light blue
+  {255,  64, 255, 14}, // light magenta
+  { 64, 255, 255, 15}, // light cyan
+  {255, 255, 255, 16}, // white
+};
+
+    void
+cterm_color2rgb(int nr, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *ansi_idx)
+{
+    int idx;
+
+    if (nr < 16)
+    {
+	*r = ansi_table[nr][0];
+	*g = ansi_table[nr][1];
+	*b = ansi_table[nr][2];
+	*ansi_idx = ansi_table[nr][3];
+    }
+    else if (nr < 232)
+    {
+	/* 216 color cube */
+	idx = nr - 16;
+	*r = cube_value[idx / 36 % 6];
+	*g = cube_value[idx / 6  % 6];
+	*b = cube_value[idx      % 6];
+	*ansi_idx = VTERM_ANSI_INDEX_NONE;
+    }
+    else if (nr < 256)
+    {
+	/* 24 grey scale ramp */
+	idx = nr - 232;
+	*r = grey_ramp[idx];
+	*g = grey_ramp[idx];
+	*b = grey_ramp[idx];
+	*ansi_idx = VTERM_ANSI_INDEX_NONE;
+    }
+    else
+    {
+	*r = 0;
+	*g = 0;
+	*b = 0;
+	*ansi_idx = 0;
+    }
+}
+#endif