Mercurial > vim
comparison src/undo.c @ 2394:a3aca345aafa vim73
Add the 'undoreload' option to be able to undo a file reload.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Sat, 24 Jul 2010 20:27:03 +0200 |
parents | 85b7dc8da5eb |
children | 8f6106dd3d12 |
comparison
equal
deleted
inserted
replaced
2393:210a5605e126 | 2394:a3aca345aafa |
---|---|
88 #include "vim.h" | 88 #include "vim.h" |
89 | 89 |
90 static void u_unch_branch __ARGS((u_header_T *uhp)); | 90 static void u_unch_branch __ARGS((u_header_T *uhp)); |
91 static u_entry_T *u_get_headentry __ARGS((void)); | 91 static u_entry_T *u_get_headentry __ARGS((void)); |
92 static void u_getbot __ARGS((void)); | 92 static void u_getbot __ARGS((void)); |
93 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T)); | |
94 static void u_doit __ARGS((int count)); | 93 static void u_doit __ARGS((int count)); |
95 static void u_undoredo __ARGS((int undo)); | 94 static void u_undoredo __ARGS((int undo)); |
96 static void u_undo_end __ARGS((int did_undo, int absolute)); | 95 static void u_undo_end __ARGS((int did_undo, int absolute)); |
97 static void u_add_time __ARGS((char_u *buf, size_t buflen, time_t tt)); | 96 static void u_add_time __ARGS((char_u *buf, size_t buflen, time_t tt)); |
98 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); | 97 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); |
248 return FALSE; /* rely on caller to do error messages */ | 247 return FALSE; /* rely on caller to do error messages */ |
249 | 248 |
250 if (top + 2 == bot) | 249 if (top + 2 == bot) |
251 u_saveline((linenr_T)(top + 1)); | 250 u_saveline((linenr_T)(top + 1)); |
252 | 251 |
253 return (u_savecommon(top, bot, (linenr_T)0)); | 252 return (u_savecommon(top, bot, (linenr_T)0, FALSE)); |
254 } | 253 } |
255 | 254 |
256 /* | 255 /* |
257 * Save the line "lnum" (used by ":s" and "~" command). | 256 * Save the line "lnum" (used by ":s" and "~" command). |
258 * The line is replaced, so the new bottom line is lnum + 1. | 257 * The line is replaced, so the new bottom line is lnum + 1. |
264 linenr_T lnum; | 263 linenr_T lnum; |
265 { | 264 { |
266 if (undo_off) | 265 if (undo_off) |
267 return OK; | 266 return OK; |
268 | 267 |
269 return (u_savecommon(lnum - 1, lnum + 1, lnum + 1)); | 268 return (u_savecommon(lnum - 1, lnum + 1, lnum + 1, FALSE)); |
270 } | 269 } |
271 | 270 |
272 /* | 271 /* |
273 * A new line is inserted before line "lnum" (used by :s command). | 272 * A new line is inserted before line "lnum" (used by :s command). |
274 * The line is inserted, so the new bottom line is lnum + 1. | 273 * The line is inserted, so the new bottom line is lnum + 1. |
280 linenr_T lnum; | 279 linenr_T lnum; |
281 { | 280 { |
282 if (undo_off) | 281 if (undo_off) |
283 return OK; | 282 return OK; |
284 | 283 |
285 return (u_savecommon(lnum - 1, lnum, lnum + 1)); | 284 return (u_savecommon(lnum - 1, lnum, lnum + 1, FALSE)); |
286 } | 285 } |
287 | 286 |
288 /* | 287 /* |
289 * Save the lines "lnum" - "lnum" + nlines (used by delete command). | 288 * Save the lines "lnum" - "lnum" + nlines (used by delete command). |
290 * The lines are deleted, so the new bottom line is lnum, unless the buffer | 289 * The lines are deleted, so the new bottom line is lnum, unless the buffer |
299 { | 298 { |
300 if (undo_off) | 299 if (undo_off) |
301 return OK; | 300 return OK; |
302 | 301 |
303 return (u_savecommon(lnum - 1, lnum + nlines, | 302 return (u_savecommon(lnum - 1, lnum + nlines, |
304 nlines == curbuf->b_ml.ml_line_count ? 2 : lnum)); | 303 nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, FALSE)); |
305 } | 304 } |
306 | 305 |
307 /* | 306 /* |
308 * Return TRUE when undo is allowed. Otherwise give an error message and | 307 * Return TRUE when undo is allowed. Otherwise give an error message and |
309 * return FALSE. | 308 * return FALSE. |
340 | 339 |
341 /* | 340 /* |
342 * Common code for various ways to save text before a change. | 341 * Common code for various ways to save text before a change. |
343 * "top" is the line above the first changed line. | 342 * "top" is the line above the first changed line. |
344 * "bot" is the line below the last changed line. | 343 * "bot" is the line below the last changed line. |
344 * "newbot" is the new bottom line. Use zero when not known. | |
345 * "reload" is TRUE when saving for a buffer reload. | |
345 * Careful: may trigger autocommands that reload the buffer. | 346 * Careful: may trigger autocommands that reload the buffer. |
346 * Returns FAIL when lines could not be saved, OK otherwise. | 347 * Returns FAIL when lines could not be saved, OK otherwise. |
347 */ | 348 */ |
348 static int | 349 int |
349 u_savecommon(top, bot, newbot) | 350 u_savecommon(top, bot, newbot, reload) |
350 linenr_T top, bot; | 351 linenr_T top, bot; |
351 linenr_T newbot; | 352 linenr_T newbot; |
353 int reload; | |
352 { | 354 { |
353 linenr_T lnum; | 355 linenr_T lnum; |
354 long i; | 356 long i; |
355 u_header_T *uhp; | 357 u_header_T *uhp; |
356 u_header_T *old_curhead; | 358 u_header_T *old_curhead; |
357 u_entry_T *uep; | 359 u_entry_T *uep; |
358 u_entry_T *prev_uep; | 360 u_entry_T *prev_uep; |
359 long size; | 361 long size; |
360 | 362 |
361 /* When making changes is not allowed return FAIL. It's a crude way to | 363 if (!reload) |
362 * make all change commands fail. */ | 364 { |
363 if (!undo_allowed()) | 365 /* When making changes is not allowed return FAIL. It's a crude way |
364 return FAIL; | 366 * to make all change commands fail. */ |
367 if (!undo_allowed()) | |
368 return FAIL; | |
369 | |
370 #ifdef FEAT_NETBEANS_INTG | |
371 /* | |
372 * Netbeans defines areas that cannot be modified. Bail out here when | |
373 * trying to change text in a guarded area. | |
374 */ | |
375 if (netbeans_active()) | |
376 { | |
377 if (netbeans_is_guarded(top, bot)) | |
378 { | |
379 EMSG(_(e_guarded)); | |
380 return FAIL; | |
381 } | |
382 if (curbuf->b_p_ro) | |
383 { | |
384 EMSG(_(e_nbreadonly)); | |
385 return FAIL; | |
386 } | |
387 } | |
388 #endif | |
389 | |
390 #ifdef FEAT_AUTOCMD | |
391 /* | |
392 * Saving text for undo means we are going to make a change. Give a | |
393 * warning for a read-only file before making the change, so that the | |
394 * FileChangedRO event can replace the buffer with a read-write version | |
395 * (e.g., obtained from a source control system). | |
396 */ | |
397 change_warning(0); | |
398 if (bot > curbuf->b_ml.ml_line_count + 1) | |
399 { | |
400 /* This happens when the FileChangedRO autocommand changes the | |
401 * file in a way it becomes shorter. */ | |
402 EMSG(_("E834: Line count changed unexpectedly")); | |
403 return FAIL; | |
404 } | |
405 #endif | |
406 } | |
365 | 407 |
366 #ifdef U_DEBUG | 408 #ifdef U_DEBUG |
367 u_check(FALSE); | 409 u_check(FALSE); |
368 #endif | |
369 #ifdef FEAT_NETBEANS_INTG | |
370 /* | |
371 * Netbeans defines areas that cannot be modified. Bail out here when | |
372 * trying to change text in a guarded area. | |
373 */ | |
374 if (netbeans_active()) | |
375 { | |
376 if (netbeans_is_guarded(top, bot)) | |
377 { | |
378 EMSG(_(e_guarded)); | |
379 return FAIL; | |
380 } | |
381 if (curbuf->b_p_ro) | |
382 { | |
383 EMSG(_(e_nbreadonly)); | |
384 return FAIL; | |
385 } | |
386 } | |
387 #endif | |
388 | |
389 #ifdef FEAT_AUTOCMD | |
390 /* | |
391 * Saving text for undo means we are going to make a change. Give a | |
392 * warning for a read-only file before making the change, so that the | |
393 * FileChangedRO event can replace the buffer with a read-write version | |
394 * (e.g., obtained from a source control system). | |
395 */ | |
396 change_warning(0); | |
397 if (bot > curbuf->b_ml.ml_line_count + 1) | |
398 { | |
399 /* This happens when the FileChangedRO autocommand changes the file in | |
400 * a way it becomes shorter. */ | |
401 EMSG(_("E834: Line count changed unexpectedly")); | |
402 return FAIL; | |
403 } | |
404 #endif | 410 #endif |
405 | 411 |
406 size = bot - top - 1; | 412 size = bot - top - 1; |
407 | 413 |
408 /* | 414 /* |
2903 curbuf->b_u_synced = FALSE; /* no entries, nothing to do */ | 2909 curbuf->b_u_synced = FALSE; /* no entries, nothing to do */ |
2904 } | 2910 } |
2905 } | 2911 } |
2906 | 2912 |
2907 /* | 2913 /* |
2908 * Called after writing the file and setting b_changed to FALSE. | 2914 * Called after writing or reloading the file and setting b_changed to FALSE. |
2909 * Now an undo means that the buffer is modified. | 2915 * Now an undo means that the buffer is modified. |
2910 */ | 2916 */ |
2911 void | 2917 void |
2912 u_unchanged(buf) | 2918 u_unchanged(buf) |
2913 buf_T *buf; | 2919 buf_T *buf; |
3195 return; | 3201 return; |
3196 } | 3202 } |
3197 | 3203 |
3198 /* first save the line for the 'u' command */ | 3204 /* first save the line for the 'u' command */ |
3199 if (u_savecommon(curbuf->b_u_line_lnum - 1, | 3205 if (u_savecommon(curbuf->b_u_line_lnum - 1, |
3200 curbuf->b_u_line_lnum + 1, (linenr_T)0) == FAIL) | 3206 curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) |
3201 return; | 3207 return; |
3202 oldp = u_save_line(curbuf->b_u_line_lnum); | 3208 oldp = u_save_line(curbuf->b_u_line_lnum); |
3203 if (oldp == NULL) | 3209 if (oldp == NULL) |
3204 { | 3210 { |
3205 do_outofmem_msg((long_u)0); | 3211 do_outofmem_msg((long_u)0); |