aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/api/ui_events.in.h2
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/edit.c27
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/hardcopy.c4
-rw-r--r--src/nvim/message.c50
-rw-r--r--src/nvim/normal.c9
-rw-r--r--src/nvim/popupmnu.c27
-rw-r--r--src/nvim/screen.c807
-rw-r--r--src/nvim/types.h10
-rw-r--r--src/nvim/ui.c34
-rw-r--r--src/nvim/ui.h2
-rw-r--r--src/nvim/version.c4
-rw-r--r--src/nvim/window.c24
14 files changed, 552 insertions, 453 deletions
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 10331fd5c2..5c48cb4804 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -81,6 +81,8 @@ void grid_line(Integer grid, Integer row, Integer col_start, Array data)
void grid_scroll(Integer grid, Integer top, Integer bot,
Integer left, Integer right, Integer rows, Integer cols)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL;
+void grid_destroy(Integer grid)
+ FUNC_API_SINCE(5) FUNC_API_REMOTE_ONLY;
void popupmenu_show(Array items, Integer selected, Integer row, Integer col)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index d270714611..01f3044332 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1183,6 +1183,8 @@ struct window_S {
int w_tagstackidx; /* idx just below active entry */
int w_tagstacklen; /* number of tags on stack */
+ ScreenGrid w_grid; // the grid specific to the window
+
/*
* w_fraction is the fractional row of the cursor within the window, from
* 0 at the top row to FRACTION_MULT at the last row.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index c04190eaba..14577d5abb 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -560,7 +560,7 @@ static int insert_check(VimState *state)
if (curwin->w_wcol < s->mincol - curbuf->b_p_ts
&& curwin->w_wrow == curwin->w_winrow
- + curwin->w_height - 1 - p_so
+ + curwin->w_grid.Rows - 1 - p_so
&& (curwin->w_cursor.lnum != curwin->w_topline
|| curwin->w_topfill > 0)) {
if (curwin->w_topfill > 0) {
@@ -1502,17 +1502,17 @@ void edit_putchar(int c, int highlight)
} else {
attr = 0;
}
- pc_row = curwin->w_winrow + curwin->w_wrow;
- pc_col = curwin->w_wincol;
+ pc_row = curwin->w_wrow;
+ pc_col = 0;
pc_status = PC_STATUS_UNSET;
if (curwin->w_p_rl) {
- pc_col += curwin->w_width - 1 - curwin->w_wcol;
+ pc_col += curwin->w_grid.Columns - 1 - curwin->w_wcol;
if (has_mbyte) {
int fix_col = mb_fix_col(pc_col, pc_row);
if (fix_col != pc_col) {
- screen_putchar(' ', pc_row, fix_col, attr);
- --curwin->w_wcol;
+ grid_putchar(&curwin->w_grid, ' ', pc_row, fix_col, attr);
+ curwin->w_wcol--;
pc_status = PC_STATUS_RIGHT;
}
}
@@ -1524,10 +1524,10 @@ void edit_putchar(int c, int highlight)
/* save the character to be able to put it back */
if (pc_status == PC_STATUS_UNSET) {
- screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr);
+ grid_getbytes(&curwin->w_grid, pc_row, pc_col, pc_bytes, &pc_attr);
pc_status = PC_STATUS_SET;
}
- screen_putchar(c, pc_row, pc_col, attr);
+ grid_putchar(&curwin->w_grid, c, pc_row, pc_col, attr);
}
}
@@ -1543,7 +1543,8 @@ void edit_unputchar(void)
if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) {
redrawWinline(curwin, curwin->w_cursor.lnum, false);
} else {
- screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
+ grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col,
+ pc_attr);
}
}
}
@@ -1566,7 +1567,7 @@ void display_dollar(colnr_T col)
char_u *p = get_cursor_line_ptr();
curwin->w_cursor.col -= utf_head_off(p, p + col);
curs_columns(false); // Recompute w_wrow and w_wcol
- if (curwin->w_wcol < curwin->w_width) {
+ if (curwin->w_wcol < curwin->w_grid.Columns) {
edit_putchar('$', FALSE);
dollar_vcol = curwin->w_virtcol;
}
@@ -5825,7 +5826,7 @@ static void check_auto_format(
/*
* Find out textwidth to be used for formatting:
* if 'textwidth' option is set, use it
- * else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin'
+ * else if 'wrapmargin' option is set, use curwin->w_grid.Columns-'wrapmargin'
* if invalid value, use 0.
* Set default to window width (maximum 79) for "gq" operator.
*/
@@ -5840,7 +5841,7 @@ comp_textwidth (
if (textwidth == 0 && curbuf->b_p_wm) {
/* The width is the window width minus 'wrapmargin' minus all the
* things that add to the margin. */
- textwidth = curwin->w_width - curbuf->b_p_wm;
+ textwidth = curwin->w_grid.Columns - curbuf->b_p_wm;
if (cmdwin_type != 0)
textwidth -= 1;
textwidth -= curwin->w_p_fdc;
@@ -5855,7 +5856,7 @@ comp_textwidth (
if (textwidth < 0)
textwidth = 0;
if (ff && textwidth == 0) {
- textwidth = curwin->w_width - 1;
+ textwidth = curwin->w_grid.Columns - 1;
if (textwidth > 79)
textwidth = 79;
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 097c71928c..3462199476 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -161,7 +161,8 @@ EXTERN char_u *LineWraps INIT(= NULL); /* line wraps to next line */
EXTERN int screen_Rows INIT(= 0); /* actual size of ScreenLines[] */
EXTERN int screen_Columns INIT(= 0); /* actual size of ScreenLines[] */
-EXTERN ScreenGrid default_grid INIT(= { 0 });
+EXTERN ScreenGrid default_grid INIT(= { 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0,
+ 0, 0, 0 });
/*
* When vgetc() is called, it sets mod_mask to the set of modifiers that are
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index a8731d5bd7..f66592682b 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -582,8 +582,8 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum,
*/
static void prt_message(char_u *s)
{
- screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
- screen_puts(s, (int)Rows - 1, 0, HL_ATTR(HLF_R));
+ grid_fill(&default_grid, (int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ grid_puts(&default_grid, s, (int)Rows - 1, 0, HL_ATTR(HLF_R));
ui_flush();
}
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 6de81a8aaf..bb7c605428 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1547,7 +1547,7 @@ void msg_prt_line(char_u *s, int list)
}
/*
- * Use screen_puts() to output one multi-byte character.
+ * Use grid_puts() to output one multi-byte character.
* Return the pointer "s" advanced to the next character.
*/
static char_u *screen_puts_mbyte(char_u *s, int l, int attr)
@@ -1563,7 +1563,7 @@ static char_u *screen_puts_mbyte(char_u *s, int l, int attr)
return s;
}
- screen_puts_len(s, l, msg_row, msg_col, attr);
+ grid_puts_len(&default_grid, s, l, msg_row, msg_col, attr);
if (cmdmsg_rl) {
msg_col -= cw;
if (msg_col == 0) {
@@ -1888,17 +1888,17 @@ static void msg_scroll_up(void)
{
if (dy_flags & DY_MSGSEP) {
if (msg_scrolled == 0) {
- screen_fill(Rows-p_ch-1, Rows-p_ch, 0, (int)Columns,
- fill_msgsep, fill_msgsep, HL_ATTR(HLF_MSGSEP));
+ grid_fill(&default_grid, Rows-p_ch-1, Rows-p_ch, 0, (int)Columns,
+ fill_msgsep, fill_msgsep, HL_ATTR(HLF_MSGSEP));
}
int nscroll = MIN(msg_scrollsize()+1, Rows);
- screen_del_lines(Rows-nscroll, 1, Rows, 0, Columns);
+ grid_del_lines(&default_grid, Rows-nscroll, 1, Rows, 0, Columns);
} else {
- screen_del_lines(0, 1, (int)Rows, 0, Columns);
+ grid_del_lines(&default_grid, 0, 1, (int)Rows, 0, Columns);
}
// TODO(bfredl): when msgsep display is properly batched, this fill should be
// eliminated.
- screen_fill(Rows-1, Rows, 0, (int)Columns, ' ', ' ', 0);
+ grid_fill(&default_grid, Rows-1, Rows, 0, (int)Columns, ' ', ' ', 0);
}
/*
@@ -2097,7 +2097,7 @@ static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr)
{
// Output postponed text.
msg_didout = true; // Remember that line is not empty.
- screen_puts_len((char_u *)t_s, (int)(s - t_s), msg_row, msg_col, attr);
+ grid_puts_len(&default_grid, (char_u *)t_s, (int)(s - t_s), msg_row, msg_col, attr);
msg_col += *t_col;
*t_col = 0;
/* If the string starts with a composing character don't increment the
@@ -2313,8 +2313,9 @@ static int do_more_prompt(int typed_char)
}
if (toscroll == -1
- && screen_ins_lines(0, 1, (int)Rows, 0, (int)Columns) == OK) {
- screen_fill(0, 1, 0, (int)Columns, ' ', ' ', 0);
+ && grid_ins_lines(&default_grid, 0, 1, (int)Rows,
+ 0, (int)Columns) == OK) {
+ grid_fill(&default_grid, 0, 1, 0, (int)Columns, ' ', ' ', 0);
// display line at top
(void)disp_sb_line(0, mp);
} else {
@@ -2333,7 +2334,7 @@ static int do_more_prompt(int typed_char)
/* scroll up, display line at bottom */
msg_scroll_up();
inc_msg_scrolled();
- screen_fill((int)Rows - 2, (int)Rows - 1, 0,
+ grid_fill(&default_grid, (int)Rows - 2, (int)Rows - 1, 0,
(int)Columns, ' ', ' ', 0);
mp_last = disp_sb_line((int)Rows - 2, mp_last);
--toscroll;
@@ -2342,7 +2343,7 @@ static int do_more_prompt(int typed_char)
if (toscroll <= 0) {
/* displayed the requested text, more prompt again */
- screen_fill((int)Rows - 1, (int)Rows, 0,
+ grid_fill(&default_grid, (int)Rows - 1, (int)Rows, 0,
(int)Columns, ' ', ' ', 0);
msg_moremsg(FALSE);
continue;
@@ -2356,7 +2357,7 @@ static int do_more_prompt(int typed_char)
}
/* clear the --more-- message */
- screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ grid_fill(&default_grid, (int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
State = oldState;
setmouse();
if (quit_more) {
@@ -2452,8 +2453,8 @@ void mch_msg(char *str)
*/
static void msg_screen_putchar(int c, int attr)
{
- msg_didout = TRUE; /* remember that line is not empty */
- screen_putchar(c, msg_row, msg_col, attr);
+ msg_didout = true; // remember that line is not empty
+ grid_putchar(&default_grid, c, msg_row, msg_col, attr);
if (cmdmsg_rl) {
if (--msg_col == 0) {
msg_col = Columns;
@@ -2473,11 +2474,12 @@ void msg_moremsg(int full)
char_u *s = (char_u *)_("-- More --");
attr = HL_ATTR(HLF_M);
- screen_puts(s, (int)Rows - 1, 0, attr);
- if (full)
- screen_puts((char_u *)
- _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
- (int)Rows - 1, vim_strsize(s), attr);
+ grid_puts(&default_grid, s, (int)Rows - 1, 0, attr);
+ if (full) {
+ grid_puts(&default_grid, (char_u *)
+ _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "),
+ (int)Rows - 1, vim_strsize(s), attr);
+ }
}
/*
@@ -2526,11 +2528,11 @@ void msg_clr_eos(void)
void msg_clr_eos_force(void)
{
if (cmdmsg_rl) {
- screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0);
- screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ grid_fill(&default_grid, msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0);
+ grid_fill(&default_grid, msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
} else {
- screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ', 0);
- screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ grid_fill(&default_grid, msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ', 0);
+ grid_fill(&default_grid, msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
}
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 38ee0936aa..4e6c3c4063 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -3466,10 +3466,10 @@ static void display_showcmd(void)
int len;
len = (int)STRLEN(showcmd_buf);
- if (len == 0)
+ if (len == 0) {
showcmd_is_clear = true;
- else {
- screen_puts(showcmd_buf, (int)Rows - 1, sc_col, 0);
+ } else {
+ grid_puts(&default_grid, showcmd_buf, (int)Rows - 1, sc_col, 0);
showcmd_is_clear = false;
}
@@ -3477,7 +3477,8 @@ static void display_showcmd(void)
* clear the rest of an old message by outputting up to SHOWCMD_COLS
* spaces
*/
- screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0);
+ grid_puts(&default_grid, (char_u *)" " + len, (int)Rows - 1,
+ sc_col + len, 0);
setcursor(); /* put cursor back where it belongs */
}
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index 68c8967b91..e9a0c7c6b4 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -351,10 +351,10 @@ void pum_redraw(void)
// prepend a space if there is room
if (curwin->w_p_rl) {
if (pum_col < curwin->w_wincol + curwin->w_width - 1) {
- screen_putchar(' ', row, pum_col + 1, attr);
+ grid_putchar(&default_grid, ' ', row, pum_col + 1, attr);
}
} else if (pum_col > 0) {
- screen_putchar(' ', row, pum_col - 1, attr);
+ grid_putchar(&default_grid, ' ', row, pum_col - 1, attr);
}
// Display each entry, use two spaces for a Tab.
@@ -416,12 +416,13 @@ void pum_redraw(void)
size++;
}
}
- screen_puts_len(rt, (int)STRLEN(rt), row, col - size + 1, attr);
+ grid_puts_len(&default_grid, rt, (int)STRLEN(rt), row, col - size + 1,
+ attr);
xfree(rt_start);
xfree(st);
col -= width;
} else {
- screen_puts_len(st, (int)STRLEN(st), row, col, attr);
+ grid_puts_len(&default_grid, st, (int)STRLEN(st), row, col, attr);
xfree(st);
col += width;
}
@@ -432,10 +433,10 @@ void pum_redraw(void)
// Display two spaces for a Tab.
if (curwin->w_p_rl) {
- screen_puts_len((char_u *)" ", 2, row, col - 1, attr);
+ grid_puts_len(&default_grid, (char_u *)" ", 2, row, col - 1, attr);
col -= 2;
} else {
- screen_puts_len((char_u *)" ", 2, row, col, attr);
+ grid_puts_len(&default_grid, (char_u *)" ", 2, row, col, attr);
col += 2;
}
totwidth += 2;
@@ -466,11 +467,11 @@ void pum_redraw(void)
}
if (curwin->w_p_rl) {
- screen_fill(row, row + 1, pum_col - pum_base_width - n + 1,
+ grid_fill(&default_grid, row, row + 1, pum_col - pum_base_width - n + 1,
col + 1, ' ', ' ', attr);
col = pum_col - pum_base_width - n + 1;
} else {
- screen_fill(row, row + 1, col, pum_col + pum_base_width + n,
+ grid_fill(&default_grid, row, row + 1, col, pum_col + pum_base_width + n,
' ', ' ', attr);
col = pum_col + pum_base_width + n;
}
@@ -478,24 +479,24 @@ void pum_redraw(void)
}
if (curwin->w_p_rl) {
- screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ', ' ',
+ grid_fill(&default_grid, row, row + 1, pum_col - pum_width + 1, col + 1, ' ', ' ',
attr);
} else {
- screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', attr);
+ grid_fill(&default_grid, row, row + 1, col, pum_col + pum_width, ' ', ' ', attr);
}
if (pum_scrollbar > 0) {
if (curwin->w_p_rl) {
- screen_putchar(' ', row, pum_col - pum_width,
+ grid_putchar(&default_grid, ' ', row, pum_col - pum_width,
i >= thumb_pos && i < thumb_pos + thumb_heigth
? attr_thumb : attr_scroll);
} else {
- screen_putchar(' ', row, pum_col + pum_width,
+ grid_putchar(&default_grid, ' ', row, pum_col + pum_width,
i >= thumb_pos && i < thumb_pos + thumb_heigth
? attr_thumb : attr_scroll);
}
}
- screen_puts_line_flush(false);
+ grid_puts_line_flush(&default_grid, false);
row++;
}
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index fcb225084d..3aaca394f5 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -118,22 +118,14 @@
#define MB_FILLER_CHAR '<' /* character used when a double-width character
* doesn't fit. */
-#define W_ENDCOL(wp) (wp->w_wincol + wp->w_width)
+#define W_ENDCOL(wp) (wp->w_width + wp->w_wincol)
static match_T search_hl; /* used for 'hlsearch' highlight matching */
static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
-/*
- * Buffer for one screen line (characters and attributes).
- */
-static schar_T *current_ScreenLine;
-
StlClickDefinition *tab_page_click_defs = NULL;
-int grid_Rows = 0;
-int grid_Columns = 0;
-
long tab_page_click_defs_size = 0;
// for line_putchar. Contains the state that needs to be remembered from
@@ -145,6 +137,13 @@ typedef struct {
} LineState;
#define LINE_STATE(p) { p, 0, 0 }
+/// The last handle that was assigned to a ScreenGrid. 1 is reserved for
+/// the default_grid.
+static int last_handle = 1;
+
+/// Whether to call "ui_call_grid_resize" in win_grid_alloc
+static int send_grid_resize;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "screen.c.generated.h"
#endif
@@ -304,12 +303,12 @@ void update_screen(int type)
wp->w_redr_status = true;
}
}
- } else if (msg_scrolled > Rows - 5) { // clearing is faster
+ } else if (msg_scrolled > default_grid.Rows - 5) { // clearing is faster
type = CLEAR;
} else if (type != CLEAR) {
check_for_delay(false);
- if (screen_ins_lines(0, msg_scrolled, (int)Rows, 0, (int)Columns)
- == FAIL) {
+ if (grid_ins_lines(&default_grid, 0, msg_scrolled, (int)Rows,
+ 0, (int)Columns) == FAIL) {
type = CLEAR;
}
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
@@ -434,6 +433,7 @@ void update_screen(int type)
win_redr_status(wp, true); // any popup menu will be redrawn below
}
}
+ send_grid_resize = false;
end_search_hl();
// May need to redraw the popup menu.
if (pum_drawn()) {
@@ -502,7 +502,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 (!screen_valid(true) || updating_screen) {
+ if (wp->w_grid.ScreenLines == NULL || updating_screen) {
return;
}
updating_screen = true;
@@ -673,19 +673,21 @@ static void win_update(win_T *wp)
type = wp->w_redr_type;
+ win_grid_alloc(wp, false);
+
if (type >= NOT_VALID) {
wp->w_redr_status = true;
wp->w_lines_valid = 0;
}
/* Window is zero-height: nothing to draw. */
- if (wp->w_height == 0) {
+ if (wp->w_grid.Rows == 0) {
wp->w_redr_type = 0;
return;
}
/* Window is zero-width: Only need to draw the separator. */
- if (wp->w_width == 0) {
+ if (wp->w_grid.Columns == 0) {
/* draw the vertical separator right of this window */
draw_vsep_win(wp, 0);
wp->w_redr_type = 0;
@@ -876,19 +878,19 @@ static void win_update(win_T *wp)
j = 0;
for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ++ln) {
++j;
- if (j >= wp->w_height - 2)
+ if (j >= wp->w_grid.Rows - 2)
break;
(void)hasFoldingWin(wp, ln, NULL, &ln, true, NULL);
}
} else
j = wp->w_lines[0].wl_lnum - wp->w_topline;
- if (j < wp->w_height - 2) { /* not too far off */
+ if (j < wp->w_grid.Rows - 2) { /* not too far off */
i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1);
/* insert extra lines for previously invisible filler lines */
if (wp->w_lines[0].wl_lnum != wp->w_topline)
i += diff_check_fill(wp, wp->w_lines[0].wl_lnum)
- wp->w_old_topfill;
- if (i < wp->w_height - 2) { // less than a screen off
+ if (i < wp->w_grid.Rows - 2) { // less than a screen off
// Try to insert the correct number of lines.
// If not the last window, delete the lines at the bottom.
// win_ins_lines may fail when the terminal can't do it.
@@ -901,8 +903,8 @@ static void win_update(win_T *wp)
/* Move the entries that were scrolled, disable
* the entries for the lines to be redrawn. */
- if ((wp->w_lines_valid += j) > wp->w_height)
- wp->w_lines_valid = wp->w_height;
+ if ((wp->w_lines_valid += j) > wp->w_grid.Rows)
+ wp->w_lines_valid = wp->w_grid.Rows;
for (idx = wp->w_lines_valid; idx - j >= 0; idx--)
wp->w_lines[idx] = wp->w_lines[idx - j];
while (idx >= 0)
@@ -951,7 +953,7 @@ static void win_update(win_T *wp)
row -= wp->w_topfill;
if (row > 0) {
if (win_del_lines(wp, 0, row) == OK) {
- bot_start = wp->w_height - row;
+ bot_start = wp->w_grid.Rows - row;
} else {
mid_start = 0; // redraw all lines
}
@@ -970,7 +972,7 @@ static void win_update(win_T *wp)
/* stop at line that didn't fit, unless it is still
* valid (no lines deleted) */
if (row > 0 && bot_start + row
- + (int)wp->w_lines[j].wl_size > wp->w_height) {
+ + (int)wp->w_lines[j].wl_size > wp->w_grid.Rows) {
wp->w_lines_valid = idx + 1;
break;
}
@@ -994,18 +996,18 @@ static void win_update(win_T *wp)
// When starting redraw in the first line, redraw all lines.
if (mid_start == 0) {
- mid_end = wp->w_height;
+ mid_end = wp->w_grid.Rows;
}
} else {
/* Not VALID or INVERTED: redraw all lines. */
mid_start = 0;
- mid_end = wp->w_height;
+ mid_end = wp->w_grid.Rows;
}
if (type == SOME_VALID) {
/* SOME_VALID: redraw all lines. */
mid_start = 0;
- mid_end = wp->w_height;
+ mid_end = wp->w_grid.Rows;
type = NOT_VALID;
}
@@ -1150,7 +1152,7 @@ static void win_update(win_T *wp)
++lnum;
}
srow += mid_start;
- mid_end = wp->w_height;
+ mid_end = wp->w_grid.Rows;
for (; idx < wp->w_lines_valid; ++idx) { /* find end */
if (wp->w_lines[idx].wl_valid
&& wp->w_lines[idx].wl_lnum >= to + 1) {
@@ -1191,7 +1193,7 @@ static void win_update(win_T *wp)
for (;; ) {
/* stop updating when reached the end of the window (check for _past_
* the end of the window is at the end of the loop) */
- if (row == wp->w_height) {
+ if (row == wp->w_grid.Rows) {
didline = TRUE;
break;
}
@@ -1290,7 +1292,7 @@ static void win_update(win_T *wp)
new_rows += plines_win(wp, l, true);
}
j++;
- if (new_rows > wp->w_height - row - 2) {
+ if (new_rows > wp->w_grid.Rows - row - 2) {
/* it's getting too much, must redraw the rest */
new_rows = 9999;
break;
@@ -1302,20 +1304,20 @@ static void win_update(win_T *wp)
* remaining text or scrolling fails, must redraw the
* rest. If scrolling works, must redraw the text
* below the scrolled text. */
- if (row - xtra_rows >= wp->w_height - 2) {
+ if (row - xtra_rows >= wp->w_grid.Rows - 2) {
mod_bot = MAXLNUM;
} else {
if (win_del_lines(wp, row, -xtra_rows) == FAIL) {
mod_bot = MAXLNUM;
} else {
- bot_start = wp->w_height + xtra_rows;
+ bot_start = wp->w_grid.Rows + xtra_rows;
}
}
} else if (xtra_rows > 0) {
/* May scroll text down. If there is not enough
* remaining text of scrolling fails, must redraw the
* rest. */
- if (row + xtra_rows >= wp->w_height - 2) {
+ if (row + xtra_rows >= wp->w_grid.Rows - 2) {
mod_bot = MAXLNUM;
} else {
if (win_ins_lines(wp, row + old_rows, xtra_rows) == FAIL) {
@@ -1344,7 +1346,7 @@ static void win_update(win_T *wp)
wp->w_lines[j] = wp->w_lines[i];
/* stop at a line that won't fit */
if (x + (int)wp->w_lines[j].wl_size
- > wp->w_height) {
+ > wp->w_grid.Rows) {
wp->w_lines_valid = j + 1;
break;
}
@@ -1357,8 +1359,8 @@ static void win_update(win_T *wp)
/* move entries in w_lines[] downwards */
j -= i;
wp->w_lines_valid += j;
- if (wp->w_lines_valid > wp->w_height)
- wp->w_lines_valid = wp->w_height;
+ if (wp->w_lines_valid > wp->w_grid.Rows)
+ wp->w_lines_valid = wp->w_grid.Rows;
for (i = wp->w_lines_valid; i - j >= idx; --i)
wp->w_lines[i] = wp->w_lines[i - j];
@@ -1392,12 +1394,12 @@ static void win_update(win_T *wp)
&& wp->w_lines[idx].wl_lnum == lnum
&& lnum > wp->w_topline
&& !(dy_flags & (DY_LASTLINE | DY_TRUNCATE))
- && srow + wp->w_lines[idx].wl_size > wp->w_height
+ && srow + wp->w_lines[idx].wl_size > wp->w_grid.Rows
&& diff_check_fill(wp, lnum) == 0
) {
/* This line is not going to fit. Don't draw anything here,
* will draw "@ " lines below. */
- row = wp->w_height + 1;
+ row = wp->w_grid.Rows + 1;
} else {
prepare_search_hl(wp, lnum);
/* Let the syntax stuff know we skipped a few lines. */
@@ -1408,7 +1410,7 @@ static void win_update(win_T *wp)
/*
* Display one line.
*/
- row = win_line(wp, lnum, srow, wp->w_height, mod_top == 0, false);
+ row = win_line(wp, lnum, srow, wp->w_grid.Rows, mod_top == 0, false);
wp->w_lines[idx].wl_folded = FALSE;
wp->w_lines[idx].wl_lastlnum = lnum;
@@ -1422,7 +1424,7 @@ static void win_update(win_T *wp)
// Past end of the window or end of the screen. Note that after
// resizing wp->w_height may be end up too big. That's a problem
// elsewhere, but prevent a crash here.
- if (row > wp->w_height || row + wp->w_winrow >= Rows) {
+ if (row > wp->w_grid.Rows || row + wp->w_winrow >= Rows) {
// we may need the size of that too long line later on
if (dollar_vcol == -1) {
wp->w_lines[idx].wl_size = plines_win(wp, lnum, true);
@@ -1443,7 +1445,7 @@ static void win_update(win_T *wp)
// This line does not need to be drawn, advance to the next one.
row += wp->w_lines[idx++].wl_size;
- if (row > wp->w_height) /* past end of screen */
+ if (row > wp->w_grid.Rows) /* past end of screen */
break;
lnum = wp->w_lines[idx - 1].wl_lastlnum + 1;
did_update = DID_NONE;
@@ -1483,31 +1485,28 @@ static void win_update(win_T *wp)
* Don't overwrite it, it can be edited.
*/
wp->w_botline = lnum + 1;
- } else if (diff_check_fill(wp, lnum) >= wp->w_height - srow) {
+ } else if (diff_check_fill(wp, lnum) >= wp->w_grid.Rows - srow) {
/* Window ends in filler lines. */
wp->w_botline = lnum;
- wp->w_filler_rows = wp->w_height - srow;
+ wp->w_filler_rows = wp->w_grid.Rows - srow;
} else if (dy_flags & DY_TRUNCATE) { // 'display' has "truncate"
- int scr_row = wp->w_winrow + wp->w_height - 1;
+ int scr_row = wp->w_grid.Rows - 1;
// Last line isn't finished: Display "@@@" in the last screen line.
- screen_puts_len((char_u *)"@@", 2, scr_row, wp->w_wincol, at_attr);
+ grid_puts_len(&wp->w_grid, (char_u *)"@@", 2, scr_row, 0, at_attr);
- screen_fill(scr_row, scr_row + 1,
- (int)wp->w_wincol + 2, (int)W_ENDCOL(wp),
- '@', ' ', at_attr);
+ grid_fill(&wp->w_grid, scr_row, scr_row + 1, 2, (int)wp->w_grid.Columns,
+ '@', ' ', at_attr);
set_empty_rows(wp, srow);
wp->w_botline = lnum;
} else if (dy_flags & DY_LASTLINE) { // 'display' has "lastline"
// Last line isn't finished: Display "@@@" at the end.
- screen_fill(wp->w_winrow + wp->w_height - 1,
- wp->w_winrow + wp->w_height,
- W_ENDCOL(wp) - 3, W_ENDCOL(wp),
- '@', '@', at_attr);
+ grid_fill(&wp->w_grid, wp->w_height - 1, wp->w_height,
+ wp->w_grid.Columns - 3, wp->w_grid.Columns, '@', '@', at_attr);
set_empty_rows(wp, srow);
wp->w_botline = lnum;
} else {
- win_draw_end(wp, '@', ' ', srow, wp->w_height, HLF_AT);
+ win_draw_end(wp, '@', ' ', srow, wp->w_grid.Rows, HLF_AT);
wp->w_botline = lnum;
}
} else {
@@ -1522,8 +1521,8 @@ static void win_update(win_T *wp)
i = '-';
else
i = fill_diff;
- if (row + j > wp->w_height)
- j = wp->w_height - row;
+ if (row + j > wp->w_grid.Rows)
+ j = wp->w_grid.Rows - row;
win_draw_end(wp, i, i, row, row + (int)j, HLF_DED);
row += j;
}
@@ -1614,9 +1613,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
/* draw the fold column at the right */
if (n > wp->w_width)
n = wp->w_width;
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- W_ENDCOL(wp) - n, W_ENDCOL(wp),
- ' ', ' ', win_hl_attr(wp, HLF_FC));
+ grid_fill(&wp->w_grid, row, endrow, wp->w_grid.Columns - n,
+ wp->w_grid.Columns, ' ', ' ', win_hl_attr(wp, HLF_FC));
}
if (signcolumn_on(wp)) {
@@ -1626,27 +1624,24 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
if (nn > wp->w_width) {
nn = wp->w_width;
}
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- W_ENDCOL(wp) - nn, W_ENDCOL(wp) - n,
- ' ', ' ', win_hl_attr(wp, HLF_SC));
+ grid_fill(&wp->w_grid, row, endrow, wp->w_grid.Columns - nn,
+ wp->w_grid.Columns - n, ' ', ' ', win_hl_attr(wp, HLF_SC));
n = nn;
}
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- wp->w_wincol, W_ENDCOL(wp) - 1 - FDC_OFF,
- c2, c2, attr);
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- W_ENDCOL(wp) - 1 - FDC_OFF, W_ENDCOL(wp) - FDC_OFF,
- c1, c2, attr);
+ grid_fill(&wp->w_grid, row, endrow, 0, wp->w_grid.Columns - 1 - FDC_OFF,
+ c2, c2, attr);
+ grid_fill(&wp->w_grid, row, endrow,
+ wp->w_grid.Columns - 1 - FDC_OFF, wp->w_grid.Columns - FDC_OFF,
+ c1, c2, attr);
} else {
if (cmdwin_type != 0 && wp == curwin) {
/* draw the cmdline character in the leftmost column */
n = 1;
if (n > wp->w_width)
n = wp->w_width;
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- wp->w_wincol, wp->w_wincol + n,
- cmdwin_type, ' ', win_hl_attr(wp, HLF_AT));
+ grid_fill(&wp->w_grid, row, endrow, 0, n, cmdwin_type, ' ',
+ win_hl_attr(wp, HLF_AT));
}
if (fdc > 0) {
int nn = n + fdc;
@@ -1654,9 +1649,8 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
/* draw the fold column at the left */
if (nn > wp->w_width)
nn = wp->w_width;
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- wp->w_wincol + n, wp->w_wincol + nn,
- ' ', ' ', win_hl_attr(wp, HLF_FC));
+ grid_fill(&wp->w_grid, row, endrow, n, nn, ' ', ' ',
+ win_hl_attr(wp, HLF_FC));
n = nn;
}
@@ -1667,15 +1661,12 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
if (nn > wp->w_width) {
nn = wp->w_width;
}
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- wp->w_wincol + n, wp->w_wincol + nn,
- ' ', ' ', win_hl_attr(wp, HLF_SC));
+ grid_fill(&wp->w_grid, row, endrow, n, nn, ' ', ' ',
+ win_hl_attr(wp, HLF_SC));
n = nn;
}
- screen_fill(wp->w_winrow + row, wp->w_winrow + endrow,
- wp->w_wincol + FDC_OFF, W_ENDCOL(wp),
- c1, c2, attr);
+ grid_fill(&wp->w_grid, row, endrow, FDC_OFF, wp->w_grid.Columns, c1, c2, attr);
}
set_empty_rows(wp, row);
}
@@ -1768,8 +1759,9 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
int fdc;
int col;
int txtcol;
- int off = (int)(current_ScreenLine - ScreenLines);
+ int off;
int ri;
+ ScreenGrid *grid = &wp->w_grid;
/* Build the fold line:
* 1. Add the cmdwin_type for the command-line window
@@ -1780,14 +1772,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->Rows * grid->Columns);
/*
* 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(ScreenLines[off], cmdwin_type);
- ScreenAttrs[off] = win_hl_attr(wp, HLF_AT);
+ schar_from_ascii(grid->ScreenLines[off], cmdwin_type);
+ grid->ScreenAttrs[off] = win_hl_attr(wp, HLF_AT);
col++;
}
@@ -1803,7 +1796,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(ScreenLines[off + wp->w_width - i - 1 - col], buf[i]);
+ schar_from_ascii(grid->ScreenLines[off + wp->w_width - i - 1 - col], buf[i]);
}
} else {
copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC));
@@ -1813,10 +1806,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) \
- ScreenAttrs[off + (wp->w_width - (p) - (l)) + ri] = v; \
+ grid->ScreenAttrs[off + (wp->w_width - (p) - (l)) + ri] = v; \
else \
for (ri = 0; ri < l; ++ri) \
- ScreenAttrs[off + (p) + ri] = v
+ grid->ScreenAttrs[off + (p) + ri] = v
/* Set all attributes of the 'number' or 'relativenumber' column and the
* text */
@@ -1882,11 +1875,9 @@ 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 current_ScreenLine. 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.
- */
+ // 5. move the text to grid->ScreenLines[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;
if (wp->w_p_rl) {
@@ -1903,7 +1894,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
// 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, &ScreenLines[idx], maxcells, wp->w_p_rl);
+ int cells = line_putchar(&s, &grid->ScreenLines[idx], maxcells, wp->w_p_rl);
if (cells == -1) {
break;
}
@@ -1920,7 +1911,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(ScreenLines[off+col++], sc);
+ schar_copy(grid->ScreenLines[off+col++], sc);
}
if (text != buf)
@@ -1984,8 +1975,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) {
- ScreenAttrs[off + txtcol] =
- hl_combine_attr(ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_MC));
+ grid->ScreenAttrs[off + txtcol] =
+ hl_combine_attr(grid->ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_MC));
}
txtcol = old_txtcol;
j = wp->w_p_cc_cols[++i];
@@ -2000,12 +1991,12 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
else
txtcol -= wp->w_leftcol;
if (txtcol >= 0 && txtcol < wp->w_width)
- ScreenAttrs[off + txtcol] = hl_combine_attr(
- ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_CUC));
+ grid->ScreenAttrs[off + txtcol] = hl_combine_attr(
+ grid->ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_CUC));
}
- screen_line(row + wp->w_winrow, wp->w_wincol, wp->w_width,
- wp->w_width, false, wp, wp->w_hl_attr_normal, false);
+ grid_move_line(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
@@ -2114,7 +2105,7 @@ win_line (
char_u *line; // current line
char_u *ptr; // current position in "line"
int row; // row in the window, excl w_winrow
- int screen_row; // row on the screen, incl w_winrow
+ ScreenGrid *grid = &wp->w_grid; // grid specfic to the window
char_u extra[18]; /* line number and 'fdc' must fit in here */
int n_extra = 0; /* number of extra chars */
@@ -2244,7 +2235,9 @@ win_line (
return startrow;
row = startrow;
- screen_row = row + wp->w_winrow;
+
+ // 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,
@@ -2681,11 +2674,11 @@ win_line (
cur = cur->next;
}
- off = (unsigned)(current_ScreenLine - ScreenLines);
+ off = (unsigned)(grid->Rows * grid->Columns);
int col = 0; // Visual column on screen.
if (wp->w_p_rl) {
// Rightleft window: process the text in the normal direction, but put
- // it in current_ScreenLine[] from right to left. Start at the
+ // it in grid->ScreenLines[off] from right to left. Start at the
// rightmost column of the window.
col = wp->w_width - 1;
off += col;
@@ -2906,14 +2899,14 @@ win_line (
&& lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol
&& filler_todo <= 0)
|| (number_only && draw_state > WL_NR)) {
- screen_line(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl, wp,
- wp->w_hl_attr_normal, false);
+ grid_move_line(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) {
row = wp->w_cline_row + wp->w_cline_height;
} else {
- row = wp->w_height;
+ row = wp->w_grid.Rows;
}
break;
}
@@ -3851,7 +3844,7 @@ win_line (
col += n;
} else {
// Add a blank character to highlight.
- schar_from_ascii(ScreenLines[off], ' ');
+ schar_from_ascii(grid->ScreenLines[off], ' ');
}
if (area_attr == 0) {
/* Use attributes from match with highest priority among
@@ -3882,7 +3875,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);
}
- ScreenAttrs[off] = eol_attr;
+ grid->ScreenAttrs[off] = eol_attr;
if (wp->w_p_rl) {
--col;
--off;
@@ -3976,14 +3969,14 @@ win_line (
}
}
if (*s.p != NUL) {
- cells = line_putchar(&s, &ScreenLines[off], wp->w_width - col,
+ cells = line_putchar(&s, &grid->ScreenLines[off], wp->w_width - col,
false);
}
}
delay_virttext = false;
if (cells == -1) {
- schar_from_ascii(ScreenLines[off], ' ');
+ schar_from_ascii(grid->ScreenLines[off], ' ');
cells = 1;
}
col += cells * col_stride;
@@ -4025,13 +4018,13 @@ win_line (
// terminal buffers may need to highlight beyond the end of the
// logical line
while (col < wp->w_width) {
- schar_from_ascii(ScreenLines[off], ' ');
- ScreenAttrs[off++] = term_attrs[vcol++];
+ schar_from_ascii(grid->ScreenLines[off], ' ');
+ grid->ScreenAttrs[off++] = term_attrs[vcol++];
col++;
}
}
- screen_line(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl, wp,
- wp->w_hl_attr_normal, false);
+ grid_move_line(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
+ wp->w_hl_attr_normal, false);
row++;
/*
@@ -4111,22 +4104,22 @@ win_line (
--col;
}
if (mb_utf8) {
- schar_from_cc(ScreenLines[off], mb_c, u8cc);
+ schar_from_cc(grid->ScreenLines[off], mb_c, u8cc);
} else {
- schar_from_ascii(ScreenLines[off], c);
+ schar_from_ascii(grid->ScreenLines[off], c);
}
if (multi_attr) {
- ScreenAttrs[off] = multi_attr;
+ grid->ScreenAttrs[off] = multi_attr;
multi_attr = 0;
} else
- ScreenAttrs[off] = char_attr;
+ grid->ScreenAttrs[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.
- ScreenLines[off][0] = 0;
+ grid->ScreenLines[off][0] = 0;
if (draw_state > WL_NR && filler_todo <= 0) {
vcol++;
}
@@ -4240,25 +4233,24 @@ win_line (
|| (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str)
|| (n_extra != 0 && (c_extra != NUL || *p_extra != NUL)))
) {
- bool wrap = wp->w_p_wrap // Wrapping enabled.
- && filler_todo <= 0 // Not drawing diff filler lines.
- && lcs_eol_one != -1 // Haven't printed the lcs_eol character.
- && row != endrow - 1 // Not the last line being displayed.
- && wp->w_width == Columns // Window spans the width of the screen.
- && !wp->w_p_rl; // Not right-to-left.
- screen_line(screen_row, wp->w_wincol, col - boguscols,
- wp->w_width, wp->w_p_rl, wp, wp->w_hl_attr_normal, wrap);
+ bool wrap = wp->w_p_wrap // Wrapping enabled.
+ && filler_todo <= 0 // Not drawing diff filler lines.
+ && lcs_eol_one != -1 // Haven't printed the lcs_eol character.
+ && 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);
if (wrap) {
// Force a redraw of the first column of the next line.
- ScreenAttrs[LineOffset[screen_row + 1]] = -1;
+ grid->ScreenAttrs[grid->LineOffset[row + 1]] = -1;
// Remember that the line wraps, used for modeless copy.
- LineWraps[screen_row] = true;
+ grid->LineWraps[row] = true;
}
boguscols = 0;
++row;
- ++screen_row;
/* When not wrapping and finished diff lines, or when displayed
* '$' and highlighting until last column, break here. */
@@ -4271,7 +4263,7 @@ win_line (
if (draw_state != WL_LINE
&& filler_todo <= 0
) {
- win_draw_end(wp, '@', ' ', row, wp->w_height, HLF_AT);
+ win_draw_end(wp, '@', ' ', row, wp->w_grid.Rows, HLF_AT);
row = endrow;
}
@@ -4282,7 +4274,7 @@ win_line (
}
col = 0;
- off = (unsigned)(current_ScreenLine - ScreenLines);
+ off = (unsigned)(grid->Rows * grid->Columns);
if (wp->w_p_rl) {
col = wp->w_width - 1; /* col is not used if breaking! */
off += col;
@@ -4325,32 +4317,32 @@ win_line (
* - the character is multi-byte and the next byte is different
* - the character is two cells wide and the second cell differs.
*/
-static int char_needs_redraw(int off_from, int off_to, int cols)
+static int grid_char_needs_redraw(ScreenGrid *grid, int off_from, int off_to,
+ int cols)
{
return (cols > 0
- && ((schar_cmp(ScreenLines[off_from], ScreenLines[off_to])
- || ScreenAttrs[off_from] != ScreenAttrs[off_to]
+ && ((schar_cmp(grid->ScreenLines[off_from], grid->ScreenLines[off_to])
+ || grid->ScreenAttrs[off_from] != grid->ScreenAttrs[off_to]
|| (utf_off2cells(off_from, off_from + cols) > 1
- && schar_cmp(ScreenLines[off_from + 1],
- ScreenLines[off_to + 1])))
+ && schar_cmp(grid->ScreenLines[off_from + 1],
+ grid->ScreenLines[off_to + 1])))
|| p_wd < 0));
}
-/*
- * Move one "cooked" screen line to the screen, but only the characters that
- * have actually changed. Handle insert/delete character.
- * "coloff" gives the first column on the screen for this line.
- * "endcol" gives the columns where valid characters are.
- * "clear_width" is the width of the window. It's > 0 if the rest of the line
- * needs to be cleared, negative otherwise.
- * "rlflag" is TRUE in a rightleft window:
- * When TRUE and "clear_width" > 0, clear columns 0 to "endcol"
- * 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 screen_line(int row, int coloff, int endcol, int clear_width,
- int rlflag, win_T *wp, int bg_attr, bool wrap)
+/// Move one "cooked" 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.
+/// "clear_width" is the width of the window. It's > 0 if the rest of the line
+/// needs to be cleared, negative otherwise.
+/// "rlflag" is TRUE in a rightleft window:
+/// When TRUE and "clear_width" > 0, clear columns 0 to "endcol"
+/// 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)
{
unsigned off_from;
unsigned off_to;
@@ -4364,46 +4356,50 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
// 2: occupies two display cells
int start_dirty = -1, end_dirty = 0;
+ if (grid == NULL) {
+ grid = &default_grid;
+ }
+
/* Check for illegal row and col, just in case. */
- if (row >= Rows)
- row = Rows - 1;
- if (endcol > Columns)
- endcol = Columns;
+ if (row >= grid->Rows)
+ row = grid->Rows - 1;
+ if (endcol > grid->Columns)
+ endcol = grid->Columns;
- off_from = (unsigned)(current_ScreenLine - ScreenLines);
- off_to = LineOffset[row] + coloff;
- max_off_from = off_from + screen_Columns;
- max_off_to = LineOffset[row] + screen_Columns;
+ off_from = (unsigned)(grid->Rows * grid->Columns);
+ off_to = grid->LineOffset[row] + coloff;
+ max_off_from = off_from + grid->Columns;
+ max_off_to = grid->LineOffset[row] + grid->Columns;
if (rlflag) {
/* Clear rest first, because it's left of the text. */
if (clear_width > 0) {
- while (col <= endcol && ScreenLines[off_to][0] == ' '
- && ScreenLines[off_to][1] == NUL
- && ScreenAttrs[off_to] == bg_attr
+ while (col <= endcol && grid->ScreenLines[off_to][0] == ' '
+ && grid->ScreenLines[off_to][1] == NUL
+ && grid->ScreenAttrs[off_to] == bg_attr
) {
++off_to;
++col;
}
if (col <= endcol) {
- screen_fill(row, row + 1, col + coloff, endcol + coloff + 1, ' ', ' ',
- bg_attr);
+ grid_fill(grid, row, row + 1, col + coloff, endcol + coloff + 1,
+ ' ', ' ', bg_attr);
}
}
col = endcol + 1;
- off_to = LineOffset[row] + col + coloff;
+ off_to = grid->LineOffset[row] + col + coloff;
off_from += col;
endcol = (clear_width > 0 ? clear_width : -clear_width);
}
if (bg_attr) {
for (int c = col; c < endcol; c++) {
- ScreenAttrs[off_from+c] = hl_combine_attr(bg_attr,
- ScreenAttrs[off_from+c]);
+ grid->ScreenAttrs[off_from+c] =
+ hl_combine_attr(bg_attr, grid->ScreenAttrs[off_from+c]);
}
}
- redraw_next = char_needs_redraw(off_from, off_to, endcol - col);
+ redraw_next = grid_char_needs_redraw(grid, off_from, off_to, endcol - col);
while (col < endcol) {
char_cells = 1;
@@ -4411,9 +4407,9 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
char_cells = utf_off2cells(off_from, max_off_from);
}
redraw_this = redraw_next;
- redraw_next = char_needs_redraw(off_from + char_cells,
- off_to + char_cells,
- endcol - col - char_cells);
+ redraw_next = grid_char_needs_redraw(grid, off_from + char_cells,
+ off_to + char_cells,
+ endcol - col - char_cells);
if (redraw_this) {
if (start_dirty == -1) {
@@ -4434,16 +4430,16 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
clear_next = true;
}
- schar_copy(ScreenLines[off_to], ScreenLines[off_from]);
+ schar_copy(grid->ScreenLines[off_to], grid->ScreenLines[off_from]);
if (char_cells == 2) {
- schar_copy(ScreenLines[off_to+1], ScreenLines[off_from+1]);
+ schar_copy(grid->ScreenLines[off_to+1], grid->ScreenLines[off_from+1]);
}
- ScreenAttrs[off_to] = ScreenAttrs[off_from];
+ grid->ScreenAttrs[off_to] = grid->ScreenAttrs[off_from];
// For simplicity set the attributes of second half of a
// double-wide character equal to the first half.
if (char_cells == 2) {
- ScreenAttrs[off_to + 1] = ScreenAttrs[off_from];
+ grid->ScreenAttrs[off_to + 1] = grid->ScreenAttrs[off_from];
}
}
@@ -4455,7 +4451,7 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
if (clear_next) {
/* Clear the second half of a double-wide character of which the left
* half was overwritten with a single-wide character. */
- schar_from_ascii(ScreenLines[off_to], ' ');
+ schar_from_ascii(grid->ScreenLines[off_to], ' ');
end_dirty++;
}
@@ -4464,11 +4460,11 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
// blank out the rest of the line
// TODO(bfredl): we could cache winline widths
while (col < clear_width) {
- if (ScreenLines[off_to][0] != ' ' || ScreenLines[off_to][1] != NUL
- || ScreenAttrs[off_to] != bg_attr) {
- ScreenLines[off_to][0] = ' ';
- ScreenLines[off_to][1] = NUL;
- ScreenAttrs[off_to] = bg_attr;
+ if (grid->ScreenLines[off_to][0] != ' ' || grid->ScreenLines[off_to][1] != NUL
+ || grid->ScreenAttrs[off_to] != bg_attr) {
+ grid->ScreenLines[off_to][0] = ' ';
+ grid->ScreenLines[off_to][1] = NUL;
+ grid->ScreenAttrs[off_to] = bg_attr;
if (start_dirty == -1) {
start_dirty = col;
end_dirty = col;
@@ -4482,10 +4478,10 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
}
}
- if (clear_width > 0 || wp->w_width != Columns) {
+ if (clear_width > 0 || wp->w_width != grid->Columns) {
// If we cleared after the end of the line, it did not wrap.
// For vsplit, line wrapping is not possible.
- LineWraps[row] = false;
+ grid->LineWraps[row] = false;
}
if (clear_end < end_dirty) {
@@ -4495,7 +4491,7 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
start_dirty = end_dirty;
}
if (clear_end > start_dirty) {
- ui_line(row, coloff+start_dirty, coloff+end_dirty, coloff+clear_end,
+ ui_line(grid, row, coloff+start_dirty, coloff+end_dirty, coloff+clear_end,
bg_attr, wrap);
}
}
@@ -4590,9 +4586,8 @@ static void draw_vsep_win(win_T *wp, int row)
if (wp->w_vsep_width) {
// draw the vertical separator right of this window
c = fillchar_vsep(wp, &hl);
- screen_fill(wp->w_winrow + row, wp->w_winrow + wp->w_height,
- W_ENDCOL(wp), W_ENDCOL(wp) + 1,
- c, ' ', hl);
+ grid_fill(&default_grid, wp->w_winrow + row, wp->w_winrow + wp->w_height,
+ W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
}
}
@@ -4677,7 +4672,7 @@ win_redr_status_matches (
if (matches == NULL) /* interrupted completion? */
return;
- buf = xmalloc(has_mbyte ? Columns * MB_MAXBYTES + 1 : Columns + 1);
+ buf = xmalloc(has_mbyte ? default_grid.Columns * MB_MAXBYTES + 1 : default_grid.Columns + 1);
if (match == -1) { /* don't show match but original text */
match = 0;
@@ -4698,13 +4693,13 @@ win_redr_status_matches (
if (first_match > 0)
clen += 2;
/* jumping right, put match at the left */
- if ((long)clen > Columns) {
+ if ((long)clen > default_grid.Columns) {
first_match = match;
/* if showing the last match, we can add some on the left */
clen = 2;
for (i = match; i < num_matches; ++i) {
clen += status_match_len(xp, L_MATCH(i)) + 2;
- if ((long)clen >= Columns)
+ if ((long)clen >= default_grid.Columns)
break;
}
if (i == num_matches)
@@ -4714,7 +4709,7 @@ win_redr_status_matches (
if (add_left)
while (first_match > 0) {
clen += status_match_len(xp, L_MATCH(first_match - 1)) + 2;
- if ((long)clen >= Columns)
+ if ((long)clen >= default_grid.Columns)
break;
--first_match;
}
@@ -4731,7 +4726,7 @@ win_redr_status_matches (
clen = len;
i = first_match;
- while ((long)(clen + status_match_len(xp, L_MATCH(i)) + 2) < Columns) {
+ while ((long)(clen + status_match_len(xp, L_MATCH(i)) + 2) < default_grid.Columns) {
if (i == match) {
selstart = buf + len;
selstart_col = clen;
@@ -4782,8 +4777,8 @@ win_redr_status_matches (
if (msg_scrolled > 0) {
/* Put the wildmenu just above the command line. If there is
* no room, scroll the screen one line up. */
- if (cmdline_row == Rows - 1) {
- screen_del_lines(0, 1, (int)Rows, 0, (int)Columns);
+ if (cmdline_row == default_grid.Rows - 1) {
+ grid_del_lines(&default_grid, 0, 1, (int)Rows, 0, (int)Columns);
msg_scrolled++;
} else {
cmdline_row++;
@@ -4805,13 +4800,14 @@ win_redr_status_matches (
}
}
- screen_puts(buf, row, 0, attr);
+ grid_puts(&default_grid, buf, row, 0, attr);
if (selstart != NULL && highlight) {
*selend = NUL;
- screen_puts(selstart, row, selstart_col, HL_ATTR(HLF_WM));
+ grid_puts(&default_grid, selstart, row, selstart_col, HL_ATTR(HLF_WM));
}
- screen_fill(row, row + 1, clen, (int)Columns, fillchar, fillchar, attr);
+ grid_fill(&default_grid, row, row + 1, clen, (int)default_grid.Columns,
+ fillchar, fillchar, attr);
}
win_redraw_last_status(topframe);
@@ -4910,14 +4906,14 @@ static void win_redr_status(win_T *wp, int ignore_pum)
}
row = wp->w_winrow + wp->w_height;
- screen_puts(p, row, wp->w_wincol, attr);
- screen_fill(row, row + 1, len + wp->w_wincol,
- this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
+ grid_puts(&default_grid, p, row, wp->w_wincol, attr);
+ grid_fill(&default_grid, row, row + 1, len + wp->w_wincol,
+ this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)
&& this_ru_col - len > (int)(STRLEN(NameBuff) + 1))
- screen_puts(NameBuff, row, (int)(this_ru_col - STRLEN(NameBuff)
- - 1 + wp->w_wincol), attr);
+ grid_puts(&default_grid, NameBuff, row,
+ (int)(this_ru_col - STRLEN(NameBuff) - 1), attr);
win_redr_ruler(wp, TRUE);
}
@@ -4931,8 +4927,8 @@ static void win_redr_status(win_T *wp, int ignore_pum)
} else {
fillchar = fillchar_vsep(wp, &attr);
}
- screen_putchar(fillchar, wp->w_winrow + wp->w_height,
- W_ENDCOL(wp), attr);
+ grid_putchar(&default_grid, fillchar, wp->w_winrow + wp->w_height,
+ W_ENDCOL(wp), attr);
}
busy = FALSE;
}
@@ -5076,7 +5072,7 @@ win_redr_custom (
row = 0;
fillchar = ' ';
attr = HL_ATTR(HLF_TPF);
- maxwidth = Columns;
+ maxwidth = default_grid.Columns;
use_sandbox = was_set_insecurely((char_u *)"tabline", 0);
} else {
row = wp->w_winrow + wp->w_height;
@@ -5095,12 +5091,12 @@ win_redr_custom (
if (*stl++ != '(')
stl = p_ruf;
}
- col = ru_col - (Columns - wp->w_width);
+ col = ru_col - (default_grid.Columns - wp->w_width);
if (col < (wp->w_width + 1) / 2)
col = (wp->w_width + 1) / 2;
maxwidth = wp->w_width - col;
if (!wp->w_status_height) {
- row = Rows - 1;
+ row = default_grid.Rows - 1;
--maxwidth; /* writing in last column may cause scrolling */
fillchar = ' ';
attr = 0;
@@ -5116,7 +5112,7 @@ win_redr_custom (
*wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
}
- col += wp->w_wincol;
+ col += wp->w_winrow;
}
if (maxwidth <= 0)
@@ -5159,7 +5155,7 @@ win_redr_custom (
p = buf;
for (n = 0; hltab[n].start != NULL; n++) {
int len = (int)(hltab[n].start - p);
- screen_puts_len(p, len, row, col, curattr);
+ grid_puts_len(&default_grid, p, len, row, col, curattr);
col += vim_strnsize(p, len);
p = hltab[n].start;
@@ -5173,9 +5169,9 @@ win_redr_custom (
curattr = highlight_user[hltab[n].userhl - 1];
}
// Make sure to use an empty string instead of p, if p is beyond buf + len.
- screen_puts(p >= buf + len ? (char_u *)"" : p, row, col, curattr);
+ grid_puts(&default_grid, p >= buf + len ? (char_u *)"" : p, row, col, curattr);
- screen_puts_line_flush(false);
+ grid_puts_line_flush(&default_grid, false);
if (wp == NULL) {
// Fill the tab_page_click_defs array for clicking in the tab pages line.
@@ -5193,7 +5189,7 @@ win_redr_custom (
p = (char_u *) tabtab[n].start;
cur_click_def = tabtab[n].def;
}
- while (col < Columns) {
+ while (col < default_grid.Columns) {
tab_page_click_defs[col++] = cur_click_def;
}
}
@@ -5247,42 +5243,42 @@ static void schar_copy(char_u *sc1, char_u *sc2)
}
-/*
- * Output a single character directly to the screen and update ScreenLines.
- */
-void screen_putchar(int c, int row, int col, int attr)
+/// output a single character directly to the grid and update ScreenLines.
+void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr)
{
char_u buf[MB_MAXBYTES + 1];
buf[utf_char2bytes(c, buf)] = NUL;
- screen_puts(buf, row, col, attr);
+ grid_puts(grid, buf, row, col, attr);
}
-/*
- * Get a single character directly from ScreenLines into "bytes[]".
- * Also return its attribute in *attrp;
- */
-void screen_getbytes(int row, int col, char_u *bytes, int *attrp)
+/// get a single character directly from grid.ScreenLines into "bytes[]".
+/// Also return its attribute in *attrp;
+void grid_getbytes(ScreenGrid *grid, int row, int col, char_u *bytes,
+ int *attrp)
{
unsigned off;
- /* safety check */
- if (ScreenLines != NULL && row < screen_Rows && col < screen_Columns) {
- off = LineOffset[row] + col;
- *attrp = ScreenAttrs[off];
- schar_copy(bytes, ScreenLines[off]);
+ if (grid == NULL) {
+ grid = &default_grid;
+ }
+
+ // safety check
+ if (grid->ScreenLines != NULL && row < grid->Rows && col < grid->Columns) {
+ off = grid->LineOffset[row] + col;
+ *attrp = grid->ScreenAttrs[off];
+ schar_copy(bytes, grid->ScreenLines[off]);
}
}
-/*
- * Put string '*text' on the screen at position 'row' and 'col', with
- * attributes 'attr', and update ScreenLines[] and ScreenAttrs[].
- * Note: only outputs within one row, message is truncated at screen boundary!
- * Note: if ScreenLines[], row and/or col is invalid, nothing is done.
- */
-void screen_puts(char_u *text, int row, int col, int attr)
+
+/// put string '*text' on the window grid at position 'row' and 'col', with
+/// attributes 'attr', and update ScreenLines[] and ScreenAttrs[].
+/// Note: only outputs within one row, message is truncated at grid boundary!
+/// Note: if ScreenLines[], row and/or col is invalid, nothing is done.
+void grid_puts(ScreenGrid *grid, char_u *text, int row, int col, int attr)
{
- screen_puts_len(text, -1, row, col, attr);
+ grid_puts_len(grid, text, -1, row, col, attr);
}
static int put_dirty_row = -1;
@@ -5299,11 +5295,10 @@ void screen_puts_line_start(int row)
put_dirty_row = row;
}
-/*
- * Like screen_puts(), but output "text[len]". When "len" is -1 output up to
- * a NUL.
- */
-void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
+/// 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,
+ int col, int attr)
{
unsigned off;
char_u *ptr = text;
@@ -5321,8 +5316,17 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
int force_redraw_this;
int force_redraw_next = FALSE;
int need_redraw;
-
bool do_flush = false;
+
+ if (grid == NULL) {
+ grid = &default_grid;
+ }
+
+ // safety check
+ if (grid->ScreenLines == NULL || row >= grid->Rows || col >= grid->Columns) {
+ return;
+ }
+
if (put_dirty_row == -1) {
screen_puts_line_start(row);
do_flush = true;
@@ -5331,16 +5335,13 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
abort();
}
}
-
- if (ScreenLines == NULL || row >= screen_Rows) /* safety check */
- return;
- off = LineOffset[row] + col;
+ off = grid->LineOffset[row] + col;
/* 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 < screen_Columns && mb_fix_col(col, row) != col) {
- schar_from_ascii(ScreenLines[off - 1], ' ');
- ScreenAttrs[off - 1] = 0;
+ if (col > 0 && col < grid->Columns && mb_fix_col(col, row) != col) {
+ schar_from_ascii(grid->ScreenLines[off - 1], ' ');
+ grid->ScreenAttrs[off - 1] = 0;
// redraw the previous cell, make it empty
if (put_dirty_first == -1) {
put_dirty_first = col-1;
@@ -5350,8 +5351,8 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
force_redraw_next = true;
}
- max_off = LineOffset[row] + screen_Columns;
- while (col < screen_Columns
+ max_off = grid->LineOffset[row] + grid->Columns;
+ while (col < grid->Columns
&& (len < 0 || (int)(ptr - text) < len)
&& *ptr != NUL) {
c = *ptr;
@@ -5384,7 +5385,7 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
} else {
prev_c = u8c;
}
- if (col + mbyte_cells > screen_Columns) {
+ if (col + mbyte_cells > grid->Columns) {
// Only 1 cell left, but character requires 2 cells:
// display a '>' in the last column to avoid wrapping. */
c = '>';
@@ -5398,9 +5399,9 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
force_redraw_this = force_redraw_next;
force_redraw_next = FALSE;
- need_redraw = schar_cmp(ScreenLines[off], buf)
- || (mbyte_cells == 2 && ScreenLines[off + 1][0] != 0)
- || ScreenAttrs[off] != attr
+ need_redraw = schar_cmp(grid->ScreenLines[off], buf)
+ || (mbyte_cells == 2 && grid->ScreenLines[off + 1][0] != 0)
+ || grid->ScreenAttrs[off] != attr
|| exmode_active;
if (need_redraw || force_redraw_this) {
@@ -5420,11 +5421,11 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
clear_next_cell = true;
}
- schar_copy(ScreenLines[off], buf);
- ScreenAttrs[off] = attr;
+ schar_copy(grid->ScreenLines[off], buf);
+ grid->ScreenAttrs[off] = attr;
if (mbyte_cells == 2) {
- ScreenLines[off + 1][0] = 0;
- ScreenAttrs[off + 1] = attr;
+ grid->ScreenLines[off + 1][0] = 0;
+ grid->ScreenAttrs[off + 1] = attr;
}
if (put_dirty_first == -1) {
put_dirty_first = col;
@@ -5443,25 +5444,26 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
}
if (do_flush) {
- screen_puts_line_flush(true);
+ grid_puts_line_flush(grid, true);
}
}
/// End a group of screen_puts_len calls and send the screen buffer to the UI
/// layer.
///
+/// @param grid The grid which contains the buffer.
/// @param set_cursor Move the visible cursor to the end of the changed region.
/// This is a workaround for not yet refactored code paths
/// and shouldn't be used in new code.
-void screen_puts_line_flush(bool set_cursor)
+void grid_puts_line_flush(ScreenGrid *grid, bool set_cursor)
{
assert(put_dirty_row != -1);
if (put_dirty_first != -1) {
if (set_cursor) {
- ui_cursor_goto(put_dirty_row, put_dirty_last);
+ ui_grid_cursor_goto(grid, put_dirty_row, put_dirty_last);
}
- ui_line(put_dirty_row, put_dirty_first, put_dirty_last, put_dirty_last, 0,
- false);
+ ui_line(grid, put_dirty_row, put_dirty_first, put_dirty_last,
+ put_dirty_last, 0, false);
put_dirty_first = -1;
put_dirty_last = 0;
}
@@ -5764,20 +5766,23 @@ next_search_hl_pos(
}
-/*
- * Fill the screen from 'start_row' to 'end_row', from 'start_col' to 'end_col'
- * with character 'c1' in first column followed by 'c2' in the other columns.
- * Use attributes 'attr'.
- */
-void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, int c2, int attr)
+/// Fill the grid from 'start_row' to 'end_row', from 'start_col' to 'end_col'
+/// with character 'c1' in first column followed by 'c2' in the other columns.
+/// Use attributes 'attr'.
+void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col,
+ int end_col, int c1, int c2, int attr)
{
schar_T sc;
- if (end_row > screen_Rows) /* safety check */
- end_row = screen_Rows;
- if (end_col > screen_Columns) /* safety check */
- end_col = screen_Columns;
- if (ScreenLines == NULL
+ if (grid == NULL) {
+ grid = &default_grid;
+ }
+
+ if (end_row > grid->Rows) // safety check
+ end_row = grid->Rows;
+ if (end_col > grid->Columns) // safety check
+ end_col = grid->Columns;
+ if (grid->ScreenLines == NULL
|| start_row >= end_row
|| start_col >= end_col) /* nothing to do */
return;
@@ -5789,10 +5794,10 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
// double wide-char clear out the right halve. Only needed in a
// terminal.
if (start_col > 0 && mb_fix_col(start_col, row) != start_col) {
- screen_puts_len((char_u *)" ", 1, row, start_col - 1, 0);
+ grid_puts_len(grid, (char_u *)" ", 1, row, start_col - 1, 0);
}
- if (end_col < screen_Columns && mb_fix_col(end_col, row) != end_col) {
- screen_puts_len((char_u *)" ", 1, row, end_col, 0);
+ if (end_col < grid->Columns && mb_fix_col(end_col, row) != end_col) {
+ grid_puts_len(grid, (char_u *)" ", 1, row, end_col, 0);
}
}
@@ -5800,12 +5805,13 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
int dirty_last = 0;
int col = start_col;
schar_from_char(sc, c1);
- int lineoff = LineOffset[row];
+ int lineoff = grid->LineOffset[row];
for (col = start_col; col < end_col; col++) {
int off = lineoff + col;
- if (schar_cmp(ScreenLines[off], sc) || ScreenAttrs[off] != attr) {
- schar_copy(ScreenLines[off], sc);
- ScreenAttrs[off] = attr;
+ if (schar_cmp(grid->ScreenLines[off], sc)
+ || grid->ScreenAttrs[off] != attr) {
+ schar_copy(grid->ScreenLines[off], sc);
+ grid->ScreenAttrs[off] = attr;
if (dirty_first == INT_MAX) {
dirty_first = col;
}
@@ -5824,16 +5830,16 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
put_dirty_last = MAX(put_dirty_last, dirty_last);
} else {
int last = c2 != ' ' ? dirty_last : dirty_first + (c1 != ' ');
- ui_line(row, dirty_first, last, dirty_last, attr, false);
+ ui_line(grid, row, dirty_first, last, dirty_last, attr, false);
}
}
if (end_col == Columns) {
- LineWraps[row] = false;
+ grid->LineWraps[row] = false;
}
// TODO(bfredl): The relevant caller should do this
- if (row == Rows - 1) { // overwritten the command line
+ if (row == default_grid.Rows - 1) { // overwritten the command line
redraw_cmdline = true;
if (start_col == 0 && end_col == Columns
&& c1 == ' ' && c2 == ' ' && attr == 0) {
@@ -5872,7 +5878,34 @@ void check_for_delay(int check_msg_scroll)
int screen_valid(int doclear)
{
screenalloc(doclear); /* allocate screen buffers if size changed */
- return ScreenLines != NULL;
+ return default_grid.ScreenLines != NULL;
+}
+
+/// (re)allocate a window grid if size changed
+/// If "doclear" is true, clear the screen if resized.
+// TODO(utkarshme): Think of a better name, place
+void win_grid_alloc(win_T *wp, int doclear)
+{
+ if (wp->w_grid.ScreenLines == NULL
+ || wp->w_grid.Rows != wp->w_height
+ || wp->w_grid.Columns != wp->w_width) {
+ grid_alloc(&wp->w_grid, wp->w_height, wp->w_width, doclear);
+
+ // only assign a grid handle if not already
+ if (wp->w_grid.handle == 0) {
+ wp->w_grid.handle = ++last_handle;
+ }
+
+ wp->w_grid.OffsetRow = wp->w_winrow;
+ wp->w_grid.OffsetColumn = wp->w_wincol;
+
+ wp->w_grid.was_resized = true;
+ }
+
+ if (send_grid_resize || wp->w_grid.was_resized) {
+ ui_call_grid_resize(wp->w_grid.handle, wp->w_grid.Columns, wp->w_grid.Rows);
+ wp->w_grid.was_resized = false;
+ }
}
/*
@@ -5895,12 +5928,12 @@ retry:
// when Rows and Columns have been set and we have started doing full
// screen stuff.
if ((default_grid.ScreenLines != NULL
- && Rows == screen_Rows
- && Columns == screen_Columns
+ && Rows == default_grid.Rows
+ && Columns == default_grid.Columns
)
|| Rows == 0
|| Columns == 0
- || (!full_screen && ScreenLines == NULL)) {
+ || (!full_screen && default_grid.ScreenLines == NULL)) {
return;
}
@@ -5940,7 +5973,7 @@ retry:
if (aucmd_win != NULL)
win_free_lsize(aucmd_win);
- alloc_grid(&default_grid, Rows, Columns, !doclear);
+ grid_alloc(&default_grid, Rows, Columns, !doclear);
StlClickDefinition *new_tab_page_click_defs = xcalloc(
(size_t)Columns, sizeof(*new_tab_page_click_defs));
@@ -5957,12 +5990,16 @@ retry:
set_screengrid(&default_grid);
tab_page_click_defs = new_tab_page_click_defs;
- tab_page_click_defs_size = Columns;
+ tab_page_click_defs_size = default_grid.Columns;
/* It's important that screen_Rows and screen_Columns reflect the actual
* size of ScreenLines[]. Set them before calling anything. */
- screen_Rows = Rows;
- screen_Columns = Columns;
+ screen_Rows = default_grid.Rows;
+ screen_Columns = default_grid.Columns;
+
+ default_grid.OffsetRow = 0;
+ default_grid.OffsetColumn = 0;
+ default_grid.handle = 1;
must_redraw = CLEAR; /* need to clear the screen later */
if (doclear)
@@ -5984,35 +6021,35 @@ retry:
}
}
-void alloc_grid(ScreenGrid *grid, int Rows, int Columns, bool copy)
+void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy)
{
int new_row, old_row;
- ScreenGrid new = { 0 };
+ ScreenGrid new = *grid;
- size_t ncells = (size_t)((Rows+1) * Columns);
+ size_t ncells = (size_t)((rows+1) * columns);
new.ScreenLines = xmalloc(ncells * sizeof(schar_T));
new.ScreenAttrs = xmalloc(ncells * sizeof(sattr_T));
- new.LineOffset = xmalloc((size_t)(Rows * sizeof(unsigned)));
- new.LineWraps = xmalloc((size_t)(Rows * sizeof(char_u)));
+ new.LineOffset = xmalloc((size_t)(rows * sizeof(unsigned)));
+ new.LineWraps = xmalloc((size_t)(rows * sizeof(char_u)));
- new.Rows = Rows;
- new.Columns = Columns;
+ new.Rows = rows;
+ new.Columns = columns;
- for (new_row = 0; new_row < Rows; new_row++) {
- new.LineOffset[new_row] = new_row * Columns;
+ for (new_row = 0; new_row < new.Rows; new_row++) {
+ new.LineOffset[new_row] = new_row * new.Columns;
new.LineWraps[new_row] = false;
if (copy) {
// If the screen is not going to be cleared, copy as much as
// possible from the old screen to the new one and clear the rest
// (used when resizing the window at the "--more--" prompt or when
// executing an external command, for the GUI).
- memset(new.ScreenLines + new_row * Columns,
- ' ', (size_t)Columns * sizeof(schar_T));
- memset(new.ScreenAttrs + new_row * Columns,
- 0, (size_t)Columns * sizeof(sattr_T));
- old_row = new_row + (grid->Rows - Rows);
+ memset(new.ScreenLines + new_row * new.Columns,
+ ' ', (size_t)new.Columns * sizeof(schar_T));
+ memset(new.ScreenAttrs + new_row * new.Columns,
+ 0, (size_t)new.Columns * sizeof(sattr_T));
+ old_row = new_row + (grid->Rows - new.Rows);
if (old_row >= 0 && grid->ScreenLines != NULL) {
- int len = MIN(grid->Columns, Columns);
+ int len = MIN(grid->Columns, new.Columns);
memmove(new.ScreenLines + new.LineOffset[new_row],
grid->ScreenLines + grid->LineOffset[old_row],
(size_t)len * sizeof(schar_T));
@@ -6041,9 +6078,6 @@ void set_screengrid(ScreenGrid *grid)
ScreenAttrs = grid->ScreenAttrs;
LineOffset = grid->LineOffset;
LineWraps = grid->LineWraps;
- grid_Rows = grid->Rows;
- grid_Columns = grid->Columns;
- current_ScreenLine = ScreenLines + grid_Rows * grid_Columns;
}
/// Clear tab_page_click_defs table
@@ -6078,10 +6112,10 @@ static void screenclear2(void)
return;
}
- // blank out ScreenLines
- for (i = 0; i < Rows; i++) {
- lineclear(LineOffset[i], (int)Columns, true);
- LineWraps[i] = false;
+ /* blank out ScreenLines */
+ for (i = 0; i < default_grid.Rows; ++i) {
+ grid_clear_line(&default_grid, LineOffset[i], (int)default_grid.Columns, true);
+ LineWraps[i] = FALSE;
}
ui_call_grid_clear(1); // clear the display
@@ -6102,27 +6136,26 @@ static void screenclear2(void)
msg_didout = false;
}
-/*
- * Clear one line in ScreenLines.
- */
-static void lineclear(unsigned off, int width, bool valid)
+/// clear a line in the grid starting at "off" until "width" characters
+/// are cleared.
+static void grid_clear_line(ScreenGrid *grid, unsigned off, int width, bool valid)
{
for (int col = 0; col < width; col++) {
- schar_from_ascii(ScreenLines[off + col], ' ');
+ schar_from_ascii(grid->ScreenLines[off + col], ' ');
}
int fill = valid ? 0 : -1;
- (void)memset(ScreenAttrs + off, fill, (size_t)width * sizeof(sattr_T));
+ (void)memset(grid->ScreenAttrs + off, fill, (size_t)width * sizeof(sattr_T));
}
/// Copy part of a Screenline for vertically split window.
-static void linecopy(int to, int from, int col, int width)
+static void linecopy(ScreenGrid *grid, int to, int from, int col, int width)
{
- unsigned off_to = LineOffset[to] + col;
- unsigned off_from = LineOffset[from] + col;
+ unsigned off_to = grid->LineOffset[to] + col;
+ unsigned off_from = grid->LineOffset[from] + col;
- memmove(ScreenLines + off_to, ScreenLines + off_from,
+ memmove(grid->ScreenLines + off_to, grid->ScreenLines + off_from,
width * sizeof(schar_T));
- memmove(ScreenAttrs + off_to, ScreenAttrs + off_from,
+ memmove(grid->ScreenAttrs + off_to, grid->ScreenAttrs + off_from,
width * sizeof(sattr_T));
}
@@ -6141,8 +6174,7 @@ void setcursor(void)
- ((utf_ptr2cells(get_cursor_pos_ptr()) == 2
&& vim_isprintc(gchar_cursor())) ? 2 : 1);
}
- ui_cursor_goto(curwin->w_winrow + curwin->w_wrow,
- curwin->w_wincol + left_offset);
+ ui_grid_cursor_goto(&curwin->w_grid, curwin->w_wrow, left_offset);
}
}
@@ -6178,15 +6210,12 @@ static int win_do_lines(win_T *wp, int row, int line_count, int del)
check_for_delay(false);
clear_cmdline = true;
int retval;
-
if (del) {
- retval = screen_del_lines(wp->w_winrow + row, line_count,
- wp->w_winrow + wp->w_height,
- wp->w_wincol, wp->w_width);
+ retval = grid_del_lines(&wp->w_grid, row, line_count,
+ wp->w_height, 0, wp->w_width);
} else {
- retval = screen_ins_lines(wp->w_winrow + row, line_count,
- wp->w_winrow + wp->w_height,
- wp->w_wincol, wp->w_width);
+ retval = grid_ins_lines(&wp->w_grid, row, line_count,
+ wp->w_height, 0, wp->w_width);
}
return retval;
}
@@ -6208,12 +6237,17 @@ static int win_do_lines(win_T *wp, int row, int line_count, int del)
/// 'row' and 'end' are relative to the start of the region.
///
/// @return FAIL for failure, OK for success.
-int screen_ins_lines(int row, int line_count, int end, int col, int width)
+int grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end,
+ int col, int width)
{
int i;
int j;
unsigned temp;
+ if (grid == NULL) {
+ grid = &default_grid;
+ }
+
if (!screen_valid(TRUE) || line_count <= 0) {
return FAIL;
}
@@ -6221,29 +6255,29 @@ int screen_ins_lines(int row, int line_count, int end, int col, int width)
// Shift LineOffset[] line_count down to reflect the inserted lines.
// Clear the inserted lines in ScreenLines[].
for (i = 0; i < line_count; i++) {
- if (width != Columns) {
+ if (width != grid->Columns) {
// need to copy part of a line
j = end - 1 - i;
while ((j -= line_count) >= row) {
- linecopy(j + line_count, j, col, width);
+ linecopy(grid, j + line_count, j, col, width);
}
j += line_count;
- lineclear(LineOffset[j] + col, width, false);
- LineWraps[j] = false;
+ grid_clear_line(grid, grid->LineOffset[j] + col, width, false);
+ grid->LineWraps[j] = false;
} else {
j = end - 1 - i;
- temp = LineOffset[j];
+ temp = grid->LineOffset[j];
while ((j -= line_count) >= row) {
- LineOffset[j + line_count] = LineOffset[j];
- LineWraps[j + line_count] = LineWraps[j];
+ grid->LineOffset[j + line_count] = grid->LineOffset[j];
+ grid->LineWraps[j + line_count] = grid->LineWraps[j];
}
- LineOffset[j + line_count] = temp;
- LineWraps[j + line_count] = false;
- lineclear(temp, (int)Columns, false);
+ grid->LineOffset[j + line_count] = temp;
+ grid->LineWraps[j + line_count] = false;
+ grid_clear_line(grid, temp, (int)grid->Columns, false);
}
}
- ui_call_grid_scroll(1, row, end, col, col+width, -line_count, 0);
+ ui_call_grid_scroll(grid->handle, row, end, col, col+width, -line_count, 0);
return OK;
}
@@ -6254,12 +6288,17 @@ int screen_ins_lines(int row, int line_count, int end, int col, int width)
/// 'row' and 'end' are relative to the start of the region.
///
/// Return OK for success, FAIL if the lines are not deleted.
-int screen_del_lines(int row, int line_count, int end, int col, int width)
+int grid_del_lines(ScreenGrid *grid, int row, int line_count, int end,
+ int col, int width)
{
int j;
int i;
unsigned temp;
+ if (grid == NULL) {
+ grid = &default_grid;
+ }
+
if (!screen_valid(TRUE) || line_count <= 0) {
return FAIL;
}
@@ -6267,30 +6306,30 @@ int screen_del_lines(int row, int line_count, int end, int col, int width)
// Now shift LineOffset[] line_count up to reflect the deleted lines.
// Clear the inserted lines in ScreenLines[].
for (i = 0; i < line_count; i++) {
- if (width != Columns) {
+ if (width != grid->Columns) {
// need to copy part of a line
j = row + i;
while ((j += line_count) <= end - 1) {
- linecopy(j - line_count, j, col, width);
+ linecopy(grid, j - line_count, j, col, width);
}
j -= line_count;
- lineclear(LineOffset[j] + col, width, false);
- LineWraps[j] = false;
+ grid_clear_line(grid, grid->LineOffset[j] + col, width, false);
+ grid->LineWraps[j] = false;
} else {
// whole width, moving the line pointers is faster
j = row + i;
- temp = LineOffset[j];
+ temp = grid->LineOffset[j];
while ((j += line_count) <= end - 1) {
- LineOffset[j - line_count] = LineOffset[j];
- LineWraps[j - line_count] = LineWraps[j];
+ grid->LineOffset[j - line_count] = grid->LineOffset[j];
+ grid->LineWraps[j - line_count] = grid->LineWraps[j];
}
- LineOffset[j - line_count] = temp;
- LineWraps[j - line_count] = false;
- lineclear(temp, (int)Columns, false);
+ grid->LineOffset[j - line_count] = temp;
+ grid->LineWraps[j - line_count] = false;
+ grid_clear_line(grid, temp, (int)grid->Columns, false);
}
}
- ui_call_grid_scroll(1, row, end, col, col+width, line_count, 0);
+ ui_call_grid_scroll(grid->handle, row, end, col, col+width, line_count, 0);
return OK;
}
@@ -6337,7 +6376,7 @@ int showmode(void)
/* if the cmdline is more than one line high, erase top lines */
need_clear = clear_cmdline;
- if (clear_cmdline && cmdline_row < Rows - 1)
+ if (clear_cmdline && cmdline_row < default_grid.Rows - 1)
msg_clr_cmdline(); /* will reset clear_cmdline */
/* Position on the last line in the window, column 0 */
@@ -6356,7 +6395,7 @@ int showmode(void)
if (edit_submode != NULL && !shortmess(SHM_COMPLETIONMENU)) {
/* These messages can get long, avoid a wrap in a narrow
* window. Prefer showing edit_submode_extra. */
- length = (Rows - msg_row) * Columns - 3;
+ length = (default_grid.Rows - msg_row) * default_grid.Columns - 3;
if (edit_submode_extra != NULL)
length -= vim_strsize(edit_submode_extra);
if (length > 0) {
@@ -6479,7 +6518,7 @@ int showmode(void)
static void msg_pos_mode(void)
{
msg_col = 0;
- msg_row = Rows - 1;
+ msg_row = default_grid.Rows - 1;
}
/// Delete mode message. Used when ESC is typed which is expected to end
@@ -6538,7 +6577,7 @@ static void draw_tabline(void)
int use_sep_chars = (t_colors < 8
);
- if (ScreenLines == NULL) {
+ if (default_grid.ScreenLines == NULL) {
return;
}
redraw_tabline = false;
@@ -6553,7 +6592,7 @@ static void draw_tabline(void)
// Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
- assert(Columns == tab_page_click_defs_size);
+ assert(default_grid.Columns == tab_page_click_defs_size);
clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
/* Use the 'tabline' option if it's set. */
@@ -6575,7 +6614,7 @@ static void draw_tabline(void)
}
if (tabcount > 0) {
- tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
+ tabwidth = (default_grid.Columns - 1 + tabcount / 2) / tabcount;
}
if (tabwidth < 6) {
@@ -6586,7 +6625,7 @@ static void draw_tabline(void)
tabcount = 0;
FOR_ALL_TABS(tp) {
- if (col >= Columns - 4) {
+ if (col >= default_grid.Columns - 4) {
break;
}
@@ -6605,14 +6644,14 @@ static void draw_tabline(void)
attr = win_hl_attr(cwp, HLF_TPS);
}
if (use_sep_chars && col > 0) {
- screen_putchar('|', 0, col++, attr);
+ grid_putchar(&default_grid, '|', 0, col++, attr);
}
if (tp->tp_topframe != topframe) {
attr = win_hl_attr(cwp, HLF_TP);
}
- screen_putchar(' ', 0, col++, attr);
+ grid_putchar(&default_grid, ' ', 0, col++, attr);
modified = false;
@@ -6627,15 +6666,17 @@ static void draw_tabline(void)
if (wincount > 1) {
vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount);
len = (int)STRLEN(NameBuff);
- if (col + len >= Columns - 3)
+ if (col + len >= default_grid.Columns - 3) {
break;
- screen_puts_len(NameBuff, len, 0, col,
+ }
+ grid_puts_len(&default_grid, NameBuff, len, 0, col,
hl_combine_attr(attr, win_hl_attr(cwp, HLF_T)));
col += len;
}
- if (modified)
- screen_puts_len((char_u *)"+", 1, 0, col++, attr);
- screen_putchar(' ', 0, col++, attr);
+ if (modified) {
+ grid_puts_len(&default_grid, (char_u *)"+", 1, 0, col++, attr);
+ }
+ grid_putchar(&default_grid, ' ', 0, col++, attr);
}
room = scol - col + tabwidth - 1;
@@ -6654,13 +6695,13 @@ static void draw_tabline(void)
p += len - room;
len = room;
}
- if (len > Columns - col - 1)
- len = Columns - col - 1;
+ if (len > default_grid.Columns - col - 1)
+ len = default_grid.Columns - col - 1;
- screen_puts_len(p, (int)STRLEN(p), 0, col, attr);
+ grid_puts_len(&default_grid, p, (int)STRLEN(p), 0, col, attr);
col += len;
}
- screen_putchar(' ', 0, col++, attr);
+ grid_putchar(&default_grid, ' ', 0, col++, attr);
// Store the tab page number in tab_page_click_defs[], so that
// jump_to_mouse() knows where each one is.
@@ -6678,12 +6719,12 @@ static void draw_tabline(void)
c = '_';
else
c = ' ';
- screen_fill(0, 1, col, (int)Columns, c, c, attr_fill);
+ grid_fill(&default_grid, 0, 1, col, (int)default_grid.Columns, c, c, attr_fill);
/* Put an "X" for closing the current tab if there are several. */
if (first_tabpage->tp_next != NULL) {
- screen_putchar('X', 0, (int)Columns - 1, attr_nosel);
- tab_page_click_defs[Columns - 1] = (StlClickDefinition) {
+ grid_putchar(&default_grid, 'X', 0, (int)default_grid.Columns - 1, attr_nosel);
+ tab_page_click_defs[default_grid.Columns - 1] = (StlClickDefinition) {
.type = kStlClickTabClose,
.tabnr = 999,
.func = NULL,
@@ -6879,10 +6920,10 @@ static void win_redr_ruler(win_T *wp, int always)
off = wp->w_wincol;
width = wp->w_width;
} else {
- row = Rows - 1;
+ row = default_grid.Rows - 1;
fillchar = ' ';
attr = 0;
- width = Columns;
+ width = default_grid.Columns;
off = 0;
}
@@ -6919,7 +6960,7 @@ static void win_redr_ruler(win_T *wp, int always)
int o = i + vim_strsize(buffer + i + 1);
if (wp->w_status_height == 0) /* can't use last char of screen */
++o;
- int this_ru_col = ru_col - (Columns - width);
+ int this_ru_col = ru_col - (default_grid.Columns - width);
if (this_ru_col < 0)
this_ru_col = 0;
/* Never use more than half the window/screen width, leave the other
@@ -6944,9 +6985,9 @@ static void win_redr_ruler(win_T *wp, int always)
}
}
- screen_puts(buffer, row, this_ru_col + off, attr);
+ grid_puts(&default_grid, buffer, row, this_ru_col + off, attr);
i = redraw_cmdline;
- screen_fill(row, row + 1,
+ grid_fill(&default_grid, row, row + 1,
this_ru_col + off + (int)STRLEN(buffer),
off + width,
fillchar, fillchar, attr);
@@ -7032,6 +7073,8 @@ void screen_resize(int width, int height)
width = Columns;
ui_resize(width, height);
+ send_grid_resize = true;
+
/* The window layout used to be adjusted here, but it now happens in
* screenalloc() (also invoked from screenclear()). That is because the
* "busy" check above may skip this, but not screenalloc(). */
diff --git a/src/nvim/types.h b/src/nvim/types.h
index 84634b1cb7..aa83bc04bf 100644
--- a/src/nvim/types.h
+++ b/src/nvim/types.h
@@ -23,14 +23,24 @@ typedef char_u schar_T[(MAX_MCO+1) * 4 + 1];
typedef int16_t sattr_T;
// TODO(bfredl): find me a good home
+typedef int GridHandle;
typedef struct {
+ GridHandle handle;
+
schar_T *ScreenLines;
sattr_T *ScreenAttrs;
unsigned *LineOffset;
char_u *LineWraps;
+ // the size of the allocated grid
int Rows;
int Columns;
+
+ // offsets for the grid relative to the screen
+ int OffsetRow;
+ int OffsetColumn;
+
+ int was_resized;
} ScreenGrid;
#endif // NVIM_TYPES_H
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 0c69e94e5d..a454afad24 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -57,6 +57,7 @@ static int busy = 0;
static int mode_idx = SHAPE_IDX_N;
static bool pending_mode_info_update = false;
static bool pending_mode_update = false;
+static GridHandle cursor_grid_handle = 1;
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
# define UI_LOG(funname, ...)
@@ -315,12 +316,18 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
}
}
-void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr,
- bool wrap)
+void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
+ int clearattr, bool wrap)
{
- size_t off = LineOffset[row]+(size_t)startcol;
- UI_CALL(raw_line, 1, row, startcol, endcol, clearcol, clearattr, wrap,
- (const schar_T *)ScreenLines+off, (const sattr_T *)ScreenAttrs+off);
+ size_t off = grid->LineOffset[row] + (size_t)startcol;
+ int row_off = ui_is_external(kUIMultigrid) ? 0 : grid->OffsetRow;
+ int col_off = ui_is_external(kUIMultigrid) ? 0 : grid->OffsetColumn;
+
+ UI_CALL(raw_line, grid->handle, row_off + row, col_off + startcol,
+ col_off + endcol, col_off + clearcol, clearattr, wrap,
+ (const schar_T *)grid->ScreenLines + off,
+ (const sattr_T *)grid->ScreenAttrs + off);
+
if (p_wd) { // 'writedelay': flush & delay each time.
int old_row = row, old_col = col;
// If'writedelay is active, we set the cursor to highlight what was drawn
@@ -334,11 +341,20 @@ void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr,
void ui_cursor_goto(int new_row, int new_col)
{
- if (new_row == row && new_col == col) {
+ ui_grid_cursor_goto(&default_grid, new_row, new_col);
+}
+
+void ui_grid_cursor_goto(ScreenGrid *grid, int new_row, int new_col)
+{
+ int off_row = (ui_is_external(kUIMultigrid) ? 0 : grid->OffsetRow);
+ int off_col = (ui_is_external(kUIMultigrid) ? 0 : grid->OffsetColumn);
+
+ if (new_row + off_row == row && new_col + off_col == col) {
return;
}
- row = new_row;
- col = new_col;
+ row = new_row + off_row;
+ col = new_col + off_col;
+ cursor_grid_handle = grid->handle;
pending_cursor_update = true;
}
@@ -361,7 +377,7 @@ void ui_flush(void)
{
cmdline_ui_flush();
if (pending_cursor_update) {
- ui_call_grid_cursor_goto(1, row, col);
+ ui_call_grid_cursor_goto(cursor_grid_handle, row, col);
pending_cursor_update = false;
}
if (pending_mode_info_update) {
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index d89ad60ce7..16237214cb 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -16,6 +16,7 @@ typedef enum {
kUIWildmenu,
#define kUIGlobalCount (kUIWildmenu+1)
kUILinegrid,
+ kUIMultigrid,
kUIHlState,
kUIExtCount,
} UIExtension;
@@ -26,6 +27,7 @@ EXTERN const char *ui_ext_names[] INIT(= {
"ext_tabline",
"ext_wildmenu",
"ext_linegrid",
+ "ext_multigrid",
"ext_hlstate",
});
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 11dc813997..9b9053d7a9 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -2271,8 +2271,8 @@ static void do_intro_line(long row, char_u *mesg, int attr)
}
}
assert(row <= INT_MAX && col <= INT_MAX);
- screen_puts_len(p, l, (int)row, (int)col,
- *p == '<' ? HL_ATTR(HLF_8) : attr);
+ grid_puts_len(&default_grid, p, l, (int)row, (int)col,
+ *p == '<' ? HL_ATTR(HLF_8) : attr);
col += clen;
}
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 8be79f0cff..4d2b238b7a 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -3958,6 +3958,8 @@ win_free (
xfree(wp->w_p_cc_cols);
+ win_free_grid(wp, false);
+
if (wp != aucmd_win)
win_remove(wp, tp);
if (autocmd_busy) {
@@ -3970,6 +3972,20 @@ win_free (
unblock_autocmds();
}
+void win_free_grid(win_T *wp, bool reinit)
+{
+ if (wp->w_grid.handle != 0 && ui_is_external(kUIMultigrid)) {
+ ui_call_grid_destroy(wp->w_grid.handle);
+ wp->w_grid.handle = 0;
+ }
+ free_screengrid(&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
+ memset(&wp->w_grid, 0, sizeof(wp->w_grid));
+ }
+}
+
/*
* Append window "wp" in the window list after window "after".
*/
@@ -4247,6 +4263,7 @@ void win_setheight_win(int height, win_T *win)
}
frame_setheight(win->w_frame, height + win->w_status_height);
+ win_grid_alloc(win, false);
/* recompute the window positions */
row = win_comp_pos();
@@ -4256,7 +4273,7 @@ void win_setheight_win(int height, win_T *win)
* line, clear it.
*/
if (full_screen && msg_scrolled == 0 && row < cmdline_row)
- screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
+ grid_fill(&default_grid, row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
cmdline_row = row;
msg_row = row;
msg_col = 0;
@@ -4443,6 +4460,7 @@ void win_setwidth_win(int width, win_T *wp)
}
frame_setwidth(wp->w_frame, width + wp->w_vsep_width);
+ win_grid_alloc(wp, false);
/* recompute the window positions */
(void)win_comp_pos();
@@ -4706,7 +4724,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
fr = fr->fr_next;
}
row = win_comp_pos();
- screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
+ grid_fill(&default_grid, row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
cmdline_row = row;
p_ch = Rows - cmdline_row;
if (p_ch < 1)
@@ -5054,7 +5072,7 @@ void command_height(void)
/* clear the lines added to cmdline */
if (full_screen)
- screen_fill(cmdline_row, (int)Rows, 0,
+ grid_fill(&default_grid, cmdline_row, (int)Rows, 0,
(int)Columns, ' ', ' ', 0);
msg_row = cmdline_row;
redraw_cmdline = TRUE;