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