diff options
author | Yegappan Lakshmanan <yegappan@yahoo.com> | 2021-10-18 22:13:57 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-10-18 22:13:57 +0100 |
commit | ad6b90c33cc239794a6694ef53e8baeee2ed97bd (patch) | |
tree | 1267387b34eeafbd30a9687bfdb4ba85e6965dff /src/highlight.c | |
parent | 9b0b844d252ea84b3607f39603b4afa8cb002418 (diff) |
patch 8.2.3536: the do_highlight() function is way too longv8.2.3536
Problem: The do_highlight() function is way too long.
Solution: Split it into several functions. (Yegappan Lakshmanan,
closes #9011)
Diffstat (limited to 'src/highlight.c')
-rw-r--r-- | src/highlight.c | 1681 |
1 files changed, 912 insertions, 769 deletions
diff --git a/src/highlight.c b/src/highlight.c index a08d1f1d23..44a7c6623d 100644 --- a/src/highlight.c +++ b/src/highlight.c @@ -377,10 +377,8 @@ init_highlight( #ifdef FEAT_EVAL char_u *p; - /* - * Try finding the color scheme file. Used when a color file was loaded - * and 'background' or 't_Co' is changed. - */ + // Try finding the color scheme file. Used when a color file was loaded + // and 'background' or 't_Co' is changed. p = get_var_value((char_u *)"g:colors_name"); if (p != NULL) { @@ -400,9 +398,7 @@ init_highlight( #endif - /* - * Didn't use a color file, use the compiled-in colors. - */ + // Didn't use a color file, use the compiled-in colors. if (both) { had_both = TRUE; @@ -441,9 +437,7 @@ init_highlight( } #ifdef FEAT_SYN_HL - /* - * If syntax highlighting is enabled load the highlighting for it. - */ + // If syntax highlighting is enabled load the highlighting for it. if (get_var_value((char_u *)"g:syntax_on") != NULL) { static int recursive = 0; @@ -581,11 +575,9 @@ lookup_color(int idx, int foreground, int *boldp) else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) { - /* - * Guess: if the termcap entry ends in 'm', it is - * probably an xterm-like terminal. Use the changed - * order for colors. - */ + // Guess: if the termcap entry ends in 'm', it is + // probably an xterm-like terminal. Use the changed + // order for colors. if (*T_CAF != NUL) p = T_CAF; else @@ -611,6 +603,758 @@ lookup_color(int idx, int foreground, int *boldp) } /* + * Link highlight group 'from_hg' to 'to_hg'. + * 'dodefault' is set to TRUE for ":highlight default link". + * 'forceit' is set to TRUE for ":higlight! link" + * 'init' is set to TRUE when initializing all the highlight groups. + */ + static void +highlight_group_link( + char_u *from_hg, + int from_len, + char_u *to_hg, + int to_len, + int dodefault, + int forceit, + int init) +{ + int from_id; + int to_id; + hl_group_T *hlgroup = NULL; + + from_id = syn_check_group(from_hg, from_len); + if (STRNCMP(to_hg, "NONE", 4) == 0) + to_id = 0; + else + to_id = syn_check_group(to_hg, to_len); + + if (from_id > 0) + { + hlgroup = &HL_TABLE()[from_id - 1]; + if (dodefault && (forceit || hlgroup->sg_deflink == 0)) + { + hlgroup->sg_deflink = to_id; +#ifdef FEAT_EVAL + hlgroup->sg_deflink_sctx = current_sctx; + hlgroup->sg_deflink_sctx.sc_lnum += SOURCING_LNUM; +#endif + } + } + + if (from_id > 0 && (!init || hlgroup->sg_set == 0)) + { + // Don't allow a link when there already is some highlighting + // for the group, unless '!' is used + if (to_id > 0 && !forceit && !init + && hl_has_settings(from_id - 1, dodefault)) + { + if (SOURCING_NAME == NULL && !dodefault) + emsg(_("E414: group has settings, highlight link ignored")); + } + else if (hlgroup->sg_link != to_id +#ifdef FEAT_EVAL + || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid +#endif + || hlgroup->sg_cleared) + { + if (!init) + hlgroup->sg_set |= SG_LINK; + hlgroup->sg_link = to_id; +#ifdef FEAT_EVAL + hlgroup->sg_script_ctx = current_sctx; + hlgroup->sg_script_ctx.sc_lnum += SOURCING_LNUM; +#endif + hlgroup->sg_cleared = FALSE; + redraw_all_later(SOME_VALID); + + // Only call highlight_changed() once after multiple changes. + need_highlight_changed = TRUE; + } + } + +} + +/* + * Reset all highlighting to the defaults. Removes all highlighting for the + * groups added by the user. + */ + static void +highlight_reset_all(void) +{ + int idx; + +#ifdef FEAT_GUI + // First, we do not destroy the old values, but allocate the new + // ones and update the display. THEN we destroy the old values. + // If we destroy the old values first, then the old values + // (such as GuiFont's or GuiFontset's) will still be displayed but + // invalid because they were free'd. + if (gui.in_use) + { +# ifdef FEAT_BEVAL_TIP + gui_init_tooltip_font(); +# endif +# if defined(FEAT_MENU) && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF)) + gui_init_menu_font(); +# endif + } +# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_X11) + gui_mch_def_colors(); +# endif +# ifdef FEAT_GUI_X11 +# ifdef FEAT_MENU + + // This only needs to be done when there is no Menu highlight + // group defined by default, which IS currently the case. + gui_mch_new_menu_colors(); +# endif + if (gui.in_use) + { + gui_new_scrollbar_colors(); +# ifdef FEAT_BEVAL_GUI + gui_mch_new_tooltip_colors(); +# endif +# ifdef FEAT_MENU + gui_mch_new_menu_font(); +# endif + } +# endif + + // Ok, we're done allocating the new default graphics items. + // The screen should already be refreshed at this point. + // It is now Ok to clear out the old data. +#endif +#ifdef FEAT_EVAL + do_unlet((char_u *)"g:colors_name", TRUE); +#endif + restore_cterm_colors(); + + // Clear all default highlight groups and load the defaults. + for (idx = 0; idx < highlight_ga.ga_len; ++idx) + highlight_clear(idx); + init_highlight(TRUE, TRUE); +#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) + if (USE_24BIT) + highlight_gui_started(); + else +#endif + highlight_changed(); + redraw_later_clear(); +} + +/* + * Set the 'term' or 'cterm' or 'gui' attributes for the highlight group at + * index 'idx'. + * 'key' is one of 'TERM' or 'CTERM' or 'GUI' + * 'arg' is the list of attribute names separated by comma. + * 'init' is set to TRUE when initializing all the highlight groups. + * Returns TRUE if the attributes are set. + */ + static int +highlight_set_termgui_attr(int idx, char_u *key, char_u *arg, int init) +{ + int attr; + int off; + long i; + int len; + + attr = 0; + off = 0; + while (arg[off] != NUL) + { + for (i = ARRAY_LENGTH(hl_attr_table); --i >= 0; ) + { + len = (int)STRLEN(hl_name_table[i]); + if (STRNICMP(arg + off, hl_name_table[i], len) == 0) + { + attr |= hl_attr_table[i]; + off += len; + break; + } + } + if (i < 0) + { + semsg(_("E418: Illegal value: %s"), arg); + return FALSE; + } + if (arg[off] == ',') // another one follows + ++off; + } + if (*key == 'T') + { + if (!init || !(HL_TABLE()[idx].sg_set & SG_TERM)) + { + if (!init) + HL_TABLE()[idx].sg_set |= SG_TERM; + HL_TABLE()[idx].sg_term = attr; + } + } + else if (*key == 'C') + { + if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) + { + if (!init) + HL_TABLE()[idx].sg_set |= SG_CTERM; + HL_TABLE()[idx].sg_cterm = attr; + HL_TABLE()[idx].sg_cterm_bold = FALSE; + } + } +#if defined(FEAT_GUI) || defined(FEAT_EVAL) + else + { + if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) + { + if (!init) + HL_TABLE()[idx].sg_set |= SG_GUI; + HL_TABLE()[idx].sg_gui = attr; + } + } +#endif + + return TRUE; +} + +#ifdef FEAT_GUI +/* + * Set the font for the highlight group at 'idx'. + * 'arg' is the font name. + * Returns TRUE if the font is changed. + */ + static int +highlight_set_font( + int idx, + char_u *arg, + int is_normal_group, + int is_menu_group, + int is_tooltip_group) +{ + int did_change = FALSE; + + // in non-GUI fonts are simply ignored + if (HL_TABLE()[idx].sg_font_name != NULL + && STRCMP(HL_TABLE()[idx].sg_font_name, arg) == 0) + { + // Font name didn't change, ignore. + } + else if (!gui.shell_created) + { + // GUI not started yet, always accept the name. + vim_free(HL_TABLE()[idx].sg_font_name); + HL_TABLE()[idx].sg_font_name = vim_strsave(arg); + did_change = TRUE; + } + else + { + GuiFont temp_sg_font = HL_TABLE()[idx].sg_font; +# ifdef FEAT_XFONTSET + GuiFontset temp_sg_fontset = HL_TABLE()[idx].sg_fontset; +# endif + // First, save the current font/fontset. + // Then try to allocate the font/fontset. + // If the allocation fails, HL_TABLE()[idx].sg_font OR + // sg_fontset will be set to NOFONT or NOFONTSET respectively. + + HL_TABLE()[idx].sg_font = NOFONT; +# ifdef FEAT_XFONTSET + HL_TABLE()[idx].sg_fontset = NOFONTSET; +# endif + hl_do_font(idx, arg, is_normal_group, is_menu_group, + is_tooltip_group, FALSE); + +# ifdef FEAT_XFONTSET + if (HL_TABLE()[idx].sg_fontset != NOFONTSET) + { + // New fontset was accepted. Free the old one, if there + // was one. + gui_mch_free_fontset(temp_sg_fontset); + vim_free(HL_TABLE()[idx].sg_font_name); + HL_TABLE()[idx].sg_font_name = vim_strsave(arg); + did_change = TRUE; + } + else + HL_TABLE()[idx].sg_fontset = temp_sg_fontset; +# endif + if (HL_TABLE()[idx].sg_font != NOFONT) + { + // New font was accepted. Free the old one, if there was + // one. + gui_mch_free_font(temp_sg_font); + vim_free(HL_TABLE()[idx].sg_font_name); + HL_TABLE()[idx].sg_font_name = vim_strsave(arg); + did_change = TRUE; + } + else + HL_TABLE()[idx].sg_font = temp_sg_font; + } + + return did_change; +} +#endif + +/* + * Set the cterm foreground color for the highlight group at 'idx' to 'color'. + * Returns TRUE if the foreground color is set. + */ + static void +highlight_set_ctermfg(int idx, int color, int is_normal_group) +{ + HL_TABLE()[idx].sg_cterm_fg = color + 1; + if (is_normal_group) + { + cterm_normal_fg_color = color + 1; + cterm_normal_fg_bold = (HL_TABLE()[idx].sg_cterm & HL_BOLD); +#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_fg_color(color); + } + } +} + +/* + * Set the cterm background color for the highlight group at 'idx' to 'color'. + * Returns TRUE if the background color is set. + */ + static void +highlight_set_ctermbg(int idx, int color, int is_normal_group) +{ + HL_TABLE()[idx].sg_cterm_bg = color + 1; + if (is_normal_group) + { + cterm_normal_bg_color = color + 1; +#ifdef FEAT_GUI + // Don't mess with 'background' if the GUI is used. + if (!gui.in_use && !gui.starting) +#endif + { + must_redraw = CLEAR; + if (color >= 0) + { + int dark = -1; + + if (termcap_active) + term_bg_color(color); + if (t_colors < 16) + dark = (color == 0 || color == 4); + // Limit the heuristic to the standard 16 colors + else if (color < 16) + dark = (color < 7 || color == 8); + // Set the 'background' option if the value is + // wrong. + if (dark != -1 + && dark != (*p_bg == 'd') + && !option_was_set((char_u *)"bg")) + { + set_option_value((char_u *)"bg", 0L, + (char_u *)(dark ? "dark" : "light"), 0); + reset_option_was_set((char_u *)"bg"); + } + } + } + } +} + +/* + * Set the cterm underline color for the highlight group at 'idx' to 'color'. + * Returns TRUE if the underline color is set. + */ + static void +highlight_set_ctermul(int idx, int color, int is_normal_group) +{ + 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); + } + } +} + +/* + * 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. + * 'arg' is the color name or the numeric value as a string. + * 'is_normal_group' is set if the highlight group is 'NORMAL' + * 'init' is set to TRUE when initializing highlighting. + * Called for the ":highlight" command and the "hlset()" function. + * + * Returns TRUE if the color is set. + */ + static int +highlight_set_cterm_color( + int idx, + char_u *key, + char_u *key_start, + char_u *arg, + int is_normal_group, + int init) +{ + int color; + long i; + int off; + + if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) + { + if (!init) + HL_TABLE()[idx].sg_set |= SG_CTERM; + + // When setting the foreground color, and previously the "bold" + // flag was set for a light color, reset it now + if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold) + { + HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; + HL_TABLE()[idx].sg_cterm_bold = FALSE; + } + + if (VIM_ISDIGIT(*arg)) + color = atoi((char *)arg); + else if (STRICMP(arg, "fg") == 0) + { + if (cterm_normal_fg_color) + color = cterm_normal_fg_color - 1; + else + { + emsg(_("E419: FG color unknown")); + return FALSE; + } + } + else if (STRICMP(arg, "bg") == 0) + { + if (cterm_normal_bg_color > 0) + color = cterm_normal_bg_color - 1; + else + { + emsg(_("E420: BG color unknown")); + return FALSE; + } + } + else if (STRICMP(arg, "ul") == 0) + { + if (cterm_normal_ul_color > 0) + color = cterm_normal_ul_color - 1; + else + { + emsg(_("E453: UL color unknown")); + return FALSE; + } + } + else + { + int bold = MAYBE; + + // reduce calls to STRICMP a bit, it can be slow + off = TOUPPER_ASC(*arg); + for (i = ARRAY_LENGTH(color_names); --i >= 0; ) + if (off == color_names[i][0] + && STRICMP(arg + 1, color_names[i] + 1) == 0) + break; + if (i < 0) + { + semsg(_("E421: Color name or number not recognized: %s"), + key_start); + return FALSE; + } + + color = lookup_color(i, key[5] == 'F', &bold); + + // set/reset bold attribute to get light foreground + // colors (on some terminals, e.g. "linux") + if (bold == TRUE) + { + HL_TABLE()[idx].sg_cterm |= HL_BOLD; + HL_TABLE()[idx].sg_cterm_bold = TRUE; + } + else if (bold == FALSE) + HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; + } + + // Add one to the argument, to avoid zero. Zero is used for + // "NONE", then "color" is -1. + if (key[5] == 'F') + highlight_set_ctermfg(idx, color, is_normal_group); + else if (key[5] == 'B') + highlight_set_ctermbg(idx, color, is_normal_group); + else // ctermul + highlight_set_ctermul(idx, color, is_normal_group); + } + + return TRUE; +} + +#if defined(FEAT_GUI) || defined(FEAT_EVAL) +/* + * Set the GUI foreground color for the highlight group at 'idx'. + * Returns TRUE if the color is set. + */ + static int +highlight_set_guifg( + int idx, + char_u *arg, + int is_menu_group UNUSED, + int is_scrollbar_group UNUSED, + int is_tooltip_group UNUSED, + int *do_colors UNUSED, + int init) +{ + long i; + char_u **namep; + int did_change = FALSE; + + namep = &HL_TABLE()[idx].sg_gui_fg_name; + if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) + { + if (!init) + HL_TABLE()[idx].sg_set |= SG_GUI; + +# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) + // In GUI guifg colors are only used when recognized + i = color_name2handle(arg); + if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT) + { + HL_TABLE()[idx].sg_gui_fg = i; +# endif + if (*namep == NULL || STRCMP(*namep, arg) != 0) + { + vim_free(*namep); + if (STRCMP(arg, "NONE") != 0) + *namep = vim_strsave(arg); + else + *namep = NULL; + did_change = TRUE; + } +# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) +# ifdef FEAT_GUI_X11 + if (is_menu_group && gui.menu_fg_pixel != i) + { + gui.menu_fg_pixel = i; + *do_colors = TRUE; + } + if (is_scrollbar_group && gui.scroll_fg_pixel != i) + { + gui.scroll_fg_pixel = i; + *do_colors = TRUE; + } +# ifdef FEAT_BEVAL_GUI + if (is_tooltip_group && gui.tooltip_fg_pixel != i) + { + gui.tooltip_fg_pixel = i; + *do_colors = TRUE; + } +# endif +# endif + } +# endif + } + + return did_change; +} + +/* + * Set the GUI background color for the highlight group at 'idx'. + * Returns TRUE if the color is set. + */ + static int +highlight_set_guibg( + int idx, + char_u *arg, + int is_menu_group UNUSED, + int is_scrollbar_group UNUSED, + int is_tooltip_group UNUSED, + int *do_colors UNUSED, + int init) +{ + int i; + char_u **namep; + int did_change = FALSE; + + namep = &HL_TABLE()[idx].sg_gui_bg_name; + if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) + { + if (!init) + HL_TABLE()[idx].sg_set |= SG_GUI; + +# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) + // In GUI guifg colors are only used when recognized + i = color_name2handle(arg); + if (i != INVALCOLOR || STRCMP(arg, "NONE") == 0 || !USE_24BIT) + { + HL_TABLE()[idx].sg_gui_bg = i; +# endif + if (*namep == NULL || STRCMP(*namep, arg) != 0) + { + vim_free(*namep); + if (STRCMP(arg, "NONE") != 0) + *namep = vim_strsave(arg); + else + *namep = NULL; + did_change = TRUE; + } +# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) +# ifdef FEAT_GUI_X11 + if (is_menu_group && gui.menu_bg_pixel != i) + { + gui.menu_bg_pixel = i; + *do_colors = TRUE; + } + if (is_scrollbar_group && gui.scroll_bg_pixel != i) + { + gui.scroll_bg_pixel = i; + *do_colors = TRUE; + } +# ifdef FEAT_BEVAL_GUI + if (is_tooltip_group && gui.tooltip_bg_pixel != i) + { + gui.tooltip_bg_pixel = i; + *do_colors = TRUE; + } +# endif +# endif + } +# endif + } + + return did_change; +} + +/* + * Set the GUI undercurl/strikethrough color for the highlight group at 'idx'. + * Returns TRUE if the color is set. + */ + static int +highlight_set_guisp(int idx, char_u *arg, int init) +{ +# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) + int i; +# endif + int did_change = FALSE; + char_u **namep; + + namep = &HL_TABLE()[idx].sg_gui_sp_name; + if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) + { + if (!init) + HL_TABLE()[idx].sg_set |= SG_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 || !USE_24BIT) + { + HL_TABLE()[idx].sg_gui_sp = i; +# endif + if (*namep == NULL || STRCMP(*namep, arg) != 0) + { + vim_free(*namep); + if (STRCMP(arg, "NONE") != 0) + *namep = vim_strsave(arg); + else + *namep = NULL; + did_change = TRUE; + } +# if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) + } +# endif + } + + return did_change; +} +#endif + +/* + * Set the start/stop terminal codes for a highlight group. + * Returns TRUE if the terminal code is set. + */ + static int +highlight_set_startstop_termcode(int idx, char_u *key, char_u *arg, int init) +{ + int off; + char_u buf[100]; + int len; + char_u *tname; + char_u *p; + + if (!init) + HL_TABLE()[idx].sg_set |= SG_TERM; + + // The "start" and "stop" arguments can be a literal escape + // sequence, or a comma separated list of terminal codes. + if (STRNCMP(arg, "t_", 2) == 0) + { + off = 0; + buf[0] = 0; + while (arg[off] != NUL) + { + // Isolate one termcap name + for (len = 0; arg[off + len] && + arg[off + len] != ','; ++len) + ; + tname = vim_strnsave(arg + off, len); + if (tname == NULL) // out of memory + return FALSE; + // lookup the escape sequence for the item + p = get_term_code(tname); + vim_free(tname); + if (p == NULL) // ignore non-existing things + p = (char_u *)""; + + // Append it to the already found stuff + if ((int)(STRLEN(buf) + STRLEN(p)) >= 99) + { + semsg(_("E422: terminal code too long: %s"), arg); + return FALSE; + } + STRCAT(buf, p); + + // Advance to the next item + off += len; + if (arg[off] == ',') // another one follows + ++off; + } + } + else + { + // Copy characters from arg[] to buf[], translating <> codes. + for (p = arg, off = 0; off < 100 - 6 && *p; ) + { + len = trans_special(&p, buf + off, FSK_SIMPLIFY, NULL); + if (len > 0) // recognized special char + off += len; + else // copy as normal char + buf[off++] = *p++; + } + buf[off] = NUL; + } + + if (STRCMP(buf, "NONE") == 0) // resetting the value + p = NULL; + else + p = vim_strsave(buf); + if (key[2] == 'A') + { + vim_free(HL_TABLE()[idx].sg_start); + HL_TABLE()[idx].sg_start = p; + } + else + { + vim_free(HL_TABLE()[idx].sg_stop); + HL_TABLE()[idx].sg_stop = p; + } + return TRUE; +} + +/* * Handle the ":highlight .." command. * When using ":hi clear" this is called recursively for each group with * "forceit" and "init" both TRUE. @@ -622,15 +1366,11 @@ do_highlight( int init) // TRUE when called for initializing { char_u *name_end; - char_u *p; char_u *linep; char_u *key_start; char_u *arg_start; char_u *key = NULL, *arg = NULL; long i; - int off; - int len; - int attr; int id; int idx; hl_group_T item_before; @@ -639,24 +1379,24 @@ do_highlight( int doclear = FALSE; int dolink = FALSE; int error = FALSE; - int color; int is_normal_group = FALSE; // "Normal" group #ifdef FEAT_GUI_X11 int is_menu_group = FALSE; // "Menu" group int is_scrollbar_group = FALSE; // "Scrollbar" group int is_tooltip_group = FALSE; // "Tooltip" group - int do_colors = FALSE; // need to update colors? #else # define is_menu_group 0 # define is_tooltip_group 0 +# define is_scrollbar_group 0 +#endif +#if defined(FEAT_GUI) || defined(FEAT_EVAL) + int do_colors = FALSE; // need to update colors? #endif #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) int did_highlight_changed = FALSE; #endif - /* - * If no argument, list current highlighting. - */ + // If no argument, list current highlighting. if (!init && ends_excmd2(line - 1, line)) { for (i = 1; i <= highlight_ga.ga_len && !got_int; ++i) @@ -665,15 +1405,11 @@ do_highlight( return; } - /* - * Isolate the name. - */ + // Isolate the name. name_end = skiptowhite(line); linep = skipwhite(name_end); - /* - * Check for "default" argument. - */ + // Check for "default" argument. if (STRNCMP(line, "default", name_end - line) == 0) { dodefault = TRUE; @@ -682,17 +1418,13 @@ do_highlight( linep = skipwhite(name_end); } - /* - * Check for "clear" or "link" argument. - */ + // Check for "clear" or "link" argument. if (STRNCMP(line, "clear", name_end - line) == 0) doclear = TRUE; if (STRNCMP(line, "link", name_end - line) == 0) dolink = TRUE; - /* - * ":highlight {group-name}": list highlighting for one group. - */ + // ":highlight {group-name}": list highlighting for one group. if (!doclear && !dolink && ends_excmd2(line, linep)) { id = syn_namen2id(line, (int)(name_end - line)); @@ -703,18 +1435,15 @@ do_highlight( return; } - /* - * Handle ":highlight link {from} {to}" command. - */ + // Handle ":highlight link {from} {to}" command. if (dolink) { char_u *from_start = linep; char_u *from_end; + int from_len; char_u *to_start; char_u *to_end; - int from_id; - int to_id; - hl_group_T *hlgroup = NULL; + int to_len; from_end = skiptowhite(from_start); to_start = skipwhite(from_end); @@ -734,127 +1463,20 @@ do_highlight( return; } - from_id = syn_check_group(from_start, (int)(from_end - from_start)); - if (STRNCMP(to_start, "NONE", 4) == 0) - to_id = 0; - else - to_id = syn_check_group(to_start, (int)(to_end - to_start)); - - if (from_id > 0) - { - hlgroup = &HL_TABLE()[from_id - 1]; - if (dodefault && (forceit || hlgroup->sg_deflink == 0)) - { - hlgroup->sg_deflink = to_id; -#ifdef FEAT_EVAL - hlgroup->sg_deflink_sctx = current_sctx; - hlgroup->sg_deflink_sctx.sc_lnum += SOURCING_LNUM; -#endif - } - } - - if (from_id > 0 && (!init || hlgroup->sg_set == 0)) - { - /* - * Don't allow a link when there already is some highlighting - * for the group, unless '!' is used - */ - if (to_id > 0 && !forceit && !init - && hl_has_settings(from_id - 1, dodefault)) - { - if (SOURCING_NAME == NULL && !dodefault) - emsg(_("E414: group has settings, highlight link ignored")); - } - else if (hlgroup->sg_link != to_id -#ifdef FEAT_EVAL - || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid -#endif - || hlgroup->sg_cleared) - { - if (!init) - hlgroup->sg_set |= SG_LINK; - hlgroup->sg_link = to_id; -#ifdef FEAT_EVAL - hlgroup->sg_script_ctx = current_sctx; - hlgroup->sg_script_ctx.sc_lnum += SOURCING_LNUM; -#endif - hlgroup->sg_cleared = FALSE; - redraw_all_later(SOME_VALID); - - // Only call highlight_changed() once after multiple changes. - need_highlight_changed = TRUE; - } - } - + from_len = (int)(from_end - from_start); + to_len = (int)(to_end - to_start); + highlight_group_link(from_start, from_len, to_start, to_len, + dodefault, forceit, init); return; } if (doclear) { - /* - * ":highlight clear [group]" command. - */ + // ":highlight clear [group]" command. if (ends_excmd2(line, linep)) { -#ifdef FEAT_GUI - // First, we do not destroy the old values, but allocate the new - // ones and update the display. THEN we destroy the old values. - // If we destroy the old values first, then the old values - // (such as GuiFont's or GuiFontset's) will still be displayed but - // invalid because they were free'd. - if (gui.in_use) - { -# ifdef FEAT_BEVAL_TIP - gui_init_tooltip_font(); -# endif -# if defined(FEAT_MENU) && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF)) - gui_init_menu_font(); -# endif - } -# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_X11) - gui_mch_def_colors(); -# endif -# ifdef FEAT_GUI_X11 -# ifdef FEAT_MENU - - // This only needs to be done when there is no Menu highlight - // group defined by default, which IS currently the case. - gui_mch_new_menu_colors(); -# endif - if (gui.in_use) - { - gui_new_scrollbar_colors(); -# ifdef FEAT_BEVAL_GUI - gui_mch_new_tooltip_colors(); -# endif -# ifdef FEAT_MENU - gui_mch_new_menu_font(); -# endif - } -# endif - - // Ok, we're done allocating the new default graphics items. - // The screen should already be refreshed at this point. - // It is now Ok to clear out the old data. -#endif -#ifdef FEAT_EVAL - do_unlet((char_u *)"g:colors_name", TRUE); -#endif - restore_cterm_colors(); - - /* - * Clear all default highlight groups and load the defaults. - */ - for (idx = 0; idx < highlight_ga.ga_len; ++idx) - highlight_clear(idx); - init_highlight(TRUE, TRUE); -#if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) - if (USE_24BIT) - highlight_gui_started(); - else -#endif - highlight_changed(); - redraw_later_clear(); + // ":highlight clear" without group name + highlight_reset_all(); return; } line = linep; @@ -862,13 +1484,11 @@ do_highlight( linep = skipwhite(name_end); } - /* - * Find the group name in the table. If it does not exist yet, add it. - */ + // Find the group name in the table. If it does not exist yet, add it. id = syn_check_group(line, (int)(name_end - line)); - if (id == 0) // failed (out of memory) + if (id == 0) // failed (out of memory) return; - idx = id - 1; // index is ID minus one + idx = id - 1; // index is ID minus one // Return if "default" was used and the group already has settings. if (dodefault && hl_has_settings(idx, TRUE)) @@ -897,609 +1517,164 @@ do_highlight( } if (!doclear) - while (!ends_excmd2(line, linep)) - { - key_start = linep; - if (*linep == '=') - { - semsg(_("E415: unexpected equal sign: %s"), key_start); - error = TRUE; - break; - } - - /* - * Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" or - * "guibg"). - */ - while (*linep && !VIM_ISWHITE(*linep) && *linep != '=') - ++linep; - vim_free(key); - key = vim_strnsave_up(key_start, linep - key_start); - if (key == NULL) + while (!ends_excmd2(line, linep)) { - error = TRUE; - break; - } - linep = skipwhite(linep); - - if (STRCMP(key, "NONE") == 0) - { - if (!init || HL_TABLE()[idx].sg_set == 0) + key_start = linep; + if (*linep == '=') { - if (!init) - HL_TABLE()[idx].sg_set |= SG_TERM+SG_CTERM+SG_GUI; - highlight_clear(idx); + semsg(_("E415: unexpected equal sign: %s"), key_start); + error = TRUE; + break; } - continue; - } - - /* - * Check for the equal sign. - */ - if (*linep != '=') - { - semsg(_("E416: missing equal sign: %s"), key_start); - error = TRUE; - break; - } - ++linep; - /* - * Isolate the argument. - */ - linep = skipwhite(linep); - if (*linep == '\'') // guifg='color name' - { - arg_start = ++linep; - linep = vim_strchr(linep, '\''); - if (linep == NULL) + // Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" + // or "guibg"). + while (*linep && !VIM_ISWHITE(*linep) && *linep != '=') + ++linep; + vim_free(key); + key = vim_strnsave_up(key_start, linep - key_start); + if (key == NULL) { - semsg(_(e_invarg2), key_start); error = TRUE; break; } - } - else - { - arg_start = linep; - linep = skiptowhite(linep); - } - if (linep == arg_start) - { - semsg(_("E417: missing argument: %s"), key_start); - error = TRUE; - break; - } - vim_free(arg); - arg = vim_strnsave(arg_start, linep - arg_start); - if (arg == NULL) - { - error = TRUE; - break; - } - if (*linep == '\'') - ++linep; + linep = skipwhite(linep); - /* - * Store the argument. - */ - if ( STRCMP(key, "TERM") == 0 - || STRCMP(key, "CTERM") == 0 - || STRCMP(key, "GUI") == 0) - { - attr = 0; - off = 0; - while (arg[off] != NUL) + if (STRCMP(key, "NONE") == 0) { - for (i = ARRAY_LENGTH(hl_attr_table); --i >= 0; ) - { - len = (int)STRLEN(hl_name_table[i]); - if (STRNICMP(arg + off, hl_name_table[i], len) == 0) - { - attr |= hl_attr_table[i]; - off += len; - break; - } - } - if (i < 0) - { - semsg(_("E418: Illegal value: %s"), arg); - error = TRUE; - break; - } - if (arg[off] == ',') // another one follows - ++off; - } - if (error) - break; - if (*key == 'T') - { - if (!init || !(HL_TABLE()[idx].sg_set & SG_TERM)) + if (!init || HL_TABLE()[idx].sg_set == 0) { if (!init) - HL_TABLE()[idx].sg_set |= SG_TERM; - HL_TABLE()[idx].sg_term = attr; + HL_TABLE()[idx].sg_set |= SG_TERM+SG_CTERM+SG_GUI; + highlight_clear(idx); } + continue; } - else if (*key == 'C') + + // Check for the equal sign. + if (*linep != '=') { - if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) - { - if (!init) - HL_TABLE()[idx].sg_set | |