comparison src/undo.c @ 2189:cb94c42c0e1a v7.2.445

updated for version 7.2.445 Problem: Crash when using undo/redo and a FileChangedRO autocmd event that reloads the buffer. (Dominique Pelle) Solution: Do not allow autocommands while performing and undo or redo.
author Bram Moolenaar <bram@vim.org>
date Wed, 07 Jul 2010 18:20:28 +0200
parents f838615313cd
children 073ff46fe397
comparison
equal deleted inserted replaced
2187:dc8ee74574f8 2189:cb94c42c0e1a
183 /* Check the next header in this branch. */ 183 /* Check the next header in this branch. */
184 u_check_tree(uhp->uh_prev, uhp, NULL); 184 u_check_tree(uhp->uh_prev, uhp, NULL);
185 } 185 }
186 } 186 }
187 187
188 void 188 static void
189 u_check(int newhead_may_be_NULL) 189 u_check(int newhead_may_be_NULL)
190 { 190 {
191 seen_b_u_newhead = 0; 191 seen_b_u_newhead = 0;
192 seen_b_u_curhead = 0; 192 seen_b_u_curhead = 0;
193 header_count = 0; 193 header_count = 0;
318 } 318 }
319 319
320 return TRUE; 320 return TRUE;
321 } 321 }
322 322
323 /*
324 * Common code for various ways to save text before a change.
325 */
323 static int 326 static int
324 u_savecommon(top, bot, newbot) 327 u_savecommon(top, bot, newbot)
325 linenr_T top, bot; 328 linenr_T top, bot;
326 linenr_T newbot; 329 linenr_T newbot;
327 { 330 {
372 #endif 375 #endif
373 376
374 size = bot - top - 1; 377 size = bot - top - 1;
375 378
376 /* 379 /*
377 * if curbuf->b_u_synced == TRUE make a new header 380 * If curbuf->b_u_synced == TRUE make a new header.
378 */ 381 */
379 if (curbuf->b_u_synced) 382 if (curbuf->b_u_synced)
380 { 383 {
381 #ifdef FEAT_JUMPLIST 384 #ifdef FEAT_JUMPLIST
382 /* Need to create new entry in b_changelist. */ 385 /* Need to create new entry in b_changelist. */
707 u_oldcount = 0; 710 u_oldcount = 0;
708 if (curbuf->b_ml.ml_flags & ML_EMPTY) 711 if (curbuf->b_ml.ml_flags & ML_EMPTY)
709 u_oldcount = -1; 712 u_oldcount = -1;
710 while (count--) 713 while (count--)
711 { 714 {
715 /* Do the change warning now, so that it triggers FileChangedRO when
716 * needed. This may cause the file to be reloaded, that must happen
717 * before we do anything, because it may change curbuf->b_u_curhead
718 * and more. */
719 change_warning(0);
720
712 if (undo_undoes) 721 if (undo_undoes)
713 { 722 {
714 if (curbuf->b_u_curhead == NULL) /* first undo */ 723 if (curbuf->b_u_curhead == NULL) /* first undo */
715 curbuf->b_u_curhead = curbuf->b_u_newhead; 724 curbuf->b_u_curhead = curbuf->b_u_newhead;
716 else if (p_ul > 0) /* multi level undo */ 725 else if (p_ul > 0) /* multi level undo */
950 if (uhp != NULL) 959 if (uhp != NULL)
951 { 960 {
952 /* 961 /*
953 * First go up the tree as much as needed. 962 * First go up the tree as much as needed.
954 */ 963 */
955 for (;;) 964 while (!got_int)
956 { 965 {
966 /* Do the change warning now, for the same reason as above. */
967 change_warning(0);
968
957 uhp = curbuf->b_u_curhead; 969 uhp = curbuf->b_u_curhead;
958 if (uhp == NULL) 970 if (uhp == NULL)
959 uhp = curbuf->b_u_newhead; 971 uhp = curbuf->b_u_newhead;
960 else 972 else
961 uhp = uhp->uh_next; 973 uhp = uhp->uh_next;
968 } 980 }
969 981
970 /* 982 /*
971 * And now go down the tree (redo), branching off where needed. 983 * And now go down the tree (redo), branching off where needed.
972 */ 984 */
973 uhp = curbuf->b_u_curhead; 985 while (!got_int)
974 while (uhp != NULL) 986 {
975 { 987 /* Do the change warning now, for the same reason as above. */
988 change_warning(0);
989
990 uhp = curbuf->b_u_curhead;
991 if (uhp == NULL)
992 break;
993
976 /* Go back to the first branch with a mark. */ 994 /* Go back to the first branch with a mark. */
977 while (uhp->uh_alt_prev != NULL 995 while (uhp->uh_alt_prev != NULL
978 && uhp->uh_alt_prev->uh_walk == mark) 996 && uhp->uh_alt_prev->uh_walk == mark)
979 uhp = uhp->uh_alt_prev; 997 uhp = uhp->uh_alt_prev;
980 998
1068 visualinfo_T visualinfo; 1086 visualinfo_T visualinfo;
1069 #endif 1087 #endif
1070 int empty_buffer; /* buffer became empty */ 1088 int empty_buffer; /* buffer became empty */
1071 u_header_T *curhead = curbuf->b_u_curhead; 1089 u_header_T *curhead = curbuf->b_u_curhead;
1072 1090
1091 #ifdef FEAT_AUTOCMD
1092 /* Don't want autocommands using the undo structures here, they are
1093 * invalid till the end. */
1094 block_autocmds();
1095 #endif
1096
1073 #ifdef U_DEBUG 1097 #ifdef U_DEBUG
1074 u_check(FALSE); 1098 u_check(FALSE);
1075 #endif 1099 #endif
1076 old_flags = curhead->uh_flags; 1100 old_flags = curhead->uh_flags;
1077 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 1101 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
1097 if (bot == 0) 1121 if (bot == 0)
1098 bot = curbuf->b_ml.ml_line_count + 1; 1122 bot = curbuf->b_ml.ml_line_count + 1;
1099 if (top > curbuf->b_ml.ml_line_count || top >= bot 1123 if (top > curbuf->b_ml.ml_line_count || top >= bot
1100 || bot > curbuf->b_ml.ml_line_count + 1) 1124 || bot > curbuf->b_ml.ml_line_count + 1)
1101 { 1125 {
1126 #ifdef FEAT_AUTOCMD
1127 unblock_autocmds();
1128 #endif
1102 EMSG(_("E438: u_undo: line numbers wrong")); 1129 EMSG(_("E438: u_undo: line numbers wrong"));
1103 changed(); /* don't want UNCHANGED now */ 1130 changed(); /* don't want UNCHANGED now */
1104 return; 1131 return;
1105 } 1132 }
1106 1133
1302 --curbuf->b_u_seq_cur; 1329 --curbuf->b_u_seq_cur;
1303 1330
1304 /* The timestamp can be the same for multiple changes, just use the one of 1331 /* The timestamp can be the same for multiple changes, just use the one of
1305 * the undone/redone change. */ 1332 * the undone/redone change. */
1306 curbuf->b_u_seq_time = curhead->uh_time; 1333 curbuf->b_u_seq_time = curhead->uh_time;
1334
1335 #ifdef FEAT_AUTOCMD
1336 unblock_autocmds();
1337 #endif
1307 #ifdef U_DEBUG 1338 #ifdef U_DEBUG
1308 u_check(FALSE); 1339 u_check(FALSE);
1309 #endif 1340 #endif
1310 } 1341 }
1311 1342