syntax: Refactor to store all term and gui attributes independently

Now the attrentry_T structure will store all attributes in separate fields for
cterm and rgb UIs.
This commit is contained in:
Thiago de Arruda 2015-02-13 12:06:08 -03:00
parent 9a2dd7c498
commit d8f3458ec7
8 changed files with 192 additions and 425 deletions

View File

@ -14418,7 +14418,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv)
if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_UNKNOWN) {
mode = get_tv_string_buf(&argvars[2], modebuf); mode = get_tv_string_buf(&argvars[2], modebuf);
modec = TOLOWER_ASC(mode[0]); modec = TOLOWER_ASC(mode[0]);
if (modec != 't' && modec != 'c' && modec != 'g') if (modec != 'c' && modec != 'g')
modec = 0; /* replace invalid with current */ modec = 0; /* replace invalid with current */
} else { } else {
modec = 'c'; modec = 'c';

View File

@ -617,10 +617,7 @@ void ex_hardcopy(exarg_T *eap)
eap->forceit) == FAIL) eap->forceit) == FAIL)
return; return;
if (t_colors > 1) settings.modec = 'c';
settings.modec = 'c';
else
settings.modec = 't';
if (!syntax_present(curwin)) if (!syntax_present(curwin))
settings.do_syntax = FALSE; settings.do_syntax = FALSE;

View File

