aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/syntax.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/syntax.c')
-rw-r--r--src/nvim/syntax.c1166
1 files changed, 485 insertions, 681 deletions
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 98e457db18..22eabc75c1 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -16,12 +16,14 @@
#include "nvim/ascii.h"
#include "nvim/syntax.h"
#include "nvim/charset.h"
+#include "nvim/cursor_shape.h"
#include "nvim/eval.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/hashtab.h"
+#include "nvim/highlight.h"
#include "nvim/indent_c.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
@@ -42,7 +44,6 @@
#include "nvim/ui.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
-#include "nvim/api/private/helpers.h"
#include "nvim/buffer.h"
static bool did_syntax_onoff = false;
@@ -53,7 +54,7 @@ static bool did_syntax_onoff = false;
struct hl_group {
char_u *sg_name; ///< highlight group name
char_u *sg_name_u; ///< uppercase of sg_name
- int sg_cleared; ///< "hi clear" was used
+ bool sg_cleared; ///< "hi clear" was used
int sg_attr; ///< Screen attr @see ATTR_ENTRY
int sg_link; ///< link to this highlight group ID
int sg_set; ///< combination of flags in \ref SG_SET
@@ -62,7 +63,7 @@ struct hl_group {
int sg_cterm; ///< "cterm=" highlighting attr
int sg_cterm_fg; ///< terminal fg color number + 1
int sg_cterm_bg; ///< terminal bg color number + 1
- int sg_cterm_bold; ///< bold attr was set for light color
+ bool sg_cterm_bold; ///< bold attr was set for light color
// for RGB UIs
int sg_gui; ///< "gui=" highlighting attributes
///< (combination of \ref HlAttrFlags)
@@ -115,42 +116,42 @@ static int hl_attr_table[] =
{HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERCURL, HL_ITALIC, HL_INVERSE,
HL_INVERSE, 0};
-/*
- * The patterns that are being searched for are stored in a syn_pattern.
- * A match item consists of one pattern.
- * A start/end item consists of n start patterns and m end patterns.
- * A start/skip/end item consists of n start patterns, one skip pattern and m
- * end patterns.
- * For the latter two, the patterns are always consecutive: start-skip-end.
- *
- * A character offset can be given for the matched text (_m_start and _m_end)
- * and for the actually highlighted text (_h_start and _h_end).
- */
+// The patterns that are being searched for are stored in a syn_pattern.
+// A match item consists of one pattern.
+// A start/end item consists of n start patterns and m end patterns.
+// A start/skip/end item consists of n start patterns, one skip pattern and m
+// end patterns.
+// For the latter two, the patterns are always consecutive: start-skip-end.
+//
+// A character offset can be given for the matched text (_m_start and _m_end)
+// and for the actually highlighted text (_h_start and _h_end).
+//
+// Note that ordering of members is optimized to reduce padding.
typedef struct syn_pattern {
- char sp_type; /* see SPTYPE_ defines below */
- char sp_syncing; /* this item used for syncing */
- int sp_flags; /* see HL_ defines below */
- int sp_cchar; /* conceal substitute character */
- struct sp_syn sp_syn; /* struct passed to in_id_list() */
- short sp_syn_match_id; /* highlight group ID of pattern */
- char_u *sp_pattern; /* regexp to match, pattern */
- regprog_T *sp_prog; /* regexp to match, program */
+ char sp_type; // see SPTYPE_ defines below
+ bool sp_syncing; // this item used for syncing
+ int16_t sp_syn_match_id; // highlight group ID of pattern
+ int16_t sp_off_flags; // see below
+ int sp_offsets[SPO_COUNT]; // offsets
+ int sp_flags; // see HL_ defines below
+ int sp_cchar; // conceal substitute character
+ int sp_ic; // ignore-case flag for sp_prog
+ int sp_sync_idx; // sync item index (syncing only)
+ int sp_line_id; // ID of last line where tried
+ int sp_startcol; // next match in sp_line_id line
+ int16_t *sp_cont_list; // cont. group IDs, if non-zero
+ int16_t *sp_next_list; // next group IDs, if non-zero
+ struct sp_syn sp_syn; // struct passed to in_id_list()
+ char_u *sp_pattern; // regexp to match, pattern
+ regprog_T *sp_prog; // regexp to match, program
syn_time_T sp_time;
- int sp_ic; /* ignore-case flag for sp_prog */
- short sp_off_flags; /* see below */
- int sp_offsets[SPO_COUNT]; /* offsets */
- short *sp_cont_list; /* cont. group IDs, if non-zero */
- short *sp_next_list; /* next group IDs, if non-zero */
- int sp_sync_idx; /* sync item index (syncing only) */
- int sp_line_id; /* ID of last line where tried */
- int sp_startcol; /* next match in sp_line_id line */
} synpat_T;
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 */
+ char_u *scl_name; // syntax cluster name
+ char_u *scl_name_u; // uppercase of scl_name
+ int16_t *scl_list; // IDs in this syntax cluster
} syn_cluster_T;
/*
@@ -159,27 +160,27 @@ typedef struct syn_cluster_S {
* (The end positions have the column number of the next char)
*/
typedef struct state_item {
- int si_idx; /* index of syntax pattern or
- KEYWORD_IDX */
- int si_id; /* highlight group ID for keywords */
- int si_trans_id; /* idem, transparency removed */
- int si_m_lnum; /* lnum of the match */
- int si_m_startcol; /* starting column of the match */
- lpos_T si_m_endpos; /* just after end posn of the match */
- lpos_T si_h_startpos; /* start position of the highlighting */
- lpos_T si_h_endpos; /* end position of the highlighting */
- lpos_T si_eoe_pos; /* end position of end pattern */
- int si_end_idx; /* group ID for end pattern or zero */
- int si_ends; /* if match ends before si_m_endpos */
- int si_attr; /* attributes in this state */
- long si_flags; /* HL_HAS_EOL flag in this state, and
- * HL_SKIP* for si_next_list */
- int si_seqnr; /* sequence number */
- int si_cchar; /* substitution character for conceal */
- short *si_cont_list; /* list of contained groups */
- short *si_next_list; /* nextgroup IDs after this item ends */
- reg_extmatch_T *si_extmatch; /* \z(...\) matches from start
- * pattern */
+ int si_idx; // index of syntax pattern or
+ // KEYWORD_IDX
+ int si_id; // highlight group ID for keywords
+ int si_trans_id; // idem, transparency removed
+ int si_m_lnum; // lnum of the match
+ int si_m_startcol; // starting column of the match
+ lpos_T si_m_endpos; // just after end posn of the match
+ lpos_T si_h_startpos; // start position of the highlighting
+ lpos_T si_h_endpos; // end position of the highlighting
+ lpos_T si_eoe_pos; // end position of end pattern
+ int si_end_idx; // group ID for end pattern or zero
+ int si_ends; // if match ends before si_m_endpos
+ int si_attr; // attributes in this state
+ long si_flags; // HL_HAS_EOL flag in this state, and
+ // HL_SKIP* for si_next_list
+ int si_seqnr; // sequence number
+ int si_cchar; // substitution character for conceal
+ int16_t *si_cont_list; // list of contained groups
+ int16_t *si_next_list; // nextgroup IDs after this item ends
+ reg_extmatch_T *si_extmatch; // \z(...\) matches from start
+ // pattern
} stateitem_T;
/*
@@ -187,14 +188,14 @@ typedef struct state_item {
* very often.
*/
typedef struct {
- int flags; /* flags for contained and transparent */
- int keyword; /* TRUE for ":syn keyword" */
- int *sync_idx; /* syntax item for "grouphere" argument, NULL
- if not allowed */
- char has_cont_list; /* TRUE if "cont_list" can be used */
- short *cont_list; /* group IDs for "contains" argument */
- short *cont_in_list; /* group IDs for "containedin" argument */
- short *next_list; /* group IDs for "nextgroup" argument */
+ int flags; // flags for contained and transparent
+ bool keyword; // true for ":syn keyword"
+ int *sync_idx; // syntax item for "grouphere" argument, NULL
+ // if not allowed
+ bool has_cont_list; // true if "cont_list" can be used
+ int16_t *cont_list; // group IDs for "contains" argument
+ int16_t *cont_in_list; // group IDs for "containedin" argument
+ int16_t *next_list; // group IDs for "nextgroup" argument
} syn_opt_arg_T;
typedef struct {
@@ -216,12 +217,6 @@ struct name_list {
# include "syntax.c.generated.h"
#endif
-/*
- * An attribute number is the index in attr_table plus ATTR_OFF.
- */
-#define ATTR_OFF 1
-
-
static char *(spo_name_tab[SPO_COUNT]) =
{"ms=", "me=", "hs=", "he=", "rs=", "re=", "lc="};
@@ -324,9 +319,10 @@ static int keepend_level = -1;
static char msg_no_items[] = N_("No Syntax items defined for this buffer");
-#define KEYWORD_IDX -1 /* value of si_idx for keywords */
-#define ID_LIST_ALL (short *)-1 /* valid of si_cont_list for containing all
- but contained groups */
+// value of si_idx for keywords
+#define KEYWORD_IDX -1
+// valid of si_cont_list for containing all but contained groups
+#define ID_LIST_ALL (int16_t *)-1
static int next_seqnr = 1; /* value to use for si_seqnr */
@@ -369,9 +365,9 @@ static int current_state_stored = 0; /* TRUE if stored current state
static int current_finished = 0; /* current line has been finished */
static garray_T current_state /* current stack of state_items */
= GA_EMPTY_INIT_VALUE;
-static short *current_next_list = NULL; /* when non-zero, nextgroup list */
-static int current_next_flags = 0; /* flags for current_next_list */
-static int current_line_id = 0; /* unique number for current line */
+static int16_t *current_next_list = NULL; // when non-zero, nextgroup list
+static int current_next_flags = 0; // flags for current_next_list
+static int current_line_id = 0; // unique number for current line
#define CUR_STATE(idx) ((stateitem_T *)(current_state.ga_data))[idx]
@@ -1531,32 +1527,26 @@ int syntax_check_changed(linenr_T lnum)
*/
static bool
syn_finish_line(
- bool syncing // called for syncing
+ const bool syncing // called for syncing
)
{
- stateitem_T *cur_si;
- colnr_T prev_current_col;
-
while (!current_finished) {
- (void)syn_current_attr(syncing, FALSE, NULL, FALSE);
- /*
- * When syncing, and found some item, need to check the item.
- */
+ (void)syn_current_attr(syncing, false, NULL, false);
+
+ // When syncing, and found some item, need to check the item.
if (syncing && current_state.ga_len) {
- /*
- * Check for match with sync item.
- */
- cur_si = &CUR_STATE(current_state.ga_len - 1);
+ // Check for match with sync item.
+ const stateitem_T *const cur_si = &CUR_STATE(current_state.ga_len - 1);
if (cur_si->si_idx >= 0
&& (SYN_ITEMS(syn_block)[cur_si->si_idx].sp_flags
& (HL_SYNC_HERE|HL_SYNC_THERE))) {
return true;
}
- /* syn_current_attr() will have skipped the check for an item
- * that ends here, need to do that now. Be careful not to go
- * past the NUL. */
- prev_current_col = current_col;
+ // syn_current_attr() will have skipped the check for an item
+ // that ends here, need to do that now. Be careful not to go
+ // past the NUL.
+ const colnr_T prev_current_col = current_col;
if (syn_getcurline()[current_col] != NUL) {
current_col++;
}
@@ -1579,9 +1569,9 @@ syn_finish_line(
*/
int
get_syntax_attr(
- colnr_T col,
- bool *can_spell,
- int keep_state /* keep state of char at "col" */
+ const colnr_T col,
+ bool *const can_spell,
+ const bool keep_state // keep state of char at "col"
)
{
int attr = 0;
@@ -1615,9 +1605,9 @@ get_syntax_attr(
* Skip from the current column to "col", get the attributes for "col".
*/
while (current_col <= col) {
- attr = syn_current_attr(FALSE, TRUE, can_spell,
- current_col == col ? keep_state : FALSE);
- ++current_col;
+ attr = syn_current_attr(false, true, can_spell,
+ current_col == col ? keep_state : false);
+ current_col++;
}
return attr;
@@ -1626,42 +1616,37 @@ get_syntax_attr(
/*
* Get syntax attributes for current_lnum, current_col.
*/
-static int
-syn_current_attr(
- int syncing, // When 1: called for syncing
- int displaying, // result will be displayed
- bool *can_spell, // return: do spell checking
- int keep_state // keep syntax stack afterwards
+static int syn_current_attr(
+ const bool syncing, // When true: called for syncing
+ const bool displaying, // result will be displayed
+ bool *const can_spell, // return: do spell checking
+ const bool keep_state // keep syntax stack afterwards
)
{
- int syn_id;
- lpos_T endpos; /* was: char_u *endp; */
- lpos_T hl_startpos; /* was: int hl_startcol; */
+ lpos_T endpos; // was: char_u *endp;
+ lpos_T hl_startpos; // was: int hl_startcol;
lpos_T hl_endpos;
- lpos_T eos_pos; /* end-of-start match (start region) */
- lpos_T eoe_pos; /* end-of-end pattern */
- int end_idx; /* group ID for end pattern */
- synpat_T *spp;
+ lpos_T eos_pos; // end-of-start match (start region)
+ lpos_T eoe_pos; // end-of-end pattern
+ int end_idx; // group ID for end pattern
stateitem_T *cur_si, *sip = NULL;
int startcol;
int endcol;
long flags;
int cchar;
- short *next_list;
- int found_match; /* found usable match */
- static int try_next_column = FALSE; /* must try in next col */
- int do_keywords;
+ int16_t *next_list;
+ bool found_match; // found usable match
+ static bool try_next_column = false; // must try in next col
regmmatch_T regmatch;
lpos_T pos;
- int lc_col;
reg_extmatch_T *cur_extmatch = NULL;
char_u buf_chartab[32]; // chartab array for syn iskeyword
char_u *line; // current line. NOTE: becomes invalid after
// looking for a pattern match!
- /* variables for zero-width matches that have a "nextgroup" argument */
- int keep_next_list;
- int zero_width_next_list = FALSE;
+ // variables for zero-width matches that have a "nextgroup" argument
+ bool keep_next_list;
+ bool zero_width_next_list = false;
garray_T zero_width_next_ga;
/*
@@ -1696,13 +1681,13 @@ syn_current_attr(
*/
if (try_next_column) {
next_match_idx = -1;
- try_next_column = FALSE;
+ try_next_column = false;
}
- /* Only check for keywords when not syncing and there are some. */
- do_keywords = !syncing
- && (syn_block->b_keywtab.ht_used > 0
- || syn_block->b_keywtab_ic.ht_used > 0);
+ // Only check for keywords when not syncing and there are some.
+ const bool do_keywords = !syncing
+ && (syn_block->b_keywtab.ht_used > 0
+ || syn_block->b_keywtab_ic.ht_used > 0);
/* Init the list of zero-width matches with a nextlist. This is used to
* avoid matching the same item in the same position twice. */
@@ -1717,9 +1702,9 @@ syn_current_attr(
* column.
*/
do {
- found_match = FALSE;
- keep_next_list = FALSE;
- syn_id = 0;
+ found_match = false;
+ keep_next_list = false;
+ int syn_id = 0;
/*
* 1. Check for a current state.
@@ -1741,16 +1726,12 @@ syn_current_attr(
*/
if (do_keywords) {
line = syn_getcurline();
- if (vim_iswordp_buf(line + current_col, syn_buf)
- && (current_col == 0
- || !vim_iswordp_buf(line + current_col - 1
- - (has_mbyte
- ? (*mb_head_off)(line, line + current_col - 1)
- : 0)
- , syn_buf))) {
- syn_id = check_keyword_id(line, (int)current_col,
- &endcol, &flags, &next_list, cur_si,
- &cchar);
+ const char_u *cur_pos = line + current_col;
+ if (vim_iswordp_buf(cur_pos, syn_buf)
+ && (current_col == 0 || !vim_iswordp_buf(
+ cur_pos - 1 - utf_head_off(line, cur_pos - 1), syn_buf))) {
+ syn_id = check_keyword_id(line, (int)current_col, &endcol, &flags,
+ &next_list, cur_si, &cchar);
if (syn_id != 0) {
push_current_state(KEYWORD_IDX);
{
@@ -1812,7 +1793,7 @@ syn_current_attr(
next_match_idx = 0; /* no match in this line yet */
next_match_col = MAXCOL;
for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) {
- spp = &(SYN_ITEMS(syn_block)[idx]);
+ synpat_T *const spp = &(SYN_ITEMS(syn_block)[idx]);
if ( spp->sp_syncing == syncing
&& (displaying || !(spp->sp_flags & HL_DISPLAY))
&& (spp->sp_type == SPTYPE_MATCH
@@ -1833,13 +1814,14 @@ syn_current_attr(
continue;
spp->sp_line_id = current_line_id;
- lc_col = current_col - spp->sp_offsets[SPO_LC_OFF];
- if (lc_col < 0)
+ colnr_T lc_col = current_col - spp->sp_offsets[SPO_LC_OFF];
+ if (lc_col < 0) {
lc_col = 0;
+ }
regmatch.rmm_ic = spp->sp_ic;
regmatch.regprog = spp->sp_prog;
- int r = syn_regexec(&regmatch, current_lnum, (colnr_T)lc_col,
+ int r = syn_regexec(&regmatch, current_lnum, lc_col,
IF_SYN_TIME(&spp->sp_time));
spp->sp_prog = regmatch.regprog;
if (!r) {
@@ -1878,7 +1860,7 @@ syn_current_attr(
* column, because it may match from there.
*/
if (did_match_already(idx, &zero_width_next_ga)) {
- try_next_column = TRUE;
+ try_next_column = true;
continue;
}
@@ -1940,9 +1922,9 @@ syn_current_attr(
* If an empty string is matched, may need
* to try matching again at next column.
*/
- if (regmatch.startpos[0].col
- == regmatch.endpos[0].col)
- try_next_column = TRUE;
+ if (regmatch.startpos[0].col == regmatch.endpos[0].col) {
+ try_next_column = true;
+ }
continue;
}
}
@@ -1987,8 +1969,8 @@ syn_current_attr(
&& lspp->sp_next_list != NULL) {
current_next_list = lspp->sp_next_list;
current_next_flags = lspp->sp_flags;
- keep_next_list = TRUE;
- zero_width_next_list = TRUE;
+ keep_next_list = true;
+ zero_width_next_list = true;
/* Add the index to a list, so that we can check
* later that we don't match it again (and cause an
@@ -2031,8 +2013,9 @@ syn_current_attr(
*/
current_next_list = NULL;
next_match_idx = -1;
- if (!zero_width_next_list)
- found_match = TRUE;
+ if (!zero_width_next_list) {
+ found_match = true;
+ }
}
} while (found_match);
@@ -2937,39 +2920,35 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T
* The caller must check if a keyword can start at startcol.
* Return its ID if found, 0 otherwise.
*/
-static int
-check_keyword_id(
- char_u *line,
- int startcol, /* position in line to check for keyword */
- int *endcolp, /* return: character after found keyword */
- long *flagsp, /* return: flags of matching keyword */
- short **next_listp, /* return: next_list of matching keyword */
- stateitem_T *cur_si, /* item at the top of the stack */
- int *ccharp /* conceal substitution char */
+static int check_keyword_id(
+ char_u *const line,
+ const int startcol, // position in line to check for keyword
+ int *const endcolp, // return: character after found keyword
+ long *const flagsp, // return: flags of matching keyword
+ int16_t **const next_listp, // return: next_list of matching keyword
+ stateitem_T *const cur_si, // item at the top of the stack
+ int *const ccharp // conceal substitution char
)
{
- char_u *kwp;
- int kwlen;
- char_u keyword[MAXKEYWLEN + 1]; /* assume max. keyword len is 80 */
-
- /* Find first character after the keyword. First character was already
- * checked. */
- kwp = line + startcol;
- kwlen = 0;
+ // Find first character after the keyword. First character was already
+ // checked.
+ char_u *const kwp = line + startcol;
+ int kwlen = 0;
do {
- if (has_mbyte)
+ if (has_mbyte) {
kwlen += (*mb_ptr2len)(kwp + kwlen);
- else
- ++kwlen;
+ } else {
+ kwlen++;
+ }
} while (vim_iswordp_buf(kwp + kwlen, syn_buf));
- if (kwlen > MAXKEYWLEN)
+ if (kwlen > MAXKEYWLEN) {
return 0;
+ }
- /*
- * Must make a copy of the keyword, so we can add a NUL and make it
- * lowercase.
- */
+ // Must make a copy of the keyword, so we can add a NUL and make it
+ // lowercase.
+ char_u keyword[MAXKEYWLEN + 1]; // assume max. keyword len is 80
STRLCPY(keyword, kwp, kwlen + 1);
keyentry_T *kp = NULL;
@@ -3327,12 +3306,10 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
EMSG2(_("E391: No such syntax cluster: %s"), arg);
break;
} else {
- /*
- * We can't physically delete a cluster without changing
- * the IDs of other clusters, so we do the next best thing
- * and make it empty.
- */
- short scl_id = id - SYNID_CLUSTER;
+ // We can't physically delete a cluster without changing
+ // the IDs of other clusters, so we do the next best thing
+ // and make it empty.
+ int scl_id = id - SYNID_CLUSTER;
xfree(SYN_CLSTR(curwin->w_s)[scl_id].scl_list);
SYN_CLSTR(curwin->w_s)[scl_id].scl_list = NULL;
@@ -3355,7 +3332,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
/*
* Clear one syntax group for the current buffer.
*/
-static void syn_clear_one(int id, int syncing)
+static void syn_clear_one(const int id, const bool syncing)
{
synpat_T *spp;
@@ -3425,9 +3402,9 @@ static void syn_cmd_off(exarg_T *eap, int syncing)
static void syn_cmd_onoff(exarg_T *eap, char *name)
FUNC_ATTR_NONNULL_ALL
{
- did_syntax_onoff = true;
eap->nextcmd = check_nextcmd(eap->arg);
if (!eap->skip) {
+ did_syntax_onoff = true;
char buf[100];
memcpy(buf, "so ", 4);
vim_snprintf(buf + 3, sizeof(buf) - 3, SYNTAX_FNAME, name);
@@ -3497,8 +3474,8 @@ syn_cmd_list(
/*
* No argument: List all group IDs and all syntax clusters.
*/
- for (int id = 1; id <= highlight_ga.ga_len && !got_int; ++id) {
- syn_list_one(id, syncing, FALSE);
+ for (int id = 1; id <= highlight_ga.ga_len && !got_int; id++) {
+ syn_list_one(id, syncing, false);
}
for (int id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; ++id) {
syn_list_cluster(id);
@@ -3517,10 +3494,11 @@ syn_cmd_list(
syn_list_cluster(id - SYNID_CLUSTER);
} else {
int id = syn_namen2id(arg, (int)(arg_end - arg));
- if (id == 0)
+ if (id == 0) {
EMSG2(_(e_nogroup), arg);
- else
- syn_list_one(id, syncing, TRUE);
+ } else {
+ syn_list_one(id, syncing, true);
+ }
}
arg = skipwhite(arg_end);
}
@@ -3564,14 +3542,12 @@ static int last_matchgroup;
*/
static void
syn_list_one(
- int id,
- int syncing, /* when TRUE: list syncing items */
- int link_only /* when TRUE; list link-only too */
+ const int id,
+ const bool syncing, // when true: list syncing items
+ const bool link_only // when true; list link-only too
)
{
- int attr;
- int did_header = FALSE;
- synpat_T *spp;
+ bool did_header = false;
static struct name_list namelist1[] =
{
{HL_DISPLAY, "display"},
@@ -3594,23 +3570,26 @@ syn_list_one(
{0, NULL}
};
- attr = HL_ATTR(HLF_D); // highlight like directories
+ const int attr = HL_ATTR(HLF_D); // highlight like directories
- /* list the keywords for "id" */
+ // list the keywords for "id"
if (!syncing) {
- did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab, FALSE, attr);
+ did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab, false, attr);
did_header = syn_list_keywords(id, &curwin->w_s->b_keywtab_ic,
- did_header, attr);
+ did_header, attr);
}
- /* list the patterns for "id" */
- for (int idx = 0; idx < curwin->w_s->b_syn_patterns.ga_len && !got_int; ++idx) {
- spp = &(SYN_ITEMS(curwin->w_s)[idx]);
- if (spp->sp_syn.id != id || spp->sp_syncing != syncing)
+ // list the patterns for "id"
+ for (int idx = 0;
+ idx < curwin->w_s->b_syn_patterns.ga_len && !got_int;
+ idx++) {
+ const synpat_T *const spp = &(SYN_ITEMS(curwin->w_s)[idx]);
+ if (spp->sp_syn.id != id || spp->sp_syncing != syncing) {
continue;
+ }
(void)syn_list_header(did_header, 999, id);
- did_header = TRUE;
+ did_header = true;
last_matchgroup = 0;
if (spp->sp_type == SPTYPE_MATCH) {
put_pattern("match", ' ', spp, attr);
@@ -3701,15 +3680,13 @@ static void syn_list_cluster(int id)
}
}
-static void put_id_list(const char *name,
- short *list, // NOLINT(runtime/int)
- int attr)
+static void put_id_list(const char *const name,
+ const int16_t *const list,
+ const int attr)
{
- short *p;
-
msg_puts_attr(name, attr);
msg_putchar('=');
- for (p = list; *p; ++p) {
+ for (const int16_t *p = list; *p; p++) {
if (*p >= SYNID_ALLBUT && *p < SYNID_TOP) {
if (p[1]) {
msg_puts("ALLBUT");
@@ -3721,7 +3698,7 @@ static void put_id_list(const char *name,
} else if (*p >= SYNID_CONTAINED && *p < SYNID_CLUSTER) {
msg_puts("CONTAINED");
} else if (*p >= SYNID_CLUSTER) {
- short scl_id = *p - SYNID_CLUSTER;
+ int scl_id = *p - SYNID_CLUSTER;
msg_putchar('@');
msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name);
@@ -3733,12 +3710,10 @@ static void put_id_list(const char *name,
msg_putchar(' ');
}
-static void put_pattern(char *s, int c, synpat_T *spp, int attr)
+static void put_pattern(const char *const s, const int c,
+ const synpat_T *const spp, const int attr)
{
- long n;
- int mask;
- int first;
- static char *sepchars = "/+=-#@\"|'^&";
+ static const char *const sepchars = "/+=-#@\"|'^&";
int i;
/* May have to write "matchgroup=group" */
@@ -3767,10 +3742,10 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
msg_outtrans(spp->sp_pattern);
msg_putchar(sepchars[i]);
- /* output any pattern options */
- first = TRUE;
- for (i = 0; i < SPO_COUNT; ++i) {
- mask = (1 << i);
+ // output any pattern options
+ bool first = true;
+ for (i = 0; i < SPO_COUNT; i++) {
+ const int mask = (1 << i);
if (!(spp->sp_off_flags & (mask + (mask << SPO_COUNT)))) {
continue;
}
@@ -3778,7 +3753,7 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
msg_putchar(','); // Separate with commas.
}
msg_puts(spo_name_tab[i]);
- n = spp->sp_offsets[i];
+ const long n = spp->sp_offsets[i];
if (i != SPO_LC_OFF) {
if (spp->sp_off_flags & mask)
msg_putchar('s');
@@ -3787,47 +3762,40 @@ static void put_pattern(char *s, int c, synpat_T *spp, int attr)
if (n > 0)
msg_putchar('+');
}
- if (n || i == SPO_LC_OFF)
+ if (n || i == SPO_LC_OFF) {
msg_outnum(n);
- first = FALSE;
+ }
+ first = false;
}
msg_putchar(' ');
}
-/*
- * List or clear the keywords for one syntax group.
- * Return TRUE if the header has been printed.
- */
-static int
-syn_list_keywords(
- int id,
- hashtab_T *ht,
- int did_header, /* header has already been printed */
- int attr
+// List or clear the keywords for one syntax group.
+// Return true if the header has been printed.
+static bool syn_list_keywords(
+ const int id,
+ const hashtab_T *const ht,
+ bool did_header, // header has already been printed
+ const int attr
)
{
int outlen;
- hashitem_T *hi;
- keyentry_T *kp;
- int todo;
int prev_contained = 0;
- short *prev_next_list = NULL;
- short *prev_cont_in_list = NULL;
+ const int16_t *prev_next_list = NULL;
+ const int16_t *prev_cont_in_list = NULL;
int prev_skipnl = 0;
int prev_skipwhite = 0;
int prev_skipempty = 0;
- /*
- * Unfortunately, this list of keywords is not sorted on alphabet but on
- * hash value...
- */
- todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0 && !got_int; ++hi) {
+ // Unfortunately, this list of keywords is not sorted on alphabet but on
+ // hash value...
+ size_t todo = ht->ht_used;
+ for (const hashitem_T *hi = ht->ht_array; todo > 0 && !got_int; hi++) {
if (HASHITEM_EMPTY(hi)) {
continue;
}
- --todo;
- for (kp = HI2KE(hi); kp != NULL && !got_int; kp = kp->ke_next) {
+ todo--;
+ for (keyentry_T *kp = HI2KE(hi); kp != NULL && !got_int; kp = kp->ke_next) {
if (kp->k_syn.id == id) {
if (prev_contained != (kp->flags & HL_CONTAINED)
|| prev_skipnl != (kp->flags & HL_SKIPNL)
@@ -3847,7 +3815,7 @@ syn_list_keywords(
prev_skipwhite = 0;
prev_skipempty = 0;
}
- did_header = TRUE;
+ did_header = true;
if (prev_contained != (kp->flags & HL_CONTAINED)) {
msg_puts_attr("contained", attr);
msg_putchar(' ');
@@ -3958,19 +3926,19 @@ static void clear_keywtab(hashtab_T *ht)
/// @param flags flags for this keyword
/// @param cont_in_list containedin for this keyword
/// @param next_list nextgroup for this keyword
-static void add_keyword(char_u *name,
- int id,
- int flags,
- short *cont_in_list,
- short *next_list,
- int conceal_char)
+static void add_keyword(char_u *const name,
+ const int id,
+ const int flags,
+ int16_t *const cont_in_list,
+ int16_t *const next_list,
+ const int conceal_char)
{
char_u name_folded[MAXKEYWLEN + 1];
- char_u *name_ic = (curwin->w_s->b_syn_ic)
- ? str_foldcase(name, (int)STRLEN(name), name_folded, sizeof(name_folded))
- : name;
+ const char_u *const name_ic = (curwin->w_s->b_syn_ic)
+ ? str_foldcase(name, (int)STRLEN(name), name_folded, sizeof(name_folded))
+ : name;
- keyentry_T *kp = xmalloc(sizeof(keyentry_T) + STRLEN(name_ic));
+ keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + STRLEN(name_ic));
STRCPY(kp->keyword, name_ic);
kp->k_syn.id = id;
kp->k_syn.inc_tag = current_syn_inc_tag;
@@ -3982,11 +3950,12 @@ static void add_keyword(char_u *name,
}
kp->next_list = copy_id_list(next_list);
- hash_T hash = hash_hash(kp->keyword);
- hashtab_T *ht = (curwin->w_s->b_syn_ic) ? &curwin->w_s->b_keywtab_ic
- : &curwin->w_s->b_keywtab;
- hashitem_T *hi = hash_lookup(ht, (const char *)kp->keyword,
- STRLEN(kp->keyword), hash);
+ const hash_T hash = hash_hash(kp->keyword);
+ hashtab_T *const ht = (curwin->w_s->b_syn_ic)
+ ? &curwin->w_s->b_keywtab_ic
+ : &curwin->w_s->b_keywtab;
+ hashitem_T *const hi = hash_lookup(ht, (const char *)kp->keyword,
+ STRLEN(kp->keyword), hash);
// even though it looks like only the kp->keyword member is
// being used here, vim uses some pointer trickery to get the orignal
@@ -4129,13 +4098,9 @@ get_syn_options(
return NULL;
}
} else if (flagtab[fidx].argtype == 11 && arg[5] == '=') {
- /* cchar=? */
- if (has_mbyte) {
- *conceal_char = mb_ptr2char(arg + 6);
- arg += mb_ptr2len(arg + 6) - 1;
- } else {
- *conceal_char = arg[6];
- }
+ // cchar=?
+ *conceal_char = utf_ptr2char(arg + 6);
+ arg += mb_ptr2len(arg + 6) - 1;
if (!vim_isprintc_strict(*conceal_char)) {
EMSG(_("E844: invalid cchar value"));
return NULL;
@@ -4197,8 +4162,8 @@ static void syn_incl_toplevel(int id, int *flagsp)
return;
*flagsp |= HL_CONTAINED;
if (curwin->w_s->b_syn_topgrp >= SYNID_CLUSTER) {
- /* We have to alloc this, because syn_combine_list() will free it. */
- short *grp_list = xmalloc(2 * sizeof(short));
+ // We have to alloc this, because syn_combine_list() will free it.
+ int16_t *grp_list = xmalloc(2 * sizeof(*grp_list));
int tlg_id = curwin->w_s->b_syn_topgrp - SYNID_CLUSTER;
grp_list[0] = id;
@@ -4413,9 +4378,9 @@ syn_cmd_match(
/* Get options before the pattern */
syn_opt_arg.flags = 0;
- syn_opt_arg.keyword = FALSE;
+ syn_opt_arg.keyword = false;
syn_opt_arg.sync_idx = syncing ? &sync_idx : NULL;
- syn_opt_arg.has_cont_list = TRUE;
+ syn_opt_arg.has_cont_list = true;
syn_opt_arg.cont_list = NULL;
syn_opt_arg.cont_in_list = NULL;
syn_opt_arg.next_list = NULL;
@@ -4535,9 +4500,9 @@ syn_cmd_region(
init_syn_patterns();
syn_opt_arg.flags = 0;
- syn_opt_arg.keyword = FALSE;
+ syn_opt_arg.keyword = false;
syn_opt_arg.sync_idx = NULL;
- syn_opt_arg.has_cont_list = TRUE;
+ syn_opt_arg.has_cont_list = true;
syn_opt_arg.cont_list = NULL;
syn_opt_arg.cont_in_list = NULL;
syn_opt_arg.next_list = NULL;
@@ -4715,30 +4680,25 @@ syn_cmd_region(
}
}
-/*
- * A simple syntax group ID comparison function suitable for use in qsort()
- */
-static int syn_compare_stub(const void *v1, const void *v2)
+// A simple syntax group ID comparison function suitable for use in qsort()
+static int syn_compare_stub(const void *const v1, const void *const v2)
{
- const short *s1 = v1;
- const short *s2 = v2;
+ const int16_t *const s1 = v1;
+ const int16_t *const s2 = v2;
return *s1 > *s2 ? 1 : *s1 < *s2 ? -1 : 0;
}
-/*
- * Combines lists of syntax clusters.
- * *clstr1 and *clstr2 must both be allocated memory; they will be consumed.
- */
-static void syn_combine_list(short **clstr1, short **clstr2, int list_op)
+// Combines lists of syntax clusters.
+// *clstr1 and *clstr2 must both be allocated memory; they will be consumed.
+static void syn_combine_list(int16_t **const clstr1, int16_t **const clstr2,
+ const int list_op)
{
- int count1 = 0;
- int count2 = 0;
- short *g1;
- short *g2;
- short *clstr = NULL;
- int count;
- int round;
+ size_t count1 = 0;
+ size_t count2 = 0;
+ const int16_t *g1;
+ const int16_t *g2;
+ int16_t *clstr = NULL;
/*
* Handle degenerate cases.
@@ -4755,27 +4715,25 @@ static void syn_combine_list(short **clstr1, short **clstr2, int list_op)
return;
}
- for (g1 = *clstr1; *g1; g1++)
- ++count1;
- for (g2 = *clstr2; *g2; g2++)
- ++count2;
+ for (g1 = *clstr1; *g1; g1++) {
+ count1++;
+ }
+ for (g2 = *clstr2; *g2; g2++) {
+ count2++;
+ }
- /*
- * For speed purposes, sort both lists.
- */
- qsort(*clstr1, (size_t)count1, sizeof(short), syn_compare_stub);
- qsort(*clstr2, (size_t)count2, sizeof(short), syn_compare_stub);
+ // For speed purposes, sort both lists.
+ qsort(*clstr1, count1, sizeof(**clstr1), syn_compare_stub);
+ qsort(*clstr2, count2, sizeof(**clstr2), syn_compare_stub);
- /*
- * We proceed in two passes; in round 1, we count the elements to place
- * in the new list, and in round 2, we allocate and populate the new
- * list. For speed, we use a mergesort-like method, adding the smaller
- * of the current elements in each list to the new list.
- */
- for (round = 1; round <= 2; round++) {
+ // We proceed in two passes; in round 1, we count the elements to place
+ // in the new list, and in round 2, we allocate and populate the new
+ // list. For speed, we use a mergesort-like method, adding the smaller
+ // of the current elements in each list to the new list.
+ for (int round = 1; round <= 2; round++) {
g1 = *clstr1;
g2 = *clstr2;
- count = 0;
+ int count = 0;
/*
* First, loop through the lists until one of them is empty.
@@ -4827,7 +4785,7 @@ static void syn_combine_list(short **clstr1, short **clstr2, int list_op)
clstr = NULL;
break;
}
- clstr = xmalloc((count + 1) * sizeof(short));
+ clstr = xmalloc((count + 1) * sizeof(*clstr));
clstr[count] = 0;
}
}
@@ -4932,9 +4890,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
char_u *arg = eap->arg;
char_u *group_name_end;
char_u *rest;
- int scl_id;
- short *clstr_list;
- int got_clstr = FALSE;
+ bool got_clstr = false;
int opt_len;
int list_op;
@@ -4945,9 +4901,10 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
rest = get_group_name(arg, &group_name_end);
if (rest != NULL) {
- scl_id = syn_check_cluster(arg, (int)(group_name_end - arg));
- if (scl_id == 0)
+ int scl_id = syn_check_cluster(arg, (int)(group_name_end - arg));
+ if (scl_id == 0) {
return;
+ }
scl_id -= SYNID_CLUSTER;
for (;; ) {
@@ -4966,7 +4923,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
} else
break;
- clstr_list = NULL;
+ int16_t *clstr_list = NULL;
if (get_id_list(&rest, opt_len, &clstr_list, eap->skip) == FAIL) {
EMSG2(_(e_invarg2), rest);
break;
@@ -5224,35 +5181,28 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
*/
static int
get_id_list(
- char_u **arg,
- int keylen, // length of keyword
- int16_t **list, // where to store the resulting list, if not
- // NULL, the list is silently skipped!
- int skip
+ char_u **const arg,
+ const int keylen, // length of keyword
+ int16_t **const list, // where to store the resulting list, if not
+ // NULL, the list is silently skipped!
+ const bool skip
)
{
char_u *p = NULL;
char_u *end;
- int round;
- int count;
int total_count = 0;
- short *retval = NULL;
- char_u *name;
+ int16_t *retval = NULL;
regmatch_T regmatch;
int id;
- int failed = FALSE;
-
- /*
- * We parse the list twice:
- * round == 1: count the number of items, allocate the array.
- * round == 2: fill the array with the items.
- * In round 1 new groups may be added, causing the number of items to
- * grow when a regexp is used. In that case round 1 is done once again.
- */
- for (round = 1; round <= 2; ++round) {
- /*
- * skip "contains"
- */
+ bool failed = false;
+
+ // We parse the list twice:
+ // round == 1: count the number of items, allocate the array.
+ // round == 2: fill the array with the items.
+ // In round 1 new groups may be added, causing the number of items to
+ // grow when a regexp is used. In that case round 1 is done once again.
+ for (int round = 1; round <= 2; round++) {
+ // skip "contains"
p = skipwhite(*arg + keylen);
if (*p != '=') {
EMSG2(_("E405: Missing equal sign: %s"), *arg);
@@ -5264,14 +5214,12 @@ get_id_list(
break;
}
- /*
- * parse the arguments after "contains"
- */
- count = 0;
+ // parse the arguments after "contains"
+ int count = 0;
do {
- for (end = p; *end && !ascii_iswhite(*end) && *end != ','; ++end)
- ;
- name = xmalloc((int)(end - p + 3)); /* leave room for "^$" */
+ for (end = p; *end && !ascii_iswhite(*end) && *end != ','; end++) {
+ }
+ char_u *const name = xmalloc((int)(end - p + 3)); // leave room for "^$"
STRLCPY(name + 1, p, end - p + 1);
if ( STRCMP(name + 1, "ALLBUT") == 0
|| STRCMP(name + 1, "ALL") == 0
@@ -5279,7 +5227,7 @@ get_id_list(
|| STRCMP(name + 1, "CONTAINED") == 0) {
if (TOUPPER_ASC(**arg) != 'C') {
EMSG2(_("E407: %s not allowed here"), name + 1);
- failed = TRUE;
+ failed = true;
xfree(name);
break;
}
@@ -5315,7 +5263,7 @@ get_id_list(
STRCAT(name, "$");
regmatch.regprog = vim_regcomp(name, RE_MAGIC);
if (regmatch.regprog == NULL) {
- failed = TRUE;
+ failed = true;
xfree(name);
break;
}
@@ -5346,7 +5294,7 @@ get_id_list(
xfree(name);
if (id == 0) {
EMSG2(_("E409: Unknown group name: %s"), p);
- failed = TRUE;
+ failed = true;
break;
}
if (id > 0) {
@@ -5369,8 +5317,8 @@ get_id_list(
if (failed)
break;
if (round == 1) {
- retval = xmalloc((count + 1) * sizeof(short));
- retval[count] = 0; /* zero means end of the list */
+ retval = xmalloc((count + 1) * sizeof(*retval));
+ retval[count] = 0; // zero means end of the list
total_count = count;
}
}
@@ -5392,20 +5340,18 @@ get_id_list(
/*
* Make a copy of an ID list.
*/
-static short *copy_id_list(short *list)
+static int16_t *copy_id_list(const int16_t *const list)
{
- int len;
- int count;
- short *retval;
-
- if (list == NULL)
+ if (list == NULL) {
return NULL;
+ }
- for (count = 0; list[count]; ++count)
- ;
- len = (count + 1) * sizeof(short);
- retval = xmalloc(len);
- memmove(retval, list, (size_t)len);
+ int count;
+ for (count = 0; list[count]; count++) {
+ }
+ const size_t len = (count + 1) * sizeof(int16_t);
+ int16_t *const retval = xmalloc(len);
+ memmove(retval, list, len);
return retval;
}
@@ -6380,17 +6326,101 @@ int load_colors(char_u *name)
recursive = true;
size_t buflen = STRLEN(name) + 12;
buf = xmalloc(buflen);
+ apply_autocmds(EVENT_COLORSCHEMEPRE, name, curbuf->b_fname, false, curbuf);
snprintf((char *)buf, buflen, "colors/%s.vim", name);
retval = source_runtime(buf, DIP_START + DIP_OPT);
xfree(buf);
apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, FALSE, curbuf);
recursive = false;
- ui_refresh();
return retval;
}
+static char *(color_names[28]) = {
+ "Black", "DarkBlue", "DarkGreen", "DarkCyan",
+ "DarkRed", "DarkMagenta", "Brown", "DarkYellow",
+ "Gray", "Grey", "LightGray", "LightGrey",
+ "DarkGray", "DarkGrey",
+ "Blue", "LightBlue", "Green", "LightGreen",
+ "Cyan", "LightCyan", "Red", "LightRed", "Magenta",
+ "LightMagenta", "Yellow", "LightYellow", "White", "NONE" };
+ // indices:
+ // 0, 1, 2, 3,
+ // 4, 5, 6, 7,
+ // 8, 9, 10, 11,
+ // 12, 13,
+ // 14, 15, 16, 17,
+ // 18, 19, 20, 21, 22,
+ // 23, 24, 25, 26, 27
+static int color_numbers_16[28] = { 0, 1, 2, 3,
+ 4, 5, 6, 6,
+ 7, 7, 7, 7,
+ 8, 8,
+ 9, 9, 10, 10,
+ 11, 11, 12, 12, 13,
+ 13, 14, 14, 15, -1 };
+// for xterm with 88 colors...
+static int color_numbers_88[28] = { 0, 4, 2, 6,
+ 1, 5, 32, 72,
+ 84, 84, 7, 7,
+ 82, 82,
+ 12, 43, 10, 61,
+ 14, 63, 9, 74, 13,
+ 75, 11, 78, 15, -1 };
+// for xterm with 256 colors...
+static int color_numbers_256[28] = { 0, 4, 2, 6,
+ 1, 5, 130, 130,
+ 248, 248, 7, 7,
+ 242, 242,
+ 12, 81, 10, 121,
+ 14, 159, 9, 224, 13,
+ 225, 11, 229, 15, -1 };
+// for terminals with less than 16 colors...
+static int color_numbers_8[28] = { 0, 4, 2, 6,
+ 1, 5, 3, 3,
+ 7, 7, 7, 7,
+ 0+8, 0+8,
+ 4+8, 4+8, 2+8, 2+8,
+ 6+8, 6+8, 1+8, 1+8, 5+8,
+ 5+8, 3+8, 3+8, 7+8, -1 };
+
+// Lookup the "cterm" value to be used for color with index "idx" in
+// color_names[].
+// "boldp" will be set to TRUE or FALSE for a foreground color when using 8
+// colors, otherwise it will be unchanged.
+int lookup_color(const int idx, const bool foreground, TriState *const boldp)
+{
+ int color = color_numbers_16[idx];
+
+ // Use the _16 table to check if it's a valid color name.
+ if (color < 0) {
+ return -1;
+ }
+
+ if (t_colors == 8) {
+ // t_Co is 8: use the 8 colors table
+ color = color_numbers_8[idx];
+ if (foreground) {
+ // set/reset bold attribute to get light foreground
+ // colors (on some terminals, e.g. "linux")
+ if (color & 8) {
+ *boldp = kTrue;
+ } else {
+ *boldp = kFalse;
+ }
+ }
+ color &= 7; // truncate to 8 colors
+ } else if (t_colors == 16) {
+ color = color_numbers_8[idx];
+ } else if (t_colors == 88) {
+ color = color_numbers_88[idx];
+ } else if (t_colors >= 256) {
+ color = color_numbers_256[idx];
+ }
+ return color;
+}
+
/// Handle ":highlight" command
///
@@ -6414,12 +6444,14 @@ void do_highlight(const char *line, const bool forceit, const bool init)
int attr;
int id;
int idx;
- int dodefault = FALSE;
- int doclear = FALSE;
- int dolink = FALSE;
- int error = FALSE;
+ struct hl_group item_before;
+ bool dodefault = false;
+ bool doclear = false;
+ bool dolink = false;
+ bool error = false;
int color;
bool is_normal_group = false; // "Normal" group
+ bool did_highlight_changed = false;
// If no argument, list current highlighting.
if (ends_excmd((uint8_t)(*line))) {
@@ -6502,19 +6534,22 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (sourcing_name == NULL && !dodefault) {
EMSG(_("E414: group has settings, highlight link ignored"));
}
- } else {
- if (!init)
+ } else if (HL_TABLE()[from_id - 1].sg_link != to_id
+ || HL_TABLE()[from_id - 1].sg_scriptID != current_SID
+ || HL_TABLE()[from_id - 1].sg_cleared) {
+ if (!init) {
HL_TABLE()[from_id - 1].sg_set |= SG_LINK;
+ }
HL_TABLE()[from_id - 1].sg_link = to_id;
HL_TABLE()[from_id - 1].sg_scriptID = current_SID;
HL_TABLE()[from_id - 1].sg_cleared = false;
redraw_all_later(SOME_VALID);
+
+ // Only call highlight changed() once after multiple changes
+ need_highlight_changed = true;
}
}
- // Only call highlight_changed() once, after sourcing a syntax file.
- need_highlight_changed = true;
-
return;
}
@@ -6531,7 +6566,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
init_highlight(true, true);
highlight_changed();
- redraw_later_clear();
+ redraw_all_later(NOT_VALID);
return;
}
name_end = (const char *)skiptowhite((const char_u *)line);
@@ -6550,13 +6585,16 @@ void do_highlight(const char *line, const bool forceit, const bool init)
return;
}
+ // Make a copy so we can check if any attribute actually changed
+ item_before = HL_TABLE()[idx];
is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0);
// Clear the highlighting for ":hi clear {group}" and ":hi clear".
if (doclear || (forceit && init)) {
highlight_clear(idx);
- if (!doclear)
+ if (!doclear) {
HL_TABLE()[idx].sg_set = 0;
+ }
}
char *key = NULL;
@@ -6657,7 +6695,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
HL_TABLE()[idx].sg_set |= SG_CTERM;
}
HL_TABLE()[idx].sg_cterm = attr;
- HL_TABLE()[idx].sg_cterm_bold = FALSE;
+ HL_TABLE()[idx].sg_cterm_bold = false;
}
} else if (*key == 'G') {
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
@@ -6679,7 +6717,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
* 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;
+ HL_TABLE()[idx].sg_cterm_bold = false;
}
if (ascii_isdigit(*arg)) {
@@ -6701,60 +6739,6 @@ void do_highlight(const char *line, const bool forceit, const bool init)
break;
}
} else {
- static const char *color_names[] = {
- "Black", "DarkBlue", "DarkGreen", "DarkCyan",
- "DarkRed", "DarkMagenta", "Brown", "DarkYellow",
- "Gray", "Grey",
- "LightGray", "LightGrey", "DarkGray", "DarkGrey",
- "Blue", "LightBlue", "Green", "LightGreen",
- "Cyan", "LightCyan", "Red", "LightRed", "Magenta",
- "LightMagenta", "Yellow", "LightYellow", "White",
- "NONE"
- };
- static const int color_numbers_16[] = {
- 0, 1, 2, 3,
- 4, 5, 6, 6,
- 7, 7,
- 7, 7, 8, 8,
- 9, 9, 10, 10,
- 11, 11, 12, 12, 13,
- 13, 14, 14, 15,
- -1
- };
- // For xterm with 88 colors:
- static int color_numbers_88[] = {
- 0, 4, 2, 6,
- 1, 5, 32, 72,
- 84, 84,
- 7, 7, 82, 82,
- 12, 43, 10, 61,
- 14, 63, 9, 74, 13,
- 75, 11, 78, 15,
- -1
- };
- // For xterm with 256 colors:
- static int color_numbers_256[] = {
- 0, 4, 2, 6,
- 1, 5, 130, 130,
- 248, 248,
- 7, 7, 242, 242,
- 12, 81, 10, 121,
- 14, 159, 9, 224, 13,
- 225, 11, 229, 15,
- -1
- };
- // For terminals with less than 16 colors:
- static int color_numbers_8[28] = {
- 0, 4, 2, 6,
- 1, 5, 3, 3,
- 7, 7,
- 7, 7, 0+8, 0+8,
- 4+8, 4+8, 2+8, 2+8,
- 6+8, 6+8, 1+8, 1+8, 5+8,
- 5+8, 3+8, 3+8, 7+8,
- -1
- };
-
// Reduce calls to STRICMP a bit, it can be slow.
off = TOUPPER_ASC(*arg);
for (i = ARRAY_SIZE(color_names); --i >= 0; ) {
@@ -6770,32 +6754,16 @@ void do_highlight(const char *line, const bool forceit, const bool init)
break;
}
- // Use the _16 table to check if it's a valid color name.
- color = color_numbers_16[i];
- if (color >= 0) {
- if (t_colors == 8) {
- // t_Co is 8: use the 8 colors table.
- color = color_numbers_8[i];
- if (key[5] == 'F') {
- /* set/reset bold attribute to get light foreground
- * colors (on some terminals, e.g. "linux") */
- if (color & 8) {
- HL_TABLE()[idx].sg_cterm |= HL_BOLD;
- HL_TABLE()[idx].sg_cterm_bold = true;
- } else {
- HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
- }
- }
- color &= 7; // truncate to 8 colors
- } else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) {
- if (t_colors == 88) {
- color = color_numbers_88[i];
- } else if (t_colors >= 256) {
- color = color_numbers_256[i];
- } else {
- color = color_numbers_8[i];
- }
- }
+ TriState bold = kNone;
+ 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 == kTrue) {
+ HL_TABLE()[idx].sg_cterm |= HL_BOLD;
+ HL_TABLE()[idx].sg_cterm_bold = true;
+ } else if (bold == kFalse) {
+ HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
}
}
// Add one to the argument, to avoid zero. Zero is used for
@@ -6804,14 +6772,12 @@ void do_highlight(const char *line, const bool forceit, const bool init)
HL_TABLE()[idx].sg_cterm_fg = color + 1;
if (is_normal_group) {
cterm_normal_fg_color = color + 1;
- must_redraw = CLEAR;
}
} else {
HL_TABLE()[idx].sg_cterm_bg = color + 1;
if (is_normal_group) {
cterm_normal_bg_color = color + 1;
if (!ui_rgb_attached()) {
- must_redraw = CLEAR;
if (color >= 0) {
int dark = -1;
@@ -6836,8 +6802,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
} else if (strcmp(key, "GUIFG") == 0) {
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init)
+ if (!init) {
HL_TABLE()[idx].sg_set |= SG_GUI;
+ }
xfree(HL_TABLE()[idx].sg_rgb_fg_name);
if (strcmp(arg, "NONE")) {
@@ -6854,8 +6821,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
} else if (STRCMP(key, "GUIBG") == 0) {
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init)
+ if (!init) {
HL_TABLE()[idx].sg_set |= SG_GUI;
+ }
xfree(HL_TABLE()[idx].sg_rgb_bg_name);
if (STRCMP(arg, "NONE") != 0) {
@@ -6872,8 +6840,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
} else if (strcmp(key, "GUISP") == 0) {
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init)
+ if (!init) {
HL_TABLE()[idx].sg_set |= SG_GUI;
+ }
xfree(HL_TABLE()[idx].sg_rgb_sp_name);
if (strcmp(arg, "NONE") != 0) {
@@ -6915,19 +6884,33 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// Need to update all groups, because they might be using "bg" and/or
// "fg", which have been changed now.
highlight_attr_set_all();
- // If the normal group has changed, it is simpler to refresh every UI
- ui_refresh();
+
+ if (!ui_is_external(kUILinegrid) && starting == 0) {
+ // Older UIs assume that we clear the screen after normal group is
+ // changed
+ ui_refresh();
+ } else {
+ // TUI and newer UIs will repaint the screen themselves. NOT_VALID
+ // redraw below will still handle usages of guibg=fg etc.
+ ui_default_colors_set();
+ }
+ did_highlight_changed = true;
+ redraw_all_later(NOT_VALID);
} else {
set_hl_attr(idx);
}
HL_TABLE()[idx].sg_scriptID = current_SID;
- redraw_all_later(NOT_VALID);
}
xfree(key);
xfree(arg);
- // Only call highlight_changed() once, after sourcing a syntax file
- need_highlight_changed = true;
+ // Only call highlight_changed() once, after a sequence of highlight
+ // commands, and only if an attribute actually changed
+ if (memcmp(&HL_TABLE()[idx], &item_before, sizeof(item_before)) != 0
+ && !did_highlight_changed) {
+ redraw_all_later(NOT_VALID);
+ need_highlight_changed = true;
+ }
}
#if defined(EXITFREE)
@@ -6980,7 +6963,7 @@ static void highlight_clear(int idx)
HL_TABLE()[idx].sg_attr = 0;
HL_TABLE()[idx].sg_cterm = 0;
- HL_TABLE()[idx].sg_cterm_bold = FALSE;
+ HL_TABLE()[idx].sg_cterm_bold = false;
HL_TABLE()[idx].sg_cterm_fg = 0;
HL_TABLE()[idx].sg_cterm_bg = 0;
HL_TABLE()[idx].sg_gui = 0;
@@ -7001,161 +6984,6 @@ static void highlight_clear(int idx)
}
-/// Table with the specifications for an attribute number.
-/// Note that this table is used by ALL buffers. This is required because the
-/// GUI can redraw at any time for any buffer.
-static garray_T attr_table = GA_EMPTY_INIT_VALUE;
-
-static inline HlAttrs * ATTR_ENTRY(int idx)
-{
- return &((HlAttrs *)attr_table.ga_data)[idx];
-}
-
-
-/// Return the attr number for a set of colors and font.
-/// Add a new entry to the term_attr_table, attr_table or gui_attr_table
-/// if the combination is new.
-/// @return 0 for error.
-int get_attr_entry(HlAttrs *aep)
-{
- garray_T *table = &attr_table;
- HlAttrs *taep;
- static int recursive = false;
-
- /*
- * Init the table, in case it wasn't done yet.
- */
- table->ga_itemsize = sizeof(HlAttrs);
- ga_set_growsize(table, 7);
-
- // Try to find an entry with the same specifications.
- for (int i = 0; i < table->ga_len; i++) {
- taep = &(((HlAttrs *)table->ga_data)[i]);
- if (aep->cterm_ae_attr == taep->cterm_ae_attr
- && aep->cterm_fg_color == taep->cterm_fg_color
- && aep->cterm_bg_color == taep->cterm_bg_color
- && aep->rgb_ae_attr == taep->rgb_ae_attr
- && aep->rgb_fg_color == taep->rgb_fg_color
- && aep->rgb_bg_color == taep->rgb_bg_color
- && aep->rgb_sp_color == taep->rgb_sp_color) {
- return i + ATTR_OFF;
- }
- }
-
- if (table->ga_len + ATTR_OFF > MAX_TYPENR) {
- /*
- * Running out of attribute entries! remove all attributes, and
- * compute new ones for all groups.
- * When called recursively, we are really out of numbers.
- */
- if (recursive) {
- EMSG(_("E424: Too many different highlighting attributes in use"));
- return 0;
- }
- recursive = TRUE;
-
- clear_hl_tables();
-
- must_redraw = CLEAR;
-
- for (int i = 0; i < highlight_ga.ga_len; ++i) {
- set_hl_attr(i);
- }
-
- recursive = FALSE;
- }
-
-
- // This is a new combination of colors and font, add an entry.
- taep = GA_APPEND_VIA_PTR(HlAttrs, table);
- memset(taep, 0, sizeof(*taep));
- taep->cterm_ae_attr = aep->cterm_ae_attr;
- taep->cterm_fg_color = aep->cterm_fg_color;
- taep->cterm_bg_color = aep->cterm_bg_color;
- taep->rgb_ae_attr = aep->rgb_ae_attr;
- taep->rgb_fg_color = aep->rgb_fg_color;
- taep->rgb_bg_color = aep->rgb_bg_color;
- taep->rgb_sp_color = aep->rgb_sp_color;
-
- return table->ga_len - 1 + ATTR_OFF;
-}
-
-// Clear all highlight tables.
-void clear_hl_tables(void)
-{
- ga_clear(&attr_table);
-}
-
-// Combine special attributes (e.g., for spelling) with other attributes
-// (e.g., for syntax highlighting).
-// "prim_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(int char_attr, int prim_attr)
-{
- HlAttrs *char_aep = NULL;
- HlAttrs *spell_aep;
- HlAttrs new_en = HLATTRS_INIT;
-
- if (char_attr == 0) {
- return prim_attr;
- }
-
- if (prim_attr == 0) {
- return char_attr;
- }
-
- // Find the entry for char_attr
- char_aep = syn_cterm_attr2entry(char_attr);
-
- if (char_aep != NULL) {
- // Copy all attributes from char_aep to the new entry
- new_en = *char_aep;
- }
-
- spell_aep = syn_cterm_attr2entry(prim_attr);
- if (spell_aep != NULL) {
- new_en.cterm_ae_attr |= spell_aep->cterm_ae_attr;
- new_en.rgb_ae_attr |= spell_aep->rgb_ae_attr;
-
- if (spell_aep->cterm_fg_color > 0) {
- new_en.cterm_fg_color = spell_aep->cterm_fg_color;
- }
-
- if (spell_aep->cterm_bg_color > 0) {
- new_en.cterm_bg_color = spell_aep->cterm_bg_color;
- }
-
- if (spell_aep->rgb_fg_color >= 0) {
- new_en.rgb_fg_color = spell_aep->rgb_fg_color;
- }
-
- if (spell_aep->rgb_bg_color >= 0) {
- new_en.rgb_bg_color = spell_aep->rgb_bg_color;
- }
-
- if (spell_aep->rgb_sp_color >= 0) {
- new_en.rgb_sp_color = spell_aep->rgb_sp_color;
- }
- }
- return get_attr_entry(&new_en);
-}
-
-/// \note this function does not apply exclusively to cterm attr contrary
-/// to what its name implies
-/// \warn don't call it with attr 0 (i.e., the null attribute)
-HlAttrs *syn_cterm_attr2entry(int attr)
-{
- attr -= ATTR_OFF;
- if (attr >= attr_table.ga_len) {
- // did ":syntax clear"
- return NULL;
- }
- return ATTR_ENTRY(attr);
-}
-
/// \addtogroup LIST_XXX
/// @{
#define LIST_ATTR 1
@@ -7163,12 +6991,10 @@ HlAttrs *syn_cterm_attr2entry(int attr)
#define LIST_INT 3
/// @}
-static void highlight_list_one(int id)
+static void highlight_list_one(const int id)
{
- struct hl_group *sgp;
- int didh = FALSE;
-
- sgp = &HL_TABLE()[id - 1]; /* index is ID minus one */
+ struct hl_group *const sgp = &HL_TABLE()[id - 1]; // index is ID minus one
+ bool didh = false;
didh = highlight_list_arg(id, didh, LIST_ATTR,
sgp->sg_cterm, NULL, "cterm");
@@ -7205,24 +7031,24 @@ static void highlight_list_one(int id)
/// @param type one of \ref LIST_XXX
/// @param iarg integer argument used if \p type == LIST_INT
/// @param sarg string used if \p type == LIST_STRING
-static int highlight_list_arg(int id, int didh, int type, int iarg,
- char_u *sarg, const char *name)
+static bool highlight_list_arg(
+ const int id, bool didh, const int type, int iarg,
+ char_u *const sarg, const char *const name)
{
char_u buf[100];
- char_u *ts;
- int i;
- if (got_int)
- return FALSE;
+ if (got_int) {
+ return false;
+ }
if (type == LIST_STRING ? (sarg != NULL) : (iarg != 0)) {
- ts = buf;
- if (type == LIST_INT)
- sprintf((char *)buf, "%d", iarg - 1);
- else if (type == LIST_STRING)
+ char_u *ts = buf;
+ if (type == LIST_INT) {
+ snprintf((char *)buf, sizeof(buf), "%d", iarg - 1);
+ } else if (type == LIST_STRING) {
ts = sarg;
- else { /* type == LIST_ATTR */
+ } else { // type == LIST_ATTR
buf[0] = NUL;
- for (i = 0; hl_attr_table[i] != 0; ++i) {
+ for (int i = 0; hl_attr_table[i] != 0; i++) {
if (iarg & hl_attr_table[i]) {
if (buf[0] != NUL)
xstrlcat((char *)buf, ",", 100);
@@ -7232,9 +7058,8 @@ static int highlight_list_arg(int id, int didh, int type, int iarg,
}
}
- (void)syn_list_header(didh,
- (int)(vim_strsize(ts) + STRLEN(name) + 1), id);
- didh = TRUE;
+ (void)syn_list_header(didh, (int)(vim_strsize(ts) + STRLEN(name) + 1), id);
+ didh = true;
if (!got_int) {
if (*name != NUL) {
MSG_PUTS_ATTR(name, HL_ATTR(HLF_D));
@@ -7352,11 +7177,11 @@ const char *highlight_color(const int id, const char *const what,
/// @param outlen length of string that comes
/// @param id highlight group id
/// @return true when started a new line.
-static int
-syn_list_header(int did_header, int outlen, int id)
+static bool syn_list_header(const bool did_header, const int outlen,
+ const int id)
{
int endcol = 19;
- int newline = TRUE;
+ bool newline = true;
if (!did_header) {
msg_putchar('\n');
@@ -7367,11 +7192,13 @@ syn_list_header(int did_header, int outlen, int id)
endcol = 15;
} else if (msg_col + outlen + 1 >= Columns) {
msg_putchar('\n');
- if (got_int)
- return TRUE;
+ if (got_int) {
+ return true;
+ }
} else {
- if (msg_col >= endcol) /* wrap around is like starting a new line */
- newline = FALSE;
+ if (msg_col >= endcol) { // wrap around is like starting a new line
+ newline = false;
+ }
}
if (msg_col >= endcol) /* output at least one space */
@@ -7398,7 +7225,6 @@ static void set_hl_attr(int idx)
HlAttrs at_en = HLATTRS_INIT;
struct hl_group *sgp = HL_TABLE() + idx;
-
at_en.cterm_ae_attr = sgp->sg_cterm;
at_en.cterm_fg_color = sgp->sg_cterm_fg;
at_en.cterm_bg_color = sgp->sg_cterm_bg;
@@ -7410,14 +7236,11 @@ static void set_hl_attr(int idx)
at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1;
- if (at_en.cterm_fg_color != 0 || at_en.cterm_bg_color != 0
- || at_en.rgb_fg_color != -1 || at_en.rgb_bg_color != -1
- || at_en.rgb_sp_color != -1 || at_en.cterm_ae_attr != 0
- || at_en.rgb_ae_attr != 0) {
- sgp->sg_attr = get_attr_entry(&at_en);
- } else {
- // If all the fields are cleared, clear the attr field back to default value
- sgp->sg_attr = 0;
+ sgp->sg_attr = hl_get_syn_attr(idx+1, at_en);
+
+ // a cursor style uses this syn_id, make sure its atribute is updated.
+ if (cursor_mode_uses_syn_id(idx+1)) {
+ ui_mode_info_set();
}
}
@@ -7553,7 +7376,7 @@ static void syn_unadd_group(void)
/// Translate a group ID to highlight attributes.
-/// @see syn_cterm_attr2entry
+/// @see syn_attr2entry
int syn_id2attr(int hl_id)
{
struct hl_group *sgp;
@@ -7590,7 +7413,7 @@ int syn_get_final_id(int hl_id)
}
/// Refresh the color attributes of all highlight groups.
-static void highlight_attr_set_all(void)
+void highlight_attr_set_all(void)
{
for (int idx = 0; idx < highlight_ga.ga_len; idx++) {
struct hl_group *sgp = &HL_TABLE()[idx];
@@ -7613,7 +7436,6 @@ static void highlight_attr_set_all(void)
/// screen redraw after any :highlight command.
void highlight_changed(void)
{
- int attr;
int id;
char_u userhl[10];
int id_SNC = -1;
@@ -7628,13 +7450,15 @@ void highlight_changed(void)
if (id == 0) {
abort();
}
- attr = syn_id2attr(id);
+ int final_id = syn_get_final_id(id);
if (hlf == (int)HLF_SNC) {
- id_SNC = syn_get_final_id(id);
+ id_SNC = final_id;
} else if (hlf == (int)HLF_S) {
- id_S = syn_get_final_id(id);
+ id_S = final_id;
}
- highlight_attr[hlf] = attr;
+
+ highlight_attr[hlf] = hl_get_ui_attr(hlf, final_id,
+ hlf == (int)HLF_INACTIVE);
}
/* Setup the user highlights
@@ -8522,26 +8346,6 @@ RgbValue name_to_color(const char_u *name)
return -1;
}
-/// Gets highlight description for id `attr_id` as a map.
-Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Error *err)
-{
- HlAttrs *aep = NULL;
- Dictionary dic = ARRAY_DICT_INIT;
-
- if (attr_id == 0) {
- return dic;
- }
-
- aep = syn_cterm_attr2entry((int)attr_id);
- if (!aep) {
- api_set_error(err, kErrorTypeException,
- "Invalid attribute id: %" PRId64, attr_id);
- return dic;
- }
-
- return hlattrs2dict(aep, rgb);
-}
-
/**************************************
* End of Highlighting stuff *