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