aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/drawscreen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/drawscreen.c')
-rw-r--r--src/nvim/drawscreen.c687
1 files changed, 310 insertions, 377 deletions
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 6cc623cb72..145229bacc 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -1,5 +1,5 @@
// drawscreen.c: Code for updating all the windows on the screen.
-// This is the top level, drawline.c is the middle and grid.c/screen.c the lower level.
+// This is the top level, drawline.c is the middle and grid.c the lower level.
// update_screen() is the function that updates all windows and status lines.
// It is called from the main loop when must_redraw is non-zero. It may be
@@ -59,15 +59,16 @@
#include <stdlib.h>
#include <string.h>
-#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
#include "nvim/digraph.h"
@@ -76,31 +77,36 @@
#include "nvim/eval.h"
#include "nvim/ex_getln.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
+#include "nvim/fold_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/insexpand.h"
+#include "nvim/marktree_defs.h"
#include "nvim/match.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
+#include "nvim/os/os_defs.h"
#include "nvim/plines.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
#include "nvim/search.h"
-#include "nvim/sign_defs.h"
#include "nvim/spell.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
@@ -108,10 +114,13 @@
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
+#include "nvim/ui_defs.h"
#include "nvim/version.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#include "klib/kvec.h"
+
/// corner value flags for hsep_connected and vsep_connected
typedef enum {
WC_TOP_LEFT = 0,
@@ -151,8 +160,8 @@ void conceal_check_cursor_line(void)
/// There may be some time between setting Rows and Columns and (re)allocating
/// default_grid arrays. This happens when starting up and when
/// (manually) changing the screen size. Always use default_grid.rows and
-/// default_grid.Columns to access items in default_grid.chars[]. Use Rows
-/// and Columns for positioning text etc. where the final size of the screen is
+/// default_grid.cols to access items in default_grid.chars[]. Use Rows and
+/// Columns for positioning text etc. where the final size of the screen is
/// needed.
///
/// @return whether resizing has been done
@@ -171,12 +180,8 @@ bool default_grid_alloc(void)
// Allocation of the screen buffers is done only when the size changes and
// when Rows and Columns have been set and we have started doing full
// screen stuff.
- if ((default_grid.chars != NULL
- && Rows == default_grid.rows
- && Columns == default_grid.cols)
- || Rows == 0
- || Columns == 0
- || (!full_screen && default_grid.chars == NULL)) {
+ if ((default_grid.chars != NULL && Rows == default_grid.rows && Columns == default_grid.cols)
+ || Rows == 0 || Columns == 0 || (!full_screen && default_grid.chars == NULL)) {
resizing = false;
return false;
}
@@ -194,8 +199,8 @@ bool default_grid_alloc(void)
grid_alloc(&default_grid, Rows, Columns, true, true);
stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
- tab_page_click_defs = stl_alloc_click_defs(tab_page_click_defs, Columns,
- &tab_page_click_defs_size);
+ tab_page_click_defs
+ = stl_alloc_click_defs(tab_page_click_defs, Columns, &tab_page_click_defs_size);
default_grid.comp_height = Rows;
default_grid.comp_width = Columns;
@@ -218,8 +223,7 @@ void screenclear(void)
// blank out the default grid
for (int i = 0; i < default_grid.rows; i++) {
- grid_clear_line(&default_grid, default_grid.line_offset[i],
- default_grid.cols, true);
+ grid_clear_line(&default_grid, default_grid.line_offset[i], default_grid.cols, true);
}
ui_call_grid_clear(1); // clear the display
@@ -266,7 +270,7 @@ void screen_resize(int width, int height)
return;
}
- if (width < 0 || height < 0) { // just checking...
+ if (width < 0 || height < 0) { // just checking...
return;
}
@@ -307,9 +311,9 @@ void screen_resize(int width, int height)
RedrawingDisabled++;
- win_new_screensize(); // fit the windows in the new sized screen
+ win_new_screensize(); // fit the windows in the new sized screen
- comp_col(); // recompute columns for shown command and ruler
+ comp_col(); // recompute columns for shown command and ruler
RedrawingDisabled--;
@@ -403,8 +407,7 @@ void check_screensize(void)
/// Return true if redrawing should currently be done.
bool redrawing(void)
{
- return !RedrawingDisabled
- && !(p_lz && char_avail() && !KeyTyped && !do_redraw);
+ return !RedrawingDisabled && !(p_lz && char_avail() && !KeyTyped && !do_redraw);
}
/// Redraw the parts of the screen that is marked for redraw.
@@ -443,7 +446,7 @@ int update_screen(void)
// will be redrawn later or in win_update().
must_redraw = 0;
- updating_screen = 1;
+ updating_screen = true;
display_tick++; // let syntax code know we're in a next round of
// display updating
@@ -475,8 +478,7 @@ int update_screen(void)
if (msg_grid.chars) {
// non-displayed part of msg_grid is considered invalid.
for (int i = 0; i < MIN(msg_scrollsize(), msg_grid.rows); i++) {
- grid_clear_line(&msg_grid, msg_grid.line_offset[i],
- msg_grid.cols, i < p_ch);
+ grid_clear_line(&msg_grid, msg_grid.line_offset[i], msg_grid.cols, i < p_ch);
}
}
msg_grid.throttled = false;
@@ -486,8 +488,7 @@ int update_screen(void)
if (type == UPD_NOT_VALID && !ui_has(kUIMultigrid) && msg_scrolled) {
was_invalidated = ui_comp_set_screen_valid(false);
for (int i = valid; i < Rows - p_ch; i++) {
- grid_clear_line(&default_grid, default_grid.line_offset[i],
- Columns, false);
+ grid_clear_line(&default_grid, default_grid.line_offset[i], Columns, false);
}
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_floating) {
@@ -533,10 +534,10 @@ int update_screen(void)
hl_changed = true;
}
- if (type == UPD_CLEAR) { // first clear screen
- screenclear(); // will reset clear_cmdline
- // and set UPD_NOT_VALID for each window
- cmdline_screen_cleared(); // clear external cmdline state
+ if (type == UPD_CLEAR) { // first clear screen
+ screenclear(); // will reset clear_cmdline
+ // and set UPD_NOT_VALID for each window
+ cmdline_screen_cleared(); // clear external cmdline state
type = UPD_NOT_VALID;
// must_redraw may be set indirectly, avoid another redraw later
must_redraw = 0;
@@ -547,13 +548,12 @@ int update_screen(void)
// might need to clear space on default_grid for the message area.
if (type == UPD_NOT_VALID && clear_cmdline && !ui_has(kUIMessages)) {
- grid_fill(&default_grid, Rows - (int)p_ch, Rows, 0, Columns, ' ', ' ', 0);
+ grid_clear(&default_grid, Rows - (int)p_ch, Rows, 0, Columns, 0);
}
ui_comp_set_screen_valid(true);
- DecorProviders providers;
- decor_providers_start(&providers);
+ decor_providers_start();
// "start" callback could have changed highlights for global elements
if (win_check_ns_hl(NULL)) {
@@ -561,7 +561,7 @@ int update_screen(void)
redraw_tabline = true;
}
- if (clear_cmdline) { // going to clear cmdline (done below)
+ if (clear_cmdline) { // going to clear cmdline (done below)
msg_check_for_delay(false);
}
@@ -570,8 +570,9 @@ int update_screen(void)
// TODO(bfredl): special casing curwin here is SÅ JÄVLA BULL.
// Either this should be done for all windows or not at all.
if (curwin->w_redr_type < UPD_NOT_VALID
- && curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu || *curwin->w_p_stc)
- ? number_width(curwin) : 0)) {
+ && curwin->w_nrwidth
+ != ((curwin->w_p_nu || curwin->w_p_rnu || *curwin->w_p_stc) ? number_width(curwin)
+ : 0)) {
curwin->w_redr_type = UPD_NOT_VALID;
}
@@ -593,26 +594,16 @@ int update_screen(void)
buf_T *buf = wp->w_buffer;
if (buf->b_mod_set) {
- if (buf->b_mod_tick_syn < display_tick
- && syntax_present(wp)) {
+ if (buf->b_mod_tick_syn < display_tick && syntax_present(wp)) {
syn_stack_apply_changes(buf);
buf->b_mod_tick_syn = display_tick;
}
if (buf->b_mod_tick_decor < display_tick) {
- decor_providers_invoke_buf(buf, &providers);
+ decor_providers_invoke_buf(buf);
buf->b_mod_tick_decor = display_tick;
}
}
-
- // Reset 'statuscolumn' if there is no dedicated signcolumn but it is invalid.
- if (*wp->w_p_stc != NUL && wp->w_minscwidth <= SCL_NO
- && (wp->w_buffer->b_signcols.invalid_bot || !wp->w_buffer->b_signcols.sentinel)) {
- wp->w_nrwidth_line_count = 0;
- wp->w_valid &= ~VALID_WCOL;
- wp->w_redr_type = UPD_NOT_VALID;
- wp->w_buffer->b_signcols.invalid_bot = 0;
- }
}
// Go from top to bottom through the windows, redrawing the ones that need it.
@@ -639,7 +630,7 @@ int update_screen(void)
did_one = true;
start_search_hl();
}
- win_update(wp, &providers);
+ win_update(wp);
}
// redraw status line and window bar after the window to minimize cursor movement
@@ -659,13 +650,14 @@ int update_screen(void)
win_check_ns_hl(NULL);
- // Reset b_mod_set flags. Going through all windows is probably faster
- // than going through all buffers (there could be many buffers).
+ // Reset b_mod_set and b_signcols.resized flags. Going through all windows is
+ // probably faster than going through all buffers (there could be many buffers).
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
wp->w_buffer->b_mod_set = false;
+ wp->w_buffer->b_signcols.resized = false;
}
- updating_screen = 0;
+ updating_screen = false;
// Clear or redraw the command line. Done last, because scrolling may
// mess up the command line.
@@ -679,8 +671,7 @@ int update_screen(void)
}
did_intro = true;
- decor_providers_invoke_end(&providers);
- kvi_destroy(providers);
+ decor_providers_invoke_end();
// either cmdline is cleared, not drawn or mode is last drawn
cmdline_was_last_drawn = false;
@@ -740,7 +731,7 @@ int win_get_bordertext_col(int total_col, int text_width, AlignTextPos align)
static void win_redr_border(win_T *wp)
{
wp->w_redr_border = false;
- if (!(wp->w_floating && wp->w_float_config.border)) {
+ if (!(wp->w_floating && wp->w_config.border)) {
return;
}
@@ -748,9 +739,9 @@ static void win_redr_border(win_T *wp)
schar_T chars[8];
for (int i = 0; i < 8; i++) {
- chars[i] = schar_from_str(wp->w_float_config.border_chars[i]);
+ chars[i] = schar_from_str(wp->w_config.border_chars[i]);
}
- int *attrs = wp->w_float_config.border_attr;
+ int *attrs = wp->w_config.border_attr;
int *adj = wp->w_border_adj;
int irow = wp->w_height_inner + wp->w_winbar_height;
@@ -766,10 +757,10 @@ static void win_redr_border(win_T *wp)
grid_line_put_schar(i + adj[3], chars[1], attrs[1]);
}
- if (wp->w_float_config.title) {
- int title_col = win_get_bordertext_col(icol, wp->w_float_config.title_width,
- wp->w_float_config.title_pos);
- win_redr_bordertext(wp, wp->w_float_config.title_chunks, title_col);
+ if (wp->w_config.title) {
+ int title_col
+ = win_get_bordertext_col(icol, wp->w_config.title_width, wp->w_config.title_pos);
+ win_redr_bordertext(wp, wp->w_config.title_chunks, title_col);
}
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[2], attrs[2]);
@@ -802,10 +793,10 @@ static void win_redr_border(win_T *wp)
grid_line_put_schar(i + adj[3], chars[ic], attrs[ic]);
}
- if (wp->w_float_config.footer) {
- int footer_col = win_get_bordertext_col(icol, wp->w_float_config.footer_width,
- wp->w_float_config.footer_pos);
- win_redr_bordertext(wp, wp->w_float_config.footer_chunks, footer_col);
+ if (wp->w_config.footer) {
+ int footer_col
+ = win_get_bordertext_col(icol, wp->w_config.footer_width, wp->w_config.footer_pos);
+ win_redr_bordertext(wp, wp->w_config.footer_chunks, footer_col);
}
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[4], attrs[4]);
@@ -834,8 +825,7 @@ void setcursor_mayforce(bool force)
// With 'rightleft' set and the cursor on a double-wide character,
// position it on the leftmost column.
col = curwin->w_width_inner - curwin->w_wcol
- - ((utf_ptr2cells(get_cursor_pos_ptr()) == 2
- && vim_isprintc(gchar_cursor())) ? 2 : 1);
+ - ((utf_ptr2cells(get_cursor_pos_ptr()) == 2 && vim_isprintc(gchar_cursor())) ? 2 : 1);
}
grid_adjust(&grid, &row, &col);
@@ -849,22 +839,19 @@ void setcursor_mayforce(bool force)
void show_cursor_info_later(bool force)
{
int state = get_real_state();
- int empty_line = (State & MODE_INSERT) == 0
- && *ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum) == NUL;
+ int empty_line
+ = (State & MODE_INSERT) == 0 && *ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum) == NUL;
// Only draw when something changed.
validate_virtcol_win(curwin);
- if (force
- || curwin->w_cursor.lnum != curwin->w_stl_cursor.lnum
+ if (force || curwin->w_cursor.lnum != curwin->w_stl_cursor.lnum
|| curwin->w_cursor.col != curwin->w_stl_cursor.col
|| curwin->w_virtcol != curwin->w_stl_virtcol
|| curwin->w_cursor.coladd != curwin->w_stl_cursor.coladd
|| curwin->w_topline != curwin->w_stl_topline
|| curwin->w_buffer->b_ml.ml_line_count != curwin->w_stl_line_count
- || curwin->w_topfill != curwin->w_stl_topfill
- || empty_line != curwin->w_stl_empty
- || reg_recording != curwin->w_stl_recording
- || state != curwin->w_stl_state
+ || curwin->w_topfill != curwin->w_stl_topfill || empty_line != curwin->w_stl_empty
+ || reg_recording != curwin->w_stl_recording || state != curwin->w_stl_state
|| (VIsual_active && VIsual_mode != curwin->w_stl_visual_mode)) {
if (curwin->w_status_height || global_stl_height()) {
curwin->w_redr_status = true;
@@ -876,8 +863,7 @@ void show_cursor_info_later(bool force)
curwin->w_redr_status = true;
}
- if ((p_icon && (stl_syntax & STL_IN_ICON))
- || (p_title && (stl_syntax & STL_IN_TITLE))) {
+ if ((p_icon && (stl_syntax & STL_IN_ICON)) || (p_title && (stl_syntax & STL_IN_TITLE))) {
need_maketitle = true;
}
}
@@ -928,15 +914,12 @@ int showmode(void)
msg_grid_validate();
- int do_mode = ((p_smd && msg_silent == 0)
- && ((State & MODE_TERMINAL)
- || (State & MODE_INSERT)
- || restart_edit != NUL
- || VIsual_active));
+ bool do_mode = ((p_smd && msg_silent == 0)
+ && ((State & MODE_TERMINAL) || (State & MODE_INSERT) || restart_edit != NUL
+ || VIsual_active));
bool can_show_mode = (p_ch != 0 || ui_has(kUIMessages));
if ((do_mode || reg_recording != 0) && can_show_mode) {
- int sub_attr;
if (skip_showmode()) {
return 0; // show mode later
}
@@ -954,7 +937,7 @@ int showmode(void)
// Position on the last line in the window, column 0
msg_pos_mode();
- int attr = HL_ATTR(HLF_CM); // Highlight mode
+ int attr = HL_ATTR(HLF_CM); // Highlight mode
// When the screen is too narrow to show the entire mode message,
// avoid scrolling and truncate instead.
@@ -989,7 +972,8 @@ int showmode(void)
}
if (edit_submode_extra != NULL) {
msg_puts_attr(" ", attr); // Add a space in between.
- if ((int)edit_submode_highl < HLF_COUNT) {
+ int sub_attr;
+ if (edit_submode_highl < HLF_COUNT) {
sub_attr = win_hl_attr(curwin, (int)edit_submode_highl);
} else {
sub_attr = attr;
@@ -1009,8 +993,8 @@ int showmode(void)
msg_puts_attr(_(" REVERSE"), attr);
}
msg_puts_attr(_(" INSERT"), attr);
- } else if (restart_edit == 'I' || restart_edit == 'i'
- || restart_edit == 'a' || restart_edit == 'A') {
+ } else if (restart_edit == 'I' || restart_edit == 'i' || restart_edit == 'a'
+ || restart_edit == 'A') {
if (curbuf->terminal) {
msg_puts_attr(_(" (terminal)"), attr);
} else {
@@ -1024,8 +1008,7 @@ int showmode(void)
if (State & MODE_LANGMAP) {
if (curwin->w_p_arab) {
msg_puts_attr(_(" Arabic"), attr);
- } else if (get_keymap_str(curwin, " (%s)",
- NameBuff, MAXPATHL)) {
+ } else if (get_keymap_str(curwin, " (%s)", NameBuff, MAXPATHL)) {
msg_puts_attr(NameBuff, attr);
}
}
@@ -1038,21 +1021,25 @@ int showmode(void)
// Don't concatenate separate words to avoid translation
// problems.
- switch ((VIsual_select ? 4 : 0)
- + (VIsual_mode == Ctrl_V) * 2
- + (VIsual_mode == 'V')) {
+ switch ((VIsual_select ? 4 : 0) + (VIsual_mode == Ctrl_V) * 2 + (VIsual_mode == 'V')) {
case 0:
- p = N_(" VISUAL"); break;
+ p = N_(" VISUAL");
+ break;
case 1:
- p = N_(" VISUAL LINE"); break;
+ p = N_(" VISUAL LINE");
+ break;
case 2:
- p = N_(" VISUAL BLOCK"); break;
+ p = N_(" VISUAL BLOCK");
+ break;
case 4:
- p = N_(" SELECT"); break;
+ p = N_(" SELECT");
+ break;
case 5:
- p = N_(" SELECT LINE"); break;
+ p = N_(" SELECT LINE");
+ break;
default:
- p = N_(" SELECT BLOCK"); break;
+ p = N_(" SELECT BLOCK");
+ break;
}
msg_puts_attr(_(p), attr);
}
@@ -1061,9 +1048,8 @@ int showmode(void)
need_clear = true;
}
- if (reg_recording != 0
- && edit_submode == NULL // otherwise it gets too long
- ) {
+ if (reg_recording != 0 && edit_submode == NULL // otherwise it gets too long
+ ) {
recording_mode(attr);
need_clear = true;
}
@@ -1072,12 +1058,12 @@ int showmode(void)
if (need_clear || clear_cmdline || redraw_mode) {
msg_clr_eos();
}
- msg_didout = false; // overwrite this message
+ msg_didout = false; // overwrite this message
length = msg_col;
msg_col = 0;
msg_no_more = false;
lines_left = save_lines_left;
- need_wait_return = nwr_save; // never ask for hit-return for this
+ need_wait_return = nwr_save; // never ask for hit-return for this
} else if (clear_cmdline && msg_silent == 0) {
// Clear the whole command line. Will reset "clear_cmdline".
msg_clr_cmdline();
@@ -1151,17 +1137,19 @@ void clearmode(void)
static void recording_mode(int attr)
{
- msg_puts_attr(_("recording"), attr);
if (shortmess(SHM_RECORDING)) {
return;
}
- char s[4];
- snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording);
+ msg_puts_attr(_("recording"), attr);
+ char reg_str[8];
+ reg_str[utf_char2bytes(reg_recording, reg_str)] = 0;
+ char s[16];
+ snprintf(s, ARRAY_SIZE(s), " @%s", reg_str);
msg_puts_attr(s, attr);
}
-#define COL_RULER 17 // columns needed by standard ruler
+#define COL_RULER 17 // columns needed by standard ruler
/// Compute columns for ruler and shown command. 'sc_col' is also used to
/// decide what the maximum length of a message on the status line can be.
@@ -1180,19 +1168,17 @@ void comp_col(void)
sc_col = ru_col;
}
}
- if (p_sc) {
+ if (p_sc && *p_sloc == 'l') {
sc_col += SHOWCMD_COLS;
- if (!p_ru || last_has_status) { // no need for separating space
+ if (!p_ru || last_has_status) { // no need for separating space
sc_col++;
}
}
- assert(sc_col >= 0
- && INT_MIN + sc_col <= Columns);
+ assert(sc_col >= 0 && INT_MIN + sc_col <= Columns);
sc_col = Columns - sc_col;
- assert(ru_col >= 0
- && INT_MIN + ru_col <= Columns);
+ assert(ru_col >= 0 && INT_MIN + ru_col <= Columns);
ru_col = Columns - ru_col;
- if (sc_col <= 0) { // screen too narrow, will become a mess
+ if (sc_col <= 0) { // screen too narrow, will become a mess
sc_col = 1;
}
if (ru_col <= 0) {
@@ -1201,17 +1187,34 @@ void comp_col(void)
set_vim_var_nr(VV_ECHOSPACE, sc_col - 1);
}
-static void redraw_win_signcol(win_T *wp)
+/// Redraw entire window "wp" if "auto" 'signcolumn' width has changed.
+static bool win_redraw_signcols(win_T *wp)
{
- // If we can compute a change in the automatic sizing of the sign column
- // under 'signcolumn=auto:X' and signs currently placed in the buffer, better
- // figuring it out here so we can redraw the entire screen for it.
- int scwidth = wp->w_scwidth;
- wp->w_scwidth = win_signcol_count(wp);
- if (wp->w_scwidth != scwidth) {
- changed_line_abv_curs_win(wp);
- redraw_later(wp, UPD_NOT_VALID);
+ buf_T *buf = wp->w_buffer;
+
+ if (!buf->b_signcols.autom
+ && (*wp->w_p_stc != NUL || (wp->w_maxscwidth > 1 && wp->w_minscwidth != wp->w_maxscwidth))) {
+ buf->b_signcols.autom = true;
+ buf_signcols_count_range(buf, 0, buf->b_ml.ml_line_count, MAXLNUM, kFalse);
}
+
+ while (buf->b_signcols.max > 0 && buf->b_signcols.count[buf->b_signcols.max - 1] == 0) {
+ buf->b_signcols.resized = true;
+ buf->b_signcols.max--;
+ }
+
+ int width = MIN(wp->w_maxscwidth, buf->b_signcols.max);
+ bool rebuild_stc = buf->b_signcols.resized && *wp->w_p_stc != NUL;
+
+ if (rebuild_stc) {
+ wp->w_nrwidth_line_count = 0;
+ } else if (wp->w_minscwidth == 0 && wp->w_maxscwidth == 1) {
+ width = buf_meta_total(buf, kMTMetaSignText) > 0;
+ }
+
+ int scwidth = wp->w_scwidth;
+ wp->w_scwidth = MAX(MAX(0, wp->w_minscwidth), width);
+ return (wp->w_scwidth != scwidth || rebuild_stc);
}
/// Check if horizontal separator of window "wp" at specified window corner is connected to the
@@ -1220,8 +1223,7 @@ static void redraw_win_signcol(win_T *wp)
static bool hsep_connected(win_T *wp, WindowCorner corner)
{
bool before = (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT);
- int sep_row = (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT)
- ? wp->w_winrow - 1 : W_ENDROW(wp);
+ int sep_row = (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT) ? wp->w_winrow - 1 : W_ENDROW(wp);
frame_T *fr = wp->w_frame;
while (fr->fr_parent != NULL) {
@@ -1255,8 +1257,8 @@ static bool hsep_connected(win_T *wp, WindowCorner corner)
static bool vsep_connected(win_T *wp, WindowCorner corner)
{
bool before = (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT);
- int sep_col = (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT)
- ? wp->w_wincol - 1 : W_ENDCOL(wp);
+ int sep_col
+ = (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT) ? wp->w_wincol - 1 : W_ENDCOL(wp);
frame_T *fr = wp->w_frame;
while (fr->fr_parent != NULL) {
@@ -1293,10 +1295,11 @@ static void draw_vsep_win(win_T *wp)
}
// draw the vertical separator right of this window
- int hl = win_hl_attr(wp, HLF_C);
- int c = wp->w_p_fcs_chars.vert;
- grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
- W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
+ for (int row = wp->w_winrow; row < W_ENDROW(wp); row++) {
+ grid_line_start(&default_grid, row);
+ grid_line_put_schar(W_ENDCOL(wp), wp->w_p_fcs_chars.vert, win_hl_attr(wp, HLF_C));
+ grid_line_flush();
+ }
}
/// Draw the horizontal separator below window "wp"
@@ -1307,10 +1310,9 @@ static void draw_hsep_win(win_T *wp)
}
// draw the horizontal separator below this window
- int hl = win_hl_attr(wp, HLF_C);
- int c = wp->w_p_fcs_chars.horiz;
- grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
- wp->w_wincol, W_ENDCOL(wp), c, c, hl);
+ grid_line_start(&default_grid, W_ENDROW(wp));
+ grid_line_fill(wp->w_wincol, W_ENDCOL(wp), wp->w_p_fcs_chars.horiz, win_hl_attr(wp, HLF_C));
+ grid_line_flush();
}
/// Get the separator connector for specified window corner of window "wp"
@@ -1318,21 +1320,19 @@ static schar_T get_corner_sep_connector(win_T *wp, WindowCorner corner)
{
// It's impossible for windows to be connected neither vertically nor horizontally
// So if they're not vertically connected, assume they're horizontally connected
- int c;
if (vsep_connected(wp, corner)) {
if (hsep_connected(wp, corner)) {
- c = wp->w_p_fcs_chars.verthoriz;
+ return wp->w_p_fcs_chars.verthoriz;
} else if (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT) {
- c = wp->w_p_fcs_chars.vertright;
+ return wp->w_p_fcs_chars.vertright;
} else {
- c = wp->w_p_fcs_chars.vertleft;
+ return wp->w_p_fcs_chars.vertleft;
}
} else if (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT) {
- c = wp->w_p_fcs_chars.horizdown;
+ return wp->w_p_fcs_chars.horizdown;
} else {
- c = wp->w_p_fcs_chars.horizup;
+ return wp->w_p_fcs_chars.horizup;
}
- return schar_from_char(c);
}
/// Draw separator connecting characters on the corners of window "wp"
@@ -1414,28 +1414,28 @@ static void draw_sep_connectors_win(win_T *wp)
/// - if wp->w_buffer->b_mod_set set, update lines between
/// b_mod_top and b_mod_bot.
/// - if wp->w_redraw_top non-zero, redraw lines between
-/// wp->w_redraw_top and wp->w_redr_bot.
+/// wp->w_redraw_top and wp->w_redraw_bot.
/// - continue redrawing when syntax status is invalid.
/// 4. if scrolled up, update lines at the bottom.
/// This results in three areas that may need updating:
/// top: from first row to top_end (when scrolled down)
/// mid: from mid_start to mid_end (update inversion or changed text)
/// bot: from bot_start to last row (when scrolled up)
-static void win_update(win_T *wp, DecorProviders *providers)
+static void win_update(win_T *wp)
{
- int top_end = 0; // Below last row of the top area that needs
- // updating. 0 when no top area updating.
- int mid_start = 999; // first row of the mid area that needs
- // updating. 999 when no mid area updating.
- int mid_end = 0; // Below last row of the mid area that needs
- // updating. 0 when no mid area updating.
- int bot_start = 999; // first row of the bot area that needs
- // updating. 999 when no bot area updating
- bool scrolled_down = false; // true when scrolled down when w_topline got smaller a bit
- bool top_to_mod = false; // redraw above mod_top
-
- int bot_scroll_start = 999; // first line that needs to be redrawn due to
- // scrolling. only used for EOB
+ int top_end = 0; // Below last row of the top area that needs
+ // updating. 0 when no top area updating.
+ int mid_start = 999; // first row of the mid area that needs
+ // updating. 999 when no mid area updating.
+ int mid_end = 0; // Below last row of the mid area that needs
+ // updating. 0 when no mid area updating.
+ int bot_start = 999; // first row of the bot area that needs
+ // updating. 999 when no bot area updating
+ bool scrolled_down = false; // true when scrolled down when w_topline got smaller a bit
+ bool top_to_mod = false; // redraw above mod_top
+
+ int bot_scroll_start = 999; // first line that needs to be redrawn due to
+ // scrolling. only used for EOB
static bool recursive = false; // being called recursively
@@ -1444,9 +1444,10 @@ static void win_update(win_T *wp, DecorProviders *providers)
DID_NONE = 1, // didn't update a line
DID_LINE = 2, // updated a normal line
DID_FOLD = 3, // updated a folded line
- } did_update = DID_NONE;
+ } did_update
+ = DID_NONE;
- linenr_T syntax_last_parsed = 0; // last parsed text line
+ linenr_T syntax_last_parsed = 0; // last parsed text line
linenr_T mod_top = 0;
linenr_T mod_bot = 0;
@@ -1488,10 +1489,13 @@ static void win_update(win_T *wp, DecorProviders *providers)
decor_redraw_reset(wp, &decor_state);
- DecorProviders line_providers;
- decor_providers_invoke_win(wp, providers, &line_providers);
+ decor_providers_invoke_win(wp);
- redraw_win_signcol(wp);
+ if (win_redraw_signcols(wp)) {
+ wp->w_lines_valid = 0;
+ wp->w_redr_type = UPD_NOT_VALID;
+ changed_line_abv_curs_win(wp);
+ }
init_search_hl(wp, &screen_search_hl);
@@ -1521,13 +1525,6 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (wp->w_nrwidth != nrwidth_new) {
type = UPD_NOT_VALID;
wp->w_nrwidth = nrwidth_new;
- } else if (buf->b_mod_set
- && buf->b_mod_xlines != 0
- && wp->w_redraw_top != 0) {
- // When there are both inserted/deleted lines and specific lines to be
- // redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
- // everything (only happens when redrawing is off for while).
- type = UPD_NOT_VALID;
} else {
// Set mod_top to the first line that needs displaying because of
// changes. Set mod_bot to the first line after the changes.
@@ -1558,14 +1555,12 @@ static void win_update(win_T *wp, DecorProviders *providers)
// previous line invalid. Simple solution: redraw all visible
// lines above the change.
// Same for a match pattern.
- if (screen_search_hl.rm.regprog != NULL
- && re_multiline(screen_search_hl.rm.regprog)) {
+ if (screen_search_hl.rm.regprog != NULL && re_multiline(screen_search_hl.rm.regprog)) {
top_to_mod = true;
} else {
const matchitem_T *cur = wp->w_match_head;
while (cur != NULL) {
- if (cur->mit_match.regprog != NULL
- && re_multiline(cur->mit_match.regprog)) {
+ if (cur->mit_match.regprog != NULL && re_multiline(cur->mit_match.regprog)) {
top_to_mod = true;
break;
}
@@ -1602,14 +1597,14 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
}
- (void)hasFoldingWin(wp, mod_top, &mod_top, NULL, true, NULL);
+ hasFoldingWin(wp, mod_top, &mod_top, NULL, true, NULL);
if (mod_top > lnumt) {
mod_top = lnumt;
}
// Now do the same for the bottom line (one above mod_bot).
mod_bot--;
- (void)hasFoldingWin(wp, mod_bot, NULL, &mod_bot, true, NULL);
+ hasFoldingWin(wp, mod_bot, NULL, &mod_bot, true, NULL);
mod_bot++;
if (mod_bot < lnumb) {
mod_bot = lnumb;
@@ -1627,12 +1622,6 @@ static void win_update(win_T *wp, DecorProviders *providers)
top_end = 1;
}
}
-
- // When line numbers are displayed need to redraw all lines below
- // inserted/deleted lines.
- if (mod_top != 0 && buf->b_mod_xlines != 0 && wp->w_p_nu) {
- mod_bot = MAXLNUM;
- }
}
wp->w_redraw_top = 0; // reset for next time
@@ -1664,13 +1653,11 @@ static void win_update(win_T *wp, DecorProviders *providers)
// 2: wp->w_topline is below wp->w_lines[0].wl_lnum: may scroll up
// 3: wp->w_topline is wp->w_lines[0].wl_lnum: find first entry in
// w_lines[] that needs updating.
- if ((type == UPD_VALID || type == UPD_SOME_VALID
- || type == UPD_INVERTED || type == UPD_INVERTED_ALL)
+ if ((type == UPD_VALID || type == UPD_SOME_VALID || type == UPD_INVERTED
+ || type == UPD_INVERTED_ALL)
&& !wp->w_botfill && !wp->w_old_botfill) {
- if (mod_top != 0
- && wp->w_topline == mod_top
- && (!wp->w_lines[0].wl_valid
- || wp->w_topline == wp->w_lines[0].wl_lnum)) {
+ if (mod_top != 0 && wp->w_topline == mod_top
+ && (!wp->w_lines[0].wl_valid || wp->w_topline == wp->w_lines[0].wl_lnum)) {
// w_topline is the first changed line and window is not scrolled,
// the scrolling from changed lines will be done further down.
} else if (wp->w_lines[0].wl_valid
@@ -1680,22 +1667,20 @@ static void win_update(win_T *wp, DecorProviders *providers)
// New topline is above old topline: May scroll down.
int j;
if (hasAnyFolding(wp)) {
- linenr_T ln;
-
// count the number of lines we are off, counting a sequence
// of folded lines as one
j = 0;
- for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ln++) {
+ for (linenr_T ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ln++) {
j++;
if (j >= wp->w_grid.rows - 2) {
break;
}
- (void)hasFoldingWin(wp, ln, NULL, &ln, true, NULL);
+ hasFoldingWin(wp, ln, NULL, &ln, true, NULL);
}
} else {
j = wp->w_lines[0].wl_lnum - wp->w_topline;
}
- if (j < wp->w_grid.rows - 2) { // not too far off
+ if (j < wp->w_grid.rows - 2) { // not too far off
int i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1, true);
// insert extra lines for previously invisible filler lines
if (wp->w_lines[0].wl_lnum != wp->w_topline) {
@@ -1741,8 +1726,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
int j = -1;
int row = 0;
for (int i = 0; i < wp->w_lines_valid; i++) {
- if (wp->w_lines[i].wl_valid
- && wp->w_lines[i].wl_lnum == wp->w_topline) {
+ if (wp->w_lines[i].wl_valid && wp->w_lines[i].wl_lnum == wp->w_topline) {
j = i;
break;
}
@@ -1781,8 +1765,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
wp->w_lines[idx] = wp->w_lines[j];
// stop at line that didn't fit, unless it is still
// valid (no lines deleted)
- if (row > 0 && bot_start + row
- + (int)wp->w_lines[j].wl_size > wp->w_grid.rows) {
+ if (row > 0 && bot_start + row + (int)wp->w_lines[j].wl_size > wp->w_grid.rows) {
wp->w_lines_valid = idx + 1;
break;
}
@@ -1798,8 +1781,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Correct the first entry for filler lines at the top
// when it won't get updated below.
if (win_may_fill(wp) && bot_start > 0) {
- wp->w_lines[0].wl_size = (uint16_t)(plines_win_nofill(wp, wp->w_topline, true)
- + wp->w_topfill);
+ wp->w_lines[0].wl_size
+ = (uint16_t)(plines_win_nofill(wp, wp->w_topline, true) + wp->w_topfill);
}
}
}
@@ -1862,15 +1845,13 @@ static void win_update(win_T *wp, DecorProviders *providers)
} else {
from = wp->w_old_cursor_lnum;
to = curwin->w_cursor.lnum;
- if (from == 0) { // Visual mode just started
+ if (from == 0) { // Visual mode just started
from = to;
}
}
- if (VIsual.lnum != wp->w_old_visual_lnum
- || VIsual.col != wp->w_old_visual_col) {
- if (wp->w_old_visual_lnum < from
- && wp->w_old_visual_lnum != 0) {
+ if (VIsual.lnum != wp->w_old_visual_lnum || VIsual.col != wp->w_old_visual_col) {
+ if (wp->w_old_visual_lnum < from && wp->w_old_visual_lnum != 0) {
from = wp->w_old_visual_lnum;
}
if (wp->w_old_visual_lnum > to) {
@@ -1926,8 +1907,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
}
- if (fromc != wp->w_old_cursor_fcol
- || toc != wp->w_old_cursor_lcol) {
+ if (fromc != wp->w_old_cursor_fcol || toc != wp->w_old_cursor_lcol) {
if (from > VIsual.lnum) {
from = VIsual.lnum;
}
@@ -1981,7 +1961,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
} else {
mid_start = 0;
}
- while (lnum < from && idx < wp->w_lines_valid) { // find start
+ while (lnum < from && idx < wp->w_lines_valid) { // find start
if (wp->w_lines[idx].wl_valid) {
mid_start += wp->w_lines[idx].wl_size;
} else if (!scrolled_down) {
@@ -1996,9 +1976,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
srow += mid_start;
mid_end = wp->w_grid.rows;
- for (; idx < wp->w_lines_valid; idx++) { // find end
- if (wp->w_lines[idx].wl_valid
- && wp->w_lines[idx].wl_lnum >= to + 1) {
+ for (; idx < wp->w_lines_valid; idx++) { // find end
+ if (wp->w_lines[idx].wl_valid && wp->w_lines[idx].wl_lnum >= to + 1) {
// Only update until first row of this line
mid_end = srow;
break;
@@ -2042,12 +2021,12 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
// Update all the window rows.
- int idx = 0; // first entry in w_lines[].wl_size
- int row = 0; // current window row to display
- int srow = 0; // starting row of the current line
+ int idx = 0; // first entry in w_lines[].wl_size
+ int row = 0; // current window row to display
+ int srow = 0; // starting row of the current line
- bool eof = false; // if true, we hit the end of the file
- bool didline = false; // if true, we finished the last line
+ bool eof = false; // if true, we hit the end of the file
+ bool didline = false; // if true, we finished the last line
while (true) {
// stop updating when reached the end of the window (check for _past_
// the end of the window is at the end of the loop)
@@ -2073,27 +2052,19 @@ static void win_update(win_T *wp, DecorProviders *providers)
// When syntax folding is being used, the saved syntax states will
// already have been updated, we can't see where the syntax state is
// the same again, just update until the end of the window.
- if (row < top_end
- || (row >= mid_start && row < mid_end)
- || top_to_mod
- || idx >= wp->w_lines_valid
- || (row + wp->w_lines[idx].wl_size > bot_start)
+ if (row < top_end || (row >= mid_start && row < mid_end) || top_to_mod
+ || idx >= wp->w_lines_valid || (row + wp->w_lines[idx].wl_size > bot_start)
|| (mod_top != 0
&& (lnum == mod_top
|| (lnum >= mod_top
- && (lnum < mod_bot
- || did_update == DID_FOLD
- || (did_update == DID_LINE
- && syntax_present(wp)
- && ((foldmethodIsSyntax(wp)
- && hasAnyFolding(wp))
+ && (lnum < mod_bot || did_update == DID_FOLD
+ || (did_update == DID_LINE && syntax_present(wp)
+ && ((foldmethodIsSyntax(wp) && hasAnyFolding(wp))
|| syntax_check_changed(lnum)))
// match in fixed position might need redraw
// if lines were inserted or deleted
- || (wp->w_match_head != NULL
- && buf->b_mod_xlines != 0)))))
- || lnum == wp->w_cursorline
- || lnum == wp->w_last_cursorline) {
+ || (wp->w_match_head != NULL && buf->b_mod_xlines != 0)))))
+ || lnum == wp->w_cursorline || lnum == wp->w_last_cursorline) {
if (lnum == mod_top) {
top_to_mod = false;
}
@@ -2103,9 +2074,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Don't do this when the change continues until the end.
// Don't scroll when dollar_vcol >= 0, keep the "$".
// Don't scroll when redrawing the top, scrolled already above.
- if (lnum == mod_top
- && mod_bot != MAXLNUM
- && !(dollar_vcol >= 0 && mod_bot == mod_top + 1)
+ if (lnum == mod_top && mod_bot != MAXLNUM && !(dollar_vcol >= 0 && mod_bot == mod_top + 1)
&& row >= top_end) {
int old_rows = 0;
linenr_T l;
@@ -2117,18 +2086,15 @@ static void win_update(win_T *wp, DecorProviders *providers)
for (i = idx; i < wp->w_lines_valid; i++) {
// Only valid lines have a meaningful wl_lnum. Invalid
// lines are part of the changed area.
- if (wp->w_lines[i].wl_valid
- && wp->w_lines[i].wl_lnum == mod_bot) {
+ if (wp->w_lines[i].wl_valid && wp->w_lines[i].wl_lnum == mod_bot) {
break;
}
old_rows += wp->w_lines[i].wl_size;
- if (wp->w_lines[i].wl_valid
- && wp->w_lines[i].wl_lastlnum + 1 == mod_bot) {
+ if (wp->w_lines[i].wl_valid && wp->w_lines[i].wl_lastlnum + 1 == mod_bot) {
// Must have found the last valid entry above mod_bot.
// Add following invalid entries.
i++;
- while (i < wp->w_lines_valid
- && !wp->w_lines[i].wl_valid) {
+ while (i < wp->w_lines_valid && !wp->w_lines[i].wl_valid) {
old_rows += wp->w_lines[i++].wl_size;
}
break;
@@ -2211,8 +2177,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
wp->w_lines[j] = wp->w_lines[i];
// stop at a line that won't fit
- if (x + (int)wp->w_lines[j].wl_size
- > wp->w_grid.rows) {
+ if (x + (int)wp->w_lines[j].wl_size > wp->w_grid.rows) {
wp->w_lines_valid = j + 1;
break;
}
@@ -2222,8 +2187,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (bot_start > x) {
bot_start = x;
}
- } else { // j > i
- // move entries in w_lines[] downwards
+ } else { // j > i
+ // move entries in w_lines[] downwards
j -= i;
wp->w_lines_valid += (linenr_T)j;
if (wp->w_lines_valid > wp->w_grid.rows) {
@@ -2248,52 +2213,52 @@ static void win_update(win_T *wp, DecorProviders *providers)
// When lines are folded, display one line for all of them.
// Otherwise, display normally (can be several display lines when
// 'wrap' is on).
- foldinfo_T foldinfo = wp->w_p_cul && lnum == wp->w_cursor.lnum
- ? cursorline_fi : fold_info(wp, lnum);
-
- if (foldinfo.fi_lines == 0
- && idx < wp->w_lines_valid
- && wp->w_lines[idx].wl_valid
- && wp->w_lines[idx].wl_lnum == lnum
- && lnum > wp->w_topline
+ foldinfo_T foldinfo
+ = wp->w_p_cul && lnum == wp->w_cursor.lnum ? cursorline_fi : fold_info(wp, lnum);
+
+ if (foldinfo.fi_lines == 0 && idx < wp->w_lines_valid && wp->w_lines[idx].wl_valid
+ && wp->w_lines[idx].wl_lnum == lnum && lnum > wp->w_topline
&& !(dy_flags & (DY_LASTLINE | DY_TRUNCATE))
- && srow + wp->w_lines[idx].wl_size > wp->w_grid.rows
- && win_get_fill(wp, lnum) == 0) {
+ && srow + wp->w_lines[idx].wl_size > wp->w_grid.rows && win_get_fill(wp, lnum) == 0) {
// This line is not going to fit. Don't draw anything here,
// will draw "@ " lines below.
row = wp->w_grid.rows + 1;
} else {
prepare_search_hl(wp, &screen_search_hl, lnum);
// Let the syntax stuff know we skipped a few lines.
- if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum
- && syntax_present(wp)) {
+ if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum && syntax_present(wp)) {
syntax_end_parsing(wp, syntax_last_parsed + 1);
}
+ bool display_buf_line = (foldinfo.fi_lines == 0 || *wp->w_p_fdt == NUL);
+
// Display one line
spellvars_T zero_spv = { 0 };
- row = win_line(wp, lnum, srow, wp->w_grid.rows, false,
- foldinfo.fi_lines > 0 ? &zero_spv : &spv,
- foldinfo, &line_providers);
+ row = win_line(wp, lnum, srow, wp->w_grid.rows, 0, display_buf_line ? &spv : &zero_spv,
+ foldinfo);
+
+ if (display_buf_line) {
+ syntax_last_parsed = lnum;
+ } else {
+ spv.spv_capcol_lnum = 0;
+ }
if (foldinfo.fi_lines == 0) {
wp->w_lines[idx].wl_folded = false;
wp->w_lines[idx].wl_lastlnum = lnum;
did_update = DID_LINE;
- syntax_last_parsed = lnum;
} else {
foldinfo.fi_lines--;
wp->w_lines[idx].wl_folded = true;
wp->w_lines[idx].wl_lastlnum = lnum + foldinfo.fi_lines;
did_update = DID_FOLD;
- spv.spv_capcol_lnum = 0;
}
}
wp->w_lines[idx].wl_lnum = lnum;
wp->w_lines[idx].wl_valid = true;
- if (row > wp->w_grid.rows) { // past end of grid
+ if (row > wp->w_grid.rows) { // past end of grid
// we may need the size of that too long line later on
if (dollar_vcol == -1) {
wp->w_lines[idx].wl_size = (uint16_t)plines_win(wp, lnum, true);
@@ -2307,12 +2272,15 @@ static void win_update(win_T *wp, DecorProviders *providers)
idx++;
lnum += foldinfo.fi_lines + 1;
} else {
- if (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum) {
- // 'relativenumber' set and cursor moved vertically: The
- // text doesn't need to be drawn, but the number column does.
- foldinfo_T info = wp->w_p_cul && lnum == wp->w_cursor.lnum
- ? cursorline_fi : fold_info(wp, lnum);
- (void)win_line(wp, lnum, srow, wp->w_grid.rows, true, &spv, info, &line_providers);
+ // If:
+ // - 'number' is set and below inserted/deleted lines, or
+ // - 'relativenumber' is set and cursor moved vertically,
+ // the text doesn't need to be redrawn, but the number column does.
+ if ((wp->w_p_nu && mod_top != 0 && lnum >= mod_bot && buf->b_mod_xlines != 0)
+ || (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum)) {
+ foldinfo_T info
+ = wp->w_p_cul && lnum == wp->w_cursor.lnum ? cursorline_fi : fold_info(wp, lnum);
+ win_line(wp, lnum, srow, wp->w_grid.rows, wp->w_lines[idx].wl_size, &spv, info);
}
// This line does not need to be drawn, advance to the next one.
@@ -2327,6 +2295,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// 'statuscolumn' width has changed or errored, start from the top.
if (wp->w_redr_statuscol) {
+ redr_statuscol:
wp->w_redr_statuscol = false;
idx = 0;
row = 0;
@@ -2334,7 +2303,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
wp->w_lines_valid = 0;
wp->w_valid &= ~VALID_WCOL;
decor_redraw_reset(wp, &decor_state);
- decor_providers_invoke_win(wp, providers, &line_providers);
+ decor_providers_invoke_win(wp);
continue;
}
@@ -2376,26 +2345,26 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Window ends in filler lines.
wp->w_botline = lnum;
wp->w_filler_rows = wp->w_grid.rows - srow;
- } else if (dy_flags & DY_TRUNCATE) { // 'display' has "truncate"
+ } else if (dy_flags & DY_TRUNCATE) { // 'display' has "truncate"
// Last line isn't finished: Display "@@@" in the last screen line.
grid_line_start(&wp->w_grid, wp->w_grid.rows - 1);
grid_line_fill(0, MIN(wp->w_grid.cols, 3), wp->w_p_fcs_chars.lastline, at_attr);
- grid_line_fill(3, wp->w_grid.cols, ' ', at_attr);
+ grid_line_fill(3, wp->w_grid.cols, schar_from_ascii(' '), at_attr);
grid_line_flush();
set_empty_rows(wp, srow);
wp->w_botline = lnum;
- } else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline"
+ } else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline"
// Last line isn't finished: Display "@@@" at the end.
// If this would split a doublewidth char in two, we need to display "@@@@" instead
grid_line_start(&wp->w_grid, wp->w_grid.rows - 1);
int width = grid_line_getchar(MAX(wp->w_grid.cols - 3, 0), NULL) == NUL ? 4 : 3;
- grid_line_fill(MAX(wp->w_grid.cols - width, 0), wp->w_grid.cols,
- wp->w_p_fcs_chars.lastline, at_attr);
+ grid_line_fill(MAX(wp->w_grid.cols - width, 0), wp->w_grid.cols, wp->w_p_fcs_chars.lastline,
+ at_attr);
grid_line_flush();
set_empty_rows(wp, srow);
wp->w_botline = lnum;
} else {
- win_draw_end(wp, wp->w_p_fcs_chars.lastline, ' ', true, srow, wp->w_grid.rows, HLF_AT);
+ win_draw_end(wp, wp->w_p_fcs_chars.lastline, true, srow, wp->w_grid.rows, HLF_AT);
set_empty_rows(wp, srow);
wp->w_botline = lnum;
}
@@ -2408,8 +2377,11 @@ static void win_update(win_T *wp, DecorProviders *providers)
// for ml_line_count+1 and only draw filler lines
spellvars_T zero_spv = { 0 };
foldinfo_T zero_foldinfo = { 0 };
- row = win_line(wp, wp->w_botline, row, wp->w_grid.rows, false, &zero_spv,
- zero_foldinfo, &line_providers);
+ row = win_line(wp, wp->w_botline, row, wp->w_grid.rows, 0, &zero_spv, zero_foldinfo);
+ if (wp->w_redr_statuscol) {
+ eof = false;
+ goto redr_statuscol;
+ }
}
} else if (dollar_vcol == -1) {
wp->w_botline = lnum;
@@ -2428,13 +2400,10 @@ static void win_update(win_T *wp, DecorProviders *providers)
lastline = 0;
}
- win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, MAX(lastline, row), wp->w_grid.rows,
- HLF_EOB);
+ win_draw_end(wp, wp->w_p_fcs_chars.eob, false, MAX(lastline, row), wp->w_grid.rows, HLF_EOB);
set_empty_rows(wp, row);
}
- kvi_destroy(line_providers);
-
if (wp->w_redr_type >= UPD_REDRAW_TOP) {
draw_vsep_win(wp);
draw_hsep_win(wp);
@@ -2449,9 +2418,9 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Send win_extmarks if needed
for (size_t n = 0; n < kv_size(win_extmark_arr); n++) {
- ui_call_win_extmark(wp->w_grid_alloc.handle, wp->handle,
- kv_A(win_extmark_arr, n).ns_id, (Integer)kv_A(win_extmark_arr, n).mark_id,
- kv_A(win_extmark_arr, n).win_row, kv_A(win_extmark_arr, n).win_col);
+ ui_call_win_extmark(wp->w_grid_alloc.handle, wp->handle, kv_A(win_extmark_arr, n).ns_id,
+ (Integer)kv_A(win_extmark_arr, n).mark_id, kv_A(win_extmark_arr, n).win_row,
+ kv_A(win_extmark_arr, n).win_col);
}
if (dollar_vcol == -1) {
@@ -2475,7 +2444,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Don't update for changes in buffer again.
int mod_set = curbuf->b_mod_set;
curbuf->b_mod_set = false;
- win_update(curwin, providers);
+ win_update(curwin);
must_redraw = 0;
curbuf->b_mod_set = mod_set;
}
@@ -2509,71 +2478,49 @@ void win_scroll_lines(win_T *wp, int row, int line_count)
}
if (line_count < 0) {
- grid_del_lines(&wp->w_grid, row, -line_count,
- wp->w_grid.rows, 0, wp->w_grid.cols);
+ grid_del_lines(&wp->w_grid, row, -line_count, wp->w_grid.rows, 0, wp->w_grid.cols);
} else {
- grid_ins_lines(&wp->w_grid, row, line_count,
- wp->w_grid.rows, 0, wp->w_grid.cols);
+ grid_ins_lines(&wp->w_grid, row, line_count, wp->w_grid.rows, 0, wp->w_grid.cols);
}
}
-/// Call grid_fill() with columns adjusted for 'rightleft' if needed.
-/// Return the new offset.
-static int win_fill_end(win_T *wp, int c1, int c2, int off, int width, int row, int endrow,
- int attr)
-{
- int nn = off + width;
- const int endcol = wp->w_grid.cols;
-
- if (nn > endcol) {
- nn = endcol;
- }
-
- if (wp->w_p_rl) {
- grid_fill(&wp->w_grid, row, endrow, endcol - nn, endcol - off, c1, c2, attr);
- } else {
- grid_fill(&wp->w_grid, row, endrow, off, nn, c1, c2, attr);
- }
-
- return nn;
-}
-
/// Clear lines near the end of the window and mark the unused lines with "c1".
-/// Use "c2" as filler character.
/// When "draw_margin" is true, then draw the sign/fold/number columns.
-void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endrow, hlf_T hl)
+void win_draw_end(win_T *wp, schar_T c1, bool draw_margin, int startrow, int endrow, hlf_T hl)
{
assert(hl >= 0 && hl < HLF_COUNT);
- int n = 0;
-
- if (draw_margin) {
- // draw the fold column
- int fdc = compute_foldcolumn(wp, 0);
- if (fdc > 0) {
- n = win_fill_end(wp, ' ', ' ', n, fdc, row, endrow,
- win_hl_attr(wp, HLF_FC));
- }
- // draw the sign column
- int count = wp->w_scwidth;
- if (count > 0) {
- n = win_fill_end(wp, ' ', ' ', n, SIGN_WIDTH * count, row,
- endrow, win_hl_attr(wp, HLF_SC));
+ for (int row = startrow; row < endrow; row++) {
+ grid_line_start(&wp->w_grid, row);
+
+ int n = 0;
+ if (draw_margin) {
+ // draw the fold column
+ int fdc = MAX(0, compute_foldcolumn(wp, 0));
+ n = grid_line_fill(n, n + fdc, schar_from_ascii(' '), win_hl_attr(wp, HLF_FC));
+
+ // draw the sign column
+ n = grid_line_fill(n, n + wp->w_scwidth, schar_from_ascii(' '), win_hl_attr(wp, HLF_FC));
+
+ // draw the number column
+ if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) == NULL) {
+ int width = number_width(wp) + 1;
+ n = grid_line_fill(n, n + width, schar_from_ascii(' '), win_hl_attr(wp, HLF_N));
+ }
}
- // draw the number column
- if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) == NULL) {
- n = win_fill_end(wp, ' ', ' ', n, number_width(wp) + 1, row, endrow,
- win_hl_attr(wp, HLF_N));
+
+ int attr = hl_combine_attr(win_bg_attr(wp), win_hl_attr(wp, (int)hl));
+
+ if (n < wp->w_grid.cols) {
+ grid_line_put_schar(n, c1, 0); // base attr is inherited from clear
+ n++;
}
- }
- int attr = hl_combine_attr(win_bg_attr(wp), win_hl_attr(wp, (int)hl));
+ grid_line_clear_end(n, wp->w_grid.cols, attr);
- const int endcol = wp->w_grid.cols;
- if (wp->w_p_rl) {
- grid_fill(&wp->w_grid, row, endrow, 0, endcol - 1 - n, c2, c2, attr);
- grid_fill(&wp->w_grid, row, endrow, endcol - 1 - n, endcol - n, c1, c2, attr);
- } else {
- grid_fill(&wp->w_grid, row, endrow, n, endcol, c1, c2, attr);
+ if (wp->w_p_rl) {
+ grid_line_mirror();
+ }
+ grid_line_flush();
}
}
@@ -2631,7 +2578,7 @@ int number_width(win_T *wp)
// If 'signcolumn' is set to 'number' and there is a sign to display, then
// the minimal width for the number column is 2.
- if (n < 2 && wp->w_buffer->b_signs_with_text && wp->w_minscwidth == SCL_NUM) {
+ if (n < 2 && buf_meta_total(wp->w_buffer, kMTMetaSignText) && wp->w_minscwidth == SCL_NUM) {
n = 2;
}
@@ -2644,14 +2591,15 @@ int number_width(win_T *wp)
/// Set must_redraw only if not already set to a higher value.
/// e.g. if must_redraw is UPD_CLEAR, type UPD_NOT_VALID will do nothing.
void redraw_later(win_T *wp, int type)
- FUNC_ATTR_NONNULL_ALL
{
- if (!exiting && wp->w_redr_type < type) {
+ // curwin may have been set to NULL when exiting
+ assert(wp != NULL || exiting);
+ if (!exiting && !redraw_not_allowed && wp->w_redr_type < type) {
wp->w_redr_type = type;
if (type >= UPD_NOT_VALID) {
wp->w_lines_valid = 0;
}
- if (must_redraw < type) { // must_redraw is the maximum of all windows
+ if (must_redraw < type) { // must_redraw is the maximum of all windows
must_redraw = type;
}
}
@@ -2664,7 +2612,14 @@ void redraw_all_later(int type)
redraw_later(wp, type);
}
// This may be needed when switching tabs.
- if (must_redraw < type) {
+ set_must_redraw(type);
+}
+
+/// Set "must_redraw" to "type" unless it already has a higher value
+/// or it is currently not allowed.
+void set_must_redraw(int type)
+{
+ if (!redraw_not_allowed && must_redraw < type) {
must_redraw = type;
}
}
@@ -2704,11 +2659,10 @@ void redraw_buf_line_later(buf_T *buf, linenr_T line, bool force)
}
}
-void redraw_buf_range_later(buf_T *buf, linenr_T firstline, linenr_T lastline)
+void redraw_buf_range_later(buf_T *buf, linenr_T firstline, linenr_T lastline)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf
- && lastline >= wp->w_topline && firstline < wp->w_botline) {
+ if (wp->w_buffer == buf && lastline >= wp->w_topline && firstline < wp->w_botline) {
if (wp->w_redraw_top == 0 || wp->w_redraw_top > firstline) {
wp->w_redraw_top = firstline;
}
@@ -2725,13 +2679,9 @@ void redraw_buf_status_later(buf_T *buf)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer == buf
- && (wp->w_status_height
- || (wp == curwin && global_stl_height())
- || wp->w_winbar_height)) {
+ && (wp->w_status_height || (wp == curwin && global_stl_height()) || wp->w_winbar_height)) {
wp->w_redr_status = true;
- if (must_redraw < UPD_VALID) {
- must_redraw = UPD_VALID;
- }
+ set_must_redraw(UPD_VALID);
}
}
}
@@ -2742,8 +2692,7 @@ void status_redraw_all(void)
bool is_stl_global = global_stl_height() != 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if ((!is_stl_global && wp->w_status_height) || wp == curwin
- || wp->w_winbar_height) {
+ if ((!is_stl_global && wp->w_status_height) || wp == curwin || wp->w_winbar_height) {
wp->w_redr_status = true;
redraw_later(wp, UPD_VALID);
}
@@ -2762,8 +2711,9 @@ void status_redraw_buf(buf_T *buf)
bool is_stl_global = global_stl_height() != 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf && ((!is_stl_global && wp->w_status_height)
- || (is_stl_global && wp == curwin) || wp->w_winbar_height)) {
+ if (wp->w_buffer == buf
+ && ((!is_stl_global && wp->w_status_height) || (is_stl_global && wp == curwin)
+ || wp->w_winbar_height)) {
wp->w_redr_status = true;
redraw_later(wp, UPD_VALID);
}
@@ -2793,8 +2743,7 @@ void redraw_statuslines(void)
}
/// Redraw all status lines at the bottom of frame "frp".
-void win_redraw_last_status(const frame_T *frp)
- FUNC_ATTR_NONNULL_ARG(1)
+void win_redraw_last_status(const frame_T *frp) FUNC_ATTR_NONNULL_ARG(1)
{
if (frp->fr_layout == FR_LEAF) {
frp->fr_win->w_redr_status = true;
@@ -2818,11 +2767,9 @@ void win_redraw_last_status(const frame_T *frp)
/// Used to remove the "$" from a change command.
/// Note that when also inserting/deleting lines w_redraw_top and w_redraw_bot
/// may become invalid and the whole window will have to be redrawn.
-void redrawWinline(win_T *wp, linenr_T lnum)
- FUNC_ATTR_NONNULL_ALL
+void redrawWinline(win_T *wp, linenr_T lnum) FUNC_ATTR_NONNULL_ALL
{
- if (lnum >= wp->w_topline
- && lnum < wp->w_botline) {
+ if (lnum >= wp->w_topline && lnum < wp->w_botline) {
if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum) {
wp->w_redraw_top = lnum;
}
@@ -2835,8 +2782,7 @@ void redrawWinline(win_T *wp, linenr_T lnum)
/// Return true if the cursor line in window "wp" may be concealed, according
/// to the 'concealcursor' option.
-bool conceal_cursor_line(const win_T *wp)
- FUNC_ATTR_NONNULL_ALL
+bool conceal_cursor_line(const win_T *wp) FUNC_ATTR_NONNULL_ALL
{
int c;
@@ -2860,20 +2806,7 @@ bool conceal_cursor_line(const win_T *wp)
/// Whether cursorline is drawn in a special way
///
/// If true, both old and new cursorline will need to be redrawn when moving cursor within windows.
-bool win_cursorline_standout(const win_T *wp)
- FUNC_ATTR_NONNULL_ALL
+bool win_cursorline_standout(const win_T *wp) FUNC_ATTR_NONNULL_ALL
{
return wp->w_p_cul || (wp->w_p_cole > 0 && !conceal_cursor_line(wp));
}
-
-/// Redraw when w_cline_row changes and 'relativenumber' or 'cursorline' is set.
-/// Also when concealing is on and 'concealcursor' is not active.
-void redraw_for_cursorline(win_T *wp)
- FUNC_ATTR_NONNULL_ALL
-{
- if ((wp->w_valid & VALID_CROW) == 0 && !pum_visible()
- && (wp->w_p_rnu || win_cursorline_standout(wp))) {
- // win_line() will redraw the number column and cursorline only.
- redraw_later(wp, UPD_VALID);
- }
-}