comparison src/misc1.c @ 26155:f2392648af3e v8.2.3609

patch 8.2.3609: internal error when ModeChanged is triggered recursively Commit: https://github.com/vim/vim/commit/3075a45592fe76f2febb6321632a23e352efe949 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Nov 17 15:51:52 2021 +0000 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.
author Bram Moolenaar <Bram@vim.org>
date Wed, 17 Nov 2021 17:00:05 +0100
parents 6b39ab99e367
children 3f842f7b5278
comparison
equal deleted inserted replaced
26154:fa84cd94d8b6 26155:f2392648af3e
2652 2652
2653 // "://" or ":\\" must follow 2653 // "://" or ":\\" must follow
2654 return path_is_url(p); 2654 return path_is_url(p);
2655 } 2655 }
2656 2656
2657 #if defined(FEAT_EVAL) || defined(PROTO)
2658 /*
2659 * Return the dictionary of v:event.
2660 * Save and clear the value in case it already has items.
2661 */
2662 dict_T *
2663 get_v_event(save_v_event_T *sve)
2664 {
2665 dict_T *v_event = get_vim_var_dict(VV_EVENT);
2666
2667 if (v_event->dv_hashtab.ht_used > 0)
2668 {
2669 // recursive use of v:event, save, make empty and restore later
2670 sve->sve_did_save = TRUE;
2671 sve->sve_hashtab = v_event->dv_hashtab;
2672 hash_init(&v_event->dv_hashtab);
2673 }
2674 else
2675 sve->sve_did_save = FALSE;
2676 return v_event;
2677 }
2678
2679 void
2680 restore_v_event(dict_T *v_event, save_v_event_T *sve)
2681 {
2682 dict_free_contents(v_event);
2683 if (sve->sve_did_save)
2684 v_event->dv_hashtab = sve->sve_hashtab;
2685 else
2686 hash_init(&v_event->dv_hashtab);
2687 }
2688 #endif
2689
2657 /* 2690 /*
2658 * Fires a ModeChanged autocmd 2691 * Fires a ModeChanged autocmd
2659 */ 2692 */
2660 void 2693 void
2661 trigger_modechanged() 2694 trigger_modechanged()
2662 { 2695 {
2663 #if defined(FEAT_EVAL) || defined(PROTO) 2696 #ifdef FEAT_EVAL
2664 dict_T *v_event; 2697 dict_T *v_event;
2665 typval_T rettv; 2698 typval_T rettv;
2666 typval_T tv[2]; 2699 typval_T tv[2];
2667 char_u *pat_pre; 2700 char_u *pat_pre;
2668 char_u *pat; 2701 char_u *pat;
2702 save_v_event_T save_v_event;
2669 2703
2670 if (!has_modechanged()) 2704 if (!has_modechanged())
2671 return; 2705 return;
2672 2706
2673 tv[0].v_type = VAR_NUMBER; 2707 tv[0].v_type = VAR_NUMBER;
2678 { 2712 {
2679 vim_free(rettv.vval.v_string); 2713 vim_free(rettv.vval.v_string);
2680 return; 2714 return;
2681 } 2715 }
2682 2716
2683 v_event = get_vim_var_dict(VV_EVENT); 2717 v_event = get_v_event(&save_v_event);
2684 (void)dict_add_string(v_event, "new_mode", rettv.vval.v_string); 2718 (void)dict_add_string(v_event, "new_mode", rettv.vval.v_string);
2685 (void)dict_add_string(v_event, "old_mode", last_mode); 2719 (void)dict_add_string(v_event, "old_mode", last_mode);
2686 dict_set_items_ro(v_event); 2720 dict_set_items_ro(v_event);
2687 2721
2688 // concatenate modes in format "old_mode:new_mode" 2722 // concatenate modes in format "old_mode:new_mode"
2692 2726
2693 apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf); 2727 apply_autocmds(EVENT_MODECHANGED, pat, NULL, FALSE, curbuf);
2694 STRCPY(last_mode, rettv.vval.v_string); 2728 STRCPY(last_mode, rettv.vval.v_string);
2695 2729
2696 vim_free(pat); 2730 vim_free(pat);
2697 dict_free_contents(v_event); 2731 restore_v_event(v_event, &save_v_event);
2698 hash_init(&v_event->dv_hashtab);
2699 vim_free(rettv.vval.v_string); 2732 vim_free(rettv.vval.v_string);
2700 #endif 2733 #endif
2701 } 2734 }