diff options
Diffstat (limited to 'src/syntax.c')
-rw-r--r-- | src/syntax.c | 197 |
1 files changed, 181 insertions, 16 deletions
diff --git a/src/syntax.c b/src/syntax.c index 003b62430..662b8a59c 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -204,12 +204,12 @@ static int current_id = 0; /* ID of current char for syn_get_id() */ static int current_trans_id = 0; /* idem, transparancy removed */ #endif -struct syn_cluster +typedef struct syn_cluster_S { char_u *scl_name; /* syntax cluster name */ char_u *scl_name_u; /* uppercase of scl_name */ short *scl_list; /* IDs in this syntax cluster */ -}; +} syn_cluster_T; /* * Methods of combining two clusters @@ -218,7 +218,7 @@ struct syn_cluster #define CLUSTER_ADD 2 /* add second list to first */ #define CLUSTER_SUBTRACT 3 /* subtract second list from first */ -#define SYN_CLSTR(buf) ((struct syn_cluster *)((buf)->b_syn_clusters.ga_data)) +#define SYN_CLSTR(buf) ((syn_cluster_T *)((buf)->b_syn_clusters.ga_data)) /* * Syntax group IDs have different types: @@ -372,7 +372,7 @@ static void invalidate_current_state __ARGS((void)); static int syn_stack_equal __ARGS((synstate_T *sp)); static void validate_current_state __ARGS((void)); static int syn_finish_line __ARGS((int syncing)); -static int syn_current_attr __ARGS((int syncing, int displaying)); +static int syn_current_attr __ARGS((int syncing, int displaying, int *can_spell)); static int did_match_already __ARGS((int idx, garray_T *gap)); static stateitem_T *push_next_match __ARGS((stateitem_T *cur_si)); static void check_state_ends __ARGS((void)); @@ -1660,7 +1660,7 @@ syn_finish_line(syncing) { while (!current_finished) { - (void)syn_current_attr(syncing, FALSE); + (void)syn_current_attr(syncing, FALSE, NULL); /* * When syncing, and found some item, need to check the item. */ @@ -1693,10 +1693,13 @@ syn_finish_line(syncing) * "col" is normally 0 for the first use in a line, and increments by one each * time. It's allowed to skip characters and to stop before the end of the * line. But only a "col" after a previously used column is allowed. + * When "can_spell" is not NULL set it to TRUE when spell-checking should be + * done. */ int -get_syntax_attr(col) +get_syntax_attr(col, can_spell) colnr_T col; + int *can_spell; { int attr = 0; @@ -1715,7 +1718,7 @@ get_syntax_attr(col) */ while (current_col <= col) { - attr = syn_current_attr(FALSE, TRUE); + attr = syn_current_attr(FALSE, TRUE, can_spell); ++current_col; } @@ -1727,9 +1730,10 @@ get_syntax_attr(col) * Get syntax attributes for current_lnum, current_col. */ static int -syn_current_attr(syncing, displaying) +syn_current_attr(syncing, displaying, can_spell) int syncing; /* When 1: called for syncing */ int displaying; /* result will be displayed */ + int *can_spell; /* return: do spell checking */ { int syn_id; lpos_T endpos; /* was: char_u *endp; */ @@ -1740,7 +1744,7 @@ syn_current_attr(syncing, displaying) int end_idx; /* group ID for end pattern */ int idx; synpat_T *spp; - stateitem_T *cur_si, *sip; + stateitem_T *cur_si, *sip = NULL; int startcol; int endcol; long flags; @@ -2166,6 +2170,9 @@ syn_current_attr(syncing, displaying) #endif if (cur_si != NULL) { +#ifndef FEAT_EVAL + int current_trans_id = 0; +#endif for (idx = current_state.ga_len - 1; idx >= 0; --idx) { sip = &CUR_STATE(idx); @@ -2180,12 +2187,36 @@ syn_current_attr(syncing, displaying) current_attr = sip->si_attr; #ifdef FEAT_EVAL current_id = sip->si_id; - current_trans_id = sip->si_trans_id; #endif + current_trans_id = sip->si_trans_id; break; } } + if (can_spell != NULL) + { + struct sp_syn sps; + + /* + * set "can_spell" to TRUE if spell checking is supposed to be + * done in the current item. + */ + + /* Always do spelling if there is no @Spell cluster. */ + if (syn_buf->b_spell_cluster_id == 0) + *can_spell = TRUE; + else if (current_trans_id == 0) + *can_spell = FALSE; + else + { + sps.inc_tag = 0; + sps.id = syn_buf->b_spell_cluster_id; + sps.cont_in_list = NULL; + *can_spell = in_id_list(sip, sip->si_cont_list, &sps, 0); + } + } + + /* * Check for end of current state (and the states before it) at the * next column. Don't do this for syncing, because we would miss a @@ -2205,6 +2236,9 @@ syn_current_attr(syncing, displaying) } } } + else if (can_spell != NULL) + /* Only do spelling when there is no @Spell cluster. */ + *can_spell = (syn_buf->b_spell_cluster_id == 0); /* nextgroup ends at end of line, unless "skipnl" or "skipemtpy" present */ if (current_next_list != NULL @@ -5029,16 +5063,16 @@ syn_check_cluster(pp, len) */ static int syn_add_cluster(name) - char_u *name; + char_u *name; { - int len; + int len; /* * First call for this growarray: init growing array. */ if (curbuf->b_syn_clusters.ga_data == NULL) { - curbuf->b_syn_clusters.ga_itemsize = sizeof(struct syn_cluster); + curbuf->b_syn_clusters.ga_itemsize = sizeof(syn_cluster_T); curbuf->b_syn_clusters.ga_growsize = 10; } @@ -5052,12 +5086,15 @@ syn_add_cluster(name) } len = curbuf->b_syn_clusters.ga_len; - vim_memset(&(SYN_CLSTR(curbuf)[len]), 0, sizeof(struct syn_cluster)); + vim_memset(&(SYN_CLSTR(curbuf)[len]), 0, sizeof(syn_cluster_T)); SYN_CLSTR(curbuf)[len].scl_name = name; SYN_CLSTR(curbuf)[len].scl_name_u = vim_strsave_up(name); SYN_CLSTR(curbuf)[len].scl_list = NULL; ++curbuf->b_syn_clusters.ga_len; + if (STRICMP(name, "Spell") == 0) + curbuf->b_spell_cluster_id = len + SYNID_CLUSTER; + return len + SYNID_CLUSTER; } @@ -5089,7 +5126,7 @@ syn_cmd_cluster(eap, syncing) if (rest != NULL) { scl_id = syn_check_cluster(arg, (int)(group_name_end - arg)) - - SYNID_CLUSTER; + - SYNID_CLUSTER; for (;;) { @@ -5896,7 +5933,7 @@ syn_get_id(lnum, col, trans) || col < (long)current_col) syntax_start(curwin, lnum); - (void)get_syntax_attr((colnr_T)col); + (void)get_syntax_attr((colnr_T)col, NULL); return (trans ? current_trans_id : current_id); } @@ -5968,6 +6005,9 @@ static char *(highlight_init_light[]) = "Normal gui=NONE", "Question term=standout ctermfg=DarkGreen gui=bold guifg=SeaGreen", "Search term=reverse ctermbg=Yellow ctermfg=NONE guibg=Yellow guifg=NONE", + "SpellBad term=reverse ctermbg=LightRed guisp=Red gui=undercurl", + "SpellRare term=reverse ctermbg=LightMagenta guisp=Magenta gui=undercurl", + "SpellLocal term=underline ctermbg=Cyan guisp=DarkCyan gui=undercurl", "SpecialKey term=bold ctermfg=DarkBlue guifg=Blue", "Title term=bold ctermfg=DarkMagenta gui=bold guifg=Magenta", "WarningMsg term=standout ctermfg=DarkRed guifg=Red", @@ -5990,6 +6030,9 @@ static char *(highlight_init_dark[]) = "Question term=standout ctermfg=LightGreen gui=bold guifg=Green", "Search term=reverse ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black", "SpecialKey term=bold ctermfg=LightBlue guifg=Cyan", + "SpellBad term=reverse ctermbg=Red guisp=Red gui=undercurl", + "SpellRare term=reverse ctermbg=Magenta guisp=Magenta gui=undercurl", + "SpellLocal term=underline ctermbg=Cyan guisp=Cyan gui=undercurl", "Title term=bold ctermfg=LightMagenta gui=bold guifg=Magenta", "WarningMsg term=standout ctermfg=LightRed guifg=Red", "WildMenu term=standout ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black", @@ -7519,6 +7562,128 @@ get_attr_entry(table, aep) return (table->ga_len - 1 + ATTR_OFF); } +#if defined(FEAT_SYN_HL) || defined(PROTO) +/* + * Combine the spelling attributes with other attributes. "spell_attr" + * overrules "char_attr". + * This creates a new group when required. + * Since we expect there to be few spelling mistakes we don't cache the + * result. + * Return the resulting attributes. + */ + int +hl_combine_attr(char_attr, spell_attr) + int char_attr; + int spell_attr; +{ + attrentry_T *char_aep = NULL; + attrentry_T *spell_aep; + attrentry_T new_en; + + if (char_attr == 0) + return spell_attr; + if (char_attr <= HL_ALL && spell_attr <= HL_ALL) + return char_attr | spell_attr; +#ifdef FEAT_GUI + if (gui.in_use) + { + if (char_attr > HL_ALL) + char_aep = syn_gui_attr2entry(char_attr); + if (char_aep != NULL) + new_en = *char_aep; + else + { + vim_memset(&new_en, 0, sizeof(new_en)); + if (char_attr <= HL_ALL) + new_en.ae_attr = char_attr; + } + + if (spell_attr <= HL_ALL) + new_en.ae_attr |= spell_attr; + else + { + spell_aep = syn_gui_attr2entry(spell_attr); + if (spell_aep != NULL) + { + new_en.ae_attr |= spell_aep->ae_attr; + if (spell_aep->ae_u.gui.fg_color != INVALCOLOR) + new_en.ae_u.gui.fg_color = spell_aep->ae_u.gui.fg_color; + if (spell_aep->ae_u.gui.bg_color != INVALCOLOR) + new_en.ae_u.gui.bg_color = spell_aep->ae_u.gui.bg_color; + if (spell_aep->ae_u.gui.sp_color != INVALCOLOR) + new_en.ae_u.gui.sp_color = spell_aep->ae_u.gui.sp_color; + if (spell_aep->ae_u.gui.font != NOFONT) + new_en.ae_u.gui.font = spell_aep->ae_u.gui.font; +# ifdef FEAT_XFONTSET + if (spell_aep->ae_u.gui.fontset != NOFONTSET) + new_en.ae_u.gui.fontset = spell_aep->ae_u.gui.fontset; +# endif + } + } + return get_attr_entry(&gui_attr_table, &new_en); + } +#endif + + if (t_colors > 1) + { + if (char_attr > HL_ALL) + char_aep = syn_cterm_attr2entry(char_attr); + if (char_aep != NULL) + new_en = *char_aep; + else + { + vim_memset(&new_en, 0, sizeof(new_en)); + if (char_attr <= HL_ALL) + new_en.ae_attr = char_attr; + } + + if (spell_attr <= HL_ALL) + new_en.ae_attr |= spell_attr; + else + { + spell_aep = syn_cterm_attr2entry(spell_attr); + if (spell_aep != NULL) + { + new_en.ae_attr |= spell_aep->ae_attr; + if (spell_aep->ae_u.cterm.fg_color > 0) + 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; + } + } + return get_attr_entry(&cterm_attr_table, &new_en); + } + + if (char_attr > HL_ALL) + char_aep = syn_term_attr2entry(char_attr); + if (char_aep != NULL) + new_en = *char_aep; + else + { + vim_memset(&new_en, 0, sizeof(new_en)); + if (char_attr <= HL_ALL) + new_en.ae_attr = char_attr; + } + + if (spell_attr <= HL_ALL) + new_en.ae_attr |= spell_attr; + else + { + spell_aep = syn_cterm_attr2entry(spell_attr); + if (spell_aep != NULL) + { + new_en.ae_attr |= spell_aep->ae_attr; + if (spell_aep->ae_u.term.start != NULL) + { + new_en.ae_u.term.start = spell_aep->ae_u.term.start; + new_en.ae_u.term.stop = spell_aep->ae_u.term.stop; + } + } + } + return get_attr_entry(&term_attr_table, &new_en); +} +#endif + #ifdef FEAT_GUI attrentry_T * |