diff options
Diffstat (limited to 'src/nvim/screen.c')
| -rw-r--r-- | src/nvim/screen.c | 296 |
1 files changed, 164 insertions, 132 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 5255fd2a51..4c830bb256 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -363,7 +363,7 @@ void update_screen(int type) need_wait_return = FALSE; } - if (type >= NOT_VALID) { + if (type >= CLEAR || !default_grid.valid) { ui_comp_set_screen_valid(false); } win_ui_flush_positions(); @@ -621,6 +621,11 @@ static void win_update(win_T *wp) linenr_T mod_bot = 0; int save_got_int; + // 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. + buf_signcols(buf); + type = wp->w_redr_type; win_grid_alloc(wp); @@ -673,8 +678,6 @@ static void win_update(win_T *wp) mod_bot = wp->w_redraw_bot + 1; else mod_bot = 0; - wp->w_redraw_top = 0; /* reset for next time */ - wp->w_redraw_bot = 0; if (buf->b_mod_set) { if (mod_top == 0 || mod_top > buf->b_mod_top) { mod_top = buf->b_mod_top; @@ -771,6 +774,8 @@ static void win_update(win_T *wp) 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 + wp->w_redraw_bot = 0; /* * When only displaying the lines at the top, set top_end. Used when @@ -1130,6 +1135,9 @@ static void win_update(win_T *wp) /* reset got_int, otherwise regexp won't work */ save_got_int = got_int; got_int = 0; + // Set the time limit to 'redrawtime'. + proftime_T syntax_tm = profile_setlimit(p_rdt); + syn_set_timeout(&syntax_tm); win_foldinfo.fi_level = 0; /* @@ -1456,7 +1464,7 @@ static void win_update(win_T *wp) set_empty_rows(wp, srow); wp->w_botline = lnum; } else { - win_draw_end(wp, '@', ' ', srow, wp->w_grid.Rows, HLF_AT); + win_draw_end(wp, '@', ' ', true, srow, wp->w_grid.Rows, at_attr); wp->w_botline = lnum; } } else { @@ -1473,7 +1481,7 @@ static void win_update(win_T *wp) if (row + j > wp->w_grid.Rows) { j = wp->w_grid.Rows - row; } - win_draw_end(wp, i, i, row, row + (int)j, HLF_DED); + win_draw_end(wp, i, i, true, row, row + (int)j, HLF_DED); row += j; } } else if (dollar_vcol == -1) @@ -1481,12 +1489,14 @@ static void win_update(win_T *wp) // make sure the rest of the screen is blank // write the 'eob' character to rows that aren't part of the file. - win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', row, wp->w_grid.Rows, HLF_EOB); + win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, row, wp->w_grid.Rows, + HLF_EOB); } if (wp->w_redr_type >= REDRAW_TOP) { draw_vsep_win(wp, 0); } + syn_set_timeout(NULL); /* Reset the type of redrawing required, the window has been updated. */ wp->w_redr_type = 0; @@ -1543,85 +1553,66 @@ int win_signcol_width(win_T *wp) return 2; } -/* - * Clear the rest of the window and mark the unused lines with "c1". use "c2" - * as the filler character. - */ -static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T hl) +/// 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 n = 0; -# define FDC_OFF n - int fdc = compute_foldcolumn(wp, 0); + int nn = off + width; - int attr = hl_combine_attr(wp->w_hl_attr_normal, win_hl_attr(wp, hl)); + if (nn > wp->w_grid.Columns) { + nn = wp->w_grid.Columns; + } if (wp->w_p_rl) { - // No check for cmdline window: should never be right-left. - n = fdc; + grid_fill(&wp->w_grid, row, endrow, W_ENDCOL(wp) - nn, W_ENDCOL(wp) - off, + c1, c2, attr); + } else { + grid_fill(&wp->w_grid, row, endrow, off, nn, c1, c2, attr); + } - if (n > 0) { - // draw the fold column at the right - if (n > wp->w_grid.Columns) { - n = wp->w_grid.Columns; - } - grid_fill(&wp->w_grid, row, endrow, wp->w_grid.Columns - n, - wp->w_grid.Columns, ' ', ' ', win_hl_attr(wp, HLF_FC)); - } + return nn; +} - if (signcolumn_on(wp)) { - int nn = n + win_signcol_width(wp); +/// 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. +static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, + int endrow, hlf_T hl) +{ + int n = 0; - // draw the sign column left of the fold column - if (nn > wp->w_grid.Columns) { - nn = wp->w_grid.Columns; - } - grid_fill(&wp->w_grid, row, endrow, wp->w_grid.Columns - nn, - wp->w_grid.Columns - n, ' ', ' ', win_hl_attr(wp, HLF_SC)); - n = nn; + 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)); } - - grid_fill(&wp->w_grid, row, endrow, 0, wp->w_grid.Columns - 1 - FDC_OFF, - c2, c2, attr); - grid_fill(&wp->w_grid, row, endrow, - wp->w_grid.Columns - 1 - FDC_OFF, wp->w_grid.Columns - FDC_OFF, - c1, c2, attr); - } else { - if (cmdwin_type != 0 && wp == curwin) { - /* draw the cmdline character in the leftmost column */ - n = 1; - if (n > wp->w_grid.Columns) { - n = wp->w_grid.Columns; - } - grid_fill(&wp->w_grid, row, endrow, 0, n, cmdwin_type, ' ', - win_hl_attr(wp, HLF_AT)); + // draw the sign column + int count = win_signcol_count(wp); + if (count > 0) { + n = win_fill_end(wp, ' ', ' ', n, win_signcol_width(wp) * count, row, + endrow, win_hl_attr(wp, HLF_SC)); } - if (fdc > 0) { - int nn = n + fdc; - - // draw the fold column at the left - if (nn > wp->w_grid.Columns) { - nn = wp->w_grid.Columns; - } - grid_fill(&wp->w_grid, row, endrow, n, nn, ' ', ' ', - win_hl_attr(wp, HLF_FC)); - n = nn; + // 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)); } + } - if (signcolumn_on(wp)) { - int nn = n + win_signcol_width(wp); - - // draw the sign column after the fold column - if (nn > wp->w_grid.Columns) { - nn = wp->w_grid.Columns; - } - grid_fill(&wp->w_grid, row, endrow, n, nn, ' ', ' ', - win_hl_attr(wp, HLF_SC)); - n = nn; - } + int attr = hl_combine_attr(wp->w_hl_attr_normal, win_hl_attr(wp, hl)); - grid_fill(&wp->w_grid, row, endrow, FDC_OFF, wp->w_grid.Columns, c1, c2, - attr); + if (wp->w_p_rl) { + grid_fill(&wp->w_grid, row, endrow, wp->w_wincol, W_ENDCOL(wp) - 1 - n, + c2, c2, attr); + grid_fill(&wp->w_grid, row, endrow, W_ENDCOL(wp) - 1 - n, W_ENDCOL(wp) - n, + c1, c2, attr); + } else { + grid_fill(&wp->w_grid, row, endrow, n, wp->w_grid.Columns, c1, c2, attr); } + set_empty_rows(wp, row); } @@ -1773,10 +1764,10 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_grid.Columns - col); // If signs are being displayed, add spaces. - if (signcolumn_on(wp)) { + if (win_signcol_count(wp) > 0) { len = wp->w_grid.Columns - col; if (len > 0) { - int len_max = win_signcol_width(wp); + int len_max = win_signcol_width(wp) * win_signcol_count(wp); if (len > len_max) { len = len_max; } @@ -2180,7 +2171,6 @@ win_line ( int vcol_off = 0; ///< offset for concealed characters int did_wcol = false; int match_conc = 0; ///< cchar for match functions - int has_match_conc = 0; ///< match wants to conceal int old_boguscols = 0; # define VCOL_HLC (vcol - vcol_off) # define FIX_FOR_BOGUSCOLS \ @@ -2202,7 +2192,7 @@ win_line ( // To speed up the loop below, set extra_check when there is linebreak, // trailing white space and/or syntax processing to be done. extra_check = wp->w_p_lbr; - if (syntax_present(wp) && !wp->w_s->b_syn_error) { + if (syntax_present(wp) && !wp->w_s->b_syn_error && !wp->w_s->b_syn_slow) { // Prepare for syntax highlighting in this line. When there is an // error, stop syntax highlighting. save_did_emsg = did_emsg; @@ -2212,8 +2202,10 @@ win_line ( wp->w_s->b_syn_error = true; } else { did_emsg = save_did_emsg; - has_syntax = true; - extra_check = true; + if (!wp->w_s->b_syn_slow) { + has_syntax = true; + extra_check = true; + } } } @@ -2377,31 +2369,34 @@ win_line ( filler_lines = wp->w_topfill; filler_todo = filler_lines; - // Cursor line highlighting for 'cursorline' in the current window. Not - // when Visual mode is active, because it's not clear what is selected - // then. - if (wp->w_p_cul && lnum == wp->w_cursor.lnum - && !(wp == curwin && VIsual_active)) { - int cul_attr = win_hl_attr(wp, HLF_CUL); - HlAttrs ae = syn_attr2entry(cul_attr); - - // We make a compromise here (#7383): - // * low-priority CursorLine if fg is not set - // * high-priority ("same as Vim" priority) CursorLine if fg is set - if (ae.rgb_fg_color == -1 && ae.cterm_fg_color == 0) { - line_attr_lowprio = cul_attr; - } else { - if (!(State & INSERT) && bt_quickfix(wp->w_buffer) - && qf_current_entry(wp) == lnum) { - line_attr = hl_combine_attr(cul_attr, line_attr); + // Cursor line highlighting for 'cursorline' in the current window. + if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { + // Do not show the cursor line when Visual mode is active, because it's + // not clear what is selected then. + if (!(wp == curwin && VIsual_active)) { + int cul_attr = win_hl_attr(wp, HLF_CUL); + HlAttrs ae = syn_attr2entry(cul_attr); + + // We make a compromise here (#7383): + // * low-priority CursorLine if fg is not set + // * high-priority ("same as Vim" priority) CursorLine if fg is set + if (ae.rgb_fg_color == -1 && ae.cterm_fg_color == 0) { + line_attr_lowprio = cul_attr; } else { - line_attr = cul_attr; + if (!(State & INSERT) && bt_quickfix(wp->w_buffer) + && qf_current_entry(wp) == lnum) { + line_attr = hl_combine_attr(cul_attr, line_attr); + } else { + line_attr = cul_attr; + } } } + // Update w_last_cursorline even if Visual mode is active. + wp->w_last_cursorline = wp->w_cursor.lnum; } // If this line has a sign with line highlighting set line_attr. - v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL); + v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL, 0, 1); if (v != 0) { line_attr = sign_get_attr((int)v, SIGN_LINEHL); } @@ -2450,7 +2445,9 @@ win_line ( } if (wp->w_p_list) { - if (curwin->w_p_lcs_chars.space || wp->w_p_lcs_chars.trail) { + if (curwin->w_p_lcs_chars.space + || wp->w_p_lcs_chars.trail + || wp->w_p_lcs_chars.nbsp) { extra_check = true; } // find start of trailing whitespace @@ -2549,9 +2546,10 @@ win_line ( } wp->w_cursor = pos; - /* Need to restart syntax highlighting for this line. */ - if (has_syntax) + // Need to restart syntax highlighting for this line. + if (has_syntax) { syntax_start(wp, lnum); + } } } @@ -2597,6 +2595,9 @@ win_line ( } next_search_hl(wp, shl, lnum, (colnr_T)v, shl == &search_hl ? NULL : cur); + if (wp->w_s->b_syn_slow) { + has_syntax = false; + } // Need to get the line again, a multi-line regexp may have made it // invalid. @@ -2651,9 +2652,11 @@ win_line ( extra_check = true; } + int sign_idx = 0; // Repeat for the whole displayed line. for (;; ) { - has_match_conc = 0; + int has_match_conc = 0; ///< match wants to conceal + bool did_decrement_ptr = false; // Skip this quickly when working on the text. if (draw_state != WL_LINE) { if (draw_state == WL_CMDLINE - 1 && n_extra == 0) { @@ -2691,7 +2694,8 @@ win_line ( draw_state = WL_SIGN; /* Show the sign column when there are any signs in this * buffer or when using Netbeans. */ - if (signcolumn_on(wp)) { + int count = win_signcol_count(wp); + if (count > 0) { int text_sign; // Draw cells with the sign value or blank. c_extra = ' '; @@ -2700,7 +2704,8 @@ win_line ( n_extra = win_signcol_width(wp); if (row == startrow + filler_lines && filler_todo <= 0) { - text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT); + text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT, + sign_idx, count); if (text_sign != 0) { p_extra = sign_get_text(text_sign); int symbol_blen = (int)STRLEN(p_extra); @@ -2718,6 +2723,11 @@ win_line ( char_attr = sign_get_attr(text_sign, SIGN_TEXT); } } + + sign_idx++; + if (sign_idx < count) { + draw_state = WL_SIGN - 1; + } } } @@ -2754,8 +2764,15 @@ win_line ( if (wp->w_skipcol > 0) for (p_extra = extra; *p_extra == ' '; ++p_extra) *p_extra = '-'; - if (wp->w_p_rl) /* reverse line numbers */ - rl_mirror(extra); + if (wp->w_p_rl) { // reverse line numbers + // like rl_mirror(), but keep the space at the end + char_u *p2 = skiptowhite(extra) - 1; + for (char_u *p1 = extra; p1 < p2; p1++, p2--) { + const int t = *p1; + *p1 = *p2; + *p2 = t; + } + } p_extra = extra; c_extra = NUL; c_final = NUL; @@ -2766,7 +2783,8 @@ win_line ( n_extra = number_width(wp) + 1; char_attr = win_hl_attr(wp, HLF_N); - int num_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_NUMHL); + int num_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_NUMHL, + 0, 1); if (num_sign != 0) { // :sign defined with "numhl" highlight. char_attr = sign_get_attr(num_sign, SIGN_NUMHL); @@ -2853,6 +2871,7 @@ win_line ( } if (draw_state == WL_LINE - 1 && n_extra == 0) { + sign_idx = 0; draw_state = WL_LINE; if (saved_n_extra) { /* Continue item from end of wrapped line. */ @@ -2936,8 +2955,11 @@ win_line ( shl->endcol = tmp_col; } shl->attr_cur = shl->attr; - if (cur != NULL && syn_name2id((char_u *)"Conceal") - == cur->hlg_id) { + // Match with the "Conceal" group results in hiding + // the match. + if (cur != NULL + && shl != &search_hl + && syn_name2id((char_u *)"Conceal") == cur->hlg_id) { has_match_conc = v == (long)shl->startcol ? 2 : 1; match_conc = cur->conceal_char; } else { @@ -3207,6 +3229,7 @@ win_line ( // Put pointer back so that the character will be // displayed at the start of the next line. ptr--; + did_decrement_ptr = true; } else if (*ptr != NUL) { ptr += mb_l - 1; } @@ -3255,16 +3278,18 @@ win_line ( line = ml_get_buf(wp->w_buffer, lnum, FALSE); ptr = line + v; - if (!attr_pri) + if (!attr_pri) { char_attr = syntax_attr; - else + } else { char_attr = hl_combine_attr(syntax_attr, char_attr); - /* no concealing past the end of the line, it interferes - * with line highlighting */ - if (c == NUL) + } + // no concealing past the end of the line, it interferes + // with line highlighting. + if (c == NUL) { syntax_flags = 0; - else + } else { syntax_flags = get_syntax_info(&syntax_seqnr); + } } else if (!attr_pri) { char_attr = 0; } @@ -3356,7 +3381,7 @@ win_line ( } if (wp->w_buffer->terminal) { - char_attr = hl_combine_attr(char_attr, term_attrs[vcol]); + char_attr = hl_combine_attr(term_attrs[vcol], char_attr); } // Found last space before word: check for line break. @@ -3663,6 +3688,11 @@ win_line ( prev_syntax_id = 0; is_concealing = FALSE; } + + if (n_skip > 0 && did_decrement_ptr) { + // not showing the '>', put pointer back to avoid getting stuck + ptr++; + } } /* In the cursor line and we may be concealing characters: correct @@ -3971,8 +4001,10 @@ win_line ( break; } - // line continues beyond line end - if (wp->w_p_lcs_chars.ext + // Show "extends" character from 'listchars' if beyond the line end and + // 'list' is set. + if (wp->w_p_lcs_chars.ext != NUL + && wp->w_p_list && !wp->w_p_wrap && filler_todo <= 0 && (wp->w_p_rl ? col == 0 : col == grid->Columns - 1) @@ -4192,11 +4224,9 @@ win_line ( ) || lcs_eol_one == -1) break; - /* When the window is too narrow draw all "@" lines. */ - if (draw_state != WL_LINE - && filler_todo <= 0 - ) { - win_draw_end(wp, '@', ' ', row, wp->w_grid.Rows, HLF_AT); + // When the window is too narrow draw all "@" lines. + if (draw_state != WL_LINE && filler_todo <= 0) { + win_draw_end(wp, '@', ' ', true, row, wp->w_grid.Rows, HLF_AT); row = endrow; } @@ -4813,13 +4843,13 @@ static void win_redr_status(win_T *wp) p = NameBuff; len = (int)STRLEN(p); - if (wp->w_buffer->b_help + if (bt_help(wp->w_buffer) || wp->w_p_pvw || bufIsChanged(wp->w_buffer) || wp->w_buffer->b_p_ro) { *(p + len++) = ' '; } - if (wp->w_buffer->b_help) { + if (bt_help(wp->w_buffer)) { STRCPY(p + len, _("[Help]")); len += (int)STRLEN(p + len); } @@ -6351,14 +6381,12 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col, } -/* - * show the current mode and ruler - * - * If clear_cmdline is TRUE, clear the rest of the cmdline. - * If clear_cmdline is FALSE there may be a message there that needs to be - * cleared only if a mode is shown. - * Return the length of the message (0 if no message). - */ +// Show the current mode and ruler. +// +// If clear_cmdline is TRUE, clear the rest of the cmdline. +// If clear_cmdline is FALSE there may be a message there that needs to be +// cleared only if a mode is shown. +// Return the length of the message (0 if no message). int showmode(void) { int need_clear; @@ -7151,8 +7179,12 @@ void screen_resize(int width, int height) if (curwin->w_p_scb) do_check_scrollbind(TRUE); if (State & CMDLINE) { + redraw_popupmenu = false; update_screen(NOT_VALID); redrawcmdline(); + if (pum_drawn()) { + cmdline_pum_display(false); + } } else { update_topline(); if (pum_drawn()) { |