aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/edit.c4
-rw-r--r--src/nvim/mbyte.c46
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/screen.c256
-rw-r--r--src/nvim/window.c4
5 files changed, 172 insertions, 140 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 3558bdea06..768d37bd01 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1508,7 +1508,7 @@ void edit_putchar(int c, int highlight)
if (curwin->w_p_rl) {
pc_col += curwin->w_grid.Columns - 1 - curwin->w_wcol;
if (has_mbyte) {
- int fix_col = mb_fix_col(&curwin->w_grid, pc_col, pc_row);
+ int fix_col = grid_fix_col(&curwin->w_grid, pc_col, pc_row);
if (fix_col != pc_col) {
grid_putchar(&curwin->w_grid, ' ', pc_row, fix_col, attr);
@@ -1518,7 +1518,7 @@ void edit_putchar(int c, int highlight)
}
} else {
pc_col += curwin->w_wcol;
- if (mb_lefthalve(&curwin->w_grid, pc_row, pc_col))
+ if (grid_lefthalve(&curwin->w_grid, pc_row, pc_col))
pc_status = PC_STATUS_LEFT;
}
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 775e5b24fc..73748154e7 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -1823,32 +1823,6 @@ const char *mb_unescape(const char **const pp)
return NULL;
}
-/*
- * Return true if the character at "row"/"col" on the screen is the left side
- * of a double-width character.
- * Caller must make sure "row" and "col" are not invalid!
- */
-bool mb_lefthalve(ScreenGrid *grid, int row, int col)
-{
- return utf_off2cells(grid, grid->LineOffset[row] + col,
- grid->LineOffset[row] + grid->Columns) > 1;
-}
-
-/*
- * Correct a position on the screen, if it's the right half of a double-wide
- * char move it to the left half. Returns the corrected column.
- */
-int mb_fix_col(ScreenGrid *grid, int col, int row)
-{
- col = check_col(grid, col);
- row = check_row(grid, row);
- if (grid->ScreenLines != NULL && col > 0
- && grid->ScreenLines[grid->LineOffset[row] + col][0] == 0) {
- return col - 1;
- }
- return col;
-}
-
/*
* Skip the Vim specific head of a 'encoding' name.
@@ -2525,23 +2499,3 @@ char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr,
return retval;
}
-
-// Check bounds for column number
-static int check_col(ScreenGrid *grid, int col)
-{
- if (col < 0)
- return 0;
- if (col >= grid->Columns)
- return grid->Columns - 1;
- return col;
-}
-
-// Check bounds for row number
-static int check_row(ScreenGrid *grid, int row)
-{
- if (row < 0)
- return 0;
- if (row >= grid->Rows)
- return grid->Rows - 1;
- return row;
-}
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index ce914b43f9..d38079ca72 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -699,7 +699,7 @@ void free_all_mem(void)
}
// free screenlines (can't display anything now!)
- free_screengrid(&default_grid);
+ screen_free_all_mem();
clear_hl_tables(false);
list_free_log();
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index dca11fd49e..063363755a 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -121,8 +121,12 @@
#define W_ENDCOL(wp) (wp->w_wincol + wp->w_width)
#define W_ENDROW(wp) (wp->w_winrow + wp->w_height)
-// Get the offset for the current line buffer when redrawing a line for a grid
-#define GRID_TMPLINE(grid) ((grid)->Rows * (grid)->Columns)
+
+// temporary buffer for rendering a single screenline, so it can be
+// comparared with previous contents to calulate smallest delta.
+static size_t linebuf_size = 0;
+static schar_T *linebuf_char = NULL;
+static sattr_T *linebuf_attr = NULL;
static match_T search_hl; /* used for 'hlsearch' highlight matching */
@@ -502,7 +506,7 @@ void update_single_line(win_T *wp, linenr_T lnum)
int j;
// Don't do anything if the screen structures are (not yet) valid.
- if (wp->w_grid.ScreenLines == NULL || updating_screen) {
+ if (linebuf_char == NULL || updating_screen) {
return;
}
updating_screen = true;
@@ -516,6 +520,8 @@ void update_single_line(win_T *wp, linenr_T lnum)
start_search_hl();
prepare_search_hl(wp, lnum);
update_window_hl(wp, false);
+ // allocate window grid if not already
+ win_grid_alloc(wp, false);
win_line(wp, lnum, row, row + wp->w_lines[j].wl_size, false, false);
end_search_hl();
break;
@@ -1774,15 +1780,15 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
* 6. set highlighting for the Visual area an other text
*/
col = 0;
- off = (int)GRID_TMPLINE(grid);
+ off = 0;
/*
* 1. Add the cmdwin_type for the command-line window
* Ignores 'rightleft', this window is never right-left.
*/
if (cmdwin_type != 0 && wp == curwin) {
- schar_from_ascii(grid->ScreenLines[off], cmdwin_type);
- grid->ScreenAttrs[off] = win_hl_attr(wp, HLF_AT);
+ schar_from_ascii(linebuf_char[off], cmdwin_type);
+ linebuf_attr[off] = win_hl_attr(wp, HLF_AT);
col++;
}
@@ -1798,7 +1804,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
win_hl_attr(wp, HLF_FC));
// reverse the fold column
for (i = 0; i < fdc; i++) {
- schar_from_ascii(grid->ScreenLines[off + wp->w_width - i - 1 - col], buf[i]);
+ schar_from_ascii(linebuf_char[off + wp->w_width - i - 1 - col], buf[i]);
}
} else {
copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC));
@@ -1808,10 +1814,10 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
# define RL_MEMSET(p, v, l) if (wp->w_p_rl) \
for (ri = 0; ri < l; ++ri) \
- grid->ScreenAttrs[off + (wp->w_width - (p) - (l)) + ri] = v; \
+ linebuf_attr[off + (wp->w_width - (p) - (l)) + ri] = v; \
else \
for (ri = 0; ri < l; ++ri) \
- grid->ScreenAttrs[off + (p) + ri] = v
+ linebuf_attr[off + (p) + ri] = v
/* Set all attributes of the 'number' or 'relativenumber' column and the
* text */
@@ -1877,7 +1883,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
txtcol = col; /* remember where text starts */
- // 5. move the text to grid->ScreenLines[off]. Fill up with "fill_fold".
+ // 5. move the text to linebuf_char[off]. Fill up with "fill_fold".
// Right-left text is put in columns 0 - number-col, normal text is put
// in columns number-col - window-width.
int idx;
@@ -1895,8 +1901,8 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
// if(col + cells > wp->w_width - (wp->w_p_rl ? col : 0)) { break; }
// This is obvious wrong. If Vim ever fixes this, solve for "cells" again
// in the correct condition.
- int maxcells = wp->w_width - col - (wp->w_p_rl ? col : 0);
- int cells = line_putchar(&s, &grid->ScreenLines[idx], maxcells, wp->w_p_rl);
+ int maxcells = grid->Columns - col - (wp->w_p_rl ? col : 0);
+ int cells = line_putchar(&s, &linebuf_char[idx], maxcells, wp->w_p_rl);
if (cells == -1) {
break;
}
@@ -1913,7 +1919,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
while (col < wp->w_width
- (wp->w_p_rl ? txtcol : 0)
) {
- schar_copy(grid->ScreenLines[off+col++], sc);
+ schar_copy(linebuf_char[off+col++], sc);
}
if (text != buf)
@@ -1977,8 +1983,8 @@ 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) {
- grid->ScreenAttrs[off + txtcol] =
- hl_combine_attr(grid->ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_MC));
+ linebuf_attr[off + txtcol] =
+ hl_combine_attr(linebuf_attr[off + txtcol], win_hl_attr(wp, HLF_MC));
}
txtcol = old_txtcol;
j = wp->w_p_cc_cols[++i];
@@ -1992,13 +1998,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
txtcol -= wp->w_skipcol;
else
txtcol -= wp->w_leftcol;
- if (txtcol >= 0 && txtcol < wp->w_width)
- grid->ScreenAttrs[off + txtcol] = hl_combine_attr(
- grid->ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_CUC));
+ if (txtcol >= 0 && txtcol < wp->w_width) {
+ linebuf_attr[off + txtcol] = hl_combine_attr(
+ linebuf_attr[off + txtcol], win_hl_attr(wp, HLF_CUC));
+ }
}
- grid_move_line(grid, row, 0, grid->Columns, grid->Columns, false, wp,
- wp->w_hl_attr_normal, false);
+ grid_put_linebuf(grid, row, 0, grid->Columns, grid->Columns, false, wp,
+ wp->w_hl_attr_normal, false);
/*
* Update w_cline_height and w_cline_folded if the cursor line was
@@ -2023,8 +2030,8 @@ static void copy_text_attr(int off, char_u *buf, int len, int attr)
int i;
for (i = 0; i < len; i++) {
- schar_from_ascii(default_grid.ScreenLines[off + i], buf[i]);
- default_grid.ScreenAttrs[off + i] = attr;
+ schar_from_ascii(linebuf_char[off + i], buf[i]);
+ linebuf_attr[off + i] = attr;
}
}
@@ -2099,7 +2106,6 @@ win_line (
bool number_only // only update the number column
)
{
- 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
@@ -2238,9 +2244,6 @@ win_line (
row = startrow;
- // allocate window grid if not already
- win_grid_alloc(wp, true);
-
if (!number_only) {
// To speed up the loop below, set extra_check when there is linebreak,
// trailing white space and/or syntax processing to be done.
@@ -2676,11 +2679,11 @@ win_line (
cur = cur->next;
}
- off = (unsigned)GRID_TMPLINE(grid);
+ unsigned off = 0; // Offset relative start of line
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 grid->ScreenLines[off] from right to left. Start at the
+ // it in linebuf_char[off] from right to left. Start at the
// rightmost column of the window.
col = grid->Columns - 1;
off += col;
@@ -2901,8 +2904,8 @@ win_line (
&& lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol
&& filler_todo <= 0)
|| (number_only && draw_state > WL_NR)) {
- grid_move_line(grid, row, 0, col, -grid->Columns, wp->w_p_rl, wp,
- wp->w_hl_attr_normal, false);
+ 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
// 'cursorcolumn' is set.
if (wp->w_p_cuc) {
@@ -3846,7 +3849,7 @@ win_line (
col += n;
} else {
// Add a blank character to highlight.
- schar_from_ascii(grid->ScreenLines[off], ' ');
+ schar_from_ascii(linebuf_char[off], ' ');
}
if (area_attr == 0) {
/* Use attributes from match with highest priority among
@@ -3877,7 +3880,7 @@ win_line (
if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
eol_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUL), eol_attr);
}
- grid->ScreenAttrs[off] = eol_attr;
+ linebuf_attr[off] = eol_attr;
if (wp->w_p_rl) {
--col;
--off;
@@ -3971,14 +3974,14 @@ win_line (
}
}
if (*s.p != NUL) {
- cells = line_putchar(&s, &grid->ScreenLines[off], grid->Columns - col,
+ cells = line_putchar(&s, &linebuf_char[off], grid->Columns - col,
false);
}
}
delay_virttext = false;
if (cells == -1) {
- schar_from_ascii(grid->ScreenLines[off], ' ');
+ schar_from_ascii(linebuf_char[off], ' ');
cells = 1;
}
col += cells * col_stride;
@@ -4000,9 +4003,9 @@ win_line (
attr = hl_combine_attr(attr, line_attr);
- grid->ScreenAttrs[off] = attr;
+ linebuf_attr[off] = attr;
if (cells == 2) {
- grid->ScreenAttrs[off+1] = attr;
+ linebuf_attr[off+1] = attr;
}
off += cells * col_stride;
@@ -4020,12 +4023,12 @@ win_line (
// terminal buffers may need to highlight beyond the end of the
// logical line
while (col < grid->Columns) {
- schar_from_ascii(grid->ScreenLines[off], ' ');
- grid->ScreenAttrs[off++] = term_attrs[vcol++];
+ schar_from_ascii(linebuf_char[off], ' ');
+ linebuf_attr[off++] = term_attrs[vcol++];
col++;
}
}
- grid_move_line(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
+ grid_put_linebuf(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
wp->w_hl_attr_normal, false);
row++;
@@ -4106,22 +4109,23 @@ win_line (
--col;
}
if (mb_utf8) {
- schar_from_cc(grid->ScreenLines[off], mb_c, u8cc);
+ schar_from_cc(linebuf_char[off], mb_c, u8cc);
} else {
- schar_from_ascii(grid->ScreenLines[off], c);
+ schar_from_ascii(linebuf_char[off], c);
}
if (multi_attr) {
- grid->ScreenAttrs[off] = multi_attr;
+ linebuf_attr[off] = multi_attr;
multi_attr = 0;
- } else
- grid->ScreenAttrs[off] = char_attr;
+ } else {
+ linebuf_attr[off] = char_attr;
+ }
if (has_mbyte && (*mb_char2cells)(mb_c) > 1) {
// Need to fill two screen columns.
off++;
col++;
// UTF-8: Put a 0 in the second screen char.
- grid->ScreenLines[off][0] = 0;
+ linebuf_char[off][0] = 0;
if (draw_state > WL_NR && filler_todo <= 0) {
vcol++;
}
@@ -4241,8 +4245,8 @@ win_line (
&& row != endrow - 1 // Not the last line being displayed.
&& grid->Columns == Columns // Window spans the width of the screen.
&& !wp->w_p_rl; // Not right-to-left.
- grid_move_line(grid, row, 0, col - boguscols, grid->Columns, wp->w_p_rl,
- wp, wp->w_hl_attr_normal, wrap);
+ grid_put_linebuf(grid, row, 0, col - boguscols, grid->Columns, wp->w_p_rl,
+ wp, wp->w_hl_attr_normal, wrap);
if (wrap) {
// Force a redraw of the first column of the next line.
grid->ScreenAttrs[grid->LineOffset[row + 1]] = -1;
@@ -4276,7 +4280,7 @@ win_line (
}
col = 0;
- off = (unsigned)GRID_TMPLINE(grid);
+ off = 0;
if (wp->w_p_rl) {
col = grid->Columns - 1; /* col is not used if breaking! */
off += col;
@@ -4323,15 +4327,15 @@ static int grid_char_needs_redraw(ScreenGrid *grid, int off_from, int off_to,
int cols)
{
return (cols > 0
- && ((schar_cmp(grid->ScreenLines[off_from], grid->ScreenLines[off_to])
- || grid->ScreenAttrs[off_from] != grid->ScreenAttrs[off_to]
- || (utf_off2cells(grid, off_from, off_from + cols) > 1
- && schar_cmp(grid->ScreenLines[off_from + 1],
+ && ((schar_cmp(linebuf_char[off_from], grid->ScreenLines[off_to])
+ || linebuf_attr[off_from] != grid->ScreenAttrs[off_to]
+ || (line_off2cells(linebuf_char, off_from, off_from + cols) > 1
+ && schar_cmp(linebuf_char[off_from + 1],
grid->ScreenLines[off_to + 1])))
|| p_wd < 0));
}
-/// Move one "cooked" line to the window grid, but only the characters that
+/// Move one buffered line to the window grid, but only the characters that
/// have actually changed. Handle insert/delete character.
/// "coloff" gives the first column on the grid for this line.
/// "endcol" gives the columns where valid characters are.
@@ -4342,9 +4346,9 @@ static int grid_char_needs_redraw(ScreenGrid *grid, int off_from, int off_to,
/// When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width"
/// If "wrap" is true, then hint to the UI that "row" contains a line
/// which has wrapped into the next row.
-static void grid_move_line(ScreenGrid *grid, int row, int coloff, int endcol,
- int clear_width, int rlflag, win_T *wp, int bg_attr,
- bool wrap)
+static void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol,
+ int clear_width, int rlflag, win_T *wp,
+ int bg_attr, bool wrap)
{
unsigned off_from;
unsigned off_to;
@@ -4372,18 +4376,12 @@ static void grid_move_line(ScreenGrid *grid, int row, int coloff, int endcol,
if (!ui_is_external(kUIMultigrid) && grid != &default_grid) {
row += grid->OffsetRow;
coloff += grid->OffsetColumn;
- memcpy(default_grid.ScreenLines + GRID_TMPLINE(&default_grid),
- grid->ScreenLines + GRID_TMPLINE(grid),
- sizeof(schar_T) * grid->Columns);
- memcpy(default_grid.ScreenAttrs + GRID_TMPLINE(&default_grid),
- grid->ScreenAttrs + GRID_TMPLINE(grid),
- sizeof(sattr_T) * grid->Columns);
grid = &default_grid;
}
- off_from = (unsigned)GRID_TMPLINE(grid);
+ off_from = 0;
off_to = grid->LineOffset[row] + coloff;
- max_off_from = off_from + grid->Columns;
+ max_off_from = linebuf_size;
max_off_to = grid->LineOffset[row] + grid->Columns;
if (rlflag) {
@@ -4409,8 +4407,8 @@ static void grid_move_line(ScreenGrid *grid, int row, int coloff, int endcol,
if (bg_attr) {
for (int c = col; c < endcol; c++) {
- grid->ScreenAttrs[off_from+c] =
- hl_combine_attr(bg_attr, grid->ScreenAttrs[off_from+c]);
+ linebuf_attr[off_from+c] =
+ hl_combine_attr(bg_attr, linebuf_attr[off_from+c]);
}
}
@@ -4419,7 +4417,7 @@ static void grid_move_line(ScreenGrid *grid, int row, int coloff, int endcol,
while (col < endcol) {
char_cells = 1;
if (col + 1 < endcol) {
- char_cells = utf_off2cells(grid, off_from, max_off_from);
+ char_cells = line_off2cells(linebuf_char, off_from, max_off_from);
}
redraw_this = redraw_next;
redraw_next = grid_char_needs_redraw(grid, off_from + char_cells,
@@ -4438,23 +4436,23 @@ static void grid_move_line(ScreenGrid *grid, int row, int coloff, int endcol,
// char over the left halve of an existing one
if (col + char_cells == endcol
&& ((char_cells == 1
- && utf_off2cells(grid, off_to, max_off_to) > 1)
+ && grid_off2cells(grid, off_to, max_off_to) > 1)
|| (char_cells == 2
- && utf_off2cells(grid, off_to, max_off_to) == 1
- && utf_off2cells(grid, off_to + 1, max_off_to) > 1))) {
+ && grid_off2cells(grid, off_to, max_off_to) == 1
+ && grid_off2cells(grid, off_to + 1, max_off_to) > 1))) {
clear_next = true;
}
- schar_copy(grid->ScreenLines[off_to], grid->ScreenLines[off_from]);
+ schar_copy(grid->ScreenLines[off_to], linebuf_char[off_from]);
if (char_cells == 2) {
- schar_copy(grid->ScreenLines[off_to+1], grid->ScreenLines[off_from+1]);
+ schar_copy(grid->ScreenLines[off_to+1], linebuf_char[off_from+1]);
}
- grid->ScreenAttrs[off_to] = grid->ScreenAttrs[off_from];
+ grid->ScreenAttrs[off_to] = linebuf_attr[off_from];
// For simplicity set the attributes of second half of a
// double-wide character equal to the first half.
if (char_cells == 2) {
- grid->ScreenAttrs[off_to + 1] = grid->ScreenAttrs[off_from];
+ grid->ScreenAttrs[off_to + 1] = linebuf_attr[off_from];
}
}
@@ -5257,6 +5255,52 @@ static void schar_copy(char_u *sc1, char_u *sc2)
STRLCPY(sc1, sc2, sizeof(schar_T));
}
+static int line_off2cells(schar_T *line, size_t off, size_t max_off)
+{
+ return (off + 1 < max_off && line[off + 1][0] == 0) ? 2 : 1;
+}
+
+/// Return number of display cells for char at ScreenLines[off].
+/// We make sure that the offset used is less than "max_off".
+static int grid_off2cells(ScreenGrid *grid, size_t off, size_t max_off)
+{
+ return line_off2cells(grid->ScreenLines, off, max_off);
+}
+
+/// Return true if the character at "row"/"col" on the screen is the left side
+/// of a double-width character.
+///
+/// Caller must make sure "row" and "col" are not invalid!
+bool grid_lefthalve(ScreenGrid *grid, int row, int col)
+{
+ if (!ui_is_external(kUIMultigrid)) {
+ row += grid->OffsetRow;
+ col += grid->OffsetColumn;
+ grid = &default_grid;
+ }
+
+ return grid_off2cells(grid, grid->LineOffset[row] + col,
+ grid->LineOffset[row] + grid->Columns) > 1;
+}
+
+/// Correct a position on the screen, if it's the right half of a double-wide
+/// char move it to the left half. Returns the corrected column.
+int grid_fix_col(ScreenGrid *grid, int col, int row)
+{
+ int coloff = 0;
+ if (!ui_is_external(kUIMultigrid)) {
+ row += grid->OffsetRow;
+ coloff = grid->OffsetColumn;
+ grid = &default_grid;
+ }
+
+ col += coloff;
+ if (grid->ScreenLines != NULL && col > 0
+ && grid->ScreenLines[grid->LineOffset[row] + col][0] == 0) {
+ return col - 1 - coloff;
+ }
+ return col - coloff;
+}
/// output a single character directly to the grid and update ScreenLines.
void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr)
@@ -5363,7 +5407,7 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row,
/* When drawing over the right halve of a double-wide char clear out the
* left halve. Only needed in a terminal. */
- if (col > 0 && col < grid->Columns && mb_fix_col(grid, col, row) != col) {
+ if (col > 0 && col < grid->Columns && grid_fix_col(grid, col, row) != col) {
schar_from_ascii(grid->ScreenLines[off - 1], ' ');
grid->ScreenAttrs[off - 1] = 0;
// redraw the previous cell, make it empty
@@ -5438,10 +5482,11 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row,
clear_next_cell = false;
} else if ((len < 0 ? ptr[mbyte_blen] == NUL
: ptr + mbyte_blen >= text + len)
- && ((mbyte_cells == 1 && utf_off2cells(grid, off, max_off) > 1)
+ && ((mbyte_cells == 1
+ && grid_off2cells(grid, off, max_off) > 1)
|| (mbyte_cells == 2
- && utf_off2cells(grid, off, max_off) == 1
- && utf_off2cells(grid, off + 1, max_off) > 1))) {
+ && grid_off2cells(grid, off, max_off) == 1
+ && grid_off2cells(grid, off + 1, max_off) > 1))) {
clear_next_cell = true;
}
@@ -5826,10 +5871,11 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col,
// out the left halve. When drawing over the left halve of a
// double wide-char clear out the right halve. Only needed in a
// terminal.
- if (start_col > 0 && mb_fix_col(grid, start_col, row) != start_col) {
+ if (start_col > 0 && grid_fix_col(grid, start_col, row) != start_col) {
grid_puts_len(grid, (char_u *)" ", 1, row, start_col - 1, 0);
}
- if (end_col < grid->Columns && mb_fix_col(grid, end_col, row) != end_col) {
+ if (end_col < grid->Columns
+ && grid_fix_col(grid, end_col, row) != end_col) {
grid_puts_len(grid, (char_u *)" ", 1, row, end_col, 0);
}
}
@@ -5936,20 +5982,30 @@ void win_grid_alloc(win_T *wp, int doclear)
columns = wp->w_width;
}
- if (grid->ScreenLines == NULL
+ // TODO(bfredl): floating windows should force this to true
+ bool want_allocation = ui_is_external(kUIMultigrid);
+ bool has_allocation = (grid->ScreenLines != NULL);
+
+ if ((has_allocation != want_allocation)
|| grid->Rows != rows
|| grid->Columns != columns) {
- grid_alloc(grid, rows, columns, doclear);
- win_free_lsize(wp);
- win_alloc_lines(wp);
+ if (want_allocation) {
+ grid_alloc(grid, rows, columns, !doclear);
+ win_free_lsize(wp);
+ win_alloc_lines(wp);
+ } 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 = columns;
+ }
grid->was_resized = true;
}
grid->OffsetRow = wp->w_winrow;
grid->OffsetColumn = wp->w_wincol;
- grid_assign_handle(grid);
-
// send grid resize event if:
// - a grid was just resized
// - screen_resize was called and all grid sizes must be sent
@@ -6116,17 +6172,39 @@ void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy)
}
}
}
- free_screengrid(grid);
+ grid_free(grid);
*grid = new;
-}
+ // Share a single scratch buffer for all grids, by
+ // ensuring it is as wide as the widest grid.
+ if (linebuf_size < (size_t)columns) {
+ xfree(linebuf_char);
+ xfree(linebuf_attr);
+ linebuf_char = xmalloc(columns * sizeof(schar_T));
+ linebuf_attr = xmalloc(columns * sizeof(sattr_T));
+ linebuf_size = columns;
+ }
+}
-void free_screengrid(ScreenGrid *grid)
+void grid_free(ScreenGrid *grid)
{
xfree(grid->ScreenLines);
xfree(grid->ScreenAttrs);
xfree(grid->LineOffset);
xfree(grid->LineWraps);
+
+ grid->ScreenLines = NULL;
+ grid->ScreenAttrs = NULL;
+ grid->LineOffset = NULL;
+ grid->LineWraps = NULL;
+}
+
+/// Doesn't allow reinit, so must only be called by free_all_mem!
+void screen_free_all_mem(void)
+{
+ grid_free(&default_grid);
+ xfree(linebuf_char);
+ xfree(linebuf_attr);
}
/// Clear tab_page_click_defs table
diff --git a/src/nvim/window.c b/src/nvim/window.c
index ba44d7334f..3d11076a40 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -3990,7 +3990,7 @@ void win_free_grid(win_T *wp, bool reinit)
ui_call_grid_destroy(wp->w_grid.handle);
wp->w_grid.handle = 0;
}
- free_screengrid(&wp->w_grid);
+ grid_free(&wp->w_grid);
if (reinit) {
// if a float is turned into a split and back into a float, the grid
// data structure will be reused
@@ -4100,7 +4100,7 @@ void win_alloc_lines(win_T *wp)
{
wp->w_lines_valid = 0;
assert(wp->w_grid.Rows >= 0);
- wp->w_lines = xcalloc(wp->w_grid.Rows + 1, sizeof(wline_T));
+ wp->w_lines = xcalloc(MAX(wp->w_grid.Rows + 1, Rows), sizeof(wline_T));
}
/*