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);