diff options
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r-- | src/nvim/screen.c | 439 |
1 files changed, 319 insertions, 120 deletions
diff --git a/src/nvim/screen.c b/src/nvim/screen.c index a78f905a70..6be3b6fb60 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -143,7 +143,7 @@ long tab_page_click_defs_size = 0; // for line_putchar. Contains the state that needs to be remembered from // putting one character to the next. typedef struct { - const char_u *p; + const char *p; int prev_c; // previous Arabic character int prev_c1; // first composing char for prev_c } LineState; @@ -232,7 +232,7 @@ void screen_invalidate_highlights(void) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { redraw_later(wp, NOT_VALID); - wp->w_grid.valid = false; + wp->w_grid_alloc.valid = false; } } @@ -582,11 +582,18 @@ int update_screen(int type) FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_redr_type == CLEAR && wp->w_floating && wp->w_grid.chars) { - grid_invalidate(&wp->w_grid); + if (wp->w_redr_type == CLEAR && wp->w_floating && wp->w_grid_alloc.chars) { + grid_invalidate(&wp->w_grid_alloc); wp->w_redr_type = NOT_VALID; } + // reallocate grid if needed. + win_grid_alloc(wp); + + if (wp->w_redr_border || wp->w_redr_type >= NOT_VALID) { + win_redr_border(wp); + } + if (wp->w_redr_type != 0) { if (!did_one) { did_one = TRUE; @@ -774,8 +781,6 @@ static void win_update(win_T *wp, Providers *providers) type = wp->w_redr_type; - win_grid_alloc(wp); - if (type >= NOT_VALID) { wp->w_redr_status = true; wp->w_lines_valid = 0; @@ -1857,7 +1862,7 @@ static int compute_foldcolumn(win_T *wp, int col) /// Handles composing chars and arabic shaping state. static int line_putchar(LineState *s, schar_T *dest, int maxcells, bool rl) { - const char_u *p = s->p; + const char_u *p = (char_u *)s->p; int cells = utf_ptr2cells(p); int c_len = utfc_ptr2len(p); int u8c, u8cc[MAX_MCO]; @@ -2077,12 +2082,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, 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 + colnr_T leadcol = 0; // start of leading spaces bool need_showbreak = false; // overlong line, skip first x chars + sign_attrs_T sattrs[SIGN_SHOW_MAX]; // attributes for signs + int num_signs; // number of signs for line int line_attr = 0; // attribute for the whole line int line_attr_lowprio = 0; // low-priority attribute for the 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 + bool shl_flag; // flag to indicate whether search_hl // has been processed or not bool prevcol_hl_flag; // flag to indicate whether prevcol // equals startcol of search_hl or one @@ -2096,6 +2104,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, char_u buf_fold[FOLD_TEXT_LEN + 1]; // Hold value returned by get_foldtext + bool area_active = false; + /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ # define WL_CMDLINE WL_START + 1 /* cmdline window column */ @@ -2315,7 +2325,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, getvcol(curwin, &pos, (colnr_T *)&tocol, NULL, NULL); } // do at least one character; happens when past end of line - if (fromcol == tocol) { + if (fromcol == tocol && search_match_endcol) { tocol = fromcol + 1; } area_highlighting = true; @@ -2367,11 +2377,14 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, wp->w_last_cursorline = wp->w_cursor.lnum; } + memset(sattrs, 0, sizeof(sattrs)); + num_signs = buf_get_signattrs(wp->w_buffer, lnum, sattrs); + // If this line has a sign with line highlighting set line_attr. // TODO(bfredl, vigoux): this should not take priority over decoration! - v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL, 0, 1); - if (v != 0) { - line_attr = sign_get_attr((int)v, SIGN_LINEHL); + sign_attrs_T * sattr = sign_get_attr(SIGN_LINEHL, sattrs, 0, 1); + if (sattr != NULL) { + line_attr = sattr->sat_linehl; } // Highlight the current line in the quickfix window. @@ -2420,6 +2433,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, if (wp->w_p_list && !has_fold) { if (wp->w_p_lcs_chars.space || wp->w_p_lcs_chars.trail + || wp->w_p_lcs_chars.lead || wp->w_p_lcs_chars.nbsp) { extra_check = true; } @@ -2431,6 +2445,20 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, } trailcol += (colnr_T) (ptr - line); } + // find end of leading whitespace + if (wp->w_p_lcs_chars.lead) { + leadcol = 0; + while (ascii_iswhite(ptr[leadcol])) { + leadcol++; + } + if (ptr[leadcol] == NUL) { + // in a line full of spaces all of them are treated as trailing + leadcol = (colnr_T)0; + } else { + // keep track of the first column not filled with spaces + leadcol += (colnr_T)(ptr - line) + 1; + } + } } /* @@ -2656,7 +2684,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, // already be in use. xfree(p_extra_free); p_extra_free = xmalloc(MAX_MCO * fdc + 1); - n_extra = fill_foldcolumn(p_extra_free, wp, foldinfo, lnum); + n_extra = (int)fill_foldcolumn(p_extra_free, wp, foldinfo, lnum); p_extra_free[n_extra] = NUL; p_extra = p_extra_free; c_extra = NUL; @@ -2673,7 +2701,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int count = win_signcol_count(wp); if (count > 0) { get_sign_display_info( - false, wp, lnum, row, + false, wp, sattrs, row, startrow, filler_lines, filler_todo, count, &c_extra, &c_final, extra, sizeof(extra), &p_extra, &n_extra, @@ -2692,10 +2720,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, // in 'lnum', then display the sign instead of the line // number. if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' - && buf_findsign_id(wp->w_buffer, lnum, (char_u *)"*") != 0) { + && num_signs > 0) { int count = win_signcol_count(wp); get_sign_display_info( - true, wp, lnum, row, + true, wp, sattrs, row, startrow, filler_lines, filler_todo, count, &c_extra, &c_final, extra, sizeof(extra), &p_extra, &n_extra, @@ -2745,13 +2773,13 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, 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, 0, 1); - if (num_sign != 0) { + sign_attrs_T *num_sattr = sign_get_attr(SIGN_NUMHL, sattrs, 0, 1); + if (num_sattr != NULL) { // :sign defined with "numhl" highlight. - char_attr = sign_get_attr(num_sign, SIGN_NUMHL); + char_attr = num_sattr->sat_numhl; } else if ((wp->w_p_cul || wp->w_p_rnu) - && lnum == wp->w_cursor.lnum) { + && lnum == wp->w_cursor.lnum + && filler_todo == 0) { // When 'cursorline' is set highlight the line number of // the current line differently. // TODO(vim): Can we use CursorLine instead of CursorLineNr @@ -2850,6 +2878,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, if (draw_state == WL_LINE - 1 && n_extra == 0) { sign_idx = 0; draw_state = WL_LINE; + + if (has_decor && row == startrow + filler_lines) { + // hide virt_text on text hidden by 'nowrap' + decor_redraw_col(wp->w_buffer, vcol, off, true, &decor_state); + } + if (saved_n_extra) { /* Continue item from end of wrapped line. */ n_extra = saved_n_extra; @@ -2870,6 +2904,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, && vcol >= (long)wp->w_virtcol) || (number_only && draw_state > WL_NR)) && filler_todo <= 0) { + draw_virt_text(buf, &col, grid->Columns); grid_put_linebuf(grid, row, 0, col, -grid->Columns, wp->w_p_rl, wp, wp->w_hl_attr_normal, false); // Pretend we have finished updating the window. Except when @@ -2933,10 +2968,14 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, && vcol_prev < vcol // not at margin && vcol < tocol)) { area_attr = attr; // start highlighting + if (area_highlighting) { + area_active = true; + } } else if (area_attr != 0 && (vcol == tocol || (noinvcur && (colnr_T)vcol == wp->w_virtcol))) { area_attr = 0; // stop highlighting + area_active = false; } if (!n_extra) { @@ -2950,16 +2989,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, */ v = (long)(ptr - line); cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE - && ((cur != NULL - && cur->priority > SEARCH_HL_PRIORITY) - || cur == NULL)) { + shl_flag = false; + while (cur != NULL || !shl_flag) { + if (!shl_flag + && (cur == NULL || cur->priority > SEARCH_HL_PRIORITY)) { shl = &search_hl; - shl_flag = TRUE; - } else + shl_flag = true; + } else { shl = &cur->hl; + } if (cur != NULL) { cur->pos.cur = 0; } @@ -2984,7 +3022,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, has_match_conc = v == (long)shl->startcol ? 2 : 1; match_conc = cur->conceal_char; } else { - has_match_conc = match_conc = 0; + has_match_conc = 0; } } else if (v == (long)shl->endcol) { shl->attr_cur = 0; @@ -3026,16 +3064,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, search_attr_from_match = false; search_attr = search_hl.attr_cur; cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE - && ((cur != NULL - && cur->priority > SEARCH_HL_PRIORITY) - || cur == NULL)) { + shl_flag = false; + while (cur != NULL || !shl_flag) { + if (!shl_flag + && (cur == NULL || cur->priority > SEARCH_HL_PRIORITY)) { shl = &search_hl; - shl_flag = TRUE; - } else + shl_flag = true; + } else { shl = &cur->hl; + } if (shl->attr_cur != 0) { search_attr = shl->attr_cur; search_attr_from_match = shl != &search_hl; @@ -3048,6 +3085,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, && (wp->w_p_list && lcs_eol_one == -1)) { search_attr = 0; } + + // Do not allow a conceal over EOL otherwise EOL will be missed + // and bad things happen. + if (*ptr == NUL) { + has_match_conc = 0; + } } if (diff_hlf != (hlf_T)0) { @@ -3115,6 +3158,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, mb_utf8 = false; } } else { + assert(p_extra != NULL); c = *p_extra; mb_c = c; // If the UTF-8 character is more than one byte: @@ -3392,9 +3436,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, char_attr = hl_combine_attr(spell_attr, char_attr); } + if (wp->w_buffer->terminal) { + char_attr = hl_combine_attr(term_attrs[vcol], char_attr); + } + if (has_decor && v > 0) { - int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1, - &decor_state); + bool selected = (area_active || (area_highlighting && noinvcur + && (colnr_T)vcol == wp->w_virtcol)); + int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v-1, off, + selected, &decor_state); if (extmark_attr != 0) { if (!attr_pri) { char_attr = hl_combine_attr(char_attr, extmark_attr); @@ -3404,10 +3454,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, } } - if (wp->w_buffer->terminal) { - char_attr = hl_combine_attr(term_attrs[vcol], char_attr); - } - // Found last space before word: check for line break. if (wp->w_p_lbr && c0 == c && vim_isbreak(c) && !vim_isbreak((int)(*ptr))) { @@ -3416,8 +3462,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, // TODO: is passing p for start of the line OK? n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1; if (c == TAB && n_extra + col > grid->Columns) { - n_extra = (int)wp->w_buffer->b_p_ts - - vcol % (int)wp->w_buffer->b_p_ts - 1; + n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts, + wp->w_buffer->b_p_vts_array) - 1; } c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; c_final = NUL; @@ -3437,6 +3483,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, || (mb_utf8 && (mb_c == 160 || mb_c == 0x202f))) && curwin->w_p_lcs_chars.nbsp) || (c == ' ' && curwin->w_p_lcs_chars.space + && ptr - line >= leadcol && ptr - line <= trailcol))) { c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp; n_attr = 1; @@ -3452,8 +3499,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, } } - if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') { - c = wp->w_p_lcs_chars.trail; + if ((trailcol != MAXCOL && ptr > line + trailcol && c == ' ') + || (leadcol != 0 && ptr < line + leadcol && c == ' ')) { + c = (ptr > line + trailcol) ? wp->w_p_lcs_chars.trail + : wp->w_p_lcs_chars.lead; n_attr = 1; extra_attr = win_hl_attr(wp, HLF_0); saved_attr2 = char_attr; // save current attr @@ -3483,8 +3532,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, vcol_adjusted = vcol - MB_CHARLEN(p_sbr); } // tab amount depends on current column - tab_len = (int)wp->w_buffer->b_p_ts - - vcol_adjusted % (int)wp->w_buffer->b_p_ts - 1; + tab_len = tabstop_padding(vcol_adjusted, + wp->w_buffer->b_p_ts, + wp->w_buffer->b_p_vts_array) - 1; if (!wp->w_p_lbr || !wp->w_p_list) { n_extra = tab_len; @@ -3517,6 +3567,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, xfree(p_extra_free); p_extra_free = p; for (i = 0; i < tab_len; i++) { + if (*p == NUL) { + tab_len = i; + break; + } int lcs = wp->w_p_lcs_chars.tab2; // if tab3 is given, need to change the char @@ -3672,12 +3726,13 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, && vim_strchr(wp->w_p_cocu, 'v') == NULL)) { char_attr = conceal_attr; if ((prev_syntax_id != syntax_seqnr || has_match_conc > 1) - && (syn_get_sub_char() != NUL || match_conc + && (syn_get_sub_char() != NUL + || (has_match_conc && match_conc) || wp->w_p_cole == 1) && wp->w_p_cole != 3) { // First time at this concealed item: display one // character. - if (match_conc) { + if (has_match_conc && match_conc) { c = match_conc; } else if (syn_get_sub_char() != NUL) { c = syn_get_sub_char(); @@ -3837,16 +3892,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, // 'search_hl' and the match list. char_attr = search_hl.attr; cur = wp->w_match_head; - shl_flag = FALSE; - while (cur != NULL || shl_flag == FALSE) { - if (shl_flag == FALSE - && ((cur != NULL - && cur->priority > SEARCH_HL_PRIORITY) - || cur == NULL)) { + shl_flag = false; + while (cur != NULL || !shl_flag) { + if (!shl_flag + && (cur == NULL || cur->priority > SEARCH_HL_PRIORITY)) { shl = &search_hl; - shl_flag = TRUE; - } else + shl_flag = true; + } else { shl = &cur->hl; + } if ((ptr - line) - 1 == (long)shl->startcol && (shl == &search_hl || !shl->is_addpos)) { char_attr = shl->attr; @@ -3897,9 +3951,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, .hl_id = hl_err })); do_virttext = true; } else if (has_decor) { - VirtText *vp = decor_redraw_virt_text(wp->w_buffer, &decor_state); - if (vp) { - virt_text = *vp; + virt_text = decor_redraw_eol(wp->w_buffer, &decor_state, &line_attr); + if (kv_size(virt_text)) { do_virttext = true; } } @@ -3915,7 +3968,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int i; size_t virt_pos = 0; - LineState s = LINE_STATE((char_u *)""); + LineState s = LINE_STATE(""); int virt_attr = 0; // Make sure alignment is the same regardless @@ -3959,7 +4012,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, if (do_virttext && !delay_virttext) { if (*s.p == NUL) { if (virt_pos < virt_text.size) { - s.p = (char_u *)kv_A(virt_text, virt_pos).text; + s.p = kv_A(virt_text, virt_pos).text; int hl_id = kv_A(virt_text, virt_pos).hl_id; virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0; virt_pos++; @@ -4025,6 +4078,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, col += n; } } + + draw_virt_text(buf, &col, grid->Columns); grid_put_linebuf(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp, wp->w_hl_attr_normal, false); row++; @@ -4243,7 +4298,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, && (grid->Columns == Columns // Window spans the width of the screen, || ui_has(kUIMultigrid)) // or has dedicated grid. && !wp->w_p_rl; // Not right-to-left. - grid_put_linebuf(grid, row, 0, col - boguscols, grid->Columns, wp->w_p_rl, + + int draw_col = col - boguscols; + draw_virt_text(buf, &draw_col, grid->Columns); + grid_put_linebuf(grid, row, 0, draw_col, grid->Columns, wp->w_p_rl, wp, wp->w_hl_attr_normal, wrap); if (wrap) { ScreenGrid *current_grid = grid; @@ -4319,6 +4377,56 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, return row; } +void draw_virt_text(buf_T *buf, int *end_col, int max_col) +{ + DecorState *state = &decor_state; + for (size_t i = 0; i < kv_size(state->active); i++) { + DecorRange *item = &kv_A(state->active, i); + if (item->start_row == state->row && kv_size(item->decor.virt_text) + && item->decor.virt_text_pos == kVTOverlay + && item->virt_col >= 0) { + VirtText vt = item->decor.virt_text; + HlMode hl_mode = item->decor.hl_mode; + LineState s = LINE_STATE(""); + int virt_attr = 0; + int col = item->virt_col; + size_t virt_pos = 0; + item->virt_col = -2; // deactivate + + while (col < max_col) { + if (!*s.p) { + if (virt_pos == kv_size(vt)) { + break; + } + s.p = kv_A(vt, virt_pos).text; + int hl_id = kv_A(vt, virt_pos).hl_id; + virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0; + virt_pos++; + continue; + } + int attr; + bool through = false; + if (hl_mode == kHlModeCombine) { + attr = hl_combine_attr(linebuf_attr[col], virt_attr); + } else if (hl_mode == kHlModeBlend) { + through = (*s.p == ' '); + attr = hl_blend_attrs(linebuf_attr[col], virt_attr, &through); + } else { + attr = virt_attr; + } + schar_T dummy[2]; + int cells = line_putchar(&s, through ? dummy : &linebuf_char[col], + max_col-col, false); + linebuf_attr[col++] = attr; + if (cells > 1) { + linebuf_attr[col++] = attr; + } + } + *end_col = MAX(*end_col, col); + } + } +} + /// Determine if dedicated window grid should be used or the default_grid /// /// If UI did not request multigrid support, draw all windows on the @@ -4331,14 +4439,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, /// screen positions. void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off) { - if (!(*grid)->chars && *grid != &default_grid) { - *row_off += (*grid)->row_offset; - *col_off += (*grid)->col_offset; - if (*grid == &msg_grid_adj && msg_grid.chars) { - *grid = &msg_grid; - } else { - *grid = &default_grid; - } + if ((*grid)->target) { + *row_off += (*grid)->row_offset; + *col_off += (*grid)->col_offset; + *grid = (*grid)->target; } } @@ -4352,7 +4456,7 @@ void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off) static void get_sign_display_info( bool nrcol, win_T *wp, - linenr_T lnum, + sign_attrs_T sattrs[], int row, int startrow, int filler_lines, @@ -4369,8 +4473,6 @@ static void get_sign_display_info( int *sign_idxp ) { - int text_sign; - // Draw cells with the sign value or blank. *c_extrap = ' '; *c_finalp = NUL; @@ -4382,10 +4484,9 @@ static void get_sign_display_info( } if (row == startrow + filler_lines && filler_todo <= 0) { - text_sign = buf_getsigntype(wp->w_buffer, lnum, SIGN_TEXT, - *sign_idxp, count); - if (text_sign != 0) { - *pp_extra = sign_get_text(text_sign); + sign_attrs_T *sattr = sign_get_attr(SIGN_TEXT, sattrs, *sign_idxp, count); + if (sattr != NULL) { + *pp_extra = sattr->sat_text; if (*pp_extra != NULL) { *c_extrap = NUL; *c_finalp = NUL; @@ -4418,7 +4519,7 @@ static void get_sign_display_info( (*pp_extra)[*n_extrap] = NUL; } } - *char_attrp = sign_get_attr(text_sign, SIGN_TEXT); + *char_attrp = sattr->sat_texthl; } } @@ -5092,9 +5193,9 @@ static void redraw_custom_statusline(win_T *wp) // When there is an error disable the statusline, otherwise the // display is messed up with errors and a redraw triggers the problem // again and again. - set_string_option_direct((char_u *)"statusline", -1, - (char_u *)"", OPT_FREE | (*wp->w_p_stl != NUL - ? OPT_LOCAL : OPT_GLOBAL), SID_ERROR); + set_string_option_direct("statusline", -1, (char_u *)"", + OPT_FREE | (*wp->w_p_stl != NUL + ? OPT_LOCAL : OPT_GLOBAL), SID_ERROR); } did_emsg |= saved_did_emsg; entered = false; @@ -5175,7 +5276,7 @@ get_keymap_str ( static void win_redr_custom ( win_T *wp, - int draw_ruler /* TRUE or FALSE */ + bool draw_ruler ) { static int entered = FALSE; @@ -5342,6 +5443,64 @@ theend: entered = FALSE; } +static void win_redr_border(win_T *wp) +{ + wp->w_redr_border = false; + if (!(wp->w_floating && wp->w_float_config.border)) { + return; + } + + ScreenGrid *grid = &wp->w_grid_alloc; + + schar_T *chars = wp->w_float_config.border_chars; + int *attrs = wp->w_float_config.border_attr; + + + int *adj = wp->w_border_adj; + int irow = wp->w_height_inner, icol = wp->w_width_inner; + + if (adj[0]) { + grid_puts_line_start(grid, 0); + if (adj[3]) { + grid_put_schar(grid, 0, 0, chars[0], attrs[0]); + } + for (int i = 0; i < icol; i++) { + grid_put_schar(grid, 0, i+adj[3], chars[1], attrs[1]); + } + if (adj[1]) { + grid_put_schar(grid, 0, icol+adj[3], chars[2], attrs[2]); + } + grid_puts_line_flush(false); + } + + for (int i = 0; i < irow; i++) { + if (adj[3]) { + grid_puts_line_start(grid, i+adj[0]); + grid_put_schar(grid, i+adj[0], 0, chars[7], attrs[7]); + grid_puts_line_flush(false); + } + if (adj[1]) { + int ic = (i == 0 && !adj[0] && chars[2][0]) ? 2 : 3; + grid_puts_line_start(grid, i+adj[0]); + grid_put_schar(grid, i+adj[0], icol+adj[3], chars[ic], attrs[ic]); + grid_puts_line_flush(false); + } + } + + if (adj[2]) { + grid_puts_line_start(grid, irow+adj[0]); + if (adj[3]) { + grid_put_schar(grid, irow+adj[0], 0, chars[6], attrs[6]); + } + for (int i = 0; i < icol; i++) { + int ic = (i == 0 && !adj[3] && chars[6][0]) ? 6 : 5; + grid_put_schar(grid, irow+adj[0], i+adj[3], chars[ic], attrs[ic]); + } + grid_put_schar(grid, irow+adj[0], icol+adj[3], chars[4], attrs[4]); + grid_puts_line_flush(false); + } +} + // Low-level functions to manipulate invidual character cells on the // screen grid. @@ -5479,6 +5638,20 @@ void grid_puts_line_start(ScreenGrid *grid, int row) put_dirty_grid = grid; } +void grid_put_schar(ScreenGrid *grid, int row, int col, char_u *schar, int attr) +{ + assert(put_dirty_row == row); + unsigned int off = grid->line_offset[row] + col; + if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar)) { + schar_copy(grid->chars[off], schar); + grid->attrs[off] = attr; + + put_dirty_first = MIN(put_dirty_first, col); + // TODO(bfredl): Y U NO DOUBLEWIDTH? + put_dirty_last = MAX(put_dirty_last, col+1); + } +} + /// like grid_puts(), but output "text[len]". When "len" is -1 output up to /// a NUL. void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, @@ -6054,7 +6227,7 @@ void check_for_delay(int check_msg_scroll) && !did_wait_return && emsg_silent == 0) { ui_flush(); - os_delay(1000L, true); + os_delay(1006L, true); emsg_on_display = false; if (check_msg_scroll) { msg_scroll = false; @@ -6070,12 +6243,15 @@ void check_for_delay(int check_msg_scroll) void win_grid_alloc(win_T *wp) { ScreenGrid *grid = &wp->w_grid; + ScreenGrid *grid_allocated = &wp->w_grid_alloc; int rows = wp->w_height_inner; int cols = wp->w_width_inner; + int total_rows = wp->w_height_outer; + int total_cols = wp->w_width_outer; bool want_allocation = ui_has(kUIMultigrid) || wp->w_floating; - bool has_allocation = (grid->chars != NULL); + bool has_allocation = (grid_allocated->chars != NULL); if (grid->Rows != rows) { wp->w_lines_valid = 0; @@ -6084,35 +6260,47 @@ void win_grid_alloc(win_T *wp) } int was_resized = false; - if ((has_allocation != want_allocation) - || grid->Rows != rows - || grid->Columns != cols) { - if (want_allocation) { - grid_alloc(grid, rows, cols, wp->w_grid.valid, false); - grid->valid = true; - } else { - // Single grid mode, all rendering will be redirected to default_grid. - // Only keep track of the size and offset of the window. - grid_free(grid); - grid->Rows = rows; - grid->Columns = cols; - grid->valid = false; + if (want_allocation && (!has_allocation + || grid_allocated->Rows != total_rows + || grid_allocated->Columns != total_cols)) { + grid_alloc(grid_allocated, total_rows, total_cols, + wp->w_grid_alloc.valid, false); + grid_allocated->valid = true; + if (wp->w_floating && wp->w_float_config.border) { + wp->w_redr_border = true; } was_resized = true; - } else if (want_allocation && has_allocation && !wp->w_grid.valid) { - grid_invalidate(grid); - grid->valid = true; + } else if (!want_allocation && has_allocation) { + // Single grid mode, all rendering will be redirected to default_grid. + // Only keep track of the size and offset of the window. + grid_free(grid_allocated); + grid_allocated->valid = false; + was_resized = true; + } else if (want_allocation && has_allocation && !wp->w_grid_alloc.valid) { + grid_invalidate(grid_allocated); + grid_allocated->valid = true; } - grid->row_offset = wp->w_winrow; - grid->col_offset = wp->w_wincol; + grid->Rows = rows; + grid->Columns = cols; + + if (want_allocation) { + grid->target = grid_allocated; + grid->row_offset = wp->w_border_adj[0]; + grid->col_offset = wp->w_border_adj[3]; + } else { + grid->target = &default_grid; + grid->row_offset = wp->w_winrow; + grid->col_offset = wp->w_wincol; + } // send grid resize event if: // - a grid was just resized // - screen_resize was called and all grid sizes must be sent // - the UI wants multigrid event (necessary) if ((send_grid_resize || was_resized) && want_allocation) { - ui_call_grid_resize(grid->handle, grid->Columns, grid->Rows); + ui_call_grid_resize(grid_allocated->handle, + grid_allocated->Columns, grid_allocated->Rows); } } @@ -6201,6 +6389,9 @@ retry: tab_page_click_defs = new_tab_page_click_defs; tab_page_click_defs_size = Columns; + default_grid.comp_height = Rows; + default_grid.comp_width = Columns; + default_grid.row_offset = 0; default_grid.col_offset = 0; default_grid.handle = DEFAULT_GRID_HANDLE; @@ -6852,7 +7043,7 @@ void draw_tabline(void) did_emsg = false; win_redr_custom(NULL, false); if (did_emsg) { - set_string_option_direct((char_u *)"tabline", -1, + set_string_option_direct("tabline", -1, (char_u *)"", OPT_FREE, SID_ERROR); } did_emsg |= saved_did_emsg; @@ -7105,20 +7296,23 @@ static void win_redr_ruler(win_T *wp, int always) if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) return; - /* Don't draw the ruler while doing insert-completion, it might overwrite - * the (long) mode message. */ - if (wp == lastwin && lastwin->w_status_height == 0) - if (edit_submode != NULL) + // Don't draw the ruler while doing insert-completion, it might overwrite + // the (long) mode message. + if (wp == lastwin && lastwin->w_status_height == 0) { + if (edit_submode != NULL) { return; + } + } if (*p_ruf) { int save_called_emsg = called_emsg; - called_emsg = FALSE; - win_redr_custom(wp, TRUE); - if (called_emsg) - set_string_option_direct((char_u *)"rulerformat", -1, - (char_u *)"", OPT_FREE, SID_ERROR); + called_emsg = false; + win_redr_custom(wp, true); + if (called_emsg) { + set_string_option_direct("rulerformat", -1, (char_u *)"", + OPT_FREE, SID_ERROR); + } called_emsg |= save_called_emsg; return; } @@ -7334,6 +7528,10 @@ void screen_resize(int width, int height) Rows = height; Columns = width; check_shellsize(); + int max_p_ch = Rows - min_rows() + 1; + if (!ui_has(kUIMessages) && p_ch > max_p_ch) { + p_ch = max_p_ch ? max_p_ch : 1; + } height = Rows; width = Columns; p_lines = Rows; @@ -7436,8 +7634,9 @@ void win_new_shellsize(void) static long old_Columns = 0; if (old_Rows != Rows) { - // if 'window' uses the whole screen, keep it using that */ - if (p_window == old_Rows - 1 || old_Rows == 0) { + // If 'window' uses the whole screen, keep it using that. + // Don't change it when set with "-w size" on the command line. + if (p_window == old_Rows - 1 || (old_Rows == 0 && p_window == 0)) { p_window = Rows - 1; } old_Rows = Rows; @@ -7452,7 +7651,7 @@ void win_new_shellsize(void) win_T *get_win_by_grid_handle(handle_T handle) { FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (wp->w_grid.handle == handle) { + if (wp->w_grid_alloc.handle == handle) { return wp; } } |