summaryrefslogtreecommitdiffstats
path: root/src/misc1.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-11-17 15:51:52 +0000
committerBram Moolenaar <Bram@vim.org>2021-11-17 15:51:52 +0000
commit3075a45592fe76f2febb6321632a23e352efe949 (patch)
tree03456a8d38fac32baca2c5157b264f2c759e55c4 /src/misc1.c
parent125ffd21f9601a90b845f1d50c24da0d3938bb59 (diff)
patch 8.2.3609: internal error when ModeChanged is triggered recursivelyv8.2.3609
Problem: Internal error when ModeChanged is triggered when v:event is already in use. Solution: Save and restore v:event if needed.
Diffstat (limited to 'src/misc1.c')
-rw-r--r--src/misc1.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/src/misc1.c b/src/misc1.c
index 58f515dffb..e35ba98f43 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -2654,18 +2654,52 @@ path_with_url(char_u *fname)
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
*/
void
trigger_modechanged()
{
-#if defined(FEAT_EVAL) || defined(PROTO)
+#ifdef FEAT_EVAL
dict_T *v_event;
typval_T rettv;
typval_T tv[2];
char_u *pat_pre;
char_u *pat;
+ save_v_event_T save_v_event;
if (!has_modechanged())
return;
@@ -2680,7 +2714,7 @@ trigger_modechanged()
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, "old_mode", last_mode);
dict_set_items_ro(v_event);
@@ -2694,8 +2728,7 @@ trigger_modechanged()
STRCPY(last_mode, rettv.vval.v_string);
vim_free(pat);
- dict_free_contents(v_event);
- hash_init(&v_event->dv_hashtab);
+ restore_v_event(v_event, &save_v_event);
vim_free(rettv.vval.v_string);
#endif
}