mirror of
https://github.com/neovim/neovim.git
synced 2025-10-26 12:27:24 +00:00
Merge pull request #8455 from UtkarshMe/grid-split
implement ext_multigrid: draw each window on a separate resizable grid.
This commit is contained in:
@@ -116,9 +116,9 @@ set(NVIM_VERSION_PATCH 0)
|
||||
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
|
||||
|
||||
# API level
|
||||
set(NVIM_API_LEVEL 5) # Bump this after any API change.
|
||||
set(NVIM_API_LEVEL 6) # Bump this after any API change.
|
||||
set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
|
||||
set(NVIM_API_PRERELEASE false)
|
||||
set(NVIM_API_PRERELEASE true)
|
||||
|
||||
file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR)
|
||||
include(GetGitRevisionDescription)
|
||||
|
||||
@@ -12,9 +12,10 @@ Nvim UI protocol *ui*
|
||||
UI Events *ui-events*
|
||||
|
||||
GUIs can be implemented as external processes communicating with Nvim over the
|
||||
RPC API. The UI model consists of a terminal-like grid with a single,
|
||||
monospace font size. Some elements (UI "widgets") can be drawn separately from
|
||||
the grid ("externalized").
|
||||
RPC API. The default UI model consists of a terminal-like grid with a single,
|
||||
monospace font size. The UI can opt-in to have windows drawn on separate
|
||||
grids, as well as to have some elements (UI "widgets") be drawn by the UI
|
||||
itself rather than by nvim ("externalized").
|
||||
|
||||
|
||||
*ui-options*
|
||||
@@ -32,6 +33,7 @@ a dictionary with these (optional) keys:
|
||||
`ext_cmdline` Externalize the cmdline. |ui-cmdline|
|
||||
`ext_wildmenu` Externalize the wildmenu. |ui-wildmenu|
|
||||
`ext_linegrid` Use new revision of the grid events. |ui-linegrid|
|
||||
`ext_multigrid` Use per-window grid based events. |ui-multigrid|
|
||||
`ext_hlstate` Use detailed highlight state. |ui-hlstate|
|
||||
|
||||
Specifying a non-existent option is an error. UIs can check the |api-metadata|
|
||||
@@ -46,7 +48,7 @@ Each update event is itself an array whose first element is the event name and
|
||||
remaining elements are event-parameter tuples. This allows multiple events of
|
||||
the same kind to be sent in a row without the event name being repeated. This
|
||||
batching is mostly used for "grid_line", because each "grid_line" event puts
|
||||
contents in one screen line, but clients must be prepared for multiple argument
|
||||
contents in one grid line, but clients must be prepared for multiple argument
|
||||
sets being batched for all event kinds.
|
||||
|
||||
Events must be handled in-order. A "flush" event is sent when nvim is done
|
||||
@@ -61,10 +63,12 @@ By default, Nvim sends |ui-global| and |ui-grid-old| events; these suffice to
|
||||
implement a terminal-like interface. However there are two revisions of the
|
||||
grid part of the protocol. The newer revision |ui-linegrid|, enabled by
|
||||
`ext_linegrid` option, has a more effecient representation of text (especially
|
||||
highlighted text), and room for futher enhancements that will use
|
||||
multiple grids. The older revision is available and used by default only for
|
||||
backwards compatibility reasons. New UIs are strongly recommended to use
|
||||
|ui-linegrid|, as further protocol extensions will require it.
|
||||
highlighted text), and allows extensions that use multiple grids.
|
||||
|
||||
The older revision is available and used by default only for backwards
|
||||
compatibility reasons. New UIs are strongly recommended to use |ui-linegrid|,
|
||||
as further protocol extensions require it. The |ui-multigrid| extension
|
||||
enables |ui-linegrid| implicitly.
|
||||
|
||||
Nvim optionally sends screen elements "semantically" as structured events
|
||||
instead of raw grid-lines, controlled by |ui-ext-options|. The UI must present
|
||||
@@ -220,7 +224,8 @@ Most of these events take a `grid` index as first parameter. Grid 1 is the
|
||||
global grid used by default for the entire editor screen state. Grids other
|
||||
than that will be defined by future extensions. Just activating the
|
||||
`ext_linegrid` option by itself will never cause any additional grids to be
|
||||
created.
|
||||
created. To enable per-window grids, `ext_multigrid` option should be set (see
|
||||
|ui-multigrid|).
|
||||
|
||||
Highlight attribute groups are predefined. UIs should maintain a table to map
|
||||
numerical highlight `id`:s to the actual attributes.
|
||||
@@ -475,19 +480,66 @@ because 'winhighlight' was used. UI items will be transmitted, even if the
|
||||
highlight group is cleared, so `ui_name` can always be used to reliably identify
|
||||
screen elements, even if no attributes have been applied.
|
||||
|
||||
==============================================================================
|
||||
Multigrid Events *ui-multigrid*
|
||||
|
||||
Only sent if `ext_multigrid` option is set in |ui-options|. Enables the
|
||||
`ext_linegrid` extension implicitly.
|
||||
|
||||
The multigrid extension gives the UIs more control over how windows are
|
||||
displayed. The UIs receive updates on a separate grid for each window. The UIs
|
||||
can set the grid size independently of how much space the window occupies on
|
||||
the global layout. This enables the UIs to set a different font size for each
|
||||
window if the UI so desires. The UI can also reserve space around the border
|
||||
of the window for its own elements, for instance scrollbars from the UI
|
||||
toolkit.
|
||||
|
||||
By default, the grid size is handled by nvim and set to the outer grid size
|
||||
(i.e. the size of the window frame in nvim) whenever the split is created.
|
||||
Once a UI sets a grid size, nvim does not handle the size for that grid and
|
||||
the UI must change the grid size whenever the outer size is changed. To
|
||||
delegate the handling of grid size back to nvim, the UIs should request the
|
||||
size (0, 0).
|
||||
|
||||
A window can be hidden and redisplayed without its grid being deallocated.
|
||||
This can happen multiple times for the same window, for instance when switching
|
||||
tabs.
|
||||
|
||||
["win_pos", grid, win, start_row, start_col, width, height]
|
||||
Set the position and size of the grid in nvim (i.e. the outer grid
|
||||
size). If the window was previously hidden, it should now be shown
|
||||
again.
|
||||
|
||||
["win_hide", grid]
|
||||
Stop displaying the window.
|
||||
|
||||
["win_scroll_over_start"]
|
||||
Hint that following `grid_scroll` on the default grid should
|
||||
scroll over windows. This is a temporary workaround to allow
|
||||
UIs to use the builtin message drawing. Later on, messages will be
|
||||
drawn on a dedicated grid.
|
||||
|
||||
["win_scroll_over_reset"]
|
||||
Hint that scrolled over windows should be redrawn again, and not be
|
||||
overdrawn by default grid scrolling anymore.
|
||||
|
||||
See |ui-linegrid| for grid events.
|
||||
See |nvim_ui_try_resize_grid| in |api-ui| to request changing the grid size.
|
||||
|
||||
==============================================================================
|
||||
Popupmenu Events *ui-popupmenu*
|
||||
|
||||
Only sent if `ext_popupmenu` option is set in |ui-options|
|
||||
|
||||
["popupmenu_show", items, selected, row, col]
|
||||
["popupmenu_show", items, selected, row, col, grid]
|
||||
Show |popupmenu-completion|. `items` is an array of completion items
|
||||
to show; each item is an array of the form [word, kind, menu, info] as
|
||||
defined at |complete-items|, except that `word` is replaced by `abbr`
|
||||
if present. `selected` is the initially-selected item, a zero-based
|
||||
index into the array of items (-1 if no item is selected). `row` and
|
||||
`col` give the anchor position, where the first character of the
|
||||
completed word will be.
|
||||
completed word will be. When |ui-multigrid| is used, `grid` is the
|
||||
grid for the anchor position.
|
||||
|
||||
["popupmenu_select", selected]
|
||||
Select an item in the current popupmenu. `selected` is a zero-based
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1920,13 +1920,13 @@ Object nvim_get_proc(Integer pid, Error *err)
|
||||
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()) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -120,11 +120,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)
|
||||
@@ -223,9 +223,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 +437,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();
|
||||
|
||||
/*
|
||||
|
||||
@@ -560,7 +560,7 @@ static int insert_check(VimState *state)
|
||||
|
||||
if (curwin->w_wcol < s->mincol - curbuf->b_p_ts
|
||||
&& curwin->w_wrow == curwin->w_winrow
|
||||
+ curwin->w_height - 1 - p_so
|
||||
+ curwin->w_grid.Rows - 1 - p_so
|
||||
&& (curwin->w_cursor.lnum != curwin->w_topline
|
||||
|| curwin->w_topfill > 0)) {
|
||||
if (curwin->w_topfill > 0) {
|
||||
@@ -1494,40 +1494,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1543,7 +1544,8 @@ void edit_unputchar(void)
|
||||
if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) {
|
||||
redrawWinline(curwin, curwin->w_cursor.lnum, false);
|
||||
} else {
|
||||
screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
|
||||
grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col,
|
||||
pc_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1566,8 +1568,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;
|
||||
@@ -5825,7 +5827,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 +5842,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 +5858,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;
|
||||
}
|
||||
|
||||
@@ -14023,11 +14023,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 +14042,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;
|
||||
}
|
||||
@@ -16774,10 +16774,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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -9194,10 +9194,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 +9459,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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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'
|
||||
@@ -128,45 +129,6 @@ typedef off_t off_T;
|
||||
# endif
|
||||
#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
|
||||
|
||||
59
src/nvim/grid_defs.h
Normal file
59
src/nvim/grid_defs.h
Normal file
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -463,8 +463,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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = ' ';
|
||||
}
|
||||
|
||||
236
src/nvim/move.c
236
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;
|
||||
}
|
||||
@@ -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();
|
||||
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_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)
|
||||
// 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();
|
||||
|
||||
@@ -3466,10 +3466,10 @@ static void display_showcmd(void)
|
||||
int len;
|
||||
|
||||
len = (int)STRLEN(showcmd_buf);
|
||||
if (len == 0)
|
||||
if (len == 0) {
|
||||
showcmd_is_clear = true;
|
||||
else {
|
||||
screen_puts(showcmd_buf, (int)Rows - 1, sc_col, 0);
|
||||
} else {
|
||||
grid_puts(&default_grid, showcmd_buf, (int)Rows - 1, sc_col, 0);
|
||||
showcmd_is_clear = false;
|
||||
}
|
||||
|
||||
@@ -3477,7 +3477,8 @@ static void display_showcmd(void)
|
||||
* clear the rest of an old message by outputting up to SHOWCMD_COLS
|
||||
* spaces
|
||||
*/
|
||||
screen_puts((char_u *)" " + len, (int)Rows - 1, sc_col + len, 0);
|
||||
grid_puts(&default_grid, (char_u *)" " + len, (int)Rows - 1,
|
||||
sc_col + len, 0);
|
||||
|
||||
setcursor(); /* put cursor back where it belongs */
|
||||
}
|
||||
@@ -3905,18 +3906,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();
|
||||
@@ -4255,7 +4254,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 +4269,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 +4306,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 +5016,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 +5032,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. */
|
||||
@@ -6747,9 +6748,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 +6762,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 +6810,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 +6840,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 +7955,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,13 +90,20 @@ 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (array_changed) {
|
||||
Array arr = ARRAY_DICT_INIT;
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
1452
src/nvim/screen.c
1452
src/nvim/screen.c
File diff suppressed because it is too large
Load Diff
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -57,6 +57,7 @@ static int busy = 0;
|
||||
static int mode_idx = SHAPE_IDX_N;
|
||||
static bool pending_mode_info_update = false;
|
||||
static bool pending_mode_update = false;
|
||||
static handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE;
|
||||
|
||||
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
|
||||
# define UI_LOG(funname, ...)
|
||||
@@ -196,13 +197,6 @@ void ui_refresh(void)
|
||||
row = 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,12 +317,18 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
|
||||
}
|
||||
}
|
||||
|
||||
void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr,
|
||||
bool wrap)
|
||||
void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
|
||||
int clearattr, bool wrap)
|
||||
{
|
||||
size_t off = LineOffset[row]+(size_t)startcol;
|
||||
UI_CALL(raw_line, 1, row, startcol, endcol, clearcol, clearattr, wrap,
|
||||
(const schar_T *)ScreenLines+off, (const sattr_T *)ScreenAttrs+off);
|
||||
size_t off = grid->line_offset[row] + (size_t)startcol;
|
||||
int row_off = ui_is_external(kUIMultigrid) ? 0 : grid->row_offset;
|
||||
int col_off = ui_is_external(kUIMultigrid) ? 0 : grid->col_offset;
|
||||
|
||||
UI_CALL(raw_line, grid->handle, row_off + row, col_off + startcol,
|
||||
col_off + endcol, col_off + 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
|
||||
@@ -334,11 +342,23 @@ void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr,
|
||||
|
||||
void ui_cursor_goto(int new_row, int new_col)
|
||||
{
|
||||
if (new_row == row && new_col == col) {
|
||||
ui_grid_cursor_goto(&default_grid, new_row, new_col);
|
||||
}
|
||||
|
||||
void ui_grid_cursor_goto(ScreenGrid *grid, int new_row, int new_col)
|
||||
{
|
||||
new_row += ui_is_external(kUIMultigrid) ? 0 : grid->row_offset;
|
||||
new_col += ui_is_external(kUIMultigrid) ? 0 : grid->col_offset;
|
||||
int handle = ui_is_external(kUIMultigrid) ? grid->handle
|
||||
: DEFAULT_GRID_HANDLE;
|
||||
|
||||
if (new_row == row && new_col == col && handle == cursor_grid_handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
row = new_row;
|
||||
col = new_col;
|
||||
cursor_grid_handle = handle;
|
||||
pending_cursor_update = true;
|
||||
}
|
||||
|
||||
@@ -360,8 +380,9 @@ int ui_current_col(void)
|
||||
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, row, col);
|
||||
pending_cursor_update = false;
|
||||
}
|
||||
if (pending_mode_info_update) {
|
||||
@@ -421,3 +442,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);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
@@ -3339,6 +3358,20 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_au
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to tab page "n". For ":tab N" and "Ngt".
|
||||
* When "n" is 9999 go to the last tab page.
|
||||
@@ -3860,6 +3893,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 +3993,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 +4007,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 +4122,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 +4253,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 +4307,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;
|
||||
@@ -4706,7 +4759,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 +4919,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 +5051,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 +5108,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 +6088,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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1261,6 +1261,7 @@ describe('API', function()
|
||||
ext_tabline = false,
|
||||
ext_wildmenu = false,
|
||||
ext_linegrid = screen._options.ext_linegrid or false,
|
||||
ext_multigrid = false,
|
||||
ext_hlstate=false,
|
||||
height = 4,
|
||||
rgb = true,
|
||||
|
||||
@@ -84,6 +84,10 @@ end
|
||||
|
||||
local session, loop_running, last_error
|
||||
|
||||
local function get_session()
|
||||
return session
|
||||
end
|
||||
|
||||
local function set_session(s, keep)
|
||||
if session and not keep then
|
||||
session:close()
|
||||
@@ -164,34 +168,34 @@ local function expect_msg_seq(...)
|
||||
error(final_error)
|
||||
end
|
||||
|
||||
local function call_and_stop_on_error(...)
|
||||
local function call_and_stop_on_error(lsession, ...)
|
||||
local status, result = copcall(...) -- luacheck: ignore
|
||||
if not status then
|
||||
session:stop()
|
||||
lsession:stop()
|
||||
last_error = result
|
||||
return ''
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function run(request_cb, notification_cb, setup_cb, timeout)
|
||||
local function run_session(lsession, request_cb, notification_cb, setup_cb, timeout)
|
||||
local on_request, on_notification, on_setup
|
||||
|
||||
if request_cb then
|
||||
function on_request(method, args)
|
||||
return call_and_stop_on_error(request_cb, method, args)
|
||||
return call_and_stop_on_error(lsession, request_cb, method, args)
|
||||
end
|
||||
end
|
||||
|
||||
if notification_cb then
|
||||
function on_notification(method, args)
|
||||
call_and_stop_on_error(notification_cb, method, args)
|
||||
call_and_stop_on_error(lsession, notification_cb, method, args)
|
||||
end
|
||||
end
|
||||
|
||||
if setup_cb then
|
||||
function on_setup()
|
||||
call_and_stop_on_error(setup_cb)
|
||||
call_and_stop_on_error(lsession, setup_cb)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -205,6 +209,10 @@ local function run(request_cb, notification_cb, setup_cb, timeout)
|
||||
end
|
||||
end
|
||||
|
||||
local function run(request_cb, notification_cb, setup_cb, timeout)
|
||||
run_session(session, request_cb, notification_cb, setup_cb, timeout)
|
||||
end
|
||||
|
||||
local function stop()
|
||||
session:stop()
|
||||
end
|
||||
@@ -677,6 +685,7 @@ local module = {
|
||||
buffer = buffer,
|
||||
bufmeths = bufmeths,
|
||||
call = nvim_call,
|
||||
create_callindex = create_callindex,
|
||||
clear = clear,
|
||||
command = nvim_command,
|
||||
connect = connect,
|
||||
@@ -701,6 +710,7 @@ local module = {
|
||||
filter = filter,
|
||||
funcs = funcs,
|
||||
get_pathsep = get_pathsep,
|
||||
get_session = get_session,
|
||||
insert = insert,
|
||||
iswin = iswin,
|
||||
map = map,
|
||||
@@ -732,6 +742,7 @@ local module = {
|
||||
retry = retry,
|
||||
rmdir = rmdir,
|
||||
run = run,
|
||||
run_session = run_session,
|
||||
set_session = set_session,
|
||||
set_shell_powershell = set_shell_powershell,
|
||||
skip_fragile = skip_fragile,
|
||||
|
||||
@@ -72,10 +72,10 @@ local function screen_setup(extra_rows, command, cols)
|
||||
if command == default_command then
|
||||
-- Wait for "tty ready" to be printed before each test or the terminal may
|
||||
-- still be in canonical mode (will echo characters for example).
|
||||
local empty_line = (' '):rep(cols + 1)
|
||||
local empty_line = (' '):rep(cols)
|
||||
local expected = {
|
||||
'tty ready'..(' '):rep(cols - 8),
|
||||
'{1: }' ..(' '):rep(cols),
|
||||
'tty ready'..(' '):rep(cols - 9),
|
||||
'{1: }' ..(' '):rep(cols - 1),
|
||||
empty_line,
|
||||
empty_line,
|
||||
empty_line,
|
||||
@@ -85,8 +85,8 @@ local function screen_setup(extra_rows, command, cols)
|
||||
table.insert(expected, empty_line)
|
||||
end
|
||||
|
||||
table.insert(expected, '{3:-- TERMINAL --}' .. ((' '):rep(cols - 13)))
|
||||
screen:expect(table.concat(expected, '\n'))
|
||||
table.insert(expected, '{3:-- TERMINAL --}' .. ((' '):rep(cols - 14)))
|
||||
screen:expect(table.concat(expected, '|\n')..'|')
|
||||
else
|
||||
-- This eval also acts as a wait().
|
||||
if 0 == nvim('eval', "exists('b:terminal_job_id')") then
|
||||
|
||||
@@ -259,10 +259,10 @@ describe('tui', function()
|
||||
feed_data(':echo map(nvim_list_uis(), {k,v -> sort(items(v))})\013')
|
||||
screen:expect([=[
|
||||
[[['ext_cmdline', v:false], ['ext_hlstate', v:fals|
|
||||
e], ['ext_linegrid', v:true], ['ext_popupmenu', v:|
|
||||
false], ['ext_tabline', v:false], ['ext_wildmenu',|
|
||||
v:false], ['height', 6], ['rgb', v:false], ['widt|
|
||||
h', 50]]] |
|
||||
e], ['ext_linegrid', v:true], ['ext_multigrid', v:|
|
||||
false], ['ext_popupmenu', v:false], ['ext_tabline'|
|
||||
, v:false], ['ext_wildmenu', v:false], ['height', |
|
||||
6], ['rgb', v:false], ['width', 50]]] |
|
||||
{10:Press ENTER or type command to continue}{1: } |
|
||||
{3:-- TERMINAL --} |
|
||||
]=])
|
||||
@@ -401,7 +401,7 @@ describe('tui FocusGained/FocusLost', function()
|
||||
-- Exit cmdline-mode. Redraws from timers/events are blocked during
|
||||
-- cmdline-mode, so the buffer won't be updated until we exit cmdline-mode.
|
||||
feed_data('\n')
|
||||
screen:expect{any='lost'..(' '):rep(46)..'\ngained'}
|
||||
screen:expect{any='lost'..(' '):rep(46)..'|\ngained'}
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
1524
test/functional/ui/multigrid_spec.lua
Normal file
1524
test/functional/ui/multigrid_spec.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@ describe('ui receives option updates', function()
|
||||
ext_wildmenu=false,
|
||||
ext_linegrid=false,
|
||||
ext_hlstate=false,
|
||||
ext_multigrid=false,
|
||||
}
|
||||
|
||||
clear(...)
|
||||
|
||||
@@ -75,9 +75,11 @@ local global_helpers = require('test.helpers')
|
||||
local deepcopy = global_helpers.deepcopy
|
||||
local shallowcopy = global_helpers.shallowcopy
|
||||
local helpers = require('test.functional.helpers')(nil)
|
||||
local request, run, uimeths = helpers.request, helpers.run, helpers.uimeths
|
||||
local request, run_session = helpers.request, helpers.run_session
|
||||
local eq = helpers.eq
|
||||
local dedent = helpers.dedent
|
||||
local get_session = helpers.get_session
|
||||
local create_callindex = helpers.create_callindex
|
||||
|
||||
local inspect = require('inspect')
|
||||
|
||||
@@ -155,6 +157,8 @@ function Screen.new(width, height)
|
||||
cmdline_block = {},
|
||||
wildmenu_items = nil,
|
||||
wildmenu_selected = nil,
|
||||
win_position = {},
|
||||
_session = nil,
|
||||
_default_attr_ids = nil,
|
||||
_default_attr_ignore = nil,
|
||||
_mouse_enabled = true,
|
||||
@@ -165,11 +169,19 @@ function Screen.new(width, height)
|
||||
_new_attrs = false,
|
||||
_width = width,
|
||||
_height = height,
|
||||
_grids = {},
|
||||
_cursor = {
|
||||
row = 1, col = 1
|
||||
grid = 1, row = 1, col = 1
|
||||
},
|
||||
_busy = false
|
||||
_busy = false,
|
||||
}, Screen)
|
||||
local function ui(method, ...)
|
||||
local status, rv = self._session:request('nvim_ui_'..method, ...)
|
||||
if not status then
|
||||
error(rv[2])
|
||||
end
|
||||
end
|
||||
self.uimeths = create_callindex(ui)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -189,34 +201,50 @@ function Screen:set_hlstate_cterm(val)
|
||||
self._hlstate_cterm = val
|
||||
end
|
||||
|
||||
function Screen:attach(options)
|
||||
function Screen:attach(options, session)
|
||||
if session == nil then
|
||||
session = get_session()
|
||||
end
|
||||
if options == nil then
|
||||
options = {}
|
||||
end
|
||||
if options.ext_linegrid == nil then
|
||||
options.ext_linegrid = true
|
||||
end
|
||||
|
||||
self._session = session
|
||||
self._options = options
|
||||
self._clear_attrs = (options.ext_linegrid and {{},{}}) or {}
|
||||
self:_handle_resize(self._width, self._height)
|
||||
uimeths.attach(self._width, self._height, options)
|
||||
self.uimeths.attach(self._width, self._height, options)
|
||||
if self._options.rgb == nil then
|
||||
-- nvim defaults to rgb=true internally,
|
||||
-- simplify test code by doing the same.
|
||||
self._options.rgb = true
|
||||
end
|
||||
if self._options.ext_multigrid then
|
||||
self._options.ext_linegrid = true
|
||||
end
|
||||
self._session = session
|
||||
end
|
||||
|
||||
function Screen:detach()
|
||||
uimeths.detach()
|
||||
self.uimeths.detach()
|
||||
self._session = nil
|
||||
end
|
||||
|
||||
function Screen:try_resize(columns, rows)
|
||||
uimeths.try_resize(columns, rows)
|
||||
self._width = columns
|
||||
self._height = rows
|
||||
self.uimeths.try_resize(columns, rows)
|
||||
end
|
||||
|
||||
function Screen:try_resize_grid(grid, columns, rows)
|
||||
self.uimeths.try_resize_grid(grid, columns, rows)
|
||||
end
|
||||
|
||||
function Screen:set_option(option, value)
|
||||
uimeths.set_option(option, value)
|
||||
self.uimeths.set_option(option, value)
|
||||
self._options[option] = value
|
||||
end
|
||||
|
||||
@@ -321,7 +349,6 @@ function Screen:expect(expected, attr_ids, attr_ignore)
|
||||
-- value.
|
||||
grid = dedent(grid:gsub('\n[ ]+$', ''), 0)
|
||||
for row in grid:gmatch('[^\n]+') do
|
||||
row = row:sub(1, #row - 1) -- Last char must be the screen delimiter.
|
||||
table.insert(expected_rows, row)
|
||||
end
|
||||
end
|
||||
@@ -341,19 +368,11 @@ function Screen:expect(expected, attr_ids, attr_ignore)
|
||||
end
|
||||
end
|
||||
|
||||
if grid ~= nil and self._height ~= #expected_rows then
|
||||
return ("Expected screen state's row count(" .. #expected_rows
|
||||
.. ') differs from configured height(' .. self._height .. ') of Screen.')
|
||||
end
|
||||
|
||||
if self._options.ext_hlstate and self._new_attrs then
|
||||
attr_state.id_to_index = self:hlstate_check_attrs(attr_state.ids or {})
|
||||
end
|
||||
|
||||
local actual_rows = {}
|
||||
for i = 1, self._height do
|
||||
actual_rows[i] = self:_row_repr(self._rows[i], attr_state)
|
||||
end
|
||||
local actual_rows = self:render(not expected.any, attr_state)
|
||||
|
||||
if expected.any ~= nil then
|
||||
-- Search for `any` anywhere in the screen lines.
|
||||
@@ -362,13 +381,17 @@ function Screen:expect(expected, attr_ids, attr_ignore)
|
||||
return (
|
||||
'Failed to match any screen lines.\n'
|
||||
.. 'Expected (anywhere): "' .. expected.any .. '"\n'
|
||||
.. 'Actual:\n |' .. table.concat(actual_rows, '|\n |') .. '|\n\n')
|
||||
.. 'Actual:\n |' .. table.concat(actual_rows, '\n |') .. '\n\n')
|
||||
end
|
||||
end
|
||||
|
||||
if grid ~= nil then
|
||||
-- `expected` must match the screen lines exactly.
|
||||
for i = 1, self._height do
|
||||
if #actual_rows ~= #expected_rows then
|
||||
return "Expected screen state's row count(" .. #expected_rows
|
||||
.. ') differs from configured height(' .. #actual_rows .. ') of Screen.'
|
||||
end
|
||||
for i = 1, #actual_rows do
|
||||
if expected_rows[i] ~= actual_rows[i] then
|
||||
local msg_expected_rows = {}
|
||||
for j = 1, #expected_rows do
|
||||
@@ -378,8 +401,8 @@ function Screen:expect(expected, attr_ids, attr_ignore)
|
||||
actual_rows[i] = '*' .. actual_rows[i]
|
||||
return (
|
||||
'Row ' .. tostring(i) .. ' did not match.\n'
|
||||
..'Expected:\n |'..table.concat(msg_expected_rows, '|\n |')..'|\n'
|
||||
..'Actual:\n |'..table.concat(actual_rows, '|\n |')..'|\n\n'..[[
|
||||
..'Expected:\n |'..table.concat(msg_expected_rows, '\n |')..'\n'
|
||||
..'Actual:\n |'..table.concat(actual_rows, '\n |')..'\n\n'..[[
|
||||
To print the expect() call that would assert the current screen state, use
|
||||
screen:snapshot_util(). In case of non-deterministic failures, use
|
||||
screen:redraw_debug() to show all intermediate screen states. ]])
|
||||
@@ -465,7 +488,7 @@ function Screen:_wait(check, flags)
|
||||
if not err then
|
||||
success_seen = true
|
||||
if did_miminal_timeout then
|
||||
helpers.stop()
|
||||
self._session:stop()
|
||||
end
|
||||
elseif success_seen and #args > 0 then
|
||||
failure_after_success = true
|
||||
@@ -474,7 +497,7 @@ function Screen:_wait(check, flags)
|
||||
|
||||
return true
|
||||
end
|
||||
run(nil, notification_cb, nil, minimal_timeout)
|
||||
run_session(self._session, nil, notification_cb, nil, minimal_timeout)
|
||||
if not did_flush then
|
||||
err = "no flush received"
|
||||
elseif not checked then
|
||||
@@ -487,7 +510,7 @@ function Screen:_wait(check, flags)
|
||||
|
||||
if not success_seen then
|
||||
did_miminal_timeout = true
|
||||
run(nil, notification_cb, nil, timeout-minimal_timeout)
|
||||
run_session(self._session, nil, notification_cb, nil, timeout-minimal_timeout)
|
||||
end
|
||||
|
||||
local did_warn = false
|
||||
@@ -547,7 +570,7 @@ function Screen:sleep(ms)
|
||||
assert(method == 'redraw')
|
||||
self:_redraw(args)
|
||||
end
|
||||
run(nil, notification_cb, nil, ms)
|
||||
run_session(self._session, nil, notification_cb, nil, ms)
|
||||
end
|
||||
|
||||
function Screen:_redraw(updates)
|
||||
@@ -579,6 +602,22 @@ function Screen:set_on_event_handler(callback)
|
||||
end
|
||||
|
||||
function Screen:_handle_resize(width, height)
|
||||
self:_handle_grid_resize(1, width, height)
|
||||
self._scroll_region = {
|
||||
top = 1, bot = height, left = 1, right = width
|
||||
}
|
||||
self._grid = self._grids[1]
|
||||
end
|
||||
|
||||
local function min(x,y)
|
||||
if x < y then
|
||||
return x
|
||||
else
|
||||
return y
|
||||
end
|
||||
end
|
||||
|
||||
function Screen:_handle_grid_resize(grid, width, height)
|
||||
local rows = {}
|
||||
for _ = 1, height do
|
||||
local cols = {}
|
||||
@@ -587,22 +626,36 @@ function Screen:_handle_resize(width, height)
|
||||
end
|
||||
table.insert(rows, cols)
|
||||
end
|
||||
self._cursor.row = 1
|
||||
self._cursor.col = 1
|
||||
self._rows = rows
|
||||
self._width = width
|
||||
self._height = height
|
||||
self._scroll_region = {
|
||||
top = 1, bot = height, left = 1, right = width
|
||||
if grid > 1 and self._grids[grid] ~= nil then
|
||||
local old = self._grids[grid]
|
||||
for i = 1, min(height,old.height) do
|
||||
for j = 1, min(width,old.width) do
|
||||
rows[i][j] = old.rows[i][j]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self._cursor.grid == grid then
|
||||
self._cursor.row = 1
|
||||
self._cursor.col = 1
|
||||
end
|
||||
self._grids[grid] = {
|
||||
rows=rows,
|
||||
width=width,
|
||||
height=height,
|
||||
}
|
||||
end
|
||||
|
||||
function Screen:_handle_flush()
|
||||
function Screen:_handle_win_scroll_over_start()
|
||||
self.scroll_over = true
|
||||
self.scroll_over_pos = self._grids[1].height
|
||||
end
|
||||
|
||||
function Screen:_handle_grid_resize(grid, width, height)
|
||||
assert(grid == 1)
|
||||
self:_handle_resize(width, height)
|
||||
function Screen:_handle_win_scroll_over_reset()
|
||||
self.scroll_over = false
|
||||
end
|
||||
|
||||
function Screen:_handle_flush()
|
||||
end
|
||||
|
||||
function Screen:_reset()
|
||||
@@ -641,20 +694,27 @@ function Screen:_handle_clear()
|
||||
-- newer clients, to check we remain compatible with both kind of clients,
|
||||
-- ensure the scroll region is in a reset state.
|
||||
local expected_region = {
|
||||
top = 1, bot = self._height, left = 1, right = self._width
|
||||
top = 1, bot = self._grid.height, left = 1, right = self._grid.width
|
||||
}
|
||||
eq(expected_region, self._scroll_region)
|
||||
self:_clear_block(1, self._height, 1, self._width)
|
||||
self:_handle_grid_clear(1)
|
||||
end
|
||||
|
||||
function Screen:_handle_grid_clear(grid)
|
||||
assert(grid == 1)
|
||||
self:_clear_block(1, self._height, 1, self._width)
|
||||
self:_clear_block(self._grids[grid], 1, self._grids[grid].height, 1, self._grids[grid].width)
|
||||
end
|
||||
|
||||
function Screen:_handle_grid_destroy(grid)
|
||||
self._grids[grid] = nil
|
||||
if self._options.ext_multigrid then
|
||||
assert(self.win_position[grid])
|
||||
self.win_position[grid] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function Screen:_handle_eol_clear()
|
||||
local row, col = self._cursor.row, self._cursor.col
|
||||
self:_clear_block(row, row, col, self._scroll_region.right)
|
||||
self:_clear_block(self._grid, row, row, col, self._grid.width)
|
||||
end
|
||||
|
||||
function Screen:_handle_cursor_goto(row, col)
|
||||
@@ -663,7 +723,7 @@ function Screen:_handle_cursor_goto(row, col)
|
||||
end
|
||||
|
||||
function Screen:_handle_grid_cursor_goto(grid, row, col)
|
||||
assert(grid == 1)
|
||||
self._cursor.grid = grid
|
||||
self._cursor.row = row + 1
|
||||
self._cursor.col = col + 1
|
||||
end
|
||||
@@ -704,13 +764,18 @@ function Screen:_handle_scroll(count)
|
||||
self:_handle_grid_scroll(1, top-1, bot, left-1, right, count, 0)
|
||||
end
|
||||
|
||||
function Screen:_handle_grid_scroll(grid, top, bot, left, right, rows, cols)
|
||||
function Screen:_handle_grid_scroll(g, top, bot, left, right, rows, cols)
|
||||
if self.scroll_over and g == 1 and top < self.scroll_over_pos then
|
||||
self.scroll_over_pos = top
|
||||
end
|
||||
|
||||
top = top+1
|
||||
left = left+1
|
||||
assert(grid == 1)
|
||||
assert(cols == 0)
|
||||
local grid = self._grids[g]
|
||||
local start, stop, step
|
||||
|
||||
|
||||
if rows > 0 then
|
||||
start = top
|
||||
stop = bot - rows
|
||||
@@ -723,8 +788,8 @@ function Screen:_handle_grid_scroll(grid, top, bot, left, right, rows, cols)
|
||||
|
||||
-- shift scroll region
|
||||
for i = start, stop, step do
|
||||
local target = self._rows[i]
|
||||
local source = self._rows[i + rows]
|
||||
local target = grid.rows[i]
|
||||
local source = grid.rows[i + rows]
|
||||
for j = left, right do
|
||||
target[j].text = source[j].text
|
||||
target[j].attrs = source[j].attrs
|
||||
@@ -734,7 +799,7 @@ function Screen:_handle_grid_scroll(grid, top, bot, left, right, rows, cols)
|
||||
|
||||
-- clear invalid rows
|
||||
for i = stop + step, stop + rows, step do
|
||||
self:_clear_row_section(i, left, right)
|
||||
self:_clear_row_section(grid, i, left, right)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -744,13 +809,35 @@ function Screen:_handle_hl_attr_define(id, rgb_attrs, cterm_attrs, info)
|
||||
self._new_attrs = true
|
||||
end
|
||||
|
||||
function Screen:_handle_win_pos(grid, win, startrow, startcol, width, height)
|
||||
self.win_position[grid] = {
|
||||
win = win,
|
||||
startrow = startrow,
|
||||
startcol = startcol,
|
||||
width = width,
|
||||
height = height
|
||||
}
|
||||
end
|
||||
|
||||
function Screen:_handle_win_hide(grid)
|
||||
self.win_position[grid] = nil
|
||||
end
|
||||
|
||||
function Screen:get_hl(val)
|
||||
if self._options.ext_newgrid then
|
||||
return self._attr_table[val][1]
|
||||
else
|
||||
return val
|
||||
end
|
||||
end
|
||||
|
||||
function Screen:_handle_highlight_set(attrs)
|
||||
self._attrs = attrs
|
||||
end
|
||||
|
||||
function Screen:_handle_put(str)
|
||||
assert(not self._options.ext_linegrid)
|
||||
local cell = self._rows[self._cursor.row][self._cursor.col]
|
||||
local cell = self._grid.rows[self._cursor.row][self._cursor.col]
|
||||
cell.text = str
|
||||
cell.attrs = self._attrs
|
||||
cell.hl_id = -1
|
||||
@@ -759,8 +846,7 @@ end
|
||||
|
||||
function Screen:_handle_grid_line(grid, row, col, items)
|
||||
assert(self._options.ext_linegrid)
|
||||
assert(grid == 1)
|
||||
local line = self._rows[row+1]
|
||||
local line = self._grids[grid].rows[row+1]
|
||||
local colpos = col+1
|
||||
local hl = self._clear_attrs
|
||||
local hl_id = 0
|
||||
@@ -887,45 +973,68 @@ function Screen:_handle_wildmenu_hide()
|
||||
self.wildmenu_items, self.wildmenu_pos = nil, nil
|
||||
end
|
||||
|
||||
function Screen:_clear_block(top, bot, left, right)
|
||||
function Screen:_clear_block(grid, top, bot, left, right)
|
||||
for i = top, bot do
|
||||
self:_clear_row_section(i, left, right)
|
||||
self:_clear_row_section(grid, i, left, right)
|
||||
end
|
||||
end
|
||||
|
||||
function Screen:_clear_row_section(rownum, startcol, stopcol)
|
||||
local row = self._rows[rownum]
|
||||
function Screen:_clear_row_section(grid, rownum, startcol, stopcol)
|
||||
local row = grid.rows[rownum]
|
||||
for i = startcol, stopcol do
|
||||
row[i].text = ' '
|
||||
row[i].attrs = self._clear_attrs
|
||||
end
|
||||
end
|
||||
|
||||
function Screen:_row_repr(row, attr_state)
|
||||
function Screen:_row_repr(gridnr, rownr, attr_state, cursor)
|
||||
local rv = {}
|
||||
local current_attr_id
|
||||
for i = 1, self._width do
|
||||
local attrs = row[i].attrs
|
||||
if self._options.ext_linegrid then
|
||||
attrs = attrs[(self._options.rgb and 1) or 2]
|
||||
local i = 1
|
||||
local has_windows = self._options.ext_multigrid and gridnr == 1
|
||||
if self.scroll_over and self.scroll_over_pos < rownr then
|
||||
has_windows = false
|
||||
end
|
||||
local row = self._grids[gridnr].rows[rownr]
|
||||
while i <= #row do
|
||||
local did_window = false
|
||||
if has_windows then
|
||||
for id,pos in pairs(self.win_position) do
|
||||
if i-1 == pos.startcol and pos.startrow <= rownr-1 and rownr-1 < pos.startrow + pos.height then
|
||||
if current_attr_id then
|
||||
-- close current attribute bracket
|
||||
table.insert(rv, '}')
|
||||
current_attr_id = nil
|
||||
end
|
||||
table.insert(rv, '['..id..':'..string.rep('-',pos.width)..']')
|
||||
i = i + pos.width
|
||||
did_window = true
|
||||
end
|
||||
end
|
||||
end
|
||||
local attr_id = self:_get_attr_id(attr_state, attrs, row[i].hl_id)
|
||||
if current_attr_id and attr_id ~= current_attr_id then
|
||||
-- close current attribute bracket, add it before any whitespace
|
||||
-- up to the current cell
|
||||
-- table.insert(rv, backward_find_meaningful(rv, i), '}')
|
||||
table.insert(rv, '}')
|
||||
current_attr_id = nil
|
||||
|
||||
if not did_window then
|
||||
local attrs = row[i].attrs
|
||||
if self._options.ext_linegrid then
|
||||
attrs = attrs[(self._options.rgb and 1) or 2]
|
||||
end
|
||||
local attr_id = self:_get_attr_id(attr_state, attrs, row[i].hl_id)
|
||||
if current_attr_id and attr_id ~= current_attr_id then
|
||||
-- close current attribute bracket
|
||||
table.insert(rv, '}')
|
||||
current_attr_id = nil
|
||||
end
|
||||
if not current_attr_id and attr_id then
|
||||
-- open a new attribute bracket
|
||||
table.insert(rv, '{' .. attr_id .. ':')
|
||||
current_attr_id = attr_id
|
||||
end
|
||||
if not self._busy and cursor and self._cursor.col == i then
|
||||
table.insert(rv, '^')
|
||||
end
|
||||
table.insert(rv, row[i].text)
|
||||
i = i + 1
|
||||
end
|
||||
if not current_attr_id and attr_id then
|
||||
-- open a new attribute bracket
|
||||
table.insert(rv, '{' .. attr_id .. ':')
|
||||
current_attr_id = attr_id
|
||||
end
|
||||
if not self._busy and self._rows[self._cursor.row] == row and self._cursor.col == i then
|
||||
table.insert(rv, '^')
|
||||
end
|
||||
table.insert(rv, row[i].text)
|
||||
end
|
||||
if current_attr_id then
|
||||
table.insert(rv, '}')
|
||||
@@ -997,7 +1106,23 @@ function Screen:redraw_debug(attrs, ignore, timeout)
|
||||
if timeout == nil then
|
||||
timeout = 250
|
||||
end
|
||||
run(nil, notification_cb, nil, timeout)
|
||||
run_session(self._session, nil, notification_cb, nil, timeout)
|
||||
end
|
||||
|
||||
function Screen:render(headers, attr_state, preview)
|
||||
headers = headers and self._options.ext_multigrid
|
||||
local rv = {}
|
||||
for igrid,grid in pairs(self._grids) do
|
||||
if headers then
|
||||
table.insert(rv, "## grid "..igrid)
|
||||
end
|
||||
for i = 1, grid.height do
|
||||
local cursor = self._cursor.grid == igrid and self._cursor.row == i
|
||||
local prefix = (headers or preview) and " " or ""
|
||||
table.insert(rv, prefix..self:_row_repr(igrid, i, attr_state, cursor).."|")
|
||||
end
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
function Screen:print_snapshot(attrs, ignore)
|
||||
@@ -1020,10 +1145,7 @@ function Screen:print_snapshot(attrs, ignore)
|
||||
attr_state.id_to_index = self:hlstate_check_attrs(attr_state.ids)
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
for i = 1, self._height do
|
||||
table.insert(lines, " "..self:_row_repr(self._rows[i], attr_state).."|")
|
||||
end
|
||||
local lines = self:render(true, attr_state, true)
|
||||
|
||||
local ext_state = self:_extstate_repr(attr_state)
|
||||
local keys = false
|
||||
|
||||
@@ -165,7 +165,7 @@ describe("'wildmenu'", function()
|
||||
feed([[:<Tab>]]) -- Invoke wildmenu.
|
||||
-- Check only the last 2 lines, because the shell output is
|
||||
-- system-dependent.
|
||||
expect_stay_unchanged{any='! # & < = > @ > \n:!^'}
|
||||
expect_stay_unchanged{any='! # & < = > @ > |\n:!^'}
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ local check_logs_useless_lines = {
|
||||
local function eq(expected, actual, ctx)
|
||||
return assert.are.same(expected, actual, ctx)
|
||||
end
|
||||
local function neq(expected, actual)
|
||||
return assert.are_not.same(expected, actual)
|
||||
local function neq(expected, actual, context)
|
||||
return assert.are_not.same(expected, actual, context)
|
||||
end
|
||||
local function ok(res)
|
||||
return assert.is_true(res)
|
||||
|
||||
Reference in New Issue
Block a user