aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/charset.c11
-rw-r--r--src/nvim/eval.c81
-rw-r--r--src/nvim/eval_defs.h9
-rw-r--r--src/nvim/fileio.c2
-rw-r--r--src/nvim/path.c39
-rw-r--r--src/nvim/regexp.c101
-rw-r--r--src/nvim/regexp_nfa.c52
-rw-r--r--src/nvim/search.c50
-rw-r--r--src/nvim/strings.c8
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test55.in160
-rw-r--r--src/nvim/testdir/test55.ok58
-rw-r--r--src/nvim/testdir/test83-tags22
-rw-r--r--src/nvim/testdir/test83-tags3102
-rw-r--r--src/nvim/testdir/test83.in75
-rw-r--r--src/nvim/testdir/test83.ok4
-rw-r--r--src/nvim/version.c6
-rw-r--r--src/nvim/window.c291
18 files changed, 577 insertions, 475 deletions
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index e0c9443511..9c63eca1f2 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -1791,7 +1791,6 @@ void vim_str2nr(char_u *start, int *prep, int *len,
int pre = 0; // default is decimal
int negative = false;
unsigned long un = 0;
- int n;
if (ptr[0] == '-') {
negative = true;
@@ -1818,7 +1817,7 @@ void vim_str2nr(char_u *start, int *prep, int *len,
if (dooct) {
// Don't interpret "0", "08" or "0129" as octal.
- for (n = 1; ascii_isdigit(ptr[n]); ++n) {
+ for (int n = 1; ascii_isdigit(ptr[n]); ++n) {
if (ptr[n] > '7') {
// can't be octal
pre = 0;
@@ -1836,9 +1835,6 @@ void vim_str2nr(char_u *start, int *prep, int *len,
// Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
if ((pre == 'B') || (pre == 'b') || (dobin > 1)) {
// bin
- if (pre != 0) {
- n += 2; // skip over "0b"
- }
while ('0' <= *ptr && *ptr <= '1') {
un = 2 * un + (unsigned long)(*ptr - '0');
ptr++;
@@ -1849,11 +1845,8 @@ void vim_str2nr(char_u *start, int *prep, int *len,
un = 8 * un + (unsigned long)(*ptr - '0');
ptr++;
}
- } else if (pre != 0 || dohex > 1) {
+ } else if ((pre == 'X') || (pre == 'x') || dohex > 1) {
// hex
- if (pre != 0) {
- n += 2; // skip over "0x"
- }
while (ascii_isxdigit(*ptr)) {
un = 16 * un + (unsigned long)hex2nr(*ptr);
ptr++;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 33c584eede..a1c5f958d1 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -2890,9 +2890,12 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit)
else if (do_unlet(lp->ll_name, forceit) == FAIL)
ret = FAIL;
*name_end = cc;
- } else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
+ } else if ((lp->ll_list != NULL
+ && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name))
+ || (lp->ll_dict != NULL
+ && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name))) {
return FAIL;
- else if (lp->ll_range) {
+ } else if (lp->ll_range) {
listitem_T *li;
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;
@@ -2953,17 +2956,30 @@ int do_unlet(char_u *name, int forceit)
hashtab_T *ht;
hashitem_T *hi;
char_u *varname;
+ dict_T *d;
dictitem_T *di;
dict_T *dict;
ht = find_var_ht_dict(name, &varname, &dict);
if (ht != NULL && *varname != NUL) {
+ if (ht == &globvarht) {
+ d = &globvardict;
+ } else if (current_funccal != NULL
+ && ht == &current_funccal->l_vars.dv_hashtab) {
+ d = &current_funccal->l_vars;
+ } else {
+ di = find_var_in_ht(ht, *name, (char_u *)"", false);
+ d = di->di_tv.vval.v_dict;
+ }
+
hi = hash_find(ht, varname);
if (!HASHITEM_EMPTY(hi)) {
di = HI2DI(hi);
if (var_check_fixed(di->di_flags, name)
- || var_check_ro(di->di_flags, name))
+ || var_check_ro(di->di_flags, name)
+ || tv_check_lock(d->dv_lock, name)) {
return FAIL;
+ }
typval_T oldtv;
bool watched = is_watched(dict);
@@ -6055,7 +6071,7 @@ dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET
#ifndef __clang_analyzer__
STRCPY(di->di_key, key);
#endif
- di->di_flags = 0;
+ di->di_flags = DI_FLAGS_ALLOC;
return di;
}
@@ -6067,7 +6083,7 @@ static dictitem_T *dictitem_copy(dictitem_T *org) FUNC_ATTR_NONNULL_RET
dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(org->di_key));
STRCPY(di->di_key, org->di_key);
- di->di_flags = 0;
+ di->di_flags = DI_FLAGS_ALLOC;
copy_tv(&org->di_tv, &di->di_tv);
return di;
@@ -6095,7 +6111,9 @@ static void dictitem_remove(dict_T *dict, dictitem_T *item)
void dictitem_free(dictitem_T *item)
{
clear_tv(&item->di_tv);
- xfree(item);
+ if (item->di_flags & DI_FLAGS_ALLOC) {
+ xfree(item);
+ }
}
/// Make a copy of dictionary
@@ -9212,6 +9230,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
hashitem_T *hi2;
int todo;
bool watched = is_watched(d1);
+ char *arg_errmsg = N_("extend() argument");
todo = (int)d2->dv_hashtab.ht_used;
for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) {
@@ -9245,6 +9264,11 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
} else if (*action == 'f' && HI2DI(hi2) != di1) {
typval_T oldtv;
+ if (tv_check_lock(di1->di_tv.v_lock, (char_u *)_(arg_errmsg))
+ || var_check_ro(di1->di_flags, (char_u *)_(arg_errmsg))) {
+ break;
+ }
+
if (watched) {
copy_tv(&di1->di_tv, &oldtv);
}
@@ -9460,12 +9484,14 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map)
if (argvars[0].v_type == VAR_LIST) {
if ((l = argvars[0].vval.v_list) == NULL
- || tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))
+ || (!map && tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))) {
return;
+ }
} else if (argvars[0].v_type == VAR_DICT) {
if ((d = argvars[0].vval.v_dict) == NULL
- || tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))
+ || (!map && tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))) {
return;
+ }
} else {
EMSG2(_(e_listdictarg), ermsg);
return;
@@ -9494,17 +9520,26 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map)
for (hi = ht->ht_array; todo > 0; ++hi) {
if (!HASHITEM_EMPTY(hi)) {
--todo;
+
di = HI2DI(hi);
- if (tv_check_lock(di->di_tv.v_lock,
- (char_u *)_(arg_errmsg)))
+ if (map
+ && (tv_check_lock(di->di_tv.v_lock, (char_u *)_(arg_errmsg))
+ || var_check_ro(di->di_flags, (char_u *)_(arg_errmsg)))) {
break;
+ }
+
vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
int r = filter_map_one(&di->di_tv, expr, map, &rem);
clear_tv(&vimvars[VV_KEY].vv_tv);
if (r == FAIL || did_emsg)
break;
- if (!map && rem)
+ if (!map && rem) {
+ if (var_check_fixed(di->di_flags, (char_u *)_(arg_errmsg))
+ || var_check_ro(di->di_flags, (char_u *)_(arg_errmsg))) {
+ break;
+ }
dictitem_remove(d, di);
+ }
}
}
hash_unlock(ht);
@@ -9512,8 +9547,9 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map)
vimvars[VV_KEY].vv_type = VAR_NUMBER;
for (li = l->lv_first; li != NULL; li = nli) {
- if (tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg)))
+ if (map && tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg))) {
break;
+ }
nli = li->li_next;
vimvars[VV_KEY].vv_nr = idx;
if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
@@ -13878,9 +13914,10 @@ static void f_remove(typval_T *argvars, typval_T *rettv)
key = get_tv_string_chk(&argvars[1]);
if (key != NULL) {
di = dict_find(d, key, -1);
- if (di == NULL)
+ if (di == NULL) {
EMSG2(_(e_dictkey), key);
- else {
+ } else if (!var_check_fixed(di->di_flags, (char_u *)_(arg_errmsg))
+ && !var_check_ro(di->di_flags, (char_u *)_(arg_errmsg))) {
*rettv = di->di_tv;
init_tv(&di->di_tv);
dictitem_remove(d, di);
@@ -18648,14 +18685,16 @@ static void vars_clear_ext(hashtab_T *ht, int free_val)
if (!HASHITEM_EMPTY(hi)) {
--todo;
- /* Free the variable. Don't remove it from the hashtab,
- * ht_array might change then. hash_clear() takes care of it
- * later. */
+ // Free the variable. Don't remove it from the hashtab,
+ // ht_array might change then. hash_clear() takes care of it
+ // later.
v = HI2DI(hi);
- if (free_val)
+ if (free_val) {
clear_tv(&v->di_tv);
- if ((v->di_flags & DI_FLAGS_FIX) == 0)
+ }
+ if (v->di_flags & DI_FLAGS_ALLOC) {
xfree(v);
+ }
}
}
hash_clear(ht);
@@ -18829,7 +18868,7 @@ set_var (
xfree(v);
return;
}
- v->di_flags = 0;
+ v->di_flags = DI_FLAGS_ALLOC;
}
if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) {
@@ -20720,7 +20759,7 @@ call_user_func (
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
} else {
v = xmalloc(sizeof(dictitem_T) + STRLEN(name));
- v->di_flags = DI_FLAGS_RO;
+ v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
}
STRCPY(v->di_key, name);
hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h
index ed419268d2..cdad1f3197 100644
--- a/src/nvim/eval_defs.h
+++ b/src/nvim/eval_defs.h
@@ -101,10 +101,11 @@ struct dictitem_S {
typedef struct dictitem_S dictitem_T;
-#define DI_FLAGS_RO 1 /* "di_flags" value: read-only variable */
-#define DI_FLAGS_RO_SBX 2 /* "di_flags" value: read-only in the sandbox */
-#define DI_FLAGS_FIX 4 /* "di_flags" value: fixed variable, not allocated */
-#define DI_FLAGS_LOCK 8 /* "di_flags" value: locked variable */
+#define DI_FLAGS_RO 1 // "di_flags" value: read-only variable
+#define DI_FLAGS_RO_SBX 2 // "di_flags" value: read-only in the sandbox
+#define DI_FLAGS_FIX 4 // "di_flags" value: fixed: no :unlet or remove()
+#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable
+#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated
/*
* Structure to hold info about a Dictionary.
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 899e338b48..badb5b85b0 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -6305,7 +6305,7 @@ bool has_event(int event) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
/// @param force When true, ignore autocmd_busy
/// @param group autocmd group ID or AUGROUP_ALL
/// @param buf Buffer for <abuf>
-/// @param exarg Ex command arguments
+/// @param eap Ex command arguments
///
/// @return true if some commands were executed.
static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 5ac3d07f67..8b9a49dfc0 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -681,11 +681,16 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
/* remove backslashes for the remaining components only */
(void)do_path_expand(gap, buf, len + 1, flags, false);
} else {
- /* no more wildcards, check if there is a match */
- /* remove backslashes for the remaining components only */
- if (*path_end != NUL)
+ FileInfo file_info;
+
+ // no more wildcards, check if there is a match
+ // remove backslashes for the remaining components only
+ if (*path_end != NUL) {
backslash_halve(buf + len + 1);
- if (os_file_exists(buf)) { /* add existing file */
+ }
+ // add existing file or symbolic link
+ if ((flags & EW_ALLLINKS) ? os_fileinfo_link((char *)buf, &file_info)
+ : os_file_exists(buf)) {
addfile(gap, buf, flags);
}
}
@@ -1294,26 +1299,28 @@ expand_backtick (
return cnt;
}
-/*
- * Add a file to a file list. Accepted flags:
- * EW_DIR add directories
- * EW_FILE add files
- * EW_EXEC add executable files
- * EW_NOTFOUND add even when it doesn't exist
- * EW_ADDSLASH add slash after directory name
- */
-void
-addfile (
+// Add a file to a file list. Accepted flags:
+// EW_DIR add directories
+// EW_FILE add files
+// EW_EXEC add executable files
+// EW_NOTFOUND add even when it doesn't exist
+// EW_ADDSLASH add slash after directory name
+// EW_ALLLINKS add symlink also when the referred file does not exist
+void addfile(
garray_T *gap,
char_u *f, /* filename */
int flags
)
{
bool isdir;
+ FileInfo file_info;
- /* if the file/dir doesn't exist, may not add it */
- if (!(flags & EW_NOTFOUND) && !os_file_exists(f))
+ // if the file/dir/link doesn't exist, may not add it
+ if (!(flags & EW_NOTFOUND) &&
+ ((flags & EW_ALLLINKS) ?
+ !os_fileinfo_link((char *)f, &file_info) : !os_file_exists(f))) {
return;
+ }
#ifdef FNAME_ILLEGAL
/* if the file/dir contains illegal characters, don't add it */
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index e01e812a70..608aa38466 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -796,13 +796,14 @@ static void reg_equi_class(int c)
if (enc_utf8 || STRCMP(p_enc, "latin1") == 0
|| STRCMP(p_enc, "iso-8859-15") == 0) {
switch (c) {
- case 'A': case '\300': case '\301': case '\302':
+ // Do not use '\300' style, it results in a negative number.
+ case 'A': case 0xc0: case 0xc1: case 0xc2:
+ case 0xc3: case 0xc4: case 0xc5:
CASEMBC(0x100) CASEMBC(0x102) CASEMBC(0x104) CASEMBC(0x1cd)
CASEMBC(0x1de) CASEMBC(0x1e0) CASEMBC(0x1ea2)
- case '\303': case '\304': case '\305':
- regmbc('A'); regmbc('\300'); regmbc('\301');
- regmbc('\302'); regmbc('\303'); regmbc('\304');
- regmbc('\305');
+ regmbc('A'); regmbc(0xc0); regmbc(0xc1);
+ regmbc(0xc2); regmbc(0xc3); regmbc(0xc4);
+ regmbc(0xc5);
REGMBC(0x100) REGMBC(0x102) REGMBC(0x104)
REGMBC(0x1cd) REGMBC(0x1de) REGMBC(0x1e0)
REGMBC(0x1ea2)
@@ -810,9 +811,9 @@ static void reg_equi_class(int c)
case 'B': CASEMBC(0x1e02) CASEMBC(0x1e06)
regmbc('B'); REGMBC(0x1e02) REGMBC(0x1e06)
return;
- case 'C': case '\307':
+ case 'C': case 0xc7:
CASEMBC(0x106) CASEMBC(0x108) CASEMBC(0x10a) CASEMBC(0x10c)
- regmbc('C'); regmbc('\307');
+ regmbc('C'); regmbc(0xc7);
REGMBC(0x106) REGMBC(0x108) REGMBC(0x10a)
REGMBC(0x10c)
return;
@@ -821,11 +822,11 @@ static void reg_equi_class(int c)
regmbc('D'); REGMBC(0x10e) REGMBC(0x110)
REGMBC(0x1e0a) REGMBC(0x1e0e) REGMBC(0x1e10)
return;
- case 'E': case '\310': case '\311': case '\312': case '\313':
+ case 'E': case 0xc8: case 0xc9: case 0xca: case 0xcb:
CASEMBC(0x112) CASEMBC(0x114) CASEMBC(0x116) CASEMBC(0x118)
CASEMBC(0x11a) CASEMBC(0x1eba) CASEMBC(0x1ebc)
- regmbc('E'); regmbc('\310'); regmbc('\311');
- regmbc('\312'); regmbc('\313');
+ regmbc('E'); regmbc(0xc8); regmbc(0xc9);
+ regmbc(0xca); regmbc(0xcb);
REGMBC(0x112) REGMBC(0x114) REGMBC(0x116)
REGMBC(0x118) REGMBC(0x11a) REGMBC(0x1eba)
REGMBC(0x1ebc)
@@ -845,11 +846,11 @@ static void reg_equi_class(int c)
regmbc('H'); REGMBC(0x124) REGMBC(0x126)
REGMBC(0x1e22) REGMBC(0x1e26) REGMBC(0x1e28)
return;
- case 'I': case '\314': case '\315': case '\316': case '\317':
+ case 'I': case 0xcc: case 0xcd: case 0xce: case 0xcf:
CASEMBC(0x128) CASEMBC(0x12a) CASEMBC(0x12c) CASEMBC(0x12e)
CASEMBC(0x130) CASEMBC(0x1cf) CASEMBC(0x1ec8)
- regmbc('I'); regmbc('\314'); regmbc('\315');
- regmbc('\316'); regmbc('\317');
+ regmbc('I'); regmbc(0xcc); regmbc(0xcd);
+ regmbc(0xce); regmbc(0xcf);
REGMBC(0x128) REGMBC(0x12a) REGMBC(0x12c)
REGMBC(0x12e) REGMBC(0x130) REGMBC(0x1cf)
REGMBC(0x1ec8)
@@ -871,20 +872,20 @@ static void reg_equi_class(int c)
case 'M': CASEMBC(0x1e3e) CASEMBC(0x1e40)
regmbc('M'); REGMBC(0x1e3e) REGMBC(0x1e40)
return;
- case 'N': case '\321':
+ case 'N': case 0xd1:
CASEMBC(0x143) CASEMBC(0x145) CASEMBC(0x147) CASEMBC(0x1e44)
CASEMBC(0x1e48)
- regmbc('N'); regmbc('\321');
+ regmbc('N'); regmbc(0xd1);
REGMBC(0x143) REGMBC(0x145) REGMBC(0x147)
REGMBC(0x1e44) REGMBC(0x1e48)
return;
- case 'O': case '\322': case '\323': case '\324': case '\325':
- case '\326': case '\330':
+ case 'O': case 0xd2: case 0xd3: case 0xd4: case 0xd5:
+ case 0xd6: case 0xd8:
CASEMBC(0x14c) CASEMBC(0x14e) CASEMBC(0x150) CASEMBC(0x1a0)
CASEMBC(0x1d1) CASEMBC(0x1ea) CASEMBC(0x1ec) CASEMBC(0x1ece)
- regmbc('O'); regmbc('\322'); regmbc('\323');
- regmbc('\324'); regmbc('\325'); regmbc('\326');
- regmbc('\330');
+ regmbc('O'); regmbc(0xd2); regmbc(0xd3);
+ regmbc(0xd4); regmbc(0xd5); regmbc(0xd6);
+ regmbc(0xd8);
REGMBC(0x14c) REGMBC(0x14e) REGMBC(0x150)
REGMBC(0x1a0) REGMBC(0x1d1) REGMBC(0x1ea)
REGMBC(0x1ec) REGMBC(0x1ece)
@@ -907,12 +908,12 @@ static void reg_equi_class(int c)
regmbc('T'); REGMBC(0x162) REGMBC(0x164)
REGMBC(0x166) REGMBC(0x1e6a) REGMBC(0x1e6e)
return;
- case 'U': case '\331': case '\332': case '\333': case '\334':
+ case 'U': case 0xd9: case 0xda: case 0xdb: case 0xdc:
CASEMBC(0x168) CASEMBC(0x16a) CASEMBC(0x16c) CASEMBC(0x16e)
CASEMBC(0x170) CASEMBC(0x172) CASEMBC(0x1af) CASEMBC(0x1d3)
CASEMBC(0x1ee6)
- regmbc('U'); regmbc('\331'); regmbc('\332');
- regmbc('\333'); regmbc('\334');
+ regmbc('U'); regmbc(0xd9); regmbc(0xda);
+ regmbc(0xdb); regmbc(0xdc);
REGMBC(0x168) REGMBC(0x16a) REGMBC(0x16c)
REGMBC(0x16e) REGMBC(0x170) REGMBC(0x172)
REGMBC(0x1af) REGMBC(0x1d3) REGMBC(0x1ee6)
@@ -928,10 +929,10 @@ static void reg_equi_class(int c)
case 'X': CASEMBC(0x1e8a) CASEMBC(0x1e8c)
regmbc('X'); REGMBC(0x1e8a) REGMBC(0x1e8c)
return;
- case 'Y': case '\335':
+ case 'Y': case 0xdd:
CASEMBC(0x176) CASEMBC(0x178) CASEMBC(0x1e8e) CASEMBC(0x1ef2)
CASEMBC(0x1ef6) CASEMBC(0x1ef8)
- regmbc('Y'); regmbc('\335');
+ regmbc('Y'); regmbc(0xdd);
REGMBC(0x176) REGMBC(0x178) REGMBC(0x1e8e)
REGMBC(0x1ef2) REGMBC(0x1ef6) REGMBC(0x1ef8)
return;
@@ -941,13 +942,13 @@ static void reg_equi_class(int c)
REGMBC(0x17d) REGMBC(0x1b5) REGMBC(0x1e90)
REGMBC(0x1e94)
return;
- case 'a': case '\340': case '\341': case '\342':
- case '\343': case '\344': case '\345':
+ case 'a': case 0xe0: case 0xe1: case 0xe2:
+ case 0xe3: case 0xe4: case 0xe5:
CASEMBC(0x101) CASEMBC(0x103) CASEMBC(0x105) CASEMBC(0x1ce)
CASEMBC(0x1df) CASEMBC(0x1e1) CASEMBC(0x1ea3)
- regmbc('a'); regmbc('\340'); regmbc('\341');
- regmbc('\342'); regmbc('\343'); regmbc('\344');
- regmbc('\345');
+ regmbc('a'); regmbc(0xe0); regmbc(0xe1);
+ regmbc(0xe2); regmbc(0xe3); regmbc(0xe4);
+ regmbc(0xe5);
REGMBC(0x101) REGMBC(0x103) REGMBC(0x105)
REGMBC(0x1ce) REGMBC(0x1df) REGMBC(0x1e1)
REGMBC(0x1ea3)
@@ -955,9 +956,9 @@ static void reg_equi_class(int c)
case 'b': CASEMBC(0x1e03) CASEMBC(0x1e07)
regmbc('b'); REGMBC(0x1e03) REGMBC(0x1e07)
return;
- case 'c': case '\347':
+ case 'c': case 0xe7:
CASEMBC(0x107) CASEMBC(0x109) CASEMBC(0x10b) CASEMBC(0x10d)
- regmbc('c'); regmbc('\347');
+ regmbc('c'); regmbc(0xe7);
REGMBC(0x107) REGMBC(0x109) REGMBC(0x10b)
REGMBC(0x10d)
return;
@@ -966,11 +967,11 @@ static void reg_equi_class(int c)
regmbc('d'); REGMBC(0x10f) REGMBC(0x111)
REGMBC(0x1e0b) REGMBC(0x1e0f) REGMBC(0x1e11)
return;
- case 'e': case '\350': case '\351': case '\352': case '\353':
+ case 'e': case 0xe8: case 0xe9: case 0xea: case 0xeb:
CASEMBC(0x113) CASEMBC(0x115) CASEMBC(0x117) CASEMBC(0x119)
CASEMBC(0x11b) CASEMBC(0x1ebb) CASEMBC(0x1ebd)
- regmbc('e'); regmbc('\350'); regmbc('\351');
- regmbc('\352'); regmbc('\353');
+ regmbc('e'); regmbc(0xe8); regmbc(0xe9);
+ regmbc(0xea); regmbc(0xeb);
REGMBC(0x113) REGMBC(0x115) REGMBC(0x117)
REGMBC(0x119) REGMBC(0x11b) REGMBC(0x1ebb)
REGMBC(0x1ebd)
@@ -991,11 +992,11 @@ static void reg_equi_class(int c)
REGMBC(0x1e23) REGMBC(0x1e27) REGMBC(0x1e29)
REGMBC(0x1e96)
return;
- case 'i': case '\354': case '\355': case '\356': case '\357':
+ case 'i': case 0xec: case 0xed: case 0xee: case 0xef:
CASEMBC(0x129) CASEMBC(0x12b) CASEMBC(0x12d) CASEMBC(0x12f)
CASEMBC(0x1d0) CASEMBC(0x1ec9)
- regmbc('i'); regmbc('\354'); regmbc('\355');
- regmbc('\356'); regmbc('\357');
+ regmbc('i'); regmbc(0xec); regmbc(0xed);
+ regmbc(0xee); regmbc(0xef);
REGMBC(0x129) REGMBC(0x12b) REGMBC(0x12d)
REGMBC(0x12f) REGMBC(0x1d0) REGMBC(0x1ec9)
return;
@@ -1016,20 +1017,20 @@ static void reg_equi_class(int c)
case 'm': CASEMBC(0x1e3f) CASEMBC(0x1e41)
regmbc('m'); REGMBC(0x1e3f) REGMBC(0x1e41)
return;
- case 'n': case '\361':
+ case 'n': case 0xf1:
CASEMBC(0x144) CASEMBC(0x146) CASEMBC(0x148) CASEMBC(0x149)
CASEMBC(0x1e45) CASEMBC(0x1e49)
- regmbc('n'); regmbc('\361');
+ regmbc('n'); regmbc(0xf1);
REGMBC(0x144) REGMBC(0x146) REGMBC(0x148)
REGMBC(0x149) REGMBC(0x1e45) REGMBC(0x1e49)
return;
- case 'o': case '\362': case '\363': case '\364': case '\365':
- case '\366': case '\370':
+ case 'o': case 0xf2: case 0xf3: case 0xf4: case 0xf5:
+ case 0xf6: case 0xf8:
CASEMBC(0x14d) CASEMBC(0x14f) CASEMBC(0x151) CASEMBC(0x1a1)
CASEMBC(0x1d2) CASEMBC(0x1eb) CASEMBC(0x1ed) CASEMBC(0x1ecf)
- regmbc('o'); regmbc('\362'); regmbc('\363');
- regmbc('\364'); regmbc('\365'); regmbc('\366');
- regmbc('\370');
+ regmbc('o'); regmbc(0xf2); regmbc(0xf3);
+ regmbc(0xf4); regmbc(0xf5); regmbc(0xf6);
+ regmbc(0xf8);
REGMBC(0x14d) REGMBC(0x14f) REGMBC(0x151)
REGMBC(0x1a1) REGMBC(0x1d2) REGMBC(0x1eb)
REGMBC(0x1ed) REGMBC(0x1ecf)
@@ -1052,12 +1053,12 @@ static void reg_equi_class(int c)
regmbc('t'); REGMBC(0x163) REGMBC(0x165) REGMBC(0x167)
REGMBC(0x1e6b) REGMBC(0x1e6f) REGMBC(0x1e97)
return;
- case 'u': case '\371': case '\372': case '\373': case '\374':
+ case 'u': case 0xf9: case 0xfa: case 0xfb: case 0xfc:
CASEMBC(0x169) CASEMBC(0x16b) CASEMBC(0x16d) CASEMBC(0x16f)
CASEMBC(0x171) CASEMBC(0x173) CASEMBC(0x1b0) CASEMBC(0x1d4)
CASEMBC(0x1ee7)
- regmbc('u'); regmbc('\371'); regmbc('\372');
- regmbc('\373'); regmbc('\374');
+ regmbc('u'); regmbc(0xf9); regmbc(0xfa);
+ regmbc(0xfb); regmbc(0xfc);
REGMBC(0x169) REGMBC(0x16b) REGMBC(0x16d)
REGMBC(0x16f) REGMBC(0x171) REGMBC(0x173)
REGMBC(0x1b0) REGMBC(0x1d4) REGMBC(0x1ee7)
@@ -1074,10 +1075,10 @@ static void reg_equi_class(int c)
case 'x': CASEMBC(0x1e8b) CASEMBC(0x1e8d)
regmbc('x'); REGMBC(0x1e8b) REGMBC(0x1e8d)
return;
- case 'y': case '\375': case '\377':
+ case 'y': case 0xfd: case 0xff:
CASEMBC(0x177) CASEMBC(0x1e8f) CASEMBC(0x1e99)
CASEMBC(0x1ef3) CASEMBC(0x1ef7) CASEMBC(0x1ef9)
- regmbc('y'); regmbc('\375'); regmbc('\377');
+ regmbc('y'); regmbc(0xfd); regmbc(0xff);
REGMBC(0x177) REGMBC(0x1e8f) REGMBC(0x1e99)
REGMBC(0x1ef3) REGMBC(0x1ef7) REGMBC(0x1ef9)
return;
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 1fd024a062..4020fa6e28 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -4762,48 +4762,54 @@ static int skip_to_start(int c, colnr_T *colp)
*/
static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
{
- colnr_T col = startcol;
- int c1, c2;
- int len1, len2;
- int match;
+#define PTR2LEN(x) enc_utf8 ? utf_ptr2len(x) : MB_PTR2LEN(x)
- for (;; ) {
- match = TRUE;
- len2 = MB_CHAR2LEN(regstart); /* skip regstart */
- for (len1 = 0; match_text[len1] != NUL; len1 += MB_CHAR2LEN(c1)) {
- c1 = PTR2CHAR(match_text + len1);
- c2 = PTR2CHAR(regline + col + len2);
- if (c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) {
- match = FALSE;
+ colnr_T col = startcol;
+ int regstart_len = PTR2LEN(regline + startcol);
+
+ for (;;) {
+ bool match = true;
+ char_u *s1 = match_text;
+ char_u *s2 = regline + col + regstart_len; // skip regstart
+ while (*s1) {
+ int c1_len = PTR2LEN(s1);
+ int c1 = PTR2CHAR(s1);
+ int c2_len = PTR2LEN(s2);
+ int c2 = PTR2CHAR(s2);
+
+ if ((c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) ||
+ c1_len != c2_len) {
+ match = false;
break;
}
- len2 += MB_CHAR2LEN(c2);
+ s1 += c1_len;
+ s2 += c2_len;
}
if (match
- /* check that no composing char follows */
- && !(enc_utf8
- && STRLEN(regline) > (size_t)(col + len2)
- && utf_iscomposing(PTR2CHAR(regline + col + len2)))
- ) {
+ // check that no composing char follows
+ && !(enc_utf8 && utf_iscomposing(PTR2CHAR(s2)))) {
cleanup_subexpr();
if (REG_MULTI) {
reg_startpos[0].lnum = reglnum;
reg_startpos[0].col = col;
reg_endpos[0].lnum = reglnum;
- reg_endpos[0].col = col + len2;
+ reg_endpos[0].col = s2 - regline;
} else {
reg_startp[0] = regline + col;
- reg_endp[0] = regline + col + len2;
+ reg_endp[0] = s2;
}
return 1L;
}
- /* Try finding regstart after the current match. */
- col += MB_CHAR2LEN(regstart); /* skip regstart */
- if (skip_to_start(regstart, &col) == FAIL)
+ // Try finding regstart after the current match.
+ col += regstart_len; // skip regstart
+ if (skip_to_start(regstart, &col) == FAIL) {
break;
+ }
}
return 0L;
+
+#undef PTR2LEN
}
/*
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 18a72524cb..d393ee7d02 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -621,43 +621,39 @@ int searchit(
break;
}
matchcol = endpos.col;
- /* for empty match: advance one char */
- if (matchcol == matchpos.col
- && ptr[matchcol] != NUL) {
- if (has_mbyte)
- matchcol +=
- (*mb_ptr2len)(ptr + matchcol);
- else
- ++matchcol;
- }
+ // for empty match (matchcol == matchpos.col): advance one char
} else {
+ // Prepare to start after first matched character.
matchcol = matchpos.col;
- if (ptr[matchcol] != NUL) {
- if (has_mbyte)
- matchcol += (*mb_ptr2len)(ptr
- + matchcol);
- else
- ++matchcol;
- }
}
- if (matchcol == 0 && (options & SEARCH_START))
+
+ if (matchcol == matchpos.col && ptr[matchcol] != NUL) {
+ matchcol += MB_PTR2LEN(ptr + matchcol);
+ }
+
+ if (matchcol == 0 && (options & SEARCH_START)) {
break;
- if (STRLEN(ptr) <= (size_t)matchcol || ptr[matchcol] == NUL
- || (nmatched = vim_regexec_multi(&regmatch,
- win, buf, lnum + matchpos.lnum,
- matchcol,
- tm
- )) == 0) {
- match_ok = FALSE;
+ }
+
+ if (ptr[matchcol] == NUL ||
+ (nmatched = vim_regexec_multi(&regmatch, win, buf, lnum,
+ matchcol, tm)) == 0) {
+ match_ok = false;
break;
}
matchpos = regmatch.startpos[0];
endpos = regmatch.endpos[0];
submatch = first_submatch(&regmatch);
- /* Need to get the line pointer again, a
- * multi-line search may have made it invalid. */
- ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
+ // This while-loop only works with matchpos.lnum == 0.
+ // For bigger values the next line pointer ptr might not be a
+ // buffer line.
+ if (matchpos.lnum != 0) {
+ break;
+ }
+ // Need to get the line pointer again, a multi-line search may
+ // have made it invalid.
+ ptr = ml_get_buf(buf, lnum, false);
}
if (!match_ok)
continue;
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index fe91141375..37a0fb82da 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -425,9 +425,13 @@ char_u *vim_strchr(const char_u *string, int c)
const char_u *p = string;
if (enc_utf8 && c >= 0x80) {
while (*p != NUL) {
- if (utf_ptr2char(p) == c)
+ int l = (*mb_ptr2len)(p);
+
+ // Avoid matching an illegal byte here.
+ if (l > 1 && utf_ptr2char(p) == c) {
return (char_u *) p;
- p += (*mb_ptr2len)(p);
+ }
+ p += l;
}
return NULL;
}
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index aaa6f4b97e..e27ac227c8 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -22,7 +22,6 @@ SCRIPTS := test_eval.out \
test68.out test69.out \
test73.out \
test79.out \
- test83.out \
test88.out \
test_listlbr.out \
test_breakindent.out \
diff --git a/src/nvim/testdir/test55.in b/src/nvim/testdir/test55.in
index c4e82d429c..7b6f684caa 100644
--- a/src/nvim/testdir/test55.in
+++ b/src/nvim/testdir/test55.in
@@ -282,6 +282,166 @@ let l = [0, 1, 2, 3]
: $put =ps
: endfor
:endfor
+:"
+:" Unletting locked variables
+:$put ='Unletting:'
+:for depth in range(5)
+: $put ='depth is ' . depth
+: for u in range(3)
+: unlet l
+: let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}]
+: exe "lockvar " . depth . " l"
+: if u == 1
+: exe "unlockvar l"
+: elseif u == 2
+: exe "unlockvar " . depth . " l"
+: endif
+: let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]")
+: $put =ps
+: let ps = ''
+: try
+: unlet l[2]['6'][7]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[2][6]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[2]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[1][1][0]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[1][1]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[1]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: $put =ps
+: endfor
+:endfor
+:"
+:" Locked variables and :unlet or list / dict functions
+:$put ='Locks and commands or functions:'
+:"
+:$put ='No :unlet after lock on dict:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar 1 d
+:try
+: unlet d.a
+: $put ='did :unlet'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put =':unlet after lock on dict item:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar d.a
+:try
+: unlet d.a
+: $put ='did :unlet'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put ='filter() after lock on dict item:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar d.a
+:try
+: call filter(d, 'v:key != "a"')
+: $put ='did filter()'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put ='map() after lock on dict:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar 1 d
+:try
+: call map(d, 'v:val + 200')
+: $put ='did map()'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put ='No extend() after lock on dict item:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar d.a
+:try
+: $put =string(extend(d, {'a': 123}))
+: $put ='did extend()'
+:catch
+: $put =v:exception[:14]
+:endtry
+:$put =string(d)
+:"
+:$put ='No remove() of write-protected scope-level variable:'
+:fun! Tfunc(this_is_a_loooooooooong_parameter_name)
+: try
+: $put =string(remove(a:, 'this_is_a_loooooooooong_parameter_name'))
+: $put ='did remove()'
+: catch
+: $put =v:exception[:14]
+: endtry
+:endfun
+:call Tfunc('testval')
+:"
+:$put ='No extend() of write-protected scope-level variable:'
+:fun! Tfunc(this_is_a_loooooooooong_parameter_name)
+: try
+: $put =string(extend(a:, {'this_is_a_loooooooooong_parameter_name': 1234}))
+: $put ='did extend()'
+: catch
+: $put =v:exception[:14]
+: endtry
+:endfun
+:call Tfunc('testval')
+:"
+:$put ='No :unlet of variable in locked scope:'
+:let b:testvar = 123
+:lockvar 1 b:
+:try
+: unlet b:testvar
+: $put ='b:testvar was :unlet: '. (!exists('b:testvar'))
+:catch
+: $put =v:exception[:16]
+:endtry
+:unlockvar 1 b:
+:unlet! b:testvar
+:"
:unlet l
:let l = [1, 2, 3, 4]
:lockvar! l
diff --git a/src/nvim/testdir/test55.ok b/src/nvim/testdir/test55.ok
index ba029b2898..4e0303c26e 100644
--- a/src/nvim/testdir/test55.ok
+++ b/src/nvim/testdir/test55.ok
@@ -86,6 +86,64 @@ FFFFFFF
FFpFFpp
0000-000
ppppppp
+Unletting:
+depth is 0
+0000-000
+ppppppp
+0000-000
+ppppppp
+0000-000
+ppppppp
+depth is 1
+1000-000
+ppFppFp
+0000-000
+ppppppp
+0000-000
+ppppppp
+depth is 2
+1100-100
+pFFpFFp
+0000-000
+ppppppp
+0000-000
+ppppppp
+depth is 3
+1110-110
+FFFFFFp
+0010-010
+FppFppp
+0000-000
+ppppppp
+depth is 4
+1111-111
+FFFFFFp
+0011-011
+FppFppp
+0000-000
+ppppppp
+Locks and commands or functions:
+No :unlet after lock on dict:
+Vim(unlet):E741:
+{'a': 99, 'b': 100}
+:unlet after lock on dict item:
+did :unlet
+{'b': 100}
+filter() after lock on dict item:
+did filter()
+{'b': 100}
+map() after lock on dict:
+did map()
+{'a': 299, 'b': 300}
+No extend() after lock on dict item:
+Vim(put):E741:
+{'a': 99, 'b': 100}
+No remove() of write-protected scope-level variable:
+Vim(put):E795:
+No extend() of write-protected scope-level variable:
+Vim(put):E742:
+No :unlet of variable in locked scope:
+Vim(unlet):E741:
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
diff --git a/src/nvim/testdir/test83-tags2 b/src/nvim/testdir/test83-tags2
deleted file mode 100644
index 7f9f21b0eb..0000000000
--- a/src/nvim/testdir/test83-tags2
+++ /dev/null
@@ -1,2 +0,0 @@
-!_TAG_FILE_ENCODING cp932 //
-‚`‚a‚b Xtags2.txt /‚`‚a‚b
diff --git a/src/nvim/testdir/test83-tags3 b/src/nvim/testdir/test83-tags3
deleted file mode 100644
index 0cb6591562..0000000000
--- a/src/nvim/testdir/test83-tags3
+++ /dev/null
@@ -1,102 +0,0 @@
-!_TAG_FILE_SORTED 1 //
-!_TAG_FILE_ENCODING cp932 //
-abc1 Xtags3.txt /‚`‚a‚b
-abc2 Xtags3.txt /‚`‚a‚b
-abc3 Xtags3.txt /‚`‚a‚b
-abc4 Xtags3.txt /‚`‚a‚b
-abc5 Xtags3.txt /‚`‚a‚b
-abc6 Xtags3.txt /‚`‚a‚b
-abc7 Xtags3.txt /‚`‚a‚b
-abc8 Xtags3.txt /‚`‚a‚b
-abc9 Xtags3.txt /‚`‚a‚b
-abc10 Xtags3.txt /‚`‚a‚b
-abc11 Xtags3.txt /‚`‚a‚b
-abc12 Xtags3.txt /‚`‚a‚b
-abc13 Xtags3.txt /‚`‚a‚b
-abc14 Xtags3.txt /‚`‚a‚b
-abc15 Xtags3.txt /‚`‚a‚b
-abc16 Xtags3.txt /‚`‚a‚b
-abc17 Xtags3.txt /‚`‚a‚b
-abc18 Xtags3.txt /‚`‚a‚b
-abc19 Xtags3.txt /‚`‚a‚b
-abc20 Xtags3.txt /‚`‚a‚b
-abc21 Xtags3.txt /‚`‚a‚b
-abc22 Xtags3.txt /‚`‚a‚b
-abc23 Xtags3.txt /‚`‚a‚b
-abc24 Xtags3.txt /‚`‚a‚b
-abc25 Xtags3.txt /‚`‚a‚b
-abc26 Xtags3.txt /‚`‚a‚b
-abc27 Xtags3.txt /‚`‚a‚b
-abc28 Xtags3.txt /‚`‚a‚b
-abc29 Xtags3.txt /‚`‚a‚b
-abc30 Xtags3.txt /‚`‚a‚b
-abc31 Xtags3.txt /‚`‚a‚b
-abc32 Xtags3.txt /‚`‚a‚b
-abc33 Xtags3.txt /‚`‚a‚b
-abc34 Xtags3.txt /‚`‚a‚b
-abc35 Xtags3.txt /‚`‚a‚b
-abc36 Xtags3.txt /‚`‚a‚b
-abc37 Xtags3.txt /‚`‚a‚b
-abc38 Xtags3.txt /‚`‚a‚b
-abc39 Xtags3.txt /‚`‚a‚b
-abc40 Xtags3.txt /‚`‚a‚b
-abc41 Xtags3.txt /‚`‚a‚b
-abc42 Xtags3.txt /‚`‚a‚b
-abc43 Xtags3.txt /‚`‚a‚b
-abc44 Xtags3.txt /‚`‚a‚b
-abc45 Xtags3.txt /‚`‚a‚b
-abc46 Xtags3.txt /‚`‚a‚b
-abc47 Xtags3.txt /‚`‚a‚b
-abc48 Xtags3.txt /‚`‚a‚b
-abc49 Xtags3.txt /‚`‚a‚b
-abc50 Xtags3.txt /‚`‚a‚b
-abc51 Xtags3.txt /‚`‚a‚b
-abc52 Xtags3.txt /‚`‚a‚b
-abc53 Xtags3.txt /‚`‚a‚b
-abc54 Xtags3.txt /‚`‚a‚b
-abc55 Xtags3.txt /‚`‚a‚b
-abc56 Xtags3.txt /‚`‚a‚b
-abc57 Xtags3.txt /‚`‚a‚b
-abc58 Xtags3.txt /‚`‚a‚b
-abc59 Xtags3.txt /‚`‚a‚b
-abc60 Xtags3.txt /‚`‚a‚b
-abc61 Xtags3.txt /‚`‚a‚b
-abc62 Xtags3.txt /‚`‚a‚b
-abc63 Xtags3.txt /‚`‚a‚b
-abc64 Xtags3.txt /‚`‚a‚b
-abc65 Xtags3.txt /‚`‚a‚b
-abc66 Xtags3.txt /‚`‚a‚b
-abc67 Xtags3.txt /‚`‚a‚b
-abc68 Xtags3.txt /‚`‚a‚b
-abc69 Xtags3.txt /‚`‚a‚b
-abc70 Xtags3.txt /‚`‚a‚b
-abc71 Xtags3.txt /‚`‚a‚b
-abc72 Xtags3.txt /‚`‚a‚b
-abc73 Xtags3.txt /‚`‚a‚b
-abc74 Xtags3.txt /‚`‚a‚b
-abc75 Xtags3.txt /‚`‚a‚b
-abc76 Xtags3.txt /‚`‚a‚b
-abc77 Xtags3.txt /‚`‚a‚b
-abc78 Xtags3.txt /‚`‚a‚b
-abc79 Xtags3.txt /‚`‚a‚b
-abc80 Xtags3.txt /‚`‚a‚b
-abc81 Xtags3.txt /‚`‚a‚b
-abc82 Xtags3.txt /‚`‚a‚b
-abc83 Xtags3.txt /‚`‚a‚b
-abc84 Xtags3.txt /‚`‚a‚b
-abc85 Xtags3.txt /‚`‚a‚b
-abc86 Xtags3.txt /‚`‚a‚b
-abc87 Xtags3.txt /‚`‚a‚b
-abc88 Xtags3.txt /‚`‚a‚b
-abc89 Xtags3.txt /‚`‚a‚b
-abc90 Xtags3.txt /‚`‚a‚b
-abc91 Xtags3.txt /‚`‚a‚b
-abc92 Xtags3.txt /‚`‚a‚b
-abc93 Xtags3.txt /‚`‚a‚b
-abc94 Xtags3.txt /‚`‚a‚b
-abc95 Xtags3.txt /‚`‚a‚b
-abc96 Xtags3.txt /‚`‚a‚b
-abc97 Xtags3.txt /‚`‚a‚b
-abc98 Xtags3.txt /‚`‚a‚b
-abc99 Xtags3.txt /‚`‚a‚b
-abc100 Xtags3.txt /‚`‚a‚b
diff --git a/src/nvim/testdir/test83.in b/src/nvim/testdir/test83.in
deleted file mode 100644
index d54b1bcddd..0000000000
--- a/src/nvim/testdir/test83.in
+++ /dev/null
@@ -1,75 +0,0 @@
-Tests for tag search with !_TAG_FILE_ENCODING.
-
-STARTTEST
-:so mbyte.vim
-:if !has('iconv') || iconv("\x82\x60", "cp932", "utf-8") != "\uff21"
-: e! test.ok
-: w! test.out
-: qa!
-:endif
-
-:/^text for tags1$/,/^text for tags1$/+1w! Xtags1.txt
-:/^text for tags2$/,/^text for tags2$/+1w! Xtags2.txt
-:/^text for tags3$/,/^text for tags3$/+1w! Xtags3.txt
-:/^tags1$/+1,/^tags1-end$/-1w! Xtags1
-
-ggdG
-
-:call setline('.', 'Results of test83')
-
-:" case1:
-:new
-:set tags=Xtags1
-:let v:errmsg = ''
-:tag abcdefghijklmnopqrs
-:if v:errmsg =~ 'E426:' || getline('.') != 'abcdefghijklmnopqrs'
-: close
-: put ='case1: failed'
-:else
-: close
-: put ='case1: ok'
-:endif
-
-:" case2:
-:new
-:set tags=test83-tags2
-:let v:errmsg = ''
-:tag /.BC
-:if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
-: close
-: put ='case2: failed'
-:else
-: close
-: put ='case2: ok'
-:endif
-
-:" case3:
-:new
-:set tags=test83-tags3
-:let v:errmsg = ''
-:tag abc50
-:if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
-: close
-: put ='case3: failed'
-:else
-: close
-: put ='case3: ok'
-:endif
-:close
-
-:wq! test.out
-ENDTEST
-
-text for tags1
-abcdefghijklmnopqrs
-
-text for tags2
-ABC
-
-text for tags3
-ABC
-
-tags1
-!_TAG_FILE_ENCODING utf-8 //
-abcdefghijklmnopqrs Xtags1.txt /abcdefghijklmnopqrs
-tags1-end
diff --git a/src/nvim/testdir/test83.ok b/src/nvim/testdir/test83.ok
deleted file mode 100644
index 61a1a04a18..0000000000
--- a/src/nvim/testdir/test83.ok
+++ /dev/null
@@ -1,4 +0,0 @@
-Results of test83
-case1: ok
-case2: ok
-case3: ok
diff --git a/src/nvim/version.c b/src/nvim/version.c
index acdee8c005..c73c7805a7 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -426,13 +426,13 @@ static int included_patches[] = {
707,
706,
// 705 NA
- // 704,
+ 704,
// 703 NA
702,
// 701 NA
// 700,
699,
- // 698,
+ 698,
// 697,
696,
695,
@@ -474,7 +474,7 @@ static int included_patches[] = {
659,
658,
// 657 NA
- // 656,
+ 656,
655,
654,
653,
diff --git a/src/nvim/window.c b/src/nvim/window.c
index f0c6cacdf0..853f8755c3 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -1044,19 +1044,21 @@ static void win_init_some(win_T *newp, win_T *oldp)
}
-/*
- * Check if "win" is a pointer to an existing window.
- */
-int win_valid(win_T *win)
+/// Check if "win" is a pointer to an existing window in the current tabpage.
+///
+/// @param win window to check
+bool win_valid(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (win == NULL)
- return FALSE;
+ if (win == NULL) {
+ return false;
+ }
+
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp == win) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/*
@@ -1732,21 +1734,18 @@ close_windows (
shell_new_rows();
}
-/*
- * Return TRUE if the current window is the only window that exists (ignoring
- * "aucmd_win").
- * Returns FALSE if there is a window, possibly in another tab page.
- */
-static int last_window(void)
+/// Check that current window is the last one.
+///
+/// @return true if the current window is the only window that exists, false if
+/// there is another, possibly in another tab page.
+static bool last_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return one_window() && first_tabpage->tp_next == NULL;
}
-/*
- * Return TRUE if there is only one window other than "aucmd_win" in the
- * current tab page.
- */
-bool one_window(void)
+/// Check that current tab page contains no more then one window other than
+/// "aucmd_win".
+bool one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
bool seen_one = false;
@@ -1761,14 +1760,20 @@ bool one_window(void)
return true;
}
-/*
- * Close the possibly last window in a tab page.
- * Returns TRUE when the window was closed already.
- */
-static int close_last_window_tabpage(win_T *win, int free_buf, tabpage_T *prev_curtab)
+/// Close the possibly last window in a tab page.
+///
+/// @param win window to close
+/// @param free_buf whether to free the window's current buffer
+/// @param prev_curtab previous tabpage that will be closed if "win" is the
+/// last window in the tabpage
+///
+/// @return true when the window was closed already.
+static bool close_last_window_tabpage(win_T *win, bool free_buf,
+ tabpage_T *prev_curtab)
+ FUNC_ATTR_NONNULL_ARG(1)
{
if (firstwin != lastwin) {
- return FALSE;
+ return false;
}
buf_T *old_curbuf = curbuf;
@@ -1809,14 +1814,15 @@ static int close_last_window_tabpage(win_T *win, int free_buf, tabpage_T *prev_c
terminal_resize(term, 0, 0);
}
- /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do
- * that now. */
- apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, FALSE, curbuf);
- apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
- apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
- if (old_curbuf != curbuf)
- apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
- return TRUE;
+ // Since goto_tabpage_tp above did not trigger *Enter autocommands, do
+ // that now.
+ apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, false, curbuf);
+ apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
+ apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
+ if (old_curbuf != curbuf) {
+ apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf);
+ }
+ return true;
}
/*
@@ -2301,20 +2307,22 @@ static win_T *frame2win(frame_T *frp)
return frp->fr_win;
}
-/*
- * Return TRUE if frame "frp" contains window "wp".
- */
-static int frame_has_win(frame_T *frp, win_T *wp)
+/// Check that the frame "frp" contains the window "wp".
+///
+/// @param frp frame
+/// @param wp window
+static bool frame_has_win(frame_T *frp, win_T *wp)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
- frame_T *p;
-
- if (frp->fr_layout == FR_LEAF)
+ if (frp->fr_layout == FR_LEAF) {
return frp->fr_win == wp;
-
- for (p = frp->fr_child; p != NULL; p = p->fr_next)
- if (frame_has_win(p, wp))
- return TRUE;
- return FALSE;
+ }
+ for (frame_T *p = frp->fr_child; p != NULL; p = p->fr_next) {
+ if (frame_has_win(p, wp)) {
+ return true;
+ }
+ }
+ return false;
}
/*
@@ -2406,58 +2414,72 @@ frame_new_height (
topfrp->fr_height = height;
}
-/*
- * Return TRUE if height of frame "frp" should not be changed because of
- * the 'winfixheight' option.
- */
-static int frame_fixed_height(frame_T *frp)
+/// Return true if height of frame "frp" should not be changed because of
+/// the 'winfixheight' option.
+///
+/// @param frp frame
+///
+/// @return true if the frame has a fixed height
+static bool frame_fixed_height(frame_T *frp)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- /* frame with one window: fixed height if 'winfixheight' set. */
- if (frp->fr_win != NULL)
+ // frame with one window: fixed height if 'winfixheight' set.
+ if (frp->fr_win != NULL) {
return frp->fr_win->w_p_wfh;
-
+ }
if (frp->fr_layout == FR_ROW) {
- /* The frame is fixed height if one of the frames in the row is fixed
- * height. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frame_fixed_height(frp))
- return TRUE;
- return FALSE;
+ // The frame is fixed height if one of the frames in the row is fixed
+ // height.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frame_fixed_height(frp)) {
+ return true;
+ }
+ }
+ return false;
}
- /* frp->fr_layout == FR_COL: The frame is fixed height if all of the
- * frames in the row are fixed height. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (!frame_fixed_height(frp))
- return FALSE;
- return TRUE;
+ // frp->fr_layout == FR_COL: The frame is fixed height if all of the
+ // frames in the row are fixed height.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (!frame_fixed_height(frp)) {
+ return false;
+ }
+ }
+ return true;
}
-/*
- * Return TRUE if width of frame "frp" should not be changed because of
- * the 'winfixwidth' option.
- */
-static int frame_fixed_width(frame_T *frp)
+/// Return true if width of frame "frp" should not be changed because of
+/// the 'winfixwidth' option.
+///
+/// @param frp frame
+///
+/// @return true if the frame has a fixed width
+static bool frame_fixed_width(frame_T *frp)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- /* frame with one window: fixed width if 'winfixwidth' set. */
- if (frp->fr_win != NULL)
+ // frame with one window: fixed width if 'winfixwidth' set.
+ if (frp->fr_win != NULL) {
return frp->fr_win->w_p_wfw;
-
+ }
if (frp->fr_layout == FR_COL) {
- /* The frame is fixed width if one of the frames in the row is fixed
- * width. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frame_fixed_width(frp))
- return TRUE;
- return FALSE;
+ // The frame is fixed width if one of the frames in the row is fixed
+ // width.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frame_fixed_width(frp)) {
+ return true;
+ }
+ }
+ return false;
}
- /* frp->fr_layout == FR_ROW: The frame is fixed width if all of the
- * frames in the row are fixed width. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (!frame_fixed_width(frp))
- return FALSE;
- return TRUE;
+ // frp->fr_layout == FR_ROW: The frame is fixed width if all of the
+ // frames in the row are fixed width.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (!frame_fixed_width(frp)) {
+ return false;
+ }
+ }
+ return true;
}
/*
@@ -3028,10 +3050,10 @@ int make_tabpages(int maxcount)
return count - todo;
}
-/*
- * Return TRUE when "tpc" points to a valid tab page.
- */
-bool valid_tabpage(tabpage_T *tpc)
+/// Check that tpc points to a valid tab page.
+///
+/// @param[in] tpc Tabpage to check.
+bool valid_tabpage(tabpage_T *tpc) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
FOR_ALL_TABS(tp) {
if (tp == tpc) {
@@ -5052,27 +5074,22 @@ int min_rows(void)
return total;
}
-/*
- * Return TRUE if there is only one window (in the current tab page), not
- * counting a help or preview window, unless it is the current window.
- * Does not count "aucmd_win".
- */
-int only_one_window(void)
+/// Check that there is only one window (and only one tab page), not counting a
+/// help or preview window, unless it is the current window. Does not count
+/// "aucmd_win".
+bool only_one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- int count = 0;
-
- /* If there is another tab page there always is another window. */
- if (first_tabpage->tp_next != NULL)
- return FALSE;
+ // If there is another tab page there always is another window.
+ if (first_tabpage->tp_next != NULL) {
+ return false;
+ }
+ int count = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer != NULL
&& (!((wp->w_buffer->b_help && !curbuf->b_help)
- || wp->w_p_pvw
- ) || wp == curwin)
- && wp != aucmd_win
- ) {
- ++count;
+ || wp->w_p_pvw) || wp == curwin) && wp != aucmd_win) {
+ count++;
}
}
return count <= 1;
@@ -5571,38 +5588,42 @@ matchitem_T *get_match(win_T *wp, int id)
}
-/*
- * Return TRUE if "topfrp" and its children are at the right height.
- */
-static int frame_check_height(frame_T *topfrp, int height)
+/// Check that "topfrp" and its children are at the right height.
+///
+/// @param topfrp top frame pointer
+/// @param height expected height
+static bool frame_check_height(frame_T *topfrp, int height)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- frame_T *frp;
-
- if (topfrp->fr_height != height)
- return FALSE;
-
- if (topfrp->fr_layout == FR_ROW)
- for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frp->fr_height != height)
- return FALSE;
-
- return TRUE;
+ if (topfrp->fr_height != height) {
+ return false;
+ }
+ if (topfrp->fr_layout == FR_ROW) {
+ for (frame_T *frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frp->fr_height != height) {
+ return false;
+ }
+ }
+ }
+ return true;
}
-/*
- * Return TRUE if "topfrp" and its children are at the right width.
- */
-static int frame_check_width(frame_T *topfrp, int width)
+/// Check that "topfrp" and its children are at the right width.
+///
+/// @param topfrp top frame pointer
+/// @param width expected width
+static bool frame_check_width(frame_T *topfrp, int width)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- frame_T *frp;
-
- if (topfrp->fr_width != width)
- return FALSE;
-
- if (topfrp->fr_layout == FR_COL)
- for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frp->fr_width != width)
- return FALSE;
-
- return TRUE;
+ if (topfrp->fr_width != width) {
+ return false;
+ }
+ if (topfrp->fr_layout == FR_COL) {
+ for (frame_T *frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frp->fr_width != width) {
+ return false;
+ }
+ }
+ }
+ return true;
}