mirror of
https://github.com/vim/vim.git
synced 2025-08-22 19:27:53 -04:00
patch 8.2.3609: internal error when ModeChanged is triggered recursively
Problem: Internal error when ModeChanged is triggered when v:event is already in use. Solution: Save and restore v:event if needed.
This commit is contained in:
parent
125ffd21f9
commit
3075a45592
@ -962,7 +962,7 @@ pum_enough_matches(void)
|
|||||||
return (i >= 2);
|
return (i >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_EVAL
|
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||||
/*
|
/*
|
||||||
* Allocate Dict for the completed item.
|
* Allocate Dict for the completed item.
|
||||||
* { word, abbr, menu, kind, info }
|
* { word, abbr, menu, kind, info }
|
||||||
@ -993,17 +993,18 @@ trigger_complete_changed_event(int cur)
|
|||||||
dict_T *v_event;
|
dict_T *v_event;
|
||||||
dict_T *item;
|
dict_T *item;
|
||||||
static int recursive = FALSE;
|
static int recursive = FALSE;
|
||||||
|
save_v_event_T save_v_event;
|
||||||
|
|
||||||
if (recursive)
|
if (recursive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
v_event = get_vim_var_dict(VV_EVENT);
|
|
||||||
if (cur < 0)
|
if (cur < 0)
|
||||||
item = dict_alloc();
|
item = dict_alloc();
|
||||||
else
|
else
|
||||||
item = ins_compl_dict_alloc(compl_curr_match);
|
item = ins_compl_dict_alloc(compl_curr_match);
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
return;
|
return;
|
||||||
|
v_event = get_v_event(&save_v_event);
|
||||||
dict_add_dict(v_event, "completed_item", item);
|
dict_add_dict(v_event, "completed_item", item);
|
||||||
pum_set_event_info(v_event);
|
pum_set_event_info(v_event);
|
||||||
dict_set_items_ro(v_event);
|
dict_set_items_ro(v_event);
|
||||||
@ -1014,8 +1015,7 @@ trigger_complete_changed_event(int cur)
|
|||||||
textwinlock--;
|
textwinlock--;
|
||||||
recursive = FALSE;
|
recursive = FALSE;
|
||||||
|
|
||||||
dict_free_contents(v_event);
|
restore_v_event(v_event, &save_v_event);
|
||||||
hash_init(&v_event->dv_hashtab);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
41
src/misc1.c
41
src/misc1.c
@ -2654,18 +2654,52 @@ path_with_url(char_u *fname)
|
|||||||
return path_is_url(p);
|
return path_is_url(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||||
|
/*
|
||||||
|
* Return the dictionary of v:event.
|
||||||
|
* Save and clear the value in case it already has items.
|
||||||
|
*/
|
||||||
|
dict_T *
|
||||||
|
get_v_event(save_v_event_T *sve)
|
||||||
|
{
|
||||||
|
dict_T *v_event = get_vim_var_dict(VV_EVENT);
|
||||||
|
|
||||||
|
if (v_event->dv_hashtab.ht_used > 0)
|
||||||
|
{
|
||||||
|
// recursive use of v:event, save, make empty and restore later
|
||||||
|
sve->sve_did_save = TRUE;
|
||||||
|
sve->sve_hashtab = v_event->dv_hashtab;
|
||||||
|
hash_init(&v_event->dv_hashtab);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sve->sve_did_save = FALSE;
|
||||||
|
return v_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
restore_v_event(dict_T *v_event, save_v_event_T *sve)
|
||||||
|
{
|
||||||
|
dict_free_contents(v_event);
|
||||||
|
if (sve->sve_did_save)
|
||||||
|
v_event->dv_hashtab = sve->sve_hashtab;
|
||||||
|
else
|
||||||
|
hash_init(&v_event->dv_hashtab);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fires a ModeChanged autocmd
|
* Fires a ModeChanged autocmd
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
trigger_modechanged()
|
trigger_modechanged()
|
||||||
{
|
{
|
||||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
#ifdef FEAT_EVAL
|
||||||
dict_T *v_event;
|
dict_T *v_event;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
typval_T tv[2];
|
typval_T tv[2];
|
||||||
char_u *pat_pre;
|
char_u *pat_pre;
|
||||||
char_u *pat;
|
char_u *pat;
|
||||||
|
save_v_event_T save_v_event;
|
||||||
|
|
||||||
if (!has_modechanged())
|
if (!has_modechanged())
|
||||||
return;
|
return;
|
||||||
@ -2680,7 +2714,7 @@ trigger_modechanged()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v_event = get_vim_var_dict(VV_EVENT);
|
v_event = get_v_event(&save_v_event);
|
||||||
(void)dict_add_string(v_event, "new_mode", rettv.vval.v_string);
|
(void)dict_add_string(v_event, "new_mode", rettv.vval.v_string);
|
||||||
(void)dict_add_string(v_event, "old_mode", last_mode);
|
(void)dict_add_string(v_event, "old_mode", last_mode);
|
||||||
dict_set_items_ro(v_event);
|
dict_set_items_ro(v_event);
|
||||||
@ -2694,8 +2728,7 @@ trigger_modechanged()
|
|||||||
STRCPY(last_mode, rettv.vval.v_string);
|
STRCPY(last_mode, rettv.vval.v_string);
|
||||||
|
|
||||||
vim_free(pat);
|
vim_free(pat);
|
||||||
dict_free_contents(v_event);
|
restore_v_event(v_event, &save_v_event);
|
||||||
hash_init(&v_event->dv_hashtab);
|
|
||||||
vim_free(rettv.vval.v_string);
|
vim_free(rettv.vval.v_string);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -47,5 +47,7 @@ int goto_im(void);
|
|||||||
char_u *get_isolated_shell_name(void);
|
char_u *get_isolated_shell_name(void);
|
||||||
int path_is_url(char_u *p);
|
int path_is_url(char_u *p);
|
||||||
int path_with_url(char_u *fname);
|
int path_with_url(char_u *fname);
|
||||||
|
dict_T *get_v_event(save_v_event_T *sve);
|
||||||
|
void restore_v_event(dict_T *v_event, save_v_event_T *sve);
|
||||||
void trigger_modechanged(void);
|
void trigger_modechanged(void);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -991,17 +991,18 @@ shift_delete_registers()
|
|||||||
void
|
void
|
||||||
yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
||||||
{
|
{
|
||||||
static int recursive = FALSE;
|
static int recursive = FALSE;
|
||||||
dict_T *v_event;
|
dict_T *v_event;
|
||||||
list_T *list;
|
list_T *list;
|
||||||
int n;
|
int n;
|
||||||
char_u buf[NUMBUFLEN + 2];
|
char_u buf[NUMBUFLEN + 2];
|
||||||
long reglen = 0;
|
long reglen = 0;
|
||||||
|
save_v_event_T save_v_event;
|
||||||
|
|
||||||
if (recursive)
|
if (recursive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
v_event = get_vim_var_dict(VV_EVENT);
|
v_event = get_v_event(&save_v_event);
|
||||||
|
|
||||||
list = list_alloc();
|
list = list_alloc();
|
||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
@ -1045,8 +1046,7 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
|||||||
recursive = FALSE;
|
recursive = FALSE;
|
||||||
|
|
||||||
// Empty the dictionary, v:event is still valid
|
// Empty the dictionary, v:event is still valid
|
||||||
dict_free_contents(v_event);
|
restore_v_event(v_event, &save_v_event);
|
||||||
hash_init(&v_event->dv_hashtab);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4465,3 +4465,8 @@ typedef struct {
|
|||||||
|
|
||||||
#define WHERE_INIT {NULL, 0, 0}
|
#define WHERE_INIT {NULL, 0, 0}
|
||||||
|
|
||||||
|
// Struct passed to get_v_event() and restore_v_event().
|
||||||
|
typedef struct {
|
||||||
|
int sve_did_save;
|
||||||
|
hashtab_T sve_hashtab;
|
||||||
|
} save_v_event_T;
|
||||||
|
@ -2034,6 +2034,12 @@ func Test_mode_changes()
|
|||||||
unlet! g:i_to_any
|
unlet! g:i_to_any
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_recursive_ModeChanged()
|
||||||
|
au! ModeChanged * norm 0u
|
||||||
|
sil! norm
|
||||||
|
au!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" Test toggling of input method. See :help i_CTRL-^
|
" Test toggling of input method. See :help i_CTRL-^
|
||||||
func Test_edit_CTRL_hat()
|
func Test_edit_CTRL_hat()
|
||||||
CheckFeature xim
|
CheckFeature xim
|
||||||
|
@ -757,6 +757,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 */
|
||||||
|
/**/
|
||||||
|
3609,
|
||||||
/**/
|
/**/
|
||||||
3608,
|
3608,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user