0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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)
This commit is contained in:
Bram Moolenaar 2017-02-17 16:31:35 +01:00
parent 226c534291
commit 79518e2ace
20 changed files with 200 additions and 178 deletions

View File

@ -2099,6 +2099,7 @@ test_arglist \
test_cdo \ test_cdo \
test_channel \ test_channel \
test_charsearch \ test_charsearch \
test_changedtick \
test_cmdline \ test_cmdline \
test_command_count \ test_command_count \
test_crypt \ test_crypt \

View File

@ -832,6 +832,7 @@ free_buffer(buf_T *buf)
free_buffer_stuff(buf, TRUE); free_buffer_stuff(buf, TRUE);
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
unref_var_dict(buf->b_vars); unref_var_dict(buf->b_vars);
buf->b_changedtick = &buf->b_ct_val;
#endif #endif
#ifdef FEAT_LUA #ifdef FEAT_LUA
lua_buffer_free(buf); lua_buffer_free(buf);
@ -872,6 +873,29 @@ free_buffer(buf_T *buf)
vim_free(buf); vim_free(buf);
} }
/*
* Initializes buf->b_changedtick.
*/
static void
init_changedtick(buf_T *buf)
{
#ifdef FEAT_EVAL
dictitem_T *di = dictitem_alloc((char_u *)"changedtick");
if (di != NULL)
{
di->di_flags |= DI_FLAGS_LOCK | DI_FLAGS_FIX | DI_FLAGS_RO;
di->di_tv.v_type = VAR_NUMBER;
di->di_tv.v_lock = VAR_FIXED;
di->di_tv.vval.v_number = 0;
dict_add(buf->b_vars, di);
buf->b_changedtick = &di->di_tv.vval.v_number;
}
else
#endif
buf->b_changedtick = &buf->b_ct_val;
}
/* /*
* Free stuff in the buffer for ":bdel" and when wiping out the buffer. * Free stuff in the buffer for ":bdel" and when wiping out the buffer.
*/ */
@ -889,8 +913,14 @@ free_buffer_stuff(
#endif #endif
} }
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
vars_clear(&buf->b_vars->dv_hashtab); /* free all internal variables */ {
hash_init(&buf->b_vars->dv_hashtab); varnumber_T tick = *buf->b_changedtick;
vars_clear(&buf->b_vars->dv_hashtab); /* free all buffer variables */
hash_init(&buf->b_vars->dv_hashtab);
init_changedtick(buf);
*buf->b_changedtick = tick;
}
#endif #endif
#ifdef FEAT_USR_CMDS #ifdef FEAT_USR_CMDS
uc_clear(&buf->b_ucmds); /* clear local user commands */ uc_clear(&buf->b_ucmds); /* clear local user commands */
@ -1979,6 +2009,7 @@ buflist_new(
} }
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE); init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
#endif #endif
init_changedtick(buf);
} }
if (ffname != NULL) if (ffname != NULL)

View File

