changeset 20619:68c206d3a251 v8.2.0863

patch 8.2.0863: cannot set a separate color for underline/undercurl Commit: https://github.com/vim/vim/commit/e023e88bed3f2e0a7ea4cf10cac2de80bc9c271c Author: Bram Moolenaar <Bram@vim.org> Date: Sun May 31 16:42:30 2020 +0200 patch 8.2.0863: cannot set a separate color for underline/undercurl Problem: Cannot set a separate color for underline/undercurl. Solution: Add the t_AU and t_8u termcap codes. (Timur Celik, closes https://github.com/vim/vim/issues/6011)
author Bram Moolenaar <Bram@vim.org>
date Sun, 31 May 2020 16:45:03 +0200
parents 8b79d6353530
children 3c6739c316cc
files runtime/doc/syntax.txt runtime/doc/term.txt src/globals.h src/highlight.c src/optiondefs.h src/proto/term.pro src/screen.c src/structs.h src/term.c src/term.h src/testdir/test_options.vim src/version.c
diffstat 12 files changed, 118 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -4901,6 +4901,10 @@ cterm={attr-list}					*highlight-cterm*
 
 ctermfg={color-nr}				*highlight-ctermfg* *E421*
 ctermbg={color-nr}				*highlight-ctermbg*
+ctermul={color-nr}				*highlight-ctermul*
+	These give the foreground (ctermfg), background (ctermbg) and
+	underline (ctermul) color to use in the terminal.
+
 	The {color-nr} argument is a color number.  Its range is zero to
 	(not including) the number given by the termcap entry "Co".
 	The actual color with this number depends on the type of terminal
@@ -4978,11 +4982,11 @@ ctermbg={color-nr}				*highlight-ctermbg
 	needs to reset the color when exiting.	This is done with the "op"
 	termcap entry |t_op|.  If this doesn't work correctly, try setting the
 	't_op' option in your .vimrc.
-							*E419* *E420*
-	When Vim knows the normal foreground and background colors, "fg" and
-	"bg" can be used as color names.  This only works after setting the
-	colors for the Normal group and for the MS-Windows console.  Example,
-	for reverse video: >
+							*E419* *E420* *E453*
+	When Vim knows the normal foreground, background and underline colors,
+	"fg", "bg" and "ul" can be used as color names.  This only works after
+	setting the colors for the Normal group and for the MS-Windows
+	console.  Example, for reverse video: >
 	    :highlight Visual ctermfg=bg ctermbg=fg
 <	Note that the colors are used that are valid at the moment this
 	command are given.  If the Normal group colors are changed later, the
--- a/runtime/doc/term.txt
+++ b/runtime/doc/term.txt
@@ -322,6 +322,7 @@ OUTPUT CODES						*terminal-output-codes
 	t_ZR	italics end					*t_ZR* *'t_ZR'*
 
 Added by Vim (there are no standard codes for these):
+	t_AU	set underline color (ANSI)			*t_AU* *'t_AU'*
 	t_Ce	undercurl end					*t_Ce* *'t_Ce'*
 	t_Cs	undercurl mode					*t_Cs* *'t_Cs'*
 	t_Te	strikethrough end				*t_Te* *'t_Te'*
