aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/drawline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/drawline.c')
-rw-r--r--src/nvim/drawline.c431
1 files changed, 300 insertions, 131 deletions
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index b6c4400c60..8fc1a4b029 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -5,38 +5,69 @@
// This is the middle level, drawscreen.c is the top and grid.c/screen.c the lower level.
#include <assert.h>
-#include <inttypes.h>
+#include <limits.h>
#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "nvim/arabic.h"
+#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
+#include "nvim/decoration.h"
+#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
#include "nvim/drawline.h"
+#include "nvim/eval.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fold.h"
+#include "nvim/garray.h"
+#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
+#include "nvim/mark.h"
#include "nvim/match.h"
+#include "nvim/mbyte.h"
+#include "nvim/memline.h"
+#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/plines.h"
+#include "nvim/pos.h"
#include "nvim/quickfix.h"
-#include "nvim/search.h"
+#include "nvim/screen.h"
#include "nvim/sign.h"
#include "nvim/spell.h"
#include "nvim/state.h"
+#include "nvim/statusline.h"
+#include "nvim/strings.h"
#include "nvim/syntax.h"
-#include "nvim/undo.h"
-#include "nvim/window.h"
+#include "nvim/terminal.h"
+#include "nvim/types.h"
+#include "nvim/ui.h"
+#include "nvim/vim.h"
#define MB_FILLER_CHAR '<' // character used when a double-width character
// doesn't fit.
+/// possible draw states in win_line(), drawn in sequence.
+typedef enum {
+ WL_START = 0, // nothing done yet
+ WL_CMDLINE, // cmdline window column
+ WL_FOLD, // 'foldcolumn'
+ WL_SIGN, // column for signs
+ WL_NR, // line number
+ WL_STC, // 'statuscolumn'
+ WL_BRI, // 'breakindent'
+ WL_SBR, // 'showbreak' or 'diff'
+ WL_LINE, // text in the line
+} LineDrawState;
+
/// for line_putchar. Contains the state that needs to be remembered from
/// putting one character to the next.
typedef struct {
@@ -109,39 +140,39 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
/// Handles composing chars and arabic shaping state.
static int line_putchar(buf_T *buf, LineState *s, schar_T *dest, int maxcells, bool rl, int vcol)
{
- const char_u *p = (char_u *)s->p;
- int cells = utf_ptr2cells((char *)p);
- int c_len = utfc_ptr2len((char *)p);
+ const char *p = s->p;
+ int cells = utf_ptr2cells(p);
+ int c_len = utfc_ptr2len(p);
int u8c, u8cc[MAX_MCO];
if (cells > maxcells) {
return -1;
}
- u8c = utfc_ptr2char((char *)p, u8cc);
+ u8c = utfc_ptr2char(p, u8cc);
if (*p == TAB) {
cells = MIN(tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array), maxcells);
for (int c = 0; c < cells; c++) {
schar_from_ascii(dest[c], ' ');
}
goto done;
- } else if (*p < 0x80 && u8cc[0] == 0) {
- schar_from_ascii(dest[0], (char)(*p));
+ } else if ((uint8_t)(*p) < 0x80 && u8cc[0] == 0) {
+ schar_from_ascii(dest[0], *p);
s->prev_c = u8c;
} else {
if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c)) {
// Do Arabic shaping.
int pc, pc1, nc;
int pcc[MAX_MCO];
- int firstbyte = *p;
+ int firstbyte = (uint8_t)(*p);
// The idea of what is the previous and next
// character depends on 'rightleft'.
if (rl) {
pc = s->prev_c;
pc1 = s->prev_c1;
- nc = utf_ptr2char((char *)p + c_len);
+ nc = utf_ptr2char(p + c_len);
s->prev_c1 = u8cc[0];
} else {
- pc = utfc_ptr2char((char *)p + c_len, pcc);
+ pc = utfc_ptr2char(p + c_len, pcc);
nc = s->prev_c;
pc1 = pcc[0];
}
@@ -285,8 +316,8 @@ static bool use_cursor_line_sign(win_T *wp, linenr_T lnum)
// @param sign_idxp Index of the displayed sign
static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, SignTextAttrs sattrs[],
int row, int startrow, int filler_lines, int filler_todo,
- int *c_extrap, int *c_finalp, char_u *extra, size_t extra_size,
- char_u **pp_extra, int *n_extrap, int *char_attrp, int sign_idx,
+ int *c_extrap, int *c_finalp, char *extra, size_t extra_size,
+ char **pp_extra, int *n_extrap, int *char_attrp, int sign_idx,
int cul_attr)
{
// Draw cells with the sign value or blank.
@@ -320,16 +351,16 @@ static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, SignText
STRCAT(extra, *pp_extra);
STRCAT(extra, " ");
*pp_extra = extra;
- *n_extrap = (int)STRLEN(*pp_extra);
+ *n_extrap = (int)strlen(*pp_extra);
} else {
- size_t symbol_blen = STRLEN(*pp_extra);
+ size_t symbol_blen = strlen(*pp_extra);
// TODO(oni-link): Is sign text already extended to
// full cell width?
assert((size_t)win_signcol_width(wp) >= mb_string2cells((char *)(*pp_extra)));
// symbol(s) bytes + (filling spaces) (one byte each)
*n_extrap = (int)symbol_blen + win_signcol_width(wp) -
- (int)mb_string2cells((char *)(*pp_extra));
+ (int)mb_string2cells(*pp_extra);
assert(extra_size > symbol_blen);
memset(extra, ' ', extra_size);
@@ -367,6 +398,98 @@ static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int
return num_signs;
}
+/// Prepare and build the 'statuscolumn' string for line "lnum" in window "wp".
+/// Fill "stcp" with the built status column string and attributes.
+///
+/// @param[out] stcp Status column attributes
+static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines,
+ int cul_attr, int sign_num_attr, int sign_cul_attr, char_u *extra,
+ foldinfo_T foldinfo, SignTextAttrs *sattrs, statuscol_T *stcp)
+{
+ long relnum = 0;
+ bool wrapped = row != startrow + filler_lines;
+ bool use_cul = use_cursor_line_sign(wp, lnum);
+
+ // Set num, fold and sign text and attrs, empty when wrapped
+ if (row == startrow) {
+ relnum = labs(get_cursor_rel_lnum(wp, lnum));
+ stcp->num_attr = sign_num_attr ? sign_num_attr
+ : get_line_number_attr(wp, lnum, row, startrow, filler_lines);
+
+ if (compute_foldcolumn(wp, 0)) {
+ size_t n = fill_foldcolumn(stcp->fold_text, wp, foldinfo, lnum);
+ stcp->fold_text[n] = NUL;
+ stcp->fold_attr = win_hl_attr(wp, use_cul ? HLF_CLF : HLF_FC);
+ }
+ }
+
+ int i = 0;
+ for (; i < wp->w_scwidth; i++) {
+ SignTextAttrs *sattr = wrapped ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
+ stcp->sign_text[i] = sattr && sattr->text ? sattr->text : " ";
+ stcp->sign_attr[i] = sattr ? (use_cul && sign_cul_attr ? sign_cul_attr : sattr->hl_attr_id)
+ : win_hl_attr(wp, use_cul ? HLF_CLS : HLF_SC);
+ }
+ stcp->sign_text[i] = NULL;
+
+ int width = build_statuscol_str(wp, row == startrow, wrapped, lnum, relnum,
+ stcp->width, ' ', stcp->text, &stcp->hlrec, 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) { // Avoid truncating 'statuscolumn'
+ wp->w_nrwidth = MIN(MAX_NUMBERWIDTH, wp->w_nrwidth + stcp->truncate);
+ wp->w_nrwidth_width = wp->w_nrwidth;
+ } else { // 'statuscolumn' reset due to error
+ wp->w_nrwidth_line_count = 0;
+ wp->w_nrwidth = (wp->w_p_nu || wp->w_p_rnu) * number_width(wp);
+ }
+ wp->w_redr_statuscol = true;
+ 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;
+ }
+}
+
+/// Get information needed to display the next segment in the 'statuscolumn'.
+/// If not yet at the end, prepare for next segment and decrement "draw_state".
+///
+/// @param stcp Status column attributes
+/// @param[out] draw_state Current draw state in win_line()
+static void get_statuscol_display_info(LineDrawState *draw_state, int *char_attr, int *n_extrap,
+ int *c_extrap, int *c_finalp, char_u *extra, char **pp_extra,
+ statuscol_T *stcp)
+{
+ *c_extrap = NUL;
+ *c_finalp = NUL;
+ do {
+ *draw_state = WL_STC;
+ *char_attr = stcp->cur_attr;
+ *pp_extra = stcp->textp;
+ *n_extrap = (int)((stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end) - stcp->textp);
+ // Prepare for next highlight section if not yet at the end
+ if (stcp->textp + *n_extrap < stcp->text_end) {
+ int hl = stcp->hlrecp->userhl;
+ stcp->textp = stcp->hlrecp->start;
+ stcp->cur_attr = hl < 0 ? syn_id2attr(-stcp->hlrecp->userhl)
+ : hl > 0 ? hl : stcp->num_attr;
+ stcp->hlrecp++;
+ *draw_state = WL_STC - 1;
+ }
+ // Skip over empty highlight sections
+ } while (*n_extrap == 0 && stcp->textp < stcp->text_end);
+}
+
/// Return true if CursorLineNr highlight is to be used for the number column.
///
/// - 'cursorline' must be set
@@ -480,29 +603,28 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
long vcol = 0; // virtual column (for tabs)
long vcol_sbr = -1; // virtual column after showbreak
long vcol_prev = -1; // "vcol" of previous character
- char_u *line; // current line
- char_u *ptr; // current position in "line"
+ char *line; // current line
+ char *ptr; // current position in "line"
int row; // row in the window, excl w_winrow
ScreenGrid *grid = &wp->w_grid; // grid specific to the window
char_u extra[57]; // sign, line number and 'fdc' must
// fit in here
int n_extra = 0; // number of extra chars
- char_u *p_extra = NULL; // string of extra chars, plus NUL
- char_u *p_extra_free = NULL; // p_extra needs to be freed
+ char *p_extra = NULL; // string of extra chars, plus NUL
+ char *p_extra_free = NULL; // p_extra needs to be freed
int c_extra = NUL; // extra chars, all the same
int c_final = NUL; // final char, mandatory if set
int extra_attr = 0; // attributes when n_extra != 0
- static char_u *at_end_str = (char_u *)""; // used for p_extra when displaying
- // curwin->w_p_lcs_chars.eol at
- // end-of-line
+ static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol
+ // at end-of-line
int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used
int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used
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_u *saved_p_extra = NULL;
+ char *saved_p_extra = NULL;
int saved_c_extra = 0;
int saved_c_final = 0;
int saved_char_attr = 0;
@@ -525,7 +647,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
int char_attr = 0; // attributes for next character
bool attr_pri = false; // char_attr has priority
bool area_highlighting = false; // Visual or incsearch highlighting in this line
- int attr = 0; // attributes for area highlighting
+ int vi_attr = 0; // attributes for Visual and incsearch highlighting
int area_attr = 0; // attributes desired by highlighting
int search_attr = 0; // attributes desired by 'hlsearch'
int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
@@ -537,7 +659,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
int *color_cols = NULL; // pointer to according columns array
bool has_spell = false; // this buffer has spell checking
#define SPWORDLEN 150
- char_u nextline[SPWORDLEN * 2]; // text with start of the next line
+ char nextline[SPWORDLEN * 2]; // text with start of the next line
int nextlinecol = 0; // column where nextline[] starts
int nextline_idx = 0; // index in nextline[] where next line
// starts
@@ -576,7 +698,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
bool has_decor = false; // this buffer has decoration
int win_col_offset = 0; // offset for window columns
- char_u buf_fold[FOLD_TEXT_LEN]; // Hold value returned by get_foldtext
+ char buf_fold[FOLD_TEXT_LEN]; // Hold value returned by get_foldtext
bool area_active = false;
@@ -588,17 +710,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
int left_curline_col = 0;
int right_curline_col = 0;
- // draw_state: items that are drawn in sequence:
-#define WL_START 0 // nothing done yet
-#define WL_CMDLINE (WL_START + 1) // cmdline window column
-#define WL_FOLD (WL_CMDLINE + 1) // 'foldcolumn'
-#define WL_SIGN (WL_FOLD + 1) // column for signs
-#define WL_NR (WL_SIGN + 1) // line number
-#define WL_BRI (WL_NR + 1) // 'breakindent'
-#define WL_SBR (WL_BRI + 1) // 'showbreak' or 'diff'
-#define WL_LINE (WL_SBR + 1) // text in the line
- int draw_state = WL_START; // what to draw next
+ LineDrawState draw_state = WL_START; // what to draw next
+ int match_conc = 0; ///< cchar for match functions
+ bool on_last_col = false;
int syntax_flags = 0;
int syntax_seqnr = 0;
int prev_syntax_id = 0;
@@ -608,7 +723,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
///< force wrapping
int vcol_off = 0; ///< offset for concealed characters
int did_wcol = false;
- int match_conc = 0; ///< cchar for match functions
int old_boguscols = 0;
#define VCOL_HLC (vcol - vcol_off)
#define FIX_FOR_BOGUSCOLS \
@@ -654,7 +768,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
has_decor = decor_redraw_line(buf, lnum - 1, &decor_state);
- providers_invoke_line(wp, providers, lnum - 1, &has_decor, provider_err);
+ decor_providers_invoke_line(wp, providers, lnum - 1, &has_decor, provider_err);
if (*provider_err) {
provider_err_virt_text(lnum, *provider_err);
@@ -688,7 +802,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
nextline[SPWORDLEN] = NUL;
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
line = ml_get_buf(wp->w_buffer, lnum + 1, false);
- spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN);
+ spell_cat_line(nextline + SPWORDLEN, (char_u *)line, SPWORDLEN);
}
// When a word wrapped from the previous line the start of the current
@@ -772,7 +886,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// if inverting in this line set area_highlighting
if (fromcol >= 0) {
area_highlighting = true;
- attr = win_hl_attr(wp, HLF_V);
+ vi_attr = win_hl_attr(wp, HLF_V);
}
// handle 'incsearch' and ":s///c" highlighting
} else if (highlight_match
@@ -796,15 +910,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
tocol = fromcol + 1;
}
area_highlighting = true;
- attr = win_hl_attr(wp, HLF_I);
+ vi_attr = win_hl_attr(wp, HLF_I);
}
}
int bg_attr = win_bg_attr(wp);
- filler_lines = diff_check(wp, lnum);
- if (filler_lines < 0) {
- if (filler_lines == -1) {
+ int linestatus = 0;
+ filler_lines = diff_check_with_linestatus(wp, lnum, &linestatus);
+ if (filler_lines < 0 || linestatus < 0) {
+ if (filler_lines == -1 || linestatus == -1) {
if (diff_find_change(wp, lnum, &change_start, &change_end)) {
diff_hlf = HLF_ADD; // added line
} else if (change_start == 0) {
@@ -815,7 +930,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
} else {
diff_hlf = HLF_ADD; // added line
}
- filler_lines = 0;
+ if (linestatus == 0) {
+ filler_lines = 0;
+ }
area_highlighting = true;
}
VirtLines virt_lines = KV_INITIAL_VALUE;
@@ -864,13 +981,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
line_attr_lowprio_save = line_attr_lowprio;
}
- line = end_fill ? (char_u *)"" : ml_get_buf(wp->w_buffer, lnum, false);
+ line = end_fill ? "" : ml_get_buf(wp->w_buffer, lnum, false);
ptr = line;
if (has_spell && !number_only) {
// For checking first word with a capital skip white space.
if (cap_col == 0) {
- cap_col = (int)getwhitecols((char *)line);
+ cap_col = (int)getwhitecols(line);
}
// To be able to spell-check over line boundaries copy the end of the
@@ -881,7 +998,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
nextlinecol = MAXCOL;
nextline_idx = 0;
} else {
- v = (long)STRLEN(line);
+ v = (long)strlen(line);
if (v < SPWORDLEN) {
// Short line, use it completely and append the start of the
// next line.
@@ -892,7 +1009,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
} else {
// Long line, use only the last SPWORDLEN bytes.
nextlinecol = (int)v - SPWORDLEN;
- memmove(nextline, line + nextlinecol, SPWORDLEN); // -V512
+ memmove(nextline, line + nextlinecol, SPWORDLEN); // -V1086
nextline_idx = SPWORDLEN + 1;
}
}
@@ -909,7 +1026,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
// find start of trailing whitespace
if (wp->w_p_lcs_chars.trail) {
- trailcol = (colnr_T)STRLEN(ptr);
+ trailcol = (colnr_T)strlen(ptr);
while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1])) {
trailcol--;
}
@@ -939,7 +1056,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
v = wp->w_leftcol;
}
if (v > 0 && !number_only) {
- char_u *prev_ptr = ptr;
+ char *prev_ptr = ptr;
chartabsize_T cts;
int charsize;
@@ -947,11 +1064,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
while (cts.cts_vcol < v && *cts.cts_ptr != NUL) {
charsize = win_lbr_chartabsize(&cts, NULL);
cts.cts_vcol += charsize;
- prev_ptr = (char_u *)cts.cts_ptr;
+ prev_ptr = cts.cts_ptr;
MB_PTR_ADV(cts.cts_ptr);
}
vcol = cts.cts_vcol;
- ptr = (char_u *)cts.cts_ptr;
+ ptr = cts.cts_ptr;
clear_chartabsize_arg(&cts);
// When:
@@ -974,7 +1091,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
ptr = prev_ptr;
// If the character fits on the screen, don't need to skip it.
// Except for a TAB.
- if (utf_ptr2cells((char *)ptr) >= charsize || *ptr == TAB) {
+ if (utf_ptr2cells(ptr) >= charsize || *ptr == TAB) {
n_skip = (int)(v - vcol);
}
}
@@ -1011,7 +1128,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// no bad word found at line start, don't check until end of a
// word
spell_hlf = HLF_COUNT;
- word_end = (int)(spell_to_word_end(ptr, wp) - line + 1);
+ word_end = (int)(spell_to_word_end((char_u *)ptr, wp) - (char_u *)line + 1);
} else {
// bad word found, use attributes until end of word
assert(len <= INT_MAX);
@@ -1075,6 +1192,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
extra_check = true;
}
+ statuscol_T statuscol = { 0 };
+ if (*wp->w_p_stc != NUL) {
+ // Draw the 'statuscolumn' if option is set.
+ statuscol.draw = true;
+ statuscol.width = win_col_off(wp);
+ }
+
int sign_idx = 0;
// Repeat for the whole displayed line.
for (;;) {
@@ -1102,9 +1226,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
+ // Skip fold, sign and number states if 'statuscolumn' is set.
+ if (draw_state == WL_FOLD - 1 && n_extra == 0 && statuscol.draw) {
+ draw_state = WL_STC - 1;
+ }
+
if (draw_state == WL_FOLD - 1 && n_extra == 0) {
int fdc = compute_foldcolumn(wp, 0);
-
draw_state = WL_FOLD;
if (fdc > 0) {
// Draw the 'foldcolumn'. Allocate a buffer, "extra" may
@@ -1131,7 +1259,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wp->w_scwidth > 0) {
get_sign_display_info(false, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
- &c_extra, &c_final, extra, sizeof(extra),
+ &c_extra, &c_final, (char *)extra, sizeof(extra),
&p_extra, &n_extra, &char_attr, sign_idx,
sign_cul_attr);
sign_idx++;
@@ -1156,7 +1284,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) {
get_sign_display_info(true, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
- &c_extra, &c_final, extra, sizeof(extra),
+ &c_extra, &c_final, (char *)extra, sizeof(extra),
&p_extra, &n_extra, &char_attr, sign_idx,
sign_cul_attr);
} else {
@@ -1164,21 +1292,21 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (row == startrow + filler_lines) {
get_line_number_str(wp, lnum, (char_u *)extra, sizeof(extra));
if (wp->w_skipcol > 0) {
- for (p_extra = extra; *p_extra == ' '; p_extra++) {
+ for (p_extra = (char *)extra; *p_extra == ' '; p_extra++) {
*p_extra = '-';
}
}
if (wp->w_p_rl) { // reverse line numbers
// like rl_mirror(), but keep the space at the end
- char_u *p2 = (char_u *)skipwhite((char *)extra);
- p2 = (char_u *)skiptowhite((char *)p2) - 1;
- for (char_u *p1 = (char_u *)skipwhite((char *)extra); p1 < p2; p1++, p2--) {
- const char_u t = *p1;
+ char *p2 = skipwhite((char *)extra);
+ p2 = skiptowhite(p2) - 1;
+ for (char *p1 = skipwhite((char *)extra); p1 < p2; p1++, p2--) {
+ const char t = *p1;
*p1 = *p2;
*p2 = t;
}
}
- p_extra = extra;
+ p_extra = (char *)extra;
c_extra = NUL;
} else {
c_extra = ' ';
@@ -1194,7 +1322,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
- if (draw_state == WL_NR && n_extra == 0) {
+ if (draw_state == WL_STC - 1 && n_extra == 0) {
+ draw_state = WL_STC;
+ // Draw the 'statuscolumn' if option is set.
+ if (statuscol.draw) {
+ if (statuscol.textp == NULL) {
+ get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr, sign_num_attr,
+ sign_cul_attr, extra, foldinfo, sattrs, &statuscol);
+ if (wp->w_redr_statuscol) {
+ return 0;
+ }
+ }
+ get_statuscol_display_info(&draw_state, &char_attr, &n_extra, &c_extra,
+ &c_final, extra, &p_extra, &statuscol);
+ }
+ }
+
+ if (draw_state == WL_STC && n_extra == 0) {
win_col_offset = off;
}
@@ -1269,13 +1413,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
char_attr = win_hl_attr(wp, HLF_DED);
}
- char_u *const sbr = get_showbreak_value(wp);
+ char *const sbr = (char *)get_showbreak_value(wp);
if (*sbr != NUL && need_showbreak) {
// Draw 'showbreak' at the start of each broken line.
p_extra = sbr;
c_extra = NUL;
c_final = NUL;
- n_extra = (int)STRLEN(sbr);
+ n_extra = (int)strlen(sbr);
char_attr = win_hl_attr(wp, HLF_AT);
if (wp->w_skipcol == 0 || !wp->w_p_wrap) {
need_showbreak = false;
@@ -1326,7 +1470,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& wp == curwin
&& lnum == wp->w_cursor.lnum
&& vcol >= (long)wp->w_virtcol)
- || (number_only && draw_state > WL_NR))
+ || (number_only && draw_state > WL_STC))
&& filler_todo <= 0) {
draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row);
grid_put_linebuf(grid, row, 0, col, -grid->cols, wp->w_p_rl, wp, bg_attr, false);
@@ -1350,7 +1494,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
memset(buf_fold, ' ', FOLD_TEXT_LEN);
p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold);
- n_extra = (int)STRLEN(p_extra);
+ n_extra = (int)strlen(p_extra);
if (p_extra != buf_fold) {
xfree(p_extra_free);
@@ -1386,11 +1530,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// handle Visual or match highlighting in this line
if (vcol == fromcol
|| (vcol + 1 == fromcol && n_extra == 0
- && utf_ptr2cells((char *)ptr) > 1)
+ && utf_ptr2cells(ptr) > 1)
|| ((int)vcol_prev == fromcol_prev
&& vcol_prev < vcol // not at margin
&& vcol < tocol)) {
- area_attr = attr; // start highlighting
+ area_attr = vi_attr; // start highlighting
if (area_highlighting) {
area_active = true;
}
@@ -1407,8 +1551,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// When another match, have to check for start again.
v = (ptr - line);
search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, &screen_search_hl,
- &has_match_conc,
- &match_conc, lcs_eol_one, &search_attr_from_match);
+ &has_match_conc, &match_conc, lcs_eol_one,
+ &on_last_col, &search_attr_from_match);
ptr = line + v; // "line" may have been changed
// Do not allow a conceal over EOL otherwise EOL will be missed
@@ -1480,16 +1624,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
mb_utf8 = check_mb_utf8(&c, u8cc);
} else {
assert(p_extra != NULL);
- c = *p_extra;
+ c = (uint8_t)(*p_extra);
mb_c = c;
// If the UTF-8 character is more than one byte:
// Decode it into "mb_c".
- mb_l = utfc_ptr2len((char *)p_extra);
+ mb_l = utfc_ptr2len(p_extra);
mb_utf8 = false;
if (mb_l > n_extra) {
mb_l = 1;
} else if (mb_l > 1) {
- mb_c = utfc_ptr2char((char *)p_extra, u8cc);
+ mb_c = utfc_ptr2char(p_extra, u8cc);
mb_utf8 = true;
c = 0xc0;
}
@@ -1533,14 +1677,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
XFREE_CLEAR(p_extra_free);
// Get a character from the line itself.
- c0 = c = *ptr;
+ c0 = c = (uint8_t)(*ptr);
mb_c = c;
// If the UTF-8 character is more than one byte: Decode it
// into "mb_c".
- mb_l = utfc_ptr2len((char *)ptr);
+ mb_l = utfc_ptr2len(ptr);
mb_utf8 = false;
if (mb_l > 1) {
- mb_c = utfc_ptr2char((char *)ptr, u8cc);
+ mb_c = utfc_ptr2char(ptr, u8cc);
// Overlong encoded ASCII or ASCII with composing char
// is displayed normally, except a NUL.
if (mb_c < 0x80) {
@@ -1568,14 +1712,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Non-BMP character : display as ? or fullwidth ?.
transchar_hex((char *)extra, mb_c);
if (wp->w_p_rl) { // reverse
- rl_mirror(extra);
+ rl_mirror((char *)extra);
}
- p_extra = extra;
- c = *p_extra;
+ p_extra = (char *)extra;
+ c = (uint8_t)(*p_extra);
mb_c = mb_ptr2char_adv((const char_u **)&p_extra);
mb_utf8 = (c >= 0x80);
- n_extra = (int)STRLEN(p_extra);
+ n_extra = (int)strlen(p_extra);
c_extra = NUL;
c_final = NUL;
if (area_attr == 0 && search_attr == 0) {
@@ -1595,10 +1739,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wp->w_p_rl) {
pc = prev_c;
pc1 = prev_c1;
- nc = utf_ptr2char((char *)ptr + mb_l);
+ nc = utf_ptr2char(ptr + mb_l);
prev_c1 = u8cc[0];
} else {
- pc = utfc_ptr2char((char *)ptr + mb_l, pcc);
+ pc = utfc_ptr2char(ptr + mb_l, pcc);
nc = prev_c;
pc1 = pcc[0];
}
@@ -1646,7 +1790,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
ptr++;
if (extra_check) {
- bool can_spell = true;
+ bool no_plain_buffer = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) != 0;
+ bool can_spell = !no_plain_buffer;
// Get syntax attribute, unless still at the start of the line
// (double-wide char that doesn't fit).
@@ -1698,6 +1843,27 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
char_attr = 0;
}
+ if (has_decor && v > 0) {
+ bool selected = (area_active || (area_highlighting && noinvcur
+ && (colnr_T)vcol == wp->w_virtcol));
+ int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off,
+ selected, &decor_state);
+ if (extmark_attr != 0) {
+ if (!attr_pri) {
+ char_attr = hl_combine_attr(char_attr, extmark_attr);
+ } else {
+ char_attr = hl_combine_attr(extmark_attr, char_attr);
+ }
+ }
+
+ decor_conceal = decor_state.conceal;
+ if (decor_conceal && decor_state.conceal_char) {
+ decor_conceal = 2; // really??
+ }
+
+ can_spell = TRISTATE_TO_BOOL(decor_state.spell, can_spell);
+ }
+
// Check spelling (unless at the end of the line).
// Only do this when there is no syntax highlighting, the
// @Spell cluster is not used or the current syntax item
@@ -1706,11 +1872,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (has_spell && v >= word_end && v > cur_checked_col) {
spell_attr = 0;
if (!attr_pri) {
- char_attr = syntax_attr;
+ char_attr = hl_combine_attr(char_attr, syntax_attr);
}
- if (c != 0 && (!has_syntax || can_spell)) {
- char_u *prev_ptr;
- char_u *p;
+ if (c != 0 && ((!has_syntax && !no_plain_buffer) || can_spell)) {
+ char *prev_ptr;
+ char *p;
int len;
hlf_T spell_hlf = HLF_COUNT;
prev_ptr = ptr - mb_l;
@@ -1724,7 +1890,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
p = prev_ptr;
}
cap_col -= (int)(prev_ptr - line);
- size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, nochange);
+ size_t tmplen = spell_check(wp, (char_u *)p, &spell_hlf, &cap_col, nochange);
assert(tmplen <= INT_MAX);
len = (int)tmplen;
word_end = (int)v + len;
@@ -1781,30 +1947,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
char_attr = hl_combine_attr(term_attrs[vcol], char_attr);
}
- if (has_decor && v > 0) {
- bool selected = (area_active || (area_highlighting && noinvcur
- && (colnr_T)vcol == wp->w_virtcol));
- int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off,
- selected, &decor_state);
- if (extmark_attr != 0) {
- if (!attr_pri) {
- char_attr = hl_combine_attr(char_attr, extmark_attr);
- } else {
- char_attr = hl_combine_attr(extmark_attr, char_attr);
- }
- }
-
- decor_conceal = decor_state.conceal;
- if (decor_conceal && decor_state.conceal_char) {
- decor_conceal = 2; // really??
- }
- }
-
// Found last space before word: check for line break.
if (wp->w_p_lbr && c0 == c && vim_isbreak(c)
&& !vim_isbreak((int)(*ptr))) {
int mb_off = utf_head_off(line, ptr - 1);
- char_u *p = ptr - (mb_off + 1);
+ char *p = ptr - (mb_off + 1);
chartabsize_T cts;
init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, p);
@@ -1813,11 +1960,17 @@ 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 (vcol == vcol_sbr) {
- n_extra -= mb_charlen(get_showbreak_value(wp));
+ n_extra -= mb_charlen((char *)get_showbreak_value(wp));
if (n_extra < 0) {
n_extra = 0;
}
}
+ if (on_last_col && c != TAB) {
+ // Do not continue search/match highlighting over the
+ // line break, but for TABs the highlighting should
+ // include the complete width of the character
+ search_attr = 0;
+ }
if (c == TAB && n_extra + col > grid->cols) {
n_extra = tabstop_padding((colnr_T)vcol, wp->w_buffer->b_p_ts,
@@ -1908,7 +2061,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 && vcol == vcol_sbr && wp->w_p_wrap) {
- vcol_adjusted = vcol - mb_charlen(sbr);
+ vcol_adjusted = vcol - mb_charlen((char *)sbr);
}
// tab amount depends on current column
tab_len = tabstop_padding((colnr_T)vcol_adjusted,
@@ -1918,7 +2071,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (!wp->w_p_lbr || !wp->w_p_list) {
n_extra = tab_len;
} else {
- char_u *p;
+ char *p;
int i;
int saved_nextra = n_extra;
@@ -1959,7 +2112,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wp->w_p_lcs_chars.tab3 && i == tab_len - 1) {
lcs = wp->w_p_lcs_chars.tab3;
}
- p += utf_char2bytes(lcs, (char *)p);
+ p += utf_char2bytes(lcs, p);
n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0);
}
p_extra = p_extra_free;
@@ -2051,7 +2204,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
mb_c = c;
mb_utf8 = check_mb_utf8(&c, u8cc);
} else if (c != NUL) {
- p_extra = transchar_buf(wp->w_buffer, c);
+ p_extra = (char *)transchar_buf(wp->w_buffer, c);
if (n_extra == 0) {
n_extra = byte2cells(c) - 1;
}
@@ -2061,18 +2214,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
c_extra = NUL;
c_final = NUL;
if (wp->w_p_lbr) {
- char_u *p;
+ char *p;
- c = *p_extra;
+ c = (uint8_t)(*p_extra);
p = xmalloc((size_t)n_extra + 1);
memset(p, ' ', (size_t)n_extra);
- STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1); // NOLINT(runtime/printf)
+ strncpy(p, // NOLINT(runtime/printf)
+ p_extra + 1,
+ (size_t)strlen(p_extra) - 1);
p[n_extra] = NUL;
xfree(p_extra_free);
p_extra_free = p_extra = p;
} else {
n_extra = byte2cells(c) - 1;
- c = *p_extra++;
+ c = (uint8_t)(*p_extra++);
}
n_attr = n_extra + 1;
extra_attr = win_hl_attr(wp, HLF_8);
@@ -2180,7 +2335,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& wp->w_p_list
&& (wp->w_p_wrap ? (wp->w_skipcol > 0 && row == 0) : wp->w_leftcol > 0)
&& filler_todo <= 0
- && draw_state > WL_NR
+ && draw_state > WL_STC
&& c != NUL) {
c = wp->w_p_lcs_chars.prec;
lcs_prec_todo = NUL;
@@ -2205,7 +2360,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// flag to indicate whether prevcol equals startcol of search_hl or
// one of the matches
bool prevcol_hl_flag = get_prevcol_hl_flag(wp, &screen_search_hl,
- (long)(ptr - line) - 1);
+ (long)(ptr - line) - 1); // NOLINT(google-readability-casting)
// Invert at least one char, used for Visual and empty line or
// highlight match at end of line. If it's beyond the last
@@ -2241,7 +2396,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (area_attr == 0 && !has_fold) {
// Use attributes from match with highest priority among
// 'search_hl' and the match list.
- get_search_match_hl(wp, &screen_search_hl, (long)(ptr - line), &char_attr);
+ get_search_match_hl(wp,
+ &screen_search_hl,
+ (long)(ptr - line), // NOLINT(google-readability-casting)
+ &char_attr);
}
int eol_attr = char_attr;
@@ -2471,7 +2629,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
col++;
// UTF-8: Put a 0 in the second screen char.
linebuf_char[off][0] = 0;
- if (draw_state > WL_NR && filler_todo <= 0) {
+ if (draw_state > WL_STC && filler_todo <= 0) {
vcol++;
}
// When "tocol" is halfway through a character, set it to the end of
@@ -2554,7 +2712,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Only advance the "vcol" when after the 'number' or 'relativenumber'
// column.
- if (draw_state > WL_NR
+ if (draw_state > WL_STC
&& filler_todo <= 0) {
vcol++;
}
@@ -2564,7 +2722,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
// restore attributes after "predeces" in 'listchars'
- if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0) {
+ if (draw_state > WL_STC && n_attr3 > 0 && --n_attr3 == 0) {
char_attr = saved_attr3;
}
@@ -2600,7 +2758,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
assert(i >= 0);
int offset = kv_A(virt_lines, i).left_col ? 0 : win_col_offset;
draw_virt_text_item(buf, offset, kv_A(virt_lines, i).line,
- kHlModeReplace, grid->cols, offset);
+ kHlModeReplace, grid->cols, 0);
}
} else {
draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, row);
@@ -2631,6 +2789,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// When the window is too narrow draw all "@" lines.
if (draw_state != WL_LINE && filler_todo <= 0) {
win_draw_end(wp, '@', ' ', true, row, wp->w_grid.rows, HLF_AT);
+ set_empty_rows(wp, row);
row = endrow;
}
@@ -2659,6 +2818,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (filler_todo <= 0) {
need_showbreak = true;
}
+ if (statuscol.draw) {
+ if (row == startrow + 1 || row == startrow + filler_lines) {
+ // Re-evaluate 'statuscolumn' for the first wrapped row and non filler line
+ statuscol.textp = NULL;
+ } else { // Otherwise just reset the text/hlrec pointers
+ statuscol.textp = statuscol.text;
+ statuscol.hlrecp = statuscol.hlrec;
+ } // Fall back to default columns if the 'n' flag isn't in 'cpo'
+ statuscol.draw = vim_strchr(p_cpo, CPO_NUMCOL) == NULL;
+ }
filler_todo--;
// When the filler lines are actually below the last line of the
// file, don't draw the line itself, break here.
@@ -2669,7 +2838,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
} // for every character in the line
// After an empty line check first word for capital.
- if (*skipwhite((char *)line) == NUL) {
+ if (*skipwhite(line) == NUL) {
capcol_lnum = lnum + 1;
cap_col = 0;
}