changeset 34136:36843e079f64 v9.1.0030

patch 9.1.0030: Cannot use terminal alternate font Commit: https://github.com/vim/vim/commit/a606f3ac036e5f3dc313f620e6b4bc00812314f9 Author: PMunch <peterme@peterme.net> Date: Wed Nov 15 15:35:49 2023 +0100 patch 9.1.0030: Cannot use terminal alternate font Problem: Cannot use terminal alternate fonts (PMunch) Solution: Support terminal alternate fonts using CSI SGR 10-20 and t_CF code (PMunch) Add support for alternate font highlighting This adds support for alternate font highlighting using CSI SGR 10-20. Few terminals currently support this, but with added tool support this should improve over time. The change here is more or less taken from how colors are configured and applied, but there might be some parts I missed while implementing it. Changing fonts is done through the new `:hi ctermfont` attribute which takes a number, 0 is the normal font, and the numbers 1-9 select an "alternative" font. Which fonts are in use is up to the terminal. fixes: #13513 closes: #13537 Signed-off-by: PMunch <peterme@peterme.net> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Mon, 15 Jan 2024 22:30:03 +0100
parents 65a3e7bb12b7
children ce8b57bc90b8
files runtime/doc/syntax.txt runtime/doc/tags runtime/doc/term.txt runtime/syntax/vim.vim src/highlight.c src/optiondefs.h src/proto/term.pro src/screen.c src/structs.h src/term.c src/termdefs.h src/testdir/test_highlight.vim src/version.c
diffstat 13 files changed, 130 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -5304,6 +5304,14 @@ ctermul={color-nr}				*highlight-ctermul
 	command is given.  If the Normal group colors are changed later, the
 	"fg" and "bg" colors will not be adjusted.
 