@@ -350,6 +351,7 @@ Added by Vim (there are no standard code
 		|xterm-true-color|
 	t_8b	set background color (R, G, B)			*t_8b* *'t_8b'*
 		|xterm-true-color|
+	t_8u	set underline color (R, G, B)			*t_8u* *'t_8u'*
 	t_BE	enable bracketed paste mode			*t_BE* *'t_BE'*
 		|xterm-bracketed-paste|
 	t_BD	disable bracketed paste mode			*t_BD* *'t_BD'*
--- a/src/globals.h
+++ b/src/globals.h
@@ -485,9 +485,11 @@ EXTERN char_u	*use_gvimrc INIT(= NULL);	
 EXTERN int	cterm_normal_fg_color INIT(= 0);
 EXTERN int	cterm_normal_fg_bold INIT(= 0);
 EXTERN int	cterm_normal_bg_color INIT(= 0);
+EXTERN int	cterm_normal_ul_color INIT(= 0);
 #ifdef FEAT_TERMGUICOLORS
 EXTERN guicolor_T cterm_normal_fg_gui_color INIT(= INVALCOLOR);
 EXTERN guicolor_T cterm_normal_bg_gui_color INIT(= INVALCOLOR);
+EXTERN guicolor_T cterm_normal_ul_gui_color INIT(= INVALCOLOR);
 #endif
 #ifdef FEAT_TERMRESPONSE
 EXTERN int	is_mac_terminal INIT(= FALSE);  // recognized Terminal.app
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -50,14 +50,15 @@ typedef struct
     int		sg_cterm_bold;	// bold attr was set for light color
     int		sg_cterm_fg;	// terminal fg color number + 1
     int		sg_cterm_bg;	// terminal bg color number + 1
+    int		sg_cterm_ul;	// terminal ul color number + 1
     int		sg_cterm_attr;	// Screen attr for color term mode
 // for when using the GUI
 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
     guicolor_T	sg_gui_fg;	// GUI foreground color handle
     guicolor_T	sg_gui_bg;	// GUI background color handle
+    guicolor_T	sg_gui_sp;	// GUI special color handle
 #endif
 #ifdef FEAT_GUI
-    guicolor_T	sg_gui_sp;	// GUI special color handle
     GuiFont	sg_font;	// GUI font handle
 #ifdef FEAT_XFONTSET
     GuiFontset	sg_fontset;	// GUI fontset handle
@@ -1095,7 +1096,8 @@ do_highlight(
 	    }
 #endif
 	}
-	else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0)
+	else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0
+						|| STRCMP(key, "CTERMUL") == 0)
 	{
 	  if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM))
 	  {
@@ -1134,6 +1136,17 @@ do_highlight(
 		    break;
 		}
 	    }
+	    else if (STRICMP(arg, "ul") == 0)
+	    {
+		if (cterm_normal_ul_color > 0)
+		    color = cterm_normal_ul_color - 1;
+		else
+		{
+		    emsg(_("E453: UL color unknown"));
+		    error = TRUE;
+		    break;
+		}
+	    }
 	    else
 	    {
 		int bold = MAYBE;
@@ -1184,7 +1197,7 @@ do_highlight(
 		    }
 		}
 	    }
-	    else
+	    else if (key[5] == 'B')
 	    {
 		HL_TABLE()[idx].sg_cterm_bg = color + 1;
 		if (is_normal_group)
@@ -1221,6 +1234,23 @@ do_highlight(
 		    }
 		}
 	    }
+	    else // ctermul
+	    {
+		HL_TABLE()[idx].sg_cterm_ul = color + 1;
+		if (is_normal_group)
+		{
+		    cterm_normal_ul_color = color + 1;
+#ifdef FEAT_GUI
+		    // Don't do this if the GUI is used.
+		    if (!gui.in_use && !gui.starting)
+#endif
+		    {
+			must_redraw = CLEAR;
+			if (termcap_active && color >= 0)
+			    term_ul_color(color);
+		    }
+		}
+	    }
 	  }
 	}
 	else if (STRCMP(key, "GUIFG") == 0)
@@ -1335,9 +1365,10 @@ do_highlight(
 		if (!init)
 		    HL_TABLE()[idx].sg_set |= SG_GUI;
 
-# ifdef FEAT_GUI
+# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
+		// In GUI guisp colors are only used when recognized
 		i = color_name2handle(arg);
-		if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !gui.in_use)
+		if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT)
 		{
 		    HL_TABLE()[idx].sg_gui_sp = i;
 # endif
@@ -1350,7 +1381,7 @@ do_highlight(
 			    *namep = NULL;
 			did_change = TRUE;
 		    }
-# ifdef FEAT_GUI
+# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
 		}
 # endif
 	    }
@@ -1587,6 +1618,7 @@ restore_cterm_colors(void)
 # ifdef FEAT_TERMGUICOLORS
     cterm_normal_fg_gui_color = INVALCOLOR;
     cterm_normal_bg_gui_color = INVALCOLOR;
+    cterm_normal_ul_gui_color = INVALCOLOR;
 # endif
 #endif
 }
@@ -1638,9 +1670,9 @@ highlight_clear(int idx)
 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
     HL_TABLE()[idx].sg_gui_fg = INVALCOLOR;
     HL_TABLE()[idx].sg_gui_bg = INVALCOLOR;
+    HL_TABLE()[idx].sg_gui_sp = INVALCOLOR;
 #endif
 #ifdef FEAT_GUI
