diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/ui.c | 3 | ||||
-rw-r--r-- | src/nvim/api/ui_events.in.h | 11 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 6 | ||||
-rw-r--r-- | src/nvim/highlight_defs.h | 29 | ||||
-rw-r--r-- | src/nvim/options.lua | 2 | ||||
-rw-r--r-- | src/nvim/screen.c | 43 | ||||
-rw-r--r-- | src/nvim/syntax.c | 47 | ||||
-rw-r--r-- | src/nvim/syntax.h | 13 | ||||
-rw-r--r-- | src/nvim/syntax_defs.h | 17 | ||||
-rw-r--r-- | src/nvim/terminal.c | 2 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 113 | ||||
-rw-r--r-- | src/nvim/ugrid.c | 7 | ||||
-rw-r--r-- | src/nvim/ugrid.h | 6 | ||||
-rw-r--r-- | src/nvim/ui.c | 143 | ||||
-rw-r--r-- | src/nvim/ui.h | 8 | ||||
-rw-r--r-- | src/nvim/ui_bridge.c | 27 |
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; |