aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/screen.c')
-rw-r--r--src/nvim/screen.c439
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;
}
}