diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/ui_events.in.h | 2 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/edit.c | 27 | ||||
-rw-r--r-- | src/nvim/globals.h | 3 | ||||
-rw-r--r-- | src/nvim/hardcopy.c | 4 | ||||
-rw-r--r-- | src/nvim/message.c | 50 | ||||
-rw-r--r-- | src/nvim/normal.c | 9 | ||||
-rw-r--r-- | src/nvim/popupmnu.c | 27 | ||||
-rw-r--r-- | src/nvim/screen.c | 807 | ||||
-rw-r--r-- | src/nvim/types.h | 10 | ||||
-rw-r--r-- | src/nvim/ui.c | 34 | ||||
-rw-r--r-- | src/nvim/ui.h | 2 | ||||
-rw-r--r-- | src/nvim/version.c | 4 | ||||
-rw-r--r-- | src/nvim/window.c | 24 |
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; |