Skip to content

Commit 79518e2

Browse files
committed
patch 8.0.0334: can't access b:changedtick from a dict reference
Problem: Can't access b:changedtick from a dict reference. Solution: Make changedtick a member of the b: dict. (inspired by neovim #6112)
1 parent 226c534 commit 79518e2

File tree

20 files changed

+200
-178
lines changed

20 files changed

+200
-178
lines changed

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,6 +2099,7 @@ test_arglist \
20992099
test_cdo \
21002100
test_channel \
21012101
test_charsearch \
2102+
test_changedtick \
21022103
test_cmdline \
21032104
test_command_count \
21042105
test_crypt \

src/buffer.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ free_buffer(buf_T *buf)
832832
free_buffer_stuff(buf, TRUE);
833833
#ifdef FEAT_EVAL
834834
unref_var_dict(buf->b_vars);
835+
buf->b_changedtick = &buf->b_ct_val;
835836
#endif
836837
#ifdef FEAT_LUA
837838
lua_buffer_free(buf);
@@ -872,6 +873,29 @@ free_buffer(buf_T *buf)
872873
vim_free(buf);
873874
}
874875

876+
/*
877+
* Initializes buf->b_changedtick.
878+
*/
879+
static void
880+
init_changedtick(buf_T *buf)
881+
{
882+
#ifdef FEAT_EVAL
883+
dictitem_T *di = dictitem_alloc((char_u *)"changedtick");
884+
885+
if (di != NULL)
886+
{
887+
di->di_flags |= DI_FLAGS_LOCK | DI_FLAGS_FIX | DI_FLAGS_RO;
888+
di->di_tv.v_type = VAR_NUMBER;
889+
di->di_tv.v_lock = VAR_FIXED;
890+
di->di_tv.vval.v_number = 0;
891+
dict_add(buf->b_vars, di);
892+
buf->b_changedtick = &di->di_tv.vval.v_number;
893+
}
894+
else
895+
#endif
896+
buf->b_changedtick = &buf->b_ct_val;
897+
}
898+
875899
/*
876900
* Free stuff in the buffer for ":bdel" and when wiping out the buffer.
877901
*/
@@ -889,8 +913,14 @@ free_buffer_stuff(
889913
#endif
890914
}
891915
#ifdef FEAT_EVAL
892-
vars_clear(&buf->b_vars->dv_hashtab); /* free all internal variables */
893-
hash_init(&buf->b_vars->dv_hashtab);
916+
{
917+
varnumber_T tick = *buf->b_changedtick;
918+
919+
vars_clear(&buf->b_vars->dv_hashtab); /* free all buffer variables */
920+
hash_init(&buf->b_vars->dv_hashtab);
921+
init_changedtick(buf);
922+
*buf->b_changedtick = tick;
923+
}
894924
#endif
895925
#ifdef FEAT_USR_CMDS
896926
uc_clear(&buf->b_ucmds); /* clear local user commands */
@@ -1979,6 +2009,7 @@ buflist_new(
19792009
}
19802010
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
19812011
#endif
2012+
init_changedtick(buf);
19822013
}
19832014

19842015
if (ffname != NULL)

src/edit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,7 +1668,7 @@ ins_redraw(
16681668
#ifdef FEAT_AUTOCMD
16691669
/* Trigger TextChangedI if b_changedtick differs. */
16701670
if (ready && has_textchangedI()
1671-
&& last_changedtick != curbuf->b_changedtick
1671+
&& last_changedtick != *curbuf->b_changedtick
16721672
# ifdef FEAT_INS_EXPAND
16731673
&& !pum_visible()
16741674
# endif
@@ -1677,7 +1677,7 @@ ins_redraw(
16771677
if (last_changedtick_buf == curbuf)
16781678
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
16791679
last_changedtick_buf = curbuf;
1680-
last_changedtick = curbuf->b_changedtick;
1680+
last_changedtick = *curbuf->b_changedtick;
16811681
}
16821682
#endif
16831683

src/eval.c

Lines changed: 31 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,14 +1451,8 @@ list_glob_vars(int *first)
14511451
static void
14521452
list_buf_vars(int *first)
14531453
{
1454-
char_u numbuf[NUMBUFLEN];
1455-
14561454
list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
14571455
TRUE, first);
1458-
1459-
sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
1460-
list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
1461-
numbuf, first);
14621456
}
14631457

