@@ -279,6 +279,7 @@ static colnr_T get_nolist_virtcol(void);
279279#if defined(FEAT_EVAL )
280280static char_u * do_insert_char_pre (int c );
281281#endif
282+ static int ins_apply_autocmds (event_T event );
282283
283284static colnr_T Insstart_textlen ; /* length of line when insert started */
284285static colnr_T Insstart_blank_vcol ; /* vcol for first inserted blank */
@@ -411,7 +412,7 @@ edit(
411412 set_vim_var_string (VV_INSERTMODE , ptr , 1 );
412413 set_vim_var_string (VV_CHAR , NULL , -1 ); /* clear v:char */
413414#endif
414- apply_autocmds (EVENT_INSERTENTER , NULL , NULL , FALSE, curbuf );
415+ ins_apply_autocmds (EVENT_INSERTENTER );
415416
416417 /* Make sure the cursor didn't move. Do call check_cursor_col() in
417418 * case the text was modified. Since Insert mode was not started yet
@@ -1061,8 +1062,7 @@ edit(
10611062 if (ins_esc (& count , cmdchar , nomove ))
10621063 {
10631064 if (cmdchar != 'r' && cmdchar != 'v' )
1064- apply_autocmds (EVENT_INSERTLEAVE , NULL , NULL ,
1065- FALSE, curbuf );
1065+ ins_apply_autocmds (EVENT_INSERTLEAVE );
10661066 did_cursorhold = FALSE;
10671067 return (c == Ctrl_O );
10681068 }
@@ -1285,7 +1285,7 @@ edit(
12851285 break ;
12861286
12871287 case K_CURSORHOLD : /* Didn't type something for a while. */
1288- apply_autocmds (EVENT_CURSORHOLDI , NULL , NULL , FALSE, curbuf );
1288+ ins_apply_autocmds (EVENT_CURSORHOLDI );
12891289 did_cursorhold = TRUE;
12901290 break ;
12911291
@@ -1708,7 +1708,7 @@ ins_redraw(
17081708 /* Make sure curswant is correct, an autocommand may call
17091709 * getcurpos(). */
17101710 update_curswant ();
1711- apply_autocmds (EVENT_CURSORMOVEDI , NULL , NULL , FALSE, curbuf );
1711+ ins_apply_autocmds (EVENT_CURSORMOVEDI );
17121712 }
17131713# ifdef FEAT_CONCEAL
17141714 if (curwin -> w_p_cole > 0 )
@@ -1731,12 +1731,16 @@ ins_redraw(
17311731 )
17321732 {
17331733 aco_save_T aco ;
1734+ varnumber_T tick = CHANGEDTICK (curbuf );
17341735
17351736 // save and restore curwin and curbuf, in case the autocmd changes them
17361737 aucmd_prepbuf (& aco , curbuf );
17371738 apply_autocmds (EVENT_TEXTCHANGEDI , NULL , NULL , FALSE, curbuf );
17381739 aucmd_restbuf (& aco );
17391740 curbuf -> b_last_changedtick = CHANGEDTICK (curbuf );
1741+ if (tick != CHANGEDTICK (curbuf )) // see ins_apply_autocmds()
1742+ u_save (curwin -> w_cursor .lnum ,
1743+ (linenr_T )(curwin -> w_cursor .lnum + 1 ));
17401744 }
17411745
17421746#ifdef FEAT_INS_EXPAND
@@ -1748,12 +1752,16 @@ ins_redraw(
17481752 && pum_visible ())
17491753 {
17501754 aco_save_T aco ;
1755+ varnumber_T tick = CHANGEDTICK (curbuf );
17511756
17521757 // save and restore curwin and curbuf, in case the autocmd changes them
17531758 aucmd_prepbuf (& aco , curbuf );
17541759 apply_autocmds (EVENT_TEXTCHANGEDP , NULL , NULL , FALSE, curbuf );
17551760 aucmd_restbuf (& aco );
17561761 curbuf -> b_last_changedtick_pum = CHANGEDTICK (curbuf );
1762+ if (tick != CHANGEDTICK (curbuf )) // see ins_apply_autocmds()
1763+ u_save (curwin -> w_cursor .lnum ,
1764+ (linenr_T )(curwin -> w_cursor .lnum + 1 ));
17571765 }
17581766#endif
17591767
@@ -4127,13 +4135,13 @@ ins_compl_prep(int c)
41274135#endif
41284136 /* Trigger the CompleteDone event to give scripts a chance to act
41294137 * upon the completion. */
4130- apply_autocmds (EVENT_COMPLETEDONE , NULL , NULL , FALSE, curbuf );
4138+ ins_apply_autocmds (EVENT_COMPLETEDONE );
41314139 }
41324140 }
41334141 else if (ctrl_x_mode == CTRL_X_LOCAL_MSG )
41344142 /* Trigger the CompleteDone event to give scripts a chance to act
41354143 * upon the (possibly failed) completion. */
4136- apply_autocmds (EVENT_COMPLETEDONE , NULL , NULL , FALSE, curbuf );
4144+ ins_apply_autocmds (EVENT_COMPLETEDONE );
41374145
41384146 /* reset continue_* if we left expansion-mode, if we stay they'll be
41394147 * (re)set properly in ins_complete() */
@@ -4434,10 +4442,15 @@ ins_compl_get_exp(pos_T *ini)
44344442 ? (char_u * )"." : curbuf -> b_p_cpt ;
44354443 last_match_pos = first_match_pos = * ini ;
44364444 }
4445+ else if (ins_buf != curbuf && !buf_valid (ins_buf ))
4446+ ins_buf = curbuf ; // In case the buffer was wiped out.
44374447
44384448 compl_old_match = compl_curr_match ; /* remember the last current match */
44394449 pos = (compl_direction == FORWARD ) ? & last_match_pos : & first_match_pos ;
4440- /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */
4450+
4451+ /*
4452+ * For ^N/^P loop over all the flags/windows/buffers in 'complete'.
4453+ */
44414454 for (;;)
44424455 {
44434456 found_new_match = FAIL ;
@@ -8942,7 +8955,7 @@ ins_insert(int replaceState)
89428955 : replaceState == VREPLACE ? "v"
89438956 : "r" ), 1 );
89448957# endif
8945- apply_autocmds (EVENT_INSERTCHANGE , NULL , NULL , FALSE, curbuf );
8958+ ins_apply_autocmds (EVENT_INSERTCHANGE );
89468959 if (State & REPLACE_FLAG )
89478960 State = INSERT | (State & LANGMAP );
89488961 else
@@ -10755,7 +10768,7 @@ do_insert_char_pre(int c)
1075510768 set_vim_var_string (VV_CHAR , buf , -1 ); /* set v:char */
1075610769
1075710770 res = NULL ;
10758- if (apply_autocmds (EVENT_INSERTCHARPRE , NULL , NULL , FALSE, curbuf ))
10771+ if (ins_apply_autocmds (EVENT_INSERTCHARPRE ))
1075910772 {
1076010773 /* Get the value of v:char. It may be empty or more than one
1076110774 * character. Only use it when changed, otherwise continue with the
@@ -10770,3 +10783,22 @@ do_insert_char_pre(int c)
1077010783 return res ;
1077110784}
1077210785#endif
10786+
10787+ /*
10788+ * Trigger "event" and take care of fixing undo.
10789+ */
10790+ static int
10791+ ins_apply_autocmds (event_T event )
10792+ {
10793+ varnumber_T tick = CHANGEDTICK (curbuf );
10794+ int r ;
10795+
10796+ r = apply_autocmds (event , NULL , NULL , FALSE, curbuf );
10797+
10798+ // If u_savesub() was called then we are not prepared to start
10799+ // a new line. Call u_save() with no contents to fix that.
10800+ if (tick != CHANGEDTICK (curbuf ))
10801+ u_save (curwin -> w_cursor .lnum , (linenr_T )(curwin -> w_cursor .lnum + 1 ));
10802+
10803+ return r ;
10804+ }
0 commit comments