To: vim_dev@googlegroups.com Subject: Patch 8.2.3609 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3609 Problem: Internal error when ModeChanged is triggered when v:event is already in use. Solution: Save and restore v:event if needed. Files: src/misc1.c, src/proto/misc1.pro, src/testdir/test_edit.vim, src/insexpand.c, src/structs.h, src/register.c *** ../vim-8.2.3608/src/misc1.c 2021-10-22 18:55:40.818752232 +0100 --- src/misc1.c 2021-11-17 15:51:07.694209752 +0000 *************** *** 2654,2671 **** return path_is_url(p); } /* * Fires a ModeChanged autocmd */ void trigger_modechanged() { ! #if defined(FEAT_EVAL) || defined(PROTO) dict_T *v_event; typval_T rettv; typval_T tv[2]; char_u *pat_pre; char_u *pat; if (!has_modechanged()) return; --- 2654,2705 ---- 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() { ! #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,2686 **** return; } ! v_event = get_vim_var_dict(VV_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); --- 2714,2720 ---- return; } ! 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,2701 **** STRCPY(last_mode, rettv.vval.v_string); vim_free(pat); ! dict_free_contents(v_event); ! hash_init(&v_event->dv_hashtab); vim_free(rettv.vval.v_string); #endif } --- 2728,2734 ---- STRCPY(last_mode, rettv.vval.v_string); vim_free(pat); ! restore_v_event(v_event, &save_v_event); vim_free(rettv.vval.v_string); #endif } *** ../vim-8.2.3608/src/proto/misc1.pro 2021-09-12 20:00:10.625837682 +0100 --- src/proto/misc1.pro 2021-11-17 15:48:35.634483031 +0000 *************** *** 47,51 **** --- 47,53 ---- char_u *get_isolated_shell_name(void); int path_is_url(char_u *p); 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); /* vim: set ft=c : */ *** ../vim-8.2.3608/src/testdir/test_edit.vim 2021-10-31 20:19:13.000618757 +0000 --- src/testdir/test_edit.vim 2021-11-17 15:34:07.987852757 +0000 *************** *** 2034,2039 **** --- 2034,2045 ---- unlet! g:i_to_any endfunc + func Test_recursive_ModeChanged() + au! ModeChanged * norm 0u + sil! norm  + au! + endfunc + " Test toggling of input method. See :help i_CTRL-^ func Test_edit_CTRL_hat() CheckFeature xim *** ../vim-8.2.3608/src/insexpand.c 2021-10-22 18:55:40.818752232 +0100 --- src/insexpand.c 2021-11-17 15:47:03.458626629 +0000 *************** *** 962,968 **** return (i >= 2); } ! #ifdef FEAT_EVAL /* * Allocate Dict for the completed item. * { word, abbr, menu, kind, info } --- 962,968 ---- return (i >= 2); } ! #if defined(FEAT_EVAL) || defined(PROTO) /* * Allocate Dict for the completed item. * { word, abbr, menu, kind, info } *************** *** 993,1009 **** dict_T *v_event; dict_T *item; static int recursive = FALSE; if (recursive) return; - v_event = get_vim_var_dict(VV_EVENT); if (cur < 0) item = dict_alloc(); else item = ins_compl_dict_alloc(compl_curr_match); if (item == NULL) return; dict_add_dict(v_event, "completed_item", item); pum_set_event_info(v_event); dict_set_items_ro(v_event); --- 993,1010 ---- dict_T *v_event; dict_T *item; static int recursive = FALSE; + save_v_event_T save_v_event; if (recursive) return; if (cur < 0) item = dict_alloc(); else item = ins_compl_dict_alloc(compl_curr_match); if (item == NULL) return; + v_event = get_v_event(&save_v_event); dict_add_dict(v_event, "completed_item", item); pum_set_event_info(v_event); dict_set_items_ro(v_event); *************** *** 1014,1021 **** textwinlock--; recursive = FALSE; ! dict_free_contents(v_event); ! hash_init(&v_event->dv_hashtab); } #endif --- 1015,1021 ---- textwinlock--; recursive = FALSE; ! restore_v_event(v_event, &save_v_event); } #endif *** ../vim-8.2.3608/src/structs.h 2021-10-23 13:32:27.227954893 +0100 --- src/structs.h 2021-11-17 15:43:48.598931019 +0000 *************** *** 4465,4467 **** --- 4465,4472 ---- #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; *** ../vim-8.2.3608/src/register.c 2021-11-16 12:50:42.128595270 +0000 --- src/register.c 2021-11-17 15:48:18.610509526 +0000 *************** *** 991,1007 **** void yank_do_autocmd(oparg_T *oap, yankreg_T *reg) { ! static int recursive = FALSE; ! dict_T *v_event; ! list_T *list; ! int n; ! char_u buf[NUMBUFLEN + 2]; ! long reglen = 0; if (recursive) return; ! v_event = get_vim_var_dict(VV_EVENT); list = list_alloc(); if (list == NULL) --- 991,1008 ---- void yank_do_autocmd(oparg_T *oap, yankreg_T *reg) { ! static int recursive = FALSE; ! dict_T *v_event; ! list_T *list; ! int n; ! char_u buf[NUMBUFLEN + 2]; ! long reglen = 0; ! save_v_event_T save_v_event; if (recursive) return; ! v_event = get_v_event(&save_v_event); list = list_alloc(); if (list == NULL) *************** *** 1045,1052 **** recursive = FALSE; // Empty the dictionary, v:event is still valid ! dict_free_contents(v_event); ! hash_init(&v_event->dv_hashtab); } #endif --- 1046,1052 ---- recursive = FALSE; // Empty the dictionary, v:event is still valid ! restore_v_event(v_event, &save_v_event); } #endif *** ../vim-8.2.3608/src/version.c 2021-11-17 14:01:10.470090290 +0000 --- src/version.c 2021-11-17 15:33:04.039956545 +0000 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 3609, /**/ -- Trees moving back and forth is what makes the wind blow. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///