+ctermfont={font-nr}				*highlight-ctermfont*
+	This gives the alternative font number to use in the terminal. The
+	available fonts depend on the terminal, and if the terminal is not set
+	up for alternative fonts this simply won't do anything. The range of
+	{font-nr} is 0-10 where 0 resets the font to the default font, 1-9
+	selects one of the 9 alternate fonts, and 10 selects the Fraktur font.
+	For more information see your terminal's handling of SGR parameters
+	10-20. |t_CF|
 
 3. highlight arguments for the GUI
 
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -7947,6 +7947,7 @@ highlight-clear	syntax.txt	/*highlight-c
 highlight-cterm	syntax.txt	/*highlight-cterm*
 highlight-ctermbg	syntax.txt	/*highlight-ctermbg*
 highlight-ctermfg	syntax.txt	/*highlight-ctermfg*
+highlight-ctermfont	syntax.txt	/*highlight-ctermfont*
 highlight-ctermul	syntax.txt	/*highlight-ctermul*
 highlight-default	syntax.txt	/*highlight-default*
 highlight-font	syntax.txt	/*highlight-font*
--- a/runtime/doc/term.txt
+++ b/runtime/doc/term.txt
@@ -1,4 +1,4 @@
-*term.txt*      For Vim version 9.1.  Last change: 2023 Dec 09
+*term.txt*      For Vim version 9.1.  Last change: 2024 Jan 15
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -448,6 +448,7 @@ Added by Vim (there are no standard code
 	t_AU	set underline color (ANSI)			*t_AU* *'t_AU'*
 	t_Ce	undercurl and underline end			*t_Ce* *'t_Ce'*
 	t_Cs	undercurl (curly underline) mode		*t_Cs* *'t_Cs'*
+	t_CF	set alternate font (using index 0 - 10)		*t_CF* *'t_CF'*
 	t_Us	double underline mode				*t_Us* *'t_Us'*
 	t_ds	dotted underline mode				*t_ds* *'t_ds'*
 	t_Ds	dashed underline mode				*t_Ds* *'t_Ds'*
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -9,6 +9,7 @@
 " 	2023 Dec 21 by Vim Project (improve ex command matching)
 " 	2023 Dec 30 by Vim Project (:syntax improvements)
 " 	2024 Jan 14 by Vim Project (TermResponseAll autocommand)
+" 	2024 Jan 15 by Vim Project (:hi ctermfont attribute)
 " Version:	9.0-25
 " URL:	http://www.drchip.org/astronaut/vim/index.html#SYNTAX_VIM
 " Automatically generated keyword lists: {{{1
@@ -663,7 +664,7 @@ syn match	vimHiGuiFontname	contained	"'[
 syn match	vimHiGuiRgb	contained	"#\x\{6}"
 
 " Highlighting: hi group key=arg ... {{{2
-syn cluster	vimHiCluster contains=vimGroup,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiCtermul,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation
+syn cluster	vimHiCluster contains=vimGroup,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiCtermul,vimHiCtermfont,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation
 syn region	vimHiKeyList	contained oneline start="\i\+" skip="\\\\\|\\|" end="$\||"	contains=@vimHiCluster
 if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_vimhikeyerror")
  syn match	vimHiKeyError	contained	"\i\+="he=e-1
@@ -673,6 +674,7 @@ syn match	vimHiStartStop	contained	"\c\(
 syn match	vimHiCTerm	contained	"\ccterm="he=e-1		nextgroup=vimHiAttribList
 syn match	vimHiCtermFgBg	contained	"\ccterm[fb]g="he=e-1	nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError
 syn match	vimHiCtermul	contained	"\cctermul="he=e-1	nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError
+syn match	vimHiCtermfont	contained	"\cctermfont="he=e-1	nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError
 syn match	vimHiGui	contained	"\cgui="he=e-1		nextgroup=vimHiAttribList
 syn match	vimHiGuiFont	contained	"\cfont="he=e-1		nextgroup=vimHiFontname
 syn match	vimHiGuiFgBg	contained	"\cgui\%([fb]g\|sp\)="he=e-1	nextgroup=vimHiGroup,vimHiGuiFontname,vimHiGuiRgb,vimFgBgAttrib
@@ -951,6 +953,7 @@ if !exists("skip_vim_syntax_inits")
  hi def link vimFgBgAttrib	vimHiAttrib
  hi def link vimFuncEcho	vimCommand
  hi def link vimHiCtermul	vimHiTerm
+ hi def link vimHiCtermfont	vimHiTerm
  hi def link vimFold	Folded
  hi def link vimFor	vimCommand
  hi def link vimFTCmd	vimCommand
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -59,6 +59,7 @@ typedef struct
     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
+    int		sg_cterm_font;	// terminal alternative font (0 for normal)
 // for when using the GUI
 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS)
     guicolor_T	sg_gui_fg;	// GUI foreground color handle
@@ -1035,6 +1036,39 @@ highlight_set_ctermul(int idx, int color
 }
 
 /*
+ * Set the cterm font for the highlight group at 'idx'.
+ * 'arg' is the color name or the numeric value as a string.
+ * 'init' is set to TRUE when initializing highlighting.
+ * Called for the ":highlight" command and the "hlset()" function.
+ *
+ * Returns TRUE if the font is set.
+ */
+    static int
+highlight_set_cterm_font(
+	int	idx,
+	char_u	*arg,
+	int	init)
+{
+    int		font;
+
+    if (init && (HL_TABLE()[idx].sg_set & SG_CTERM))
+	return FALSE;
+
+    if (!init)
+	HL_TABLE()[idx].sg_set |= SG_CTERM;
+
+    if (VIM_ISDIGIT(*arg))
+	font = atoi((char *)arg);
+    else if (STRICMP(arg, "NONE") == 0)
+	font = -1;
+    else
+	return FALSE;
+
+    HL_TABLE()[idx].sg_cterm_font = font + 1;
+    return TRUE;
+}
+
+/*
  * Set the cterm fg/bg/ul color for the highlight group at 'idx'.
  * 'key' is one of 'CTERMFG' or 'CTERMBG' or 'CTERMUL'.
  * 'keystart' is the color name/value.
@@ -1679,6 +1713,14 @@ do_highlight(
 		    break;
 		}
 	    }
+	    else if (STRCMP(key, "CTERMFONT") == 0)
+	    {
+		if (!highlight_set_cterm_font(idx, arg, init))
+		{
+		    error = TRUE;
+		    break;
+		}
+	    }
 	    else if (STRCMP(key, "GUIFG") == 0)
 	    {
 #if defined(FEAT_GUI) || defined(FEAT_EVAL)
@@ -1865,6 +1907,7 @@ hl_has_settings(int idx, int check_link)
 	    || HL_TABLE()[idx].sg_cterm_attr != 0
 	    || HL_TABLE()[idx].sg_cterm_fg != 0
 	    || HL_TABLE()[idx].sg_cterm_bg != 0
+	    || HL_TABLE()[idx].sg_cterm_font != 0
 #ifdef FEAT_GUI
 	    || HL_TABLE()[idx].sg_gui_attr != 0
 	    || HL_TABLE()[idx].sg_gui_fg_name != NULL
@@ -1892,6 +1935,7 @@ highlight_clear(int idx)
     HL_TABLE()[idx].sg_cterm_fg = 0;
     HL_TABLE()[idx].sg_cterm_bg = 0;
     HL_TABLE()[idx].sg_cterm_attr = 0;
+    HL_TABLE()[idx].sg_cterm_font = 0;
 #if defined(FEAT_GUI) || defined(FEAT_EVAL)
     HL_TABLE()[idx].sg_gui = 0;
     VIM_CLEAR(HL_TABLE()[idx].sg_gui_fg_name);
@@ -2539,6 +2583,8 @@ get_attr_entry(garray_T *table, attrentr
 						  == taep->ae_u.cterm.bg_color
 			    && aep->ae_u.cterm.ul_color
 						  == taep->ae_u.cterm.ul_color
+			    && aep->ae_u.cterm.font
+						  == taep->ae_u.cterm.font
 #ifdef FEAT_TERMGUICOLORS
 			    && aep->ae_u.cterm.fg_rgb
 						    == taep->ae_u.cterm.fg_rgb
@@ -2609,6 +2655,7 @@ 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;
+	taep->ae_u.cterm.font = aep->ae_u.cterm.font;
 #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;
@@ -2639,6 +2686,7 @@ get_cterm_attr_idx(int attr, int fg, int
     at_en.ae_u.cterm.fg_color = fg;
     at_en.ae_u.cterm.bg_color = bg;
     at_en.ae_u.cterm.ul_color = 0;
+    at_en.ae_u.cterm.font = 0;
     return get_attr_entry(&cterm_attr_table, &at_en);
 }
 #endif
@@ -2809,6 +2857,8 @@ hl_combine_attr(int char_attr, int prim_
 		    new_en.ae_u.cterm.bg_color = prim_aep->ae_u.cterm.bg_color;
 		if (prim_aep->ae_u.cterm.ul_color > 0)
 		    new_en.ae_u.cterm.ul_color = prim_aep->ae_u.cterm.ul_color;
+		if (prim_aep->ae_u.cterm.font > 0)
+		    new_en.ae_u.cterm.font = prim_aep->ae_u.cterm.font;
 #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.
@@ -2948,6 +2998,8 @@ highlight_list_one(int id)
 				    sgp->sg_cterm_bg, NULL, "ctermbg");
     didh = highlight_list_arg(id, didh, LIST_INT,
 				    sgp->sg_cterm_ul, NULL, "ctermul");
+    didh = highlight_list_arg(id, didh, LIST_INT,
+				    sgp->sg_cterm_font, NULL, "ctermfont");
 
 #if defined(FEAT_GUI) || defined(FEAT_EVAL)
     didh = highlight_list_arg(id, didh, LIST_ATTR,
@@ -3138,7 +3190,7 @@ highlight_color(
 	    return (HL_TABLE()[id - 1].sg_gui_sp_name);
 	return (HL_TABLE()[id - 1].sg_gui_bg_name);
     }
-    if (font || sp)
+    if (sp)
 	return NULL;
     if (modec == 'c')
     {
@@ -3146,6 +3198,8 @@ highlight_color(
 	    n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
 	else if (ul)
 	    n = HL_TABLE()[id - 1].sg_cterm_ul - 1;
+	else if (font)
+	    n = HL_TABLE()[id - 1].sg_cterm_font - 1;
 	else
 	    n = HL_TABLE()[id - 1].sg_cterm_bg - 1;
 	if (n < 0)
@@ -3296,7 +3350,8 @@ 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 && sgp->sg_cterm_ul == 0
+    if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0 &&
+	sgp->sg_cterm_ul == 0 && sgp->sg_cterm_font == 0
 # ifdef FEAT_TERMGUICOLORS
 	    && sgp->sg_gui_fg == INVALCOLOR
 	    && sgp->sg_gui_bg == INVALCOLOR
@@ -3310,6 +3365,7 @@ set_hl_attr(
 	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;
+	at_en.ae_u.cterm.font = sgp->sg_cterm_font;
 # ifdef FEAT_TERMGUICOLORS
 	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);
@@ -3717,6 +3773,8 @@ combine_stl_hlt(
 	hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg;
     if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg)
 	hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg;
+    if (hlt[id - 1].sg_cterm_font != hlt[id_S - 1].sg_cterm_font)
+	hlt[hlcnt + i].sg_cterm_font = hlt[id - 1].sg_cterm_font;
 #  if defined(FEAT_GUI) || defined(FEAT_EVAL)
     hlt[hlcnt + i].sg_gui ^=
 	hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
@@ -4180,6 +4238,10 @@ highlight_get_info(int hl_idx, int resol
 	if (dict_add_string(dict, "ctermul",
 			highlight_color(hlgid, (char_u *)"ul", 'c')) == FAIL)
 	    goto error;
+    if (sgp->sg_cterm_font != 0)
+	if (dict_add_string(dict, "ctermfont",
+			highlight_color(hlgid, (char_u *)"font", 'c')) == FAIL)
+	    goto error;
     if (sgp->sg_gui != 0)
     {
 	attr_dict = highlight_get_attr_dict(sgp->sg_gui);
@@ -4408,6 +4470,7 @@ hlg_add_or_update(dict_T *dict)
     char_u	*ctermfg;
     char_u	*ctermbg;
     char_u	*ctermul;
+    char_u	*ctermfont;
     char_u	*guifg;
     char_u	*guibg;
     char_u	*guisp;
@@ -4492,6 +4555,10 @@ hlg_add_or_update(dict_T *dict)
     if (error)
 	return FALSE;
 
+    ctermfont = hldict_get_string(dict, (char_u *)"ctermfont", &error);
+    if (error)
+	return FALSE;
+
     if (!hldict_attr_to_str(dict, (char_u *)"gui", gui_attr, sizeof(gui_attr)))
 	return FALSE;
 
@@ -4516,7 +4583,7 @@ hlg_add_or_update(dict_T *dict)
     // If none of the attributes are specified, then do nothing.
     if (term_attr[0] == NUL && start == NULL && stop == NULL
 	    && cterm_attr[0] == NUL && ctermfg == NULL && ctermbg == NULL
-	    && ctermul == NULL && gui_attr[0] == NUL
+	    && ctermul == NULL && ctermfont == NULL && gui_attr[0] == NUL
 # ifdef FEAT_GUI
 	    && font == NULL
 # endif
@@ -4536,6 +4603,7 @@ hlg_add_or_update(dict_T *dict)
     p = add_attr_and_value(p, (char_u *)" ctermfg=", 9, ctermfg);
     p = add_attr_and_value(p, (char_u *)" ctermbg=", 9, ctermbg);
     p = add_attr_and_value(p, (char_u *)" ctermul=", 9, ctermul);
+    p = add_attr_and_value(p, (char_u *)" ctermfont=", 9, ctermfont);
     p = add_attr_and_value(p, (char_u *)" gui=", 5, gui_attr);
 # ifdef FEAT_GUI
     p = add_attr_and_value(p, (char_u *)" font=", 6, font);
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -2931,6 +2931,7 @@ static struct vimoption options[] =
     p_term("t_cd", T_CD)
     p_term("t_ce", T_CE)
     p_term("t_Ce", T_UCE)
+    p_term("t_CF", T_CFO)
     p_term("t_cl", T_CL)
     p_term("t_cm", T_CM)
     p_term("t_Co", T_CCO)
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -33,6 +33,7 @@ void term_set_winsize(int height, int wi
 void term_fg_color(int n);
 void term_bg_color(int n);
 void term_ul_color(int n);
+void term_font(int n);
 char_u *term_bg_default(void);
 void term_fg_rgb_color(guicolor_T rgb);
 void term_bg_rgb_color(guicolor_T rgb);
--- a/src/screen.c
+++ b/src/screen.c
@@ -1667,6 +1667,8 @@ screen_start_highlight(int attr)
      */
     if (aep != NULL)
     {
+	if (aep->ae_u.cterm.font > 0 && aep->ae_u.cterm.font < 12)
+		term_font(aep->ae_u.cterm.font);
 #ifdef FEAT_TERMGUICOLORS
 	// When 'termguicolors' is set but fg or bg is unset,
 	// fall back to the cterm colors.   This helps for SpellBad,
--- a/src/structs.h
+++ b/src/structs.h
@@ -1186,6 +1186,7 @@ typedef struct attr_entry
 	    short_u	    fg_color;	// foreground color number
 	    short_u	    bg_color;	// background color number
 	    short_u	    ul_color;	// underline color number
+	    short_u	    font;	// font number
 # ifdef FEAT_TERMGUICOLORS
 	    guicolor_T	    fg_rgb;	// foreground color RGB
 	    guicolor_T	    bg_rgb;	// background color RGB
--- a/src/term.c
+++ b/src/term.c
@@ -625,7 +625,7 @@ static tcap_entry_T builtin_kitty[] = {
 
 #ifdef FEAT_TERMGUICOLORS
 /*
- * Additions for using the RGB colors
+ * Additions for using the RGB colors and terminal font
  */
 static tcap_entry_T builtin_rgb[] = {
     // These are printf strings, not terminal codes.
@@ -637,6 +637,12 @@ static tcap_entry_T builtin_rgb[] = {
 };
 #endif
 
+static tcap_entry_T special_term[] = {
+    // These are printf strings, not terminal codes.
+    {(int)KS_CF,	"\033[%dm"},
+    {(int)KS_NAME,	NULL}  // end marker
+};
+
 /*
  * iris-ansi for Silicon Graphics machines.
  */
@@ -1235,6 +1241,7 @@ static tcap_entry_T builtin_debug[] = {
     {(int)KS_U7,	"[U7]"},
     {(int)KS_RFG,	"[RFG]"},
     {(int)KS_RBG,	"[RBG]"},
+    {(int)KS_CF,	"[CF%d]"},
     {K_UP,		"[KU]"},
     {K_DOWN,		"[KD]"},
     {K_LEFT,		"[KL]"},
@@ -1754,6 +1761,7 @@ get_term_entries(int *height, int *width
 			{KS_CBE, "BE"}, {KS_CBD, "BD"},
 			{KS_CST, "ST"}, {KS_CRT, "RT"},
 			{KS_SSI, "Si"}, {KS_SRI, "Ri"},
+			{KS_CF, "CF"},
 			{(enum SpecialKey)0, NULL}
 		    };
     int		    i;
@@ -2113,6 +2121,8 @@ set_termname(char_u *term)
 		&& term_strings_not_set(KS_8U))
 	    apply_builtin_tcap(term, builtin_rgb, TRUE);
 #endif
+	if (term_strings_not_set(KS_CF))
+	    apply_builtin_tcap(term, special_term, TRUE);
     }
 
 /*
@@ -3116,6 +3126,17 @@ term_set_winsize(int height, int width)
 }
 #endif
 
+    void
+term_font(int n)
+{
+    if (*T_CFO)
+    {
+	char buf[20];
+	sprintf(buf, (char *)T_CFO, 9 + n);
+	OUT_STR(buf);
+    }
+}
+
     static void
 term_color(char_u *s, int n)
 {
--- a/src/termdefs.h
+++ b/src/termdefs.h
@@ -114,10 +114,11 @@ enum SpecialKey
     KS_SSI,	// save icon text
     KS_SRI,	// restore icon text
     KS_FD,	// disable focus event tracking
-    KS_FE	// enable focus event tracking
+    KS_FE,	// enable focus event tracking
+    KS_CF	// set terminal alternate font
 };
 
-#define KS_LAST	    KS_FE
+#define KS_LAST	    KS_CF
 
 /*
  * the terminal capabilities are stored in this array
@@ -191,6 +192,7 @@ extern char_u *(term_strings[]);    // c
 #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_CFO	(TERM_STR(KS_CF))	// set alternate font
 #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
--- a/src/testdir/test_highlight.vim
+++ b/src/testdir/test_highlight.vim
@@ -888,6 +888,16 @@ func Test_highlight_ctermul()
   highlight Normal ctermul=NONE
 endfunc
 
+" Test for 'ctermfont' in a highlight group
+func Test_highlight_ctermfont()
+  CheckNotGui
+  call assert_notmatch('ctermfont=', HighlightArgs('Normal'))
+  highlight Normal ctermfont=3
+  call assert_match('ctermfont=3', HighlightArgs('Normal'))
+  call assert_equal('3', synIDattr(synIDtrans(hlID('Normal')), 'font'))
+  highlight Normal ctermfont=NONE
+endfunc
+
 " Test for specifying 'start' and 'stop' in a highlight group
 func Test_highlight_start_stop()
   hi HlGrp1 start=<Esc>[27h;<Esc>[<Space>r;
@@ -1314,6 +1324,7 @@ func Test_hlset()
   call hlset([{'name': 'hlg11', 'ctermfg': ''}])
   call hlset([{'name': 'hlg11', 'ctermbg': ''}])
   call hlset([{'name': 'hlg11', 'ctermul': ''}])
+  call hlset([{'name': 'hlg11', 'ctermfont': ''}])
   call hlset([{'name': 'hlg11', 'font': ''}])
   call hlset([{'name': 'hlg11', 'gui': {}}])
   call hlset([{'name': 'hlg11', 'guifg': ''}])
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    30,
+/**/
     29,
 /**/
     28,