@ -4359,23 +4359,6 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl
if (char_cells == 2) if (char_cells == 2)
ScreenLines[off_to + 1] = ScreenLines[off_from + 1]; ScreenLines[off_to + 1] = ScreenLines[off_from + 1];
#if defined(FEAT_GUI) || defined(UNIX)
/* The bold trick makes a single column of pixels appear in the
* next character. When a bold character is removed, the next
* character should be redrawn too. This happens for our own GUI
* and for some xterms. */
if (
# ifdef UNIX
term_is_xterm
# endif
) {
hl = ScreenAttrs[off_to];
if (hl > HL_ALL)
hl = syn_attr2attr(hl);
if (hl & HL_BOLD)
redraw_next = TRUE;
}
#endif
ScreenAttrs[off_to] = ScreenAttrs[off_from]; ScreenAttrs[off_to] = ScreenAttrs[off_from];
/* For simplicity set the attributes of second half of a /* For simplicity set the attributes of second half of a
* double-wide character equal to the first half. */ * double-wide character equal to the first half. */
@ -5343,24 +5326,6 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
if (need_redraw if (need_redraw
|| force_redraw_this || force_redraw_this
) { ) {
#if defined(FEAT_GUI) || defined(UNIX)
/* The bold trick makes a single row of pixels appear in the next
* character. When a bold character is removed, the next
* character should be redrawn too. This happens for our own GUI
* and for some xterms. */
if (need_redraw && ScreenLines[off] != ' ' && (
# ifdef UNIX
term_is_xterm
# endif
)) {
int n = ScreenAttrs[off];
if (n > HL_ALL)
n = syn_attr2attr(n);
if (n & HL_BOLD)
force_redraw_next = TRUE;
}
#endif
/* When at the end of the text and overwriting a two-cell /* When at the end of the text and overwriting a two-cell
* character with a one-cell character, need to clear the next * character with a one-cell character, need to clear the next
* cell. Also when overwriting the left halve of a two-cell char * cell. Also when overwriting the left halve of a two-cell char
@ -5977,24 +5942,6 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
|| force_next || force_next
#endif #endif
) { ) {
#if defined(FEAT_GUI) || defined(UNIX)
/* The bold trick may make a single row of pixels appear in
* the next character. When a bold character is removed, the
* next character should be redrawn too. This happens for our
* own GUI and for some xterms. */
if (
# ifdef UNIX
term_is_xterm
# endif
) {
if (ScreenLines[off] != ' '
&& (ScreenAttrs[off] > HL_ALL
|| ScreenAttrs[off] & HL_BOLD))
force_next = TRUE;
else
force_next = FALSE;
}
#endif
ScreenLines[off] = c; ScreenLines[off] = c;
if (enc_utf8) { if (enc_utf8) {
if (c >= 0x80) { if (c >= 0x80) {

View File

@ -49,40 +49,32 @@
#include "nvim/os/os.h" #include "nvim/os/os.h"
#include "nvim/os/time.h" #include "nvim/os/time.h"
/* // Structure that stores information about a highlight group.
* Structure that stores information about a highlight group. // The ID of a highlight group is also called group ID. It is the index in
* The ID of a highlight group is also called group ID. It is the index in // the highlight_ga array PLUS ONE.
* the highlight_ga array PLUS ONE.
*/
struct hl_group { struct hl_group {
char_u *sg_name; /* highlight group name */ char_u *sg_name; // highlight group name
char_u *sg_name_u; /* uppercase of sg_name */ char_u *sg_name_u; // uppercase of sg_name
/* for normal terminals */ int sg_attr; // Screen attr
int sg_term; /* "term=" highlighting attributes */ int sg_link; // link to this highlight group ID
char_u *sg_start; /* terminal string for start highl */ int sg_set; // combination of SG_* flags
char_u *sg_stop; /* terminal string for stop highl */ scid_T sg_scriptID; // script in which the group was last set
int sg_term_attr; /* Screen attr for term mode */ // for terminal UIs
/* for color terminals */ int sg_cterm; // "cterm=" highlighting attr
int sg_cterm; /* "cterm=" highlighting attr */ int sg_cterm_fg; // terminal fg color number + 1
int sg_cterm_bold; /* bold attr was set for light color */ int sg_cterm_bg; // terminal bg color number + 1
int sg_cterm_fg; /* terminal fg color number + 1 */ int sg_cterm_bold; // bold attr was set for light color
int sg_cterm_bg; /* terminal bg color number + 1 */ // for RGB UIs
int sg_cterm_attr; /* Screen attr for color term mode */ int sg_gui; // "gui=" highlighting attributes
/* Store the sp color name for the GUI or synIDattr() */
int sg_gui; /* "gui=" highlighting attributes */
RgbValue sg_rgb_fg; // RGB foreground color RgbValue sg_rgb_fg; // RGB foreground color
RgbValue sg_rgb_bg; // RGB background color RgbValue sg_rgb_bg; // RGB background color
uint8_t *sg_rgb_fg_name; // RGB foreground color name uint8_t *sg_rgb_fg_name; // RGB foreground color name
uint8_t *sg_rgb_bg_name; // RGB background color name uint8_t *sg_rgb_bg_name; // RGB background color name
int sg_link; /* link to this highlight group ID */
int sg_set; /* combination of SG_* flags */
scid_T sg_scriptID; /* script in which the group was last set */
}; };
#define SG_TERM 1 /* term has been set */ #define SG_CTERM 2 // cterm has been set
#define SG_CTERM 2 /* cterm has been set */ #define SG_GUI 4 // gui has been set
#define SG_GUI 4 /* gui has been set */ #define SG_LINK 8 // link has been set
#define SG_LINK 8 /* link has been set */
// highlight groups for 'highlight' option // highlight groups for 'highlight' option
static garray_T highlight_ga = GA_EMPTY_INIT_VALUE; static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
@ -221,7 +213,7 @@ struct name_list {
/* /*
* An attribute number is the index in attr_table plus ATTR_OFF. * An attribute number is the index in attr_table plus ATTR_OFF.
*/ */
#define ATTR_OFF (HL_ALL + 1) #define ATTR_OFF 1
static char *(spo_name_tab[SPO_COUNT]) = static char *(spo_name_tab[SPO_COUNT]) =
@ -6054,7 +6046,6 @@ do_highlight (
) )
{ {
char_u *name_end; char_u *name_end;
char_u *p;
char_u *linep; char_u *linep;
char_u *key_start; char_u *key_start;
char_u *arg_start; char_u *arg_start;
@ -6242,7 +6233,7 @@ do_highlight (
if (STRCMP(key, "NONE") == 0) { if (STRCMP(key, "NONE") == 0) {
if (!init || HL_TABLE()[idx].sg_set == 0) { if (!init || HL_TABLE()[idx].sg_set == 0) {
if (!init) if (!init)
HL_TABLE()[idx].sg_set |= SG_TERM+SG_CTERM+SG_GUI; HL_TABLE()[idx].sg_set |= SG_CTERM+SG_GUI;
highlight_clear(idx); highlight_clear(idx);
} }
continue; continue;
@ -6312,20 +6303,14 @@ do_highlight (
} }
if (error) if (error)
break; break;
if (*key == 'T') { if (*key == 'C') {
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)) {
if (!init) if (!init)
HL_TABLE()[idx].sg_set |= SG_CTERM; HL_TABLE()[idx].sg_set |= SG_CTERM;
HL_TABLE()[idx].sg_cterm = attr; HL_TABLE()[idx].sg_cterm = attr;
HL_TABLE()[idx].sg_cterm_bold = FALSE; HL_TABLE()[idx].sg_cterm_bold = FALSE;
} }
} else { } else if (*key == 'G') {
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init) if (!init)
HL_TABLE()[idx].sg_set |= SG_GUI; HL_TABLE()[idx].sg_set |= SG_GUI;
@ -6438,15 +6423,6 @@ do_highlight (
} }
color &= 7; /* truncate to 8 colors */ color &= 7; /* truncate to 8 colors */
} else if (t_colors == 16 || t_colors == 88 || t_colors == 256) { } 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.
*/
if (*T_CAF != NUL)
p = T_CAF;
else
p = T_CSF;
switch (t_colors) { switch (t_colors) {
case 16: case 16:
color = color_numbers_8[i]; color = color_numbers_8[i];
@ -6531,73 +6507,9 @@ do_highlight (
normal_bg = HL_TABLE()[idx].sg_rgb_bg; normal_bg = HL_TABLE()[idx].sg_rgb_bg;
} }
} else if (STRCMP(key, "GUISP") == 0) { } else if (STRCMP(key, "GUISP") == 0) {
// Ignored // Ignored for now
} else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0) { } else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0) {
char_u buf[100]; // Ignored for now
char_u *tname;
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);
/* lookup the escape sequence for the item */
p = get_term_code(tname);
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) {
EMSG2(_("E422: terminal code too long: %s"), arg);
error = TRUE;
break;
}
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 = (int)trans_special(&p, buf + off, FALSE);
if (len > 0) /* recognized special char */
off += len;
else /* copy as normal char */
buf[off++] = *p++;
}
buf[off] = NUL;
}
if (error)
break;
if (STRCMP(buf, "NONE") == 0) /* resetting the value */
p = NULL;
else
p = vim_strsave(buf);
if (key[2] == 'A') {
free(HL_TABLE()[idx].sg_start);
HL_TABLE()[idx].sg_start = p;
} else {
free(HL_TABLE()[idx].sg_stop);
HL_TABLE()[idx].sg_stop = p;
}
} else { } else {
EMSG2(_("E423: Illegal argument: %s"), key_start); EMSG2(_("E423: Illegal argument: %s"), key_start);
error = TRUE; error = TRUE;
@ -6623,8 +6535,7 @@ do_highlight (
syn_unadd_group(); syn_unadd_group();
else { else {
if (is_normal_group) { if (is_normal_group) {
HL_TABLE()[idx].sg_term_attr = 0; HL_TABLE()[idx].sg_attr = 0;
HL_TABLE()[idx].sg_cterm_attr = 0;
// If the normal group has changed, it is simpler to refresh every UI // If the normal group has changed, it is simpler to refresh every UI
ui_refresh(); ui_refresh();
} else } else
@ -6671,10 +6582,11 @@ void restore_cterm_colors(void)
*/ */
static int hl_has_settings(int idx, int check_link) static int hl_has_settings(int idx, int check_link)
{ {
return HL_TABLE()[idx].sg_term_attr != 0 return HL_TABLE()[idx].sg_attr != 0
|| HL_TABLE()[idx].sg_cterm_attr != 0
|| HL_TABLE()[idx].sg_cterm_fg != 0 || HL_TABLE()[idx].sg_cterm_fg != 0
|| HL_TABLE()[idx].sg_cterm_bg != 0 || HL_TABLE()[idx].sg_cterm_bg != 0
|| HL_TABLE()[idx].sg_rgb_fg_name != NULL
|| HL_TABLE()[idx].sg_rgb_bg_name != NULL
|| (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)); || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK));
} }
@ -6683,17 +6595,11 @@ static int hl_has_settings(int idx, int check_link)
*/ */
static void highlight_clear(int idx) static void highlight_clear(int idx)
{ {
HL_TABLE()[idx].sg_term = 0; HL_TABLE()[idx].sg_attr = 0;
free(HL_TABLE()[idx].sg_start);
HL_TABLE()[idx].sg_start = NULL;
free(HL_TABLE()[idx].sg_stop);
HL_TABLE()[idx].sg_stop = NULL;
HL_TABLE()[idx].sg_term_attr = 0;
HL_TABLE()[idx].sg_cterm = 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_fg = 0;
HL_TABLE()[idx].sg_cterm_bg = 0; HL_TABLE()[idx].sg_cterm_bg = 0;
HL_TABLE()[idx].sg_cterm_attr = 0;
HL_TABLE()[idx].sg_gui = 0; HL_TABLE()[idx].sg_gui = 0;
HL_TABLE()[idx].sg_rgb_fg = -1; HL_TABLE()[idx].sg_rgb_fg = -1;
HL_TABLE()[idx].sg_rgb_bg = -1; HL_TABLE()[idx].sg_rgb_bg = -1;
@ -6713,23 +6619,20 @@ static void highlight_clear(int idx)
* Note that this table is used by ALL buffers. This is required because the * Note that this table is used by ALL buffers. This is required because the
* GUI can redraw at any time for any buffer. * GUI can redraw at any time for any buffer.
*/ */
static garray_T term_attr_table = GA_EMPTY_INIT_VALUE; static garray_T attr_table = GA_EMPTY_INIT_VALUE;
#define TERM_ATTR_ENTRY(idx) ((attrentry_T *)term_attr_table.ga_data)[idx] #define ATTR_ENTRY(idx) ((attrentry_T *)attr_table.ga_data)[idx]
static garray_T cterm_attr_table = GA_EMPTY_INIT_VALUE;
#define CTERM_ATTR_ENTRY(idx) ((attrentry_T *)cterm_attr_table.ga_data)[idx]
/* /*
* Return the attr number for a set of colors and font. * Return the attr number for a set of colors and font.
* Add a new entry to the term_attr_table, cterm_attr_table or gui_attr_table * Add a new entry to the term_attr_table, attr_table or gui_attr_table
* if the combination is new. * if the combination is new.
* Return 0 for error. * Return 0 for error.
*/ */
static int get_attr_entry(garray_T *table, attrentry_T *aep) static int get_attr_entry(attrentry_T *aep)
{ {
garray_T *table = &attr_table;
attrentry_T *taep; attrentry_T *taep;
static int recursive = FALSE; static int recursive = FALSE;
@ -6744,31 +6647,14 @@ static int get_attr_entry(garray_T *table, attrentry_T *aep)
*/ */
for (int i = 0; i < table->ga_len; ++i) { for (int i = 0; i < table->ga_len; ++i) {
taep = &(((attrentry_T *)table->ga_data)[i]); taep = &(((attrentry_T *)table->ga_data)[i]);
if ( aep->ae_attr == taep->ae_attr if (aep->cterm_ae_attr == taep->cterm_ae_attr
&& ( && aep->cterm_fg_color == taep->cterm_fg_color
(table == &term_attr_table && aep->cterm_bg_color == taep->cterm_bg_color
&& (aep->ae_u.term.start == NULL) && aep->rgb_ae_attr == taep->rgb_ae_attr
== (taep->ae_u.term.start == NULL) && aep->rgb_fg_color == taep->rgb_fg_color
&& (aep->ae_u.term.start == NULL && aep->rgb_bg_color == taep->rgb_bg_color) {
|| STRCMP(aep->ae_u.term.start,
taep->ae_u.term.start) == 0)
&& (aep->ae_u.term.stop == NULL)
== (taep->ae_u.term.stop == NULL)
&& (aep->ae_u.term.stop == NULL
|| STRCMP(aep->ae_u.term.stop,
taep->ae_u.term.stop) == 0))
|| (table == &cterm_attr_table
&& aep->ae_u.cterm.fg_color
== taep->ae_u.cterm.fg_color
&& aep->ae_u.cterm.bg_color
== taep->ae_u.cterm.bg_color
&& aep->fg_color
== taep->fg_color
&& aep->bg_color
== taep->bg_color)
))
return i + ATTR_OFF; return i + ATTR_OFF;
}
} }
if (table->ga_len + ATTR_OFF > MAX_TYPENR) { if (table->ga_len + ATTR_OFF > MAX_TYPENR) {
@ -6794,115 +6680,83 @@ static int get_attr_entry(garray_T *table, attrentry_T *aep)
recursive = FALSE; recursive = FALSE;
} }
/*
* This is a new combination of colors and font, add an entry. // This is a new combination of colors and font, add an entry.
*/
taep = GA_APPEND_VIA_PTR(attrentry_T, table); taep = GA_APPEND_VIA_PTR(attrentry_T, table);
memset(taep, 0, sizeof(*taep)); memset(taep, 0, sizeof(*taep));
taep->ae_attr = aep->ae_attr; taep->cterm_ae_attr = aep->cterm_ae_attr;
if (table == &term_attr_table) { taep->cterm_fg_color = aep->cterm_fg_color;
if (aep->ae_u.term.start == NULL) taep->cterm_bg_color = aep->cterm_bg_color;
taep->ae_u.term.start = NULL; taep->rgb_ae_attr = aep->rgb_ae_attr;
else taep->rgb_fg_color = aep->rgb_fg_color;
taep->ae_u.term.start = vim_strsave(aep->ae_u.term.start); taep->rgb_bg_color = aep->rgb_bg_color;
if (aep->ae_u.term.stop == NULL)
taep->ae_u.term.stop = NULL;
else
taep->ae_u.term.stop = vim_strsave(aep->ae_u.term.stop);
} else if (table == &cterm_attr_table) {
taep->ae_u.cterm.fg_color = aep->ae_u.cterm.fg_color;
taep->ae_u.cterm.bg_color = aep->ae_u.cterm.bg_color;
taep->fg_color = aep->fg_color;
taep->bg_color = aep->bg_color;
}
return table->ga_len - 1 + ATTR_OFF; return table->ga_len - 1 + ATTR_OFF;
} }
/* // Clear all highlight tables.
* Clear all highlight tables.
*/
void clear_hl_tables(void) void clear_hl_tables(void)
{ {
attrentry_T *taep; ga_clear(&attr_table);
for (int i = 0; i < term_attr_table.ga_len; ++i) {
taep = &(((attrentry_T *)term_attr_table.ga_data)[i]);
free(taep->ae_u.term.start);
free(taep->ae_u.term.stop);
}
ga_clear(&term_attr_table);
ga_clear(&cterm_attr_table);
} }
/* // Combine special attributes (e.g., for spelling) with other attributes
* Combine special attributes (e.g., for spelling) with other attributes // (e.g., for syntax highlighting).
* (e.g., for syntax highlighting). // "prim_attr" overrules "char_attr".
* "prim_attr" overrules "char_attr". // This creates a new group when required.
* This creates a new group when required. // Since we expect there to be few spelling mistakes we don't cache the
* Since we expect there to be few spelling mistakes we don't cache the // result.
* result. // Return the resulting attributes.
* Return the resulting attributes.
*/
int hl_combine_attr(int char_attr, int prim_attr) int hl_combine_attr(int char_attr, int prim_attr)
{ {
attrentry_T *char_aep = NULL; attrentry_T *char_aep = NULL;
attrentry_T *spell_aep; attrentry_T *spell_aep;
attrentry_T new_en; attrentry_T new_en;
if (char_attr == 0) if (char_attr == 0) {
return prim_attr; return prim_attr;
if (char_attr <= HL_ALL && prim_attr <= HL_ALL)
return char_attr | prim_attr;
if (char_attr > HL_ALL)
char_aep = syn_cterm_attr2entry(char_attr);
if (char_aep != NULL)
new_en = *char_aep;
else {
memset(&new_en, 0, sizeof(new_en));
if (char_attr <= HL_ALL)
new_en.ae_attr = char_attr;
} }
if (prim_attr <= HL_ALL) // Find the entry for char_attr
new_en.ae_attr |= prim_attr; char_aep = syn_cterm_attr2entry(char_attr);
else {
spell_aep = syn_cterm_attr2entry(prim_attr); if (char_aep != NULL) {
if (spell_aep != NULL) { // Copy all attributes from char_aep to the new entry
new_en.ae_attr |= spell_aep->ae_attr; new_en = *char_aep;
if (spell_aep->ae_u.cterm.fg_color > 0) } else {
new_en.ae_u.cterm.fg_color = spell_aep->ae_u.cterm.fg_color; memset(&new_en, 0, sizeof(new_en));
if (spell_aep->ae_u.cterm.bg_color > 0) }
new_en.ae_u.cterm.bg_color = spell_aep->ae_u.cterm.bg_color;
if (spell_aep->fg_color >= 0) spell_aep = syn_cterm_attr2entry(prim_attr);
new_en.fg_color = spell_aep->fg_color; if (spell_aep != NULL) {
if (spell_aep->bg_color >= 0) new_en.cterm_ae_attr |= spell_aep->cterm_ae_attr;
new_en.bg_color = spell_aep->bg_color; 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;
} }
} }
return get_attr_entry(&cterm_attr_table, &new_en); return get_attr_entry(&new_en);
}
/*
* Get the highlight attributes (HL_BOLD etc.) from an attribute nr.
* Only to be used when "attr" > HL_ALL.
*/
int syn_attr2attr(int attr)
{
attrentry_T *aep = syn_cterm_attr2entry(attr);
if (aep == NULL) /* highlighting not set */
return 0;
return aep->ae_attr;
} }
attrentry_T *syn_cterm_attr2entry(int attr) attrentry_T *syn_cterm_attr2entry(int attr)
{ {
attr -= ATTR_OFF; attr -= ATTR_OFF;
if (attr >= cterm_attr_table.ga_len) /* did ":syntax clear" */ if (attr >= attr_table.ga_len) /* did ":syntax clear" */
return NULL; return NULL;
return &(CTERM_ATTR_ENTRY(attr)); return &(ATTR_ENTRY(attr));
} }
#define LIST_ATTR 1 #define LIST_ATTR 1
@ -6916,13 +6770,6 @@ static void highlight_list_one(int id)
sgp = &HL_TABLE()[id - 1]; /* index is ID minus one */ sgp = &HL_TABLE()[id - 1]; /* index is ID minus one */
didh = highlight_list_arg(id, didh, LIST_ATTR,
sgp->sg_term, NULL, "term");
didh = highlight_list_arg(id, didh, LIST_STRING,
0, sgp->sg_start, "start");
didh = highlight_list_arg(id, didh, LIST_STRING,
0, sgp->sg_stop, "stop");
didh = highlight_list_arg(id, didh, LIST_ATTR, didh = highlight_list_arg(id, didh, LIST_ATTR,
sgp->sg_cterm, NULL, "cterm"); sgp->sg_cterm, NULL, "cterm");
didh = highlight_list_arg(id, didh, LIST_INT, didh = highlight_list_arg(id, didh, LIST_INT,
@ -7001,7 +6848,7 @@ char_u *
highlight_has_attr ( highlight_has_attr (
int id, int id,
int flag, int flag,
int modec /* 'g' for GUI, 'c' for cterm, 't' for term */ int modec // 'g' for GUI, 'c' for cterm
) )
{ {
int attr; int attr;
@ -7009,12 +6856,11 @@ highlight_has_attr (
if (id <= 0 || id > highlight_ga.ga_len) if (id <= 0 || id > highlight_ga.ga_len)
return NULL; return NULL;
if (modec == 'g') if (modec == 'g') {
attr = HL_TABLE()[id - 1].sg_gui; attr = HL_TABLE()[id - 1].sg_gui;
else if (modec == 'c') } else {
attr = HL_TABLE()[id - 1].sg_cterm; attr = HL_TABLE()[id - 1].sg_cterm;
else }
attr = HL_TABLE()[id - 1].sg_term;
if (attr & flag) if (attr & flag)
return (char_u *)"1"; return (char_u *)"1";
@ -7131,37 +6977,16 @@ set_hl_attr (
if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0) if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0)
return; return;
/* at_en.cterm_ae_attr = sgp->sg_cterm;
* For the term mode: If there are other than "normal" highlighting at_en.cterm_fg_color = sgp->sg_cterm_fg;
* attributes, need to allocate an attr number. at_en.cterm_bg_color = sgp->sg_cterm_bg;
*/ at_en.rgb_ae_attr = sgp->sg_gui;
if (sgp->sg_start == NULL && sgp->sg_stop == NULL) // FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is
sgp->sg_term_attr = sgp->sg_term; // initialized with 0(by garray functions), check for sg_rgb_{f,b}g_name
else { // before setting attr_entry->{f,g}g_color to a other than -1
at_en.ae_attr = sgp->sg_term; at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1;
at_en.ae_u.term.start = sgp->sg_start; at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
at_en.ae_u.term.stop = sgp->sg_stop; sgp->sg_attr = get_attr_entry(&at_en);
sgp->sg_term_attr = get_attr_entry(&term_attr_table, &at_en);
}
/*
* For the color term mode: If there are other than "normal"
* highlighting attributes, need to allocate an attr number.
*/
if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0
&& sgp->sg_rgb_fg == -1 && sgp->sg_rgb_bg == -1) {
sgp->sg_cterm_attr = sgp->sg_cterm;
} else {
at_en.ae_attr = sgp->sg_gui;
at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
// FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is
// initialized with 0(by garray functions), check for sg_rgb_{f,b}g_name
// before setting attr_entry->{f,g}g_color to a other than -1
at_en.fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1;
at_en.bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
sgp->sg_cterm_attr = get_attr_entry(&cterm_attr_table, &at_en);
}
} }
/* /*
@ -7304,7 +7129,7 @@ int syn_id2attr(int hl_id)
hl_id = syn_get_final_id(hl_id); hl_id = syn_get_final_id(hl_id);
sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */ sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
return sgp->sg_cterm_attr; return sgp->sg_attr;
} }
@ -7391,11 +7216,12 @@ int highlight_changed(void)
* bold-underlined. * bold-underlined.
*/ */
attr = 0; attr = 0;
bool colon = false;
for (; *p && *p != ','; ++p) { /* parse upto comma */ for (; *p && *p != ','; ++p) { /* parse upto comma */
if (vim_iswhite(*p)) /* ignore white space */ if (vim_iswhite(*p)) /* ignore white space */
continue; continue;
if (attr > HL_ALL) /* Combination with ':' is not allowed. */ if (colon) /* Combination with ':' is not allowed. */
return FAIL; return FAIL;
switch (*p) { switch (*p) {
@ -7417,6 +7243,7 @@ int highlight_changed(void)
case ':': ++p; /* highlight group name */ case ':': ++p; /* highlight group name */
if (attr || *p == NUL) /* no combinations */ if (attr || *p == NUL) /* no combinations */
return FAIL; return FAIL;
colon = true;
end = vim_strchr(p, ','); end = vim_strchr(p, ',');
if (end == NULL) if (end == NULL)
end = p + STRLEN(p); end = p + STRLEN(p);
@ -7451,7 +7278,6 @@ int highlight_changed(void)
hlcnt = highlight_ga.ga_len; hlcnt = highlight_ga.ga_len;
if (id_S == 0) { /* Make sure id_S is always valid to simplify code below */ if (id_S == 0) { /* Make sure id_S is always valid to simplify code below */
memset(&HL_TABLE()[hlcnt + 9], 0, sizeof(struct hl_group)); memset(&HL_TABLE()[hlcnt + 9], 0, sizeof(struct hl_group));
HL_TABLE()[hlcnt + 9].sg_term = highlight_attr[HLF_S];
id_S = hlcnt + 10; id_S = hlcnt + 10;
} }
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
@ -7466,7 +7292,6 @@ int highlight_changed(void)
highlight_user[i] = syn_id2attr(id); highlight_user[i] = syn_id2attr(id);
if (id_SNC == 0) { if (id_SNC == 0) {
memset(&hlt[hlcnt + i], 0, sizeof(struct hl_group)); memset(&hlt[hlcnt + i], 0, sizeof(struct hl_group));
hlt[hlcnt + i].sg_term = highlight_attr[HLF_SNC];
hlt[hlcnt + i].sg_cterm = highlight_attr[HLF_SNC]; hlt[hlcnt + i].sg_cterm = highlight_attr[HLF_SNC];
hlt[hlcnt + i].sg_gui = highlight_attr[HLF_SNC]; hlt[hlcnt + i].sg_gui = highlight_attr[HLF_SNC];
} else } else
@ -7476,20 +7301,26 @@ int highlight_changed(void)
hlt[hlcnt + i].sg_link = 0; hlt[hlcnt + i].sg_link = 0;
/* Apply difference between UserX and HLF_S to HLF_SNC */ /* Apply difference between UserX and HLF_S to HLF_SNC */
hlt[hlcnt + i].sg_term ^= hlt[hlcnt + i].sg_cterm ^= hlt[id - 1].sg_cterm ^ hlt[id_S - 1].sg_cterm;
hlt[id - 1].sg_term ^ hlt[id_S - 1].sg_term;
if (hlt[id - 1].sg_start != hlt[id_S - 1].sg_start) if (hlt[id - 1].sg_cterm_fg != hlt[id_S - 1].sg_cterm_fg) {
hlt[hlcnt + i].sg_start = hlt[id - 1].sg_start;
if (hlt[id - 1].sg_stop != hlt[id_S - 1].sg_stop)
hlt[hlcnt + i].sg_stop = hlt[id - 1].sg_stop;
hlt[hlcnt + i].sg_cterm ^=
hlt[id - 1].sg_cterm ^ hlt[id_S - 1].sg_cterm;
if (hlt[id - 1].sg_cterm_fg != hlt[id_S - 1].sg_cterm_fg)
hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg; hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg;
if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg) }
if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg) {
hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg; hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg;
hlt[hlcnt + i].sg_gui ^= }
hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
hlt[hlcnt + i].sg_gui ^= hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
if (hlt[id - 1].sg_rgb_fg != hlt[id_S - 1].sg_rgb_fg) {
hlt[hlcnt + i].sg_rgb_fg = hlt[id - 1].sg_rgb_fg;
}
if (hlt[id - 1].sg_rgb_bg != hlt[id_S - 1].sg_rgb_bg) {
hlt[hlcnt + i].sg_rgb_bg = hlt[id - 1].sg_rgb_bg;
}
highlight_ga.ga_len = hlcnt + i + 1; highlight_ga.ga_len = hlcnt + i + 1;
set_hl_attr(hlcnt + i); /* At long last we can apply */ set_hl_attr(hlcnt + i); /* At long last we can apply */
highlight_stlnc[i] = syn_id2attr(hlcnt + i + 1); highlight_stlnc[i] = syn_id2attr(hlcnt + i + 1);

View File

@ -16,7 +16,6 @@
#define HL_UNDERLINE 0x08 #define HL_UNDERLINE 0x08
#define HL_UNDERCURL 0x10 #define HL_UNDERCURL 0x10
#define HL_STANDOUT 0x20 #define HL_STANDOUT 0x20
#define HL_ALL 0x3f
#define HL_CONTAINED 0x01 /* not used on toplevel */ #define HL_CONTAINED 0x01 /* not used on toplevel */
#define HL_TRANSP 0x02 /* has no highlighting */ #define HL_TRANSP 0x02 /* has no highlighting */

View File

@ -67,23 +67,11 @@ struct syn_state {
* may have made the state invalid */ * may have made the state invalid */
}; };
/* // Structure shared between syntax.c, screen.c
* Structure shared between syntax.c, screen.c and gui_x11.c.
*/
typedef struct attr_entry { typedef struct attr_entry {
short ae_attr; /* HL_BOLD, etc. */ short rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc.
RgbValue fg_color, bg_color; RgbValue rgb_fg_color, rgb_bg_color;
union { int cterm_fg_color, cterm_bg_color;
struct {
char_u *start; /* start escape sequence */
char_u *stop; /* stop escape sequence */
} term;
struct {
/* These colors need to be > 8 bits to hold 256. */
uint16_t fg_color; /* foreground color number */
uint16_t bg_color; /* background color number */
} cterm;
} ae_u;
} attrentry_T; } attrentry_T;
#endif // NVIM_SYNTAX_DEFS_H #endif // NVIM_SYNTAX_DEFS_H

View File

@ -60,7 +60,7 @@ static int row, col;
static struct { static struct {
int top, bot, left, right; int top, bot, left, right;
} sr; } sr;
static int current_highlight_mask = 0; static int current_attr_code = 0;
static bool cursor_enabled = true, pending_cursor_update = false; static bool cursor_enabled = true, pending_cursor_update = false;
static int height, width; static int height, width;
@ -273,71 +273,76 @@ void ui_detach(UI *ui)
} }
} }
static void highlight_start(int mask) static void highlight_start(int attr_code)
{ {
if (mask > HL_ALL) { current_attr_code = attr_code;
// attribute code
current_highlight_mask = mask;
} else {
// attribute mask
current_highlight_mask |= mask;
}
if (!ui_count) { if (!ui_count) {
return; return;
} }
set_highlight_args(current_highlight_mask); set_highlight_args(current_attr_code);
} }
static void highlight_stop(int mask) static void highlight_stop(int mask)
{ {
if (mask > HL_ALL) { current_attr_code = HL_NORMAL;
// attribute code
current_highlight_mask = HL_NORMAL; if (!ui_count) {
} else { return;
// attribute mask
current_highlight_mask &= ~mask;
} }
set_highlight_args(current_highlight_mask); set_highlight_args(current_attr_code);
} }
static void set_highlight_args(int mask) static void set_highlight_args(int attr_code)
{ {
HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 }; HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 };
attrentry_T *aep = NULL;
if (mask > HL_ALL) {
aep = syn_cterm_attr2entry(mask);
mask = aep ? aep->ae_attr : 0;
}
rgb_attrs.bold = mask & HL_BOLD;
rgb_attrs.underline = mask & HL_UNDERLINE;
rgb_attrs.undercurl = mask & HL_UNDERCURL;
rgb_attrs.italic = mask & HL_ITALIC;
rgb_attrs.reverse = mask & (HL_INVERSE | HL_STANDOUT);
HlAttrs cterm_attrs = rgb_attrs; HlAttrs cterm_attrs = rgb_attrs;
if (aep) { if (attr_code == HL_NORMAL) {
if (aep->fg_color != normal_fg) { goto end;
rgb_attrs.foreground = aep->fg_color;
}
if (aep->bg_color != normal_bg) {
rgb_attrs.background = aep->bg_color;
}
if (cterm_normal_fg_color != aep->ae_u.cterm.fg_color) {
cterm_attrs.foreground = aep->ae_u.cterm.fg_color - 1;
}
if (cterm_normal_bg_color != aep->ae_u.cterm.bg_color) {
cterm_attrs.background = aep->ae_u.cterm.bg_color - 1;
}
} }
int rgb_mask = 0;
int cterm_mask = 0;
attrentry_T *aep = syn_cterm_attr2entry(attr_code);
if (!aep) {
goto end;
}
rgb_mask = aep->rgb_ae_attr;
cterm_mask = aep->cterm_ae_attr;
rgb_attrs.bold = rgb_mask & HL_BOLD;
rgb_attrs.underline = rgb_mask & HL_UNDERLINE;
rgb_attrs.undercurl = rgb_mask & HL_UNDERCURL;
rgb_attrs.italic = rgb_mask & HL_ITALIC;
rgb_attrs.reverse = rgb_mask & (HL_INVERSE | HL_STANDOUT);
cterm_attrs.bold = cterm_mask & HL_BOLD;
cterm_attrs.underline = cterm_mask & HL_UNDERLINE;
cterm_attrs.undercurl = cterm_mask & HL_UNDERCURL;
cterm_attrs.italic = cterm_mask & HL_ITALIC;
cterm_attrs.reverse = cterm_mask & (HL_INVERSE | HL_STANDOUT);
if (aep->rgb_fg_color != normal_fg) {
rgb_attrs.foreground = aep->rgb_fg_color;
}
if (aep->rgb_bg_color != normal_bg) {
rgb_attrs.background = aep->rgb_bg_color;
}
if (cterm_normal_fg_color != aep->cterm_fg_color) {
cterm_attrs.foreground = aep->cterm_fg_color - 1;
}
if (cterm_normal_bg_color != aep->cterm_bg_color) {
cterm_attrs.background = aep->cterm_bg_color - 1;
}
end:
UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs)); UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs));
} }