-    HL_TABLE()[idx].sg_gui_sp = INVALCOLOR;
     gui_mch_free_font(HL_TABLE()[idx].sg_font);
     HL_TABLE()[idx].sg_font = NOFONT;
 # ifdef FEAT_XFONTSET
@@ -2098,11 +2130,15 @@ get_attr_entry(garray_T *table, attrentr
 						  == taep->ae_u.cterm.fg_color
 			    && aep->ae_u.cterm.bg_color
 						  == taep->ae_u.cterm.bg_color
+			    && aep->ae_u.cterm.ul_color
+						  == taep->ae_u.cterm.ul_color
 #ifdef FEAT_TERMGUICOLORS
 			    && aep->ae_u.cterm.fg_rgb
 						    == taep->ae_u.cterm.fg_rgb
 			    && aep->ae_u.cterm.bg_rgb
 						    == taep->ae_u.cterm.bg_rgb
+			    && aep->ae_u.cterm.ul_rgb
+						    == taep->ae_u.cterm.ul_rgb
 #endif
 		       )))
 
@@ -2169,9 +2205,11 @@ get_attr_entry(garray_T *table, attrentr
     {
 	taep->ae_u.cterm.fg_color = aep->ae_u.cterm.fg_color;
 	taep->ae_u.cterm.bg_color = aep->ae_u.cterm.bg_color;
+	taep->ae_u.cterm.ul_color = aep->ae_u.cterm.ul_color;
 #ifdef FEAT_TERMGUICOLORS
 	taep->ae_u.cterm.fg_rgb = aep->ae_u.cterm.fg_rgb;
 	taep->ae_u.cterm.bg_rgb = aep->ae_u.cterm.bg_rgb;
+	taep->ae_u.cterm.ul_rgb = aep->ae_u.cterm.ul_rgb;
 #endif
     }
     ++table->ga_len;
@@ -2344,6 +2382,7 @@ hl_combine_attr(int char_attr, int prim_
 #ifdef FEAT_TERMGUICOLORS
 	    new_en.ae_u.cterm.bg_rgb = INVALCOLOR;
 	    new_en.ae_u.cterm.fg_rgb = INVALCOLOR;
+	    new_en.ae_u.cterm.ul_rgb = INVALCOLOR;
 #endif
 	    if (char_attr <= HL_ALL)
 		new_en.ae_attr = char_attr;
@@ -2362,6 +2401,8 @@ hl_combine_attr(int char_attr, int prim_
 		    new_en.ae_u.cterm.fg_color = spell_aep->ae_u.cterm.fg_color;
 		if (spell_aep->ae_u.cterm.bg_color > 0)
 		    new_en.ae_u.cterm.bg_color = spell_aep->ae_u.cterm.bg_color;
+		if (spell_aep->ae_u.cterm.ul_color > 0)
+		    new_en.ae_u.cterm.ul_color = spell_aep->ae_u.cterm.ul_color;
 #ifdef FEAT_TERMGUICOLORS
 		// If both fg and bg are not set fall back to cterm colors.
 		// Helps for SpellBad which uses undercurl in the GUI.
@@ -2380,6 +2421,8 @@ hl_combine_attr(int char_attr, int prim_
 		    if (spell_aep->ae_u.cterm.bg_rgb != INVALCOLOR)
 			new_en.ae_u.cterm.bg_rgb = spell_aep->ae_u.cterm.bg_rgb;
 		}
+		if (spell_aep->ae_u.cterm.ul_rgb != INVALCOLOR)
+		    new_en.ae_u.cterm.ul_rgb = spell_aep->ae_u.cterm.ul_rgb;
 #endif
 	    }
 	}
@@ -2497,6 +2540,8 @@ highlight_list_one(int id)
 				    sgp->sg_cterm_fg, NULL, "ctermfg");
     didh = highlight_list_arg(id, didh, LIST_INT,
 				    sgp->sg_cterm_bg, NULL, "ctermbg");
