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