aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/buffer.c14
-rw-r--r--src/nvim/charset.c5
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/eval.c16
-rw-r--r--src/nvim/ex_cmds.c10
-rw-r--r--src/nvim/ex_cmds2.c6
-rw-r--r--src/nvim/ex_docmd.c6
-rw-r--r--src/nvim/ex_getln.c2
-rw-r--r--src/nvim/fileio.c8
-rw-r--r--src/nvim/garray.c2
-rw-r--r--src/nvim/getchar.c2
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/main.c25
-rw-r--r--src/nvim/mark.c2
-rw-r--r--src/nvim/mbyte.c10
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/menu.c2
-rw-r--r--src/nvim/message.c2
-rw-r--r--src/nvim/misc1.c2
-rw-r--r--src/nvim/msgpack_rpc/channel.c42
-rw-r--r--src/nvim/msgpack_rpc/remote_ui.c109
-rw-r--r--src/nvim/ops.c2
-rw-r--r--src/nvim/option.c2
-rw-r--r--src/nvim/os/input.c15
-rw-r--r--src/nvim/os/shell.c12
-rw-r--r--src/nvim/os_unix.c21
-rw-r--r--src/nvim/path.c6
-rw-r--r--src/nvim/regexp.c2
-rw-r--r--src/nvim/screen.c14
-rw-r--r--src/nvim/search.c2
-rw-r--r--src/nvim/strings.c4
-rw-r--r--src/nvim/syntax.c28
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/term.c30
-rw-r--r--src/nvim/ui.c139
-rw-r--r--src/nvim/ui.h7
-rw-r--r--src/nvim/undo.c2
-rw-r--r--src/nvim/window.c2
-rw-r--r--test/functional/legacy/066_visual_block_tab_spec.lua10
-rw-r--r--test/functional/ui/highlight_spec.lua27
-rw-r--r--test/functional/ui/mouse_spec.lua84
-rw-r--r--test/functional/ui/screen.lua115
-rw-r--r--test/functional/ui/screen_basic_spec.lua254
-rw-r--r--third-party/CMakeLists.txt6
45 files changed, 764 insertions, 298 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 58310a22a4..3a378ea360 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -602,7 +602,6 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)
{
(void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
start, dir, count, eap->forceit);
-#ifdef HAS_SWAP_EXISTS_ACTION
buf_T *old_curbuf = curbuf;
swap_exists_action = SEA_DIALOG;
@@ -624,10 +623,8 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)
} else {
handle_swap_exists(old_curbuf);
}
-#endif
}
-#if defined(HAS_SWAP_EXISTS_ACTION) || defined(PROTO)
/*
* Handle the situation of swap_exists_action being set.
* It is allowed for "old_curbuf" to be NULL or invalid.
@@ -678,7 +675,6 @@ void handle_swap_exists(buf_T *old_curbuf)
}
swap_exists_action = SEA_NONE;
}
-#endif
/*
* do_bufdel() - delete or unload buffer(s)
@@ -2351,7 +2347,7 @@ int buflist_add(char_u *fname, int flags)
return 0;
}
-#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+#if defined(BACKSLASH_IN_FILENAME)
/*
* Adjust slashes in file names. Called after 'shellslash' was set.
*/
@@ -2752,7 +2748,7 @@ void resettitle(void)
mch_settitle(lasttitle, lasticon);
}
-# if defined(EXITFREE) || defined(PROTO)
+# if defined(EXITFREE)
void free_titles(void)
{
free(lasttitle);
@@ -3934,17 +3930,12 @@ void ex_buffer_all(exarg_T *eap)
continue;
/* Open the buffer in this window. */
-#if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_action = SEA_DIALOG;
-#endif
set_curbuf(buf, DOBUF_GOTO);
if (!buf_valid(buf)) { /* autocommands deleted the buffer!!! */
-#if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_action = SEA_NONE;
-# endif
break;
}
-#if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT) {
cleanup_T cs;
@@ -3964,7 +3955,6 @@ void ex_buffer_all(exarg_T *eap)
leave_cleanup(&cs);
} else
handle_swap_exists(NULL);
-#endif
}
os_breakcheck();
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 7356d91ac2..b86c66c3fe 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1853,7 +1853,7 @@ int hex2nr(int c)
return c - '0';
}
-#if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK) || defined(PROTO)
+#if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK)
/// Convert two hex characters to a byte.
/// Return -1 if one of the characters is not hex.
@@ -1870,8 +1870,7 @@ int hexhex2nr(char_u *p)
return (hex2nr(p[0]) << 4) + hex2nr(p[1]);
}
-#endif // if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK)
- // || defined(PROTO)
+#endif // if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK)
/// Return true if "str" starts with a backslash that should be removed.
/// For WIN32 this is only done when the character after the
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index e1a1fb18fa..4c00547daa 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -5800,7 +5800,7 @@ void set_last_insert(int c)
last_insert_skip = 0;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_last_insert(void)
{
free(last_insert);
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d60ce2de73..1833461fa9 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -76,6 +76,7 @@
#include "nvim/tag.h"
#include "nvim/tempfile.h"
#include "nvim/term.h"
+#include "nvim/ui.h"
#include "nvim/mouse.h"
#include "nvim/undo.h"
#include "nvim/version.h"
@@ -499,7 +500,7 @@ void eval_init(void)
job_event_pool = kmp_init(JobEventPool);
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void eval_clear(void)
{
struct vimvar *p;
@@ -4847,7 +4848,6 @@ list_equal (
return item1 == NULL && item2 == NULL;
}
-#if defined(PROTO)
/*
* Return the dictitem that an entry in a hashtable points to.
*/
@@ -4855,12 +4855,6 @@ dictitem_T *dict_lookup(hashitem_T *hi)
{
return HI2DI(hi);
}
-#endif
-
-dictitem_T * dict_lookup(hashitem_T *hi)
-{
- return HI2DI(hi);
-}
/*
* Return TRUE when two dictionaries have exactly the same key/values.
@@ -10023,6 +10017,8 @@ static void f_has(typval_T *argvars, typval_T *rettv)
#endif
} else if (STRICMP(name, "syntax_items") == 0) {
n = syntax_present(curwin);
+ } else if (STRICMP(name, "gui_running") == 0) {
+ n = ui_rgb_attached();
}
}
@@ -14440,7 +14436,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv)
if (modec != 't' && modec != 'c' && modec != 'g')
modec = 0; /* replace invalid with current */
} else {
- if (t_colors > 1)
+ if (abstract_ui || t_colors > 1)
modec = 'c';
else
modec = 't';
@@ -18047,7 +18043,7 @@ static ufunc_T *find_func(char_u *name)
return NULL;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_all_functions(void)
{
hashitem_T *hi;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 03b45f9d49..763a2d6212 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -825,7 +825,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
static char_u *prevcmd = NULL; /* the previous command */
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_prev_shellcmd(void)
{
free(prevcmd);
@@ -2978,9 +2978,7 @@ do_ecmd (
lnum = curwin->w_cursor.lnum;
topline = curwin->w_topline;
if (!oldbuf) { /* need to read the file */
-#if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_action = SEA_DIALOG;
-#endif
curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
/*
@@ -2989,11 +2987,9 @@ do_ecmd (
if (should_abort(open_buffer(FALSE, eap, readfile_flags)))
retval = FAIL;
-#if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT)
retval = FAIL;
handle_swap_exists(old_curbuf);
-#endif
} else {
/* Read the modelines, but only to set window-local options. Any
* buffer-local options have already been set and may have been
@@ -4609,7 +4605,7 @@ void write_viminfo_sub_string(FILE *fp)
}
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_old_sub(void)
{
free(old_sub);
@@ -6184,7 +6180,7 @@ char_u * sign_typenr2name(int typenr)
return (char_u *)_("[Deleted]");
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
/*
* Undefine/free all signs.
*/
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index c796cf6ac7..7de47cb296 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2546,7 +2546,7 @@ void ex_scriptnames(exarg_T *eap)
}
}
-# if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+# if defined(BACKSLASH_IN_FILENAME)
/*
* Fix slashes in the list of script names for 'shellslash'.
*/
@@ -2579,7 +2579,7 @@ char_u *get_scriptname(scid_T id)
return SCRIPT_ITEM(id).sn_name;
}
-# if defined(EXITFREE) || defined(PROTO)
+# if defined(EXITFREE)
void free_scriptnames()
{
# define FREE_SCRIPTNAME(item) free((item)->sn_name)
@@ -3204,7 +3204,7 @@ static char_u **find_locales(void)
return (char_u **)locales_ga.ga_data;
}
-# if defined(EXITFREE) || defined(PROTO)
+# if defined(EXITFREE)
void free_locales(void)
{
int i;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 3661a65b11..b4dfe99aed 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -5530,7 +5530,7 @@ void alist_new(void)
alist_init(curwin->w_alist);
}
-#if !defined(UNIX) || defined(PROTO)
+#if !defined(UNIX)
/*
* Expand the file names in the global argument list.
* If "fnum_list" is not NULL, use "fnum_list[fnum_len]" as a list of buffer
@@ -5623,7 +5623,7 @@ alist_add (
++al->al_ga.ga_len;
}
-#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+#if defined(BACKSLASH_IN_FILENAME)
/*
* Adjust slashes in file names. Called after 'shellslash' was set.
*/
@@ -6256,7 +6256,7 @@ static void ex_read(exarg_T *eap)
static char_u *prev_dir = NULL;
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_cd_dir(void)
{
free(prev_dir);
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 3ce8263457..b942f69f61 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1972,7 +1972,7 @@ static void realloc_cmdbuff(int len)
static char_u *arshape_buf = NULL;
-# if defined(EXITFREE) || defined(PROTO)
+# if defined(EXITFREE)
void free_cmdline_buf(void)
{
free(arshape_buf);
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 58e67fa58c..370584b095 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -636,14 +636,12 @@ readfile (
#endif
}
-#if defined(HAS_SWAP_EXISTS_ACTION)
/* If "Quit" selected at ATTENTION dialog, don't load the file */
if (swap_exists_action == SEA_QUIT) {
if (!read_buffer && !read_stdin)
close(fd);
return FAIL;
}
-#endif
++no_wait_return; /* don't wait for return yet */
@@ -5149,7 +5147,7 @@ void write_lnum_adjust(linenr_T offset)
curbuf->b_no_eol_lnum += offset;
}
-#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+#if defined(BACKSLASH_IN_FILENAME)
/*
* Convert all backslashes in fname to forward slashes in-place.
*/
@@ -5547,7 +5545,7 @@ void do_augroup(char_u *arg, int del_group)
}
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_all_autocmds(void)
{
for (current_augroup = -1; current_augroup < augroups.ga_len;
@@ -7454,7 +7452,7 @@ file_pat_to_reg_pat (
return reg_pat;
}
-#if defined(EINTR) || defined(PROTO)
+#if defined(EINTR)
/*
* Version of read() that retries when interrupted by EINTR (possibly
* by a SIGWINCH).
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index c4f8f66bfe..c3a3426e87 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -199,7 +199,7 @@ void ga_append(garray_T *gap, char c)
GA_APPEND(char, gap, c);
}
-#if defined(UNIX) || defined(WIN3264) || defined(PROTO)
+#if defined(UNIX) || defined(WIN3264)
/// Append the text in "gap" below the cursor line and clear "gap".
///
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index e12601e4c9..d97c983133 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1307,7 +1307,7 @@ static void closescript(void)
--curscript;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void close_all_scripts(void)
{
while (scriptin[0] != NULL)
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 11a7e9ecac..73bcdea226 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -859,7 +859,6 @@ EXTERN int cmd_silent INIT(= FALSE); /* don't echo the command line */
#define SEA_QUIT 2 /* quit editing the file */
#define SEA_RECOVER 3 /* recover the file */
-#define HAS_SWAP_EXISTS_ACTION
EXTERN int swap_exists_action INIT(= SEA_NONE);
/* For dialog when swap file already
* exists. */
diff --git a/src/nvim/main.c b/src/nvim/main.c
index f063cc1238..05b9778102 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -261,10 +261,7 @@ int main(int argc, char **argv)
if (params.want_full_screen && !silent_mode) {
if (embedded_mode) {
- // In embedded mode don't do terminal-related initializations, assume an
- // initial screen size of 80x20
- full_screen = true;
- screen_resize(80, 20, false);
+ // embedded mode implies abstract_ui
termcapinit((uint8_t *)"abstract_ui");
} else {
// set terminal name and get terminal capabilities (will set full_screen)
@@ -278,7 +275,9 @@ int main(int argc, char **argv)
event_init();
if (abstract_ui) {
+ full_screen = true;
t_colors = 256;
+ T_CCO = (uint8_t *)"256";
} else {
// Print a warning if stdout is not a terminal TODO(tarruda): Remove this
// check once the new terminal UI is implemented
@@ -1560,19 +1559,15 @@ static void handle_quickfix(mparm_T *paramp)
static void handle_tag(char_u *tagname)
{
if (tagname != NULL) {
-#if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_did_quit = FALSE;
-#endif
vim_snprintf((char *)IObuff, IOSIZE, "ta %s", tagname);
do_cmdline_cmd(IObuff);
TIME_MSG("jumping to tag");
-#if defined(HAS_SWAP_EXISTS_ACTION)
/* If the user doesn't want to edit the file then we quit here. */
if (swap_exists_did_quit)
getout(1);
-#endif
}
}
@@ -1607,10 +1602,8 @@ static void read_stdin(void)
{
int i;
-#if defined(HAS_SWAP_EXISTS_ACTION)
/* When getting the ATTENTION prompt here, use a dialog */
swap_exists_action = SEA_DIALOG;
-#endif
no_wait_return = TRUE;
i = msg_didany;
set_buflisted(TRUE);
@@ -1618,9 +1611,7 @@ static void read_stdin(void)
no_wait_return = FALSE;
msg_didany = i;
TIME_MSG("reading stdin");
-#if defined(HAS_SWAP_EXISTS_ACTION)
check_swap_exists_action();
-#endif
/*
* Close stdin and dup it from stderr. Required for GPM to work
* properly, and for running external commands.
@@ -1702,16 +1693,13 @@ static void create_windows(mparm_T *parmp)
/* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
if (p_fdls >= 0)
curwin->w_p_fdl = p_fdls;
-#if defined(HAS_SWAP_EXISTS_ACTION)
/* When getting the ATTENTION prompt here, use a dialog */
swap_exists_action = SEA_DIALOG;
-#endif
set_buflisted(TRUE);
/* create memfile, read file */
(void)open_buffer(FALSE, NULL, 0);
-#if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT) {
if (got_int || only_one_window()) {
/* abort selected or quit and only one window */
@@ -1726,7 +1714,6 @@ static void create_windows(mparm_T *parmp)
swap_exists_action = SEA_NONE;
} else
handle_swap_exists(NULL);
-#endif
dorewind = TRUE; /* start again */
}
os_breakcheck();
@@ -1797,13 +1784,10 @@ static void edit_buffers(mparm_T *parmp)
curwin->w_arg_idx = arg_idx;
/* Edit file from arg list, if there is one. When "Quit" selected
* at the ATTENTION prompt close the window. */
-# ifdef HAS_SWAP_EXISTS_ACTION
swap_exists_did_quit = FALSE;
-# endif
(void)do_ecmd(0, arg_idx < GARGCOUNT
? alist_name(&GARGLIST[arg_idx]) : NULL,
NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin);
-# ifdef HAS_SWAP_EXISTS_ACTION
if (swap_exists_did_quit) {
/* abort or quit selected */
if (got_int || only_one_window()) {
@@ -1814,7 +1798,6 @@ static void edit_buffers(mparm_T *parmp)
win_close(curwin, TRUE);
advance = FALSE;
}
-# endif
if (arg_idx == GARGCOUNT - 1)
arg_had_last = TRUE;
++arg_idx;
@@ -2215,7 +2198,6 @@ static void usage(void)
mch_exit(0);
}
-#if defined(HAS_SWAP_EXISTS_ACTION)
/*
* Check the result of the ATTENTION dialog:
* When "Quit" selected, exit Vim.
@@ -2228,5 +2210,4 @@ static void check_swap_exists_action(void)
handle_swap_exists(NULL);
}
-#endif
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index cf11be665a..cfc702f189 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -1180,7 +1180,7 @@ void set_last_cursor(win_T *win)
win->w_buffer->b_last_cursor = win->w_cursor;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_all_marks(void)
{
int i;
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 3274c8d8ec..bc8f768724 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -106,8 +106,6 @@
#include "nvim/os/os.h"
#include "nvim/arabic.h"
-#define WINBYTE BYTE
-
typedef struct {
int rangeStart;
int rangeEnd;
@@ -365,10 +363,6 @@ enc_alias_table[] =
{NULL, 0}
};
-#ifndef CP_UTF8
-# define CP_UTF8 65001 /* magic number from winnls.h */
-#endif
-
/*
* Find encoding "name" in the list of canonical encoding names.
* Returns -1 if not found.
@@ -3452,7 +3446,7 @@ char_u * enc_locale(void)
return enc_canonize((char_u *)buf);
}
-# if defined(USE_ICONV) || defined(PROTO)
+# if defined(USE_ICONV)
/*
@@ -3591,7 +3585,7 @@ static char_u * iconv_string(vimconv_T *vcp, char_u *str, int slen, int *unconvl
return result;
}
-# if defined(DYNAMIC_ICONV) || defined(PROTO)
+# if defined(DYNAMIC_ICONV)
/*
* Dynamically load the "iconv.dll" on Win32.
*/
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index f6246c8b57..1fa6d6acc6 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -3000,7 +3000,7 @@ static void ml_lineadd(buf_T *buf, int count)
}
}
-#if defined(HAVE_READLINK) || defined(PROTO)
+#if defined(HAVE_READLINK)
/*
* Resolve a symlink in the last component of a file name.
* Note that f_resolve() does it for every part of the path, we don't do that
@@ -3367,9 +3367,7 @@ findswapname (
* for the current file, and the buffer was not recovered. */
if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL) {
-#if defined(HAS_SWAP_EXISTS_ACTION)
int choice = 0;
-#endif
#ifdef UNIX
process_still_running = FALSE;
@@ -3427,7 +3425,6 @@ findswapname (
redraw_all_later(NOT_VALID);
}
-#if defined(HAS_SWAP_EXISTS_ACTION)
if (choice > 0) {
switch (choice) {
case 1:
@@ -3454,7 +3451,6 @@ findswapname (
if (!os_file_exists(fname))
break;
} else
-#endif
{
MSG_PUTS("\n");
if (msg_silent == 0)
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index f38dfd56ac..a2274a25fe 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -440,7 +440,7 @@ void do_outofmem_msg(size_t size)
}
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
#include "nvim/file_search.h"
#include "nvim/buffer.h"
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index ea15fd68e3..9c1ca71477 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -1359,7 +1359,7 @@ void ex_emenu(exarg_T *eap)
#if defined(FEAT_GUI_MSWIN) \
|| defined(FEAT_GUI_GTK) \
- || defined(FEAT_BEVAL_TIP) || defined(PROTO)
+ || defined(FEAT_BEVAL_TIP)
/*
* Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy.
*/
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 46e0a1a0df..9cd3814826 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -10,8 +10,6 @@
* message.c: functions for displaying messages on the command line
*/
-#define MESSAGE_FILE /* don't include prototype for smsg() */
-
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index c0d2e254ac..f756201efb 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -2662,7 +2662,7 @@ void init_homedir(void)
}
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_homedir(void)
{
free(homedir);
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 4c35cce09a..c8f8252e6d 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -45,6 +45,7 @@ typedef struct {
typedef struct {
uint64_t id;
+ size_t pending_requests;
PMap(cstr_t) *subscribed_events;
bool is_job, closed;
msgpack_unpacker *unpacker;
@@ -83,7 +84,6 @@ static uint64_t next_id = 1;
static PMap(uint64_t) *channels = NULL;
static PMap(cstr_t) *event_strings = NULL;
static msgpack_sbuffer out_buffer;
-static size_t pending_requests = 0;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/channel.c.generated.h"
@@ -103,14 +103,7 @@ void channel_init(void)
}
if (abstract_ui) {
- // Add handler for "attach_ui"
remote_ui_init();
- String method = cstr_as_string("attach_ui");
- MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = true};
- msgpack_rpc_add_method_handler(method, handler);
- method = cstr_as_string("detach_ui");
- handler.fn = remote_ui_detach;
- msgpack_rpc_add_method_handler(method, handler);
}
}
@@ -200,20 +193,21 @@ bool channel_send_event(uint64_t id, char *name, Array args)
return false;
}
- if (pending_requests) {
- DelayedNotification p = {
- .channel = channel,
- .method = cstr_to_string(name),
- .args = args
- };
- // Pending request, queue the notification for sending later
- *kl_pushp(DelayedNotification, delayed_notifications) = p;
- } else {
- if (channel) {
- send_event(channel, name, args);
+ if (channel) {
+ if (channel->pending_requests) {
+ DelayedNotification p = {
+ .channel = channel,
+ .method = cstr_to_string(name),
+ .args = args
+ };
+ // Pending request, queue the notification for sending later
+ *kl_pushp(DelayedNotification, delayed_notifications) = p;
} else {
- broadcast_event(name, args);
+ send_event(channel, name, args);
}
+ } else {
+ // TODO(tarruda): Implement event broadcasting in vimscript
+ broadcast_event(name, args);
}
return true;
@@ -246,10 +240,10 @@ Object channel_send_call(uint64_t id,
// Push the frame
ChannelCallFrame frame = {request_id, false, false, NIL};
kv_push(ChannelCallFrame *, channel->call_stack, &frame);
- pending_requests++;
+ channel->pending_requests++;
event_poll_until(-1, frame.returned);
(void)kv_pop(channel->call_stack);
- pending_requests--;
+ channel->pending_requests--;
if (frame.errored) {
api_set_error(err, Exception, "%s", frame.result.data.string.data);
@@ -261,7 +255,7 @@ Object channel_send_call(uint64_t id,
free_channel(channel);
}
- if (!pending_requests) {
+ if (!channel->pending_requests) {
send_delayed_notifications();
}
@@ -644,6 +638,7 @@ static void close_channel(Channel *channel)
uv_handle_t *handle = (uv_handle_t *)channel->data.streams.uv;
if (handle) {
uv_close(handle, close_cb);
+ free_channel(channel);
} else {
event_push((Event) { .handler = on_stdio_close }, false);
}
@@ -687,6 +682,7 @@ static Channel *register_channel(void)
rv->closed = false;
rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
rv->id = next_id++;
+ rv->pending_requests = 0;
rv->subscribed_events = pmap_new(cstr_t)();
rv->next_request_id = 1;
kv_init(rv->call_stack);
diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c
index f980a77b4c..361e93a6da 100644
--- a/src/nvim/msgpack_rpc/remote_ui.c
+++ b/src/nvim/msgpack_rpc/remote_ui.c
@@ -26,18 +26,44 @@ static PMap(uint64_t) *connected_uis = NULL;
void remote_ui_init(void)
{
connected_uis = pmap_new(uint64_t)();
+ // Add handler for "attach_ui"
+ String method = cstr_as_string("ui_attach");
+ MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = false};
+ msgpack_rpc_add_method_handler(method, handler);
+ method = cstr_as_string("ui_detach");
+ handler.fn = remote_ui_detach;
+ msgpack_rpc_add_method_handler(method, handler);
+ method = cstr_as_string("ui_try_resize");
+ handler.fn = remote_ui_try_resize;
+ msgpack_rpc_add_method_handler(method, handler);
}
-Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args,
- Error *error)
+void remote_ui_disconnect(uint64_t channel_id)
+{
+ UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ if (!ui) {
+ return;
+ }
+ UIData *data = ui->data;
+ // destroy pending screen updates
+ api_free_array(data->buffer);
+ pmap_del(uint64_t)(connected_uis, channel_id);
+ free(ui->data);
+ ui_detach(ui);
+ free(ui);
+}
+
+static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
+ Array args, Error *error)
{
if (pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI already attached for channel"));
return NIL;
}
- if (args.size != 2 || args.items[0].type != kObjectTypeInteger
+ if (args.size != 3 || args.items[0].type != kObjectTypeInteger
|| args.items[1].type != kObjectTypeInteger
+ || args.items[2].type != kObjectTypeBoolean
|| args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
api_set_error(error, Validation,
_("Arguments must be a pair of positive integers "
@@ -50,6 +76,7 @@ Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args,
UI *ui = xcalloc(1, sizeof(UI));
ui->width = (int)args.items[0].data.integer;
ui->height = (int)args.items[1].data.integer;
+ ui->rgb = args.items[2].data.boolean;
ui->data = data;
ui->resize = remote_ui_resize;
ui->clear = remote_ui_clear;
@@ -67,16 +94,19 @@ Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args,
ui->put = remote_ui_put;
ui->bell = remote_ui_bell;
ui->visual_bell = remote_ui_visual_bell;
+ ui->update_fg = remote_ui_update_fg;
+ ui->update_bg = remote_ui_update_bg;
ui->flush = remote_ui_flush;
ui->suspend = remote_ui_suspend;
+ ui->set_title = remote_ui_set_title;
+ ui->set_icon = remote_ui_set_icon;
pmap_put(uint64_t)(connected_uis, channel_id, ui);
ui_attach(ui);
-
return NIL;
}
-Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, Array args,
- Error *error)
+static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id,
+ Array args, Error *error)
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI is not attached for channel"));
@@ -86,21 +116,30 @@ Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, Array args,
return NIL;
}
-void remote_ui_disconnect(uint64_t channel_id)
+static Object remote_ui_try_resize(uint64_t channel_id, uint64_t request_id,
+ Array args, Error *error)
{
- UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
- if (!ui) {
- return;
+ if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ api_set_error(error, Exception, _("UI is not attached for channel"));
}
- UIData *data = ui->data;
- // destroy pending screen updates
- api_free_array(data->buffer);
- pmap_del(uint64_t)(connected_uis, channel_id);
- free(ui->data);
- ui_detach(ui);
- free(ui);
+
+ if (args.size != 2 || args.items[0].type != kObjectTypeInteger
+ || args.items[1].type != kObjectTypeInteger
+ || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
+ api_set_error(error, Validation,
+ _("Arguments must be a pair of positive integers "
+ "representing the remote screen width/height"));
+ return NIL;
+ }
+
+ UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ ui->width = (int)args.items[0].data.integer;
+ ui->height = (int)args.items[1].data.integer;
+ ui_refresh();
+ return NIL;
}
+
static void push_call(UI *ui, char *name, Array args)
{
Array call = ARRAY_DICT_INIT;
@@ -214,10 +253,6 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
PUT(hl, "bold", BOOLEAN_OBJ(true));
}
- if (attrs.standout) {
- PUT(hl, "standout", BOOLEAN_OBJ(true));
- }
-
if (attrs.underline) {
PUT(hl, "underline", BOOLEAN_OBJ(true));
}
@@ -266,6 +301,20 @@ static void remote_ui_visual_bell(UI *ui)
push_call(ui, "visual_bell", args);
}
+static void remote_ui_update_fg(UI *ui, int fg)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(fg));
+ push_call(ui, "update_fg", args);
+}
+
+static void remote_ui_update_bg(UI *ui, int bg)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(bg));
+ push_call(ui, "update_bg", args);
+}
+
static void remote_ui_flush(UI *ui)
{
UIData *data = ui->data;
@@ -275,6 +324,20 @@ static void remote_ui_flush(UI *ui)
static void remote_ui_suspend(UI *ui)
{
- UIData *data = ui->data;
- remote_ui_disconnect(data->channel_id);
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "suspend", args);
+}
+
+static void remote_ui_set_title(UI *ui, char *title)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, STRING_OBJ(cstr_to_string(title)));
+ push_call(ui, "set_title", args);
+}
+
+static void remote_ui_set_icon(UI *ui, char *icon)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, STRING_OBJ(cstr_to_string(icon)));
+ push_call(ui, "set_icon", args);
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 87a2c2ca05..8fb3ba7f08 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2293,7 +2293,7 @@ void init_yank(void)
y_regs[i].y_array = NULL;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void clear_registers(void)
{
int i;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 6c774937cd..88108b14a2 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -2237,7 +2237,7 @@ void set_number_default(char *name, long val)
options[opt_idx].def_val[VI_DEFAULT] = (char_u *)val;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
/*
* Free all options.
*/
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index c0d588f4ef..2ae4558f3d 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -187,14 +187,20 @@ size_t input_enqueue(String keys)
unsigned int new_size = trans_special((uint8_t **)&ptr, buf, false);
if (!new_size) {
+ if (*ptr == '<') {
+ // Invalid key sequence, skip until the next '>' or until *end
+ do {
+ ptr++;
+ } while (ptr < end && *ptr != '>');
+ ptr++;
+ continue;
+ }
// copy the character unmodified
*buf = (uint8_t)*ptr++;
new_size = 1;
}
new_size = handle_mouse_event(&ptr, buf, new_size);
- // TODO(tarruda): Don't produce past unclosed '<' characters, except if
- // there's a lot of characters after the '<'
rbuffer_write(input_buffer, (char *)buf, new_size);
}
@@ -217,7 +223,8 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf,
mouse_code = buf[5];
}
- if (mouse_code < KE_LEFTMOUSE || mouse_code > KE_RIGHTRELEASE) {
+ if (!((mouse_code >= KE_LEFTMOUSE && mouse_code <= KE_RIGHTRELEASE)
+ || (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT))) {
return bufsize;
}
@@ -226,7 +233,7 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf,
// find mouse coordinates, and it would be too expensive to refactor this
// now.
int col, row, advance;
- if (sscanf(*ptr, "<%d,%d>%n", &col, &row, &advance)) {
+ if (sscanf(*ptr, "<%d,%d>%n", &col, &row, &advance) != EOF && advance) {
if (col >= 0 && row >= 0) {
mouse_row = row;
mouse_col = col;
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index d0f8442768..d481d6af56 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -24,7 +24,6 @@
#include "nvim/option_defs.h"
#include "nvim/charset.h"
#include "nvim/strings.h"
-#include "nvim/ui.h"
#define DYNAMIC_BUFFER_INIT {NULL, 0, 0}
@@ -414,6 +413,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
char *start = output;
size_t off = 0;
+ int lastrow = (int)Rows - 1;
while (off < remaining) {
if (output[off] == NL) {
// Insert the line
@@ -421,10 +421,8 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
if (to_buffer) {
ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false);
} else {
- // pending data from the output buffer has been flushed to the screen,
- // safe to call ui_write directly
- ui_write((char_u *)output, (int)off);
- ui_write((char_u *)"\r\n", 2);
+ screen_del_lines(0, 0, 1, (int)Rows, true, NULL);
+ screen_puts_len((char_u *)output, (int)off, lastrow, 0, 0);
}
size_t skip = off + 1;
output += skip;
@@ -448,8 +446,8 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer,
// remember that the NL was missing
curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
} else {
- ui_write((char_u *)output, (int)remaining);
- ui_write((char_u *)"\r\n", 2);
+ screen_del_lines(0, 0, 1, (int)Rows, true, NULL);
+ screen_puts_len((char_u *)output, (int)remaining, lastrow, 0, 0);
}
output += remaining;
} else if (to_buffer) {
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index 7ec4059bce..f7b47f9569 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -43,6 +43,7 @@
#include "nvim/syntax.h"
#include "nvim/tempfile.h"
#include "nvim/term.h"
+#include "nvim/ui.h"
#include "nvim/types.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
@@ -181,22 +182,26 @@ void mch_settitle(char_u *title, char_u *icon)
* Note: if "t_ts" is set, title is set with escape sequence rather
* than x11 calls, because the x11 calls don't always work
*/
- if ((type || *T_TS != NUL) && title != NULL) {
+ if ((type || *T_TS != NUL || abstract_ui) && title != NULL) {
if (oldtitle == NULL
) /* first call but not in GUI, save title */
(void)get_x11_title(FALSE);
- if (*T_TS != NUL) /* it's OK if t_fs is empty */
+ if (abstract_ui) {
+ ui_set_title((char *)title);
+ } else if (*T_TS != NUL) /* it's OK if t_fs is empty */
term_settitle(title);
did_set_title = TRUE;
}
- if ((type || *T_CIS != NUL) && icon != NULL) {
+ if ((type || *T_CIS != NUL || abstract_ui) && icon != NULL) {
if (oldicon == NULL
) /* first call, save icon */
get_x11_icon(FALSE);
- if (*T_CIS != NUL) {
+ if (abstract_ui) {
+ ui_set_icon((char *)icon);
+ } else if (*T_CIS != NUL) {
out_str(T_CIS); /* set icon start */
out_str_nf(icon);
out_str(T_CIE); /* set icon end */
@@ -270,7 +275,7 @@ int use_xterm_mouse(void)
return 0;
}
-#if defined(USE_FNAME_CASE) || defined(PROTO)
+#if defined(USE_FNAME_CASE)
/*
* Set the case of the file name, if it already exists. This will cause the
* file name to remain exactly the same.
@@ -326,7 +331,7 @@ int len /* buffer size, only used when name gets longer */
}
#endif
-#if defined(HAVE_ACL) || defined(PROTO)
+#if defined(HAVE_ACL)
# ifdef HAVE_SYS_ACL_H
# include <sys/acl.h>
# endif
@@ -335,7 +340,7 @@ int len /* buffer size, only used when name gets longer */
# endif
-#if defined(HAVE_SELINUX) || defined(PROTO)
+#if defined(HAVE_SELINUX)
/*
* Copy security info from "from_file" to "to_file".
*/
@@ -437,7 +442,7 @@ int mch_nodetype(char_u *name)
return NODE_WRITABLE;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void mch_free_mem(void)
{
free(oldtitle);
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 8af4015611..219dac12de 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -403,9 +403,9 @@ char_u *save_absolute_path(const char_u *name)
}
-#if !defined(NO_EXPANDPATH) || defined(PROTO)
+#if !defined(NO_EXPANDPATH)
-#if defined(UNIX) || defined(USE_UNIXFILENAME) || defined(PROTO)
+#if defined(UNIX) || defined(USE_UNIXFILENAME)
/*
* Unix style wildcard expansion code.
* It's here because it's used both for Unix and Mac.
@@ -1622,7 +1622,7 @@ int same_directory(char_u *f1, char_u *f2)
&& pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0;
}
-#if !defined(NO_EXPANDPATH) || defined(PROTO)
+#if !defined(NO_EXPANDPATH)
/*
* Compare path "p[]" to "q[]".
* If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]"
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 62c01e3798..fafd99c046 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -3228,7 +3228,7 @@ static garray_T backpos = GA_EMPTY_INIT_VALUE;
#define REGSTACK_INITIAL 2048
#define BACKPOS_INITIAL 64
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_regexp_stuff(void)
{
ga_clear(&regstack);
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 52ded0aa49..8f4f894128 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -5971,7 +5971,7 @@ void screen_stop_highlight(void)
*/
void reset_cterm_colors(void)
{
- if (t_colors > 1) {
+ if (!abstract_ui && t_colors > 1) {
/* set Normal cterm colors */
if (cterm_normal_fg_color > 0 || cterm_normal_bg_color > 0) {
out_str(T_OP);
@@ -6150,8 +6150,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
return;
/* it's a "normal" terminal when not in a GUI or cterm */
- norm_term = (
- t_colors <= 1);
+ norm_term = (!abstract_ui && t_colors <= 1);
for (row = start_row; row < end_row; ++row) {
if (has_mbyte
) {
@@ -6675,8 +6674,8 @@ static void linecopy(int to, int from, win_T *wp)
*/
int can_clear(char_u *p)
{
- return *p != NUL && (t_colors <= 1
- || cterm_normal_bg_color == 0 || *T_UT != NUL);
+ return abstract_ui || (*p != NUL && (t_colors <= 1
+ || cterm_normal_bg_color == 0 || *T_UT != NUL));
}
/*
@@ -8186,8 +8185,13 @@ void screen_resize(int width, int height, int mustset)
Columns = width;
}
check_shellsize();
+ height = Rows;
+ width = Columns;
if (abstract_ui) {
+ // Clear the output buffer to ensure UIs don't receive redraw command meant
+ // for invalid screen sizes.
+ out_buf_clear();
ui_resize(width, height);
} else {
mch_set_shellsize();
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 25b8277933..e2781f17d5 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -294,7 +294,7 @@ void restore_search_patterns(void)
}
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_search_patterns(void)
{
free(spats[0].pat);
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 25e4a6c93b..20fa35ed1c 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -329,7 +329,7 @@ void vim_strcat(char_u *restrict to, const char_u *restrict from,
STRCPY(to + tolen, from);
}
-#if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO)
+#if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP))
/*
* Compare two strings, ignoring case, using current locale.
* Doesn't work for multi-byte characters.
@@ -353,7 +353,7 @@ int vim_stricmp(const char *s1, const char *s2)
}
#endif
-#if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO)
+#if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP))
/*
* Compare two strings, for length "len", ignoring case, using current locale.
* Doesn't work for multi-byte characters.
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index e9a814bc97..3980a4d8e6 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -45,6 +45,7 @@
#include "nvim/strings.h"
#include "nvim/syntax_defs.h"
#include "nvim/term.h"
+#include "nvim/ui.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
@@ -223,8 +224,6 @@ struct name_list {
#define ATTR_OFF (HL_ALL + 1)
-#define SYN_NAMELEN 50 /* maximum length of a syntax name */
-
static char *(spo_name_tab[SPO_COUNT]) =
{"ms=", "me=", "hs=", "he=", "rs=", "re=", "lc="};
@@ -6036,6 +6035,7 @@ int load_colors(char_u *name)
apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, FALSE, curbuf);
recursive = FALSE;
+ ui_refresh();
return retval;
}
@@ -6070,8 +6070,6 @@ do_highlight (
int error = FALSE;
int color;
int is_normal_group = FALSE; /* "Normal" group */
-# define is_menu_group 0
-# define is_tooltip_group 0
/*
* If no argument, list current highlighting.
@@ -6438,8 +6436,7 @@ do_highlight (
HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
}
color &= 7; /* truncate to 8 colors */
- } else if (t_colors == 16 || t_colors == 88
- || t_colors == 256) {
+ } else if (t_colors == 16 || t_colors == 88 || t_colors == 256) {
/*
* Guess: if the termcap entry ends in 'm', it is
* probably an xterm-like terminal. Use the changed
@@ -6449,7 +6446,7 @@ do_highlight (
p = T_CAF;
else
p = T_CSF;
- if (*p != NUL && *(p + STRLEN(p) - 1) == 'm')
+ if (abstract_ui || (*p != NUL && *(p + STRLEN(p) - 1) == 'm'))
switch (t_colors) {
case 16:
color = color_numbers_8[i];
@@ -6632,6 +6629,10 @@ do_highlight (
if (is_normal_group) {
HL_TABLE()[idx].sg_term_attr = 0;
HL_TABLE()[idx].sg_cterm_attr = 0;
+ if (abstract_ui) {
+ // If the normal group has changed, it is simpler to refresh every UI
+ ui_refresh();
+ }
} else
set_hl_attr(idx);
HL_TABLE()[idx].sg_scriptID = current_SID;
@@ -6644,7 +6645,7 @@ do_highlight (
need_highlight_changed = TRUE;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_highlight(void)
{
for (int i = 0; i < highlight_ga.ga_len; ++i) {
@@ -6860,7 +6861,7 @@ int hl_combine_attr(int char_attr, int prim_attr)
if (char_attr <= HL_ALL && prim_attr <= HL_ALL)
return char_attr | prim_attr;
- if (t_colors > 1) {
+ if (abstract_ui || t_colors > 1) {
if (char_attr > HL_ALL)
char_aep = syn_cterm_attr2entry(char_attr);
if (char_aep != NULL)
@@ -6924,7 +6925,7 @@ int syn_attr2attr(int attr)
{
attrentry_T *aep;
- if (t_colors > 1)
+ if (abstract_ui || t_colors > 1)
aep = syn_cterm_attr2entry(attr);
else
aep = syn_term_attr2entry(attr);
@@ -7194,9 +7195,10 @@ set_hl_attr (
* For the color term mode: If there are other than "normal"
* highlighting attributes, need to allocate an attr number.
*/
- if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0)
+ if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0
+ && sgp->sg_rgb_fg == -1 && sgp->sg_rgb_bg == -1) {
sgp->sg_cterm_attr = sgp->sg_cterm;
- else {
+ } else {
at_en.ae_attr = abstract_ui ? sgp->sg_gui : sgp->sg_cterm;
at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
@@ -7351,7 +7353,7 @@ int syn_id2attr(int hl_id)
hl_id = syn_get_final_id(hl_id);
sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
- if (t_colors > 1)
+ if (abstract_ui || t_colors > 1)
attr = sgp->sg_cterm_attr;
else
attr = sgp->sg_term_attr;
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index fb39e069f0..bab594a27d 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1981,7 +1981,7 @@ static void found_tagfile_cb(char_u *fname, void *cookie)
GA_APPEND(char_u *, &tag_fnames, vim_strsave(fname));
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void free_tag_stuff(void)
{
ga_clear_strings(&tag_fnames);
diff --git a/src/nvim/term.c b/src/nvim/term.c
index b78b01b68a..78fd3c6a67 100644
--- a/src/nvim/term.c
+++ b/src/nvim/term.c
@@ -170,6 +170,7 @@ static struct builtin_term builtin_termcaps[] =
{(int)KS_DL, "\033|d"},
{(int)KS_CDL, "\033|%p1%dD"},
{(int)KS_CS, "\033|%p1%d;%p2%dR"},
+ {(int)KS_CSV, "\033|%p1%d;%p2%dV"},
{(int)KS_CL, "\033|C"},
// attributes switched on with 'h', off with * 'H'
{(int)KS_ME, "\033|31H"}, // HL_ALL
@@ -1487,7 +1488,7 @@ set_mouse_termcode (
add_termcode(name, s, FALSE);
}
-# if (defined(UNIX) && defined(FEAT_MOUSE_TTY)) || defined(PROTO)
+# if (defined(UNIX) && defined(FEAT_MOUSE_TTY))
void
del_mouse_termcode (
char_u n /* KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE */
@@ -1704,7 +1705,7 @@ static char_u term_7to8bit(char_u *p)
}
-#if !defined(HAVE_TGETENT) || defined(PROTO)
+#if !defined(HAVE_TGETENT)
char_u *tltoa(unsigned long i)
{
@@ -1816,17 +1817,20 @@ void term_write(char_u *s, size_t len)
static char_u out_buf[OUT_SIZE + 1];
static int out_pos = 0; /* number of chars in out_buf */
+// Clear the output buffer
+void out_buf_clear(void)
+{
+ out_pos = 0;
+}
+
/*
* out_flush(): flush the output buffer
*/
void out_flush(void)
{
- if (out_pos != 0) {
- /* set out_pos to 0 before ui_write, to avoid recursiveness */
- int len = out_pos;
- out_pos = 0;
- ui_write(out_buf, len);
- }
+ int len = out_pos;
+ out_pos = 0;
+ ui_write(out_buf, len);
}
/*
@@ -1945,7 +1949,7 @@ void term_delete_lines(int line_count)
OUT_STR(tgoto((char *)T_CDL, 0, line_count));
}
-#if defined(HAVE_TGETENT) || defined(PROTO)
+#if defined(HAVE_TGETENT)
void term_set_winpos(int x, int y)
{
/* Can't handle a negative value here */
@@ -2010,7 +2014,7 @@ static void term_color(char_u *s, int n)
OUT_STR(tgoto((char *)s, 0, n));
}
-#if defined(UNIX) || defined(MACOS_X) || defined(PROTO)
+#if defined(UNIX) || defined(MACOS_X)
/*
* Generic function to set window title, using t_ts and t_fs.
*/
@@ -2202,7 +2206,11 @@ void win_new_shellsize(void)
*/
void shell_resized(void)
{
- screen_resize(0, 0, FALSE);
+ if (abstract_ui) {
+ ui_refresh();
+ } else {
+ screen_resize(0, 0, FALSE);
+ }
}
/*
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 25d6a81960..a8ca58d633 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -60,11 +60,8 @@ static struct {
int top, bot, left, right;
} sr;
static int current_highlight_mask = 0;
-static HlAttrs current_attrs = {
- false, false, false, false, false, false, -1, -1
-};
static bool cursor_enabled = true;
-static int height = INT_MAX, width = INT_MAX;
+static int height, width;
// This set of macros allow us to use UI_CALL to invoke any function on
// registered UI instances. The functions can have 0-5 arguments(configurable
@@ -98,6 +95,10 @@ void ui_write(uint8_t *s, int len)
return;
}
+ if (!len) {
+ return;
+ }
+
char_u *tofree = NULL;
if (output_conv.vc_type != CONV_NONE) {
@@ -113,6 +114,16 @@ void ui_write(uint8_t *s, int len)
free(tofree);
}
+bool ui_rgb_attached(void)
+{
+ for (size_t i = 0; i < ui_count; i++) {
+ if (uis[i]->rgb) {
+ return true;
+ }
+ }
+ return false;
+}
+
/*
* If the machine has job control, use it to suspend the program,
* otherwise fake it by starting a new shell.
@@ -122,11 +133,24 @@ void ui_suspend(void)
{
if (abstract_ui) {
UI_CALL(suspend);
+ UI_CALL(flush);
} else {
mch_suspend();
}
}
+void ui_set_title(char *title)
+{
+ UI_CALL(set_title, title);
+ UI_CALL(flush);
+}
+
+void ui_set_icon(char *icon)
+{
+ UI_CALL(set_icon, icon);
+ UI_CALL(flush);
+}
+
/*
* Try to get the current Vim shell size. Put the result in Rows and Columns.
* Use the new sizes as defaults for 'columns' and 'lines'.
@@ -165,8 +189,31 @@ void ui_cursor_shape(void)
}
}
-void ui_resize(int width, int height)
+void ui_refresh(void)
{
+ if (!ui_count) {
+ return;
+ }
+
+ int width = INT_MAX, height = INT_MAX;
+
+ for (size_t i = 0; i < ui_count; i++) {
+ UI *ui = uis[i];
+ width = ui->width < width ? ui->width : width;
+ height = ui->height < height ? ui->height : height;
+ }
+
+ screen_resize(width, height, true);
+}
+
+void ui_resize(int new_width, int new_height)
+{
+ width = new_width;
+ height = new_height;
+
+ UI_CALL(update_fg, (ui->rgb ? normal_fg : cterm_normal_fg_color - 1));
+ UI_CALL(update_bg, (ui->rgb ? normal_bg : cterm_normal_bg_color - 1));
+
sr.top = 0;
sr.bot = height - 1;
sr.left = 0;
@@ -240,7 +287,7 @@ void ui_attach(UI *ui)
}
uis[ui_count++] = ui;
- resized(ui);
+ ui_refresh();
}
void ui_detach(UI *ui)
@@ -267,17 +314,8 @@ void ui_detach(UI *ui)
ui_count--;
- if (ui->width == width || ui->height == height) {
- // It is possible that the UI being detached had the smallest screen,
- // so check for the new minimum dimensions
- width = height = INT_MAX;
- for (size_t i = 0; i < ui_count; i++) {
- check_dimensions(uis[i]);
- }
- }
-
if (ui_count) {
- screen_resize(width, height, true);
+ ui_refresh();
}
}
@@ -295,8 +333,7 @@ static void highlight_start(int mask)
return;
}
- set_highlight_args(current_highlight_mask, &current_attrs);
- UI_CALL(highlight_set, current_attrs);
+ set_highlight_args(current_highlight_mask);
}
static void highlight_stop(int mask)
@@ -309,12 +346,12 @@ static void highlight_stop(int mask)
current_highlight_mask &= ~mask;
}
- set_highlight_args(current_highlight_mask, &current_attrs);
- UI_CALL(highlight_set, current_attrs);
+ set_highlight_args(current_highlight_mask);
}
-static void set_highlight_args(int mask, HlAttrs *attrs)
+static void set_highlight_args(int mask)
{
+ HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 };
attrentry_T *aep = NULL;
if (mask > HL_ALL) {
@@ -322,18 +359,40 @@ static void set_highlight_args(int mask, HlAttrs *attrs)
mask = aep ? aep->ae_attr : 0;
}
- attrs->bold = mask & HL_BOLD;
- attrs->standout = mask & HL_STANDOUT;
- attrs->underline = mask & HL_UNDERLINE;
- attrs->undercurl = mask & HL_UNDERCURL;
- attrs->italic = mask & HL_ITALIC;
- attrs->reverse = mask & HL_INVERSE;
- attrs->foreground = aep && aep->fg_color >= 0 ? aep->fg_color : normal_fg;
- attrs->background = aep && aep->bg_color >= 0 ? aep->bg_color : normal_bg;
+ rgb_attrs.bold = mask & HL_BOLD;
+ rgb_attrs.underline = mask & HL_UNDERLINE;
+ rgb_attrs.undercurl = mask & HL_UNDERCURL;
+ rgb_attrs.italic = mask & HL_ITALIC;
+ rgb_attrs.reverse = mask & (HL_INVERSE | HL_STANDOUT);
+ HlAttrs cterm_attrs = rgb_attrs;
+
+ if (aep) {
+ if (aep->fg_color != normal_fg) {
+ rgb_attrs.foreground = aep->fg_color;
+ }
+
+ if (aep->bg_color != normal_bg) {
+ rgb_attrs.background = aep->bg_color;
+ }
+
+ if (cterm_normal_fg_color != aep->ae_u.cterm.fg_color) {
+ cterm_attrs.foreground = aep->ae_u.cterm.fg_color - 1;
+ }
+
+ if (cterm_normal_bg_color != aep->ae_u.cterm.bg_color) {
+ cterm_attrs.background = aep->ae_u.cterm.bg_color - 1;
+ }
+ }
+
+ UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs));
}
static void parse_abstract_ui_codes(uint8_t *ptr, int len)
{
+ if (!ui_count) {
+ return;
+ }
+
int arg1 = 0, arg2 = 0;
uint8_t *end = ptr + len, *p, c;
bool update_cursor = false;
@@ -444,6 +503,9 @@ static void parse_abstract_ui_codes(uint8_t *ptr, int len)
UI_CALL(put, NULL, 0);
col++;
}
+ if (col >= width) {
+ ui_linefeed();
+ }
p += clen;
}
ptr = p;
@@ -457,25 +519,6 @@ static void parse_abstract_ui_codes(uint8_t *ptr, int len)
UI_CALL(flush);
}
-static void resized(UI *ui)
-{
- check_dimensions(ui);
- screen_resize(width, height, true);
-}
-
-static void check_dimensions(UI *ui)
-{
- // The internal screen dimensions are always the minimum required to fit on
- // all connected screens
- if (ui->width < width) {
- width = ui->width;
- }
-
- if (ui->height < height) {
- height = ui->height;
- }
-}
-
static void ui_linefeed(void)
{
int new_col = 0;
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index d0933055cc..099f2643d5 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -6,13 +6,14 @@
#include <stdint.h>
typedef struct {
- bool bold, standout, underline, undercurl, italic, reverse;
+ bool bold, underline, undercurl, italic, reverse;
int foreground, background;
} HlAttrs;
typedef struct ui_t UI;
struct ui_t {
+ bool rgb;
int width, height;
void *data;
void (*resize)(UI *ui, int rows, int columns);
@@ -32,7 +33,11 @@ struct ui_t {
void (*bell)(UI *ui);
void (*visual_bell)(UI *ui);
void (*flush)(UI *ui);
+ void (*update_fg)(UI *ui, int fg);
+ void (*update_bg)(UI *ui, int bg);
void (*suspend)(UI *ui);
+ void (*set_title)(UI *ui, char *title);
+ void (*set_icon)(UI *ui, char *icon);
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 59920cfbe1..4d84c69158 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -128,7 +128,7 @@ static int undo_undoes = FALSE;
static int lastmark = 0;
-#if defined(U_DEBUG) || defined(PROTO)
+#if defined(U_DEBUG)
/*
* Check the undo structures for being valid. Print a warning when something
* looks wrong.
diff --git a/src/nvim/window.c b/src/nvim/window.c
index f9190e6915..cf0977e280 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2060,7 +2060,7 @@ win_free_mem (
return wp;
}
-#if defined(EXITFREE) || defined(PROTO)
+#if defined(EXITFREE)
void win_free_all(void)
{
int dummy;
diff --git a/test/functional/legacy/066_visual_block_tab_spec.lua b/test/functional/legacy/066_visual_block_tab_spec.lua
index cd283e6746..82bb988c67 100644
--- a/test/functional/legacy/066_visual_block_tab_spec.lua
+++ b/test/functional/legacy/066_visual_block_tab_spec.lua
@@ -23,18 +23,18 @@ describe('visual block shift and tab characters', function()
abcdefghijklmnopqrstuvwxyz]])
feed('gg')
- feed([[fe<C-v>4jR<esc>ugvr1:'<,'>yank A<cr>]])
+ feed([[fe<C-v>4jR<esc>ugvr1:'<lt>,'>yank A<cr>]])
execute('/^abcdefgh')
- feed('<C-v>4jI <esc>j<<11|D')
+ feed('<C-v>4jI <esc>j<lt><lt>11|D')
feed('j7|a <esc>')
feed('j7|a <esc>')
- feed('j7|a <esc>4k13|<C-v>4j<')
+ feed('j7|a <esc>4k13|<C-v>4j<lt>')
execute('$-5,$yank A')
execute([[$-4,$s/\s\+//g]])
- feed('<C-v>4kI <esc>j<<')
+ feed('<C-v>4kI <esc>j<lt><lt>')
feed('j7|a <esc>')
feed('j7|a <esc>')
- feed('j7|a <esc>4k13|<C-v>4j3<')
+ feed('j7|a <esc>4k13|<C-v>4j3<lt>')
execute('$-4,$yank A')
-- Put @a and clean empty lines
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 3c55c09f95..701297cc15 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -1,7 +1,30 @@
local helpers = require('test.functional.helpers')
local Screen = require('test.functional.ui.screen')
local clear, feed, nvim = helpers.clear, helpers.feed, helpers.nvim
-local execute = helpers.execute
+local execute, request, eq = helpers.execute, helpers.request, helpers.eq
+
+
+describe('color scheme compatibility', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('t_Co is set to 256 by default', function()
+ eq('256', request('vim_eval', '&t_Co'))
+ request('vim_set_option', 't_Co', '88')
+ eq('88', request('vim_eval', '&t_Co'))
+ end)
+
+ it('emulates gui_running when a rgb UI is attached', function()
+ eq(0, request('vim_eval', 'has("gui_running")'))
+ local screen = Screen.new()
+ screen:attach()
+ eq(1, request('vim_eval', 'has("gui_running")'))
+ screen:detach()
+ eq(0, request('vim_eval', 'has("gui_running")'))
+ end)
+end)
+
describe('Default highlight groups', function()
-- Test the default attributes for highlight groups shown by the :highlight
@@ -24,7 +47,6 @@ describe('Default highlight groups', function()
after_each(function()
screen:detach()
end)
-
it('window status bar', function()
screen:set_default_attr_ids({
[1] = {reverse = true, bold = true}, -- StatusLine
@@ -142,7 +164,6 @@ describe('Default highlight groups', function()
end)
it('end of file markers', function()
- nvim('command', 'hi Normal guibg=black')
screen:expect([[
^ |
{1:~ }|
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index 507b5aacae..653d8ad92c 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')
local Screen = require('test.functional.ui.screen')
local clear, feed, nvim = helpers.clear, helpers.feed, helpers.nvim
+local insert, execute = helpers.insert, helpers.execute
describe('Mouse input', function()
local screen, hlgroup_colors
@@ -154,4 +155,87 @@ describe('Mouse input', function()
]])
feed('<cr>')
end)
+
+ it('mouse whell will target the hovered window', function()
+ feed('ggdG')
+ insert([[
+ Inserting
+ text
+ with
+ many
+ lines
+ to
+ test
+ mouse scrolling
+ ]])
+ screen:try_resize(53, 14)
+ execute('sp', 'vsp')
+ screen:expect([[
+ lines |lines |
+ to |to |
+ test |test |
+ mouse scrolling |mouse scrolling |
+ ^ | |
+ ~ |~ |
+ [No Name] [+] [No Name] [+] |
+ to |
+ test |
+ mouse scrolling |
+ |
+ ~ |
+ [No Name] [+] |
+ :vsp |
+ ]])
+ feed('<MouseUp><0,0>')
+ screen:expect([[
+ mouse scrolling |lines |
+ ^ |to |
+ ~ |test |
+ ~ |mouse scrolling |
+ ~ | |
+ ~ |~ |
+ [No Name] [+] [No Name] [+] |
+ to |
+ test |
+ mouse scrolling |
+ |
+ ~ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('<MouseDown><27,0>')
+ screen:expect([[
+ mouse scrolling |text |
+ ^ |with |
+ ~ |many |
+ ~ |lines |
+ ~ |to |
+ ~ |test |
+ [No Name] [+] [No Name] [+] |
+ to |
+ test |
+ mouse scrolling |
+ |
+ ~ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('<MouseDown><27,7><MouseDown>')
+ screen:expect([[
+ mouse scrolling |text |
+ ^ |with |
+ ~ |many |
+ ~ |lines |
+ ~ |to |
+ ~ |test |
+ [No Name] [+] [No Name] [+] |
+ Inserting |
+ text |
+ with |
+ many |
+ lines |
+ [No Name] [+] |
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 8e7d1ed798..105e43843c 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -83,6 +83,21 @@ local eq, dedent = helpers.eq, helpers.dedent
local Screen = {}
Screen.__index = Screen
+local debug_screen
+
+
+function Screen.debug(command)
+ if not command then
+ command = 'pynvim -n -g -c '
+ end
+ command = command .. request('vim_eval', '$NVIM_LISTEN_ADDRESS')
+ if debug_screen then
+ debug_screen:close()
+ end
+ debug_screen = io.popen(command, 'r')
+ debug_screen:read()
+end
+
function Screen.new(width, height)
if not width then
width = 53
@@ -90,24 +105,22 @@ function Screen.new(width, height)
if not height then
height = 14
end
- return setmetatable({
+ local self = setmetatable({
+ title = '',
+ icon = '',
+ bell = false,
+ visual_bell = false,
+ suspended = false,
_default_attr_ids = nil,
- _width = width,
- _height = height,
- _rows = new_cell_grid(width, height),
_mode = 'normal',
_mouse_enabled = true,
- _bell = false,
- _visual_bell = false,
- _suspended = true,
_attrs = {},
_cursor = {
enabled = true, row = 1, col = 1
- },
- _scroll_region = {
- top = 1, bot = height, left = 1, right = width
}
}, Screen)
+ self:_handle_resize(width, height)
+ return self
end
function Screen:set_default_attr_ids(attr_ids)
@@ -115,13 +128,15 @@ function Screen:set_default_attr_ids(attr_ids)
end
function Screen:attach()
- request('attach_ui', self._width, self._height)
- self._suspended = false
+ request('ui_attach', self._width, self._height, true)
end
function Screen:detach()
- request('detach_ui')
- self._suspended = true
+ request('ui_detach')
+end
+
+function Screen:try_resize(columns, rows)
+ request('ui_try_resize', columns, rows)
end
function Screen:expect(expected, attr_ids)
@@ -134,7 +149,7 @@ function Screen:expect(expected, attr_ids)
table.insert(expected_rows, row)
end
local ids = attr_ids or self._default_attr_ids
- self:_wait(function()
+ self:wait(function()
for i = 1, self._height do
local expected_row = expected_rows[i]
local actual_row = self:_row_repr(self._rows[i], ids)
@@ -146,7 +161,7 @@ function Screen:expect(expected, attr_ids)
end)
end
-function Screen:_wait(check, timeout)
+function Screen:wait(check, timeout)
local err, checked = false
local function notification_cb(method, args)
assert(method == 'redraw')
@@ -181,16 +196,30 @@ function Screen:_redraw(updates)
end
function Screen:_handle_resize(width, height)
- self._rows = new_cell_grid(width, height)
+ local rows = {}
+ for i = 1, height do
+ local cols = {}
+ for j = 1, width do
+ table.insert(cols, {text = ' ', attrs = {}})
+ end
+ table.insert(rows, cols)
+ end
+ self._rows = rows
+ self._width = width
+ self._height = height
+ self._scroll_region = {
+ top = 1, bot = height, left = 1, right = width
+ }
end
function Screen:_handle_clear()
- self:_clear_block(1, self._height, 1, self._width)
+ self:_clear_block(self._scroll_region.top, self._scroll_region.bot,
+ self._scroll_region.left, self._scroll_region.right)
end
function Screen:_handle_eol_clear()
local row, col = self._cursor.row, self._cursor.col
- self:_clear_block(row, 1, col, self._width - col)
+ self:_clear_block(row, 1, col, self._scroll_region.right - col)
end
function Screen:_handle_cursor_goto(row, col)
@@ -250,11 +279,14 @@ function Screen:_handle_scroll(count)
for i = start, stop, step do
local target = self._rows[i]
local source = self._rows[i + count]
- self:_copy_row_section(target, source, left, right)
+ for j = left, right do
+ target[j].text = source[j].text
+ target[j].attrs = source[j].attrs
+ end
end
-- clear invalid rows
- for i = stop + 1, stop + count, step do
+ for i = stop + step, stop + count, step do
self:_clear_row_section(i, left, right)
end
end
@@ -271,15 +303,31 @@ function Screen:_handle_put(str)
end
function Screen:_handle_bell()
- self._bell = true
+ self.bell = true
end
function Screen:_handle_visual_bell()
- self._visual_bell = true
+ self.visual_bell = true
+end
+
+function Screen:_handle_update_fg(fg)
+ self._fg = fg
+end
+
+function Screen:_handle_update_bg(bg)
+ self._bg = bg
end
function Screen:_handle_suspend()
- self._suspended = true
+ self.suspended = true
+end
+
+function Screen:_handle_set_title(title)
+ self.title = title
+end
+
+function Screen:_handle_set_icon(icon)
+ self.icon = icon
end
function Screen:_clear_block(top, lines, left, columns)
@@ -296,13 +344,6 @@ function Screen:_clear_row_section(rownum, startcol, stopcol)
end
end
-function Screen:_copy_row_section(target, source, startcol, stopcol)
- for i = startcol, stopcol do
- target[i].text = source[i].text
- target[i].attrs = source[i].attrs
- end
-end
-
function Screen:_row_repr(row, attr_ids)
local rv = {}
local current_attr_id
@@ -353,18 +394,6 @@ function backward_find_meaningful(tbl, from)
return from
end
-function new_cell_grid(width, height)
- local rows = {}
- for i = 1, height do
- local cols = {}
- for j = 1, width do
- table.insert(cols, {text = ' ', attrs = {}})
- end
- table.insert(rows, cols)
- end
- return rows
-end
-
function get_attr_id(attr_ids, attrs)
if not attr_ids then
return
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index a1110b3231..4ee6c43528 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -16,6 +16,69 @@ describe('Screen', function()
screen:detach()
end)
+ describe(':suspend', function()
+ it('is forwarded to the UI', function()
+ local function check()
+ if not screen.suspended then
+ return 'Screen was not suspended'
+ end
+ end
+ execute('suspend')
+ screen:wait(check)
+ screen.suspended = false
+ feed('<c-z>')
+ screen:wait(check)
+ end)
+ end)
+
+ describe('bell/visual bell', function()
+ it('is forwarded to the UI', function()
+ feed('<left>')
+ screen:wait(function()
+ if not screen.bell or screen.visual_bell then
+ return 'Bell was not sent'
+ end
+ end)
+ screen.bell = false
+ execute('set visualbell')
+ feed('<left>')
+ screen:wait(function()
+ if not screen.visual_bell or screen.bell then
+ return 'Visual bell was not sent'
+ end
+ end)
+ end)
+ end)
+
+ describe(':set title', function()
+ it('is forwarded to the UI', function()
+ local expected = 'test-title'
+ execute('set titlestring='..expected)
+ execute('set title')
+ screen:wait(function()
+ local actual = screen.title
+ if actual ~= expected then
+ return 'Expected title to be "'..expected..'" but was "'..actual..'"'
+ end
+ end)
+ end)
+ end)
+
+ describe(':set icon', function()
+ it('is forwarded to the UI', function()
+ local expected = 'test-icon'
+ execute('set iconstring='..expected)
+ execute('set icon')
+ screen:wait(function()
+ local actual = screen.icon
+ if actual ~= expected then
+ return 'Expected title to be "'..expected..'" but was "'..actual..'"'
+ end
+ end)
+ end)
+ end)
+
+
describe('window', function()
describe('split', function()
it('horizontal', function()
@@ -95,6 +158,8 @@ describe('Screen', function()
|
]])
end)
+
+
end)
end)
@@ -221,4 +286,193 @@ describe('Screen', function()
feed('<cr>') -- skip the "Press ENTER..." state or tests will hang
end)
end)
+
+ describe('scrolling and clearing', function()
+ before_each(function()
+ insert([[
+ Inserting
+ text
+ with
+ many
+ lines
+ to
+ test
+ scrolling
+ and
+ clearing
+ in
+ split
+ windows
+ ]])
+ execute('sp', 'vsp', 'vsp')
+ screen:expect([[
+ and |and |and |
+ clearing |clearing |clearing |
+ in |in |in |
+ split |split |split |
+ windows |windows |windows |
+ ^ | | |
+ [No Name] [+] [No Name] [+] [No Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ end)
+
+ it('only affects the current scroll region', function()
+ feed('6k')
+ screen:expect([[
+ ^crolling |and |and |
+ and |clearing |clearing |
+ clearing |in |in |
+ in |split |split |
+ split |windows |windows |
+ windows | | |
+ [No Name] [+] [No Name] [+] [No Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('<c-w>l')
+ screen:expect([[
+ scrolling |and |and |
+ and |clearing |clearing |
+ clearing |in |in |
+ in |split |split |
+ split |windows |windows |
+ windows |^ | |
+ [No Name] [+] [No Name] [+] <Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('gg')
+ screen:expect([[
+ scrolling |^nserting |and |
+ and |text |clearing |
+ clearing |with |in |
+ in |many |split |
+ split |lines |windows |
+ windows |to | |
+ [No Name] [+] [No Name] [+] <Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('7j')
+ screen:expect([[
+ scrolling |with |and |
+ and |many |clearing |
+ clearing |lines |in |
+ in |to |split |
+ split |test |windows |
+ windows |^crolling | |
+ [No Name] [+] [No Name] [+] <Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('2j')
+ screen:expect([[
+ scrolling |lines |and |
+ and |to |clearing |
+ clearing |test |in |
+ in |scrolling |split |
+ split |and |windows |
+ windows |^learing | |
+ [No Name] [+] [No Name] [+] <Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('5k')
+ screen:expect([[
+ scrolling |^ines |and |
+ and |to |clearing |
+ clearing |test |in |
+ in |scrolling |split |
+ split |and |windows |
+ windows |clearing | |
+ [No Name] [+] [No Name] [+] <Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ feed('k')
+ screen:expect([[
+ scrolling |^any |and |
+ and |lines |clearing |
+ clearing |to |in |
+ in |test |split |
+ split |scrolling |windows |
+ windows |and | |
+ [No Name] [+] [No Name] [+] <Name] [+] |
+ clearing |
+ in |
+ split |
+ windows |
+ |
+ [No Name] [+] |
+ |
+ ]])
+ end)
+ end)
+
+ describe('resize', function()
+ before_each(function()
+ screen:try_resize(25, 5)
+ feed('iresize')
+ end)
+
+ it('rebuilds the whole screen', function()
+ screen:expect([[
+ resize^ |
+ ~ |
+ ~ |
+ ~ |
+ -- INSERT -- |
+ ]])
+ end)
+
+ it('has minimum width/height values', function()
+ screen:try_resize(1, 1)
+ screen:expect([[
+ -- INS^RT --|
+ |
+ ]])
+ feed('<esc>:ls')
+ screen:expect([[
+ resize |
+ :ls^ |
+ ]])
+ end)
+ end)
end)
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index debad7bf85..7c5906931d 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -73,9 +73,9 @@ set(LIBTERMKEY_URL https://github.com/neovim/libtermkey/archive/7b3bdafdf589d084
set(LIBTERMKEY_SHA1 28bfe54dfd9269910a132b51dee7725a2121578d)
set(LIBTERMKEY_MD5 f0bac9c2467cc80c821be937ea5c13bc)
-set(LIBTICKIT_URL https://github.com/neovim/libtickit/archive/0430ba2f43fdf1c31bca66def52a2537c581ade5.tar.gz)
-set(LIBTICKIT_SHA1 732b145a4dab06e6f1b40a352424f808730726bf)
-set(LIBTICKIT_MD5 3fcb635e572851472fc5009709d980fe)
+set(LIBTICKIT_URL https://github.com/neovim/libtickit/archive/33f4afb3891df05955429acbf5b406dfe87ec22b.tar.gz)
+set(LIBTICKIT_SHA1 3aab459b9fb3cd83e85ac2e08f05e5f162c8c9d2)
+set(LIBTICKIT_MD5 19ee9271c16716620d0906db74158ec6)
if(USE_BUNDLED_LIBUNIBILIUM)
ExternalProject_Add(libunibilium