+    didh = highlight_list_arg(id, didh, LIST_INT,
+				    sgp->sg_cterm_ul, NULL, "ctermul");
 
 #if defined(FEAT_GUI) || defined(FEAT_EVAL)
     didh = highlight_list_arg(id, didh, LIST_ATTR,
@@ -2662,11 +2707,7 @@ highlight_color(
 	    if (fg)
 		color = HL_TABLE()[id - 1].sg_gui_fg;
 	    else if (sp)
-#  ifdef FEAT_GUI
 		color = HL_TABLE()[id - 1].sg_gui_sp;
-#  else
-		color = INVALCOLOR;
-#  endif
 	    else
 		color = HL_TABLE()[id - 1].sg_gui_bg;
 	    if (color == INVALCOLOR)
@@ -2847,10 +2888,11 @@ set_hl_attr(
      * For the color term mode: If there are other than "normal"
      * highlighting attributes, need to allocate an attr number.
      */
-    if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0
+    if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0 && sgp->sg_cterm_ul == 0
 # ifdef FEAT_TERMGUICOLORS
 	    && sgp->sg_gui_fg == INVALCOLOR
 	    && sgp->sg_gui_bg == INVALCOLOR
+	    && sgp->sg_gui_sp == INVALCOLOR
 # endif
 	    )
 	sgp->sg_cterm_attr = sgp->sg_cterm;
@@ -2859,6 +2901,7 @@ set_hl_attr(
 	at_en.ae_attr = sgp->sg_cterm;
 	at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
 	at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
+	at_en.ae_u.cterm.ul_color = sgp->sg_cterm_ul;
 # ifdef FEAT_TERMGUICOLORS
 #  ifdef MSWIN
 #   ifdef VIMDLL
@@ -2883,6 +2926,7 @@ set_hl_attr(
 #  endif
 	at_en.ae_u.cterm.fg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_fg);
 	at_en.ae_u.cterm.bg_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_bg);
+	at_en.ae_u.cterm.ul_rgb = GUI_MCH_GET_RGB2(sgp->sg_gui_sp);
 	if (at_en.ae_u.cterm.fg_rgb == INVALCOLOR
 		&& at_en.ae_u.cterm.bg_rgb == INVALCOLOR)
 	{
@@ -3067,9 +3111,7 @@ syn_add_group(char_u *name)
 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
     HL_TABLE()[highlight_ga.ga_len].sg_gui_bg = INVALCOLOR;
     HL_TABLE()[highlight_ga.ga_len].sg_gui_fg = INVALCOLOR;
-# ifdef FEAT_GUI
     HL_TABLE()[highlight_ga.ga_len].sg_gui_sp = INVALCOLOR;
-# endif
 #endif
     ++highlight_ga.ga_len;
 
@@ -3230,14 +3272,12 @@ gui_do_one_color(
 			    color_name2handle(HL_TABLE()[idx].sg_gui_bg_name);
 	didit = TRUE;
     }
-# ifdef FEAT_GUI
     if (HL_TABLE()[idx].sg_gui_sp_name != NULL)
     {
 	HL_TABLE()[idx].sg_gui_sp =
 			    color_name2handle(HL_TABLE()[idx].sg_gui_sp_name);
 	didit = TRUE;
     }
-# endif
     if (didit)	// need to get a new attr number
 	set_hl_attr(idx);
 }
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -2924,6 +2924,7 @@ static struct vimoption options[] =
 
     p_term("t_AB", T_CAB)
     p_term("t_AF", T_CAF)
+    p_term("t_AU", T_CAU)
     p_term("t_AL", T_CAL)
     p_term("t_al", T_AL)
     p_term("t_bc", T_BC)
@@ -3002,6 +3003,7 @@ static struct vimoption options[] =
     p_term("t_ZR", T_CZR)
     p_term("t_8f", T_8F)
     p_term("t_8b", T_8B)
+    p_term("t_8u", T_8U)
 
 // terminal key codes are not in here
 
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -26,9 +26,11 @@ int term_get_winpos(int *x, int *y, varn
 void term_set_winsize(int height, int width);
 void term_fg_color(int n);
 void term_bg_color(int n);
+void term_ul_color(int n);
 char_u *term_bg_default(void);
 void term_fg_rgb_color(guicolor_T rgb);
 void term_bg_rgb_color(guicolor_T rgb);
+void term_ul_rgb_color(guicolor_T rgb);
 void term_settitle(char_u *title);
 void term_push_title(int which);
 void term_pop_title(int which);
--- a/src/screen.c
+++ b/src/screen.c
@@ -1866,6 +1866,19 @@ screen_start_highlight(int attr)
 		    if (aep->ae_u.cterm.bg_color)
 			term_bg_color(aep->ae_u.cterm.bg_color - 1);
 		}
+#ifdef FEAT_TERMGUICOLORS
+		if (p_tgc && aep->ae_u.cterm.ul_rgb != CTERMCOLOR)
+		{
+		    if (aep->ae_u.cterm.ul_rgb != INVALCOLOR)
+			term_ul_rgb_color(aep->ae_u.cterm.ul_rgb);
+		}
+		else
+#endif
+		if (t_colors > 1)
+		{
+		    if (aep->ae_u.cterm.ul_color)
+			term_ul_color(aep->ae_u.cterm.ul_color - 1);
+		}
 
 		if (!IS_CTERM)
 		{
@@ -2021,6 +2034,8 @@ screen_stop_highlight(void)
 		    term_fg_rgb_color(cterm_normal_fg_gui_color);
 		if (cterm_normal_bg_gui_color != INVALCOLOR)
 		    term_bg_rgb_color(cterm_normal_bg_gui_color);
+		if (cterm_normal_ul_gui_color != INVALCOLOR)
+		    term_ul_rgb_color(cterm_normal_ul_gui_color);
 	    }
 	    else
 #endif
@@ -2032,6 +2047,8 @@ screen_stop_highlight(void)
 			term_fg_color(cterm_normal_fg_color - 1);
 		    if (cterm_normal_bg_color != 0)
 			term_bg_color(cterm_normal_bg_color - 1);
+		    if (cterm_normal_ul_color != 0)
+			term_ul_color(cterm_normal_ul_color - 1);
 		    if (cterm_normal_fg_bold)
 			out_str(T_MD);
 		}
--- a/src/structs.h
+++ b/src/structs.h
@@ -1068,9 +1068,11 @@ typedef struct attr_entry
 	    // These colors need to be > 8 bits to hold 256.
 	    short_u	    fg_color;	// foreground color number
 	    short_u	    bg_color;	// background color number
+	    short_u	    ul_color;	// underline color number
 # ifdef FEAT_TERMGUICOLORS
 	    guicolor_T	    fg_rgb;	// foreground color RGB
 	    guicolor_T	    bg_rgb;	// background color RGB
+	    guicolor_T	    ul_rgb;	// underline color RGB
 # endif
 	} cterm;
 # ifdef FEAT_GUI
