Mercurial > vim
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 } |