Mercurial > vim
comparison src/edit.c @ 14485:c71d65c3672f v8.1.0256
patch 8.1.0256: using setline() in TextChangedI splits undo
commit https://github.com/vim/vim/commit/9fa9506853516c82851baec643aa47458cb8b3bc
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Aug 8 22:08:32 2018 +0200
patch 8.1.0256: using setline() in TextChangedI splits undo
Problem: Using setline() in TextChangedI splits undo.
Solution: Use another solution for undo not working properly.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 08 Aug 2018 22:15:05 +0200 |
parents | 78d4375b6bb2 |
children | a9665096074b |
comparison
equal
deleted
inserted
replaced
14484:c7016941d02a | 14485:c71d65c3672f |
---|---|
277 #endif | 277 #endif |
278 static colnr_T get_nolist_virtcol(void); | 278 static colnr_T get_nolist_virtcol(void); |
279 #if defined(FEAT_EVAL) | 279 #if defined(FEAT_EVAL) |
280 static char_u *do_insert_char_pre(int c); | 280 static char_u *do_insert_char_pre(int c); |
281 #endif | 281 #endif |
282 static int ins_apply_autocmds(event_T event); | |
282 | 283 |
283 static colnr_T Insstart_textlen; /* length of line when insert started */ | 284 static colnr_T Insstart_textlen; /* length of line when insert started */ |
284 static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */ | 285 static colnr_T Insstart_blank_vcol; /* vcol for first inserted blank */ |
285 static int update_Insstart_orig = TRUE; /* set Insstart_orig to Insstart */ | 286 static int update_Insstart_orig = TRUE; /* set Insstart_orig to Insstart */ |
286 | 287 |
409 else | 410 else |
410 ptr = (char_u *)"i"; | 411 ptr = (char_u *)"i"; |
411 set_vim_var_string(VV_INSERTMODE, ptr, 1); | 412 set_vim_var_string(VV_INSERTMODE, ptr, 1); |
412 set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */ | 413 set_vim_var_string(VV_CHAR, NULL, -1); /* clear v:char */ |
413 #endif | 414 #endif |
414 apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf); | 415 ins_apply_autocmds(EVENT_INSERTENTER); |
415 | 416 |
416 /* Make sure the cursor didn't move. Do call check_cursor_col() in | 417 /* Make sure the cursor didn't move. Do call check_cursor_col() in |
417 * case the text was modified. Since Insert mode was not started yet | 418 * case the text was modified. Since Insert mode was not started yet |
418 * a call to check_cursor_col() may move the cursor, especially with | 419 * a call to check_cursor_col() may move the cursor, especially with |
419 * the "A" command, thus set State to avoid that. Also check that the | 420 * the "A" command, thus set State to avoid that. Also check that the |
1059 o_lnum = curwin->w_cursor.lnum; | 1060 o_lnum = curwin->w_cursor.lnum; |
1060 | 1061 |
1061 if (ins_esc(&count, cmdchar, nomove)) | 1062 if (ins_esc(&count, cmdchar, nomove)) |
1062 { | 1063 { |
1063 if (cmdchar != 'r' && cmdchar != 'v') | 1064 if (cmdchar != 'r' && cmdchar != 'v') |
1064 apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL, | 1065 ins_apply_autocmds(EVENT_INSERTLEAVE); |
1065 FALSE, curbuf); | |
1066 did_cursorhold = FALSE; | 1066 did_cursorhold = FALSE; |
1067 return (c == Ctrl_O); | 1067 return (c == Ctrl_O); |
1068 } | 1068 } |
1069 continue; | 1069 continue; |
1070 | 1070 |
1273 | 1273 |
1274 case K_IGNORE: /* Something mapped to nothing */ | 1274 case K_IGNORE: /* Something mapped to nothing */ |
1275 break; | 1275 break; |
1276 | 1276 |
1277 case K_CURSORHOLD: /* Didn't type something for a while. */ | 1277 case K_CURSORHOLD: /* Didn't type something for a while. */ |
1278 apply_autocmds(EVENT_CURSORHOLDI, NULL, NULL, FALSE, curbuf); | 1278 ins_apply_autocmds(EVENT_CURSORHOLDI); |
1279 did_cursorhold = TRUE; | 1279 did_cursorhold = TRUE; |
1280 break; | 1280 break; |
1281 | 1281 |
1282 #ifdef FEAT_GUI_W32 | 1282 #ifdef FEAT_GUI_W32 |
1283 /* On Win32 ignore <M-F4>, we get it when closing the window was | 1283 /* On Win32 ignore <M-F4>, we get it when closing the window was |
1696 if (has_cursormovedI()) | 1696 if (has_cursormovedI()) |
1697 { | 1697 { |
1698 /* Make sure curswant is correct, an autocommand may call | 1698 /* Make sure curswant is correct, an autocommand may call |
1699 * getcurpos(). */ | 1699 * getcurpos(). */ |
1700 update_curswant(); | 1700 update_curswant(); |
1701 apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf); | 1701 ins_apply_autocmds(EVENT_CURSORMOVEDI); |
1702 } | 1702 } |
1703 # ifdef FEAT_CONCEAL | 1703 # ifdef FEAT_CONCEAL |
1704 if (curwin->w_p_cole > 0) | 1704 if (curwin->w_p_cole > 0) |
1705 { | 1705 { |
1706 conceal_old_cursor_line = last_cursormoved.lnum; | 1706 conceal_old_cursor_line = last_cursormoved.lnum; |
1719 && !pum_visible() | 1719 && !pum_visible() |
1720 #endif | 1720 #endif |
1721 ) | 1721 ) |
1722 { | 1722 { |
1723 aco_save_T aco; | 1723 aco_save_T aco; |
1724 | 1724 varnumber_T tick = CHANGEDTICK(curbuf); |
1725 #ifdef FEAT_EVAL | |
1726 // Sync undo when the autocommand calls setline() or append(), so that | |
1727 // it can be undone separately. | |
1728 u_sync_once = 2; | |
1729 #endif | |
1730 | 1725 |
1731 // save and restore curwin and curbuf, in case the autocmd changes them | 1726 // save and restore curwin and curbuf, in case the autocmd changes them |
1732 aucmd_prepbuf(&aco, curbuf); | 1727 aucmd_prepbuf(&aco, curbuf); |
1733 apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); | 1728 apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); |
1734 aucmd_restbuf(&aco); | 1729 aucmd_restbuf(&aco); |
1735 curbuf->b_last_changedtick = CHANGEDTICK(curbuf); | 1730 curbuf->b_last_changedtick = CHANGEDTICK(curbuf); |
1736 | 1731 if (tick != CHANGEDTICK(curbuf)) // see ins_apply_autocmds() |
1737 #ifdef FEAT_EVAL | 1732 u_save(curwin->w_cursor.lnum, |
1738 if (u_sync_once == 1) | 1733 (linenr_T)(curwin->w_cursor.lnum + 1)); |
1739 ins_need_undo = TRUE; | |
1740 u_sync_once = 0; | |
1741 #endif | |
1742 } | 1734 } |
1743 | 1735 |
1744 #ifdef FEAT_INS_EXPAND | 1736 #ifdef FEAT_INS_EXPAND |
1745 /* Trigger TextChangedP if b_changedtick differs. When the popupmenu closes | 1737 /* Trigger TextChangedP if b_changedtick differs. When the popupmenu closes |
1746 * TextChangedI will need to trigger for backwards compatibility, thus use | 1738 * TextChangedI will need to trigger for backwards compatibility, thus use |
1748 if (ready && has_textchangedP() | 1740 if (ready && has_textchangedP() |
1749 && curbuf->b_last_changedtick_pum != CHANGEDTICK(curbuf) | 1741 && curbuf->b_last_changedtick_pum != CHANGEDTICK(curbuf) |
1750 && pum_visible()) | 1742 && pum_visible()) |
1751 { | 1743 { |
1752 aco_save_T aco; | 1744 aco_save_T aco; |
1745 varnumber_T tick = CHANGEDTICK(curbuf); | |
1753 | 1746 |
1754 // save and restore curwin and curbuf, in case the autocmd changes them | 1747 // save and restore curwin and curbuf, in case the autocmd changes them |
1755 aucmd_prepbuf(&aco, curbuf); | 1748 aucmd_prepbuf(&aco, curbuf); |
1756 apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf); | 1749 apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf); |
1757 aucmd_restbuf(&aco); | 1750 aucmd_restbuf(&aco); |
1758 curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf); | 1751 curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf); |
1752 if (tick != CHANGEDTICK(curbuf)) // see ins_apply_autocmds() | |
1753 u_save(curwin->w_cursor.lnum, | |
1754 (linenr_T)(curwin->w_cursor.lnum + 1)); | |
1759 } | 1755 } |
1760 #endif | 1756 #endif |
1761 | 1757 |
1762 if (must_redraw) | 1758 if (must_redraw) |
1763 update_screen(0); | 1759 update_screen(0); |
4122 if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) | 4118 if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0))) |
4123 do_c_expr_indent(); | 4119 do_c_expr_indent(); |
4124 #endif | 4120 #endif |
4125 /* Trigger the CompleteDone event to give scripts a chance to act | 4121 /* Trigger the CompleteDone event to give scripts a chance to act |
4126 * upon the completion. */ | 4122 * upon the completion. */ |
4127 apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf); | 4123 ins_apply_autocmds(EVENT_COMPLETEDONE); |
4128 } | 4124 } |
4129 } | 4125 } |
4130 else if (ctrl_x_mode == CTRL_X_LOCAL_MSG) | 4126 else if (ctrl_x_mode == CTRL_X_LOCAL_MSG) |
4131 /* Trigger the CompleteDone event to give scripts a chance to act | 4127 /* Trigger the CompleteDone event to give scripts a chance to act |
4132 * upon the (possibly failed) completion. */ | 4128 * upon the (possibly failed) completion. */ |
4133 apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf); | 4129 ins_apply_autocmds(EVENT_COMPLETEDONE); |
4134 | 4130 |
4135 /* reset continue_* if we left expansion-mode, if we stay they'll be | 4131 /* reset continue_* if we left expansion-mode, if we stay they'll be |
4136 * (re)set properly in ins_complete() */ | 4132 * (re)set properly in ins_complete() */ |
4137 if (!vim_is_ctrl_x_key(c)) | 4133 if (!vim_is_ctrl_x_key(c)) |
4138 { | 4134 { |
8942 set_vim_var_string(VV_INSERTMODE, | 8938 set_vim_var_string(VV_INSERTMODE, |
8943 (char_u *)((State & REPLACE_FLAG) ? "i" | 8939 (char_u *)((State & REPLACE_FLAG) ? "i" |
8944 : replaceState == VREPLACE ? "v" | 8940 : replaceState == VREPLACE ? "v" |
8945 : "r"), 1); | 8941 : "r"), 1); |
8946 # endif | 8942 # endif |
8947 apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf); | 8943 ins_apply_autocmds(EVENT_INSERTCHANGE); |
8948 if (State & REPLACE_FLAG) | 8944 if (State & REPLACE_FLAG) |
8949 State = INSERT | (State & LANGMAP); | 8945 State = INSERT | (State & LANGMAP); |
8950 else | 8946 else |
8951 State = replaceState | (State & LANGMAP); | 8947 State = replaceState | (State & LANGMAP); |
8952 AppendCharToRedobuff(K_INS); | 8948 AppendCharToRedobuff(K_INS); |
10736 /* Lock the text to avoid weird things from happening. */ | 10732 /* Lock the text to avoid weird things from happening. */ |
10737 ++textlock; | 10733 ++textlock; |
10738 set_vim_var_string(VV_CHAR, buf, -1); /* set v:char */ | 10734 set_vim_var_string(VV_CHAR, buf, -1); /* set v:char */ |
10739 | 10735 |
10740 res = NULL; | 10736 res = NULL; |
10741 if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf)) | 10737 if (ins_apply_autocmds(EVENT_INSERTCHARPRE)) |
10742 { | 10738 { |
10743 /* Get the value of v:char. It may be empty or more than one | 10739 /* Get the value of v:char. It may be empty or more than one |
10744 * character. Only use it when changed, otherwise continue with the | 10740 * character. Only use it when changed, otherwise continue with the |
10745 * original character to avoid breaking autoindent. */ | 10741 * original character to avoid breaking autoindent. */ |
10746 if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) | 10742 if (STRCMP(buf, get_vim_var_str(VV_CHAR)) != 0) |
10751 --textlock; | 10747 --textlock; |
10752 | 10748 |
10753 return res; | 10749 return res; |
10754 } | 10750 } |
10755 #endif | 10751 #endif |
10752 | |
10753 /* | |
10754 * Trigger "event" and take care of fixing undo. | |
10755 */ | |
10756 static int | |
10757 ins_apply_autocmds(event_T event) | |
10758 { | |
10759 varnumber_T tick = CHANGEDTICK(curbuf); | |
10760 int r; | |
10761 | |
10762 r = apply_autocmds(event, NULL, NULL, FALSE, curbuf); | |
10763 | |
10764 // If u_savesub() was called then we are not prepared to start | |
10765 // a new line. Call u_save() with no contents to fix that. | |
10766 if (tick != CHANGEDTICK(curbuf)) | |
10767 u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1)); | |
10768 | |
10769 return r; | |
10770 } |