14641458
/*
@@ -1805,20 +1799,6 @@ ex_let_one(
18051799
return arg_end;
18061800
}
18071801

1808-
/*
1809-
* If "arg" is equal to "b:changedtick" give an error and return TRUE.
1810-
*/
1811-
int
1812-
check_changedtick(char_u *arg)
1813-
{
1814-
if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
1815-
{
1816-
EMSG2(_(e_readonlyvar), arg);
1817-
return TRUE;
1818-
}
1819-
return FALSE;
1820-
}
1821-
18221802
/*
18231803
* Get an lval: variable, Dict item or List item that can be assigned a value
18241804
* to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
@@ -2208,32 +2188,29 @@ set_var_lval(
22082188

22092189
if (lp->ll_tv == NULL)
22102190
{
2211-
if (!check_changedtick(lp->ll_name))
2191+
cc = *endp;
2192+
*endp = NUL;
2193+
if (op != NULL && *op != '=')
22122194
{
2213-
cc = *endp;
2214-
*endp = NUL;
2215-
if (op != NULL && *op != '=')
2216-
{
2217-
typval_T tv;
2195+
typval_T tv;
22182196

2219-
/* handle +=, -= and .= */
2220-
di = NULL;
2221-
if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
2222-
&tv, &di, TRUE, FALSE) == OK)
2223-
{
2224-
if ((di == NULL
2225-
|| (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
2226-
&& !tv_check_lock(di->di_tv.v_lock, lp->ll_name,
2227-
FALSE)))
2228-
&& tv_op(&tv, rettv, op) == OK)
2229-
set_var(lp->ll_name, &tv, FALSE);
2230-
clear_tv(&tv);
2231-
}
2197+
/* handle +=, -= and .= */
2198+
di = NULL;
2199+
if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
2200+
&tv, &di, TRUE, FALSE) == OK)
2201+
{
2202+
if ((di == NULL
2203+
|| (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
2204+
&& !tv_check_lock(di->di_tv.v_lock, lp->ll_name,
2205+
FALSE)))
2206+
&& tv_op(&tv, rettv, op) == OK)
2207+
set_var(lp->ll_name, &tv, FALSE);
2208+
clear_tv(&tv);
22322209
}
2233-
else
2234-
set_var(lp->ll_name, rettv, copy);
2235-
*endp = cc;
22362210
}
2211+
else
2212+
set_var(lp->ll_name, rettv, copy);
2213+
*endp = cc;
22372214
}
22382215
else if (tv_check_lock(lp->ll_newkey == NULL
22392216
? lp->ll_tv->v_lock
@@ -2776,9 +2753,7 @@ do_unlet_var(
27762753
*name_end = NUL;
27772754

27782755
/* Normal name or expanded name. */
2779-
if (check_changedtick(lp->ll_name))
2780-
ret = FAIL;
2781-
else if (do_unlet(lp->ll_name, forceit) == FAIL)
2756+
if (do_unlet(lp->ll_name, forceit) == FAIL)
27822757
ret = FAIL;
27832758
*name_end = cc;
27842759
}
@@ -2904,21 +2879,16 @@ do_lock_var(
29042879
*name_end = NUL;
29052880

29062881
/* Normal name or expanded name. */
2907-
if (check_changedtick(lp->ll_name))
2882+
di = find_var(lp->ll_name, NULL, TRUE);
2883+
if (di == NULL)
29082884
ret = FAIL;
29092885
else
29102886
{
2911-
di = find_var(lp->ll_name, NULL, TRUE);
2912-
if (di == NULL)
2913-
ret = FAIL;
2887+
if (lock)
2888+
di->di_flags |= DI_FLAGS_LOCK;
29142889
else
2915-
{
2916-
if (lock)
2917-
di->di_flags |= DI_FLAGS_LOCK;
2918-
else
2919-
di->di_flags &= ~DI_FLAGS_LOCK;
2920-
item_lock(&di->di_tv, deep, lock);
2921-
}
2890+
di->di_flags &= ~DI_FLAGS_LOCK;
2891+
item_lock(&di->di_tv, deep, lock);
29222892
}
29232893
*name_end = cc;
29242894
}
@@ -3139,11 +3109,6 @@ get_user_var_name(expand_T *xp, int idx)
31393109
++hi;
31403110
return cat_prefix_varname('b', hi->hi_key);
31413111
}
3142-
if (bdone == ht->ht_used)
3143-
{
3144-
++bdone;
3145-
return (char_u *)"b:changedtick";
3146-
}
31473112

31483113
/* w: variables */
31493114
ht = &curwin->w_vars->dv_hashtab;
@@ -6815,36 +6780,22 @@ get_var_tv(
68156780
{
68166781
int ret = OK;
68176782
typval_T *tv = NULL;
6818-
typval_T atv;
68196783
dictitem_T *v;
68206784
int cc;
68216785

68226786
/* truncate the name, so that we can use strcmp() */
68236787
cc = name[len];
68246788
name[len] = NUL;
68256789

6826-
/*
6827-
* Check for "b:changedtick".
6828-
*/
6829-
if (STRCMP(name, "b:changedtick") == 0)
6830-
{
6831-
atv.v_type = VAR_NUMBER;
6832-
atv.vval.v_number = curbuf->b_changedtick;
6833-
tv = &atv;
6834-
}
6835-
68366790
/*
68376791
* Check for user-defined variables.
68386792
*/
6839-
else
6793+
v = find_var(name, NULL, no_autoload);
6794+
if (v != NULL)
68406795
{
6841-
v = find_var(name, NULL, no_autoload);
6842-
if (v != NULL)
6843-
{
6844-
tv = &v->di_tv;
6845-
if (dip != NULL)
6846-
*dip = v;
6847-
}
6796+
tv = &v->di_tv;
6797+
if (dip != NULL)
6798+
*dip = v;
68486799
}
68496800

68506801
if (tv == NULL)

src/evalfunc.c

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,7 +2539,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
25392539
#ifdef FEAT_DIFF
25402540
linenr_T lnum = get_tv_lnum(argvars);
25412541
static linenr_T prev_lnum = 0;
2542-
static int changedtick = 0;
2542+
static varnumber_T changedtick = 0;
25432543
static int fnum = 0;
25442544
static int change_start = 0;
25452545
static int change_end = 0;
@@ -2550,7 +2550,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
25502550
if (lnum < 0) /* ignore type error in {lnum} arg */
25512551
lnum = 0;
25522552
if (lnum != prev_lnum
2553-
|| changedtick != curbuf->b_changedtick
2553+
|| changedtick != *curbuf->b_changedtick
25542554
|| fnum != curbuf->b_fnum)
25552555
{
25562556
/* New line, buffer, change: need to get the values. */
@@ -2572,7 +2572,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
25722572
else
25732573
hlID = (hlf_T)0;
25742574
prev_lnum = lnum;
2575-
changedtick = curbuf->b_changedtick;
2575+
changedtick = *curbuf->b_changedtick;
25762576
fnum = curbuf->b_fnum;
25772577
}
25782578

@@ -3957,7 +3957,7 @@ get_buffer_info(buf_T *buf)
39573957
dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL);
39583958
dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL);
39593959
dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL);
3960-
dict_add_nr_str(dict, "changedtick", buf->b_changedtick, NULL);
3960+
dict_add_nr_str(dict, "changedtick", *buf->b_changedtick, NULL);
39613961
dict_add_nr_str(dict, "hidden",
39623962
buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0,
39633963
NULL);
@@ -4190,12 +4190,6 @@ f_getbufvar(typval_T *argvars, typval_T *rettv)
41904190
/* buffer-local-option */
41914191
done = TRUE;
41924192
}
4193-
else if (STRCMP(varname, "changedtick") == 0)
4194-
{
4195-
rettv->v_type = VAR_NUMBER;
4196-
rettv->vval.v_number = curbuf->b_changedtick;
4197-
done = TRUE;
4198-
}
41994193
else
42004194
{
42014195
/* Look up the variable. */
@@ -6576,21 +6570,16 @@ f_islocked(typval_T *argvars, typval_T *rettv)
65766570
{
65776571
if (lv.ll_tv == NULL)
65786572
{
6579-
if (check_changedtick(lv.ll_name))
6580-
rettv->vval.v_number = 1; /* always locked */
6581-
else
6573+
di = find_var(lv.ll_name, NULL, TRUE);
6574+
if (di != NULL)
65826575
{
6583-
di = find_var(lv.ll_name, NULL, TRUE);
6584-
if (di != NULL)
6585-
{
6586-
/* Consider a variable locked when:
6587-
* 1. the variable itself is locked
6588-
* 2. the value of the variable is locked.
6589-
* 3. the List or Dict value is locked.
6590-
*/
6591-
rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
6592-
|| tv_islocked(&di->di_tv));
6593-
}
6576+
/* Consider a variable locked when:
6577+
* 1. the variable itself is locked
6578+
* 2. the value of the variable is locked.
6579+
* 3. the List or Dict value is locked.
6580+
*/
6581+
rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
6582+
|| tv_islocked(&di->di_tv));
65946583
}
65956584
}
65966585
else if (lv.ll_range)
@@ -11551,8 +11540,8 @@ f_submatch(typval_T *argvars, typval_T *rettv)
1155111540
return;
1155211541
if (no < 0 || no >= NSUBEXP)
1155311542
{
11554-
EMSGN(_("E935: invalid submatch number: %d"), no);
11555-
return;
11543+
EMSGN(_("E935: invalid submatch number: %d"), no);
11544+
return;
1155611545
}
1155711546
if (argvars[1].v_type != VAR_UNKNOWN)
1155811547
retList = (int)get_tv_number_chk(&argvars[1], &error);

