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