aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/ui.c3
-rw-r--r--src/nvim/api/ui_events.in.h11
-rw-r--r--src/nvim/ex_getln.c6
-rw-r--r--src/nvim/highlight_defs.h29
-rw-r--r--src/nvim/options.lua2
-rw-r--r--src/nvim/screen.c43
-rw-r--r--src/nvim/syntax.c47
-rw-r--r--src/nvim/syntax.h13
-rw-r--r--src/nvim/syntax_defs.h17
-rw-r--r--src/nvim/terminal.c2
-rw-r--r--src/nvim/tui/tui.c113
-rw-r--r--src/nvim/ugrid.c7
-rw-r--r--src/nvim/ugrid.h6
-rw-r--r--src/nvim/ui.c143
-rw-r--r--src/nvim/ui.h8
-rw-r--r--src/nvim/ui_bridge.c27
16 files changed, 190 insertions, 287 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 760c95eb5b..e53a45bd93 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -86,6 +86,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
ui->put = remote_ui_put;
ui->bell = remote_ui_bell;
ui->visual_bell = remote_ui_visual_bell;
+ ui->default_colors_set = remote_ui_default_colors_set;
ui->update_fg = remote_ui_update_fg;
ui->update_bg = remote_ui_update_bg;
ui->update_sp = remote_ui_update_sp;
@@ -243,7 +244,7 @@ static void push_call(UI *ui, char *name, Array args)
static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
{
Array args = ARRAY_DICT_INIT;
- Dictionary hl = hlattrs2dict(attrs);
+ Dictionary hl = hlattrs2dict(&attrs, ui->rgb);
ADD(args, DICTIONARY_OBJ(hl));
push_call(ui, "highlight_set", args);
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 3d2253e918..c599b0ce72 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -47,11 +47,14 @@ void visual_bell(void)
void flush(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL;
void update_fg(Integer fg)
- FUNC_API_SINCE(3);
+ FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
void update_bg(Integer bg)
- FUNC_API_SINCE(3);
+ FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
void update_sp(Integer sp)
- FUNC_API_SINCE(3);
+ FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
+void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
+ Integer cterm_fg, Integer cterm_bg)
+ FUNC_API_SINCE(4);
void suspend(void)
FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
void set_title(String title)
@@ -59,7 +62,7 @@ void set_title(String title)
void set_icon(String icon)
FUNC_API_SINCE(3);
void option_set(String name, Object value)
- FUNC_API_SINCE(4) FUNC_API_BRIDGE_IMPL;
+ FUNC_API_SINCE(4);
void popupmenu_show(Array items, Integer selected, Integer row, Integer col)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index ba51f18518..40b4cc6d79 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2929,11 +2929,11 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
Array item = ARRAY_DICT_INIT;
if (chunk.attr) {
- attrentry_T *aep = syn_cterm_attr2entry(chunk.attr);
+ HlAttrs *aep = syn_cterm_attr2entry(chunk.attr);
// TODO(bfredl): this desicion could be delayed by making attr_code a
// recognized type
- HlAttrs rgb_attrs = attrentry2hlattrs(aep, true);
- ADD(item, DICTIONARY_OBJ(hlattrs2dict(rgb_attrs)));
+ Dictionary rgb_attrs = hlattrs2dict(aep, true);
+ ADD(item, DICTIONARY_OBJ(rgb_attrs));
} else {
ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
}
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 927fc94bbe..08157935f5 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -7,6 +7,34 @@
typedef int32_t RgbValue;
+/// Highlighting attribute bits.
+typedef enum {
+ HL_INVERSE = 0x01,
+ HL_BOLD = 0x02,
+ HL_ITALIC = 0x04,
+ HL_UNDERLINE = 0x08,
+ HL_UNDERCURL = 0x10,
+ HL_STANDOUT = 0x20,
+} HlAttrFlags;
+
+/// Stores a complete highlighting entry, including colors and attributes
+/// for both TUI and GUI.
+typedef struct attr_entry {
+ int16_t rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc.
+ RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
+ int cterm_fg_color, cterm_bg_color;
+} HlAttrs;
+
+#define HLATTRS_INIT (HlAttrs) { \
+ .rgb_ae_attr = 0, \
+ .cterm_ae_attr = 0, \
+ .rgb_fg_color = -1, \
+ .rgb_bg_color = -1, \
+ .rgb_sp_color = -1, \
+ .cterm_fg_color = 0, \
+ .cterm_bg_color = 0, \
+}
+
/// Values for index in highlight_attr[].
/// When making changes, also update hlf_names below!
typedef enum {
@@ -117,7 +145,6 @@ EXTERN int highlight_attr[HLF_COUNT]; // Highl. attr for each context.
EXTERN int highlight_user[9]; // User[1-9] attributes
EXTERN int highlight_stlnc[9]; // On top of user
EXTERN int cterm_normal_fg_color INIT(= 0);
-EXTERN int cterm_normal_fg_bold INIT(= 0);
EXTERN int cterm_normal_bg_color INIT(= 0);
EXTERN RgbValue normal_fg INIT(= -1);
EXTERN RgbValue normal_bg INIT(= -1);
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index dac5c0ee16..6e8100594d 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2447,7 +2447,7 @@ return {
full_name='termguicolors', abbreviation='tgc',
type='bool', scope={'global'},
vi_def=false,
- redraw={'everything', 'ui_option'},
+ redraw={'ui_option'},
varname='p_tgc',
defaults={if_true={vi=false}}
},
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 8a29734025..122f760c51 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -139,11 +139,6 @@
* doesn't fit. */
#define W_ENDCOL(wp) (wp->w_wincol + wp->w_width)
-/*
- * The attributes that are actually active for writing to the screen.
- */
-static int screen_attr = 0;
-
static match_T search_hl; /* used for 'hlsearch' highlight matching */
static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
@@ -189,8 +184,6 @@ void redraw_win_later(win_T *wp, int type)
void redraw_later_clear(void)
{
redraw_all_later(CLEAR);
- /* Use attributes that is very unlikely to appear in text. */
- screen_attr = HL_BOLD | HL_UNDERLINE | HL_INVERSE;
}
/*
@@ -5847,30 +5840,16 @@ next_search_hl_pos(
return 0;
}
-static void screen_start_highlight(int attr)
-{
- screen_attr = attr;
- ui_start_highlight(attr);
-}
-
-static void screen_stop_highlight(void)
-{
- ui_stop_highlight();
- screen_attr = 0;
-}
-
/*
* Put character ScreenLines["off"] on the screen at position "row" and "col",
* using the attributes from ScreenAttrs["off"].
*/
static void screen_char(unsigned off, int row, int col)
{
- int attr;
-
- /* Check for illegal values, just in case (could happen just after
- * resizing). */
- if (row >= screen_Rows || col >= screen_Columns)
+ // Check for illegal values, just in case (could happen just after resizing).
+ if (row >= screen_Rows || col >= screen_Columns) {
return;
+ }
// Outputting the last character on the screen may scrollup the screen.
// Don't to it! Mark the character invalid (update it when scrolled up)
@@ -5882,17 +5861,8 @@ static void screen_char(unsigned off, int row, int col)
return;
}
- /*
- * Stop highlighting first, so it's easier to move the cursor.
- */
- attr = ScreenAttrs[off];
- if (screen_attr != attr)
- screen_stop_highlight();
-
ui_cursor_goto(row, col);
-
- if (screen_attr != attr)
- screen_start_highlight(attr);
+ ui_set_highlight(ScreenAttrs[off]);
if (enc_utf8 && ScreenLinesUC[off] != 0) {
char_u buf[MB_MAXBYTES + 1];
@@ -6001,7 +5971,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
++off;
if (off < end_off) { /* something to be cleared */
col = off - LineOffset[row];
- screen_stop_highlight();
+ ui_clear_highlight();
ui_cursor_goto(row, col); // clear rest of this screen line
ui_call_eol_clear();
col = end_col - col;
@@ -6383,8 +6353,7 @@ static void screenclear2(void)
return;
}
- screen_stop_highlight(); /* don't want highlighting here */
-
+ ui_clear_highlight(); // don't want highlighting here
/* blank out ScreenLines */
for (i = 0; i < Rows; ++i) {
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 40479e05dd..0a7f703461 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -64,7 +64,7 @@ struct hl_group {
int sg_cterm_bold; ///< bold attr was set for light color
// for RGB UIs
int sg_gui; ///< "gui=" highlighting attributes
- ///< (combination of \ref HL_ATTRIBUTES)
+ ///< (combination of \ref HlAttrFlags)
RgbValue sg_rgb_fg; ///< RGB foreground color
RgbValue sg_rgb_bg; ///< RGB background color
RgbValue sg_rgb_sp; ///< RGB special color
@@ -6796,7 +6796,6 @@ 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;
- cterm_normal_fg_bold = (HL_TABLE()[idx].sg_cterm & HL_BOLD);
must_redraw = CLEAR;
}
} else {
@@ -6940,7 +6939,6 @@ void restore_cterm_colors(void)
normal_bg = -1;
normal_sp = -1;
cterm_normal_fg_color = 0;
- cterm_normal_fg_bold = 0;
cterm_normal_bg_color = 0;
}
@@ -6994,9 +6992,9 @@ static void highlight_clear(int idx)
/// GUI can redraw at any time for any buffer.
static garray_T attr_table = GA_EMPTY_INIT_VALUE;
-static inline attrentry_T * ATTR_ENTRY(int idx)
+static inline HlAttrs * ATTR_ENTRY(int idx)
{
- return &((attrentry_T *)attr_table.ga_data)[idx];
+ return &((HlAttrs *)attr_table.ga_data)[idx];
}
@@ -7004,23 +7002,21 @@ static inline attrentry_T * ATTR_ENTRY(int idx)
/// 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(attrentry_T *aep)
+int get_attr_entry(HlAttrs *aep)
{
garray_T *table = &attr_table;
- attrentry_T *taep;
- static int recursive = FALSE;
+ HlAttrs *taep;
+ static int recursive = false;
/*
* Init the table, in case it wasn't done yet.
*/
- table->ga_itemsize = sizeof(attrentry_T);
+ 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 = &(((attrentry_T *)table->ga_data)[i]);
+ // 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
@@ -7057,7 +7053,7 @@ int get_attr_entry(attrentry_T *aep)
// 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(HlAttrs, table);
memset(taep, 0, sizeof(*taep));
taep->cterm_ae_attr = aep->cterm_ae_attr;
taep->cterm_fg_color = aep->cterm_fg_color;
@@ -7085,9 +7081,9 @@ void clear_hl_tables(void)
// Return the resulting attributes.
int hl_combine_attr(int char_attr, int prim_attr)
{
- attrentry_T *char_aep = NULL;
- attrentry_T *spell_aep;
- attrentry_T new_en = ATTRENTRY_INIT;
+ HlAttrs *char_aep = NULL;
+ HlAttrs *spell_aep;
+ HlAttrs new_en = HLATTRS_INIT;
if (char_attr == 0) {
return prim_attr;
@@ -7136,7 +7132,7 @@ int hl_combine_attr(int char_attr, int prim_attr)
/// \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)
-attrentry_T *syn_cterm_attr2entry(int attr)
+HlAttrs *syn_cterm_attr2entry(int attr)
{
attr -= ATTR_OFF;
if (attr >= attr_table.ga_len) {
@@ -7385,7 +7381,7 @@ syn_list_header(int did_header, int outlen, int id)
/// @param idx corrected highlight index
static void set_hl_attr(int idx)
{
- attrentry_T at_en = ATTRENTRY_INIT;
+ HlAttrs at_en = HLATTRS_INIT;
struct hl_group *sgp = HL_TABLE() + idx;
@@ -8509,24 +8505,21 @@ RgbValue name_to_color(const char_u *name)
/// Gets highlight description for id `attr_id` as a map.
Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Error *err)
{
- HlAttrs attrs = HLATTRS_INIT;
+ HlAttrs *aep = NULL;
Dictionary dic = ARRAY_DICT_INIT;
if (attr_id == 0) {
- goto end;
+ return dic;
}
- attrentry_T *aep = syn_cterm_attr2entry((int)attr_id);
+ aep = syn_cterm_attr2entry((int)attr_id);
if (!aep) {
api_set_error(err, kErrorTypeException,
"Invalid attribute id: %" PRId64, attr_id);
return dic;
}
- attrs = attrentry2hlattrs(aep, rgb);
-
-end:
- return hlattrs2dict(attrs);
+ return hlattrs2dict(aep, rgb);
}
diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h
index c9b0665ec8..f8282955a6 100644
--- a/src/nvim/syntax.h
+++ b/src/nvim/syntax.h
@@ -6,19 +6,6 @@
#include "nvim/buffer_defs.h"
#include "nvim/ex_cmds_defs.h"
-/// Terminal highlighting attribute bits.
-/// Attributes above HL_ALL are used for syntax highlighting.
-/// \addtogroup HL_ATTRIBUTES
-/// @{
-#define HL_NORMAL 0x00
-#define HL_INVERSE 0x01
-#define HL_BOLD 0x02
-#define HL_ITALIC 0x04
-#define HL_UNDERLINE 0x08
-#define HL_UNDERCURL 0x10
-#define HL_STANDOUT 0x20
-/// @}
-
#define HL_CONTAINED 0x01 /* not used on toplevel */
#define HL_TRANSP 0x02 /* has no highlighting */
#define HL_ONELINE 0x04 /* match within one line only */
diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h
index 7260853703..63089a62af 100644
--- a/src/nvim/syntax_defs.h
+++ b/src/nvim/syntax_defs.h
@@ -68,21 +68,4 @@ struct syn_state {
* may have made the state invalid */
};
-// Structure shared between syntax.c, screen.c
-typedef struct attr_entry {
- int16_t rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc.
- RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
- int cterm_fg_color, cterm_bg_color;
-} attrentry_T;
-
-#define ATTRENTRY_INIT { \
- .rgb_ae_attr = 0, \
- .cterm_ae_attr = 0, \
- .rgb_fg_color = -1, \
- .rgb_bg_color = -1, \
- .rgb_sp_color = -1, \
- .cterm_fg_color = 0, \
- .cterm_bg_color = 0, \
-}
-
#endif // NVIM_SYNTAX_DEFS_H
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 137855469f..f3eb6883ce 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -585,7 +585,7 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr,
int attr_id = 0;
if (hl_attrs || vt_fg != -1 || vt_bg != -1) {
- attr_id = get_attr_entry(&(attrentry_T) {
+ attr_id = get_attr_entry(&(HlAttrs) {
.cterm_ae_attr = (int16_t)hl_attrs,
.cterm_fg_color = vt_fg_idx,
.cterm_bg_color = vt_bg_idx,
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 70e19e1d93..62bdc61a68 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -125,7 +125,6 @@ UI *tui_start(void)
{
UI *ui = xcalloc(1, sizeof(UI)); // Freed by ui_bridge_stop().
ui->stop = tui_stop;
- ui->rgb = p_tgc;
ui->resize = tui_resize;
ui->clear = tui_clear;
ui->eol_clear = tui_eol_clear;
@@ -143,15 +142,12 @@ UI *tui_start(void)
ui->put = tui_put;
ui->bell = tui_bell;
ui->visual_bell = tui_visual_bell;
- ui->update_fg = tui_update_fg;
- ui->update_bg = tui_update_bg;
- ui->update_sp = tui_update_sp;
+ ui->default_colors_set = tui_default_colors_set;
ui->flush = tui_flush;
ui->suspend = tui_suspend;
ui->set_title = tui_set_title;
ui->set_icon = tui_set_icon;
ui->option_set= tui_option_set;
- ui->event = tui_event;
memset(ui->ui_ext, 0, sizeof(ui->ui_ext));
@@ -410,36 +406,58 @@ static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
ui_schedule_refresh();
}
-static bool attrs_differ(HlAttrs a1, HlAttrs a2)
+static bool attrs_differ(HlAttrs a1, HlAttrs a2, bool rgb)
{
- return a1.foreground != a2.foreground || a1.background != a2.background
- || a1.bold != a2.bold || a1.italic != a2.italic
- || a1.undercurl != a2.undercurl || a1.underline != a2.underline
- || a1.reverse != a2.reverse;
+ if (rgb) {
+ // TODO(bfredl): when we start to support special color,
+ // rgb_sp_color must be added here
+ return a1.rgb_fg_color != a2.rgb_fg_color
+ || a1.rgb_bg_color != a2.rgb_bg_color
+ || a1.rgb_ae_attr != a2.rgb_ae_attr;
+ } else {
+ return a1.cterm_fg_color != a2.cterm_fg_color
+ || a1.cterm_bg_color != a2.cterm_bg_color
+ || a1.cterm_ae_attr != a2.cterm_ae_attr;
+ }
}
static void update_attrs(UI *ui, HlAttrs attrs)
{
TUIData *data = ui->data;
- if (!attrs_differ(attrs, data->print_attrs)) {
+ if (!attrs_differ(attrs, data->print_attrs, ui->rgb)) {
return;
}
data->print_attrs = attrs;
UGrid *grid = &data->grid;
- int fg = attrs.foreground != -1 ? attrs.foreground : grid->fg;
- int bg = attrs.background != -1 ? attrs.background : grid->bg;
+ int fg = ui->rgb ? attrs.rgb_fg_color : (attrs.cterm_fg_color - 1);
+ if (fg == -1) {
+ fg = ui->rgb ? grid->clear_attrs.rgb_fg_color
+ : (grid->clear_attrs.cterm_fg_color - 1);
+ }
+
+ int bg = ui->rgb ? attrs.rgb_bg_color : (attrs.cterm_bg_color - 1);
+ if (bg == -1) {
+ bg = ui->rgb ? grid->clear_attrs.rgb_bg_color
+ : (grid->clear_attrs.cterm_bg_color - 1);
+ }
+
+ int attr = ui->rgb ? attrs.rgb_ae_attr : attrs.cterm_ae_attr;
+ bool bold = attr & HL_BOLD;
+ bool italic = attr & HL_ITALIC;
+ bool reverse = attr & (HL_INVERSE | HL_STANDOUT);
+ bool underline = attr & (HL_UNDERLINE), undercurl = attr & (HL_UNDERCURL);
if (unibi_get_str(data->ut, unibi_set_attributes)) {
- if (attrs.bold || attrs.reverse || attrs.underline || attrs.undercurl) {
+ if (bold || reverse || underline || undercurl) {
UNIBI_SET_NUM_VAR(data->params[0], 0); // standout
- UNIBI_SET_NUM_VAR(data->params[1], attrs.underline || attrs.undercurl);
- UNIBI_SET_NUM_VAR(data->params[2], attrs.reverse);
+ UNIBI_SET_NUM_VAR(data->params[1], underline || undercurl);
+ UNIBI_SET_NUM_VAR(data->params[2], reverse);
UNIBI_SET_NUM_VAR(data->params[3], 0); // blink
UNIBI_SET_NUM_VAR(data->params[4], 0); // dim
- UNIBI_SET_NUM_VAR(data->params[5], attrs.bold);
+ UNIBI_SET_NUM_VAR(data->params[5], bold);
UNIBI_SET_NUM_VAR(data->params[6], 0); // blank
UNIBI_SET_NUM_VAR(data->params[7], 0); // protect
UNIBI_SET_NUM_VAR(data->params[8], 0); // alternate character set
@@ -451,17 +469,17 @@ static void update_attrs(UI *ui, HlAttrs attrs)
if (!data->default_attr) {
unibi_out(ui, unibi_exit_attribute_mode);
}
- if (attrs.bold) {
+ if (bold) {
unibi_out(ui, unibi_enter_bold_mode);
}
- if (attrs.underline || attrs.undercurl) {
+ if (underline || undercurl) {
unibi_out(ui, unibi_enter_underline_mode);
}
- if (attrs.reverse) {
+ if (reverse) {
unibi_out(ui, unibi_enter_reverse_mode);
}
}
- if (attrs.italic) {
+ if (italic) {
unibi_out(ui, unibi_enter_italics_mode);
}
if (ui->rgb) {
@@ -491,8 +509,7 @@ static void update_attrs(UI *ui, HlAttrs attrs)
}
data->default_attr = fg == -1 && bg == -1
- && !attrs.bold && !attrs.italic && !attrs.underline && !attrs.undercurl
- && !attrs.reverse;
+ && !bold && !italic && !underline && !undercurl && !reverse;
}
static void final_column_wrap(UI *ui)
@@ -534,7 +551,7 @@ static bool cheap_to_print(UI *ui, int row, int col, int next)
UCell *cell = grid->cells[row] + col;
while (next) {
next--;
- if (attrs_differ(cell->attrs, data->print_attrs)) {
+ if (attrs_differ(cell->attrs, data->print_attrs, ui->rgb)) {
if (data->default_attr) {
return false;
}
@@ -659,13 +676,12 @@ static void clear_region(UI *ui, int top, int bot, int left, int right)
int saved_col = grid->col;
bool cleared = false;
- if (grid->bg == -1 && right == ui->width -1) {
+ bool nobg = ui->rgb ? grid->clear_attrs.rgb_bg_color == -1
+ : grid->clear_attrs.cterm_bg_color == 0;
+ if (nobg && right == ui->width -1) {
// Background is set to the default color and the right edge matches the
// screen end, try to use terminal codes for clearing the requested area.
- HlAttrs clear_attrs = HLATTRS_INIT;
- clear_attrs.foreground = grid->fg;
- clear_attrs.background = grid->bg;
- update_attrs(ui, clear_attrs);
+ update_attrs(ui, grid->clear_attrs);
if (left == 0) {
if (bot == ui->height - 1) {
if (top == 0) {
@@ -788,6 +804,7 @@ static void tui_clear(UI *ui)
TUIData *data = ui->data;
UGrid *grid = &data->grid;
ugrid_clear(grid);
+ kv_size(data->invalid_regions) = 0;
clear_region(ui, grid->top, grid->bot, grid->left, grid->right);
}
@@ -905,7 +922,7 @@ static void tui_set_mode(UI *ui, ModeShape mode)
if (c.id != 0 && ui->rgb) {
int attr = syn_id2attr(c.id);
if (attr > 0) {
- attrentry_T *aep = syn_cterm_attr2entry(attr);
+ HlAttrs *aep = syn_cterm_attr2entry(attr);
UNIBI_SET_NUM_VAR(data->params[0], aep->rgb_bg_color);
unibi_out_ext(ui, data->unibi_ext.set_cursor_color);
}
@@ -960,10 +977,7 @@ static void tui_scroll(UI *ui, Integer count)
cursor_goto(ui, grid->top, grid->left);
// also set default color attributes or some terminals can become funny
if (scroll_clears_to_current_colour) {
- HlAttrs clear_attrs = HLATTRS_INIT;
- clear_attrs.foreground = grid->fg;
- clear_attrs.background = grid->bg;
- update_attrs(ui, clear_attrs);
+ update_attrs(ui, grid->clear_attrs);
}
if (count > 0) {
@@ -1028,19 +1042,16 @@ static void tui_visual_bell(UI *ui)
unibi_out(ui, unibi_flash_screen);
}
-static void tui_update_fg(UI *ui, Integer fg)
-{
- ((TUIData *)ui->data)->grid.fg = (int)fg;
-}
-
-static void tui_update_bg(UI *ui, Integer bg)
-{
- ((TUIData *)ui->data)->grid.bg = (int)bg;
-}
-
-static void tui_update_sp(UI *ui, Integer sp)
+static void tui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg,
+ Integer rgb_sp,
+ Integer cterm_fg, Integer cterm_bg)
{
- // Do nothing; 'special' color is for GUI only
+ UGrid *grid = &((TUIData *)ui->data)->grid;
+ grid->clear_attrs.rgb_fg_color = (int)rgb_fg;
+ grid->clear_attrs.rgb_bg_color = (int)rgb_bg;
+ grid->clear_attrs.rgb_sp_color = (int)rgb_sp;
+ grid->clear_attrs.cterm_fg_color = (int)cterm_fg;
+ grid->clear_attrs.cterm_bg_color = (int)cterm_bg;
}
static void tui_flush(UI *ui)
@@ -1065,6 +1076,7 @@ static void tui_flush(UI *ui)
while (kv_size(data->invalid_regions)) {
Rect r = kv_pop(data->invalid_regions);
+ assert(r.bot < grid->height && r.right < grid->width);
UGRID_FOREACH_CELL(grid, r.top, r.bot, r.left, r.right, {
cursor_goto(ui, row, col);
print_cell(ui, cell);
@@ -1149,18 +1161,13 @@ static void tui_set_icon(UI *ui, String icon)
static void tui_option_set(UI *ui, String name, Object value)
{
+ TUIData *data = ui->data;
if (strequal(name.data, "termguicolors")) {
- // NB: value for bridge is set in ui_bridge.c
ui->rgb = value.data.boolean;
+ invalidate(ui, 0, data->grid.height-1, 0, data->grid.width-1);
}
}
-// NB: if we start to use this, the ui_bridge must be updated
-// to make a copy for the tui thread
-static void tui_event(UI *ui, char *name, Array args, bool *args_consumed)
-{
-}
-
static void invalidate(UI *ui, int top, int bot, int left, int right)
{
TUIData *data = ui->data;
diff --git a/src/nvim/ugrid.c b/src/nvim/ugrid.c
index e0880b4c76..6d420ef2f8 100644
--- a/src/nvim/ugrid.c
+++ b/src/nvim/ugrid.c
@@ -17,7 +17,7 @@
void ugrid_init(UGrid *grid)
{
grid->attrs = HLATTRS_INIT;
- grid->fg = grid->bg = -1;
+ grid->clear_attrs = HLATTRS_INIT;
grid->cells = NULL;
}
@@ -107,6 +107,7 @@ UCell *ugrid_put(UGrid *grid, uint8_t *text, size_t size)
UCell *cell = grid->cells[grid->row] + grid->col;
cell->data[size] = 0;
cell->attrs = grid->attrs;
+ assert(size <= CELLBYTES);
if (text) {
memcpy(cell->data, text, size);
@@ -118,9 +119,7 @@ UCell *ugrid_put(UGrid *grid, uint8_t *text, size_t size)
static void clear_region(UGrid *grid, int top, int bot, int left, int right)
{
- HlAttrs clear_attrs = HLATTRS_INIT;
- clear_attrs.foreground = grid->fg;
- clear_attrs.background = grid->bg;
+ HlAttrs clear_attrs = grid->clear_attrs;
UGRID_FOREACH_CELL(grid, top, bot, left, right, {
cell->data[0] = ' ';
cell->data[1] = 0;
diff --git a/src/nvim/ugrid.h b/src/nvim/ugrid.h
index 1cf047502d..60c9068eb1 100644
--- a/src/nvim/ugrid.h
+++ b/src/nvim/ugrid.h
@@ -7,15 +7,17 @@
typedef struct ucell UCell;
typedef struct ugrid UGrid;
+#define CELLBYTES (4 * (MAX_MCO+1))
+
struct ucell {
- char data[6 * MAX_MCO + 1];
+ char data[CELLBYTES + 1];
HlAttrs attrs;
};
struct ugrid {
int top, bot, left, right;
int row, col;
- int bg, fg;
+ HlAttrs clear_attrs;
int width, height;
HlAttrs attrs;
UCell **cells;
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 709a172449..e8f5477db0 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -55,7 +55,7 @@ static int row = 0, col = 0;
static struct {
int top, bot, left, right;
} sr;
-static int current_attr_code = 0;
+static int current_attr_code = -1;
static bool pending_cursor_update = false;
static int busy = 0;
static int height, width;
@@ -107,8 +107,9 @@ static char uilog_last_event[1024] = { 0 };
} \
} while (0)
#endif
-#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, ZERO, ignore)
-#define SELECT_NTH(a1, a2, a3, a4, a5, a6, ...) a6
+#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, \
+ MORE, MORE, ZERO, ignore)
+#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, ...) a7
#define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__)
// Resolves to UI_CALL_MORE or UI_CALL_ZERO.
#define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__)
@@ -151,6 +152,9 @@ bool ui_is_stopped(UI *ui)
bool ui_rgb_attached(void)
{
+ if (!headless_mode && p_tgc) {
+ return true;
+ }
for (size_t i = 0; i < ui_count; i++) {
if (uis[i]->rgb) {
return true;
@@ -174,84 +178,57 @@ void ui_event(char *name, Array args)
}
-/// Converts an attrentry_T into an HlAttrs
+/// Converts an HlAttrs into Dictionary
///
/// @param[in] aep data to convert
/// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*'
-HlAttrs attrentry2hlattrs(const attrentry_T *aep, bool use_rgb)
+Dictionary hlattrs2dict(const HlAttrs *aep, bool use_rgb)
{
assert(aep);
-
- HlAttrs attrs = HLATTRS_INIT;
- int mask = 0;
-
- mask = use_rgb ? aep->rgb_ae_attr : aep->cterm_ae_attr;
-
- attrs.bold = mask & HL_BOLD;
- attrs.underline = mask & HL_UNDERLINE;
- attrs.undercurl = mask & HL_UNDERCURL;
- attrs.italic = mask & HL_ITALIC;
- attrs.reverse = mask & (HL_INVERSE | HL_STANDOUT);
-
- if (use_rgb) {
- if (aep->rgb_fg_color != -1) {
- attrs.foreground = aep->rgb_fg_color;
- }
-
- if (aep->rgb_bg_color != -1) {
- attrs.background = aep->rgb_bg_color;
- }
-
- if (aep->rgb_sp_color != -1) {
- attrs.special = aep->rgb_sp_color;
- }
- } else {
- if (cterm_normal_fg_color != aep->cterm_fg_color) {
- attrs.foreground = aep->cterm_fg_color - 1;
- }
-
- if (cterm_normal_bg_color != aep->cterm_bg_color) {
- attrs.background = aep->cterm_bg_color - 1;
- }
- }
-
- return attrs;
-}
-
-Dictionary hlattrs2dict(HlAttrs attrs)
-{
Dictionary hl = ARRAY_DICT_INIT;
+ int mask = use_rgb ? aep->rgb_ae_attr : aep->cterm_ae_attr;
- if (attrs.bold) {
+ if (mask & HL_BOLD) {
PUT(hl, "bold", BOOLEAN_OBJ(true));
}
- if (attrs.underline) {
+ if (mask & HL_UNDERLINE) {
PUT(hl, "underline", BOOLEAN_OBJ(true));
}
- if (attrs.undercurl) {
+ if (mask & HL_UNDERCURL) {
PUT(hl, "undercurl", BOOLEAN_OBJ(true));
}
- if (attrs.italic) {
+ if (mask & HL_ITALIC) {
PUT(hl, "italic", BOOLEAN_OBJ(true));
}
- if (attrs.reverse) {
+ if (mask & (HL_INVERSE | HL_STANDOUT)) {
PUT(hl, "reverse", BOOLEAN_OBJ(true));
}
- if (attrs.foreground != -1) {
- PUT(hl, "foreground", INTEGER_OBJ(attrs.foreground));
- }
- if (attrs.background != -1) {
- PUT(hl, "background", INTEGER_OBJ(attrs.background));
- }
+ if (use_rgb) {
+ if (aep->rgb_fg_color != -1) {
+ PUT(hl, "foreground", INTEGER_OBJ(aep->rgb_fg_color));
+ }
- if (attrs.special != -1) {
- PUT(hl, "special", INTEGER_OBJ(attrs.special));
+ if (aep->rgb_bg_color != -1) {
+ PUT(hl, "background", INTEGER_OBJ(aep->rgb_bg_color));
+ }
+
+ if (aep->rgb_sp_color != -1) {
+ PUT(hl, "special", INTEGER_OBJ(aep->rgb_sp_color));
+ }
+ } else {
+ if (cterm_normal_fg_color != aep->cterm_fg_color) {
+ PUT(hl, "foreground", INTEGER_OBJ(aep->cterm_fg_color - 1));
+ }
+
+ if (cterm_normal_bg_color != aep->cterm_bg_color) {
+ PUT(hl, "background", INTEGER_OBJ(aep->cterm_bg_color - 1));
+ }
}
return hl;
@@ -296,6 +273,7 @@ void ui_refresh(void)
ui_mode_info_set();
old_mode_idx = -1;
ui_cursor_shape();
+ current_attr_code = -1;
}
static void ui_refresh_event(void **argv)
@@ -313,6 +291,11 @@ void ui_resize(int new_width, int new_height)
width = new_width;
height = new_height;
+ // TODO(bfredl): update default colors when they changed, NOT on resize.
+ ui_call_default_colors_set(normal_fg, normal_bg, normal_sp,
+ cterm_normal_fg_color, cterm_normal_bg_color);
+
+ // Deprecated:
UI_CALL(update_fg, (ui->rgb ? normal_fg : cterm_normal_fg_color - 1));
UI_CALL(update_bg, (ui->rgb ? normal_bg : cterm_normal_bg_color - 1));
UI_CALL(update_sp, (ui->rgb ? normal_sp : -1));
@@ -406,26 +389,28 @@ void ui_reset_scroll_region(void)
ui_call_set_scroll_region(sr.top, sr.bot, sr.left, sr.right);
}
-void ui_start_highlight(int attr_code)
+void ui_set_highlight(int attr_code)
{
+ if (current_attr_code == attr_code) {
+ return;
+ }
current_attr_code = attr_code;
- if (!ui_active()) {
- return;
+ HlAttrs attrs = HLATTRS_INIT;
+
+ if (attr_code != 0) {
+ HlAttrs *aep = syn_cterm_attr2entry(attr_code);
+ if (aep) {
+ attrs = *aep;
+ }
}
- set_highlight_args(current_attr_code);
+ UI_CALL(highlight_set, attrs);
}
-void ui_stop_highlight(void)
+void ui_clear_highlight(void)
{
- current_attr_code = HL_NORMAL;
-
- if (!ui_active()) {
- return;
- }
-
- set_highlight_args(current_attr_code);
+ ui_set_highlight(0);
}
void ui_puts(uint8_t *str)
@@ -503,26 +488,6 @@ void ui_flush(void)
ui_call_flush();
}
-static void set_highlight_args(int attr_code)
-{
- HlAttrs rgb_attrs = HLATTRS_INIT;
- HlAttrs cterm_attrs = rgb_attrs;
-
- if (attr_code == HL_NORMAL) {
- goto end;
- }
- attrentry_T *aep = syn_cterm_attr2entry(attr_code);
-
- if (!aep) {
- goto end;
- }
-
- rgb_attrs = attrentry2hlattrs(aep, true);
- cterm_attrs = attrentry2hlattrs(aep, false);
-
-end:
- UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs));
-}
void ui_linefeed(void)
{
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 0e40a1a215..60adcb974f 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -16,14 +16,6 @@ typedef enum {
} UIWidget;
#define UI_WIDGETS (kUIWildmenu + 1)
-typedef struct {
- bool bold, underline, undercurl, italic, reverse;
- int foreground, background, special;
-} HlAttrs;
-
-#define HLATTRS_INIT \
- ((HlAttrs){ false, false, false, false, false, -1, -1, -1 })
-
typedef struct ui_t UI;
struct ui_t {
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index 16dd42ebaa..b0f8905771 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -59,9 +59,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
rv->bridge.put = ui_bridge_put;
rv->bridge.bell = ui_bridge_bell;
rv->bridge.visual_bell = ui_bridge_visual_bell;
- rv->bridge.update_fg = ui_bridge_update_fg;
- rv->bridge.update_bg = ui_bridge_update_bg;
- rv->bridge.update_sp = ui_bridge_update_sp;
+ rv->bridge.default_colors_set = ui_bridge_default_colors_set;
rv->bridge.flush = ui_bridge_flush;
rv->bridge.suspend = ui_bridge_suspend;
rv->bridge.set_title = ui_bridge_set_title;
@@ -146,29 +144,6 @@ static void ui_bridge_highlight_set_event(void **argv)
xfree(argv[1]);
}
-static void ui_bridge_option_set(UI *ui, String name, Object value)
-{
- // Assumes bridge is only used by TUI
- if (strequal(name.data, "termguicolors")) {
- ui->rgb = value.data.boolean;
- }
- String copy_name = copy_string(name);
- Object *copy_value = xmalloc(sizeof(Object));
- *copy_value = copy_object(value);
- UI_BRIDGE_CALL(ui, option_set, 4, ui,
- copy_name.data, INT2PTR(copy_name.size), copy_value);
-}
-static void ui_bridge_option_set_event(void **argv)
-{
- UI *ui = UI(argv[0]);
- String name = (String){ .data = argv[1], .size = (size_t)argv[2] };
- Object value = *(Object *)argv[3];
- ui->option_set(ui, name, value);
- api_free_string(name);
- api_free_object(value);
- xfree(argv[3]);
-}
-
static void ui_bridge_suspend(UI *b)
{
UIBridgeData *data = (UIBridgeData *)b;