vim-patch:9.0.0533: the win_line() function is much too long

Problem:    The win_line() function is much too long.
Solution:   Move code to separate functions.

e49f9acecc

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
zeertzjq 2023-03-03 18:13:53 +08:00
parent a7dbfec9f3
commit bdde07f60e

View File

@ -92,6 +92,7 @@ typedef struct {
int fromcol; ///< start of inverting
int tocol; ///< end of inverting
long vcol_sbr; ///< virtual column after showbreak
bool need_showbreak; ///< overlong line, skipping first x chars
int char_attr; ///< attributes for next character
@ -104,10 +105,18 @@ typedef struct {
int c_extra; ///< extra chars, all the same
int c_final; ///< final char, mandatory if set
// saved "extra" items for when draw_state becomes WL_LINE (again)
int saved_n_extra;
char *saved_p_extra;
int saved_c_extra;
int saved_c_final;
int saved_char_attr;
char extra[57]; ///< sign, line number and 'fdc' must fit in here
hlf_T diff_hlf; ///< type of diff highlighting
int n_virt_lines; ///< nr of virtual lines
int filler_lines; ///< nr of filler lines to be drawn
int filler_todo; ///< nr of filler lines still to do + 1
SignTextAttrs sattrs[SIGN_SHOW_MAX]; ///< sign attributes for the sign column
@ -689,6 +698,60 @@ static void handle_breakindent(win_T *wp, winlinevars_T *wlv)
}
}
static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv)
{
if (wlv->filler_todo > wlv->filler_lines - wlv->n_virt_lines) {
// TODO(bfredl): check this doesn't inhibit TUI-style
// clear-to-end-of-line.
wlv->c_extra = ' ';
wlv->c_final = NUL;
if (wp->w_p_rl) {
wlv->n_extra = wlv->col + 1;
} else {
wlv->n_extra = wp->w_grid.cols - wlv->col;
}
wlv->char_attr = 0;
} else if (wlv->filler_todo > 0) {
// Draw "deleted" diff line(s)
if (char2cells(wp->w_p_fcs_chars.diff) > 1) {
wlv->c_extra = '-';
wlv->c_final = NUL;
} else {
wlv->c_extra = wp->w_p_fcs_chars.diff;
wlv->c_final = NUL;
}
if (wp->w_p_rl) {
wlv->n_extra = wlv->col + 1;
} else {
wlv->n_extra = wp->w_grid.cols - wlv->col;
}
wlv->char_attr = win_hl_attr(wp, HLF_DED);
}
char *const sbr = get_showbreak_value(wp);
if (*sbr != NUL && wlv->need_showbreak) {
// Draw 'showbreak' at the start of each broken line.
wlv->p_extra = sbr;
wlv->c_extra = NUL;
wlv->c_final = NUL;
wlv->n_extra = (int)strlen(sbr);
wlv->char_attr = win_hl_attr(wp, HLF_AT);
if (wp->w_skipcol == 0 || !wp->w_p_wrap) {
wlv->need_showbreak = false;
}
wlv->vcol_sbr = wlv->vcol + mb_charlen(sbr);
// Correct end of highlighted area for 'showbreak',
// required when 'linebreak' is also set.
if (wlv->tocol == wlv->vcol) {
wlv->tocol += wlv->n_extra;
}
// Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'.
if (wlv->cul_attr) {
wlv->char_attr = hl_combine_attr(wlv->cul_attr, wlv->char_attr);
}
}
}
static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv)
{
wlv->cul_attr = win_hl_attr(wp, HLF_CUL);
@ -756,10 +819,11 @@ static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line)
}
/// Start a screen line at column zero.
static void win_line_start(win_T *wp, winlinevars_T *wlv)
static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra)
{
wlv->col = 0;
wlv->off = 0;
if (wp->w_p_rl) {
// Rightleft window: process the text in the normal direction, but put
// it in linebuf_char[wlv.off] from right to left. Start at the
@ -767,6 +831,33 @@ static void win_line_start(win_T *wp, winlinevars_T *wlv)
wlv->col = wp->w_grid.cols - 1;
wlv->off += wlv->col;
}
if (save_extra) {
// reset the drawing state for the start of a wrapped line
wlv->draw_state = WL_START;
wlv->saved_n_extra = wlv->n_extra;
wlv->saved_p_extra = wlv->p_extra;
wlv->saved_c_extra = wlv->c_extra;
wlv->saved_c_final = wlv->c_final;
wlv->saved_char_attr = wlv->char_attr;
wlv->n_extra = 0;
}
}
/// Called when wlv->draw_state is set to WL_LINE.
static void win_line_continue(winlinevars_T *wlv)
{
if (wlv->saved_n_extra > 0) {
// Continue item from end of wrapped line.
wlv->n_extra = wlv->saved_n_extra;
wlv->c_extra = wlv->saved_c_extra;
wlv->c_final = wlv->saved_c_final;
wlv->p_extra = wlv->saved_p_extra;
wlv->char_attr = wlv->saved_char_attr;
} else {
wlv->char_attr = 0;
}
}
/// Display line "lnum" of window 'wp' on the screen.
@ -789,7 +880,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
winlinevars_T wlv; // variables passed between functions
int c = 0; // init for GCC
long vcol_sbr = -1; // virtual column after showbreak
long vcol_prev = -1; // "wlv.vcol" of previous character
char *line; // current line
char *ptr; // current position in "line"
@ -799,13 +889,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// at end-of-line
bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
// saved "extra" items for when draw_state becomes WL_LINE (again)
int saved_n_extra = 0;
char *saved_p_extra = NULL;
int saved_c_extra = 0;
int saved_c_final = 0;
int saved_char_attr = 0;
int n_attr = 0; // chars with special attr
int saved_attr2 = 0; // char_attr saved for n_attr
int n_attr3 = 0; // chars with overruling special attr
@ -907,6 +990,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.row = startrow;
wlv.fromcol = -10;
wlv.tocol = MAXCOL;
wlv.vcol_sbr = -1;
buf_T *buf = wp->w_buffer;
bool end_fill = (lnum == buf->b_ml.ml_line_count + 1);
@ -1103,11 +1187,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
area_highlighting = true;
}
VirtLines virt_lines = KV_INITIAL_VALUE;
int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold);
wlv.filler_lines += n_virt_lines;
wlv.n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold);
wlv.filler_lines += wlv.n_virt_lines;
if (lnum == wp->w_topline) {
wlv.filler_lines = wp->w_topfill;
n_virt_lines = MIN(n_virt_lines, wlv.filler_lines);
wlv.n_virt_lines = MIN(wlv.n_virt_lines, wlv.filler_lines);
}
wlv.filler_todo = wlv.filler_lines;
@ -1323,7 +1407,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
ptr = line + v; // "line" may have been updated
}
win_line_start(wp, &wlv);
win_line_start(wp, &wlv, false);
// won't highlight after TERM_ATTRS_MAX columns
int term_attrs[TERM_ATTRS_MAX] = { 0 };
@ -1375,7 +1459,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) {
if (wlv.filler_todo > 0) {
int index = wlv.filler_todo - (wlv.filler_lines - n_virt_lines);
int index = wlv.filler_todo - (wlv.filler_lines - wlv.n_virt_lines);
if (index > 0) {
virt_line_index = (int)kv_size(virt_lines) - index;
assert(virt_line_index >= 0);
@ -1443,76 +1527,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wlv.draw_state == WL_SBR - 1 && wlv.n_extra == 0) {
wlv.draw_state = WL_SBR;
if (wlv.filler_todo > wlv.filler_lines - n_virt_lines) {
// TODO(bfredl): check this doesn't inhibit TUI-style
// clear-to-end-of-line.
wlv.c_extra = ' ';
wlv.c_final = NUL;
if (wp->w_p_rl) {
wlv.n_extra = wlv.col + 1;
} else {
wlv.n_extra = grid->cols - wlv.col;
}
wlv.char_attr = 0;
} else if (wlv.filler_todo > 0) {
// Draw "deleted" diff line(s)
if (char2cells(wp->w_p_fcs_chars.diff) > 1) {
wlv.c_extra = '-';
wlv.c_final = NUL;
} else {
wlv.c_extra = wp->w_p_fcs_chars.diff;
wlv.c_final = NUL;
}
if (wp->w_p_rl) {
wlv.n_extra = wlv.col + 1;
} else {
wlv.n_extra = grid->cols - wlv.col;
}
wlv.char_attr = win_hl_attr(wp, HLF_DED);
}
char *const sbr = get_showbreak_value(wp);
if (*sbr != NUL && wlv.need_showbreak) {
// Draw 'showbreak' at the start of each broken line.
wlv.p_extra = sbr;
wlv.c_extra = NUL;
wlv.c_final = NUL;
wlv.n_extra = (int)strlen(sbr);
wlv.char_attr = win_hl_attr(wp, HLF_AT);
if (wp->w_skipcol == 0 || !wp->w_p_wrap) {
wlv.need_showbreak = false;
}
vcol_sbr = wlv.vcol + mb_charlen(sbr);
// Correct end of highlighted area for 'showbreak',
// required when 'linebreak' is also set.
if (wlv.tocol == wlv.vcol) {
wlv.tocol += wlv.n_extra;
}
// Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'.
if (wlv.cul_attr) {
wlv.char_attr = hl_combine_attr(wlv.cul_attr, wlv.char_attr);
}
}
handle_showbreak_and_filler(wp, &wlv);
}
if (wlv.draw_state == WL_LINE - 1 && wlv.n_extra == 0) {
sign_idx = 0;
wlv.draw_state = WL_LINE;
if (has_decor && wlv.row == startrow + wlv.filler_lines) {
// hide virt_text on text hidden by 'nowrap'
decor_redraw_col(wp->w_buffer, wlv.vcol, wlv.off, true, &decor_state);
}
if (saved_n_extra) {
// Continue item from end of wrapped line.
wlv.n_extra = saved_n_extra;
wlv.c_extra = saved_c_extra;
wlv.c_final = saved_c_final;
wlv.p_extra = saved_p_extra;
wlv.char_attr = saved_char_attr;
} else {
wlv.char_attr = 0;
}
win_line_continue(&wlv); // use wlv.saved_ values
}
}
@ -2011,7 +2036,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// We have just drawn the showbreak value, no need to add
// space for it again.
if (wlv.vcol == vcol_sbr) {
if (wlv.vcol == wlv.vcol_sbr) {
wlv.n_extra -= mb_charlen(get_showbreak_value(wp));
if (wlv.n_extra < 0) {
wlv.n_extra = 0;
@ -2112,7 +2137,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Only adjust the tab_len, when at the first column after the
// showbreak value was drawn.
if (*sbr != NUL && wlv.vcol == vcol_sbr && wp->w_p_wrap) {
if (*sbr != NUL && wlv.vcol == wlv.vcol_sbr && wp->w_p_wrap) {
vcol_adjusted = wlv.vcol - mb_charlen(sbr);
}
// tab amount depends on current column
@ -2850,16 +2875,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
break;
}
win_line_start(wp, &wlv);
win_line_start(wp, &wlv, true);
// reset the drawing state for the start of a wrapped line
wlv.draw_state = WL_START;
saved_n_extra = wlv.n_extra;
saved_p_extra = wlv.p_extra;
saved_c_extra = wlv.c_extra;
saved_c_final = wlv.c_final;
saved_char_attr = wlv.char_attr;
wlv.n_extra = 0;
lcs_prec_todo = wp->w_p_lcs_chars.prec;
if (wlv.filler_todo <= 0) {
wlv.need_showbreak = true;