Compare commits

...

14 Commits

Author SHA1 Message Date
Bram Moolenaar
a83fe75ca7 patch 8.0.0691: compiler warning without the linebreak feature
Problem:    Compiler warning without the linebreak feature.
Solution:   Add #ifdef. (John Marriott)
2017-06-29 22:33:13 +02:00
Bram Moolenaar
c2226845eb patch 8.0.0690: compiler warning on non-Unix system
Problem:    Compiler warning on non-Unix system.
Solution:   Add #ifdef. (John Marriott)
2017-06-29 22:27:24 +02:00
Bram Moolenaar
a693d0584b patch 8.0.0689: ~ character not escaped when extending search pattern
Problem:    The ~ character is not escaped when adding to the search pattern
            with CTRL-L. (Ramel Eshed)
Solution:   Escape the character. (Christian Brabandt)
2017-06-29 22:23:06 +02:00
Bram Moolenaar
9c4fefffb6 patch 8.0.0688: cannot resize the window in a FileType autocommand
Problem:    Cannot resize the window in a FileType autocommand. (Ingo Karkat)
Solution:   Add the CMDWIN flag to :resize. (test by Ingo Karkat,
            closes #1804)
2017-06-28 22:26:54 +02:00
Bram Moolenaar
86f100dc09 patch 8.0.0687: minor issues related to quickfix
Problem:    Minor issues related to quickfix.
Solution:   Set the proper return status for all cases in setqflist() and at
            test cases for this.  Move the "adding" flag outside of
            FEAT_WINDOWS. Minor update to the setqflist() help text. (Yegappan
            Lakshmanan)
2017-06-28 21:26:27 +02:00
Bram Moolenaar
9f5f7bf4d5 patch 8.0.0686: extra redraw when using CTRL-L in second window
Problem:    When typing CTRL-L in a window that's not the first one, another
            redraw will happen later. (Christian Brabandt)
Solution:   Reset must_redraw after calling screenclear().
2017-06-28 20:45:26 +02:00
Bram Moolenaar
e6bf655bc4 patch 8.0.0685: when conversion fails written file may be truncated
Problem:    When making backups is disabled and conversion with iconv fails
            the written file is truncated. (Luo Chen)
Solution:   First try converting the file and write the file only when it did
            not fail. (partly by Christian Brabandt)
2017-06-27 22:11:51 +02:00
Bram Moolenaar
28b238225a patch 8.0.0684: old style tests are not nice
Problem:    Old style tests are not nice.
Solution:   Turn two tests into new style. (pschuh, closes #1797)
2017-06-27 18:29:17 +02:00
Bram Moolenaar
2e147caa14 patch 8.0.0683: visual bell flashes too quickly
Problem:    When using a visual bell there is no delay, causing the flash to
            be very short, possibly unnoticeable.  Also, the flash and the
            beep can lockup the UI when repeated often.
Solution:   Do the delay in Vim or flush the output before the delay. Limit the
            bell to once per half a second. (Ozaki Kiichi, closes #1789)
2017-06-27 17:09:37 +02:00
Bram Moolenaar
0b2eef24bc patch 8.0.0682: no test for synIDtrans()
Problem:    No test for synIDtrans().
Solution:   Add a test. (Dominique Pelle, closes #1796)
2017-06-27 15:43:49 +02:00
Bram Moolenaar
18d90b95c4 patch 8.0.0681: unnamed register only contains the last deleted text
Problem:    Unnamed register only contains the last deleted text when
            appending deleted text to a register. (Wolfgang Jeltsch)
Solution:   Only set y_previous when not using y_append. (Christian Brabandt)
2017-06-27 15:39:14 +02:00
Bram Moolenaar
07ecfa64a1 patch 8.0.0680: plugins in start packages are sourced twice
Problem:    Plugins in start packages are sourced twice. (mseplowitz)
Solution:   Use the unmodified runtime path when loading plugins (test by Ingo
            Karkat, closes #1801)
2017-06-27 14:43:55 +02:00
Bram Moolenaar
41cc038ff8 patch 8.0.0679: using freed memory
Problem:    Using freed memory.
Solution:   Get the parent frame pointer earlier.
2017-06-26 09:59:35 +02:00
Bram Moolenaar
8eeeba8c02 patch 8.0.0678: closing a window does not trigger resizing
Problem:    When 'equalalways' is set and closing a window in a separate
            frame, not all window sizes are adjusted. (Glacambre)
Solution:   Resize all windows if the new current window is not in the same
            frame as the closed window. (closes #1707)
2017-06-25 22:45:39 +02:00
32 changed files with 919 additions and 592 deletions

View File

@@ -7008,7 +7008,8 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
title quickfix list title text title quickfix list title text
Unsupported keys in {what} are ignored. Unsupported keys in {what} are ignored.
If the "nr" item is not present, then the current quickfix list If the "nr" item is not present, then the current quickfix list
is modified. is modified. When creating a new quickfix list, "nr" can be
set to a value one greater than the quickfix stack size.
Examples: > Examples: >
:call setqflist([], 'r', {'title': 'My search'}) :call setqflist([], 'r', {'title': 'My search'})

View File

@@ -2089,8 +2089,8 @@ test1 \
test50 test51 test52 test53 test54 test55 test56 test57 test59 \ test50 test51 test52 test53 test54 test55 test56 test57 test59 \
test60 test64 test66 test67 test68 test69 \ test60 test64 test66 test67 test68 test69 \
test70 test72 test73 test74 test75 test77 test78 test79 \ test70 test72 test73 test74 test75 test77 test78 test79 \
test80 test82 test83 test84 test85 test86 test87 test88 \ test80 test83 test84 test85 test86 test87 test88 \
test90 test91 test94 test95 test97 test98 test99 \ test91 test94 test95 test97 test98 test99 \
test100 test101 test103 test104 test107 test108: test100 test101 test103 test104 test107 test108:
cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE)
@@ -2207,6 +2207,7 @@ test_arglist \
test_search \ test_search \
test_searchpos \ test_searchpos \
test_set \ test_set \
test_sha256 \
test_signs \ test_signs \
test_smartindent \ test_smartindent \
test_sort \ test_sort \
@@ -2233,6 +2234,7 @@ test_arglist \
test_unlet \ test_unlet \
test_usercommands \ test_usercommands \
test_utf8 \ test_utf8 \
test_utf8_comparisons \
test_viminfo \ test_viminfo \
test_vimscript \ test_vimscript \
test_visual \ test_visual \

View File

@@ -7329,7 +7329,9 @@ oneleft(void)
#ifdef FEAT_VIRTUALEDIT #ifdef FEAT_VIRTUALEDIT
if (virtual_active()) if (virtual_active())
{ {
# ifdef FEAT_LINEBREAK
int width; int width;
# endif
int v = getviscol(); int v = getviscol();
if (v == 0) if (v == 0)

View File

@@ -51,7 +51,9 @@
#define BUFUNL 0x20000L /* accepts unlisted buffer too */ #define BUFUNL 0x20000L /* accepts unlisted buffer too */
#define ARGOPT 0x40000L /* allow "++opt=val" argument */ #define ARGOPT 0x40000L /* allow "++opt=val" argument */
#define SBOXOK 0x80000L /* allowed in the sandbox */ #define SBOXOK 0x80000L /* allowed in the sandbox */
#define CMDWIN 0x100000L /* allowed in cmdline window */ #define CMDWIN 0x100000L /* allowed in cmdline window; when missing
* disallows editing another buffer when
* curbuf_lock is set */
#define MODIFY 0x200000L /* forbidden in non-'modifiable' buffer */ #define MODIFY 0x200000L /* forbidden in non-'modifiable' buffer */
#define EXFLAGS 0x400000L /* allow flags after count in argument */ #define EXFLAGS 0x400000L /* allow flags after count in argument */
#define FILES (XFILE | EXTRA) /* multiple extra files allowed */ #define FILES (XFILE | EXTRA) /* multiple extra files allowed */
@@ -1176,7 +1178,7 @@ EX(CMD_registers, "registers", ex_display,
EXTRA|NOTRLCOM|TRLBAR|CMDWIN, EXTRA|NOTRLCOM|TRLBAR|CMDWIN,
ADDR_LINES), ADDR_LINES),
EX(CMD_resize, "resize", ex_resize, EX(CMD_resize, "resize", ex_resize,
RANGE|NOTADR|TRLBAR|WORD1, RANGE|NOTADR|TRLBAR|WORD1|CMDWIN,
ADDR_LINES), ADDR_LINES),
EX(CMD_retab, "retab", ex_retab, EX(CMD_retab, "retab", ex_retab,
TRLBAR|RANGE|WHOLEFOLD|DFLALL|BANG|WORD1|CMDWIN|MODIFY, TRLBAR|RANGE|WHOLEFOLD|DFLALL|BANG|WORD1|CMDWIN|MODIFY,

View File

@@ -3285,19 +3285,6 @@ source_callback(char_u *fname, void *cookie UNUSED)
(void)do_source(fname, FALSE, DOSO_NONE); (void)do_source(fname, FALSE, DOSO_NONE);
} }
/*
* Source the file "name" from all directories in 'runtimepath'.
* "name" can contain wildcards.
* When "flags" has DIP_ALL: source all files, otherwise only the first one.
*
* return FAIL when no file could be sourced, OK otherwise.
*/
int
source_runtime(char_u *name, int flags)
{
return do_in_runtimepath(name, flags, source_callback, NULL);
}
/* /*
* Find the file "name" in all directories in "path" and invoke * Find the file "name" in all directories in "path" and invoke
* "callback(fname, cookie)". * "callback(fname, cookie)".
@@ -3435,18 +3422,19 @@ do_in_path(
} }
/* /*
* Find "name" in 'runtimepath'. When found, invoke the callback function for * Find "name" in "path". When found, invoke the callback function for
* it: callback(fname, "cookie") * it: callback(fname, "cookie")
* When "flags" has DIP_ALL repeat for all matches, otherwise only the first * When "flags" has DIP_ALL repeat for all matches, otherwise only the first
* one is used. * one is used.
* Returns OK when at least one match found, FAIL otherwise. * Returns OK when at least one match found, FAIL otherwise.
* *
* If "name" is NULL calls callback for each entry in runtimepath. Cookie is * If "name" is NULL calls callback for each entry in "path". Cookie is
* passed by reference in this case, setting it to NULL indicates that callback * passed by reference in this case, setting it to NULL indicates that callback
* has done its job. * has done its job.
*/ */
int static int
do_in_runtimepath( do_in_path_and_pp(
char_u *path,
char_u *name, char_u *name,
int flags, int flags,
void (*callback)(char_u *fname, void *ck), void (*callback)(char_u *fname, void *ck),
@@ -3459,7 +3447,7 @@ do_in_runtimepath(
char *opt_dir = "pack/*/opt/*/%s"; char *opt_dir = "pack/*/opt/*/%s";
if ((flags & DIP_NORTP) == 0) if ((flags & DIP_NORTP) == 0)
done = do_in_path(p_rtp, name, flags, callback, cookie); done = do_in_path(path, name, flags, callback, cookie);
if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START))
{ {
@@ -3486,6 +3474,42 @@ do_in_runtimepath(
return done; return done;
} }
/*
* Just like do_in_path_and_pp(), using 'runtimepath' for "path".
*/
int
do_in_runtimepath(
char_u *name,
int flags,
void (*callback)(char_u *fname, void *ck),
void *cookie)
{
return do_in_path_and_pp(p_rtp, name, flags, callback, cookie);
}
/*
* Source the file "name" from all directories in 'runtimepath'.
* "name" can contain wildcards.
* When "flags" has DIP_ALL: source all files, otherwise only the first one.
*
* return FAIL when no file could be sourced, OK otherwise.
*/
int
source_runtime(char_u *name, int flags)
{
return source_in_path(p_rtp, name, flags);
}
/*
* Just like source_runtime(), but use "path" instead of 'runtimepath'.
*/
int
source_in_path(char_u *path, char_u *name, int flags)
{
return do_in_path_and_pp(path, name, flags, source_callback, NULL);
}
/* /*
* Expand wildcards in "pat" and invoke do_source() for each match. * Expand wildcards in "pat" and invoke do_source() for each match.
*/ */

View File

@@ -1492,7 +1492,7 @@ getcmdline(
if (c != NUL) if (c != NUL)
{ {
if (c == firstc || vim_strchr((char_u *)( if (c == firstc || vim_strchr((char_u *)(
p_magic ? "\\^$.*[" : "\\^$"), c) p_magic ? "\\~^$.*[" : "\\^$"), c)
!= NULL) != NULL)
{ {
/* put a backslash before special /* put a backslash before special

View File

@@ -3166,6 +3166,7 @@ buf_write(
int device = FALSE; /* writing to a device */ int device = FALSE; /* writing to a device */
stat_T st_old; stat_T st_old;
int prev_got_int = got_int; int prev_got_int = got_int;
int checking_conversion;
int file_readonly = FALSE; /* overwritten file is read-only */ int file_readonly = FALSE; /* overwritten file is read-only */
static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')"; static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
#if defined(UNIX) /*XXX fix me sometime? */ #if defined(UNIX) /*XXX fix me sometime? */
@@ -4343,13 +4344,41 @@ buf_write(
} }
#endif #endif
/*
* If conversion is taking place, we may first pretend to write and check
* for conversion errors. Then loop again to write for real.
* When not doing conversion this writes for real right away.
*/
for (checking_conversion = TRUE; ; checking_conversion = FALSE)
{
/*
* There is no need to check conversion when:
* - there is no conversion
* - we make a backup file, that can be restored in case of conversion
* failure.
*/
#ifdef FEAT_MBYTE
if (!converted || dobackup)
#endif
checking_conversion = FALSE;
if (checking_conversion)
{
/* Make sure we don't write anything. */
fd = -1;
write_info.bw_fd = fd;
}
else
{
/* /*
* Open the file "wfname" for writing. * Open the file "wfname" for writing.
* We may try to open the file twice: If we can't write to the * We may try to open the file twice: If we can't write to the file
* file and forceit is TRUE we delete the existing file and try to create * and forceit is TRUE we delete the existing file and try to
* a new one. If this still fails we may have lost the original file! * create a new one. If this still fails we may have lost the
* (this may happen when the user reached his quotum for number of files). * original file! (this may happen when the user reached his
* Appending will fail if the file does not exist and forceit is FALSE. * quotum for number of files).
* Appending will fail if the file does not exist and forceit is
* FALSE.
*/ */
while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
? (forceit ? (O_APPEND | O_CREAT) : O_APPEND) ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
@@ -4357,16 +4386,17 @@ buf_write(
, perm < 0 ? 0666 : (perm & 0777))) < 0) , perm < 0 ? 0666 : (perm & 0777))) < 0)
{ {
/* /*
* A forced write will try to create a new file if the old one is * A forced write will try to create a new file if the old one
* still readonly. This may also happen when the directory is * is still readonly. This may also happen when the directory
* read-only. In that case the mch_remove() will fail. * is read-only. In that case the mch_remove() will fail.
*/ */
if (errmsg == NULL) if (errmsg == NULL)
{ {
#ifdef UNIX #ifdef UNIX
stat_T st; stat_T st;
/* Don't delete the file when it's a hard or symbolic link. */ /* Don't delete the file when it's a hard or symbolic link.
*/
if ((!newfile && st_old.st_nlink > 1) if ((!newfile && st_old.st_nlink > 1)
|| (mch_lstat((char *)fname, &st) == 0 || (mch_lstat((char *)fname, &st) == 0
&& (st.st_dev != st_old.st_dev && (st.st_dev != st_old.st_dev
@@ -4385,7 +4415,8 @@ buf_write(
if (!(perm & 0200)) if (!(perm & 0200))
made_writable = TRUE; made_writable = TRUE;
perm |= 0200; perm |= 0200;
if (st_old.st_uid != getuid() || st_old.st_gid != getgid()) if (st_old.st_uid != getuid()
|| st_old.st_gid != getgid())
perm &= 0777; perm &= 0777;
#endif #endif
if (!append) /* don't remove when appending */ if (!append) /* don't remove when appending */
@@ -4400,24 +4431,26 @@ restore_backup:
stat_T st; stat_T st;
/* /*
* If we failed to open the file, we don't need a backup. Throw it * If we failed to open the file, we don't need a backup.
* away. If we moved or removed the original file try to put the * Throw it away. If we moved or removed the original file
* backup in its place. * try to put the backup in its place.
*/ */
if (backup != NULL && wfname == fname) if (backup != NULL && wfname == fname)
{ {
if (backup_copy) if (backup_copy)
{ {
/* /*
* There is a small chance that we removed the original, * There is a small chance that we removed the
* try to move the copy in its place. * original, try to move the copy in its place.
* This may not work if the vim_rename() fails. * This may not work if the vim_rename() fails.
* In that case we leave the copy around. * In that case we leave the copy around.
*/ */
/* If file does not exist, put the copy in its place */ /* If file does not exist, put the copy in its
* place */
if (mch_stat((char *)fname, &st) < 0) if (mch_stat((char *)fname, &st) < 0)
vim_rename(backup, fname); vim_rename(backup, fname);
/* if original file does exist throw away the copy */ /* if original file does exist throw away the copy
*/
if (mch_stat((char *)fname, &st) >= 0) if (mch_stat((char *)fname, &st) >= 0)
mch_remove(backup); mch_remove(backup);
} }
@@ -4428,7 +4461,8 @@ restore_backup:
} }
} }
/* if original file no longer exists give an extra warning */ /* if original file no longer exists give an extra warning
*/
if (!newfile && mch_stat((char *)fname, &st) < 0) if (!newfile && mch_stat((char *)fname, &st) < 0)
end = 0; end = 0;
} }
@@ -4439,7 +4473,7 @@ restore_backup:
#endif #endif
goto fail; goto fail;
} }
errmsg = NULL; write_info.bw_fd = fd;
#if defined(MACOS_CLASSIC) || defined(WIN3264) #if defined(MACOS_CLASSIC) || defined(WIN3264)
/* TODO: Is it need for MACOS_X? (Dany) */ /* TODO: Is it need for MACOS_X? (Dany) */
@@ -4464,15 +4498,14 @@ restore_backup:
} }
#endif #endif
write_info.bw_fd = fd;
#ifdef FEAT_CRYPT #ifdef FEAT_CRYPT
if (*buf->b_p_key != NUL && !filtering) if (*buf->b_p_key != NUL && !filtering)
{ {
char_u *header; char_u *header;
int header_len; int header_len;
buf->b_cryptstate = crypt_create_for_writing(crypt_get_method_nr(buf), buf->b_cryptstate = crypt_create_for_writing(
crypt_get_method_nr(buf),
buf->b_p_key, &header, &header_len); buf->b_p_key, &header, &header_len);
if (buf->b_cryptstate == NULL || header == NULL) if (buf->b_cryptstate == NULL || header == NULL)
end = 0; end = 0;
@@ -4490,6 +4523,8 @@ restore_backup:
} }
} }
#endif #endif
}
errmsg = NULL;
write_info.bw_buf = buffer; write_info.bw_buf = buffer;
nchars = 0; nchars = 0;
@@ -4503,8 +4538,8 @@ restore_backup:
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
/* /*
* The BOM is written just after the encryption magic number. * The BOM is written just after the encryption magic number.
* Skip it when appending and the file already existed, the BOM only makes * Skip it when appending and the file already existed, the BOM only
* sense at the start of the file. * makes sense at the start of the file.
*/ */
if (buf->b_p_bomb && !write_bin && (!append || perm < 0)) if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
{ {
@@ -4523,8 +4558,12 @@ restore_backup:
#endif #endif
#ifdef FEAT_PERSISTENT_UNDO #ifdef FEAT_PERSISTENT_UNDO
write_undo_file = (buf->b_p_udf && overwriting && !append write_undo_file = (buf->b_p_udf
&& !filtering && reset_changed); && overwriting
&& !append
&& !filtering
&& reset_changed
&& !checking_conversion);
if (write_undo_file) if (write_undo_file)
/* Prepare for computing the hash value of the text. */ /* Prepare for computing the hash value of the text. */
sha256_start(&sha_ctx); sha256_start(&sha_ctx);
@@ -4546,7 +4585,8 @@ restore_backup:
ptr = ml_get_buf(buf, lnum, FALSE) - 1; ptr = ml_get_buf(buf, lnum, FALSE) - 1;
#ifdef FEAT_PERSISTENT_UNDO #ifdef FEAT_PERSISTENT_UNDO
if (write_undo_file) if (write_undo_file)
sha256_update(&sha_ctx, ptr + 1, (UINT32_T)(STRLEN(ptr + 1) + 1)); sha256_update(&sha_ctx, ptr + 1,
(UINT32_T)(STRLEN(ptr + 1) + 1));
#endif #endif
while ((c = *++ptr) != NUL) while ((c = *++ptr) != NUL)
{ {
@@ -4576,7 +4616,8 @@ restore_backup:
|| (lnum == end || (lnum == end
&& (write_bin || !buf->b_p_fixeol) && (write_bin || !buf->b_p_fixeol)
&& (lnum == buf->b_no_eol_lnum && (lnum == buf->b_no_eol_lnum
|| (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol)))) || (lnum == buf->b_ml.ml_line_count
&& !buf->b_p_eol))))
{ {
++lnum; /* written the line, count it */ ++lnum; /* written the line, count it */
no_eol = TRUE; no_eol = TRUE;
@@ -4623,12 +4664,12 @@ restore_backup:
} }
#ifdef VMS #ifdef VMS
/* /*
* On VMS there is a problem: newlines get added when writing blocks * On VMS there is a problem: newlines get added when writing
* at a time. Fix it by writing a line at a time. * blocks at a time. Fix it by writing a line at a time.
* This is much slower! * This is much slower!
* Explanation: VAX/DECC RTL insists that records in some RMS * Explanation: VAX/DECC RTL insists that records in some RMS
* structures end with a newline (carriage return) character, and if * structures end with a newline (carriage return) character, and
* they don't it adds one. * if they don't it adds one.
* With other RMS structures it works perfect without this fix. * With other RMS structures it works perfect without this fix.
*/ */
if (buf->b_fab_rfm == FAB$C_VFC if (buf->b_fab_rfm == FAB$C_VFC
@@ -4666,15 +4707,29 @@ restore_backup:
nchars += len; nchars += len;
} }
/* Stop when writing done or an error was encountered. */
if (!checking_conversion || end == 0)
break;
/* If no error happened until now, writing should be ok, so loop to
* really write the buffer. */
}
/* If we started writing, finish writing. Also when an error was
* encountered. */
if (!checking_conversion)
{
#if defined(UNIX) && defined(HAVE_FSYNC) #if defined(UNIX) && defined(HAVE_FSYNC)
/* On many journalling file systems there is a bug that causes both the /*
* original and the backup file to be lost when halting the system right * On many journalling file systems there is a bug that causes both the
* after writing the file. That's because only the meta-data is * original and the backup file to be lost when halting the system
* journalled. Syncing the file slows down the system, but assures it has * right after writing the file. That's because only the meta-data is
* been written to disk and we don't lose it. * journalled. Syncing the file slows down the system, but assures it
* For a device do try the fsync() but don't complain if it does not work * has been written to disk and we don't lose it.
* (could be a pipe). * For a device do try the fsync() but don't complain if it does not
* If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */ * work (could be a pipe).
* If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
*/
if (p_fs && fsync(fd) != 0 && !device) if (p_fs && fsync(fd) != 0 && !device)
{ {
errmsg = (char_u *)_("E667: Fsync failed"); errmsg = (char_u *)_("E667: Fsync failed");
@@ -4689,8 +4744,8 @@ restore_backup:
#endif #endif
#ifdef UNIX #ifdef UNIX
/* When creating a new file, set its owner/group to that of the original /* When creating a new file, set its owner/group to that of the
* file. Get the new device and inode number. */ * original file. Get the new device and inode number. */
if (backup != NULL && !backup_copy) if (backup != NULL && !backup_copy)
{ {
# ifdef HAVE_FCHOWN # ifdef HAVE_FCHOWN
@@ -4731,9 +4786,9 @@ restore_backup:
* Probably need to set the ACL before changing the user (can't set the * Probably need to set the ACL before changing the user (can't set the
* ACL on a file the user doesn't own). * ACL on a file the user doesn't own).
* On Solaris, with ZFS and the aclmode property set to "discard" (the * On Solaris, with ZFS and the aclmode property set to "discard" (the
* default), chmod() discards all part of a file's ACL that don't represent * default), chmod() discards all part of a file's ACL that don't
* the mode of the file. It's non-trivial for us to discover whether we're * represent the mode of the file. It's non-trivial for us to discover
* in that situation, so we simply always re-set the ACL. * whether we're in that situation, so we simply always re-set the ACL.
*/ */
# ifndef HAVE_SOLARIS_ZFS_ACL # ifndef HAVE_SOLARIS_ZFS_ACL
if (!backup_copy) if (!backup_copy)
@@ -4752,13 +4807,13 @@ restore_backup:
if (wfname != fname) if (wfname != fname)
{ {
/* /*
* The file was written to a temp file, now it needs to be converted * The file was written to a temp file, now it needs to be
* with 'charconvert' to (overwrite) the output file. * converted with 'charconvert' to (overwrite) the output file.
*/ */
if (end != 0) if (end != 0)
{ {
if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc, if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc,
wfname, fname) == FAIL) fenc, wfname, fname) == FAIL)
{ {
write_info.bw_conv_error = TRUE; write_info.bw_conv_error = TRUE;
end = 0; end = 0;
@@ -4768,9 +4823,13 @@ restore_backup:
vim_free(wfname); vim_free(wfname);
} }
#endif #endif
}
if (end == 0) if (end == 0)
{ {
/*
* Error encountered.
*/
if (errmsg == NULL) if (errmsg == NULL)
{ {
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
@@ -5690,6 +5749,10 @@ buf_write_bytes(struct bw_info *ip)
} }
#endif /* FEAT_MBYTE */ #endif /* FEAT_MBYTE */
if (ip->bw_fd < 0)
/* Only checking conversion, which is OK if we get here. */
return OK;
#ifdef FEAT_CRYPT #ifdef FEAT_CRYPT
if (flags & FIO_ENCRYPTED) if (flags & FIO_ENCRYPTED)
{ {

View File

@@ -449,18 +449,28 @@ vim_main2(void)
*/ */
if (p_lpl) if (p_lpl)
{ {
char_u *rtp_copy = NULL;
/* First add all package directories to 'runtimepath', so that their /* First add all package directories to 'runtimepath', so that their
* autoload directories can be found. Only if not done already with a * autoload directories can be found. Only if not done already with a
* :packloadall command. */ * :packloadall command.
* Make a copy of 'runtimepath', so that source_runtime does not use
* the pack directories. */
if (!did_source_packages) if (!did_source_packages)
{
rtp_copy = vim_strsave(p_rtp);
add_pack_start_dirs(); add_pack_start_dirs();
}
source_in_path(rtp_copy == NULL ? p_rtp : rtp_copy,
# ifdef VMS /* Somehow VMS doesn't handle the "**". */ # ifdef VMS /* Somehow VMS doesn't handle the "**". */
source_runtime((char_u *)"plugin/*.vim", DIP_ALL | DIP_NOAFTER); (char_u *)"plugin/*.vim",
# else # else
source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_NOAFTER); (char_u *)"plugin/**/*.vim",
# endif # endif
DIP_ALL | DIP_NOAFTER);
TIME_MSG("loading plugins"); TIME_MSG("loading plugins");
vim_free(rtp_copy);
/* Only source "start" packages if not done already with a :packloadall /* Only source "start" packages if not done already with a :packloadall
* command. */ * command. */

View File

@@ -3685,16 +3685,30 @@ vim_beep(
{ {
if (!((bo_flags & val) || (bo_flags & BO_ALL))) if (!((bo_flags & val) || (bo_flags & BO_ALL)))
{ {
#ifdef ELAPSED_FUNC
static int did_init = FALSE;
static ELAPSED_TYPE start_tv;
/* Only beep once per half a second, otherwise a sequence of beeps
* would freeze Vim. */
if (!did_init || ELAPSED_FUNC(start_tv) > 500)
{
did_init = TRUE;
ELAPSED_INIT(start_tv);
#endif
if (p_vb if (p_vb
#ifdef FEAT_GUI #ifdef FEAT_GUI
/* While the GUI is starting up the termcap is set for the /* While the GUI is starting up the termcap is set for
* GUI but the output still goes to a terminal. */ * the GUI but the output still goes to a terminal. */
&& !(gui.in_use && gui.starting) && !(gui.in_use && gui.starting)
#endif #endif
) )
out_str(T_VB); out_str_cf(T_VB);
else else
out_char(BELL); out_char(BELL);
#ifdef ELAPSED_FUNC
}
#endif
} }
/* When 'verbose' is set and we are sourcing a script or executing a /* When 'verbose' is set and we are sourcing a script or executing a

View File

@@ -1636,7 +1636,9 @@ shift_delete_registers()
free_yank_all(); /* free register nine */ free_yank_all(); /* free register nine */
for (n = 9; n > 1; --n) for (n = 9; n > 1; --n)
y_regs[n] = y_regs[n - 1]; y_regs[n] = y_regs[n - 1];
y_previous = y_current = &y_regs[1]; y_current = &y_regs[1];
if (!y_append)
y_previous = y_current;
y_regs[1].y_array = NULL; /* set register one to empty */ y_regs[1].y_array = NULL; /* set register one to empty */
} }

View File

@@ -69,9 +69,10 @@ void ex_argdelete(exarg_T *eap);
void ex_listdo(exarg_T *eap); void ex_listdo(exarg_T *eap);
void ex_compiler(exarg_T *eap); void ex_compiler(exarg_T *eap);
void ex_runtime(exarg_T *eap); void ex_runtime(exarg_T *eap);
int source_runtime(char_u *name, int flags);
int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
int source_runtime(char_u *name, int flags);
int source_in_path(char_u *path, char_u *name, int flags);
void add_pack_start_dirs(void); void add_pack_start_dirs(void);
void load_start_packages(void); void load_start_packages(void);
void ex_packloadall(exarg_T *eap); void ex_packloadall(exarg_T *eap);

View File

@@ -16,6 +16,7 @@ void out_flush_check(void);
void out_trash(void); void out_trash(void);
void out_char(unsigned c); void out_char(unsigned c);
void out_str_nf(char_u *s); void out_str_nf(char_u *s);
void out_str_cf(char_u *s);
void out_str(char_u *s); void out_str(char_u *s);
void term_windgoto(int row, int col); void term_windgoto(int row, int col);
void term_cursor_right(int i); void term_cursor_right(int i);

View File

@@ -1163,8 +1163,8 @@ qf_init_ext(
qffields_T fields; qffields_T fields;
#ifdef FEAT_WINDOWS #ifdef FEAT_WINDOWS
qfline_T *old_last = NULL; qfline_T *old_last = NULL;
int adding = FALSE;
#endif #endif
int adding = FALSE;
static efm_T *fmt_first = NULL; static efm_T *fmt_first = NULL;
char_u *efm; char_u *efm;
static char_u *last_efm = NULL; static char_u *last_efm = NULL;
@@ -1199,14 +1199,15 @@ qf_init_ext(
if (newlist || qi->qf_curlist == qi->qf_listcount) if (newlist || qi->qf_curlist == qi->qf_listcount)
/* make place for a new list */ /* make place for a new list */
qf_new_list(qi, qf_title); qf_new_list(qi, qf_title);
#ifdef FEAT_WINDOWS else
else if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
{ {
/* Adding to existing list, use last entry. */ /* Adding to existing list, use last entry. */
adding = TRUE; adding = TRUE;
#ifdef FEAT_WINDOWS
if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
old_last = qi->qf_lists[qi->qf_curlist].qf_last; old_last = qi->qf_lists[qi->qf_curlist].qf_last;
}
#endif #endif
}
/* Use the local value of 'errorformat' if it's set. */ /* Use the local value of 'errorformat' if it's set. */
if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL) if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL)
@@ -4785,6 +4786,8 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
(void)get_errorlist(wp, qf_idx, l); (void)get_errorlist(wp, qf_idx, l);
dict_add_list(retdict, "items", l); dict_add_list(retdict, "items", l);
} }
else
status = FAIL;
} }
if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
@@ -4795,9 +4798,12 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (di != NULL) if (di != NULL)
{ {
copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv); copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
if (dict_add(retdict, di) == FAIL) status = dict_add(retdict, di);
if (status == FAIL)
dictitem_free(di); dictitem_free(di);
} }
else
status = FAIL;
} }
else else
status = dict_add_nr_str(retdict, "context", 0L, (char_u *)""); status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
@@ -5020,6 +5026,7 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action)
if (ctx != NULL) if (ctx != NULL)
copy_tv(&di->di_tv, ctx); copy_tv(&di->di_tv, ctx);
qi->qf_lists[qf_idx].qf_ctx = ctx; qi->qf_lists[qf_idx].qf_ctx = ctx;
retval = OK;
} }
return retval; return retval;

View File

@@ -648,6 +648,8 @@ update_screen(int type_arg)
{ {
screenclear(); /* will reset clear_cmdline */ screenclear(); /* will reset clear_cmdline */
type = NOT_VALID; type = NOT_VALID;
/* must_redraw may be set indirectly, avoid another redraw later */
must_redraw = 0;
} }
if (clear_cmdline) /* going to clear cmdline (done below) */ if (clear_cmdline) /* going to clear cmdline (done below) */

View File

@@ -2513,6 +2513,77 @@ out_str_nf(char_u *s)
} }
#endif #endif
/*
* A conditional-flushing out_str, mainly for visualbell.
* Handles a delay internally, because termlib may not respect the delay or do
* it at the wrong time.
* Note: Only for terminal strings.
*/
void
out_str_cf(char_u *s)
{
if (s != NULL && *s)
{
#ifdef HAVE_TGETENT
char_u *p;
#endif
#ifdef FEAT_GUI
/* Don't use tputs() when GUI is used, ncurses crashes. */
if (gui.in_use)
{
out_str_nf(s);
return;
}
#endif
if (out_pos > OUT_SIZE - 20)
out_flush();
#ifdef HAVE_TGETENT
for (p = s; *s; ++s)
{
/* flush just before delay command */
if (*s == '$' && *(s + 1) == '<')
{
char_u save_c = *s;
int duration = atoi((char *)s + 2);
*s = NUL;
tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
*s = save_c;
out_flush();
# ifdef ELAPSED_FUNC
/* Only sleep here if we can limit this happening in
* vim_beep(). */
p = vim_strchr(s, '>');
if (p == NULL || duration <= 0)
{
/* can't parse the time, don't sleep here */
p = s;
}
else
{
++p;
do_sleep(duration);
}
# else
/* Rely on the terminal library to sleep. */
p = s;
# endif
break;
}
}
tputs((char *)p, 1, TPUTSFUNCAST out_char_nf);
#else
while (*s)
out_char_nf(*s++);
#endif
/* For testing we write one string at a time. */
if (p_wd)
out_flush();
}
}
/* /*
* out_str(s): Put a character string a byte at a time into the output buffer. * out_str(s): Put a character string a byte at a time into the output buffer.
* If HAVE_TGETENT is defined use the termcap parser. (jw) * If HAVE_TGETENT is defined use the termcap parser. (jw)

View File

@@ -60,10 +60,8 @@ SCRIPTS_ALL = \
test77.out \ test77.out \
test79.out \ test79.out \
test80.out \ test80.out \
test82.out \
test84.out \ test84.out \
test88.out \ test88.out \
test90.out \
test91.out \ test91.out \
test94.out \ test94.out \
test95.out \ test95.out \

View File

@@ -91,8 +91,8 @@ SCRIPT = test1.out test3.out test4.out test5.out \
test66.out test67.out test68.out test69.out \ test66.out test67.out test68.out test69.out \
test72.out test75.out \ test72.out test75.out \
test77a.out test78.out test79.out test80.out \ test77a.out test78.out test79.out test80.out \
test82.out test84.out test88.out \ test84.out test88.out \
test90.out test91.out test94.out \ test91.out test94.out \
test95.out test98.out test99.out \ test95.out test98.out test99.out \
test103.out test104.out \ test103.out test104.out \
test107.out test108.out\ test107.out test108.out\

View File

@@ -1,103 +0,0 @@
Tests for case-insensitive UTF-8 comparisons (utf_strnicmp() in mbyte.c)
Also test "g~ap".
STARTTEST
:so small.vim
:if !has("multi_byte")
: e! test.ok
: w! test.out
: qa!
:endif
:set enc=utf8
ggdG:
:
:function! Ch(a, op, b, expected)
: if eval(printf('"%s" %s "%s"', a:a, a:op, a:b)) != a:expected
: call append(line('$'), printf('"%s" %s "%s" should return %d', a:a, a:op, a:b, a:expected))
: else
: let b:passed += 1
: endif
:endfunction
:
:function! Chk(a, b, result)
: if a:result == 0
: call Ch(a:a, '==?', a:b, 1)
: call Ch(a:a, '!=?', a:b, 0)
: call Ch(a:a, '<=?', a:b, 1)
: call Ch(a:a, '>=?', a:b, 1)
: call Ch(a:a, '<?', a:b, 0)
: call Ch(a:a, '>?', a:b, 0)
: elseif a:result > 0
: call Ch(a:a, '==?', a:b, 0)
: call Ch(a:a, '!=?', a:b, 1)
: call Ch(a:a, '<=?', a:b, 0)
: call Ch(a:a, '>=?', a:b, 1)
: call Ch(a:a, '<?', a:b, 0)
: call Ch(a:a, '>?', a:b, 1)
: else
: call Ch(a:a, '==?', a:b, 0)
: call Ch(a:a, '!=?', a:b, 1)
: call Ch(a:a, '<=?', a:b, 1)
: call Ch(a:a, '>=?', a:b, 0)
: call Ch(a:a, '<?', a:b, 1)
: call Ch(a:a, '>?', a:b, 0)
: endif
:endfunction
:
:function! Check(a, b, result)
: call Chk(a:a, a:b, a:result)
: call Chk(a:b, a:a, -a:result)
:endfunction
:
:function! LT(a, b)
: call Check(a:a, a:b, -1)
:endfunction
:
:function! GT(a, b)
: call Check(a:a, a:b, 1)
:endfunction
:
:function! EQ(a, b)
: call Check(a:a, a:b, 0)
:endfunction
:
:let b:passed=0
:call EQ('', '')
:call LT('', 'a')
:call EQ('abc', 'abc')
:call EQ('Abc', 'abC')
:call LT('ab', 'abc')
:call LT('AB', 'abc')
:call LT('ab', 'aBc')
:call EQ('\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd', '\xd0\xb9\xd0\xa6\xd0\xa3\xd0\xba\xd0\x95\xd0\xbd')
:call LT('\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd', '\xd0\xaf\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd')
:call EQ('\xe2\x84\xaa', 'k')
:call LT('\xe2\x84\xaa', 'kkkkkk')
:call EQ('\xe2\x84\xaa\xe2\x84\xaa\xe2\x84\xaa', 'kkk')
:call LT('kk', '\xe2\x84\xaa\xe2\x84\xaa\xe2\x84\xaa')
:call EQ('\xe2\x84\xaa\xe2\x84\xa6k\xe2\x84\xaak\xcf\x89', 'k\xcf\x89\xe2\x84\xaakk\xe2\x84\xa6')
:call EQ('Abc\x80', 'AbC\x80')
:call LT('Abc\x80', 'AbC\x81')
:call LT('Abc', 'AbC\x80')
:call LT('abc\x80DEF', 'abc\x80def') " case folding stops at the first bad character
:call LT('\xc3XYZ', '\xc3xyz')
:call EQ('\xef\xbc\xba', '\xef\xbd\x9a') " FF3A (upper), FF5A (lower)
:call GT('\xef\xbc\xba', '\xef\xbc\xff') " first string is ok and equals \xef\xbd\x9a after folding, second string is illegal and was left unchanged, then the strings were bytewise compared
:call LT('\xc3', '\xc3\x83')
:call EQ('\xc3\xa3xYz', '\xc3\x83XyZ')
:for n in range(0x60, 0xFF) | call LT(printf('xYz\x%.2X', n-1), printf('XyZ\x%.2X', n)) | endfor
:for n in range(0x80, 0xBF) | call EQ(printf('xYz\xc2\x%.2XUvW', n), printf('XyZ\xc2\x%.2XuVw', n)) | endfor
:for n in range(0xC0, 0xFF) | call LT(printf('xYz\xc2\x%.2XUvW', n), printf('XyZ\xc2\x%.2XuVw', n)) | endfor
:call append(0, printf('%d checks passed', b:passed))
:"
:" test that g~ap changes one paragraph only.
:new
iabcd
defggg0g~ap:let lns = getline(1,3)
:q!
:call append(line('$'), lns)
:"
:wq! test.out
ENDTEST

View File

@@ -1,5 +0,0 @@
3732 checks passed
ABCD
defg

View File

@@ -1,53 +0,0 @@
Tests for sha256() function. vim: set ft=vim et ts=2 sw=2 :
STARTTEST
:so small.vim
:if !has('cryptv') || !exists('*sha256')
e! test.ok
wq! test.out
:endif
:"
:let testcase='test for empty string: '
:if sha256("") ==# 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
: let res='ok'
:else
: let res='ng'
:endif
:$put =testcase.res
:"
:let testcase='test for 1 char: '
:if sha256("a") ==# 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb'
: let res='ok'
:else
: let res='ng'
:endif
:$put =testcase.res
:"
:let testcase='test for 3 chars: '
:if sha256("abc") ==# 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
: let res='ok'
:else
: let res='ng'
:endif
:$put =testcase.res
:"
:let testcase='test for contains meta char: '
:if sha256("foo\nbar") ==# '807eff6267f3f926a21d234f7b0cf867a86f47e07a532f15e8cc39ed110ca776'
: let res='ok'
:else
: let res='ng'
:endif
:$put =testcase.res
:"
:let testcase='test for contains non-ascii char: '
:if sha256("\xde\xad\xbe\xef") ==# '5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953'
: let res='ok'
:else
: let res='ng'
:endif
:$put =testcase.res
:"
:/^start:/,$wq! test.out
ENDTEST
start:

View File

@@ -1,6 +0,0 @@
start:
test for empty string: ok
test for 1 char: ok
test for 3 chars: ok
test for contains meta char: ok
test for contains non-ascii char: ok

View File

@@ -34,3 +34,14 @@ func Test_put_char_block2()
bw! bw!
call setreg('a', a[0], a[1]) call setreg('a', a[0], a[1])
endfunc endfunc
func Test_put_lines()
new
let a = [ getreg('a'), getregtype('a') ]
call setline(1, ['Line 1', 'Line2', 'Line 3', ''])
exe 'norm! gg"add"AddG""p'
call assert_equal(['Line 3', '', 'Line 1', 'Line2'], getline(1,'$'))
" clean up
bw!
call setreg('a', a[0], a[1])
endfunc

View File

@@ -1720,7 +1720,8 @@ func Xproperty_tests(cchar)
Xopen Xopen
wincmd p wincmd p
call g:Xsetlist([{'filename':'foo', 'lnum':27}]) call g:Xsetlist([{'filename':'foo', 'lnum':27}])
call g:Xsetlist([], 'a', {'title' : 'Sample'}) let s = g:Xsetlist([], 'a', {'title' : 'Sample'})
call assert_equal(0, s)
let d = g:Xgetlist({"title":1}) let d = g:Xgetlist({"title":1})
call assert_equal('Sample', d.title) call assert_equal('Sample', d.title)
@@ -1774,7 +1775,8 @@ func Xproperty_tests(cchar)
endif endif
" Context related tests " Context related tests
call g:Xsetlist([], 'a', {'context':[1,2,3]}) let s = g:Xsetlist([], 'a', {'context':[1,2,3]})
call assert_equal(0, s)
call test_garbagecollect_now() call test_garbagecollect_now()
let d = g:Xgetlist({'context':1}) let d = g:Xgetlist({'context':1})
call assert_equal([1,2,3], d.context) call assert_equal([1,2,3], d.context)
@@ -1839,8 +1841,9 @@ func Xproperty_tests(cchar)
" Test for setting/getting items " Test for setting/getting items
Xexpr "" Xexpr ""
let qfprev = g:Xgetlist({'nr':0}) let qfprev = g:Xgetlist({'nr':0})
call g:Xsetlist([], ' ', {'title':'Green', let s = g:Xsetlist([], ' ', {'title':'Green',
\ 'items' : [{'filename':'F1', 'lnum':10}]}) \ 'items' : [{'filename':'F1', 'lnum':10}]})
call assert_equal(0, s)
let qfcur = g:Xgetlist({'nr':0}) let qfcur = g:Xgetlist({'nr':0})
call assert_true(qfcur.nr == qfprev.nr + 1) call assert_true(qfcur.nr == qfprev.nr + 1)
let l = g:Xgetlist({'items':1}) let l = g:Xgetlist({'items':1})
@@ -2187,18 +2190,6 @@ func Test_bufoverflow()
set efm&vim set efm&vim
endfunc endfunc
func Test_cclose_from_copen()
augroup QF_Test
au!
au FileType qf :call assert_fails(':cclose', 'E788')
augroup END
copen
augroup QF_Test
au!
augroup END
augroup! QF_Test
endfunc
" Tests for getting the quickfix stack size " Tests for getting the quickfix stack size
func XsizeTests(cchar) func XsizeTests(cchar)
call s:setup_commands(a:cchar) call s:setup_commands(a:cchar)
@@ -2228,6 +2219,18 @@ func Test_Qf_Size()
call XsizeTests('l') call XsizeTests('l')
endfunc endfunc
func Test_cclose_from_copen()
augroup QF_Test
au!
au FileType qf :call assert_fails(':cclose', 'E788')
augroup END
copen
augroup QF_Test
au!
augroup END
augroup! QF_Test
endfunc
func Test_cclose_in_autocmd() func Test_cclose_in_autocmd()
" Problem is only triggered if "starting" is zero, so that the OptionsSet " Problem is only triggered if "starting" is zero, so that the OptionsSet
" event will be triggered. " event will be triggered.
@@ -2243,3 +2246,20 @@ func Test_cclose_in_autocmd()
augroup! QF_Test augroup! QF_Test
call test_override('starting', 0) call test_override('starting', 0)
endfunc endfunc
func Test_resize_from_copen()
augroup QF_Test
au!
au FileType qf resize 5
augroup END
try
" This should succeed without any exception. No other buffers are
" involved in the autocmd.
copen
finally
augroup QF_Test
au!
augroup END
augroup! QF_Test
endtry
endfunc

View File

@@ -302,3 +302,23 @@ func Test_searchc()
exe "norm 0t\u93cf" exe "norm 0t\u93cf"
bw! bw!
endfunc endfunc
func Test_search_cmdline3()
if !exists('+incsearch')
return
endif
" need to disable char_avail,
" so that expansion of commandline works
call test_override("char_avail", 1)
new
call setline(1, [' 1', ' 2 the~e', ' 3 the theother'])
set incsearch
1
" first match
call feedkeys("/the\<c-l>\<cr>", 'tx')
call assert_equal(' 2 the~e', getline('.'))
" clean up
set noincsearch
call test_override("char_avail", 0)
bw!
endfunc

View File

@@ -0,0 +1,22 @@
" Tests for the sha256() function.
if !has('cryptv') || !exists('*sha256')
finish
endif
function Test_sha256()
" test for empty string:
call assert_equal(sha256(""), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855')
"'test for 1 char:
call assert_equal(sha256("a"), 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb')
"
"test for 3 chars:
call assert_equal(sha256("abc"), 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad')
" test for contains meta char:
call assert_equal(sha256("foo\nbar"), '807eff6267f3f926a21d234f7b0cf867a86f47e07a532f15e8cc39ed110ca776')
" test for contains non-ascii char:
call assert_equal(sha256("\xde\xad\xbe\xef"), '5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953')
endfunction

View File

@@ -23,28 +23,34 @@ func Test_after_comes_later()
\ 'set guioptions+=M', \ 'set guioptions+=M',
\ 'let $HOME = "/does/not/exist"', \ 'let $HOME = "/does/not/exist"',
\ 'set loadplugins', \ 'set loadplugins',
\ 'set rtp=Xhere,Xafter', \ 'set rtp=Xhere,Xafter,Xanother',
\ 'set packpath=Xhere,Xafter', \ 'set packpath=Xhere,Xafter',
\ 'set nomore', \ 'set nomore',
\ 'let g:sequence = ""',
\ ] \ ]
let after = [ let after = [
\ 'redir! > Xtestout', \ 'redir! > Xtestout',
\ 'scriptnames', \ 'scriptnames',
\ 'redir END', \ 'redir END',
\ 'redir! > Xsequence',
\ 'echo g:sequence',
\ 'redir END',
\ 'quit', \ 'quit',
\ ] \ ]
call mkdir('Xhere/plugin', 'p') call mkdir('Xhere/plugin', 'p')
call writefile(['let done = 1'], 'Xhere/plugin/here.vim') call writefile(['let g:sequence .= "here "'], 'Xhere/plugin/here.vim')
call mkdir('Xanother/plugin', 'p')
call writefile(['let g:sequence .= "another "'], 'Xanother/plugin/another.vim')
call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p') call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p')
call writefile(['let done = 1'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim') call writefile(['let g:sequence .= "pack "'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim')
call mkdir('Xafter/plugin', 'p') call mkdir('Xafter/plugin', 'p')
call writefile(['let done = 1'], 'Xafter/plugin/later.vim') call writefile(['let g:sequence .= "after "'], 'Xafter/plugin/later.vim')
if RunVim(before, after, '') if RunVim(before, after, '')
let lines = readfile('Xtestout') let lines = readfile('Xtestout')
let expected = ['Xbefore.vim', 'here.vim', 'foo.vim', 'later.vim', 'Xafter.vim'] let expected = ['Xbefore.vim', 'here.vim', 'another.vim', 'foo.vim', 'later.vim', 'Xafter.vim']
let found = [] let found = []
for line in lines for line in lines
for one in expected for one in expected
@@ -56,8 +62,12 @@ func Test_after_comes_later()
call assert_equal(expected, found) call assert_equal(expected, found)
endif endif
call assert_equal('here another pack after', substitute(join(readfile('Xsequence', 1), ''), '\s\+$', '', ''))
call delete('Xtestout') call delete('Xtestout')
call delete('Xsequence')
call delete('Xhere', 'rf') call delete('Xhere', 'rf')
call delete('Xanother', 'rf')
call delete('Xafter', 'rf') call delete('Xafter', 'rf')
endfunc endfunc

View File

@@ -418,7 +418,7 @@ func Test_bg_detection()
hi Normal ctermbg=15 hi Normal ctermbg=15
call assert_equal('light', &bg) call assert_equal('light', &bg)
" manually-set &bg takes precendence over auto-detection " manually-set &bg takes precedence over auto-detection
set bg=light set bg=light
hi Normal ctermbg=4 hi Normal ctermbg=4
call assert_equal('light', &bg) call assert_equal('light', &bg)
@@ -461,7 +461,6 @@ func Test_syntax_hangs()
bwipe! bwipe!
endfunc endfunc
func Test_conceal() func Test_conceal()
if !has('conceal') if !has('conceal')
return return
@@ -497,3 +496,27 @@ func Test_conceal()
set conceallevel& set conceallevel&
bw! bw!
endfunc endfunc
fun Test_synstack_synIDtrans()
new
setfiletype c
syntax on
call setline(1, ' /* A comment with a TODO */')
call assert_equal([], synstack(1, 1))
norm f/
call assert_equal(['cComment', 'cCommentStart'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
call assert_equal(['Comment', 'Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
norm fA
call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
call assert_equal(['Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
norm fT
call assert_equal(['cComment', 'cTodo'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
call assert_equal(['Comment', 'Todo'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
syn clear
bw!
endfunc

View File

@@ -0,0 +1,95 @@
" Tests for case-insensitive UTF-8 comparisons (utf_strnicmp() in mbyte.c)
" Also test "g~ap".
if !has("multi_byte")
finish
endif
function! Ch(a, op, b, expected)
call assert_equal(eval(printf('"%s" %s "%s"', a:a, a:op, a:b)), a:expected,
\ printf('"%s" %s "%s" should return %d', a:a, a:op, a:b, a:expected))
endfunction
function! Chk(a, b, result)
if a:result == 0
call Ch(a:a, '==?', a:b, 1)
call Ch(a:a, '!=?', a:b, 0)
call Ch(a:a, '<=?', a:b, 1)
call Ch(a:a, '>=?', a:b, 1)
call Ch(a:a, '<?', a:b, 0)
call Ch(a:a, '>?', a:b, 0)
elseif a:result > 0
call Ch(a:a, '==?', a:b, 0)
call Ch(a:a, '!=?', a:b, 1)
call Ch(a:a, '<=?', a:b, 0)
call Ch(a:a, '>=?', a:b, 1)
call Ch(a:a, '<?', a:b, 0)
call Ch(a:a, '>?', a:b, 1)
else
call Ch(a:a, '==?', a:b, 0)
call Ch(a:a, '!=?', a:b, 1)
call Ch(a:a, '<=?', a:b, 1)
call Ch(a:a, '>=?', a:b, 0)
call Ch(a:a, '<?', a:b, 1)
call Ch(a:a, '>?', a:b, 0)
endif
endfunction
function! Check(a, b, result)
call Chk(a:a, a:b, a:result)
call Chk(a:b, a:a, -a:result)
endfunction
function! LT(a, b)
call Check(a:a, a:b, -1)
endfunction
function! GT(a, b)
call Check(a:a, a:b, 1)
endfunction
function! EQ(a, b)
call Check(a:a, a:b, 0)
endfunction
function Test_comparisons()
call EQ('', '')
call LT('', 'a')
call EQ('abc', 'abc')
call EQ('Abc', 'abC')
call LT('ab', 'abc')
call LT('AB', 'abc')
call LT('ab', 'aBc')
call EQ('\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd', '\xd0\xb9\xd0\xa6\xd0\xa3\xd0\xba\xd0\x95\xd0\xbd')
call LT('\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd', '\xd0\xaf\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd')
call EQ('\xe2\x84\xaa', 'k')
call LT('\xe2\x84\xaa', 'kkkkkk')
call EQ('\xe2\x84\xaa\xe2\x84\xaa\xe2\x84\xaa', 'kkk')
call LT('kk', '\xe2\x84\xaa\xe2\x84\xaa\xe2\x84\xaa')
call EQ('\xe2\x84\xaa\xe2\x84\xa6k\xe2\x84\xaak\xcf\x89', 'k\xcf\x89\xe2\x84\xaakk\xe2\x84\xa6')
call EQ('Abc\x80', 'AbC\x80')
call LT('Abc\x80', 'AbC\x81')
call LT('Abc', 'AbC\x80')
call LT('abc\x80DEF', 'abc\x80def') " case folding stops at the first bad character
call LT('\xc3XYZ', '\xc3xyz')
call EQ('\xef\xbc\xba', '\xef\xbd\x9a') " FF3A (upper), FF5A (lower)
call GT('\xef\xbc\xba', '\xef\xbc\xff') " first string is ok and equals \xef\xbd\x9a after folding, second string is illegal and was left unchanged, then the strings were bytewise compared
call LT('\xc3', '\xc3\x83')
call EQ('\xc3\xa3xYz', '\xc3\x83XyZ')
for n in range(0x60, 0xFF)
call LT(printf('xYz\x%.2X', n-1), printf('XyZ\x%.2X', n))
endfor
for n in range(0x80, 0xBF)
call EQ(printf('xYz\xc2\x%.2XUvW', n), printf('XyZ\xc2\x%.2XuVw', n))
endfor
for n in range(0xC0, 0xFF)
call LT(printf('xYz\xc2\x%.2XUvW', n), printf('XyZ\xc2\x%.2XuVw', n))
endfor
endfunction
" test that g~ap changes one paragraph only.
function Test_gap()
new
call feedkeys("iabcd\n\ndefggg0g~ap", "tx")
call assert_equal(["ABCD", "", "defg"], getline(1,3))
endfunction

View File

@@ -318,6 +318,50 @@ func Test_window_width()
bw Xa Xb Xc bw Xa Xb Xc
endfunc endfunc
func Test_equalalways_on_close()
set equalalways
vsplit
windo split
split
wincmd J
" now we have a frame top-left with two windows, a frame top-right with two
" windows and a frame at the bottom, full-width.
let height_1 = winheight(1)
let height_2 = winheight(2)
let height_3 = winheight(3)
let height_4 = winheight(4)
" closing the bottom window causes all windows to be resized.
close
call assert_notequal(height_1, winheight(1))
call assert_notequal(height_2, winheight(2))
call assert_notequal(height_3, winheight(3))
call assert_notequal(height_4, winheight(4))
call assert_equal(winheight(1), winheight(3))
call assert_equal(winheight(2), winheight(4))
1wincmd w
split
4wincmd w
resize + 5
" left column has three windows, equalized heights.
" right column has two windows, top one a bit higher
let height_1 = winheight(1)
let height_2 = winheight(2)
let height_4 = winheight(4)
let height_5 = winheight(5)
3wincmd w
" closing window in left column equalizes heights in left column but not in
" the right column
close
call assert_notequal(height_1, winheight(1))
call assert_notequal(height_2, winheight(2))
call assert_equal(height_4, winheight(3))
call assert_equal(height_5, winheight(4))
only
set equalalways&
endfunc
func Test_window_jump_tag() func Test_window_jump_tag()
help help
/iccf /iccf

View File

@@ -31,3 +31,21 @@ func Test_writefile_fails_gently()
call assert_fails('call writefile([], [])', 'E730:') call assert_fails('call writefile([], [])', 'E730:')
endfunc endfunc
func Test_writefile_fails_conversion()
if !has('multi_byte') || !has('iconv')
return
endif
set nobackup nowritebackup
new
let contents = ["line one", "line two"]
call writefile(contents, 'Xfile')
edit Xfile
call setline(1, ["first line", "cannot convert \u010b", "third line"])
call assert_fails('write ++enc=cp932')
call assert_equal(contents, readfile('Xfile'))
call delete('Xfile')
bwipe!
set backup& writebackup&
endfunc

View File

@@ -764,6 +764,34 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
691,
/**/
690,
/**/
689,
/**/
688,
/**/
687,
/**/
686,
/**/
685,
/**/
684,
/**/
683,
/**/
682,
/**/
681,
/**/
680,
/**/
679,
/**/
678,
/**/ /**/
677, 677,
/**/ /**/

View File

@@ -2282,6 +2282,7 @@ win_close(win_T *win, int free_buf)
int dir; int dir;
int help_window = FALSE; int help_window = FALSE;
tabpage_T *prev_curtab = curtab; tabpage_T *prev_curtab = curtab;
frame_T *win_frame = win->w_frame->fr_parent;
if (last_window()) if (last_window())
{ {
@@ -2459,7 +2460,9 @@ win_close(win_T *win, int free_buf)
check_cursor(); check_cursor();
} }
if (p_ea && (*p_ead == 'b' || *p_ead == dir)) if (p_ea && (*p_ead == 'b' || *p_ead == dir))
win_equal(curwin, TRUE, dir); /* If the frame of the closed window contains the new current window,
* only resize that frame. Otherwise resize all windows. */
win_equal(curwin, curwin->w_frame->fr_parent == win_frame, dir);
else else
win_comp_pos(); win_comp_pos();
if (close_curwin) if (close_curwin)