aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/drawline.c96
-rw-r--r--src/nvim/statusline.c6
-rw-r--r--src/nvim/statusline_defs.h11
3 files changed, 41 insertions, 72 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index e34c22d907..e7b56dcd68 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -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.
-/// 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
-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
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
// width of the status column by building with "w_nrwidth_line_count". Add
// potentially truncated width and rebuild before drawing anything.
if (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);
- 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) {
// Add truncated width to avoid unnecessary redraws
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);
- 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
if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
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;
}
- // Reset text/highlight pointer and current attr for new line
- stcp->textp = stcp->text;
- stcp->hlrecp = stcp->hlrec;
- stcp->cur_attr = stcp->num_attr;
- stcp->text_end = stcp->text + strlen(stcp->text);
-
- int fill = stcp->width - width;
- if (fill > 0) {
- // Fill up with ' '
- memset(stcp->text_end, ' ', (size_t)fill);
- *(stcp->text_end += fill) = NUL;
+ char *p = buf;
+ char transbuf[MAXPATHL];
+ int attr = stcp->num_attr;
+ size_t len = strlen(buf);
+
+ // Draw each segment with the specified highlighting.
+ for (stl_hlrec_t *sp = stcp->hlrec; sp->start != NULL; sp++) {
+ ptrdiff_t textlen = sp->start - p;
+ // Make all characters printable.
+ 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'.
-///
-/// @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);
+ // Fill up with ' '
+ draw_col_fill(wlv, ' ', stcp->width - width, stcp->num_attr);
}
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) {
statuscol.num_attr = get_line_number_attr(wp, &wlv);
}
- if (statuscol.textp == NULL) {
- v = (ptr - line);
- get_statuscol_str(wp, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol);
- if (!end_fill) {
- // Get the line again as evaluating 'statuscolumn' may free it.
- line = ml_get_buf(wp->w_buffer, lnum);
- ptr = line + v;
- }
- if (wp->w_redr_statuscol) {
- break;
- }
+ v = (ptr - line);
+ draw_statuscol(wp, &wlv, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol);
+ if (wp->w_redr_statuscol) {
+ break;
+ }
+ if (!end_fill) {
+ // Get the line again as evaluating 'statuscolumn' may free it.
+ line = ml_get_buf(wp->w_buffer, lnum);
+ ptr = line + v;
}
- draw_statuscol(wp, &statuscol, &wlv);
} else {
// draw builtin info columns: fold, sign, number
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) {
wlv.need_showbreak = true;
}
- if (statuscol.draw) {
- if (vim_strchr(p_cpo, CPO_NUMCOL) && wlv.row > startrow + wlv.filler_lines) {
- statuscol.draw = false; // don't draw status column if "n" is in 'cpo'
- } else {
- statuscol.textp = NULL; // re-evaluate with new v:virtnum
- }
+ if (statuscol.draw && vim_strchr(p_cpo, CPO_NUMCOL)
+ && wlv.row > startrow + wlv.filler_lines) {
+ statuscol.draw = false; // don't draw status column if "n" is in 'cpo'
}
wlv.filler_todo--;
virt_line_offset = -1;
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index e249317bd3..563e1d0a5b 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -867,7 +867,7 @@ void draw_tabline(void)
/// 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"
-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.
// 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;
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);
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);
wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, stcp->width,
&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;
diff --git a/src/nvim/statusline_defs.h b/src/nvim/statusline_defs.h
index c1a54f4f54..e4b1c627ad 100644
--- a/src/nvim/statusline_defs.h
+++ b/src/nvim/statusline_defs.h
@@ -57,21 +57,14 @@ struct stl_item {
};
/// Struct to hold info for 'statuscolumn'
-typedef struct statuscol statuscol_T;
-
-struct statuscol {
+typedef struct {
int width; ///< width of the status column
- int cur_attr; ///< current attributes in text
int num_attr; ///< default highlight attr
int sign_cul_id; ///< cursorline sign highlight id
int truncate; ///< truncated width
bool draw; ///< whether to draw the statuscolumn
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 *hlrecp; ///< current highlight group
foldinfo_T foldinfo; ///< fold information
SignTextAttrs *sattrs; ///< sign attributes
-};
+} statuscol_T;