@ -1668,7 +1668,7 @@ ins_redraw(
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
/* Trigger TextChangedI if b_changedtick differs. */ /* Trigger TextChangedI if b_changedtick differs. */
if (ready && has_textchangedI() if (ready && has_textchangedI()
&& last_changedtick != curbuf->b_changedtick && last_changedtick != *curbuf->b_changedtick
# ifdef FEAT_INS_EXPAND # ifdef FEAT_INS_EXPAND
&& !pum_visible() && !pum_visible()
# endif # endif
@ -1677,7 +1677,7 @@ ins_redraw(
if (last_changedtick_buf == curbuf) if (last_changedtick_buf == curbuf)
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
last_changedtick_buf = curbuf; last_changedtick_buf = curbuf;
last_changedtick = curbuf->b_changedtick; last_changedtick = *curbuf->b_changedtick;
} }
#endif #endif

View File

@ -1451,14 +1451,8 @@ list_glob_vars(int *first)
static void static void
list_buf_vars(int *first) list_buf_vars(int *first)
{ {
char_u numbuf[NUMBUFLEN];
list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:", list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
TRUE, first); TRUE, first);
sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
numbuf, first);
} }
/* /*
@ -1805,20 +1799,6 @@ ex_let_one(
return arg_end; return arg_end;
} }
/*
* If "arg" is equal to "b:changedtick" give an error and return TRUE.
*/
int
check_changedtick(char_u *arg)
{
if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
{
EMSG2(_(e_readonlyvar), arg);
return TRUE;
}
return FALSE;
}
/* /*
* Get an lval: variable, Dict item or List item that can be assigned a value * Get an lval: variable, Dict item or List item that can be assigned a value
* to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
@ -2208,32 +2188,29 @@ set_var_lval(
if (lp->ll_tv == NULL) if (lp->ll_tv == NULL)
{ {
if (!check_changedtick(lp->ll_name)) cc = *endp;
*endp = NUL;
if (op != NULL && *op != '=')
{ {
cc = *endp; typval_T tv;
*endp = NUL;
if (op != NULL && *op != '=')
{
typval_T tv;
/* handle +=, -= and .= */ /* handle +=, -= and .= */
di = NULL; di = NULL;
if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
&tv, &di, TRUE, FALSE) == OK) &tv, &di, TRUE, FALSE) == OK)
{ {
if ((di == NULL if ((di == NULL
|| (!var_check_ro(di->di_flags, lp->ll_name, FALSE) || (!var_check_ro(di->di_flags, lp->ll_name, FALSE)
&& !tv_check_lock(di->di_tv.v_lock, lp->ll_name, && !tv_check_lock(di->di_tv.v_lock, lp->ll_name,
FALSE))) FALSE)))
&& tv_op(&tv, rettv, op) == OK) && tv_op(&tv, rettv, op) == OK)
set_var(lp->ll_name, &tv, FALSE); set_var(lp->ll_name, &tv, FALSE);
clear_tv(&tv); clear_tv(&tv);
}
} }
else
set_var(lp->ll_name, rettv, copy);
*endp = cc;
} }
else
set_var(lp->ll_name, rettv, copy);
*endp = cc;
} }
else if (tv_check_lock(lp->ll_newkey == NULL else if (tv_check_lock(lp->ll_newkey == NULL
? lp->ll_tv->v_lock ? lp->ll_tv->v_lock
@ -2776,9 +2753,7 @@ do_unlet_var(
*name_end = NUL; *name_end = NUL;
/* Normal name or expanded name. */ /* Normal name or expanded name. */
if (check_changedtick(lp->ll_name)) if (do_unlet(lp->ll_name, forceit) == FAIL)
ret = FAIL;
else if (do_unlet(lp->ll_name, forceit) == FAIL)
ret = FAIL; ret = FAIL;
*name_end = cc; *name_end = cc;
} }
@ -2904,21 +2879,16 @@ do_lock_var(
*name_end = NUL; *name_end = NUL;
/* Normal name or expanded name. */ /* Normal name or expanded name. */
if (check_changedtick(lp->ll_name)) di = find_var(lp->ll_name, NULL, TRUE);
if (di == NULL)
ret = FAIL; ret = FAIL;
else else
{ {
di = find_var(lp->ll_name, NULL, TRUE); if (lock)
if (di == NULL) di->di_flags |= DI_FLAGS_LOCK;
ret = FAIL;
else else
{ di->di_flags &= ~DI_FLAGS_LOCK;
if (lock) item_lock(&di->di_tv, deep, lock);
di->di_flags |= DI_FLAGS_LOCK;
else
di->di_flags &= ~DI_FLAGS_LOCK;
item_lock(&di->di_tv, deep, lock);
}
} }
*name_end = cc; *name_end = cc;
} }
@ -3139,11 +3109,6 @@ get_user_var_name(expand_T *xp, int idx)
++hi; ++hi;
return cat_prefix_varname('b', hi->hi_key); return cat_prefix_varname('b', hi->hi_key);
} }
if (bdone == ht->ht_used)
{
++bdone;
return (char_u *)"b:changedtick";
}
/* w: variables */ /* w: variables */
ht = &curwin->w_vars->dv_hashtab; ht = &curwin->w_vars->dv_hashtab;
@ -6815,7 +6780,6 @@ get_var_tv(
{ {
int ret = OK; int ret = OK;
typval_T *tv = NULL; typval_T *tv = NULL;
typval_T atv;
dictitem_T *v; dictitem_T *v;
int cc; int cc;
@ -6823,28 +6787,15 @@ get_var_tv(
cc = name[len]; cc = name[len];
name[len] = NUL; name[len] = NUL;
/*
* Check for "b:changedtick".
*/
if (STRCMP(name, "b:changedtick") == 0)
{
atv.v_type = VAR_NUMBER;
atv.vval.v_number = curbuf->b_changedtick;
tv = &atv;
}
/* /*
* Check for user-defined variables. * Check for user-defined variables.
*/ */
else v = find_var(name, NULL, no_autoload);
if (v != NULL)
{ {
v = find_var(name, NULL, no_autoload); tv = &v->di_tv;
if (v != NULL) if (dip != NULL)
{ *dip = v;
tv = &v->di_tv;
if (dip != NULL)
*dip = v;
}
} }
if (tv == NULL) if (tv == NULL)

View File

@ -2539,7 +2539,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
linenr_T lnum = get_tv_lnum(argvars); linenr_T lnum = get_tv_lnum(argvars);
static linenr_T prev_lnum = 0; static linenr_T prev_lnum = 0;
static int changedtick = 0; static varnumber_T changedtick = 0;
static int fnum = 0; static int fnum = 0;
static int change_start = 0; static int change_start = 0;
static int change_end = 0; static int change_end = 0;
@ -2550,7 +2550,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
if (lnum < 0) /* ignore type error in {lnum} arg */ if (lnum < 0) /* ignore type error in {lnum} arg */
lnum = 0; lnum = 0;
if (lnum != prev_lnum if (lnum != prev_lnum
|| changedtick != curbuf->b_changedtick || changedtick != *curbuf->b_changedtick
|| fnum != curbuf->b_fnum) || fnum != curbuf->b_fnum)
{ {
/* New line, buffer, change: need to get the values. */ /* New line, buffer, change: need to get the values. */
@ -2572,7 +2572,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
else else
hlID = (hlf_T)0; hlID = (hlf_T)0;
prev_lnum = lnum; prev_lnum = lnum;
changedtick = curbuf->b_changedtick; changedtick = *curbuf->b_changedtick;
fnum = curbuf->b_fnum; fnum = curbuf->b_fnum;
} }
@ -3957,7 +3957,7 @@ get_buffer_info(buf_T *buf)
dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL); dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL);
dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL); dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL);
dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL); dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL);
dict_add_nr_str(dict, "changedtick", buf->b_changedtick, NULL); dict_add_nr_str(dict, "changedtick", *buf->b_changedtick, NULL);
dict_add_nr_str(dict, "hidden", dict_add_nr_str(dict, "hidden",
buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0, buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0,
NULL); NULL);
@ -4190,12 +4190,6 @@ f_getbufvar(typval_T *argvars, typval_T *rettv)
/* buffer-local-option */ /* buffer-local-option */
done = TRUE; done = TRUE;
} }
else if (STRCMP(varname, "changedtick") == 0)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = curbuf->b_changedtick;
done = TRUE;
}
else else
{ {
/* Look up the variable. */ /* Look up the variable. */
@ -6576,21 +6570,16 @@ f_islocked(typval_T *argvars, typval_T *rettv)
{ {
if (lv.ll_tv == NULL) if (lv.ll_tv == NULL)
{ {
if (check_changedtick(lv.ll_name)) di = find_var(lv.ll_name, NULL, TRUE);
rettv->vval.v_number = 1; /* always locked */ if (di != NULL)
else
{ {
di = find_var(lv.ll_name, NULL, TRUE); /* Consider a variable locked when:
if (di != NULL) * 1. the variable itself is locked
{ * 2. the value of the variable is locked.
/* Consider a variable locked when: * 3. the List or Dict value is locked.
* 1. the variable itself is locked */
* 2. the value of the variable is locked. rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
* 3. the List or Dict value is locked. || tv_islocked(&di->di_tv));
*/
rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
|| tv_islocked(&di->di_tv));
}
} }
} }
else if (lv.ll_range) else if (lv.ll_range)
@ -11551,8 +11540,8 @@ f_submatch(typval_T *argvars, typval_T *rettv)
return; return;
if (no < 0 || no >= NSUBEXP) if (no < 0 || no >= NSUBEXP)
{ {
EMSGN(_("E935: invalid submatch number: %d"), no); EMSGN(_("E935: invalid submatch number: %d"), no);
return; return;
} }
if (argvars[1].v_type != VAR_UNKNOWN) if (argvars[1].v_type != VAR_UNKNOWN)
retList = (int)get_tv_number_chk(&argvars[1], &error); retList = (int)get_tv_number_chk(&argvars[1], &error);

View File

@ -626,7 +626,7 @@ do_exmode(
int save_msg_scroll; int save_msg_scroll;
int prev_msg_row; int prev_msg_row;
linenr_T prev_line; linenr_T prev_line;
int changedtick; varnumber_T changedtick;
if (improved) if (improved)
exmode_active = EXMODE_VIM; exmode_active = EXMODE_VIM;
@ -660,7 +660,7 @@ do_exmode(
need_wait_return = FALSE; need_wait_return = FALSE;
ex_pressedreturn = FALSE; ex_pressedreturn = FALSE;
ex_no_reprint = FALSE; ex_no_reprint = FALSE;
changedtick = curbuf->b_changedtick; changedtick = *curbuf->b_changedtick;
prev_msg_row = msg_row; prev_msg_row = msg_row;
prev_line = curwin->w_cursor.lnum; prev_line = curwin->w_cursor.lnum;
if (improved) if (improved)
@ -673,7 +673,7 @@ do_exmode(
lines_left = Rows - 1; lines_left = Rows - 1;
if ((prev_line != curwin->w_cursor.lnum if ((prev_line != curwin->w_cursor.lnum
|| changedtick != curbuf->b_changedtick) && !ex_no_reprint) || changedtick != *curbuf->b_changedtick) && !ex_no_reprint)
{ {
if (curbuf->b_ml.ml_flags & ML_EMPTY) if (curbuf->b_ml.ml_flags & ML_EMPTY)
EMSG(_(e_emptybuf)); EMSG(_(e_emptybuf));

View File

@ -4926,9 +4926,9 @@ restore_backup:
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
/* buf->b_changedtick is always incremented in unchanged() but that /* buf->b_changedtick is always incremented in unchanged() but that
* should not trigger a TextChanged event. */ * should not trigger a TextChanged event. */
if (last_changedtick + 1 == buf->b_changedtick if (last_changedtick + 1 == *buf->b_changedtick
&& last_changedtick_buf == buf) && last_changedtick_buf == buf)
last_changedtick = buf->b_changedtick; last_changedtick = *buf->b_changedtick;
#endif #endif
u_unchanged(buf); u_unchanged(buf);
u_update_save_nr(buf); u_update_save_nr(buf);

View File

@ -1088,7 +1088,7 @@ EXTERN pos_T last_cursormoved /* for CursorMoved event */
= INIT_POS_T(0, 0, 0) = INIT_POS_T(0, 0, 0)
# endif # endif
; ;
EXTERN int last_changedtick INIT(= 0); /* for TextChanged event */ EXTERN varnumber_T last_changedtick INIT(= 0); /* for TextChanged event */
EXTERN buf_T *last_changedtick_buf INIT(= NULL); EXTERN buf_T *last_changedtick_buf INIT(= NULL);
#endif #endif

View File

@ -1164,13 +1164,13 @@ main_loop(
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
/* Trigger TextChanged if b_changedtick differs. */ /* Trigger TextChanged if b_changedtick differs. */
if (!finish_op && has_textchanged() if (!finish_op && has_textchanged()
&& last_changedtick != curbuf->b_changedtick) && last_changedtick != *curbuf->b_changedtick)
{ {
if (last_changedtick_buf == curbuf) if (last_changedtick_buf == curbuf)
apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL,
FALSE, curbuf); FALSE, curbuf);
last_changedtick_buf = curbuf; last_changedtick_buf = curbuf;
last_changedtick = curbuf->b_changedtick; last_changedtick = *curbuf->b_changedtick;
} }
#endif #endif
@ -1388,11 +1388,11 @@ getout(int exitval)
/* Autocmd must have close the buffer already, skip. */ /* Autocmd must have close the buffer already, skip. */
continue; continue;
buf = wp->w_buffer; buf = wp->w_buffer;
if (buf->b_changedtick != -1) if (buf->b_ct_val != -1)
{ {
apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname,
buf->b_fname, FALSE, buf); buf->b_fname, FALSE, buf);
buf->b_changedtick = -1; /* note that we did it already */ buf->b_ct_val = -1; /* note that we did it already */
/* start all over, autocommands may mess up the lists */ /* start all over, autocommands may mess up the lists */
next_tp = first_tabpage; next_tp = first_tabpage;
break; break;

View File

@ -1148,11 +1148,11 @@ ml_recover(void)
len = (int)STRLEN(fname); len = (int)STRLEN(fname);
if (len >= 4 && if (len >= 4 &&
#if defined(VMS) #if defined(VMS)
STRNICMP(fname + len - 4, "_s" , 2) STRNICMP(fname + len - 4, "_s", 2)
#else #else
STRNICMP(fname + len - 4, ".s" , 2) STRNICMP(fname + len - 4, ".s", 2)
#endif #endif
== 0 == 0
&& vim_strchr((char_u *)"UVWuvw", fname[len - 2]) != NULL && vim_strchr((char_u *)"UVWuvw", fname[len - 2]) != NULL
&& ASCII_ISALPHA(fname[len - 1])) && ASCII_ISALPHA(fname[len - 1]))
{ {
@ -1649,7 +1649,7 @@ ml_recover(void)
if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL))
{ {
changed_int(); changed_int();
++curbuf->b_changedtick; ++*curbuf->b_changedtick;
} }
} }
else else
@ -1663,7 +1663,7 @@ ml_recover(void)
if (i != 0) if (i != 0)
{ {
changed_int(); changed_int();
++curbuf->b_changedtick; ++*curbuf->b_changedtick;
break; break;
} }
} }

View File

@ -492,7 +492,7 @@ get_breakindent_win(
static int prev_indent = 0; /* cached indent value */ static int prev_indent = 0; /* cached indent value */
static long prev_ts = 0L; /* cached tabstop value */ static long prev_ts = 0L; /* cached tabstop value */
static char_u *prev_line = NULL; /* cached pointer to line */ static char_u *prev_line = NULL; /* cached pointer to line */
static int prev_tick = 0; /* changedtick of cached value */ static varnumber_T prev_tick = 0; /* changedtick of cached value */
int bri = 0; int bri = 0;
/* window width minus window margin space, i.e. what rests for text */ /* window width minus window margin space, i.e. what rests for text */
const int eff_wwidth = W_WIDTH(wp) const int eff_wwidth = W_WIDTH(wp)
@ -502,11 +502,11 @@ get_breakindent_win(
/* used cached indent, unless pointer or 'tabstop' changed */ /* used cached indent, unless pointer or 'tabstop' changed */
if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
|| prev_tick != wp->w_buffer->b_changedtick) || prev_tick != *wp->w_buffer->b_changedtick)
{ {
prev_line = line; prev_line = line;
prev_ts = wp->w_buffer->b_p_ts; prev_ts = wp->w_buffer->b_p_ts;
prev_tick = wp->w_buffer->b_changedtick; prev_tick = *wp->w_buffer->b_changedtick;
prev_indent = get_indent_str(line, prev_indent = get_indent_str(line,
(int)wp->w_buffer->b_p_ts, wp->w_p_list); (int)wp->w_buffer->b_p_ts, wp->w_p_list);
} }
@ -2768,7 +2768,7 @@ changed(void)
} }
changed_int(); changed_int();
} }
++curbuf->b_changedtick; ++*curbuf->b_changedtick;
} }
/* /*
@ -3195,7 +3195,7 @@ unchanged(
need_maketitle = TRUE; /* set window title later */ need_maketitle = TRUE; /* set window title later */
#endif #endif
} }
++buf->b_changedtick; ++*buf->b_changedtick;
#ifdef FEAT_NETBEANS_INTG #ifdef FEAT_NETBEANS_INTG
netbeans_unmodified(buf); netbeans_unmodified(buf);
#endif #endif

