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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20211117155225.297A31C656A%40moolenaar.net.

Raspunde prin e-mail lui