mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #7982 from bfredl/hlrefactor
Refactor HlAttrs so that termguicolors is implemented purely on TUI side
This commit is contained in:
commit
564ad60c06
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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}}
|
||||
},
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
static void tui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg,
|
||||
Integer rgb_sp,
|
||||
Integer cterm_fg, Integer cterm_bg)
|
||||
{
|
||||
((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)
|
||||
{
|
||||
// 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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
143
src/nvim/ui.c
143
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)
|
||||
{
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -242,7 +242,7 @@ describe('tui', function()
|
||||
{9:~ }|
|
||||
{9:~ }|
|
||||
{3:[No Name] [+] }|
|
||||
|
|
||||
:set termguicolors |
|
||||
{4:-- TERMINAL --} |
|
||||
]])
|
||||
|
||||
@ -253,7 +253,7 @@ describe('tui', function()
|
||||
{2:~ }|
|
||||
{2:~ }|
|
||||
{3:[No Name] [+] }|
|
||||
|
|
||||
:set notermguicolors |
|
||||
{4:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
|
@ -455,6 +455,9 @@ function Screen:_handle_visual_bell()
|
||||
self.visual_bell = true
|
||||
end
|
||||
|
||||
function Screen:_handle_default_colors_set()
|
||||
end
|
||||
|
||||
function Screen:_handle_update_fg(fg)
|
||||
self._fg = fg
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user