View File

@ -25,7 +25,6 @@ void *call_func_retlist(char_u *func, int argc, char_u **argv, int safe);
int eval_foldexpr(char_u *arg, int *cp); int eval_foldexpr(char_u *arg, int *cp);
void ex_let(exarg_T *eap); void ex_let(exarg_T *eap);
void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first); void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first);
int check_changedtick(char_u *arg);
char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags); char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
void clear_lval(lval_T *lp); void clear_lval(lval_T *lp);
void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip); void *eval_for_line(char_u *arg, int *errp, char_u **nextcmdp, int skip);

View File

@ -1916,7 +1916,9 @@ struct file_buffer
int b_changed; /* 'modified': Set to TRUE if something in the int b_changed; /* 'modified': Set to TRUE if something in the
file has been changed and not written out. */ file has been changed and not written out. */
int b_changedtick; /* incremented for each change, also for undo */ varnumber_T *b_changedtick; /* points into b:changedtick or b_ct_val;
incremented for each change, also for undo */
varnumber_T b_ct_val; /* fallback for b:changedtick */
int b_saving; /* Set to TRUE if we are in the middle of int b_saving; /* Set to TRUE if we are in the middle of
saving the buffer. */ saving the buffer. */

View File

@ -503,7 +503,7 @@ syntax_start(win_T *wp, linenr_T lnum)
linenr_T parsed_lnum; linenr_T parsed_lnum;
linenr_T first_stored; linenr_T first_stored;
int dist; int dist;
static int changedtick = 0; /* remember the last change ID */ static varnumber_T changedtick = 0; /* remember the last change ID */
#ifdef FEAT_CONCEAL #ifdef FEAT_CONCEAL
current_sub_char = NUL; current_sub_char = NUL;
@ -516,13 +516,13 @@ syntax_start(win_T *wp, linenr_T lnum)
*/ */
if (syn_block != wp->w_s if (syn_block != wp->w_s
|| syn_buf != wp->w_buffer || syn_buf != wp->w_buffer
|| changedtick != syn_buf->b_changedtick) || changedtick != *syn_buf->b_changedtick)
{ {
invalidate_current_state(); invalidate_current_state();
syn_buf = wp->w_buffer; syn_buf = wp->w_buffer;
syn_block = wp->w_s; syn_block = wp->w_s;
} }
changedtick = syn_buf->b_changedtick; changedtick = *syn_buf->b_changedtick;
syn_win = wp; syn_win = wp;
/* /*

View File

@ -1,4 +1,4 @@
Tests for getbufvar(), getwinvar(), gettabvar() and gettabwinvar(). Tests for getwinvar(), gettabvar() and gettabwinvar().
vim: set ft=vim : vim: set ft=vim :
STARTTEST STARTTEST
@ -10,34 +10,7 @@ STARTTEST
:let t:testvar='abcd' :let t:testvar='abcd'
:$put =string(gettabvar(1,'testvar')) :$put =string(gettabvar(1,'testvar'))
:$put =string(gettabvar(1,'testvar')) :$put =string(gettabvar(1,'testvar'))
:" Test for getbufvar()
:let b:var_num = '1234'
:let def_num = '5678'
:$put =string(getbufvar(1, 'var_num'))
:$put =string(getbufvar(1, 'var_num', def_num))
:$put =string(getbufvar(1, ''))
:$put =string(getbufvar(1, '', def_num))
:unlet b:var_num
:$put =string(getbufvar(1, 'var_num', def_num))
:$put =string(getbufvar(1, ''))
:$put =string(getbufvar(1, '', def_num))
:$put =string(getbufvar(9, ''))
:$put =string(getbufvar(9, '', def_num))
:unlet def_num
:$put =string(getbufvar(1, '&autoindent'))
:$put =string(getbufvar(1, '&autoindent', 1))
:" :"
:" Open new window with forced option values
:set fileformats=unix,dos
:new ++ff=dos ++bin ++enc=iso-8859-2
:let otherff = getbufvar(bufnr('%'), '&fileformat')
:let otherbin = getbufvar(bufnr('%'), '&bin')
:let otherfenc = getbufvar(bufnr('%'), '&fenc')
:close
:$put =otherff
:$put =string(otherbin)
:$put =otherfenc
:unlet otherff otherbin otherfenc
:" test for getwinvar() :" test for getwinvar()
:let w:var_str = "Dance" :let w:var_str = "Dance"
:let def_str = "Chance" :let def_str = "Chance"

View File

@ -1,20 +1,6 @@
start: start:
'abcd' 'abcd'
'abcd' 'abcd'
'1234'
'1234'
{'var_num': '1234'}
{'var_num': '1234'}
'5678'
{}
{}
''
'5678'
0
0
dos
1
iso-8859-2
'Dance' 'Dance'
'Dance' 'Dance'
{'var_str': 'Dance'} {'var_str': 'Dance'}

View File

@ -3,10 +3,11 @@
source test_assign.vim source test_assign.vim
source test_autocmd.vim source test_autocmd.vim
source test_changedtick.vim
source test_cursor_func.vim source test_cursor_func.vim
source test_delete.vim source test_delete.vim
source test_execute_func.vim
source test_ex_undo.vim source test_ex_undo.vim
source test_execute_func.vim
source test_expand.vim source test_expand.vim
source test_expr.vim source test_expr.vim
source test_expand_dllpath.vim source test_expand_dllpath.vim

View File

@ -0,0 +1,45 @@
" Tests for b:changedtick
func Test_changedtick_increments()
new
" New buffer has an empty line, tick starts at 2.
let expected = 2
call assert_equal(expected, b:changedtick)
call assert_equal(expected, b:['changedtick'])
call setline(1, 'hello')
let expected += 1
call assert_equal(expected, b:changedtick)
call assert_equal(expected, b:['changedtick'])
undo
" Somehow undo counts as two changes.
let expected += 2
call assert_equal(expected, b:changedtick)
call assert_equal(expected, b:['changedtick'])
bwipe!
endfunc
func Test_changedtick_dict_entry()
let d = b:
call assert_equal(b:changedtick, d['changedtick'])
endfunc
func Test_changedtick_bdel()
new
let bnr = bufnr('%')
let v = b:changedtick
bdel
" Delete counts as a change too.
call assert_equal(v + 1, getbufvar(bnr, 'changedtick'))
endfunc
func Test_changedtick_fixed()
call assert_fails('let b:changedtick = 4', 'E46')
call assert_fails('let b:["changedtick"] = 4', 'E46')
call assert_fails('unlet b:changedtick', 'E795')
call assert_fails('unlet b:["changedtick"]', 'E46')
let d = b:
call assert_fails('unlet d["changedtick"]', 'E46')
endfunc

View File

@ -424,3 +424,45 @@ func! Test_mode()
bwipe! bwipe!
iunmap <F2> iunmap <F2>
endfunc endfunc
func Test_getbufvar()
let bnr = bufnr('%')
let b:var_num = '1234'
let def_num = '5678'
call assert_equal('1234', getbufvar(bnr, 'var_num'))
call assert_equal('1234', getbufvar(bnr, 'var_num', def_num))
let bd = getbufvar(bnr, '')
call assert_equal('1234', bd['var_num'])
call assert_true(exists("bd['changedtick']"))
call assert_equal(2, len(bd))
let bd2 = getbufvar(bnr, '', def_num)
call assert_equal(bd, bd2)
unlet b:var_num
call assert_equal(def_num, getbufvar(bnr, 'var_num', def_num))
call assert_equal('', getbufvar(bnr, 'var_num'))
let bd = getbufvar(bnr, '')
call assert_equal(1, len(bd))
let bd = getbufvar(bnr, '',def_num)
call assert_equal(1, len(bd))
call assert_equal('', getbufvar(9, ''))
call assert_equal(def_num, getbufvar(9, '', def_num))
unlet def_num
call assert_equal(0, getbufvar(1, '&autoindent'))
call assert_equal(0, getbufvar(1, '&autoindent', 1))
" Open new window with forced option values
set fileformats=unix,dos
new ++ff=dos ++bin ++enc=iso-8859-2
call assert_equal('dos', getbufvar(bufnr('%'), '&fileformat'))
call assert_equal(1, getbufvar(bufnr('%'), '&bin'))
call assert_equal('iso-8859-2', getbufvar(bufnr('%'), '&fenc'))
close
set fileformats&
endfunc

View File

@ -764,6 +764,8 @@ 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 */
/**/
334,
/**/ /**/
333, 333,
/**/ /**/