diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/autocmd.c | 2 | ||||
-rw-r--r-- | src/nvim/cmdexpand.c | 2 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 281 | ||||
-rw-r--r-- | src/nvim/edit.c | 4 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 3 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 15 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 16 | ||||
-rw-r--r-- | src/nvim/fileio.c | 7 | ||||
-rw-r--r-- | src/nvim/generators/gen_options.lua | 1 | ||||
-rw-r--r-- | src/nvim/getchar.c | 2 | ||||
-rw-r--r-- | src/nvim/insexpand.c | 10 | ||||
-rw-r--r-- | src/nvim/main.c | 38 | ||||
-rw-r--r-- | src/nvim/message.c | 74 | ||||
-rw-r--r-- | src/nvim/move.c | 10 | ||||
-rw-r--r-- | src/nvim/normal.c | 8 | ||||
-rw-r--r-- | src/nvim/ops.c | 8 | ||||
-rw-r--r-- | src/nvim/option.c | 16 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/options.lua | 15 | ||||
-rw-r--r-- | src/nvim/popupmenu.c | 4 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 5 | ||||
-rw-r--r-- | src/nvim/search.c | 2 | ||||
-rw-r--r-- | src/nvim/state.c | 2 | ||||
-rw-r--r-- | src/nvim/terminal.c | 2 | ||||
-rw-r--r-- | src/nvim/ui_compositor.c | 2 | ||||
-rw-r--r-- | src/nvim/version.c | 1 | ||||
-rw-r--r-- | src/nvim/window.c | 11 |
27 files changed, 213 insertions, 330 deletions
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 439704d120..81d495ee27 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -2720,7 +2720,7 @@ static void do_autocmd_focusgained(bool gained) redrawcmdline(); } else if ((State & MODE_NORMAL) || (State & MODE_INSERT)) { if (must_redraw != 0) { - update_screen(0); + update_screen(); } setcursor(); diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 65b07cc17b..a29d022606 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -2810,7 +2810,7 @@ void wildmenu_cleanup(CmdlineInfo *cclp) p_ls = save_p_ls; p_wmh = save_p_wmh; last_status(false); - update_screen(UPD_VALID); // redraw the screen NOW + update_screen(); // redraw the screen NOW redrawcmd(); save_p_ls = -1; wild_menu_showing = 0; diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 8c18bf75e5..15a7294496 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -97,7 +97,7 @@ typedef enum { static bool redraw_popupmenu = false; static bool msg_grid_invalid = false; -static bool resizing = false; +static bool resizing_autocmd = false; static char *provider_err = NULL; @@ -115,7 +115,7 @@ void conceal_check_cursor_line(void) } } -/// Resize the screen to Rows and Columns. +/// Resize default_grid to Rows and Columns. /// /// Allocate default_grid.chars[] and other grid arrays. /// @@ -125,19 +125,18 @@ void conceal_check_cursor_line(void) /// 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 /// needed. -void screenalloc(void) +bool default_grid_alloc(void) { + static bool resizing = false; + // It's possible that we produce an out-of-memory message below, which // will cause this function to be called again. To break the loop, just // return here. if (resizing) { - return; + return false; } resizing = true; - int retry_count = 0; - -retry: // 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. @@ -148,24 +147,9 @@ retry: || Columns == 0 || (!full_screen && default_grid.chars == NULL)) { resizing = false; - return; - } - - // Note that the window sizes are updated before reallocating the arrays, - // thus we must not redraw here! - RedrawingDisabled++; - - // win_new_screensize will recompute floats position, but tell the - // compositor to not redraw them yet - ui_comp_set_screen_valid(false); - if (msg_grid.chars) { - msg_grid_invalid = true; + return false; } - win_new_screensize(); // fit the windows in the new sized screen - - comp_col(); // recompute columns for shown command and ruler - // We're changing the size of the screen. // - Allocate new arrays for default_grid // - Move lines from the old arrays into the new arrays, clear extra @@ -193,26 +177,13 @@ retry: default_grid.col_offset = 0; default_grid.handle = DEFAULT_GRID_HANDLE; - must_redraw = UPD_CLEAR; // need to clear the screen later - - RedrawingDisabled--; - - // Do not apply autocommands more than 3 times to avoid an endless loop - // in case applying autocommands always changes Rows or Columns. - if (starting == 0 && ++retry_count <= 3) { - apply_autocmds(EVENT_VIMRESIZED, NULL, NULL, false, curbuf); - // In rare cases, autocommands may have altered Rows or Columns, - // jump back to check if we need to allocate the screen again. - goto retry; - } - resizing = false; + return true; } void screenclear(void) { check_for_delay(false); - screenalloc(); // allocate screen buffers if size changed int i; @@ -281,13 +252,6 @@ void screen_resize(int width, int height) return; } - // curwin->w_buffer can be NULL when we are closing a window and the - // buffer has already been closed and removing a scrollbar causes a resize - // event. Don't resize then, it will happen after entering another buffer. - if (curwin->w_buffer == NULL) { - return; - } - resizing_screen = true; Rows = height; @@ -301,16 +265,54 @@ void screen_resize(int width, int height) width = Columns; p_lines = Rows; p_columns = Columns; - ui_call_grid_resize(1, width, height); - /// The window layout used to be adjusted here, but it now happens in - /// screenalloc() (also invoked from screenclear()). That is because the - /// recursize "resizing_screen" check above may skip this, but not screenalloc(). + // was invoked recursively from a VimResized autocmd, handled as a loop below + if (resizing_autocmd) { + return; + } + + int retry_count = 0; + resizing_autocmd = true; + + bool retry_resize = true; + while (retry_resize) { + retry_resize = default_grid_alloc(); - if (State != MODE_ASKMORE && State != MODE_EXTERNCMD && State != MODE_CONFIRM) { - screenclear(); + // Do not apply autocommands more than 3 times to avoid an endless loop + // in case applying autocommands always changes Rows or Columns. + if (++retry_count > 3) { + break; + } + + if (retry_resize) { + // In rare cases, autocommands may have altered Rows or Columns, + // retry to check if we need to allocate the screen again. + apply_autocmds(EVENT_VIMRESIZED, NULL, NULL, false, curbuf); + } } + resizing_autocmd = false; + + ui_call_grid_resize(1, width, height); + + // win_new_screensize will recompute floats position, but tell the + // compositor to not redraw them yet + ui_comp_set_screen_valid(false); + if (msg_grid.chars) { + msg_grid_invalid = true; + } + + // Note that the window sizes are updated before reallocating the arrays, + // thus we must not redraw here! + RedrawingDisabled++; + + win_new_screensize(); // fit the windows in the new sized screen + + comp_col(); // recompute columns for shown command and ruler + + RedrawingDisabled--; + redraw_all_later(UPD_CLEAR); + if (starting != NO_SCREEN) { maketitle(); @@ -320,14 +322,11 @@ void screen_resize(int width, int height) // We only redraw when it's needed: // - While at the more prompt or executing an external command, don't // redraw, but position the cursor. - // - While editing the command line, only redraw that. + // - While editing the command line, only redraw that. TODO: lies // - in Ex mode, don't redraw anything. // - Otherwise, redraw right now, and position the cursor. - // Always need to call update_screen() or screenalloc(), to make - // sure Rows/Columns and the size of the screen is correct! if (State == MODE_ASKMORE || State == MODE_EXTERNCMD || State == MODE_CONFIRM || exmode_active) { - screenalloc(); if (msg_grid.chars) { msg_grid_validate(); } @@ -341,7 +340,7 @@ void screen_resize(int width, int height) } if (State & MODE_CMDLINE) { redraw_popupmenu = false; - update_screen(UPD_NOT_VALID); + update_screen(); redrawcmdline(); if (pum_drawn()) { cmdline_pum_display(false); @@ -350,12 +349,12 @@ void screen_resize(int width, int height) update_topline(curwin); if (pum_drawn()) { // TODO(bfredl): ins_compl_show_pum wants to redraw the screen first. - // For now make sure the nested update_screen(0) won't redraw the + // For now make sure the nested update_screen() won't redraw the // pum at the old position. Try to untangle this later. redraw_popupmenu = false; ins_compl_show_pum(); } - update_screen(UPD_NOT_VALID); + update_screen(); if (redrawing()) { setcursor(); } @@ -370,9 +369,7 @@ void screen_resize(int width, int height) /// /// Most code shouldn't call this directly, rather use redraw_later() and /// and redraw_all_later() to mark parts of the screen as needing a redraw. -/// -/// @param type set to a UPD_NOT_VALID to force redraw of entire screen -int update_screen(int type) +int update_screen(void) { static bool did_intro = false; bool is_stl_global = global_stl_height() > 0; @@ -380,7 +377,7 @@ int update_screen(int type) // Don't do anything if the screen structures are (not yet) valid. // A VimResized autocmd can invoke redrawing in the middle of a resize, // which would bypass the checks in screen_resize for popupmenu etc. - if (!default_grid.chars || resizing) { + if (resizing_autocmd || !default_grid.chars) { return FAIL; } @@ -389,41 +386,25 @@ int update_screen(int type) diff_redraw(true); } - // TODO(bfredl): completely get rid of using update_screen(UPD_XX_VALID) - // to redraw curwin - int curwin_type = MIN(type, UPD_NOT_VALID); - - if (must_redraw) { - if (type < must_redraw) { // use maximal type - type = must_redraw; - } - - // must_redraw is reset here, so that when we run into some weird - // reason to redraw while busy redrawing (e.g., asynchronous - // scrolling), or update_topline() in win_update() will cause a - // scroll, or a decoration provider requires a redraw, the screen - // will be redrawn later or in win_update(). - must_redraw = 0; - } - - // Need to update w_lines[]. - if (curwin->w_lines_valid == 0 && type < UPD_NOT_VALID) { - type = UPD_NOT_VALID; - } - // Postpone the redrawing when it's not needed and when being called // recursively. if (!redrawing() || updating_screen) { - must_redraw = type; - if (type > UPD_INVERTED_ALL) { - curwin->w_lines_valid = 0; // don't use w_lines[].wl_size now - } return FAIL; } + + int type = must_redraw; + + // must_redraw is reset here, so that when we run into some weird + // reason to redraw while busy redrawing (e.g., asynchronous + // scrolling), or update_topline() in win_update() will cause a + // scroll, or a decoration provider requires a redraw, the screen + // will be redrawn later or in win_update(). + must_redraw = 0; + updating_screen = 1; - display_tick++; // let syntax code know we're in a next round of - // display updating + display_tick++; // let syntax code know we're in a next round of + // display updating // Tricky: vim code can reset msg_scrolled behind our back, so need // separate bookkeeping for now. @@ -447,75 +428,41 @@ int update_screen(int type) msg_grid.cols, false); } } - if (msg_use_msgsep()) { - msg_grid.throttled = false; - bool was_invalidated = false; + msg_grid.throttled = false; + bool was_invalidated = false; - // UPD_CLEAR is already handled - 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); + // UPD_CLEAR is already handled + 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); + } + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_floating) { + continue; } - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_floating) { - continue; - } - if (W_ENDROW(wp) > valid) { - // TODO(bfredl): too pessimistic. type could be UPD_NOT_VALID - // only because windows that are above the separator. - wp->w_redr_type = MAX(wp->w_redr_type, UPD_NOT_VALID); - } - if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height > valid) { - wp->w_redr_status = true; - } + if (W_ENDROW(wp) > valid) { + // TODO(bfredl): too pessimistic. type could be UPD_NOT_VALID + // only because windows that are above the separator. + wp->w_redr_type = MAX(wp->w_redr_type, UPD_NOT_VALID); } - if (is_stl_global && Rows - p_ch - 1 > valid) { - curwin->w_redr_status = true; + if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height > valid) { + wp->w_redr_status = true; } } - msg_grid_set_pos(Rows - (int)p_ch, false); - msg_grid_invalid = false; - if (was_invalidated) { - // screen was only invalid for the msgarea part. - // @TODO(bfredl): using the same "valid" flag - // for both messages and floats moving is bit of a mess. - ui_comp_set_screen_valid(true); - } - } else if (type != UPD_CLEAR) { - if (msg_scrolled > Rows - 5) { // redrawing is faster - type = UPD_NOT_VALID; - curwin_type = UPD_NOT_VALID; - } else { - check_for_delay(false); - grid_ins_lines(&default_grid, 0, msg_scrolled, Rows, 0, Columns); - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_floating) { - continue; - } - if (wp->w_winrow < msg_scrolled) { - if (W_ENDROW(wp) > msg_scrolled - && wp->w_redr_type < UPD_REDRAW_TOP - && wp->w_lines_valid > 0 - && wp->w_topline == wp->w_lines[0].wl_lnum) { - wp->w_upd_rows = msg_scrolled - wp->w_winrow; - wp->w_redr_type = UPD_REDRAW_TOP; - } else { - wp->w_redr_type = UPD_NOT_VALID; - if (wp->w_winrow + wp->w_winbar_height <= msg_scrolled) { - wp->w_redr_status = true; - } - } - } - } - if (is_stl_global && Rows - p_ch - 1 <= msg_scrolled) { - curwin->w_redr_status = true; - } - redraw_cmdline = true; - redraw_tabline = true; + if (is_stl_global && Rows - p_ch - 1 > valid) { + curwin->w_redr_status = true; } } + msg_grid_set_pos(Rows - (int)p_ch, false); + msg_grid_invalid = false; + if (was_invalidated) { + // screen was only invalid for the msgarea part. + // @TODO(bfredl): using the same "valid" flag + // for both messages and floats moving is bit of a mess. + ui_comp_set_screen_valid(true); + } msg_scrolled = 0; msg_scrolled_at_flush = 0; need_wait_return = false; @@ -535,7 +482,8 @@ int update_screen(int type) } if (type == UPD_CLEAR) { // first clear screen - screenclear(); // will reset clear_cmdline + 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 @@ -545,9 +493,8 @@ int update_screen(int type) default_grid.valid = true; } - // After disabling msgsep the grid might not have been deallocated yet, - // hence we also need to check msg_grid.chars - if (type == UPD_NOT_VALID && (msg_use_grid() || msg_grid.chars)) { + // 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); } @@ -576,28 +523,6 @@ int update_screen(int type) curwin->w_redr_type = UPD_NOT_VALID; } - // Only start redrawing if there is really something to do. - // TODO(bfredl): more curwin special casing to get rid of. - // Change update_screen(UPD_INVERTED) to a wrapper function - // perhaps? - if (curwin_type == UPD_INVERTED) { - update_curswant(); - } - if (curwin->w_redr_type < curwin_type - && !((curwin_type == UPD_VALID - && curwin->w_lines[0].wl_valid - && curwin->w_topfill == curwin->w_old_topfill - && curwin->w_botfill == curwin->w_old_botfill - && curwin->w_topline == curwin->w_lines[0].wl_lnum) - || (curwin_type == UPD_INVERTED - && VIsual_active - && curwin->w_old_cursor_lnum == curwin->w_cursor.lnum - && curwin->w_old_visual_mode == VIsual_mode - && (curwin->w_valid & VALID_VIRTCOL) - && curwin->w_old_curswant == curwin->w_curswant))) { - curwin->w_redr_type = curwin_type; - } - // Redraw the tab pages line if needed. if (redraw_tabline || type >= UPD_NOT_VALID) { update_window_hl(curwin, type >= UPD_NOT_VALID); @@ -2034,7 +1959,7 @@ win_update_start: } } -/// Redraw a window later, with update_screen(type). +/// Redraw a window later, with wp->w_redr_type >= type. /// /// 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. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index a165078bdf..781e9e3553 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1286,7 +1286,7 @@ void ins_redraw(bool ready) // a "(". The autocommand may also require a redraw, so it's done // again below, unfortunately. if (syntax_present(curwin) && must_redraw) { - update_screen(0); + update_screen(); } // Make sure curswant is correct, an autocommand may call // getcurpos() @@ -1348,7 +1348,7 @@ void ins_redraw(bool ready) pum_check_clear(); if (must_redraw) { - update_screen(0); + update_screen(); } else if (clear_cmdline || redraw_cmdline) { showmode(); // clear cmdline and show mode } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 77feddbbf9..ea51cac163 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3876,7 +3876,8 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T update_topline(curwin); validate_cursor(); - update_screen(UPD_SOME_VALID); + redraw_later(curwin, UPD_SOME_VALID); + update_screen(); highlight_match = false; redraw_later(curwin, UPD_SOME_VALID); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 987fb439d7..5591b5f55d 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -254,7 +254,7 @@ void do_exmode(void) RedrawingDisabled--; no_wait_return--; redraw_all_later(UPD_NOT_VALID); - update_screen(UPD_NOT_VALID); + update_screen(); need_wait_return = false; msg_scroll = save_msg_scroll; } @@ -6090,9 +6090,10 @@ static void ex_redraw(exarg_T *eap) if (eap->forceit) { redraw_all_later(UPD_NOT_VALID); redraw_cmdline = true; + } else if (VIsual_active) { + redraw_curbuf_later(UPD_INVERTED); } - update_screen(eap->forceit ? UPD_NOT_VALID - : VIsual_active ? UPD_INVERTED : 0); + update_screen(); if (need_maketitle) { maketitle(); } @@ -6123,16 +6124,16 @@ static void ex_redrawstatus(exarg_T *eap) } else { status_redraw_curbuf(); } - if (msg_scrolled && !msg_use_msgsep() && (State & MODE_CMDLINE)) { - return; // redraw later - } RedrawingDisabled = 0; p_lz = false; if (State & MODE_CMDLINE) { redraw_statuslines(); } else { - update_screen(VIsual_active ? UPD_INVERTED : 0); + if (VIsual_active) { + redraw_curbuf_later(UPD_INVERTED); + } + update_screen(); } RedrawingDisabled = r; p_lz = p; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 4b54b58ac1..6883dc5b14 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -501,7 +501,8 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat curwin->w_redr_status = true; } - update_screen(UPD_SOME_VALID); + redraw_later(curwin, UPD_SOME_VALID); + update_screen(); highlight_match = false; restore_last_search_pattern(); @@ -588,7 +589,7 @@ static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool validate_cursor(); // needed for TAB redraw_all_later(UPD_SOME_VALID); if (call_update_screen) { - update_screen(UPD_SOME_VALID); + update_screen(); } } } @@ -774,7 +775,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool init // Redraw the statusline in case it uses the current mode using the mode() // function. - if (!cmd_silent && (msg_scrolled == 0 || msg_use_msgsep())) { + if (!cmd_silent) { bool found_one = false; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { @@ -1376,7 +1377,8 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_ validate_cursor(); highlight_match = true; save_viewstate(curwin, &s->old_viewstate); - update_screen(UPD_NOT_VALID); + redraw_later(curwin, UPD_NOT_VALID); + update_screen(); highlight_match = false; redrawcmdline(); curwin->w_cursor = s->match_end; @@ -2336,7 +2338,7 @@ static bool cmdpreview_may_show(CommandLineState *s) if (cmdpreview_type != 0) { int save_rd = RedrawingDisabled; RedrawingDisabled = 0; - update_screen(UPD_SOME_VALID); + update_screen(); RedrawingDisabled = save_rd; } @@ -2406,7 +2408,9 @@ static int command_line_changed(CommandLineState *s) } else { cmdpreview = false; if (prev_cmdpreview) { - update_screen(UPD_SOME_VALID); // Clear 'inccommand' preview. + // TODO(bfredl): add an immediate redraw flag for cmdline mode which will trigger + // at next wait-for-input + update_screen(); // Clear 'inccommand' preview. } if (s->xpc.xp_context == EXPAND_NOTHING && (KeyTyped || vpeekc() == NUL)) { may_do_incsearch_highlighting(s->firstc, s->count, &s->is_state); diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 76317298dc..b31b8336aa 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -1721,13 +1721,6 @@ failed: appended_lines_mark(from, linecnt); } - // If we were reading from the same terminal as where messages go, - // the screen will have been messed up. - // Switch on raw mode now and clear the screen. - if (read_stdin) { - screenclear(); - } - if (got_int) { if (!(flags & READ_DUMMY)) { filemess(curbuf, sfname, _(e_interr), 0); diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index 24b4739fc7..6dba6552b3 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -34,7 +34,6 @@ local redraw_flags={ current_window_only='P_RWINONLY', current_buffer='P_RBUF', all_windows='P_RALL', - everything='P_RCLR', curswant='P_CURSWANT', ui_option='P_UI_OPTION', } diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index ef66e2d355..4135065787 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2601,7 +2601,7 @@ static int vgetorpeek(bool advance) // input buffer (e.g., termresponse). if (((State & MODE_INSERT) != 0 || p_lz) && (State & MODE_CMDLINE) == 0 && advance && must_redraw != 0 && !need_wait_return) { - update_screen(0); + update_screen(); setcursor(); // put cursor back where it belongs } diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 1426f28453..da1063f699 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -1228,7 +1228,7 @@ void ins_compl_show_pum(void) do_cmdline_cmd("if exists('g:loaded_matchparen')|3match none|endif"); // Update the screen before drawing the popup menu over it. - update_screen(0); + update_screen(); int cur = -1; bool array_changed = false; @@ -1648,7 +1648,7 @@ int ins_compl_bs(void) ins_compl_restart(); } - // ins_compl_restart() calls update_screen(0) which may invalidate the pointer + // ins_compl_restart() calls update_screen() which may invalidate the pointer // TODO(bfredl): get rid of random update_screen() calls deep inside completion logic line = get_cursor_line_ptr(); @@ -1759,7 +1759,7 @@ static void ins_compl_restart(void) // update screen before restart. // so if complete is blocked, // will stay to the last popup menu and reduce flicker - update_screen(0); + update_screen(); // TODO(bfredl): no. ins_compl_free(); compl_started = false; compl_matches = 0; @@ -2048,7 +2048,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval) if (c == Ctrl_C && cmdwin_type != 0) { // Avoid the popup menu remains displayed when leaving the // command line window. - update_screen(0); + update_screen(); } // Indent now if a key was typed that is in 'cinkeys'. @@ -3533,7 +3533,7 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match if (!allow_get_expansion) { // redraw to show the user what was inserted - update_screen(0); + update_screen(); // TODO(bfredl): no! // display the updated popup menu ins_compl_show_pum(); diff --git a/src/nvim/main.c b/src/nvim/main.c index 1119cee6ad..673b177463 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -185,11 +185,11 @@ void early_init(mparm_T *paramp) init_locale(); #endif - // Allocate the first window and buffer. - // Can't do anything without it, exit when it fails. - if (!win_alloc_first()) { - os_exit(0); - } + // tabpage local options (p_ch) must be set before allocating first tabpage. + set_init_tablocal(); + + // Allocate the first tabpage, window and buffer. + win_alloc_first(); TIME_MSG("init first window"); alist_init(&global_alist); // Init the argument list to empty. @@ -314,7 +314,7 @@ int main(int argc, char **argv) assert(p_ch >= 0 && Rows >= p_ch && Rows - p_ch <= INT_MAX); cmdline_row = (int)(Rows - p_ch); msg_row = cmdline_row; - screenalloc(); // allocate screen buffers + default_grid_alloc(); // allocate screen buffers set_init_2(headless_mode); TIME_MSG("inits 2"); @@ -346,13 +346,14 @@ int main(int argc, char **argv) ui_builtin_start(); } TIME_MSG("done waiting for UI"); - - // prepare screen now, so external UIs can display messages - starting = NO_BUFFERS; - screenclear(); - TIME_MSG("init screen for UI"); } + // prepare screen now + starting = NO_BUFFERS; + screenclear(); + win_new_screensize(); + TIME_MSG("clear screen"); + if (ui_client_channel_id) { ui_client_init(ui_client_channel_id); ui_client_execute(ui_client_channel_id); @@ -361,8 +362,8 @@ int main(int argc, char **argv) // Default mappings (incl. menus) Error err = ERROR_INIT; - Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim._init_default_mappings()"), - (Array)ARRAY_DICT_INIT, &err); + Object o = NLUA_EXEC_STATIC("return vim._init_default_mappings()", + (Array)ARRAY_DICT_INIT, &err); assert(!ERROR_SET(&err)); api_clear_error(&err); assert(o.type == kObjectTypeNil); @@ -432,10 +433,8 @@ int main(int argc, char **argv) p_ut = 1; } - // // Read in registers, history etc, from the ShaDa file. // This is where v:oldfiles gets filled. - // if (*p_shada != NUL) { shada_read_everything(NULL, false, true); TIME_MSG("reading ShaDa"); @@ -474,14 +473,7 @@ int main(int argc, char **argv) setmouse(); // may start using the mouse - if (exmode_active || use_remote_ui || use_builtin_ui) { - // Don't clear the screen when starting in Ex mode, or when a UI might have - // displayed messages. - redraw_later(curwin, UPD_VALID); - } else { - screenclear(); // clear screen - TIME_MSG("clearing screen"); - } + redraw_later(curwin, UPD_VALID); no_wait_return = true; diff --git a/src/nvim/message.c b/src/nvim/message.c index 060d969f4b..fef5055c84 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -153,8 +153,7 @@ void msg_grid_set_pos(int row, bool scrolled) bool msg_use_grid(void) { - return default_grid.chars && msg_use_msgsep() - && !ui_has(kUIMessages); + return default_grid.chars && !ui_has(kUIMessages); } void msg_grid_validate(void) @@ -172,19 +171,17 @@ void msg_grid_validate(void) xfree(msg_grid.dirty_col); msg_grid.dirty_col = xcalloc((size_t)Rows, sizeof(*msg_grid.dirty_col)); - // Tricky: allow resize while pager is active - int pos = msg_scrolled ? msg_grid_pos : max_rows; + // Tricky: allow resize while pager or ex mode is active + int pos = MAX(max_rows - msg_scrolled, 0); + msg_grid.throttled = false; // don't throttle in 'cmdheight' area + msg_grid_set_pos(pos, msg_scrolled); ui_comp_put_grid(&msg_grid, pos, 0, msg_grid.rows, msg_grid.cols, false, true); ui_call_grid_resize(msg_grid.handle, msg_grid.cols, msg_grid.rows); - msg_grid.throttled = false; // don't throttle in 'cmdheight' area msg_scrolled_at_flush = msg_scrolled; msg_grid.focusable = false; msg_grid_adj.target = &msg_grid; - if (!msg_scrolled) { - msg_grid_set_pos(max_rows, false); - } } else if (!should_alloc && msg_grid.chars) { ui_comp_remove_grid(&msg_grid); grid_free(&msg_grid); @@ -1159,10 +1156,6 @@ void wait_return(int redraw) c = CAR; // no need for a return in ex mode got_int = false; } else { - // Make sure the hit-return prompt is on screen when 'guioptions' was - // just changed. - screenalloc(); - State = MODE_HITRETURN; setmouse(); cmdline_row = msg_row; @@ -2340,13 +2333,6 @@ int msg_scrollsize(void) return msg_scrolled + (int)p_ch + ((p_ch > 0 || msg_scrolled > 1) ? 1 : 0); } -bool msg_use_msgsep(void) -{ - // the full-screen scroll behavior doesn't really make sense with - // 'ext_multigrid' - return (dy_flags & DY_MSGSEP) || p_ch == 0 || ui_has(kUIMultigrid); -} - bool msg_do_throttle(void) { return msg_use_grid() && !(rdb_flags & RDB_NOTHROTTLE); @@ -2359,23 +2345,19 @@ void msg_scroll_up(bool may_throttle, bool zerocmd) msg_grid.throttled = true; } msg_did_scroll = true; - if (msg_use_msgsep()) { - if (msg_grid_pos > 0) { - msg_grid_set_pos(msg_grid_pos - 1, !zerocmd); - - // When displaying the first line with cmdheight=0, we need to draw over - // the existing last line of the screen. - if (zerocmd && msg_grid.chars) { - grid_clear_line(&msg_grid, msg_grid.line_offset[0], msg_grid.cols, false); - } - } else { - grid_del_lines(&msg_grid, 0, 1, msg_grid.rows, 0, msg_grid.cols); - memmove(msg_grid.dirty_col, msg_grid.dirty_col + 1, - (size_t)(msg_grid.rows - 1) * sizeof(*msg_grid.dirty_col)); - msg_grid.dirty_col[msg_grid.rows - 1] = 0; + if (msg_grid_pos > 0) { + msg_grid_set_pos(msg_grid_pos - 1, !zerocmd); + + // When displaying the first line with cmdheight=0, we need to draw over + // the existing last line of the screen. + if (zerocmd && msg_grid.chars) { + grid_clear_line(&msg_grid, msg_grid.line_offset[0], msg_grid.cols, false); } } else { - grid_del_lines(&msg_grid_adj, 0, 1, Rows, 0, Columns); + grid_del_lines(&msg_grid, 0, 1, msg_grid.rows, 0, msg_grid.cols); + memmove(msg_grid.dirty_col, msg_grid.dirty_col + 1, + (size_t)(msg_grid.rows - 1) * sizeof(*msg_grid.dirty_col)); + msg_grid.dirty_col[msg_grid.rows - 1] = 0; } grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ', HL_ATTR(HLF_MSG)); @@ -2440,21 +2422,17 @@ void msg_reset_scroll(void) } // TODO(bfredl): some duplicate logic with update_screen(). Later on // we should properly disentangle message clear with full screen redraw. - if (msg_use_grid()) { - msg_grid.throttled = false; - // TODO(bfredl): risk for extra flicker i e with - // "nvim -o has_swap also_has_swap" - msg_grid_set_pos(Rows - (int)p_ch, false); - clear_cmdline = true; - 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, false); - } + msg_grid.throttled = false; + // TODO(bfredl): risk for extra flicker i e with + // "nvim -o has_swap also_has_swap" + msg_grid_set_pos(Rows - (int)p_ch, false); + clear_cmdline = true; + 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, false); } - } else { - redraw_all_later(UPD_NOT_VALID); } msg_scrolled = 0; msg_scrolled_at_flush = 0; diff --git a/src/nvim/move.c b/src/nvim/move.c index 481746881b..9d1d2e9cad 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -130,16 +130,6 @@ static void redraw_for_cursorcolumn(win_T *wp) } } -// Update curwin->w_topline and redraw if necessary. -// Used to update the screen before printing a message. -void update_topline_redraw(void) -{ - update_topline(curwin); - if (must_redraw) { - update_screen(0); - } -} - // Update curwin->w_topline to move the cursor onto the screen. void update_topline(win_T *wp) { diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 95665053b3..ec89e25b97 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -636,7 +636,7 @@ static void normal_redraw_mode_message(NormalState *s) // Showmode() will clear keep_msg, but we want to use it anyway. // First update w_topline. setcursor(); - update_screen(0); + update_screen(); // now reset it, otherwise it's put in the history again keep_msg = kmsg; @@ -1284,9 +1284,9 @@ static void normal_redraw(NormalState *s) if (VIsual_active) { redraw_curbuf_later(UPD_INVERTED); // update inverted part - update_screen(0); + update_screen(); } else if (must_redraw) { - update_screen(0); + update_screen(); } else if (redraw_cmdline || clear_cmdline || redraw_mode) { showmode(); } @@ -1841,7 +1841,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) if (jump_flags) { jump_flags = jump_to_mouse(jump_flags, NULL, which_button); redraw_curbuf_later(VIsual_active ? UPD_INVERTED : UPD_VALID); - update_screen(0); + update_screen(); setcursor(); ui_flush(); // Update before showing popup menu } diff --git a/src/nvim/ops.c b/src/nvim/ops.c index dee23e9193..7fbf495922 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -2220,7 +2220,8 @@ void op_insert(oparg_T *oap, long count1) // vis block is still marked. Get rid of it now. curwin->w_cursor.lnum = oap->start.lnum; - update_screen(UPD_INVERTED); + redraw_curbuf_later(UPD_INVERTED); + update_screen(); if (oap->motion_type == kMTBlockWise) { // When 'virtualedit' is used, need to insert the extra spaces before @@ -2772,7 +2773,10 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) } // redisplay now, so message is not deleted - update_topline_redraw(); + update_topline(curwin); + if (must_redraw) { + update_screen(); + } if (yank_type == kMTBlockWise) { smsg(NGETTEXT("block of %" PRId64 " line yanked%s", "block of %" PRId64 " lines yanked%s", yanklines), diff --git a/src/nvim/option.c b/src/nvim/option.c index e7d0b171f6..4a93fddc1b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -147,6 +147,13 @@ typedef enum { # include "option.c.generated.h" #endif +void set_init_tablocal(void) +{ + // susy baka: cmdheight calls itself OPT_GLOBAL but is really tablocal! + int ch_idx = findoption("cmdheight"); + p_ch = (long)options[ch_idx].def_val; +} + /// Initialize the options, first part. /// /// Called only once from main(), just after creating the first buffer. @@ -2634,9 +2641,8 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, /// Called after an option changed: check if something needs to be redrawn. void check_redraw(uint32_t flags) { - // Careful: P_RCLR and P_RALL are a combination of other P_ flags - bool doclear = (flags & P_RCLR) == P_RCLR; - bool all = ((flags & P_RALL) == P_RALL || doclear); + // Careful: P_RALL is a combination of other P_ flags + bool all = (flags & P_RALL) == P_RALL; if ((flags & P_RSTAT) || all) { // mark all status lines and window bars dirty status_redraw_all(); @@ -2651,9 +2657,7 @@ void check_redraw(uint32_t flags) if (flags & P_RWINONLY) { redraw_later(curwin, UPD_NOT_VALID); } - if (doclear) { - redraw_all_later(UPD_CLEAR); - } else if (all) { + if (all) { redraw_all_later(UPD_NOT_VALID); } } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index e27607d7a8..4e48c992c2 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -492,7 +492,7 @@ EXTERN unsigned dy_flags; #define DY_LASTLINE 0x001 #define DY_TRUNCATE 0x002 #define DY_UHEX 0x004 -// code should use msg_use_msgsep() to check if msgsep is active +// legacy flag, not used #define DY_MSGSEP 0x008 EXTERN int p_ed; // 'edcompatible' EXTERN char *p_ead; // 'eadirection' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index aa643eec36..82fd0d7428 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -20,7 +20,7 @@ -- lists: (nil), comma, onecomma, flags, flagscomma -- scopes: global, buffer, window -- redraw options: statuslines, current_window, curent_window_only, --- current_buffer, all_windows, everything, curswant +-- current_buffer, all_windows, curswant -- defaults: {condition=#if condition, if_true=default, if_false=default} -- #if condition: -- string: #ifdef string @@ -128,7 +128,6 @@ return { full_name='background', abbreviation='bg', short_desc=N_("\"dark\" or \"light\", used for highlight colors"), type='string', scope={'global'}, - redraw={'all_windows'}, varname='p_bg', defaults={if_true="dark"} }, @@ -395,7 +394,6 @@ return { short_desc=N_("number of columns in the display"), type='number', scope={'global'}, no_mkrc=true, - redraw={'everything'}, varname='p_columns', defaults={if_true=macros('DFLT_COLS')} }, @@ -422,7 +420,6 @@ return { full_name='compatible', abbreviation='cp', short_desc=N_("No description"), type='bool', scope={'global'}, - redraw={'all_windows'}, varname='p_force_off', -- pri_mkrc isn't needed here, optval_default() -- always returns TRUE for 'compatible' @@ -663,7 +660,7 @@ return { deny_duplicates=true, redraw={'all_windows'}, varname='p_dy', - defaults={if_true="lastline,msgsep"} + defaults={if_true="lastline"} }, { full_name='eadirection', abbreviation='ead', @@ -708,7 +705,6 @@ return { full_name='equalalways', abbreviation='ea', short_desc=N_("windows are automatically made the same size"), type='bool', scope={'global'}, - redraw={'all_windows'}, varname='p_ea', defaults={if_true=true} }, @@ -1051,7 +1047,6 @@ return { full_name='guioptions', abbreviation='go', short_desc=N_("GUI: Which components and options are used"), type='string', list='flags', scope={'global'}, - redraw={'all_windows'}, enable_if=false, }, { @@ -1195,7 +1190,6 @@ return { full_name='inccommand', abbreviation='icm', short_desc=N_("Live preview of substitution"), type='string', scope={'global'}, - redraw={'all_windows'}, varname='p_icm', defaults={if_true="nosplit"} }, @@ -1403,7 +1397,6 @@ return { short_desc=N_("of lines in the display"), type='number', scope={'global'}, no_mkrc=true, - redraw={'everything'}, varname='p_lines', defaults={if_true=macros('DFLT_ROWS')} }, @@ -2023,7 +2016,6 @@ return { full_name='scrolloff', abbreviation='so', short_desc=N_("minimum nr. of lines above and below cursor"), type='number', scope={'global', 'window'}, - redraw={'all_windows'}, varname='p_so', defaults={if_true=0} }, @@ -2260,7 +2252,6 @@ return { full_name='sidescrolloff', abbreviation='siso', short_desc=N_("min. nr. of columns to left and right of cursor"), type='number', scope={'global', 'window'}, - redraw={'all_windows'}, varname='p_siso', defaults={if_true=0} }, @@ -2453,7 +2444,7 @@ return { short_desc=N_("custom format for the console tab pages line"), type='string', scope={'global'}, modelineexpr=true, - redraw={'all_windows'}, + redraw={'statuslines'}, varname='p_tal', defaults={if_true=""} }, diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 5483c9cb94..74376c8b8a 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -818,7 +818,7 @@ static bool pum_set_selected(int n, int repeat) // TODO(bfredl): can simplify, get rid of the flag munging? // or at least eliminate extra redraw before win_enter()? pum_is_visible = false; - update_screen(0); + update_screen(); pum_is_visible = true; if (!resized && win_valid(curwin_save)) { @@ -830,7 +830,7 @@ static bool pum_set_selected(int n, int repeat) // May need to update the screen again when there are // autocommands involved. pum_is_visible = false; - update_screen(0); + update_screen(); pum_is_visible = true; } } diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index eeba7fe3c3..f9d139c466 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2784,7 +2784,10 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf // Update the screen before showing the message, unless the screen // scrolled up. if (!msg_scrolled) { - update_topline_redraw(); + update_topline(curwin); + if (must_redraw) { + update_screen(); + } } snprintf((char *)IObuff, IOSIZE, _("(%d of %d)%s%s: "), qf_index, qf_get_curlist(qi)->qf_count, diff --git a/src/nvim/search.c b/src/nvim/search.c index 336dd50292..ed0f25cba0 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -2321,7 +2321,7 @@ void showmatch(int c) dollar_vcol = -1; } curwin->w_virtcol++; // do display ')' just before "$" - update_screen(UPD_VALID); // show the new char first + update_screen(); // show the new char first save_dollar_vcol = dollar_vcol; save_state = State; diff --git a/src/nvim/state.c b/src/nvim/state.c index 0353e61742..7712fcd39a 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -57,7 +57,7 @@ getkey: // Duplicate display updating logic in vgetorpeek() if (((State & MODE_INSERT) != 0 || p_lz) && (State & MODE_CMDLINE) == 0 && must_redraw != 0 && !need_wait_return) { - update_screen(0); + update_screen(); setcursor(); // put cursor back where it belongs } // Flush screen updates before blocking diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index c52586fea2..e54a1c8334 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -522,7 +522,7 @@ static int terminal_check(VimState *state) terminal_check_cursor(); if (must_redraw) { - update_screen(0); + update_screen(); } if (need_maketitle) { // Update title in terminal-mode. #7248 diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 8ef24b484e..47c83b8ed1 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -138,7 +138,7 @@ bool ui_comp_should_draw(void) /// /// TODO(bfredl): later on the compositor should just use win_float_pos events, /// though that will require slight event order adjustment: emit the win_pos -/// events in the beginning of update_screen(0), rather than in ui_flush() +/// events in the beginning of update_screen(), rather than in ui_flush() bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width, bool valid, bool on_top) { diff --git a/src/nvim/version.c b/src/nvim/version.c index 5888d4614e..d4d406482d 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -2324,6 +2324,7 @@ static void do_intro_line(long row, char *mesg, int attr) /// @param eap void ex_intro(exarg_T *eap) { + // TODO(bfredl): use msg_grid instead! screenclear(); intro_message(true); wait_return(true); diff --git a/src/nvim/window.c b/src/nvim/window.c index c3806e10ff..c0edef7abc 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3865,13 +3865,12 @@ void close_others(int message, int forceit) } // Allocate the first window and put an empty buffer in it. -// Called from main(). -// -// Return FAIL when something goes wrong. -int win_alloc_first(void) +// Only called from main(). +void win_alloc_first(void) { if (win_alloc_firstwin(NULL) == FAIL) { - return FAIL; + // allocating first buffer before any autocmds should not fail. + abort(); } first_tabpage = alloc_tabpage(); @@ -3880,8 +3879,6 @@ int win_alloc_first(void) curtab->tp_firstwin = firstwin; curtab->tp_lastwin = lastwin; curtab->tp_curwin = curwin; - - return OK; } // Init `aucmd_win`. This can only be done after the first window |