src/ex_docmd.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ do_exmode(
626626
int save_msg_scroll;
627627
int prev_msg_row;
628628
linenr_T prev_line;
629-
int changedtick;
629+
varnumber_T changedtick;
630630

631631
if (improved)
632632
exmode_active = EXMODE_VIM;
@@ -660,7 +660,7 @@ do_exmode(
660660
need_wait_return = FALSE;
661661
ex_pressedreturn = FALSE;
662662
ex_no_reprint = FALSE;
663-
changedtick = curbuf->b_changedtick;
663+
changedtick = *curbuf->b_changedtick;
664664
prev_msg_row = msg_row;
665665
prev_line = curwin->w_cursor.lnum;
666666
if (improved)
@@ -673,7 +673,7 @@ do_exmode(
673673
lines_left = Rows - 1;
674674

675675
if ((prev_line != curwin->w_cursor.lnum
676-
|| changedtick != curbuf->b_changedtick) && !ex_no_reprint)
676+
|| changedtick != *curbuf->b_changedtick) && !ex_no_reprint)
677677
{
678678
if (curbuf->b_ml.ml_flags & ML_EMPTY)
679679
EMSG(_(e_emptybuf));

src/fileio.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4926,9 +4926,9 @@ buf_write(
49264926
#ifdef FEAT_AUTOCMD
49274927
/* buf->b_changedtick is always incremented in unchanged() but that
49284928
* should not trigger a TextChanged event. */
4929-
if (last_changedtick + 1 == buf->b_changedtick
4929+
if (last_changedtick + 1 == *buf->b_changedtick
49304930
&& last_changedtick_buf == buf)
4931-
last_changedtick = buf->b_changedtick;
4931+
last_changedtick = *buf->b_changedtick;
49324932
#endif
49334933
u_unchanged(buf);
49344934
u_update_save_nr(buf);

0 commit comments

Comments
 (0)