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