mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(drawline): avoid storing info to draw 'statuscolumn' (#26712)
We no longer return to the main loop in win_line() to put column characters on the screen. Simplify and sync statuscolumn drawing logic with that of statusline.
This commit is contained in:
parent
2b0acacb3c
commit
e632396bab
@ -604,24 +604,24 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepare and build the 'statuscolumn' string for line "lnum" in window "wp".
|
/// Build and draw the 'statuscolumn' string for line "lnum" in window "wp".
|
||||||
/// Fill "stcp" with the built status column string and attributes.
|
/// Fill "stcp" with the built status column string and attributes.
|
||||||
/// This can be called three times per win_line(), once for virt_lines, once for
|
|
||||||
/// the start of the buffer line "lnum" and once for the wrapped lines.
|
|
||||||
///
|
///
|
||||||
/// @param[out] stcp Status column attributes
|
/// @param[out] stcp Status column attributes
|
||||||
static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T *stcp)
|
static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int virtnum,
|
||||||
|
statuscol_T *stcp)
|
||||||
{
|
{
|
||||||
// When called for the first non-filler row of line "lnum" set num v:vars
|
// When called for the first non-filler row of line "lnum" set num v:vars
|
||||||
linenr_T relnum = virtnum == 0 ? abs(get_cursor_rel_lnum(wp, lnum)) : -1;
|
linenr_T relnum = virtnum == 0 ? abs(get_cursor_rel_lnum(wp, lnum)) : -1;
|
||||||
|
|
||||||
|
char buf[MAXPATHL];
|
||||||
// When a buffer's line count has changed, make a best estimate for the full
|
// When a buffer's line count has changed, make a best estimate for the full
|
||||||
// width of the status column by building with "w_nrwidth_line_count". Add
|
// width of the status column by building with "w_nrwidth_line_count". Add
|
||||||
// potentially truncated width and rebuild before drawing anything.
|
// potentially truncated width and rebuild before drawing anything.
|
||||||
if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) {
|
if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) {
|
||||||
wp->w_statuscol_line_count = wp->w_nrwidth_line_count;
|
wp->w_statuscol_line_count = wp->w_nrwidth_line_count;
|
||||||
set_vim_var_nr(VV_VIRTNUM, 0);
|
set_vim_var_nr(VV_VIRTNUM, 0);
|
||||||
build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, stcp);
|
build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, buf, stcp);
|
||||||
if (stcp->truncate > 0) {
|
if (stcp->truncate > 0) {
|
||||||
// Add truncated width to avoid unnecessary redraws
|
// Add truncated width to avoid unnecessary redraws
|
||||||
int addwidth = MIN(stcp->truncate, MAX_NUMBERWIDTH - wp->w_nrwidth);
|
int addwidth = MIN(stcp->truncate, MAX_NUMBERWIDTH - wp->w_nrwidth);
|
||||||
@ -634,7 +634,7 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T
|
|||||||
}
|
}
|
||||||
set_vim_var_nr(VV_VIRTNUM, virtnum);
|
set_vim_var_nr(VV_VIRTNUM, virtnum);
|
||||||
|
|
||||||
int width = build_statuscol_str(wp, lnum, relnum, stcp);
|
int width = build_statuscol_str(wp, lnum, relnum, buf, stcp);
|
||||||
// Force a redraw in case of error or when truncated
|
// Force a redraw in case of error or when truncated
|
||||||
if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
|
if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
|
||||||
if (stcp->truncate > 0) { // Avoid truncating 'statuscolumn'
|
if (stcp->truncate > 0) { // Avoid truncating 'statuscolumn'
|
||||||
@ -648,44 +648,26 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset text/highlight pointer and current attr for new line
|
char *p = buf;
|
||||||
stcp->textp = stcp->text;
|
char transbuf[MAXPATHL];
|
||||||
stcp->hlrecp = stcp->hlrec;
|
int attr = stcp->num_attr;
|
||||||
stcp->cur_attr = stcp->num_attr;
|
size_t len = strlen(buf);
|
||||||
stcp->text_end = stcp->text + strlen(stcp->text);
|
|
||||||
|
|
||||||
int fill = stcp->width - width;
|
// Draw each segment with the specified highlighting.
|
||||||
if (fill > 0) {
|
for (stl_hlrec_t *sp = stcp->hlrec; sp->start != NULL; sp++) {
|
||||||
// Fill up with ' '
|
ptrdiff_t textlen = sp->start - p;
|
||||||
memset(stcp->text_end, ' ', (size_t)fill);
|
// Make all characters printable.
|
||||||
*(stcp->text_end += fill) = NUL;
|
size_t translen = transstr_buf(p, textlen, transbuf, MAXPATHL, true);
|
||||||
|
draw_col_buf(wp, wlv, transbuf, translen, attr, false);
|
||||||
|
p = sp->start;
|
||||||
|
int hl = sp->userhl;
|
||||||
|
attr = hl < 0 ? syn_id2attr(-hl) : stcp->num_attr;
|
||||||
}
|
}
|
||||||
}
|
size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true);
|
||||||
|
draw_col_buf(wp, wlv, transbuf, translen, attr, false);
|
||||||
|
|
||||||
/// Get information needed to display the next segment in the 'statuscolumn'.
|
// Fill up with ' '
|
||||||
///
|
draw_col_fill(wlv, ' ', stcp->width - width, stcp->num_attr);
|
||||||
/// @param stcp Status column attributes
|
|
||||||
/// @param[in,out] wlv
|
|
||||||
static void draw_statuscol(win_T *wp, statuscol_T *stcp, winlinevars_T *wlv)
|
|
||||||
{
|
|
||||||
do {
|
|
||||||
int attr = stcp->cur_attr;
|
|
||||||
char *start = stcp->textp;
|
|
||||||
stcp->textp = stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end;
|
|
||||||
ptrdiff_t len = stcp->textp - start;
|
|
||||||
// Prepare for next highlight section if not yet at the end
|
|
||||||
if (stcp->textp < stcp->text_end) {
|
|
||||||
int hl = stcp->hlrecp->userhl;
|
|
||||||
stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : stcp->num_attr;
|
|
||||||
stcp->hlrecp++;
|
|
||||||
}
|
|
||||||
// Skip over empty highlight sections
|
|
||||||
if (len) {
|
|
||||||
static char transbuf[(MAX_NUMBERWIDTH + 9 + 9 * SIGN_WIDTH) * MB_MAXBYTES + 1];
|
|
||||||
size_t translen = transstr_buf(start, len, transbuf, sizeof transbuf, true);
|
|
||||||
draw_col_buf(wp, wlv, transbuf, translen, attr, false);
|
|
||||||
}
|
|
||||||
} while (stcp->textp < stcp->text_end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_breakindent(win_T *wp, winlinevars_T *wlv)
|
static void handle_breakindent(win_T *wp, winlinevars_T *wlv)
|
||||||
@ -1550,19 +1532,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
|||||||
if (sign_num_attr == 0) {
|
if (sign_num_attr == 0) {
|
||||||
statuscol.num_attr = get_line_number_attr(wp, &wlv);
|
statuscol.num_attr = get_line_number_attr(wp, &wlv);
|
||||||
}
|
}
|
||||||
if (statuscol.textp == NULL) {
|
v = (ptr - line);
|
||||||
v = (ptr - line);
|
draw_statuscol(wp, &wlv, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol);
|
||||||
get_statuscol_str(wp, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol);
|
if (wp->w_redr_statuscol) {
|
||||||
if (!end_fill) {
|
break;
|
||||||
// Get the line again as evaluating 'statuscolumn' may free it.
|
}
|
||||||
line = ml_get_buf(wp->w_buffer, lnum);
|
if (!end_fill) {
|
||||||
ptr = line + v;
|
// Get the line again as evaluating 'statuscolumn' may free it.
|
||||||
}
|
line = ml_get_buf(wp->w_buffer, lnum);
|
||||||
if (wp->w_redr_statuscol) {
|
ptr = line + v;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
draw_statuscol(wp, &statuscol, &wlv);
|
|
||||||
} else {
|
} else {
|
||||||
// draw builtin info columns: fold, sign, number
|
// draw builtin info columns: fold, sign, number
|
||||||
draw_foldcolumn(wp, &wlv);
|
draw_foldcolumn(wp, &wlv);
|
||||||
@ -2906,12 +2885,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
|
|||||||
if (wlv.filler_todo <= 0) {
|
if (wlv.filler_todo <= 0) {
|
||||||
wlv.need_showbreak = true;
|
wlv.need_showbreak = true;
|
||||||
}
|
}
|
||||||
if (statuscol.draw) {
|
if (statuscol.draw && vim_strchr(p_cpo, CPO_NUMCOL)
|
||||||
if (vim_strchr(p_cpo, CPO_NUMCOL) && wlv.row > startrow + wlv.filler_lines) {
|
&& wlv.row > startrow + wlv.filler_lines) {
|
||||||
statuscol.draw = false; // don't draw status column if "n" is in 'cpo'
|
statuscol.draw = false; // don't draw status column if "n" is in 'cpo'
|
||||||
} else {
|
|
||||||
statuscol.textp = NULL; // re-evaluate with new v:virtnum
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
wlv.filler_todo--;
|
wlv.filler_todo--;
|
||||||
virt_line_offset = -1;
|
virt_line_offset = -1;
|
||||||
|
@ -867,7 +867,7 @@ void draw_tabline(void)
|
|||||||
/// the v:lnum and v:relnum variables don't have to be updated.
|
/// the v:lnum and v:relnum variables don't have to be updated.
|
||||||
///
|
///
|
||||||
/// @return The width of the built status column string for line "lnum"
|
/// @return The width of the built status column string for line "lnum"
|
||||||
int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *stcp)
|
int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, char *buf, statuscol_T *stcp)
|
||||||
{
|
{
|
||||||
// Only update click definitions once per window per redraw.
|
// Only update click definitions once per window per redraw.
|
||||||
// Don't update when current width is 0, since it will be redrawn again if not empty.
|
// Don't update when current width is 0, since it will be redrawn again if not empty.
|
||||||
@ -880,7 +880,7 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
|
|||||||
|
|
||||||
StlClickRecord *clickrec;
|
StlClickRecord *clickrec;
|
||||||
char *stc = xstrdup(wp->w_p_stc);
|
char *stc = xstrdup(wp->w_p_stc);
|
||||||
int width = build_stl_str_hl(wp, stcp->text, MAXPATHL, stc, kOptStatuscolumn, OPT_LOCAL, ' ',
|
int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, kOptStatuscolumn, OPT_LOCAL, ' ',
|
||||||
stcp->width, &stcp->hlrec, fillclick ? &clickrec : NULL, stcp);
|
stcp->width, &stcp->hlrec, fillclick ? &clickrec : NULL, stcp);
|
||||||
xfree(stc);
|
xfree(stc);
|
||||||
|
|
||||||
@ -888,7 +888,7 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
|
|||||||
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
|
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
|
||||||
wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, stcp->width,
|
wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, stcp->width,
|
||||||
&wp->w_statuscol_click_defs_size);
|
&wp->w_statuscol_click_defs_size);
|
||||||
stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, stcp->text, stcp->width, false);
|
stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, buf, stcp->width, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
|
@ -57,21 +57,14 @@ struct stl_item {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Struct to hold info for 'statuscolumn'
|
/// Struct to hold info for 'statuscolumn'
|
||||||
typedef struct statuscol statuscol_T;
|
typedef struct {
|
||||||
|
|
||||||
struct statuscol {
|
|
||||||
int width; ///< width of the status column
|
int width; ///< width of the status column
|
||||||
int cur_attr; ///< current attributes in text
|
|
||||||
int num_attr; ///< default highlight attr
|
int num_attr; ///< default highlight attr
|
||||||
int sign_cul_id; ///< cursorline sign highlight id
|
int sign_cul_id; ///< cursorline sign highlight id
|
||||||
int truncate; ///< truncated width
|
int truncate; ///< truncated width
|
||||||
bool draw; ///< whether to draw the statuscolumn
|
bool draw; ///< whether to draw the statuscolumn
|
||||||
bool use_cul; ///< whether to use cursorline attrs
|
bool use_cul; ///< whether to use cursorline attrs
|
||||||
char text[MAXPATHL]; ///< text in status column
|
|
||||||
char *textp; ///< current position in text
|
|
||||||
char *text_end; ///< end of text (the NUL byte)
|
|
||||||
stl_hlrec_t *hlrec; ///< highlight groups
|
stl_hlrec_t *hlrec; ///< highlight groups
|
||||||
stl_hlrec_t *hlrecp; ///< current highlight group
|
|
||||||
foldinfo_T foldinfo; ///< fold information
|
foldinfo_T foldinfo; ///< fold information
|
||||||
SignTextAttrs *sattrs; ///< sign attributes
|
SignTextAttrs *sattrs; ///< sign attributes
|
||||||
};
|
} statuscol_T;
|
||||||
|
Loading…
Reference in New Issue
Block a user