mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
Merge remote-tracking branch 'vim/master'
This commit is contained in:
@@ -3034,6 +3034,8 @@ test_feedinput({string}) none add key sequence to input buffer
|
||||
test_garbagecollect_now() none free memory right now for testing
|
||||
test_garbagecollect_soon() none free memory soon for testing
|
||||
test_getvalue({string}) any get value of an internal variable
|
||||
test_gui_mouse_event({button}, {row}, {col}, {repeated}, {mods})
|
||||
none add a mouse event to the input buffer
|
||||
test_ignore_error({expr}) none ignore a specific error
|
||||
test_null_blob() Blob null value for testing
|
||||
test_null_channel() Channel null value for testing
|
||||
@@ -5853,7 +5855,10 @@ getqflist([{what}]) *getqflist()*
|
||||
bufname() to get the name
|
||||
module module name
|
||||
lnum line number in the buffer (first line is 1)
|
||||
end_lnum
|
||||
end of line number if the item is multiline
|
||||
col column number (first column is 1)
|
||||
end_col end of column number if the item has range
|
||||
vcol |TRUE|: "col" is visual column
|
||||
|FALSE|: "col" is byte index
|
||||
nr error number
|
||||
@@ -11983,6 +11988,7 @@ scrollbind Compiled with 'scrollbind' support. (always true)
|
||||
showcmd Compiled with 'showcmd' support.
|
||||
signs Compiled with |:sign| support.
|
||||
smartindent Compiled with 'smartindent' support.
|
||||
sodium Compiled with libsodium for better crypt support
|
||||
sound Compiled with sound support, e.g. `sound_playevent()`
|
||||
spell Compiled with spell checking support |spell|.
|
||||
startuptime Compiled with |--startuptime| support.
|
||||
|
||||
@@ -2399,6 +2399,23 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
you write the file the encrypted bytes will be
|
||||
different. The whole undo file is encrypted, not just
|
||||
the pieces of text.
|
||||
*E1193* *E1194* *E1195* *E1196*
|
||||
*E1197* *E1198* *E1199* *E1200* *E1201*
|
||||
xchacha20 XChaCha20 Cipher with Poly1305 Message Authentication
|
||||
Code. Medium strong till strong encryption.
|
||||
Encryption is provided by the libsodium library, it
|
||||
requires Vim to be built with |+sodium|
|
||||
It adds a seed and a message authentication code (MAC)
|
||||
to the file. This needs at least a Vim 8.2.3022 to
|
||||
read the encrypted file.
|
||||
Encryption of swap files is not supported, therefore
|
||||
no swap file will be used when xchacha20 encryption is
|
||||
enabled.
|
||||
Encryption of undo files is not yet supported,
|
||||
therefore no undo file will currently be written.
|
||||
CURRENTLY EXPERIMENTAL: Files written with this method
|
||||
might have to be read back with the same version of
|
||||
Vim if the binary format changes later.
|
||||
|
||||
You should use "blowfish2", also to re-encrypt older files.
|
||||
|
||||
|
||||
+25
-1
@@ -1,4 +1,4 @@
|
||||
*testing.txt* For Vim version 8.2. Last change: 2021 Apr 02
|
||||
*testing.txt* For Vim version 8.2. Last change: 2021 Jun 21
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -78,6 +78,30 @@ test_getvalue({name}) *test_getvalue()*
|
||||
|
||||
Can also be used as a |method|: >
|
||||
GetName()->test_getvalue()
|
||||
<
|
||||
*test_gui_mouse_event()*
|
||||
test_gui_mouse_event({button}, {row}, {col}, {multiclick}, {modifiers})
|
||||
Inject a mouse button click event. This function works only
|
||||
when GUI is running.
|
||||
The supported values for {button} are:
|
||||
0 right mouse button
|
||||
1 middle mouse button
|
||||
2 left mouse button
|
||||
3 mouse button release
|
||||
4 scroll wheel down
|
||||
5 scroll wheel up
|
||||
6 scroll wheel left
|
||||
7 scroll wheel right
|
||||
{row} and {col} specify the location of the mouse click.
|
||||
To inject a multiclick event, set {multiclick} to 1.
|
||||
The supported values for {modifiers} are:
|
||||
4 shift is pressed
|
||||
8 alt is pressed
|
||||
16 ctrl is pressed
|
||||
After injecting the mouse event you probably should call
|
||||
|feedkeys()| to have them processed, e.g.: >
|
||||
call feedkeys("y", 'Lx!')
|
||||
|
||||
|
||||
test_ignore_error({expr}) *test_ignore_error()*
|
||||
Ignore any error containing {expr}. A normal message is given
|
||||
|
||||
@@ -1021,6 +1021,7 @@ Testing: *test-functions*
|
||||
test_garbagecollect_now() free memory right now
|
||||
test_garbagecollect_soon() set a flag to free memory soon
|
||||
test_getvalue() get value of an internal variable
|
||||
test_gui_mouse_event() add a GUI mouse event to the input buffer
|
||||
test_ignore_error() ignore a specific error message
|
||||
test_null_blob() return a null Blob
|
||||
test_null_channel() return a null Channel
|
||||
|
||||
@@ -446,6 +446,7 @@ m *+ruby/dyn* Ruby interface |ruby-dynamic| |/dyn|
|
||||
T *+scrollbind* |'scrollbind'|
|
||||
B *+signs* |:sign|
|
||||
N *+smartindent* |'smartindent'|
|
||||
B *+sodium* compiled with libsodium for better encryption support
|
||||
B *+sound* |sound_playevent()|, |sound_playfile()| functions, etc.
|
||||
N *+spell* spell checking support, see |spell|
|
||||
N *+startuptime* |--startuptime| argument
|
||||
|
||||
@@ -322,6 +322,9 @@ MSYS2 has its own git package, and you can also install it via pacman:
|
||||
|
||||
$ pacman -S git
|
||||
|
||||
For enabling libsodium support, you also need to install the package
|
||||
|
||||
$ pacman -S mingw-w64-x86_64-libsodium
|
||||
|
||||
2.3. Keep the build environment up-to-date
|
||||
|
||||
|
||||
+13
-2
@@ -41,6 +41,9 @@ DEBUG=no
|
||||
# set to yes to measure code coverage
|
||||
COVERAGE=no
|
||||
|
||||
# better encryption support using libsodium
|
||||
#SODIUM=yes
|
||||
|
||||
# set to SIZE for size, SPEED for speed, MAXSPEED for maximum optimization
|
||||
OPTIMIZE=MAXSPEED
|
||||
|
||||
@@ -517,6 +520,10 @@ CXXFLAGS = -std=gnu++11
|
||||
WINDRES_FLAGS =
|
||||
EXTRA_LIBS =
|
||||
|
||||
ifdef SODIUM
|
||||
DEFINES += -DHAVE_SODIUM
|
||||
endif
|
||||
|
||||
ifdef GETTEXT
|
||||
DEFINES += -DHAVE_GETTEXT -DHAVE_LOCALE_H
|
||||
GETTEXTINCLUDE = $(GETTEXT)/include
|
||||
@@ -660,6 +667,10 @@ DEFINES += -DFEAT_DIRECTX_COLOR_EMOJI
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(SODIUM),yes)
|
||||
SODIUMLIB = -lsodium
|
||||
endif
|
||||
|
||||
# Only allow XPM for a GUI build.
|
||||
ifeq (yes, $(GUI))
|
||||
|
||||
@@ -1064,7 +1075,7 @@ $(EXEOBJC): | $(OUTDIR)
|
||||
|
||||
ifeq ($(VIMDLL),yes)
|
||||
$(TARGET): $(OBJ)
|
||||
$(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid -lgdi32 $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB)
|
||||
$(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid -lgdi32 $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB) $(SODIUMLIB)
|
||||
|
||||
$(GVIMEXE): $(EXEOBJG) $(VIMDLLBASE).dll
|
||||
$(CC) -L. $(EXELFLAGS) -mwindows -o $@ $(EXEOBJG) -l$(VIMDLLBASE)
|
||||
@@ -1073,7 +1084,7 @@ $(VIMEXE): $(EXEOBJC) $(VIMDLLBASE).dll
|
||||
$(CC) -L. $(EXELFLAGS) -o $@ $(EXEOBJC) -l$(VIMDLLBASE)
|
||||
else
|
||||
$(TARGET): $(OBJ)
|
||||
$(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB)
|
||||
$(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB) $(SODIUMLIB)
|
||||
endif
|
||||
|
||||
upx: exes
|
||||
|
||||
+29
-2
@@ -41,6 +41,13 @@
|
||||
#
|
||||
# Sound support: SOUND=yes (default is yes)
|
||||
#
|
||||
# Sodium support: SODIUM=[Path to Sodium directory]
|
||||
# Dynamic built with libsodium
|
||||
# You need to install the msvc package from
|
||||
# https://download.libsodium.org/libsodium/releases/
|
||||
# and package the libsodium.dll with Vim
|
||||
#
|
||||
#
|
||||
# DLL support (EXPERIMENTAL): VIMDLL=yes (default is no)
|
||||
# Creates vim{32,64}.dll, and stub gvim.exe and vim.exe.
|
||||
# The shared codes between the GUI and the console are built into
|
||||
@@ -372,6 +379,26 @@ SOUND = no
|
||||
! endif
|
||||
!endif
|
||||
|
||||
!ifndef SODIUM
|
||||
SODIUM = no
|
||||
!endif
|
||||
|
||||
!if "$(SODIUM)" != "no"
|
||||
! if "$(CPU)" == "AMD64"
|
||||
SOD_LIB = $(SODIUM)\x64\Release\v140\dynamic
|
||||
! elseif "$(CPU)" == "i386"
|
||||
SOD_LIB = $(SODIUM)\Win32\Release\v140\dynamic
|
||||
! else
|
||||
SODIUM = no
|
||||
! endif
|
||||
!endif
|
||||
|
||||
!if "$(SODIUM)" != "no"
|
||||
SOD_INC = /I "$(SODIUM)\include"
|
||||
SOD_DEFS = -DFEAT_SODIUM
|
||||
SOD_LIB = $(SOD_LIB)\libsodium.lib
|
||||
!endif
|
||||
|
||||
!ifndef NETBEANS
|
||||
NETBEANS = $(GUI)
|
||||
!endif
|
||||
@@ -491,7 +518,7 @@ CON_LIB = $(CON_LIB) /DELAYLOAD:comdlg32.dll /DELAYLOAD:ole32.dll DelayImp.lib
|
||||
|
||||
CFLAGS = -c /W3 /GF /nologo $(CVARS) -I. -Iproto -DHAVE_PATHDEF -DWIN32 \
|
||||
$(CSCOPE_DEFS) $(TERM_DEFS) $(SOUND_DEFS) $(NETBEANS_DEFS) $(CHANNEL_DEFS) \
|
||||
$(NBDEBUG_DEFS) $(XPM_DEFS) \
|
||||
$(NBDEBUG_DEFS) $(XPM_DEFS) $(SOD_DEFS) $(SOD_INC) \
|
||||
$(DEFINES) -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER)
|
||||
|
||||
#>>>>> end of choices
|
||||
@@ -1282,7 +1309,7 @@ conflags = $(conflags) /map /mapinfo:lines
|
||||
LINKARGS1 = $(linkdebug) $(conflags)
|
||||
LINKARGS2 = $(CON_LIB) $(GUI_LIB) $(NODEFAULTLIB) $(LIBC) $(OLE_LIB) user32.lib \
|
||||
$(LUA_LIB) $(MZSCHEME_LIB) $(PERL_LIB) $(PYTHON_LIB) $(PYTHON3_LIB) $(RUBY_LIB) \
|
||||
$(TCL_LIB) $(SOUND_LIB) $(NETBEANS_LIB) $(XPM_LIB) $(LINK_PDB)
|
||||
$(TCL_LIB) $(SOUND_LIB) $(NETBEANS_LIB) $(XPM_LIB) $(SOD_LIB) $(LINK_PDB)
|
||||
|
||||
# Report link time code generation progress if used.
|
||||
!ifdef NODEBUG
|
||||
|
||||
Vendored
+66
@@ -844,6 +844,7 @@ with_motif_lib
|
||||
with_tlib
|
||||
enable_largefile
|
||||
enable_canberra
|
||||
enable_libsodium
|
||||
enable_acl
|
||||
enable_gpm
|
||||
enable_sysmouse
|
||||
@@ -1510,6 +1511,7 @@ Optional Features:
|
||||
--disable-desktop-database-update update disabled
|
||||
--disable-largefile omit support for large files
|
||||
--disable-canberra Do not use libcanberra.
|
||||
--disable-libsodium Do not use libsodium.
|
||||
--disable-acl No check for ACL support.
|
||||
--disable-gpm Don't use gpm (Linux mouse daemon).
|
||||
--disable-sysmouse Don't use sysmouse (mouse in *BSD console).
|
||||
@@ -13235,6 +13237,70 @@ rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-libsodium argument" >&5
|
||||
$as_echo_n "checking --enable-libsodium argument... " >&6; }
|
||||
# Check whether --enable-libsodium was given.
|
||||
if test "${enable_libsodium+set}" = set; then :
|
||||
enableval=$enable_libsodium;
|
||||
else
|
||||
enable_libsodium="maybe"
|
||||
fi
|
||||
|
||||
|
||||
if test "$enable_libsodium" = "maybe"; then
|
||||
if test "$features" = "big" -o "$features" = "huge"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Defaulting to yes" >&5
|
||||
$as_echo "Defaulting to yes" >&6; }
|
||||
enable_libsodium="yes"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Defaulting to no" >&5
|
||||
$as_echo "Defaulting to no" >&6; }
|
||||
enable_libsodium="no"
|
||||
fi
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_libsodium" >&5
|
||||
$as_echo "$enable_libsodium" >&6; }
|
||||
fi
|
||||
if test "$enable_libsodium" = "yes"; then
|
||||
if test "x$PKG_CONFIG" != "xno"; then
|
||||
libsodium_lib=`$PKG_CONFIG --libs libsodium 2>/dev/null`
|
||||
libsodium_cflags=`$PKG_CONFIG --cflags libsodium 2>/dev/null`
|
||||
fi
|
||||
if test "x$libsodium_lib" = "x"; then
|
||||
libsodium_lib=-lsodium
|
||||
libsodium_cflags=
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcanberra" >&5
|
||||
$as_echo_n "checking for libcanberra... " >&6; }
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $libsodium_cflags"
|
||||
LIBS="$LIBS $libsodium_lib"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
# include <sodium.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
printf("%d", sodium_init());
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }; $as_echo "#define HAVE_SODIUM 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no; try installing libsodium-dev" >&5
|
||||
$as_echo "no; try installing libsodium-dev" >&6; }; CFLAGS="$ac_save_CFLAGS"; LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for st_blksize" >&5
|
||||
$as_echo_n "checking for st_blksize... " >&6; }
|
||||
|
||||
+4
-3
@@ -596,7 +596,8 @@ crypt_blowfish_encode(
|
||||
cryptstate_T *state,
|
||||
char_u *from,
|
||||
size_t len,
|
||||
char_u *to)
|
||||
char_u *to,
|
||||
int last UNUSED)
|
||||
{
|
||||
bf_state_T *bfs = state->method_state;
|
||||
size_t i;
|
||||
@@ -619,7 +620,8 @@ crypt_blowfish_decode(
|
||||
cryptstate_T *state,
|
||||
char_u *from,
|
||||
size_t len,
|
||||
char_u *to)
|
||||
char_u *to,
|
||||
int last UNUSED)
|
||||
{
|
||||
bf_state_T *bfs = state->method_state;
|
||||
size_t i;
|
||||
@@ -680,5 +682,4 @@ blowfish_self_test(void)
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif // FEAT_CRYPT
|
||||
|
||||
+17
-2
@@ -30,6 +30,7 @@ struct bw_info
|
||||
int bw_flags; // FIO_ flags
|
||||
#ifdef FEAT_CRYPT
|
||||
buf_T *bw_buffer; // buffer being written
|
||||
int bw_finish; // finish encrypting
|
||||
#endif
|
||||
char_u bw_rest[CONV_RESTLEN]; // not converted bytes
|
||||
int bw_restlen; // nr of bytes in bw_rest[]
|
||||
@@ -493,14 +494,14 @@ buf_write_bytes(struct bw_info *ip)
|
||||
if (crypt_works_inplace(ip->bw_buffer->b_cryptstate))
|
||||
{
|
||||
# endif
|
||||
crypt_encode_inplace(ip->bw_buffer->b_cryptstate, buf, len);
|
||||
crypt_encode_inplace(ip->bw_buffer->b_cryptstate, buf, len, ip->bw_finish);
|
||||
# ifdef CRYPT_NOT_INPLACE
|
||||
}
|
||||
else
|
||||
{
|
||||
char_u *outbuf;
|
||||
|
||||
len = crypt_encode_alloc(curbuf->b_cryptstate, buf, len, &outbuf);
|
||||
len = crypt_encode_alloc(curbuf->b_cryptstate, buf, len, &outbuf, ip->bw_finish);
|
||||
if (len == 0)
|
||||
return OK; // Crypt layer is buffering, will flush later.
|
||||
wlen = write_eintr(ip->bw_fd, outbuf, len);
|
||||
@@ -724,6 +725,7 @@ buf_write(
|
||||
#endif
|
||||
#ifdef FEAT_CRYPT
|
||||
write_info.bw_buffer = buf;
|
||||
write_info.bw_finish = FALSE;
|
||||
#endif
|
||||
|
||||
// After writing a file changedtick changes but we don't want to display
|
||||
@@ -2015,6 +2017,13 @@ restore_backup:
|
||||
++s;
|
||||
if (++len != bufsize)
|
||||
continue;
|
||||
#ifdef FEAT_CRYPT
|
||||
if (write_info.bw_fd > 0 && lnum == end
|
||||
&& (write_info.bw_flags & FIO_ENCRYPTED)
|
||||
&& *buf->b_p_key != NUL && !filtering
|
||||
&& *ptr == NUL)
|
||||
write_info.bw_finish = TRUE;
|
||||
#endif
|
||||
if (buf_write_bytes(&write_info) == FAIL)
|
||||
{
|
||||
end = 0; // write error: break loop
|
||||
@@ -2118,6 +2127,12 @@ restore_backup:
|
||||
if (len > 0 && end > 0)
|
||||
{
|
||||
write_info.bw_len = len;
|
||||
#ifdef FEAT_CRYPT
|
||||
if (write_info.bw_fd > 0 && lnum >= end
|
||||
&& (write_info.bw_flags & FIO_ENCRYPTED)
|
||||
&& *buf->b_p_key != NUL && !filtering)
|
||||
write_info.bw_finish = TRUE;
|
||||
#endif
|
||||
if (buf_write_bytes(&write_info) == FAIL)
|
||||
end = 0; // write error
|
||||
nchars += len;
|
||||
|
||||
@@ -208,6 +208,7 @@
|
||||
#undef HAVE_STRPTIME
|
||||
#undef HAVE_STRTOL
|
||||
#undef HAVE_CANBERRA
|
||||
#undef HAVE_SODIUM
|
||||
#undef HAVE_ST_BLKSIZE
|
||||
#undef HAVE_SYSCONF
|
||||
#undef HAVE_SYSCTL
|
||||
|
||||
@@ -3952,6 +3952,43 @@ if test "$enable_canberra" = "yes"; then
|
||||
AC_MSG_RESULT(no; try installing libcanberra-dev); CFLAGS="$ac_save_CFLAGS"; LIBS="$ac_save_LIBS")
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(--enable-libsodium argument)
|
||||
AC_ARG_ENABLE(libsodium,
|
||||
[ --disable-libsodium Do not use libsodium.],
|
||||
, [enable_libsodium="maybe"])
|
||||
|
||||
if test "$enable_libsodium" = "maybe"; then
|
||||
if test "$features" = "big" -o "$features" = "huge"; then
|
||||
AC_MSG_RESULT(Defaulting to yes)
|
||||
enable_libsodium="yes"
|
||||
else
|
||||
AC_MSG_RESULT(Defaulting to no)
|
||||
enable_libsodium="no"
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT($enable_libsodium)
|
||||
fi
|
||||
if test "$enable_libsodium" = "yes"; then
|
||||
if test "x$PKG_CONFIG" != "xno"; then
|
||||
libsodium_lib=`$PKG_CONFIG --libs libsodium 2>/dev/null`
|
||||
libsodium_cflags=`$PKG_CONFIG --cflags libsodium 2>/dev/null`
|
||||
fi
|
||||
if test "x$libsodium_lib" = "x"; then
|
||||
libsodium_lib=-lsodium
|
||||
libsodium_cflags=
|
||||
fi
|
||||
AC_MSG_CHECKING(for libcanberra)
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $libsodium_cflags"
|
||||
LIBS="$LIBS $libsodium_lib"
|
||||
AC_TRY_LINK([
|
||||
# include <sodium.h>
|
||||
], [
|
||||
printf("%d", sodium_init()); ],
|
||||
AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SODIUM),
|
||||
AC_MSG_RESULT(no; try installing libsodium-dev); CFLAGS="$ac_save_CFLAGS"; LIBS="$ac_save_LIBS")
|
||||
fi
|
||||
|
||||
dnl fstatfs() can take 2 to 4 arguments, try to use st_blksize if possible
|
||||
AC_MSG_CHECKING(for st_blksize)
|
||||
|
||||
+402
-30
@@ -12,6 +12,10 @@
|
||||
*/
|
||||
#include "vim.h"
|
||||
|
||||
#ifdef FEAT_SODIUM
|
||||
# include <sodium.h>
|
||||
#endif
|
||||
|
||||
#if defined(FEAT_CRYPT) || defined(PROTO)
|
||||
/*
|
||||
* Optional encryption support.
|
||||
@@ -33,7 +37,7 @@ typedef struct {
|
||||
char *name; // encryption name as used in 'cryptmethod'
|
||||
char *magic; // magic bytes stored in file header
|
||||
int salt_len; // length of salt, or 0 when not using salt
|
||||
int seed_len; // length of seed, or 0 when not using salt
|
||||
int seed_len; // length of seed, or 0 when not using seed
|
||||
#ifdef CRYPT_NOT_INPLACE
|
||||
int works_inplace; // encryption/decryption can be done in-place
|
||||
#endif
|
||||
@@ -49,16 +53,16 @@ typedef struct {
|
||||
// Function pointers for encoding/decoding from one buffer into another.
|
||||
// Optional, however, these or the _buffer ones should be configured.
|
||||
void (*encode_fn)(cryptstate_T *state, char_u *from, size_t len,
|
||||
char_u *to);
|
||||
char_u *to, int last);
|
||||
void (*decode_fn)(cryptstate_T *state, char_u *from, size_t len,
|
||||
char_u *to);
|
||||
char_u *to, int last);
|
||||
|
||||
// Function pointers for encoding and decoding, can buffer data if needed.
|
||||
// Optional (however, these or the above should be configured).
|
||||
long (*encode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len,
|
||||
char_u **newptr);
|
||||
char_u **newptr, int last);
|
||||
long (*decode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len,
|
||||
char_u **newptr);
|
||||
char_u **newptr, int last);
|
||||
|
||||
// Function pointers for in-place encoding and decoding, used for
|
||||
// crypt_*_inplace(). "from" and "to" arguments will be equal.
|
||||
@@ -68,9 +72,9 @@ typedef struct {
|
||||
// padding to files).
|
||||
// This method is used for swap and undo files which have a rigid format.
|
||||
void (*encode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len,
|
||||
char_u *p2);
|
||||
char_u *p2, int last);
|
||||
void (*decode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len,
|
||||
char_u *p2);
|
||||
char_u *p2, int last);
|
||||
} cryptmethod_T;
|
||||
|
||||
// index is method_nr of cryptstate_T, CRYPT_M_*
|
||||
@@ -126,10 +130,41 @@ static cryptmethod_T cryptmethods[CRYPT_M_COUNT] = {
|
||||
crypt_blowfish_encode, crypt_blowfish_decode,
|
||||
},
|
||||
|
||||
// XChaCha20 using libsodium
|
||||
{
|
||||
"xchacha20",
|
||||
"VimCrypt~04!",
|
||||
#ifdef FEAT_SODIUM
|
||||
crypto_pwhash_argon2id_SALTBYTES, // 16
|
||||
#else
|
||||
16,
|
||||
#endif
|
||||
8,
|
||||
#ifdef CRYPT_NOT_INPLACE
|
||||
FALSE,
|
||||
#endif
|
||||
FALSE,
|
||||
NULL,
|
||||
crypt_sodium_init,
|
||||
NULL, NULL,
|
||||
crypt_sodium_buffer_encode, crypt_sodium_buffer_decode,
|
||||
NULL, NULL,
|
||||
},
|
||||
|
||||
// NOTE: when adding a new method, use some random bytes for the magic key,
|
||||
// to avoid that a text file is recognized as encrypted.
|
||||
};
|
||||
|
||||
#ifdef FEAT_SODIUM
|
||||
typedef struct {
|
||||
size_t count;
|
||||
unsigned char key[crypto_box_SEEDBYTES];
|
||||
// 32, same as crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||
crypto_secretstream_xchacha20poly1305_state
|
||||
state;
|
||||
} sodium_state_T;
|
||||
#endif
|
||||
|
||||
#define CRYPT_MAGIC_LEN 12 // cannot change
|
||||
static char crypt_magic_head[] = "VimCrypt~";
|
||||
|
||||
@@ -215,6 +250,26 @@ crypt_get_header_len(int method_nr)
|
||||
+ cryptmethods[method_nr].seed_len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get maximum crypt method specific length of the file header in bytes.
|
||||
*/
|
||||
int
|
||||
crypt_get_max_header_len()
|
||||
{
|
||||
int i;
|
||||
int max = 0;
|
||||
int temp = 0;
|
||||
|
||||
for (i = 0; i < CRYPT_M_COUNT; ++i)
|
||||
{
|
||||
temp = crypt_get_header_len(i);
|
||||
if (temp > max)
|
||||
max = temp;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the crypt method for buffer "buf" to "method_nr" using the int value as
|
||||
* returned by crypt_method_nr_from_name().
|
||||
@@ -260,7 +315,7 @@ crypt_create(
|
||||
|
||||
state->method_nr = method_nr;
|
||||
if (cryptmethods[method_nr].init_fn(
|
||||
state, key, salt, salt_len, seed, seed_len) == FAIL)
|
||||
state, key, salt, salt_len, seed, seed_len) == FAIL)
|
||||
{
|
||||
vim_free(state);
|
||||
return NULL;
|
||||
@@ -365,9 +420,18 @@ crypt_create_for_writing(
|
||||
// TODO: Should this be crypt method specific? (Probably not worth
|
||||
// it). sha2_seed is pretty bad for large amounts of entropy, so make
|
||||
// that into something which is suitable for anything.
|
||||
sha2_seed(salt, salt_len, seed, seed_len);
|
||||
#ifdef FEAT_SODIUM
|
||||
if (sodium_init() >= 0)
|
||||
{
|
||||
if (salt_len > 0)
|
||||
randombytes_buf(salt, salt_len);
|
||||
if (seed_len > 0)
|
||||
randombytes_buf(seed, seed_len);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
sha2_seed(salt, salt_len, seed, seed_len);
|
||||
}
|
||||
|
||||
state = crypt_create(method_nr, key, salt, salt_len, seed, seed_len);
|
||||
if (state == NULL)
|
||||
VIM_CLEAR(*header);
|
||||
@@ -380,7 +444,15 @@ crypt_create_for_writing(
|
||||
void
|
||||
crypt_free_state(cryptstate_T *state)
|
||||
{
|
||||
vim_free(state->method_state);
|
||||
#ifdef FEAT_SODIUM
|
||||
if (state->method_nr == CRYPT_M_SOD)
|
||||
{
|
||||
sodium_memzero(state->method_state, sizeof(sodium_state_T));
|
||||
sodium_free(state->method_state);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
vim_free(state->method_state);
|
||||
vim_free(state);
|
||||
}
|
||||
|
||||
@@ -395,21 +467,22 @@ crypt_encode_alloc(
|
||||
cryptstate_T *state,
|
||||
char_u *from,
|
||||
size_t len,
|
||||
char_u **newptr)
|
||||
char_u **newptr,
|
||||
int last)
|
||||
{
|
||||
cryptmethod_T *method = &cryptmethods[state->method_nr];
|
||||
|
||||
if (method->encode_buffer_fn != NULL)
|
||||
// Has buffer function, pass through.
|
||||
return method->encode_buffer_fn(state, from, len, newptr);
|
||||
return method->encode_buffer_fn(state, from, len, newptr, last);
|
||||
if (len == 0)
|
||||
// Not buffering, just return EOF.
|
||||
return (long)len;
|
||||
|
||||
*newptr = alloc(len);
|
||||
*newptr = alloc(len + 50);
|
||||
if (*newptr == NULL)
|
||||
return -1;
|
||||
method->encode_fn(state, from, len, *newptr);
|
||||
method->encode_fn(state, from, len, *newptr, last);
|
||||
return (long)len;
|
||||
}
|
||||
|
||||
@@ -423,13 +496,14 @@ crypt_decode_alloc(
|
||||
cryptstate_T *state,
|
||||
char_u *ptr,
|
||||
long len,
|
||||
char_u **newptr)
|
||||
char_u **newptr,
|
||||
int last)
|
||||
{
|
||||
cryptmethod_T *method = &cryptmethods[state->method_nr];
|
||||
|
||||
if (method->decode_buffer_fn != NULL)
|
||||
// Has buffer function, pass through.
|
||||
return method->decode_buffer_fn(state, ptr, len, newptr);
|
||||
return method->decode_buffer_fn(state, ptr, len, newptr, last);
|
||||
|
||||
if (len == 0)
|
||||
// Not buffering, just return EOF.
|
||||
@@ -438,7 +512,7 @@ crypt_decode_alloc(
|
||||
*newptr = alloc(len);
|
||||
if (*newptr == NULL)
|
||||
return -1;
|
||||
method->decode_fn(state, ptr, len, *newptr);
|
||||
method->decode_fn(state, ptr, len, *newptr, last);
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
@@ -451,9 +525,10 @@ crypt_encode(
|
||||
cryptstate_T *state,
|
||||
char_u *from,
|
||||
size_t len,
|
||||
char_u *to)
|
||||
char_u *to,
|
||||
int last)
|
||||
{
|
||||
cryptmethods[state->method_nr].encode_fn(state, from, len, to);
|
||||
cryptmethods[state->method_nr].encode_fn(state, from, len, to, last);
|
||||
}
|
||||
|
||||
#if 0 // unused
|
||||
@@ -465,9 +540,10 @@ crypt_decode(
|
||||
cryptstate_T *state,
|
||||
char_u *from,
|
||||
size_t len,
|
||||
char_u *to)
|
||||
char_u *to,
|
||||
int last)
|
||||
{
|
||||
cryptmethods[state->method_nr].decode_fn(state, from, len, to);
|
||||
cryptmethods[state->method_nr].decode_fn(state, from, len, to, last);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -478,9 +554,11 @@ crypt_decode(
|
||||
crypt_encode_inplace(
|
||||
cryptstate_T *state,
|
||||
char_u *buf,
|
||||
size_t len)
|
||||
size_t len,
|
||||
int last)
|
||||
{
|
||||
cryptmethods[state->method_nr].encode_inplace_fn(state, buf, len, buf);
|
||||
cryptmethods[state->method_nr].encode_inplace_fn(state, buf, len,
|
||||
buf, last);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -490,9 +568,11 @@ crypt_encode_inplace(
|
||||
crypt_decode_inplace(
|
||||
cryptstate_T *state,
|
||||
char_u *buf,
|
||||
size_t len)
|
||||
size_t len,
|
||||
int last)
|
||||
{
|
||||
cryptmethods[state->method_nr].decode_inplace_fn(state, buf, len, buf);
|
||||
cryptmethods[state->method_nr].decode_inplace_fn(state, buf, len,
|
||||
buf, last);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -525,6 +605,26 @@ crypt_check_method(int method)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FEAT_SODIUM
|
||||
static void
|
||||
crypt_check_swapfile_curbuf(void)
|
||||
{
|
||||
int method = crypt_get_method_nr(curbuf);
|
||||
if (method == CRYPT_M_SOD)
|
||||
{
|
||||
// encryption uses padding and MAC, that does not work very well with
|
||||
// swap and undo files, so disable them
|
||||
mf_close_file(curbuf, TRUE); // remove the swap file
|
||||
set_option_value((char_u *)"swf", 0, NULL, OPT_LOCAL);
|
||||
#ifdef FEAT_PERSISTENT_UNDO
|
||||
set_option_value((char_u *)"udf", 0, NULL, OPT_LOCAL);
|
||||
#endif
|
||||
msg_scroll = TRUE;
|
||||
msg(_("Note: Encryption of swapfile not supported, disabling swap- and undofile"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
crypt_check_current_method(void)
|
||||
{
|
||||
@@ -576,6 +676,9 @@ crypt_get_key(
|
||||
set_option_value((char_u *)"key", 0L, p1, OPT_LOCAL);
|
||||
crypt_free_key(p1);
|
||||
p1 = curbuf->b_p_key;
|
||||
#ifdef FEAT_SODIUM
|
||||
crypt_check_swapfile_curbuf();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -583,10 +686,13 @@ crypt_get_key(
|
||||
}
|
||||
|
||||
// since the user typed this, no need to wait for return
|
||||
if (msg_didout)
|
||||
msg_putchar('\n');
|
||||
need_wait_return = FALSE;
|
||||
msg_didout = FALSE;
|
||||
if (crypt_get_method_nr(curbuf) != CRYPT_M_SOD)
|
||||
{
|
||||
if (msg_didout)
|
||||
msg_putchar('\n');
|
||||
need_wait_return = FALSE;
|
||||
msg_didout = FALSE;
|
||||
}
|
||||
|
||||
crypt_free_key(p2);
|
||||
return p1;
|
||||
@@ -610,4 +716,270 @@ crypt_append_msg(
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
crypt_sodium_init(
|
||||
cryptstate_T *state UNUSED,
|
||||
char_u *key UNUSED,
|
||||
char_u *salt UNUSED,
|
||||
int salt_len UNUSED,
|
||||
char_u *seed UNUSED,
|
||||
int seed_len UNUSED)
|
||||
{
|
||||
# ifdef FEAT_SODIUM
|
||||
// crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||
unsigned char dkey[crypto_box_SEEDBYTES]; // 32
|
||||
sodium_state_T *sd_state;
|
||||
|
||||
if (sodium_init() < 0)
|
||||
return FAIL;
|
||||
|
||||
sd_state = (sodium_state_T *)sodium_malloc(sizeof(sodium_state_T));
|
||||
sodium_memzero(sd_state, sizeof(sodium_state_T));
|
||||
|
||||
// derive a key from the password
|
||||
if (crypto_pwhash(dkey, sizeof(dkey), (const char *)key, STRLEN(key), salt,
|
||||
crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_ALG_DEFAULT) != 0)
|
||||
{
|
||||
// out of memory
|
||||
sodium_free(sd_state);
|
||||
return FAIL;
|
||||
}
|
||||
memcpy(sd_state->key, dkey, crypto_box_SEEDBYTES);
|
||||
sd_state->count = 0;
|
||||
state->method_state = sd_state;
|
||||
|
||||
return OK;
|
||||
# else
|
||||
emsg(e_libsodium_not_built_in);
|
||||
return FAIL;
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt "from[len]" into "to[len]".
|
||||
* "from" and "to" can be equal to encrypt in place.
|
||||
* Call needs to ensure that there is enough space in to (for the header)
|
||||
*/
|
||||
#if 0 // Currently unused
|
||||
void
|
||||
crypt_sodium_encode(
|
||||
cryptstate_T *state UNUSED,
|
||||
char_u *from UNUSED,
|
||||
size_t len UNUSED,
|
||||
char_u *to UNUSED,
|
||||
int last UNUSED)
|
||||
{
|
||||
# ifdef FEAT_SODIUM
|
||||
// crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||
sodium_state_T *sod_st = state->method_state;
|
||||
unsigned char tag = last
|
||||
? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
|
||||
|
||||
if (sod_st->count == 0)
|
||||
{
|
||||
if (len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES)
|
||||
{
|
||||
emsg(e_libsodium_cannot_encrypt_header);
|
||||
return;
|
||||
}
|
||||
crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state,
|
||||
to, sod_st->key);
|
||||
to += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
||||
}
|
||||
|
||||
if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||
{
|
||||
emsg(e_libsodium_cannot_encrypt_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
crypto_secretstream_xchacha20poly1305_push(&sod_st->state, to, NULL,
|
||||
from, len, NULL, 0, tag);
|
||||
|
||||
sod_st->count++;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Decrypt "from[len]" into "to[len]".
|
||||
* "from" and "to" can be equal to encrypt in place.
|
||||
*/
|
||||
#if 0 // Currently unused
|
||||
void
|
||||
crypt_sodium_decode(
|
||||
cryptstate_T *state UNUSED,
|
||||
char_u *from UNUSED,
|
||||
size_t len UNUSED,
|
||||
char_u *to UNUSED,
|
||||
int last UNUSED)
|
||||
{
|
||||
# ifdef FEAT_SODIUM
|
||||
// crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||
sodium_state_T *sod_st = state->method_state;
|
||||
unsigned char tag;
|
||||
unsigned long long buf_len;
|
||||
char_u *p1 = from;
|
||||
char_u *p2 = to;
|
||||
char_u *buf_out;
|
||||
|
||||
if (sod_st->count == 0
|
||||
&& len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES)
|
||||
{
|
||||
emsg(e_libsodium_cannot_decrypt_header);
|
||||
return;
|
||||
}
|
||||
|
||||
buf_out = (char_u *)alloc(len);
|
||||
|
||||
if (buf_out == NULL)
|
||||
{
|
||||
emsg(e_libsodium_cannot_allocate_buffer);
|
||||
return;
|
||||
}
|
||||
if (sod_st->count == 0)
|
||||
{
|
||||
if (crypto_secretstream_xchacha20poly1305_init_pull(
|
||||
&sod_st->state, from, sod_st->key) != 0)
|
||||
{
|
||||
emsg(e_libsodium_decryption_failed_header_incomplete);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
from += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
||||
len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
||||
|
||||
if (p1 == p2)
|
||||
to += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
||||
}
|
||||
|
||||
if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||
{
|
||||
emsg(e_libsodium_cannot_decrypt_buffer);
|
||||
goto fail;
|
||||
}
|
||||
if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state,
|
||||
buf_out, &buf_len, &tag, from, len, NULL, 0) != 0)
|
||||
{
|
||||
emsg(e_libsodium_decryption_failed);
|
||||
goto fail;
|
||||
}
|
||||
sod_st->count++;
|
||||
|
||||
if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last)
|
||||
{
|
||||
emsg(e_libsodium_decryption_failed_premature);
|
||||
goto fail;
|
||||
}
|
||||
if (p1 == p2)
|
||||
mch_memmove(p2, buf_out, buf_len);
|
||||
|
||||
fail:
|
||||
vim_free(buf_out);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Encrypt "from[len]" into "to[len]".
|
||||
* "from" and "to" can be equal to encrypt in place.
|
||||
*/
|
||||
long
|
||||
crypt_sodium_buffer_encode(
|
||||
cryptstate_T *state UNUSED,
|
||||
char_u *from UNUSED,
|
||||
size_t len UNUSED,
|
||||
char_u **buf_out UNUSED,
|
||||
int last UNUSED)
|
||||
{
|
||||
# ifdef FEAT_SODIUM
|
||||
// crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||
unsigned long long out_len;
|
||||
char_u *ptr;
|
||||
unsigned char tag = last
|
||||
? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
|
||||
int length;
|
||||
sodium_state_T *sod_st = state->method_state;
|
||||
int first = (sod_st->count == 0);
|
||||
|
||||
length = (int)len + crypto_secretstream_xchacha20poly1305_ABYTES
|
||||
+ (first ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0);
|
||||
*buf_out = alloc_clear(length);
|
||||
if (*buf_out == NULL)
|
||||
{
|
||||
emsg(e_libsodium_cannot_allocate_buffer);
|
||||
return -1;
|
||||
}
|
||||
ptr = *buf_out;
|
||||
|
||||
if (first)
|
||||
{
|
||||
crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state,
|
||||
ptr, sod_st->key);
|
||||
ptr += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
||||
}
|
||||
|
||||
crypto_secretstream_xchacha20poly1305_push(&sod_st->state, ptr,
|
||||
&out_len, from, len, NULL, 0, tag);
|
||||
|
||||
sod_st->count++;
|
||||
return out_len + (first
|
||||
? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0);
|
||||
# else
|
||||
return -1;
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt "from[len]" into "to[len]".
|
||||
* "from" and "to" can be equal to encrypt in place.
|
||||
*/
|
||||
long
|
||||
crypt_sodium_buffer_decode(
|
||||
cryptstate_T *state UNUSED,
|
||||
char_u *from UNUSED,
|
||||
size_t len UNUSED,
|
||||
char_u **buf_out UNUSED,
|
||||
int last UNUSED)
|
||||
{
|
||||
# ifdef FEAT_SODIUM
|
||||
// crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||
sodium_state_T *sod_st = state->method_state;
|
||||
unsigned char tag;
|
||||
unsigned long long out_len;
|
||||
*buf_out = alloc_clear(len);
|
||||
if (*buf_out == NULL)
|
||||
{
|
||||
emsg(e_libsodium_cannot_allocate_buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sod_st->count == 0)
|
||||
{
|
||||
if (crypto_secretstream_xchacha20poly1305_init_pull(&sod_st->state,
|
||||
from, sod_st->key) != 0)
|
||||
{
|
||||
emsg(e_libsodium_decryption_failed_header_incomplete);
|
||||
return -1;
|
||||
}
|
||||
from += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
||||
len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
||||
sod_st->count++;
|
||||
}
|
||||
if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state,
|
||||
*buf_out, &out_len, &tag, from, len, NULL, 0) != 0)
|
||||
{
|
||||
emsg(e_libsodium_decryption_failed);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last)
|
||||
emsg(e_libsodium_decryption_failed_premature);
|
||||
return (long) out_len;
|
||||
# else
|
||||
return -1;
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif // FEAT_CRYPT
|
||||
|
||||
+4
-2
@@ -114,7 +114,8 @@ crypt_zip_encode(
|
||||
cryptstate_T *state,
|
||||
char_u *from,
|
||||
size_t len,
|
||||
char_u *to)
|
||||
char_u *to,
|
||||
int last UNUSED)
|
||||
{
|
||||
zip_state_T *zs = state->method_state;
|
||||
size_t i;
|
||||
@@ -137,7 +138,8 @@ crypt_zip_decode(
|
||||
cryptstate_T *state,
|
||||
char_u *from,
|
||||
size_t len,
|
||||
char_u *to)
|
||||
char_u *to,
|
||||
int last UNUSED)
|
||||
{
|
||||
zip_state_T *zs = state->method_state;
|
||||
size_t i;
|
||||
|
||||
+1
-1
@@ -606,7 +606,7 @@ dbg_parsearg(
|
||||
}
|
||||
|
||||
if (bp->dbg_type == DBG_FUNC)
|
||||
bp->dbg_name = vim_strsave(p);
|
||||
bp->dbg_name = vim_strsave(STRNCMP(p, "g:", 2) == 0 ? p + 2 : p);
|
||||
else if (here)
|
||||
bp->dbg_name = vim_strsave(curbuf->b_ffname);
|
||||
else if (bp->dbg_type == DBG_EXPR)
|
||||
|
||||
+3
-2
@@ -1121,8 +1121,9 @@ win_line(
|
||||
int t;
|
||||
|
||||
// like rl_mirror(), but keep the space at the end
|
||||
p2 = skiptowhite(extra) - 1;
|
||||
for (p1 = extra; p1 < p2; ++p1, --p2)
|
||||
p2 = skipwhite(extra);
|
||||
p2 = skiptowhite(p2) - 1;
|
||||
for (p1 = skipwhite(extra); p1 < p2; ++p1, --p2)
|
||||
{
|
||||
t = *p1;
|
||||
*p1 = *p2;
|
||||
|
||||
@@ -427,3 +427,22 @@ EXTERN char e_call_to_function_that_failed_to_compile_str[]
|
||||
INIT(= N_("E1191: Call to function that failed to compile: %s"));
|
||||
EXTERN char e_empty_function_name[]
|
||||
INIT(= N_("E1192: Empty function name"));
|
||||
// libsodium
|
||||
EXTERN char e_libsodium_not_built_in[]
|
||||
INIT(= N_("E1193: cryptmethod xchacha20 not built into this Vim"));
|
||||
EXTERN char e_libsodium_cannot_encrypt_header[]
|
||||
INIT(= N_("E1194: Cannot encrypt header, not enough space"));
|
||||
EXTERN char e_libsodium_cannot_encrypt_buffer[]
|
||||
INIT(= N_("E1195: Cannot encrypt buffer, not enough space"));
|
||||
EXTERN char e_libsodium_cannot_decrypt_header[]
|
||||
INIT(= N_("E1196: Cannot decrypt header, not enough space"));
|
||||
EXTERN char e_libsodium_cannot_allocate_buffer[]
|
||||
INIT(= N_("E1197: Cannot allocate_buffer for encryption"));
|
||||
EXTERN char e_libsodium_decryption_failed_header_incomplete[]
|
||||
INIT(= N_("E1198: Decryption failed: Header incomplete!"));
|
||||
EXTERN char e_libsodium_cannot_decrypt_buffer[]
|
||||
INIT(= N_("E1199: Cannot decrypt buffer, not enough space"));
|
||||
EXTERN char e_libsodium_decryption_failed[]
|
||||
INIT(= N_("E1200: Decryption failed!"));
|
||||
EXTERN char e_libsodium_decryption_failed_premature[]
|
||||
INIT(= N_("E1201: Decryption failed: pre-mature end of file!"));
|
||||
|
||||
+10
-2
@@ -2218,12 +2218,15 @@ eval0(
|
||||
int did_emsg_before = did_emsg;
|
||||
int called_emsg_before = called_emsg;
|
||||
int flags = evalarg == NULL ? 0 : evalarg->eval_flags;
|
||||
int end_error = FALSE;
|
||||
|
||||
p = skipwhite(arg);
|
||||
ret = eval1(&p, rettv, evalarg);
|
||||
p = skipwhite(p);
|
||||
|
||||
if (ret == FAIL || !ends_excmd2(arg, p))
|
||||
if (ret != FAIL)
|
||||
end_error = !ends_excmd2(arg, p);
|
||||
if (ret == FAIL || end_error)
|
||||
{
|
||||
if (ret != FAIL)
|
||||
clear_tv(rettv);
|
||||
@@ -2238,7 +2241,12 @@ eval0(
|
||||
&& called_emsg == called_emsg_before
|
||||
&& (flags & EVAL_CONSTANT) == 0
|
||||
&& (!in_vim9script() || !vim9_bad_comment(p)))
|
||||
semsg(_(e_invexpr2), arg);
|
||||
{
|
||||
if (end_error)
|
||||
semsg(_(e_trailing_arg), p);
|
||||
else
|
||||
semsg(_(e_invexpr2), arg);
|
||||
}
|
||||
|
||||
// Some of the expression may not have been consumed. Do not check for
|
||||
// a next command to avoid more errors, unless "|" is following, which
|
||||
|
||||
+100
-65
@@ -301,6 +301,27 @@ arg_list_or_blob(type_T *type, argcontext_T *context)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check "type" is a string or a list of strings.
|
||||
*/
|
||||
static int
|
||||
arg_string_or_list(type_T *type, argcontext_T *context)
|
||||
{
|
||||
if (type->tt_type == VAR_ANY || type->tt_type == VAR_STRING)
|
||||
return OK;
|
||||
if (type->tt_type != VAR_LIST)
|
||||
{
|
||||
arg_type_mismatch(&t_string, type, context->arg_idx + 1);
|
||||
return FAIL;
|
||||
}
|
||||
if (type->tt_member->tt_type == VAR_ANY
|
||||
|| type->tt_member->tt_type == VAR_STRING)
|
||||
return OK;
|
||||
|
||||
arg_type_mismatch(&t_list_string, type, context->arg_idx + 1);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check "type" is a list or a dict.
|
||||
*/
|
||||
@@ -382,11 +403,16 @@ arg_extend3(type_T *type, argcontext_T *context)
|
||||
* Lists of functions that check the argument types of a builtin function.
|
||||
*/
|
||||
argcheck_T arg1_string[] = {arg_string};
|
||||
argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
|
||||
argcheck_T arg1_number[] = {arg_number};
|
||||
argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
|
||||
argcheck_T arg2_float_or_nr[] = {arg_float_or_nr, arg_float_or_nr};
|
||||
argcheck_T arg2_number[] = {arg_number, arg_number};
|
||||
argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev};
|
||||
argcheck_T arg2_execute[] = {arg_string_or_list, arg_string};
|
||||
argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3};
|
||||
argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3};
|
||||
argcheck_T arg3_string[] = {arg_string, arg_string, arg_string};
|
||||
argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool};
|
||||
argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
|
||||
|
||||
/*
|
||||
@@ -648,25 +674,25 @@ static funcentry_T global_functions[] =
|
||||
{
|
||||
{"abs", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_any, FLOAT_FUNC(f_abs)},
|
||||
{"acos", 1, 1, FEARG_1, NULL,
|
||||
{"acos", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_acos)},
|
||||
{"add", 2, 2, FEARG_1, NULL /* arg2_listblob_item */,
|
||||
ret_first_arg, f_add},
|
||||
{"and", 2, 2, FEARG_1, NULL,
|
||||
{"and", 2, 2, FEARG_1, arg2_number,
|
||||
ret_number, f_and},
|
||||
{"append", 2, 2, FEARG_2, NULL,
|
||||
ret_number_bool, f_append},
|
||||
{"appendbufline", 3, 3, FEARG_3, NULL,
|
||||
ret_number_bool, f_appendbufline},
|
||||
{"argc", 0, 1, 0, NULL,
|
||||
{"argc", 0, 1, 0, arg1_number,
|
||||
ret_number, f_argc},
|
||||
{"argidx", 0, 0, 0, NULL,
|
||||
ret_number, f_argidx},
|
||||
{"arglistid", 0, 2, 0, NULL,
|
||||
{"arglistid", 0, 2, 0, arg2_number,
|
||||
ret_number, f_arglistid},
|
||||
{"argv", 0, 2, 0, NULL,
|
||||
{"argv", 0, 2, 0, arg2_number,
|
||||
ret_argv, f_argv},
|
||||
{"asin", 1, 1, FEARG_1, NULL,
|
||||
{"asin", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_asin)},
|
||||
{"assert_beeps", 1, 2, FEARG_1, NULL,
|
||||
ret_number_bool, f_assert_beeps},
|
||||
@@ -694,9 +720,9 @@ static funcentry_T global_functions[] =
|
||||
ret_number_bool, f_assert_report},
|
||||
{"assert_true", 1, 2, FEARG_1, NULL,
|
||||
ret_number_bool, f_assert_true},
|
||||
{"atan", 1, 1, FEARG_1, NULL,
|
||||
{"atan", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_atan)},
|
||||
{"atan2", 2, 2, FEARG_1, NULL,
|
||||
{"atan2", 2, 2, FEARG_1, arg2_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_atan2)},
|
||||
{"balloon_gettext", 0, 0, 0, NULL,
|
||||
ret_string,
|
||||
@@ -758,7 +784,7 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_byteidxcomp},
|
||||
{"call", 2, 3, FEARG_1, NULL,
|
||||
ret_any, f_call},
|
||||
{"ceil", 1, 1, FEARG_1, NULL,
|
||||
{"ceil", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_ceil)},
|
||||
{"ch_canread", 1, 1, FEARG_1, NULL,
|
||||
ret_number_bool, JOB_FUNC(f_ch_canread)},
|
||||
@@ -810,7 +836,7 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_chdir},
|
||||
{"cindent", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_cindent},
|
||||
{"clearmatches", 0, 1, FEARG_1, NULL,
|
||||
{"clearmatches", 0, 1, FEARG_1, arg1_number,
|
||||
ret_void, f_clearmatches},
|
||||
{"col", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_col},
|
||||
@@ -826,9 +852,9 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_confirm},
|
||||
{"copy", 1, 1, FEARG_1, NULL,
|
||||
ret_first_arg, f_copy},
|
||||
{"cos", 1, 1, FEARG_1, NULL,
|
||||
{"cos", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_cos)},
|
||||
{"cosh", 1, 1, FEARG_1, NULL,
|
||||
{"cosh", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_cosh)},
|
||||
{"count", 2, 4, FEARG_1, NULL,
|
||||
ret_number, f_count},
|
||||
@@ -836,7 +862,7 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_cscope_connection},
|
||||
{"cursor", 1, 3, FEARG_1, NULL,
|
||||
ret_number, f_cursor},
|
||||
{"debugbreak", 1, 1, FEARG_1, NULL,
|
||||
{"debugbreak", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number,
|
||||
#ifdef MSWIN
|
||||
f_debugbreak
|
||||
@@ -870,13 +896,13 @@ static funcentry_T global_functions[] =
|
||||
ret_number_bool, f_eventhandler},
|
||||
{"executable", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_executable},
|
||||
{"execute", 1, 2, FEARG_1, NULL,
|
||||
{"execute", 1, 2, FEARG_1, arg2_execute,
|
||||
ret_string, f_execute},
|
||||
{"exepath", 1, 1, FEARG_1, NULL,
|
||||
ret_string, f_exepath},
|
||||
{"exists", 1, 1, FEARG_1, NULL,
|
||||
ret_number_bool, f_exists},
|
||||
{"exp", 1, 1, FEARG_1, NULL,
|
||||
{"exp", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_exp)},
|
||||
{"expand", 1, 3, FEARG_1, NULL,
|
||||
ret_any, f_expand},
|
||||
@@ -904,11 +930,11 @@ static funcentry_T global_functions[] =
|
||||
ret_list_any, f_flatten},
|
||||
{"flattennew", 1, 2, FEARG_1, NULL,
|
||||
ret_list_any, f_flattennew},
|
||||
{"float2nr", 1, 1, FEARG_1, NULL,
|
||||
{"float2nr", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_number, FLOAT_FUNC(f_float2nr)},
|
||||
{"floor", 1, 1, FEARG_1, NULL,
|
||||
{"floor", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_floor)},
|
||||
{"fmod", 2, 2, FEARG_1, NULL,
|
||||
{"fmod", 2, 2, FEARG_1, arg2_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_fmod)},
|
||||
{"fnameescape", 1, 1, FEARG_1, NULL,
|
||||
ret_string, f_fnameescape},
|
||||
@@ -964,11 +990,11 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_getcmdwintype},
|
||||
{"getcompletion", 2, 3, FEARG_1, NULL,
|
||||
ret_list_string, f_getcompletion},
|
||||
{"getcurpos", 0, 1, FEARG_1, NULL,
|
||||
{"getcurpos", 0, 1, FEARG_1, arg1_number,
|
||||
ret_list_number, f_getcurpos},
|
||||
{"getcursorcharpos", 0, 1, FEARG_1, NULL,
|
||||
{"getcursorcharpos", 0, 1, FEARG_1, arg1_number,
|
||||
ret_list_number, f_getcursorcharpos},
|
||||
{"getcwd", 0, 2, FEARG_1, NULL,
|
||||
{"getcwd", 0, 2, FEARG_1, arg2_number,
|
||||
ret_string, f_getcwd},
|
||||
{"getenv", 1, 1, FEARG_1, NULL,
|
||||
ret_any, f_getenv},
|
||||
@@ -984,7 +1010,7 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_getftype},
|
||||
{"getimstatus", 0, 0, 0, NULL,
|
||||
ret_number_bool, f_getimstatus},
|
||||
{"getjumplist", 0, 2, FEARG_1, NULL,
|
||||
{"getjumplist", 0, 2, FEARG_1, arg2_number,
|
||||
ret_list_any, f_getjumplist},
|
||||
{"getline", 1, 2, FEARG_1, NULL,
|
||||
ret_f_getline, f_getline},
|
||||
@@ -992,7 +1018,7 @@ static funcentry_T global_functions[] =
|
||||
ret_list_or_dict_1, f_getloclist},
|
||||
{"getmarklist", 0, 1, FEARG_1, NULL,
|
||||
ret_list_dict_any, f_getmarklist},
|
||||
{"getmatches", 0, 1, 0, NULL,
|
||||
{"getmatches", 0, 1, 0, arg1_number,
|
||||
ret_list_dict_any, f_getmatches},
|
||||
{"getmousepos", 0, 0, 0, NULL,
|
||||
ret_dict_number, f_getmousepos},
|
||||
@@ -1008,19 +1034,19 @@ static funcentry_T global_functions[] =
|
||||
ret_dict_any, f_getreginfo},
|
||||
{"getregtype", 0, 1, FEARG_1, NULL,
|
||||
ret_string, f_getregtype},
|
||||
{"gettabinfo", 0, 1, FEARG_1, NULL,
|
||||
{"gettabinfo", 0, 1, FEARG_1, arg1_number,
|
||||
ret_list_dict_any, f_gettabinfo},
|
||||
{"gettabvar", 2, 3, FEARG_1, NULL,
|
||||
ret_any, f_gettabvar},
|
||||
{"gettabwinvar", 3, 4, FEARG_1, NULL,
|
||||
ret_any, f_gettabwinvar},
|
||||
{"gettagstack", 0, 1, FEARG_1, NULL,
|
||||
{"gettagstack", 0, 1, FEARG_1, arg1_number,
|
||||
ret_dict_any, f_gettagstack},
|
||||
{"gettext", 1, 1, FEARG_1, NULL,
|
||||
ret_string, f_gettext},
|
||||
{"getwininfo", 0, 1, FEARG_1, NULL,
|
||||
{"getwininfo", 0, 1, FEARG_1, arg1_number,
|
||||
ret_list_dict_any, f_getwininfo},
|
||||
{"getwinpos", 0, 1, FEARG_1, NULL,
|
||||
{"getwinpos", 0, 1, FEARG_1, arg1_number,
|
||||
ret_list_number, f_getwinpos},
|
||||
{"getwinposx", 0, 0, 0, NULL,
|
||||
ret_number, f_getwinposx},
|
||||
@@ -1038,7 +1064,7 @@ static funcentry_T global_functions[] =
|
||||
ret_number_bool, f_has},
|
||||
{"has_key", 2, 2, FEARG_1, NULL,
|
||||
ret_number_bool, f_has_key},
|
||||
{"haslocaldir", 0, 2, FEARG_1, NULL,
|
||||
{"haslocaldir", 0, 2, FEARG_1, arg2_number,
|
||||
ret_number, f_haslocaldir},
|
||||
{"hasmapto", 1, 3, FEARG_1, NULL,
|
||||
ret_number_bool, f_hasmapto},
|
||||
@@ -1082,15 +1108,15 @@ static funcentry_T global_functions[] =
|
||||
ret_first_arg, f_insert},
|
||||
{"interrupt", 0, 0, 0, NULL,
|
||||
ret_void, f_interrupt},
|
||||
{"invert", 1, 1, FEARG_1, NULL,
|
||||
{"invert", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number, f_invert},
|
||||
{"isdirectory", 1, 1, FEARG_1, NULL,
|
||||
ret_number_bool, f_isdirectory},
|
||||
{"isinf", 1, 1, FEARG_1, NULL,
|
||||
{"isinf", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_number, MATH_FUNC(f_isinf)},
|
||||
{"islocked", 1, 1, FEARG_1, NULL,
|
||||
ret_number_bool, f_islocked},
|
||||
{"isnan", 1, 1, FEARG_1, NULL,
|
||||
{"isnan", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_number_bool, MATH_FUNC(f_isnan)},
|
||||
{"items", 1, 1, FEARG_1, NULL,
|
||||
ret_list_any, f_items},
|
||||
@@ -1138,13 +1164,13 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_listener_add},
|
||||
{"listener_flush", 0, 1, FEARG_1, NULL,
|
||||
ret_void, f_listener_flush},
|
||||
{"listener_remove", 1, 1, FEARG_1, NULL,
|
||||
{"listener_remove", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number_bool, f_listener_remove},
|
||||
{"localtime", 0, 0, 0, NULL,
|
||||
ret_number, f_localtime},
|
||||
{"log", 1, 1, FEARG_1, NULL,
|
||||
{"log", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_log)},
|
||||
{"log10", 1, 1, FEARG_1, NULL,
|
||||
{"log10", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_log10)},
|
||||
{"luaeval", 1, 2, FEARG_1, NULL,
|
||||
ret_any,
|
||||
@@ -1170,9 +1196,9 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_matchadd},
|
||||
{"matchaddpos", 2, 5, FEARG_1, NULL,
|
||||
ret_number, f_matchaddpos},
|
||||
{"matcharg", 1, 1, FEARG_1, NULL,
|
||||
{"matcharg", 1, 1, FEARG_1, arg1_number,
|
||||
ret_list_string, f_matcharg},
|
||||
{"matchdelete", 1, 2, FEARG_1, NULL,
|
||||
{"matchdelete", 1, 2, FEARG_1, arg2_number,
|
||||
ret_number_bool, f_matchdelete},
|
||||
{"matchend", 2, 4, FEARG_1, NULL,
|
||||
ret_number, f_matchend},
|
||||
@@ -1214,7 +1240,7 @@ static funcentry_T global_functions[] =
|
||||
ret_number, f_nextnonblank},
|
||||
{"nr2char", 1, 2, FEARG_1, NULL,
|
||||
ret_string, f_nr2char},
|
||||
{"or", 2, 2, FEARG_1, NULL,
|
||||
{"or", 2, 2, FEARG_1, arg2_number,
|
||||
ret_number, f_or},
|
||||
{"pathshorten", 1, 2, FEARG_1, NULL,
|
||||
ret_string, f_pathshorten},
|
||||
@@ -1268,7 +1294,7 @@ static funcentry_T global_functions[] =
|
||||
ret_void, PROP_FUNC(f_popup_settext)},
|
||||
{"popup_show", 1, 1, FEARG_1, NULL,
|
||||
ret_void, PROP_FUNC(f_popup_show)},
|
||||
{"pow", 2, 2, FEARG_1, NULL,
|
||||
{"pow", 2, 2, FEARG_1, arg2_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_pow)},
|
||||
{"prevnonblank", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_prevnonblank},
|
||||
@@ -1376,7 +1402,7 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_resolve},
|
||||
{"reverse", 1, 1, FEARG_1, NULL,
|
||||
ret_first_arg, f_reverse},
|
||||
{"round", 1, 1, FEARG_1, NULL,
|
||||
{"round", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_round)},
|
||||
{"rubyeval", 1, 1, FEARG_1, NULL,
|
||||
ret_any,
|
||||
@@ -1386,11 +1412,11 @@ static funcentry_T global_functions[] =
|
||||
NULL
|
||||
#endif
|
||||
},
|
||||
{"screenattr", 2, 2, FEARG_1, NULL,
|
||||
{"screenattr", 2, 2, FEARG_1, arg2_number,
|
||||
ret_number, f_screenattr},
|
||||
{"screenchar", 2, 2, FEARG_1, NULL,
|
||||
{"screenchar", 2, 2, FEARG_1, arg2_number,
|
||||
ret_number, f_screenchar},
|
||||
{"screenchars", 2, 2, FEARG_1, NULL,
|
||||
{"screenchars", 2, 2, FEARG_1, arg2_number,
|
||||
ret_list_number, f_screenchars},
|
||||
{"screencol", 0, 0, 0, NULL,
|
||||
ret_number, f_screencol},
|
||||
@@ -1398,7 +1424,7 @@ static funcentry_T global_functions[] =
|
||||
ret_dict_number, f_screenpos},
|
||||
{"screenrow", 0, 0, 0, NULL,
|
||||
ret_number, f_screenrow},
|
||||
{"screenstring", 2, 2, FEARG_1, NULL,
|
||||
{"screenstring", 2, 2, FEARG_1, arg2_number,
|
||||
ret_string, f_screenstring},
|
||||
{"search", 1, 5, FEARG_1, NULL,
|
||||
ret_number, f_search},
|
||||
@@ -1426,7 +1452,7 @@ static funcentry_T global_functions[] =
|
||||
ret_number_bool, f_setcharpos},
|
||||
{"setcharsearch", 1, 1, FEARG_1, NULL,
|
||||
ret_void, f_setcharsearch},
|
||||
{"setcmdpos", 1, 1, FEARG_1, NULL,
|
||||
{"setcmdpos", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number_bool, f_setcmdpos},
|
||||
{"setcursorcharpos", 1, 3, FEARG_1, NULL,
|
||||
ret_number_bool, f_setcursorcharpos},
|
||||
@@ -1464,7 +1490,7 @@ static funcentry_T global_functions[] =
|
||||
},
|
||||
{"shellescape", 1, 2, FEARG_1, NULL,
|
||||
ret_string, f_shellescape},
|
||||
{"shiftwidth", 0, 1, FEARG_1, NULL,
|
||||
{"shiftwidth", 0, 1, FEARG_1, arg1_number,
|
||||
ret_number, f_shiftwidth},
|
||||
{"sign_define", 1, 2, FEARG_1, NULL,
|
||||
ret_any, SIGN_FUNC(f_sign_define)},
|
||||
@@ -1486,9 +1512,9 @@ static funcentry_T global_functions[] =
|
||||
ret_list_number, SIGN_FUNC(f_sign_unplacelist)},
|
||||
{"simplify", 1, 1, FEARG_1, NULL,
|
||||
ret_string, f_simplify},
|
||||
{"sin", 1, 1, FEARG_1, NULL,
|
||||
{"sin", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_sin)},
|
||||
{"sinh", 1, 1, FEARG_1, NULL,
|
||||
{"sinh", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_sinh)},
|
||||
{"slice", 2, 3, FEARG_1, NULL,
|
||||
ret_first_arg, f_slice},
|
||||
@@ -1510,7 +1536,7 @@ static funcentry_T global_functions[] =
|
||||
ret_list_string, f_spellsuggest},
|
||||
{"split", 1, 3, FEARG_1, NULL,
|
||||
ret_list_string, f_split},
|
||||
{"sqrt", 1, 1, FEARG_1, NULL,
|
||||
{"sqrt", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_sqrt)},
|
||||
{"srand", 0, 1, FEARG_1, NULL,
|
||||
ret_list_number, f_srand},
|
||||
@@ -1594,9 +1620,9 @@ static funcentry_T global_functions[] =
|
||||
ret_list_string, f_tagfiles},
|
||||
{"taglist", 1, 2, FEARG_1, NULL,
|
||||
ret_list_dict_any, f_taglist},
|
||||
{"tan", 1, 1, FEARG_1, NULL,
|
||||
{"tan", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_tan)},
|
||||
{"tanh", 1, 1, FEARG_1, NULL,
|
||||
{"tanh", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_tanh)},
|
||||
{"tempname", 0, 0, 0, NULL,
|
||||
ret_string, f_tempname},
|
||||
@@ -1674,6 +1700,8 @@ static funcentry_T global_functions[] =
|
||||
ret_void, f_test_garbagecollect_soon},
|
||||
{"test_getvalue", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_test_getvalue},
|
||||
{"test_gui_mouse_event", 5, 5, 0, NULL,
|
||||
ret_void, f_test_gui_mouse_event},
|
||||
{"test_ignore_error", 1, 1, FEARG_1, NULL,
|
||||
ret_void, f_test_ignore_error},
|
||||
{"test_null_blob", 0, 0, 0, NULL,
|
||||
@@ -1726,15 +1754,15 @@ static funcentry_T global_functions[] =
|
||||
ret_void, TIMER_FUNC(f_timer_stop)},
|
||||
{"timer_stopall", 0, 0, 0, NULL,
|
||||
ret_void, TIMER_FUNC(f_timer_stopall)},
|
||||
{"tolower", 1, 1, FEARG_1, NULL,
|
||||
{"tolower", 1, 1, FEARG_1, arg1_string,
|
||||
ret_string, f_tolower},
|
||||
{"toupper", 1, 1, FEARG_1, NULL,
|
||||
{"toupper", 1, 1, FEARG_1, arg1_string,
|
||||
ret_string, f_toupper},
|
||||
{"tr", 3, 3, FEARG_1, NULL,
|
||||
{"tr", 3, 3, FEARG_1, arg3_string,
|
||||
ret_string, f_tr},
|
||||
{"trim", 1, 3, FEARG_1, NULL,
|
||||
ret_string, f_trim},
|
||||
{"trunc", 1, 1, FEARG_1, NULL,
|
||||
{"trunc", 1, 1, FEARG_1, arg1_float_or_nr,
|
||||
ret_float, FLOAT_FUNC(f_trunc)},
|
||||
{"type", 1, 1, FEARG_1, NULL,
|
||||
ret_number, f_type},
|
||||
@@ -1760,27 +1788,27 @@ static funcentry_T global_functions[] =
|
||||
ret_list_number, f_win_findbuf},
|
||||
{"win_getid", 0, 2, FEARG_1, NULL,
|
||||
ret_number, f_win_getid},
|
||||
{"win_gettype", 0, 1, FEARG_1, NULL,
|
||||
{"win_gettype", 0, 1, FEARG_1, arg1_number,
|
||||
ret_string, f_win_gettype},
|
||||
{"win_gotoid", 1, 1, FEARG_1, NULL,
|
||||
{"win_gotoid", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number_bool, f_win_gotoid},
|
||||
{"win_id2tabwin", 1, 1, FEARG_1, NULL,
|
||||
{"win_id2tabwin", 1, 1, FEARG_1, arg1_number,
|
||||
ret_list_number, f_win_id2tabwin},
|
||||
{"win_id2win", 1, 1, FEARG_1, NULL,
|
||||
{"win_id2win", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number, f_win_id2win},
|
||||
{"win_screenpos", 1, 1, FEARG_1, NULL,
|
||||
{"win_screenpos", 1, 1, FEARG_1, arg1_number,
|
||||
ret_list_number, f_win_screenpos},
|
||||
{"win_splitmove", 2, 3, FEARG_1, NULL,
|
||||
ret_number_bool, f_win_splitmove},
|
||||
{"winbufnr", 1, 1, FEARG_1, NULL,
|
||||
{"winbufnr", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number, f_winbufnr},
|
||||
{"wincol", 0, 0, 0, NULL,
|
||||
ret_number, f_wincol},
|
||||
{"windowsversion", 0, 0, 0, NULL,
|
||||
ret_string, f_windowsversion},
|
||||
{"winheight", 1, 1, FEARG_1, NULL,
|
||||
{"winheight", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number, f_winheight},
|
||||
{"winlayout", 0, 1, FEARG_1, NULL,
|
||||
{"winlayout", 0, 1, FEARG_1, arg1_number,
|
||||
ret_list_any, f_winlayout},
|
||||
{"winline", 0, 0, 0, NULL,
|
||||
ret_number, f_winline},
|
||||
@@ -1792,13 +1820,13 @@ static funcentry_T global_functions[] =
|
||||
ret_void, f_winrestview},
|
||||
{"winsaveview", 0, 0, 0, NULL,
|
||||
ret_dict_number, f_winsaveview},
|
||||
{"winwidth", 1, 1, FEARG_1, NULL,
|
||||
{"winwidth", 1, 1, FEARG_1, arg1_number,
|
||||
ret_number, f_winwidth},
|
||||
{"wordcount", 0, 0, 0, NULL,
|
||||
ret_dict_number, f_wordcount},
|
||||
{"writefile", 2, 3, FEARG_1, NULL,
|
||||
ret_number_bool, f_writefile},
|
||||
{"xor", 2, 2, FEARG_1, NULL,
|
||||
{"xor", 2, 2, FEARG_1, arg2_number,
|
||||
ret_number, f_xor},
|
||||
};
|
||||
|
||||
@@ -5091,6 +5119,13 @@ f_has(typval_T *argvars, typval_T *rettv)
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{"sodium",
|
||||
#ifdef FEAT_SODIUM
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{"sound",
|
||||
|
||||
+17
-4
@@ -3643,6 +3643,17 @@ skip_substitute(char_u *start, int delimiter)
|
||||
return p;
|
||||
}
|
||||
|
||||
static int
|
||||
check_regexp_delim(int c)
|
||||
{
|
||||
if (isalpha(c))
|
||||
{
|
||||
emsg(_("E146: Regular expressions can't be delimited by letters"));
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a substitution from line eap->line1 to line eap->line2 using the
|
||||
* command pointed to by eap->arg which should be of the form:
|
||||
@@ -3705,11 +3716,9 @@ ex_substitute(exarg_T *eap)
|
||||
&& vim_strchr((char_u *)"0123456789cegriIp|\"", *cmd) == NULL)
|
||||
{
|
||||
// don't accept alphanumeric for separator
|
||||
if (isalpha(*cmd))
|
||||
{
|
||||
emsg(_("E146: Regular expressions can't be delimited by letters"));
|
||||
if (check_regexp_delim(*cmd) == FAIL)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* undocumented vi feature:
|
||||
* "\/sub/" and "\?sub?" use last used search pattern (almost like
|
||||
@@ -4909,6 +4918,10 @@ ex_global(exarg_T *eap)
|
||||
emsg(_("E148: Regular expression missing from global"));
|
||||
return;
|
||||
}
|
||||
else if (check_regexp_delim(*cmd) == FAIL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
delim = *cmd; // get the delimiter
|
||||
|
||||
+11
-5
@@ -3491,6 +3491,8 @@ find_ex_command(
|
||||
// can't be an assignment.
|
||||
if (*eap->cmd == '[')
|
||||
{
|
||||
char_u *eq;
|
||||
|
||||
p = to_name_const_end(eap->cmd);
|
||||
if (p == eap->cmd && *p == '[')
|
||||
{
|
||||
@@ -3499,12 +3501,19 @@ find_ex_command(
|
||||
|
||||
p = skip_var_list(eap->cmd, TRUE, &count, &semicolon, TRUE);
|
||||
}
|
||||
if (p == NULL || p == eap->cmd || *skipwhite(p) != '=')
|
||||
eq = p;
|
||||
if (eq != NULL)
|
||||
{
|
||||
eq = skipwhite(eq);
|
||||
if (vim_strchr((char_u *)"+-*/%", *eq) != NULL)
|
||||
++eq;
|
||||
}
|
||||
if (p == NULL || p == eap->cmd || *eq != '=')
|
||||
{
|
||||
eap->cmdidx = CMD_eval;
|
||||
return eap->cmd;
|
||||
}
|
||||
if (p > eap->cmd && *skipwhite(p) == '=')
|
||||
if (p > eap->cmd && *eq == '=')
|
||||
{
|
||||
eap->cmdidx = CMD_var;
|
||||
return eap->cmd;
|
||||
@@ -4529,9 +4538,6 @@ invalid_range(exarg_T *eap)
|
||||
#endif
|
||||
break;
|
||||
case ADDR_UNSIGNED:
|
||||
if (eap->line2 < 0)
|
||||
return _(e_invrange);
|
||||
break;
|
||||
case ADDR_NONE:
|
||||
// Will give an error elsewhere.
|
||||
break;
|
||||
|
||||
@@ -596,6 +596,13 @@
|
||||
# define FEAT_SOUND_CANBERRA
|
||||
#endif
|
||||
|
||||
/*
|
||||
* libsodium - add cryptography support
|
||||
*/
|
||||
#if defined(HAVE_SODIUM) && defined(FEAT_BIG)
|
||||
# define FEAT_SODIUM
|
||||
#endif
|
||||
|
||||
// There are two ways to use XPM.
|
||||
#if (defined(HAVE_XM_XPMP_H) && defined(FEAT_GUI_MOTIF)) \
|
||||
|| defined(HAVE_X11_XPM_H)
|
||||
|
||||
+40
-2
@@ -13,6 +13,10 @@
|
||||
|
||||
#include "vim.h"
|
||||
|
||||
#ifdef FEAT_SODIUM
|
||||
# include <sodium.h>
|
||||
#endif
|
||||
|
||||
#if defined(__TANDEM)
|
||||
# include <limits.h> // for SSIZE_MAX
|
||||
#endif
|
||||
@@ -148,6 +152,8 @@ readfile(
|
||||
char_u *p;
|
||||
off_T filesize = 0;
|
||||
int skip_read = FALSE;
|
||||
off_T filesize_disk = 0; // file size read from disk
|
||||
off_T filesize_count = 0; // counter
|
||||
#ifdef FEAT_CRYPT
|
||||
char_u *cryptkey = NULL;
|
||||
int did_ask_for_key = FALSE;
|
||||
@@ -215,6 +221,7 @@ readfile(
|
||||
int using_b_ffname;
|
||||
int using_b_fname;
|
||||
static char *msg_is_a_directory = N_("is a directory");
|
||||
int eof;
|
||||
|
||||
au_did_filetype = FALSE; // reset before triggering any autocommands
|
||||
|
||||
@@ -405,6 +412,7 @@ readfile(
|
||||
{
|
||||
buf_store_time(curbuf, &st, fname);
|
||||
curbuf->b_mtime_read = curbuf->b_mtime;
|
||||
filesize_disk = st.st_size;
|
||||
#ifdef UNIX
|
||||
/*
|
||||
* Use the protection bits of the original file for the swap file.
|
||||
@@ -1080,6 +1088,7 @@ retry:
|
||||
{
|
||||
linerest = 0;
|
||||
filesize = 0;
|
||||
filesize_count = 0;
|
||||
skip_count = lines_to_skip;
|
||||
read_count = lines_to_read;
|
||||
conv_restlen = 0;
|
||||
@@ -1204,6 +1213,7 @@ retry:
|
||||
* Read bytes from curbuf. Used for converting text read
|
||||
* from stdin.
|
||||
*/
|
||||
eof = FALSE;
|
||||
if (read_buf_lnum > from)
|
||||
size = 0;
|
||||
else
|
||||
@@ -1252,6 +1262,7 @@ retry:
|
||||
if (!curbuf->b_p_eol)
|
||||
--tlen;
|
||||
size = tlen;
|
||||
eof = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1263,7 +1274,23 @@ retry:
|
||||
/*
|
||||
* Read bytes from the file.
|
||||
*/
|
||||
# ifdef FEAT_SODIUM
|
||||
// Let the crypt layer work with a buffer size of 8192
|
||||
if (filesize == 0)
|
||||
// set size to 8K + Sodium Crypt Metadata
|
||||
size = WRITEBUFSIZE + crypt_get_max_header_len()
|
||||
+ crypto_secretstream_xchacha20poly1305_HEADERBYTES
|
||||
+ crypto_secretstream_xchacha20poly1305_ABYTES;
|
||||
|
||||
else if (filesize > 0 && (curbuf->b_cryptstate != NULL &&
|
||||
curbuf->b_cryptstate->method_nr == CRYPT_M_SOD))
|
||||
size = WRITEBUFSIZE + crypto_secretstream_xchacha20poly1305_ABYTES;
|
||||
# endif
|
||||
eof = size;
|
||||
size = read_eintr(fd, ptr, size);
|
||||
filesize_count += size;
|
||||
// hit end of file
|
||||
eof = (size < eof || filesize_count == filesize_disk);
|
||||
}
|
||||
|
||||
#ifdef FEAT_CRYPT
|
||||
@@ -1285,7 +1312,8 @@ retry:
|
||||
if (crypt_works_inplace(curbuf->b_cryptstate))
|
||||
{
|
||||
# endif
|
||||
crypt_decode_inplace(curbuf->b_cryptstate, ptr, size);
|
||||
crypt_decode_inplace(curbuf->b_cryptstate, ptr,
|
||||
size, eof);
|
||||
# ifdef CRYPT_NOT_INPLACE
|
||||
}
|
||||
else
|
||||
@@ -1294,8 +1322,16 @@ retry:
|
||||
int decrypted_size;
|
||||
|
||||
decrypted_size = crypt_decode_alloc(
|
||||
curbuf->b_cryptstate, ptr, size, &newptr);
|
||||
curbuf->b_cryptstate, ptr, size,
|
||||
&newptr, eof);
|
||||
|
||||
if (decrypted_size < 0)
|
||||
{
|
||||
// error message already given
|
||||
error = TRUE;
|
||||
vim_free(newptr);
|
||||
break;
|
||||
}
|
||||
// If the crypt layer is buffering, not producing
|
||||
// anything yet, need to read more.
|
||||
if (decrypted_size == 0)
|
||||
@@ -1325,6 +1361,7 @@ retry:
|
||||
if (newptr != NULL)
|
||||
mch_memmove(new_buffer + linerest, newptr,
|
||||
decrypted_size);
|
||||
vim_free(newptr);
|
||||
}
|
||||
|
||||
if (new_buffer != NULL)
|
||||
@@ -1334,6 +1371,7 @@ retry:
|
||||
new_buffer = NULL;
|
||||
line_start = buffer;
|
||||
ptr = buffer + linerest;
|
||||
real_size = size;
|
||||
}
|
||||
size = decrypted_size;
|
||||
}
|
||||
|
||||
@@ -418,6 +418,9 @@ EXTERN type_T t_blob INIT6(VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
|
||||
EXTERN type_T t_job INIT6(VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL);
|
||||
EXTERN type_T t_channel INIT6(VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL);
|
||||
|
||||
// Special value used for @#.
|
||||
EXTERN type_T t_number_or_string INIT6(VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL);
|
||||
|
||||
EXTERN type_T t_func_unknown INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_unknown, NULL);
|
||||
EXTERN type_T t_func_void INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_void, NULL);
|
||||
EXTERN type_T t_func_any INIT6(VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_any, NULL);
|
||||
|
||||
+31
-8
@@ -48,6 +48,11 @@
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
// for randombytes_buf
|
||||
#ifdef FEAT_SODIUM
|
||||
# include <sodium.h>
|
||||
#endif
|
||||
|
||||
#if defined(SASC) || defined(__amigaos4__)
|
||||
# include <proto/dos.h> // for Open() and Close()
|
||||
#endif
|
||||
@@ -64,12 +69,14 @@ typedef struct pointer_entry PTR_EN; // block/line-count pair
|
||||
#define BLOCK0_ID1_C0 'c' // block 0 id 1 'cm' 0
|
||||
#define BLOCK0_ID1_C1 'C' // block 0 id 1 'cm' 1
|
||||
#define BLOCK0_ID1_C2 'd' // block 0 id 1 'cm' 2
|
||||
#define BLOCK0_ID1_C3 'S' // block 0 id 1 'cm' 3 - but not actually used
|
||||
|
||||
#if defined(FEAT_CRYPT)
|
||||
static int id1_codes[] = {
|
||||
BLOCK0_ID1_C0, // CRYPT_M_ZIP
|
||||
BLOCK0_ID1_C1, // CRYPT_M_BF
|
||||
BLOCK0_ID1_C2, // CRYPT_M_BF2
|
||||
BLOCK0_ID1_C3, // CRYPT_M_SOD - Unused!
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -426,11 +433,15 @@ ml_set_mfp_crypt(buf_T *buf)
|
||||
{
|
||||
int method_nr = crypt_get_method_nr(buf);
|
||||
|
||||
if (method_nr > CRYPT_M_ZIP)
|
||||
if (method_nr > CRYPT_M_ZIP && method_nr < CRYPT_M_SOD)
|
||||
{
|
||||
// Generate a seed and store it in the memfile.
|
||||
sha2_seed(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN, NULL, 0);
|
||||
}
|
||||
#ifdef FEAT_SODIUM
|
||||
else if (method_nr == CRYPT_M_SOD)
|
||||
randombytes_buf(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,7 +458,7 @@ ml_set_b0_crypt(buf_T *buf, ZERO_BL *b0p)
|
||||
int method_nr = crypt_get_method_nr(buf);
|
||||
|
||||
b0p->b0_id[1] = id1_codes[method_nr];
|
||||
if (method_nr > CRYPT_M_ZIP)
|
||||
if (method_nr > CRYPT_M_ZIP && method_nr < CRYPT_M_SOD)
|
||||
{
|
||||
// Generate a seed and store it in block 0 and in the memfile.
|
||||
sha2_seed(&b0p->b0_seed, MF_SEED_LEN, NULL, 0);
|
||||
@@ -482,10 +493,18 @@ ml_set_crypt_key(
|
||||
int top;
|
||||
int old_method;
|
||||
|
||||
if (mfp == NULL)
|
||||
if (mfp == NULL || mfp->mf_fd < 0)
|
||||
return; // no memfile yet, nothing to do
|
||||
old_method = crypt_method_nr_from_name(old_cm);
|
||||
|
||||
// Swapfile encryption not supported by XChaCha20
|
||||
if (crypt_get_method_nr(buf) == CRYPT_M_SOD && *buf->b_p_key != NUL)
|
||||
{
|
||||
// close the swapfile
|
||||
mf_close_file(buf, TRUE);
|
||||
buf->b_p_swf = FALSE;
|
||||
return;
|
||||
}
|
||||
// First make sure the swapfile is in a consistent state, using the old
|
||||
// key and method.
|
||||
{
|
||||
@@ -911,7 +930,8 @@ ml_check_b0_id(ZERO_BL *b0p)
|
||||
|| (b0p->b0_id[1] != BLOCK0_ID1
|
||||
&& b0p->b0_id[1] != BLOCK0_ID1_C0
|
||||
&& b0p->b0_id[1] != BLOCK0_ID1_C1
|
||||
&& b0p->b0_id[1] != BLOCK0_ID1_C2)
|
||||
&& b0p->b0_id[1] != BLOCK0_ID1_C2
|
||||
&& b0p->b0_id[1] != BLOCK0_ID1_C3)
|
||||
)
|
||||
return FAIL;
|
||||
return OK;
|
||||
@@ -2402,7 +2422,9 @@ ml_sync_all(int check_file, int check_char)
|
||||
|
||||
FOR_ALL_BUFFERS(buf)
|
||||
{
|
||||
if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
|
||||
if (buf->b_ml.ml_mfp == NULL
|
||||
|| buf->b_ml.ml_mfp->mf_fname == NULL
|
||||
|| buf->b_ml.ml_mfp->mf_fd < 0)
|
||||
continue; // no file
|
||||
|
||||
ml_flush_line(buf); // flush buffered line
|
||||
@@ -5320,7 +5342,8 @@ ml_encrypt_data(
|
||||
mch_memmove(new_data, dp, head_end - (char_u *)dp);
|
||||
|
||||
// Encrypt the text.
|
||||
crypt_encode(state, text_start, text_len, new_data + dp->db_txt_start);
|
||||
crypt_encode(state, text_start, text_len, new_data + dp->db_txt_start,
|
||||
FALSE);
|
||||
crypt_free_state(state);
|
||||
|
||||
// Clear the gap.
|
||||
@@ -5360,7 +5383,7 @@ ml_decrypt_data(
|
||||
if (state != NULL)
|
||||
{
|
||||
// Decrypt the text in place.
|
||||
crypt_decode_inplace(state, text_start, text_len);
|
||||
crypt_decode_inplace(state, text_start, text_len, FALSE);
|
||||
crypt_free_state(state);
|
||||
}
|
||||
}
|
||||
@@ -5407,7 +5430,7 @@ ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading)
|
||||
// of the block for the salt.
|
||||
vim_snprintf((char *)salt, sizeof(salt), "%ld", (long)offset);
|
||||
return crypt_create(method_nr, key, salt, (int)STRLEN(salt),
|
||||
seed, MF_SEED_LEN);
|
||||
seed, MF_SEED_LEN);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+8
-3
@@ -1324,9 +1324,10 @@ do_set(
|
||||
// remember character after option name
|
||||
afterchar = arg[len];
|
||||
|
||||
// skip white space, allow ":set ai ?"
|
||||
while (VIM_ISWHITE(arg[len]))
|
||||
++len;
|
||||
if (!in_vim9script())
|
||||
// skip white space, allow ":set ai ?", ":set hlsearch !"
|
||||
while (VIM_ISWHITE(arg[len]))
|
||||
++len;
|
||||
|
||||
adding = FALSE;
|
||||
prepending = FALSE;
|
||||
@@ -2734,6 +2735,10 @@ set_bool_option(
|
||||
|| (opt_flags & OPT_GLOBAL) || opt_flags == 0)
|
||||
&& !curbufIsChanged() && curbuf->b_ml.ml_mfp != NULL)
|
||||
{
|
||||
#ifdef FEAT_CRYPT
|
||||
if (crypt_get_method_nr(curbuf) == CRYPT_M_SOD)
|
||||
continue;
|
||||
#endif
|
||||
u_compute_hash(hash);
|
||||
u_read_undo(NULL, hash, curbuf->b_fname);
|
||||
}
|
||||
|
||||
+5
-1
@@ -24,7 +24,11 @@ static char *(p_bo_values[]) = {"all", "backspace", "cursor", "complete",
|
||||
static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", "unsigned", NULL};
|
||||
static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL};
|
||||
#ifdef FEAT_CRYPT
|
||||
static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", NULL};
|
||||
static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2",
|
||||
# ifdef FEAT_SODIUM
|
||||
"xchacha20",
|
||||
# endif
|
||||
NULL};
|
||||
#endif
|
||||
static char *(p_cmp_values[]) = {"internal", "keepascii", NULL};
|
||||
static char *(p_dy_values[]) = {"lastline", "truncate", "uhex", NULL};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* blowfish.c */
|
||||
void crypt_blowfish_encode(cryptstate_T *state, char_u *from, size_t len, char_u *to);
|
||||
void crypt_blowfish_decode(cryptstate_T *state, char_u *from, size_t len, char_u *to);
|
||||
void crypt_blowfish_encode(cryptstate_T *state, char_u *from, size_t len, char_u *to, int last);
|
||||
void crypt_blowfish_decode(cryptstate_T *state, char_u *from, size_t len, char_u *to, int last);
|
||||
int crypt_blowfish_init(cryptstate_T *state, char_u *key, char_u *salt, int salt_len, char_u *seed, int seed_len);
|
||||
int blowfish_self_test(void);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
+10
-3
@@ -1,9 +1,11 @@
|
||||
/* crypt.c */
|
||||
int crypt_method_nr_from_name(char_u *name);
|
||||
int crypt_method_nr_from_magic(char *ptr, int len);
|
||||
int crypt_works_inplace(cryptstate_T *state);
|
||||
int crypt_get_method_nr(buf_T *buf);
|
||||
int crypt_whole_undofile(int method_nr);
|
||||
int crypt_get_header_len(int method_nr);
|
||||
int crypt_get_max_header_len(void);
|
||||
void crypt_set_cm_option(buf_T *buf, int method_nr);
|
||||
int crypt_self_test(void);
|
||||
cryptstate_T *crypt_create(int method_nr, char_u *key, char_u *salt, int salt_len, char_u *seed, int seed_len);
|
||||
@@ -11,12 +13,17 @@ cryptstate_T *crypt_create_from_header(int method_nr, char_u *key, char_u *heade
|
||||
cryptstate_T *crypt_create_from_file(FILE *fp, char_u *key);
|
||||
cryptstate_T *crypt_create_for_writing(int method_nr, char_u *key, char_u **header, int *header_len);
|
||||
void crypt_free_state(cryptstate_T *state);
|
||||
void crypt_encode(cryptstate_T *state, char_u *from, size_t len, char_u *to);
|
||||
void crypt_encode_inplace(cryptstate_T *state, char_u *buf, size_t len);
|
||||
void crypt_decode_inplace(cryptstate_T *state, char_u *buf, size_t len);
|
||||
long crypt_encode_alloc(cryptstate_T *state, char_u *from, size_t len, char_u **newptr, int last);
|
||||
long crypt_decode_alloc(cryptstate_T *state, char_u *ptr, long len, char_u **newptr, int last);
|
||||
void crypt_encode(cryptstate_T *state, char_u *from, size_t len, char_u *to, int last);
|
||||
void crypt_encode_inplace(cryptstate_T *state, char_u *buf, size_t len, int last);
|
||||
void crypt_decode_inplace(cryptstate_T *state, char_u *buf, size_t len, int last);
|
||||
void crypt_free_key(char_u *key);
|
||||
void crypt_check_method(int method);
|
||||
void crypt_check_current_method(void);
|
||||
char_u *crypt_get_key(int store, int twice);
|
||||
void crypt_append_msg(buf_T *buf);
|
||||
int crypt_sodium_init(cryptstate_T *state, char_u *key, char_u *salt, int salt_len, char_u *seed, int seed_len);
|
||||
long crypt_sodium_buffer_encode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last);
|
||||
long crypt_sodium_buffer_decode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* crypt_zip.c */
|
||||
int crypt_zip_init(cryptstate_T *state, char_u *key, char_u *salt, int salt_len, char_u *seed, int seed_len);
|
||||
void crypt_zip_encode(cryptstate_T *state, char_u *from, size_t len, char_u *to);
|
||||
void crypt_zip_decode(cryptstate_T *state, char_u *from, size_t len, char_u *to);
|
||||
void crypt_zip_encode(cryptstate_T *state, char_u *from, size_t len, char_u *to, int last);
|
||||
void crypt_zip_decode(cryptstate_T *state, char_u *from, size_t len, char_u *to, int last);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
@@ -34,5 +34,6 @@ void f_test_unknown(typval_T *argvars, typval_T *rettv);
|
||||
void f_test_void(typval_T *argvars, typval_T *rettv);
|
||||
void f_test_scrollbar(typval_T *argvars, typval_T *rettv);
|
||||
void f_test_setmouse(typval_T *argvars, typval_T *rettv);
|
||||
void f_test_gui_mouse_event(typval_T *argvars, typval_T *rettv);
|
||||
void f_test_settime(typval_T *argvars, typval_T *rettv);
|
||||
/* vim: set ft=c : */
|
||||
|
||||
+81
-22
@@ -30,13 +30,16 @@ struct qfline_S
|
||||
qfline_T *qf_next; // pointer to next error in the list
|
||||
qfline_T *qf_prev; // pointer to previous error in the list
|
||||
linenr_T qf_lnum; // line number where the error occurred
|
||||
linenr_T qf_end_lnum; // line number when the error has range or zero
|
||||
int qf_fnum; // file number for the line
|
||||
int qf_col; // column where the error occurred
|
||||
int qf_end_col; // column when the error has range or zero
|
||||
int qf_nr; // error number
|
||||
char_u *qf_module; // module name for this error
|
||||
char_u *qf_pattern; // search pattern for the error
|
||||
char_u *qf_text; // description of the error
|
||||
char_u qf_viscol; // set to TRUE if qf_col is screen column
|
||||
char_u qf_viscol; // set to TRUE if qf_col and qf_end_col is
|
||||
// screen column
|
||||
char_u qf_cleared; // set to TRUE if line has been deleted
|
||||
char_u qf_type; // type of the error (mostly 'E'); 1 for
|
||||
// :helpgrep
|
||||
@@ -165,7 +168,7 @@ static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls
|
||||
static callback_T qftf_cb;
|
||||
|
||||
static void qf_new_list(qf_info_T *qi, char_u *qf_title);
|
||||
static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid);
|
||||
static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, long end_lnum, int col, int end_col, int vis_col, char_u *pattern, int nr, int type, int valid);
|
||||
static void qf_free(qf_list_T *qfl);
|
||||
static char_u *qf_types(int, int);
|
||||
static int qf_get_fnum(qf_list_T *qfl, char_u *, char_u *);
|
||||
@@ -174,6 +177,7 @@ static char_u *qf_pop_dir(struct dir_stack_T **);
|
||||
static char_u *qf_guess_filepath(qf_list_T *qfl, char_u *);
|
||||
static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, int newwin);
|
||||
static void qf_fmt_text(char_u *text, char_u *buf, int bufsize);
|
||||
static void qf_range_text(qfline_T *qfp, char_u *buf, int bufsize);
|
||||
static int qf_win_pos_update(qf_info_T *qi, int old_qf_index);
|
||||
static win_T *qf_find_win(qf_info_T *qi);
|
||||
static buf_T *qf_find_buf(qf_info_T *qi);
|
||||
@@ -899,7 +903,9 @@ typedef struct {
|
||||
char_u *errmsg;
|
||||
int errmsglen;
|
||||
long lnum;
|
||||
long end_lnum;
|
||||
int col;
|
||||
int end_col;
|
||||
char_u use_viscol;
|
||||
char_u *pattern;
|
||||
int enr;
|
||||
@@ -1235,7 +1241,9 @@ qf_parse_get_fields(
|
||||
if (!qf_multiscan)
|
||||
fields->errmsg[0] = NUL;
|
||||
fields->lnum = 0;
|
||||
fields->end_lnum = 0;
|
||||
fields->col = 0;
|
||||
fields->end_col = 0;
|
||||
fields->use_viscol = FALSE;
|
||||
fields->enr = -1;
|
||||
fields->type = 0;
|
||||
@@ -1630,7 +1638,9 @@ qf_init_process_nextline(
|
||||
0,
|
||||
fields->errmsg,
|
||||
fields->lnum,
|
||||
fields->end_lnum,
|
||||
fields->col,
|
||||
fields->end_col,
|
||||
fields->use_viscol,
|
||||
fields->pattern,
|
||||
fields->enr,
|
||||
@@ -2053,7 +2063,9 @@ qf_add_entry(
|
||||
int bufnum, // buffer number or zero
|
||||
char_u *mesg, // message
|
||||
long lnum, // line number
|
||||
long end_lnum, // line number for end
|
||||
int col, // column
|
||||
int end_col, // column for end
|
||||
int vis_col, // using visual column
|
||||
char_u *pattern, // search pattern
|
||||
int nr, // error number
|
||||
@@ -2082,7 +2094,9 @@ qf_add_entry(
|
||||
return QF_FAIL;
|
||||
}
|
||||
qfp->qf_lnum = lnum;
|
||||
qfp->qf_end_lnum = end_lnum;
|
||||
qfp->qf_col = col;
|
||||
qfp->qf_end_col = end_col;
|
||||
qfp->qf_viscol = vis_col;
|
||||
if (pattern == NULL || *pattern == NUL)
|
||||
qfp->qf_pattern = NULL;
|
||||
@@ -2239,7 +2253,9 @@ copy_loclist_entries(qf_list_T *from_qfl, qf_list_T *to_qfl)
|
||||
0,
|
||||
from_qfp->qf_text,
|
||||
from_qfp->qf_lnum,
|
||||
from_qfp->qf_end_lnum,
|
||||
from_qfp->qf_col,
|
||||
from_qfp->qf_end_col,
|
||||
from_qfp->qf_viscol,
|
||||
from_qfp->qf_pattern,
|
||||
from_qfp->qf_nr,
|
||||
@@ -3555,11 +3571,8 @@ qf_list_entry(qfline_T *qfp, int qf_idx, int cursel)
|
||||
msg_puts_attr(":", qfSepAttr);
|
||||
if (qfp->qf_lnum == 0)
|
||||
IObuff[0] = NUL;
|
||||
else if (qfp->qf_col == 0)
|
||||
sprintf((char *)IObuff, "%ld", qfp->qf_lnum);
|
||||
else
|
||||
sprintf((char *)IObuff, "%ld col %d",
|
||||
qfp->qf_lnum, qfp->qf_col);
|
||||
qf_range_text(qfp, IObuff, IOSIZE);
|
||||
sprintf((char *)IObuff + STRLEN(IObuff), "%s",
|
||||
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
|
||||
msg_puts_attr((char *)IObuff, qfLineAttr);
|
||||
@@ -3685,6 +3698,37 @@ qf_fmt_text(char_u *text, char_u *buf, int bufsize)
|
||||
buf[i] = NUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Range information from lnum, col, end_lnum, and end_col.
|
||||
* Put the result in "buf[bufsize]".
|
||||
*/
|
||||
static void
|
||||
qf_range_text(qfline_T *qfp, char_u *buf, int bufsize)
|
||||
{
|
||||
int len;
|
||||
vim_snprintf((char *)buf, bufsize, "%ld", qfp->qf_lnum);
|
||||
len = (int)STRLEN(buf);
|
||||
|
||||
if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum)
|
||||
{
|
||||
vim_snprintf((char *)buf + len, bufsize - len,
|
||||
"-%ld", qfp->qf_end_lnum);
|
||||
len += (int)STRLEN(buf + len);
|
||||
}
|
||||
if (qfp->qf_col > 0)
|
||||
{
|
||||
vim_snprintf((char *)buf + len, bufsize - len, " col %d", qfp->qf_col);
|
||||
len += (int)STRLEN(buf + len);
|
||||
if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col)
|
||||
{
|
||||
vim_snprintf((char *)buf + len, bufsize - len,
|
||||
"-%d", qfp->qf_end_col);
|
||||
len += (int)STRLEN(buf + len);
|
||||
}
|
||||
}
|
||||
buf[len] = NUL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display information (list number, list size and the title) about a
|
||||
* quickfix/location list.
|
||||
@@ -4473,7 +4517,17 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
|
||||
int qf_winid = 0;
|
||||
|
||||
if (IS_LL_STACK(qi))
|
||||
qf_winid = curwin->w_id;
|
||||
{
|
||||
if (curwin->w_llist == qi)
|
||||
win = curwin;
|
||||
else
|
||||
{
|
||||
win = qf_find_win_with_loclist(qi);
|
||||
if (win == NULL)
|
||||
return;
|
||||
}
|
||||
qf_winid = win->w_id;
|
||||
}
|
||||
|
||||
if (old_last == NULL)
|
||||
// set curwin/curbuf to buf and save a few things
|
||||
@@ -4555,17 +4609,9 @@ qf_buf_add_line(
|
||||
|
||||
if (qfp->qf_lnum > 0)
|
||||
{
|
||||
vim_snprintf((char *)IObuff + len, IOSIZE - len, "%ld",
|
||||
qfp->qf_lnum);
|
||||
qf_range_text(qfp, IObuff + len, IOSIZE - len);
|
||||
len += (int)STRLEN(IObuff + len);
|
||||
|
||||
if (qfp->qf_col > 0)
|
||||
{
|
||||
vim_snprintf((char *)IObuff + len, IOSIZE - len,
|
||||
" col %d", qfp->qf_col);
|
||||
len += (int)STRLEN(IObuff + len);
|
||||
}
|
||||
|
||||
vim_snprintf((char *)IObuff + len, IOSIZE - len, "%s",
|
||||
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
|
||||
len += (int)STRLEN(IObuff + len);
|
||||
@@ -5943,7 +5989,9 @@ vgr_match_buflines(
|
||||
ml_get_buf(buf,
|
||||
regmatch->startpos[0].lnum + lnum, FALSE),
|
||||
regmatch->startpos[0].lnum + lnum,
|
||||
regmatch->endpos[0].lnum + lnum,
|
||||
regmatch->startpos[0].col + 1,
|
||||
regmatch->endpos[0].col + 1,
|
||||
FALSE, // vis_col
|
||||
NULL, // search pattern
|
||||
0, // nr
|
||||
@@ -5986,7 +6034,9 @@ vgr_match_buflines(
|
||||
duplicate_name ? 0 : buf->b_fnum,
|
||||
str,
|
||||
lnum,
|
||||
0,
|
||||
matches[0] + col + 1,
|
||||
0,
|
||||
FALSE, // vis_col
|
||||
NULL, // search pattern
|
||||
0, // nr
|
||||
@@ -6616,10 +6666,12 @@ get_qfline_items(qfline_T *qfp, list_T *list)
|
||||
buf[0] = qfp->qf_type;
|
||||
buf[1] = NUL;
|
||||
if (dict_add_number(dict, "bufnr", (long)bufnum) == FAIL
|
||||
|| dict_add_number(dict, "lnum", (long)qfp->qf_lnum) == FAIL
|
||||
|| dict_add_number(dict, "col", (long)qfp->qf_col) == FAIL
|
||||
|| dict_add_number(dict, "vcol", (long)qfp->qf_viscol) == FAIL
|
||||
|| dict_add_number(dict, "nr", (long)qfp->qf_nr) == FAIL
|
||||
|| dict_add_number(dict, "lnum", (long)qfp->qf_lnum) == FAIL
|
||||
|| dict_add_number(dict, "end_lnum", (long)qfp->qf_end_lnum) == FAIL
|
||||
|| dict_add_number(dict, "col", (long)qfp->qf_col) == FAIL
|
||||
|| dict_add_number(dict, "end_col", (long)qfp->qf_end_col) == FAIL
|
||||
|| dict_add_number(dict, "vcol", (long)qfp->qf_viscol) == FAIL
|
||||
|| dict_add_number(dict, "nr", (long)qfp->qf_nr) == FAIL
|
||||
|| dict_add_string(dict, "module", qfp->qf_module) == FAIL
|
||||
|| dict_add_string(dict, "pattern", qfp->qf_pattern) == FAIL
|
||||
|| dict_add_string(dict, "text", qfp->qf_text) == FAIL
|
||||
@@ -7133,8 +7185,8 @@ qf_add_entry_from_dict(
|
||||
{
|
||||
static int did_bufnr_emsg;
|
||||
char_u *filename, *module, *pattern, *text, *type;
|
||||
int bufnum, valid, status, col, vcol, nr;
|
||||
long lnum;
|
||||
int bufnum, valid, status, col, end_col, vcol, nr;
|
||||
long lnum, end_lnum;
|
||||
|
||||
if (first_entry)
|
||||
did_bufnr_emsg = FALSE;
|
||||
@@ -7143,7 +7195,9 @@ qf_add_entry_from_dict(
|
||||
module = dict_get_string(d, (char_u *)"module", TRUE);
|
||||
bufnum = (int)dict_get_number(d, (char_u *)"bufnr");
|
||||
lnum = (int)dict_get_number(d, (char_u *)"lnum");
|
||||
end_lnum = (int)dict_get_number(d, (char_u *)"end_lnum");
|
||||
col = (int)dict_get_number(d, (char_u *)"col");
|
||||
end_col = (int)dict_get_number(d, (char_u *)"end_col");
|
||||
vcol = (int)dict_get_number(d, (char_u *)"vcol");
|
||||
nr = (int)dict_get_number(d, (char_u *)"nr");
|
||||
type = dict_get_string(d, (char_u *)"type", TRUE);
|
||||
@@ -7180,7 +7234,9 @@ qf_add_entry_from_dict(
|
||||
bufnum,
|
||||
text,
|
||||
lnum,
|
||||
end_lnum,
|
||||
col,
|
||||
end_col,
|
||||
vcol, // vis_col
|
||||
pattern, // search pattern
|
||||
nr,
|
||||
@@ -8048,8 +8104,11 @@ hgr_search_file(
|
||||
0,
|
||||
line,
|
||||
lnum,
|
||||
0,
|
||||
(int)(p_regmatch->startp[0] - line)
|
||||
+ 1, // col
|
||||
(int)(p_regmatch->endp[0] - line)
|
||||
+ 1, // end_col
|
||||
FALSE, // vis_col
|
||||
NULL, // search pattern
|
||||
0, // nr
|
||||
|
||||
@@ -462,6 +462,9 @@ stuff_yank(int regname, char_u *p)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Last executed register (@ command)
|
||||
*/
|
||||
static int execreg_lastc = NUL;
|
||||
|
||||
int
|
||||
|
||||
+8
-2
@@ -1629,6 +1629,11 @@ typedef struct
|
||||
# endif
|
||||
|
||||
garray_T uf_lines; // function lines
|
||||
|
||||
int uf_debug_tick; // when last checked for a breakpoint in this
|
||||
// function.
|
||||
int uf_has_breakpoint; // TRUE when a breakpoint has been set in
|
||||
// this function.
|
||||
# ifdef FEAT_PROFILE
|
||||
int uf_profiling; // TRUE when func is being profiled
|
||||
int uf_prof_initialized;
|
||||
@@ -2516,11 +2521,12 @@ typedef struct {
|
||||
# define CRYPT_M_ZIP 0
|
||||
# define CRYPT_M_BF 1
|
||||
# define CRYPT_M_BF2 2
|
||||
# define CRYPT_M_COUNT 3 // number of crypt methods
|
||||
# define CRYPT_M_SOD 3
|
||||
# define CRYPT_M_COUNT 4 // number of crypt methods
|
||||
|
||||
// Currently all crypt methods work inplace. If one is added that isn't then
|
||||
// define this.
|
||||
// # define CRYPT_NOT_INPLACE 1
|
||||
# define CRYPT_NOT_INPLACE 1
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|m|a|t|c|h|e|s| @67
|
||||
|~+0#4040ff13&| @73
|
||||
|X+1#0000000&|C|w|i|n|d|o|w| @48|1|,|4| @11|A|l@1
|
||||
>X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4||+0#0000000&| |s|o|m|e| @52
|
||||
|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2||+0#0000000&| |t|e|x|t| @52
|
||||
|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6||+0#0000000&| |m|a|t|c|h|e|s| @49
|
||||
>X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4|-|5||+0#0000000&| |s|o|m|e| @50
|
||||
|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2|-|3||+0#0000000&| |t|e|x|t| @50
|
||||
|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6|-|7||+0#0000000&| |m|a|t|c|h|e|s| @47
|
||||
|~+0#4040ff13&| @73
|
||||
|[+3#0000000&|Q|u|i|c|k|f|i|x| |L|i|s|t|]| |:|v|i|m|g|r|e|p| |e| |X|C|w|i|n|d|o|w| @20|1|,|1| @12|A|l@1
|
||||
| +0&&@74
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|m|a|t|c|h|e|s| @67
|
||||
|~+0#4040ff13&| @73
|
||||
|X+3#0000000&|C|w|i|n|d|o|w| @48|2|,|2| @11|A|l@1
|
||||
|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4||+0#0000000&| |s|o|m|e| @52
|
||||
|X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2||+0#0000000&| |t|e|x|t| @52
|
||||
|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6||+0#0000000&| |m|a|t|c|h|e|s| @49
|
||||
|X+0#0000e05&|C|w|i|n|d|o|w||+0#0000000&|1+0#af5f00255&| |c|o|l| |4|-|5||+0#0000000&| |s|o|m|e| @50
|
||||
|X+0#0000e05#ffff4012|C|w|i|n|d|o|w||+0#0000000&|2+0#af5f00255&| |c|o|l| |2|-|3||+0#0000000&| |t|e|x|t| @50
|
||||
|X+0#0000e05#ffffff0|C|w|i|n|d|o|w||+0#0000000&|4+0#af5f00255&| |c|o|l| |6|-|7||+0#0000000&| |m|a|t|c|h|e|s| @47
|
||||
|~+0#4040ff13&| @73
|
||||
|[+1#0000000&|Q|u|i|c|k|f|i|x| |L|i|s|t|]| |:|v|i|m|g|r|e|p| |e| |X|C|w|i|n|d|o|w| @20|2|,|1| @12|A|l@1
|
||||
|:+0&&|c|n|e|x|t| @68
|
||||
|
||||
Binary file not shown.
@@ -374,6 +374,8 @@ func Test_mouse_position()
|
||||
call test_setmouse(5, 1)
|
||||
call feedkeys("\<LeftMouse>", "xt")
|
||||
call assert_equal([0, 2, 1, 0], getpos('.'))
|
||||
call assert_fails('call test_setmouse("", 2)', 'E474:')
|
||||
call assert_fails('call test_setmouse(1, "")', 'E474:')
|
||||
bwipe!
|
||||
let &mouse = save_mouse
|
||||
endfunc
|
||||
|
||||
+126
-1
@@ -22,6 +22,11 @@ func Test_head_only_3()
|
||||
call Common_head_only('VimCrypt~03!abc')
|
||||
endfunc
|
||||
|
||||
func Test_head_only_4()
|
||||
CheckFeature sodium
|
||||
call Common_head_only('VimCrypt~04!abc')
|
||||
endfunc
|
||||
|
||||
func Crypt_uncrypt(method)
|
||||
exe "set cryptmethod=" . a:method
|
||||
" If the blowfish test fails 'cryptmethod' will be 'zip' now.
|
||||
@@ -55,6 +60,11 @@ func Test_crypt_blowfish2()
|
||||
call Crypt_uncrypt('blowfish2')
|
||||
endfunc
|
||||
|
||||
func Test_crypt_sodium()
|
||||
CheckFeature sodium
|
||||
call Crypt_uncrypt('xchacha20')
|
||||
endfunc
|
||||
|
||||
func Uncrypt_stable(method, crypted_text, key, uncrypted_text)
|
||||
split Xtest.txt
|
||||
set bin noeol key= fenc=latin1
|
||||
@@ -70,6 +80,16 @@ func Uncrypt_stable(method, crypted_text, key, uncrypted_text)
|
||||
set key=
|
||||
endfunc
|
||||
|
||||
func Uncrypt_stable_xxd(method, hex, key, uncrypted_text)
|
||||
" use xxd to write the binary content
|
||||
call system('xxd -r >Xtest.txt', a:hex)
|
||||
call feedkeys(":split Xtest.txt\<CR>" . a:key . "\<CR>", 'xt')
|
||||
call assert_equal(a:uncrypted_text, getline(1, len(a:uncrypted_text)))
|
||||
bwipe!
|
||||
call delete('Xtest.txt')
|
||||
set key=
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_zip()
|
||||
call Uncrypt_stable('zip', "VimCrypt~01!\u0006\u001clV'\u00de}Mg\u00a0\u00ea\u00a3V\u00a9\u00e7\u0007E#3\u008e2U\u00e9\u0097", "foofoo", ["1234567890", "aábbccddeëff"])
|
||||
endfunc
|
||||
@@ -78,10 +98,115 @@ func Test_uncrypt_blowfish()
|
||||
call Uncrypt_stable('blowfish', "VimCrypt~02!k)\u00be\u0017\u0097#\u0016\u00ddS\u009c\u00f5=\u00ba\u00e0\u00c8#\u00a5M\u00b4\u0086J\u00c3A\u00cd\u00a5M\u00b4\u0086!\u0080\u0015\u009b\u00f5\u000f\u00e1\u00d2\u0019\u0082\u0016\u0098\u00f7\u000d\u00da", "barbar", ["asdfasdfasdf", "0001112223333"])
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_blowfish2()
|
||||
func Test_uncrypt_blowfish2a()
|
||||
call Uncrypt_stable('blowfish', "VimCrypt~03!\u001e\u00d1N\u00e3;\u00d3\u00c0\u00a0^C)\u0004\u00f7\u007f.\u00b6\u00abF\u000eS\u0019\u00e0\u008b6\u00d2[T\u00cb\u00a7\u0085\u00d8\u00be9\u000b\u00812\u000bQ\u00b3\u00cc@\u0097\u000f\u00df\u009a\u00adIv\u00aa.\u00d8\u00c9\u00ee\u009e`\u00bd$\u00af%\u00d0", "barburp", ["abcdefghijklmnopqrstuvwxyz", "!@#$%^&*()_+=-`~"])
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_blowfish2()
|
||||
call Uncrypt_stable('blowfish2', "VimCrypt~03!\u001e\u00d1N\u00e3;\u00d3\u00c0\u00a0^C)\u0004\u00f7\u007f.\u00b6\u00abF\u000eS\u0019\u00e0\u008b6\u00d2[T\u00cb\u00a7\u0085\u00d8\u00be9\u000b\u00812\u000bQ\u00b3\u00cc@\u0097\u000f\u00df\u009a\u00adIv\u00aa.\u00d8\u00c9\u00ee\u009e`\u00bd$\u00af%\u00d0", "barburp", ["abcdefghijklmnopqrstuvwxyz", "!@#$%^&*()_+=-`~"])
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_xchacha20()
|
||||
CheckFeature sodium
|
||||
let hex=['00000000: 5669 6d43 7279 7074 7e30 3421 6b7d e607 vimCrypt~04!k}..',
|
||||
\ '00000010: 4ea4 e99f 923e f67f 7b59 a80d 3bca 2f06 N....>..{Y..;./.',
|
||||
\ '00000020: fa11 b951 8d09 0dc9 470f e7cf 8b90 4310 ...Q....G.....C.',
|
||||
\ '00000030: 653b b83b e493 378b 0390 0e38 f912 626b e;.;..7....8..bk',
|
||||
\ '00000040: a02e 4697 0254 2625 2d8e 3a0b 784b e89c ..F..T&%-.:.xK..',
|
||||
\ '00000050: 0c67 a975 3c17 9319 8ffd 1463 7783 a1f3 .g.u<......cw...',
|
||||
\ '00000060: d917 dcb3 8b3e ecd7 c7d4 086b 6059 7ead .....>.....k`Y~.',
|
||||
\ '00000070: 9b07 f96b 5c1b 4d08 cd91 f208 5221 7484 ...k\.M.....R!t.',
|
||||
\ '00000080: 72be 0136 84a1 d3 r..6...']
|
||||
" the file should be in latin1 encoding, this makes sure that readfile()
|
||||
" retries several times converting the multi-byte characters
|
||||
call Uncrypt_stable_xxd('xchacha20', hex, "sodium_crypt", ["abcdefghijklmnopqrstuvwxyzäöü", "ZZZ_äüöÄÜÖ_!@#$%^&*()_+=-`~"])
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_xchacha20_invalid()
|
||||
CheckFeature sodium
|
||||
" load an invalid encrypted file and verify it can be decrypted with an
|
||||
" error message
|
||||
try
|
||||
call feedkeys(":split samples/crypt_sodium_invalid.txt\<CR>sodium\<CR>", 'xt')
|
||||
call assert_false(1, 'should not happen')
|
||||
catch
|
||||
call assert_exception('pre-mature')
|
||||
endtry
|
||||
call assert_match("Note: Encryption of swapfile not supported, disabling swap- and undofile", execute(':5messages'))
|
||||
|
||||
call assert_equal(0, &swapfile)
|
||||
call assert_equal("xchacha20", &cryptmethod)
|
||||
call assert_equal('311111111111111111111111', getline('$'))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_xchacha20_2()
|
||||
CheckFeature sodium
|
||||
sp Xcrypt_sodium.txt
|
||||
" Create a larger file, so that Vim will write in several blocks
|
||||
call setline(1, range(1,4000))
|
||||
call assert_equal(1, &swapfile)
|
||||
set cryptmethod=xchacha20
|
||||
call feedkeys(":X\<CR>sodium\<CR>sodium\<CR>", 'xt')
|
||||
" swapfile disabled
|
||||
call assert_equal(0, &swapfile)
|
||||
call assert_match("Note: Encryption of swapfile not supported, disabling swap- and undofile", execute(':messages'))
|
||||
w!
|
||||
" encrypted using xchacha20
|
||||
call assert_match("\[xchacha20\]", execute(':messages'))
|
||||
bw!
|
||||
call feedkeys(":sp Xcrypt_sodium.txt\<CR>sodium\<CR>", 'xt')
|
||||
" successfully decrypted
|
||||
call assert_equal(range(1, 4000)->map( {_, v -> string(v)}), getline(1,'$'))
|
||||
set key=
|
||||
w!
|
||||
" enryption removed
|
||||
call assert_match('"Xcrypt_sodium.txt" 4000L, 18893B written', execute(':message'))
|
||||
bw!
|
||||
call delete('Xcrypt_sodium.txt')
|
||||
set cryptmethod&vim
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_xchacha20_3_persistent_undo()
|
||||
CheckFeature sodium
|
||||
CheckFeature persistent_undo
|
||||
sp Xcrypt_sodium_undo.txt
|
||||
set cryptmethod=xchacha20 undofile
|
||||
call feedkeys(":X\<CR>sodium\<CR>sodium\<CR>", 'xt')
|
||||
call assert_equal(0, &undofile)
|
||||
let ufile=undofile(@%)
|
||||
call append(0, ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
|
||||
call cursor(1, 1)
|
||||
|
||||
set undolevels=100
|
||||
normal dd
|
||||
set undolevels=100
|
||||
normal dd
|
||||
set undolevels=100
|
||||
normal dd
|
||||
set undolevels=100
|
||||
w!
|
||||
bw!
|
||||
call feedkeys(":sp Xcrypt_sodium_undo.txt\<CR>sodium\<CR>", 'xt')
|
||||
" should fail
|
||||
norm! u
|
||||
call assert_match('Already at oldest change', execute(':1mess'))
|
||||
call assert_fails('verbose rundo' .. fnameescape(ufile), 'E822')
|
||||
bw!
|
||||
set undolevels& cryptmethod& undofile&
|
||||
call delete('Xcrypt_sodium_undo.txt')
|
||||
endfunc
|
||||
|
||||
func Test_encrypt_xchacha20_missing()
|
||||
if has("sodium")
|
||||
return
|
||||
endif
|
||||
sp Xcrypt_sodium_undo.txt
|
||||
call assert_fails(':set cryptmethod=xchacha20', 'E474')
|
||||
bw!
|
||||
set cm&
|
||||
endfunc
|
||||
|
||||
func Test_uncrypt_unknown_method()
|
||||
split Xuncrypt_unknown.txt
|
||||
set bin noeol key= fenc=latin1
|
||||
|
||||
+107
-11
@@ -885,19 +885,19 @@ func Test_Backtrace_DefFunction()
|
||||
\ ':debug call GlobalFunction()',
|
||||
\ ['cmd: call GlobalFunction()'])
|
||||
|
||||
call RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
|
||||
call RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
|
||||
call RunDbgCmd(buf, 'step', ['line 1: var some = "some var"'])
|
||||
call RunDbgCmd(buf, 'step', ['line 2: CallAFunction()'])
|
||||
call RunDbgCmd(buf, 'echo some', ['some var'])
|
||||
|
||||
call RunDbgCmd(buf, 'backtrace', [
|
||||
\ '\V>backtrace',
|
||||
\ '\V->0 function GlobalFunction',
|
||||
\ '\Vline 2: CallAFunction()',
|
||||
\ '\Vline 2: CallAFunction()',
|
||||
\ ],
|
||||
\ #{match: 'pattern'})
|
||||
|
||||
call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
|
||||
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
|
||||
call RunDbgCmd(buf, 'step', ['line 1: SourceAnotherFile()'])
|
||||
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
|
||||
" Repeated line, because we fist are in the compiled function before the
|
||||
" EXEC and then in do_cmdline() before the :source command.
|
||||
call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim'])
|
||||
@@ -932,17 +932,83 @@ func Test_Backtrace_DefFunction()
|
||||
call delete('Xtest2.vim')
|
||||
endfunc
|
||||
|
||||
func Test_debug_DefFunction()
|
||||
CheckCWD
|
||||
let file =<< trim END
|
||||
vim9script
|
||||
def g:SomeFunc()
|
||||
echo "here"
|
||||
echo "and"
|
||||
echo "there"
|
||||
breakadd func 2 LocalFunc
|
||||
LocalFunc()
|
||||
enddef
|
||||
|
||||
def LocalFunc()
|
||||
echo "first"
|
||||
echo "second"
|
||||
breakadd func 1 LegacyFunc
|
||||
LegacyFunc()
|
||||
enddef
|
||||
|
||||
func LegacyFunc()
|
||||
echo "legone"
|
||||
echo "legtwo"
|
||||
endfunc
|
||||
|
||||
breakadd func 2 g:SomeFunc
|
||||
END
|
||||
call writefile(file, 'XtestDebug.vim')
|
||||
|
||||
let buf = RunVimInTerminal('-S XtestDebug.vim', {})
|
||||
|
||||
call RunDbgCmd(buf,':call SomeFunc()', ['line 2: echo "and"'])
|
||||
call RunDbgCmd(buf,'next', ['line 3: echo "there"'])
|
||||
call RunDbgCmd(buf,'next', ['line 4: breakadd func 2 LocalFunc'])
|
||||
|
||||
" continue, next breakpoint is in LocalFunc()
|
||||
call RunDbgCmd(buf,'cont', ['line 2: echo "second"'])
|
||||
|
||||
" continue, next breakpoint is in LegacyFunc()
|
||||
call RunDbgCmd(buf,'cont', ['line 1: echo "legone"'])
|
||||
|
||||
call RunDbgCmd(buf, 'cont')
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xtest1.vim')
|
||||
call delete('Xtest2.vim')
|
||||
endfunc
|
||||
|
||||
func Test_debug_def_function()
|
||||
CheckCWD
|
||||
let file =<< trim END
|
||||
vim9script
|
||||
def g:Func()
|
||||
var n: number
|
||||
def Closure(): number
|
||||
return n + 3
|
||||
enddef
|
||||
n += Closure()
|
||||
echo 'result: ' .. n
|
||||
var n: number
|
||||
def Closure(): number
|
||||
return n + 3
|
||||
enddef
|
||||
n += Closure()
|
||||
echo 'result: ' .. n
|
||||
enddef
|
||||
|
||||
def g:FuncWithArgs(text: string, nr: number, ...items: list<number>)
|
||||
echo text .. nr
|
||||
for it in items
|
||||
echo it
|
||||
endfor
|
||||
echo "done"
|
||||
enddef
|
||||
|
||||
def g:FuncWithDict()
|
||||
var d = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
}
|
||||
# comment
|
||||
def Inner()
|
||||
eval 1
|
||||
enddef
|
||||
enddef
|
||||
END
|
||||
call writefile(file, 'Xtest.vim')
|
||||
@@ -954,7 +1020,37 @@ func Test_debug_def_function()
|
||||
\ ['cmd: call Func()'])
|
||||
call RunDbgCmd(buf, 'next', ['result: 3'])
|
||||
call term_sendkeys(buf, "\r")
|
||||
call RunDbgCmd(buf, 'cont')
|
||||
|
||||
call RunDbgCmd(buf,
|
||||
\ ':debug call FuncWithArgs("asdf", 42, 1, 2, 3)',
|
||||
\ ['cmd: call FuncWithArgs("asdf", 42, 1, 2, 3)'])
|
||||
call RunDbgCmd(buf, 'step', ['line 1: echo text .. nr'])
|
||||
call RunDbgCmd(buf, 'echo text', ['asdf'])
|
||||
call RunDbgCmd(buf, 'echo nr', ['42'])
|
||||
call RunDbgCmd(buf, 'echo items', ['[1, 2, 3]'])
|
||||
call RunDbgCmd(buf, 'step', ['asdf42', 'function FuncWithArgs', 'line 2: for it in items'])
|
||||
call RunDbgCmd(buf, 'echo it', ['1'])
|
||||
call RunDbgCmd(buf, 'step', ['line 3: echo it'])
|
||||
call RunDbgCmd(buf, 'step', ['1', 'function FuncWithArgs', 'line 4: endfor'])
|
||||
call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
|
||||
call RunDbgCmd(buf, 'echo it', ['2'])
|
||||
call RunDbgCmd(buf, 'step', ['line 3: echo it'])
|
||||
call RunDbgCmd(buf, 'step', ['2', 'function FuncWithArgs', 'line 4: endfor'])
|
||||
call RunDbgCmd(buf, 'step', ['line 2: for it in items'])
|
||||
call RunDbgCmd(buf, 'echo it', ['3'])
|
||||
call RunDbgCmd(buf, 'step', ['line 3: echo it'])
|
||||
call RunDbgCmd(buf, 'step', ['3', 'function FuncWithArgs', 'line 4: endfor'])
|
||||
call RunDbgCmd(buf, 'step', ['line 5: echo "done"'])
|
||||
call RunDbgCmd(buf, 'cont')
|
||||
|
||||
call RunDbgCmd(buf,
|
||||
\ ':debug call FuncWithDict()',
|
||||
\ ['cmd: call FuncWithDict()'])
|
||||
call RunDbgCmd(buf, 'step', ['line 1: var d = { a: 1, b: 2, }'])
|
||||
call RunDbgCmd(buf, 'step', ['line 6: def Inner()'])
|
||||
|
||||
call RunDbgCmd(buf, 'cont')
|
||||
call StopVimInTerminal(buf)
|
||||
call delete('Xtest.vim')
|
||||
endfunc
|
||||
|
||||
@@ -165,7 +165,7 @@ func Test_string_concat_scriptversion2()
|
||||
|
||||
call assert_fails('echo a . b', 'E15:')
|
||||
call assert_fails('let a .= b', 'E985:')
|
||||
call assert_fails('let vers = 1.2.3', 'E15:')
|
||||
call assert_fails('let vers = 1.2.3', 'E488:')
|
||||
|
||||
if has('float')
|
||||
let f = .5
|
||||
|
||||
@@ -40,7 +40,7 @@ func Test_execute_string()
|
||||
if has('float')
|
||||
call assert_fails('call execute(3.4)', 'E492:')
|
||||
call assert_equal("\nx", execute("echo \"x\"", 3.4))
|
||||
call CheckDefExecAndScriptFailure(['execute("echo \"x\"", 3.4)'], 'E806:')
|
||||
call CheckDefExecAndScriptFailure2(['execute("echo \"x\"", 3.4)'], 'E1013: Argument 2: type mismatch, expected string but got float', 'E806:')
|
||||
endif
|
||||
endfunc
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
" Test for 'fileformat'
|
||||
|
||||
source shared.vim
|
||||
|
||||
" Test behavior of fileformat after bwipeout of last buffer
|
||||
func Test_fileformat_after_bw()
|
||||
bwipeout
|
||||
@@ -308,4 +310,18 @@ func Test_fileformat_plusplus_read()
|
||||
call assert_fails('e ++abc1 Xfile1', 'E474:')
|
||||
endfunc
|
||||
|
||||
" When Vim starts up with an empty buffer the first item in 'fileformats' is
|
||||
" used as the 'fileformat'.
|
||||
func Test_fileformat_on_startup()
|
||||
let after =<< trim END
|
||||
call writefile([&fileformat], 'Xfile', 'a')
|
||||
quit
|
||||
END
|
||||
call RunVim(["set ffs=dos,unix,mac"], after, '')
|
||||
call RunVim(["set ffs=mac,dos,unix"], after, '')
|
||||
call RunVim(["set ffs=unix,mac,dos"], after, '')
|
||||
call assert_equal(['dos', 'mac', 'unix'], readfile('Xfile'))
|
||||
call delete('Xfile')
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -83,4 +83,8 @@ func Test_global_newline()
|
||||
close!
|
||||
endfunc
|
||||
|
||||
func Test_wrong_delimiter()
|
||||
call assert_fails('g x^bxd', 'E146:')
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
+284
-1
@@ -389,7 +389,7 @@ func Test_set_guifont()
|
||||
endif
|
||||
|
||||
" This only works if 'renderoptions' exists and does not work for Windows XP
|
||||
" and older.
|
||||
" and older.
|
||||
if exists('+renderoptions') && windowsversion() !~ '^[345]\.'
|
||||
" doing this four times used to cause a crash
|
||||
set renderoptions=type:directx
|
||||
@@ -880,4 +880,287 @@ func Test_gui_recursive_mapping()
|
||||
nunmap <C-W>a
|
||||
endfunc
|
||||
|
||||
" Test GUI mouse events
|
||||
func Test_gui_mouse_event()
|
||||
set mousemodel=extend
|
||||
call test_override('no_query_mouse', 1)
|
||||
new
|
||||
call setline(1, ['one two three', 'four five six'])
|
||||
|
||||
" place the cursor using left click in normal mode
|
||||
call cursor(1, 1)
|
||||
call test_gui_mouse_event(0, 2, 4, 0, 0)
|
||||
call test_gui_mouse_event(3, 2, 4, 0, 0)
|
||||
call feedkeys("\<Esc>", 'Lx!')
|
||||
call assert_equal([0, 2, 4, 0], getpos('.'))
|
||||
|
||||
" select and yank a word
|
||||
let @" = ''
|
||||
call test_gui_mouse_event(0, 1, 9, 0, 0)
|
||||
call test_gui_mouse_event(0, 1, 9, 1, 0)
|
||||
call test_gui_mouse_event(3, 1, 9, 0, 0)
|
||||
call feedkeys("y", 'Lx!')
|
||||
call assert_equal('three', @")
|
||||
|
||||
" create visual selection using right click
|
||||
let @" = ''
|
||||
call test_gui_mouse_event(0, 2, 6, 0, 0)
|
||||
call test_gui_mouse_event(3, 2, 6, 0, 0)
|
||||
call test_gui_mouse_event(2, 2, 13, 0, 0)
|
||||
call test_gui_mouse_event(3, 2, 13, 0, 0)
|
||||
call feedkeys("y", 'Lx!')
|
||||
call assert_equal('five six', @")
|
||||
|
||||
" paste using middle mouse button
|
||||
let @* = 'abc '
|
||||
call feedkeys('""', 'Lx!')
|
||||
call test_gui_mouse_event(1, 1, 9, 0, 0)
|
||||
call test_gui_mouse_event(3, 1, 9, 0, 0)
|
||||
call feedkeys("\<Esc>", 'Lx!')
|
||||
call assert_equal(['one two abc three', 'four five six'], getline(1, '$'))
|
||||
|
||||
" extend visual selection using right click in visual mode
|
||||
let @" = ''
|
||||
call cursor(1, 1)
|
||||
call feedkeys('v', 'Lx!')
|
||||
call test_gui_mouse_event(2, 1, 17, 0, 0)
|
||||
call test_gui_mouse_event(3, 1, 17, 0, 0)
|
||||
call feedkeys("y", 'Lx!')
|
||||
call assert_equal('one two abc three', @")
|
||||
|
||||
" extend visual selection using mouse drag
|
||||
let @" = ''
|
||||
call cursor(1, 1)
|
||||
call test_gui_mouse_event(0, 2, 1, 0, 0)
|
||||
call test_gui_mouse_event(0x43, 2, 9, 0, 0)
|
||||
call test_gui_mouse_event(0x3, 2, 9, 0, 0)
|
||||
call feedkeys("y", 'Lx!')
|
||||
call assert_equal('four five', @")
|
||||
|
||||
" select text by moving the mouse
|
||||
let @" = ''
|
||||
call cursor(1, 1)
|
||||
redraw!
|
||||
call test_gui_mouse_event(0, 1, 4, 0, 0)
|
||||
call test_gui_mouse_event(0x700, 1, 9, 0, 0)
|
||||
call test_gui_mouse_event(0x700, 1, 13, 0, 0)
|
||||
call test_gui_mouse_event(0x3, 1, 13, 0, 0)
|
||||
call feedkeys("y", 'Lx!')
|
||||
call assert_equal(' two abc t', @")
|
||||
|
||||
" Using mouse in insert mode
|
||||
call cursor(1, 1)
|
||||
call feedkeys('i', 't')
|
||||
call test_gui_mouse_event(0, 2, 11, 0, 0)
|
||||
call test_gui_mouse_event(3, 2, 11, 0, 0)
|
||||
call feedkeys("po\<Esc>", 'Lx!')
|
||||
call assert_equal(['one two abc three', 'four five posix'], getline(1, '$'))
|
||||
|
||||
%d _
|
||||
call setline(1, range(1, 100))
|
||||
" scroll up
|
||||
call test_gui_mouse_event(0x200, 2, 1, 0, 0)
|
||||
call test_gui_mouse_event(0x200, 2, 1, 0, 0)
|
||||
call test_gui_mouse_event(0x200, 2, 1, 0, 0)
|
||||
call feedkeys("H", 'Lx!')
|
||||
call assert_equal(10, line('.'))
|
||||
|
||||
" scroll down
|
||||
call test_gui_mouse_event(0x100, 2, 1, 0, 0)
|
||||
call test_gui_mouse_event(0x100, 2, 1, 0, 0)
|
||||
call feedkeys("H", 'Lx!')
|
||||
call assert_equal(4, line('.'))
|
||||
|
||||
%d _
|
||||
set nowrap
|
||||
call setline(1, range(10)->join('')->repeat(10))
|
||||
" scroll left
|
||||
call test_gui_mouse_event(0x500, 1, 5, 0, 0)
|
||||
call test_gui_mouse_event(0x500, 1, 10, 0, 0)
|
||||
call test_gui_mouse_event(0x500, 1, 15, 0, 0)
|
||||
call feedkeys('g0', 'Lx!')
|
||||
call assert_equal(19, col('.'))
|
||||
|
||||
" scroll right
|
||||
call test_gui_mouse_event(0x600, 1, 15, 0, 0)
|
||||
call test_gui_mouse_event(0x600, 1, 10, 0, 0)
|
||||
call feedkeys('g0', 'Lx!')
|
||||
call assert_equal(7, col('.'))
|
||||
set wrap&
|
||||
|
||||
%d _
|
||||
call setline(1, repeat([repeat('a', 60)], 10))
|
||||
|
||||
" record various mouse events
|
||||
let mouseEventNames = [
|
||||
\ 'LeftMouse', 'LeftRelease', '2-LeftMouse', '3-LeftMouse',
|
||||
\ 'S-LeftMouse', 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse',
|
||||
\ 'MiddleRelease', '2-MiddleMouse', '3-MiddleMouse',
|
||||
\ 'S-MiddleMouse', 'A-MiddleMouse', 'C-MiddleMouse',
|
||||
\ 'RightMouse', 'RightRelease', '2-RightMouse',
|
||||
\ '3-RightMouse', 'S-RightMouse', 'A-RightMouse', 'C-RightMouse',
|
||||
\ 'X1Mouse', 'S-X1Mouse', 'A-X1Mouse', 'C-X1Mouse', 'X2Mouse',
|
||||
\ 'S-X2Mouse', 'A-X2Mouse', 'C-X2Mouse'
|
||||
\ ]
|
||||
let mouseEventCodes = map(copy(mouseEventNames), "'<' .. v:val .. '>'")
|
||||
let g:events = []
|
||||
for e in mouseEventCodes
|
||||
exe 'nnoremap ' .. e .. ' <Cmd>call add(g:events, "' ..
|
||||
\ substitute(e, '[<>]', '', 'g') .. '")<CR>'
|
||||
endfor
|
||||
|
||||
" Test various mouse buttons (0 - Left, 1 - Middle, 2 - Right, 0x300 - X1,
|
||||
" 0x300- X2)
|
||||
for button in [0, 1, 2, 0x300, 0x400]
|
||||
" Single click
|
||||
call test_gui_mouse_event(button, 2, 5, 0, 0)
|
||||
call test_gui_mouse_event(3, 2, 5, 0, 0)
|
||||
|
||||
" Double/Triple click is supported by only the Left/Middle/Right mouse
|
||||
" buttons
|
||||
if button <= 2
|
||||
" Double Click
|
||||
call test_gui_mouse_event(button, 2, 5, 0, 0)
|
||||
call test_gui_mouse_event(button, 2, 5, 1, 0)
|
||||
call test_gui_mouse_event(3, 2, 5, 0, 0)
|
||||
|
||||
" Triple Click
|
||||
call test_gui_mouse_event(button, 2, 5, 0, 0)
|
||||
call test_gui_mouse_event(button, 2, 5, 1, 0)
|
||||
call test_gui_mouse_event(button, 2, 5, 1, 0)
|
||||
call test_gui_mouse_event(3, 2, 5, 0, 0)
|
||||
endif
|
||||
|
||||
" Shift click
|
||||
call test_gui_mouse_event(button, 3, 7, 0, 4)
|
||||
call test_gui_mouse_event(3, 3, 7, 0, 4)
|
||||
|
||||
" Alt click
|
||||
call test_gui_mouse_event(button, 3, 7, 0, 8)
|
||||
call test_gui_mouse_event(3, 3, 7, 0, 8)
|
||||
|
||||
" Ctrl click
|
||||
call test_gui_mouse_event(button, 3, 7, 0, 16)
|
||||
call test_gui_mouse_event(3, 3, 7, 0, 16)
|
||||
|
||||
call feedkeys("\<Esc>", 'Lx!')
|
||||
endfor
|
||||
|
||||
call assert_equal(['LeftMouse', 'LeftRelease', 'LeftMouse', '2-LeftMouse',
|
||||
\ 'LeftMouse', '2-LeftMouse', '3-LeftMouse', 'S-LeftMouse',
|
||||
\ 'A-LeftMouse', 'C-LeftMouse', 'MiddleMouse', 'MiddleRelease',
|
||||
\ 'MiddleMouse', '2-MiddleMouse', 'MiddleMouse', '2-MiddleMouse',
|
||||
\ '3-MiddleMouse', 'S-MiddleMouse', 'A-MiddleMouse', 'C-MiddleMouse',
|
||||
\ 'RightMouse', 'RightRelease', 'RightMouse', '2-RightMouse',
|
||||
\ 'RightMouse', '2-RightMouse', '3-RightMouse', 'S-RightMouse',
|
||||
\ 'A-RightMouse', 'C-RightMouse', 'X1Mouse', 'S-X1Mouse', 'A-X1Mouse',
|
||||
\ 'C-X1Mouse', 'X2Mouse', 'S-X2Mouse', 'A-X2Mouse', 'C-X2Mouse'],
|
||||
\ g:events)
|
||||
|
||||
for e in mouseEventCodes
|
||||
exe 'nunmap ' .. e
|
||||
endfor
|
||||
|
||||
" modeless selection
|
||||
set mouse=
|
||||
let save_guioptions = &guioptions
|
||||
set guioptions+=A
|
||||
%d _
|
||||
call setline(1, ['one two three', 'four five sixteen'])
|
||||
call cursor(1, 1)
|
||||
redraw!
|
||||
" Double click should select the word and copy it to clipboard
|
||||
let @* = ''
|
||||
call test_gui_mouse_event(0, 2, 11, 0, 0)
|
||||
call test_gui_mouse_event(0, 2, 11, 1, 0)
|
||||
call test_gui_mouse_event(3, 2, 11, 0, 0)
|
||||
call feedkeys("\<Esc>", 'Lx!')
|
||||
call assert_equal([0, 1, 1, 0], getpos('.'))
|
||||
call assert_equal('sixteen', @*)
|
||||
" Right click should extend the selection from cursor
|
||||
call cursor(1, 6)
|
||||
redraw!
|
||||
let @* = ''
|
||||
call test_gui_mouse_event(2, 1, 11, 0, 0)
|
||||
call test_gui_mouse_event(3, 1, 11, 0, 0)
|
||||
call feedkeys("\<Esc>", 'Lx!')
|
||||
call assert_equal([0, 1, 6, 0], getpos('.'))
|
||||
call assert_equal('wo thr', @*)
|
||||
" Middle click should paste the clipboard contents
|
||||
call cursor(2, 1)
|
||||
redraw!
|
||||
call test_gui_mouse_event(1, 1, 11, 0, 0)
|
||||
call test_gui_mouse_event(3, 1, 11, 0, 0)
|
||||
call feedkeys("\<Esc>", 'Lx!')
|
||||
call assert_equal([0, 2, 7, 0], getpos('.'))
|
||||
call assert_equal('wo thrfour five sixteen', getline(2))
|
||||
set mouse&
|
||||
let &guioptions = save_guioptions
|
||||
|
||||
" Test invalid parameters for test_gui_mouse_event()
|
||||
call assert_fails('call test_gui_mouse_event("", 1, 2, 3, 4)', 'E474:')
|
||||
call assert_fails('call test_gui_mouse_event(0, "", 2, 3, 4)', 'E474:')
|
||||
call assert_fails('call test_gui_mouse_event(0, 1, "", 3, 4)', 'E474:')
|
||||
call assert_fails('call test_gui_mouse_event(0, 1, 2, "", 4)', 'E474:')
|
||||
call assert_fails('call test_gui_mouse_event(0, 1, 2, 3, "")', 'E474:')
|
||||
|
||||
bw!
|
||||
call test_override('no_query_mouse', 0)
|
||||
set mousemodel&
|
||||
endfunc
|
||||
|
||||
" Test for 'guitablabel' and 'guitabtooltip' options
|
||||
func TestGuiTabLabel()
|
||||
call add(g:TabLabels, v:lnum + 100)
|
||||
let bufnrlist = tabpagebuflist(v:lnum)
|
||||
return bufname(bufnrlist[tabpagewinnr(v:lnum) - 1])
|
||||
endfunc
|
||||
|
||||
func TestGuiTabToolTip()
|
||||
call add(g:TabToolTips, v:lnum + 200)
|
||||
let bufnrlist = tabpagebuflist(v:lnum)
|
||||
return bufname(bufnrlist[tabpagewinnr(v:lnum) - 1])
|
||||
endfunc
|
||||
|
||||
func Test_gui_tablabel_tooltip()
|
||||
%bw!
|
||||
" Removing the tabline at the end of this test, reduces the window height by
|
||||
" one. Save and restore it after the test.
|
||||
let save_lines = &lines
|
||||
edit one
|
||||
set modified
|
||||
tabnew two
|
||||
set modified
|
||||
tabnew three
|
||||
set modified
|
||||
let g:TabLabels = []
|
||||
set guitablabel=%{TestGuiTabLabel()}
|
||||
call test_override('starting', 1)
|
||||
redrawtabline
|
||||
call test_override('starting', 0)
|
||||
call assert_true(index(g:TabLabels, 101) != -1)
|
||||
call assert_true(index(g:TabLabels, 102) != -1)
|
||||
call assert_true(index(g:TabLabels, 103) != -1)
|
||||
set guitablabel&
|
||||
unlet g:TabLabels
|
||||
|
||||
if has('gui_gtk')
|
||||
" Only on GTK+, the tooltip function is called even if the mouse is not
|
||||
" on the tabline. on Win32 and Motif, the tooltip function is called only
|
||||
" when the mouse pointer is over the tabline.
|
||||
let g:TabToolTips = []
|
||||
set guitabtooltip=%{TestGuiTabToolTip()}
|
||||
call test_override('starting', 1)
|
||||
redrawtabline
|
||||
call test_override('starting', 0)
|
||||
call assert_true(index(g:TabToolTips, 201) != -1)
|
||||
call assert_true(index(g:TabToolTips, 202) != -1)
|
||||
call assert_true(index(g:TabToolTips, 203) != -1)
|
||||
set guitabtooltip&
|
||||
unlet g:TabToolTips
|
||||
endif
|
||||
%bw!
|
||||
let &lines = save_lines
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -314,6 +314,7 @@ func Test_let_errors()
|
||||
let ch = test_null_channel()
|
||||
call assert_fails('let ch += 1', 'E734:')
|
||||
endif
|
||||
call assert_fails('let name = "a" .. "b",', 'E488: Trailing characters: ,')
|
||||
|
||||
" This test works only when the language is English
|
||||
if v:lang == "C" || v:lang =~ '^[Ee]n'
|
||||
|
||||
@@ -298,4 +298,26 @@ func Test_relativenumber_colors()
|
||||
call delete('XTest_relnr')
|
||||
endfunc
|
||||
|
||||
" Test for displaying line numbers with 'rightleft'
|
||||
func Test_number_rightleft()
|
||||
CheckFeature rightleft
|
||||
new
|
||||
setlocal number
|
||||
setlocal rightleft
|
||||
call setline(1, range(1, 1000))
|
||||
normal! 9Gzt
|
||||
redraw!
|
||||
call assert_match('^\s\+9 9$', Screenline(1))
|
||||
normal! 10Gzt
|
||||
redraw!
|
||||
call assert_match('^\s\+01 10$', Screenline(1))
|
||||
normal! 100Gzt
|
||||
redraw!
|
||||
call assert_match('^\s\+001 100$', Screenline(1))
|
||||
normal! 1000Gzt
|
||||
redraw!
|
||||
call assert_match('^\s\+0001 1000$', Screenline(1))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -1552,8 +1552,8 @@ func Test_popup_filter()
|
||||
call assert_equal(9, getcurpos()[2])
|
||||
call feedkeys('0', 'xt')
|
||||
call assert_equal('0', g:ignored)
|
||||
redraw
|
||||
call assert_equal(1, getcurpos()[2])
|
||||
normal! l
|
||||
call assert_equal(2, getcurpos()[2])
|
||||
|
||||
" x closes the popup
|
||||
call feedkeys('x', 'xt')
|
||||
|
||||
@@ -134,6 +134,21 @@ func XlistTests(cchar)
|
||||
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
|
||||
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
|
||||
|
||||
" Ranged entries
|
||||
call g:Xsetlist([{'lnum':10,'text':'Line1'},
|
||||
\ {'lnum':20,'col':10,'text':'Line2'},
|
||||
\ {'lnum':30,'col':15,'end_col':20,'text':'Line3'},
|
||||
\ {'lnum':40,'end_lnum':45,'text':'Line4'},
|
||||
\ {'lnum':50,'end_lnum':55,'col':15,'text':'Line5'},
|
||||
\ {'lnum':60,'end_lnum':65,'col':25,'end_col':35,'text':'Line6'}])
|
||||
let l = split(execute('Xlist', ""), "\n")
|
||||
call assert_equal([' 1:10: Line1',
|
||||
\ ' 2:20 col 10: Line2',
|
||||
\ ' 3:30 col 15-20: Line3',
|
||||
\ ' 4:40-45: Line4',
|
||||
\ ' 5:50-55 col 15: Line5',
|
||||
\ ' 6:60-65 col 25-35: Line6'], l)
|
||||
|
||||
" Different types of errors
|
||||
call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11},
|
||||
\ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22},
|
||||
@@ -644,6 +659,7 @@ func s:test_xhelpgrep(cchar)
|
||||
call assert_true(&buftype == 'help')
|
||||
call assert_true(winnr() == 1)
|
||||
call assert_true(winnr('$') == 2)
|
||||
call assert_match('|\d\+ col \d\+-\d\+|', getbufline(winbufnr(2), 1)[0])
|
||||
|
||||
" This wipes out the buffer, make sure that doesn't cause trouble.
|
||||
Xclose
|
||||
@@ -1514,10 +1530,13 @@ func SetXlistTests(cchar, bnum)
|
||||
call s:setup_commands(a:cchar)
|
||||
|
||||
call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1},
|
||||
\ {'bufnr': a:bnum, 'lnum': 2}])
|
||||
\ {'bufnr': a:bnum, 'lnum': 2, 'end_lnum': 3, 'col': 4, 'end_col': 5}])
|
||||
let l = g:Xgetlist()
|
||||
call assert_equal(2, len(l))
|
||||
call assert_equal(2, l[1].lnum)
|
||||
call assert_equal(3, l[1].end_lnum)
|
||||
call assert_equal(4, l[1].col)
|
||||
call assert_equal(5, l[1].end_col)
|
||||
|
||||
Xnext
|
||||
call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a')
|
||||
@@ -2852,7 +2871,9 @@ func XvimgrepTests(cchar)
|
||||
let l = g:Xgetlist()
|
||||
call assert_equal(2, len(l))
|
||||
call assert_equal(8, l[0].col)
|
||||
call assert_equal(11, l[0].end_col)
|
||||
call assert_equal(12, l[1].col)
|
||||
call assert_equal(15, l[1].end_col)
|
||||
|
||||
1Xvimgrep ?Editor? Xtestfile*
|
||||
let l = g:Xgetlist()
|
||||
@@ -5098,15 +5119,21 @@ func Xtest_qftextfunc(cchar)
|
||||
call assert_equal('Tqfexpr', &quickfixtextfunc)
|
||||
call assert_equal('',
|
||||
\ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)
|
||||
Xexpr ['F1:10:2:green', 'F1:20:4:blue']
|
||||
call g:Xsetlist([
|
||||
\ { 'filename': 'F1', 'lnum': 10, 'col': 2,
|
||||
\ 'end_col': 7, 'text': 'green'},
|
||||
\ { 'filename': 'F1', 'lnum': 20, 'end_lnum': 25, 'col': 4,
|
||||
\ 'end_col': 8, 'text': 'blue'},
|
||||
\ ])
|
||||
|
||||
Xwindow
|
||||
call assert_equal('F1-L10C2-green', getline(1))
|
||||
call assert_equal('F1-L20C4-blue', getline(2))
|
||||
Xclose
|
||||
set quickfixtextfunc&vim
|
||||
Xwindow
|
||||
call assert_equal('F1|10 col 2| green', getline(1))
|
||||
call assert_equal('F1|20 col 4| blue', getline(2))
|
||||
call assert_equal('F1|10 col 2-7| green', getline(1))
|
||||
call assert_equal('F1|20-25 col 4-8| blue', getline(2))
|
||||
Xclose
|
||||
set efm&
|
||||
set quickfixtextfunc&
|
||||
@@ -5231,6 +5258,64 @@ func Test_qftextfunc()
|
||||
call Xtest_qftextfunc('l')
|
||||
endfunc
|
||||
|
||||
" Test for updating a location list for some other window and check that
|
||||
" 'qftextfunc' uses the correct location list.
|
||||
func Test_qftextfunc_other_loclist()
|
||||
%bw!
|
||||
call setloclist(0, [], 'f')
|
||||
|
||||
" create a window and a location list for it and open the location list
|
||||
" window
|
||||
lexpr ['F1:10:12:one', 'F1:20:14:two']
|
||||
let w1_id = win_getid()
|
||||
call setloclist(0, [], ' ',
|
||||
\ {'lines': ['F1:10:12:one', 'F1:20:14:two'],
|
||||
\ 'quickfixtextfunc':
|
||||
\ {d -> map(getloclist(d.winid, {'id' : d.id,
|
||||
\ 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
|
||||
\ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}})
|
||||
lwindow
|
||||
let w2_id = win_getid()
|
||||
|
||||
" create another window and a location list for it and open the location
|
||||
" list window
|
||||
topleft new
|
||||
let w3_id = win_getid()
|
||||
call setloclist(0, [], ' ',
|
||||
\ {'lines': ['F2:30:32:eleven', 'F2:40:34:twelve'],
|
||||
\ 'quickfixtextfunc':
|
||||
\ {d -> map(getloclist(d.winid, {'id' : d.id,
|
||||
\ 'items' : 1}).items[d.start_idx-1:d.end_idx-1],
|
||||
\ "'Ligne ' .. v:val.lnum .. ', Colonne ' .. v:val.col")}})
|
||||
lwindow
|
||||
let w4_id = win_getid()
|
||||
|
||||
topleft new
|
||||
lexpr ['F3:50:52:green', 'F3:60:54:blue']
|
||||
let w5_id = win_getid()
|
||||
|
||||
" change the location list for some other window
|
||||
call setloclist(0, [], 'r', {'lines': ['F3:55:56:aaa', 'F3:57:58:bbb']})
|
||||
call setloclist(w1_id, [], 'r', {'lines': ['F1:62:63:bbb', 'F1:64:65:ccc']})
|
||||
call setloclist(w3_id, [], 'r', {'lines': ['F2:76:77:ddd', 'F2:78:79:eee']})
|
||||
call assert_equal(['Line 62, Col 63', 'Line 64, Col 65'],
|
||||
\ getbufline(winbufnr(w2_id), 1, '$'))
|
||||
call assert_equal(['Ligne 76, Colonne 77', 'Ligne 78, Colonne 79'],
|
||||
\ getbufline(winbufnr(w4_id), 1, '$'))
|
||||
call setloclist(w2_id, [], 'r', {'lines': ['F1:32:33:fff', 'F1:34:35:ggg']})
|
||||
call setloclist(w4_id, [], 'r', {'lines': ['F2:46:47:hhh', 'F2:48:49:jjj']})
|
||||
call assert_equal(['Line 32, Col 33', 'Line 34, Col 35'],
|
||||
\ getbufline(winbufnr(w2_id), 1, '$'))
|
||||
call assert_equal(['Ligne 46, Colonne 47', 'Ligne 48, Colonne 49'],
|
||||
\ getbufline(winbufnr(w4_id), 1, '$'))
|
||||
|
||||
call win_gotoid(w5_id)
|
||||
lwindow
|
||||
call assert_equal(['F3|55 col 56| aaa', 'F3|57 col 58| bbb'],
|
||||
\ getline(1, '$'))
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
" Running :lhelpgrep command more than once in a help window, doesn't jump to
|
||||
" the help topic
|
||||
func Test_lhelpgrep_from_help_window()
|
||||
@@ -5281,7 +5366,42 @@ func Test_add_invalid_entry_with_qf_window()
|
||||
call setqflist(['bb'], 'a')
|
||||
call assert_equal(1, line('$'))
|
||||
call assert_equal(['Xfile1|10| aa'], getline(1, '$'))
|
||||
call assert_equal([{'lnum': 10, 'bufnr': bufnr('Xfile1'), 'col': 0, 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': -1, 'type': '', 'module': '', 'text': 'aa'}], getqflist())
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
|
||||
call setqflist([{'lnum': 10 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
|
||||
call assert_equal(1 , line('$'))
|
||||
call assert_equal(['Xfile1|10| aa'] , getline(1 , '$'))
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
|
||||
call setqflist([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
|
||||
call assert_equal(1 , line('$'))
|
||||
call assert_equal(['Xfile1|10| aa'] , getline(1 , '$'))
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': 0 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
|
||||
call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
|
||||
call assert_equal(1 , line('$'))
|
||||
call assert_equal(['Xfile1|10| aa'] , getline(1 , '$'))
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 0 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
|
||||
call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
|
||||
call assert_equal(1 , line('$'))
|
||||
call assert_equal(['Xfile1|10 col 666| aa'] , getline(1 , '$'))
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 0 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
|
||||
call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
|
||||
call assert_equal(1 , line('$'))
|
||||
call assert_equal(['Xfile1|10 col 666| aa'] , getline(1 , '$'))
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': -456 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
|
||||
call setqflist([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
|
||||
call assert_equal(1 , line('$'))
|
||||
call assert_equal(['Xfile1|10 col 666-222| aa'] , getline(1 , '$'))
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': -123 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
|
||||
call setqflist([{'lnum': 10 , 'end_lnum': 6 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , 'r')
|
||||
call assert_equal(1 , line('$'))
|
||||
call assert_equal(['Xfile1|10-6 col 666-222| aa'] , getline(1 , '$'))
|
||||
call assert_equal([{'lnum': 10 , 'end_lnum': 6 , 'bufnr': bufnr('Xfile1') , 'col': 666 , 'end_col': 222 , 'pattern': '' , 'valid': 1 , 'vcol': 0 , 'nr': -1 , 'type': '' , 'module': '' , 'text': 'aa'}] , getqflist())
|
||||
cclose
|
||||
endfunc
|
||||
|
||||
|
||||
@@ -111,4 +111,27 @@ func Test_si_comment_line_continuation()
|
||||
close!
|
||||
endfunc
|
||||
|
||||
" When 'paste' is set, 'smartindent' should not take effect.
|
||||
func Test_si_with_paste()
|
||||
new
|
||||
setlocal smartindent autoindent
|
||||
set paste
|
||||
" insert text that will trigger smartindent
|
||||
exe "norm! i {\nif (x)\ni = 1;\n#define FOO 1\nj = 2;\n}"
|
||||
exe "norm! Ok = 3;"
|
||||
exe "norm! 4G>>"
|
||||
call assert_equal([' {', 'if (x)', 'i = 1;', '#define FOO 1',
|
||||
\ 'j = 2;', 'k = 3;', '}'], getline(1, '$'))
|
||||
call assert_true(&smartindent)
|
||||
set nopaste
|
||||
%d _
|
||||
exe "norm! i {\nif (x)\ni = 1;\n#define FOO 1\nj = 2;\n}"
|
||||
exe "norm! Ok = 3;"
|
||||
exe "norm! 4G>>"
|
||||
call assert_equal([' {', "\t if (x)", "\t\t i = 1;",
|
||||
\ '#define FOO 1', "\t\t j = 2;", "\t k = 3;", ' }'],
|
||||
\ getline(1, '$'))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -1304,6 +1304,8 @@ func Test_write_in_vimrc()
|
||||
endfunc
|
||||
|
||||
func Test_echo_true_in_cmd()
|
||||
CheckNotGui
|
||||
|
||||
let lines =<< trim END
|
||||
echo v:true
|
||||
call writefile(['done'], 'Xresult')
|
||||
@@ -1315,7 +1317,6 @@ func Test_echo_true_in_cmd()
|
||||
endif
|
||||
call delete('Xscript')
|
||||
call delete('Xresult')
|
||||
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -837,15 +837,16 @@ func Test_ltag()
|
||||
ltag third
|
||||
call assert_equal('Xfoo', bufname(''))
|
||||
call assert_equal(3, line('.'))
|
||||
call assert_equal([{'lnum': 3, 'bufnr': bufnr('Xfoo'), 'col': 0,
|
||||
\ 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '',
|
||||
\ 'module': '', 'text': 'third'}], getloclist(0))
|
||||
call assert_equal([{'lnum': 3, 'end_lnum': 0, 'bufnr': bufnr('Xfoo'),
|
||||
\ 'col': 0, 'end_col': 0, 'pattern': '', 'valid': 1, 'vcol': 0,
|
||||
\ 'nr': 0, 'type': '', 'module': '', 'text': 'third'}], getloclist(0))
|
||||
|
||||
ltag second
|
||||
call assert_equal(2, line('.'))
|
||||
call assert_equal([{'lnum': 0, 'bufnr': bufnr('Xfoo'), 'col': 0,
|
||||
\ 'pattern': '^\Vint second() {}\$', 'valid': 1, 'vcol': 0, 'nr': 0,
|
||||
\ 'type': '', 'module': '', 'text': 'second'}], getloclist(0))
|
||||
call assert_equal([{'lnum': 0, 'end_lnum': 0, 'bufnr': bufnr('Xfoo'),
|
||||
\ 'col': 0, 'end_col': 0, 'pattern': '^\Vint second() {}\$',
|
||||
\ 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'module': '',
|
||||
\ 'text': 'second'}], getloclist(0))
|
||||
|
||||
call delete('Xtags')
|
||||
call delete('Xfoo')
|
||||
|
||||
@@ -283,6 +283,29 @@ def Test_assign_unpack()
|
||||
[v1, v2; _] = [1, 2, 3, 4, 5]
|
||||
assert_equal(1, v1)
|
||||
assert_equal(2, v2)
|
||||
|
||||
var a = 1
|
||||
var b = 3
|
||||
[a, b] += [2, 4]
|
||||
assert_equal(3, a)
|
||||
assert_equal(7, b)
|
||||
|
||||
[a, b] -= [1, 2]
|
||||
assert_equal(2, a)
|
||||
assert_equal(5, b)
|
||||
|
||||
[a, b] *= [3, 2]
|
||||
assert_equal(6, a)
|
||||
assert_equal(10, b)
|
||||
|
||||
[a, b] /= [2, 4]
|
||||
assert_equal(3, a)
|
||||
assert_equal(2, b)
|
||||
|
||||
[a, b] = [17, 15]
|
||||
[a, b] %= [5, 3]
|
||||
assert_equal(2, a)
|
||||
assert_equal(0, b)
|
||||
END
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
|
||||
@@ -1820,6 +1843,19 @@ def Test_assign_command_modifier()
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
enddef
|
||||
|
||||
def Test_assign_alt_buf_register()
|
||||
var lines =<< trim END
|
||||
edit 'file_b1'
|
||||
var b1 = bufnr()
|
||||
edit 'file_b2'
|
||||
var b2 = bufnr()
|
||||
assert_equal(b1, bufnr('#'))
|
||||
@# = b2
|
||||
assert_equal(b2, bufnr('#'))
|
||||
END
|
||||
CheckDefAndScriptSuccess(lines)
|
||||
enddef
|
||||
|
||||
def Test_script_funcref_case()
|
||||
var lines =<< trim END
|
||||
var Len = (s: string): number => len(s) + 1
|
||||
|
||||
@@ -141,6 +141,11 @@ def Test_add_blob()
|
||||
CheckScriptSuccess(lines)
|
||||
enddef
|
||||
|
||||
def Test_and()
|
||||
CheckDefFailure(['echo and("x", 0x2)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo and(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_append()
|
||||
new
|
||||
setline(1, range(3))
|
||||
@@ -155,6 +160,22 @@ def Test_append()
|
||||
bwipe!
|
||||
enddef
|
||||
|
||||
def Test_argc()
|
||||
CheckDefFailure(['echo argc("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_arglistid()
|
||||
CheckDefFailure(['echo arglistid("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo arglistid(1, "y")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo arglistid("x", "y")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_argv()
|
||||
CheckDefFailure(['echo argv("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo argv(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo argv("x", "y")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_balloon_show()
|
||||
CheckGui
|
||||
CheckFeature balloon_eval
|
||||
@@ -256,6 +277,10 @@ def Test_chdir()
|
||||
assert_fails('chdir(true)', 'E1174')
|
||||
enddef
|
||||
|
||||
def Test_clearmatches()
|
||||
CheckDefFailure(['echo clearmatches("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_col()
|
||||
new
|
||||
setline(1, 'asdf')
|
||||
@@ -311,6 +336,11 @@ def Test_cursor()
|
||||
CheckDefExecAndScriptFailure(lines, 'E475:')
|
||||
enddef
|
||||
|
||||
def Test_debugbreak()
|
||||
CheckMSWindows
|
||||
CheckDefFailure(['echo debugbreak("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_delete()
|
||||
var res: bool = delete('doesnotexist')
|
||||
assert_equal(true, res)
|
||||
@@ -324,6 +354,18 @@ def Test_executable()
|
||||
CheckDefExecFailure(['echo executable(true)'], 'E1174:')
|
||||
enddef
|
||||
|
||||
def Test_execute()
|
||||
var res = execute("echo 'hello'")
|
||||
assert_equal("\nhello", res)
|
||||
res = execute(["echo 'here'", "echo 'there'"])
|
||||
assert_equal("\nhere\nthere", res)
|
||||
|
||||
CheckDefFailure(['echo execute(123)'], 'E1013: Argument 1: type mismatch, expected string but got number')
|
||||
CheckDefFailure(['echo execute([123])'], 'E1013: Argument 1: type mismatch, expected list<string> but got list<number>')
|
||||
CheckDefExecFailure(['echo execute(["xx", 123])'], 'E492')
|
||||
CheckDefFailure(['echo execute("xx", 123)'], 'E1013: Argument 2: type mismatch, expected string but got number')
|
||||
enddef
|
||||
|
||||
def Test_exepath()
|
||||
CheckDefExecFailure(['echo exepath(true)'], 'E1174:')
|
||||
CheckDefExecFailure(['echo exepath(v:null)'], 'E1174:')
|
||||
@@ -520,6 +562,64 @@ def Test_flattennew()
|
||||
CheckDefAndScriptFailure(lines, 'E1158:')
|
||||
enddef
|
||||
|
||||
" Test for float functions argument type
|
||||
def Test_float_funcs_args()
|
||||
CheckFeature float
|
||||
|
||||
# acos()
|
||||
CheckDefFailure(['echo acos("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# asin()
|
||||
CheckDefFailure(['echo asin("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# atan()
|
||||
CheckDefFailure(['echo atan("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# atan2()
|
||||
CheckDefFailure(['echo atan2("a", 1.1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo atan2(1.2, "a")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo atan2(1.2)'], 'E119:')
|
||||
# ceil()
|
||||
CheckDefFailure(['echo ceil("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# cos()
|
||||
CheckDefFailure(['echo cos("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# cosh()
|
||||
CheckDefFailure(['echo cosh("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# exp()
|
||||
CheckDefFailure(['echo exp("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# float2nr()
|
||||
CheckDefFailure(['echo float2nr("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# floor()
|
||||
CheckDefFailure(['echo floor("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# fmod()
|
||||
CheckDefFailure(['echo fmod(1.1, "a")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo fmod("a", 1.1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo fmod(1.1)'], 'E119:')
|
||||
# isinf()
|
||||
CheckDefFailure(['echo isinf("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# isnan()
|
||||
CheckDefFailure(['echo isnan("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# log()
|
||||
CheckDefFailure(['echo log("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# log10()
|
||||
CheckDefFailure(['echo log10("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# pow()
|
||||
CheckDefFailure(['echo pow("a", 1.1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo pow(1.1, "a")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo pow(1.1)'], 'E119:')
|
||||
# round()
|
||||
CheckDefFailure(['echo round("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# sin()
|
||||
CheckDefFailure(['echo sin("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# sinh()
|
||||
CheckDefFailure(['echo sinh("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# sqrt()
|
||||
CheckDefFailure(['echo sqrt("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# tan()
|
||||
CheckDefFailure(['echo tan("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# tanh()
|
||||
CheckDefFailure(['echo tanh("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
# trunc()
|
||||
CheckDefFailure(['echo trunc("a")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_fnamemodify()
|
||||
CheckDefSuccess(['echo fnamemodify(test_null_string(), ":p")'])
|
||||
CheckDefSuccess(['echo fnamemodify("", ":p")'])
|
||||
@@ -640,6 +740,20 @@ def Test_getcompletion()
|
||||
set wildignore&
|
||||
enddef
|
||||
|
||||
def Test_getcurpos()
|
||||
CheckDefFailure(['echo getcursorcharpos("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_getcursorcharpos()
|
||||
CheckDefFailure(['echo getcursorcharpos("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_getcwd()
|
||||
CheckDefFailure(['echo getcwd("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo getcwd("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo getcwd(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_getloclist_return_type()
|
||||
var l = getloclist(1)
|
||||
l->assert_equal([])
|
||||
@@ -680,6 +794,16 @@ def Test_getftype()
|
||||
CheckDefExecFailure(['echo getftype(v:null)'], 'E1174:')
|
||||
enddef
|
||||
|
||||
def Test_getjumplist()
|
||||
CheckDefFailure(['echo getjumplist("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo getjumplist("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo getjumplist(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_getmatches()
|
||||
CheckDefFailure(['echo getmatches("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_getqflist_return_type()
|
||||
var l = getqflist()
|
||||
l->assert_equal([])
|
||||
@@ -715,6 +839,22 @@ def Test_getregtype()
|
||||
assert_fails('getregtype("ab")', 'E1162:')
|
||||
enddef
|
||||
|
||||
def Test_gettabinfo()
|
||||
CheckDefFailure(['echo gettabinfo("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_gettagstack()
|
||||
CheckDefFailure(['echo gettagstack("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_getwininfo()
|
||||
CheckDefFailure(['echo getwininfo("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_getwinpos()
|
||||
CheckDefFailure(['echo getwinpos("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_glob()
|
||||
glob('runtest.vim', true, true, true)->assert_equal(['runtest.vim'])
|
||||
enddef
|
||||
@@ -727,6 +867,12 @@ def Test_has()
|
||||
has('eval', true)->assert_equal(1)
|
||||
enddef
|
||||
|
||||
def Test_haslocaldir()
|
||||
CheckDefFailure(['echo haslocaldir("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo haslocaldir("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo haslocaldir(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_hasmapto()
|
||||
hasmapto('foobar', 'i', true)->assert_equal(0)
|
||||
iabbrev foo foobar
|
||||
@@ -778,6 +924,10 @@ def Test_insert()
|
||||
CheckDefFailure(['insert([2, 3], 1, "x")'], 'E1013: Argument 3: type mismatch, expected number but got string', 1)
|
||||
enddef
|
||||
|
||||
def Test_invert()
|
||||
CheckDefFailure(['echo invert("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_keys_return_type()
|
||||
const var: list<string> = {a: 1, b: 2}->keys()
|
||||
var->assert_equal(['a', 'b'])
|
||||
@@ -800,6 +950,10 @@ def SID(): number
|
||||
->str2nr()
|
||||
enddef
|
||||
|
||||
def Test_listener_remove()
|
||||
CheckDefFailure(['echo listener_remove("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_map_function_arg()
|
||||
var lines =<< trim END
|
||||
def MapOne(i: number, v: string): string
|
||||
@@ -902,6 +1056,16 @@ def Test_map_failure()
|
||||
delete('Xtmpfile')
|
||||
enddef
|
||||
|
||||
def Test_matcharg()
|
||||
CheckDefFailure(['echo matcharg("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_matchdelete()
|
||||
CheckDefFailure(['echo matchdelete("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo matchdelete("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo matchdelete(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_max()
|
||||
g:flag = true
|
||||
var l1: list<number> = g:flag
|
||||
@@ -934,6 +1098,11 @@ def Test_nr2char()
|
||||
nr2char(97, true)->assert_equal('a')
|
||||
enddef
|
||||
|
||||
def Test_or()
|
||||
CheckDefFailure(['echo or("x", 0x2)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo or(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_readdir()
|
||||
eval expand('sautest')->readdir((e) => e[0] !=# '.')
|
||||
eval expand('sautest')->readdirex((e) => e.name[0] !=# '.')
|
||||
@@ -983,6 +1152,26 @@ def Test_reverse_return_type()
|
||||
res->assert_equal(6)
|
||||
enddef
|
||||
|
||||
def Test_screenattr()
|
||||
CheckDefFailure(['echo screenattr("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo screenattr(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_screenchar()
|
||||
CheckDefFailure(['echo screenchar("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo screenchar(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_screenchars()
|
||||
CheckDefFailure(['echo screenchars("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo screenchars(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_screenstring()
|
||||
CheckDefFailure(['echo screenstring("x", 1)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo screenstring(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_search()
|
||||
new
|
||||
setline(1, ['foo', 'bar'])
|
||||
@@ -1145,6 +1334,10 @@ def Test_setbufvar()
|
||||
getbufvar('%', 'myvar')->assert_equal(123)
|
||||
enddef
|
||||
|
||||
def Test_setcmdpos()
|
||||
CheckDefFailure(['echo setcmdpos("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_setloclist()
|
||||
var items = [{filename: '/tmp/file', lnum: 1, valid: true}]
|
||||
var what = {items: items}
|
||||
@@ -1160,6 +1353,10 @@ def Test_setreg()
|
||||
assert_fails('setreg("ab", 0)', 'E1162:')
|
||||
enddef
|
||||
|
||||
def Test_shiftwidth()
|
||||
CheckDefFailure(['echo shiftwidth("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_slice()
|
||||
assert_equal('12345', slice('012345', 1))
|
||||
assert_equal('123', slice('012345', 1, 4))
|
||||
@@ -1297,6 +1494,20 @@ def Test_timer_paused()
|
||||
timer_stop(id)
|
||||
enddef
|
||||
|
||||
def Test_tolower()
|
||||
CheckDefFailure(['echo tolower(1)'], 'E1013: Argument 1: type mismatch, expected string but got number')
|
||||
enddef
|
||||
|
||||
def Test_toupper()
|
||||
CheckDefFailure(['echo toupper(1)'], 'E1013: Argument 1: type mismatch, expected string but got number')
|
||||
enddef
|
||||
|
||||
def Test_tr()
|
||||
CheckDefFailure(['echo tr(1, "a", "b")'], 'E1013: Argument 1: type mismatch, expected string but got number')
|
||||
CheckDefFailure(['echo tr("a", 1, "b")'], 'E1013: Argument 2: type mismatch, expected string but got number')
|
||||
CheckDefFailure(['echo tr("a", "a", 1)'], 'E1013: Argument 3: type mismatch, expected string but got number')
|
||||
enddef
|
||||
|
||||
def Test_win_execute()
|
||||
assert_equal("\n" .. winnr(), win_execute(win_getid(), 'echo winnr()'))
|
||||
assert_equal('', win_execute(342343, 'echo winnr()'))
|
||||
@@ -1326,7 +1537,45 @@ def Test_winsaveview()
|
||||
CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<number>', 1)
|
||||
enddef
|
||||
|
||||
def Test_win_gettype()
|
||||
CheckDefFailure(['echo win_gettype("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_win_gotoid()
|
||||
CheckDefFailure(['echo win_gotoid("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_win_id2tabwin()
|
||||
CheckDefFailure(['echo win_id2tabwin("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_win_id2win()
|
||||
CheckDefFailure(['echo win_id2win("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_win_screenpos()
|
||||
CheckDefFailure(['echo win_screenpos("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_winbufnr()
|
||||
CheckDefFailure(['echo winbufnr("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_winheight()
|
||||
CheckDefFailure(['echo winheight("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_winlayout()
|
||||
CheckDefFailure(['echo winlayout("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_winwidth()
|
||||
CheckDefFailure(['echo winwidth("x")'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
def Test_xor()
|
||||
CheckDefFailure(['echo xor("x", 0x2)'], 'E1013: Argument 1: type mismatch, expected number but got string')
|
||||
CheckDefFailure(['echo xor(0x1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string')
|
||||
enddef
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
||||
@@ -452,6 +452,37 @@ def Test_disassemble_list_assign()
|
||||
res)
|
||||
enddef
|
||||
|
||||
def s:ListAssignWithOp()
|
||||
var a = 2
|
||||
var b = 3
|
||||
[a, b] += [4, 5]
|
||||
enddef
|
||||
|
||||
def Test_disassemble_list_assign_with_op()
|
||||
var res = execute('disass s:ListAssignWithOp')
|
||||
assert_match('<SNR>\d*_ListAssignWithOp\_s*' ..
|
||||
'var a = 2\_s*' ..
|
||||
'\d STORE 2 in $0\_s*' ..
|
||||
'var b = 3\_s*' ..
|
||||
'\d STORE 3 in $1\_s*' ..
|
||||
'\[a, b\] += \[4, 5\]\_s*' ..
|
||||
'\d\+ PUSHNR 4\_s*' ..
|
||||
'\d\+ PUSHNR 5\_s*' ..
|
||||
'\d\+ NEWLIST size 2\_s*' ..
|
||||
'\d\+ CHECKLEN 2\_s*' ..
|
||||
'\d\+ LOAD $0\_s*' ..
|
||||
'\d\+ ITEM 0 with op\_s*' ..
|
||||
'\d\+ OPNR +\_s*' ..
|
||||
'\d\+ STORE $0\_s*' ..
|
||||
'\d\+ LOAD $1\_s*' ..
|
||||
'\d\+ ITEM 1 with op\_s*' ..
|
||||
'\d\+ OPNR +\_s*' ..
|
||||
'\d\+ STORE $1\_s*' ..
|
||||
'\d\+ DROP\_s*' ..
|
||||
'\d\+ RETURN void',
|
||||
res)
|
||||
enddef
|
||||
|
||||
def s:ListAdd()
|
||||
var l: list<number> = []
|
||||
add(l, 123)
|
||||
|
||||
@@ -2340,7 +2340,7 @@ def Test_expr7_dict()
|
||||
CheckScriptFailure(['vim9script', "var x = {xxx: 1,"], 'E723:', 2)
|
||||
CheckDefAndScriptFailure2(["var x = {['a']: xxx}"], 'E1001:', 'E121:', 1)
|
||||
CheckDefAndScriptFailure(["var x = {a: 1, a: 2}"], 'E721:', 1)
|
||||
CheckDefExecAndScriptFailure2(["var x = g:anint.member"], 'E715:', 'E15:', 1)
|
||||
CheckDefExecAndScriptFailure2(["var x = g:anint.member"], 'E715:', 'E488:', 1)
|
||||
CheckDefExecAndScriptFailure(["var x = g:dict_empty.member"], 'E716:', 1)
|
||||
|
||||
CheckDefExecAndScriptFailure(['var x: dict<number> = {a: 234, b: "1"}'], 'E1012:', 1)
|
||||
@@ -2943,7 +2943,9 @@ def Test_expr7_method_call()
|
||||
loclist->setloclist(0)
|
||||
assert_equal([{bufnr: bufnr,
|
||||
lnum: 42,
|
||||
end_lnum: 0,
|
||||
col: 17,
|
||||
end_col: 0,
|
||||
text: 'wrong',
|
||||
pattern: '',
|
||||
valid: 1,
|
||||
@@ -3052,7 +3054,7 @@ func Test_expr7_fails()
|
||||
|
||||
call CheckDefAndScriptFailure2(["var x = [notfound]"], "E1001:", 'E121:', 1)
|
||||
|
||||
call CheckDefAndScriptFailure2(["var X = () => 123)"], "E488:", 'E15:', 1)
|
||||
call CheckDefAndScriptFailure(["var X = () => 123)"], 'E488:', 1)
|
||||
call CheckDefAndScriptFailure(["var x = 123->((x) => x + 5)"], "E107:", 1)
|
||||
|
||||
call CheckDefAndScriptFailure(["var x = ¬exist"], 'E113:', 1)
|
||||
@@ -3070,7 +3072,7 @@ func Test_expr7_fails()
|
||||
call CheckDefExecAndScriptFailure(["var x = +g:alist"], 'E745:', 1)
|
||||
call CheckDefExecAndScriptFailure(["var x = +g:adict"], 'E728:', 1)
|
||||
|
||||
call CheckDefAndScriptFailure2(["var x = ''", "var y = x.memb"], 'E715:', 'E15:', 2)
|
||||
call CheckDefAndScriptFailure2(["var x = ''", "var y = x.memb"], 'E715:', 'E488:', 2)
|
||||
|
||||
call CheckDefAndScriptFailure2(["'yes'->", "Echo()"], 'E488: Trailing characters: ->', 'E260: Missing name after ->', 1)
|
||||
|
||||
@@ -3354,8 +3356,8 @@ func Test_expr7_trailing_fails()
|
||||
endfunc
|
||||
|
||||
func Test_expr_fails()
|
||||
call CheckDefAndScriptFailure2(["var x = '1'is2"], 'E488:', 'E15:', 1)
|
||||
call CheckDefAndScriptFailure2(["var x = '1'isnot2"], 'E488:', 'E15:', 1)
|
||||
call CheckDefAndScriptFailure(["var x = '1'is2"], 'E488:', 1)
|
||||
call CheckDefAndScriptFailure(["var x = '1'isnot2"], 'E488:', 1)
|
||||
|
||||
call CheckDefAndScriptFailure2(["CallMe ('yes')"], 'E476:', 'E492:', 1)
|
||||
|
||||
|
||||
@@ -90,6 +90,24 @@ def Test_compile_error_in_called_function()
|
||||
CheckScriptFailureList(lines, ['E1012:', 'E1191:'])
|
||||
enddef
|
||||
|
||||
def Test_wrong_function_name()
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
func _Foo()
|
||||
echo 'foo'
|
||||
endfunc
|
||||
END
|
||||
CheckScriptFailure(lines, 'E128:')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
def _Foo()
|
||||
echo 'foo'
|
||||
enddef
|
||||
END
|
||||
CheckScriptFailure(lines, 'E128:')
|
||||
enddef
|
||||
|
||||
def Test_autoload_name_mismatch()
|
||||
var dir = 'Xdir/autoload'
|
||||
mkdir(dir, 'p')
|
||||
@@ -987,6 +1005,20 @@ def Test_pass_legacy_lambda_to_def_func()
|
||||
Foo()
|
||||
END
|
||||
CheckScriptSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
def g:TestFunc(f: func())
|
||||
enddef
|
||||
legacy call g:TestFunc({-> 0})
|
||||
delfunc g:TestFunc
|
||||
|
||||
def g:TestFunc(f: func(number))
|
||||
enddef
|
||||
legacy call g:TestFunc({nr -> 0})
|
||||
delfunc g:TestFunc
|
||||
END
|
||||
CheckScriptSuccess(lines)
|
||||
enddef
|
||||
|
||||
" Default arg and varargs
|
||||
|
||||
@@ -3212,7 +3212,7 @@ def Test_vim9_comment_not_compiled()
|
||||
'if 1# comment3',
|
||||
' echo "yes"',
|
||||
'endif',
|
||||
], 'E15:')
|
||||
], 'E488:')
|
||||
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
@@ -3221,7 +3221,7 @@ def Test_vim9_comment_not_compiled()
|
||||
'elseif 2#comment',
|
||||
' echo "no"',
|
||||
'endif',
|
||||
], 'E15:')
|
||||
], 'E488:')
|
||||
|
||||
CheckScriptSuccess([
|
||||
'vim9script',
|
||||
@@ -3231,7 +3231,7 @@ def Test_vim9_comment_not_compiled()
|
||||
CheckScriptFailure([
|
||||
'vim9script',
|
||||
'var v = 1# comment6',
|
||||
], 'E15:')
|
||||
], 'E488:')
|
||||
|
||||
CheckScriptSuccess([
|
||||
'vim9script',
|
||||
@@ -3937,6 +3937,26 @@ def Test_mapping_line_number()
|
||||
delfunc g:FuncA
|
||||
enddef
|
||||
|
||||
def Test_option_modifier()
|
||||
var lines =<< trim END
|
||||
set hlsearch & hlsearch !
|
||||
call assert_equal(1, &hlsearch)
|
||||
END
|
||||
CheckScriptSuccess(lines)
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
set hlsearch &
|
||||
END
|
||||
CheckScriptFailure(lines, 'E518:')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
set hlsearch & hlsearch !
|
||||
END
|
||||
CheckScriptFailure(lines, 'E518:')
|
||||
enddef
|
||||
|
||||
" Keep this last, it messes up highlighting.
|
||||
def Test_substitute_cmd()
|
||||
new
|
||||
|
||||
@@ -4,7 +4,7 @@ source check.vim
|
||||
source term_util.vim
|
||||
source shared.vim
|
||||
|
||||
function Test_viminfo_read_and_write()
|
||||
func Test_viminfo_read_and_write()
|
||||
" First clear 'history', so that "hislen" is zero. Then set it again,
|
||||
" simulating Vim starting up.
|
||||
set history=0
|
||||
@@ -12,6 +12,7 @@ function Test_viminfo_read_and_write()
|
||||
set history=1000
|
||||
|
||||
call histdel(':')
|
||||
let @/=''
|
||||
let lines = [
|
||||
\ '# comment line',
|
||||
\ '*encoding=utf-8',
|
||||
@@ -62,6 +63,7 @@ func Test_global_vars()
|
||||
let g:MY_GLOBAL_NULL = test_null
|
||||
let test_none = v:none
|
||||
let g:MY_GLOBAL_NONE = test_none
|
||||
let g:MY_GLOBAL_FUNCREF = function('min')
|
||||
|
||||
set viminfo='100,<50,s10,h,!,nviminfo
|
||||
wv! Xviminfo
|
||||
@@ -76,6 +78,7 @@ func Test_global_vars()
|
||||
unlet g:MY_GLOBAL_TRUE
|
||||
unlet g:MY_GLOBAL_NULL
|
||||
unlet g:MY_GLOBAL_NONE
|
||||
unlet g:MY_GLOBAL_FUNCREF
|
||||
|
||||
rv! Xviminfo
|
||||
call assert_equal("Vim Editor", g:MY_GLOBAL_STRING)
|
||||
@@ -88,6 +91,37 @@ func Test_global_vars()
|
||||
call assert_equal(test_true, g:MY_GLOBAL_TRUE)
|
||||
call assert_equal(test_null, g:MY_GLOBAL_NULL)
|
||||
call assert_equal(test_none, g:MY_GLOBAL_NONE)
|
||||
call assert_false(exists("g:MY_GLOBAL_FUNCREF"))
|
||||
|
||||
" When reading global variables from viminfo, if a variable cannot be
|
||||
" modified, then the value should not be changed.
|
||||
unlet g:MY_GLOBAL_STRING
|
||||
unlet g:MY_GLOBAL_NUM
|
||||
unlet g:MY_GLOBAL_FLOAT
|
||||
unlet g:MY_GLOBAL_DICT
|
||||
unlet g:MY_GLOBAL_LIST
|
||||
unlet g:MY_GLOBAL_BLOB
|
||||
|
||||
const g:MY_GLOBAL_STRING = 'New Value'
|
||||
const g:MY_GLOBAL_NUM = 987
|
||||
const g:MY_GLOBAL_FLOAT = 1.16
|
||||
const g:MY_GLOBAL_DICT = {'editor': 'vim'}
|
||||
const g:MY_GLOBAL_LIST = [5, 7, 13]
|
||||
const g:MY_GLOBAL_BLOB = 0zDEADBEEF
|
||||
call assert_fails('rv! Xviminfo', 'E741:')
|
||||
call assert_equal('New Value', g:MY_GLOBAL_STRING)
|
||||
call assert_equal(987, g:MY_GLOBAL_NUM)
|
||||
call assert_equal(1.16, g:MY_GLOBAL_FLOAT)
|
||||
call assert_equal({'editor': 'vim'}, g:MY_GLOBAL_DICT)
|
||||
call assert_equal([5, 7 , 13], g:MY_GLOBAL_LIST)
|
||||
call assert_equal(0zDEADBEEF, g:MY_GLOBAL_BLOB)
|
||||
|
||||
unlet g:MY_GLOBAL_STRING
|
||||
unlet g:MY_GLOBAL_NUM
|
||||
unlet g:MY_GLOBAL_FLOAT
|
||||
unlet g:MY_GLOBAL_DICT
|
||||
unlet g:MY_GLOBAL_LIST
|
||||
unlet g:MY_GLOBAL_BLOB
|
||||
|
||||
" Test for invalid values for a blob, list, dict in a viminfo file
|
||||
call writefile([
|
||||
@@ -97,7 +131,7 @@ func Test_global_vars()
|
||||
\ "!GLOB_BLOB_4\tBLO\t0z12 ab",
|
||||
\ "!GLOB_LIST_1\tLIS\t1 2",
|
||||
\ "!GLOB_DICT_1\tDIC\t1 2"], 'Xviminfo')
|
||||
call assert_fails('rv! Xviminfo', 'E15:')
|
||||
call assert_fails('rv! Xviminfo', 'E488:')
|
||||
call assert_equal('123', g:GLOB_BLOB_1)
|
||||
call assert_equal(1, type(g:GLOB_BLOB_1))
|
||||
call assert_equal('012', g:GLOB_BLOB_2)
|
||||
@@ -199,7 +233,26 @@ func Test_cmdline_history()
|
||||
call assert_equal("echo " . long800, histget(':', -2))
|
||||
call assert_equal("echo 'one'", histget(':', -3))
|
||||
|
||||
" If the value for the '/' or ':' or '@' field in 'viminfo' is zero, then
|
||||
" the corresponding history entries are not saved.
|
||||
set viminfo='100,/0,:0,@0,<50,s10,h,!,nviminfo
|
||||
call histdel('/')
|
||||
call histdel(':')
|
||||
call histdel('@')
|
||||
call histadd('/', 'foo')
|
||||
call histadd(':', 'bar')
|
||||
call histadd('@', 'baz')
|
||||
wviminfo! Xviminfo
|
||||
call histdel('/')
|
||||
call histdel(':')
|
||||
call histdel('@')
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal('', histget('/'))
|
||||
call assert_equal('', histget(':'))
|
||||
call assert_equal('', histget('@'))
|
||||
|
||||
call delete('Xviminfo')
|
||||
set viminfo&vim
|
||||
endfunc
|
||||
|
||||
func Test_cmdline_history_order()
|
||||
@@ -315,7 +368,33 @@ func Test_viminfo_registers()
|
||||
let len += 1
|
||||
endwhile
|
||||
|
||||
" If the maximum number of lines saved for a register ('<' in 'viminfo') is
|
||||
" zero, then register values should not be saved.
|
||||
let @a = 'abc'
|
||||
set viminfo='100,<0,s10,h,!,nviminfo
|
||||
wviminfo Xviminfo
|
||||
let @a = 'xyz'
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal('xyz', @a)
|
||||
" repeat the test with '"' instead of '<'
|
||||
let @b = 'def'
|
||||
set viminfo='100,\"0,s10,h,!,nviminfo
|
||||
wviminfo Xviminfo
|
||||
let @b = 'rst'
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal('rst', @b)
|
||||
|
||||
" If the maximum size of an item ('s' in 'viminfo') is zero, then register
|
||||
" values should not be saved.
|
||||
let @c = '123'
|
||||
set viminfo='100,<20,s0,h,!,nviminfo
|
||||
wviminfo Xviminfo
|
||||
let @c = '456'
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal('456', @c)
|
||||
|
||||
call delete('Xviminfo')
|
||||
set viminfo&vim
|
||||
endfunc
|
||||
|
||||
func Test_viminfo_marks()
|
||||
@@ -510,6 +589,35 @@ func Test_viminfo_bad_syntax()
|
||||
call delete('Xviminfo')
|
||||
endfunc
|
||||
|
||||
func Test_viminfo_bad_syntax2()
|
||||
let lines = []
|
||||
call add(lines, '|1,4')
|
||||
|
||||
" bad viminfo syntax for history barline
|
||||
call add(lines, '|2') " invalid number of fields in a history barline
|
||||
call add(lines, '|2,9,1,1,"x"') " invalid value for the history type
|
||||
call add(lines, '|2,0,,1,"x"') " no timestamp
|
||||
call add(lines, '|2,0,1,1,10') " non-string text
|
||||
|
||||
" bad viminfo syntax for register barline
|
||||
call add(lines, '|3') " invalid number of fields in a register barline
|
||||
call add(lines, '|3,1,1,1,1,,1,"x"') " missing width field
|
||||
call add(lines, '|3,0,80,1,1,1,1,"x"') " invalid register number
|
||||
call add(lines, '|3,0,10,5,1,1,1,"x"') " invalid register type
|
||||
call add(lines, '|3,0,10,1,20,1,1,"x"') " invalid line count
|
||||
call add(lines, '|3,0,10,1,0,1,1') " zero line count
|
||||
|
||||
" bad viminfo syntax for mark barline
|
||||
call add(lines, '|4') " invalid number of fields in a mark barline
|
||||
call add(lines, '|4,1,1,1,1,1') " invalid value for file name
|
||||
call add(lines, '|4,20,1,1,1,"x"') " invalid value for file name
|
||||
call add(lines, '|4,49,0,1,1,"x"') " invalid value for line number
|
||||
|
||||
call writefile(lines, 'Xviminfo')
|
||||
rviminfo Xviminfo
|
||||
call delete('Xviminfo')
|
||||
endfunc
|
||||
|
||||
func Test_viminfo_file_marks()
|
||||
silent! bwipe test_viminfo.vim
|
||||
silent! bwipe Xviminfo
|
||||
@@ -664,6 +772,7 @@ func Test_viminfo_bufferlist()
|
||||
" If there are arguments, then :rviminfo doesn't read the buffer list.
|
||||
" Need to delete all the arguments for :rviminfo to work.
|
||||
%argdelete
|
||||
set viminfo&vim
|
||||
|
||||
edit Xfile1
|
||||
edit Xfile2
|
||||
@@ -684,9 +793,42 @@ func Test_viminfo_bufferlist()
|
||||
call assert_equal('Xfile1', bufname(l[1].bufnr))
|
||||
call assert_equal('Xfile2', bufname(l[2].bufnr))
|
||||
|
||||
" The quickfix, terminal, unlisted, unnamed buffers are not stored in the
|
||||
" viminfo file
|
||||
%bw!
|
||||
edit Xfile1
|
||||
new
|
||||
setlocal nobuflisted
|
||||
new
|
||||
copen
|
||||
if has('terminal')
|
||||
terminal
|
||||
endif
|
||||
wviminfo! Xviminfo
|
||||
%bwipe!
|
||||
rviminfo Xviminfo
|
||||
let l = getbufinfo()
|
||||
call assert_equal(2, len(l))
|
||||
call assert_true(bufexists('Xfile1'))
|
||||
|
||||
" If a count is specified for '%', then only that many buffers should be
|
||||
" stored in the viminfo file.
|
||||
%bw!
|
||||
set viminfo&vim
|
||||
new Xbuf1
|
||||
new Xbuf2
|
||||
set viminfo+=%1
|
||||
wviminfo! Xviminfo
|
||||
%bwipe!
|
||||
rviminfo! Xviminfo
|
||||
let l = getbufinfo()
|
||||
call assert_equal(2, len(l))
|
||||
call assert_true(bufexists('Xbuf1'))
|
||||
call assert_false(bufexists('Xbuf2'))
|
||||
|
||||
call delete('Xviminfo')
|
||||
%bwipe
|
||||
set viminfo-=%
|
||||
set viminfo&vim
|
||||
endfunc
|
||||
|
||||
" Test for errors in a viminfo file
|
||||
@@ -747,6 +889,12 @@ func Test_viminfo_registers_old()
|
||||
\ ' Vim',
|
||||
\ '"a CHAR 0',
|
||||
\ ' red',
|
||||
\ '"c BLOCK 0',
|
||||
\ ' a',
|
||||
\ ' d',
|
||||
\ '"d LINE 0',
|
||||
\ ' abc',
|
||||
\ ' def',
|
||||
\ '"m@ CHAR 0',
|
||||
\ " :echo 'Hello'\<CR>",
|
||||
\ "",
|
||||
@@ -760,7 +908,12 @@ func Test_viminfo_registers_old()
|
||||
silent! normal @t
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal('red', getreg('a'))
|
||||
call assert_equal("v", getregtype('a'))
|
||||
call assert_equal('two', getreg('b'))
|
||||
call assert_equal("a\nd", getreg('c'))
|
||||
call assert_equal("\<C-V>1", getregtype('c'))
|
||||
call assert_equal("abc\ndef\n", getreg('d'))
|
||||
call assert_equal("V", getregtype('d'))
|
||||
call assert_equal(":echo 'Hello'\<CR>", getreg('m'))
|
||||
call assert_equal('Vim', getreg('"'))
|
||||
call assert_equal("\nHello", execute('normal @@'))
|
||||
@@ -811,6 +964,7 @@ func Test_viminfo_perm()
|
||||
" Try to write the viminfo to a directory
|
||||
call mkdir('Xdir')
|
||||
call assert_fails('wviminfo Xdir', 'E137:')
|
||||
call assert_fails('rviminfo Xdir', 'E195:')
|
||||
call delete('Xdir', 'rf')
|
||||
endfunc
|
||||
|
||||
@@ -914,4 +1068,228 @@ func Test_viminfo_oldfiles_newfile()
|
||||
let &viminfofile = save_viminfofile
|
||||
endfunc
|
||||
|
||||
" When writing CTRL-V or "\n" to a viminfo file, it is converted to CTRL-V
|
||||
" CTRL-V and CTRL-V n respectively.
|
||||
func Test_viminfo_with_Ctrl_V()
|
||||
silent! exe "normal! /\<C-V>\<C-V>\n"
|
||||
wviminfo Xviminfo
|
||||
call assert_notequal(-1, readfile('Xviminfo')->index("?/\<C-V>\<C-V>"))
|
||||
let @/ = 'abc'
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal("\<C-V>", @/)
|
||||
silent! exe "normal! /\<C-V>\<C-J>\n"
|
||||
wviminfo Xviminfo
|
||||
call assert_notequal(-1, readfile('Xviminfo')->index("?/\<C-V>n"))
|
||||
let @/ = 'abc'
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal("\n", @/)
|
||||
call delete('Xviminfo')
|
||||
endfunc
|
||||
|
||||
" Test for the 'r' field in 'viminfo' (removal media)
|
||||
func Test_viminfo_removable_media()
|
||||
CheckUnix
|
||||
if !isdirectory('/tmp') || getftype('/tmp') != 'dir'
|
||||
return
|
||||
endif
|
||||
let save_viminfo = &viminfo
|
||||
set viminfo+=r/tmp
|
||||
edit /tmp/Xvima1b2c3
|
||||
wviminfo Xviminfo
|
||||
let matches = readfile('Xviminfo')->filter("v:val =~ 'Xvima1b2c3'")
|
||||
call assert_equal(0, matches->len())
|
||||
let &viminfo = save_viminfo
|
||||
call delete('Xviminfo')
|
||||
endfunc
|
||||
|
||||
" Test for the 'h' flag in 'viminfo'. If 'h' is not present, then the last
|
||||
" search pattern read from 'viminfo' should be highlighted with 'hlsearch'.
|
||||
" If 'h' is present, then the last search pattern should not be highlighted.
|
||||
func Test_viminfo_hlsearch()
|
||||
set viminfo&vim
|
||||
|
||||
new
|
||||
call setline(1, ['one two three'])
|
||||
" save the screen attribute for the Search highlighted text and the normal
|
||||
" text for later comparison
|
||||
set hlsearch
|
||||
let @/ = 'three'
|
||||
redraw!
|
||||
let hiSearch = screenattr(1, 9)
|
||||
let hiNormal = screenattr(1, 1)
|
||||
|
||||
set viminfo-=h
|
||||
let @/='two'
|
||||
wviminfo! Xviminfo
|
||||
let @/='one'
|
||||
rviminfo! Xviminfo
|
||||
redraw!
|
||||
call assert_equal(hiSearch, screenattr(1, 5))
|
||||
call assert_equal(hiSearch, screenattr(1, 6))
|
||||
call assert_equal(hiSearch, screenattr(1, 7))
|
||||
|
||||
set viminfo+=h
|
||||
let @/='two'
|
||||
wviminfo! Xviminfo
|
||||
let @/='one'
|
||||
rviminfo! Xviminfo
|
||||
redraw!
|
||||
call assert_equal(hiNormal, screenattr(1, 5))
|
||||
call assert_equal(hiNormal, screenattr(1, 6))
|
||||
call assert_equal(hiNormal, screenattr(1, 7))
|
||||
|
||||
call delete('Xviminfo')
|
||||
set hlsearch& viminfo&vim
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" Test for restoring the magicness of the last search pattern from the viminfo
|
||||
" file.
|
||||
func Test_viminfo_last_spat_magic()
|
||||
set viminfo&vim
|
||||
new
|
||||
call setline(1, ' one abc a.c')
|
||||
|
||||
" restore 'nomagic'
|
||||
set nomagic
|
||||
exe "normal gg/a.c\<CR>"
|
||||
wviminfo! Xviminfo
|
||||
set magic
|
||||
exe "normal gg/one\<CR>"
|
||||
rviminfo! Xviminfo
|
||||
exe "normal! gg/\<CR>"
|
||||
call assert_equal(10, col('.'))
|
||||
|
||||
" restore 'magic'
|
||||
set magic
|
||||
exe "normal gg/a.c\<CR>"
|
||||
wviminfo! Xviminfo
|
||||
set nomagic
|
||||
exe "normal gg/one\<CR>"
|
||||
rviminfo! Xviminfo
|
||||
exe "normal! gg/\<CR>"
|
||||
call assert_equal(6, col('.'))
|
||||
|
||||
call delete('Xviminfo')
|
||||
set viminfo&vim magic&
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" Test for restoring the smartcase of the last search pattern from the viminfo
|
||||
" file.
|
||||
func Test_viminfo_last_spat_smartcase()
|
||||
new
|
||||
call setline(1, ' one abc Abc')
|
||||
set ignorecase smartcase
|
||||
|
||||
" Searching with * should disable smartcase
|
||||
exe "normal! gg$b*"
|
||||
wviminfo! Xviminfo
|
||||
exe "normal gg/one\<CR>"
|
||||
rviminfo! Xviminfo
|
||||
exe "normal! gg/\<CR>"
|
||||
call assert_equal(6, col('.'))
|
||||
|
||||
call delete('Xviminfo')
|
||||
set ignorecase& smartcase& viminfo&
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" Test for restoring the last search pattern with a line or character offset
|
||||
" from the viminfo file.
|
||||
func Test_viminfo_last_spat_offset()
|
||||
new
|
||||
call setline(1, ['one', 'two', 'three', 'four', 'five'])
|
||||
" line offset
|
||||
exe "normal! /two/+2\<CR>"
|
||||
wviminfo! Xviminfo
|
||||
exe "normal gg/five\<CR>"
|
||||
rviminfo! Xviminfo
|
||||
exe "normal! gg/\<CR>"
|
||||
call assert_equal(4, line('.'))
|
||||
" character offset
|
||||
exe "normal! gg/^th/e+2\<CR>"
|
||||
wviminfo! Xviminfo
|
||||
exe "normal gg/two\<CR>"
|
||||
rviminfo! Xviminfo
|
||||
exe "normal! gg/\<CR>"
|
||||
call assert_equal([3, 4], [line('.'), col('.')])
|
||||
call delete('Xviminfo')
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" Test for saving and restoring the last executed register (@ command)
|
||||
" from the viminfo file
|
||||
func Test_viminfo_last_exec_reg()
|
||||
let g:val = 1
|
||||
let @a = ":let g:val += 1\n"
|
||||
normal! @a
|
||||
wviminfo! Xviminfo
|
||||
let @b = ''
|
||||
normal! @b
|
||||
rviminfo! Xviminfo
|
||||
normal @@
|
||||
call assert_equal(3, g:val)
|
||||
call delete('Xviminfo')
|
||||
endfunc
|
||||
|
||||
" Test for merging file marks in a viminfo file
|
||||
func Test_viminfo_merge_file_marks()
|
||||
for [f, l, t] in [['a.txt', 5, 10], ['b.txt', 10, 20]]
|
||||
call test_settime(t)
|
||||
exe 'edit ' .. f
|
||||
call setline(1, range(1, 20))
|
||||
exe l . 'mark a'
|
||||
wviminfo Xviminfo
|
||||
bw!
|
||||
endfor
|
||||
call test_settime(30)
|
||||
for [f, l] in [['a.txt', 5], ['b.txt', 10]]
|
||||
exe 'edit ' .. f
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal(l, line("'a"))
|
||||
bw!
|
||||
endfor
|
||||
call delete('Xviminfo')
|
||||
call test_settime(0)
|
||||
endfunc
|
||||
|
||||
" Test for merging file marks from a old viminfo file
|
||||
func Test_viminfo_merge_old_filemarks()
|
||||
let lines = []
|
||||
call add(lines, '|1,4')
|
||||
call add(lines, '> ' .. fnamemodify('a.txt', ':p:~'))
|
||||
call add(lines, "\tb\t7\t0\n")
|
||||
call writefile(lines, 'Xviminfo')
|
||||
edit b.txt
|
||||
call setline(1, range(1, 20))
|
||||
12mark b
|
||||
wviminfo Xviminfo
|
||||
bw!
|
||||
edit a.txt
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal(7, line("'b"))
|
||||
edit b.txt
|
||||
rviminfo! Xviminfo
|
||||
call assert_equal(12, line("'b"))
|
||||
call delete('Xviminfo')
|
||||
endfunc
|
||||
|
||||
" Test for merging the jump list from a old viminfo file
|
||||
func Test_viminfo_merge_old_jumplist()
|
||||
let lines = []
|
||||
call add(lines, "-' 10 1 " .. fnamemodify('a.txt', ':p:~'))
|
||||
call add(lines, "-' 20 1 " .. fnamemodify('a.txt', ':p:~'))
|
||||
call add(lines, "-' 30 1 " .. fnamemodify('b.txt', ':p:~'))
|
||||
call add(lines, "-' 40 1 " .. fnamemodify('b.txt', ':p:~'))
|
||||
call writefile(lines, 'Xviminfo')
|
||||
clearjumps
|
||||
rviminfo! Xviminfo
|
||||
let l = getjumplist()[0]
|
||||
call assert_equal([40, 30, 20, 10], [l[0].lnum, l[1].lnum, l[2].lnum,
|
||||
\ l[3].lnum])
|
||||
bw!
|
||||
call delete('Xviminfo')
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -5570,7 +5570,7 @@ func Test_expr_eval_error_msg()
|
||||
call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
|
||||
call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
|
||||
call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
|
||||
call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression")
|
||||
call T(22, '1 2 + CONT(22)', 'E488', "Trailing characters: 2 +")
|
||||
call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
|
||||
call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
|
||||
call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")
|
||||
|
||||
@@ -1211,10 +1211,46 @@ f_test_scrollbar(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
void
|
||||
f_test_setmouse(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
if (argvars[0].v_type != VAR_NUMBER || (argvars[1].v_type) != VAR_NUMBER)
|
||||
{
|
||||
emsg(_(e_invarg));
|
||||
return;
|
||||
}
|
||||
|
||||
mouse_row = (time_t)tv_get_number(&argvars[0]) - 1;
|
||||
mouse_col = (time_t)tv_get_number(&argvars[1]) - 1;
|
||||
}
|
||||
|
||||
void
|
||||
f_test_gui_mouse_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
||||
{
|
||||
#ifdef FEAT_GUI
|
||||
int button;
|
||||
int row;
|
||||
int col;
|
||||
int repeated_click;
|
||||
int_u mods;
|
||||
|
||||
if (argvars[0].v_type != VAR_NUMBER
|
||||
|| (argvars[1].v_type) != VAR_NUMBER
|
||||
|| (argvars[2].v_type) != VAR_NUMBER
|
||||
|| (argvars[3].v_type) != VAR_NUMBER
|
||||
|| (argvars[4].v_type) != VAR_NUMBER)
|
||||
{
|
||||
emsg(_(e_invarg));
|
||||
return;
|
||||
}
|
||||
|
||||
button = tv_get_number(&argvars[0]);
|
||||
row = tv_get_number(&argvars[1]);
|
||||
col = tv_get_number(&argvars[2]);
|
||||
repeated_click = tv_get_number(&argvars[3]);
|
||||
mods = tv_get_number(&argvars[4]);
|
||||
|
||||
gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1), repeated_click, mods);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
f_test_settime(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
|
||||
+8
-4
@@ -963,7 +963,9 @@ undo_flush(bufinfo_T *bi)
|
||||
{
|
||||
if (bi->bi_buffer != NULL && bi->bi_state != NULL && bi->bi_used > 0)
|
||||
{
|
||||
crypt_encode_inplace(bi->bi_state, bi->bi_buffer, bi->bi_used);
|
||||
// Last parameter is only used for sodium encryption and that
|
||||
// explicitly disables encryption of undofiles.
|
||||
crypt_encode_inplace(bi->bi_state, bi->bi_buffer, bi->bi_used, FALSE);
|
||||
if (fwrite(bi->bi_buffer, bi->bi_used, (size_t)1, bi->bi_fp) != 1)
|
||||
return FAIL;
|
||||
bi->bi_used = 0;
|
||||
@@ -995,7 +997,9 @@ fwrite_crypt(bufinfo_T *bi, char_u *ptr, size_t len)
|
||||
if (copy == NULL)
|
||||
return 0;
|
||||
}
|
||||
crypt_encode(bi->bi_state, ptr, len, copy);
|
||||
// Last parameter is only used for sodium encryption and that
|
||||
// explicitly disables encryption of undofiles.
|
||||
crypt_encode(bi->bi_state, ptr, len, copy, TRUE);
|
||||
i = fwrite(copy, len, (size_t)1, bi->bi_fp);
|
||||
if (copy != small_buf)
|
||||
vim_free(copy);
|
||||
@@ -1129,7 +1133,7 @@ undo_read(bufinfo_T *bi, char_u *buffer, size_t size)
|
||||
}
|
||||
bi->bi_avail = n;
|
||||
bi->bi_used = 0;
|
||||
crypt_decode_inplace(bi->bi_state, bi->bi_buffer, bi->bi_avail);
|
||||
crypt_decode_inplace(bi->bi_state, bi->bi_buffer, bi->bi_avail, FALSE);
|
||||
}
|
||||
n = size_todo;
|
||||
if (n > bi->bi_avail - bi->bi_used)
|
||||
@@ -1176,7 +1180,7 @@ read_string_decrypt(bufinfo_T *bi, int len)
|
||||
ptr[len] = NUL;
|
||||
#ifdef FEAT_CRYPT
|
||||
if (bi->bi_state != NULL && bi->bi_buffer == NULL)
|
||||
crypt_decode_inplace(bi->bi_state, ptr, len);
|
||||
crypt_decode_inplace(bi->bi_state, ptr, len, FALSE);
|
||||
#endif
|
||||
}
|
||||
return ptr;
|
||||
|
||||
+2
-1
@@ -3595,7 +3595,8 @@ trans_function_name(
|
||||
lead += (int)STRLEN(sid_buf);
|
||||
}
|
||||
}
|
||||
else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len))
|
||||
else if (!(flags & TFN_INT) && (builtin_function(lv.ll_name, len)
|
||||
|| (in_vim9script() && *lv.ll_name == '_')))
|
||||
{
|
||||
semsg(_("E128: Function name must start with a capital or \"s:\": %s"),
|
||||
start);
|
||||
|
||||
@@ -563,6 +563,11 @@ static char *(features[]) =
|
||||
#else
|
||||
"-smartindent",
|
||||
#endif
|
||||
#ifdef FEAT_SODIUM
|
||||
"+sodium",
|
||||
#else
|
||||
"-sodium",
|
||||
#endif
|
||||
#ifdef FEAT_SOUND
|
||||
"+sound",
|
||||
#else
|
||||
@@ -765,6 +770,62 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
3036,
|
||||
/**/
|
||||
3035,
|
||||
/**/
|
||||
3034,
|
||||
/**/
|
||||
3033,
|
||||
/**/
|
||||
3032,
|
||||
/**/
|
||||
3031,
|
||||
/**/
|
||||
3030,
|
||||
/**/
|
||||
3029,
|
||||
/**/
|
||||
3028,
|
||||
/**/
|
||||
3027,
|
||||
/**/
|
||||
3026,
|
||||
/**/
|
||||
3025,
|
||||
/**/
|
||||
3024,
|
||||
/**/
|
||||
3023,
|
||||
/**/
|
||||
3022,
|
||||
/**/
|
||||
3021,
|
||||
/**/
|
||||
3020,
|
||||
/**/
|
||||
3019,
|
||||
/**/
|
||||
3018,
|
||||
/**/
|
||||
3017,
|
||||
/**/
|
||||
3016,
|
||||
/**/
|
||||
3015,
|
||||
/**/
|
||||
3014,
|
||||
/**/
|
||||
3013,
|
||||
/**/
|
||||
3012,
|
||||
/**/
|
||||
3011,
|
||||
/**/
|
||||
3010,
|
||||
/**/
|
||||
3009,
|
||||
/**/
|
||||
3008,
|
||||
/**/
|
||||
|
||||
@@ -1813,9 +1813,9 @@ typedef enum {
|
||||
|
||||
// Keep in sync with INSTRUCTIONS().
|
||||
#ifdef FEAT_PROFILE
|
||||
# define COMPILE_TYPE(ufunc) (debug_break_level > 0 ? CT_DEBUG : do_profiling == PROF_YES && (ufunc)->uf_profiling ? CT_PROFILE : CT_NONE)
|
||||
# define COMPILE_TYPE(ufunc) (debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : do_profiling == PROF_YES && (ufunc)->uf_profiling ? CT_PROFILE : CT_NONE)
|
||||
#else
|
||||
# define COMPILE_TYPE(ufunc) debug_break_level > 0 ? CT_DEBUG : CT_NONE
|
||||
# define COMPILE_TYPE(ufunc) debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : CT_NONE
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
+8
-1
@@ -209,6 +209,12 @@ typedef struct {
|
||||
int cuf_argcount; // number of arguments on top of stack
|
||||
} cufunc_T;
|
||||
|
||||
// arguments to ISN_GETITEM
|
||||
typedef struct {
|
||||
varnumber_T gi_index;
|
||||
int gi_with_op;
|
||||
} getitem_T;
|
||||
|
||||
typedef enum {
|
||||
JUMP_ALWAYS,
|
||||
JUMP_IF_FALSE, // pop and jump if false
|
||||
@@ -432,6 +438,7 @@ struct isn_S {
|
||||
isn_T *instr;
|
||||
tostring_T tostring;
|
||||
tobool_T tobool;
|
||||
getitem_T getitem;
|
||||
} isn_arg;
|
||||
};
|
||||
|
||||
@@ -498,7 +505,7 @@ extern garray_T def_functions;
|
||||
// Keep in sync with COMPILE_TYPE()
|
||||
#ifdef FEAT_PROFILE
|
||||
# define INSTRUCTIONS(dfunc) \
|
||||
(debug_break_level > 0 \
|
||||
(debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
|
||||
? (dfunc)->df_instr_debug \
|
||||
: ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \
|
||||
? (dfunc)->df_instr_prof \
|
||||
|
||||
+44
-17
@@ -1240,13 +1240,16 @@ generate_PUSHFUNC(cctx_T *cctx, char_u *name, type_T *type)
|
||||
|
||||
/*
|
||||
* Generate an ISN_GETITEM instruction with "index".
|
||||
* "with_op" is TRUE for "+=" and other operators, the stack has the current
|
||||
* value below the list with values.
|
||||
*/
|
||||
static int
|
||||
generate_GETITEM(cctx_T *cctx, int index)
|
||||
generate_GETITEM(cctx_T *cctx, int index, int with_op)
|
||||
{
|
||||
isn_T *isn;
|
||||
garray_T *stack = &cctx->ctx_type_stack;
|
||||
type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||
type_T *type = ((type_T **)stack->ga_data)[stack->ga_len
|
||||
- (with_op ? 2 : 1)];
|
||||
type_T *item_type = &t_any;
|
||||
|
||||
RETURN_OK_IF_SKIP(cctx);
|
||||
@@ -1260,7 +1263,8 @@ generate_GETITEM(cctx_T *cctx, int index)
|
||||
item_type = type->tt_member;
|
||||
if ((isn = generate_instr(cctx, ISN_GETITEM)) == NULL)
|
||||
return FAIL;
|
||||
isn->isn_arg.number = index;
|
||||
isn->isn_arg.getitem.gi_index = index;
|
||||
isn->isn_arg.getitem.gi_with_op = with_op;
|
||||
|
||||
// add the item type to the type stack
|
||||
if (ga_grow(stack, 1) == FAIL)
|
||||
@@ -5852,7 +5856,7 @@ get_var_dest(
|
||||
return FAIL;
|
||||
}
|
||||
*dest = dest_reg;
|
||||
*type = &t_string;
|
||||
*type = name[1] == '#' ? &t_number_or_string : &t_string;
|
||||
}
|
||||
else if (STRNCMP(name, "g:", 2) == 0)
|
||||
{
|
||||
@@ -5927,7 +5931,8 @@ generate_store_var(
|
||||
case dest_env:
|
||||
return generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
|
||||
case dest_reg:
|
||||
return generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
|
||||
return generate_STORE(cctx, ISN_STOREREG,
|
||||
name[1] == '@' ? '"' : name[1], NULL);
|
||||
case dest_vimvar:
|
||||
return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
|
||||
case dest_script:
|
||||
@@ -6745,19 +6750,17 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
int is_const = FALSE;
|
||||
char_u *wp;
|
||||
|
||||
// for "+=", "*=", "..=" etc. first load the current value
|
||||
if (*op != '='
|
||||
&& compile_load_lhs_with_index(&lhs, var_start,
|
||||
cctx) == FAIL)
|
||||
goto theend;
|
||||
|
||||
// For "var = expr" evaluate the expression.
|
||||
if (var_count == 0)
|
||||
{
|
||||
int r;
|
||||
|
||||
// for "+=", "*=", "..=" etc. first load the current value
|
||||
if (*op != '=')
|
||||
{
|
||||
if (compile_load_lhs_with_index(&lhs, var_start,
|
||||
cctx) == FAIL)
|
||||
goto theend;
|
||||
}
|
||||
|
||||
// Compile the expression.
|
||||
instr_count = instr->ga_len;
|
||||
if (incdec)
|
||||
@@ -6794,7 +6797,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
{
|
||||
// For "[var, var] = expr" get the "var_idx" item from the
|
||||
// list.
|
||||
if (generate_GETITEM(cctx, var_idx) == FAIL)
|
||||
if (generate_GETITEM(cctx, var_idx, *op != '=') == FAIL)
|
||||
goto theend;
|
||||
}
|
||||
|
||||
@@ -6843,9 +6846,19 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type,
|
||||
else
|
||||
{
|
||||
type_T *lhs_type = lhs.lhs_member_type;
|
||||
|
||||
// Special case: assigning to @# can use a number or a
|
||||
// string.
|
||||
if (lhs_type == &t_number_or_string
|
||||
&& rhs_type->tt_type == VAR_NUMBER)
|
||||
lhs_type = &t_number;
|
||||
if (*p != '=' && need_type(rhs_type, lhs_type,
|
||||
-1, 0, cctx, FALSE, FALSE) == FAIL)
|
||||
goto theend;
|
||||
}
|
||||
}
|
||||
else if (cmdidx == CMD_final)
|
||||
{
|
||||
@@ -7711,6 +7724,7 @@ compile_for(char_u *arg_start, cctx_T *cctx)
|
||||
int semicolon = FALSE;
|
||||
size_t varlen;
|
||||
garray_T *stack = &cctx->ctx_type_stack;
|
||||
garray_T *instr = &cctx->ctx_instr;
|
||||
scope_T *scope;
|
||||
lvar_T *loop_lvar; // loop iteration variable
|
||||
lvar_T *var_lvar; // variable for "var"
|
||||
@@ -7737,6 +7751,13 @@ compile_for(char_u *arg_start, cctx_T *cctx)
|
||||
if (may_get_next_line_error(wp, &p, cctx) == FAIL)
|
||||
return NULL;
|
||||
|
||||
// Remove the already generated ISN_DEBUG, it is written below the ISN_FOR
|
||||
// instruction.
|
||||
if (cctx->ctx_compile_type == CT_DEBUG && instr->ga_len > 0
|
||||
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||
.isn_type == ISN_DEBUG)
|
||||
--instr->ga_len;
|
||||
|
||||
scope = new_scope(cctx, FOR_SCOPE);
|
||||
if (scope == NULL)
|
||||
return NULL;
|
||||
@@ -7788,11 +7809,12 @@ compile_for(char_u *arg_start, cctx_T *cctx)
|
||||
item_type = vartype->tt_member->tt_member;
|
||||
}
|
||||
|
||||
// CMDMOD_REV must come before the FOR instruction
|
||||
// CMDMOD_REV must come before the FOR instruction.
|
||||
generate_undo_cmdmods(cctx);
|
||||
|
||||
// "for_end" is set when ":endfor" is found
|
||||
scope->se_u.se_for.fs_top_label = current_instr_idx(cctx);
|
||||
|
||||
generate_FOR(cctx, loop_lvar->lv_idx);
|
||||
|
||||
arg = arg_start;
|
||||
@@ -7893,6 +7915,10 @@ compile_for(char_u *arg_start, cctx_T *cctx)
|
||||
vim_free(name);
|
||||
}
|
||||
|
||||
if (cctx->ctx_compile_type == CT_DEBUG)
|
||||
// Add ISN_DEBUG here, so that the loop variables can be inspected.
|
||||
generate_instr_debug(cctx);
|
||||
|
||||
return arg_end;
|
||||
|
||||
failed:
|
||||
@@ -7927,7 +7953,7 @@ compile_endfor(char_u *arg, cctx_T *cctx)
|
||||
// At end of ":for" scope jump back to the FOR instruction.
|
||||
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
||||
|
||||
// Fill in the "end" label in the FOR statement so it can jump here
|
||||
// Fill in the "end" label in the FOR statement so it can jump here.
|
||||
isn = ((isn_T *)instr->ga_data) + forscope->fs_top_label;
|
||||
isn->isn_arg.forloop.for_end = instr->ga_len;
|
||||
|
||||
@@ -8234,6 +8260,7 @@ compile_catch(char_u *arg, cctx_T *cctx UNUSED)
|
||||
#ifdef FEAT_PROFILE
|
||||
// the profile-start should be after the jump
|
||||
if (cctx->ctx_compile_type == CT_PROFILE
|
||||
&& instr->ga_len > 0
|
||||
&& ((isn_T *)instr->ga_data)[instr->ga_len - 1]
|
||||
.isn_type == ISN_PROF_START)
|
||||
--instr->ga_len;
|
||||
|
||||
+114
-28
@@ -147,6 +147,23 @@ exe_newlist(int count, ectx_T *ectx)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* If debug_tick changed check if "ufunc" has a breakpoint and update
|
||||
* "uf_has_breakpoint".
|
||||
*/
|
||||
static void
|
||||
update_has_breakpoint(ufunc_T *ufunc)
|
||||
{
|
||||
if (ufunc->uf_debug_tick != debug_tick)
|
||||
{
|
||||
linenr_T breakpoint;
|
||||
|
||||
ufunc->uf_debug_tick = debug_tick;
|
||||
breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name, 0);
|
||||
ufunc->uf_has_breakpoint = breakpoint > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Call compiled function "cdf_idx" from compiled code.
|
||||
* This adds a stack frame and sets the instruction pointer to the start of the
|
||||
@@ -212,6 +229,9 @@ call_dfunc(
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update uf_has_breakpoint if needed.
|
||||
update_has_breakpoint(ufunc);
|
||||
|
||||
// When debugging and using "cont" switches to the not-debugged
|
||||
// instructions, may need to still compile them.
|
||||
if ((func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
|
||||
@@ -1394,7 +1414,7 @@ typedef struct subs_expr_S {
|
||||
|
||||
// Set when calling do_debug().
|
||||
static ectx_T *debug_context = NULL;
|
||||
static int debug_arg_count;
|
||||
static int debug_var_count;
|
||||
|
||||
/*
|
||||
* When debugging lookup "name" and return the typeval.
|
||||
@@ -1405,23 +1425,100 @@ lookup_debug_var(char_u *name)
|
||||
{
|
||||
int idx;
|
||||
dfunc_T *dfunc;
|
||||
ufunc_T *ufunc;
|
||||
ectx_T *ectx = debug_context;
|
||||
int varargs_off;
|
||||
|
||||
if (ectx == NULL)
|
||||
return NULL;
|
||||
dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
|
||||
|
||||
// Go through the local variable names, from last to first.
|
||||
for (idx = debug_arg_count - 1; idx >= 0; --idx)
|
||||
for (idx = debug_var_count - 1; idx >= 0; --idx)
|
||||
{
|
||||
char_u *s = ((char_u **)dfunc->df_var_names.ga_data)[idx];
|
||||
if (STRCMP(s, name) == 0)
|
||||
if (STRCMP(((char_u **)dfunc->df_var_names.ga_data)[idx], name) == 0)
|
||||
return STACK_TV_VAR(idx);
|
||||
}
|
||||
|
||||
// Go through argument names.
|
||||
ufunc = dfunc->df_ufunc;
|
||||
varargs_off = ufunc->uf_va_name == NULL ? 0 : 1;
|
||||
for (idx = 0; idx < ufunc->uf_args.ga_len; ++idx)
|
||||
if (STRCMP(((char_u **)(ufunc->uf_args.ga_data))[idx], name) == 0)
|
||||
return STACK_TV(ectx->ec_frame_idx - ufunc->uf_args.ga_len
|
||||
- varargs_off + idx);
|
||||
if (ufunc->uf_va_name != NULL && STRCMP(ufunc->uf_va_name, name) == 0)
|
||||
return STACK_TV(ectx->ec_frame_idx - 1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_debug(isn_T *iptr, ectx_T *ectx)
|
||||
{
|
||||
char_u *line;
|
||||
ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
|
||||
+ ectx->ec_dfunc_idx)->df_ufunc;
|
||||
isn_T *ni;
|
||||
int end_lnum = iptr->isn_lnum;
|
||||
garray_T ga;
|
||||
int lnum;
|
||||
|
||||
if (ex_nesting_level > debug_break_level)
|
||||
{
|
||||
linenr_T breakpoint;
|
||||
|
||||
if (!ufunc->uf_has_breakpoint)
|
||||
return;
|
||||
|
||||
// check for the next breakpoint if needed
|
||||
breakpoint = dbg_find_breakpoint(FALSE, ufunc->uf_name,
|
||||
iptr->isn_lnum - 1);
|
||||
if (breakpoint <= 0 || breakpoint > iptr->isn_lnum)
|
||||
return;
|
||||
}
|
||||
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
debug_context = ectx;
|
||||
debug_var_count = iptr->isn_arg.number;
|
||||
|
||||
for (ni = iptr + 1; ni->isn_type != ISN_FINISH; ++ni)
|
||||
if (ni->isn_type == ISN_DEBUG
|
||||
|| ni->isn_type == ISN_RETURN
|
||||
|| ni->isn_type == ISN_RETURN_VOID)
|
||||
{
|
||||
end_lnum = ni->isn_lnum;
|
||||
break;
|
||||
}
|
||||
|
||||
if (end_lnum > iptr->isn_lnum)
|
||||
{
|
||||
ga_init2(&ga, sizeof(char_u *), 10);
|
||||
for (lnum = iptr->isn_lnum; lnum < end_lnum; ++lnum)
|
||||
{
|
||||
char_u *p = skipwhite(
|
||||
((char_u **)ufunc->uf_lines.ga_data)[lnum - 1]);
|
||||
|
||||
if (*p == '#')
|
||||
break;
|
||||
if (ga_grow(&ga, 1) == OK)
|
||||
((char_u **)(ga.ga_data))[ga.ga_len++] = p;
|
||||
if (STRNCMP(p, "def ", 4) == 0)
|
||||
break;
|
||||
}
|
||||
line = ga_concat_strings(&ga, " ");
|
||||
vim_free(ga.ga_data);
|
||||
}
|
||||
else
|
||||
line = ((char_u **)ufunc->uf_lines.ga_data)[iptr->isn_lnum - 1];
|
||||
|
||||
do_debug(line == NULL ? (char_u *)"[empty]" : line);
|
||||
debug_context = NULL;
|
||||
|
||||
if (end_lnum > iptr->isn_lnum)
|
||||
vim_free(line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute instructions in execution context "ectx".
|
||||
* Return OK or FAIL;
|
||||
@@ -2127,8 +2224,7 @@ exec_instructions(ectx_T *ectx)
|
||||
|
||||
--ectx->ec_stack.ga_len;
|
||||
tv = STACK_TV_BOT(0);
|
||||
write_reg_contents(reg == '@' ? '"' : reg,
|
||||
tv_get_string(tv), -1, FALSE);
|
||||
write_reg_contents(reg, tv_get_string(tv), -1, FALSE);
|
||||
clear_tv(tv);
|
||||
}
|
||||
break;
|
||||
@@ -3736,12 +3832,12 @@ exec_instructions(ectx_T *ectx)
|
||||
case ISN_GETITEM:
|
||||
{
|
||||
listitem_T *li;
|
||||
int index = iptr->isn_arg.number;
|
||||
getitem_T *gi = &iptr->isn_arg.getitem;
|
||||
|
||||
// Get list item: list is at stack-1, push item.
|
||||
// List type and length is checked for when compiling.
|
||||
tv = STACK_TV_BOT(-1);
|
||||
li = list_find(tv->vval.v_list, index);
|
||||
tv = STACK_TV_BOT(-1 - gi->gi_with_op);
|
||||
li = list_find(tv->vval.v_list, gi->gi_index);
|
||||
|
||||
if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
|
||||
goto theend;
|
||||
@@ -3750,7 +3846,7 @@ exec_instructions(ectx_T *ectx)
|
||||
|
||||
// Useful when used in unpack assignment. Reset at
|
||||
// ISN_DROP.
|
||||
ectx->ec_where.wt_index = index + 1;
|
||||
ectx->ec_where.wt_index = gi->gi_index + 1;
|
||||
ectx->ec_where.wt_variable = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -4144,22 +4240,7 @@ exec_instructions(ectx_T *ectx)
|
||||
break;
|
||||
|
||||
case ISN_DEBUG:
|
||||
if (ex_nesting_level <= debug_break_level)
|
||||
{
|
||||
char_u *line;
|
||||
ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data)
|
||||
+ ectx->ec_dfunc_idx)->df_ufunc;
|
||||
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
debug_context = ectx;
|
||||
debug_arg_count = iptr->isn_arg.number;
|
||||
line = ((char_u **)ufunc->uf_lines.ga_data)[
|
||||
iptr->isn_lnum - 1];
|
||||
if (line == NULL)
|
||||
line = (char_u *)"[empty]";
|
||||
do_debug(line);
|
||||
debug_context = NULL;
|
||||
}
|
||||
handle_debug(iptr, ectx);
|
||||
break;
|
||||
|
||||
case ISN_SHUFFLE:
|
||||
@@ -4335,6 +4416,9 @@ call_def_function(
|
||||
#undef STACK_TV_VAR
|
||||
#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
|
||||
|
||||
// Update uf_has_breakpoint if needed.
|
||||
update_has_breakpoint(ufunc);
|
||||
|
||||
if (ufunc->uf_def_status == UF_NOT_COMPILED
|
||||
|| ufunc->uf_def_status == UF_COMPILE_ERROR
|
||||
|| (func_needs_compiling(ufunc, COMPILE_TYPE(ufunc))
|
||||
@@ -5292,8 +5376,10 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
||||
case ISN_ANYSLICE: smsg("%s%4d ANYSLICE", pfx, current); break;
|
||||
case ISN_SLICE: smsg("%s%4d SLICE %lld",
|
||||
pfx, current, iptr->isn_arg.number); break;
|
||||
case ISN_GETITEM: smsg("%s%4d ITEM %lld",
|
||||
pfx, current, iptr->isn_arg.number); break;
|
||||
case ISN_GETITEM: smsg("%s%4d ITEM %lld%s", pfx, current,
|
||||
iptr->isn_arg.getitem.gi_index,
|
||||
iptr->isn_arg.getitem.gi_with_op ?
|
||||
" with op" : ""); break;
|
||||
case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break;
|
||||
case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current,
|
||||
iptr->isn_arg.string); break;
|
||||
|
||||
+2
-2
@@ -171,7 +171,7 @@ alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
|
||||
if (type == NULL)
|
||||
return &t_any;
|
||||
type->tt_type = VAR_FUNC;
|
||||
type->tt_member = ret_type;
|
||||
type->tt_member = ret_type == NULL ? &t_unknown : ret_type;
|
||||
type->tt_argcount = argcount;
|
||||
type->tt_args = NULL;
|
||||
return type;
|
||||
@@ -188,7 +188,7 @@ get_func_type(type_T *ret_type, int argcount, garray_T *type_gap)
|
||||
// recognize commonly used types
|
||||
if (argcount <= 0)
|
||||
{
|
||||
if (ret_type == &t_unknown)
|
||||
if (ret_type == &t_unknown || ret_type == NULL)
|
||||
{
|
||||
// (argcount == 0) is not possible
|
||||
return &t_func_unknown;
|
||||
|
||||
Reference in New Issue
Block a user