aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/private/defs.h3
-rw-r--r--src/nvim/api/ui.c24
-rw-r--r--src/nvim/api/ui_events.in.h15
-rw-r--r--src/nvim/api/vim.c41
-rw-r--r--src/nvim/api/window.c2
-rw-r--r--src/nvim/assert.h30
-rw-r--r--src/nvim/buffer.c20
-rw-r--r--src/nvim/buffer_defs.h5
-rw-r--r--src/nvim/charset.c25
-rw-r--r--src/nvim/cursor.c25
-rw-r--r--src/nvim/cursor_shape.c10
-rw-r--r--src/nvim/diff.c15
-rw-r--r--src/nvim/edit.c113
-rw-r--r--src/nvim/eval.c97
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/encode.c6
-rw-r--r--src/nvim/ex_cmds.c20
-rw-r--r--src/nvim/ex_cmds.lua24
-rw-r--r--src/nvim/ex_cmds2.c128
-rw-r--r--src/nvim/ex_docmd.c16
-rw-r--r--src/nvim/ex_getln.c3
-rw-r--r--src/nvim/fileio.c7
-rw-r--r--src/nvim/getchar.c8
-rw-r--r--src/nvim/globals.h55
-rw-r--r--src/nvim/grid_defs.h59
-rw-r--r--src/nvim/hardcopy.c5
-rw-r--r--src/nvim/highlight.c10
-rw-r--r--src/nvim/indent.c26
-rw-r--r--src/nvim/main.c3
-rw-r--r--src/nvim/mbyte.c53
-rw-r--r--src/nvim/mbyte.h7
-rw-r--r--src/nvim/memory.c4
-rw-r--r--src/nvim/message.c75
-rw-r--r--src/nvim/misc1.c15
-rw-r--r--src/nvim/mouse.c6
-rw-r--r--src/nvim/move.c242
-rw-r--r--src/nvim/msgpack_rpc/channel.c4
-rw-r--r--src/nvim/normal.c123
-rw-r--r--src/nvim/ops.c34
-rw-r--r--src/nvim/option.c4
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/popupmnu.c62
-rw-r--r--src/nvim/quickfix.c8
-rw-r--r--src/nvim/regexp.c2
-rw-r--r--src/nvim/screen.c1619
-rw-r--r--src/nvim/screen.h13
-rw-r--r--src/nvim/search.c7
-rw-r--r--src/nvim/shada.c133
-rw-r--r--src/nvim/spell.c16
-rw-r--r--src/nvim/spellfile.c4
-rw-r--r--src/nvim/state.c4
-rw-r--r--src/nvim/syntax.c6
-rw-r--r--src/nvim/terminal.c14
-rw-r--r--src/nvim/testdir/pyxfile/py2_magic.py4
-rw-r--r--src/nvim/testdir/pyxfile/py2_shebang.py4
-rw-r--r--src/nvim/testdir/pyxfile/py3_magic.py4
-rw-r--r--src/nvim/testdir/pyxfile/py3_shebang.py4
-rw-r--r--src/nvim/testdir/pyxfile/pyx.py2
-rw-r--r--src/nvim/testdir/runtest.vim6
-rw-r--r--src/nvim/testdir/test_arglist.vim9
-rw-r--r--src/nvim/testdir/test_fold.vim20
-rw-r--r--src/nvim/testdir/test_mapping.vim54
-rw-r--r--src/nvim/testdir/test_pyx2.vim74
-rw-r--r--src/nvim/testdir/test_pyx3.vim74
-rw-r--r--src/nvim/testdir/test_visual.vim41
-rw-r--r--src/nvim/tui/input.c4
-rw-r--r--src/nvim/tui/terminfo.c3
-rw-r--r--src/nvim/tui/terminfo_defs.h8
-rw-r--r--src/nvim/tui/tui.c34
-rw-r--r--src/nvim/types.h3
-rw-r--r--src/nvim/ugrid.h4
-rw-r--r--src/nvim/ui.c97
-rw-r--r--src/nvim/ui.h2
-rw-r--r--src/nvim/version.c4
-rw-r--r--src/nvim/viml/parser/expressions.c46
-rw-r--r--src/nvim/window.c104
77 files changed, 2417 insertions, 1448 deletions
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index 390b7e8363..feca140547 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -6,6 +6,7 @@
#include <string.h>
#include "nvim/func_attr.h"
+#include "nvim/types.h"
#define ARRAY_DICT_INIT {.size = 0, .capacity = 0, .items = NULL}
#define STRING_INIT {.data = NULL, .size = 0}
@@ -20,8 +21,6 @@
# define DictionaryOf(...) Dictionary
#endif
-typedef int handle_T;
-
// Basic types
typedef enum {
kErrorTypeNone = -1,
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 01f8c9f71c..7ba5251c60 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -126,7 +126,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
}
}
- if (ui->ui_ext[kUIHlState]) {
+ if (ui->ui_ext[kUIHlState] || ui->ui_ext[kUIMultigrid]) {
ui->ui_ext[kUILinegrid] = true;
}
@@ -245,6 +245,28 @@ static void ui_set_option(UI *ui, bool init, String name, Object value,
name.data);
}
+/// Tell nvim to resize a grid. Nvim sends grid_resize event with the
+/// requested grid size is within size limits and with maximum allowed size
+/// otherwise.
+///
+/// On invalid grid handle, fails with error.
+///
+/// @param grid The handle of the grid to be changed.
+/// @param width The new requested width.
+/// @param height The new requested height.
+void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width,
+ Integer height, Error *error)
+ FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY
+{
+ if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ api_set_error(error, kErrorTypeException,
+ "UI not attached to channel: %" PRId64, channel_id);
+ return;
+ }
+
+ ui_grid_resize((handle_T)grid, (int)width, (int)height, error);
+}
+
/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().
static void push_call(UI *ui, const char *name, Array args)
{
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 10331fd5c2..59a7780651 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -81,8 +81,21 @@ 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(6) FUNC_API_REMOTE_ONLY;
-void popupmenu_show(Array items, Integer selected, Integer row, Integer col)
+void win_pos(Integer grid, Integer win, Integer startrow,
+ Integer startcol, Integer width, Integer height)
+ FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
+void win_hide(Integer grid)
+ FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
+void win_scroll_over_start(void)
+ FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
+void win_scroll_over_reset(void)
+ FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
+
+void popupmenu_show(Array items, Integer selected,
+ Integer row, Integer col, Integer grid)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void popupmenu_hide(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index ecfff1ea8f..24e76ecf88 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -28,6 +28,7 @@
#include "nvim/screen.h"
#include "nvim/memory.h"
#include "nvim/message.h"
+#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/option.h"
@@ -75,7 +76,6 @@ void nvim_command(String command, Error *err)
{
try_start();
do_cmdline_cmd(command.data);
- update_screen(VALID);
try_end(err);
}
@@ -1916,17 +1916,46 @@ Object nvim_get_proc(Integer pid, Error *err)
return rvobj;
}
+/// Selects an item in the completion popupmenu
+///
+/// When insert completion is not active, this API call is silently ignored.
+/// It is mostly useful for an external UI using |ui-popupmenu| for instance
+/// to control the popupmenu with the mouse. But it can also be used in an
+/// insert mode mapping, use <cmd> mapping |:map-cmd| to ensure the mapping
+/// doesn't end completion mode.
+///
+/// @param item Index of the item to select, starting with zero. Pass in "-1"
+/// to select no item (restore original text).
+/// @param insert Whether the selection should be inserted in the buffer.
+/// @param finish If true, completion will be finished with this item, and the
+/// popupmenu dissmissed. Implies `insert`.
+void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish,
+ Dictionary opts, Error *err)
+ FUNC_API_SINCE(6)
+{
+ if (opts.size > 0) {
+ api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
+ return;
+ }
+
+ if (finish) {
+ insert = true;
+ }
+
+ pum_ext_select_item((int)item, insert, finish);
+}
+
/// NB: if your UI doesn't use hlstate, this will not return hlstate first time
Array nvim__inspect_cell(Integer row, Integer col, Error *err)
{
Array ret = ARRAY_DICT_INIT;
- if (row < 0 || row >= screen_Rows
- || col < 0 || col >= screen_Columns) {
+ if (row < 0 || row >= default_grid.Rows
+ || col < 0 || col >= default_grid.Columns) {
return ret;
}
- size_t off = LineOffset[(size_t)row] + (size_t)col;
- ADD(ret, STRING_OBJ(cstr_to_string((char *)ScreenLines[off])));
- int attr = ScreenAttrs[off];
+ size_t off = default_grid.line_offset[(size_t)row] + (size_t)col;
+ ADD(ret, STRING_OBJ(cstr_to_string((char *)default_grid.chars[off])));
+ int attr = default_grid.attrs[off];
ADD(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, err)));
// will not work first time
if (!highlight_use_hlstate()) {
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index cf1d1f5e45..33857f95b7 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -135,7 +135,7 @@ void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
// make sure cursor is in visible range even if win != curwin
update_topline_win(win);
- update_screen(VALID);
+ redraw_win_later(win, VALID);
}
/// Gets the window height
diff --git a/src/nvim/assert.h b/src/nvim/assert.h
index 761636305e..29195a49dc 100644
--- a/src/nvim/assert.h
+++ b/src/nvim/assert.h
@@ -121,4 +121,34 @@
((enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }) 0)
#endif
+/// @def STRICT_ADD
+/// @brief Adds (a + b) and stores result in `c`. Aborts on overflow.
+///
+/// Requires GCC 5+ and Clang 3.8+
+/// https://clang.llvm.org/docs/LanguageExtensions.html
+/// https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
+///
+/// Alternative for compilers without __builtin_xx_overflow ?
+/// https://stackoverflow.com/a/44830670/152142
+///
+/// @param MAX Maximum value of the narrowest type of operand.
+/// Not used if compiler supports __builtin_add_overflow.
+#if HAVE_BUILTIN_ADD_OVERFLOW
+# define STRICT_ADD(a, b, c, t) \
+ do { if (__builtin_add_overflow(a, b, c)) { abort(); } } while (0)
+#else
+# define STRICT_ADD(a, b, c, t) \
+ do { *(c) = (t)(a + b); } while (0)
+#endif
+
+/// @def STRICT_SUB
+/// @brief Subtracts (a - b) and stores result in `c`. Aborts on overflow.
+#if HAVE_BUILTIN_ADD_OVERFLOW
+# define STRICT_SUB(a, b, c, t) \
+ do { if (__builtin_sub_overflow(a, b, c)) { abort(); } } while (0)
+#else
+# define STRICT_SUB(a, b, c, t) \
+ do { *(c) = (t)(a - b); } while (0)
+#endif
+
#endif // NVIM_ASSERT_H
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 8b107041b1..22c8a2bf05 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -5347,8 +5347,7 @@ int bufhl_add_hl(buf_T *buf,
hlentry->stop = col_end;
if (0 < lnum && lnum <= buf->b_ml.ml_line_count) {
- changed_lines_buf(buf, lnum, lnum+1, 0);
- redraw_buf_later(buf, VALID);
+ redraw_buf_line_later(buf, lnum);
}
return src_id;
}
@@ -5414,8 +5413,7 @@ int bufhl_add_virt_text(buf_T *buf,
}
if (0 < lnum && lnum <= buf->b_ml.ml_line_count) {
- changed_lines_buf(buf, lnum, lnum+1, 0);
- redraw_buf_later(buf, VALID);
+ redraw_buf_line_later(buf, lnum);
}
return src_id;
}
@@ -5440,8 +5438,6 @@ void bufhl_clear_line_range(buf_T *buf,
linenr_T line_start,
linenr_T line_end)
{
- linenr_T first_changed = MAXLNUM, last_changed = -1;
-
kbitr_t(bufhl) itr;
BufhlLine *l, t = BUFHLLINE_INIT(line_start);
if (!kb_itr_get(bufhl, &buf->b_bufhl_info, &t, &itr)) {
@@ -5456,12 +5452,7 @@ void bufhl_clear_line_range(buf_T *buf,
if (line_start <= line) {
BufhlLineStatus status = bufhl_clear_line(l, src_id, line);
if (status != kBLSUnchanged) {
- if (line > last_changed) {
- last_changed = line;
- }
- if (line < first_changed) {
- first_changed = line;
- }
+ redraw_buf_line_later(buf, line);
}
if (status == kBLSDeleted) {
kb_del_itr(bufhl, &buf->b_bufhl_info, &itr);
@@ -5469,11 +5460,6 @@ void bufhl_clear_line_range(buf_T *buf,
}
}
}
-
- if (last_changed != -1) {
- changed_lines_buf(buf, first_changed, last_changed+1, 0);
- redraw_buf_later(buf, VALID);
- }
}
/// Clear bufhl highlights from a given source group and given line
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index d270714611..05688790c2 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -18,6 +18,8 @@ typedef struct {
// for garray_T
#include "nvim/garray.h"
+// for ScreenGrid
+#include "nvim/grid_defs.h"
// for HLF_COUNT
#include "nvim/highlight_defs.h"
// for pos_T, lpos_T and linenr_T
@@ -1183,6 +1185,9 @@ 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
+ bool w_pos_changed; // true if window position changed
+
/*
* 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/charset.c b/src/nvim/charset.c
index 4e8bb3b0d7..c220c4e347 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1022,12 +1022,12 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
&& vim_isbreak(c)
&& !vim_isbreak((int)s[1])
&& wp->w_p_wrap
- && (wp->w_width != 0)) {
+ && (wp->w_grid.Columns != 0)) {
// Count all characters from first non-blank after a blank up to next
// non-blank after a blank.
numberextra = win_col_off(wp);
col2 = col;
- colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
+ colmax = (colnr_T)(wp->w_grid.Columns - numberextra - col_adj);
if (col >= colmax) {
colmax += col_adj;
@@ -1076,9 +1076,9 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
numberextra = numberwidth;
col += numberextra + mb_added;
- if (col >= (colnr_T)wp->w_width) {
- col -= wp->w_width;
- numberextra = wp->w_width - (numberextra - win_col_off2(wp));
+ if (col >= (colnr_T)wp->w_grid.Columns) {
+ col -= wp->w_grid.Columns;
+ numberextra = wp->w_grid.Columns - (numberextra - win_col_off2(wp));
if (col >= numberextra && numberextra > 0) {
col %= numberextra;
}
@@ -1097,16 +1097,17 @@ int win_lbr_chartabsize(win_T *wp, char_u *line, char_u *s, colnr_T col, int *he
numberwidth -= win_col_off2(wp);
}
- if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_width)) {
+ if (col == 0 || (col + size + sbrlen > (colnr_T)wp->w_grid.Columns)) {
added = 0;
if (*p_sbr != NUL) {
- if (size + sbrlen + numberwidth > (colnr_T)wp->w_width) {
+ if (size + sbrlen + numberwidth > (colnr_T)wp->w_grid.Columns) {
// Calculate effective window width.
- int width = (colnr_T)wp->w_width - sbrlen - numberwidth;
- int prev_width = col ? ((colnr_T)wp->w_width - (sbrlen + col)) : 0;
+ int width = (colnr_T)wp->w_grid.Columns - sbrlen - numberwidth;
+ int prev_width = col ? ((colnr_T)wp->w_grid.Columns - (sbrlen + col))
+ : 0;
if (width == 0) {
- width = (colnr_T)wp->w_width;
+ width = (colnr_T)wp->w_grid.Columns;
}
added += ((size - prev_width) / width) * vim_strsize(p_sbr);
if ((size - prev_width) % width) {
@@ -1175,11 +1176,11 @@ bool in_win_border(win_T *wp, colnr_T vcol)
int width1; // width of first line (after line number)
int width2; // width of further lines
- if (wp->w_width == 0) {
+ if (wp->w_grid.Columns == 0) {
// there is no border
return false;
}
- width1 = wp->w_width - win_col_off(wp);
+ width1 = wp->w_grid.Columns - win_col_off(wp);
if ((int)vcol < width1 - 1) {
return false;
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 0fda941a51..409eb653a0 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include <inttypes.h>
+#include "nvim/assert.h"
#include "nvim/cursor.h"
#include "nvim/charset.h"
#include "nvim/fold.h"
@@ -120,11 +121,11 @@ static int coladvance2(
--curwin->w_curswant;
}
} else {
- int width = curwin->w_width - win_col_off(curwin);
+ int width = curwin->w_grid.Columns - win_col_off(curwin);
if (finetune
&& curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
&& wcol >= (colnr_T)width) {
csize = linetabsize(line);
if (csize > 0)
@@ -170,7 +171,9 @@ static int coladvance2(
if (line[idx] == NUL) {
/* Append spaces */
int correct = wcol - col;
- char_u *newline = xmallocz((size_t)(idx + correct));
+ size_t newline_size;
+ STRICT_ADD(idx, correct, &newline_size, size_t);
+ char_u *newline = xmallocz(newline_size);
memcpy(newline, line, (size_t)idx);
memset(newline + idx, ' ', (size_t)correct);
@@ -187,14 +190,17 @@ static int coladvance2(
if (-correct > csize)
return FAIL;
- newline = xmallocz((size_t)(linelen - 1 + csize));
+ size_t n;
+ STRICT_ADD(linelen - 1, csize, &n, size_t);
+ newline = xmallocz(n);
// Copy first idx chars
memcpy(newline, line, (size_t)idx);
// Replace idx'th char with csize spaces
memset(newline + idx, ' ', (size_t)csize);
// Copy the rest of the line
- memcpy(newline + idx + csize, line + idx + 1,
- (size_t)(linelen - idx - 1));
+ STRICT_SUB(linelen, idx, &n, size_t);
+ STRICT_SUB(n, 1, &n, size_t);
+ memcpy(newline + idx + csize, line + idx + 1, n);
ml_replace(pos->lnum, newline, false);
changed_bytes(pos->lnum, idx);
@@ -223,9 +229,10 @@ static int coladvance2(
} else {
int b = (int)wcol - (int)col;
- /* The difference between wcol and col is used to set coladd. */
- if (b > 0 && b < (MAXCOL - 2 * curwin->w_width))
+ // The difference between wcol and col is used to set coladd.
+ if (b > 0 && b < (MAXCOL - 2 * curwin->w_grid.Columns)) {
pos->coladd = b;
+ }
col += b;
}
@@ -436,7 +443,7 @@ bool leftcol_changed(void)
bool retval = false;
changed_cline_bef_curs();
- lastcol = curwin->w_leftcol + curwin->w_width - curwin_col_off() - 1;
+ lastcol = curwin->w_leftcol + curwin->w_grid.Columns - curwin_col_off() - 1;
validate_virtcol();
/*
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index cf79005a37..5551576c6d 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -254,6 +254,16 @@ char_u *parse_shape_opt(int what)
return NULL;
}
+/// Returns true if the cursor is non-blinking "block" shape during
+/// visual selection.
+///
+/// @param exclusive If 'selection' option is "exclusive".
+bool cursor_is_block_during_visual(bool exclusive)
+{
+ int mode_idx = exclusive ? SHAPE_IDX_VE : SHAPE_IDX_V;
+ return (SHAPE_BLOCK == shape_table[mode_idx].shape
+ && 0 == shape_table[mode_idx].blinkon);
+}
/// Map cursor mode from string to integer
///
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 2e0b198c13..866161e5cf 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -695,7 +695,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
len += (long)STRLEN(ml_get_buf(buf, lnum, false)) + 1;
}
- ptr = xmalloc(len);
+ ptr = try_malloc(len);
if (ptr == NULL) {
// Allocating memory failed. This can happen, because we try to read
// the whole buffer text into memory. Set the failed flag, the diff
@@ -1088,9 +1088,6 @@ static int diff_file(diffio_T *dio)
const size_t len = (strlen(tmp_orig) + strlen(tmp_new) + strlen(tmp_diff)
+ STRLEN(p_srr) + 27);
char *const cmd = xmalloc(len);
- if (cmd == NULL) {
- return FAIL;
- }
// We don't want $DIFF_OPTIONS to get in the way.
if (os_getenv("DIFF_OPTIONS")) {
@@ -1545,9 +1542,9 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
} else if ((STRNCMP(line, "@@ ", 3) == 0)) {
diffstyle = DIFF_UNIFIED;
} else if ((STRNCMP(line, "--- ", 4) == 0)
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0)
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
&& (STRNCMP(line, "+++ ", 4) == 0)
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0)
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
&& (STRNCMP(line, "@@ ", 3) == 0)) {
diffstyle = DIFF_UNIFIED;
} else {
@@ -1565,7 +1562,8 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
&lnum_new, &count_new) == FAIL) {
continue;
}
- } else if (diffstyle == DIFF_UNIFIED) {
+ } else {
+ assert(diffstyle == DIFF_UNIFIED);
if (STRNCMP(line, "@@ ", 3) != 0) {
continue; // not the start of a diff block
}
@@ -1573,9 +1571,6 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
&lnum_new, &count_new) == FAIL) {
continue;
}
- } else {
- EMSG(_("E959: Invalid diff format."));
- break;
}
// Go over blocks before the change, for which orig and new are equal.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index c04190eaba..50c28dbaad 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -184,6 +184,16 @@ static expand_T compl_xp;
static int compl_opt_refresh_always = FALSE;
+static int pum_selected_item = -1;
+
+/// state for pum_ext_select_item.
+struct {
+ bool active;
+ int item;
+ bool insert;
+ bool finish;
+} pum_want;
+
typedef struct insert_state {
VimState state;
cmdarg_T *ca;
@@ -560,7 +570,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) {
@@ -976,10 +986,25 @@ static int insert_handle_key(InsertState *s)
case K_EVENT: // some event
multiqueue_process_events(main_loop.events);
- break;
+ goto check_pum;
case K_COMMAND: // some command
do_cmdline(NULL, getcmdkeycmd, NULL, 0);
+
+check_pum:
+ // TODO(bfredl): Not entirely sure this indirection is necessary
+ // but doing like this ensures using nvim_select_popupmenu_item is
+ // equivalent to selecting the item with a typed key.
+ if (pum_want.active) {
+ if (pum_visible()) {
+ insert_do_complete(s);
+ if (pum_want.finish) {
+ // accept the item and stop completion
+ ins_compl_prep(Ctrl_Y);
+ }
+ }
+ pum_want.active = false;
+ }
break;
case K_HOME: // <Home>
@@ -1494,40 +1519,41 @@ void edit_putchar(int c, int highlight)
{
int attr;
- if (ScreenLines != NULL) {
- update_topline(); /* just in case w_topline isn't valid */
+ if (curwin->w_grid.chars != NULL || default_grid.chars != NULL) {
+ update_topline(); // just in case w_topline isn't valid
validate_cursor();
if (highlight) {
attr = HL_ATTR(HLF_8);
} 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);
+ int fix_col = grid_fix_col(&curwin->w_grid, 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;
}
}
} else {
pc_col += curwin->w_wcol;
- if (mb_lefthalve(pc_row, pc_col))
+ if (grid_lefthalve(&curwin->w_grid, pc_row, pc_col)) {
pc_status = PC_STATUS_LEFT;
+ }
}
/* 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);
}
}
@@ -1541,9 +1567,10 @@ void edit_unputchar(void)
curwin->w_wcol++;
}
if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) {
- redrawWinline(curwin, curwin->w_cursor.lnum, false);
+ redrawWinline(curwin, curwin->w_cursor.lnum);
} 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,8 +1593,8 @@ 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) {
- edit_putchar('$', FALSE);
+ if (curwin->w_wcol < curwin->w_grid.Columns) {
+ edit_putchar('$', false);
dollar_vcol = curwin->w_virtcol;
}
curwin->w_cursor.col = save_col;
@@ -1581,7 +1608,7 @@ static void undisplay_dollar(void)
{
if (dollar_vcol >= 0) {
dollar_vcol = -1;
- redrawWinline(curwin, curwin->w_cursor.lnum, false);
+ redrawWinline(curwin, curwin->w_cursor.lnum);
}
}
@@ -2664,6 +2691,7 @@ void ins_compl_show_pum(void)
// Use the cursor to get all wrapping and other settings right.
col = curwin->w_cursor.col;
curwin->w_cursor.col = compl_col;
+ pum_selected_item = cur;
pum_display(compl_match_array, compl_match_arraysize, cur, array_changed);
curwin->w_cursor.col = col;
}
@@ -3518,6 +3546,7 @@ expand_by_function (
win_T *curwin_save;
buf_T *curbuf_save;
typval_T rettv;
+ const int save_State = State;
funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
if (*funcname == NUL)
@@ -3563,6 +3592,9 @@ expand_by_function (
ins_compl_add_dict(matchdict);
theend:
+ // Restore State, it might have been changed.
+ State = save_State;
+
if (matchdict != NULL) {
tv_dict_unref(matchdict);
}
@@ -4340,6 +4372,17 @@ ins_compl_next (
return num_matches;
}
+void pum_ext_select_item(int item, bool insert, bool finish)
+{
+ if (!pum_visible() || item < -1 || item >= compl_match_arraysize) {
+ return;
+ }
+ pum_want.active = true;
+ pum_want.item = item;
+ pum_want.insert = insert;
+ pum_want.finish = finish;
+}
+
// Call this while finding completions, to check whether the user has hit a key
// that should change the currently displayed completion, or exit completion
// mode. Also, when compl_pending is not zero, show a completion as soon as
@@ -4400,6 +4443,9 @@ void ins_compl_check_keys(int frequency, int in_compl_func)
*/
static int ins_compl_key2dir(int c)
{
+ if (c == K_EVENT || c == K_COMMAND) {
+ return pum_want.item < pum_selected_item ? BACKWARD : FORWARD;
+ }
if (c == Ctrl_P || c == Ctrl_L
|| c == K_PAGEUP || c == K_KPAGEUP
|| c == K_S_UP || c == K_UP) {
@@ -4427,6 +4473,11 @@ static int ins_compl_key2count(int c)
{
int h;
+ if (c == K_EVENT || c == K_COMMAND) {
+ int offset = pum_want.item - pum_selected_item;
+ return abs(offset);
+ }
+
if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN) {
h = pum_get_height();
if (h > 3)
@@ -4453,6 +4504,9 @@ static bool ins_compl_use_match(int c)
case K_KPAGEUP:
case K_S_UP:
return false;
+ case K_EVENT:
+ case K_COMMAND:
+ return pum_want.active && pum_want.insert;
}
return true;
}
@@ -4674,6 +4728,7 @@ static int ins_complete(int c, bool enable_pum)
pos_T pos;
win_T *curwin_save;
buf_T *curbuf_save;
+ const int save_State = State;
/* Call 'completefunc' or 'omnifunc' and get pattern length as a
* string */
@@ -4691,7 +4746,9 @@ static int ins_complete(int c, bool enable_pum)
pos = curwin->w_cursor;
curwin_save = curwin;
curbuf_save = curbuf;
- col = call_func_retnr(funcname, 2, args, FALSE);
+ col = call_func_retnr(funcname, 2, args, false);
+
+ State = save_State;
if (curwin_save != curwin || curbuf_save != curbuf) {
EMSG(_(e_complwin));
return FAIL;
@@ -5825,7 +5882,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,9 +5897,10 @@ 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;
- if (cmdwin_type != 0)
+ textwidth = curwin->w_grid.Columns - curbuf->b_p_wm;
+ if (cmdwin_type != 0) {
textwidth -= 1;
+ }
textwidth -= curwin->w_p_fdc;
if (signcolumn_on(curwin)) {
@@ -5855,9 +5913,10 @@ comp_textwidth (
if (textwidth < 0)
textwidth = 0;
if (ff && textwidth == 0) {
- textwidth = curwin->w_width - 1;
- if (textwidth > 79)
+ textwidth = curwin->w_grid.Columns - 1;
+ if (textwidth > 79) {
textwidth = 79;
+ }
}
return textwidth;
}
@@ -5921,7 +5980,7 @@ static void check_spell_redraw(void)
linenr_T lnum = spell_redraw_lnum;
spell_redraw_lnum = 0;
- redrawWinline(curwin, lnum, false);
+ redrawWinline(curwin, lnum);
}
}
@@ -8663,6 +8722,7 @@ static colnr_T get_nolist_virtcol(void)
static char_u *do_insert_char_pre(int c)
{
char buf[MB_MAXBYTES + 1];
+ const int save_State = State;
// Return quickly when there is nothing to do.
if (!has_event(EVENT_INSERTCHARPRE)) {
@@ -8687,6 +8747,9 @@ static char_u *do_insert_char_pre(int c)
set_vim_var_string(VV_CHAR, NULL, -1);
textlock--;
+ // Restore the State, it may have been changed.
+ State = save_State;
+
return res;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d67818aa81..58d42b49a7 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -2380,7 +2380,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
int ll_n1 = lp->ll_n1;
// Check whether any of the list items is locked
- for (listitem_T *ri = tv_list_first(rettv->vval.v_list);
+ for (ri = tv_list_first(rettv->vval.v_list);
ri != NULL && ll_li != NULL; ) {
if (tv_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock,
(const char *)lp->ll_name,
@@ -2476,9 +2476,9 @@ notify:
assert(lp->ll_newkey != NULL);
tv_dict_watcher_notify(dict, (char *)lp->ll_newkey, lp->ll_tv, NULL);
} else {
- dictitem_T *di = lp->ll_di;
- assert(di->di_key != NULL);
- tv_dict_watcher_notify(dict, (char *)di->di_key, lp->ll_tv, &oldtv);
+ dictitem_T *di_ = lp->ll_di;
+ assert(di_->di_key != NULL);
+ tv_dict_watcher_notify(dict, (char *)di_->di_key, lp->ll_tv, &oldtv);
tv_clear(&oldtv);
}
}
@@ -5234,8 +5234,6 @@ bool garbage_collect(bool testing)
/// @return true, if something was freed.
static int free_unref_items(int copyID)
{
- dict_T *dd, *dd_next;
- list_T *ll, *ll_next;
bool did_free = false;
// Let all "free" functions know that we are here. This means no
@@ -5273,14 +5271,16 @@ static int free_unref_items(int copyID)
}
// PASS 2: free the items themselves.
- for (dd = gc_first_dict; dd != NULL; dd = dd_next) {
+ dict_T *dd_next;
+ for (dict_T *dd = gc_first_dict; dd != NULL; dd = dd_next) {
dd_next = dd->dv_used_next;
if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) {
tv_dict_free_dict(dd);
}
}
- for (ll = gc_first_list; ll != NULL; ll = ll_next) {
+ list_T *ll_next;
+ for (list_T *ll = gc_first_list; ll != NULL; ll = ll_next) {
ll_next = ll->lv_used_next;
if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)
&& !tv_list_has_watchers(ll)) {
@@ -7103,7 +7103,7 @@ static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/*
* Get buffer by number or pattern.
*/
-static buf_T *get_buf_tv(typval_T *tv, int curtab_only)
+static buf_T *tv_get_buf(typval_T *tv, int curtab_only)
{
char_u *name = tv->vval.v_string;
int save_magic;
@@ -7149,7 +7149,7 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
emsg_off++;
- const buf_T *const buf = get_buf_tv(&argvars[0], false);
+ const buf_T *const buf = tv_get_buf(&argvars[0], false);
emsg_off--;
if (buf != NULL && buf->b_fname != NULL) {
rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname);
@@ -7168,7 +7168,7 @@ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
emsg_off++;
- const buf_T *buf = get_buf_tv(&argvars[0], false);
+ const buf_T *buf = tv_get_buf(&argvars[0], false);
emsg_off--;
// If the buffer isn't found and the second argument is not zero create a
@@ -7195,7 +7195,7 @@ static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr)
}
emsg_off++;
- buf_T *buf = get_buf_tv(&argvars[0], true);
+ buf_T *buf = tv_get_buf(&argvars[0], true);
if (buf == NULL) { // no need to search if buffer was not found
rettv->vval.v_number = -1;
goto end;
@@ -9280,7 +9280,7 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Information about one buffer. Argument specifies the buffer
if (tv_check_num(&argvars[0])) { // issue errmsg if type error
emsg_off++;
- argbuf = get_buf_tv(&argvars[0], false);
+ argbuf = tv_get_buf(&argvars[0], false);
emsg_off--;
if (argbuf == NULL) {
return;
@@ -9376,7 +9376,7 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (tv_check_str_or_nr(&argvars[0])) {
emsg_off++;
- buf = get_buf_tv(&argvars[0], false);
+ buf = tv_get_buf(&argvars[0], false);
emsg_off--;
}
@@ -9404,7 +9404,7 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const char *varname = tv_get_string_chk(&argvars[1]);
emsg_off++;
- buf_T *const buf = get_buf_tv(&argvars[0], false);
+ buf_T *const buf = tv_get_buf(&argvars[0], false);
if (buf != NULL && varname != NULL) {
// set curbuf to be our buf, temporarily
@@ -10704,6 +10704,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
"postscript",
"printer",
"profile",
+ "pythonx",
"reltime",
"quickfix",
"rightleft",
@@ -11507,23 +11508,23 @@ static void dict_list(typval_T *const tv, typval_T *const rettv,
tv_list_alloc_ret(rettv, tv_dict_len(tv->vval.v_dict));
TV_DICT_ITER(tv->vval.v_dict, di, {
- typval_T tv = { .v_lock = VAR_UNLOCKED };
+ typval_T tv_item = { .v_lock = VAR_UNLOCKED };
switch (what) {
case kDictListKeys: {
- tv.v_type = VAR_STRING;
- tv.vval.v_string = vim_strsave(di->di_key);
+ tv_item.v_type = VAR_STRING;
+ tv_item.vval.v_string = vim_strsave(di->di_key);
break;
}
case kDictListValues: {
- tv_copy(&di->di_tv, &tv);
+ tv_copy(&di->di_tv, &tv_item);
break;
}
case kDictListItems: {
// items()
list_T *const sub_l = tv_list_alloc(2);
- tv.v_type = VAR_LIST;
- tv.vval.v_list = sub_l;
+ tv_item.v_type = VAR_LIST;
+ tv_item.vval.v_list = sub_l;
tv_list_ref(sub_l);
tv_list_append_owned_tv(sub_l, (typval_T) {
@@ -11538,7 +11539,7 @@ static void dict_list(typval_T *const tv, typval_T *const rettv,
}
}
- tv_list_append_owned_tv(rettv->vval.v_list, tv);
+ tv_list_append_owned_tv(rettv->vval.v_list, tv_item);
});
}
@@ -13026,6 +13027,10 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
+ if (p_pyx == 0) {
+ p_pyx = 2;
+ }
+
script_host_eval("python", argvars, rettv);
}
@@ -13034,9 +13039,24 @@ static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
+ if (p_pyx == 0) {
+ p_pyx = 3;
+ }
+
script_host_eval("python3", argvars, rettv);
}
+// "pyxeval()" function
+static void f_pyxeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ init_pyxversion();
+ if (p_pyx == 2) {
+ f_pyeval(argvars, rettv, NULL);
+ } else {
+ f_py3eval(argvars, rettv, NULL);
+ }
+}
+
/*
* "range()" function
*/
@@ -14023,11 +14043,11 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1;
const int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1;
- if (row < 0 || row >= screen_Rows
- || col < 0 || col >= screen_Columns) {
+ if (row < 0 || row >= default_grid.Rows
+ || col < 0 || col >= default_grid.Columns) {
c = -1;
} else {
- c = ScreenAttrs[LineOffset[row] + col];
+ c = default_grid.attrs[default_grid.line_offset[row] + col];
}
rettv->vval.v_number = c;
}
@@ -14042,12 +14062,12 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const int row = tv_get_number_chk(&argvars[0], NULL) - 1;
const int col = tv_get_number_chk(&argvars[1], NULL) - 1;
- if (row < 0 || row >= screen_Rows
- || col < 0 || col >= screen_Columns) {
+ if (row < 0 || row >= default_grid.Rows
+ || col < 0 || col >= default_grid.Columns) {
c = -1;
} else {
- off = LineOffset[row] + col;
- c = utf_ptr2char(ScreenLines[off]);
+ off = default_grid.line_offset[row] + col;
+ c = utf_ptr2char(default_grid.chars[off]);
}
rettv->vval.v_number = c;
}
@@ -14471,7 +14491,7 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
const char *varname = tv_get_string_chk(&argvars[1]);
- buf_T *const buf = get_buf_tv(&argvars[0], false);
+ buf_T *const buf = tv_get_buf(&argvars[0], false);
typval_T *varp = &argvars[2];
if (buf != NULL && varname != NULL) {
@@ -14765,12 +14785,12 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
list_T *const l = argvars[0].vval.v_list;
// To some extent make sure that we are dealing with a list from
// "getmatches()".
- int i = 0;
+ int li_idx = 0;
TV_LIST_ITER_CONST(l, li, {
if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT
|| (d = TV_LIST_ITEM_TV(li)->vval.v_dict) == NULL) {
emsgf(_("E474: List item %d is either not a dictionary "
- "or an empty one"), i);
+ "or an empty one"), li_idx);
return;
}
if (!(tv_dict_find(d, S_LEN("group")) != NULL
@@ -14778,10 +14798,11 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|| tv_dict_find(d, S_LEN("pos1")) != NULL)
&& tv_dict_find(d, S_LEN("priority")) != NULL
&& tv_dict_find(d, S_LEN("id")) != NULL)) {
- emsgf(_("E474: List item %d is missing one of the required keys"), i);
+ emsgf(_("E474: List item %d is missing one of the required keys"),
+ li_idx);
return;
}
- i++;
+ li_idx++;
});
clear_matches(curwin);
@@ -16774,10 +16795,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
- uint16_t term_width = MAX(0, curwin->w_width - win_col_off(curwin));
+ uint16_t term_width = MAX(0, curwin->w_grid.Columns - win_col_off(curwin));
Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit,
true, false, false, cwd,
- term_width, curwin->w_height,
+ term_width, curwin->w_grid.Rows,
xstrdup("xterm-256color"),
&rettv->vval.v_number);
if (rettv->vval.v_number <= 0) {
@@ -20133,7 +20154,9 @@ void ex_function(exarg_T *eap)
arg = skipwhite(skiptowhite(p));
if (arg[0] == '<' && arg[1] =='<'
&& ((p[0] == 'p' && p[1] == 'y'
- && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
+ && (!ASCII_ISALNUM(p[2]) || p[2] == 't'
+ || ((p[2] == '3' || p[2] == 'x')
+ && !ASCII_ISALPHA(p[3]))))
|| (p[0] == 'p' && p[1] == 'e'
&& (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
|| (p[0] == 't' && p[1] == 'c'
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index e72bb7b870..78cac4878d 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -226,6 +226,7 @@ return {
pumvisible={},
py3eval={args=1},
pyeval={args=1},
+ pyxeval={args=1},
range={args={1, 3}},
readfile={args={1, 3}},
reltime={args={0, 2}},
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index e9ab6cd3e2..64658b52d9 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -302,11 +302,11 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,
const size_t len_ = (len); \
ga_grow(gap, (int) (2 + len_ + memcnt(buf_, '\'', len_))); \
ga_append(gap, '\''); \
- for (size_t i = 0; i < len_; i++) { \
- if (buf_[i] == '\'') { \
+ for (size_t i_ = 0; i_ < len_; i_++) { \
+ if (buf_[i_] == '\'') { \
ga_append(gap, '\''); \
} \
- ga_append(gap, buf_[i]); \
+ ga_append(gap, buf_[i_]); \
} \
ga_append(gap, '\''); \
} \
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 36c4e333cf..85844c37bd 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -256,10 +256,12 @@ void ex_align(exarg_T *eap)
*/
if (width <= 0)
width = curbuf->b_p_tw;
- if (width == 0 && curbuf->b_p_wm > 0)
- width = curwin->w_width - curbuf->b_p_wm;
- if (width <= 0)
+ if (width == 0 && curbuf->b_p_wm > 0) {
+ width = curwin->w_grid.Columns - curbuf->b_p_wm;
+ }
+ if (width <= 0) {
width = 80;
+ }
}
if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
@@ -2870,11 +2872,11 @@ void ex_z(exarg_T *eap)
// Vi compatible: ":z!" uses display height, without a count uses
// 'scroll'
if (eap->forceit) {
- bigness = curwin->w_height;
+ bigness = curwin->w_grid.Rows;
} else if (ONE_WINDOW) {
bigness = curwin->w_p_scr * 2;
} else {
- bigness = curwin->w_height - 3;
+ bigness = curwin->w_grid.Rows - 3;
}
if (bigness < 1) {
bigness = 1;
@@ -5757,7 +5759,7 @@ void ex_sign(exarg_T *eap)
id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum);
if (id > 0) {
buf_delsign(curwin->w_buffer, id);
- update_debug_sign(curwin->w_buffer, curwin->w_cursor.lnum);
+ redraw_buf_line_later(curwin->w_buffer, curwin->w_cursor.lnum);
} else {
EMSG(_("E159: Missing sign number"));
}
@@ -5786,7 +5788,7 @@ void ex_sign(exarg_T *eap)
// ":sign unplace {id}": remove placed sign by number
FOR_ALL_BUFFERS(buf) {
if ((lnum = buf_delsign(buf, id)) != 0) {
- update_debug_sign(buf, lnum);
+ redraw_buf_line_later(buf, lnum);
}
}
return;
@@ -5886,7 +5888,7 @@ void ex_sign(exarg_T *eap)
} else {
// ":sign unplace {id} file={fname}"
lnum = buf_delsign(buf, id);
- update_debug_sign(buf, lnum);
+ redraw_buf_line_later(buf, lnum);
}
} else if (sign_name != NULL) {
// idx == SIGNCMD_PLACE
@@ -5908,7 +5910,7 @@ void ex_sign(exarg_T *eap)
lnum = buf_change_sign_type(buf, id, sp->sn_typenr);
}
if (lnum > 0) {
- update_debug_sign(buf, lnum);
+ redraw_buf_line_later(buf, lnum);
} else {
EMSG2(_("E885: Not possible to change sign %s"), sign_name);
}
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 79ca5363e0..4806eff1b4 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -2067,6 +2067,30 @@ return {
func='ex_py3file',
},
{
+ command='pyx',
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type=ADDR_LINES,
+ func='ex_pyx',
+ },
+ {
+ command='pyxdo',
+ flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN),
+ addr_type=ADDR_LINES,
+ func='ex_pyxdo',
+ },
+ {
+ command='pythonx',
+ flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN),
+ addr_type=ADDR_LINES,
+ func='ex_pyx',
+ },
+ {
+ command='pyxfile',
+ flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN),
+ addr_type=ADDR_LINES,
+ func='ex_pyxfile',
+ },
+ {
command='quit',
flags=bit.bor(BANG, RANGE, COUNT, NOTADR, TRLBAR, CMDWIN),
addr_type=ADDR_WINDOWS,
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 1ffcf67ef7..484c911a8b 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -1772,7 +1772,7 @@ void ex_args(exarg_T *eap)
}
}
- if (!ends_excmd(*eap->arg)) {
+ if (*eap->arg != NUL) {
// ":args file ..": define new argument list, handle like ":next"
// Also for ":argslocal file .." and ":argsglobal file ..".
ex_next(eap);
@@ -2130,9 +2130,9 @@ void ex_listdo(exarg_T *eap)
// Remember the number of the next listed buffer, in case
// ":bwipe" is used or autocommands do something strange.
next_fnum = -1;
- for (buf_T *buf = curbuf->b_next; buf != NULL; buf = buf->b_next) {
- if (buf->b_p_bl) {
- next_fnum = buf->b_fnum;
+ for (buf_T *bp = curbuf->b_next; bp != NULL; bp = bp->b_next) {
+ if (bp->b_p_bl) {
+ next_fnum = bp->b_fnum;
break;
}
}
@@ -2809,6 +2809,126 @@ void ex_options(exarg_T *eap)
cmd_source((char_u *)SYS_OPTWIN_FILE, NULL);
}
+// Detect Python 3 or 2, and initialize 'pyxversion'.
+void init_pyxversion(void)
+{
+ if (p_pyx == 0) {
+ if (!eval_has_provider("python3")) {
+ p_pyx = 3;
+ } else if (!eval_has_provider("python")) {
+ p_pyx = 2;
+ }
+ }
+}
+
+// Does a file contain one of the following strings at the beginning of any
+// line?
+// "#!(any string)python2" => returns 2
+// "#!(any string)python3" => returns 3
+// "# requires python 2.x" => returns 2
+// "# requires python 3.x" => returns 3
+// otherwise return 0.
+static int requires_py_version(char_u *filename)
+{
+ FILE *file;
+ int requires_py_version = 0;
+ int i, lines;
+
+ lines = (int)p_mls;
+ if (lines < 0) {
+ lines = 5;
+ }
+
+ file = mch_fopen((char *)filename, "r");
+ if (file != NULL) {
+ for (i = 0; i < lines; i++) {
+ if (vim_fgets(IObuff, IOSIZE, file)) {
+ break;
+ }
+ if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!') {
+ // Check shebang.
+ if (strstr((char *)IObuff + 2, "python2") != NULL) {
+ requires_py_version = 2;
+ break;
+ }
+ if (strstr((char *)IObuff + 2, "python3") != NULL) {
+ requires_py_version = 3;
+ break;
+ }
+ }
+ IObuff[21] = '\0';
+ if (STRCMP("# requires python 2.x", IObuff) == 0) {
+ requires_py_version = 2;
+ break;
+ }
+ if (STRCMP("# requires python 3.x", IObuff) == 0) {
+ requires_py_version = 3;
+ break;
+ }
+ }
+ fclose(file);
+ }
+ return requires_py_version;
+}
+
+
+// Source a python file using the requested python version.
+static void source_pyx_file(exarg_T *eap, char_u *fname)
+{
+ exarg_T ex;
+ long int v = requires_py_version(fname);
+
+ init_pyxversion();
+ if (v == 0) {
+ // user didn't choose a preference, 'pyx' is used
+ v = p_pyx;
+ }
+
+ // now source, if required python version is not supported show
+ // unobtrusive message.
+ if (eap == NULL) {
+ memset(&ex, 0, sizeof(ex));
+ } else {
+ ex = *eap;
+ }
+ ex.arg = fname;
+ ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3");
+
+ if (v == 2) {
+ ex_pyfile(&ex);
+ } else {
+ ex_py3file(&ex);
+ }
+}
+
+// ":pyxfile {fname}"
+void ex_pyxfile(exarg_T *eap)
+{
+ source_pyx_file(eap, eap->arg);
+}
+
+// ":pyx"
+void ex_pyx(exarg_T *eap)
+{
+ init_pyxversion();
+ if (p_pyx == 2) {
+ ex_python(eap);
+ } else {
+ ex_python3(eap);
+ }
+}
+
+// ":pyxdo"
+void ex_pyxdo(exarg_T *eap)
+{
+ init_pyxversion();
+ if (p_pyx == 2) {
+ ex_pydo(eap);
+ } else {
+ ex_pydo3(eap);
+ }
+}
+
/// ":source {fname}"
void ex_source(exarg_T *eap)
{
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 4ef332186e..ffa913efcf 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -2158,6 +2158,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
case CMD_python:
case CMD_py3:
case CMD_python3:
+ case CMD_pythonx:
+ case CMD_pyx:
+ case CMD_pyxdo:
+ case CMD_pyxfile:
case CMD_return:
case CMD_rightbelow:
case CMD_ruby:
@@ -9194,10 +9198,10 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin)
/* restore height when not full height */
if (wp->w_height + wp->w_status_height < topframe->fr_height
&& (fprintf(fd,
- "exe '%dresize ' . ((&lines * %" PRId64
- " + %" PRId64 ") / %" PRId64 ")",
- n, (int64_t)wp->w_height,
- (int64_t)(Rows / 2), (int64_t)Rows) < 0
+ "exe '%dresize ' . ((&lines * %" PRId64
+ " + %" PRId64 ") / %" PRId64 ")",
+ n, (int64_t)wp->w_grid.Rows,
+ (int64_t)(Rows / 2), (int64_t)Rows) < 0
|| put_eol(fd) == FAIL))
return FAIL;
@@ -9459,8 +9463,8 @@ put_view(
" * winheight(0) + %" PRId64 ") / %" PRId64 ")",
(int64_t)wp->w_cursor.lnum,
(int64_t)(wp->w_cursor.lnum - wp->w_topline),
- (int64_t)(wp->w_height / 2),
- (int64_t)wp->w_height) < 0
+ (int64_t)(wp->w_grid.Rows / 2),
+ (int64_t)wp->w_grid.Rows) < 0
|| put_eol(fd) == FAIL
|| put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL
|| put_line(fd, "exe s:l") == FAIL
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index bfc32887ca..4ea25117d9 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -6197,9 +6197,6 @@ static int open_cmdwin(void)
stuffReadbuff(p);
stuffcharReadbuff(CAR);
}
- } else if (cmdwin_result == K_XF2) { /* :qa typed */
- ccline.cmdbuff = vim_strsave((char_u *)"qa");
- cmdwin_result = CAR;
} else if (cmdwin_result == Ctrl_C) {
/* :q or :close, don't execute any command
* and don't modify the cmd window. */
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index fe12a69801..c631057e81 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -5997,9 +5997,8 @@ void do_autocmd(char_u *arg_in, int forceit)
char_u *pat;
char_u *envpat = NULL;
char_u *cmd;
- event_T event;
- int need_free = FALSE;
- int nested = FALSE;
+ int need_free = false;
+ int nested = false;
int group;
if (*arg == '|') {
@@ -6082,7 +6081,7 @@ void do_autocmd(char_u *arg_in, int forceit)
last_event = (event_T)-1; // for listing the event name
last_group = AUGROUP_ERROR; // for listing the group name
if (*arg == '*' || *arg == NUL || *arg == '|') {
- for (event = (event_T)0; (int)event < (int)NUM_EVENTS;
+ for (event_T event = (event_T)0; (int)event < (int)NUM_EVENTS;
event = (event_T)((int)event + 1)) {
if (do_autocmd_event(event, pat, nested, cmd, forceit, group) == FAIL) {
break;
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 94702a9a3a..53e9846c2d 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2120,8 +2120,8 @@ static int vgetorpeek(int advance)
++col;
}
curwin->w_wrow = curwin->w_cline_row
- + curwin->w_wcol / curwin->w_width;
- curwin->w_wcol %= curwin->w_width;
+ + curwin->w_wcol / curwin->w_grid.Columns;
+ curwin->w_wcol %= curwin->w_grid.Columns;
curwin->w_wcol += curwin_col_off();
col = 0; /* no correction needed */
} else {
@@ -2129,8 +2129,8 @@ static int vgetorpeek(int advance)
col = curwin->w_cursor.col - 1;
}
} else if (curwin->w_p_wrap && curwin->w_wrow) {
- --curwin->w_wrow;
- curwin->w_wcol = curwin->w_width - 1;
+ curwin->w_wrow--;
+ curwin->w_wcol = curwin->w_grid.Columns - 1;
col = curwin->w_cursor.col - 1;
}
if (col > 0 && curwin->w_wcol > 0) {
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 04ff1320ce..f749c119cd 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -91,9 +91,10 @@ EXTERN struct nvim_stats_s {
/*
* Number of Rows and Columns in the screen.
* Must be long to be able to use them as options in option.c.
- * Note: Use screen_Rows and screen_Columns to access items in ScreenLines[].
- * They may have different values when the screen wasn't (re)allocated yet
- * after setting Rows or Columns (e.g., when starting up).
+ * Note: Use default_grid.Rows and default_grid.Columns to access items in
+ * default_grid.chars[]. They may have different values when the screen
+ * wasn't (re)allocated yet after setting Rows or Columns (e.g., when starting
+ * up).
*/
#define DFLT_COLS 80 // default value for 'columns'
#define DFLT_ROWS 24 // default value for 'lines'
@@ -129,45 +130,6 @@ typedef off_t off_T;
#endif
/*
- * The characters and attributes cached for the screen.
- */
-typedef char_u schar_T[(MAX_MCO+1) * 4 + 1];
-typedef int16_t sattr_T;
-
-/// ScreenLines[] contains a copy of the whole screen, as it currently is
-/// displayed. It is a single block of screen cells, the size of the screen
-/// plus one line. The extra line used as a buffer while redrawing a window
-/// line, so it can be compared with the previous state of that line. This way
-/// we can avoid sending bigger updates than neccessary to the Ul layer.
-///
-/// Screen cells are stored as NUL-terminated UTF-8 strings, and a cell can
-/// contain up to MAX_MCO composing characters after the base character.
-/// The composing characters are to be drawn on top of the original character.
-/// The content after the NUL is not defined (so comparison must be done a
-/// single cell at a time). Double-width characters are stored in the left cell,
-/// and the right cell should only contain the empty string. When a part of the
-/// screen is cleared, the cells should be filled with a single whitespace char.
-///
-/// ScreenAttrs[] contains the highlighting attribute for each cell.
-/// LineOffset[n] is the offset from ScreenLines[] and ScreenAttrs[] for the
-/// start of line 'n'. These offsets are in general not linear, as full screen
-/// scrolling is implemented by rotating the offsets in the LineOffset array.
-/// LineWraps[] is an array of boolean flags indicating if the screen line wraps
-/// to the next line. It can only be true if a window occupies the entire screen
-/// width.
-///
-///
-/// Note: before the screen is initialized and when out of memory these can be
-/// NULL.
-EXTERN schar_T *ScreenLines INIT(= NULL);
-EXTERN sattr_T *ScreenAttrs INIT(= NULL);
-EXTERN unsigned *LineOffset INIT(= NULL);
-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[] */
-
-/*
* When vgetc() is called, it sets mod_mask to the set of modifiers that are
* held down based on the MOD_MASK_* symbols that are read first.
*/
@@ -228,11 +190,8 @@ EXTERN int compl_cont_status INIT(= 0);
# define CONT_LOCAL 32 /* for ctrl_x_mode 0, ^X^P/^X^N do a local
* expansion, (eg use complete=.) */
-/*
- * Functions for putting characters in the command line,
- * while keeping ScreenLines[] updated.
- */
-EXTERN int cmdmsg_rl INIT(= FALSE); /* cmdline is drawn right to left */
+// state for putting characters in the message area
+EXTERN int cmdmsg_rl INIT(= false); // cmdline is drawn right to left
EXTERN int msg_col;
EXTERN int msg_row;
EXTERN int msg_scrolled; /* Number of screen lines that windows have
@@ -702,11 +661,13 @@ EXTERN int* (*iconv_errno)(void);
/// Visual_mode: When State is NORMAL or INSERT.
/// finish_op : When State is NORMAL, after typing the operator and
/// before typing the motion command.
+/// motion_force: Last motion_force from do_pending_operator()
EXTERN int State INIT(= NORMAL); // This is the current state of the
// command interpreter.
EXTERN bool finish_op INIT(= false); // true while an operator is pending
EXTERN long opcount INIT(= 0); // count for pending operator
+EXTERN int motion_force INIT(=0); // motion force for pending operator
// Ex Mode (Q) state
EXTERN int exmode_active INIT(= 0); // Zero, EXMODE_NORMAL or EXMODE_VIM.
diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h
new file mode 100644
index 0000000000..37d85ead0c
--- /dev/null
+++ b/src/nvim/grid_defs.h
@@ -0,0 +1,59 @@
+#ifndef NVIM_GRID_DEFS_H
+#define NVIM_GRID_DEFS_H
+
+#include <stdint.h>
+
+#include "nvim/types.h"
+
+#define MAX_MCO 6 // maximum value for 'maxcombine'
+
+// The characters and attributes drawn on grids.
+typedef char_u schar_T[(MAX_MCO+1) * 4 + 1];
+typedef int16_t sattr_T;
+
+/// ScreenGrid represents a resizable rectuangular grid displayed by UI clients.
+///
+/// chars[] contains the UTF-8 text that is currently displayed on the grid.
+/// It is stored as a single block of cells. When redrawing a part of the grid,
+/// the new state can be compared with the existing state of the grid. This way
+/// we can avoid sending bigger updates than neccessary to the Ul layer.
+///
+/// Screen cells are stored as NUL-terminated UTF-8 strings, and a cell can
+/// contain up to MAX_MCO composing characters after the base character.
+/// The composing characters are to be drawn on top of the original character.
+/// The content after the NUL is not defined (so comparison must be done a
+/// single cell at a time). Double-width characters are stored in the left cell,
+/// and the right cell should only contain the empty string. When a part of the
+/// screen is cleared, the cells should be filled with a single whitespace char.
+///
+/// attrs[] contains the highlighting attribute for each cell.
+/// line_offset[n] is the offset from chars[] and attrs[] for the
+/// start of line 'n'. These offsets are in general not linear, as full screen
+/// scrolling is implemented by rotating the offsets in the line_offset array.
+/// line_wraps[] is an array of boolean flags indicating if the screen line
+/// wraps to the next line. It can only be true if a window occupies the entire
+/// screen width.
+typedef struct {
+ handle_T handle;
+
+ schar_T *chars;
+ sattr_T *attrs;
+ unsigned *line_offset;
+ char_u *line_wraps;
+
+ // the size of the allocated grid.
+ int Rows;
+ int Columns;
+
+ // offsets for the grid relative to the global screen
+ int row_offset;
+ int col_offset;
+
+ // grid size requested by the UI. Used for window grids only.
+ int requested_rows;
+ int requested_cols;
+
+ int was_resized;
+} ScreenGrid;
+
+#endif // NVIM_GRID_DEFS_H
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index a8731d5bd7..983dbb7bbe 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -582,8 +582,9 @@ 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/highlight.c b/src/nvim/highlight.c
index 5a9727f46e..41d60fa3ea 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -98,7 +98,7 @@ static int get_attr_entry(HlEntry entry)
return id;
}
-/// When a UI connects, we need to send it the table of higlights used so far.
+/// When a UI connects, we need to send it the table of highlights used so far.
void ui_send_all_hls(UI *ui)
{
for (size_t i = 1; i < kv_size(attr_entries); i++) {
@@ -212,13 +212,7 @@ void clear_hl_tables(bool reinit)
map_clear(int, int)(combine_attr_entries);
highlight_attr_set_all();
highlight_changed();
- redraw_all_later(NOT_VALID);
- if (ScreenAttrs) {
- // the meaning of 0 doesn't change anyway
- // but the rest must be retransmitted
- memset(ScreenAttrs, 0,
- sizeof(*ScreenAttrs) * (size_t)(screen_Rows * screen_Columns));
- }
+ screen_invalidate_highlights();
} else {
kv_destroy(attr_entries);
map_free(HlEntry, int)(attr_entry_ids);
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index 3cc64e0033..13534ac1a9 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include "nvim/ascii.h"
+#include "nvim/assert.h"
#include "nvim/indent.h"
#include "nvim/eval.h"
#include "nvim/charset.h"
@@ -204,7 +205,12 @@ int set_indent(int size, int flags)
// after the if (!curbuf->b_p_et) below.
if (orig_char_len != -1) {
assert(orig_char_len + size - ind_done + line_len >= 0);
- newline = xmalloc((size_t)(orig_char_len + size - ind_done + line_len));
+ size_t n; // = orig_char_len + size - ind_done + line_len
+ size_t n2;
+ STRICT_ADD(orig_char_len, size, &n, size_t);
+ STRICT_ADD(ind_done, line_len, &n2, size_t);
+ STRICT_SUB(n, n2, &n, size_t);
+ newline = xmalloc(n);
todo = size - ind_done;
// Set total length of indent in characters, which may have been
@@ -226,7 +232,9 @@ int set_indent(int size, int flags)
} else {
todo = size;
assert(ind_len + line_len >= 0);
- newline = xmalloc((size_t)(ind_len + line_len));
+ size_t newline_size;
+ STRICT_ADD(ind_len, line_len, &newline_size, size_t);
+ newline = xmalloc(newline_size);
s = newline;
}
@@ -392,7 +400,9 @@ int copy_indent(int size, char_u *src)
// and the rest of the line.
line_len = (int)STRLEN(get_cursor_line_ptr()) + 1;
assert(ind_len + line_len >= 0);
- line = xmalloc((size_t)(ind_len + line_len));
+ size_t line_size;
+ STRICT_ADD(ind_len, line_len, &line_size, size_t);
+ line = xmalloc(line_size);
p = line;
}
}
@@ -463,8 +473,8 @@ int get_breakindent_win(win_T *wp, char_u *line)
static char_u *prev_line = NULL; // cached pointer to line.
static varnumber_T prev_tick = 0; // Changedtick of cached value.
int bri = 0;
- /* window width minus window margin space, i.e. what rests for text */
- const int eff_wwidth = wp->w_width
+ // window width minus window margin space, i.e. what rests for text
+ const int eff_wwidth = wp->w_grid.Columns
- ((wp->w_p_nu || wp->w_p_rnu)
&& (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
? number_width(wp) + 1 : 0);
@@ -544,10 +554,8 @@ int get_expr_indent(void)
// Need to make a copy, the 'indentexpr' option could be changed while
// evaluating it.
char_u *inde_copy = vim_strsave(curbuf->b_p_inde);
- if (inde_copy != NULL) {
- indent = (int)eval_to_number(inde_copy);
- xfree(inde_copy);
- }
+ indent = (int)eval_to_number(inde_copy);
+ xfree(inde_copy);
if (use_sandbox) {
sandbox--;
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 8a40577e8f..17f3a894d4 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -781,7 +781,6 @@ static void command_line_scan(mparm_T *parmp)
bool had_minmin = false; // found "--" argument
int want_argument; // option argument with argument
int c;
- char_u *p = NULL;
long n;
argc--;
@@ -1227,7 +1226,7 @@ scripterror:
// Add the file to the global argument list.
ga_grow(&global_alist.al_ga, 1);
- p = vim_strsave((char_u *)argv[0]);
+ char_u *p = vim_strsave((char_u *)argv[0]);
if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0
&& !os_isdir(alist_name(&GARGLIST[0]))) {
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 0ee8e2bd85..ead6b4405d 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -556,13 +556,6 @@ size_t mb_string2cells(const char_u *str)
return clen;
}
-/// Return number of display cells for char at ScreenLines[off].
-/// We make sure that the offset used is less than "max_off".
-int utf_off2cells(unsigned off, unsigned max_off)
-{
- return (off + 1 < max_off && ScreenLines[off + 1][0] == 0) ? 2 : 1;
-}
-
/// Convert a UTF-8 byte sequence to a wide character
///
/// If the sequence is illegal or truncated by a NUL then the first byte is
@@ -1822,32 +1815,6 @@ const char *mb_unescape(const char **const pp)
return NULL;
}
-/*
- * Return true if the character at "row"/"col" on the screen is the left side
- * of a double-width character.
- * Caller must make sure "row" and "col" are not invalid!
- */
-bool mb_lefthalve(int row, int col)
-{
- return utf_off2cells(LineOffset[row] + col,
- LineOffset[row] + screen_Columns) > 1;
-}
-
-/*
- * Correct a position on the screen, if it's the right half of a double-wide
- * char move it to the left half. Returns the corrected column.
- */
-int mb_fix_col(int col, int row)
-{
- col = check_col(col);
- row = check_row(row);
- if (ScreenLines != NULL && col > 0
- && ScreenLines[LineOffset[row] + col][0] == 0) {
- return col - 1;
- }
- return col;
-}
-
/*
* Skip the Vim specific head of a 'encoding' name.
@@ -2524,23 +2491,3 @@ char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr,
return retval;
}
-
-// Check bounds for column number
-static int check_col(int col)
-{
- if (col < 0)
- return 0;
- if (col >= screen_Columns)
- return screen_Columns - 1;
- return col;
-}
-
-// Check bounds for row number
-static int check_row(int row)
-{
- if (row < 0)
- return 0;
- if (row >= screen_Rows)
- return screen_Rows - 1;
- return row;
-}
diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h
index 70073a8540..ed48705c6d 100644
--- a/src/nvim/mbyte.h
+++ b/src/nvim/mbyte.h
@@ -19,13 +19,6 @@
#define MB_BYTE2LEN(b) utf8len_tab[b]
#define MB_BYTE2LEN_CHECK(b) (((b) < 0 || (b) > 255) ? 1 : utf8len_tab[b])
-/// Maximum value for 'maxcombine'
-///
-/// At most that number of composing characters may be attached to the leading
-/// character by various `utfc_*` functions. Note that some functions do not
-/// have this limit.
-enum { MAX_MCO = 6 };
-
// max length of an unicode char
#define MB_MAXCHAR 6
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 6b96a3b070..d38079ca72 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -698,8 +698,8 @@ void free_all_mem(void)
buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
}
- /* screenlines (can't display anything now!) */
- free_screenlines();
+ // free screenlines (can't display anything now!)
+ screen_free_all_mem();
clear_hl_tables(false);
list_free_log();
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 6de81a8aaf..37e40c3cc1 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1546,10 +1546,8 @@ void msg_prt_line(char_u *s, int list)
msg_clr_eos();
}
-/*
- * Use screen_puts() to output one multi-byte character.
- * Return the pointer "s" advanced to the next 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)
{
int cw;
@@ -1563,7 +1561,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) {
@@ -1886,19 +1884,22 @@ int msg_scrollsize(void)
*/
static void msg_scroll_up(void)
{
+ if (msg_scrolled == 0) {
+ ui_call_win_scroll_over_start();
+ }
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 +2098,8 @@ 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 +2315,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,18 +2336,18 @@ 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,
- (int)Columns, ' ', ' ', 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;
}
}
if (toscroll <= 0) {
- /* displayed the requested text, more prompt again */
- screen_fill((int)Rows - 1, (int)Rows, 0,
- (int)Columns, ' ', ' ', 0);
- msg_moremsg(FALSE);
+ // displayed the requested text, more prompt again
+ grid_fill(&default_grid, (int)Rows - 1, (int)Rows, 0,
+ (int)Columns, ' ', ' ', 0);
+ msg_moremsg(false);
continue;
}
@@ -2355,8 +2358,9 @@ static int do_more_prompt(int typed_char)
break;
}
- /* clear the --more-- message */
- screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
+ // clear the --more-- message
+ grid_fill(&default_grid, (int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ',
+ 0);
State = oldState;
setmouse();
if (quit_more) {
@@ -2452,8 +2456,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 +2477,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);
+ }
}
/*
@@ -2525,13 +2530,13 @@ 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);
- } else {
- screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ', 0);
- screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0);
- }
+ int msg_startcol = (cmdmsg_rl) ? 0 : msg_col;
+ int msg_endcol = (cmdmsg_rl) ? msg_col + 1 : (int)Columns;
+
+ grid_fill(&default_grid, msg_row, msg_row + 1, msg_startcol, msg_endcol, ' ',
+ ' ', 0);
+ grid_fill(&default_grid, msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ',
+ 0);
}
/*
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index ffe2d11f08..a66ded13f1 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -203,7 +203,7 @@ open_line (
char_u *ptr;
char_u last_char;
- pos_T old_cursor = curwin->w_cursor;
+ old_cursor = curwin->w_cursor;
ptr = saved_line;
if (flags & OPENLINE_DO_COM)
lead_len = get_leader_len(ptr, NULL, FALSE, TRUE);
@@ -1251,7 +1251,7 @@ int plines_win_nofill(
return 1;
}
- if (wp->w_width == 0) {
+ if (wp->w_grid.Columns == 0) {
return 1;
}
@@ -1261,8 +1261,8 @@ int plines_win_nofill(
}
const int lines = plines_win_nofold(wp, lnum);
- if (winheight && lines > wp->w_height) {
- return wp->w_height;
+ if (winheight && lines > wp->w_grid.Rows) {
+ return wp->w_grid.Rows;
}
return lines;
}
@@ -1292,7 +1292,7 @@ int plines_win_nofold(win_T *wp, linenr_T lnum)
/*
* Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
*/
- width = wp->w_width - win_col_off(wp);
+ width = wp->w_grid.Columns - win_col_off(wp);
if (width <= 0 || col > 32000) {
return 32000; // bigger than the number of screen columns
}
@@ -1318,8 +1318,9 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
if (!wp->w_p_wrap)
return lines + 1;
- if (wp->w_width == 0)
+ if (wp->w_grid.Columns == 0) {
return lines + 1;
+ }
char_u *line = ml_get_buf(wp->w_buffer, lnum, false);
char_u *s = line;
@@ -1340,7 +1341,7 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
}
// Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
- int width = wp->w_width - win_col_off(wp);
+ int width = wp->w_grid.Columns - win_col_off(wp);
if (width <= 0) {
return 9999;
}
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 3c792326a4..bf71e6a479 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -110,8 +110,9 @@ retnomove:
// Remember the character under the mouse, it might be a '-' or '+' in the
// fold column. NB: only works for ASCII chars!
if (row >= 0 && row < Rows && col >= 0 && col <= Columns
- && ScreenLines != NULL) {
- mouse_char = ScreenLines[LineOffset[row] + (unsigned)col][0];
+ && default_grid.chars != NULL) {
+ mouse_char = default_grid.chars[default_grid.line_offset[row]
+ + (unsigned)col][0];
} else {
mouse_char = ' ';
}
@@ -318,7 +319,6 @@ retnomove:
// Start Visual mode before coladvance(), for when 'sel' != "old"
if ((flags & MOUSE_MAY_VIS) && !VIsual_active) {
- check_visual_highlight();
VIsual = old_cursor;
VIsual_active = true;
VIsual_reselect = true;
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 3a29851ee6..f2c8996050 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -83,8 +83,9 @@ static void comp_botline(win_T *wp)
redraw_for_cursorline(wp);
wp->w_valid |= (VALID_CROW|VALID_CHEIGHT);
}
- if (done + n > wp->w_height)
+ if (done + n > wp->w_grid.Rows) {
break;
+ }
done += n;
lnum = last;
}
@@ -116,8 +117,8 @@ static void redraw_for_cursorline(win_T *wp)
// "w_last_cursorline" may be outdated, worst case we redraw
// too much. This is optimized for moving the cursor around in
// the current window.
- redrawWinline(wp, wp->w_last_cursorline, false);
- redrawWinline(wp, wp->w_cursor.lnum, false);
+ redrawWinline(wp, wp->w_last_cursorline);
+ redrawWinline(wp, wp->w_cursor.lnum);
redraw_win_later(wp, VALID);
} else {
redraw_win_later(wp, SOME_VALID);
@@ -149,9 +150,12 @@ void update_topline(void)
bool check_botline = false;
long save_so = p_so;
+ // need to have w_grid.Rows/Columns updated
+ win_grid_alloc(curwin);
+
// If there is no valid screen and when the window height is zero just use
// the cursor line.
- if (!screen_valid(true) || curwin->w_height == 0) {
+ if (!screen_valid(true) || curwin->w_grid.Rows == 0) {
curwin->w_topline = curwin->w_cursor.lnum;
curwin->w_botline = curwin->w_topline;
curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
@@ -200,9 +204,10 @@ void update_topline(void)
check_topline = true;
if (check_topline) {
- int halfheight = curwin->w_height / 2 - 1;
- if (halfheight < 2)
+ int halfheight = curwin->w_grid.Rows / 2 - 1;
+ if (halfheight < 2) {
halfheight = 2;
+ }
long n;
if (hasAnyFolding(curwin)) {
/* Count the number of logical lines between the cursor and
@@ -289,20 +294,22 @@ void update_topline(void)
* botline - p_so (approximation of how much will be
* scrolled). */
for (linenr_T lnum = curwin->w_cursor.lnum;
- lnum >= curwin->w_botline - p_so; --lnum) {
- ++line_count;
- /* stop at end of file or when we know we are far off */
- if (lnum <= 0 || line_count > curwin->w_height + 1)
+ lnum >= curwin->w_botline - p_so; lnum--) {
+ line_count++;
+ // stop at end of file or when we know we are far off
+ if (lnum <= 0 || line_count > curwin->w_grid.Rows + 1) {
break;
+ }
(void)hasFolding(lnum, &lnum, NULL);
}
} else
line_count = curwin->w_cursor.lnum - curwin->w_botline
+ 1 + p_so;
- if (line_count <= curwin->w_height + 1)
+ if (line_count <= curwin->w_grid.Rows + 1) {
scroll_cursor_bot(scrolljump_value(), false);
- else
+ } else {
scroll_cursor_halfway(false);
+ }
}
}
}
@@ -346,7 +353,7 @@ void update_topline_win(win_T* win)
*/
static int scrolljump_value(void)
{
- long result = p_sj >= 0 ? p_sj : (curwin->w_height * -p_sj) / 100;
+ long result = p_sj >= 0 ? p_sj : (curwin->w_grid.Rows * -p_sj) / 100;
assert(result <= INT_MAX);
return (int)result;
}
@@ -522,6 +529,7 @@ int cursor_valid(void)
*/
void validate_cursor(void)
{
+ win_grid_alloc(curwin); // we need to have w_grid.Rows/Columns updated
check_cursor_moved(curwin);
if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
curs_columns(true);
@@ -660,18 +668,19 @@ void validate_cursor_col(void)
colnr_T col = curwin->w_virtcol;
colnr_T off = curwin_col_off();
col += off;
- int width = curwin->w_width - off + curwin_col_off2();
-
- /* long line wrapping, adjust curwin->w_wrow */
- if (curwin->w_p_wrap
- && col >= (colnr_T)curwin->w_width
- && width > 0)
- /* use same formula as what is used in curs_columns() */
- col -= ((col - curwin->w_width) / width + 1) * width;
- if (col > (int)curwin->w_leftcol)
+ int width = curwin->w_grid.Columns - off + curwin_col_off2();
+
+ // long line wrapping, adjust curwin->w_wrow
+ if (curwin->w_p_wrap && col >= (colnr_T)curwin->w_grid.Columns
+ && width > 0) {
+ // use same formula as what is used in curs_columns()
+ col -= ((col - curwin->w_grid.Columns) / width + 1) * width;
+ }
+ if (col > (int)curwin->w_leftcol) {
col -= curwin->w_leftcol;
- else
+ } else {
col = 0;
+ }
curwin->w_wcol = col;
curwin->w_valid |= VALID_WCOL;
@@ -760,20 +769,20 @@ void curs_columns(
*/
curwin->w_wrow = curwin->w_cline_row;
- int textwidth = curwin->w_width - extra;
+ int textwidth = curwin->w_grid.Columns - extra;
if (textwidth <= 0) {
- /* No room for text, put cursor in last char of window. */
- curwin->w_wcol = curwin->w_width - 1;
- curwin->w_wrow = curwin->w_height - 1;
+ // No room for text, put cursor in last char of window.
+ curwin->w_wcol = curwin->w_grid.Columns - 1;
+ curwin->w_wrow = curwin->w_grid.Rows - 1;
} else if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
width = textwidth + curwin_col_off2();
- /* long line wrapping, adjust curwin->w_wrow */
- if (curwin->w_wcol >= curwin->w_width) {
- /* this same formula is used in validate_cursor_col() */
- n = (curwin->w_wcol - curwin->w_width) / width + 1;
+ // long line wrapping, adjust curwin->w_wrow
+ if (curwin->w_wcol >= curwin->w_grid.Columns) {
+ // this same formula is used in validate_cursor_col()
+ n = (curwin->w_wcol - curwin->w_grid.Columns) / width + 1;
curwin->w_wcol -= n * width;
curwin->w_wrow += n;
@@ -800,7 +809,7 @@ void curs_columns(
assert(p_siso <= INT_MAX);
int off_left = startcol - curwin->w_leftcol - (int)p_siso;
int off_right =
- endcol - curwin->w_leftcol - curwin->w_width + (int)p_siso + 1;
+ endcol - curwin->w_leftcol - curwin->w_grid.Columns + (int)p_siso + 1;
if (off_left < 0 || off_right > 0) {
int diff = (off_left < 0) ? -off_left: off_right;
@@ -843,17 +852,16 @@ void curs_columns(
prev_skipcol = curwin->w_skipcol;
int p_lines = 0;
- if ((curwin->w_wrow >= curwin->w_height
+ if ((curwin->w_wrow >= curwin->w_grid.Rows
|| ((prev_skipcol > 0
- || curwin->w_wrow + p_so >= curwin->w_height)
+ || curwin->w_wrow + p_so >= curwin->w_grid.Rows)
&& (p_lines =
- plines_win_nofill
- (curwin, curwin->w_cursor.lnum, false))
- - 1 >= curwin->w_height))
- && curwin->w_height != 0
+ plines_win_nofill(curwin, curwin->w_cursor.lnum, false)) - 1
+ >= curwin->w_grid.Rows))
+ && curwin->w_grid.Rows != 0
&& curwin->w_cursor.lnum == curwin->w_topline
&& width > 0
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
/* Cursor past end of screen. Happens with a single line that does
* not fit on screen. Find a skipcol to show the text around the
@@ -875,19 +883,22 @@ void curs_columns(
}
else
n = p_lines;
- if ((colnr_T)n >= curwin->w_height + curwin->w_skipcol / width)
+ if ((colnr_T)n >= curwin->w_grid.Rows + curwin->w_skipcol / width) {
extra += 2;
+ }
if (extra == 3 || p_lines < p_so * 2) {
- /* not enough room for 'scrolloff', put cursor in the middle */
+ // not enough room for 'scrolloff', put cursor in the middle
n = curwin->w_virtcol / width;
- if (n > curwin->w_height / 2)
- n -= curwin->w_height / 2;
- else
+ if (n > curwin->w_grid.Rows / 2) {
+ n -= curwin->w_grid.Rows / 2;
+ } else {
n = 0;
- /* don't skip more than necessary */
- if (n > p_lines - curwin->w_height + 1)
- n = p_lines - curwin->w_height + 1;
+ }
+ // don't skip more than necessary
+ if (n > p_lines - curwin->w_grid.Rows + 1) {
+ n = p_lines - curwin->w_grid.Rows + 1;
+ }
curwin->w_skipcol = n * width;
} else if (extra == 1) {
/* less then 'scrolloff' lines above, decrease skipcol */
@@ -900,18 +911,20 @@ void curs_columns(
curwin->w_skipcol -= extra * width;
}
} else if (extra == 2) {
- /* less then 'scrolloff' lines below, increase skipcol */
- endcol = (n - curwin->w_height + 1) * width;
- while (endcol > curwin->w_virtcol)
+ // less then 'scrolloff' lines below, increase skipcol
+ endcol = (n - curwin->w_grid.Rows + 1) * width;
+ while (endcol > curwin->w_virtcol) {
endcol -= width;
- if (endcol > curwin->w_skipcol)
+ }
+ if (endcol > curwin->w_skipcol) {
curwin->w_skipcol = endcol;
+ }
}
curwin->w_wrow -= curwin->w_skipcol / width;
- if (curwin->w_wrow >= curwin->w_height) {
- /* small window, make sure cursor is in it */
- extra = curwin->w_wrow - curwin->w_height + 1;
+ if (curwin->w_wrow >= curwin->w_grid.Rows) {
+ // small window, make sure cursor is in it
+ extra = curwin->w_wrow - curwin->w_grid.Rows + 1;
curwin->w_skipcol += extra * width;
curwin->w_wrow -= extra;
}
@@ -953,9 +966,9 @@ scrolldown (
validate_cursor(); /* w_wrow needs to be valid */
while (line_count-- > 0) {
if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)
- && curwin->w_topfill < curwin->w_height - 1) {
- ++curwin->w_topfill;
- ++done;
+ && curwin->w_topfill < curwin->w_grid.Rows - 1) {
+ curwin->w_topfill++;
+ done++;
} else {
if (curwin->w_topline == 1)
break;
@@ -988,15 +1001,15 @@ scrolldown (
*/
int wrow = curwin->w_wrow;
if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
validate_virtcol();
validate_cheight();
wrow += curwin->w_cline_height - 1 -
- curwin->w_virtcol / curwin->w_width;
+ curwin->w_virtcol / curwin->w_grid.Columns;
}
bool moved = false;
- while (wrow >= curwin->w_height && curwin->w_cursor.lnum > 1) {
+ while (wrow >= curwin->w_grid.Rows && curwin->w_cursor.lnum > 1) {
linenr_T first;
if (hasFolding(curwin->w_cursor.lnum, &first, NULL)) {
--wrow;
@@ -1081,14 +1094,15 @@ check_topfill (
{
if (wp->w_topfill > 0) {
int n = plines_win_nofill(wp, wp->w_topline, true);
- if (wp->w_topfill + n > wp->w_height) {
+ if (wp->w_topfill + n > wp->w_grid.Rows) {
if (down && wp->w_topline > 1) {
--wp->w_topline;
wp->w_topfill = 0;
} else {
- wp->w_topfill = wp->w_height - n;
- if (wp->w_topfill < 0)
+ wp->w_topfill = wp->w_grid.Rows - n;
+ if (wp->w_topfill < 0) {
wp->w_topfill = 0;
+ }
}
}
}
@@ -1101,12 +1115,13 @@ check_topfill (
static void max_topfill(void)
{
int n = plines_nofill(curwin->w_topline);
- if (n >= curwin->w_height)
+ if (n >= curwin->w_grid.Rows) {
curwin->w_topfill = 0;
- else {
+ } else {
curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline);
- if (curwin->w_topfill + n > curwin->w_height)
- curwin->w_topfill = curwin->w_height - n;
+ if (curwin->w_topfill + n > curwin->w_grid.Rows) {
+ curwin->w_topfill = curwin->w_grid.Rows - n;
+ }
}
}
@@ -1137,14 +1152,14 @@ void scrolldown_clamp(void)
else
end_row += plines_nofill(curwin->w_topline - 1);
if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
validate_cheight();
validate_virtcol();
end_row += curwin->w_cline_height - 1 -
- curwin->w_virtcol / curwin->w_width;
+ curwin->w_virtcol / curwin->w_grid.Columns;
}
- if (end_row < curwin->w_height - p_so) {
+ if (end_row < curwin->w_grid.Rows - p_so) {
if (can_fill) {
++curwin->w_topfill;
check_topfill(curwin, true);
@@ -1179,10 +1194,10 @@ void scrollup_clamp(void)
int start_row = curwin->w_wrow - plines_nofill(curwin->w_topline)
- curwin->w_topfill;
if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
validate_virtcol();
- start_row -= curwin->w_virtcol / curwin->w_width;
+ start_row -= curwin->w_virtcol / curwin->w_grid.Columns;
}
if (start_row >= p_so) {
if (curwin->w_topfill > 0)
@@ -1336,10 +1351,12 @@ void scroll_cursor_top(int min_scroll, int always)
else
used += plines(bot);
}
- if (used > curwin->w_height)
+ if (used > curwin->w_grid.Rows) {
break;
- if (top < curwin->w_topline)
+ }
+ if (top < curwin->w_topline) {
scrolled += i;
+ }
/*
* If scrolling is needed, scroll at least 'sj' lines.
@@ -1359,7 +1376,7 @@ void scroll_cursor_top(int min_scroll, int always)
* This makes sure we get the same position when using "k" and "j"
* in a small window.
*/
- if (used > curwin->w_height) {
+ if (used > curwin->w_grid.Rows) {
scroll_cursor_halfway(false);
} else {
/*
@@ -1393,10 +1410,10 @@ void scroll_cursor_top(int min_scroll, int always)
void set_empty_rows(win_T *wp, int used)
{
wp->w_filler_rows = 0;
- if (used == 0)
- wp->w_empty_rows = 0; /* single line that doesn't fit */
- else {
- wp->w_empty_rows = wp->w_height - used;
+ if (used == 0) {
+ wp->w_empty_rows = 0; // single line that doesn't fit
+ } else {
+ wp->w_empty_rows = wp->w_grid.Rows - used;
if (wp->w_botline <= wp->w_buffer->b_ml.ml_line_count) {
wp->w_filler_rows = diff_check_fill(wp, wp->w_botline);
if (wp->w_empty_rows > wp->w_filler_rows)
@@ -1439,8 +1456,9 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
curwin->w_topline = loff.lnum) {
loff.lnum = curwin->w_topline;
topline_back(&loff);
- if (loff.height == MAXCOL || used + loff.height > curwin->w_height)
+ if (loff.height == MAXCOL || used + loff.height > curwin->w_grid.Rows) {
break;
+ }
used += loff.height;
curwin->w_topfill = loff.fill;
}
@@ -1497,12 +1515,14 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
/* Add one line above */
topline_back(&loff);
- if (loff.height == MAXCOL)
+ if (loff.height == MAXCOL) {
used = MAXCOL;
- else
+ } else {
used += loff.height;
- if (used > curwin->w_height)
+ }
+ if (used > curwin->w_grid.Rows) {
break;
+ }
if (loff.lnum >= curwin->w_botline
&& (loff.lnum > curwin->w_botline
|| loff.fill <= fill_below_window)
@@ -1519,8 +1539,9 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
/* Add one line below */
botline_forw(&boff);
used += boff.height;
- if (used > curwin->w_height)
+ if (used > curwin->w_grid.Rows) {
break;
+ }
if (extra < (
mouse_dragging > 0 ? mouse_dragging - 1 :
p_so) || scrolled < min_scroll) {
@@ -1541,14 +1562,14 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
}
linenr_T line_count;
- /* curwin->w_empty_rows is larger, no need to scroll */
- if (scrolled <= 0)
+ // curwin->w_empty_rows is larger, no need to scroll
+ if (scrolled <= 0) {
line_count = 0;
- /* more than a screenfull, don't scroll but redraw */
- else if (used > curwin->w_height)
+ // more than a screenfull, don't scroll but redraw
+ } else if (used > curwin->w_grid.Rows) {
line_count = used;
- /* scroll minimal number of lines */
- else {
+ // scroll minimal number of lines
+ } else {
line_count = 0;
boff.fill = curwin->w_topfill;
boff.lnum = curwin->w_topline - 1;
@@ -1566,10 +1587,11 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
* Scroll up if the cursor is off the bottom of the screen a bit.
* Otherwise put it at 1/2 of the screen.
*/
- if (line_count >= curwin->w_height && line_count > min_scroll)
+ if (line_count >= curwin->w_grid.Rows && line_count > min_scroll) {
scroll_cursor_halfway(false);
- else
+ } else {
scrollup(line_count, true);
+ }
/*
* If topline didn't change we need to restore w_botline and w_empty_rows
@@ -1608,8 +1630,9 @@ void scroll_cursor_halfway(int atend)
if (boff.lnum < curbuf->b_ml.ml_line_count) {
botline_forw(&boff);
used += boff.height;
- if (used > curwin->w_height)
+ if (used > curwin->w_grid.Rows) {
break;
+ }
below += boff.height;
} else {
++below; /* count a "~" line */
@@ -1624,8 +1647,9 @@ void scroll_cursor_halfway(int atend)
used = MAXCOL;
else
used += loff.height;
- if (used > curwin->w_height)
+ if (used > curwin->w_grid.Rows) {
break;
+ }
above += loff.height;
topline = loff.lnum;
topfill = loff.fill;
@@ -1634,8 +1658,9 @@ void scroll_cursor_halfway(int atend)
if (!hasFolding(topline, &curwin->w_topline, NULL))
curwin->w_topline = topline;
curwin->w_topfill = topfill;
- if (old_topline > curwin->w_topline + curwin->w_height)
+ if (old_topline > curwin->w_topline + curwin->w_grid.Rows) {
curwin->w_botfill = false;
+ }
check_topfill(curwin, false);
curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
curwin->w_valid |= VALID_TOPLINE;
@@ -1662,18 +1687,20 @@ void cursor_correct(void)
}
if (curwin->w_topline == 1) {
above_wanted = 0;
- int max_off = curwin->w_height / 2;
- if (below_wanted > max_off)
+ int max_off = curwin->w_grid.Rows / 2;
+ if (below_wanted > max_off) {
below_wanted = max_off;
+ }
}
validate_botline();
if (curwin->w_botline == curbuf->b_ml.ml_line_count + 1
&& mouse_dragging == 0
) {
below_wanted = 0;
- int max_off = (curwin->w_height - 1) / 2;
- if (above_wanted > max_off)
+ int max_off = (curwin->w_grid.Rows - 1) / 2;
+ if (above_wanted > max_off) {
above_wanted = max_off;
+ }
}
/*
@@ -1844,7 +1871,7 @@ int onepage(Direction dir, long count)
/* Find the line just above the new topline to get the right line
* at the bottom of the window. */
n = 0;
- while (n <= curwin->w_height && loff.lnum >= 1) {
+ while (n <= curwin->w_grid.Rows && loff.lnum >= 1) {
topline_back(&loff);
if (loff.height == MAXCOL)
n = MAXCOL;
@@ -1935,7 +1962,7 @@ int onepage(Direction dir, long count)
*/
static void get_scroll_overlap(lineoff_T *lp, int dir)
{
- int min_height = curwin->w_height - 2;
+ int min_height = curwin->w_grid.Rows - 2;
if (lp->fill > 0)
lp->height = 1;
@@ -1989,12 +2016,13 @@ void halfpage(bool flag, linenr_T Prenum)
long scrolled = 0;
int i;
- if (Prenum)
- curwin->w_p_scr = (Prenum > curwin->w_height) ?
- curwin->w_height : Prenum;
+ if (Prenum) {
+ curwin->w_p_scr = (Prenum > curwin->w_grid.Rows) ? curwin->w_grid.Rows
+ : Prenum;
+ }
assert(curwin->w_p_scr <= INT_MAX);
- int n = curwin->w_p_scr <= curwin->w_height ? (int)curwin->w_p_scr
- : curwin->w_height;
+ int n = curwin->w_p_scr <= curwin->w_grid.Rows ? (int)curwin->w_p_scr
+ : curwin->w_grid.Rows;
update_topline();
validate_botline();
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 46a9e95b91..76fbe407c2 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -495,8 +495,8 @@ static void broadcast_event(const char *name, Array args)
kv_size(subscribed));
for (size_t i = 0; i < kv_size(subscribed); i++) {
- Channel *channel = kv_A(subscribed, i);
- channel_write(channel, buffer);
+ Channel *c = kv_A(subscribed, i);
+ channel_write(c, buffer);
}
end:
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 38ee0936aa..29c5d27258 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1,11 +1,11 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * normal.c: Contains the main routine for processing characters in command
- * mode. Communicates closely with the code in ops.c to handle
- * the operators.
- */
+//
+// normal.c: Contains the main routine for processing characters in command
+// mode. Communicates closely with the code in ops.c to handle
+// the operators.
+//
#include <assert.h>
#include <inttypes.h>
@@ -1445,8 +1445,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
oap->motion_type = kMTCharWise;
} else if (oap->motion_force == Ctrl_V) {
// Change line- or characterwise motion into Visual block mode.
- VIsual_active = true;
- VIsual = oap->start;
+ if (!VIsual_active) {
+ VIsual_active = true;
+ VIsual = oap->start;
+ }
VIsual_mode = Ctrl_V;
VIsual_select = false;
VIsual_reselect = false;
@@ -2039,6 +2041,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
curwin->w_cursor = old_cursor;
}
clearop(oap);
+ motion_force = NUL;
}
curwin->w_p_lbr = lbr_saved;
}
@@ -2761,10 +2764,9 @@ do_mouse (
} else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))
&& mouse_has(MOUSE_VISUAL)) {
if (is_click || !VIsual_active) {
- if (VIsual_active)
+ if (VIsual_active) {
orig_cursor = VIsual;
- else {
- check_visual_highlight();
+ } else {
VIsual = curwin->w_cursor;
orig_cursor = VIsual;
VIsual_active = true;
@@ -2935,22 +2937,6 @@ static int get_mouse_class(char_u *p)
}
/*
- * Check if highlighting for visual mode is possible, give a warning message
- * if not.
- */
-void check_visual_highlight(void)
-{
- static bool did_check = false;
-
- if (full_screen) {
- if (!did_check && HL_ATTR(HLF_V) == 0) {
- MSG(_("Warning: terminal cannot highlight"));
- }
- did_check = true;
- }
-}
-
-/*
* End Visual mode.
* This function should ALWAYS be called to end Visual mode, except from
* do_pending_operator().
@@ -3466,10 +3452,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 +3463,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 */
}
@@ -3905,18 +3892,16 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
col_off1 = curwin_col_off();
col_off2 = col_off1 - curwin_col_off2();
- width1 = curwin->w_width - col_off1;
- width2 = curwin->w_width - col_off2;
+ width1 = curwin->w_grid.Columns - col_off1;
+ width2 = curwin->w_grid.Columns - col_off2;
if (width2 == 0) {
width2 = 1; // Avoid divide by zero.
}
- if (curwin->w_width != 0) {
- /*
- * Instead of sticking at the last character of the buffer line we
- * try to stick in the last column of the screen.
- */
+ if (curwin->w_grid.Columns != 0) {
+ // Instead of sticking at the last character of the buffer line we
+ // try to stick in the last column of the screen.
if (curwin->w_curswant == MAXCOL) {
atend = true;
validate_virtcol();
@@ -3957,9 +3942,11 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
linelen = linetabsize(get_cursor_line_ptr());
- if (linelen > width1)
- curwin->w_curswant += (((linelen - width1 - 1) / width2)
- + 1) * width2;
+ if (linelen > width1) {
+ int w = (((linelen - width1 - 1) / width2) + 1) * width2;
+ assert(curwin->w_curswant <= INT_MAX - w);
+ curwin->w_curswant += w;
+ }
}
} else { /* dir == FORWARD */
if (linelen > width1)
@@ -4255,7 +4242,7 @@ dozet:
/* "zH" - scroll screen right half-page */
case 'H':
- cap->count1 *= curwin->w_width / 2;
+ cap->count1 *= curwin->w_grid.Columns / 2;
FALLTHROUGH;
/* "zh" - scroll screen to the right */
@@ -4270,8 +4257,8 @@ dozet:
}
break;
- /* "zL" - scroll screen left half-page */
- case 'L': cap->count1 *= curwin->w_width / 2;
+ // "zL" - scroll screen left half-page
+ case 'L': cap->count1 *= curwin->w_grid.Columns / 2;
FALLTHROUGH;
/* "zl" - scroll screen to the left */
@@ -4307,11 +4294,12 @@ dozet:
col = 0; /* like the cursor is in col 0 */
else
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
- n = curwin->w_width - curwin_col_off();
- if (col + l_p_siso < n)
+ n = curwin->w_grid.Columns - curwin_col_off();
+ if (col + l_p_siso < n) {
col = 0;
- else
+ } else {
col = col + l_p_siso - n + 1;
+ }
if (curwin->w_leftcol != col) {
curwin->w_leftcol = col;
redraw_later(NOT_VALID);
@@ -5016,11 +5004,11 @@ static void nv_scroll(cmdarg_T *cap)
/* Don't count filler lines above the window. */
used -= diff_check_fill(curwin, curwin->w_topline)
- curwin->w_topfill;
- validate_botline(); /* make sure w_empty_rows is valid */
- half = (curwin->w_height - curwin->w_empty_rows + 1) / 2;
- for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; ++n) {
- /* Count half he number of filler lines to be "below this
- * line" and half to be "above the next line". */
+ validate_botline(); // make sure w_empty_rows is valid
+ half = (curwin->w_grid.Rows - curwin->w_empty_rows + 1) / 2;
+ for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; n++) {
+ // Count half he number of filler lines to be "below this
+ // line" and half to be "above the next line".
if (n > 0 && used + diff_check_fill(curwin, curwin->w_topline
+ n) / 2 >= half) {
--n;
@@ -5032,9 +5020,10 @@ static void nv_scroll(cmdarg_T *cap)
if (hasFolding(curwin->w_topline + n, NULL, &lnum))
n = lnum - curwin->w_topline;
}
- if (n > 0 && used > curwin->w_height)
- --n;
- } else { /* (cap->cmdchar == 'H') */
+ if (n > 0 && used > curwin->w_grid.Rows) {
+ n--;
+ }
+ } else { // (cap->cmdchar == 'H')
n = cap->count1 - 1;
if (hasAnyFolding(curwin)) {
/* Count a fold for one screen line. */
@@ -6403,8 +6392,8 @@ static void nv_visual(cmdarg_T *cap)
/* 'v', 'V' and CTRL-V can be used while an operator is pending to make it
* characterwise, linewise, or blockwise. */
if (cap->oap->op_type != OP_NOP) {
- cap->oap->motion_force = cap->cmdchar;
- finish_op = false; /* operator doesn't finish now but later */
+ motion_force = cap->oap->motion_force = cap->cmdchar;
+ finish_op = false; // operator doesn't finish now but later
return;
}
@@ -6417,9 +6406,8 @@ static void nv_visual(cmdarg_T *cap)
VIsual_mode = cap->cmdchar;
showmode();
}
- redraw_curbuf_later(INVERTED); /* update the inversion */
- } else { /* start Visual mode */
- check_visual_highlight();
+ redraw_curbuf_later(INVERTED); // update the inversion
+ } else { // start Visual mode
if (cap->count0 > 0 && resel_VIsual_mode != NUL) {
/* use previously selected part */
VIsual = curwin->w_cursor;
@@ -6747,9 +6735,9 @@ static void nv_g_cmd(cmdarg_T *cap)
oap->motion_type = kMTCharWise;
oap->inclusive = false;
if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
- int width1 = curwin->w_width - curwin_col_off();
+ int width1 = curwin->w_grid.Columns - curwin_col_off();
int width2 = width1 + curwin_col_off2();
validate_virtcol();
@@ -6761,10 +6749,11 @@ static void nv_g_cmd(cmdarg_T *cap)
/* Go to the middle of the screen line. When 'number' or
* 'relativenumber' is on and lines are wrapping the middle can be more
* to the left. */
- if (cap->nchar == 'm')
- i += (curwin->w_width - curwin_col_off()
+ if (cap->nchar == 'm') {
+ i += (curwin->w_grid.Columns - curwin_col_off()
+ ((curwin->w_p_wrap && i > 0)
? curwin_col_off2() : 0)) / 2;
+ }
coladvance((colnr_T)i);
if (flag) {
do
@@ -6808,11 +6797,11 @@ static void nv_g_cmd(cmdarg_T *cap)
oap->motion_type = kMTCharWise;
oap->inclusive = true;
if (curwin->w_p_wrap
- && curwin->w_width != 0
+ && curwin->w_grid.Columns != 0
) {
curwin->w_curswant = MAXCOL; /* so we stay at the end */
if (cap->count1 == 1) {
- int width1 = curwin->w_width - col_off;
+ int width1 = curwin->w_grid.Columns - col_off;
int width2 = width1 + curwin_col_off2();
validate_virtcol();
@@ -6838,7 +6827,7 @@ static void nv_g_cmd(cmdarg_T *cap)
} else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == false)
clearopbeep(oap);
} else {
- i = curwin->w_leftcol + curwin->w_width - col_off - 1;
+ i = curwin->w_leftcol + curwin->w_grid.Columns - col_off - 1;
coladvance((colnr_T)i);
/* Make sure we stick in this column. */
@@ -7953,7 +7942,7 @@ static void get_op_vcol(
colnr_T end;
if (VIsual_mode != Ctrl_V
- || (!initial && oap->end.col < curwin->w_width)) {
+ || (!initial && oap->end.col < curwin->w_grid.Columns)) {
return;
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 5a6e56299d..e9cb480647 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2670,7 +2670,6 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
colnr_T vcol;
int delcount;
int incr = 0;
- long j;
struct block_def bd;
char_u **y_array = NULL;
long nr_lines = 0;
@@ -2840,16 +2839,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
if (curbuf->terminal) {
- for (int i = 0; i < count; i++) { // -V756
- // feed the lines to the terminal
- for (size_t j = 0; j < y_size; j++) {
- if (j) {
- // terminate the previous line
- terminal_send(curbuf->terminal, "\n", 1);
- }
- terminal_send(curbuf->terminal, (char *)y_array[j], STRLEN(y_array[j]));
- }
- }
+ terminal_paste(count, y_array, y_size);
return;
}
@@ -3035,12 +3025,14 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
yanklen = (int)STRLEN(y_array[i]);
- /* calculate number of spaces required to fill right side of block*/
+ // calculate number of spaces required to fill right side of block
spaces = y_width + 1;
- for (j = 0; j < yanklen; j++)
+ for (long j = 0; j < yanklen; j++) {
spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0);
- if (spaces < 0)
+ }
+ if (spaces < 0) {
spaces = 0;
+ }
// insert the new text
totlen = (size_t)(count * (yanklen + spaces)
@@ -3050,21 +3042,21 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
ptr = newp;
memmove(ptr, oldp, (size_t)bd.textcol);
ptr += bd.textcol;
- /* may insert some spaces before the new text */
+ // may insert some spaces before the new text
memset(ptr, ' ', (size_t)bd.startspaces);
ptr += bd.startspaces;
- /* insert the new text */
- for (j = 0; j < count; ++j) {
+ // insert the new text
+ for (long j = 0; j < count; j++) {
memmove(ptr, y_array[i], (size_t)yanklen);
ptr += yanklen;
- /* insert block's trailing spaces only if there's text behind */
+ // insert block's trailing spaces only if there's text behind
if ((j < count - 1 || !shortline) && spaces) {
memset(ptr, ' ', (size_t)spaces);
ptr += spaces;
}
}
- /* may insert some spaces after the new text */
+ // may insert some spaces after the new text
memset(ptr, ' ', (size_t)bd.endspaces);
ptr += bd.endspaces;
// move the text after the cursor to the end of the line.
@@ -5697,12 +5689,12 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
// Timestamp is not saved for clipboard registers because clipboard registers
// are not saved in the ShaDa file.
- int i = 0;
+ size_t tv_idx = 0;
TV_LIST_ITER_CONST(lines, li, {
if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
goto err;
}
- reg->y_array[i++] = (char_u *)xstrdupnul(
+ reg->y_array[tv_idx++] = (char_u *)xstrdupnul(
(const char *)TV_LIST_ITEM_TV(li)->vval.v_string);
});
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 8c692f9f42..6b1c5c998f 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4322,6 +4322,10 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
if (p_uc && !old_value) {
ml_open_files();
}
+ } else if (pp == &p_pyx) {
+ if (p_pyx != 0 && p_pyx != 2 && p_pyx != 3) {
+ errmsg = e_invarg;
+ }
} else if (pp == &p_ul || pp == &curbuf->b_p_ul) {
// sync undo before 'undolevels' changes
// use the old value, otherwise u_sync() may not work properly
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 6a0d0e32e0..7b99b6f266 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -516,6 +516,7 @@ EXTERN char_u *p_pex; // 'patchexpr'
EXTERN char_u *p_pm; // 'patchmode'
EXTERN char_u *p_path; // 'path'
EXTERN char_u *p_cdpath; // 'cdpath'
+EXTERN long p_pyx; // 'pyxversion'
EXTERN long p_rdt; // 'redrawtime'
EXTERN int p_remap; // 'remap'
EXTERN long p_re; // 'regexpengine'
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 0cc6f58c5f..aba8f8b893 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1810,6 +1810,14 @@ return {
defaults={if_true={vi=0}}
},
{
+ full_name='pyxversion', abbreviation='pyx',
+ type='number', scope={'global'},
+ secure=true,
+ vi_def=true,
+ varname='p_pyx',
+ defaults={if_true={vi=0}}
+ },
+ {
full_name='quoteescape', abbreviation='qe',
type='string', scope={'buffer'},
vi_def=true,
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index 68c8967b91..056770f2c0 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -68,12 +68,12 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
int kind_width;
int extra_width;
int i;
- int row;
int context_lines;
- int col;
int above_row;
int below_row;
int redo_count = 0;
+ int row;
+ int col;
if (!pum_is_visible) {
// To keep the code simple, we only allow changing the
@@ -90,11 +90,18 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
below_row = cmdline_row;
// anchor position: the start of the completed word
- row = curwin->w_wrow + curwin->w_winrow;
+ row = curwin->w_wrow;
if (curwin->w_p_rl) {
- col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1;
+ col = curwin->w_width - curwin->w_wcol - 1;
} else {
- col = curwin->w_wincol + curwin->w_wcol;
+ col = curwin->w_wcol;
+ }
+
+ int grid = (int)curwin->w_grid.handle;
+ if (!ui_is_external(kUIMultigrid)) {
+ grid = (int)default_grid.handle;
+ row += curwin->w_winrow;
+ col += curwin->w_wincol;
}
if (pum_external) {
@@ -108,7 +115,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_info)));
ADD(arr, ARRAY_OBJ(item));
}
- ui_call_popupmenu_show(arr, selected, row, col);
+ ui_call_popupmenu_show(arr, selected, row, col, grid);
} else {
ui_call_popupmenu_select(selected);
}
@@ -351,10 +358,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 +423,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 +440,11 @@ 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,36 +475,37 @@ void pum_redraw(void)
}
if (curwin->w_p_rl) {
- screen_fill(row, row + 1, pum_col - pum_base_width - n + 1,
- col + 1, ' ', ' ', attr);
+ 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,
- ' ', ' ', attr);
+ grid_fill(&default_grid, row, row + 1, col,
+ pum_col + pum_base_width + n, ' ', ' ', attr);
col = pum_col + pum_base_width + n;
}
totwidth = pum_base_width + n;
}
if (curwin->w_p_rl) {
- screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ', ' ',
- attr);
+ 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,
- i >= thumb_pos && i < thumb_pos + thumb_heigth
- ? attr_thumb : attr_scroll);
+ 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,
- i >= thumb_pos && i < thumb_pos + thumb_heigth
- ? attr_thumb : attr_scroll);
+ 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/quickfix.c b/src/nvim/quickfix.c
index d9e307bb71..4eeddf1d5a 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -925,11 +925,11 @@ restofline:
return QF_FAIL;
}
if (*fields->errmsg) {
- size_t len = STRLEN(qfprev->qf_text);
+ size_t textlen = STRLEN(qfprev->qf_text);
qfprev->qf_text = xrealloc(qfprev->qf_text,
- len + STRLEN(fields->errmsg) + 2);
- qfprev->qf_text[len] = '\n';
- STRCPY(qfprev->qf_text + len + 1, fields->errmsg);
+ textlen + STRLEN(fields->errmsg) + 2);
+ qfprev->qf_text[textlen] = '\n';
+ STRCPY(qfprev->qf_text + textlen + 1, fields->errmsg);
}
if (qfprev->qf_nr == -1) {
qfprev->qf_nr = fields->enr;
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index d62a009fbc..0b9e1cfdec 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -4920,7 +4920,7 @@ regmatch (
}
} else {
const char_u *const line =
- reg_getline(behind_pos.rs_u.pos.lnum);
+ reg_getline(rp->rs_un.regsave.rs_u.pos.lnum);
rp->rs_un.regsave.rs_u.pos.col -=
utf_head_off(line,
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index d095bdb7c8..513f8dac9a 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -7,8 +7,7 @@
// by remembering what is already on the screen, and only updating the parts
// that changed.
//
-// The screen_*() functions write to the screen and handle updating
-// ScreenLines[].
+// The grid_*() functions write to the screen and handle updating grid->lines[].
//
// update_screen() is the function that updates all windows and status lines.
// It is called from the main loop when must_redraw is non-zero. It may be
@@ -74,6 +73,7 @@
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
+#include "nvim/cursor_shape.h"
#include "nvim/diff.h"
#include "nvim/eval.h"
#include "nvim/ex_cmds.h"
@@ -119,17 +119,21 @@
#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_ENDROW(wp) (wp->w_winrow + wp->w_height)
+
+
+// temporary buffer for rendering a single screenline, so it can be
+// comparared with previous contents to calulate smallest delta.
+static size_t linebuf_size = 0;
+static schar_T *linebuf_char = NULL;
+static sattr_T *linebuf_attr = NULL;
static match_T search_hl; /* used for 'hlsearch' highlight matching */
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;
+
long tab_page_click_defs_size = 0;
// for line_putchar. Contains the state that needs to be remembered from
@@ -141,6 +145,12 @@ typedef struct {
} LineState;
#define LINE_STATE(p) { p, 0, 0 }
+/// Whether to call "ui_call_grid_resize" in win_grid_alloc
+static bool send_grid_resize = false;
+
+/// Highlight ids are no longer valid. Force retransmission
+static bool highlights_invalid = false;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "screen.c.generated.h"
#endif
@@ -175,6 +185,16 @@ void redraw_all_later(int type)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
redraw_win_later(wp, type);
}
+ // This may be needed when switching tabs.
+ if (must_redraw < type) {
+ must_redraw = type;
+ }
+}
+
+void screen_invalidate_highlights(void)
+{
+ redraw_all_later(NOT_VALID);
+ highlights_invalid = true;
}
/*
@@ -194,6 +214,15 @@ void redraw_buf_later(buf_T *buf, int type)
}
}
+void redraw_buf_line_later(buf_T *buf, linenr_T line)
+{
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == buf) {
+ redrawWinline(wp, line);
+ }
+ }
+}
+
/*
* Changed something in the current window, at buffer line "lnum", that
* requires that line and possibly other lines to be redrawn.
@@ -205,12 +234,11 @@ void redraw_buf_later(buf_T *buf, int type)
void
redrawWinline(
win_T *wp,
- linenr_T lnum,
- int invalid /* window line height is invalid now */
+ linenr_T lnum
)
{
- int i;
-
+ if (lnum >= wp->w_topline
+ && lnum < wp->w_botline) {
if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum) {
wp->w_redraw_top = lnum;
}
@@ -218,13 +246,6 @@ redrawWinline(
wp->w_redraw_bot = lnum;
}
redraw_win_later(wp, VALID);
-
- if (invalid) {
- // A w_lines[] entry for this lnum has become invalid.
- i = find_wl_entry(wp, lnum);
- if (i >= 0) {
- wp->w_lines[i].wl_valid = false;
- }
}
}
@@ -237,12 +258,12 @@ void update_curbuf(int type)
update_screen(type);
}
-/*
- * update_screen()
- *
- * Based on the current value of curwin->w_topline, transfer a screenfull
- * of stuff from Filemem to ScreenLines[], and update curwin->w_botline.
- */
+/// Redraw the parts of the screen that is marked for redraw.
+///
+/// Most code shouldn't call this directly, rather use redraw_later() and
+/// and redraw_all_later() to mark parts of the screen as needing a redraw.
+///
+/// @param type set to a NOT_VALID to force redraw of entire screen
void update_screen(int type)
{
static int did_intro = FALSE;
@@ -285,6 +306,7 @@ void update_screen(int type)
* if the screen was scrolled up when displaying a message, scroll it down
*/
if (msg_scrolled) {
+ ui_call_win_scroll_over_reset();
clear_cmdline = true;
if (dy_flags & DY_MSGSEP) {
int valid = MAX(Rows - msg_scrollsize(), 0);
@@ -292,25 +314,25 @@ void update_screen(int type)
redraw_tabline = true;
}
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_winrow + wp->w_height > valid) {
+ if (W_ENDROW(wp) > valid) {
wp->w_redr_type = NOT_VALID;
wp->w_lines_valid = 0;
}
- if (wp->w_winrow + wp->w_height + wp->w_status_height > valid) {
+ if (W_ENDROW(wp) + wp->w_status_height > valid) {
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) {
if (wp->w_winrow < msg_scrolled) {
- if (wp->w_winrow + wp->w_height > msg_scrolled
+ if (W_ENDROW(wp) > msg_scrolled
&& wp->w_redr_type < REDRAW_TOP
&& wp->w_lines_valid > 0
&& wp->w_topline == wp->w_lines[0].wl_lnum) {
@@ -318,7 +340,7 @@ void update_screen(int type)
wp->w_redr_type = REDRAW_TOP;
} else {
wp->w_redr_type = NOT_VALID;
- if (wp->w_winrow + wp->w_height + wp->w_status_height
+ if (W_ENDROW(wp) + wp->w_status_height
<= msg_scrolled) {
wp->w_redr_status = TRUE;
}
@@ -345,6 +367,8 @@ void update_screen(int type)
type = NOT_VALID;
// must_redraw may be set indirectly, avoid another redraw later
must_redraw = 0;
+ } else if (highlights_invalid) {
+ grid_invalidate(&default_grid);
}
if (clear_cmdline) /* going to clear cmdline (done below) */
@@ -430,6 +454,8 @@ void update_screen(int type)
win_redr_status(wp, true); // any popup menu will be redrawn below
}
}
+ send_grid_resize = false;
+ highlights_invalid = false;
end_search_hl();
// May need to redraw the popup menu.
if (pum_drawn()) {
@@ -456,6 +482,25 @@ void update_screen(int type)
}
+// Prepare for updating one or more windows.
+// Caller must check for "updating_screen" already set to avoid recursiveness.
+static void update_prepare(void)
+{
+ updating_screen = true;
+ start_search_hl();
+}
+
+// Finish updating one or more windows.
+static void update_finish(void)
+{
+ if (redraw_cmdline) {
+ showmode();
+ }
+
+ end_search_hl();
+ updating_screen = false;
+}
+
/*
* Return TRUE if the cursor line in window "wp" may be concealed, according
* to the 'concealcursor' option.
@@ -498,107 +543,33 @@ 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 (linebuf_char == NULL || updating_screen) {
return;
}
- updating_screen = true;
if (lnum >= wp->w_topline && lnum < wp->w_botline
&& foldedCount(wp, lnum, &win_foldinfo) == 0) {
+ update_prepare();
+
row = 0;
for (j = 0; j < wp->w_lines_valid; ++j) {
if (lnum == wp->w_lines[j].wl_lnum) {
init_search_hl(wp);
- start_search_hl();
prepare_search_hl(wp, lnum);
update_window_hl(wp, false);
+ // allocate window grid if not already
+ win_grid_alloc(wp);
win_line(wp, lnum, row, row + wp->w_lines[j].wl_size, false, false);
- end_search_hl();
break;
}
row += wp->w_lines[j].wl_size;
}
+
+ update_finish();
}
need_cursor_line_redraw = false;
- updating_screen = false;
-}
-
-
-/*
- * Prepare for updating one or more windows.
- * Caller must check for "updating_screen" already set to avoid recursiveness.
- */
-static void update_prepare(void)
-{
- updating_screen = TRUE;
- start_search_hl();
}
-/*
- * Finish updating one or more windows.
- */
-static void update_finish(void)
-{
- if (redraw_cmdline) {
- showmode();
- }
-
- end_search_hl();
- updating_screen = FALSE;
-}
-
-void update_debug_sign(const buf_T *const buf, const linenr_T lnum)
-{
- bool doit = false;
- win_foldinfo.fi_level = 0;
-
- // update/delete a specific mark
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (buf != NULL && lnum > 0) {
- if (wp->w_buffer == buf && lnum >= wp->w_topline
- && lnum < wp->w_botline) {
- if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum) {
- wp->w_redraw_top = lnum;
- }
- if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum) {
- wp->w_redraw_bot = lnum;
- }
- redraw_win_later(wp, VALID);
- }
- } else {
- redraw_win_later(wp, VALID);
- }
- if (wp->w_redr_type != 0) {
- doit = true;
- }
- }
-
- // Return when there is nothing to do, screen updating is already
- // happening (recursive call), messages on the screen or still starting up.
- if (!doit
- || updating_screen
- || State == ASKMORE
- || State == HITRETURN
- || msg_scrolled
- || starting) {
- return;
- }
-
- // update all windows that need updating
- update_prepare();
-
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_redr_type != 0) {
- update_window_hl(wp, wp->w_redr_type >= NOT_VALID);
- win_update(wp);
- }
- if (wp->w_redr_status) {
- win_redr_status(wp, false);
- }
- }
-
- update_finish();
-}
/*
* Update a single window.
@@ -656,11 +627,10 @@ static void win_update(win_T *wp)
static int recursive = FALSE; /* being called recursively */
int old_botline = wp->w_botline;
long fold_count;
- /* remember what happened to the previous line, to know if
- * check_visual_highlight() can be used */
-#define DID_NONE 1 /* didn't update a line */
-#define DID_LINE 2 /* updated a normal line */
-#define DID_FOLD 3 /* updated a folded line */
+ // Remember what happened to the previous line.
+#define DID_NONE 1 // didn't update a line
+#define DID_LINE 2 // updated a normal line
+#define DID_FOLD 3 // updated a folded line
int did_update = DID_NONE;
linenr_T syntax_last_parsed = 0; /* last parsed text line */
linenr_T mod_top = 0;
@@ -669,20 +639,22 @@ static void win_update(win_T *wp)
type = wp->w_redr_type;
+ win_grid_alloc(wp);
+
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) {
+ // Window is zero-height: nothing to draw.
+ 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) {
- /* draw the vertical separator right of this window */
+ // Window is zero-width: Only need to draw the separator.
+ if (wp->w_grid.Columns == 0) {
+ // draw the vertical separator right of this window
draw_vsep_win(wp, 0);
wp->w_redr_type = 0;
return;
@@ -699,8 +671,8 @@ static void win_update(win_T *wp)
if (buf->terminal) {
terminal_resize(buf->terminal,
- (uint16_t)(MAX(0, wp->w_width - win_col_off(wp))),
- (uint16_t)wp->w_height);
+ (uint16_t)(MAX(0, wp->w_grid.Columns - win_col_off(wp))),
+ (uint16_t)wp->w_grid.Rows);
}
} else if (buf->b_mod_set
&& buf->b_mod_xlines != 0
@@ -870,21 +842,22 @@ static void win_update(win_T *wp)
/* count the number of lines we are off, counting a sequence
* of folded lines as one */
j = 0;
- for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ++ln) {
- ++j;
- if (j >= wp->w_height - 2)
+ for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ln++) {
+ j++;
+ 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.
@@ -897,12 +870,15 @@ 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;
- for (idx = wp->w_lines_valid; idx - j >= 0; idx--)
+ 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)
- wp->w_lines[idx--].wl_valid = FALSE;
+ }
+ while (idx >= 0) {
+ wp->w_lines[idx--].wl_valid = false;
+ }
}
} else
mid_start = 0; /* redraw all lines */
@@ -947,7 +923,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
}
@@ -966,7 +942,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;
}
@@ -990,18 +966,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;
}
@@ -1146,8 +1122,8 @@ static void win_update(win_T *wp)
++lnum;
}
srow += mid_start;
- mid_end = wp->w_height;
- for (; idx < wp->w_lines_valid; ++idx) { /* find end */
+ 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) {
/* Only update until first row of this line */
@@ -1187,8 +1163,8 @@ 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) {
- didline = TRUE;
+ if (row == wp->w_grid.Rows) {
+ didline = true;
break;
}
@@ -1286,8 +1262,8 @@ static void win_update(win_T *wp)
new_rows += plines_win(wp, l, true);
}
j++;
- if (new_rows > wp->w_height - row - 2) {
- /* it's getting too much, must redraw the rest */
+ if (new_rows > wp->w_grid.Rows - row - 2) {
+ // it's getting too much, must redraw the rest
new_rows = 9999;
break;
}
@@ -1298,20 +1274,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) {
@@ -1340,7 +1316,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;
}
@@ -1353,10 +1329,12 @@ 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;
- for (i = wp->w_lines_valid; i - j >= idx; --i)
+ 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];
+ }
/* The w_lines[] entries for inserted lines are
* now invalid, but wl_size may be used above.
@@ -1388,12 +1366,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. */
@@ -1404,7 +1382,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;
@@ -1415,10 +1393,7 @@ static void win_update(win_T *wp)
wp->w_lines[idx].wl_lnum = lnum;
wp->w_lines[idx].wl_valid = true;
- // 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) { // past end of grid
// 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);
@@ -1434,13 +1409,19 @@ static void win_update(win_T *wp)
if (wp->w_p_rnu) {
// 'relativenumber' set: The text doesn't need to be drawn, but
// the number column nearly always does.
- (void)win_line(wp, lnum, srow, wp->w_height, true, true);
+ fold_count = foldedCount(wp, lnum, &win_foldinfo);
+ if (fold_count != 0) {
+ fold_line(wp, fold_count, &win_foldinfo, lnum, row);
+ } else {
+ (void)win_line(wp, lnum, srow, wp->w_grid.Rows, true, true);
+ }
}
// 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;
}
@@ -1479,31 +1460,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) {
- /* Window ends in filler lines. */
+ } 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_grid.Rows - 1, wp->w_grid.Rows,
+ 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 {
@@ -1518,8 +1496,9 @@ 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;
}
@@ -1528,7 +1507,7 @@ static void win_update(win_T *wp)
// make sure the rest of the screen is blank
// write the 'fill_eob' character to rows that aren't part of the file.
- win_draw_end(wp, fill_eob, ' ', row, wp->w_height, HLF_EOB);
+ win_draw_end(wp, fill_eob, ' ', row, wp->w_grid.Rows, HLF_EOB);
}
if (wp->w_redr_type >= REDRAW_TOP) {
@@ -1607,71 +1586,67 @@ static void win_draw_end(win_T *wp, int c1, int c2, int row, int endrow, hlf_T h
n = fdc;
if (n > 0) {
- /* 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));
+ // draw the fold column at the right
+ if (n > wp->w_grid.Columns) {
+ n = wp->w_grid.Columns;
+ }
+ 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)) {
int nn = n + win_signcol_width(wp);
- /* draw the sign column left of the fold column */
- if (nn > wp->w_width) {
- nn = wp->w_width;
+ // draw the sign column left of the fold column
+ if (nn > wp->w_grid.Columns) {
+ nn = wp->w_grid.Columns;
}
- 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));
+ if (n > wp->w_grid.Columns) {
+ n = wp->w_grid.Columns;
+ }
+ grid_fill(&wp->w_grid, row, endrow, 0, n, cmdwin_type, ' ',
+ win_hl_attr(wp, HLF_AT));
}
if (fdc > 0) {
int nn = n + fdc;
- /* 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));
+ // draw the fold column at the left
+ if (nn > wp->w_grid.Columns) {
+ nn = wp->w_grid.Columns;
+ }
+ grid_fill(&wp->w_grid, row, endrow, n, nn, ' ', ' ',
+ win_hl_attr(wp, HLF_FC));
n = nn;
}
if (signcolumn_on(wp)) {
int nn = n + win_signcol_width(wp);
- /* draw the sign column after the fold column */
- if (nn > wp->w_width) {
- nn = wp->w_width;
+ // draw the sign column after the fold column
+ if (nn > wp->w_grid.Columns) {
+ nn = wp->w_grid.Columns;
}
- 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);
}
@@ -1693,7 +1668,7 @@ static int compute_foldcolumn(win_T *wp, int col)
{
int fdc = wp->w_p_fdc;
int wmw = wp == curwin && p_wmw == 0 ? 1 : p_wmw;
- int wwidth = wp->w_width;
+ int wwidth = wp->w_grid.Columns;
if (fdc > wwidth - (col + wmw)) {
fdc = wwidth - (col + wmw);
@@ -1764,7 +1739,7 @@ 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;
/* Build the fold line:
@@ -1776,14 +1751,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 = 0;
/*
* 1. Add the cmdwin_type for the command-line window
* Ignores 'rightleft', this window is never right-left.
*/
if (cmdwin_type != 0 && wp == curwin) {
- schar_from_ascii(ScreenLines[off], cmdwin_type);
- ScreenAttrs[off] = win_hl_attr(wp, HLF_AT);
+ schar_from_ascii(linebuf_char[off], cmdwin_type);
+ linebuf_attr[off] = win_hl_attr(wp, HLF_AT);
col++;
}
@@ -1795,11 +1771,12 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
if (wp->w_p_rl) {
int i;
- copy_text_attr(off + wp->w_width - fdc - col, buf, fdc,
+ copy_text_attr(off + wp->w_grid.Columns - fdc - col, buf, fdc,
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(linebuf_char[off + wp->w_grid.Columns - i - 1 - col],
+ buf[i]);
}
} else {
copy_text_attr(off + col, buf, fdc, win_hl_attr(wp, HLF_FC));
@@ -1807,20 +1784,23 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
col += fdc;
}
-# 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; \
- else \
- for (ri = 0; ri < l; ++ri) \
- ScreenAttrs[off + (p) + ri] = v
+# define RL_MEMSET(p, v, l) if (wp->w_p_rl) { \
+ for (ri = 0; ri < l; ri++) { \
+ linebuf_attr[off + (wp->w_grid.Columns - (p) - (l)) + ri] = v; \
+ } \
+ } else { \
+ for (ri = 0; ri < l; ri++) { \
+ linebuf_attr[off + (p) + ri] = v; \
+ } \
+ }
/* Set all attributes of the 'number' or 'relativenumber' column and the
* text */
- RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_width - col);
+ RL_MEMSET(col, win_hl_attr(wp, HLF_FL), wp->w_grid.Columns - col);
// If signs are being displayed, add spaces.
if (signcolumn_on(wp)) {
- len = wp->w_width - col;
+ len = wp->w_grid.Columns - col;
if (len > 0) {
int len_max = win_signcol_width(wp);
if (len > len_max) {
@@ -1836,7 +1816,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
* 3. Add the 'number' or 'relativenumber' column
*/
if (wp->w_p_nu || wp->w_p_rnu) {
- len = wp->w_width - col;
+ len = wp->w_grid.Columns - col;
if (len > 0) {
int w = number_width(wp);
long num;
@@ -1862,7 +1842,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
snprintf((char *)buf, FOLD_TEXT_LEN, fmt, w, num);
if (wp->w_p_rl) {
// the line number isn't reversed
- copy_text_attr(off + wp->w_width - len - col, buf, len,
+ copy_text_attr(off + wp->w_grid.Columns - len - col, buf, len,
win_hl_attr(wp, HLF_FL));
} else {
copy_text_attr(off + col, buf, len, win_hl_attr(wp, HLF_FL));
@@ -1878,11 +1858,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 linebuf_char[off]. Fill up with "fill_fold".
+ // Right-left text is put in columns 0 - number-col, normal text is put
+ // in columns number-col - window-width.
int idx;
if (wp->w_p_rl) {
@@ -1898,8 +1876,8 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
// if(col + cells > wp->w_width - (wp->w_p_rl ? col : 0)) { break; }
// This is obvious wrong. If Vim ever fixes this, solve for "cells" again
// in the correct condition.
- int maxcells = wp->w_width - col - (wp->w_p_rl ? col : 0);
- int cells = line_putchar(&s, &ScreenLines[idx], maxcells, wp->w_p_rl);
+ int maxcells = wp->w_grid.Columns - col - (wp->w_p_rl ? col : 0);
+ int cells = line_putchar(&s, &linebuf_char[idx], maxcells, wp->w_p_rl);
if (cells == -1) {
break;
}
@@ -1913,10 +1891,10 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
schar_T sc;
schar_from_char(sc, fill_fold);
- while (col < wp->w_width
+ while (col < wp->w_grid.Columns
- (wp->w_p_rl ? txtcol : 0)
) {
- schar_copy(ScreenLines[off+col++], sc);
+ schar_copy(linebuf_char[off+col++], sc);
}
if (text != buf)
@@ -1948,20 +1926,21 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
>= (colnr_T)STRLEN(ml_get_buf(wp->w_buffer, lnume,
FALSE))))))) {
if (VIsual_mode == Ctrl_V) {
- /* Visual block mode: highlight the chars part of the block */
- if (wp->w_old_cursor_fcol + txtcol < (colnr_T)wp->w_width) {
+ // Visual block mode: highlight the chars part of the block
+ if (wp->w_old_cursor_fcol + txtcol < (colnr_T)wp->w_grid.Columns) {
if (wp->w_old_cursor_lcol != MAXCOL
&& wp->w_old_cursor_lcol + txtcol
- < (colnr_T)wp->w_width)
+ < (colnr_T)wp->w_grid.Columns) {
len = wp->w_old_cursor_lcol;
- else
- len = wp->w_width - txtcol;
+ } else {
+ len = wp->w_grid.Columns - txtcol;
+ }
RL_MEMSET(wp->w_old_cursor_fcol + txtcol, win_hl_attr(wp, HLF_V),
len - (int)wp->w_old_cursor_fcol);
}
} else {
// Set all attributes of the text
- RL_MEMSET(txtcol, win_hl_attr(wp, HLF_V), wp->w_width - txtcol);
+ RL_MEMSET(txtcol, win_hl_attr(wp, HLF_V), wp->w_grid.Columns - txtcol);
}
}
}
@@ -1979,9 +1958,9 @@ 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_MC));
+ if (txtcol >= 0 && txtcol < wp->w_grid.Columns) {
+ linebuf_attr[off + txtcol] =
+ hl_combine_attr(linebuf_attr[off + txtcol], win_hl_attr(wp, HLF_MC));
}
txtcol = old_txtcol;
j = wp->w_p_cc_cols[++i];
@@ -1995,13 +1974,14 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
txtcol -= wp->w_skipcol;
else
txtcol -= wp->w_leftcol;
- if (txtcol >= 0 && txtcol < wp->w_width)
- ScreenAttrs[off + txtcol] = hl_combine_attr(
- ScreenAttrs[off + txtcol], win_hl_attr(wp, HLF_CUC));
+ if (txtcol >= 0 && txtcol < wp->w_grid.Columns) {
+ linebuf_attr[off + txtcol] = hl_combine_attr(
+ linebuf_attr[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_put_linebuf(&wp->w_grid, row, 0, wp->w_grid.Columns, wp->w_grid.Columns,
+ false, wp, wp->w_hl_attr_normal, false);
/*
* Update w_cline_height and w_cline_folded if the cursor line was
@@ -2018,7 +1998,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
}
-/// Copy "buf[len]" to ScreenLines["off"] and set attributes to "attr".
+/// Copy "buf[len]" to linebuf_char["off"] and set attributes to "attr".
///
/// Only works for ASCII text!
static void copy_text_attr(int off, char_u *buf, int len, int attr)
@@ -2026,8 +2006,8 @@ static void copy_text_attr(int off, char_u *buf, int len, int attr)
int i;
for (i = 0; i < len; i++) {
- schar_from_ascii(ScreenLines[off + i], buf[i]);
- ScreenAttrs[off + i] = attr;
+ schar_from_ascii(linebuf_char[off + i], buf[i]);
+ linebuf_attr[off + i] = attr;
}
}
@@ -2102,7 +2082,6 @@ win_line (
bool number_only // only update the number column
)
{
- unsigned off; // offset in ScreenLines/ScreenAttrs
int c = 0; // init for GCC
long vcol = 0; // virtual column (for tabs)
long vcol_sbr = -1; // virtual column after showbreak
@@ -2110,7 +2089,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 */
@@ -2155,10 +2134,10 @@ win_line (
int syntax_attr = 0; /* attributes desired by syntax */
int has_syntax = FALSE; /* this buffer has syntax highl. */
int save_did_emsg;
- int eol_hl_off = 0; /* 1 if highlighted char after EOL */
- int draw_color_col = FALSE; /* highlight colorcolumn */
- int *color_cols = NULL; /* pointer to according columns array */
- bool has_spell = false; /* this buffer has spell checking */
+ int eol_hl_off = 0; // 1 if highlighted char after EOL
+ int draw_color_col = false; // highlight colorcolumn
+ int *color_cols = NULL; // pointer to according columns array
+ bool has_spell = false; // this buffer has spell checking
# define SPWORDLEN 150
char_u nextline[SPWORDLEN * 2]; /* text with start of the next line */
int nextlinecol = 0; /* column where nextline[] starts */
@@ -2240,7 +2219,6 @@ win_line (
return startrow;
row = startrow;
- screen_row = row + wp->w_winrow;
if (!number_only) {
// To speed up the loop below, set extra_check when there is linebreak,
@@ -2365,8 +2343,9 @@ win_line (
}
}
- // Check if the character under the cursor should not be inverted
- if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin) {
+ // Check if the char under the cursor should be inverted (highlighted).
+ if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin
+ && cursor_is_block_during_visual(*p_sel == 'e')) {
noinvcur = true;
}
@@ -2677,13 +2656,13 @@ win_line (
cur = cur->next;
}
- off = (unsigned)(current_ScreenLine - ScreenLines);
+ unsigned off = 0; // Offset relative start of line
int col = 0; // Visual column on screen.
if (wp->w_p_rl) {
// Rightleft window: process the text in the normal direction, but put
- // it in current_ScreenLine[] from right to left. Start at the
+ // it in linebuf_char[off] from right to left. Start at the
// rightmost column of the window.
- col = wp->w_width - 1;
+ col = grid->Columns - 1;
off += col;
}
@@ -2858,10 +2837,11 @@ win_line (
c_extra = '-';
else
c_extra = fill_diff;
- if (wp->w_p_rl)
+ if (wp->w_p_rl) {
n_extra = col + 1;
- else
- n_extra = wp->w_width - col;
+ } else {
+ n_extra = grid->Columns - col;
+ }
char_attr = win_hl_attr(wp, HLF_DED);
}
if (*p_sbr != NUL && need_showbreak) {
@@ -2902,20 +2882,20 @@ 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_put_linebuf(grid, row, 0, col, -grid->Columns, wp->w_p_rl, wp,
+ wp->w_hl_attr_normal, false);
// Pretend we have finished updating the window. Except when
// 'cursorcolumn' is set.
if (wp->w_p_cuc) {
row = wp->w_cline_row + wp->w_cline_height;
} else {
- row = wp->w_height;
+ row = grid->Rows;
}
break;
}
- if (draw_state == WL_LINE && area_highlighting) {
- /* handle Visual or match highlighting in this line */
+ if (draw_state == WL_LINE && (area_highlighting || has_spell)) {
+ // handle Visual or match highlighting in this line
if (vcol == fromcol
|| (vcol + 1 == fromcol && n_extra == 0
&& utf_ptr2cells(ptr) > 1)
@@ -3130,9 +3110,8 @@ win_line (
/* If a double-width char doesn't fit display a '>' in the
* last column. */
- if ((
- wp->w_p_rl ? (col <= 0) :
- (col >= wp->w_width - 1))
+ if ((wp->w_p_rl ? (col <= 0) :
+ (col >= grid->Columns - 1))
&& (*mb_char2cells)(mb_c) == 2) {
c = '>';
mb_c = c;
@@ -3272,9 +3251,8 @@ win_line (
/* If a double-width char doesn't fit display a '>' in the
* last column; the character is displayed at the start of the
* next line. */
- if ((
- wp->w_p_rl ? (col <= 0) :
- (col >= wp->w_width - 1))
+ if ((wp->w_p_rl ? (col <= 0) :
+ (col >= grid->Columns - 1))
&& (*mb_char2cells)(mb_c) == 2) {
c = '>';
mb_c = c;
@@ -3448,7 +3426,7 @@ win_line (
char_u *p = ptr - (mb_off + 1);
// TODO: is passing p for start of the line OK?
n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, NULL) - 1;
- if (c == TAB && n_extra + col > wp->w_width) {
+ if (c == TAB && n_extra + col > grid->Columns) {
n_extra = (int)wp->w_buffer->b_p_ts
- vcol % (int)wp->w_buffer->b_p_ts - 1;
}
@@ -3504,8 +3482,7 @@ win_line (
*/
if (!vim_isprintc(c)) {
// when getting a character from the file, we may have to
- // turn it into something else on the way to putting it
- // into "ScreenLines".
+ // turn it into something else on the way to putting it on the screen.
if (c == TAB && (!wp->w_p_list || lcs_tab1)) {
int tab_len = 0;
long vcol_adjusted = vcol; // removed showbreak length
@@ -3605,9 +3582,7 @@ win_line (
|| ((fromcol >= 0 || fromcol_prev >= 0)
&& tocol > vcol
&& VIsual_mode != Ctrl_V
- && (
- wp->w_p_rl ? (col >= 0) :
- (col < wp->w_width))
+ && (wp->w_p_rl ? (col >= 0) : (col < grid->Columns))
&& !(noinvcur
&& lnum == wp->w_cursor.lnum
&& (colnr_T)vcol == wp->w_virtcol)))
@@ -3672,14 +3647,11 @@ win_line (
saved_attr2 = char_attr; // save current attr
mb_utf8 = false; // don't draw as UTF-8
} else if (VIsual_active
- && (VIsual_mode == Ctrl_V
- || VIsual_mode == 'v')
+ && (VIsual_mode == Ctrl_V || VIsual_mode == 'v')
&& virtual_active()
&& tocol != MAXCOL
&& vcol < tocol
- && (
- wp->w_p_rl ? (col >= 0) :
- (col < wp->w_width))) {
+ && (wp->w_p_rl ? (col >= 0) : (col < grid->Columns))) {
c = ' ';
ptr--; // put it back at the NUL
}
@@ -3749,7 +3721,7 @@ win_line (
&& conceal_cursor_line(wp)
&& (int)wp->w_virtcol <= vcol + n_skip) {
if (wp->w_p_rl) {
- wp->w_wcol = wp->w_width - col + boguscols - 1;
+ wp->w_wcol = grid->Columns - col + boguscols - 1;
} else {
wp->w_wcol = col - boguscols;
}
@@ -3837,8 +3809,9 @@ win_line (
if (col < 0)
n = 1;
} else {
- if (col >= wp->w_width)
+ if (col >= grid->Columns) {
n = -1;
+ }
}
if (n != 0) {
/* At the window boundary, highlight the last character
@@ -3847,7 +3820,7 @@ win_line (
col += n;
} else {
// Add a blank character to highlight.
- schar_from_ascii(ScreenLines[off], ' ');
+ schar_from_ascii(linebuf_char[off], ' ');
}
if (area_attr == 0) {
/* Use attributes from match with highest priority among
@@ -3878,7 +3851,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;
+ linebuf_attr[off] = eol_attr;
if (wp->w_p_rl) {
--col;
--off;
@@ -3910,7 +3883,7 @@ win_line (
if (((wp->w_p_cuc
&& (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off
&& (int)wp->w_virtcol <
- wp->w_width * (row - startrow + 1) + v
+ grid->Columns * (row - startrow + 1) + v
&& lnum != wp->w_cursor.lnum)
|| draw_color_col || line_attr_lowprio || line_attr
|| diff_hlf != (hlf_T)0 || do_virttext)) {
@@ -3958,7 +3931,7 @@ win_line (
int col_stride = wp->w_p_rl ? -1 : 1;
- while (wp->w_p_rl ? col >= 0 : col < wp->w_width) {
+ while (wp->w_p_rl ? col >= 0 : col < grid->Columns) {
int cells = -1;
if (do_virttext && !delay_virttext) {
if (*s.p == NUL) {
@@ -3972,14 +3945,14 @@ win_line (
}
}
if (*s.p != NUL) {
- cells = line_putchar(&s, &ScreenLines[off], wp->w_width - col,
+ cells = line_putchar(&s, &linebuf_char[off], grid->Columns - col,
false);
}
}
delay_virttext = false;
if (cells == -1) {
- schar_from_ascii(ScreenLines[off], ' ');
+ schar_from_ascii(linebuf_char[off], ' ');
cells = 1;
}
col += cells * col_stride;
@@ -3987,23 +3960,23 @@ win_line (
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
}
- int attr = base_attr;
+ int col_attr = base_attr;
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) {
- attr = cuc_attr;
+ col_attr = cuc_attr;
} else if (draw_color_col && VCOL_HLC == *color_cols) {
- attr = mc_attr;
+ col_attr = mc_attr;
}
if (do_virttext) {
- attr = hl_combine_attr(attr, virt_attr);
+ col_attr = hl_combine_attr(col_attr, virt_attr);
}
- attr = hl_combine_attr(attr, line_attr);
+ col_attr = hl_combine_attr(col_attr, line_attr);
- ScreenAttrs[off] = attr;
+ linebuf_attr[off] = col_attr;
if (cells == 2) {
- ScreenAttrs[off+1] = attr;
+ linebuf_attr[off+1] = col_attr;
}
off += cells * col_stride;
@@ -4020,14 +3993,14 @@ win_line (
if (wp->w_buffer->terminal) {
// 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++];
+ while (col < grid->Columns) {
+ schar_from_ascii(linebuf_char[off], ' ');
+ linebuf_attr[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_put_linebuf(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
+ wp->w_hl_attr_normal, false);
row++;
/*
@@ -4048,9 +4021,7 @@ win_line (
if (lcs_ext
&& !wp->w_p_wrap
&& filler_todo <= 0
- && (
- wp->w_p_rl ? col == 0 :
- col == wp->w_width - 1)
+ && (wp->w_p_rl ? col == 0 : col == grid->Columns - 1)
&& (*ptr != NUL
|| (wp->w_p_list && lcs_eol_one > 0)
|| (n_extra && (c_extra != NUL || *p_extra != NUL)))) {
@@ -4107,22 +4078,23 @@ win_line (
--col;
}
if (mb_utf8) {
- schar_from_cc(ScreenLines[off], mb_c, u8cc);
+ schar_from_cc(linebuf_char[off], mb_c, u8cc);
} else {
- schar_from_ascii(ScreenLines[off], c);
+ schar_from_ascii(linebuf_char[off], c);
}
if (multi_attr) {
- ScreenAttrs[off] = multi_attr;
+ linebuf_attr[off] = multi_attr;
multi_attr = 0;
- } else
- ScreenAttrs[off] = char_attr;
+ } else {
+ linebuf_attr[off] = char_attr;
+ }
if (has_mbyte && (*mb_char2cells)(mb_c) > 1) {
// Need to fill two screen columns.
off++;
col++;
// UTF-8: Put a 0 in the second screen char.
- ScreenLines[off][0] = 0;
+ linebuf_char[off][0] = 0;
if (draw_state > WL_NR && filler_todo <= 0) {
vcol++;
}
@@ -4228,33 +4200,35 @@ win_line (
* At end of screen line and there is more to come: Display the line
* so far. If there is no more to display it is caught above.
*/
- if ((
- wp->w_p_rl ? (col < 0) :
- (col >= wp->w_width))
+ if ((wp->w_p_rl ? (col < 0) : (col >= grid->Columns))
&& (*ptr != NUL
|| filler_todo > 0
|| (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,
+ || ui_is_external(kUIMultigrid)) // or has dedicated grid.
+ && !wp->w_p_rl; // Not right-to-left.
+ grid_put_linebuf(grid, row, 0, col - boguscols, grid->Columns, wp->w_p_rl,
+ wp, wp->w_hl_attr_normal, wrap);
if (wrap) {
+ ScreenGrid *current_grid = grid;
+ int current_row = row, dummy_col = 0; // dummy_col unused
+ screen_adjust_grid(&current_grid, &current_row, &dummy_col);
+
// Force a redraw of the first column of the next line.
- ScreenAttrs[LineOffset[screen_row + 1]] = -1;
+ current_grid->attrs[current_grid->line_offset[current_row+1]] = -1;
// Remember that the line wraps, used for modeless copy.
- LineWraps[screen_row] = true;
+ current_grid->line_wraps[current_row] = true;
}
boguscols = 0;
- ++row;
- ++screen_row;
+ row++;
/* When not wrapping and finished diff lines, or when displayed
* '$' and highlighting until last column, break here. */
@@ -4267,7 +4241,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;
}
@@ -4278,9 +4252,9 @@ win_line (
}
col = 0;
- off = (unsigned)(current_ScreenLine - ScreenLines);
+ off = 0;
if (wp->w_p_rl) {
- col = wp->w_width - 1; /* col is not used if breaking! */
+ col = grid->Columns - 1; // col is not used if breaking!
off += col;
}
@@ -4313,6 +4287,22 @@ win_line (
return row;
}
+/// Determine if dedicated window grid should be used or the default_grid
+///
+/// If UI did not request multigrid support, draw all windows on the
+/// default_grid.
+///
+/// If the default_grid is used, adjust window relative positions to global
+/// screen positions.
+static void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off)
+{
+ if (!ui_is_external(kUIMultigrid) && *grid != &default_grid) {
+ *row_off += (*grid)->row_offset;
+ *col_off += (*grid)->col_offset;
+ *grid = &default_grid;
+ }
+}
+
/*
* Check whether the given character needs redrawing:
@@ -4321,32 +4311,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]
- || (utf_off2cells(off_from, off_from + cols) > 1
- && schar_cmp(ScreenLines[off_from + 1],
- ScreenLines[off_to + 1])))
+ && ((schar_cmp(linebuf_char[off_from], grid->chars[off_to])
+ || linebuf_attr[off_from] != grid->attrs[off_to]
+ || (line_off2cells(linebuf_char, off_from, off_from + cols) > 1
+ && schar_cmp(linebuf_char[off_from + 1],
+ grid->chars[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 buffered line to the window grid, but only the characters that
+/// have actually changed. Handle insert/delete character.
+/// "coloff" gives the first column on the grid for this line.
+/// "endcol" gives the columns where valid characters are.
+/// "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_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol,
+ int clear_width, int rlflag, win_T *wp,
+ int bg_attr, bool wrap)
{
unsigned off_from;
unsigned off_to;
@@ -4360,56 +4350,61 @@ 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;
- /* Check for illegal row and col, just in case. */
- if (row >= Rows)
- row = Rows - 1;
- if (endcol > Columns)
- endcol = Columns;
+ // TODO(bfredl): check all callsites and eliminate
+ // Check for illegal row and col, just in case
+ if (row >= grid->Rows) {
+ row = grid->Rows - 1;
+ }
+ if (endcol > grid->Columns) {
+ endcol = grid->Columns;
+ }
+
+ screen_adjust_grid(&grid, &row, &coloff);
- 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 = 0;
+ off_to = grid->line_offset[row] + coloff;
+ max_off_from = linebuf_size;
+ max_off_to = grid->line_offset[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->chars[off_to][0] == ' '
+ && grid->chars[off_to][1] == NUL
+ && grid->attrs[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->line_offset[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]);
+ linebuf_attr[off_from+c] =
+ hl_combine_attr(bg_attr, linebuf_attr[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;
if (col + 1 < endcol) {
- char_cells = utf_off2cells(off_from, max_off_from);
+ char_cells = line_off2cells(linebuf_char, 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) {
@@ -4423,23 +4418,23 @@ static void screen_line(int row, int coloff, int endcol, int clear_width,
// char over the left halve of an existing one
if (col + char_cells == endcol
&& ((char_cells == 1
- && utf_off2cells(off_to, max_off_to) > 1)
+ && grid_off2cells(grid, off_to, max_off_to) > 1)
|| (char_cells == 2
- && utf_off2cells(off_to, max_off_to) == 1
- && utf_off2cells(off_to + 1, max_off_to) > 1))) {
+ && grid_off2cells(grid, off_to, max_off_to) == 1
+ && grid_off2cells(grid, off_to + 1, max_off_to) > 1))) {
clear_next = true;
}
- schar_copy(ScreenLines[off_to], ScreenLines[off_from]);
+ schar_copy(grid->chars[off_to], linebuf_char[off_from]);
if (char_cells == 2) {
- schar_copy(ScreenLines[off_to+1], ScreenLines[off_from+1]);
+ schar_copy(grid->chars[off_to+1], linebuf_char[off_from+1]);
}
- ScreenAttrs[off_to] = ScreenAttrs[off_from];
+ grid->attrs[off_to] = linebuf_attr[off_from];
// For simplicity set the attributes of second half of a
// double-wide character equal to the first half.
if (char_cells == 2) {
- ScreenAttrs[off_to + 1] = ScreenAttrs[off_from];
+ grid->attrs[off_to + 1] = linebuf_attr[off_from];
}
}
@@ -4451,7 +4446,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->chars[off_to], ' ');
end_dirty++;
}
@@ -4460,28 +4455,29 @@ 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 (start_dirty == -1) {
- start_dirty = col;
- end_dirty = col;
- } else if (clear_end == -1) {
- end_dirty = endcol;
- }
- clear_end = col+1;
+ if (grid->chars[off_to][0] != ' '
+ || grid->chars[off_to][1] != NUL
+ || grid->attrs[off_to] != bg_attr) {
+ grid->chars[off_to][0] = ' ';
+ grid->chars[off_to][1] = NUL;
+ grid->attrs[off_to] = bg_attr;
+ if (start_dirty == -1) {
+ start_dirty = col;
+ end_dirty = col;
+ } else if (clear_end == -1) {
+ end_dirty = endcol;
}
- col++;
- off_to++;
+ clear_end = col+1;
+ }
+ col++;
+ off_to++;
}
}
- 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->line_wraps[row] = false;
}
if (clear_end < end_dirty) {
@@ -4491,7 +4487,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);
}
}
@@ -4586,9 +4582,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, W_ENDROW(wp),
+ W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
}
}
@@ -4673,7 +4668,8 @@ 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;
@@ -4693,15 +4689,16 @@ win_redr_status_matches (
clen += status_match_len(xp, L_MATCH(i)) + 2;
if (first_match > 0)
clen += 2;
- /* jumping right, put match at the left */
- if ((long)clen > Columns) {
+ // jumping right, put match at the left
+ 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)
add_left = TRUE;
@@ -4710,9 +4707,10 @@ 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;
+ }
+ first_match--;
}
fillchar = fillchar_status(&attr, curwin);
@@ -4727,7 +4725,8 @@ 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;
@@ -4778,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++;
@@ -4801,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);
@@ -4905,15 +4905,15 @@ 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);
+ row = W_ENDROW(wp);
+ 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);
}
@@ -4927,8 +4927,7 @@ 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, W_ENDROW(wp), W_ENDCOL(wp), attr);
}
busy = FALSE;
}
@@ -5072,10 +5071,10 @@ 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;
+ row = W_ENDROW(wp);
fillchar = fillchar_status(&attr, wp);
maxwidth = wp->w_width;
@@ -5091,13 +5090,14 @@ win_redr_custom (
if (*stl++ != '(')
stl = p_ruf;
}
- col = ru_col - (Columns - wp->w_width);
- if (col < (wp->w_width + 1) / 2)
+ 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;
- --maxwidth; /* writing in last column may cause scrolling */
+ row = default_grid.Rows - 1;
+ maxwidth--; // writing in last column may cause scrolling
fillchar = ' ';
attr = 0;
}
@@ -5154,9 +5154,9 @@ win_redr_custom (
curattr = attr;
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);
- col += vim_strnsize(p, len);
+ int textlen = (int)(hltab[n].start - p);
+ grid_puts_len(&default_grid, p, textlen, row, col, curattr);
+ col += vim_strnsize(p, textlen);
p = hltab[n].start;
if (hltab[n].userhl == 0)
@@ -5169,9 +5169,10 @@ 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.
@@ -5189,7 +5190,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;
}
}
@@ -5242,43 +5243,80 @@ static void schar_copy(char_u *sc1, char_u *sc2)
STRLCPY(sc1, sc2, sizeof(schar_T));
}
+static int line_off2cells(schar_T *line, size_t off, size_t max_off)
+{
+ return (off + 1 < max_off && line[off + 1][0] == 0) ? 2 : 1;
+}
-/*
- * Output a single character directly to the screen and update ScreenLines.
- */
-void screen_putchar(int c, int row, int col, int attr)
+/// Return number of display cells for char at grid->chars[off].
+/// We make sure that the offset used is less than "max_off".
+static int grid_off2cells(ScreenGrid *grid, size_t off, size_t max_off)
+{
+ return line_off2cells(grid->chars, off, max_off);
+}
+
+/// Return true if the character at "row"/"col" on the screen is the left side
+/// of a double-width character.
+///
+/// Caller must make sure "row" and "col" are not invalid!
+bool grid_lefthalve(ScreenGrid *grid, int row, int col)
+{
+ screen_adjust_grid(&grid, &row, &col);
+
+ return grid_off2cells(grid, grid->line_offset[row] + col,
+ grid->line_offset[row] + grid->Columns) > 1;
+}
+
+/// Correct a position on the screen, if it's the right half of a double-wide
+/// char move it to the left half. Returns the corrected column.
+int grid_fix_col(ScreenGrid *grid, int col, int row)
+{
+ int coloff = 0;
+ screen_adjust_grid(&grid, &row, &coloff);
+
+ col += coloff;
+ if (grid->chars != NULL && col > 0
+ && grid->chars[grid->line_offset[row] + col][0] == 0) {
+ return col - 1 - coloff;
+ }
+ return col - coloff;
+}
+
+/// output a single character directly to the grid
+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.chars 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]);
+ screen_adjust_grid(&grid, &row, &col);
+
+
+ // safety check
+ if (grid->chars != NULL && row < grid->Rows && col < grid->Columns) {
+ off = grid->line_offset[row] + col;
+ *attrp = grid->attrs[off];
+ schar_copy(bytes, grid->chars[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 chars[] and attrs[].
+/// Note: only outputs within one row, message is truncated at grid boundary!
+/// Note: if grid, 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;
@@ -5295,11 +5333,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;
@@ -5317,8 +5354,15 @@ 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;
+
+ screen_adjust_grid(&grid, &row, &col);
+
+ // safety check
+ if (grid->chars == NULL || row >= grid->Rows || col >= grid->Columns) {
+ return;
+ }
+
if (put_dirty_row == -1) {
screen_puts_line_start(row);
do_flush = true;
@@ -5327,16 +5371,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->line_offset[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 && grid_fix_col(grid, col, row) != col) {
+ schar_from_ascii(grid->chars[off - 1], ' ');
+ grid->attrs[off - 1] = 0;
// redraw the previous cell, make it empty
if (put_dirty_first == -1) {
put_dirty_first = col-1;
@@ -5346,8 +5387,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->line_offset[row] + grid->Columns;
+ while (col < grid->Columns
&& (len < 0 || (int)(ptr - text) < len)
&& *ptr != NUL) {
c = *ptr;
@@ -5380,7 +5421,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 = '>';
@@ -5394,9 +5435,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->chars[off], buf)
+ || (mbyte_cells == 2 && grid->chars[off + 1][0] != 0)
+ || grid->attrs[off] != attr
|| exmode_active;
if (need_redraw || force_redraw_this) {
@@ -5409,18 +5450,19 @@ void screen_puts_len(char_u *text, int textlen, int row, int col, int attr)
clear_next_cell = false;
} else if ((len < 0 ? ptr[mbyte_blen] == NUL
: ptr + mbyte_blen >= text + len)
- && ((mbyte_cells == 1 && utf_off2cells(off, max_off) > 1)
+ && ((mbyte_cells == 1
+ && grid_off2cells(grid, off, max_off) > 1)
|| (mbyte_cells == 2
- && utf_off2cells(off, max_off) == 1
- && utf_off2cells(off + 1, max_off) > 1))) {
+ && grid_off2cells(grid, off, max_off) == 1
+ && grid_off2cells(grid, off + 1, max_off) > 1))) {
clear_next_cell = true;
}
- schar_copy(ScreenLines[off], buf);
- ScreenAttrs[off] = attr;
+ schar_copy(grid->chars[off], buf);
+ grid->attrs[off] = attr;
if (mbyte_cells == 2) {
- ScreenLines[off + 1][0] = 0;
- ScreenAttrs[off + 1] = attr;
+ grid->chars[off + 1][0] = 0;
+ grid->attrs[off + 1] = attr;
}
if (put_dirty_first == -1) {
put_dirty_first = col;
@@ -5439,25 +5481,27 @@ 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->handle, put_dirty_row,
+ MIN(put_dirty_last, grid->Columns-1));
}
- 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;
}
@@ -5760,23 +5804,33 @@ 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
- || start_row >= end_row
- || start_col >= end_col) /* nothing to do */
+ int row_off = 0, col_off = 0;
+ screen_adjust_grid(&grid, &row_off, &col_off);
+ start_row += row_off;
+ end_row += row_off;
+ start_col += col_off;
+ end_col += col_off;
+
+ // safety check
+ if (end_row > grid->Rows) {
+ end_row = grid->Rows;
+ }
+ if (end_col > grid->Columns) {
+ end_col = grid->Columns;
+ }
+
+ // nothing to do
+ if (grid->chars == NULL || start_row >= end_row || start_col >= end_col) {
return;
+ }
for (int row = start_row; row < end_row; row++) {
if (has_mbyte) {
@@ -5784,24 +5838,30 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
// out the left halve. When drawing over the left halve of a
// double wide-char clear out the right halve. Only needed in a
// terminal.
- if (start_col > 0 && mb_fix_col(start_col, row) != start_col) {
- screen_puts_len((char_u *)" ", 1, row, start_col - 1, 0);
+ if (start_col > 0 && grid_fix_col(grid, start_col, row) != start_col) {
+ grid_puts_len(grid, (char_u *)" ", 1, row, start_col - 1, 0);
}
- if (end_col < 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
+ && grid_fix_col(grid, end_col, row) != end_col) {
+ grid_puts_len(grid, (char_u *)" ", 1, row, end_col, 0);
}
}
+ // if grid was resized (in ext_multigrid mode), the UI has no redraw updates
+ // for the newly resized grid. It is better mark everything as dirty and
+ // send all the updates.
int dirty_first = INT_MAX;
int dirty_last = 0;
+
int col = start_col;
schar_from_char(sc, c1);
- int lineoff = LineOffset[row];
+ int lineoff = grid->line_offset[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->chars[off], sc)
+ || grid->attrs[off] != attr) {
+ schar_copy(grid->chars[off], sc);
+ grid->attrs[off] = attr;
if (dirty_first == INT_MAX) {
dirty_first = col;
}
@@ -5820,16 +5880,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;
+ if (end_col == grid->Columns) {
+ grid->line_wraps[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) {
@@ -5867,24 +5927,90 @@ void check_for_delay(int check_msg_scroll)
*/
int screen_valid(int doclear)
{
- screenalloc(doclear); /* allocate screen buffers if size changed */
- return ScreenLines != NULL;
+ screenalloc(doclear); // allocate screen buffers if size changed
+ return default_grid.chars != NULL;
}
-/*
- * Resize the shell to Rows and Columns.
- * Allocate ScreenLines[] and associated items.
- *
- * There may be some time between setting Rows and Columns and (re)allocating
- * ScreenLines[]. This happens when starting up and when (manually) changing
- * the shell size. Always use screen_Rows and screen_Columns to access items
- * in ScreenLines[]. Use Rows and Columns for positioning text etc. where the
- * final size of the shell is needed.
- */
+/// (Re)allocates a window grid if size changed while in ext_multigrid mode.
+/// Updates size, offsets and handle for the grid regardless.
+///
+/// If "doclear" is true, don't try to copy from the old grid rather clear the
+/// resized grid.
+void win_grid_alloc(win_T *wp)
+{
+ ScreenGrid *grid = &wp->w_grid;
+
+ int rows = grid->requested_rows;
+ if (rows == 0) {
+ rows = wp->w_height;
+ }
+
+ int columns = grid->requested_cols;
+ if (columns == 0) {
+ columns = wp->w_width;
+ }
+
+ // TODO(bfredl): floating windows should force this to true
+ bool want_allocation = ui_is_external(kUIMultigrid);
+ bool has_allocation = (grid->chars != NULL);
+
+ if (want_allocation && has_allocation && highlights_invalid) {
+ grid_invalidate(grid);
+ }
+
+ int was_resized = false;
+ if ((has_allocation != want_allocation)
+ || grid->Rows != rows
+ || grid->Columns != columns) {
+ if (want_allocation) {
+ grid_alloc(grid, rows, columns, true);
+ win_free_lsize(wp);
+ win_alloc_lines(wp);
+ } else {
+ // Single grid mode, all rendering will be redirected to default_grid.
+ // Only keep track of the size and offset of the window.
+ grid_free(grid);
+ grid->Rows = rows;
+ grid->Columns = columns;
+ }
+ was_resized = true;
+ }
+
+ grid->row_offset = wp->w_winrow;
+ grid->col_offset = wp->w_wincol;
+
+ // send grid resize event if:
+ // - a grid was just resized
+ // - screen_resize was called and all grid sizes must be sent
+ // - the UI wants multigrid event (necessary)
+ if ((send_grid_resize || was_resized) && ui_is_external(kUIMultigrid)) {
+ ui_call_grid_resize(grid->handle, grid->Columns, grid->Rows);
+ }
+}
+
+/// assign a handle to the grid. The grid need not be allocated.
+void grid_assign_handle(ScreenGrid *grid)
+{
+ static int last_grid_handle = DEFAULT_GRID_HANDLE;
+
+ // only assign a grid handle if not already
+ if (grid->handle == 0) {
+ grid->handle = ++last_grid_handle;
+ }
+}
+
+/// Resize the screen to Rows and Columns.
+///
+/// Allocate default_grid.chars[] and other grid arrays.
+///
+/// There may be some time between setting Rows and Columns and (re)allocating
+/// default_grid arrays. This happens when starting up and when
+/// (manually) changing the shell size. Always use default_grid.Rows and
+/// default_grid.Columns to access items in default_grid.chars[]. Use Rows
+/// and Columns for positioning text etc. where the final size of the shell is
+/// needed.
void screenalloc(bool doclear)
{
- int new_row, old_row;
- int len;
static bool entered = false; // avoid recursiveness
int retry_count = 0;
@@ -5892,13 +6018,13 @@ retry:
// Allocation of the screen buffers is done only when the size changes and
// when Rows and Columns have been set and we have started doing full
// screen stuff.
- if ((ScreenLines != NULL
- && Rows == screen_Rows
- && Columns == screen_Columns
+ if ((default_grid.chars != NULL
+ && Rows == default_grid.Rows
+ && Columns == default_grid.Columns
)
|| Rows == 0
|| Columns == 0
- || (!full_screen && ScreenLines == NULL)) {
+ || (!full_screen && default_grid.chars == NULL)) {
return;
}
@@ -5921,30 +6047,22 @@ retry:
comp_col(); /* recompute columns for shown command and ruler */
- /*
- * We're changing the size of the screen.
- * - Allocate new arrays for ScreenLines and ScreenAttrs.
- * - Move lines from the old arrays into the new arrays, clear extra
- * lines (unless the screen is going to be cleared).
- * - Free the old arrays.
- *
- * If anything fails, make ScreenLines NULL, so we don't do anything!
- * Continuing with the old ScreenLines may result in a crash, because the
- * size is wrong.
- */
+ // We're changing the size of the screen.
+ // - Allocate new arrays for default_grid
+ // - Move lines from the old arrays into the new arrays, clear extra
+ // lines (unless the screen is going to be cleared).
+ // - Free the old arrays.
+ //
+ // If anything fails, make grid arrays NULL, so we don't do anything!
+ // Continuing with the old arrays may result in a crash, because the
+ // size is wrong.
FOR_ALL_TAB_WINDOWS(tp, wp) {
win_free_lsize(wp);
}
if (aucmd_win != NULL)
win_free_lsize(aucmd_win);
- // Allocate space for an extra row as scratch space, so that a redrawn
- // line can be compared with the previous screen line state.
- size_t ncells = (size_t)((Rows+1) * Columns);
- schar_T *new_ScreenLines = xmalloc(ncells * sizeof(*new_ScreenLines));
- sattr_T *new_ScreenAttrs = xmalloc(ncells * sizeof(*new_ScreenAttrs));
- unsigned *new_LineOffset = xmalloc((size_t)(Rows * sizeof(*new_LineOffset)));
- char_u *new_LineWraps = xmalloc((size_t)(Rows * sizeof(*new_LineWraps)));
+ grid_alloc(&default_grid, Rows, Columns, !doclear);
StlClickDefinition *new_tab_page_click_defs = xcalloc(
(size_t)Columns, sizeof(*new_tab_page_click_defs));
@@ -5955,53 +6073,15 @@ retry:
win_alloc_lines(aucmd_win);
}
- for (new_row = 0; new_row < Rows; new_row++) {
- new_LineOffset[new_row] = new_row * Columns;
- new_LineWraps[new_row] = false;
-
- // 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).
- if (!doclear) {
- for (int col = 0; col < Columns; col++) {
- schar_from_ascii(new_ScreenLines[new_row * Columns + col], ' ');
- }
- memset(new_ScreenAttrs + new_row * Columns,
- 0, (size_t)Columns * sizeof(*new_ScreenAttrs));
- old_row = new_row + (screen_Rows - Rows);
- if (old_row >= 0 && ScreenLines != NULL) {
- if (screen_Columns < Columns) {
- len = screen_Columns;
- } else {
- len = Columns;
- }
-
- memmove(new_ScreenLines + new_LineOffset[new_row],
- ScreenLines + LineOffset[old_row],
- (size_t)len * sizeof(schar_T));
- memmove(new_ScreenAttrs + new_LineOffset[new_row],
- ScreenAttrs + LineOffset[old_row],
- (size_t)len * sizeof(new_ScreenAttrs[0]));
- }
- }
- }
- // Use the last line of the screen for the current line.
- current_ScreenLine = new_ScreenLines + Rows * Columns;
-
- free_screenlines();
+ clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
+ xfree(tab_page_click_defs);
- ScreenLines = new_ScreenLines;
- ScreenAttrs = new_ScreenAttrs;
- LineOffset = new_LineOffset;
- LineWraps = new_LineWraps;
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;
+ default_grid.row_offset = 0;
+ default_grid.col_offset = 0;
+ default_grid.handle = DEFAULT_GRID_HANDLE;
must_redraw = CLEAR; /* need to clear the screen later */
if (doclear)
@@ -6023,14 +6103,75 @@ retry:
}
}
-void free_screenlines(void)
+void grid_alloc(ScreenGrid *grid, int rows, int columns, bool copy)
{
- xfree(ScreenLines);
- xfree(ScreenAttrs);
- xfree(LineOffset);
- xfree(LineWraps);
- clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
- xfree(tab_page_click_defs);
+ int new_row;
+ ScreenGrid new = *grid;
+
+ size_t ncells = (size_t)((rows+1) * columns);
+ new.chars = xmalloc(ncells * sizeof(schar_T));
+ new.attrs = xmalloc(ncells * sizeof(sattr_T));
+ new.line_offset = xmalloc((size_t)(rows * sizeof(unsigned)));
+ new.line_wraps = xmalloc((size_t)(rows * sizeof(char_u)));
+
+ new.Rows = rows;
+ new.Columns = columns;
+
+ for (new_row = 0; new_row < new.Rows; new_row++) {
+ new.line_offset[new_row] = new_row * new.Columns;
+ new.line_wraps[new_row] = false;
+
+ grid_clear_line(&new, new.line_offset[new_row], columns, true);
+
+ 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).
+ if (new_row < grid->Rows && grid->chars != NULL) {
+ int len = MIN(grid->Columns, new.Columns);
+ memmove(new.chars + new.line_offset[new_row],
+ grid->chars + grid->line_offset[new_row],
+ (size_t)len * sizeof(schar_T));
+ memmove(new.attrs + new.line_offset[new_row],
+ grid->attrs + grid->line_offset[new_row],
+ (size_t)len * sizeof(sattr_T));
+ }
+ }
+ }
+ grid_free(grid);
+ *grid = new;
+
+ // Share a single scratch buffer for all grids, by
+ // ensuring it is as wide as the widest grid.
+ if (linebuf_size < (size_t)columns) {
+ xfree(linebuf_char);
+ xfree(linebuf_attr);
+ linebuf_char = xmalloc(columns * sizeof(schar_T));
+ linebuf_attr = xmalloc(columns * sizeof(sattr_T));
+ linebuf_size = columns;
+ }
+}
+
+void grid_free(ScreenGrid *grid)
+{
+ xfree(grid->chars);
+ xfree(grid->attrs);
+ xfree(grid->line_offset);
+ xfree(grid->line_wraps);
+
+ grid->chars = NULL;
+ grid->attrs = NULL;
+ grid->line_offset = NULL;
+ grid->line_wraps = NULL;
+}
+
+/// Doesn't allow reinit, so must only be called by free_all_mem!
+void screen_free_all_mem(void)
+{
+ grid_free(&default_grid);
+ xfree(linebuf_char);
+ xfree(linebuf_attr);
}
/// Clear tab_page_click_defs table
@@ -6061,14 +6202,15 @@ static void screenclear2(void)
{
int i;
- if (starting == NO_SCREEN || ScreenLines == NULL) {
+ if (starting == NO_SCREEN || default_grid.chars == NULL) {
return;
}
- // blank out ScreenLines
- for (i = 0; i < Rows; i++) {
- lineclear(LineOffset[i], (int)Columns, true);
- LineWraps[i] = false;
+ // blank out the default grid
+ for (i = 0; i < default_grid.Rows; i++) {
+ grid_clear_line(&default_grid, default_grid.line_offset[i],
+ (int)default_grid.Columns, true);
+ default_grid.line_wraps[i] = false;
}
ui_call_grid_clear(1); // clear the display
@@ -6089,27 +6231,33 @@ 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->chars[off + col], ' ');
}
int fill = valid ? 0 : -1;
- (void)memset(ScreenAttrs + off, fill, (size_t)width * sizeof(sattr_T));
+ (void)memset(grid->attrs + 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 grid_invalidate(ScreenGrid *grid)
{
- unsigned off_to = LineOffset[to] + col;
- unsigned off_from = LineOffset[from] + col;
+ (void)memset(grid->attrs, -1, grid->Rows * grid->Columns * sizeof(sattr_T));
+}
+
- memmove(ScreenLines + off_to, ScreenLines + off_from,
+/// Copy part of a grid line for vertically split window.
+static void linecopy(ScreenGrid *grid, int to, int from, int col, int width)
+{
+ unsigned off_to = grid->line_offset[to] + col;
+ unsigned off_from = grid->line_offset[from] + col;
+
+ memmove(grid->chars + off_to, grid->chars + off_from,
width * sizeof(schar_T));
- memmove(ScreenAttrs + off_to, ScreenAttrs + off_from,
+ memmove(grid->attrs + off_to, grid->attrs + off_from,
width * sizeof(sattr_T));
}
@@ -6120,16 +6268,20 @@ void setcursor(void)
{
if (redrawing()) {
validate_cursor();
- int left_offset = curwin->w_wcol;
+
+ ScreenGrid *grid = &curwin->w_grid;
+ int row = curwin->w_wrow;
+ int col = curwin->w_wcol;
if (curwin->w_p_rl) {
// With 'rightleft' set and the cursor on a double-wide character,
// position it on the leftmost column.
- left_offset = curwin->w_width - curwin->w_wcol
+ col = curwin->w_grid.Columns - curwin->w_wcol
- ((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);
+
+ screen_adjust_grid(&grid, &row, &col);
+ ui_grid_cursor_goto(grid->handle, row, col);
}
}
@@ -6156,7 +6308,7 @@ static int win_do_lines(win_T *wp, int row, int line_count, int del)
}
// No lines are being moved, just draw over the entire area
- if (row + line_count >= wp->w_height) {
+ if (row + line_count >= wp->w_grid.Rows) {
return OK;
}
@@ -6165,15 +6317,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_grid.Rows, 0, wp->w_grid.Columns);
} 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_grid.Rows, 0, wp->w_grid.Columns);
}
return retval;
}
@@ -6189,95 +6338,109 @@ static int win_do_lines(win_T *wp, int row, int line_count, int del)
*/
-/// insert lines on the screen and update ScreenLines[]
+/// insert lines on the screen and move the existing lines down
+/// 'line_count' is the number of lines to be inserted.
/// 'end' is the line after the scrolled part. Normally it is Rows.
-/// When scrolling region used 'off' is the offset from the top for the region.
-/// 'row' and 'end' are relative to the start of the region.
+/// 'col' is the column from with we start inserting.
+//
+/// 'row', 'col' 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;
+ int row_off = 0;
+ screen_adjust_grid(&grid, &row_off, &col);
+ row += row_off;
+ end += row_off;
+
if (!screen_valid(TRUE) || line_count <= 0) {
return FAIL;
}
- // Shift LineOffset[] line_count down to reflect the inserted lines.
- // Clear the inserted lines in ScreenLines[].
+ // Shift line_offset[] line_count down to reflect the inserted lines.
+ // Clear the inserted lines.
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->line_offset[j] + col, width, false);
+ grid->line_wraps[j] = false;
} else {
j = end - 1 - i;
- temp = LineOffset[j];
+ temp = grid->line_offset[j];
while ((j -= line_count) >= row) {
- LineOffset[j + line_count] = LineOffset[j];
- LineWraps[j + line_count] = LineWraps[j];
+ grid->line_offset[j + line_count] = grid->line_offset[j];
+ grid->line_wraps[j + line_count] = grid->line_wraps[j];
}
- LineOffset[j + line_count] = temp;
- LineWraps[j + line_count] = false;
- lineclear(temp, (int)Columns, false);
+ grid->line_offset[j + line_count] = temp;
+ grid->line_wraps[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;
}
-/// delete lines on the screen and update ScreenLines[]
+/// delete lines on the screen and move lines up.
/// 'end' is the line after the scrolled part. Normally it is Rows.
/// When scrolling region used 'off' is the offset from the top for the region.
/// '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;
+ int row_off = 0;
+ screen_adjust_grid(&grid, &row_off, &col);
+ row += row_off;
+ end += row_off;
+
if (!screen_valid(TRUE) || line_count <= 0) {
return FAIL;
}
- // Now shift LineOffset[] line_count up to reflect the deleted lines.
- // Clear the inserted lines in ScreenLines[].
+ // Now shift line_offset[] line_count up to reflect the deleted lines.
+ // Clear the inserted lines.
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->line_offset[j] + col, width, false);
+ grid->line_wraps[j] = false;
} else {
// whole width, moving the line pointers is faster
j = row + i;
- temp = LineOffset[j];
+ temp = grid->line_offset[j];
while ((j += line_count) <= end - 1) {
- LineOffset[j - line_count] = LineOffset[j];
- LineWraps[j - line_count] = LineWraps[j];
+ grid->line_offset[j - line_count] = grid->line_offset[j];
+ grid->line_wraps[j - line_count] = grid->line_wraps[j];
}
- LineOffset[j - line_count] = temp;
- LineWraps[j - line_count] = false;
- lineclear(temp, (int)Columns, false);
+ grid->line_offset[j - line_count] = temp;
+ grid->line_wraps[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;
}
@@ -6324,8 +6487,9 @@ 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)
- msg_clr_cmdline(); /* will reset clear_cmdline */
+ 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 */
msg_pos_mode();
@@ -6343,9 +6507,10 @@ 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;
- if (edit_submode_extra != NULL)
+ length = (default_grid.Rows - msg_row) * default_grid.Columns - 3;
+ if (edit_submode_extra != NULL) {
length -= vim_strsize(edit_submode_extra);
+ }
if (length > 0) {
if (edit_submode_pre != NULL)
length -= vim_strsize(edit_submode_pre);
@@ -6466,7 +6631,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
@@ -6525,7 +6690,7 @@ static void draw_tabline(void)
int use_sep_chars = (t_colors < 8
);
- if (ScreenLines == NULL) {
+ if (default_grid.chars == NULL) {
return;
}
redraw_tabline = false;
@@ -6540,7 +6705,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. */
@@ -6562,7 +6727,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) {
@@ -6573,7 +6738,7 @@ static void draw_tabline(void)
tabcount = 0;
FOR_ALL_TABS(tp) {
- if (col >= Columns - 4) {
+ if (col >= default_grid.Columns - 4) {
break;
}
@@ -6592,14 +6757,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;
@@ -6614,15 +6779,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,
- hl_combine_attr(attr, win_hl_attr(cwp, HLF_T)));
+ }
+ 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;
@@ -6641,13 +6808,14 @@ 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.
@@ -6665,12 +6833,14 @@ 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,
@@ -6861,15 +7031,15 @@ static void win_redr_ruler(win_T *wp, int always)
int off;
if (wp->w_status_height) {
- row = wp->w_winrow + wp->w_height;
+ row = W_ENDROW(wp);
fillchar = fillchar_status(&attr, wp);
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;
}
@@ -6904,15 +7074,18 @@ static void win_redr_ruler(win_T *wp, int always)
int i = (int)STRLEN(buffer);
get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1);
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);
- if (this_ru_col < 0)
+ if (wp->w_status_height == 0) { // can't use last char of screen
+ o++;
+ }
+ 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
- * half for the filename. */
- if (this_ru_col < (width + 1) / 2)
+ }
+ // Never use more than half the window/screen width, leave the other half
+ // for the filename.
+ if (this_ru_col < (width + 1) / 2) {
this_ru_col = (width + 1) / 2;
+ }
if (this_ru_col + o < width) {
// Need at least 3 chars left for get_rel_pos() + NUL.
while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) {
@@ -6931,13 +7104,12 @@ 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,
- this_ru_col + off + (int)STRLEN(buffer),
- off + width,
- fillchar, fillchar, attr);
- /* don't redraw the cmdline because of showing the ruler */
+ grid_fill(&default_grid, row, row + 1,
+ this_ru_col + off + (int)STRLEN(buffer), off + width, fillchar,
+ fillchar, attr);
+ // don't redraw the cmdline because of showing the ruler
redraw_cmdline = i;
wp->w_ru_cursor = wp->w_cursor;
wp->w_ru_virtcol = wp->w_virtcol;
@@ -6958,12 +7130,13 @@ int number_width(win_T *wp)
int n;
linenr_T lnum;
- if (wp->w_p_rnu && !wp->w_p_nu)
- /* cursor line shows "0" */
- lnum = wp->w_height;
- else
- /* cursor line shows absolute line number */
+ if (wp->w_p_rnu && !wp->w_p_nu) {
+ // cursor line shows "0"
+ lnum = wp->w_grid.Rows;
+ } else {
+ // cursor line shows absolute line number
lnum = wp->w_buffer->b_ml.ml_line_count;
+ }
if (lnum == wp->w_nrwidth_line_count)
return wp->w_nrwidth_width;
@@ -7019,6 +7192,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(). */
@@ -7040,7 +7215,7 @@ void screen_resize(int width, int height)
* - in Ex mode, don't redraw anything.
* - Otherwise, redraw right now, and position the cursor.
* Always need to call update_screen() or screenalloc(), to make
- * sure Rows/Columns and the size of ScreenLines[] is correct!
+ * sure Rows/Columns and the size of the screen is correct!
*/
if (State == ASKMORE || State == EXTERNCMD || State == CONFIRM
|| exmode_active) {
@@ -7112,3 +7287,13 @@ void win_new_shellsize(void)
shell_new_columns(); // update window sizes
}
}
+
+win_T *get_win_by_grid_handle(handle_T handle)
+{
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_grid.handle == handle) {
+ return wp;
+ }
+ }
+ return NULL;
+}
diff --git a/src/nvim/screen.h b/src/nvim/screen.h
index 17515d4253..109541ef07 100644
--- a/src/nvim/screen.h
+++ b/src/nvim/screen.h
@@ -5,6 +5,7 @@
#include "nvim/types.h"
#include "nvim/buffer_defs.h"
+#include "nvim/grid_defs.h"
#include "nvim/pos.h"
/*
@@ -20,6 +21,18 @@
#define NOT_VALID 40 /* buffer needs complete redraw */
#define CLEAR 50 /* screen messed up, clear it */
+/// By default, all widows are draw on a single rectangular grid, represented by
+/// this ScreenGrid instance. In multigrid mode each window will have its own
+/// grid, then this is only used for global screen elements that hasn't been
+/// externalized.
+///
+/// Note: before the screen is initialized and when out of memory these can be
+/// NULL.
+EXTERN ScreenGrid default_grid INIT(= { 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0,
+ 0, 0, 0 });
+
+#define DEFAULT_GRID_HANDLE 1 // handle for the default_grid
+
/// Status line click definition
typedef struct {
enum {
diff --git a/src/nvim/search.c b/src/nvim/search.c
index f31ec7170b..cf0f1ea287 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -2166,9 +2166,10 @@ showmatch(
if (!curwin->w_p_wrap) {
getvcol(curwin, lpos, NULL, &vcol, NULL);
}
- if (curwin->w_p_wrap || (vcol >= curwin->w_leftcol
- && vcol < curwin->w_leftcol + curwin->w_width)) {
- mpos = *lpos; /* save the pos, update_screen() may change it */
+ if (curwin->w_p_wrap
+ || (vcol >= curwin->w_leftcol
+ && vcol < curwin->w_leftcol + curwin->w_grid.Columns)) {
+ mpos = *lpos; // save the pos, update_screen() may change it
save_cursor = curwin->w_cursor;
save_so = p_so;
save_siso = p_siso;
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 11da7195bf..36570e0ded 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -3475,53 +3475,55 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader,
} \
tgt = proc(obj.via.attr); \
} while (0)
-#define CHECK_KEY_IS_STR(entry_name) \
- if (unpacked.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \
+#define CHECK_KEY_IS_STR(un, entry_name) \
+ if (un.data.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR) { \
emsgf(_(READERR(entry_name, "has key which is not a string")), \
initial_fpos); \
CLEAR_GA_AND_ERROR_OUT(ad_ga); \
- } else if (unpacked.data.via.map.ptr[i].key.via.str.size == 0) { \
+ } else if (un.data.via.map.ptr[i].key.via.str.size == 0) { \
emsgf(_(READERR(entry_name, "has empty key")), initial_fpos); \
CLEAR_GA_AND_ERROR_OUT(ad_ga); \
}
-#define CHECKED_KEY(entry_name, name, error_desc, tgt, condition, attr, proc) \
+#define CHECKED_KEY(un, entry_name, name, error_desc, tgt, condition, attr, \
+ proc) \
else if (CHECK_KEY( /* NOLINT(readability/braces) */ \
- unpacked.data.via.map.ptr[i].key, name)) { \
+ un.data.via.map.ptr[i].key, name)) { \
CHECKED_ENTRY( \
condition, "has " name " key value " error_desc, \
- entry_name, unpacked.data.via.map.ptr[i].val, \
+ entry_name, un.data.via.map.ptr[i].val, \
tgt, attr, proc); \
}
-#define TYPED_KEY(entry_name, name, type_name, tgt, objtype, attr, proc) \
+#define TYPED_KEY(un, entry_name, name, type_name, tgt, objtype, attr, proc) \
CHECKED_KEY( \
- entry_name, name, "which is not " type_name, tgt, \
- unpacked.data.via.map.ptr[i].val.type == MSGPACK_OBJECT_##objtype, \
+ un, entry_name, name, "which is not " type_name, tgt, \
+ un.data.via.map.ptr[i].val.type == MSGPACK_OBJECT_##objtype, \
attr, proc)
-#define BOOLEAN_KEY(entry_name, name, tgt) \
- TYPED_KEY(entry_name, name, "a boolean", tgt, BOOLEAN, boolean, ID)
-#define STRING_KEY(entry_name, name, tgt) \
- TYPED_KEY(entry_name, name, "a binary", tgt, BIN, bin, BINDUP)
-#define CONVERTED_STRING_KEY(entry_name, name, tgt) \
- TYPED_KEY(entry_name, name, "a binary", tgt, BIN, bin, BIN_CONVERTED)
-#define INT_KEY(entry_name, name, tgt, proc) \
+#define BOOLEAN_KEY(un, entry_name, name, tgt) \
+ TYPED_KEY(un, entry_name, name, "a boolean", tgt, BOOLEAN, boolean, ID)
+#define STRING_KEY(un, entry_name, name, tgt) \
+ TYPED_KEY(un, entry_name, name, "a binary", tgt, BIN, bin, BINDUP)
+#define CONVERTED_STRING_KEY(un, entry_name, name, tgt) \
+ TYPED_KEY(un, entry_name, name, "a binary", tgt, BIN, bin, \
+ BIN_CONVERTED)
+#define INT_KEY(un, entry_name, name, tgt, proc) \
CHECKED_KEY( \
- entry_name, name, "which is not an integer", tgt, \
- ((unpacked.data.via.map.ptr[i].val.type \
+ un, entry_name, name, "which is not an integer", tgt, \
+ ((un.data.via.map.ptr[i].val.type \
== MSGPACK_OBJECT_POSITIVE_INTEGER) \
- || (unpacked.data.via.map.ptr[i].val.type \
+ || (un.data.via.map.ptr[i].val.type \
== MSGPACK_OBJECT_NEGATIVE_INTEGER)), \
i64, proc)
-#define INTEGER_KEY(entry_name, name, tgt) \
- INT_KEY(entry_name, name, tgt, TOINT)
-#define LONG_KEY(entry_name, name, tgt) \
- INT_KEY(entry_name, name, tgt, TOLONG)
-#define ADDITIONAL_KEY \
+#define INTEGER_KEY(un, entry_name, name, tgt) \
+ INT_KEY(un, entry_name, name, tgt, TOINT)
+#define LONG_KEY(un, entry_name, name, tgt) \
+ INT_KEY(un, entry_name, name, tgt, TOLONG)
+#define ADDITIONAL_KEY(un) \
else { /* NOLINT(readability/braces) */ \
ga_grow(&ad_ga, 1); \
- memcpy(((char *)ad_ga.ga_data) + ((size_t) ad_ga.ga_len \
- * sizeof(*unpacked.data.via.map.ptr)), \
- unpacked.data.via.map.ptr + i, \
- sizeof(*unpacked.data.via.map.ptr)); \
+ memcpy(((char *)ad_ga.ga_data) + ((size_t)ad_ga.ga_len \
+ * sizeof(*un.data.via.map.ptr)), \
+ un.data.via.map.ptr + i, \
+ sizeof(*un.data.via.map.ptr)); \
ad_ga.ga_len++; \
}
#define CONVERTED(str, len) (xmemdupz((str), (len)))
@@ -3726,28 +3728,29 @@ shada_read_next_item_start:
garray_T ad_ga;
ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1);
for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
- CHECK_KEY_IS_STR("search pattern")
- BOOLEAN_KEY("search pattern", SEARCH_KEY_MAGIC,
+ CHECK_KEY_IS_STR(unpacked, "search pattern")
+ BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_MAGIC,
entry->data.search_pattern.magic)
- BOOLEAN_KEY("search pattern", SEARCH_KEY_SMARTCASE,
+ BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_SMARTCASE,
entry->data.search_pattern.smartcase)
- BOOLEAN_KEY("search pattern", SEARCH_KEY_HAS_LINE_OFFSET,
+ BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_HAS_LINE_OFFSET,
entry->data.search_pattern.has_line_offset)
- BOOLEAN_KEY("search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END,
+ BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_PLACE_CURSOR_AT_END,
entry->data.search_pattern.place_cursor_at_end)
- BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_LAST_USED,
+ BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_IS_LAST_USED,
entry->data.search_pattern.is_last_used)
- BOOLEAN_KEY("search pattern", SEARCH_KEY_IS_SUBSTITUTE_PATTERN,
+ BOOLEAN_KEY(unpacked, "search pattern",
+ SEARCH_KEY_IS_SUBSTITUTE_PATTERN,
entry->data.search_pattern.is_substitute_pattern)
- BOOLEAN_KEY("search pattern", SEARCH_KEY_HIGHLIGHTED,
+ BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_HIGHLIGHTED,
entry->data.search_pattern.highlighted)
- BOOLEAN_KEY("search pattern", SEARCH_KEY_BACKWARD,
+ BOOLEAN_KEY(unpacked, "search pattern", SEARCH_KEY_BACKWARD,
entry->data.search_pattern.search_backward)
- INTEGER_KEY("search pattern", SEARCH_KEY_OFFSET,
+ INTEGER_KEY(unpacked, "search pattern", SEARCH_KEY_OFFSET,
entry->data.search_pattern.offset)
- CONVERTED_STRING_KEY("search pattern", SEARCH_KEY_PAT,
+ CONVERTED_STRING_KEY(unpacked, "search pattern", SEARCH_KEY_PAT,
entry->data.search_pattern.pat)
- ADDITIONAL_KEY
+ ADDITIONAL_KEY(unpacked)
}
if (entry->data.search_pattern.pat == NULL) {
emsgf(_(READERR("search pattern", "has no pattern")), initial_fpos);
@@ -3768,7 +3771,7 @@ shada_read_next_item_start:
garray_T ad_ga;
ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1);
for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
- CHECK_KEY_IS_STR("mark")
+ CHECK_KEY_IS_STR(unpacked, "mark")
if (CHECK_KEY(unpacked.data.via.map.ptr[i].key, KEY_NAME_CHAR)) {
if (type_u64 == kSDItemJump || type_u64 == kSDItemChange) {
emsgf(_(READERR("mark", "has n key which is only valid for "
@@ -3782,10 +3785,10 @@ shada_read_next_item_start:
"mark", unpacked.data.via.map.ptr[i].val,
entry->data.filemark.name, u64, TOCHAR);
}
- LONG_KEY("mark", KEY_LNUM, entry->data.filemark.mark.lnum)
- INTEGER_KEY("mark", KEY_COL, entry->data.filemark.mark.col)
- STRING_KEY("mark", KEY_FILE, entry->data.filemark.fname)
- ADDITIONAL_KEY
+ LONG_KEY(unpacked, "mark", KEY_LNUM, entry->data.filemark.mark.lnum)
+ INTEGER_KEY(unpacked, "mark", KEY_COL, entry->data.filemark.mark.col)
+ STRING_KEY(unpacked, "mark", KEY_FILE, entry->data.filemark.fname)
+ ADDITIONAL_KEY(unpacked)
}
if (entry->data.filemark.fname == NULL) {
emsgf(_(READERR("mark", "is missing file name")), initial_fpos);
@@ -3810,7 +3813,7 @@ shada_read_next_item_start:
garray_T ad_ga;
ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1);
for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
- CHECK_KEY_IS_STR("register")
+ CHECK_KEY_IS_STR(unpacked, "register")
if (CHECK_KEY(unpacked.data.via.map.ptr[i].key,
REG_KEY_CONTENTS)) {
if (unpacked.data.via.map.ptr[i].val.type != MSGPACK_OBJECT_ARRAY) {
@@ -3828,8 +3831,8 @@ shada_read_next_item_start:
}
const msgpack_object_array arr =
unpacked.data.via.map.ptr[i].val.via.array;
- for (size_t i = 0; i < arr.size; i++) {
- if (arr.ptr[i].type != MSGPACK_OBJECT_BIN) {
+ for (size_t j = 0; j < arr.size; j++) {
+ if (arr.ptr[j].type != MSGPACK_OBJECT_BIN) {
emsgf(_(READERR("register", "has " REG_KEY_CONTENTS " array "
"with non-binary value")), initial_fpos);
CLEAR_GA_AND_ERROR_OUT(ad_ga);
@@ -3837,18 +3840,19 @@ shada_read_next_item_start:
}
entry->data.reg.contents_size = arr.size;
entry->data.reg.contents = xmalloc(arr.size * sizeof(char *));
- for (size_t i = 0; i < arr.size; i++) {
- entry->data.reg.contents[i] = BIN_CONVERTED(arr.ptr[i].via.bin);
+ for (size_t j = 0; j < arr.size; j++) {
+ entry->data.reg.contents[j] = BIN_CONVERTED(arr.ptr[j].via.bin);
}
}
- BOOLEAN_KEY("register", REG_KEY_UNNAMED, entry->data.reg.is_unnamed)
- TYPED_KEY("register", REG_KEY_TYPE, "an unsigned integer",
+ BOOLEAN_KEY(unpacked, "register", REG_KEY_UNNAMED,
+ entry->data.reg.is_unnamed)
+ TYPED_KEY(unpacked, "register", REG_KEY_TYPE, "an unsigned integer",
entry->data.reg.type, POSITIVE_INTEGER, u64, TOU8)
- TYPED_KEY("register", KEY_NAME_CHAR, "an unsigned integer",
+ TYPED_KEY(unpacked, "register", KEY_NAME_CHAR, "an unsigned integer",
entry->data.reg.name, POSITIVE_INTEGER, u64, TOCHAR)
- TYPED_KEY("register", REG_KEY_WIDTH, "an unsigned integer",
+ TYPED_KEY(unpacked, "register", REG_KEY_WIDTH, "an unsigned integer",
entry->data.reg.width, POSITIVE_INTEGER, u64, TOSIZE)
- ADDITIONAL_KEY
+ ADDITIONAL_KEY(unpacked)
}
if (entry->data.reg.contents == NULL) {
emsgf(_(READERR("register", "has missing " REG_KEY_CONTENTS " array")),
@@ -3990,8 +3994,7 @@ shada_read_next_item_start:
.data = unpacked.data.via.array.ptr[i],
};
{
- msgpack_unpacked unpacked = unpacked_2;
- if (unpacked.data.type != MSGPACK_OBJECT_MAP) {
+ if (unpacked_2.data.type != MSGPACK_OBJECT_MAP) {
emsgf(_(RERR "Error while reading ShaDa file: "
"buffer list at position %" PRIu64 " "
"contains entry that is not a dictionary"),
@@ -4000,21 +4003,23 @@ shada_read_next_item_start:
}
entry->data.buffer_list.buffers[i].pos = default_pos;
garray_T ad_ga;
- ga_init(&ad_ga, sizeof(*(unpacked.data.via.map.ptr)), 1);
+ ga_init(&ad_ga, sizeof(*(unpacked_2.data.via.map.ptr)), 1);
{
+ // XXX: Temporarily reassign `i` because the macros depend on it.
const size_t j = i;
{
- for (size_t i = 0; i < unpacked.data.via.map.size; i++) {
- CHECK_KEY_IS_STR("buffer list entry")
- LONG_KEY("buffer list entry", KEY_LNUM,
+ for (i = 0; i < unpacked_2.data.via.map.size; i++) { // -V535
+ CHECK_KEY_IS_STR(unpacked_2, "buffer list entry")
+ LONG_KEY(unpacked_2, "buffer list entry", KEY_LNUM,
entry->data.buffer_list.buffers[j].pos.lnum)
- INTEGER_KEY("buffer list entry", KEY_COL,
+ INTEGER_KEY(unpacked_2, "buffer list entry", KEY_COL,
entry->data.buffer_list.buffers[j].pos.col)
- STRING_KEY("buffer list entry", KEY_FILE,
+ STRING_KEY(unpacked_2, "buffer list entry", KEY_FILE,
entry->data.buffer_list.buffers[j].fname)
- ADDITIONAL_KEY
+ ADDITIONAL_KEY(unpacked_2)
}
}
+ i = j; // XXX: Restore `i`.
}
if (entry->data.buffer_list.buffers[i].pos.lnum <= 0) {
emsgf(_(RERR "Error while reading ShaDa file: "
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 518bd0922e..a9330e792a 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -2112,9 +2112,9 @@ char_u *did_set_spelllang(win_T *wp)
}
if (region_mask != 0) {
- langp_T *p = GA_APPEND_VIA_PTR(langp_T, &ga);
- p->lp_slang = slang;
- p->lp_region = region_mask;
+ langp_T *p_ = GA_APPEND_VIA_PTR(langp_T, &ga);
+ p_->lp_slang = slang;
+ p_->lp_region = region_mask;
use_midword(slang, wp);
if (slang->sl_nobreak)
@@ -2190,11 +2190,11 @@ char_u *did_set_spelllang(win_T *wp)
}
if (region_mask != 0) {
- langp_T *p = GA_APPEND_VIA_PTR(langp_T, &ga);
- p->lp_slang = slang;
- p->lp_sallang = NULL;
- p->lp_replang = NULL;
- p->lp_region = region_mask;
+ langp_T *p_ = GA_APPEND_VIA_PTR(langp_T, &ga);
+ p_->lp_slang = slang;
+ p_->lp_sallang = NULL;
+ p_->lp_replang = NULL;
+ p_->lp_region = region_mask;
use_midword(slang, wp);
}
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 8be8d24b9f..7a6f2fce39 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -4311,8 +4311,8 @@ static int write_vim_spell(spellinfo_T *spin, char_u *fname)
qsort(gap->ga_data, (size_t)gap->ga_len,
sizeof(fromto_T), rep_compare);
- int i = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL);
- putc(i, fd); // <sectionID>
+ int sect_id = round == 1 ? SN_REP : (round == 2 ? SN_SAL : SN_REPSAL);
+ putc(sect_id, fd); // <sectionID>
// This is for making suggestions, section is not required.
putc(0, fd); // <sectionflags>
diff --git a/src/nvim/state.c b/src/nvim/state.c
index d75f4038ae..bfd73050c3 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -113,7 +113,7 @@ int get_real_state(void)
/// @returns[allocated] mode string
char *get_mode(void)
{
- char *buf = xcalloc(3, sizeof(char));
+ char *buf = xcalloc(4, sizeof(char));
if (VIsual_active) {
if (VIsual_select) {
@@ -160,6 +160,8 @@ char *get_mode(void)
buf[0] = 'n';
if (finish_op) {
buf[1] = 'o';
+ // to be able to detect force-linewise/blockwise/characterwise operations
+ buf[2] = (char)motion_force;
}
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 973d09d065..81c78ca6a9 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -6463,7 +6463,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// If no argument, list current highlighting.
if (ends_excmd((uint8_t)(*line))) {
- for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
+ for (i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
// TODO(brammool): only call when the group has attributes set
highlight_list_one(i);
}
@@ -6569,8 +6569,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
restore_cterm_colors();
// Clear all default highlight groups and load the defaults.
- for (int idx = 0; idx < highlight_ga.ga_len; idx++) {
- highlight_clear(idx);
+ for (int j = 0; j < highlight_ga.ga_len; j++) {
+ highlight_clear(j);
}
init_highlight(true, true);
highlight_changed();
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index f715344689..51bf22b31c 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -529,6 +529,20 @@ void terminal_send(Terminal *term, char *data, size_t size)
term->opts.write_cb(data, size, term->opts.data);
}
+void terminal_paste(long count, char_u **y_array, size_t y_size)
+{
+ for (int i = 0; i < count; i++) { // -V756
+ // feed the lines to the terminal
+ for (size_t j = 0; j < y_size; j++) {
+ if (j) {
+ // terminate the previous line
+ terminal_send(curbuf->terminal, "\n", 1);
+ }
+ terminal_send(curbuf->terminal, (char *)y_array[j], STRLEN(y_array[j]));
+ }
+ }
+}
+
void terminal_flush_output(Terminal *term)
{
size_t len = vterm_output_read(term->vt, term->textbuf,
diff --git a/src/nvim/testdir/pyxfile/py2_magic.py b/src/nvim/testdir/pyxfile/py2_magic.py
new file mode 100644
index 0000000000..819892fd16
--- /dev/null
+++ b/src/nvim/testdir/pyxfile/py2_magic.py
@@ -0,0 +1,4 @@
+# requires python 2.x
+
+import sys
+print(sys.version)
diff --git a/src/nvim/testdir/pyxfile/py2_shebang.py b/src/nvim/testdir/pyxfile/py2_shebang.py
new file mode 100644
index 0000000000..13bfc491ec
--- /dev/null
+++ b/src/nvim/testdir/pyxfile/py2_shebang.py
@@ -0,0 +1,4 @@
+#!/usr/bin/python2
+
+import sys
+print(sys.version)
diff --git a/src/nvim/testdir/pyxfile/py3_magic.py b/src/nvim/testdir/pyxfile/py3_magic.py
new file mode 100644
index 0000000000..d4b7ee0071
--- /dev/null
+++ b/src/nvim/testdir/pyxfile/py3_magic.py
@@ -0,0 +1,4 @@
+# requires python 3.x
+
+import sys
+print(sys.version)
diff --git a/src/nvim/testdir/pyxfile/py3_shebang.py b/src/nvim/testdir/pyxfile/py3_shebang.py
new file mode 100644
index 0000000000..ec05808ca4
--- /dev/null
+++ b/src/nvim/testdir/pyxfile/py3_shebang.py
@@ -0,0 +1,4 @@
+#!/usr/bin/python3
+
+import sys
+print(sys.version)
diff --git a/src/nvim/testdir/pyxfile/pyx.py b/src/nvim/testdir/pyxfile/pyx.py
new file mode 100644
index 0000000000..261a6512c0
--- /dev/null
+++ b/src/nvim/testdir/pyxfile/pyx.py
@@ -0,0 +1,2 @@
+import sys
+print(sys.version)
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index 4fe7db135b..bfd6240f0c 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -26,7 +26,7 @@
" It will be called after each Test_ function.
"
" When debugging a test it can be useful to add messages to v:errors:
-" call add(v:errors, "this happened")
+" call add(v:errors, "this happened")
" Check that the screen size is at least 24 x 80 characters.
@@ -130,6 +130,10 @@ func RunTheTest(test)
endtry
endif
+ " In case 'insertmode' was set and something went wrong, make sure it is
+ " reset to avoid trouble with anything else.
+ set noinsertmode
+
if exists("*TearDown")
try
call TearDown()
diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim
index 20171bb599..368fc9810d 100644
--- a/src/nvim/testdir/test_arglist.vim
+++ b/src/nvim/testdir/test_arglist.vim
@@ -170,6 +170,15 @@ func Test_argument()
call assert_fails('argument', 'E163:')
endfunc
+func Test_args_with_quote()
+ " Only on Unix can a file name include a double quote.
+ if has('unix')
+ args \"foobar
+ call assert_equal('"foobar', argv(0))
+ %argdelete
+ endif
+endfunc
+
" Test for 0argadd and 0argedit
" Ported from the test_argument_0count.in test script
func Test_zero_argadd()
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 0b4b5d1922..df3d691d85 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -704,6 +704,26 @@ func Test_fold_last_line_with_pagedown()
enew!
endfunc
+func Test_folds_with_rnu()
+ if !CanRunVimInTerminal()
+ return
+ endif
+
+ call writefile([
+ \ 'set fdm=marker rnu foldcolumn=2',
+ \ 'call setline(1, ["{{{1", "nline 1", "{{{1", "line 2"])',
+ \ ], 'Xtest_folds_with_rnu')
+ let buf = RunVimInTerminal('-S Xtest_folds_with_rnu', {})
+
+ call VerifyScreenDump(buf, 'Test_folds_with_rnu_01', {})
+ call term_sendkeys(buf, "j")
+ call VerifyScreenDump(buf, 'Test_folds_with_rnu_02', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('Xtest_folds_with_rnu')
+endfunc
+
func Test_folds_marker_in_comment2()
new
call setline(1, ['Lorem ipsum dolor sit', 'Lorem ipsum dolor sit', 'Lorem ipsum dolor sit'])
diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim
index 247c01c98d..32593a423a 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -230,3 +230,57 @@ func Test_abbreviation_CR()
delfunc Eatchar
bw!
endfunc
+
+func Test_motionforce_omap()
+ func GetCommand()
+ let g:m=mode(1)
+ let [g:lnum1, g:col1] = searchpos('-', 'Wb')
+ if g:lnum1 == 0
+ return "\<Esc>"
+ endif
+ let [g:lnum2, g:col2] = searchpos('-', 'W')
+ if g:lnum2 == 0
+ return "\<Esc>"
+ endif
+ return ":call Select()\<CR>"
+ endfunc
+ func Select()
+ call cursor([g:lnum1, g:col1])
+ exe "normal! 1 ". (strlen(g:m) == 2 ? 'v' : g:m[2])
+ call cursor([g:lnum2, g:col2])
+ execute "normal! \<BS>"
+ endfunc
+ new
+ onoremap <buffer><expr> i- GetCommand()
+ " 1) default omap mapping
+ %d_
+ call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
+ call cursor(2, 1)
+ norm di-
+ call assert_equal('no', g:m)
+ call assert_equal(['aaa -- eee'], getline(1, '$'))
+ " 2) forced characterwise operation
+ %d_
+ call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
+ call cursor(2, 1)
+ norm dvi-
+ call assert_equal('nov', g:m)
+ call assert_equal(['aaa -- eee'], getline(1, '$'))
+ " 3) forced linewise operation
+ %d_
+ call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
+ call cursor(2, 1)
+ norm dVi-
+ call assert_equal('noV', g:m)
+ call assert_equal([''], getline(1, '$'))
+ " 4) forced blockwise operation
+ %d_
+ call setline(1, ['aaa - bbb', 'x', 'ddd - eee'])
+ call cursor(2, 1)
+ exe "norm d\<C-V>i-"
+ call assert_equal("no\<C-V>", g:m)
+ call assert_equal(['aaabbb', 'x', 'dddeee'], getline(1, '$'))
+ bwipe!
+ delfunc Select
+ delfunc GetCommand
+endfunc
diff --git a/src/nvim/testdir/test_pyx2.vim b/src/nvim/testdir/test_pyx2.vim
new file mode 100644
index 0000000000..50e57c3bfb
--- /dev/null
+++ b/src/nvim/testdir/test_pyx2.vim
@@ -0,0 +1,74 @@
+" Test for pyx* commands and functions with Python 2.
+
+set pyx=2
+if !has('python')
+ finish
+endif
+
+let s:py2pattern = '^2\.[0-7]\.\d\+'
+let s:py3pattern = '^3\.\d\+\.\d\+'
+
+
+func Test_has_pythonx()
+ call assert_true(has('pythonx'))
+endfunc
+
+
+func Test_pyx()
+ redir => var
+ pyx << EOF
+import sys
+print(sys.version)
+EOF
+ redir END
+ call assert_match(s:py2pattern, split(var)[0])
+endfunc
+
+
+func Test_pyxdo()
+ pyx import sys
+ enew
+ pyxdo return sys.version.split("\n")[0]
+ call assert_match(s:py2pattern, split(getline('.'))[0])
+endfunc
+
+
+func Test_pyxeval()
+ pyx import sys
+ call assert_match(s:py2pattern, split(pyxeval('sys.version'))[0])
+endfunc
+
+
+func Test_pyxfile()
+ " No special comments nor shebangs
+ redir => var
+ pyxfile pyxfile/pyx.py
+ redir END
+ call assert_match(s:py2pattern, split(var)[0])
+
+ " Python 2 special comment
+ redir => var
+ pyxfile pyxfile/py2_magic.py
+ redir END
+ call assert_match(s:py2pattern, split(var)[0])
+
+ " Python 2 shebang
+ redir => var
+ pyxfile pyxfile/py2_shebang.py
+ redir END
+ call assert_match(s:py2pattern, split(var)[0])
+
+ if has('python3')
+ " Python 3 special comment
+ redir => var
+ pyxfile pyxfile/py3_magic.py
+ redir END
+ call assert_match(s:py3pattern, split(var)[0])
+
+ " Python 3 shebang
+ redir => var
+ pyxfile pyxfile/py3_shebang.py
+ redir END
+ call assert_match(s:py3pattern, split(var)[0])
+ endif
+endfunc
diff --git a/src/nvim/testdir/test_pyx3.vim b/src/nvim/testdir/test_pyx3.vim
new file mode 100644
index 0000000000..64546b4688
--- /dev/null
+++ b/src/nvim/testdir/test_pyx3.vim
@@ -0,0 +1,74 @@
+" Test for pyx* commands and functions with Python 3.
+
+set pyx=3
+if !has('python3')
+ finish
+endif
+
+let s:py2pattern = '^2\.[0-7]\.\d\+'
+let s:py3pattern = '^3\.\d\+\.\d\+'
+
+
+func Test_has_pythonx()
+ call assert_true(has('pythonx'))
+endfunc
+
+
+func Test_pyx()
+ redir => var
+ pyx << EOF
+import sys
+print(sys.version)
+EOF
+ redir END
+ call assert_match(s:py3pattern, split(var)[0])
+endfunc
+
+
+func Test_pyxdo()
+ pyx import sys
+ enew
+ pyxdo return sys.version.split("\n")[0]
+ call assert_match(s:py3pattern, split(getline('.'))[0])
+endfunc
+
+
+func Test_pyxeval()
+ pyx import sys
+ call assert_match(s:py3pattern, split(pyxeval('sys.version'))[0])
+endfunc
+
+
+func Test_pyxfile()
+ " No special comments nor shebangs
+ redir => var
+ pyxfile pyxfile/pyx.py
+ redir END
+ call assert_match(s:py3pattern, split(var)[0])
+
+ " Python 3 special comment
+ redir => var
+ pyxfile pyxfile/py3_magic.py
+ redir END
+ call assert_match(s:py3pattern, split(var)[0])
+
+ " Python 3 shebang
+ redir => var
+ pyxfile pyxfile/py3_shebang.py
+ redir END
+ call assert_match(s:py3pattern, split(var)[0])
+
+ if has('python')
+ " Python 2 special comment
+ redir => var
+ pyxfile pyxfile/py2_magic.py
+ redir END
+ call assert_match(s:py2pattern, split(var)[0])
+
+ " Python 2 shebang
+ redir => var
+ pyxfile pyxfile/py2_shebang.py
+ redir END
+ call assert_match(s:py2pattern, split(var)[0])
+ endif
+endfunc
diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim
index 756a455ebd..4a143d665d 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -277,3 +277,44 @@ func Test_visual_mode_reset()
set belloff&
endfunc
+
+func Test_Visual_sentence_textobject()
+ new
+ call setline(1, ['First sentence. Second sentence. Third', 'sentence. Fouth sentence'])
+
+ " When start and end of visual area are identical, 'as' or 'is' select
+ " the whole sentence.
+ norm! 1gofdvasy
+ call assert_equal('Second sentence. ', @")
+ norm! 1gofdvisy
+ call assert_equal('Second sentence.', @")
+
+ " When start and end of visual area are not identical, 'as' or 'is'
+ " extend the sentence in direction of the end of the visual area.
+ norm! 1gofdvlasy
+ call assert_equal('d sentence. ', @")
+ norm! gvasy
+ call assert_equal("d sentence. Third\nsentence. ", @")
+
+ norm! 1gofdvlisy
+ call assert_equal('d sentence.', @")
+ norm! gvisy
+ call assert_equal('d sentence. ', @")
+ norm! gvisy
+ call assert_equal("d sentence. Third\nsentence.", @")
+
+ " Extend visual area in opposite direction.
+ norm! 1gofdvhasy
+ call assert_equal(' Second', @")
+ norm! gvasy
+ call assert_equal("First sentence. Second", @")
+
+ norm! 1gofdvhisy
+ call assert_equal('Second', @")
+ norm! gvisy
+ call assert_equal(' Second', @")
+ norm! gvisy
+ call assert_equal('First sentence. Second', @")
+
+ bwipe!
+endfunc
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 0362820687..a0df80a8e8 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -352,8 +352,8 @@ static bool handle_forced_escape(TermInput *input)
return false;
}
-static void read_cb(Stream *stream, RBuffer *buf, size_t c, void *data,
- bool eof)
+static void read_cb(Stream *stream, RBuffer *buf, size_t count_, void *data,
+ bool eof)
{
TermInput *input = data;
diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c
index 27792655c9..14023ce2cb 100644
--- a/src/nvim/tui/terminfo.c
+++ b/src/nvim/tui/terminfo.c
@@ -137,9 +137,6 @@ unibi_term *terminfo_from_builtin(const char *term, char **termname)
if (*termname == NULL) {
*termname = xstrdup("builtin_?");
}
- // Disable BCE by default (for built-in terminfos). #7624
- // https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545
- unibi_set_bool(ut, unibi_back_color_erase, false);
return ut;
}
diff --git a/src/nvim/tui/terminfo_defs.h b/src/nvim/tui/terminfo_defs.h
index 82fab415a2..8d77dc7225 100644
--- a/src/nvim/tui/terminfo_defs.h
+++ b/src/nvim/tui/terminfo_defs.h
@@ -122,7 +122,7 @@ static const int8_t ansi_terminfo[] = {
// clr_eos=\E[J,
// column_address=\E[%i%p1%dG,
// cursor_address=\E[%i%p1%d;%p2%dH,
-// cursor_down=\n,
+// cursor_down=\E[B,
// cursor_home=\E[H,
// cursor_invisible=\E[?25l,
// cursor_left=^H,
@@ -284,7 +284,7 @@ static const int8_t ansi_terminfo[] = {
// user8@,
// user9@,
static const int8_t conemu_terminfo[] = {
- 30,2,61,0,38,0,15,0,-99,1,29,3,99,111,110,101,109,117,124,65,78,73,83,32,88,51,46,54,52,32,97,110,100,32,88,116,101,114,109,32,50,53,54,32,99,111,108,111,114,115,32,102,111,114,32,67,111,110,69,109,117,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,-2,-1,0,0,2,0,4,0,-2,-1,21,0,29,0,33,0,37,0,-1,-1,48,0,65,0,67,0,71,0,78,0,-1,-1,80,0,87,0,-1,-1,91,0,-2,-1,95,0,99,0,-1,-1,-1,-1,-2,-1,-2,-1,103,0,108,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,117,0,122,0,127,0,-124,0,-2,-1,-115,0,-110,0,-1,-1,-2,-1,-101,0,-95,0,-2,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-89,0,-1,-1,-85,0,-1,-1,-1,-1,-1,-1,-83,0,-1,-1,-78,0,-1,-1,-1,-1,-1,-1,-1,-1,-74,0,-69,0,-63,0,-58,0,-53,0,-48,0,-43,0,-37,0,-31,0,-25,0,-19,0,-14,0,-1,-1,-9,0,-1,-1,-5,0,0,1,5,1,9,1,16,1,-1,-1,23,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,27,1,36,1,45,1,54,1,63,1,72,1,81,1,90,1,99,1,108,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,117,1,-2,-1,-2,-1,-1,-1,-1,-1,-119,1,-116,1,-105,1,-102,1,-100,1,-97,1,-2,-1,-1,-1,-54,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-52,1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-48,1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-44,1,-39,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-35,1,-1,-1,-1,-1,-28,1,-1,-1,-1,-1,-1,-1,-1,-1,-21,1,-14,1,-7,1,-1,-1,-1,-1,0,2,-1,-1,7,2,-1,-1,-1,-1,-1,-1,14,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,21,2,27,2,33,2,39,2,45,2,51,2,57,2,63,2,69,2,75,2,81,2,87,2,93,2,99,2,105,2,111,2,117,2,123,2,-127,2,-121,2,-115,2,-109,2,-103,2,-97,2,-91,2,-85,2,-79,2,-73,2,-67,2,-61,2,-54,2,-48,2,-42,2,-36,2,-30,2,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-24,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-19,2,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-10,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-5,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,1,3,15,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,9,0,27,91,71,0,27,91,90,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,51,56,59,53,59,37,112,49,37,100,109,0,27,91,52,56,59,53,59,37,112,49,37,100,109,0,0,3,0,1,0,73,0,-106,0,-101,1,1,0,1,0,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,0,0,-2,-1,-1,-1,5,0,11,0,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,21,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,36,0,39,0,42,0,48,0,54,0,59,0,64,0,69,0,74,0,79,0,83,0,88,0,93,0,98,0,103,0,108,0,114,0,120,0,126,0,-124,0,-118,0,-112,0,-106,0,-100,0,-94,0,-88,0,-82,0,-76,0,-71,0,-66,0,-61,0,-56,0,-51,0,-45,0,-39,0,-33,0,-27,0,-21,0,-15,0,-9,0,-3,0,3,1,9,1,15,1,21,1,27,1,33,1,39,1,45,1,51,1,57,1,63,1,69,1,73,1,78,1,83,1,88,1,93,1,98,1,102,1,106,1,110,1,114,1,119,1,124,1,27,91,51,74,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,49,59,50,65,0,65,88,0,71,48,0,88,84,0,85,56,0,67,114,0,67,115,0,69,48,0,69,51,0,77,115,0,83,48,0,83,101,0,83,115,0,84,83,0,88,77,0,103,114,98,111,109,0,103,115,98,111,109,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,69,78,68,56,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,72,79,77,56,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,114,109,120,120,0,115,109,120,120,0,120,109,0 // NOLINT
+ 30,2,61,0,38,0,15,0,-99,1,31,3,99,111,110,101,109,117,124,65,78,73,83,32,88,51,46,54,52,32,97,110,100,32,88,116,101,114,109,32,50,53,54,32,99,111,108,111,114,115,32,102,111,114,32,67,111,110,69,109,117,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,-2,-1,0,0,2,0,4,0,-2,-1,21,0,29,0,33,0,37,0,-1,-1,48,0,65,0,69,0,73,0,80,0,-1,-1,82,0,89,0,-1,-1,93,0,-2,-1,97,0,101,0,-1,-1,-1,-1,-2,-1,-2,-1,105,0,110,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,119,0,124,0,-127,0,-122,0,-2,-1,-113,0,-108,0,-1,-1,-2,-1,-99,0,-93,0,-2,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-87,0,-1,-1,-83,0,-1,-1,-1,-1,-1,-1,-81,0,-1,-1,-76,0,-1,-1,-1,-1,-1,-1,-1,-1,-72,0,-67,0,-61,0,-56,0,-51,0,-46,0,-41,0,-35,0,-29,0,-23,0,-17,0,-12,0,-1,-1,-7,0,-1,-1,-3,0,2,1,7,1,11,1,18,1,-1,-1,25,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,29,1,38,1,47,1,56,1,65,1,74,1,83,1,92,1,101,1,110,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,119,1,-2,-1,-2,-1,-1,-1,-1,-1,-117,1,-114,1,-103,1,-100,1,-98,1,-95,1,-2,-1,-1,-1,-52,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-50,1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-46,1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-42,1,-37,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-33,1,-1,-1,-1,-1,-26,1,-1,-1,-1,-1,-1,-1,-1,-1,-19,1,-12,1,-5,1,-1,-1,-1,-1,2,2,-1,-1,9,2,-1,-1,-1,-1,-1,-1,16,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,23,2,29,2,35,2,41,2,47,2,53,2,59,2,65,2,71,2,77,2,83,2,89,2,95,2,101,2,107,2,113,2,119,2,125,2,-125,2,-119,2,-113,2,-107,2,-101,2,-95,2,-89,2,-83,2,-77,2,-71,2,-65,2,-59,2,-52,2,-46,2,-40,2,-34,2,-28,2,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-22,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-17,2,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-8,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-3,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,3,3,17,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,91,66,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,9,0,27,91,71,0,27,91,90,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,51,56,59,53,59,37,112,49,37,100,109,0,27,91,52,56,59,53,59,37,112,49,37,100,109,0,0,3,0,1,0,74,0,-104,0,-95,1,1,0,1,0,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,0,0,-2,-1,-1,-1,5,0,-1,-1,11,0,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,21,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,39,0,42,0,45,0,48,0,54,0,60,0,65,0,70,0,75,0,80,0,85,0,89,0,94,0,99,0,104,0,109,0,114,0,120,0,126,0,-124,0,-118,0,-112,0,-106,0,-100,0,-94,0,-88,0,-82,0,-76,0,-70,0,-65,0,-60,0,-55,0,-50,0,-45,0,-39,0,-33,0,-27,0,-21,0,-15,0,-9,0,-3,0,3,1,9,1,15,1,21,1,27,1,33,1,39,1,45,1,51,1,57,1,63,1,69,1,75,1,79,1,84,1,89,1,94,1,99,1,104,1,108,1,112,1,116,1,120,1,125,1,-126,1,27,91,51,74,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,49,59,50,65,0,65,88,0,71,48,0,88,84,0,85,56,0,67,114,0,67,115,0,69,48,0,69,51,0,77,115,0,83,48,0,83,101,0,83,109,117,108,120,0,83,115,0,84,83,0,88,77,0,103,114,98,111,109,0,103,115,98,111,109,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,69,78,68,56,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,72,79,77,56,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,114,109,120,120,0,115,109,120,120,0,120,109,0 // NOLINT
};
// cygwin|ANSI emulation for Cygwin,
@@ -1780,7 +1780,7 @@ static const int8_t vte_256colour_terminfo[] = {
// clr_eos=\E[J,
// column_address=\E[%i%p1%dG,
// cursor_address=\E[%i%p1%d;%p2%dH,
-// cursor_down=\n,
+// cursor_down=\E[B,
// cursor_home=\E[H,
// cursor_invisible=\E[?25l,
// cursor_left=^H,
@@ -1942,7 +1942,7 @@ static const int8_t vte_256colour_terminfo[] = {
// user8@,
// user9@,
static const int8_t vtpcon_terminfo[] = {
- 30,2,71,0,38,0,15,0,-99,1,19,4,118,116,112,99,111,110,124,65,78,73,83,32,101,109,117,108,97,116,105,111,110,32,102,111,114,32,99,111,110,115,111,108,101,32,118,105,114,116,117,97,108,32,116,101,114,109,105,110,97,108,32,115,101,113,117,101,110,99,101,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,-2,-1,25,0,33,0,37,0,41,0,-1,-1,52,0,69,0,71,0,75,0,82,0,-1,-1,84,0,97,0,-1,-1,101,0,-2,-1,105,0,109,0,-1,-1,-1,-1,113,0,-2,-1,117,0,122,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,-125,0,-120,0,-115,0,-110,0,-101,0,-97,0,-92,0,-1,-1,-2,-1,-83,0,-77,0,-2,-1,-1,-1,-1,-1,-1,-1,-71,0,-1,-1,-1,-1,-1,-1,-61,0,-1,-1,-57,0,-1,-1,-1,-1,-1,-1,-55,0,-1,-1,-50,0,-1,-1,-1,-1,-1,-1,-1,-1,-46,0,-41,0,-35,0,-30,0,-25,0,-20,0,-15,0,-9,0,-3,0,3,1,9,1,14,1,-1,-1,19,1,-1,-1,23,1,28,1,33,1,37,1,44,1,-1,-1,51,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,55,1,64,1,73,1,82,1,91,1,100,1,109,1,118,1,127,1,-120,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-111,1,-2,-1,-2,-1,-1,-1,-1,-1,-91,1,-88,1,-77,1,-74,1,-72,1,-69,1,-26,1,-1,-1,-23,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-21,1,-1,-1,-1,-1,-1,-1,-1,-1,-17,1,-1,-1,6,2,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,2,15,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,19,2,-1,-1,-1,-1,26,2,-1,-1,-1,-1,-1,-1,-1,-1,33,2,40,2,47,2,-1,-1,-1,-1,54,2,-1,-1,61,2,-1,-1,-1,-1,-1,-1,68,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,75,2,81,2,87,2,93,2,99,2,105,2,111,2,117,2,123,2,-127,2,-121,2,-115,2,-109,2,-103,2,-97,2,-91,2,-85,2,-79,2,-73,2,-67,2,-61,2,-55,2,-49,2,-43,2,-37,2,-31,2,-25,2,-19,2,-13,2,-7,2,0,3,6,3,12,3,18,3,24,3,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,30,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,35,3,-2,-1,44,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-119,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-114,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-108,3,-45,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,49,50,108,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,40,48,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,33,112,27,91,63,51,108,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,27,72,0,9,0,27,91,71,0,106,106,107,107,108,108,109,109,110,110,113,113,116,116,117,117,118,118,119,119,120,120,0,27,91,90,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,51,57,59,52,57,109,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,0,27,91,51,109,0,27,91,50,51,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,0,3,0,1,0,73,0,-106,0,-101,1,1,0,1,0,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,0,0,-2,-1,-1,-1,5,0,11,0,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,21,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,36,0,39,0,42,0,48,0,54,0,59,0,64,0,69,0,74,0,79,0,83,0,88,0,93,0,98,0,103,0,108,0,114,0,120,0,126,0,-124,0,-118,0,-112,0,-106,0,-100,0,-94,0,-88,0,-82,0,-76,0,-71,0,-66,0,-61,0,-56,0,-51,0,-45,0,-39,0,-33,0,-27,0,-21,0,-15,0,-9,0,-3,0,3,1,9,1,15,1,21,1,27,1,33,1,39,1,45,1,51,1,57,1,63,1,69,1,73,1,78,1,83,1,88,1,93,1,98,1,102,1,106,1,110,1,114,1,119,1,124,1,27,91,51,74,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,49,59,50,65,0,65,88,0,71,48,0,88,84,0,85,56,0,67,114,0,67,115,0,69,48,0,69,51,0,77,115,0,83,48,0,83,101,0,83,115,0,84,83,0,88,77,0,103,114,98,111,109,0,103,115,98,111,109,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,69,78,68,56,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,72,79,77,56,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,114,109,120,120,0,115,109,120,120,0,120,109,0 // NOLINT
+ 30,2,71,0,38,0,15,0,-99,1,21,4,118,116,112,99,111,110,124,65,78,73,83,32,101,109,117,108,97,116,105,111,110,32,102,111,114,32,99,111,110,115,111,108,101,32,118,105,114,116,117,97,108,32,116,101,114,109,105,110,97,108,32,115,101,113,117,101,110,99,101,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,-2,-1,25,0,33,0,37,0,41,0,-1,-1,52,0,69,0,73,0,77,0,84,0,-1,-1,86,0,99,0,-1,-1,103,0,-2,-1,107,0,111,0,-1,-1,-1,-1,115,0,-2,-1,119,0,124,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,-123,0,-118,0,-113,0,-108,0,-99,0,-95,0,-90,0,-1,-1,-2,-1,-81,0,-75,0,-2,-1,-1,-1,-1,-1,-1,-1,-69,0,-1,-1,-1,-1,-1,-1,-59,0,-1,-1,-55,0,-1,-1,-1,-1,-1,-1,-53,0,-1,-1,-48,0,-1,-1,-1,-1,-1,-1,-1,-1,-44,0,-39,0,-33,0,-28,0,-23,0,-18,0,-13,0,-7,0,-1,0,5,1,11,1,16,1,-1,-1,21,1,-1,-1,25,1,30,1,35,1,39,1,46,1,-1,-1,53,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,57,1,66,1,75,1,84,1,93,1,102,1,111,1,120,1,-127,1,-118,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-109,1,-2,-1,-2,-1,-1,-1,-1,-1,-89,1,-86,1,-75,1,-72,1,-70,1,-67,1,-24,1,-1,-1,-21,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-19,1,-1,-1,-1,-1,-1,-1,-1,-1,-15,1,-1,-1,8,2,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,12,2,17,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,21,2,-1,-1,-1,-1,28,2,-1,-1,-1,-1,-1,-1,-1,-1,35,2,42,2,49,2,-1,-1,-1,-1,56,2,-1,-1,63,2,-1,-1,-1,-1,-1,-1,70,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,77,2,83,2,89,2,95,2,101,2,107,2,113,2,119,2,125,2,-125,2,-119,2,-113,2,-107,2,-101,2,-95,2,-89,2,-83,2,-77,2,-71,2,-65,2,-59,2,-53,2,-47,2,-41,2,-35,2,-29,2,-23,2,-17,2,-11,2,-5,2,2,3,8,3,14,3,20,3,26,3,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,32,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,37,3,-2,-1,46,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-117,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-112,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-106,3,-43,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,91,66,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,49,50,108,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,40,48,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,33,112,27,91,63,51,108,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,27,72,0,9,0,27,91,71,0,106,106,107,107,108,108,109,109,110,110,113,113,116,116,117,117,118,118,119,119,120,120,0,27,91,90,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,51,57,59,52,57,109,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,0,27,91,51,109,0,27,91,50,51,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,0,3,0,1,0,74,0,-104,0,-95,1,1,0,1,0,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,0,0,-2,-1,-1,-1,5,0,-1,-1,11,0,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,21,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,39,0,42,0,45,0,48,0,54,0,60,0,65,0,70,0,75,0,80,0,85,0,89,0,94,0,99,0,104,0,109,0,114,0,120,0,126,0,-124,0,-118,0,-112,0,-106,0,-100,0,-94,0,-88,0,-82,0,-76,0,-70,0,-65,0,-60,0,-55,0,-50,0,-45,0,-39,0,-33,0,-27,0,-21,0,-15,0,-9,0,-3,0,3,1,9,1,15,1,21,1,27,1,33,1,39,1,45,1,51,1,57,1,63,1,69,1,75,1,79,1,84,1,89,1,94,1,99,1,104,1,108,1,112,1,116,1,120,1,125,1,-126,1,27,91,51,74,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,49,59,50,65,0,65,88,0,71,48,0,88,84,0,85,56,0,67,114,0,67,115,0,69,48,0,69,51,0,77,115,0,83,48,0,83,101,0,83,109,117,108,120,0,83,115,0,84,83,0,88,77,0,103,114,98,111,109,0,103,115,98,111,109,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,69,78,68,56,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,72,79,77,56,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,114,109,120,120,0,115,109,120,120,0,120,109,0 // NOLINT
};
// win32con|ANSI emulation for libuv on legacy console,
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index d1e456f185..2e26a75be1 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -121,6 +121,7 @@ typedef struct {
int resize_screen;
int reset_scroll_region;
int set_cursor_style, reset_cursor_style;
+ int save_title, restore_title;
int enter_undercurl_mode, exit_undercurl_mode, set_underline_color;
} unibi_ext;
char *space_buf;
@@ -271,9 +272,11 @@ static void terminfo_start(UI *ui)
data->invis, sizeof data->invis);
// Set 't_Co' from the result of unibilium & fix_terminfo.
t_colors = unibi_get_num(data->ut, unibi_max_colors);
- // Enter alternate screen and clear
+ // Enter alternate screen, save title, and clear.
// NOTE: Do this *before* changing terminal settings. #6433
unibi_out(ui, unibi_enter_ca_mode);
+ // Save title/icon to the "stack". #4063
+ unibi_out_ext(ui, data->unibi_ext.save_title);
unibi_out(ui, unibi_keypad_xmit);
unibi_out(ui, unibi_clear_screen);
// Enable bracketed paste
@@ -300,10 +303,12 @@ static void terminfo_stop(UI *ui)
tui_mode_change(ui, (String)STRING_INIT, SHAPE_IDX_N);
tui_mouse_off(ui);
unibi_out(ui, unibi_exit_attribute_mode);
- // cursor should be set to normal before exiting alternate screen
+ // Reset cursor to normal before exiting alternate screen.
unibi_out(ui, unibi_cursor_normal);
unibi_out(ui, unibi_keypad_local);
unibi_out(ui, unibi_exit_ca_mode);
+ // Restore title/icon from the "stack". #4063
+ unibi_out_ext(ui, data->unibi_ext.restore_title);
if (data->cursor_color_changed) {
unibi_out_ext(ui, data->unibi_ext.reset_cursor_color);
}
@@ -1047,6 +1052,7 @@ static void tui_grid_scroll(UI *ui, Integer g, Integer startrow, Integer endrow,
Integer startcol, Integer endcol,
Integer rows, Integer cols)
{
+ (void)cols; // unused
TUIData *data = ui->data;
UGrid *grid = &data->grid;
int top = (int)startrow, bot = (int)endrow-1;
@@ -1169,7 +1175,7 @@ static void tui_flush(UI *ui)
}
UGRID_FOREACH_CELL(grid, row, r.left, clear_col, {
- cursor_goto(ui, row, col);
+ cursor_goto(ui, row, curcol);
print_cell(ui, cell);
});
if (clear_col < r.right) {
@@ -1278,7 +1284,7 @@ static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
grid->cells[linerow][c].attr = attrs[c-startcol];
}
UGRID_FOREACH_CELL(grid, (int)linerow, (int)startcol, (int)endcol, {
- cursor_goto(ui, (int)linerow, col);
+ cursor_goto(ui, (int)linerow, curcol);
print_cell(ui, cell);
});
@@ -1589,9 +1595,9 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m");
unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]2");
unibi_set_if_empty(ut, unibi_from_status_line, "\x07");
- // Enter/exit alternate screen with "title stacking". #4063
- unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h\x1b[22;0;0t");
- unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l\x1b[23;0;0t");
+ // 2017-04 terminfo.src has older control sequences.
+ unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h");
+ unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l");
} else if (screen) {
// per the screen manual; 2017-04 terminfo.src lacks these.
unibi_set_if_empty(ut, unibi_to_status_line, "\x1b_");
@@ -1611,9 +1617,9 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
} else if (putty) {
// No bugs in the vanilla terminfo for our purposes.
} else if (iterm) {
- // Enter/exit alternate screen with "title stacking". #4063
- unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h\x1b[22;0;0t");
- unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l\x1b[23;0;0t");
+ // 2017-04 terminfo.src has older control sequences.
+ unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h");
+ unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l");
// 2017-04 terminfo.src lacks these.
unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr");
unibi_set_if_empty(ut, unibi_orig_pair, "\x1b[39;49m");
@@ -1675,8 +1681,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
}
// Blacklist of terminals that cannot be trusted to report DECSCUSR support.
- if (!(st || (vte_version != 0 && vte_version < 3900)
- || (konsolev > 0 && konsolev < 180770))) {
+ if (!(st || (vte_version != 0 && vte_version < 3900) || konsolev)) {
data->unibi_ext.reset_cursor_style = unibi_find_ext_str(ut, "Se");
data->unibi_ext.set_cursor_style = unibi_find_ext_str(ut, "Ss");
}
@@ -1866,6 +1871,11 @@ static void augment_terminfo(TUIData *data, const char *term,
ut, "ext.reset_cursor_color", "\x1b]112\x07");
}
+ data->unibi_ext.save_title = (int)unibi_add_ext_str(
+ ut, "ext.save_title", "\x1b[22;0;0t");
+ data->unibi_ext.restore_title = (int)unibi_add_ext_str(
+ ut, "ext.restore_title", "\x1b[23;0;0t");
+
/// Terminals usually ignore unrecognized private modes, and there is no
/// known ambiguity with these. So we just set them unconditionally.
data->unibi_ext.enable_lr_margin = (int)unibi_add_ext_str(
diff --git a/src/nvim/types.h b/src/nvim/types.h
index 317bead3bb..f803b45e27 100644
--- a/src/nvim/types.h
+++ b/src/nvim/types.h
@@ -13,6 +13,9 @@ typedef unsigned char char_u;
// Can hold one decoded UTF-8 character.
typedef uint32_t u8char_T;
+// Opaque handle used by API clients to refer to various objects in vim
+typedef int handle_T;
+
typedef struct expand expand_T;
#endif // NVIM_TYPES_H
diff --git a/src/nvim/ugrid.h b/src/nvim/ugrid.h
index 33a706b8c0..19c2e99ebb 100644
--- a/src/nvim/ugrid.h
+++ b/src/nvim/ugrid.h
@@ -25,8 +25,8 @@ struct ugrid {
#define UGRID_FOREACH_CELL(grid, row, startcol, endcol, code) \
do { \
UCell *row_cells = (grid)->cells[row]; \
- for (int col = startcol; col < endcol; col++) { \
- UCell *cell = row_cells + col; \
+ for (int curcol = startcol; curcol < endcol; curcol++) { \
+ UCell *cell = row_cells + curcol; \
(void)(cell); \
code; \
} \
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 0c69e94e5d..96232ab223 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -51,12 +51,13 @@
static UI *uis[MAX_UI_COUNT];
static bool ui_ext[kUIExtCount] = { 0 };
static size_t ui_count = 0;
-static int row = 0, col = 0;
+static int ui_mode_idx = SHAPE_IDX_N;
+static int cursor_row = 0, cursor_col = 0;
static bool pending_cursor_update = false;
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 handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE;
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
# define UI_LOG(funname, ...)
@@ -188,21 +189,14 @@ void ui_refresh(void)
UI *ui = uis[i];
width = MIN(ui->width, width);
height = MIN(ui->height, height);
- for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
- ext_widgets[i] &= ui->ui_ext[i];
+ for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
+ ext_widgets[j] &= ui->ui_ext[j];
}
}
- row = col = 0;
+ cursor_row = cursor_col = 0;
pending_cursor_update = true;
- ui_default_colors_set();
-
- int save_p_lz = p_lz;
- p_lz = false; // convince redrawing() to return true ...
- screen_resize(width, height);
- p_lz = save_p_lz;
-
for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
ui_ext[i] = ext_widgets[i];
if (i < kUIGlobalCount) {
@@ -210,6 +204,14 @@ void ui_refresh(void)
BOOLEAN_OBJ(ext_widgets[i]));
}
}
+
+ ui_default_colors_set();
+
+ int save_p_lz = p_lz;
+ p_lz = false; // convince redrawing() to return true ...
+ screen_resize(width, height);
+ p_lz = save_p_lz;
+
ui_mode_info_set();
pending_mode_update = true;
ui_cursor_shape();
@@ -315,30 +317,43 @@ 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->line_offset[row] + (size_t)startcol;
+
+ UI_CALL(raw_line, grid->handle, row, startcol, endcol, clearcol, clearattr,
+ wrap, (const schar_T *)grid->chars + off,
+ (const sattr_T *)grid->attrs + 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
- ui_cursor_goto(row, MIN(clearcol, (int)Columns-1));
+ int old_row = cursor_row, old_col = cursor_col;
+ handle_T old_grid = cursor_grid_handle;
+ // If 'writedelay' is active, set the cursor to indicate what was drawn.
+ ui_grid_cursor_goto(grid->handle, row, MIN(clearcol, (int)Columns-1));
ui_flush();
uint64_t wd = (uint64_t)labs(p_wd);
os_microdelay(wd * 1000u, true);
- ui_cursor_goto(old_row, old_col);
+ ui_grid_cursor_goto(old_grid, old_row, old_col);
}
}
void ui_cursor_goto(int new_row, int new_col)
{
- if (new_row == row && new_col == col) {
+ ui_grid_cursor_goto(DEFAULT_GRID_HANDLE, new_row, new_col);
+}
+
+void ui_grid_cursor_goto(handle_T grid_handle, int new_row, int new_col)
+{
+ if (new_row == cursor_row
+ && new_col == cursor_col
+ && grid_handle == cursor_grid_handle) {
return;
}
- row = new_row;
- col = new_col;
+
+ cursor_row = new_row;
+ cursor_col = new_col;
+ cursor_grid_handle = grid_handle;
pending_cursor_update = true;
}
@@ -349,19 +364,20 @@ void ui_mode_info_set(void)
int ui_current_row(void)
{
- return row;
+ return cursor_row;
}
int ui_current_col(void)
{
- return col;
+ return cursor_col;
}
void ui_flush(void)
{
cmdline_ui_flush();
+ win_ui_flush();
if (pending_cursor_update) {
- ui_call_grid_cursor_goto(1, row, col);
+ ui_call_grid_cursor_goto(cursor_grid_handle, cursor_row, cursor_col);
pending_cursor_update = false;
}
if (pending_mode_info_update) {
@@ -372,8 +388,8 @@ void ui_flush(void)
pending_mode_info_update = false;
}
if (pending_mode_update) {
- char *full_name = shape_table[mode_idx].full_name;
- ui_call_mode_change(cstr_as_string(full_name), mode_idx);
+ char *full_name = shape_table[ui_mode_idx].full_name;
+ ui_call_mode_change(cstr_as_string(full_name), ui_mode_idx);
pending_mode_update = false;
}
ui_call_flush();
@@ -389,8 +405,8 @@ void ui_cursor_shape(void)
}
int new_mode_idx = cursor_get_mode_idx();
- if (new_mode_idx != mode_idx) {
- mode_idx = new_mode_idx;
+ if (new_mode_idx != ui_mode_idx) {
+ ui_mode_idx = new_mode_idx;
pending_mode_update = true;
}
conceal_check_cursor_line();
@@ -421,3 +437,22 @@ Array ui_array(void)
}
return all_uis;
}
+
+void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error)
+{
+ if (grid_handle == DEFAULT_GRID_HANDLE) {
+ screen_resize(width, height);
+ return;
+ }
+
+ win_T *wp = get_win_by_grid_handle(grid_handle);
+ if (wp == NULL) {
+ api_set_error(error, kErrorTypeValidation,
+ "No window with the given handle");
+ return;
+ }
+
+ wp->w_grid.requested_rows = (int)height;
+ wp->w_grid.requested_cols = (int)width;
+ redraw_win_later(wp, SOME_VALID);
+}
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/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 1a7e55c11e..dcc64db8a0 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -2845,30 +2845,32 @@ viml_pexpr_parse_no_paren_closing_error: {}
kvi_push(ast_stack, new_top_node_p);
want_node = kENodeOperator;
} else {
- if (want_node == kENodeValue) {
- NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeNested);
- *top_node_p = cur_node;
- kvi_push(ast_stack, &cur_node->children);
- HL_CUR_TOKEN(NestingParenthesis);
- } else if (want_node == kENodeOperator) {
- if (prev_token.type == kExprLexSpacing) {
- // For some reason "function (args)" is a function call, but
- // "(funcref) (args)" is not. AFAIR this somehow involves
- // compatibility and Bram was commenting that this is
- // intentionally inconsistent and he is not very happy with the
- // situation himself.
- if ((*top_node_p)->type != kExprNodePlainIdentifier
- && (*top_node_p)->type != kExprNodeComplexIdentifier
- && (*top_node_p)->type != kExprNodeCurlyBracesIdentifier) {
- OP_MISSING;
+ switch (want_node) {
+ case kENodeValue: {
+ NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeNested);
+ *top_node_p = cur_node;
+ kvi_push(ast_stack, &cur_node->children);
+ HL_CUR_TOKEN(NestingParenthesis);
+ break;
+ }
+ case kENodeOperator: {
+ if (prev_token.type == kExprLexSpacing) {
+ // For some reason "function (args)" is a function call, but
+ // "(funcref) (args)" is not. AFAIR this somehow involves
+ // compatibility and Bram was commenting that this is
+ // intentionally inconsistent and he is not very happy with the
+ // situation himself.
+ if ((*top_node_p)->type != kExprNodePlainIdentifier
+ && (*top_node_p)->type != kExprNodeComplexIdentifier
+ && (*top_node_p)->type != kExprNodeCurlyBracesIdentifier) {
+ OP_MISSING;
+ }
}
+ NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeCall);
+ ADD_OP_NODE(cur_node);
+ HL_CUR_TOKEN(CallingParenthesis);
+ break;
}
- NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeCall);
- ADD_OP_NODE(cur_node);
- HL_CUR_TOKEN(CallingParenthesis);
- } else {
- // Currently it is impossible to reach this.
- assert(false);
}
want_node = kENodeValue;
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 8be79f0cff..97c708ed20 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -997,6 +997,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
p_wh = i;
}
+ // Send the window positions to the UI
+ oldwin->w_pos_changed = true;
+
return OK;
}
@@ -1341,6 +1344,9 @@ static void win_rotate(int upwards, int count)
(void)win_comp_pos();
}
+ wp1->w_pos_changed = true;
+ wp2->w_pos_changed = true;
+
redraw_all_later(NOT_VALID);
}
@@ -1423,6 +1429,9 @@ void win_move_after(win_T *win1, win_T *win2)
redraw_later(NOT_VALID);
}
win_enter(win1, false);
+
+ win1->w_pos_changed = true;
+ win2->w_pos_changed = true;
}
/*
@@ -2059,6 +2068,7 @@ int win_close(win_T *win, bool free_buf)
if (help_window)
restore_snapshot(SNAP_HELP_IDX, close_curwin);
+ curwin->w_pos_changed = true;
redraw_all_later(NOT_VALID);
return OK;
}
@@ -3108,6 +3118,10 @@ int win_new_tabpage(int after, char_u *filename)
redraw_all_later(NOT_VALID);
+ if (ui_is_external(kUIMultigrid)) {
+ tabpage_check_windows(tp);
+ }
+
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
@@ -3299,11 +3313,16 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au
int old_off = tp->tp_firstwin->w_winrow;
win_T *next_prevwin = tp->tp_prevwin;
+ tabpage_T *old_curtab = curtab;
curtab = tp;
firstwin = tp->tp_firstwin;
lastwin = tp->tp_lastwin;
topframe = tp->tp_topframe;
+ if (old_curtab != curtab && ui_is_external(kUIMultigrid)) {
+ tabpage_check_windows(old_curtab);
+ }
+
/* We would like doing the TabEnter event first, but we don't have a
* valid current window yet, which may break some commands.
* This triggers autocommands, thus may make "tp" invalid. */
@@ -3336,7 +3355,20 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au
}
redraw_all_later(NOT_VALID);
- must_redraw = NOT_VALID;
+}
+
+/// called when changing current tabpage from old_curtab to curtab
+static void tabpage_check_windows(tabpage_T *old_curtab)
+{
+ win_T *next_wp;
+ for (win_T *wp = old_curtab->tp_firstwin; wp; wp = next_wp) {
+ next_wp = wp->w_next;
+ wp->w_pos_changed = true;
+ }
+
+ for (win_T *wp = firstwin; wp; wp = wp->w_next) {
+ wp->w_pos_changed = true;
+ }
}
/*
@@ -3860,6 +3892,8 @@ static win_T *win_alloc(win_T *after, int hidden)
new_wp->handle = ++last_win_id;
handle_register_window(new_wp);
+ grid_assign_handle(&new_wp->w_grid);
+
// Init w: variables.
new_wp->w_vars = tv_dict_alloc();
init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
@@ -3958,6 +3992,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 +4006,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;
+ }
+ grid_free(&wp->w_grid);
+ if (reinit) {
+ // if a float is turned into a split and back into a float, the grid
+ // data structure will be reused
+ memset(&wp->w_grid, 0, sizeof(wp->w_grid));
+ }
+}
+
/*
* Append window "wp" in the window list after window "after".
*/
@@ -4071,8 +4121,8 @@ static void frame_remove(frame_T *frp)
void win_alloc_lines(win_T *wp)
{
wp->w_lines_valid = 0;
- assert(Rows >= 0);
- wp->w_lines = xcalloc(Rows, sizeof(wline_T));
+ assert(wp->w_grid.Rows >= 0);
+ wp->w_lines = xcalloc(MAX(wp->w_grid.Rows + 1, Rows), sizeof(wline_T));
}
/*
@@ -4202,7 +4252,8 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col)
wp->w_winrow = *row;
wp->w_wincol = *col;
redraw_win_later(wp, NOT_VALID);
- wp->w_redr_status = TRUE;
+ wp->w_redr_status = true;
+ wp->w_pos_changed = true;
}
*row += wp->w_height + wp->w_status_height;
*col += wp->w_width + wp->w_vsep_width;
@@ -4255,8 +4306,9 @@ void win_setheight_win(int height, win_T *win)
* If there is extra space created between the last window and the command
* line, clear it.
*/
- if (full_screen && msg_scrolled == 0 && row < cmdline_row)
- screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
+ if (full_screen && msg_scrolled == 0 && row < cmdline_row) {
+ grid_fill(&default_grid, row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
+ }
cmdline_row = row;
msg_row = row;
msg_col = 0;
@@ -4339,11 +4391,11 @@ static void frame_setheight(frame_T *curfrp, int height)
room_cmdline = 0;
}
- if (height <= room + room_cmdline)
+ if (height <= room + room_cmdline) {
break;
+ }
if (run == 2 || curfrp->fr_width == Columns) {
- if (height > room + room_cmdline)
- height = room + room_cmdline;
+ height = room + room_cmdline;
break;
}
frame_setheight(curfrp->fr_parent, height
@@ -4706,7 +4758,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)
@@ -4866,6 +4918,8 @@ void win_new_height(win_T *wp, int height)
if (!exiting) {
scroll_to_fraction(wp, prev_height);
}
+
+ wp->w_pos_changed = true;
}
void scroll_to_fraction(win_T *wp, int prev_height)
@@ -4996,6 +5050,7 @@ void win_new_width(win_T *wp, int width)
0);
}
}
+ wp->w_pos_changed = true;
}
void win_comp_scroll(win_T *wp)
@@ -5052,10 +5107,11 @@ void command_height(void)
/* Recompute window positions. */
(void)win_comp_pos();
- /* clear the lines added to cmdline */
- if (full_screen)
- screen_fill(cmdline_row, (int)Rows, 0,
- (int)Columns, ' ', ' ', 0);
+ // clear the lines added to cmdline
+ if (full_screen) {
+ grid_fill(&default_grid, cmdline_row, (int)Rows, 0, (int)Columns, ' ',
+ ' ', 0);
+ }
msg_row = cmdline_row;
redraw_cmdline = TRUE;
return;
@@ -6031,3 +6087,23 @@ void win_findbuf(typval_T *argvars, list_T *list)
}
}
}
+
+void win_ui_flush(void)
+{
+ if (!ui_is_external(kUIMultigrid)) {
+ return;
+ }
+
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ if (wp->w_pos_changed && wp->w_grid.chars != NULL) {
+ if (tp == curtab) {
+ ui_call_win_pos(wp->w_grid.handle, wp->handle, wp->w_winrow,
+ wp->w_wincol, wp->w_width, wp->w_height);
+ } else {
+ ui_call_win_hide(wp->w_grid.handle);
+ }
+ wp->w_pos_changed = false;
+ }
+ }
+
+}