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 { 1518 EMSGN("Written %ld headers, ...", headers_written); 1519 EMSGN("... but numhead is %ld", buf->b_u_numhead); 1520 } 1521 #endif 1522 1523 write_error: 1524 fclose(fp); 1525 if (!write_ok) 1526 EMSG2(_("E829: write error in undo file: %s"), file_name); 1527 1528 #if defined(MACOS_CLASSIC) || defined(WIN3264) 1529 /* Copy file attributes; for systems where this can only be done after 1530 * closing the file. */ 1531 if (buf->b_ffname != NULL) 1532 (void)mch_copy_file_attribute(buf->b_ffname, file_name); 1533 #endif 1534 #ifdef HAVE_ACL 1535 if (buf->b_ffname != NULL) 1536 { 1537 vim_acl_T acl; 1538 1539 /* For systems that support ACL: get the ACL from the original file. */ 1540 acl = mch_get_acl(buf->b_ffname); 1541 mch_set_acl(file_name, acl); 1542 mch_free_acl(acl); 1543 } 1544 #endif 1545 1546 theend: 1547 #ifdef FEAT_CRYPT 1548 if (do_crypt) 1549 crypt_pop_state(); 1550 #endif 1551 if (file_name != name) 1552 vim_free(file_name); 1553 } 1554 1555 /* 1556 * Load the undo tree from an undo file. 1557 * If "name" is not NULL use it as the undo file name. This also means being 1558 * a bit more verbose. 1559 * Otherwise use curbuf->b_ffname to generate the undo file name. 1560 * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. 1561 */ 1562 void 1563 u_read_undo(name, hash, orig_name) 1564 char_u *name; 1565 char_u *hash; 1566 char_u *orig_name; 1567 { 1568 char_u *file_name; 1569 FILE *fp; 1570 long version, str_len; 1571 char_u *line_ptr = NULL; 1572 linenr_T line_lnum; 1573 colnr_T line_colnr; 1574 linenr_T line_count; 1575 int num_head = 0; 1576 long old_header_seq, new_header_seq, cur_header_seq; 1577 long seq_last, seq_cur; 1578 long last_save_nr = 0; 1579 short old_idx = -1, new_idx = -1, cur_idx = -1; 1580 long num_read_uhps = 0; 1581 time_t seq_time; 1582 int i, j; 1583 int c; 1584 u_header_T *uhp; 1585 u_header_T **uhp_table = NULL; 1586 char_u read_hash[UNDO_HASH_SIZE]; 1587 char_u magic_buf[UF_START_MAGIC_LEN]; 1588 #ifdef U_DEBUG 1589 int *uhp_table_used; 1590 #endif 1591 #ifdef UNIX 1592 struct stat st_orig; 1593 struct stat st_undo; 1594 #endif 1595 #ifdef FEAT_CRYPT 1596 int do_decrypt = FALSE; 1597 #endif 1598 1599 if (name == NULL) 1600 { 1601 file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE); 1602 if (file_name == NULL) 1603 return; 1604 1605 #ifdef UNIX 1606 /* For safety we only read an undo file if the owner is equal to the 1607 * owner of the text file. */ 1608 if (mch_stat((char *)orig_name, &st_orig) >= 0 1609 && mch_stat((char *)file_name, &st_undo) >= 0 1610 && st_orig.st_uid != st_undo.st_uid) 1611 { 1612 if (p_verbose > 0) 1613 { 1614 verbose_enter(); 1615 smsg((char_u *)_("Not reading undo file, owner differs: %s"), 1616 file_name); 1617 verbose_leave(); 1618 } 1619 return; 1620 } 1621 #endif 1622 } 1623 else 1624 file_name = name; 1625 1626 if (p_verbose > 0) 1627 { 1628 verbose_enter(); 1629 smsg((char_u *)_("Reading undo file: %s"), file_name); 1630 verbose_leave(); 1631 } 1632 1633 fp = mch_fopen((char *)file_name, "r"); 1634 if (fp == NULL) 1635 { 1636 if (name != NULL || p_verbose > 0) 1637 EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name); 1638 goto error; 1639 } 1640 1641 /* 1642 * Read the undo file header. 1643 */ 1644 if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1 1645 || memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) 1646 { 1647 EMSG2(_("E823: Not an undo file: %s"), file_name); 1648 goto error; 1649 } 1650 version = get2c(fp); 1651 if (version == UF_VERSION_CRYPT) 1652 { 1653 #ifdef FEAT_CRYPT 1654 if (*curbuf->b_p_key == NUL) 1655 { 1656 EMSG2(_("E832: Non-encrypted file has encrypted undo file: %s"), 1657 file_name); 1658 goto error; 1659 } 1660 if (prepare_crypt_read(fp) == FAIL) 1661 { 1662 EMSG2(_("E826: Undo file decryption failed: %s"), file_name); 1663 goto error; 1664 } 1665 do_decrypt = TRUE; 1666 #else 1667 EMSG2(_("E827: Undo file is encrypted: %s"), file_name); 1668 goto error; 1669 #endif 1670 } 1671 else if (version != UF_VERSION) 1672 { 1673 EMSG2(_("E824: Incompatible undo file: %s"), file_name); 1674 goto error; 1675 } 1676 1677 if (fread(read_hash, UNDO_HASH_SIZE, 1, fp) != 1) 1678 { 1679 corruption_error("hash", file_name); 1680 goto error; 1681 } 1682 line_count = (linenr_T)get4c(fp); 1683 if (memcmp(hash, read_hash, UNDO_HASH_SIZE) != 0 1684 || line_count != curbuf->b_ml.ml_line_count) 1685 { 1686 if (p_verbose > 0 || name != NULL) 1687 { 1688 if (name == NULL) 1689 verbose_enter(); 1690 give_warning((char_u *) 1691 _("File contents changed, cannot use undo info"), TRUE); 1692 if (name == NULL) 1693 verbose_leave(); 1694 } 1695 goto error; 1696 } 1697 1698 /* Read undo data for "U" command. */ 1699 str_len = get4c(fp); 1700 if (str_len < 0) 1701 goto error; 1702 if (str_len > 0) 1703 line_ptr = read_string_decrypt(curbuf, fp, str_len); 1704 line_lnum = (linenr_T)get4c(fp); 1705 line_colnr = (colnr_T)get4c(fp); 1706 if (line_lnum < 0 || line_colnr < 0) 1707 { 1708 corruption_error("line lnum/col", file_name); 1709 goto error; 1710 } 1711 1712 /* Begin general undo data */ 1713 old_header_seq = get4c(fp); 1714 new_header_seq = get4c(fp); 1715 cur_header_seq = get4c(fp); 1716 num_head = get4c(fp); 1717 seq_last = get4c(fp); 1718 seq_cur = get4c(fp); 1719 seq_time = get8ctime(fp); 1720 1721 /* Optional header fields. */ 1722 for (;;) 1723 { 1724 int len = getc(fp); 1725 int what; 1726 1727 if (len == 0 || len == EOF) 1728 break; 1729 what = getc(fp); 1730 switch (what) 1731 { 1732 case UF_LAST_SAVE_NR: 1733 last_save_nr = get4c(fp); 1734 break; 1735 default: 1736 /* field not supported, skip */ 1737 while (--len >= 0) 1738 (void)getc(fp); 1739 } 1740 } 1741 1742 /* uhp_table will store the freshly created undo headers we allocate 1743 * until we insert them into curbuf. The table remains sorted by the 1744 * sequence numbers of the headers. 1745 * When there are no headers uhp_table is NULL. */ 1746 if (num_head > 0) 1747 { 1748 uhp_table = (u_header_T **)U_ALLOC_LINE( 1749 num_head * sizeof(u_header_T *)); 1750 if (uhp_table == NULL) 1751 goto error; 1752 } 1753 1754 while ((c = get2c(fp)) == UF_HEADER_MAGIC) 1755 { 1756 if (num_read_uhps >= num_head) 1757 { 1758 corruption_error("num_head too small", file_name); 1759 goto error; 1760 } 1761 1762 uhp = unserialize_uhp(fp, file_name); 1763 if (uhp == NULL) 1764 goto error; 1765 uhp_table[num_read_uhps++] = uhp; 1766 } 1767 1768 if (num_read_uhps != num_head) 1769 { 1770 corruption_error("num_head", file_name); 1771 goto error; 1772 } 1773 if (c != UF_HEADER_END_MAGIC) 1774 { 1775 corruption_error("end marker", file_name); 1776 goto error; 1777 } 1778 1779 #ifdef U_DEBUG 1780 uhp_table_used = (int *)alloc_clear( 1781 (unsigned)(sizeof(int) * num_head + 1)); 1782 # define SET_FLAG(j) ++uhp_table_used[j] 1783 #else 1784 # define SET_FLAG(j) 1785 #endif 1786 1787 /* We have put all of the headers into a table. Now we iterate through the 1788 * table and swizzle each sequence number we have stored in uh_*_seq into 1789 * a pointer corresponding to the header with that sequence number. */ 1790 for (i = 0; i < num_head; i++) 1791 { 1792 uhp = uhp_table[i]; 1793 if (uhp == NULL) 1794 continue; 1795 for (j = 0; j < num_head; j++) 1796 if (uhp_table[j] != NULL && i != j 1797 && uhp_table[i]->uh_seq == uhp_table[j]->uh_seq) 1798 { 1799 corruption_error("duplicate uh_seq", file_name); 1800 goto error; 1801 } 1802 for (j = 0; j < num_head; j++) 1803 if (uhp_table[j] != NULL 1804 && uhp_table[j]->uh_seq == uhp->uh_next.seq) 1805 { 1806 uhp->uh_next.ptr = uhp_table[j]; 1807 SET_FLAG(j); 1808 break; 1809 } 1810 for (j = 0; j < num_head; j++) 1811 if (uhp_table[j] != NULL 1812 && uhp_table[j]->uh_seq == uhp->uh_prev.seq) 1813 { 1814 uhp->uh_prev.ptr = uhp_table[j]; 1815 SET_FLAG(j); 1816 break; 1817 } 1818 for (j = 0; j < num_head; j++) 1819 if (uhp_table[j] != NULL 1820 && uhp_table[j]->uh_seq == uhp->uh_alt_next.seq) 1821 { 1822 uhp->uh_alt_next.ptr = uhp_table[j]; 1823 SET_FLAG(j); 1824 break; 1825 } 1826 for (j = 0; j < num_head; j++) 1827 if (uhp_table[j] != NULL 1828 && uhp_table[j]->uh_seq == uhp->uh_alt_prev.seq) 1829 { 1830 uhp->uh_alt_prev.ptr = uhp_table[j]; 1831 SET_FLAG(j); 1832 break; 1833 } 1834 if (old_header_seq > 0 && old_idx < 0 && uhp->uh_seq == old_header_seq) 1835 { 1836 old_idx = i; 1837 SET_FLAG(i); 1838 } 1839 if (new_header_seq > 0 && new_idx < 0 && uhp->uh_seq == new_header_seq) 1840 { 1841 new_idx = i; 1842 SET_FLAG(i); 1843 } 1844 if (cur_header_seq > 0 && cur_idx < 0 && uhp->uh_seq == cur_header_seq) 1845 { 1846 cur_idx = i; 1847 SET_FLAG(i); 1848 } 1849 } 1850 1851 /* Now that we have read the undo info successfully, free the current undo 1852 * info and use the info from the file. */ 1853 u_blockfree(curbuf); 1854 curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx]; 1855 curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx]; 1856 curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx]; 1857 curbuf->b_u_line_ptr = line_ptr; 1858 curbuf->b_u_line_lnum = line_lnum; 1859 curbuf->b_u_line_colnr = line_colnr; 1860 curbuf->b_u_numhead = num_head; 1861 curbuf->b_u_seq_last = seq_last; 1862 curbuf->b_u_seq_cur = seq_cur; 1863 curbuf->b_u_time_cur = seq_time; 1864 curbuf->b_u_save_nr_last = last_save_nr; 1865 curbuf->b_u_save_nr_cur = last_save_nr; 1866 1867 curbuf->b_u_synced = TRUE; 1868 vim_free(uhp_table); 1869 1870 #ifdef U_DEBUG 1871 for (i = 0; i < num_head; ++i) 1872 if (uhp_table_used[i] == 0) 1873 EMSGN("uhp_table entry %ld not used, leaking memory", i); 1874 vim_free(uhp_table_used); 1875 u_check(TRUE); 1876 #endif 1877 1878 if (name != NULL) 1879 smsg((char_u *)_("Finished reading undo file %s"), file_name); 1880 goto theend; 1881 1882 error: 1883 vim_free(line_ptr); 1884 if (uhp_table != NULL) 1885 { 1886 for (i = 0; i < num_read_uhps; i++) 1887 if (uhp_table[i] != NULL) 1888 u_free_uhp(uhp_table[i]); 1889 vim_free(uhp_table); 1890 } 1891 1892 theend: 1893 #ifdef FEAT_CRYPT 1894 if (do_decrypt) 1895 crypt_pop_state(); 1896 #endif 1897 if (fp != NULL) 1898 fclose(fp); 1899 if (file_name != name) 1900 vim_free(file_name); 1901 return; 1902 } 1903 1904 #endif /* FEAT_PERSISTENT_UNDO */ 1905 1906 1907 /* 1908 * If 'cpoptions' contains 'u': Undo the previous undo or redo (vi compatible). 1909 * If 'cpoptions' does not contain 'u': Always undo. 1910 */ 1911 void 1912 u_undo(count) 1913 int count; 1914 { 1915 /* 1916 * If we get an undo command while executing a macro, we behave like the 1917 * original vi. If this happens twice in one macro the result will not 1918 * be compatible. 1919 */ 1920 if (curbuf->b_u_synced == FALSE) 1921 { 1922 u_sync(TRUE); 1923 count = 1; 1924 } 1925 1926 if (vim_strchr(p_cpo, CPO_UNDO) == NULL) 1927 undo_undoes = TRUE; 1928 else 1929 undo_undoes = !undo_undoes; 1930 u_doit(count); 1931 } 1932 1933 /* 1934 * If 'cpoptions' contains 'u': Repeat the previous undo or redo. 1935 * If 'cpoptions' does not contain 'u': Always redo. 1936 */ 1937 void 1938 u_redo(count) 1939 int count; 1940 { 1941 if (vim_strchr(p_cpo, CPO_UNDO) == NULL) 1942 undo_undoes = FALSE; 1943 u_doit(count); 1944 } 1945 1946 /* 1947 * Undo or redo, depending on 'undo_undoes', 'count' times. 1948 */ 1949 static void 1950 u_doit(startcount) 1951 int startcount; 1952 { 1953 int count = startcount; 1954 1955 if (!undo_allowed()) 1956 return; 1957 1958 u_newcount = 0; 1959 u_oldcount = 0; 1960 if (curbuf->b_ml.ml_flags & ML_EMPTY) 1961 u_oldcount = -1; 1962 while (count--) 1963 { 1964 /* Do the change warning now, so that it triggers FileChangedRO when 1965 * needed. This may cause the file to be reloaded, that must happen 1966 * before we do anything, because it may change curbuf->b_u_curhead 1967 * and more. */ 1968 change_warning(0); 1969 1970 if (undo_undoes) 1971 { 1972 if (curbuf->b_u_curhead == NULL) /* first undo */ 1973 curbuf->b_u_curhead = curbuf->b_u_newhead; 1974 else if (p_ul > 0) /* multi level undo */ 1975 /* get next undo */ 1976 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next.ptr; 1977 /* nothing to undo */ 1978 if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL) 1979 { 1980 /* stick curbuf->b_u_curhead at end */ 1981 curbuf->b_u_curhead = curbuf->b_u_oldhead; 1982 beep_flush(); 1983 if (count == startcount - 1) 1984 { 1985 MSG(_("Already at oldest change")); 1986 return; 1987 } 1988 break; 1989 } 1990 1991 u_undoredo(TRUE); 1992 } 1993 else 1994 { 1995 if (curbuf->b_u_curhead == NULL || p_ul <= 0) 1996 { 1997 beep_flush(); /* nothing to redo */ 1998 if (count == startcount - 1) 1999 { 2000 MSG(_("Already at newest change")); 2001 return; 2002 } 2003 break; 2004 } 2005 2006 u_undoredo(FALSE); 2007 2008 /* Advance for next redo. Set "newhead" when at the end of the 2009 * redoable changes. */ 2010 if (curbuf->b_u_curhead->uh_prev.ptr == NULL) 2011 curbuf->b_u_newhead = curbuf->b_u_curhead; 2012 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev.ptr; 2013 } 2014 } 2015 u_undo_end(undo_undoes, FALSE); 2016 } 2017 2018 /* 2019 * Undo or redo over the timeline. 2020 * When "step" is negative go back in time, otherwise goes forward in time. 2021 * When "sec" is FALSE make "step" steps, when "sec" is TRUE use "step" as 2022 * seconds. 2023 * When "file" is TRUE use "step" as a number of file writes. 2024 * When "absolute" is TRUE use "step" as the sequence number to jump to. 2025 * "sec" must be FALSE then. 2026 */ 2027 void 2028 undo_time(step, sec, file, absolute) 2029 long step; 2030 int sec; 2031 int file; 2032 int absolute; 2033 { 2034 long target; 2035 long closest; 2036 long closest_start; 2037 long closest_seq = 0; 2038 long val; 2039 u_header_T *uhp; 2040 u_header_T *last; 2041 int mark; 2042 int nomark; 2043 int round; 2044 int dosec = sec; 2045 int dofile = file; 2046 int above = FALSE; 2047 int did_undo = TRUE; 2048 2049 /* First make sure the current undoable change is synced. */ 2050 if (curbuf->b_u_synced == FALSE) 2051 u_sync(TRUE); 2052 2053 u_newcount = 0; 2054 u_oldcount = 0; 2055 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2056 u_oldcount = -1; 2057 2058 /* "target" is the node below which we want to be. 2059 * Init "closest" to a value we can't reach. */ 2060 if (absolute) 2061 { 2062 target = step; 2063 closest = -1; 2064 } 2065 else 2066 { 2067 /* When doing computations with time_t subtract starttime, because 2068 * time_t converted to a long may result in a wrong number. */ 2069 if (dosec) 2070 target = (long)(curbuf->b_u_time_cur - starttime) + step; 2071 else if (dofile) 2072 { 2073 if (step < 0) 2074 { 2075 /* Going back to a previous write. If there were changes after 2076 * the last write, count that as moving one file-write, so 2077 * that ":earlier 1f" undoes all changes since the last save. */ 2078 uhp = curbuf->b_u_curhead; 2079 if (uhp != NULL) 2080 uhp = uhp->uh_next.ptr; 2081 else 2082 uhp = curbuf->b_u_newhead; 2083 if (uhp != NULL && uhp->uh_save_nr != 0) 2084 /* "uh_save_nr" was set in the last block, that means 2085 * there were no changes since the last write */ 2086 target = curbuf->b_u_save_nr_cur + step; 2087 else 2088 /* count the changes since the last write as one step */ 2089 target = curbuf->b_u_save_nr_cur + step + 1; 2090 if (target <= 0) 2091 /* Go to before first write: before the oldest change. Use 2092 * the sequence number for that. */ 2093 dofile = FALSE; 2094 } 2095 else 2096 { 2097 /* Moving forward to a newer write. */ 2098 target = curbuf->b_u_save_nr_cur + step; 2099 if (target > curbuf->b_u_save_nr_last) 2100 { 2101 /* Go to after last write: after the latest change. Use 2102 * the sequence number for that. */ 2103 target = curbuf->b_u_seq_last + 1; 2104 dofile = FALSE; 2105 } 2106 } 2107 } 2108 else 2109 target = curbuf->b_u_seq_cur + step; 2110 if (step < 0) 2111 { 2112 if (target < 0) 2113 target = 0; 2114 closest = -1; 2115 } 2116 else 2117 { 2118 if (dosec) 2119 closest = (long)(time(NULL) - starttime + 1); 2120 else if (dofile) 2121 closest = curbuf->b_u_save_nr_last + 2; 2122 else 2123 closest = curbuf->b_u_seq_last + 2; 2124 if (target >= closest) 2125 target = closest - 1; 2126 } 2127 } 2128 closest_start = closest; 2129 closest_seq = curbuf->b_u_seq_cur; 2130 2131 /* 2132 * May do this twice: 2133 * 1. Search for "target", update "closest" to the best match found. 2134 * 2. If "target" not found search for "closest". 2135 * 2136 * When using the closest time we use the sequence number in the second 2137 * round, because there may be several entries with the same time. 2138 */ 2139 for (round = 1; round <= 2; ++round) 2140 { 2141 /* Find the path from the current state to where we want to go. The 2142 * desired state can be anywhere in the undo tree, need to go all over 2143 * it. We put "nomark" in uh_walk where we have been without success, 2144 * "mark" where it could possibly be. */ 2145 mark = ++lastmark; 2146 nomark = ++lastmark; 2147 2148 if (curbuf->b_u_curhead == NULL) /* at leaf of the tree */ 2149 uhp = curbuf->b_u_newhead; 2150 else 2151 uhp = curbuf->b_u_curhead; 2152 2153 while (uhp != NULL) 2154 { 2155 uhp->uh_walk = mark; 2156 if (dosec) 2157 val = (long)(uhp->uh_time - starttime); 2158 else if (dofile) 2159 val = uhp->uh_save_nr; 2160 else 2161 val = uhp->uh_seq; 2162 2163 if (round == 1 && !(dofile && val == 0)) 2164 { 2165 /* Remember the header that is closest to the target. 2166 * It must be at least in the right direction (checked with 2167 * "b_u_seq_cur"). When the timestamp is equal find the 2168 * highest/lowest sequence number. */ 2169 if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur 2170 : uhp->uh_seq > curbuf->b_u_seq_cur) 2171 && ((dosec && val == closest) 2172 ? (step < 0 2173 ? uhp->uh_seq < closest_seq 2174 : uhp->uh_seq > closest_seq) 2175 : closest == closest_start 2176 || (val > target 2177 ? (closest > target 2178 ? val - target <= closest - target 2179 : val - target <= target - closest) 2180 : (closest > target 2181 ? target - val <= closest - target 2182 : target - val <= target - closest)))) 2183 { 2184 closest = val; 2185 closest_seq = uhp->uh_seq; 2186 } 2187 } 2188 2189 /* Quit searching when we found a match. But when searching for a 2190 * time we need to continue looking for the best uh_seq. */ 2191 if (target == val && !dosec) 2192 { 2193 target = uhp->uh_seq; 2194 break; 2195 } 2196 2197 /* go down in the tree if we haven't been there */ 2198 if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark 2199 && uhp->uh_prev.ptr->uh_walk != mark) 2200 uhp = uhp->uh_prev.ptr; 2201 2202 /* go to alternate branch if we haven't been there */ 2203 else if (uhp->uh_alt_next.ptr != NULL 2204 && uhp->uh_alt_next.ptr->uh_walk != nomark 2205 && uhp->uh_alt_next.ptr->uh_walk != mark) 2206 uhp = uhp->uh_alt_next.ptr; 2207 2208 /* go up in the tree if we haven't been there and we are at the 2209 * start of alternate branches */ 2210 else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL 2211 && uhp->uh_next.ptr->uh_walk != nomark 2212 && uhp->uh_next.ptr->uh_walk != mark) 2213 { 2214 /* If still at the start we don't go through this change. */ 2215 if (uhp == curbuf->b_u_curhead) 2216 uhp->uh_walk = nomark; 2217 uhp = uhp->uh_next.ptr; 2218 } 2219 2220 else 2221 { 2222 /* need to backtrack; mark this node as useless */ 2223 uhp->uh_walk = nomark; 2224 if (uhp->uh_alt_prev.ptr != NULL) 2225 uhp = uhp->uh_alt_prev.ptr; 2226 else 2227 uhp = uhp->uh_next.ptr; 2228 } 2229 } 2230 2231 if (uhp != NULL) /* found it */ 2232 break; 2233 2234 if (absolute) 2235 { 2236 EMSGN(_("E830: Undo number %ld not found"), step); 2237 return; 2238 } 2239 2240 if (closest == closest_start) 2241 { 2242 if (step < 0) 2243 MSG(_("Already at oldest change")); 2244 else 2245 MSG(_("Already at newest change")); 2246 return; 2247 } 2248 2249 target = closest_seq; 2250 dosec = FALSE; 2251 dofile = FALSE; 2252 if (step < 0) 2253 above = TRUE; /* stop above the header */ 2254 } 2255 2256 /* If we found it: Follow the path to go to where we want to be. */ 2257 if (uhp != NULL) 2258 { 2259 /* 2260 * First go up the tree as much as needed. 2261 */ 2262 while (!got_int) 2263 { 2264 /* Do the change warning now, for the same reason as above. */ 2265 change_warning(0); 2266 2267 uhp = curbuf->b_u_curhead; 2268 if (uhp == NULL) 2269 uhp = curbuf->b_u_newhead; 2270 else 2271 uhp = uhp->uh_next.ptr; 2272 if (uhp == NULL || uhp->uh_walk != mark 2273 || (uhp->uh_seq == target && !above)) 2274 break; 2275 curbuf->b_u_curhead = uhp; 2276 u_undoredo(TRUE); 2277 uhp->uh_walk = nomark; /* don't go back down here */ 2278 } 2279 2280 /* 2281 * And now go down the tree (redo), branching off where needed. 2282 */ 2283 while (!got_int) 2284 { 2285 /* Do the change warning now, for the same reason as above. */ 2286 change_warning(0); 2287 2288 uhp = curbuf->b_u_curhead; 2289 if (uhp == NULL) 2290 break; 2291 2292 /* Go back to the first branch with a mark. */ 2293 while (uhp->uh_alt_prev.ptr != NULL 2294 && uhp->uh_alt_prev.ptr->uh_walk == mark) 2295 uhp = uhp->uh_alt_prev.ptr; 2296 2297 /* Find the last branch with a mark, that's the one. */ 2298 last = uhp; 2299 while (last->uh_alt_next.ptr != NULL 2300 && last->uh_alt_next.ptr->uh_walk == mark) 2301 last = last->uh_alt_next.ptr; 2302 if (last != uhp) 2303 { 2304 /* Make the used branch the first entry in the list of 2305 * alternatives to make "u" and CTRL-R take this branch. */ 2306 while (uhp->uh_alt_prev.ptr != NULL) 2307 uhp = uhp->uh_alt_prev.ptr; 2308 if (last->uh_alt_next.ptr != NULL) 2309 last->uh_alt_next.ptr->uh_alt_prev.ptr = 2310 last->uh_alt_prev.ptr; 2311 last->uh_alt_prev.ptr->uh_alt_next.ptr = last->uh_alt_next.ptr; 2312 last->uh_alt_prev.ptr = NULL; 2313 last->uh_alt_next.ptr = uhp; 2314 uhp->uh_alt_prev.ptr = last; 2315 2316 if (curbuf->b_u_oldhead == uhp) 2317 curbuf->b_u_oldhead = last; 2318 uhp = last; 2319 if (uhp->uh_next.ptr != NULL) 2320 uhp->uh_next.ptr->uh_prev.ptr = uhp; 2321 } 2322 curbuf->b_u_curhead = uhp; 2323 2324 if (uhp->uh_walk != mark) 2325 break; /* must have reached the target */ 2326 2327 /* Stop when going backwards in time and didn't find the exact 2328 * header we were looking for. */ 2329 if (uhp->uh_seq == target && above) 2330 { 2331 curbuf->b_u_seq_cur = target - 1; 2332 break; 2333 } 2334 2335 u_undoredo(FALSE); 2336 2337 /* Advance "curhead" to below the header we last used. If it 2338 * becomes NULL then we need to set "newhead" to this leaf. */ 2339 if (uhp->uh_prev.ptr == NULL) 2340 curbuf->b_u_newhead = uhp; 2341 curbuf->b_u_curhead = uhp->uh_prev.ptr; 2342 did_undo = FALSE; 2343 2344 if (uhp->uh_seq == target) /* found it! */ 2345 break; 2346 2347 uhp = uhp->uh_prev.ptr; 2348 if (uhp == NULL || uhp->uh_walk != mark) 2349 { 2350 /* Need to redo more but can't find it... */ 2351 EMSG2(_(e_intern2), "undo_time()"); 2352 break; 2353 } 2354 } 2355 } 2356 u_undo_end(did_undo, absolute); 2357 } 2358 2359 /* 2360 * u_undoredo: common code for undo and redo 2361 * 2362 * The lines in the file are replaced by the lines in the entry list at 2363 * curbuf->b_u_curhead. The replaced lines in the file are saved in the entry 2364 * list for the next undo/redo. 2365 * 2366 * When "undo" is TRUE we go up in the tree, when FALSE we go down. 2367 */ 2368 static void 2369 u_undoredo(undo) 2370 int undo; 2371 { 2372 char_u **newarray = NULL; 2373 linenr_T oldsize; 2374 linenr_T newsize; 2375 linenr_T top, bot; 2376 linenr_T lnum; 2377 linenr_T newlnum = MAXLNUM; 2378 long i; 2379 u_entry_T *uep, *nuep; 2380 u_entry_T *newlist = NULL; 2381 int old_flags; 2382 int new_flags; 2383 pos_T namedm[NMARKS]; 2384 #ifdef FEAT_VISUAL 2385 visualinfo_T visualinfo; 2386 #endif 2387 int empty_buffer; /* buffer became empty */ 2388 u_header_T *curhead = curbuf->b_u_curhead; 2389 2390 #ifdef FEAT_AUTOCMD 2391 /* Don't want autocommands using the undo structures here, they are 2392 * invalid till the end. */ 2393 block_autocmds(); 2394 #endif 2395 2396 #ifdef U_DEBUG 2397 u_check(FALSE); 2398 #endif 2399 old_flags = curhead->uh_flags; 2400 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 2401 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); 2402 setpcmark(); 2403 2404 /* 2405 * save marks before undo/redo 2406 */ 2407 mch_memmove(namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS); 2408 #ifdef FEAT_VISUAL 2409 visualinfo = curbuf->b_visual; 2410 #endif 2411 curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count; 2412 curbuf->b_op_start.col = 0; 2413 curbuf->b_op_end.lnum = 0; 2414 curbuf->b_op_end.col = 0; 2415 2416 for (uep = curhead->uh_entry; uep != NULL; uep = nuep) 2417 { 2418 top = uep->ue_top; 2419 bot = uep->ue_bot; 2420 if (bot == 0) 2421 bot = curbuf->b_ml.ml_line_count + 1; 2422 if (top > curbuf->b_ml.ml_line_count || top >= bot 2423 || bot > curbuf->b_ml.ml_line_count + 1) 2424 { 2425 #ifdef FEAT_AUTOCMD 2426 unblock_autocmds(); 2427 #endif 2428 EMSG(_("E438: u_undo: line numbers wrong")); 2429 changed(); /* don't want UNCHANGED now */ 2430 return; 2431 } 2432 2433 oldsize = bot - top - 1; /* number of lines before undo */ 2434 newsize = uep->ue_size; /* number of lines after undo */ 2435 2436 if (top < newlnum) 2437 { 2438 /* If the saved cursor is somewhere in this undo block, move it to 2439 * the remembered position. Makes "gwap" put the cursor back 2440 * where it was. */ 2441 lnum = curhead->uh_cursor.lnum; 2442 if (lnum >= top && lnum <= top + newsize + 1) 2443 { 2444 curwin->w_cursor = curhead->uh_cursor; 2445 newlnum = curwin->w_cursor.lnum - 1; 2446 } 2447 else 2448 { 2449 /* Use the first line that actually changed. Avoids that 2450 * undoing auto-formatting puts the cursor in the previous 2451 * line. */ 2452 for (i = 0; i < newsize && i < oldsize; ++i) 2453 if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0) 2454 break; 2455 if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL) 2456 { 2457 newlnum = top; 2458 curwin->w_cursor.lnum = newlnum + 1; 2459 } 2460 else if (i < newsize) 2461 { 2462 newlnum = top + i; 2463 curwin->w_cursor.lnum = newlnum + 1; 2464 } 2465 } 2466 } 2467 2468 empty_buffer = FALSE; 2469 2470 /* delete the lines between top and bot and save them in newarray */ 2471 if (oldsize > 0) 2472 { 2473 if ((newarray = (char_u **)U_ALLOC_LINE( 2474 sizeof(char_u *) * oldsize)) == NULL) 2475 { 2476 do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize)); 2477 /* 2478 * We have messed up the entry list, repair is impossible. 2479 * we have to free the rest of the list. 2480 */ 2481 while (uep != NULL) 2482 { 2483 nuep = uep->ue_next; 2484 u_freeentry(uep, uep->ue_size); 2485 uep = nuep; 2486 } 2487 break; 2488 } 2489 /* delete backwards, it goes faster in most cases */ 2490 for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) 2491 { 2492 /* what can we do when we run out of memory? */ 2493 if ((newarray[i] = u_save_line(lnum)) == NULL) 2494 do_outofmem_msg((long_u)0); 2495 /* remember we deleted the last line in the buffer, and a 2496 * dummy empty line will be inserted */ 2497 if (curbuf->b_ml.ml_line_count == 1) 2498 empty_buffer = TRUE; 2499 ml_delete(lnum, FALSE); 2500 } 2501 } 2502 else 2503 newarray = NULL; 2504 2505 /* insert the lines in u_array between top and bot */ 2506 if (newsize) 2507 { 2508 for (lnum = top, i = 0; i < newsize; ++i, ++lnum) 2509 { 2510 /* 2511 * If the file is empty, there is an empty line 1 that we 2512 * should get rid of, by replacing it with the new line 2513 */ 2514 if (empty_buffer && lnum == 0) 2515 ml_replace((linenr_T)1, uep->ue_array[i], TRUE); 2516 else 2517 ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE); 2518 vim_free(uep->ue_array[i]); 2519 } 2520 vim_free((char_u *)uep->ue_array); 2521 } 2522 2523 /* adjust marks */ 2524 if (oldsize != newsize) 2525 { 2526 mark_adjust(top + 1, top + oldsize, (long)MAXLNUM, 2527 (long)newsize - (long)oldsize); 2528 if (curbuf->b_op_start.lnum > top + oldsize) 2529 curbuf->b_op_start.lnum += newsize - oldsize; 2530 if (curbuf->b_op_end.lnum > top + oldsize) 2531 curbuf->b_op_end.lnum += newsize - oldsize; 2532 } 2533 2534 changed_lines(top + 1, 0, bot, newsize - oldsize); 2535 2536 /* set '[ and '] mark */ 2537 if (top + 1 < curbuf->b_op_start.lnum) 2538 curbuf->b_op_start.lnum = top + 1; 2539 if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) 2540 curbuf->b_op_end.lnum = top + 1; 2541 else if (top + newsize > curbuf->b_op_end.lnum) 2542 curbuf->b_op_end.lnum = top + newsize; 2543 2544 u_newcount += newsize; 2545 u_oldcount += oldsize; 2546 uep->ue_size = oldsize; 2547 uep->ue_array = newarray; 2548 uep->ue_bot = top + newsize + 1; 2549 2550 /* 2551 * insert this entry in front of the new entry list 2552 */ 2553 nuep = uep->ue_next; 2554 uep->ue_next = newlist; 2555 newlist = uep; 2556 } 2557 2558 curhead->uh_entry = newlist; 2559 curhead->uh_flags = new_flags; 2560 if ((old_flags & UH_EMPTYBUF) && bufempty()) 2561 curbuf->b_ml.ml_flags |= ML_EMPTY; 2562 if (old_flags & UH_CHANGED) 2563 changed(); 2564 else 2565 #ifdef FEAT_NETBEANS_INTG 2566 /* per netbeans undo rules, keep it as modified */ 2567 if (!isNetbeansModified(curbuf)) 2568 #endif 2569 unchanged(curbuf, FALSE); 2570 2571 /* 2572 * restore marks from before undo/redo 2573 */ 2574 for (i = 0; i < NMARKS; ++i) 2575 if (curhead->uh_namedm[i].lnum != 0) 2576 { 2577 curbuf->b_namedm[i] = curhead->uh_namedm[i]; 2578 curhead->uh_namedm[i] = namedm[i]; 2579 } 2580 #ifdef FEAT_VISUAL 2581 if (curhead->uh_visual.vi_start.lnum != 0) 2582 { 2583 curbuf->b_visual = curhead->uh_visual; 2584 curhead->uh_visual = visualinfo; 2585 } 2586 #endif 2587 2588 /* 2589 * If the cursor is only off by one line, put it at the same position as 2590 * before starting the change (for the "o" command). 2591 * Otherwise the cursor should go to the first undone line. 2592 */ 2593 if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum 2594 && curwin->w_cursor.lnum > 1) 2595 --curwin->w_cursor.lnum; 2596 if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count) 2597 { 2598 if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum) 2599 { 2600 curwin->w_cursor.col = curhead->uh_cursor.col; 2601 #ifdef FEAT_VIRTUALEDIT 2602 if (virtual_active() && curhead->uh_cursor_vcol >= 0) 2603 coladvance((colnr_T)curhead->uh_cursor_vcol); 2604 else 2605 curwin->w_cursor.coladd = 0; 2606 #endif 2607 } 2608 else 2609 beginline(BL_SOL | BL_FIX); 2610 } 2611 else 2612 { 2613 /* We get here with the current cursor line being past the end (eg 2614 * after adding lines at the end of the file, and then undoing it). 2615 * check_cursor() will move the cursor to the last line. Move it to 2616 * the first column here. */ 2617 curwin->w_cursor.col = 0; 2618 #ifdef FEAT_VIRTUALEDIT 2619 curwin->w_cursor.coladd = 0; 2620 #endif 2621 } 2622 2623 /* Make sure the cursor is on an existing line and column. */ 2624 check_cursor(); 2625 2626 /* Remember where we are for "g-" and ":earlier 10s". */ 2627 curbuf->b_u_seq_cur = curhead->uh_seq; 2628 if (undo) 2629 /* We are below the previous undo. However, to make ":earlier 1s" 2630 * work we compute this as being just above the just undone change. */ 2631 --curbuf->b_u_seq_cur; 2632 2633 /* Remember where we are for ":earlier 1f" and ":later 1f". */ 2634 if (curhead->uh_save_nr != 0) 2635 { 2636 if (undo) 2637 curbuf->b_u_save_nr_cur = curhead->uh_save_nr - 1; 2638 else 2639 curbuf->b_u_save_nr_cur = curhead->uh_save_nr; 2640 } 2641 2642 /* The timestamp can be the same for multiple changes, just use the one of 2643 * the undone/redone change. */ 2644 curbuf->b_u_time_cur = curhead->uh_time; 2645 2646 #ifdef FEAT_AUTOCMD 2647 unblock_autocmds(); 2648 #endif 2649 #ifdef U_DEBUG 2650 u_check(FALSE); 2651 #endif 2652 } 2653 2654 /* 2655 * If we deleted or added lines, report the number of less/more lines. 2656 * Otherwise, report the number of changes (this may be incorrect 2657 * in some cases, but it's better than nothing). 2658 */ 2659 static void 2660 u_undo_end(did_undo, absolute) 2661 int did_undo; /* just did an undo */ 2662 int absolute; /* used ":undo N" */ 2663 { 2664 char *msgstr; 2665 u_header_T *uhp; 2666 char_u msgbuf[80]; 2667 2668 #ifdef FEAT_FOLDING 2669 if ((fdo_flags & FDO_UNDO) && KeyTyped) 2670 foldOpenCursor(); 2671 #endif 2672 2673 if (global_busy /* no messages now, wait until global is finished */ 2674 || !messaging()) /* 'lazyredraw' set, don't do messages now */ 2675 return; 2676 2677 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2678 --u_newcount; 2679 2680 u_oldcount -= u_newcount; 2681 if (u_oldcount == -1) 2682 msgstr = N_("more line"); 2683 else if (u_oldcount < 0) 2684 msgstr = N_("more lines"); 2685 else if (u_oldcount == 1) 2686 msgstr = N_("line less"); 2687 else if (u_oldcount > 1) 2688 msgstr = N_("fewer lines"); 2689 else 2690 { 2691 u_oldcount = u_newcount; 2692 if (u_newcount == 1) 2693 msgstr = N_("change"); 2694 else 2695 msgstr = N_("changes"); 2696 } 2697 2698 if (curbuf->b_u_curhead != NULL) 2699 { 2700 /* For ":undo N" we prefer a "after #N" message. */ 2701 if (absolute && curbuf->b_u_curhead->uh_next.ptr != NULL) 2702 { 2703 uhp = curbuf->b_u_curhead->uh_next.ptr; 2704 did_undo = FALSE; 2705 } 2706 else if (did_undo) 2707 uhp = curbuf->b_u_curhead; 2708 else 2709 uhp = curbuf->b_u_curhead->uh_next.ptr; 2710 } 2711 else 2712 uhp = curbuf->b_u_newhead; 2713 2714 if (uhp == NULL) 2715 *msgbuf = NUL; 2716 else 2717 u_add_time(msgbuf, sizeof(msgbuf), uhp->uh_time); 2718 2719 #ifdef FEAT_CONCEAL 2720 { 2721 win_T *wp; 2722 2723 FOR_ALL_WINDOWS(wp) 2724 { 2725 if (wp->w_buffer == curbuf && wp->w_p_cole > 0) 2726 redraw_win_later(wp, NOT_VALID); 2727 } 2728 } 2729 #endif 2730 2731 smsg((char_u *)_("%ld %s; %s #%ld %s"), 2732 u_oldcount < 0 ? -u_oldcount : u_oldcount, 2733 _(msgstr), 2734 did_undo ? _("before") : _("after"), 2735 uhp == NULL ? 0L : uhp->uh_seq, 2736 msgbuf); 2737 } 2738 2739 /* 2740 * u_sync: stop adding to the current entry list 2741 */ 2742 void 2743 u_sync(force) 2744 int force; /* Also sync when no_u_sync is set. */ 2745 { 2746 /* Skip it when already synced or syncing is disabled. */ 2747 if (curbuf->b_u_synced || (!force && no_u_sync > 0)) 2748 return; 2749 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 2750 if (im_is_preediting()) 2751 return; /* XIM is busy, don't break an undo sequence */ 2752 #endif 2753 if (p_ul < 0) 2754 curbuf->b_u_synced = TRUE; /* no entries, nothing to do */ 2755 else 2756 { 2757 u_getbot(); /* compute ue_bot of previous u_save */ 2758 curbuf->b_u_curhead = NULL; 2759 } 2760 } 2761 2762 /* 2763 * ":undolist": List the leafs of the undo tree 2764 */ 2765 void 2766 ex_undolist(eap) 2767 exarg_T *eap UNUSED; 2768 { 2769 garray_T ga; 2770 u_header_T *uhp; 2771 int mark; 2772 int nomark; 2773 int changes = 1; 2774 int i; 2775 2776 /* 2777 * 1: walk the tree to find all leafs, put the info in "ga". 2778 * 2: sort the lines 2779 * 3: display the list 2780 */ 2781 mark = ++lastmark; 2782 nomark = ++lastmark; 2783 ga_init2(&ga, (int)sizeof(char *), 20); 2784 2785 uhp = curbuf->b_u_oldhead; 2786 while (uhp != NULL) 2787 { 2788 if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark 2789 && uhp->uh_walk != mark) 2790 { 2791 if (ga_grow(&ga, 1) == FAIL) 2792 break; 2793 vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7ld ", 2794 uhp->uh_seq, changes); 2795 u_add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), 2796 uhp->uh_time); 2797 if (uhp->uh_save_nr > 0) 2798 { 2799 while (STRLEN(IObuff) < 33) 2800 STRCAT(IObuff, " "); 2801 vim_snprintf_add((char *)IObuff, IOSIZE, 2802 " %3ld", uhp->uh_save_nr); 2803 } 2804 ((char_u **)(ga.ga_data))[ga.ga_len++] = vim_strsave(IObuff); 2805 } 2806 2807 uhp->uh_walk = mark; 2808 2809 /* go down in the tree if we haven't been there */ 2810 if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark 2811 && uhp->uh_prev.ptr->uh_walk != mark) 2812 { 2813 uhp = uhp->uh_prev.ptr; 2814 ++changes; 2815 } 2816 2817 /* go to alternate branch if we haven't been there */ 2818 else if (uhp->uh_alt_next.ptr != NULL 2819 && uhp->uh_alt_next.ptr->uh_walk != nomark 2820 && uhp->uh_alt_next.ptr->uh_walk != mark) 2821 uhp = uhp->uh_alt_next.ptr; 2822 2823 /* go up in the tree if we haven't been there and we are at the 2824 * start of alternate branches */ 2825 else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL 2826 && uhp->uh_next.ptr->uh_walk != nomark 2827 && uhp->uh_next.ptr->uh_walk != mark) 2828 { 2829 uhp = uhp->uh_next.ptr; 2830 --changes; 2831 } 2832 2833 else 2834 { 2835 /* need to backtrack; mark this node as done */ 2836 uhp->uh_walk = nomark; 2837 if (uhp->uh_alt_prev.ptr != NULL) 2838 uhp = uhp->uh_alt_prev.ptr; 2839 else 2840 { 2841 uhp = uhp->uh_next.ptr; 2842 --changes; 2843 } 2844 } 2845 } 2846 2847 if (ga.ga_len == 0) 2848 MSG(_("Nothing to undo")); 2849 else 2850 { 2851 sort_strings((char_u **)ga.ga_data, ga.ga_len); 2852 2853 msg_start(); 2854 msg_puts_attr((char_u *)_("number changes when saved"), 2855 hl_attr(HLF_T)); 2856 for (i = 0; i < ga.ga_len && !got_int; ++i) 2857 { 2858 msg_putchar('\n'); 2859 if (got_int) 2860 break; 2861 msg_puts(((char_u **)ga.ga_data)[i]); 2862 } 2863 msg_end(); 2864 2865 ga_clear_strings(&ga); 2866 } 2867 } 2868 2869 /* 2870 * Put the timestamp of an undo header in "buf[buflen]" in a nice format. 2871 */ 2872 static void 2873 u_add_time(buf, buflen, tt) 2874 char_u *buf; 2875 size_t buflen; 2876 time_t tt; 2877 { 2878 #ifdef HAVE_STRFTIME 2879 struct tm *curtime; 2880 2881 if (time(NULL) - tt >= 100) 2882 { 2883 curtime = localtime(&tt); 2884 if (time(NULL) - tt < (60L * 60L * 12L)) 2885 /* within 12 hours */ 2886 (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime); 2887 else 2888 /* longer ago */ 2889 (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime); 2890 } 2891 else 2892 #endif 2893 vim_snprintf((char *)buf, buflen, _("%ld seconds ago"), 2894 (long)(time(NULL) - tt)); 2895 } 2896 2897 /* 2898 * ":undojoin": continue adding to the last entry list 2899 */ 2900 void 2901 ex_undojoin(eap) 2902 exarg_T *eap UNUSED; 2903 { 2904 if (curbuf->b_u_newhead == NULL) 2905 return; /* nothing changed before */ 2906 if (curbuf->b_u_curhead != NULL) 2907 { 2908 EMSG(_("E790: undojoin is not allowed after undo")); 2909 return; 2910 } 2911 if (!curbuf->b_u_synced) 2912 return; /* already unsynced */ 2913 if (p_ul < 0) 2914 return; /* no entries, nothing to do */ 2915 else 2916 { 2917 /* Go back to the last entry */ 2918 curbuf->b_u_curhead = curbuf->b_u_newhead; 2919 curbuf->b_u_synced = FALSE; /* no entries, nothing to do */ 2920 } 2921 } 2922 2923 /* 2924 * Called after writing or reloading the file and setting b_changed to FALSE. 2925 * Now an undo means that the buffer is modified. 2926 */ 2927 void 2928 u_unchanged(buf) 2929 buf_T *buf; 2930 { 2931 u_unch_branch(buf->b_u_oldhead); 2932 buf->b_did_warn = FALSE; 2933 } 2934 2935 /* 2936 * After reloading a buffer which was saved for 'undoreload': Find the first 2937 * line that was changed and set the cursor there. 2938 */ 2939 void 2940 u_find_first_changed() 2941 { 2942 u_header_T *uhp = curbuf->b_u_newhead; 2943 u_entry_T *uep; 2944 linenr_T lnum; 2945 2946 if (curbuf->b_u_curhead != NULL || uhp == NULL) 2947 return; /* undid something in an autocmd? */ 2948 2949 /* Check that the last undo block was for the whole file. */ 2950 uep = uhp->uh_entry; 2951 if (uep->ue_top != 0 || uep->ue_bot != 0) 2952 return; 2953 2954 for (lnum = 1; lnum < curbuf->b_ml.ml_line_count 2955 && lnum <= uep->ue_size; ++lnum) 2956 if (STRCMP(ml_get_buf(curbuf, lnum, FALSE), 2957 uep->ue_array[lnum - 1]) != 0) 2958 { 2959 clearpos(&(uhp->uh_cursor)); 2960 uhp->uh_cursor.lnum = lnum; 2961 return; 2962 } 2963 if (curbuf->b_ml.ml_line_count != uep->ue_size) 2964 { 2965 /* lines added or deleted at the end, put the cursor there */ 2966 clearpos(&(uhp->uh_cursor)); 2967 uhp->uh_cursor.lnum = lnum; 2968 } 2969 } 2970 2971 /* 2972 * Increase the write count, store it in the last undo header, what would be 2973 * used for "u". 2974 */ 2975 void 2976 u_update_save_nr(buf) 2977 buf_T *buf; 2978 { 2979 u_header_T *uhp; 2980 2981 ++buf->b_u_save_nr_last; 2982 buf->b_u_save_nr_cur = buf->b_u_save_nr_last; 2983 uhp = buf->b_u_curhead; 2984 if (uhp != NULL) 2985 uhp = uhp->uh_next.ptr; 2986 else 2987 uhp = buf->b_u_newhead; 2988 if (uhp != NULL) 2989 uhp->uh_save_nr = buf->b_u_save_nr_last; 2990 } 2991 2992 static void 2993 u_unch_branch(uhp) 2994 u_header_T *uhp; 2995 { 2996 u_header_T *uh; 2997 2998 for (uh = uhp; uh != NULL; uh = uh->uh_prev.ptr) 2999 { 3000 uh->uh_flags |= UH_CHANGED; 3001 if (uh->uh_alt_next.ptr != NULL) 3002 u_unch_branch(uh->uh_alt_next.ptr); /* recursive */ 3003 } 3004 } 3005 3006 /* 3007 * Get pointer to last added entry. 3008 * If it's not valid, give an error message and return NULL. 3009 */ 3010 static u_entry_T * 3011 u_get_headentry() 3012 { 3013 if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL) 3014 { 3015 EMSG(_("E439: undo list corrupt")); 3016 return NULL; 3017 } 3018 return curbuf->b_u_newhead->uh_entry; 3019 } 3020 3021 /* 3022 * u_getbot(): compute the line number of the previous u_save 3023 * It is called only when b_u_synced is FALSE. 3024 */ 3025 static void 3026 u_getbot() 3027 { 3028 u_entry_T *uep; 3029 linenr_T extra; 3030 3031 uep = u_get_headentry(); /* check for corrupt undo list */ 3032 if (uep == NULL) 3033 return; 3034 3035 uep = curbuf->b_u_newhead->uh_getbot_entry; 3036 if (uep != NULL) 3037 { 3038 /* 3039 * the new ue_bot is computed from the number of lines that has been 3040 * inserted (0 - deleted) since calling u_save. This is equal to the 3041 * old line count subtracted from the current line count. 3042 */ 3043 extra = curbuf->b_ml.ml_line_count - uep->ue_lcount; 3044 uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra; 3045 if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count) 3046 { 3047 EMSG(_("E440: undo line missing")); 3048 uep->ue_bot = uep->ue_top + 1; /* assume all lines deleted, will 3049 * get all the old lines back 3050 * without deleting the current 3051 * ones */ 3052 } 3053 3054 curbuf->b_u_newhead->uh_getbot_entry = NULL; 3055 } 3056 3057 curbuf->b_u_synced = TRUE; 3058 } 3059 3060 /* 3061 * Free one header "uhp" and its entry list and adjust the pointers. 3062 */ 3063 static void 3064 u_freeheader(buf, uhp, uhpp) 3065 buf_T *buf; 3066 u_header_T *uhp; 3067 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 3068 { 3069 u_header_T *uhap; 3070 3071 /* When there is an alternate redo list free that branch completely, 3072 * because we can never go there. */ 3073 if (uhp->uh_alt_next.ptr != NULL) 3074 u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp); 3075 3076 if (uhp->uh_alt_prev.ptr != NULL) 3077 uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; 3078 3079 /* Update the links in the list to remove the header. */ 3080 if (uhp->uh_next.ptr == NULL) 3081 buf->b_u_oldhead = uhp->uh_prev.ptr; 3082 else 3083 uhp->uh_next.ptr->uh_prev.ptr = uhp->uh_prev.ptr; 3084 3085 if (uhp->uh_prev.ptr == NULL) 3086 buf->b_u_newhead = uhp->uh_next.ptr; 3087 else 3088 for (uhap = uhp->uh_prev.ptr; uhap != NULL; 3089 uhap = uhap->uh_alt_next.ptr) 3090 uhap->uh_next.ptr = uhp->uh_next.ptr; 3091 3092 u_freeentries(buf, uhp, uhpp); 3093 } 3094 3095 /* 3096 * Free an alternate branch and any following alternate branches. 3097 */ 3098 static void 3099 u_freebranch(buf, uhp, uhpp) 3100 buf_T *buf; 3101 u_header_T *uhp; 3102 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 3103 { 3104 u_header_T *tofree, *next; 3105 3106 /* If this is the top branch we may need to use u_freeheader() to update 3107 * all the pointers. */ 3108 if (uhp == buf->b_u_oldhead) 3109 { 3110 u_freeheader(buf, uhp, uhpp); 3111 return; 3112 } 3113 3114 if (uhp->uh_alt_prev.ptr != NULL) 3115 uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; 3116 3117 next = uhp; 3118 while (next != NULL) 3119 { 3120 tofree = next; 3121 if (tofree->uh_alt_next.ptr != NULL) 3122 u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp); /* recursive */ 3123 next = tofree->uh_prev.ptr; 3124 u_freeentries(buf, tofree, uhpp); 3125 } 3126 } 3127 3128 /* 3129 * Free all the undo entries for one header and the header itself. 3130 * This means that "uhp" is invalid when returning. 3131 */ 3132 static void 3133 u_freeentries(buf, uhp, uhpp) 3134 buf_T *buf; 3135 u_header_T *uhp; 3136 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 3137 { 3138 u_entry_T *uep, *nuep; 3139 3140 /* Check for pointers to the header that become invalid now. */ 3141 if (buf->b_u_curhead == uhp) 3142 buf->b_u_curhead = NULL; 3143 if (buf->b_u_newhead == uhp) 3144 buf->b_u_newhead = NULL; /* freeing the newest entry */ 3145 if (uhpp != NULL && uhp == *uhpp) 3146 *uhpp = NULL; 3147 3148 for (uep = uhp->uh_entry; uep != NULL; uep = nuep) 3149 { 3150 nuep = uep->ue_next; 3151 u_freeentry(uep, uep->ue_size); 3152 } 3153 3154 #ifdef U_DEBUG 3155 uhp->uh_magic = 0; 3156 #endif 3157 vim_free((char_u *)uhp); 3158 --buf->b_u_numhead; 3159 } 3160 3161 /* 3162 * free entry 'uep' and 'n' lines in uep->ue_array[] 3163 */ 3164 static void 3165 u_freeentry(uep, n) 3166 u_entry_T *uep; 3167 long n; 3168 { 3169 while (n > 0) 3170 vim_free(uep->ue_array[--n]); 3171 vim_free((char_u *)uep->ue_array); 3172 #ifdef U_DEBUG 3173 uep->ue_magic = 0; 3174 #endif 3175 vim_free((char_u *)uep); 3176 } 3177 3178 /* 3179 * invalidate the undo buffer; called when storage has already been released 3180 */ 3181 void 3182 u_clearall(buf) 3183 buf_T *buf; 3184 { 3185 buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL; 3186 buf->b_u_synced = TRUE; 3187 buf->b_u_numhead = 0; 3188 buf->b_u_line_ptr = NULL; 3189 buf->b_u_line_lnum = 0; 3190 } 3191 3192 /* 3193 * save the line "lnum" for the "U" command 3194 */ 3195 void 3196 u_saveline(lnum) 3197 linenr_T lnum; 3198 { 3199 if (lnum == curbuf->b_u_line_lnum) /* line is already saved */ 3200 return; 3201 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */ 3202 return; 3203 u_clearline(); 3204 curbuf->b_u_line_lnum = lnum; 3205 if (curwin->w_cursor.lnum == lnum) 3206 curbuf->b_u_line_colnr = curwin->w_cursor.col; 3207 else 3208 curbuf->b_u_line_colnr = 0; 3209 if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL) 3210 do_outofmem_msg((long_u)0); 3211 } 3212 3213 /* 3214 * clear the line saved for the "U" command 3215 * (this is used externally for crossing a line while in insert mode) 3216 */ 3217 void 3218 u_clearline() 3219 { 3220 if (curbuf->b_u_line_ptr != NULL) 3221 { 3222 vim_free(curbuf->b_u_line_ptr); 3223 curbuf->b_u_line_ptr = NULL; 3224 curbuf->b_u_line_lnum = 0; 3225 } 3226 } 3227 3228 /* 3229 * Implementation of the "U" command. 3230 * Differentiation from vi: "U" can be undone with the next "U". 3231 * We also allow the cursor to be in another line. 3232 * Careful: may trigger autocommands that reload the buffer. 3233 */ 3234 void 3235 u_undoline() 3236 { 3237 colnr_T t; 3238 char_u *oldp; 3239 3240 if (undo_off) 3241 return; 3242 3243 if (curbuf->b_u_line_ptr == NULL 3244 || curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) 3245 { 3246 beep_flush(); 3247 return; 3248 } 3249 3250 /* first save the line for the 'u' command */ 3251 if (u_savecommon(curbuf->b_u_line_lnum - 1, 3252 curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) 3253 return; 3254 oldp = u_save_line(curbuf->b_u_line_lnum); 3255 if (oldp == NULL) 3256 { 3257 do_outofmem_msg((long_u)0); 3258 return; 3259 } 3260 ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE); 3261 changed_bytes(curbuf->b_u_line_lnum, 0); 3262 vim_free(curbuf->b_u_line_ptr); 3263 curbuf->b_u_line_ptr = oldp; 3264 3265 t = curbuf->b_u_line_colnr; 3266 if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) 3267 curbuf->b_u_line_colnr = curwin->w_cursor.col; 3268 curwin->w_cursor.col = t; 3269 curwin->w_cursor.lnum = curbuf->b_u_line_lnum; 3270 check_cursor_col(); 3271 } 3272 3273 /* 3274 * Free all allocated memory blocks for the buffer 'buf'. 3275 */ 3276 void 3277 u_blockfree(buf) 3278 buf_T *buf; 3279 { 3280 while (buf->b_u_oldhead != NULL) 3281 u_freeheader(buf, buf->b_u_oldhead, NULL); 3282 vim_free(buf->b_u_line_ptr); 3283 } 3284 3285 /* 3286 * u_save_line(): allocate memory and copy line 'lnum' into it. 3287 * Returns NULL when out of memory. 3288 */ 3289 static char_u * 3290 u_save_line(lnum) 3291 linenr_T lnum; 3292 { 3293 return vim_strsave(ml_get(lnum)); 3294 } 3295 3296 /* 3297 * Check if the 'modified' flag is set, or 'ff' has changed (only need to 3298 * check the first character, because it can only be "dos", "unix" or "mac"). 3299 * "nofile" and "scratch" type buffers are considered to always be unchanged. 3300 */ 3301 int 3302 bufIsChanged(buf) 3303 buf_T *buf; 3304 { 3305 return 3306 #ifdef FEAT_QUICKFIX 3307 !bt_dontwrite(buf) && 3308 #endif 3309 (buf->b_changed || file_ff_differs(buf, TRUE)); 3310 } 3311 3312 int 3313 curbufIsChanged() 3314 { 3315 return 3316 #ifdef FEAT_QUICKFIX 3317 !bt_dontwrite(curbuf) && 3318 #endif 3319 (curbuf->b_changed || file_ff_differs(curbuf, TRUE)); 3320 } 3321 3322 #if defined(FEAT_EVAL) || defined(PROTO) 3323 /* 3324 * For undotree(): Append the list of undo blocks at "first_uhp" to "list". 3325 * Recursive. 3326 */ 3327 void 3328 u_eval_tree(first_uhp, list) 3329 u_header_T *first_uhp; 3330 list_T *list; 3331 { 3332 u_header_T *uhp = first_uhp; 3333 dict_T *dict; 3334 3335 while (uhp != NULL) 3336 { 3337 dict = dict_alloc(); 3338 if (dict == NULL) 3339 return; 3340 dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL); 3341 dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL); 3342 if (uhp == curbuf->b_u_newhead) 3343 dict_add_nr_str(dict, "newhead", 1, NULL); 3344 if (uhp == curbuf->b_u_curhead) 3345 dict_add_nr_str(dict, "curhead", 1, NULL); 3346 if (uhp->uh_save_nr > 0) 3347 dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL); 3348 3349 if (uhp->uh_alt_next.ptr != NULL) 3350 { 3351 list_T *alt_list = list_alloc(); 3352 3353 if (alt_list != NULL) 3354 { 3355 /* Recursive call to add alternate undo tree. */ 3356 u_eval_tree(uhp->uh_alt_next.ptr, alt_list); 3357 dict_add_list(dict, "alt", alt_list); 3358 } 3359 } 3360 3361 list_append_dict(list, dict); 3362 uhp = uhp->uh_prev.ptr; 3363 } 3364 } 3365 #endif 3366