--- a/src/term.c
+++ b/src/term.c
@@ -928,7 +928,9 @@ static struct builtin_term builtin_termc
     // These are printf strings, not terminal codes.
     {(int)KS_8F,	IF_EB("\033[38;2;%lu;%lu;%lum", ESC_STR "[38;2;%lu;%lu;%lum")},
     {(int)KS_8B,	IF_EB("\033[48;2;%lu;%lu;%lum", ESC_STR "[48;2;%lu;%lu;%lum")},
+    {(int)KS_8U,	IF_EB("\033[58;2;%lu;%lu;%lum", ESC_STR "[58;2;%lu;%lu;%lum")},
 #  endif
+    {(int)KS_CAU,	IF_EB("\033[58;5;%dm", ESC_STR "[58;5;%dm")},
     {(int)KS_CBE,	IF_EB("\033[?2004h", ESC_STR "[?2004h")},
     {(int)KS_CBD,	IF_EB("\033[?2004l", ESC_STR "[?2004l")},
     {(int)KS_CST,	IF_EB("\033[22;2t", ESC_STR "[22;2t")},
@@ -1187,6 +1189,7 @@ static struct builtin_term builtin_termc
     {(int)KS_CSB,	"[CSB%d]"},
     {(int)KS_CSF,	"[CSF%d]"},
 #  endif
+    {(int)KS_CAU,	"[CAU%d]"},
     {(int)KS_OP,	"[OP]"},
     {(int)KS_LE,	"[LE]"},
     {(int)KS_CL,	"[CL]"},
