diff options
Diffstat (limited to 'src/nvim/screen.c')
| -rw-r--r-- | src/nvim/screen.c | 1321 |
1 files changed, 645 insertions, 676 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c index d9a21aa81f..2e64eb864f 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + /* * screen.c: code for displaying on the screen * @@ -21,8 +24,6 @@ * cells the next byte in ScreenLines[] is 0. * ScreenLinesC[][] contain up to 'maxcombine' composing characters * (drawn on top of the first character). There is 0 after the last one used. - * ScreenLines2[] is only used for euc-jp to store the second byte if the - * first byte is 0x8e (single-width character). * * The screen_*() functions write to the screen and handle updating * ScreenLines[]. @@ -83,6 +84,7 @@ #include <stdbool.h> #include <string.h> +#include "nvim/log.h" #include "nvim/vim.h" #include "nvim/ascii.h" #include "nvim/arabic.h" @@ -102,6 +104,7 @@ #include "nvim/indent.h" #include "nvim/getchar.h" #include "nvim/main.h" +#include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -128,16 +131,12 @@ #include "nvim/version.h" #include "nvim/window.h" #include "nvim/os/time.h" +#include "nvim/api/private/helpers.h" #define MB_FILLER_CHAR '<' /* character used when a double-width character * doesn't fit. */ #define W_ENDCOL(wp) (wp->w_wincol + wp->w_width) -/* - * The attributes that are actually active for writing to the screen. - */ -static int screen_attr = 0; - static match_T search_hl; /* used for 'hlsearch' highlight matching */ static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */ @@ -150,7 +149,6 @@ static schar_T *current_ScreenLine; StlClickDefinition *tab_page_click_defs = NULL; long tab_page_click_defs_size = 0; -# define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c), (rl)) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "screen.c.generated.h" #endif @@ -184,8 +182,6 @@ void redraw_win_later(win_T *wp, int type) void redraw_later_clear(void) { redraw_all_later(CLEAR); - /* Use attributes that is very unlikely to appear in text. */ - screen_attr = HL_BOLD | HL_UNDERLINE | HL_INVERSE; } /* @@ -302,13 +298,25 @@ void update_screen(int type) * if the screen was scrolled up when displaying a message, scroll it down */ if (msg_scrolled) { - clear_cmdline = TRUE; - if (msg_scrolled > Rows - 5) /* clearing is faster */ + clear_cmdline = true; + if (dy_flags & DY_MSGSEP) { + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + int valid = Rows - msg_scrollsize(); + if (wp->w_winrow + wp->w_height > valid) { + wp->w_redr_type = NOT_VALID; + wp->w_lines_valid = 0; + } + if (wp->w_winrow + wp->w_height + wp->w_status_height > valid) { + wp->w_redr_status = true; + } + } + } else if (msg_scrolled > Rows - 5) { // clearing is faster type = CLEAR; - else if (type != CLEAR) { - check_for_delay(FALSE); - if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows, NULL) == FAIL) + } else if (type != CLEAR) { + check_for_delay(false); + if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows, NULL) == FAIL) { type = CLEAR; + } FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->w_winrow < msg_scrolled) { if (wp->w_winrow + wp->w_height > msg_scrolled @@ -340,8 +348,9 @@ void update_screen(int type) if (need_highlight_changed) highlight_changed(); - if (type == CLEAR) { /* first clear screen */ - screenclear(); /* will reset clear_cmdline */ + if (type == CLEAR) { // first clear screen + screenclear(); // will reset clear_cmdline + cmdline_screen_cleared(); // clear external cmdline state type = NOT_VALID; } @@ -375,15 +384,24 @@ void update_screen(int type) )) curwin->w_redr_type = type; - /* Redraw the tab pages line if needed. */ - if (redraw_tabline || type >= NOT_VALID) + // Redraw the tab pages line if needed. + if (redraw_tabline || type >= NOT_VALID) { + update_window_hl(curwin, type >= NOT_VALID); + FOR_ALL_TABS(tp) { + if (tp != curtab) { + update_window_hl(tp->tp_curwin, type >= NOT_VALID); + } + } draw_tabline(); + } /* * Correct stored syntax highlighting info for changes in each displayed * buffer. Each buffer must only be done once. */ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + update_window_hl(wp, type >= NOT_VALID); + if (wp->w_buffer->b_mod_set) { win_T *wwp; @@ -678,12 +696,18 @@ static void win_update(win_T *wp) if (wp->w_nrwidth != i) { type = NOT_VALID; wp->w_nrwidth = i; - } 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). - */ + + if (buf->terminal) { + terminal_resize(buf->terminal, + (uint16_t)(MAX(0, wp->w_width - win_col_off(wp))), + (uint16_t)wp->w_height); + } + } 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 = NOT_VALID; } else { /* @@ -978,7 +1002,7 @@ static void win_update(win_T *wp) * first. */ if (mid_start == 0) { mid_end = wp->w_height; - if (lastwin == firstwin) { + if (ONE_WINDOW) { /* Clear the screen when it was not done by win_del_lines() or * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE * then. */ @@ -1015,14 +1039,10 @@ static void win_update(win_T *wp) linenr_T from, to; if (VIsual_active) { - if (VIsual_active - && (VIsual_mode != wp->w_old_visual_mode - || type == INVERTED_ALL)) { - /* - * If the type of Visual selection changed, redraw the whole - * selection. Also when the ownership of the X selection is - * gained or lost. - */ + if (VIsual_mode != wp->w_old_visual_mode || type == INVERTED_ALL) { + // If the type of Visual selection changed, redraw the whole + // selection. Also when the ownership of the X selection is + // gained or lost. if (curwin->w_cursor.lnum < VIsual.lnum) { from = curwin->w_cursor.lnum; to = VIsual.lnum; @@ -1487,11 +1507,11 @@ static void win_update(win_T *wp) // Last line isn't finished: Display "@@@" in the last screen line. screen_puts_len((char_u *)"@@", 2, scr_row, wp->w_wincol, - hl_attr(HLF_AT)); + win_hl_attr(wp, HLF_AT)); screen_fill(scr_row, scr_row + 1, (int)wp->w_wincol + 2, (int)W_ENDCOL(wp), - '@', ' ', hl_attr(HLF_AT)); + '@', ' ', win_hl_attr(wp, HLF_AT)); set_empty_rows(wp, srow); wp->w_botline = lnum; } else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline" @@ -1499,7 +1519,7 @@ static void win_update(win_T *wp) screen_fill(wp->w_winrow + wp->w_height - 1, wp->w_winrow + wp->w_height, W_ENDCOL(wp) - 3, W_ENDCOL(wp), - '@', '@', hl_attr(HLF_AT)); + '@', '@', win_hl_attr(wp, HLF_AT)); set_empty_rows(wp, srow); wp->w_botline = lnum; } else { @@ -1572,6 +1592,20 @@ static void win_update(win_T *wp) got_int = save_got_int; } +/// Returns width of the signcolumn that should be used for the whole window +/// +/// @param wp window we want signcolumn width from +/// @return max width of signcolumn (cell unit) +/// +/// @note Returns a constant for now but hopefully we can improve neovim so that +/// the returned value width adapts to the maximum number of marks to draw +/// for the window +/// TODO(teto) +int win_signcol_width(win_T *wp) +{ + // 2 is vim default value + return 2; +} /* * Clear the rest of the window and mark the unused lines with "c1". use "c2" @@ -1583,6 +1617,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h # define FDC_OFF n int fdc = compute_foldcolumn(wp, 0); + int attr = win_hl_attr(wp, hl); + if (wp->w_p_rl) { // No check for cmdline window: should never be right-left. n = fdc; @@ -1593,11 +1629,11 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h n = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - n, W_ENDCOL(wp), - ' ', ' ', hl_attr(HLF_FC)); + ' ', ' ', win_hl_attr(wp, HLF_FC)); } if (signcolumn_on(wp)) { - int nn = n + 2; + int nn = n + win_signcol_width(wp); /* draw the sign column left of the fold column */ if (nn > wp->w_width) { @@ -1605,16 +1641,16 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - nn, W_ENDCOL(wp) - n, - ' ', ' ', hl_attr(HLF_SC)); + ' ', ' ', win_hl_attr(wp, HLF_SC)); n = nn; } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF, - c2, c2, hl_attr(hl)); + c2, c2, attr); screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF, - c1, c2, hl_attr(hl)); + c1, c2, attr); } else { if (cmdwin_type != 0 && wp == curwin) { /* draw the cmdline character in the leftmost column */ @@ -1623,7 +1659,7 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h n = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol, wp->w_wincol + n, - cmdwin_type, ' ', hl_attr(HLF_AT)); + cmdwin_type, ' ', win_hl_attr(wp, HLF_AT)); } if (fdc > 0) { int nn = n + fdc; @@ -1633,12 +1669,12 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h nn = wp->w_width; screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + n, wp->w_wincol + nn, - ' ', ' ', hl_attr(HLF_FC)); + ' ', ' ', win_hl_attr(wp, HLF_FC)); n = nn; } if (signcolumn_on(wp)) { - int nn = n + 2; + int nn = n + win_signcol_width(wp); /* draw the sign column after the fold column */ if (nn > wp->w_width) { @@ -1646,13 +1682,13 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + n, wp->w_wincol + nn, - ' ', ' ', hl_attr(HLF_SC)); + ' ', ' ', win_hl_attr(wp, HLF_SC)); n = nn; } screen_fill(wp->w_winrow + row, wp->w_winrow + endrow, wp->w_wincol + FDC_OFF, W_ENDCOL(wp), - c1, c2, hl_attr(hl)); + c1, c2, attr); } set_empty_rows(wp, row); } @@ -1687,7 +1723,7 @@ static int compute_foldcolumn(win_T *wp, int col) */ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T lnum, int row) { - char_u buf[51]; + char_u buf[FOLD_TEXT_LEN]; pos_T *top, *bot; linenr_T lnume = lnum + fold_count - 1; int len; @@ -1714,10 +1750,9 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T */ if (cmdwin_type != 0 && wp == curwin) { ScreenLines[off] = cmdwin_type; - ScreenAttrs[off] = hl_attr(HLF_AT); - if (enc_utf8) - ScreenLinesUC[off] = 0; - ++col; + ScreenAttrs[off] = win_hl_attr(wp, HLF_AT); + ScreenLinesUC[off] = 0; + col++; } // 2. Add the 'foldcolumn' @@ -1729,12 +1764,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T int i; copy_text_attr(off + wp->w_width - fdc - col, buf, fdc, - hl_attr(HLF_FC)); - /* reverse the fold column */ - for (i = 0; i < fdc; ++i) + win_hl_attr(wp, HLF_FC)); + // reverse the fold column + for (i = 0; i < fdc; i++) { ScreenLines[off + wp->w_width - i - 1 - col] = buf[i]; - } else - copy_text_attr(off + col, buf, fdc, hl_attr(HLF_FC)); + } + } else { + copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC)); + } col += fdc; } @@ -1747,16 +1784,18 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T /* Set all attributes of the 'number' or 'relativenumber' column and the * text */ - RL_MEMSET(col, hl_attr(HLF_FL), wp->w_width - col); + RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_width - col); - // If signs are being displayed, add two spaces. + // If signs are being displayed, add spaces. if (signcolumn_on(wp)) { len = wp->w_width - col; if (len > 0) { - if (len > 2) { - len = 2; + int len_max = win_signcol_width(wp); + if (len > len_max) { + len = len_max; } - copy_text_attr(off + col, (char_u *)" ", len, hl_attr(HLF_FL)); + copy_text_attr(off + col, (char_u *)" ", len, + win_hl_attr(wp, HLF_FL)); col += len; } } @@ -1788,13 +1827,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } } - sprintf((char *)buf, fmt, w, num); - if (wp->w_p_rl) - /* the line number isn't reversed */ + snprintf((char *)buf, FOLD_TEXT_LEN, fmt, w, num); + if (wp->w_p_rl) { + // the line number isn't reversed copy_text_attr(off + wp->w_width - len - col, buf, len, - hl_attr(HLF_FL)); - else - copy_text_attr(off + col, buf, len, hl_attr(HLF_FL)); + win_hl_attr(wp, HLF_FL)); + } else { + copy_text_attr(off + col, buf, len, win_hl_attr(wp, HLF_FL)); + } col += len; } } @@ -1876,12 +1916,10 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } if (cells > 1) ScreenLines[idx + 1] = 0; - } else if (enc_dbcs == DBCS_JPNU && *p == 0x8e) - /* double-byte single width character */ - ScreenLines2[idx] = p[1]; - else if (cells > 1) - /* double-width character */ + } else if (cells > 1) { + // Double-width character. ScreenLines[idx + 1] = p[1]; + } col += cells; idx += cells; p += c_len; @@ -1909,10 +1947,15 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T if (fill_fold >= 0x80) { ScreenLinesUC[off + col] = fill_fold; ScreenLinesC[0][off + col] = 0; - } else + ScreenLines[off + col] = 0x80; // avoid storing zero + } else { ScreenLinesUC[off + col] = 0; + ScreenLines[off + col] = fill_fold; + } + col++; + } else { + ScreenLines[off + col++] = fill_fold; } - ScreenLines[off + col++] = fill_fold; } if (text != buf) @@ -1952,12 +1995,12 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T len = wp->w_old_cursor_lcol; else len = wp->w_width - txtcol; - RL_MEMSET(wp->w_old_cursor_fcol + txtcol, hl_attr(HLF_V), - len - (int)wp->w_old_cursor_fcol); + RL_MEMSET(wp->w_old_cursor_fcol + txtcol, win_hl_attr(wp, HLF_V), + len - (int)wp->w_old_cursor_fcol); } } else { - /* Set all attributes of the text */ - RL_MEMSET(txtcol, hl_attr(HLF_V), wp->w_width - txtcol); + // Set all attributes of the text + RL_MEMSET(txtcol, win_hl_attr(wp, HLF_V), wp->w_width - txtcol); } } } @@ -1977,7 +2020,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T } if (txtcol >= 0 && txtcol < wp->w_width) { ScreenAttrs[off + txtcol] = - hl_combine_attr(ScreenAttrs[off + txtcol], hl_attr(HLF_MC)); + hl_combine_attr(ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_MC)); } txtcol = old_txtcol; j = wp->w_p_cc_cols[++i]; @@ -1993,11 +2036,11 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T txtcol -= wp->w_leftcol; if (txtcol >= 0 && txtcol < wp->w_width) ScreenAttrs[off + txtcol] = hl_combine_attr( - ScreenAttrs[off + txtcol], hl_attr(HLF_CUC)); + ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_CUC)); } - SCREEN_LINE(row + wp->w_winrow, wp->w_wincol, wp->w_width, - wp->w_width, FALSE); + screen_line(row + wp->w_winrow, wp->w_wincol, wp->w_width, + wp->w_width, false, wp, 0); /* * Update w_cline_height and w_cline_folded if the cursor line was @@ -2097,16 +2140,15 @@ win_line ( bool nochange /* not updating for changed text */ ) { - int col; /* visual column on screen */ - unsigned off; /* offset in ScreenLines/ScreenAttrs */ - int c = 0; /* init for GCC */ - long vcol = 0; /* virtual column (for tabs) */ + unsigned off; // offset in ScreenLines/ScreenAttrs + int c = 0; // init for GCC + long vcol = 0; // virtual column (for tabs) long vcol_sbr = -1; // virtual column after showbreak - long vcol_prev = -1; /* "vcol" of previous character */ - char_u *line; /* current line */ - char_u *ptr; /* current position in "line" */ - int row; /* row in the window, excl w_winrow */ - int screen_row; /* row on the screen, incl w_winrow */ + long vcol_prev = -1; // "vcol" of previous character + char_u *line; // current line + char_u *ptr; // current position in "line" + int row; // row in the window, excl w_winrow + int screen_row; // row on the screen, incl w_winrow char_u extra[18]; /* line number and 'fdc' must fit in here */ int n_extra = 0; /* number of extra chars */ @@ -2180,23 +2222,23 @@ win_line ( int change_start = MAXCOL; /* first col of changed area */ int change_end = -1; /* last col of changed area */ colnr_T trailcol = MAXCOL; /* start of trailing spaces */ - int need_showbreak = FALSE; - int line_attr = 0; /* attribute for the whole line */ - matchitem_T *cur; /* points to the match list */ - match_T *shl; /* points to search_hl or a match */ - int shl_flag; /* flag to indicate whether search_hl - has been processed or not */ - int prevcol_hl_flag; /* flag to indicate whether prevcol - equals startcol of search_hl or one - of the matches */ - int prev_c = 0; /* previous Arabic character */ - int prev_c1 = 0; /* first composing char for prev_c */ + int need_showbreak = false; // overlong line, skip first x chars + int line_attr = 0; // attribute for the whole line + matchitem_T *cur; // points to the match list + match_T *shl; // points to search_hl or a match + int shl_flag; // flag to indicate whether search_hl + // has been processed or not + int prevcol_hl_flag; // flag to indicate whether prevcol + // equals startcol of search_hl or one + // of the matches + int prev_c = 0; // previous Arabic character + int prev_c1 = 0; // first composing char for prev_c int did_line_attr = 0; bool search_attr_from_match = false; // if search_attr is from :match bool has_bufhl = false; // this buffer has highlight matches int bufhl_attr = 0; // attributes desired by bufhl - bufhl_lineinfo_T bufhl_info; // bufhl data for this line + BufhlLineInfo bufhl_info; // bufhl data for this line /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ @@ -2212,7 +2254,7 @@ win_line ( int syntax_flags = 0; int syntax_seqnr = 0; int prev_syntax_id = 0; - int conceal_attr = hl_attr(HLF_CONCEAL); + int conceal_attr = win_hl_attr(wp, HLF_CONCEAL); int is_concealing = false; int boguscols = 0; ///< nonexistent columns added to ///< force wrapping @@ -2360,8 +2402,8 @@ win_line ( /* if inverting in this line set area_highlighting */ if (fromcol >= 0) { - area_highlighting = TRUE; - attr = hl_attr(HLF_V); + area_highlighting = true; + attr = win_hl_attr(wp, HLF_V); } } /* @@ -2385,8 +2427,8 @@ win_line ( /* do at least one character; happens when past end of line */ if (fromcol == tocol) tocol = fromcol + 1; - area_highlighting = TRUE; - attr = hl_attr(HLF_I); + area_highlighting = true; + attr = win_hl_attr(wp, HLF_I); } filler_lines = diff_check(wp, lnum); @@ -2407,14 +2449,15 @@ win_line ( filler_lines = wp->w_topfill; filler_todo = filler_lines; - /* If this line has a sign with line highlighting set line_attr. */ + // If this line has a sign with line highlighting set line_attr. v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL); - if (v != 0) - line_attr = sign_get_attr((int)v, TRUE); + if (v != 0) { + line_attr = sign_get_attr((int)v, true); + } // Highlight the current line in the quickfix window. if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = hl_attr(HLF_QFL); + line_attr = win_hl_attr(wp, HLF_QFL); } if (line_attr != 0) { @@ -2448,7 +2491,7 @@ win_line ( } else { /* Long line, use only the last SPWORDLEN bytes. */ nextlinecol = v - SPWORDLEN; - memmove(nextline, line + nextlinecol, SPWORDLEN); + memmove(nextline, line + nextlinecol, SPWORDLEN); // -V512 nextline_idx = SPWORDLEN + 1; } } @@ -2503,7 +2546,11 @@ win_line ( if (vcol > v) { vcol -= c; ptr = prev_ptr; - n_skip = v - vcol; + // If the character fits on the screen, don't need to skip it. + // Except for a TAB. + if (utf_ptr2cells(ptr) >= c || *ptr == TAB) { + n_skip = v - vcol; + } } /* @@ -2580,13 +2627,14 @@ win_line ( * Do this for both search_hl and the match list. */ cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE) { + shl_flag = false; + while (cur != NULL || !shl_flag) { + if (!shl_flag) { shl = &search_hl; - shl_flag = TRUE; - } else - shl = &cur->hl; + shl_flag = true; + } else { + shl = &cur->hl; // -V595 + } shl->startcol = MAXCOL; shl->endcol = MAXCOL; shl->attr_cur = 0; @@ -2634,26 +2682,26 @@ win_line ( cur = cur->next; } - /* Cursor line highlighting for 'cursorline' in the current window. Not - * when Visual mode is active, because it's not clear what is selected - * then. */ + // 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)) { if (line_attr != 0 && !(State & INSERT) && bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = hl_combine_attr(hl_attr(HLF_CUL), line_attr); + line_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUL), line_attr); } else { - line_attr = hl_attr(HLF_CUL); + line_attr = win_hl_attr(wp, HLF_CUL); } area_highlighting = true; } off = (unsigned)(current_ScreenLine - ScreenLines); - col = 0; + int col = 0; // Visual column on screen. if (wp->w_p_rl) { - /* Rightleft window: process the text in the normal direction, but put - * it in current_ScreenLine[] from right to left. Start at the - * rightmost column of the window. */ + // Rightleft window: process the text in the normal direction, but put + // it in current_ScreenLine[] from right to left. Start at the + // rightmost column of the window. col = wp->w_width - 1; off += col; } @@ -2676,7 +2724,7 @@ win_line ( /* Draw the cmdline character. */ n_extra = 1; c_extra = cmdwin_type; - char_attr = hl_attr(HLF_AT); + char_attr = win_hl_attr(wp, HLF_AT); } } @@ -2685,13 +2733,16 @@ win_line ( draw_state = WL_FOLD; if (fdc > 0) { - // Draw the 'foldcolumn'. - fill_foldcolumn(extra, wp, false, lnum); + // Draw the 'foldcolumn'. Allocate a buffer, "extra" may + // already be in use. + xfree(p_extra_free); + p_extra_free = xmalloc(12 + 1); + fill_foldcolumn(p_extra_free, wp, false, lnum); n_extra = fdc; - p_extra = extra; - p_extra[n_extra] = NUL; + p_extra_free[n_extra] = NUL; + p_extra = p_extra_free; c_extra = NUL; - char_attr = hl_attr(HLF_FC); + char_attr = win_hl_attr(wp, HLF_FC); } } @@ -2702,18 +2753,25 @@ win_line ( * buffer or when using Netbeans. */ if (signcolumn_on(wp)) { int text_sign; - /* Draw two cells with the sign value or blank. */ + // Draw cells with the sign value or blank. c_extra = ' '; - char_attr = hl_attr(HLF_SC); - n_extra = 2; + char_attr = win_hl_attr(wp, HLF_SC); + n_extra = win_signcol_width(wp); if (row == startrow + filler_lines && filler_todo <= 0) { text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT); if (text_sign != 0) { p_extra = sign_get_text(text_sign); + int symbol_blen = (int)STRLEN(p_extra); if (p_extra != NULL) { c_extra = NUL; - n_extra = (int)STRLEN(p_extra); + // symbol(s) bytes + (filling spaces) (one byte each) + n_extra = symbol_blen + + (win_signcol_width(wp) - mb_string2cells(p_extra)); + memset(extra, ' ', sizeof(extra)); + STRNCPY(extra, p_extra, STRLEN(p_extra)); + p_extra = extra; + p_extra[n_extra] = NUL; } char_attr = sign_get_attr(text_sign, FALSE); } @@ -2761,14 +2819,15 @@ win_line ( } else c_extra = ' '; n_extra = number_width(wp) + 1; - char_attr = hl_attr(HLF_N); - /* When 'cursorline' is set highlight the line number of - * the current line differently. - * TODO: Can we use CursorLine instead of CursorLineNr - * when CursorLineNr isn't set? */ + char_attr = win_hl_attr(wp, HLF_N); + // When 'cursorline' is set highlight the line number of + // the current line differently. + // TODO(vim): Can we use CursorLine instead of CursorLineNr + // when CursorLineNr isn't set? if ((wp->w_p_cul || wp->w_p_rnu) - && lnum == wp->w_cursor.lnum) - char_attr = hl_attr(HLF_CLN); + && lnum == wp->w_cursor.lnum) { + char_attr = win_hl_attr(wp, HLF_CLN); + } } } @@ -2784,13 +2843,15 @@ win_line ( // draw 'breakindent': indent wrapped text accodringly if (draw_state == WL_BRI - 1 && n_extra == 0) { draw_state = WL_BRI; - if (wp->w_p_bri && n_extra == 0 && row != startrow && filler_lines == 0) { - char_attr = 0; // was: hl_attr(HLF_AT); + // if need_showbreak is set, breakindent also applies + if (wp->w_p_bri && (row != startrow || need_showbreak) + && filler_lines == 0) { + char_attr = wp->w_hl_attr_normal; if (diff_hlf != (hlf_T)0) { - char_attr = hl_attr(diff_hlf); + char_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUL)); } } p_extra = NULL; @@ -2815,15 +2876,15 @@ win_line ( n_extra = col + 1; else n_extra = wp->w_width - col; - char_attr = hl_attr(HLF_DED); + char_attr = win_hl_attr(wp, HLF_DED); } if (*p_sbr != NUL && need_showbreak) { /* Draw 'showbreak' at the start of each broken line. */ p_extra = p_sbr; c_extra = NUL; n_extra = (int)STRLEN(p_sbr); - char_attr = hl_attr(HLF_AT); - need_showbreak = FALSE; + char_attr = win_hl_attr(wp, HLF_AT); + need_showbreak = false; vcol_sbr = vcol + MB_CHARLEN(p_sbr); /* Correct end of highlighted area for 'showbreak', * required when 'linebreak' is also set. */ @@ -2831,7 +2892,7 @@ win_line ( tocol += n_extra; /* combine 'showbreak' with 'cursorline' */ if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUL)); } } } @@ -2844,8 +2905,9 @@ win_line ( c_extra = saved_c_extra; p_extra = saved_p_extra; char_attr = saved_char_attr; - } else - char_attr = 0; + } else { + char_attr = wp->w_hl_attr_normal; + } } } @@ -2854,13 +2916,15 @@ win_line ( && lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol && filler_todo <= 0 ) { - SCREEN_LINE(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl); - /* Pretend we have finished updating the window. Except when - * 'cursorcolumn' is set. */ - if (wp->w_p_cuc) + screen_line(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl, wp, + wp->w_hl_attr_normal); + // Pretend we have finished updating the window. Except when + // 'cursorcolumn' is set. + if (wp->w_p_cuc) { row = wp->w_cline_row + wp->w_cline_height; - else + } else { row = wp->w_height; + } break; } @@ -2988,14 +3052,16 @@ win_line ( if (diff_hlf != (hlf_T)0) { if (diff_hlf == HLF_CHD && ptr - line >= change_start - && n_extra == 0) - diff_hlf = HLF_TXD; /* changed text */ + && n_extra == 0) { + diff_hlf = HLF_TXD; // changed text + } if (diff_hlf == HLF_TXD && ptr - line > change_end - && n_extra == 0) - diff_hlf = HLF_CHD; /* changed line */ - line_attr = hl_attr(diff_hlf); + && n_extra == 0) { + diff_hlf = HLF_CHD; // changed line + } + line_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - line_attr = hl_combine_attr(line_attr, hl_attr(HLF_CUL)); + line_attr = hl_combine_attr(line_attr, win_hl_attr(wp, HLF_CUL)); } } @@ -3011,14 +3077,15 @@ win_line ( // (area_attr may be 0 when "noinvcur" is set). else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) || vcol < fromcol || vcol_prev < fromcol_prev - || vcol >= tocol)) + || vcol >= tocol)) { char_attr = line_attr; - else { - attr_pri = FALSE; - if (has_syntax) + } else { + attr_pri = false; + if (has_syntax) { char_attr = syntax_attr; - else - char_attr = 0; + } else { + char_attr = wp->w_hl_attr_normal; + } } } @@ -3079,12 +3146,13 @@ win_line ( c = '>'; mb_c = c; mb_l = 1; - mb_utf8 = FALSE; - multi_attr = hl_attr(HLF_AT); - /* put the pointer back to output the double-width - * character at the start of the next line. */ - ++n_extra; - --p_extra; + mb_utf8 = false; + multi_attr = win_hl_attr(wp, HLF_AT); + + // put the pointer back to output the double-width + // character at the start of the next line. + n_extra++; + p_extra--; } else { n_extra -= mb_l - 1; p_extra += mb_l - 1; @@ -3094,14 +3162,15 @@ win_line ( } --n_extra; } else { + int c0; + if (p_extra_free != NULL) { xfree(p_extra_free); p_extra_free = NULL; } - /* - * Get a character from the line itself. - */ - c = *ptr; + + // Get a character from the line itself. + c0 = c = *ptr; if (has_mbyte) { mb_c = c; if (enc_utf8) { @@ -3111,11 +3180,12 @@ win_line ( mb_utf8 = FALSE; if (mb_l > 1) { mb_c = utfc_ptr2char(ptr, u8cc); - /* Overlong encoded ASCII or ASCII with composing char - * is displayed normally, except a NUL. */ - if (mb_c < 0x80) - c = mb_c; - mb_utf8 = TRUE; + // Overlong encoded ASCII or ASCII with composing char + // is displayed normally, except a NUL. + if (mb_c < 0x80) { + c0 = c = mb_c; + } + mb_utf8 = true; /* At start of the line we can have a composing char. * Draw it as a space with a composing char. */ @@ -3134,9 +3204,9 @@ win_line ( || (mb_l > 1 && (!vim_isprintc(mb_c)))) { // Illegal UTF-8 byte: display as <xx>. // Non-BMP character : display as ? or fullwidth ?. - transchar_hex(extra, mb_c); - if (wp->w_p_rl) { // reverse - rl_mirror(extra); + transchar_hex((char *)extra, mb_c); + if (wp->w_p_rl) { // reverse + rl_mirror(extra); } p_extra = extra; @@ -3147,8 +3217,8 @@ win_line ( c_extra = NUL; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = char_attr; // save current attr } } else if (mb_l == 0) /* at the NUL at end-of-line */ mb_l = 1; @@ -3200,8 +3270,8 @@ win_line ( c = *p_extra++; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = char_attr; // save current attr } mb_c = c; } @@ -3218,12 +3288,13 @@ win_line ( mb_c = c; mb_utf8 = FALSE; mb_l = 1; - multi_attr = hl_attr(HLF_AT); - /* Put pointer back so that the character will be - * displayed at the start of the next line. */ - --ptr; - } else if (*ptr != NUL) + multi_attr = win_hl_attr(wp, HLF_AT); + // Put pointer back so that the character will be + // displayed at the start of the next line. + ptr--; + } else if (*ptr != NUL) { ptr += mb_l - 1; + } /* If a double-width char doesn't fit at the left side display * a '<' in the first column. Don't do this for unprintable @@ -3234,8 +3305,8 @@ win_line ( c = ' '; if (area_attr == 0 && search_attr == 0) { n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_AT); - saved_attr2 = char_attr; /* save current attr */ + extra_attr = win_hl_attr(wp, HLF_AT); + saved_attr2 = char_attr; // save current attr } mb_c = c; mb_utf8 = FALSE; @@ -3283,7 +3354,7 @@ win_line ( else syntax_flags = get_syntax_info(&syntax_seqnr); } else if (!attr_pri) { - char_attr = 0; + char_attr = wp->w_hl_attr_normal; } /* Check spelling (unless at the end of the line). @@ -3308,10 +3379,11 @@ win_line ( /* Use nextline[] if possible, it has the start of the * next line concatenated. */ - if ((prev_ptr - line) - nextlinecol >= 0) - p = nextline + (prev_ptr - line) - nextlinecol; - else + if ((prev_ptr - line) - nextlinecol >= 0) { + p = nextline + ((prev_ptr - line) - nextlinecol); + } else { p = prev_ptr; + } cap_col -= (int)(prev_ptr - line); size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, nochange); assert(tmplen <= INT_MAX); @@ -3378,10 +3450,8 @@ win_line ( char_attr = hl_combine_attr(char_attr, term_attrs[vcol]); } - /* - * Found last space before word: check for line break. - */ - if (wp->w_p_lbr && vim_isbreak(c) && !vim_isbreak(*ptr)) { + // Found last space before word: check for line break. + if (wp->w_p_lbr && c0 == c && vim_isbreak(c) && !vim_isbreak(*ptr)) { int mb_off = has_mbyte ? (*mb_head_off)(line, ptr - 1) : 0; char_u *p = ptr - (mb_off + 1); // TODO: is passing p for start of the line OK? @@ -3409,7 +3479,7 @@ win_line ( || (c == ' ' && lcs_space && ptr - line <= trailcol))) { c = (c == ' ') ? lcs_space : lcs_nbsp; n_attr = 1; - extra_attr = hl_attr(HLF_0); + extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3424,7 +3494,7 @@ win_line ( if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') { c = lcs_trail; n_attr = 1; - extra_attr = hl_attr(HLF_0); + extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3467,8 +3537,7 @@ win_line ( tab_len += vcol_off; } // boguscols before FIX_FOR_BOGUSCOLS macro from above. - if (wp->w_p_list && lcs_tab1 && old_boguscols > 0 - && n_extra > tab_len) { + if (lcs_tab1 && old_boguscols > 0 && n_extra > tab_len) { tab_len += n_extra - tab_len; } @@ -3482,6 +3551,7 @@ win_line ( p = xmalloc(len + 1); memset(p, ' ', len); p[len] = NUL; + xfree(p_extra_free); p_extra_free = p; for (i = 0; i < tab_len; i++) { mb_char2bytes(lcs_tab2, p); @@ -3525,7 +3595,7 @@ win_line ( c_extra = lcs_tab2; } n_attr = tab_len + 1; - extra_attr = hl_attr(HLF_0); + extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3551,15 +3621,13 @@ win_line ( && lcs_eol_one > 0) { // Display a '$' after the line or highlight an extra // character if the line break is included. - // For a diff line the highlighting continues after the - // "$". + // For a diff line the highlighting continues after the "$". if (diff_hlf == (hlf_T)0 && line_attr == 0) { - /* In virtualedit, visual selections may extend - * beyond end of line. */ + // In virtualedit, visual selections may extend beyond end of line. if (area_highlighting && virtual_active() - && tocol != MAXCOL && vcol < tocol) + && tocol != MAXCOL && vcol < tocol) { n_extra = 0; - else { + } else { p_extra = at_end_str; n_extra = 1; c_extra = NUL; @@ -3572,7 +3640,7 @@ win_line ( } lcs_eol_one = -1; ptr--; // put it back at the NUL - extra_attr = hl_attr(HLF_AT); + extra_attr = win_hl_attr(wp, HLF_AT); n_attr = 1; mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3597,13 +3665,14 @@ win_line ( memset(p, ' ', n_extra); STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1); p[n_extra] = NUL; + xfree(p_extra_free); p_extra_free = p_extra = p; } else { n_extra = byte2cells(c) - 1; c = *p_extra++; } n_attr = n_extra + 1; - extra_attr = hl_attr(HLF_8); + extra_attr = win_hl_attr(wp, HLF_8); saved_attr2 = char_attr; // save current attr mb_utf8 = false; // don't draw as UTF-8 } else if (VIsual_active @@ -3635,9 +3704,10 @@ win_line ( if (diff_hlf == HLF_TXD) { diff_hlf = HLF_CHD; if (attr == 0 || char_attr != attr) { - char_attr = hl_attr(diff_hlf); + char_attr = win_hl_attr(wp, diff_hlf); if (wp->w_p_cul && lnum == wp->w_cursor.lnum) { - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUL)); + char_attr = hl_combine_attr(char_attr, + win_hl_attr(wp, HLF_CUL)); } } } @@ -3739,7 +3809,7 @@ win_line ( c_extra = MB_FILLER_CHAR; n_extra = 1; n_attr = 2; - extra_attr = hl_attr(HLF_AT); + extra_attr = win_hl_attr(wp, HLF_AT); } mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { @@ -3750,7 +3820,7 @@ win_line ( mb_utf8 = false; // don't draw as UTF-8 } saved_attr3 = char_attr; // save current attr - char_attr = hl_attr(HLF_AT); // later copied to char_attr + char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr n_attr3 = 1; } @@ -3834,6 +3904,10 @@ win_line ( } } } + + if (wp->w_hl_attr_normal != 0) { + char_attr = hl_combine_attr(wp->w_hl_attr_normal, char_attr); + } ScreenAttrs[off] = char_attr; if (wp->w_p_rl) { --col; @@ -3895,6 +3969,9 @@ win_line ( if (rightmost_vcol < color_cols[i]) rightmost_vcol = color_cols[i]; + int cuc_attr = win_hl_attr(wp, HLF_CUC); + int mc_attr = win_hl_attr(wp, HLF_MC); + while (col < wp->w_width) { ScreenLines[off] = ' '; if (enc_utf8) @@ -3904,12 +3981,13 @@ win_line ( draw_color_col = advance_color_col(VCOL_HLC, &color_cols); - if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) - ScreenAttrs[off++] = hl_attr(HLF_CUC); - else if (draw_color_col && VCOL_HLC == *color_cols) - ScreenAttrs[off++] = hl_attr(HLF_MC); - else - ScreenAttrs[off++] = 0; + if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) { + ScreenAttrs[off++] = cuc_attr; + } else if (draw_color_col && VCOL_HLC == *color_cols) { + ScreenAttrs[off++] = mc_attr; + } else { + ScreenAttrs[off++] = wp->w_hl_attr_normal; + } if (VCOL_HLC >= rightmost_vcol) break; @@ -3918,6 +3996,7 @@ win_line ( } } + // TODO(bfredl): integrate with the common beyond-the-end-loop if (wp->w_buffer->terminal) { // terminal buffers may need to highlight beyond the end of the // logical line @@ -3930,7 +4009,8 @@ win_line ( col++; } } - SCREEN_LINE(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl); + screen_line(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl, wp, + wp->w_hl_attr_normal); row++; /* @@ -3958,7 +4038,7 @@ win_line ( || (wp->w_p_list && lcs_eol_one > 0) || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { c = lcs_ext; - char_attr = hl_attr(HLF_AT); + char_attr = win_hl_attr(wp, HLF_AT); mb_c = c; if (enc_utf8 && (*mb_char2len)(c) > 1) { mb_utf8 = TRUE; @@ -3981,10 +4061,10 @@ win_line ( if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol && lnum != wp->w_cursor.lnum) { vcol_save_attr = char_attr; - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_CUC)); + char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), char_attr); } else if (draw_color_col && VCOL_HLC == *color_cols) { vcol_save_attr = char_attr; - char_attr = hl_combine_attr(char_attr, hl_attr(HLF_MC)); + char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), char_attr); } } @@ -4003,24 +4083,19 @@ win_line ( --col; } ScreenLines[off] = c; - if (enc_dbcs == DBCS_JPNU) { - if ((mb_c & 0xff00) == 0x8e00) - ScreenLines[off] = 0x8e; - ScreenLines2[off] = mb_c & 0xff; - } else if (enc_utf8) { - if (mb_utf8) { - int i; - - ScreenLinesUC[off] = mb_c; - if ((c & 0xff) == 0) - ScreenLines[off] = 0x80; /* avoid storing zero */ - for (i = 0; i < Screen_mco; ++i) { - ScreenLinesC[i][off] = u8cc[i]; - if (u8cc[i] == 0) - break; + if (mb_utf8) { + ScreenLinesUC[off] = mb_c; + if ((c & 0xff) == 0) { + ScreenLines[off] = 0x80; // Avoid storing zero. + } + for (int i = 0; i < Screen_mco; i++) { + ScreenLinesC[i][off] = u8cc[i]; + if (u8cc[i] == 0) { + break; } - } else - ScreenLinesUC[off] = 0; + } + } else { + ScreenLinesUC[off] = 0; } if (multi_attr) { ScreenAttrs[off] = multi_attr; @@ -4152,8 +4227,8 @@ win_line ( || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) ) { - SCREEN_LINE(screen_row, wp->w_wincol, col - boguscols, - wp->w_width, wp->w_p_rl); + screen_line(screen_row, wp->w_wincol, col - boguscols, + wp->w_width, wp->w_p_rl, wp, wp->w_hl_attr_normal); boguscols = 0; ++row; ++screen_row; @@ -4193,7 +4268,6 @@ win_line ( * (regardless of the xn,am settings). * Only do this if the cursor is on the current line * (something has been written in it). - * Don't do this for the GUI. * Don't do this for double-width characters. * Don't do this for a window not at the right screen border. */ @@ -4261,6 +4335,7 @@ win_line ( cap_col = 0; } + xfree(p_extra_free); return row; } @@ -4292,22 +4367,14 @@ static int comp_char_differs(int off_from, int off_to) static int char_needs_redraw(int off_from, int off_to, int cols) { return (cols > 0 - && ((ScreenLines[off_from] != ScreenLines[off_to] - || ScreenAttrs[off_from] != ScreenAttrs[off_to]) - - || (enc_dbcs != 0 - && MB_BYTE2LEN(ScreenLines[off_from]) > 1 - && (enc_dbcs == DBCS_JPNU && ScreenLines[off_from] == 0x8e - ? ScreenLines2[off_from] != ScreenLines2[off_to] - : (cols > 1 && ScreenLines[off_from + 1] - != ScreenLines[off_to + 1]))) - || (enc_utf8 - && (ScreenLinesUC[off_from] != ScreenLinesUC[off_to] - || (ScreenLinesUC[off_from] != 0 - && comp_char_differs(off_from, off_to)) - || ((*mb_off2cells)(off_from, off_from + cols) > 1 - && ScreenLines[off_from + 1] - != ScreenLines[off_to + 1]))))); + && (ScreenLines[off_from] != ScreenLines[off_to] + || ScreenAttrs[off_from] != ScreenAttrs[off_to] + || ScreenLinesUC[off_from] != ScreenLinesUC[off_to] + || (ScreenLinesUC[off_from] != 0 + && comp_char_differs(off_from, off_to)) + || (utf_off2cells(off_from, off_from + cols) > 1 + && ScreenLines[off_from + 1] != ScreenLines[off_to + 1]) + || p_wd < 0)); } /* @@ -4321,7 +4388,8 @@ static int char_needs_redraw(int off_from, int off_to, int cols) * When TRUE and "clear_width" > 0, clear columns 0 to "endcol" * When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width" */ -static void screen_line(int row, int coloff, int endcol, int clear_width, int rlflag) +static void screen_line(int row, int coloff, int endcol, + int clear_width, int rlflag, win_T *wp, int bg_attr) { unsigned off_from; unsigned off_to; @@ -4354,15 +4422,16 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl /* Clear rest first, because it's left of the text. */ if (clear_width > 0) { while (col <= endcol && ScreenLines[off_to] == ' ' - && ScreenAttrs[off_to] == 0 + && ScreenAttrs[off_to] == bg_attr && (!enc_utf8 || ScreenLinesUC[off_to] == 0) ) { ++off_to; ++col; } - if (col <= endcol) - screen_fill(row, row + 1, col + coloff, - endcol + coloff + 1, ' ', ' ', 0); + if (col <= endcol) { + screen_fill(row, row + 1, col + coloff, endcol + coloff + 1, ' ', ' ', + bg_attr); + } } col = endcol + 1; off_to = LineOffset[row] + col + coloff; @@ -4370,6 +4439,13 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl endcol = (clear_width > 0 ? clear_width : -clear_width); } + if (bg_attr) { + for (int c = col; c < endcol; c++) { + ScreenAttrs[off_from+c] = hl_combine_attr(bg_attr, + ScreenAttrs[off_from+c]); + } + } + redraw_next = char_needs_redraw(off_from, off_to, endcol - col); while (col < endcol) { @@ -4406,9 +4482,6 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl ScreenLines[off_to + 2] = 0; redraw_next = TRUE; } - - if (enc_dbcs == DBCS_JPNU) - ScreenLines2[off_to] = ScreenLines2[off_from]; } /* When writing a single-width character over a double-width * character and at the end of the redrawn text, need to clear out @@ -4468,26 +4541,26 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl /* blank out the rest of the line */ while (col < clear_width && ScreenLines[off_to] == ' ' - && ScreenAttrs[off_to] == 0 + && ScreenAttrs[off_to] == bg_attr && (!enc_utf8 || ScreenLinesUC[off_to] == 0) ) { ++off_to; ++col; } if (col < clear_width) { - screen_fill(row, row + 1, col + coloff, clear_width + coloff, - ' ', ' ', 0); + screen_fill(row, row + 1, col + coloff, clear_width + coloff, ' ', ' ', + bg_attr); off_to += clear_width - col; col = clear_width; } } if (clear_width > 0) { - /* For a window that's left of another, draw the separator char. */ - if (col + coloff < Columns) { + // For a window that's left of another, draw the separator char. + if (col + coloff < Columns && wp->w_vsep_width > 0) { int c; - c = fillchar_vsep(&hl); + c = fillchar_vsep(wp, &hl); if (ScreenLines[off_to] != (schar_T)c || (enc_utf8 && (int)ScreenLinesUC[off_to] != (c >= 0x80 ? c : 0)) @@ -4592,8 +4665,8 @@ static void draw_vsep_win(win_T *wp, int row) int c; if (wp->w_vsep_width) { - /* draw the vertical separator right of this window */ - c = fillchar_vsep(&hl); + // draw the vertical separator right of this window + c = fillchar_vsep(wp, &hl); screen_fill(wp->w_winrow + row, wp->w_winrow + wp->w_height, W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl); @@ -4723,7 +4796,7 @@ win_redr_status_matches ( --first_match; } - fillchar = fillchar_status(&attr, TRUE); + fillchar = fillchar_status(&attr, curwin); if (first_match == 0) { *buf = NUL; @@ -4837,11 +4910,14 @@ void win_redr_status(win_T *wp) int this_ru_col; static int busy = FALSE; - /* It's possible to get here recursively when 'statusline' (indirectly) - * invokes ":redrawstatus". Simply ignore the call then. */ - if (busy) + // May get here recursively when 'statusline' (indirectly) + // invokes ":redrawstatus". Simply ignore the call then. + if (busy + // Also ignore if wildmenu is showing. + || (wild_menu_showing != 0 && !ui_is_external(kUIWildmenu))) { return; - busy = TRUE; + } + busy = true; wp->w_redr_status = FALSE; if (wp->w_status_height == 0) { @@ -4855,7 +4931,7 @@ void win_redr_status(win_T *wp) /* redraw custom status line */ redraw_custom_statusline(wp); } else { - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); get_trans_bufname(wp->w_buffer); p = NameBuff; @@ -4927,10 +5003,11 @@ void win_redr_status(win_T *wp) * May need to draw the character below the vertical separator. */ if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing()) { - if (stl_connected(wp)) - fillchar = fillchar_status(&attr, wp == curwin); - else - fillchar = fillchar_vsep(&attr); + if (stl_connected(wp)) { + fillchar = fillchar_status(&attr, wp); + } else { + fillchar = fillchar_vsep(wp, &attr); + } screen_putchar(fillchar, wp->w_winrow + wp->w_height, W_ENDCOL(wp), attr); } @@ -5080,7 +5157,7 @@ win_redr_custom ( use_sandbox = was_set_insecurely((char_u *)"tabline", 0); } else { row = wp->w_winrow + wp->w_height; - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); maxwidth = wp->w_width; if (draw_ruler) { @@ -5137,8 +5214,8 @@ win_redr_custom ( xfree(stl); ewp->w_p_crb = p_crb_save; - /* Make all characters printable. */ - p = transstr(buf); + // Make all characters printable. + p = (char_u *)transstr((const char *)buf); len = STRLCPY(buf, p, sizeof(buf)); len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1; xfree(p); @@ -5230,16 +5307,7 @@ void screen_getbytes(int row, int col, char_u *bytes, int *attrp) bytes[0] = ScreenLines[off]; bytes[1] = NUL; - if (enc_utf8 && ScreenLinesUC[off] != 0) - bytes[utfc_char2bytes(off, bytes)] = NUL; - else if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) { - bytes[0] = ScreenLines[off]; - bytes[1] = ScreenLines2[off]; - bytes[2] = NUL; - } else if (enc_dbcs && MB_BYTE2LEN(bytes[0]) > 1) { - bytes[1] = ScreenLines[off + 1]; - bytes[2] = NUL; - } + bytes[utfc_char2bytes(off, bytes)] = NUL; } } @@ -5330,43 +5398,39 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) c = *ptr; /* check if this is the first byte of a multibyte */ if (l_has_mbyte) { - if (l_enc_utf8 && len > 0) + if (len > 0) { mbyte_blen = utfc_ptr2len_len(ptr, (int)((text + len) - ptr)); - else - mbyte_blen = (*mb_ptr2len)(ptr); - if (l_enc_dbcs == DBCS_JPNU && c == 0x8e) - mbyte_cells = 1; - else if (l_enc_dbcs != 0) - mbyte_cells = mbyte_blen; - else { /* enc_utf8 */ - if (len >= 0) - u8c = utfc_ptr2char_len(ptr, u8cc, - (int)((text + len) - ptr)); - else - u8c = utfc_ptr2char(ptr, u8cc); - mbyte_cells = utf_char2cells(u8c); - if (p_arshape && !p_tbidi && arabic_char(u8c)) { - /* Do Arabic shaping. */ - if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { - /* Past end of string to be displayed. */ - nc = NUL; - nc1 = NUL; - } else { - nc = utfc_ptr2char_len(ptr + mbyte_blen, pcc, - (int)((text + len) - ptr - mbyte_blen)); - nc1 = pcc[0]; - } - pc = prev_c; - prev_c = u8c; - u8c = arabic_shape(u8c, &c, &u8cc[0], nc, nc1, pc); - } else - prev_c = u8c; - if (col + mbyte_cells > screen_Columns) { - /* Only 1 cell left, but character requires 2 cells: - * display a '>' in the last column to avoid wrapping. */ - c = '>'; - mbyte_cells = 1; + } else { + mbyte_blen = utfc_ptr2len(ptr); + } + if (len >= 0) { + u8c = utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr)); + } else { + u8c = utfc_ptr2char(ptr, u8cc); + } + mbyte_cells = utf_char2cells(u8c); + if (p_arshape && !p_tbidi && arabic_char(u8c)) { + // Do Arabic shaping. + if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { + // Past end of string to be displayed. + nc = NUL; + nc1 = NUL; + } else { + nc = utfc_ptr2char_len(ptr + mbyte_blen, pcc, + (int)((text + len) - ptr - mbyte_blen)); + nc1 = pcc[0]; } + pc = prev_c; + prev_c = u8c; + u8c = arabic_shape(u8c, &c, &u8cc[0], nc, nc1, pc); + } else { + prev_c = u8c; + } + if (col + mbyte_cells > screen_Columns) { + // Only 1 cell left, but character requires 2 cells: + // display a '>' in the last column to avoid wrapping. */ + c = '>'; + mbyte_cells = 1; } } @@ -5374,16 +5438,11 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) force_redraw_next = FALSE; need_redraw = ScreenLines[off] != c - || (mbyte_cells == 2 - && ScreenLines[off + 1] != (l_enc_dbcs ? ptr[1] : 0)) - || (l_enc_dbcs == DBCS_JPNU - && c == 0x8e - && ScreenLines2[off] != ptr[1]) - || (l_enc_utf8 - && (ScreenLinesUC[off] != - (u8char_T)(c < 0x80 && u8cc[0] == 0 ? 0 : u8c) - || (ScreenLinesUC[off] != 0 - && screen_comp_differs(off, u8cc)))) + || (mbyte_cells == 2 && ScreenLines[off + 1] != 0) + || (ScreenLinesUC[off] != + (u8char_T)(c < 0x80 && u8cc[0] == 0 ? 0 : u8c) + || (ScreenLinesUC[off] != 0 + && screen_comp_differs(off, u8cc))) || ScreenAttrs[off] != attr || exmode_active; @@ -5438,11 +5497,9 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr) ScreenLines[off + 1] = ptr[1]; ScreenAttrs[off + 1] = attr; screen_char_2(off, row, col); - } else if (l_enc_dbcs == DBCS_JPNU && c == 0x8e) { - ScreenLines2[off] = ptr[1]; - screen_char(off, row, col); - } else + } else { screen_char(off, row, col); + } } if (l_has_mbyte) { off += mbyte_cells; @@ -5474,8 +5531,7 @@ static void start_search_hl(void) { if (p_hls && !no_hlsearch) { last_pat_prog(&search_hl.rm); - search_hl.attr = hl_attr(HLF_L); - /* Set the time limit to 'redrawtime'. */ + // Set the time limit to 'redrawtime'. search_hl.tm = profile_setlimit(p_rdt); } } @@ -5491,6 +5547,42 @@ static void end_search_hl(void) } } +static void update_window_hl(win_T *wp, bool invalid) +{ + if (!wp->w_hl_needs_update && !invalid) { + return; + } + wp->w_hl_needs_update = false; + + // determine window specific background set in 'winhighlight' + if (wp != curwin && wp->w_hl_ids[HLF_INACTIVE] > 0) { + wp->w_hl_attr_normal = syn_id2attr(wp->w_hl_ids[HLF_INACTIVE]); + } else if (wp->w_hl_id_normal > 0) { + wp->w_hl_attr_normal = syn_id2attr(wp->w_hl_id_normal); + } else { + wp->w_hl_attr_normal = 0; + } + if (wp != curwin) { + wp->w_hl_attr_normal = hl_combine_attr(hl_attr(HLF_INACTIVE), + wp->w_hl_attr_normal); + } + + for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) { + int attr; + if (wp->w_hl_ids[hlf] > 0) { + attr = syn_id2attr(wp->w_hl_ids[hlf]); + } else { + attr = hl_attr(hlf); + } + if (wp->w_hl_attr_normal != 0) { + attr = hl_combine_attr(wp->w_hl_attr_normal, attr); + } + wp->w_hl_attrs[hlf] = attr; + } +} + + + /* * Init for calling prepare_search_hl(). */ @@ -5517,7 +5609,9 @@ static void init_search_hl(win_T *wp) search_hl.buf = wp->w_buffer; search_hl.lnum = 0; search_hl.first_lnum = 0; - /* time limit is set at the toplevel, for all windows */ + search_hl.attr = win_hl_attr(wp, HLF_L); + + // time limit is set at the toplevel, for all windows } /* @@ -5537,13 +5631,14 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum) * Do this both for search_hl and the match list. */ cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE) { + shl_flag = false; + while (cur != NULL || shl_flag == false) { + if (shl_flag == false) { shl = &search_hl; - shl_flag = TRUE; - } else - shl = &cur->hl; + shl_flag = true; + } else { + shl = &cur->hl; // -V595 + } if (shl->rm.regprog != NULL && shl->lnum == 0 && re_multiline(shl->rm.regprog)) { @@ -5753,54 +5848,31 @@ next_search_hl_pos( return 0; } -static void screen_start_highlight(int attr) -{ - screen_attr = attr; - ui_start_highlight(attr); -} - -void screen_stop_highlight(void) -{ - ui_stop_highlight(); - screen_attr = 0; -} - /* * Put character ScreenLines["off"] on the screen at position "row" and "col", * using the attributes from ScreenAttrs["off"]. */ static void screen_char(unsigned off, int row, int col) { - int attr; - - /* Check for illegal values, just in case (could happen just after - * resizing). */ - if (row >= screen_Rows || col >= screen_Columns) + // Check for illegal values, just in case (could happen just after resizing). + if (row >= screen_Rows || col >= screen_Columns) { return; + } - /* Outputting the last character on the screen may scrollup the screen. - * Don't to it! Mark the character invalid (update it when scrolled up) */ + // Outputting the last character on the screen may scrollup the screen. + // Don't to it! Mark the character invalid (update it when scrolled up) + // FIXME: The premise here is not actually true (cf. deferred wrap). if (row == screen_Rows - 1 && col == screen_Columns - 1 - /* account for first command-line character in rightleft mode */ - && !cmdmsg_rl - ) { + // account for first command-line character in rightleft mode + && !cmdmsg_rl) { ScreenAttrs[off] = (sattr_T)-1; return; } - /* - * Stop highlighting first, so it's easier to move the cursor. - */ - attr = ScreenAttrs[off]; - if (screen_attr != attr) - screen_stop_highlight(); - ui_cursor_goto(row, col); + ui_set_highlight(ScreenAttrs[off]); - if (screen_attr != attr) - screen_start_highlight(attr); - - if (enc_utf8 && ScreenLinesUC[off] != 0) { + if (ScreenLinesUC[off] != 0) { char_u buf[MB_MAXBYTES + 1]; // Convert UTF-8 character to bytes and write it. @@ -5808,10 +5880,6 @@ static void screen_char(unsigned off, int row, int col) ui_puts(buf); } else { ui_putc(ScreenLines[off]); - // double-byte character in single-width cell - if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) { - ui_putc(ScreenLines2[off]); - } } } @@ -5907,9 +5975,9 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, ++off; if (off < end_off) { /* something to be cleared */ col = off - LineOffset[row]; - screen_stop_highlight(); + ui_clear_highlight(); ui_cursor_goto(row, col); // clear rest of this screen line - ui_eol_clear(); + ui_call_eol_clear(); col = end_col - col; while (col--) { /* clear chars in ScreenLines */ ScreenLines[off] = ' '; @@ -6003,40 +6071,25 @@ int screen_valid(int doclear) void screenalloc(bool doclear) { int new_row, old_row; - int outofmem = FALSE; int len; - schar_T *new_ScreenLines; - u8char_T *new_ScreenLinesUC = NULL; - u8char_T *new_ScreenLinesC[MAX_MCO]; - schar_T *new_ScreenLines2 = NULL; - int i; - sattr_T *new_ScreenAttrs; - unsigned *new_LineOffset; - char_u *new_LineWraps; - StlClickDefinition *new_tab_page_click_defs; static bool entered = false; // avoid recursiveness static bool done_outofmem_msg = false; int retry_count = 0; - const bool l_enc_utf8 = enc_utf8; - const int l_enc_dbcs = enc_dbcs; 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. - */ + // 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 ((ScreenLines != NULL && Rows == screen_Rows && Columns == screen_Columns - && l_enc_utf8 == (ScreenLinesUC != NULL) - && (l_enc_dbcs == DBCS_JPNU) == (ScreenLines2 != NULL) - && p_mco == Screen_mco - ) + && ScreenLinesUC != NULL + && p_mco == Screen_mco) || Rows == 0 || Columns == 0 - || (!full_screen && ScreenLines == NULL)) + || (!full_screen && ScreenLines == NULL)) { return; + } /* * It's possible that we produce an out-of-memory message below, which @@ -6074,22 +6127,22 @@ retry: if (aucmd_win != NULL) win_free_lsize(aucmd_win); - new_ScreenLines = xmalloc((size_t)((Rows + 1) * Columns * sizeof(schar_T))); - memset(new_ScreenLinesC, 0, sizeof(u8char_T *) * MAX_MCO); - if (l_enc_utf8) { - new_ScreenLinesUC = xmalloc( - (size_t)((Rows + 1) * Columns * sizeof(u8char_T))); - for (i = 0; i < p_mco; ++i) - new_ScreenLinesC[i] = xcalloc((Rows + 1) * Columns, sizeof(u8char_T)); - } - if (l_enc_dbcs == DBCS_JPNU) - new_ScreenLines2 = xmalloc( - (size_t)((Rows + 1) * Columns * sizeof(schar_T))); - new_ScreenAttrs = xmalloc((size_t)((Rows + 1) * Columns * sizeof(sattr_T))); - new_LineOffset = xmalloc((size_t)(Rows * sizeof(unsigned))); - new_LineWraps = xmalloc((size_t)(Rows * sizeof(char_u))); - new_tab_page_click_defs = xcalloc( - (size_t) Columns, sizeof(*new_tab_page_click_defs)); + schar_T *new_ScreenLines = xmalloc( + (size_t)((Rows + 1) * Columns * sizeof(*new_ScreenLines))); + u8char_T *new_ScreenLinesC[MAX_MCO]; + memset(new_ScreenLinesC, 0, sizeof(new_ScreenLinesC)); + u8char_T *new_ScreenLinesUC = xmalloc( + (size_t)((Rows + 1) * Columns * sizeof(*new_ScreenLinesUC))); + for (int i = 0; i < p_mco; i++) { + new_ScreenLinesC[i] = xcalloc( + (size_t)((Rows + 1) * Columns), sizeof(new_ScreenLinesC[0][0])); + } + sattr_T *new_ScreenAttrs = xmalloc( + (size_t)((Rows + 1) * Columns * sizeof(*new_ScreenAttrs))); + unsigned *new_LineOffset = xmalloc((size_t)(Rows * sizeof(*new_LineOffset))); + char_u *new_LineWraps = xmalloc((size_t)(Rows * sizeof(*new_LineWraps))); + StlClickDefinition *new_tab_page_click_defs = xcalloc( + (size_t)Columns, sizeof(*new_tab_page_click_defs)); FOR_ALL_TAB_WINDOWS(tp, wp) { win_alloc_lines(wp); @@ -6098,24 +6151,20 @@ retry: win_alloc_lines(aucmd_win); } - for (i = 0; i < p_mco; ++i) - if (new_ScreenLinesC[i] == NULL) + int i; + for (i = 0; i < p_mco; i++) { + if (new_ScreenLinesC[i] == NULL) { break; - if (new_ScreenLines == NULL - || (l_enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco)) - || (l_enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL) - || new_ScreenAttrs == NULL - || new_LineOffset == NULL - || new_LineWraps == NULL - || new_tab_page_click_defs == NULL - || outofmem) { + } + } + if (i != p_mco) { if (ScreenLines != NULL || !done_outofmem_msg) { - /* guess the size */ + // Guess the size. do_outofmem_msg((Rows + 1) * Columns); - /* Remember we did this to avoid getting outofmem messages over - * and over again. */ - done_outofmem_msg = TRUE; + // Remember we did this to avoid getting outofmem messages over + // and over again. + done_outofmem_msg = true; } xfree(new_ScreenLines); new_ScreenLines = NULL; @@ -6125,8 +6174,6 @@ retry: xfree(new_ScreenLinesC[i]); new_ScreenLinesC[i] = NULL; } - xfree(new_ScreenLines2); - new_ScreenLines2 = NULL; xfree(new_ScreenAttrs); new_ScreenAttrs = NULL; xfree(new_LineOffset); @@ -6149,52 +6196,42 @@ retry: * executing an external command, for the GUI). */ if (!doclear) { - (void)memset(new_ScreenLines + new_row * Columns, - ' ', (size_t)Columns * sizeof(schar_T)); - if (l_enc_utf8) { - (void)memset(new_ScreenLinesUC + new_row * Columns, - 0, (size_t)Columns * sizeof(u8char_T)); - for (i = 0; i < p_mco; ++i) - (void)memset(new_ScreenLinesC[i] - + new_row * Columns, - 0, (size_t)Columns * sizeof(u8char_T)); + memset(new_ScreenLines + new_row * Columns, + ' ', (size_t)Columns * sizeof(new_ScreenLines[0])); + memset(new_ScreenLinesUC + new_row * Columns, + 0, (size_t)Columns * sizeof(new_ScreenLinesUC[0])); + for (i = 0; i < p_mco; i++) { + memset(new_ScreenLinesC[i] + new_row * Columns, + 0, (size_t)Columns * sizeof(new_ScreenLinesC[0][0])); } - if (l_enc_dbcs == DBCS_JPNU) - (void)memset(new_ScreenLines2 + new_row * Columns, - 0, (size_t)Columns * sizeof(schar_T)); - (void)memset(new_ScreenAttrs + new_row * Columns, - 0, (size_t)Columns * sizeof(sattr_T)); + memset(new_ScreenAttrs + new_row * Columns, + 0, (size_t)Columns * sizeof(new_ScreenAttrs[0])); old_row = new_row + (screen_Rows - Rows); if (old_row >= 0 && ScreenLines != NULL) { if (screen_Columns < Columns) len = screen_Columns; else len = Columns; - /* When switching to utf-8 don't copy characters, they - * may be invalid now. Also when p_mco changes. */ - if (!(l_enc_utf8 && ScreenLinesUC == NULL) - && p_mco == Screen_mco) + // When switching to utf-8 don't copy characters, they + // may be invalid now. Also when p_mco changes. + if (ScreenLinesUC != NULL && p_mco == Screen_mco) { memmove(new_ScreenLines + new_LineOffset[new_row], - ScreenLines + LineOffset[old_row], - (size_t)len * sizeof(schar_T)); - if (l_enc_utf8 && ScreenLinesUC != NULL - && p_mco == Screen_mco) { + ScreenLines + LineOffset[old_row], + (size_t)len * sizeof(new_ScreenLines[0])); + } + if (ScreenLinesUC != NULL && p_mco == Screen_mco) { memmove(new_ScreenLinesUC + new_LineOffset[new_row], - ScreenLinesUC + LineOffset[old_row], - (size_t)len * sizeof(u8char_T)); - for (i = 0; i < p_mco; ++i) - memmove(new_ScreenLinesC[i] - + new_LineOffset[new_row], - ScreenLinesC[i] + LineOffset[old_row], - (size_t)len * sizeof(u8char_T)); + ScreenLinesUC + LineOffset[old_row], + (size_t)len * sizeof(new_ScreenLinesUC[0])); + for (i = 0; i < p_mco; i++) { + memmove(new_ScreenLinesC[i] + new_LineOffset[new_row], + ScreenLinesC[i] + LineOffset[old_row], + (size_t)len * sizeof(new_ScreenLinesC[0][0])); + } } - if (l_enc_dbcs == DBCS_JPNU && ScreenLines2 != NULL) - memmove(new_ScreenLines2 + new_LineOffset[new_row], - ScreenLines2 + LineOffset[old_row], - (size_t)len * sizeof(schar_T)); memmove(new_ScreenAttrs + new_LineOffset[new_row], - ScreenAttrs + LineOffset[old_row], - (size_t)len * sizeof(sattr_T)); + ScreenAttrs + LineOffset[old_row], + (size_t)len * sizeof(new_ScreenAttrs[0])); } } } @@ -6209,7 +6246,6 @@ retry: for (i = 0; i < p_mco; ++i) ScreenLinesC[i] = new_ScreenLinesC[i]; Screen_mco = p_mco; - ScreenLines2 = new_ScreenLines2; ScreenAttrs = new_ScreenAttrs; LineOffset = new_LineOffset; LineWraps = new_LineWraps; @@ -6243,12 +6279,10 @@ retry: void free_screenlines(void) { - int i; - xfree(ScreenLinesUC); - for (i = 0; i < Screen_mco; ++i) + for (int i = 0; i < Screen_mco; i++) { xfree(ScreenLinesC[i]); - xfree(ScreenLines2); + } xfree(ScreenLines); xfree(ScreenAttrs); xfree(LineOffset); @@ -6289,8 +6323,7 @@ static void screenclear2(void) return; } - screen_stop_highlight(); /* don't want highlighting here */ - + ui_clear_highlight(); // don't want highlighting here /* blank out ScreenLines */ for (i = 0; i < Rows; ++i) { @@ -6298,10 +6331,10 @@ static void screenclear2(void) LineWraps[i] = FALSE; } - ui_clear(); // clear the display - clear_cmdline = FALSE; - mode_displayed = FALSE; - screen_cleared = TRUE; /* can use contents of ScreenLines now */ + ui_call_clear(); // clear the display + clear_cmdline = false; + mode_displayed = false; + screen_cleared = true; // can use contents of ScreenLines now win_rest_invalid(firstwin); redraw_cmdline = TRUE; @@ -6333,25 +6366,21 @@ static void lineclear(unsigned off, int width) */ static void linecopy(int to, int from, win_T *wp) { - unsigned off_to = LineOffset[to] + wp->w_wincol; - unsigned off_from = LineOffset[from] + wp->w_wincol; + const unsigned off_to = LineOffset[to] + wp->w_wincol; + const unsigned off_from = LineOffset[from] + wp->w_wincol; memmove(ScreenLines + off_to, ScreenLines + off_from, - wp->w_width * sizeof(schar_T)); - if (enc_utf8) { - int i; + wp->w_width * sizeof(ScreenLines[0])); - memmove(ScreenLinesUC + off_to, ScreenLinesUC + off_from, - wp->w_width * sizeof(u8char_T)); - for (i = 0; i < p_mco; ++i) - memmove(ScreenLinesC[i] + off_to, ScreenLinesC[i] + off_from, - wp->w_width * sizeof(u8char_T)); + memmove(ScreenLinesUC + off_to, ScreenLinesUC + off_from, + wp->w_width * sizeof(ScreenLinesUC[0])); + for (int i = 0; i < p_mco; i++) { + memmove(ScreenLinesC[i] + off_to, ScreenLinesC[i] + off_from, + wp->w_width * sizeof(ScreenLinesC[0])); } - if (enc_dbcs == DBCS_JPNU) - memmove(ScreenLines2 + off_to, ScreenLines2 + off_from, - wp->w_width * sizeof(schar_T)); + memmove(ScreenAttrs + off_to, ScreenAttrs + off_from, - wp->w_width * sizeof(sattr_T)); + wp->w_width * sizeof(ScreenAttrs[0])); } /* @@ -6374,125 +6403,39 @@ void setcursor(void) } } -/* - * insert 'line_count' lines at 'row' in window 'wp' - * if 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated. - * if 'mayclear' is TRUE the screen will be cleared if it is faster than - * scrolling. - * Returns FAIL if the lines are not inserted, OK for success. - */ +/// Insert 'line_count' lines at 'row' in window 'wp'. +/// If 'invalid' is TRUE the wp->w_lines[].wl_lnum is invalidated. +/// If 'mayclear' is TRUE the screen will be cleared if it is faster than +/// scrolling. +/// Returns FAIL if the lines are not inserted, OK for success. int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) { - int did_delete; - int nextrow; - int lastrow; - int retval; - - if (invalid) - wp->w_lines_valid = 0; - - if (wp->w_height < 5) - return FAIL; - - if (line_count > wp->w_height - row) - line_count = wp->w_height - row; - - retval = win_do_lines(wp, row, line_count, mayclear, FALSE); - if (retval != MAYBE) - return retval; - - /* - * If there is a next window or a status line, we first try to delete the - * lines at the bottom to avoid messing what is after the window. - * If this fails and there are following windows, don't do anything to avoid - * messing up those windows, better just redraw. - */ - did_delete = FALSE; - if (wp->w_next != NULL || wp->w_status_height) { - if (screen_del_lines(0, wp->w_winrow + wp->w_height - line_count, - line_count, (int)Rows, NULL) == OK) - did_delete = TRUE; - else if (wp->w_next) - return FAIL; - } - /* - * if no lines deleted, blank the lines that will end up below the window - */ - if (!did_delete) { - wp->w_redr_status = TRUE; - redraw_cmdline = TRUE; - nextrow = wp->w_winrow + wp->w_height + wp->w_status_height; - lastrow = nextrow + line_count; - if (lastrow > Rows) - lastrow = Rows; - screen_fill(nextrow - line_count, lastrow - line_count, - wp->w_wincol, W_ENDCOL(wp), - ' ', ' ', 0); - } - - if (screen_ins_lines(0, wp->w_winrow + row, line_count, (int)Rows, NULL) - == FAIL) { - /* deletion will have messed up other windows */ - if (did_delete) { - wp->w_redr_status = TRUE; - win_rest_invalid(wp->w_next); - } + if (wp->w_height < 5) { return FAIL; } - return OK; + return win_do_lines(wp, row, line_count, invalid, mayclear, false); } -/* - * delete "line_count" window lines at "row" in window "wp" - * If "invalid" is TRUE curwin->w_lines[] is invalidated. - * If "mayclear" is TRUE the screen will be cleared if it is faster than - * scrolling - * Return OK for success, FAIL if the lines are not deleted. - */ +/// Delete "line_count" window lines at "row" in window "wp". +/// If "invalid" is TRUE curwin->w_lines[] is invalidated. +/// If "mayclear" is TRUE the screen will be cleared if it is faster than +/// scrolling +/// Return OK for success, FAIL if the lines are not deleted. int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) { - int retval; - - if (invalid) - wp->w_lines_valid = 0; - - if (line_count > wp->w_height - row) - line_count = wp->w_height - row; - - retval = win_do_lines(wp, row, line_count, mayclear, TRUE); - if (retval != MAYBE) - return retval; - - if (screen_del_lines(0, wp->w_winrow + row, line_count, - (int)Rows, NULL) == FAIL) { - return FAIL; - } - - /* - * If there are windows or status lines below, try to put them at the - * correct place. If we can't do that, they have to be redrawn. - */ - if (wp->w_next || wp->w_status_height || cmdline_row < Rows - 1) { - if (screen_ins_lines(0, wp->w_winrow + wp->w_height - line_count, - line_count, (int)Rows, NULL) == FAIL) { - wp->w_redr_status = TRUE; - win_rest_invalid(wp->w_next); - } - } - /* - * If this is the last window and there is no status line, redraw the - * command line later. - */ - else - redraw_cmdline = TRUE; - return OK; + return win_do_lines(wp, row, line_count, invalid, mayclear, true); } // Common code for win_ins_lines() and win_del_lines(). // Returns OK or FAIL when the work has been done. -static int win_do_lines(win_T *wp, int row, int line_count, int mayclear, int del) +static int win_do_lines(win_T *wp, int row, int line_count, + int invalid, int mayclear, int del) { + if (invalid) { + wp->w_lines_valid = 0; + } + if (!redrawing() || line_count <= 0) { return FAIL; } @@ -6600,7 +6543,7 @@ int screen_ins_lines ( } } - ui_append_lines(line_count); + ui_call_scroll(-line_count); return OK; } @@ -6655,7 +6598,7 @@ int screen_del_lines ( } } - ui_delete_lines(line_count); + ui_call_scroll(line_count); return OK; } @@ -6728,7 +6671,7 @@ int showmode(void) if (edit_submode_extra != NULL) { MSG_PUTS_ATTR(" ", attr); // Add a space in between. if ((int)edit_submode_highl < (int)HLF_COUNT) { - sub_attr = hl_attr(edit_submode_highl); + sub_attr = win_hl_attr(curwin, edit_submode_highl); } else { sub_attr = attr; } @@ -6746,16 +6689,20 @@ int showmode(void) if (p_ri) MSG_PUTS_ATTR(_(" REVERSE"), attr); MSG_PUTS_ATTR(_(" INSERT"), attr); - } else if (restart_edit == 'I') + } else if (restart_edit == 'I' || restart_edit == 'i' + || restart_edit == 'a') { MSG_PUTS_ATTR(_(" (insert)"), attr); - else if (restart_edit == 'R') + } else if (restart_edit == 'R') { MSG_PUTS_ATTR(_(" (replace)"), attr); - else if (restart_edit == 'V') + } else if (restart_edit == 'V') { MSG_PUTS_ATTR(_(" (vreplace)"), attr); - if (p_hkmap) + } + if (p_hkmap) { MSG_PUTS_ATTR(_(" Hebrew"), attr); - if (p_fkmap) + } + if (p_fkmap) { MSG_PUTS_ATTR(farsi_text_5, attr); + } if (State & LANGMAP) { if (curwin->w_p_arab) { MSG_PUTS_ATTR(_(" Arabic"), attr); @@ -6881,7 +6828,6 @@ static void draw_tabline(void) int modified; int c; int len; - int attr_sel = hl_attr(HLF_TPS); int attr_nosel = hl_attr(HLF_TP); int attr_fill = hl_attr(HLF_TPF); char_u *p; @@ -6894,6 +6840,10 @@ static void draw_tabline(void) } redraw_tabline = false; + if (ui_is_external(kUITabline)) { + ui_ext_tabline_update(); + return; + } if (tabline_height() < 1) return; @@ -6939,16 +6889,6 @@ static void draw_tabline(void) scol = col; - if (tp->tp_topframe == topframe) - attr = attr_sel; - if (use_sep_chars && col > 0) - screen_putchar('|', 0, col++, attr); - - if (tp->tp_topframe != topframe) - attr = attr_nosel; - - screen_putchar(' ', 0, col++, attr); - if (tp == curtab) { cwp = curwin; wp = firstwin; @@ -6957,10 +6897,29 @@ static void draw_tabline(void) wp = tp->tp_firstwin; } - modified = FALSE; - for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) - if (bufIsChanged(wp->w_buffer)) - modified = TRUE; + + if (tp->tp_topframe == topframe) { + attr = win_hl_attr(cwp, HLF_TPS); + } + if (use_sep_chars && col > 0) { + screen_putchar('|', 0, col++, attr); + } + + if (tp->tp_topframe != topframe) { + attr = win_hl_attr(cwp, HLF_TP); + } + + screen_putchar(' ', 0, col++, attr); + + modified = false; + + for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount) { + if (bufIsChanged(wp->w_buffer)) { + modified = true; + } + } + + if (modified || wincount > 1) { if (wincount > 1) { vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount); @@ -6968,7 +6927,7 @@ static void draw_tabline(void) if (col + len >= Columns - 3) break; screen_puts_len(NameBuff, len, 0, col, - hl_combine_attr(attr, hl_attr(HLF_T))); + hl_combine_attr(attr, win_hl_attr(cwp, HLF_T))); col += len; } if (modified) @@ -7034,6 +6993,22 @@ static void draw_tabline(void) redraw_tabline = FALSE; } +void ui_ext_tabline_update(void) +{ + Array tabs = ARRAY_DICT_INIT; + FOR_ALL_TABS(tp) { + Dictionary tab_info = ARRAY_DICT_INIT; + PUT(tab_info, "tab", TABPAGE_OBJ(tp->handle)); + + win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin; + get_trans_bufname(cwp->w_buffer); + PUT(tab_info, "name", STRING_OBJ(cstr_to_string((char *)NameBuff))); + + ADD(tabs, DICTIONARY_OBJ(tab_info)); + } + ui_call_tabline_update(curtab->handle, tabs); +} + /* * Get buffer name for "buf" into NameBuff[]. * Takes care of special buffer names and translates special characters. @@ -7050,25 +7025,28 @@ void get_trans_bufname(buf_T *buf) /* * Get the character to use in a status line. Get its attributes in "*attr". */ -static int fillchar_status(int *attr, int is_curwin) +static int fillchar_status(int *attr, win_T *wp) { int fill; + bool is_curwin = (wp == curwin); if (is_curwin) { - *attr = hl_attr(HLF_S); + *attr = win_hl_attr(wp, HLF_S); fill = fill_stl; } else { - *attr = hl_attr(HLF_SNC); + *attr = win_hl_attr(wp, HLF_SNC); fill = fill_stlnc; } /* Use fill when there is highlighting, and highlighting of current * window differs, or the fillchars differ, or this is not the * current window */ - if (*attr != 0 && ((hl_attr(HLF_S) != hl_attr(HLF_SNC) - || !is_curwin || firstwin == lastwin) - || (fill_stl != fill_stlnc))) + if (*attr != 0 && ((win_hl_attr(wp, HLF_S) != win_hl_attr(wp, HLF_SNC) + || !is_curwin || ONE_WINDOW) + || (fill_stl != fill_stlnc))) { return fill; - if (is_curwin) + } + if (is_curwin) { return '^'; + } return '='; } @@ -7076,13 +7054,10 @@ static int fillchar_status(int *attr, int is_curwin) * Get the character to use in a separator between vertically split windows. * Get its attributes in "*attr". */ -static int fillchar_vsep(int *attr) +static int fillchar_vsep(win_T *wp, int *attr) { - *attr = hl_attr(HLF_C); - if (*attr == 0 && fill_vert == ' ') - return '|'; - else - return fill_vert; + *attr = win_hl_attr(wp, HLF_C); + return fill_vert; } /* @@ -7197,7 +7172,7 @@ static void win_redr_ruler(win_T *wp, int always) if (wp->w_status_height) { row = wp->w_winrow + wp->w_height; - fillchar = fillchar_status(&attr, wp == curwin); + fillchar = fillchar_status(&attr, wp); off = wp->w_wincol; width = wp->w_width; } else { @@ -7324,13 +7299,7 @@ int number_width(win_T *wp) return n; } -/* - * Set size of the Vim shell. - * If 'mustset' is TRUE, we must set Rows and Columns, do not get the real - * window size (this is used for the :win command). - * If 'mustset' is FALSE, we may try to get the real window size and if - * it fails use 'width' and 'height'. - */ +/// Set dimensions of the Nvim application "shell". void screen_resize(int width, int height) { static int busy = FALSE; @@ -7415,8 +7384,8 @@ void screen_resize(int width, int height) --busy; } -// Check if the new shell size is valid, correct it if it's too small or way -// too big. +/// Check if the new Nvim application "shell" dimensions are valid. +/// Correct it if it's too small or way too big. void check_shellsize(void) { if (Rows < min_rows()) { |
