|
|
|
@@ -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
|
|
|
|
|