@@ -1617,7 +1620,8 @@ get_term_entries(int *height, int *width
 			{KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
 			{KS_CTI, "TI"}, {KS_CTE, "TE"},
 			{KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"},
-			{KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_LE, "le"},
+			{KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_CAU,"AU"},
+			{KS_LE, "le"},
 			{KS_ND, "nd"}, {KS_OP, "op"}, {KS_CRV, "RV"},
 			{KS_VS, "vs"}, {KS_CVS, "VS"},
 			{KS_CIS, "IS"}, {KS_CIE, "IE"},
@@ -1626,7 +1630,7 @@ get_term_entries(int *height, int *width
 			{KS_CWP, "WP"}, {KS_CWS, "WS"},
 			{KS_CSI, "SI"}, {KS_CEI, "EI"},
 			{KS_U7, "u7"}, {KS_RFG, "RF"}, {KS_RBG, "RB"},
-			{KS_8F, "8f"}, {KS_8B, "8b"},
+			{KS_8F, "8f"}, {KS_8B, "8b"}, {KS_8U, "8u"},
 			{KS_CBE, "BE"}, {KS_CBD, "BD"},
 			{KS_CPS, "PS"}, {KS_CPE, "PE"},
 			{KS_CST, "ST"}, {KS_CRT, "RT"},
@@ -2881,6 +2885,13 @@ term_bg_color(int n)
 	term_color(T_CSB, n);
 }
 
+    void
+term_ul_color(int n)
+{
+    if (*T_CAU)
+	term_color(T_CAU, n);
+}
+
 /*
  * Return "dark" or "light" depending on the kind of terminal.
  * This is just guessing!  Recognized are:
@@ -2952,6 +2963,12 @@ term_bg_rgb_color(guicolor_T rgb)
 {
     term_rgb_color(T_8B, rgb);
 }
+
+    void
+term_ul_rgb_color(guicolor_T rgb)
+{
+    term_rgb_color(T_8U, rgb);
+}
 #endif
 
 #if (defined(FEAT_TITLE) && (defined(UNIX) || defined(VMS) \
--- a/src/term.h
+++ b/src/term.h
@@ -78,6 +78,7 @@ enum SpecialKey
     KS_MB,	// blink mode
     KS_CAF,	// set foreground color (ANSI)
     KS_CAB,	// set background color (ANSI)
+    KS_CAU,	// set underline color (ANSI)
     KS_LE,	// cursor left (mostly backspace)
     KS_ND,	// cursor right
     KS_CIS,	// set icon text start
@@ -100,6 +101,7 @@ enum SpecialKey
     KS_U7,	// request cursor position
     KS_8F,	// set foreground color (RGB)
     KS_8B,	// set background color (RGB)
+    KS_8U,	// set underline color (RGB)
     KS_CBE,	// enable bracketed paste mode
     KS_CBD,	// disable bracketed paste mode
     KS_CPS,	// start of bracketed paste
@@ -179,6 +181,7 @@ extern char_u *(term_strings[]);    // c
 #define T_MB	(TERM_STR(KS_MB))	// blink mode
 #define T_CAF	(TERM_STR(KS_CAF))	// set foreground color (ANSI)
 #define T_CAB	(TERM_STR(KS_CAB))	// set background color (ANSI)
+#define T_CAU	(TERM_STR(KS_CAU))	// set underline color (ANSI)
 #define T_LE	(TERM_STR(KS_LE))	// cursor left
 #define T_ND	(TERM_STR(KS_ND))	// cursor right
 #define T_CIS	(TERM_STR(KS_CIS))	// set icon text start
@@ -200,6 +203,7 @@ extern char_u *(term_strings[]);    // c
 #define T_U7	(TERM_STR(KS_U7))	// request cursor position
 #define T_8F	(TERM_STR(KS_8F))	// set foreground color (RGB)
 #define T_8B	(TERM_STR(KS_8B))	// set background color (RGB)
+#define T_8U	(TERM_STR(KS_8U))	// set underline color (RGB)
 #define T_BE	(TERM_STR(KS_CBE))	// enable bracketed paste mode
 #define T_BD	(TERM_STR(KS_CBD))	// disable bracketed paste mode
 #define T_PS	(TERM_STR(KS_CPS))	// start of bracketed paste
--- a/src/testdir/test_options.vim
+++ b/src/testdir/test_options.vim
@@ -275,7 +275,7 @@ func Test_set_completion()
 
   " Expand terminal options.
   call feedkeys(":set t_A\<C-A>\<C-B>\"\<CR>", 'tx')
-  call assert_equal('"set t_AB t_AF t_AL', @:)
+  call assert_equal('"set t_AB t_AF t_AU t_AL', @:)
   call assert_fails('call feedkeys(":set <t_afoo>=\<C-A>\<CR>", "xt")', 'E474:')
 
   " Expand directories.
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    863,
+/**/
     862,
 /**/
     861,