1 /* vi:set ts=8 sts=4 sw=4: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * undo.c: multi level undo facility 12 * 13 * The saved lines are stored in a list of lists (one for each buffer): 14 * 15 * b_u_oldhead------------------------------------------------+ 16 * | 17 * V 18 * +--------------+ +--------------+ +--------------+ 19 * b_u_newhead--->| u_header | | u_header | | u_header | 20 * | uh_next------>| uh_next------>| uh_next---->NULL 21 * NULL<--------uh_prev |<---------uh_prev |<---------uh_prev | 22 * | uh_entry | | uh_entry | | uh_entry | 23 * +--------|-----+ +--------|-----+ +--------|-----+ 24 * | | | 25 * V V V 26 * +--------------+ +--------------+ +--------------+ 27 * | u_entry | | u_entry | | u_entry | 28 * | ue_next | | ue_next | | ue_next | 29 * +--------|-----+ +--------|-----+ +--------|-----+ 30 * | | | 31 * V V V 32 * +--------------+ NULL NULL 33 * | u_entry | 34 * | ue_next | 35 * +--------|-----+ 36 * | 37 * V 38 * etc. 39 * 40 * Each u_entry list contains the information for one undo or redo. 41 * curbuf->b_u_curhead points to the header of the last undo (the next redo), 42 * or is NULL if nothing has been undone (end of the branch). 43 * 44 * For keeping alternate undo/redo branches the uh_alt field is used. Thus at 45 * each point in the list a branch may appear for an alternate to redo. The 46 * uh_seq field is numbered sequentially to be able to find a newer or older 47 * branch. 48 * 49 * +---------------+ +---------------+ 50 * b_u_oldhead --->| u_header | | u_header | 51 * | uh_alt_next ---->| uh_alt_next ----> NULL 52 * NULL <----- uh_alt_prev |<------ uh_alt_prev | 53 * | uh_prev | | uh_prev | 54 * +-----|---------+ +-----|---------+ 55 * | | 56 * V V 57 * +---------------+ +---------------+ 58 * | u_header | | u_header | 59 * | uh_alt_next | | uh_alt_next | 60 * b_u_newhead --->| uh_alt_prev | | uh_alt_prev | 61 * | uh_prev | | uh_prev | 62 * +-----|---------+ +-----|---------+ 63 * | | 64 * V V 65 * NULL +---------------+ +---------------+ 66 * | u_header | | u_header | 67 * | uh_alt_next ---->| uh_alt_next | 68 * | uh_alt_prev |<------ uh_alt_prev | 69 * | uh_prev | | uh_prev | 70 * +-----|---------+ +-----|---------+ 71 * | | 72 * etc. etc. 73 * 74 * 75 * All data is allocated and will all be freed when the buffer is unloaded. 76 */ 77 78 /* Uncomment the next line for including the u_check() function. This warns 79 * for errors in the debug information. */ 80 /* #define U_DEBUG 1 */ 81 #define UH_MAGIC 0x18dade /* value for uh_magic when in use */ 82 #define UE_MAGIC 0xabc123 /* value for ue_magic when in use */ 83 84 #include "vim.h" 85 86 static void u_unch_branch __ARGS((u_header_T *uhp)); 87 static u_entry_T *u_get_headentry __ARGS((void)); 88 static void u_getbot __ARGS((void)); 89 static void u_doit __ARGS((int count)); 90 static void u_undoredo __ARGS((int undo)); 91 static void u_undo_end __ARGS((int did_undo, int absolute)); 92 static void u_add_time __ARGS((char_u *buf, size_t buflen, time_t tt)); 93 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); 94 static void u_freebranch __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); 95 static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); 96 static void u_freeentry __ARGS((u_entry_T *, long)); 97 #ifdef FEAT_PERSISTENT_UNDO 98 static void corruption_error __ARGS((char *mesg, char_u *file_name)); 99 static void u_free_uhp __ARGS((u_header_T *uhp)); 100 static size_t fwrite_crypt __ARGS((buf_T *buf UNUSED, char_u *ptr, size_t len, FILE *fp)); 101 static char_u *read_string_decrypt __ARGS((buf_T *buf UNUSED, FILE *fd, int len)); 102 static int serialize_header __ARGS((FILE *fp, buf_T *buf, char_u *hash)); 103 static int serialize_uhp __ARGS((FILE *fp, buf_T *buf, u_header_T *uhp)); 104 static u_header_T *unserialize_uhp __ARGS((FILE *fp, char_u *file_name)); 105 static int serialize_uep __ARGS((FILE *fp, buf_T *buf, u_entry_T *uep)); 106 static u_entry_T *unserialize_uep __ARGS((FILE *fp, int *error, char_u *file_name)); 107 static void serialize_pos __ARGS((pos_T pos, FILE *fp)); 108 static void unserialize_pos __ARGS((pos_T *pos, FILE *fp)); 109 static void serialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp)); 110 static void unserialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp)); 111 static void put_header_ptr __ARGS((FILE *fp, u_header_T *uhp)); 112 #endif 113 114 #define U_ALLOC_LINE(size) lalloc((long_u)(size), FALSE) 115 static char_u *u_save_line __ARGS((linenr_T)); 116 117 /* used in undo_end() to report number of added and deleted lines */ 118 static long u_newcount, u_oldcount; 119 120 /* 121 * When 'u' flag included in 'cpoptions', we behave like vi. Need to remember 122 * the action that "u" should do. 123 */ 124 static int undo_undoes = FALSE; 125 126 static int lastmark = 0; 127 128 #if defined(U_DEBUG) || defined(PROTO) 129 /* 130 * Check the undo structures for being valid. Print a warning when something 131 * looks wrong. 132 */ 133 static int seen_b_u_curhead; 134 static int seen_b_u_newhead; 135 static int header_count; 136 137 static void 138 u_check_tree(u_header_T *uhp, 139 u_header_T *exp_uh_next, 140 u_header_T *exp_uh_alt_prev) 141 { 142 u_entry_T *uep; 143 144 if (uhp == NULL) 145 return; 146 ++header_count; 147 if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1) 148 { 149 EMSG("b_u_curhead found twice (looping?)"); 150 return; 151 } 152 if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1) 153 { 154 EMSG("b_u_newhead found twice (looping?)"); 155 return; 156 } 157 158 if (uhp->uh_magic != UH_MAGIC) 159 EMSG("uh_magic wrong (may be using freed memory)"); 160 else 161 { 162 /* Check pointers back are correct. */ 163 if (uhp->uh_next.ptr != exp_uh_next) 164 { 165 EMSG("uh_next wrong"); 166 smsg((char_u *)"expected: 0x%x, actual: 0x%x", 167 exp_uh_next, uhp->uh_next.ptr); 168 } 169 if (uhp->uh_alt_prev.ptr != exp_uh_alt_prev) 170 { 171 EMSG("uh_alt_prev wrong"); 172 smsg((char_u *)"expected: 0x%x, actual: 0x%x", 173 exp_uh_alt_prev, uhp->uh_alt_prev.ptr); 174 } 175 176 /* Check the undo tree at this header. */ 177 for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next) 178 { 179 if (uep->ue_magic != UE_MAGIC) 180 { 181 EMSG("ue_magic wrong (may be using freed memory)"); 182 break; 183 } 184 } 185 186 /* Check the next alt tree. */ 187 u_check_tree(uhp->uh_alt_next.ptr, uhp->uh_next.ptr, uhp); 188 189 /* Check the next header in this branch. */ 190 u_check_tree(uhp->uh_prev.ptr, uhp, NULL); 191 } 192 } 193 194 static void 195 u_check(int newhead_may_be_NULL) 196 { 197 seen_b_u_newhead = 0; 198 seen_b_u_curhead = 0; 199 header_count = 0; 200 201 u_check_tree(curbuf->b_u_oldhead, NULL, NULL); 202 203 if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL 204 && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL)) 205 EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead); 206 if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0) 207 EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead); 208 if (header_count != curbuf->b_u_numhead) 209 { 210 EMSG("b_u_numhead invalid"); 211 smsg((char_u *)"expected: %ld, actual: %ld", 212 (long)header_count, (long)curbuf->b_u_numhead); 213 } 214 } 215 #endif 216 217 /* 218 * Save the current line for both the "u" and "U" command. 219 * Returns OK or FAIL. 220 */ 221 int 222 u_save_cursor() 223 { 224 return (u_save((linenr_T)(curwin->w_cursor.lnum - 1), 225 (linenr_T)(curwin->w_cursor.lnum + 1))); 226 } 227 228 /* 229 * Save the lines between "top" and "bot" for both the "u" and "U" command. 230 * "top" may be 0 and bot may be curbuf->b_ml.ml_line_count + 1. 231 * Careful: may trigger autocommands that reload the buffer. 232 * Returns FAIL when lines could not be saved, OK otherwise. 233 */ 234 int 235 u_save(top, bot) 236 linenr_T top, bot; 237 { 238 if (undo_off) 239 return OK; 240 241 if (top > curbuf->b_ml.ml_line_count || 242 top >= bot || bot > curbuf->b_ml.ml_line_count + 1) 243 return FALSE; /* rely on caller to do error messages */ 244 245 if (top + 2 == bot) 246 u_saveline((linenr_T)(top + 1)); 247 248 return (u_savecommon(top, bot, (linenr_T)0, FALSE)); 249 } 250 251 /* 252 * Save the line "lnum" (used by ":s" and "~" command). 253 * The line is replaced, so the new bottom line is lnum + 1. 254 * Careful: may trigger autocommands that reload the buffer. 255 * Returns FAIL when lines could not be saved, OK otherwise. 256 */ 257 int 258 u_savesub(lnum) 259 linenr_T lnum; 260 { 261 if (undo_off) 262 return OK; 263 264 return (u_savecommon(lnum - 1, lnum + 1, lnum + 1, FALSE)); 265 } 266 267 /* 268 * A new line is inserted before line "lnum" (used by :s command). 269 * The line is inserted, so the new bottom line is lnum + 1. 270 * Careful: may trigger autocommands that reload the buffer. 271 * Returns FAIL when lines could not be saved, OK otherwise. 272 */ 273 int 274 u_inssub(lnum) 275 linenr_T lnum; 276 { 277 if (undo_off) 278 return OK; 279 280 return (u_savecommon(lnum - 1, lnum, lnum + 1, FALSE)); 281 } 282 283 /* 284 * Save the lines "lnum" - "lnum" + nlines (used by delete command). 285 * The lines are deleted, so the new bottom line is lnum, unless the buffer 286 * becomes empty. 287 * Careful: may trigger autocommands that reload the buffer. 288 * Returns FAIL when lines could not be saved, OK otherwise. 289 */ 290 int 291 u_savedel(lnum, nlines) 292 linenr_T lnum; 293 long nlines; 294 { 295 if (undo_off) 296 return OK; 297 298 return (u_savecommon(lnum - 1, lnum + nlines, 299 nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, FALSE)); 300 } 301 302 /* 303 * Return TRUE when undo is allowed. Otherwise give an error message and 304 * return FALSE. 305 */ 306 int 307 undo_allowed() 308 { 309 /* Don't allow changes when 'modifiable' is off. */ 310 if (!curbuf->b_p_ma) 311 { 312 EMSG(_(e_modifiable)); 313 return FALSE; 314 } 315 316 #ifdef HAVE_SANDBOX 317 /* In the sandbox it's not allowed to change the text. */ 318 if (sandbox != 0) 319 { 320 EMSG(_(e_sandbox)); 321 return FALSE; 322 } 323 #endif 324 325 /* Don't allow changes in the buffer while editing the cmdline. The 326 * caller of getcmdline() may get confused. */ 327 if (textlock != 0) 328 { 329 EMSG(_(e_secure)); 330 return FALSE; 331 } 332 333 return TRUE; 334 } 335 336 /* 337 * Common code for various ways to save text before a change. 338 * "top" is the line above the first changed line. 339 * "bot" is the line below the last changed line. 340 * "newbot" is the new bottom line. Use zero when not known. 341 * "reload" is TRUE when saving for a buffer reload. 342 * Careful: may trigger autocommands that reload the buffer. 343 * Returns FAIL when lines could not be saved, OK otherwise. 344 */ 345 int 346 u_savecommon(top, bot, newbot, reload) 347 linenr_T top, bot; 348 linenr_T newbot; 349 int reload; 350 { 351 linenr_T lnum; 352 long i; 353 u_header_T *uhp; 354 u_header_T *old_curhead; 355 u_entry_T *uep; 356 u_entry_T *prev_uep; 357 long size; 358 359 if (!reload) 360 { 361 /* When making changes is not allowed return FAIL. It's a crude way 362 * to make all change commands fail. */ 363 if (!undo_allowed()) 364 return FAIL; 365 366 #ifdef FEAT_NETBEANS_INTG 367 /* 368 * Netbeans defines areas that cannot be modified. Bail out here when 369 * trying to change text in a guarded area. 370 */ 371 if (netbeans_active()) 372 { 373 if (netbeans_is_guarded(top, bot)) 374 { 375 EMSG(_(e_guarded)); 376 return FAIL; 377 } 378 if (curbuf->b_p_ro) 379 { 380 EMSG(_(e_nbreadonly)); 381 return FAIL; 382 } 383 } 384 #endif 385 386 #ifdef FEAT_AUTOCMD 387 /* 388 * Saving text for undo means we are going to make a change. Give a 389 * warning for a read-only file before making the change, so that the 390 * FileChangedRO event can replace the buffer with a read-write version 391 * (e.g., obtained from a source control system). 392 */ 393 change_warning(0); 394 if (bot > curbuf->b_ml.ml_line_count + 1) 395 { 396 /* This happens when the FileChangedRO autocommand changes the 397 * file in a way it becomes shorter. */ 398 EMSG(_("E834: Line count changed unexpectedly")); 399 return FAIL; 400 } 401 #endif 402 } 403 404 #ifdef U_DEBUG 405 u_check(FALSE); 406 #endif 407 408 size = bot - top - 1; 409 410 /* 411 * If curbuf->b_u_synced == TRUE make a new header. 412 */ 413 if (curbuf->b_u_synced) 414 { 415 #ifdef FEAT_JUMPLIST 416 /* Need to create new entry in b_changelist. */ 417 curbuf->b_new_change = TRUE; 418 #endif 419 420 if (p_ul >= 0) 421 { 422 /* 423 * Make a new header entry. Do this first so that we don't mess 424 * up the undo info when out of memory. 425 */ 426 uhp = (u_header_T *)U_ALLOC_LINE(sizeof(u_header_T)); 427 if (uhp == NULL) 428 goto nomem; 429 #ifdef U_DEBUG 430 uhp->uh_magic = UH_MAGIC; 431 #endif 432 } 433 else 434 uhp = NULL; 435 436 /* 437 * If we undid more than we redid, move the entry lists before and 438 * including curbuf->b_u_curhead to an alternate branch. 439 */ 440 old_curhead = curbuf->b_u_curhead; 441 if (old_curhead != NULL) 442 { 443 curbuf->b_u_newhead = old_curhead->uh_next.ptr; 444 curbuf->b_u_curhead = NULL; 445 } 446 447 /* 448 * free headers to keep the size right 449 */ 450 while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL) 451 { 452 u_header_T *uhfree = curbuf->b_u_oldhead; 453 454 if (uhfree == old_curhead) 455 /* Can't reconnect the branch, delete all of it. */ 456 u_freebranch(curbuf, uhfree, &old_curhead); 457 else if (uhfree->uh_alt_next.ptr == NULL) 458 /* There is no branch, only free one header. */ 459 u_freeheader(curbuf, uhfree, &old_curhead); 460 else 461 { 462 /* Free the oldest alternate branch as a whole. */ 463 while (uhfree->uh_alt_next.ptr != NULL) 464 uhfree = uhfree->uh_alt_next.ptr; 465 u_freebranch(curbuf, uhfree, &old_curhead); 466 } 467 #ifdef U_DEBUG 468 u_check(TRUE); 469 #endif 470 } 471 472 if (uhp == NULL) /* no undo at all */ 473 { 474 if (old_curhead != NULL) 475 u_freebranch(curbuf, old_curhead, NULL); 476 curbuf->b_u_synced = FALSE; 477 return OK; 478 } 479 480 uhp->uh_prev.ptr = NULL; 481 uhp->uh_next.ptr = curbuf->b_u_newhead; 482 uhp->uh_alt_next.ptr = old_curhead; 483 if (old_curhead != NULL) 484 { 485 uhp->uh_alt_prev.ptr = old_curhead->uh_alt_prev.ptr; 486 if (uhp->uh_alt_prev.ptr != NULL) 487 uhp->uh_alt_prev.ptr->uh_alt_next.ptr = uhp; 488 old_curhead->uh_alt_prev.ptr = uhp; 489 if (curbuf->b_u_oldhead == old_curhead) 490 curbuf->b_u_oldhead = uhp; 491 } 492 else 493 uhp->uh_alt_prev.ptr = NULL; 494 if (curbuf->b_u_newhead != NULL) 495 curbuf->b_u_newhead->uh_prev.ptr = uhp; 496 497 uhp->uh_seq = ++curbuf->b_u_seq_last; 498 curbuf->b_u_seq_cur = uhp->uh_seq; 499 uhp->uh_time = time(NULL); 500 uhp->uh_save_nr = 0; 501 curbuf->b_u_time_cur = uhp->uh_time + 1; 502 503 uhp->uh_walk = 0; 504 uhp->uh_entry = NULL; 505 uhp->uh_getbot_entry = NULL; 506 uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */ 507 #ifdef FEAT_VIRTUALEDIT 508 if (virtual_active() && curwin->w_cursor.coladd > 0) 509 uhp->uh_cursor_vcol = getviscol(); 510 else 511 uhp->uh_cursor_vcol = -1; 512 #endif 513 514 /* save changed and buffer empty flag for undo */ 515 uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 516 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); 517 518 /* save named marks and Visual marks for undo */ 519 mch_memmove(uhp->uh_namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS); 520 #ifdef FEAT_VISUAL 521 uhp->uh_visual = curbuf->b_visual; 522 #endif 523 524 curbuf->b_u_newhead = uhp; 525 if (curbuf->b_u_oldhead == NULL) 526 curbuf->b_u_oldhead = uhp; 527 ++curbuf->b_u_numhead; 528 } 529 else 530 { 531 if (p_ul < 0) /* no undo at all */ 532 return OK; 533 534 /* 535 * When saving a single line, and it has been saved just before, it 536 * doesn't make sense saving it again. Saves a lot of memory when 537 * making lots of changes inside the same line. 538 * This is only possible if the previous change didn't increase or 539 * decrease the number of lines. 540 * Check the ten last changes. More doesn't make sense and takes too 541 * long. 542 */ 543 if (size == 1) 544 { 545 uep = u_get_headentry(); 546 prev_uep = NULL; 547 for (i = 0; i < 10; ++i) 548 { 549 if (uep == NULL) 550 break; 551 552 /* If lines have been inserted/deleted we give up. 553 * Also when the line was included in a multi-line save. */ 554 if ((curbuf->b_u_newhead->uh_getbot_entry != uep 555 ? (uep->ue_top + uep->ue_size + 1 556 != (uep->ue_bot == 0 557 ? curbuf->b_ml.ml_line_count + 1 558 : uep->ue_bot)) 559 : uep->ue_lcount != curbuf->b_ml.ml_line_count) 560 || (uep->ue_size > 1 561 && top >= uep->ue_top 562 && top + 2 <= uep->ue_top + uep->ue_size + 1)) 563 break; 564 565 /* If it's the same line we can skip saving it again. */ 566 if (uep->ue_size == 1 && uep->ue_top == top) 567 { 568 if (i > 0) 569 { 570 /* It's not the last entry: get ue_bot for the last 571 * entry now. Following deleted/inserted lines go to 572 * the re-used entry. */ 573 u_getbot(); 574 curbuf->b_u_synced = FALSE; 575 576 /* Move the found entry to become the last entry. The 577 * order of undo/redo doesn't matter for the entries 578 * we move it over, since they don't change the line 579 * count and don't include this line. It does matter 580 * for the found entry if the line count is changed by 581 * the executed command. */ 582 prev_uep->ue_next = uep->ue_next; 583 uep->ue_next = curbuf->b_u_newhead->uh_entry; 584 curbuf->b_u_newhead->uh_entry = uep; 585 } 586 587 /* The executed command may change the line count. */ 588 if (newbot != 0) 589 uep->ue_bot = newbot; 590 else if (bot > curbuf->b_ml.ml_line_count) 591 uep->ue_bot = 0; 592 else 593 { 594 uep->ue_lcount = curbuf->b_ml.ml_line_count; 595 curbuf->b_u_newhead->uh_getbot_entry = uep; 596 } 597 return OK; 598 } 599 prev_uep = uep; 600 uep = uep->ue_next; 601 } 602 } 603 604 /* find line number for ue_bot for previous u_save() */ 605 u_getbot(); 606 } 607 608 #if !defined(UNIX) && !defined(DJGPP) && !defined(WIN32) && !defined(__EMX__) 609 /* 610 * With Amiga and MSDOS 16 bit we can't handle big undo's, because 611 * then u_alloc_line would have to allocate a block larger than 32K 612 */ 613 if (size >= 8000) 614 goto nomem; 615 #endif 616 617 /* 618 * add lines in front of entry list 619 */ 620 uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T)); 621 if (uep == NULL) 622 goto nomem; 623 vim_memset(uep, 0, sizeof(u_entry_T)); 624 #ifdef U_DEBUG 625 uep->ue_magic = UE_MAGIC; 626 #endif 627 628 uep->ue_size = size; 629 uep->ue_top = top; 630 if (newbot != 0) 631 uep->ue_bot = newbot; 632 /* 633 * Use 0 for ue_bot if bot is below last line. 634 * Otherwise we have to compute ue_bot later. 635 */ 636 else if (bot > curbuf->b_ml.ml_line_count) 637 uep->ue_bot = 0; 638 else 639 { 640 uep->ue_lcount = curbuf->b_ml.ml_line_count; 641 curbuf->b_u_newhead->uh_getbot_entry = uep; 642 } 643 644 if (size > 0) 645 { 646 if ((uep->ue_array = (char_u **)U_ALLOC_LINE( 647 sizeof(char_u *) * size)) == NULL) 648 { 649 u_freeentry(uep, 0L); 650 goto nomem; 651 } 652 for (i = 0, lnum = top + 1; i < size; ++i) 653 { 654 fast_breakcheck(); 655 if (got_int) 656 { 657 u_freeentry(uep, i); 658 return FAIL; 659 } 660 if ((uep->ue_array[i] = u_save_line(lnum++)) == NULL) 661 { 662 u_freeentry(uep, i); 663 goto nomem; 664 } 665 } 666 } 667 else 668 uep->ue_array = NULL; 669 uep->ue_next = curbuf->b_u_newhead->uh_entry; 670 curbuf->b_u_newhead->uh_entry = uep; 671 curbuf->b_u_synced = FALSE; 672 undo_undoes = FALSE; 673 674 #ifdef U_DEBUG 675 u_check(FALSE); 676 #endif 677 return OK; 678 679 nomem: 680 msg_silent = 0; /* must display the prompt */ 681 if (ask_yesno((char_u *)_("No undo possible; continue anyway"), TRUE) 682 == 'y') 683 { 684 undo_off = TRUE; /* will be reset when character typed */ 685 return OK; 686 } 687 do_outofmem_msg((long_u)0); 688 return FAIL; 689 } 690 691 #if defined(FEAT_PERSISTENT_UNDO) || defined(PROTO) 692 693 # define UF_START_MAGIC "Vim\237UnDo\345" /* magic at start of undofile */ 694 # define UF_START_MAGIC_LEN 9 695 # define UF_HEADER_MAGIC 0x5fd0 /* magic at start of header */ 696 # define UF_HEADER_END_MAGIC 0xe7aa /* magic after last header */ 697 # define UF_ENTRY_MAGIC 0xf518 /* magic at start of entry */ 698 # define UF_ENTRY_END_MAGIC 0x3581 /* magic after last entry */ 699 # define UF_VERSION 2 /* 2-byte undofile version number */ 700 # define UF_VERSION_CRYPT 0x8002 /* idem, encrypted */ 701 702 /* extra fields for header */ 703 # define UF_LAST_SAVE_NR 1 704 705 /* extra fields for uhp */ 706 # define UHP_SAVE_NR 1 707 708 static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s"); 709 710 /* 711 * Compute the hash for the current buffer text into hash[UNDO_HASH_SIZE]. 712 */ 713 void 714 u_compute_hash(hash) 715 char_u *hash; 716 { 717 context_sha256_T ctx; 718 linenr_T lnum; 719 char_u *p; 720 721 sha256_start(&ctx); 722 for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum) 723 { 724 p = ml_get(lnum); 725 sha256_update(&ctx, p, (UINT32_T)(STRLEN(p) + 1)); 726 } 727 sha256_finish(&ctx, hash); 728 } 729 730 /* 731 * Return an allocated string of the full path of the target undofile. 732 * When "reading" is TRUE find the file to read, go over all directories in 733 * 'undodir'. 734 * When "reading" is FALSE use the first name where the directory exists. 735 * Returns NULL when there is no place to write or no file to read. 736 */ 737 char_u * 738 u_get_undo_file_name(buf_ffname, reading) 739 char_u *buf_ffname; 740 int reading; 741 { 742 char_u *dirp; 743 char_u dir_name[IOSIZE + 1]; 744 char_u *munged_name = NULL; 745 char_u *undo_file_name = NULL; 746 int dir_len; 747 char_u *p; 748 struct stat st; 749 char_u *ffname = buf_ffname; 750 #ifdef HAVE_READLINK 751 char_u fname_buf[MAXPATHL]; 752 #endif 753 754 if (ffname == NULL) 755 return NULL; 756 757 #ifdef HAVE_READLINK 758 /* Expand symlink in the file name, so that we put the undo file with the 759 * actual file instead of with the symlink. */ 760 if (resolve_symlink(ffname, fname_buf) == OK) 761 ffname = fname_buf; 762 #endif 763 764 /* Loop over 'undodir'. When reading find the first file that exists. 765 * When not reading use the first directory that exists or ".". */ 766 dirp = p_udir; 767 while (*dirp != NUL) 768 { 769 dir_len = copy_option_part(&dirp, dir_name, IOSIZE, ","); 770 if (dir_len == 1 && dir_name[0] == '.') 771 { 772 /* Use same directory as the ffname, 773 * "dir/name" -> "dir/.name.un~" */ 774 undo_file_name = vim_strnsave(ffname, (int)(STRLEN(ffname) + 5)); 775 if (undo_file_name == NULL) 776 break; 777 p = gettail(undo_file_name); 778 mch_memmove(p + 1, p, STRLEN(p) + 1); 779 *p = '.'; 780 STRCAT(p, ".un~"); 781 } 782 else 783 { 784 dir_name[dir_len] = NUL; 785 if (mch_isdir(dir_name)) 786 { 787 if (munged_name == NULL) 788 { 789 munged_name = vim_strsave(ffname); 790 if (munged_name == NULL) 791 return NULL; 792 for (p = munged_name; *p != NUL; mb_ptr_adv(p)) 793 if (vim_ispathsep(*p)) 794 *p = '%'; 795 } 796 undo_file_name = concat_fnames(dir_name, munged_name, TRUE); 797 } 798 } 799 800 /* When reading check if the file exists. */ 801 if (undo_file_name != NULL && (!reading 802 || mch_stat((char *)undo_file_name, &st) >= 0)) 803 break; 804 vim_free(undo_file_name); 805 undo_file_name = NULL; 806 } 807 808 vim_free(munged_name); 809 return undo_file_name; 810 } 811 812 static void 813 corruption_error(mesg, file_name) 814 char *mesg; 815 char_u *file_name; 816 { 817 EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name); 818 } 819 820 static void 821 u_free_uhp(uhp) 822 u_header_T *uhp; 823 { 824 u_entry_T *nuep; 825 u_entry_T *uep; 826 827 uep = uhp->uh_entry; 828 while (uep != NULL) 829 { 830 nuep = uep->ue_next; 831 u_freeentry(uep, uep->ue_size); 832 uep = nuep; 833 } 834 vim_free(uhp); 835 } 836 837 /* 838 * Like fwrite() but crypt the bytes when 'key' is set. 839 * Returns 1 if successful. 840 */ 841 static size_t 842 fwrite_crypt(buf, ptr, len, fp) 843 buf_T *buf UNUSED; 844 char_u *ptr; 845 size_t len; 846 FILE *fp; 847 { 848 #ifdef FEAT_CRYPT 849 char_u *copy; 850 char_u small_buf[100]; 851 size_t i; 852 853 if (*buf->b_p_key == NUL) 854 return fwrite(ptr, len, (size_t)1, fp); 855 if (len < 100) 856 copy = small_buf; /* no malloc()/free() for short strings */ 857 else 858 { 859 copy = lalloc(len, FALSE); 860 if (copy == NULL) 861 return 0; 862 } 863 crypt_encode(ptr, len, copy); 864 i = fwrite(copy, len, (size_t)1, fp); 865 if (copy != small_buf) 866 vim_free(copy); 867 return i; 868 #else 869 return fwrite(ptr, len, (size_t)1, fp); 870 #endif 871 } 872 873 /* 874 * Read a string of length "len" from "fd". 875 * When 'key' is set decrypt the bytes. 876 */ 877 static char_u * 878 read_string_decrypt(buf, fd, len) 879 buf_T *buf UNUSED; 880 FILE *fd; 881 int len; 882 { 883 char_u *ptr; 884 885 ptr = read_string(fd, len); 886 #ifdef FEAT_CRYPT 887 if (ptr != NULL && *buf->b_p_key != NUL) 888 crypt_decode(ptr, len); 889 #endif 890 return ptr; 891 } 892 893 static int 894 serialize_header(fp, buf, hash) 895 FILE *fp; 896 buf_T *buf; 897 char_u *hash; 898 { 899 int len; 900 901 /* Start writing, first the magic marker and undo info version. */ 902 if (fwrite(UF_START_MAGIC, (size_t)UF_START_MAGIC_LEN, (size_t)1, fp) != 1) 903 return FAIL; 904 905 /* If the buffer is encrypted then all text bytes following will be 906 * encrypted. Numbers and other info is not crypted. */ 907 #ifdef FEAT_CRYPT 908 if (*buf->b_p_key != NUL) 909 { 910 char_u *header; 911 int header_len; 912 913 put_bytes(fp, (long_u)UF_VERSION_CRYPT, 2); 914 header = prepare_crypt_write(buf, &header_len); 915 if (header == NULL) 916 return FAIL; 917 len = (int)fwrite(header, (size_t)header_len, (size_t)1, fp); 918 vim_free(header); 919 if (len != 1) 920 { 921 crypt_pop_state(); 922 return FAIL; 923 } 924 } 925 else 926 #endif 927 put_bytes(fp, (long_u)UF_VERSION, 2); 928 929 930 /* Write a hash of the buffer text, so that we can verify it is still the 931 * same when reading the buffer text. */ 932 if (fwrite(hash, (size_t)UNDO_HASH_SIZE, (size_t)1, fp) != 1) 933 return FAIL; 934 935 /* buffer-specific data */ 936 put_bytes(fp, (long_u)buf->b_ml.ml_line_count, 4); 937 len = buf->b_u_line_ptr != NULL ? (int)STRLEN(buf->b_u_line_ptr) : 0; 938 put_bytes(fp, (long_u)len, 4); 939 if (len > 0 && fwrite_crypt(buf, buf->b_u_line_ptr, (size_t)len, fp) != 1) 940 return FAIL; 941 put_bytes(fp, (long_u)buf->b_u_line_lnum, 4); 942 put_bytes(fp, (long_u)buf->b_u_line_colnr, 4); 943 944 /* Undo structures header data */ 945 put_header_ptr(fp, buf->b_u_oldhead); 946 put_header_ptr(fp, buf->b_u_newhead); 947 put_header_ptr(fp, buf->b_u_curhead); 948 949 put_bytes(fp, (long_u)buf->b_u_numhead, 4); 950 put_bytes(fp, (long_u)buf->b_u_seq_last, 4); 951 put_bytes(fp, (long_u)buf->b_u_seq_cur, 4); 952 put_time(fp, buf->b_u_time_cur); 953 954 /* Optional fields. */ 955 putc(4, fp); 956 putc(UF_LAST_SAVE_NR, fp); 957 put_bytes(fp, (long_u)buf->b_u_save_nr_last, 4); 958 959 putc(0, fp); /* end marker */ 960 961 return OK; 962 } 963 964 static int 965 serialize_uhp(fp, buf, uhp) 966 FILE *fp; 967 buf_T *buf; 968 u_header_T *uhp; 969 { 970 int i; 971 u_entry_T *uep; 972 973 if (put_bytes(fp, (long_u)UF_HEADER_MAGIC, 2) == FAIL) 974 return FAIL; 975 976 put_header_ptr(fp, uhp->uh_next.ptr); 977 put_header_ptr(fp, uhp->uh_prev.ptr); 978 put_header_ptr(fp, uhp->uh_alt_next.ptr); 979 put_header_ptr(fp, uhp->uh_alt_prev.ptr); 980 put_bytes(fp, uhp->uh_seq, 4); 981 serialize_pos(uhp->uh_cursor, fp); 982 #ifdef FEAT_VIRTUALEDIT 983 put_bytes(fp, (long_u)uhp->uh_cursor_vcol, 4); 984 #else 985 put_bytes(fp, (long_u)0, 4); 986 #endif 987 put_bytes(fp, (long_u)uhp->uh_flags, 2); 988 /* Assume NMARKS will stay the same. */ 989 for (i = 0; i < NMARKS; ++i) 990 serialize_pos(uhp->uh_namedm[i], fp); 991 #ifdef FEAT_VISUAL 992 serialize_visualinfo(&uhp->uh_visual, fp); 993 #else 994 { 995 visualinfo_T info; 996 997 memset(&info, 0, sizeof(visualinfo_T)); 998 serialize_visualinfo(&info, fp); 999 } 1000 #endif 1001 put_time(fp, uhp->uh_time); 1002 1003 /* Optional fields. */ 1004 putc(4, fp); 1005 putc(UHP_SAVE_NR, fp); 1006 put_bytes(fp, (long_u)uhp->uh_save_nr, 4); 1007 1008 putc(0, fp); /* end marker */ 1009 1010 /* Write all the entries. */ 1011 for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next) 1012 { 1013 put_bytes(fp, (long_u)UF_ENTRY_MAGIC, 2); 1014 if (serialize_uep(fp, buf, uep) == FAIL) 1015 return FAIL; 1016 } 1017 put_bytes(fp, (long_u)UF_ENTRY_END_MAGIC, 2); 1018 return OK; 1019 } 1020 1021 static u_header_T * 1022 unserialize_uhp(fp, file_name) 1023 FILE *fp; 1024 char_u *file_name; 1025 { 1026 u_header_T *uhp; 1027 int i; 1028 u_entry_T *uep, *last_uep; 1029 int c; 1030 int error; 1031 1032 uhp = (u_header_T *)U_ALLOC_LINE(sizeof(u_header_T)); 1033 if (uhp == NULL) 1034 return NULL; 1035 vim_memset(uhp, 0, sizeof(u_header_T)); 1036 #ifdef U_DEBUG 1037 uhp->uh_magic = UH_MAGIC; 1038 #endif 1039 uhp->uh_next.seq = get4c(fp); 1040 uhp->uh_prev.seq = get4c(fp); 1041 uhp->uh_alt_next.seq = get4c(fp); 1042 uhp->uh_alt_prev.seq = get4c(fp); 1043 uhp->uh_seq = get4c(fp); 1044 if (uhp->uh_seq <= 0) 1045 { 1046 corruption_error("uh_seq", file_name); 1047 vim_free(uhp); 1048 return NULL; 1049 } 1050 unserialize_pos(&uhp->uh_cursor, fp); 1051 #ifdef FEAT_VIRTUALEDIT 1052 uhp->uh_cursor_vcol = get4c(fp); 1053 #else 1054 (void)get4c(fp); 1055 #endif 1056 uhp->uh_flags = get2c(fp); 1057 for (i = 0; i < NMARKS; ++i) 1058 unserialize_pos(&uhp->uh_namedm[i], fp); 1059 #ifdef FEAT_VISUAL 1060 unserialize_visualinfo(&uhp->uh_visual, fp); 1061 #else 1062 { 1063 visualinfo_T info; 1064 unserialize_visualinfo(&info, fp); 1065 } 1066 #endif 1067 uhp->uh_time = get8ctime(fp); 1068 1069 /* Optional fields. */ 1070 for (;;) 1071 { 1072 int len = getc(fp); 1073 int what; 1074 1075 if (len == 0) 1076 break; 1077 what = getc(fp); 1078 switch (what) 1079 { 1080 case UHP_SAVE_NR: 1081 uhp->uh_save_nr = get4c(fp); 1082 break; 1083 default: 1084 /* field not supported, skip */ 1085 while (--len >= 0) 1086 (void)getc(fp); 1087 } 1088 } 1089 1090 /* Unserialize the uep list. */ 1091 last_uep = NULL; 1092 while ((c = get2c(fp)) == UF_ENTRY_MAGIC) 1093 { 1094 error = FALSE; 1095 uep = unserialize_uep(fp, &error, file_name); 1096 if (last_uep == NULL) 1097 uhp->uh_entry = uep; 1098 else 1099 last_uep->ue_next = uep; 1100 last_uep = uep; 1101 if (uep == NULL || error) 1102 { 1103 u_free_uhp(uhp); 1104 return NULL; 1105 } 1106 } 1107 if (c != UF_ENTRY_END_MAGIC) 1108 { 1109 corruption_error("entry end", file_name); 1110 u_free_uhp(uhp); 1111 return NULL; 1112 } 1113 1114 return uhp; 1115 } 1116 1117 /* 1118 * Serialize "uep" to "fp". 1119 */ 1120 static int 1121 serialize_uep(fp, buf, uep) 1122 FILE *fp; 1123 buf_T *buf; 1124 u_entry_T *uep; 1125 { 1126 int i; 1127 size_t len; 1128 1129 put_bytes(fp, (long_u)uep->ue_top, 4); 1130 put_bytes(fp, (long_u)uep->ue_bot, 4); 1131 put_bytes(fp, (long_u)uep->ue_lcount, 4); 1132 put_bytes(fp, (long_u)uep->ue_size, 4); 1133 for (i = 0; i < uep->ue_size; ++i) 1134 { 1135 len = STRLEN(uep->ue_array[i]); 1136 if (put_bytes(fp, (long_u)len, 4) == FAIL) 1137 return FAIL; 1138 if (len > 0 && fwrite_crypt(buf, uep->ue_array[i], len, fp) != 1) 1139 return FAIL; 1140 } 1141 return OK; 1142 } 1143 1144 static u_entry_T * 1145 unserialize_uep(fp, error, file_name) 1146 FILE *fp; 1147 int *error; 1148 char_u *file_name; 1149 { 1150 int i; 1151 u_entry_T *uep; 1152 char_u **array; 1153 char_u *line; 1154 int line_len; 1155 1156 uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T)); 1157 if (uep == NULL) 1158 return NULL; 1159 vim_memset(uep, 0, sizeof(u_entry_T)); 1160 #ifdef U_DEBUG 1161 uep->ue_magic = UE_MAGIC; 1162 #endif 1163 uep->ue_top = get4c(fp); 1164 uep->ue_bot = get4c(fp); 1165 uep->ue_lcount = get4c(fp); 1166 uep->ue_size = get4c(fp); 1167 if (uep->ue_size > 0) 1168 { 1169 array = (char_u **)U_ALLOC_LINE(sizeof(char_u *) * uep->ue_size); 1170 if (array == NULL) 1171 { 1172 *error = TRUE; 1173 return uep; 1174 } 1175 vim_memset(array, 0, sizeof(char_u *) * uep->ue_size); 1176 } 1177 else 1178 array = NULL; 1179 uep->ue_array = array; 1180 1181 for (i = 0; i < uep->ue_size; ++i) 1182 { 1183 line_len = get4c(fp); 1184 if (line_len >= 0) 1185 line = read_string_decrypt(curbuf, fp, line_len); 1186 else 1187 { 1188 line = NULL; 1189 corruption_error("line length", file_name); 1190 } 1191 if (line == NULL) 1192 { 1193 *error = TRUE; 1194 return uep; 1195 } 1196 array[i] = line; 1197 } 1198 return uep; 1199 } 1200 1201 /* 1202 * Serialize "pos" to "fp". 1203 */ 1204 static void 1205 serialize_pos(pos, fp) 1206 pos_T pos; 1207 FILE *fp; 1208 { 1209 put_bytes(fp, (long_u)pos.lnum, 4); 1210 put_bytes(fp, (long_u)pos.col, 4); 1211 #ifdef FEAT_VIRTUALEDIT 1212 put_bytes(fp, (long_u)pos.coladd, 4); 1213 #else 1214 put_bytes(fp, (long_u)0, 4); 1215 #endif 1216 } 1217 1218 /* 1219 * Unserialize the pos_T at the current position in fp. 1220 */ 1221 static void 1222 unserialize_pos(pos, fp) 1223 pos_T *pos; 1224 FILE *fp; 1225 { 1226 pos->lnum = get4c(fp); 1227 if (pos->lnum < 0) 1228 pos->lnum = 0; 1229 pos->col = get4c(fp); 1230 if (pos->col < 0) 1231 pos->col = 0; 1232 #ifdef FEAT_VIRTUALEDIT 1233 pos->coladd = get4c(fp); 1234 if (pos->coladd < 0) 1235 pos->coladd = 0; 1236 #else 1237 (void)get4c(fp); 1238 #endif 1239 } 1240 1241 /* 1242 * Serialize "info" to "fp". 1243 */ 1244 static void 1245 serialize_visualinfo(info, fp) 1246 visualinfo_T *info; 1247 FILE *fp; 1248 { 1249 serialize_pos(info->vi_start, fp); 1250 serialize_pos(info->vi_end, fp); 1251 put_bytes(fp, (long_u)info->vi_mode, 4); 1252 put_bytes(fp, (long_u)info->vi_curswant, 4); 1253 } 1254 1255 /* 1256 * Unserialize the visualinfo_T at the current position in fp. 1257 */ 1258 static void 1259 unserialize_visualinfo(info, fp) 1260 visualinfo_T *info; 1261 FILE *fp; 1262 { 1263 unserialize_pos(&info->vi_start, fp); 1264 unserialize_pos(&info->vi_end, fp); 1265 info->vi_mode = get4c(fp); 1266 info->vi_curswant = get4c(fp); 1267 } 1268 1269 /* 1270 * Write the pointer to an undo header. Instead of writing the pointer itself 1271 * we use the sequence number of the header. This is converted back to 1272 * pointers when reading. */ 1273 static void 1274 put_header_ptr(fp, uhp) 1275 FILE *fp; 1276 u_header_T *uhp; 1277 { 1278 put_bytes(fp, (long_u)(uhp != NULL ? uhp->uh_seq : 0), 4); 1279 } 1280 1281 /* 1282 * Write the undo tree in an undo file. 1283 * When "name" is not NULL, use it as the name of the undo file. 1284 * Otherwise use buf->b_ffname to generate the undo file name. 1285 * "buf" must never be null, buf->b_ffname is used to obtain the original file 1286 * permissions. 1287 * "forceit" is TRUE for ":wundo!", FALSE otherwise. 1288 * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. 1289 */ 1290 void 1291 u_write_undo(name, forceit, buf, hash) 1292 char_u *name; 1293 int forceit; 1294 buf_T *buf; 1295 char_u *hash; 1296 { 1297 u_header_T *uhp; 1298 char_u *file_name; 1299 int mark; 1300 #ifdef U_DEBUG 1301 int headers_written = 0; 1302 #endif 1303 int fd; 1304 FILE *fp = NULL; 1305 int perm; 1306 int write_ok = FALSE; 1307 #ifdef UNIX 1308 int st_old_valid = FALSE; 1309 struct stat st_old; 1310 struct stat st_new; 1311 #endif 1312 #ifdef FEAT_CRYPT 1313 int do_crypt = FALSE; 1314 #endif 1315 1316 if (name == NULL) 1317 { 1318 file_name = u_get_undo_file_name(buf->b_ffname, FALSE); 1319 if (file_name == NULL) 1320 { 1321 if (p_verbose > 0) 1322 { 1323 verbose_enter(); 1324 smsg((char_u *) 1325 _("Cannot write undo file in any directory in 'undodir'")); 1326 verbose_leave(); 1327 } 1328 return; 1329 } 1330 } 1331 else 1332 file_name = name; 1333 1334 /* 1335 * Decide about the permission to use for the undo file. If the buffer 1336 * has a name use the permission of the original file. Otherwise only 1337 * allow the user to access the undo file. 1338 */ 1339 perm = 0600; 1340 if (buf->b_ffname != NULL) 1341 { 1342 #ifdef UNIX 1343 if (mch_stat((char *)buf->b_ffname, &st_old) >= 0) 1344 { 1345 perm = st_old.st_mode; 1346 st_old_valid = TRUE; 1347 } 1348 #else 1349 perm = mch_getperm(buf->b_ffname); 1350 if (perm < 0) 1351 perm = 0600; 1352 #endif 1353 } 1354 1355 /* strip any s-bit */ 1356 perm = perm & 0777; 1357 1358 /* If the undo file already exists, verify that it actually is an undo 1359 * file, and delete it. */ 1360 if (mch_getperm(file_name) >= 0) 1361 { 1362 if (name == NULL || !forceit) 1363 { 1364 /* Check we can read it and it's an undo file. */ 1365 fd = mch_open((char *)file_name, O_RDONLY|O_EXTRA, 0); 1366 if (fd < 0) 1367 { 1368 if (name != NULL || p_verbose > 0) 1369 { 1370 if (name == NULL) 1371 verbose_enter(); 1372 smsg((char_u *) 1373 _("Will not overwrite with undo file, cannot read: %s"), 1374 file_name); 1375 if (name == NULL) 1376 verbose_leave(); 1377 } 1378 goto theend; 1379 } 1380 else 1381 { 1382 char_u mbuf[UF_START_MAGIC_LEN]; 1383 int len; 1384 1385 len = read_eintr(fd, mbuf, UF_START_MAGIC_LEN); 1386 close(fd); 1387 if (len < UF_START_MAGIC_LEN 1388 || memcmp(mbuf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) 1389 { 1390 if (name != NULL || p_verbose > 0) 1391 { 1392 if (name == NULL) 1393 verbose_enter(); 1394 smsg((char_u *) 1395 _("Will not overwrite, this is not an undo file: %s"), 1396 file_name); 1397 if (name == NULL) 1398 verbose_leave(); 1399 } 1400 goto theend; 1401 } 1402 } 1403 } 1404 mch_remove(file_name); 1405 } 1406 1407 /* If there is no undo information at all, quit here after deleting any 1408 * existing undo file. */ 1409 if (buf->b_u_numhead == 0 && buf->b_u_line_ptr == NULL) 1410 { 1411 if (p_verbose > 0) 1412 verb_msg((char_u *)_("Skipping undo file write, nothing to undo")); 1413 goto theend; 1414 } 1415 1416 fd = mch_open((char *)file_name, 1417 O_CREAT|O_EXTRA|O_WRONLY|O_EXCL|O_NOFOLLOW, perm); 1418 if (fd < 0) 1419 { 1420 EMSG2(_(e_not_open), file_name); 1421 goto theend; 1422 } 1423 (void)mch_setperm(file_name, perm); 1424 if (p_verbose > 0) 1425 { 1426 verbose_enter(); 1427 smsg((char_u *)_("Writing undo file: %s"), file_name); 1428 verbose_leave(); 1429 } 1430 1431 #ifdef U_DEBUG 1432 /* Check there is no problem in undo info before writing. */ 1433 u_check(FALSE); 1434 #endif 1435 1436 #ifdef UNIX 1437 /* 1438 * Try to set the group of the undo file same as the original file. If 1439 * this fails, set the protection bits for the group same as the 1440 * protection bits for others. 1441 */ 1442 if (st_old_valid 1443 && mch_stat((char *)file_name, &st_new) >= 0 1444 && st_new.st_gid != st_old.st_gid 1445 # ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */ 1446 && fchown(fd, (uid_t)-1, st_old.st_gid) != 0 1447 # endif 1448 ) 1449 mch_setperm(file_name, (perm & 0707) | ((perm & 07) << 3)); 1450 # ifdef HAVE_SELINUX 1451 if (buf->b_ffname != NULL) 1452 mch_copy_sec(buf->b_ffname, file_name); 1453 # endif 1454 #endif 1455 1456 fp = fdopen(fd, "w"); 1457 if (fp == NULL) 1458 { 1459 EMSG2(_(e_not_open), file_name); 1460 close(fd); 1461 mch_remove(file_name); 1462 goto theend; 1463 } 1464 1465 /* Undo must be synced. */ 1466 u_sync(TRUE); 1467 1468 /* 1469 * Write the header. 1470 */ 1471 if (serialize_header(fp, buf, hash) == FAIL) 1472 goto write_error; 1473 #ifdef FEAT_CRYPT 1474 if (*buf->b_p_key != NUL) 1475 do_crypt = TRUE; 1476 #endif 1477 1478 /* 1479 * Iteratively serialize UHPs and their UEPs from the top down. 1480 */ 1481 mark = ++lastmark; 1482 uhp = buf->b_u_oldhead; 1483 while (uhp != NULL) 1484 { 1485 /* Serialize current UHP if we haven't seen it */ 1486 if (uhp->uh_walk != mark) 1487 { 1488 uhp->uh_walk = mark; 1489 #ifdef U_DEBUG 1490 ++headers_written; 1491 #endif 1492 if (serialize_uhp(fp, buf, uhp) == FAIL) 1493 goto write_error; 1494 } 1495 1496 /* Now walk through the tree - algorithm from undo_time(). */ 1497 if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark) 1498 uhp = uhp->uh_prev.ptr; 1499 else if (uhp->uh_alt_next.ptr != NULL 1500 && uhp->uh_alt_next.ptr->uh_walk != mark) 1501 uhp = uhp->uh_alt_next.ptr; 1502 else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL 1503 && uhp->uh_next.ptr->uh_walk != mark) 1504 uhp = uhp->uh_next.ptr; 1505 else if (uhp->uh_alt_prev.ptr != NULL) 1506 uhp = uhp->uh_alt_prev.ptr; 1507 else 1508 uhp = uhp->uh_next.ptr; 1509 } 1510 1511 if (put_bytes(fp, (long_u)UF_HEADER_END_MAGIC, 2) == OK) 1512 write_ok = TRUE; 1513 #ifdef U_DEBUG 1514 if (headers_written != buf->b_u_numhead) 1515 EMSG3("Written %ld headers, but numhead is %ld", 1516 headers_written, buf->b_u_numhead); 1517 #endif 1518 1519 write_error: 1520 fclose(fp); 1521 if (!write_ok) 1522 EMSG2(_("E829: write error in undo file: %s"), file_name); 1523 1524 #if defined(MACOS_CLASSIC) || defined(WIN3264) 1525 /* Copy file attributes; for systems where this can only be done after 1526 * closing the file. */ 1527 if (buf->b_ffname != NULL) 1528 (void)mch_copy_file_attribute(buf->b_ffname, file_name); 1529 #endif 1530 #ifdef HAVE_ACL 1531 if (buf->b_ffname != NULL) 1532 { 1533 vim_acl_T acl; 1534 1535 /* For systems that support ACL: get the ACL from the original file. */ 1536 acl = mch_get_acl(buf->b_ffname); 1537 mch_set_acl(file_name, acl); 1538 } 1539 #endif 1540 1541 theend: 1542 #ifdef FEAT_CRYPT 1543 if (do_crypt) 1544 crypt_pop_state(); 1545 #endif 1546 if (file_name != name) 1547 vim_free(file_name); 1548 } 1549 1550 /* 1551 * Load the undo tree from an undo file. 1552 * If "name" is not NULL use it as the undo file name. This also means being 1553 * a bit more verbose. 1554 * Otherwise use curbuf->b_ffname to generate the undo file name. 1555 * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. 1556 */ 1557 void 1558 u_read_undo(name, hash, orig_name) 1559 char_u *name; 1560 char_u *hash; 1561 char_u *orig_name; 1562 { 1563 char_u *file_name; 1564 FILE *fp; 1565 long version, str_len; 1566 char_u *line_ptr = NULL; 1567 linenr_T line_lnum; 1568 colnr_T line_colnr; 1569 linenr_T line_count; 1570 int num_head = 0; 1571 long old_header_seq, new_header_seq, cur_header_seq; 1572 long seq_last, seq_cur; 1573 long last_save_nr = 0; 1574 short old_idx = -1, new_idx = -1, cur_idx = -1; 1575 long num_read_uhps = 0; 1576 time_t seq_time; 1577 int i, j; 1578 int c; 1579 u_header_T *uhp; 1580 u_header_T **uhp_table = NULL; 1581 char_u read_hash[UNDO_HASH_SIZE]; 1582 char_u magic_buf[UF_START_MAGIC_LEN]; 1583 #ifdef U_DEBUG 1584 int *uhp_table_used; 1585 #endif 1586 #ifdef UNIX 1587 struct stat st_orig; 1588 struct stat st_undo; 1589 #endif 1590 #ifdef FEAT_CRYPT 1591 int do_decrypt = FALSE; 1592 #endif 1593 1594 if (name == NULL) 1595 { 1596 file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE); 1597 if (file_name == NULL) 1598 return; 1599 1600 #ifdef UNIX 1601 /* For safety we only read an undo file if the owner is equal to the 1602 * owner of the text file. */ 1603 if (mch_stat((char *)orig_name, &st_orig) >= 0 1604 && mch_stat((char *)file_name, &st_undo) >= 0 1605 && st_orig.st_uid != st_undo.st_uid) 1606 { 1607 if (p_verbose > 0) 1608 { 1609 verbose_enter(); 1610 smsg((char_u *)_("Not reading undo file, owner differs: %s"), 1611 file_name); 1612 verbose_leave(); 1613 } 1614 return; 1615 } 1616 #endif 1617 } 1618 else 1619 file_name = name; 1620 1621 if (p_verbose > 0) 1622 { 1623 verbose_enter(); 1624 smsg((char_u *)_("Reading undo file: %s"), file_name); 1625 verbose_leave(); 1626 } 1627 1628 fp = mch_fopen((char *)file_name, "r"); 1629 if (fp == NULL) 1630 { 1631 if (name != NULL || p_verbose > 0) 1632 EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name); 1633 goto error; 1634 } 1635 1636 /* 1637 * Read the undo file header. 1638 */ 1639 if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1 1640 || memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) 1641 { 1642 EMSG2(_("E823: Not an undo file: %s"), file_name); 1643 goto error; 1644 } 1645 version = get2c(fp); 1646 if (version == UF_VERSION_CRYPT) 1647 { 1648 #ifdef FEAT_CRYPT 1649 if (*curbuf->b_p_key == NUL) 1650 { 1651 EMSG2(_("E832: Non-encrypted file has encrypted undo file: %s"), 1652 file_name); 1653 goto error; 1654 } 1655 if (prepare_crypt_read(fp) == FAIL) 1656 { 1657 EMSG2(_("E826: Undo file decryption failed: %s"), file_name); 1658 goto error; 1659 } 1660 do_decrypt = TRUE; 1661 #else 1662 EMSG2(_("E827: Undo file is encrypted: %s"), file_name); 1663 goto error; 1664 #endif 1665 } 1666 else if (version != UF_VERSION) 1667 { 1668 EMSG2(_("E824: Incompatible undo file: %s"), file_name); 1669 goto error; 1670 } 1671 1672 if (fread(read_hash, UNDO_HASH_SIZE, 1, fp) != 1) 1673 { 1674 corruption_error("hash", file_name); 1675 goto error; 1676 } 1677 line_count = (linenr_T)get4c(fp); 1678 if (memcmp(hash, read_hash, UNDO_HASH_SIZE) != 0 1679 || line_count != curbuf->b_ml.ml_line_count) 1680 { 1681 if (p_verbose > 0 || name != NULL) 1682 { 1683 if (name == NULL) 1684 verbose_enter(); 1685 give_warning((char_u *) 1686 _("File contents changed, cannot use undo info"), TRUE); 1687 if (name == NULL) 1688 verbose_leave(); 1689 } 1690 goto error; 1691 } 1692 1693 /* Read undo data for "U" command. */ 1694 str_len = get4c(fp); 1695 if (str_len < 0) 1696 goto error; 1697 if (str_len > 0) 1698 line_ptr = read_string_decrypt(curbuf, fp, str_len); 1699 line_lnum = (linenr_T)get4c(fp); 1700 line_colnr = (colnr_T)get4c(fp); 1701 if (line_lnum < 0 || line_colnr < 0) 1702 { 1703 corruption_error("line lnum/col", file_name); 1704 goto error; 1705 } 1706 1707 /* Begin general undo data */ 1708 old_header_seq = get4c(fp); 1709 new_header_seq = get4c(fp); 1710 cur_header_seq = get4c(fp); 1711 num_head = get4c(fp); 1712 seq_last = get4c(fp); 1713 seq_cur = get4c(fp); 1714 seq_time = get8ctime(fp); 1715 1716 /* Optional header fields. */ 1717 for (;;) 1718 { 1719 int len = getc(fp); 1720 int what; 1721 1722 if (len == 0 || len == EOF) 1723 break; 1724 what = getc(fp); 1725 switch (what) 1726 { 1727 case UF_LAST_SAVE_NR: 1728 last_save_nr = get4c(fp); 1729 break; 1730 default: 1731 /* field not supported, skip */ 1732 while (--len >= 0) 1733 (void)getc(fp); 1734 } 1735 } 1736 1737 /* uhp_table will store the freshly created undo headers we allocate 1738 * until we insert them into curbuf. The table remains sorted by the 1739 * sequence numbers of the headers. 1740 * When there are no headers uhp_table is NULL. */ 1741 if (num_head > 0) 1742 { 1743 uhp_table = (u_header_T **)U_ALLOC_LINE( 1744 num_head * sizeof(u_header_T *)); 1745 if (uhp_table == NULL) 1746 goto error; 1747 } 1748 1749 while ((c = get2c(fp)) == UF_HEADER_MAGIC) 1750 { 1751 if (num_read_uhps >= num_head) 1752 { 1753 corruption_error("num_head too small", file_name); 1754 goto error; 1755 } 1756 1757 uhp = unserialize_uhp(fp, file_name); 1758 if (uhp == NULL) 1759 goto error; 1760 uhp_table[num_read_uhps++] = uhp; 1761 } 1762 1763 if (num_read_uhps != num_head) 1764 { 1765 corruption_error("num_head", file_name); 1766 goto error; 1767 } 1768 if (c != UF_HEADER_END_MAGIC) 1769 { 1770 corruption_error("end marker", file_name); 1771 goto error; 1772 } 1773 1774 #ifdef U_DEBUG 1775 uhp_table_used = (int *)alloc_clear( 1776 (unsigned)(sizeof(int) * num_head + 1)); 1777 # define SET_FLAG(j) ++uhp_table_used[j] 1778 #else 1779 # define SET_FLAG(j) 1780 #endif 1781 1782 /* We have put all of the headers into a table. Now we iterate through the 1783 * table and swizzle each sequence number we have stored in uh_*_seq into 1784 * a pointer corresponding to the header with that sequence number. */ 1785 for (i = 0; i < num_head; i++) 1786 { 1787 uhp = uhp_table[i]; 1788 if (uhp == NULL) 1789 continue; 1790 for (j = 0; j < num_head; j++) 1791 if (uhp_table[j] != NULL && i != j 1792 && uhp_table[i]->uh_seq == uhp_table[j]->uh_seq) 1793 { 1794 corruption_error("duplicate uh_seq", file_name); 1795 goto error; 1796 } 1797 for (j = 0; j < num_head; j++) 1798 if (uhp_table[j] != NULL 1799 && uhp_table[j]->uh_seq == uhp->uh_next.seq) 1800 { 1801 uhp->uh_next.ptr = uhp_table[j]; 1802 SET_FLAG(j); 1803 break; 1804 } 1805 for (j = 0; j < num_head; j++) 1806 if (uhp_table[j] != NULL 1807 && uhp_table[j]->uh_seq == uhp->uh_prev.seq) 1808 { 1809 uhp->uh_prev.ptr = uhp_table[j]; 1810 SET_FLAG(j); 1811 break; 1812 } 1813 for (j = 0; j < num_head; j++) 1814 if (uhp_table[j] != NULL 1815 && uhp_table[j]->uh_seq == uhp->uh_alt_next.seq) 1816 { 1817 uhp->uh_alt_next.ptr = uhp_table[j]; 1818 SET_FLAG(j); 1819 break; 1820 } 1821 for (j = 0; j < num_head; j++) 1822 if (uhp_table[j] != NULL 1823 && uhp_table[j]->uh_seq == uhp->uh_alt_prev.seq) 1824 { 1825 uhp->uh_alt_prev.ptr = uhp_table[j]; 1826 SET_FLAG(j); 1827 break; 1828 } 1829 if (old_header_seq > 0 && old_idx < 0 && uhp->uh_seq == old_header_seq) 1830 { 1831 old_idx = i; 1832 SET_FLAG(i); 1833 } 1834 if (new_header_seq > 0 && new_idx < 0 && uhp->uh_seq == new_header_seq) 1835 { 1836 new_idx = i; 1837 SET_FLAG(i); 1838 } 1839 if (cur_header_seq > 0 && cur_idx < 0 && uhp->uh_seq == cur_header_seq) 1840 { 1841 cur_idx = i; 1842 SET_FLAG(i); 1843 } 1844 } 1845 1846 /* Now that we have read the undo info successfully, free the current undo 1847 * info and use the info from the file. */ 1848 u_blockfree(curbuf); 1849 curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx]; 1850 curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx]; 1851 curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx]; 1852 curbuf->b_u_line_ptr = line_ptr; 1853 curbuf->b_u_line_lnum = line_lnum; 1854 curbuf->b_u_line_colnr = line_colnr; 1855 curbuf->b_u_numhead = num_head; 1856 curbuf->b_u_seq_last = seq_last; 1857 curbuf->b_u_seq_cur = seq_cur; 1858 curbuf->b_u_time_cur = seq_time; 1859 curbuf->b_u_save_nr_last = last_save_nr; 1860 curbuf->b_u_save_nr_cur = last_save_nr; 1861 1862 curbuf->b_u_synced = TRUE; 1863 vim_free(uhp_table); 1864 1865 #ifdef U_DEBUG 1866 for (i = 0; i < num_head; ++i) 1867 if (uhp_table_used[i] == 0) 1868 EMSGN("uhp_table entry %ld not used, leaking memory", i); 1869 vim_free(uhp_table_used); 1870 u_check(TRUE); 1871 #endif 1872 1873 if (name != NULL) 1874 smsg((char_u *)_("Finished reading undo file %s"), file_name); 1875 goto theend; 1876 1877 error: 1878 vim_free(line_ptr); 1879 if (uhp_table != NULL) 1880 { 1881 for (i = 0; i < num_read_uhps; i++) 1882 if (uhp_table[i] != NULL) 1883 u_free_uhp(uhp_table[i]); 1884 vim_free(uhp_table); 1885 } 1886 1887 theend: 1888 #ifdef FEAT_CRYPT 1889 if (do_decrypt) 1890 crypt_pop_state(); 1891 #endif 1892 if (fp != NULL) 1893 fclose(fp); 1894 if (file_name != name) 1895 vim_free(file_name); 1896 return; 1897 } 1898 1899 #endif /* FEAT_PERSISTENT_UNDO */ 1900 1901 1902 /* 1903 * If 'cpoptions' contains 'u': Undo the previous undo or redo (vi compatible). 1904 * If 'cpoptions' does not contain 'u': Always undo. 1905 */ 1906 void 1907 u_undo(count) 1908 int count; 1909 { 1910 /* 1911 * If we get an undo command while executing a macro, we behave like the 1912 * original vi. If this happens twice in one macro the result will not 1913 * be compatible. 1914 */ 1915 if (curbuf->b_u_synced == FALSE) 1916 { 1917 u_sync(TRUE); 1918 count = 1; 1919 } 1920 1921 if (vim_strchr(p_cpo, CPO_UNDO) == NULL) 1922 undo_undoes = TRUE; 1923 else 1924 undo_undoes = !undo_undoes; 1925 u_doit(count); 1926 } 1927 1928 /* 1929 * If 'cpoptions' contains 'u': Repeat the previous undo or redo. 1930 * If 'cpoptions' does not contain 'u': Always redo. 1931 */ 1932 void 1933 u_redo(count) 1934 int count; 1935 { 1936 if (vim_strchr(p_cpo, CPO_UNDO) == NULL) 1937 undo_undoes = FALSE; 1938 u_doit(count); 1939 } 1940 1941 /* 1942 * Undo or redo, depending on 'undo_undoes', 'count' times. 1943 */ 1944 static void 1945 u_doit(startcount) 1946 int startcount; 1947 { 1948 int count = startcount; 1949 1950 if (!undo_allowed()) 1951 return; 1952 1953 u_newcount = 0; 1954 u_oldcount = 0; 1955 if (curbuf->b_ml.ml_flags & ML_EMPTY) 1956 u_oldcount = -1; 1957 while (count--) 1958 { 1959 /* Do the change warning now, so that it triggers FileChangedRO when 1960 * needed. This may cause the file to be reloaded, that must happen 1961 * before we do anything, because it may change curbuf->b_u_curhead 1962 * and more. */ 1963 change_warning(0); 1964 1965 if (undo_undoes) 1966 { 1967 if (curbuf->b_u_curhead == NULL) /* first undo */ 1968 curbuf->b_u_curhead = curbuf->b_u_newhead; 1969 else if (p_ul > 0) /* multi level undo */ 1970 /* get next undo */ 1971 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next.ptr; 1972 /* nothing to undo */ 1973 if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL) 1974 { 1975 /* stick curbuf->b_u_curhead at end */ 1976 curbuf->b_u_curhead = curbuf->b_u_oldhead; 1977 beep_flush(); 1978 if (count == startcount - 1) 1979 { 1980 MSG(_("Already at oldest change")); 1981 return; 1982 } 1983 break; 1984 } 1985 1986 u_undoredo(TRUE); 1987 } 1988 else 1989 { 1990 if (curbuf->b_u_curhead == NULL || p_ul <= 0) 1991 { 1992 beep_flush(); /* nothing to redo */ 1993 if (count == startcount - 1) 1994 { 1995 MSG(_("Already at newest change")); 1996 return; 1997 } 1998 break; 1999 } 2000 2001 u_undoredo(FALSE); 2002 2003 /* Advance for next redo. Set "newhead" when at the end of the 2004 * redoable changes. */ 2005 if (curbuf->b_u_curhead->uh_prev.ptr == NULL) 2006 curbuf->b_u_newhead = curbuf->b_u_curhead; 2007 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev.ptr; 2008 } 2009 } 2010 u_undo_end(undo_undoes, FALSE); 2011 } 2012 2013 /* 2014 * Undo or redo over the timeline. 2015 * When "step" is negative go back in time, otherwise goes forward in time. 2016 * When "sec" is FALSE make "step" steps, when "sec" is TRUE use "step" as 2017 * seconds. 2018 * When "file" is TRUE use "step" as a number of file writes. 2019 * When "absolute" is TRUE use "step" as the sequence number to jump to. 2020 * "sec" must be FALSE then. 2021 */ 2022 void 2023 undo_time(step, sec, file, absolute) 2024 long step; 2025 int sec; 2026 int file; 2027 int absolute; 2028 { 2029 long target; 2030 long closest; 2031 long closest_start; 2032 long closest_seq = 0; 2033 long val; 2034 u_header_T *uhp; 2035 u_header_T *last; 2036 int mark; 2037 int nomark; 2038 int round; 2039 int dosec = sec; 2040 int dofile = file; 2041 int above = FALSE; 2042 int did_undo = TRUE; 2043 2044 /* First make sure the current undoable change is synced. */ 2045 if (curbuf->b_u_synced == FALSE) 2046 u_sync(TRUE); 2047 2048 u_newcount = 0; 2049 u_oldcount = 0; 2050 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2051 u_oldcount = -1; 2052 2053 /* "target" is the node below which we want to be. 2054 * Init "closest" to a value we can't reach. */ 2055 if (absolute) 2056 { 2057 target = step; 2058 closest = -1; 2059 } 2060 else 2061 { 2062 /* When doing computations with time_t subtract starttime, because 2063 * time_t converted to a long may result in a wrong number. */ 2064 if (dosec) 2065 target = (long)(curbuf->b_u_time_cur - starttime) + step; 2066 else if (dofile) 2067 { 2068 if (step < 0) 2069 { 2070 /* Going back to a previous write. If there were changes after 2071 * the last write, count that as moving one file-write, so 2072 * that ":earlier 1f" undoes all changes since the last save. */ 2073 uhp = curbuf->b_u_curhead; 2074 if (uhp != NULL) 2075 uhp = uhp->uh_next.ptr; 2076 else 2077 uhp = curbuf->b_u_newhead; 2078 if (uhp != NULL && uhp->uh_save_nr != 0) 2079 /* "uh_save_nr" was set in the last block, that means 2080 * there were no changes since the last write */ 2081 target = curbuf->b_u_save_nr_cur + step; 2082 else 2083 /* count the changes since the last write as one step */ 2084 target = curbuf->b_u_save_nr_cur + step + 1; 2085 if (target <= 0) 2086 /* Go to before first write: before the oldest change. Use 2087 * the sequence number for that. */ 2088 dofile = FALSE; 2089 } 2090 else 2091 { 2092 /* Moving forward to a newer write. */ 2093 target = curbuf->b_u_save_nr_cur + step; 2094 if (target > curbuf->b_u_save_nr_last) 2095 { 2096 /* Go to after last write: after the latest change. Use 2097 * the sequence number for that. */ 2098 target = curbuf->b_u_seq_last + 1; 2099 dofile = FALSE; 2100 } 2101 } 2102 } 2103 else 2104 target = curbuf->b_u_seq_cur + step; 2105 if (step < 0) 2106 { 2107 if (target < 0) 2108 target = 0; 2109 closest = -1; 2110 } 2111 else 2112 { 2113 if (dosec) 2114 closest = (long)(time(NULL) - starttime + 1); 2115 else if (dofile) 2116 closest = curbuf->b_u_save_nr_last + 2; 2117 else 2118 closest = curbuf->b_u_seq_last + 2; 2119 if (target >= closest) 2120 target = closest - 1; 2121 } 2122 } 2123 closest_start = closest; 2124 closest_seq = curbuf->b_u_seq_cur; 2125 2126 /* 2127 * May do this twice: 2128 * 1. Search for "target", update "closest" to the best match found. 2129 * 2. If "target" not found search for "closest". 2130 * 2131 * When using the closest time we use the sequence number in the second 2132 * round, because there may be several entries with the same time. 2133 */ 2134 for (round = 1; round <= 2; ++round) 2135 { 2136 /* Find the path from the current state to where we want to go. The 2137 * desired state can be anywhere in the undo tree, need to go all over 2138 * it. We put "nomark" in uh_walk where we have been without success, 2139 * "mark" where it could possibly be. */ 2140 mark = ++lastmark; 2141 nomark = ++lastmark; 2142 2143 if (curbuf->b_u_curhead == NULL) /* at leaf of the tree */ 2144 uhp = curbuf->b_u_newhead; 2145 else 2146 uhp = curbuf->b_u_curhead; 2147 2148 while (uhp != NULL) 2149 { 2150 uhp->uh_walk = mark; 2151 if (dosec) 2152 val = (long)(uhp->uh_time - starttime); 2153 else if (dofile) 2154 val = uhp->uh_save_nr; 2155 else 2156 val = uhp->uh_seq; 2157 2158 if (round == 1 && !(dofile && val == 0)) 2159 { 2160 /* Remember the header that is closest to the target. 2161 * It must be at least in the right direction (checked with 2162 * "b_u_seq_cur"). When the timestamp is equal find the 2163 * highest/lowest sequence number. */ 2164 if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur 2165 : uhp->uh_seq > curbuf->b_u_seq_cur) 2166 && ((dosec && val == closest) 2167 ? (step < 0 2168 ? uhp->uh_seq < closest_seq 2169 : uhp->uh_seq > closest_seq) 2170 : closest == closest_start 2171 || (val > target 2172 ? (closest > target 2173 ? val - target <= closest - target 2174 : val - target <= target - closest) 2175 : (closest > target 2176 ? target - val <= closest - target 2177 : target - val <= target - closest)))) 2178 { 2179 closest = val; 2180 closest_seq = uhp->uh_seq; 2181 } 2182 } 2183 2184 /* Quit searching when we found a match. But when searching for a 2185 * time we need to continue looking for the best uh_seq. */ 2186 if (target == val && !dosec) 2187 { 2188 target = uhp->uh_seq; 2189 break; 2190 } 2191 2192 /* go down in the tree if we haven't been there */ 2193 if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark 2194 && uhp->uh_prev.ptr->uh_walk != mark) 2195 uhp = uhp->uh_prev.ptr; 2196 2197 /* go to alternate branch if we haven't been there */ 2198 else if (uhp->uh_alt_next.ptr != NULL 2199 && uhp->uh_alt_next.ptr->uh_walk != nomark 2200 && uhp->uh_alt_next.ptr->uh_walk != mark) 2201 uhp = uhp->uh_alt_next.ptr; 2202 2203 /* go up in the tree if we haven't been there and we are at the 2204 * start of alternate branches */ 2205 else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL 2206 && uhp->uh_next.ptr->uh_walk != nomark 2207 && uhp->uh_next.ptr->uh_walk != mark) 2208 { 2209 /* If still at the start we don't go through this change. */ 2210 if (uhp == curbuf->b_u_curhead) 2211 uhp->uh_walk = nomark; 2212 uhp = uhp->uh_next.ptr; 2213 } 2214 2215 else 2216 { 2217 /* need to backtrack; mark this node as useless */ 2218 uhp->uh_walk = nomark; 2219 if (uhp->uh_alt_prev.ptr != NULL) 2220 uhp = uhp->uh_alt_prev.ptr; 2221 else 2222 uhp = uhp->uh_next.ptr; 2223 } 2224 } 2225 2226 if (uhp != NULL) /* found it */ 2227 break; 2228 2229 if (absolute) 2230 { 2231 EMSGN(_("E830: Undo number %ld not found"), step); 2232 return; 2233 } 2234 2235 if (closest == closest_start) 2236 { 2237 if (step < 0) 2238 MSG(_("Already at oldest change")); 2239 else 2240 MSG(_("Already at newest change")); 2241 return; 2242 } 2243 2244 target = closest_seq; 2245 dosec = FALSE; 2246 dofile = FALSE; 2247 if (step < 0) 2248 above = TRUE; /* stop above the header */ 2249 } 2250 2251 /* If we found it: Follow the path to go to where we want to be. */ 2252 if (uhp != NULL) 2253 { 2254 /* 2255 * First go up the tree as much as needed. 2256 */ 2257 while (!got_int) 2258 { 2259 /* Do the change warning now, for the same reason as above. */ 2260 change_warning(0); 2261 2262 uhp = curbuf->b_u_curhead; 2263 if (uhp == NULL) 2264 uhp = curbuf->b_u_newhead; 2265 else 2266 uhp = uhp->uh_next.ptr; 2267 if (uhp == NULL || uhp->uh_walk != mark 2268 || (uhp->uh_seq == target && !above)) 2269 break; 2270 curbuf->b_u_curhead = uhp; 2271 u_undoredo(TRUE); 2272 uhp->uh_walk = nomark; /* don't go back down here */ 2273 } 2274 2275 /* 2276 * And now go down the tree (redo), branching off where needed. 2277 */ 2278 while (!got_int) 2279 { 2280 /* Do the change warning now, for the same reason as above. */ 2281 change_warning(0); 2282 2283 uhp = curbuf->b_u_curhead; 2284 if (uhp == NULL) 2285 break; 2286 2287 /* Go back to the first branch with a mark. */ 2288 while (uhp->uh_alt_prev.ptr != NULL 2289 && uhp->uh_alt_prev.ptr->uh_walk == mark) 2290 uhp = uhp->uh_alt_prev.ptr; 2291 2292 /* Find the last branch with a mark, that's the one. */ 2293 last = uhp; 2294 while (last->uh_alt_next.ptr != NULL 2295 && last->uh_alt_next.ptr->uh_walk == mark) 2296 last = last->uh_alt_next.ptr; 2297 if (last != uhp) 2298 { 2299 /* Make the used branch the first entry in the list of 2300 * alternatives to make "u" and CTRL-R take this branch. */ 2301 while (uhp->uh_alt_prev.ptr != NULL) 2302 uhp = uhp->uh_alt_prev.ptr; 2303 if (last->uh_alt_next.ptr != NULL) 2304 last->uh_alt_next.ptr->uh_alt_prev.ptr = 2305 last->uh_alt_prev.ptr; 2306 last->uh_alt_prev.ptr->uh_alt_next.ptr = last->uh_alt_next.ptr; 2307 last->uh_alt_prev.ptr = NULL; 2308 last->uh_alt_next.ptr = uhp; 2309 uhp->uh_alt_prev.ptr = last; 2310 2311 if (curbuf->b_u_oldhead == uhp) 2312 curbuf->b_u_oldhead = last; 2313 uhp = last; 2314 if (uhp->uh_next.ptr != NULL) 2315 uhp->uh_next.ptr->uh_prev.ptr = uhp; 2316 } 2317 curbuf->b_u_curhead = uhp; 2318 2319 if (uhp->uh_walk != mark) 2320 break; /* must have reached the target */ 2321 2322 /* Stop when going backwards in time and didn't find the exact 2323 * header we were looking for. */ 2324 if (uhp->uh_seq == target && above) 2325 { 2326 curbuf->b_u_seq_cur = target - 1; 2327 break; 2328 } 2329 2330 u_undoredo(FALSE); 2331 2332 /* Advance "curhead" to below the header we last used. If it 2333 * becomes NULL then we need to set "newhead" to this leaf. */ 2334 if (uhp->uh_prev.ptr == NULL) 2335 curbuf->b_u_newhead = uhp; 2336 curbuf->b_u_curhead = uhp->uh_prev.ptr; 2337 did_undo = FALSE; 2338 2339 if (uhp->uh_seq == target) /* found it! */ 2340 break; 2341 2342 uhp = uhp->uh_prev.ptr; 2343 if (uhp == NULL || uhp->uh_walk != mark) 2344 { 2345 /* Need to redo more but can't find it... */ 2346 EMSG2(_(e_intern2), "undo_time()"); 2347 break; 2348 } 2349 } 2350 } 2351 u_undo_end(did_undo, absolute); 2352 } 2353 2354 /* 2355 * u_undoredo: common code for undo and redo 2356 * 2357 * The lines in the file are replaced by the lines in the entry list at 2358 * curbuf->b_u_curhead. The replaced lines in the file are saved in the entry 2359 * list for the next undo/redo. 2360 * 2361 * When "undo" is TRUE we go up in the tree, when FALSE we go down. 2362 */ 2363 static void 2364 u_undoredo(undo) 2365 int undo; 2366 { 2367 char_u **newarray = NULL; 2368 linenr_T oldsize; 2369 linenr_T newsize; 2370 linenr_T top, bot; 2371 linenr_T lnum; 2372 linenr_T newlnum = MAXLNUM; 2373 long i; 2374 u_entry_T *uep, *nuep; 2375 u_entry_T *newlist = NULL; 2376 int old_flags; 2377 int new_flags; 2378 pos_T namedm[NMARKS]; 2379 #ifdef FEAT_VISUAL 2380 visualinfo_T visualinfo; 2381 #endif 2382 int empty_buffer; /* buffer became empty */ 2383 u_header_T *curhead = curbuf->b_u_curhead; 2384 2385 #ifdef FEAT_AUTOCMD 2386 /* Don't want autocommands using the undo structures here, they are 2387 * invalid till the end. */ 2388 block_autocmds(); 2389 #endif 2390 2391 #ifdef U_DEBUG 2392 u_check(FALSE); 2393 #endif 2394 old_flags = curhead->uh_flags; 2395 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 2396 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); 2397 setpcmark(); 2398 2399 /* 2400 * save marks before undo/redo 2401 */ 2402 mch_memmove(namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS); 2403 #ifdef FEAT_VISUAL 2404 visualinfo = curbuf->b_visual; 2405 #endif 2406 curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count; 2407 curbuf->b_op_start.col = 0; 2408 curbuf->b_op_end.lnum = 0; 2409 curbuf->b_op_end.col = 0; 2410 2411 for (uep = curhead->uh_entry; uep != NULL; uep = nuep) 2412 { 2413 top = uep->ue_top; 2414 bot = uep->ue_bot; 2415 if (bot == 0) 2416 bot = curbuf->b_ml.ml_line_count + 1; 2417 if (top > curbuf->b_ml.ml_line_count || top >= bot 2418 || bot > curbuf->b_ml.ml_line_count + 1) 2419 { 2420 #ifdef FEAT_AUTOCMD 2421 unblock_autocmds(); 2422 #endif 2423 EMSG(_("E438: u_undo: line numbers wrong")); 2424 changed(); /* don't want UNCHANGED now */ 2425 return; 2426 } 2427 2428 oldsize = bot - top - 1; /* number of lines before undo */ 2429 newsize = uep->ue_size; /* number of lines after undo */ 2430 2431 if (top < newlnum) 2432 { 2433 /* If the saved cursor is somewhere in this undo block, move it to 2434 * the remembered position. Makes "gwap" put the cursor back 2435 * where it was. */ 2436 lnum = curhead->uh_cursor.lnum; 2437 if (lnum >= top && lnum <= top + newsize + 1) 2438 { 2439 curwin->w_cursor = curhead->uh_cursor; 2440 newlnum = curwin->w_cursor.lnum - 1; 2441 } 2442 else 2443 { 2444 /* Use the first line that actually changed. Avoids that 2445 * undoing auto-formatting puts the cursor in the previous 2446 * line. */ 2447 for (i = 0; i < newsize && i < oldsize; ++i) 2448 if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0) 2449 break; 2450 if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL) 2451 { 2452 newlnum = top; 2453 curwin->w_cursor.lnum = newlnum + 1; 2454 } 2455 else if (i < newsize) 2456 { 2457 newlnum = top + i; 2458 curwin->w_cursor.lnum = newlnum + 1; 2459 } 2460 } 2461 } 2462 2463 empty_buffer = FALSE; 2464 2465 /* delete the lines between top and bot and save them in newarray */ 2466 if (oldsize > 0) 2467 { 2468 if ((newarray = (char_u **)U_ALLOC_LINE( 2469 sizeof(char_u *) * oldsize)) == NULL) 2470 { 2471 do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize)); 2472 /* 2473 * We have messed up the entry list, repair is impossible. 2474 * we have to free the rest of the list. 2475 */ 2476 while (uep != NULL) 2477 { 2478 nuep = uep->ue_next; 2479 u_freeentry(uep, uep->ue_size); 2480 uep = nuep; 2481 } 2482 break; 2483 } 2484 /* delete backwards, it goes faster in most cases */ 2485 for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) 2486 { 2487 /* what can we do when we run out of memory? */ 2488 if ((newarray[i] = u_save_line(lnum)) == NULL) 2489 do_outofmem_msg((long_u)0); 2490 /* remember we deleted the last line in the buffer, and a 2491 * dummy empty line will be inserted */ 2492 if (curbuf->b_ml.ml_line_count == 1) 2493 empty_buffer = TRUE; 2494 ml_delete(lnum, FALSE); 2495 } 2496 } 2497 else 2498 newarray = NULL; 2499 2500 /* insert the lines in u_array between top and bot */ 2501 if (newsize) 2502 { 2503 for (lnum = top, i = 0; i < newsize; ++i, ++lnum) 2504 { 2505 /* 2506 * If the file is empty, there is an empty line 1 that we 2507 * should get rid of, by replacing it with the new line 2508 */ 2509 if (empty_buffer && lnum == 0) 2510 ml_replace((linenr_T)1, uep->ue_array[i], TRUE); 2511 else 2512 ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE); 2513 vim_free(uep->ue_array[i]); 2514 } 2515 vim_free((char_u *)uep->ue_array); 2516 } 2517 2518 /* adjust marks */ 2519 if (oldsize != newsize) 2520 { 2521 mark_adjust(top + 1, top + oldsize, (long)MAXLNUM, 2522 (long)newsize - (long)oldsize); 2523 if (curbuf->b_op_start.lnum > top + oldsize) 2524 curbuf->b_op_start.lnum += newsize - oldsize; 2525 if (curbuf->b_op_end.lnum > top + oldsize) 2526 curbuf->b_op_end.lnum += newsize - oldsize; 2527 } 2528 2529 changed_lines(top + 1, 0, bot, newsize - oldsize); 2530 2531 /* set '[ and '] mark */ 2532 if (top + 1 < curbuf->b_op_start.lnum) 2533 curbuf->b_op_start.lnum = top + 1; 2534 if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) 2535 curbuf->b_op_end.lnum = top + 1; 2536 else if (top + newsize > curbuf->b_op_end.lnum) 2537 curbuf->b_op_end.lnum = top + newsize; 2538 2539 u_newcount += newsize; 2540 u_oldcount += oldsize; 2541 uep->ue_size = oldsize; 2542 uep->ue_array = newarray; 2543 uep->ue_bot = top + newsize + 1; 2544 2545 /* 2546 * insert this entry in front of the new entry list 2547 */ 2548 nuep = uep->ue_next; 2549 uep->ue_next = newlist; 2550 newlist = uep; 2551 } 2552 2553 curhead->uh_entry = newlist; 2554 curhead->uh_flags = new_flags; 2555 if ((old_flags & UH_EMPTYBUF) && bufempty()) 2556 curbuf->b_ml.ml_flags |= ML_EMPTY; 2557 if (old_flags & UH_CHANGED) 2558 changed(); 2559 else 2560 #ifdef FEAT_NETBEANS_INTG 2561 /* per netbeans undo rules, keep it as modified */ 2562 if (!isNetbeansModified(curbuf)) 2563 #endif 2564 unchanged(curbuf, FALSE); 2565 2566 /* 2567 * restore marks from before undo/redo 2568 */ 2569 for (i = 0; i < NMARKS; ++i) 2570 if (curhead->uh_namedm[i].lnum != 0) 2571 { 2572 curbuf->b_namedm[i] = curhead->uh_namedm[i]; 2573 curhead->uh_namedm[i] = namedm[i]; 2574 } 2575 #ifdef FEAT_VISUAL 2576 if (curhead->uh_visual.vi_start.lnum != 0) 2577 { 2578 curbuf->b_visual = curhead->uh_visual; 2579 curhead->uh_visual = visualinfo; 2580 } 2581 #endif 2582 2583 /* 2584 * If the cursor is only off by one line, put it at the same position as 2585 * before starting the change (for the "o" command). 2586 * Otherwise the cursor should go to the first undone line. 2587 */ 2588 if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum 2589 && curwin->w_cursor.lnum > 1) 2590 --curwin->w_cursor.lnum; 2591 if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count) 2592 { 2593 if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum) 2594 { 2595 curwin->w_cursor.col = curhead->uh_cursor.col; 2596 #ifdef FEAT_VIRTUALEDIT 2597 if (virtual_active() && curhead->uh_cursor_vcol >= 0) 2598 coladvance((colnr_T)curhead->uh_cursor_vcol); 2599 else 2600 curwin->w_cursor.coladd = 0; 2601 #endif 2602 } 2603 else 2604 beginline(BL_SOL | BL_FIX); 2605 } 2606 else 2607 { 2608 /* We get here with the current cursor line being past the end (eg 2609 * after adding lines at the end of the file, and then undoing it). 2610 * check_cursor() will move the cursor to the last line. Move it to 2611 * the first column here. */ 2612 curwin->w_cursor.col = 0; 2613 #ifdef FEAT_VIRTUALEDIT 2614 curwin->w_cursor.coladd = 0; 2615 #endif 2616 } 2617 2618 /* Make sure the cursor is on an existing line and column. */ 2619 check_cursor(); 2620 2621 /* Remember where we are for "g-" and ":earlier 10s". */ 2622 curbuf->b_u_seq_cur = curhead->uh_seq; 2623 if (undo) 2624 /* We are below the previous undo. However, to make ":earlier 1s" 2625 * work we compute this as being just above the just undone change. */ 2626 --curbuf->b_u_seq_cur; 2627 2628 /* Remember where we are for ":earlier 1f" and ":later 1f". */ 2629 if (curhead->uh_save_nr != 0) 2630 { 2631 if (undo) 2632 curbuf->b_u_save_nr_cur = curhead->uh_save_nr - 1; 2633 else 2634 curbuf->b_u_save_nr_cur = curhead->uh_save_nr; 2635 } 2636 2637 /* The timestamp can be the same for multiple changes, just use the one of 2638 * the undone/redone change. */ 2639 curbuf->b_u_time_cur = curhead->uh_time; 2640 2641 #ifdef FEAT_AUTOCMD 2642 unblock_autocmds(); 2643 #endif 2644 #ifdef U_DEBUG 2645 u_check(FALSE); 2646 #endif 2647 } 2648 2649 /* 2650 * If we deleted or added lines, report the number of less/more lines. 2651 * Otherwise, report the number of changes (this may be incorrect 2652 * in some cases, but it's better than nothing). 2653 */ 2654 static void 2655 u_undo_end(did_undo, absolute) 2656 int did_undo; /* just did an undo */ 2657 int absolute; /* used ":undo N" */ 2658 { 2659 char *msgstr; 2660 u_header_T *uhp; 2661 char_u msgbuf[80]; 2662 2663 #ifdef FEAT_FOLDING 2664 if ((fdo_flags & FDO_UNDO) && KeyTyped) 2665 foldOpenCursor(); 2666 #endif 2667 2668 if (global_busy /* no messages now, wait until global is finished */ 2669 || !messaging()) /* 'lazyredraw' set, don't do messages now */ 2670 return; 2671 2672 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2673 --u_newcount; 2674 2675 u_oldcount -= u_newcount; 2676 if (u_oldcount == -1) 2677 msgstr = N_("more line"); 2678 else if (u_oldcount < 0) 2679 msgstr = N_("more lines"); 2680 else if (u_oldcount == 1) 2681 msgstr = N_("line less"); 2682 else if (u_oldcount > 1) 2683 msgstr = N_("fewer lines"); 2684 else 2685 { 2686 u_oldcount = u_newcount; 2687 if (u_newcount == 1) 2688 msgstr = N_("change"); 2689 else 2690 msgstr = N_("changes"); 2691 } 2692 2693 if (curbuf->b_u_curhead != NULL) 2694 { 2695 /* For ":undo N" we prefer a "after #N" message. */ 2696 if (absolute && curbuf->b_u_curhead->uh_next.ptr != NULL) 2697 { 2698 uhp = curbuf->b_u_curhead->uh_next.ptr; 2699 did_undo = FALSE; 2700 } 2701 else if (did_undo) 2702 uhp = curbuf->b_u_curhead; 2703 else 2704 uhp = curbuf->b_u_curhead->uh_next.ptr; 2705 } 2706 else 2707 uhp = curbuf->b_u_newhead; 2708 2709 if (uhp == NULL) 2710 *msgbuf = NUL; 2711 else 2712 u_add_time(msgbuf, sizeof(msgbuf), uhp->uh_time); 2713 2714 #ifdef FEAT_CONCEAL 2715 { 2716 win_T *wp; 2717 2718 FOR_ALL_WINDOWS(wp) 2719 { 2720 if (wp->w_buffer == curbuf && wp->w_p_cole > 0) 2721 redraw_win_later(wp, NOT_VALID); 2722 } 2723 } 2724 #endif 2725 2726 smsg((char_u *)_("%ld %s; %s #%ld %s"), 2727 u_oldcount < 0 ? -u_oldcount : u_oldcount, 2728 _(msgstr), 2729 did_undo ? _("before") : _("after"), 2730 uhp == NULL ? 0L : uhp->uh_seq, 2731 msgbuf); 2732 } 2733 2734 /* 2735 * u_sync: stop adding to the current entry list 2736 */ 2737 void 2738 u_sync(force) 2739 int force; /* Also sync when no_u_sync is set. */ 2740 { 2741 /* Skip it when already synced or syncing is disabled. */ 2742 if (curbuf->b_u_synced || (!force && no_u_sync > 0)) 2743 return; 2744 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 2745 if (im_is_preediting()) 2746 return; /* XIM is busy, don't break an undo sequence */ 2747 #endif 2748 if (p_ul < 0) 2749 curbuf->b_u_synced = TRUE; /* no entries, nothing to do */ 2750 else 2751 { 2752 u_getbot(); /* compute ue_bot of previous u_save */ 2753 curbuf->b_u_curhead = NULL; 2754 } 2755 } 2756 2757 /* 2758 * ":undolist": List the leafs of the undo tree 2759 */ 2760 void 2761 ex_undolist(eap) 2762 exarg_T *eap UNUSED; 2763 { 2764 garray_T ga; 2765 u_header_T *uhp; 2766 int mark; 2767 int nomark; 2768 int changes = 1; 2769 int i; 2770 2771 /* 2772 * 1: walk the tree to find all leafs, put the info in "ga". 2773 * 2: sort the lines 2774 * 3: display the list 2775 */ 2776 mark = ++lastmark; 2777 nomark = ++lastmark; 2778 ga_init2(&ga, (int)sizeof(char *), 20); 2779 2780 uhp = curbuf->b_u_oldhead; 2781 while (uhp != NULL) 2782 { 2783 if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark 2784 && uhp->uh_walk != mark) 2785 { 2786 if (ga_grow(&ga, 1) == FAIL) 2787 break; 2788 vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7ld ", 2789 uhp->uh_seq, changes); 2790 u_add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), 2791 uhp->uh_time); 2792 if (uhp->uh_save_nr > 0) 2793 { 2794 while (STRLEN(IObuff) < 33) 2795 STRCAT(IObuff, " "); 2796 vim_snprintf_add((char *)IObuff, IOSIZE, 2797 " %3ld", uhp->uh_save_nr); 2798 } 2799 ((char_u **)(ga.ga_data))[ga.ga_len++] = vim_strsave(IObuff); 2800 } 2801 2802 uhp->uh_walk = mark; 2803 2804 /* go down in the tree if we haven't been there */ 2805 if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark 2806 && uhp->uh_prev.ptr->uh_walk != mark) 2807 { 2808 uhp = uhp->uh_prev.ptr; 2809 ++changes; 2810 } 2811 2812 /* go to alternate branch if we haven't been there */ 2813 else if (uhp->uh_alt_next.ptr != NULL 2814 && uhp->uh_alt_next.ptr->uh_walk != nomark 2815 && uhp->uh_alt_next.ptr->uh_walk != mark) 2816 uhp = uhp->uh_alt_next.ptr; 2817 2818 /* go up in the tree if we haven't been there and we are at the 2819 * start of alternate branches */ 2820 else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL 2821 && uhp->uh_next.ptr->uh_walk != nomark 2822 && uhp->uh_next.ptr->uh_walk != mark) 2823 { 2824 uhp = uhp->uh_next.ptr; 2825 --changes; 2826 } 2827 2828 else 2829 { 2830 /* need to backtrack; mark this node as done */ 2831 uhp->uh_walk = nomark; 2832 if (uhp->uh_alt_prev.ptr != NULL) 2833 uhp = uhp->uh_alt_prev.ptr; 2834 else 2835 { 2836 uhp = uhp->uh_next.ptr; 2837 --changes; 2838 } 2839 } 2840 } 2841 2842 if (ga.ga_len == 0) 2843 MSG(_("Nothing to undo")); 2844 else 2845 { 2846 sort_strings((char_u **)ga.ga_data, ga.ga_len); 2847 2848 msg_start(); 2849 msg_puts_attr((char_u *)_("number changes when saved"), 2850 hl_attr(HLF_T)); 2851 for (i = 0; i < ga.ga_len && !got_int; ++i) 2852 { 2853 msg_putchar('\n'); 2854 if (got_int) 2855 break; 2856 msg_puts(((char_u **)ga.ga_data)[i]); 2857 } 2858 msg_end(); 2859 2860 ga_clear_strings(&ga); 2861 } 2862 } 2863 2864 /* 2865 * Put the timestamp of an undo header in "buf[buflen]" in a nice format. 2866 */ 2867 static void 2868 u_add_time(buf, buflen, tt) 2869 char_u *buf; 2870 size_t buflen; 2871 time_t tt; 2872 { 2873 #ifdef HAVE_STRFTIME 2874 struct tm *curtime; 2875 2876 if (time(NULL) - tt >= 100) 2877 { 2878 curtime = localtime(&tt); 2879 if (time(NULL) - tt < (60L * 60L * 12L)) 2880 /* within 12 hours */ 2881 (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime); 2882 else if (time(NULL) - tt < (60L * 60L * 24L * 180L)) 2883 /* within 6 months */ 2884 (void)strftime((char *)buf, buflen, "%m/%d %H:%M:%S", curtime); 2885 else 2886 /* long ago */ 2887 (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime); 2888 } 2889 else 2890 #endif 2891 vim_snprintf((char *)buf, buflen, _("%ld seconds ago"), 2892 (long)(time(NULL) - tt)); 2893 } 2894 2895 /* 2896 * ":undojoin": continue adding to the last entry list 2897 */ 2898 void 2899 ex_undojoin(eap) 2900 exarg_T *eap UNUSED; 2901 { 2902 if (curbuf->b_u_newhead == NULL) 2903 return; /* nothing changed before */ 2904 if (curbuf->b_u_curhead != NULL) 2905 { 2906 EMSG(_("E790: undojoin is not allowed after undo")); 2907 return; 2908 } 2909 if (!curbuf->b_u_synced) 2910 return; /* already unsynced */ 2911 if (p_ul < 0) 2912 return; /* no entries, nothing to do */ 2913 else 2914 { 2915 /* Go back to the last entry */ 2916 curbuf->b_u_curhead = curbuf->b_u_newhead; 2917 curbuf->b_u_synced = FALSE; /* no entries, nothing to do */ 2918 } 2919 } 2920 2921 /* 2922 * Called after writing or reloading the file and setting b_changed to FALSE. 2923 * Now an undo means that the buffer is modified. 2924 */ 2925 void 2926 u_unchanged(buf) 2927 buf_T *buf; 2928 { 2929 u_unch_branch(buf->b_u_oldhead); 2930 buf->b_did_warn = FALSE; 2931 } 2932 2933 /* 2934 * After reloading a buffer which was saved for 'undoreload': Find the first 2935 * line that was changed and set the cursor there. 2936 */ 2937 void 2938 u_find_first_changed() 2939 { 2940 u_header_T *uhp = curbuf->b_u_newhead; 2941 u_entry_T *uep; 2942 linenr_T lnum; 2943 2944 if (curbuf->b_u_curhead != NULL || uhp == NULL) 2945 return; /* undid something in an autocmd? */ 2946 2947 /* Check that the last undo block was for the whole file. */ 2948 uep = uhp->uh_entry; 2949 if (uep->ue_top != 0 || uep->ue_bot != 0) 2950 return; 2951 2952 for (lnum = 1; lnum < curbuf->b_ml.ml_line_count 2953 && lnum <= uep->ue_size; ++lnum) 2954 if (STRCMP(ml_get_buf(curbuf, lnum, FALSE), 2955 uep->ue_array[lnum - 1]) != 0) 2956 { 2957 clearpos(&(uhp->uh_cursor)); 2958 uhp->uh_cursor.lnum = lnum; 2959 return; 2960 } 2961 if (curbuf->b_ml.ml_line_count != uep->ue_size) 2962 { 2963 /* lines added or deleted at the end, put the cursor there */ 2964 clearpos(&(uhp->uh_cursor)); 2965 uhp->uh_cursor.lnum = lnum; 2966 } 2967 } 2968 2969 /* 2970 * Increase the write count, store it in the last undo header, what would be 2971 * used for "u". 2972 */ 2973 void 2974 u_update_save_nr(buf) 2975 buf_T *buf; 2976 { 2977 u_header_T *uhp; 2978 2979 ++buf->b_u_save_nr_last; 2980 buf->b_u_save_nr_cur = buf->b_u_save_nr_last; 2981 uhp = buf->b_u_curhead; 2982 if (uhp != NULL) 2983 uhp = uhp->uh_next.ptr; 2984 else 2985 uhp = buf->b_u_newhead; 2986 if (uhp != NULL) 2987 uhp->uh_save_nr = buf->b_u_save_nr_last; 2988 } 2989 2990 static void 2991 u_unch_branch(uhp) 2992 u_header_T *uhp; 2993 { 2994 u_header_T *uh; 2995 2996 for (uh = uhp; uh != NULL; uh = uh->uh_prev.ptr) 2997 { 2998 uh->uh_flags |= UH_CHANGED; 2999 if (uh->uh_alt_next.ptr != NULL) 3000 u_unch_branch(uh->uh_alt_next.ptr); /* recursive */ 3001 } 3002 } 3003 3004 /* 3005 * Get pointer to last added entry. 3006 * If it's not valid, give an error message and return NULL. 3007 */ 3008 static u_entry_T * 3009 u_get_headentry() 3010 { 3011 if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL) 3012 { 3013 EMSG(_("E439: undo list corrupt")); 3014 return NULL; 3015 } 3016 return curbuf->b_u_newhead->uh_entry; 3017 } 3018 3019 /* 3020 * u_getbot(): compute the line number of the previous u_save 3021 * It is called only when b_u_synced is FALSE. 3022 */ 3023 static void 3024 u_getbot() 3025 { 3026 u_entry_T *uep; 3027 linenr_T extra; 3028 3029 uep = u_get_headentry(); /* check for corrupt undo list */ 3030 if (uep == NULL) 3031 return; 3032 3033 uep = curbuf->b_u_newhead->uh_getbot_entry; 3034 if (uep != NULL) 3035 { 3036 /* 3037 * the new ue_bot is computed from the number of lines that has been 3038 * inserted (0 - deleted) since calling u_save. This is equal to the 3039 * old line count subtracted from the current line count. 3040 */ 3041 extra = curbuf->b_ml.ml_line_count - uep->ue_lcount; 3042 uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra; 3043 if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count) 3044 { 3045 EMSG(_("E440: undo line missing")); 3046 uep->ue_bot = uep->ue_top + 1; /* assume all lines deleted, will 3047 * get all the old lines back 3048 * without deleting the current 3049 * ones */ 3050 } 3051 3052 curbuf->b_u_newhead->uh_getbot_entry = NULL; 3053 } 3054 3055 curbuf->b_u_synced = TRUE; 3056 } 3057 3058 /* 3059 * Free one header "uhp" and its entry list and adjust the pointers. 3060 */ 3061 static void 3062 u_freeheader(buf, uhp, uhpp) 3063 buf_T *buf; 3064 u_header_T *uhp; 3065 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 3066 { 3067 u_header_T *uhap; 3068 3069 /* When there is an alternate redo list free that branch completely, 3070 * because we can never go there. */ 3071 if (uhp->uh_alt_next.ptr != NULL) 3072 u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp); 3073 3074 if (uhp->uh_alt_prev.ptr != NULL) 3075 uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; 3076 3077 /* Update the links in the list to remove the header. */ 3078 if (uhp->uh_next.ptr == NULL) 3079 buf->b_u_oldhead = uhp->uh_prev.ptr; 3080 else 3081 uhp->uh_next.ptr->uh_prev.ptr = uhp->uh_prev.ptr; 3082 3083 if (uhp->uh_prev.ptr == NULL) 3084 buf->b_u_newhead = uhp->uh_next.ptr; 3085 else 3086 for (uhap = uhp->uh_prev.ptr; uhap != NULL; 3087 uhap = uhap->uh_alt_next.ptr) 3088 uhap->uh_next.ptr = uhp->uh_next.ptr; 3089 3090 u_freeentries(buf, uhp, uhpp); 3091 } 3092 3093 /* 3094 * Free an alternate branch and any following alternate branches. 3095 */ 3096 static void 3097 u_freebranch(buf, uhp, uhpp) 3098 buf_T *buf; 3099 u_header_T *uhp; 3100 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 3101 { 3102 u_header_T *tofree, *next; 3103 3104 /* If this is the top branch we may need to use u_freeheader() to update 3105 * all the pointers. */ 3106 if (uhp == buf->b_u_oldhead) 3107 { 3108 u_freeheader(buf, uhp, uhpp); 3109 return; 3110 } 3111 3112 if (uhp->uh_alt_prev.ptr != NULL) 3113 uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; 3114 3115 next = uhp; 3116 while (next != NULL) 3117 { 3118 tofree = next; 3119 if (tofree->uh_alt_next.ptr != NULL) 3120 u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp); /* recursive */ 3121 next = tofree->uh_prev.ptr; 3122 u_freeentries(buf, tofree, uhpp); 3123 } 3124 } 3125 3126 /* 3127 * Free all the undo entries for one header and the header itself. 3128 * This means that "uhp" is invalid when returning. 3129 */ 3130 static void 3131 u_freeentries(buf, uhp, uhpp) 3132 buf_T *buf; 3133 u_header_T *uhp; 3134 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 3135 { 3136 u_entry_T *uep, *nuep; 3137 3138 /* Check for pointers to the header that become invalid now. */ 3139 if (buf->b_u_curhead == uhp) 3140 buf->b_u_curhead = NULL; 3141 if (buf->b_u_newhead == uhp) 3142 buf->b_u_newhead = NULL; /* freeing the newest entry */ 3143 if (uhpp != NULL && uhp == *uhpp) 3144 *uhpp = NULL; 3145 3146 for (uep = uhp->uh_entry; uep != NULL; uep = nuep) 3147 { 3148 nuep = uep->ue_next; 3149 u_freeentry(uep, uep->ue_size); 3150 } 3151 3152 #ifdef U_DEBUG 3153 uhp->uh_magic = 0; 3154 #endif 3155 vim_free((char_u *)uhp); 3156 --buf->b_u_numhead; 3157 } 3158 3159 /* 3160 * free entry 'uep' and 'n' lines in uep->ue_array[] 3161 */ 3162 static void 3163 u_freeentry(uep, n) 3164 u_entry_T *uep; 3165 long n; 3166 { 3167 while (n > 0) 3168 vim_free(uep->ue_array[--n]); 3169 vim_free((char_u *)uep->ue_array); 3170 #ifdef U_DEBUG 3171 uep->ue_magic = 0; 3172 #endif 3173 vim_free((char_u *)uep); 3174 } 3175 3176 /* 3177 * invalidate the undo buffer; called when storage has already been released 3178 */ 3179 void 3180 u_clearall(buf) 3181 buf_T *buf; 3182 { 3183 buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL; 3184 buf->b_u_synced = TRUE; 3185 buf->b_u_numhead = 0; 3186 buf->b_u_line_ptr = NULL; 3187 buf->b_u_line_lnum = 0; 3188 } 3189 3190 /* 3191 * save the line "lnum" for the "U" command 3192 */ 3193 void 3194 u_saveline(lnum) 3195 linenr_T lnum; 3196 { 3197 if (lnum == curbuf->b_u_line_lnum) /* line is already saved */ 3198 return; 3199 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */ 3200 return; 3201 u_clearline(); 3202 curbuf->b_u_line_lnum = lnum; 3203 if (curwin->w_cursor.lnum == lnum) 3204 curbuf->b_u_line_colnr = curwin->w_cursor.col; 3205 else 3206 curbuf->b_u_line_colnr = 0; 3207 if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL) 3208 do_outofmem_msg((long_u)0); 3209 } 3210 3211 /* 3212 * clear the line saved for the "U" command 3213 * (this is used externally for crossing a line while in insert mode) 3214 */ 3215 void 3216 u_clearline() 3217 { 3218 if (curbuf->b_u_line_ptr != NULL) 3219 { 3220 vim_free(curbuf->b_u_line_ptr); 3221 curbuf->b_u_line_ptr = NULL; 3222 curbuf->b_u_line_lnum = 0; 3223 } 3224 } 3225 3226 /* 3227 * Implementation of the "U" command. 3228 * Differentiation from vi: "U" can be undone with the next "U". 3229 * We also allow the cursor to be in another line. 3230 * Careful: may trigger autocommands that reload the buffer. 3231 */ 3232 void 3233 u_undoline() 3234 { 3235 colnr_T t; 3236 char_u *oldp; 3237 3238 if (undo_off) 3239 return; 3240 3241 if (curbuf->b_u_line_ptr == NULL 3242 || curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) 3243 { 3244 beep_flush(); 3245 return; 3246 } 3247 3248 /* first save the line for the 'u' command */ 3249 if (u_savecommon(curbuf->b_u_line_lnum - 1, 3250 curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) 3251 return; 3252 oldp = u_save_line(curbuf->b_u_line_lnum); 3253 if (oldp == NULL) 3254 { 3255 do_outofmem_msg((long_u)0); 3256 return; 3257 } 3258 ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE); 3259 changed_bytes(curbuf->b_u_line_lnum, 0); 3260 vim_free(curbuf->b_u_line_ptr); 3261 curbuf->b_u_line_ptr = oldp; 3262 3263 t = curbuf->b_u_line_colnr; 3264 if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) 3265 curbuf->b_u_line_colnr = curwin->w_cursor.col; 3266 curwin->w_cursor.col = t; 3267 curwin->w_cursor.lnum = curbuf->b_u_line_lnum; 3268 check_cursor_col(); 3269 } 3270 3271 /* 3272 * Free all allocated memory blocks for the buffer 'buf'. 3273 */ 3274 void 3275 u_blockfree(buf) 3276 buf_T *buf; 3277 { 3278 while (buf->b_u_oldhead != NULL) 3279 u_freeheader(buf, buf->b_u_oldhead, NULL); 3280 vim_free(buf->b_u_line_ptr); 3281 } 3282 3283 /* 3284 * u_save_line(): allocate memory and copy line 'lnum' into it. 3285 * Returns NULL when out of memory. 3286 */ 3287 static char_u * 3288 u_save_line(lnum) 3289 linenr_T lnum; 3290 { 3291 return vim_strsave(ml_get(lnum)); 3292 } 3293 3294 /* 3295 * Check if the 'modified' flag is set, or 'ff' has changed (only need to 3296 * check the first character, because it can only be "dos", "unix" or "mac"). 3297 * "nofile" and "scratch" type buffers are considered to always be unchanged. 3298 */ 3299 int 3300 bufIsChanged(buf) 3301 buf_T *buf; 3302 { 3303 return 3304 #ifdef FEAT_QUICKFIX 3305 !bt_dontwrite(buf) && 3306 #endif 3307 (buf->b_changed || file_ff_differs(buf, TRUE)); 3308 } 3309 3310 int 3311 curbufIsChanged() 3312 { 3313 return 3314 #ifdef FEAT_QUICKFIX 3315 !bt_dontwrite(curbuf) && 3316 #endif 3317 (curbuf->b_changed || file_ff_differs(curbuf, TRUE)); 3318 } 3319 3320 #if defined(FEAT_EVAL) || defined(PROTO) 3321 /* 3322 * For undotree(): Append the list of undo blocks at "first_uhp" to "list". 3323 * Recursive. 3324 */ 3325 void 3326 u_eval_tree(first_uhp, list) 3327 u_header_T *first_uhp; 3328 list_T *list; 3329 { 3330 u_header_T *uhp = first_uhp; 3331 dict_T *dict; 3332 3333 while (uhp != NULL) 3334 { 3335 dict = dict_alloc(); 3336 if (dict == NULL) 3337 return; 3338 dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL); 3339 dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL); 3340 if (uhp == curbuf->b_u_newhead) 3341 dict_add_nr_str(dict, "newhead", 1, NULL); 3342 if (uhp == curbuf->b_u_curhead) 3343 dict_add_nr_str(dict, "curhead", 1, NULL); 3344 if (uhp->uh_save_nr > 0) 3345 dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL); 3346 3347 if (uhp->uh_alt_next.ptr != NULL) 3348 { 3349 list_T *alt_list = list_alloc(); 3350 3351 if (alt_list != NULL) 3352 { 3353 /* Recursive call to add alternate undo tree. */ 3354 u_eval_tree(uhp->uh_alt_next.ptr, alt_list); 3355 dict_add_list(dict, "alt", alt_list); 3356 } 3357 } 3358 3359 list_append_dict(list, dict); 3360 uhp = uhp->uh_prev.ptr; 3361 } 3362 } 3363 #endif 3364