View File

@ -15,9 +15,9 @@ describe(':highlight', function()
-- Test setting colors. -- Test setting colors.
-- Test clearing one color and all doesn't generate error or warning -- Test clearing one color and all doesn't generate error or warning
execute('hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan') execute('hi NewGroup cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan')
execute('hi Group2 term= cterm=') execute('hi Group2 cterm=')
execute('hi Group3 term=underline cterm=bold') execute('hi Group3 cterm=bold')
execute('redir! @a') execute('redir! @a')
execute('hi NewGroup') execute('hi NewGroup')
execute('hi Group2') execute('hi Group2')
@ -29,7 +29,7 @@ describe(':highlight', function()
execute('hi Group2') execute('hi Group2')
execute('hi clear') execute('hi clear')
execute('hi Group3') execute('hi Group3')
execute([[hi Crash term='asdf]]) execute([[hi Crash cterm='asdf]])
execute('redir END') execute('redir END')
-- Filter ctermfg and ctermbg, the numbers depend on the terminal -- Filter ctermfg and ctermbg, the numbers depend on the terminal
@ -48,11 +48,11 @@ describe(':highlight', function()
expect([[ expect([[
NewGroup xxx term=bold cterm=italic ctermfg=2 ctermbg=3 NewGroup xxx cterm=italic ctermfg=2 ctermbg=3
Group2 xxx cleared Group2 xxx cleared
Group3 xxx term=underline cterm=bold Group3 xxx cterm=bold
NewGroup xxx cleared NewGroup xxx cleared
@ -65,6 +65,6 @@ describe(':highlight', function()
Group3 xxx cleared Group3 xxx cleared
E475: term='asdf]]) E475: cterm='asdf]])
end) end)
end) end)