diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 6715f655ba3bd..5abc4e95b85c2 100644 --- 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 diff --git a/runtime/doc/tags b/runtime/doc/tags index 88518600f615d..d7eb1dd7f89b0 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7947,6 +7947,7 @@ highlight-clear syntax.txt /*highlight-clear* 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* diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt index 546b0bf90d295..8154ec596e3d4 100644 --- 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 codes for these): 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'* diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 12e6f34741ad6..ceeb3dbd5cedc 100644 --- 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 "'[a-zA-Z\-* ]\+'" 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\(start\|stop\)="he=e-1 nextgroup=vimHiTer 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 diff --git a/src/highlight.c b/src/highlight.c index 318564c74b921..3381208fd1eb9 100644 --- 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 @@ -1034,6 +1035,39 @@ highlight_set_ctermul(int idx, int color, int is_normal_group) hl_set_ctermul_normal_group(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'. @@ -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, attrentry_T *aep) == 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, attrentry_T *aep) 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 bg) 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_attr) 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 resolve_link) 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); diff --git a/src/optiondefs.h b/src/optiondefs.h index 783b851f6c4a7..5fa8f37e2b187 100644 --- 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) diff --git a/src/proto/term.pro b/src/proto/term.pro index b83df860a173c..d82f9064435a5 100644 --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -33,6 +33,7 @@ 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); +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); diff --git a/src/screen.c b/src/screen.c index ac24a164648cd..ef43cfc8deeef 100644 --- 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, diff --git a/src/structs.h b/src/structs.h index 85f440d35d64c..da8c2e218ec98 100644 --- 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 diff --git a/src/term.c b/src/term.c index 734b759e30b48..2e2c6df21c720 100644 --- 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) { diff --git a/src/termdefs.h b/src/termdefs.h index 9f72dc1c5369c..f28fd199b1dfa 100644 --- 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[]); // current terminal strings #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 diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim index af605031327a4..b831878b40c5f 100644 --- 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=[27h;[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': ''}]) diff --git a/src/version.c b/src/version.c index b44385a0d5dba..8b19d814ccc3d 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 30, /**/ 29, /**/