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_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 write_error: 1790 fclose(fp); 1791 if (!write_ok) 1792 semsg(_("E829: write error in undo file: %s"), file_name); 1793 1794 #if defined(MSWIN) 1795 // Copy file attributes; for systems where this can only be done after 1796 // closing the file. 1797 if (buf->b_ffname != NULL) 1798 (void)mch_copy_file_attribute(buf->b_ffname, file_name); 1799 #endif 1800 #ifdef HAVE_ACL 1801 if (buf->b_ffname != NULL) 1802 { 1803 vim_acl_T acl; 1804 1805 // For systems that support ACL: get the ACL from the original file. 1806 acl = mch_get_acl(buf->b_ffname); 1807 mch_set_acl(file_name, acl); 1808 mch_free_acl(acl); 1809 } 1810 #endif 1811 1812 theend: 1813 #ifdef FEAT_CRYPT 1814 if (bi.bi_state != NULL) 1815 crypt_free_state(bi.bi_state); 1816 vim_free(bi.bi_buffer); 1817 #endif 1818 if (file_name != name) 1819 vim_free(file_name); 1820 } 1821 1822 /* 1823 * Load the undo tree from an undo file. 1824 * If "name" is not NULL use it as the undo file name. This also means being 1825 * a bit more verbose. 1826 * Otherwise use curbuf->b_ffname to generate the undo file name. 1827 * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text. 1828 */ 1829 void 1830 u_read_undo(char_u *name, char_u *hash, char_u *orig_name UNUSED) 1831 { 1832 char_u *file_name; 1833 FILE *fp; 1834 long version, str_len; 1835 undoline_T line_ptr; 1836 linenr_T line_lnum; 1837 colnr_T line_colnr; 1838 linenr_T line_count; 1839 long num_head = 0; 1840 long old_header_seq, new_header_seq, cur_header_seq; 1841 long seq_last, seq_cur; 1842 long last_save_nr = 0; 1843 short old_idx = -1, new_idx = -1, cur_idx = -1; 1844 long num_read_uhps = 0; 1845 time_t seq_time; 1846 int i, j; 1847 int c; 1848 u_header_T *uhp; 1849 u_header_T **uhp_table = NULL; 1850 char_u read_hash[UNDO_HASH_SIZE]; 1851 char_u magic_buf[UF_START_MAGIC_LEN]; 1852 #ifdef U_DEBUG 1853 int *uhp_table_used; 1854 #endif 1855 #ifdef UNIX 1856 stat_T st_orig; 1857 stat_T st_undo; 1858 #endif 1859 bufinfo_T bi; 1860 1861 CLEAR_FIELD(bi); 1862 line_ptr.ul_len = 0; 1863 line_ptr.ul_line = NULL; 1864 1865 if (name == NULL) 1866 { 1867 file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE); 1868 if (file_name == NULL) 1869 return; 1870 1871 #ifdef UNIX 1872 // For safety we only read an undo file if the owner is equal to the 1873 // owner of the text file or equal to the current user. 1874 if (mch_stat((char *)orig_name, &st_orig) >= 0 1875 && mch_stat((char *)file_name, &st_undo) >= 0 1876 && st_orig.st_uid != st_undo.st_uid 1877 && st_undo.st_uid != getuid()) 1878 { 1879 if (p_verbose > 0) 1880 { 1881 verbose_enter(); 1882 smsg(_("Not reading undo file, owner differs: %s"), 1883 file_name); 1884 verbose_leave(); 1885 } 1886 return; 1887 } 1888 #endif 1889 } 1890 else 1891 file_name = name; 1892 1893 if (p_verbose > 0) 1894 { 1895 verbose_enter(); 1896 smsg(_("Reading undo file: %s"), file_name); 1897 verbose_leave(); 1898 } 1899 1900 fp = mch_fopen((char *)file_name, "r"); 1901 if (fp == NULL) 1902 { 1903 if (name != NULL || p_verbose > 0) 1904 semsg(_("E822: Cannot open undo file for reading: %s"), file_name); 1905 goto error; 1906 } 1907 bi.bi_buf = curbuf; 1908 bi.bi_fp = fp; 1909 1910 /* 1911 * Read the undo file header. 1912 */ 1913 if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1 1914 || memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) 1915 { 1916 semsg(_("E823: Not an undo file: %s"), file_name); 1917 goto error; 1918 } 1919 version = get2c(fp); 1920 if (version == UF_VERSION_CRYPT) 1921 { 1922 #ifdef FEAT_CRYPT 1923 if (*curbuf->b_p_key == NUL) 1924 { 1925 semsg(_("E832: Non-encrypted file has encrypted undo file: %s"), 1926 file_name); 1927 goto error; 1928 } 1929 bi.bi_state = crypt_create_from_file(fp, curbuf->b_p_key); 1930 if (bi.bi_state == NULL) 1931 { 1932 semsg(_("E826: Undo file decryption failed: %s"), file_name); 1933 goto error; 1934 } 1935 if (crypt_whole_undofile(bi.bi_state->method_nr)) 1936 { 1937 bi.bi_buffer = alloc(CRYPT_BUF_SIZE); 1938 if (bi.bi_buffer == NULL) 1939 { 1940 crypt_free_state(bi.bi_state); 1941 bi.bi_state = NULL; 1942 goto error; 1943 } 1944 bi.bi_avail = 0; 1945 bi.bi_used = 0; 1946 } 1947 #else 1948 semsg(_("E827: Undo file is encrypted: %s"), file_name); 1949 goto error; 1950 #endif 1951 } 1952 else if (version != UF_VERSION) 1953 { 1954 semsg(_("E824: Incompatible undo file: %s"), file_name); 1955 goto error; 1956 } 1957 1958 if (undo_read(&bi, read_hash, (size_t)UNDO_HASH_SIZE) == FAIL) 1959 { 1960 corruption_error("hash", file_name); 1961 goto error; 1962 } 1963 line_count = (linenr_T)undo_read_4c(&bi); 1964 if (memcmp(hash, read_hash, UNDO_HASH_SIZE) != 0 1965 || line_count != curbuf->b_ml.ml_line_count) 1966 { 1967 if (p_verbose > 0 || name != NULL) 1968 { 1969 if (name == NULL) 1970 verbose_enter(); 1971 give_warning((char_u *) 1972 _("File contents changed, cannot use undo info"), TRUE); 1973 if (name == NULL) 1974 verbose_leave(); 1975 } 1976 goto error; 1977 } 1978 1979 // Read undo data for "U" command. 1980 str_len = undo_read_4c(&bi); 1981 if (str_len < 0) 1982 goto error; 1983 if (str_len > 0) 1984 { 1985 line_ptr.ul_line = read_string_decrypt(&bi, str_len); 1986 line_ptr.ul_len = str_len + 1; 1987 } 1988 line_lnum = (linenr_T)undo_read_4c(&bi); 1989 line_colnr = (colnr_T)undo_read_4c(&bi); 1990 if (line_lnum < 0 || line_colnr < 0) 1991 { 1992 corruption_error("line lnum/col", file_name); 1993 goto error; 1994 } 1995 1996 // Begin general undo data 1997 old_header_seq = undo_read_4c(&bi); 1998 new_header_seq = undo_read_4c(&bi); 1999 cur_header_seq = undo_read_4c(&bi); 2000 num_head = undo_read_4c(&bi); 2001 seq_last = undo_read_4c(&bi); 2002 seq_cur = undo_read_4c(&bi); 2003 seq_time = undo_read_time(&bi); 2004 2005 // Optional header fields. 2006 for (;;) 2007 { 2008 int len = undo_read_byte(&bi); 2009 int what; 2010 2011 if (len == 0 || len == EOF) 2012 break; 2013 what = undo_read_byte(&bi); 2014 switch (what) 2015 { 2016 case UF_LAST_SAVE_NR: 2017 last_save_nr = undo_read_4c(&bi); 2018 break; 2019 default: 2020 // field not supported, skip 2021 while (--len >= 0) 2022 (void)undo_read_byte(&bi); 2023 } 2024 } 2025 2026 // uhp_table will store the freshly created undo headers we allocate 2027 // until we insert them into curbuf. The table remains sorted by the 2028 // sequence numbers of the headers. 2029 // When there are no headers uhp_table is NULL. 2030 if (num_head > 0) 2031 { 2032 if (num_head < LONG_MAX / (long)sizeof(u_header_T *)) 2033 uhp_table = U_ALLOC_LINE(num_head * sizeof(u_header_T *)); 2034 if (uhp_table == NULL) 2035 goto error; 2036 } 2037 2038 while ((c = undo_read_2c(&bi)) == UF_HEADER_MAGIC) 2039 { 2040 if (num_read_uhps >= num_head) 2041 { 2042 corruption_error("num_head too small", file_name); 2043 goto error; 2044 } 2045 2046 uhp = unserialize_uhp(&bi, file_name); 2047 if (uhp == NULL) 2048 goto error; 2049 uhp_table[num_read_uhps++] = uhp; 2050 } 2051 2052 if (num_read_uhps != num_head) 2053 { 2054 corruption_error("num_head", file_name); 2055 goto error; 2056 } 2057 if (c != UF_HEADER_END_MAGIC) 2058 { 2059 corruption_error("end marker", file_name); 2060 goto error; 2061 } 2062 2063 #ifdef U_DEBUG 2064 uhp_table_used = alloc_clear(sizeof(int) * num_head + 1); 2065 # define SET_FLAG(j) ++uhp_table_used[j] 2066 #else 2067 # define SET_FLAG(j) 2068 #endif 2069 2070 // We have put all of the headers into a table. Now we iterate through the 2071 // table and swizzle each sequence number we have stored in uh_*_seq into 2072 // a pointer corresponding to the header with that sequence number. 2073 for (i = 0; i < num_head; i++) 2074 { 2075 uhp = uhp_table[i]; 2076 if (uhp == NULL) 2077 continue; 2078 for (j = 0; j < num_head; j++) 2079 if (uhp_table[j] != NULL && i != j 2080 && uhp_table[i]->uh_seq == uhp_table[j]->uh_seq) 2081 { 2082 corruption_error("duplicate uh_seq", file_name); 2083 goto error; 2084 } 2085 for (j = 0; j < num_head; j++) 2086 if (uhp_table[j] != NULL 2087 && uhp_table[j]->uh_seq == uhp->uh_next.seq) 2088 { 2089 uhp->uh_next.ptr = uhp_table[j]; 2090 SET_FLAG(j); 2091 break; 2092 } 2093 for (j = 0; j < num_head; j++) 2094 if (uhp_table[j] != NULL 2095 && uhp_table[j]->uh_seq == uhp->uh_prev.seq) 2096 { 2097 uhp->uh_prev.ptr = uhp_table[j]; 2098 SET_FLAG(j); 2099 break; 2100 } 2101 for (j = 0; j < num_head; j++) 2102 if (uhp_table[j] != NULL 2103 && uhp_table[j]->uh_seq == uhp->uh_alt_next.seq) 2104 { 2105 uhp->uh_alt_next.ptr = uhp_table[j]; 2106 SET_FLAG(j); 2107 break; 2108 } 2109 for (j = 0; j < num_head; j++) 2110 if (uhp_table[j] != NULL 2111 && uhp_table[j]->uh_seq == uhp->uh_alt_prev.seq) 2112 { 2113 uhp->uh_alt_prev.ptr = uhp_table[j]; 2114 SET_FLAG(j); 2115 break; 2116 } 2117 if (old_header_seq > 0 && old_idx < 0 && uhp->uh_seq == old_header_seq) 2118 { 2119 old_idx = i; 2120 SET_FLAG(i); 2121 } 2122 if (new_header_seq > 0 && new_idx < 0 && uhp->uh_seq == new_header_seq) 2123 { 2124 new_idx = i; 2125 SET_FLAG(i); 2126 } 2127 if (cur_header_seq > 0 && cur_idx < 0 && uhp->uh_seq == cur_header_seq) 2128 { 2129 cur_idx = i; 2130 SET_FLAG(i); 2131 } 2132 } 2133 2134 // Now that we have read the undo info successfully, free the current undo 2135 // info and use the info from the file. 2136 u_blockfree(curbuf); 2137 curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx]; 2138 curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx]; 2139 curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx]; 2140 curbuf->b_u_line_ptr = line_ptr; 2141 curbuf->b_u_line_lnum = line_lnum; 2142 curbuf->b_u_line_colnr = line_colnr; 2143 curbuf->b_u_numhead = num_head; 2144 curbuf->b_u_seq_last = seq_last; 2145 curbuf->b_u_seq_cur = seq_cur; 2146 curbuf->b_u_time_cur = seq_time; 2147 curbuf->b_u_save_nr_last = last_save_nr; 2148 curbuf->b_u_save_nr_cur = last_save_nr; 2149 2150 curbuf->b_u_synced = TRUE; 2151 vim_free(uhp_table); 2152 2153 #ifdef U_DEBUG 2154 for (i = 0; i < num_head; ++i) 2155 if (uhp_table_used[i] == 0) 2156 semsg("uhp_table entry %ld not used, leaking memory", i); 2157 vim_free(uhp_table_used); 2158 u_check(TRUE); 2159 #endif 2160 2161 if (name != NULL) 2162 smsg(_("Finished reading undo file %s"), file_name); 2163 goto theend; 2164 2165 error: 2166 vim_free(line_ptr.ul_line); 2167 if (uhp_table != NULL) 2168 { 2169 for (i = 0; i < num_read_uhps; i++) 2170 if (uhp_table[i] != NULL) 2171 u_free_uhp(uhp_table[i]); 2172 vim_free(uhp_table); 2173 } 2174 2175 theend: 2176 #ifdef FEAT_CRYPT 2177 if (bi.bi_state != NULL) 2178 crypt_free_state(bi.bi_state); 2179 vim_free(bi.bi_buffer); 2180 #endif 2181 if (fp != NULL) 2182 fclose(fp); 2183 if (file_name != name) 2184 vim_free(file_name); 2185 return; 2186 } 2187 2188 #endif // FEAT_PERSISTENT_UNDO 2189 2190 2191 /* 2192 * If 'cpoptions' contains 'u': Undo the previous undo or redo (vi compatible). 2193 * If 'cpoptions' does not contain 'u': Always undo. 2194 */ 2195 void 2196 u_undo(int count) 2197 { 2198 /* 2199 * If we get an undo command while executing a macro, we behave like the 2200 * original vi. If this happens twice in one macro the result will not 2201 * be compatible. 2202 */ 2203 if (curbuf->b_u_synced == FALSE) 2204 { 2205 u_sync(TRUE); 2206 count = 1; 2207 } 2208 2209 if (vim_strchr(p_cpo, CPO_UNDO) == NULL) 2210 undo_undoes = TRUE; 2211 else 2212 undo_undoes = !undo_undoes; 2213 u_doit(count); 2214 } 2215 2216 /* 2217 * If 'cpoptions' contains 'u': Repeat the previous undo or redo. 2218 * If 'cpoptions' does not contain 'u': Always redo. 2219 */ 2220 void 2221 u_redo(int count) 2222 { 2223 if (vim_strchr(p_cpo, CPO_UNDO) == NULL) 2224 undo_undoes = FALSE; 2225 u_doit(count); 2226 } 2227 2228 /* 2229 * Undo or redo, depending on 'undo_undoes', 'count' times. 2230 */ 2231 static void 2232 u_doit(int startcount) 2233 { 2234 int count = startcount; 2235 2236 if (!undo_allowed()) 2237 return; 2238 2239 u_newcount = 0; 2240 u_oldcount = 0; 2241 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2242 u_oldcount = -1; 2243 while (count--) 2244 { 2245 // Do the change warning now, so that it triggers FileChangedRO when 2246 // needed. This may cause the file to be reloaded, that must happen 2247 // before we do anything, because it may change curbuf->b_u_curhead 2248 // and more. 2249 change_warning(0); 2250 2251 if (undo_undoes) 2252 { 2253 if (curbuf->b_u_curhead == NULL) // first undo 2254 curbuf->b_u_curhead = curbuf->b_u_newhead; 2255 else if (get_undolevel() > 0) // multi level undo 2256 // get next undo 2257 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next.ptr; 2258 // nothing to undo 2259 if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL) 2260 { 2261 // stick curbuf->b_u_curhead at end 2262 curbuf->b_u_curhead = curbuf->b_u_oldhead; 2263 beep_flush(); 2264 if (count == startcount - 1) 2265 { 2266 msg(_("Already at oldest change")); 2267 return; 2268 } 2269 break; 2270 } 2271 2272 u_undoredo(TRUE); 2273 } 2274 else 2275 { 2276 if (curbuf->b_u_curhead == NULL || get_undolevel() <= 0) 2277 { 2278 beep_flush(); // nothing to redo 2279 if (count == startcount - 1) 2280 { 2281 msg(_("Already at newest change")); 2282 return; 2283 } 2284 break; 2285 } 2286 2287 u_undoredo(FALSE); 2288 2289 // Advance for next redo. Set "newhead" when at the end of the 2290 // redoable changes. 2291 if (curbuf->b_u_curhead->uh_prev.ptr == NULL) 2292 curbuf->b_u_newhead = curbuf->b_u_curhead; 2293 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev.ptr; 2294 } 2295 } 2296 u_undo_end(undo_undoes, FALSE); 2297 } 2298 2299 /* 2300 * Undo or redo over the timeline. 2301 * When "step" is negative go back in time, otherwise goes forward in time. 2302 * When "sec" is FALSE make "step" steps, when "sec" is TRUE use "step" as 2303 * seconds. 2304 * When "file" is TRUE use "step" as a number of file writes. 2305 * When "absolute" is TRUE use "step" as the sequence number to jump to. 2306 * "sec" must be FALSE then. 2307 */ 2308 void 2309 undo_time( 2310 long step, 2311 int sec, 2312 int file, 2313 int absolute) 2314 { 2315 long target; 2316 long closest; 2317 long closest_start; 2318 long closest_seq = 0; 2319 long val; 2320 u_header_T *uhp = NULL; 2321 u_header_T *last; 2322 int mark; 2323 int nomark = 0; // shut up compiler 2324 int round; 2325 int dosec = sec; 2326 int dofile = file; 2327 int above = FALSE; 2328 int did_undo = TRUE; 2329 2330 // First make sure the current undoable change is synced. 2331 if (curbuf->b_u_synced == FALSE) 2332 u_sync(TRUE); 2333 2334 u_newcount = 0; 2335 u_oldcount = 0; 2336 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2337 u_oldcount = -1; 2338 2339 // "target" is the node below which we want to be. 2340 // Init "closest" to a value we can't reach. 2341 if (absolute) 2342 { 2343 target = step; 2344 closest = -1; 2345 } 2346 else 2347 { 2348 if (dosec) 2349 target = (long)(curbuf->b_u_time_cur) + step; 2350 else if (dofile) 2351 { 2352 if (step < 0) 2353 { 2354 // Going back to a previous write. If there were changes after 2355 // the last write, count that as moving one file-write, so 2356 // that ":earlier 1f" undoes all changes since the last save. 2357 uhp = curbuf->b_u_curhead; 2358 if (uhp != NULL) 2359 uhp = uhp->uh_next.ptr; 2360 else 2361 uhp = curbuf->b_u_newhead; 2362 if (uhp != NULL && uhp->uh_save_nr != 0) 2363 // "uh_save_nr" was set in the last block, that means 2364 // there were no changes since the last write 2365 target = curbuf->b_u_save_nr_cur + step; 2366 else 2367 // count the changes since the last write as one step 2368 target = curbuf->b_u_save_nr_cur + step + 1; 2369 if (target <= 0) 2370 // Go to before first write: before the oldest change. Use 2371 // the sequence number for that. 2372 dofile = FALSE; 2373 } 2374 else 2375 { 2376 // Moving forward to a newer write. 2377 target = curbuf->b_u_save_nr_cur + step; 2378 if (target > curbuf->b_u_save_nr_last) 2379 { 2380 // Go to after last write: after the latest change. Use 2381 // the sequence number for that. 2382 target = curbuf->b_u_seq_last + 1; 2383 dofile = FALSE; 2384 } 2385 } 2386 } 2387 else 2388 target = curbuf->b_u_seq_cur + step; 2389 if (step < 0) 2390 { 2391 if (target < 0) 2392 target = 0; 2393 closest = -1; 2394 } 2395 else 2396 { 2397 if (dosec) 2398 closest = (long)(vim_time() + 1); 2399 else if (dofile) 2400 closest = curbuf->b_u_save_nr_last + 2; 2401 else 2402 closest = curbuf->b_u_seq_last + 2; 2403 if (target >= closest) 2404 target = closest - 1; 2405 } 2406 } 2407 closest_start = closest; 2408 closest_seq = curbuf->b_u_seq_cur; 2409 2410 // When "target" is 0; Back to origin. 2411 if (target == 0) 2412 { 2413 mark = lastmark; // avoid that GCC complains 2414 goto target_zero; 2415 } 2416 2417 /* 2418 * May do this twice: 2419 * 1. Search for "target", update "closest" to the best match found. 2420 * 2. If "target" not found search for "closest". 2421 * 2422 * When using the closest time we use the sequence number in the second 2423 * round, because there may be several entries with the same time. 2424 */ 2425 for (round = 1; round <= 2; ++round) 2426 { 2427 // Find the path from the current state to where we want to go. The 2428 // desired state can be anywhere in the undo tree, need to go all over 2429 // it. We put "nomark" in uh_walk where we have been without success, 2430 // "mark" where it could possibly be. 2431 mark = ++lastmark; 2432 nomark = ++lastmark; 2433 2434 if (curbuf->b_u_curhead == NULL) // at leaf of the tree 2435 uhp = curbuf->b_u_newhead; 2436 else 2437 uhp = curbuf->b_u_curhead; 2438 2439 while (uhp != NULL) 2440 { 2441 uhp->uh_walk = mark; 2442 if (dosec) 2443 val = (long)(uhp->uh_time); 2444 else if (dofile) 2445 val = uhp->uh_save_nr; 2446 else 2447 val = uhp->uh_seq; 2448 2449 if (round == 1 && !(dofile && val == 0)) 2450 { 2451 // Remember the header that is closest to the target. 2452 // It must be at least in the right direction (checked with 2453 // "b_u_seq_cur"). When the timestamp is equal find the 2454 // highest/lowest sequence number. 2455 if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur 2456 : uhp->uh_seq > curbuf->b_u_seq_cur) 2457 && ((dosec && val == closest) 2458 ? (step < 0 2459 ? uhp->uh_seq < closest_seq 2460 : uhp->uh_seq > closest_seq) 2461 : closest == closest_start 2462 || (val > target 2463 ? (closest > target 2464 ? val - target <= closest - target 2465 : val - target <= target - closest) 2466 : (closest > target 2467 ? target - val <= closest - target 2468 : target - val <= target - closest)))) 2469 { 2470 closest = val; 2471 closest_seq = uhp->uh_seq; 2472 } 2473 } 2474 2475 // Quit searching when we found a match. But when searching for a 2476 // time we need to continue looking for the best uh_seq. 2477 if (target == val && !dosec) 2478 { 2479 target = uhp->uh_seq; 2480 break; 2481 } 2482 2483 // go down in the tree if we haven't been there 2484 if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark 2485 && uhp->uh_prev.ptr->uh_walk != mark) 2486 uhp = uhp->uh_prev.ptr; 2487 2488 // go to alternate branch if we haven't been there 2489 else if (uhp->uh_alt_next.ptr != NULL 2490 && uhp->uh_alt_next.ptr->uh_walk != nomark 2491 && uhp->uh_alt_next.ptr->uh_walk != mark) 2492 uhp = uhp->uh_alt_next.ptr; 2493 2494 // go up in the tree if we haven't been there and we are at the 2495 // start of alternate branches 2496 else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL 2497 && uhp->uh_next.ptr->uh_walk != nomark 2498 && uhp->uh_next.ptr->uh_walk != mark) 2499 { 2500 // If still at the start we don't go through this change. 2501 if (uhp == curbuf->b_u_curhead) 2502 uhp->uh_walk = nomark; 2503 uhp = uhp->uh_next.ptr; 2504 } 2505 2506 else 2507 { 2508 // need to backtrack; mark this node as useless 2509 uhp->uh_walk = nomark; 2510 if (uhp->uh_alt_prev.ptr != NULL) 2511 uhp = uhp->uh_alt_prev.ptr; 2512 else 2513 uhp = uhp->uh_next.ptr; 2514 } 2515 } 2516 2517 if (uhp != NULL) // found it 2518 break; 2519 2520 if (absolute) 2521 { 2522 semsg(_("E830: Undo number %ld not found"), step); 2523 return; 2524 } 2525 2526 if (closest == closest_start) 2527 { 2528 if (step < 0) 2529 msg(_("Already at oldest change")); 2530 else 2531 msg(_("Already at newest change")); 2532 return; 2533 } 2534 2535 target = closest_seq; 2536 dosec = FALSE; 2537 dofile = FALSE; 2538 if (step < 0) 2539 above = TRUE; // stop above the header 2540 } 2541 2542 target_zero: 2543 // If we found it: Follow the path to go to where we want to be. 2544 if (uhp != NULL || target == 0) 2545 { 2546 /* 2547 * First go up the tree as much as needed. 2548 */ 2549 while (!got_int) 2550 { 2551 // Do the change warning now, for the same reason as above. 2552 change_warning(0); 2553 2554 uhp = curbuf->b_u_curhead; 2555 if (uhp == NULL) 2556 uhp = curbuf->b_u_newhead; 2557 else 2558 uhp = uhp->uh_next.ptr; 2559 if (uhp == NULL || (target > 0 && uhp->uh_walk != mark) 2560 || (uhp->uh_seq == target && !above)) 2561 break; 2562 curbuf->b_u_curhead = uhp; 2563 u_undoredo(TRUE); 2564 if (target > 0) 2565 uhp->uh_walk = nomark; // don't go back down here 2566 } 2567 2568 // When back to origin, redo is not needed. 2569 if (target > 0) 2570 { 2571 /* 2572 * And now go down the tree (redo), branching off where needed. 2573 */ 2574 while (!got_int) 2575 { 2576 // Do the change warning now, for the same reason as above. 2577 change_warning(0); 2578 2579 uhp = curbuf->b_u_curhead; 2580 if (uhp == NULL) 2581 break; 2582 2583 // Go back to the first branch with a mark. 2584 while (uhp->uh_alt_prev.ptr != NULL 2585 && uhp->uh_alt_prev.ptr->uh_walk == mark) 2586 uhp = uhp->uh_alt_prev.ptr; 2587 2588 // Find the last branch with a mark, that's the one. 2589 last = uhp; 2590 while (last->uh_alt_next.ptr != NULL 2591 && last->uh_alt_next.ptr->uh_walk == mark) 2592 last = last->uh_alt_next.ptr; 2593 if (last != uhp) 2594 { 2595 // Make the used branch the first entry in the list of 2596 // alternatives to make "u" and CTRL-R take this branch. 2597 while (uhp->uh_alt_prev.ptr != NULL) 2598 uhp = uhp->uh_alt_prev.ptr; 2599 if (last->uh_alt_next.ptr != NULL) 2600 last->uh_alt_next.ptr->uh_alt_prev.ptr = 2601 last->uh_alt_prev.ptr; 2602 last->uh_alt_prev.ptr->uh_alt_next.ptr = 2603 last->uh_alt_next.ptr; 2604 last->uh_alt_prev.ptr = NULL; 2605 last->uh_alt_next.ptr = uhp; 2606 uhp->uh_alt_prev.ptr = last; 2607 2608 if (curbuf->b_u_oldhead == uhp) 2609 curbuf->b_u_oldhead = last; 2610 uhp = last; 2611 if (uhp->uh_next.ptr != NULL) 2612 uhp->uh_next.ptr->uh_prev.ptr = uhp; 2613 } 2614 curbuf->b_u_curhead = uhp; 2615 2616 if (uhp->uh_walk != mark) 2617 break; // must have reached the target 2618 2619 // Stop when going backwards in time and didn't find the exact 2620 // header we were looking for. 2621 if (uhp->uh_seq == target && above) 2622 { 2623 curbuf->b_u_seq_cur = target - 1; 2624 break; 2625 } 2626 2627 u_undoredo(FALSE); 2628 2629 // Advance "curhead" to below the header we last used. If it 2630 // becomes NULL then we need to set "newhead" to this leaf. 2631 if (uhp->uh_prev.ptr == NULL) 2632 curbuf->b_u_newhead = uhp; 2633 curbuf->b_u_curhead = uhp->uh_prev.ptr; 2634 did_undo = FALSE; 2635 2636 if (uhp->uh_seq == target) // found it! 2637 break; 2638 2639 uhp = uhp->uh_prev.ptr; 2640 if (uhp == NULL || uhp->uh_walk != mark) 2641 { 2642 // Need to redo more but can't find it... 2643 internal_error("undo_time()"); 2644 break; 2645 } 2646 } 2647 } 2648 } 2649 u_undo_end(did_undo, absolute); 2650 } 2651 2652 /* 2653 * u_undoredo: common code for undo and redo 2654 * 2655 * The lines in the file are replaced by the lines in the entry list at 2656 * curbuf->b_u_curhead. The replaced lines in the file are saved in the entry 2657 * list for the next undo/redo. 2658 * 2659 * When "undo" is TRUE we go up in the tree, when FALSE we go down. 2660 */ 2661 static void 2662 u_undoredo(int undo) 2663 { 2664 undoline_T *newarray = NULL; 2665 linenr_T oldsize; 2666 linenr_T newsize; 2667 linenr_T top, bot; 2668 linenr_T lnum; 2669 linenr_T newlnum = MAXLNUM; 2670 pos_T new_curpos = curwin->w_cursor; 2671 long i; 2672 u_entry_T *uep, *nuep; 2673 u_entry_T *newlist = NULL; 2674 int old_flags; 2675 int new_flags; 2676 pos_T namedm[NMARKS]; 2677 visualinfo_T visualinfo; 2678 int empty_buffer; // buffer became empty 2679 u_header_T *curhead = curbuf->b_u_curhead; 2680 2681 // Don't want autocommands using the undo structures here, they are 2682 // invalid till the end. 2683 block_autocmds(); 2684 2685 #ifdef U_DEBUG 2686 u_check(FALSE); 2687 #endif 2688 old_flags = curhead->uh_flags; 2689 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 2690 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); 2691 setpcmark(); 2692 2693 /* 2694 * save marks before undo/redo 2695 */ 2696 mch_memmove(namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS); 2697 visualinfo = curbuf->b_visual; 2698 curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count; 2699 curbuf->b_op_start.col = 0; 2700 curbuf->b_op_end.lnum = 0; 2701 curbuf->b_op_end.col = 0; 2702 2703 for (uep = curhead->uh_entry; uep != NULL; uep = nuep) 2704 { 2705 top = uep->ue_top; 2706 bot = uep->ue_bot; 2707 if (bot == 0) 2708 bot = curbuf->b_ml.ml_line_count + 1; 2709 if (top > curbuf->b_ml.ml_line_count || top >= bot 2710 || bot > curbuf->b_ml.ml_line_count + 1) 2711 { 2712 unblock_autocmds(); 2713 iemsg(_("E438: u_undo: line numbers wrong")); 2714 changed(); // don't want UNCHANGED now 2715 return; 2716 } 2717 2718 oldsize = bot - top - 1; // number of lines before undo 2719 newsize = uep->ue_size; // number of lines after undo 2720 2721 // Decide about the cursor position, depending on what text changed. 2722 // Don't set it yet, it may be invalid if lines are going to be added. 2723 if (top < newlnum) 2724 { 2725 // If the saved cursor is somewhere in this undo block, move it to 2726 // the remembered position. Makes "gwap" put the cursor back 2727 // where it was. 2728 lnum = curhead->uh_cursor.lnum; 2729 if (lnum >= top && lnum <= top + newsize + 1) 2730 { 2731 new_curpos = curhead->uh_cursor; 2732 newlnum = new_curpos.lnum - 1; 2733 } 2734 else 2735 { 2736 // Use the first line that actually changed. Avoids that 2737 // undoing auto-formatting puts the cursor in the previous 2738 // line. 2739 for (i = 0; i < newsize && i < oldsize; ++i) 2740 { 2741 char_u *p = ml_get(top + 1 + i); 2742 2743 if (curbuf->b_ml.ml_line_len != uep->ue_array[i].ul_len 2744 || memcmp(uep->ue_array[i].ul_line, p, 2745 curbuf->b_ml.ml_line_len) != 0) 2746 break; 2747 } 2748 if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL) 2749 { 2750 newlnum = top; 2751 new_curpos.lnum = newlnum + 1; 2752 } 2753 else if (i < newsize) 2754 { 2755 newlnum = top + i; 2756 new_curpos.lnum = newlnum + 1; 2757 } 2758 } 2759 } 2760 2761 empty_buffer = FALSE; 2762 2763 /* 2764 * Delete the lines between top and bot and save them in newarray. 2765 */ 2766 if (oldsize > 0) 2767 { 2768 if ((newarray = U_ALLOC_LINE(sizeof(undoline_T) * oldsize)) == NULL) 2769 { 2770 do_outofmem_msg((long_u)(sizeof(undoline_T) * oldsize)); 2771 2772 // We have messed up the entry list, repair is impossible. 2773 // we have to free the rest of the list. 2774 while (uep != NULL) 2775 { 2776 nuep = uep->ue_next; 2777 u_freeentry(uep, uep->ue_size); 2778 uep = nuep; 2779 } 2780 break; 2781 } 2782 // delete backwards, it goes faster in most cases 2783 for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum) 2784 { 2785 // what can we do when we run out of memory? 2786 if (u_save_line(&newarray[i], lnum) == FAIL) 2787 do_outofmem_msg((long_u)0); 2788 // remember we deleted the last line in the buffer, and a 2789 // dummy empty line will be inserted 2790 if (curbuf->b_ml.ml_line_count == 1) 2791 empty_buffer = TRUE; 2792 ml_delete_flags(lnum, ML_DEL_UNDO); 2793 } 2794 } 2795 else 2796 newarray = NULL; 2797 2798 // make sure the cursor is on a valid line after the deletions 2799 check_cursor_lnum(); 2800 2801 /* 2802 * Insert the lines in u_array between top and bot. 2803 */ 2804 if (newsize) 2805 { 2806 for (lnum = top, i = 0; i < newsize; ++i, ++lnum) 2807 { 2808 // If the file is empty, there is an empty line 1 that we 2809 // should get rid of, by replacing it with the new line. 2810 if (empty_buffer && lnum == 0) 2811 ml_replace_len((linenr_T)1, uep->ue_array[i].ul_line, 2812 uep->ue_array[i].ul_len, TRUE, TRUE); 2813 else 2814 ml_append_flags(lnum, uep->ue_array[i].ul_line, 2815 (colnr_T)uep->ue_array[i].ul_len, ML_APPEND_UNDO); 2816 vim_free(uep->ue_array[i].ul_line); 2817 } 2818 vim_free((char_u *)uep->ue_array); 2819 } 2820 2821 // adjust marks 2822 if (oldsize != newsize) 2823 { 2824 mark_adjust(top + 1, top + oldsize, (long)MAXLNUM, 2825 (long)newsize - (long)oldsize); 2826 if (curbuf->b_op_start.lnum > top + oldsize) 2827 curbuf->b_op_start.lnum += newsize - oldsize; 2828 if (curbuf->b_op_end.lnum > top + oldsize) 2829 curbuf->b_op_end.lnum += newsize - oldsize; 2830 } 2831 2832 changed_lines(top + 1, 0, bot, newsize - oldsize); 2833 2834 // set '[ and '] mark 2835 if (top + 1 < curbuf->b_op_start.lnum) 2836 curbuf->b_op_start.lnum = top + 1; 2837 if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) 2838 curbuf->b_op_end.lnum = top + 1; 2839 else if (top + newsize > curbuf->b_op_end.lnum) 2840 curbuf->b_op_end.lnum = top + newsize; 2841 2842 u_newcount += newsize; 2843 u_oldcount += oldsize; 2844 uep->ue_size = oldsize; 2845 uep->ue_array = newarray; 2846 uep->ue_bot = top + newsize + 1; 2847 2848 /* 2849 * insert this entry in front of the new entry list 2850 */ 2851 nuep = uep->ue_next; 2852 uep->ue_next = newlist; 2853 newlist = uep; 2854 } 2855 2856 // Set the cursor to the desired position. Check that the line is valid. 2857 curwin->w_cursor = new_curpos; 2858 check_cursor_lnum(); 2859 2860 curhead->uh_entry = newlist; 2861 curhead->uh_flags = new_flags; 2862 if ((old_flags & UH_EMPTYBUF) && BUFEMPTY()) 2863 curbuf->b_ml.ml_flags |= ML_EMPTY; 2864 if (old_flags & UH_CHANGED) 2865 changed(); 2866 else 2867 #ifdef FEAT_NETBEANS_INTG 2868 // per netbeans undo rules, keep it as modified 2869 if (!isNetbeansModified(curbuf)) 2870 #endif 2871 unchanged(curbuf, FALSE, TRUE); 2872 2873 /* 2874 * restore marks from before undo/redo 2875 */ 2876 for (i = 0; i < NMARKS; ++i) 2877 { 2878 if (curhead->uh_namedm[i].lnum != 0) 2879 curbuf->b_namedm[i] = curhead->uh_namedm[i]; 2880 if (namedm[i].lnum != 0) 2881 curhead->uh_namedm[i] = namedm[i]; 2882 else 2883 curhead->uh_namedm[i].lnum = 0; 2884 } 2885 if (curhead->uh_visual.vi_start.lnum != 0) 2886 { 2887 curbuf->b_visual = curhead->uh_visual; 2888 curhead->uh_visual = visualinfo; 2889 } 2890 2891 /* 2892 * If the cursor is only off by one line, put it at the same position as 2893 * before starting the change (for the "o" command). 2894 * Otherwise the cursor should go to the first undone line. 2895 */ 2896 if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum 2897 && curwin->w_cursor.lnum > 1) 2898 --curwin->w_cursor.lnum; 2899 if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count) 2900 { 2901 if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum) 2902 { 2903 curwin->w_cursor.col = curhead->uh_cursor.col; 2904 if (virtual_active() && curhead->uh_cursor_vcol >= 0) 2905 coladvance((colnr_T)curhead->uh_cursor_vcol); 2906 else 2907 curwin->w_cursor.coladd = 0; 2908 } 2909 else 2910 beginline(BL_SOL | BL_FIX); 2911 } 2912 else 2913 { 2914 // We get here with the current cursor line being past the end (eg 2915 // after adding lines at the end of the file, and then undoing it). 2916 // check_cursor() will move the cursor to the last line. Move it to 2917 // the first column here. 2918 curwin->w_cursor.col = 0; 2919 curwin->w_cursor.coladd = 0; 2920 } 2921 2922 // Make sure the cursor is on an existing line and column. 2923 check_cursor(); 2924 2925 // Remember where we are for "g-" and ":earlier 10s". 2926 curbuf->b_u_seq_cur = curhead->uh_seq; 2927 if (undo) 2928 { 2929 // We are below the previous undo. However, to make ":earlier 1s" 2930 // work we compute this as being just above the just undone change. 2931 if (curhead->uh_next.ptr != NULL) 2932 curbuf->b_u_seq_cur = curhead->uh_next.ptr->uh_seq; 2933 else 2934 curbuf->b_u_seq_cur = 0; 2935 } 2936 2937 // Remember where we are for ":earlier 1f" and ":later 1f". 2938 if (curhead->uh_save_nr != 0) 2939 { 2940 if (undo) 2941 curbuf->b_u_save_nr_cur = curhead->uh_save_nr - 1; 2942 else 2943 curbuf->b_u_save_nr_cur = curhead->uh_save_nr; 2944 } 2945 2946 // The timestamp can be the same for multiple changes, just use the one of 2947 // the undone/redone change. 2948 curbuf->b_u_time_cur = curhead->uh_time; 2949 2950 unblock_autocmds(); 2951 #ifdef U_DEBUG 2952 u_check(FALSE); 2953 #endif 2954 } 2955 2956 /* 2957 * If we deleted or added lines, report the number of less/more lines. 2958 * Otherwise, report the number of changes (this may be incorrect 2959 * in some cases, but it's better than nothing). 2960 */ 2961 static void 2962 u_undo_end( 2963 int did_undo, // just did an undo 2964 int absolute) // used ":undo N" 2965 { 2966 char *msgstr; 2967 u_header_T *uhp; 2968 char_u msgbuf[80]; 2969 2970 #ifdef FEAT_FOLDING 2971 if ((fdo_flags & FDO_UNDO) && KeyTyped) 2972 foldOpenCursor(); 2973 #endif 2974 2975 if (global_busy // no messages now, wait until global is finished 2976 || !messaging()) // 'lazyredraw' set, don't do messages now 2977 return; 2978 2979 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2980 --u_newcount; 2981 2982 u_oldcount -= u_newcount; 2983 if (u_oldcount == -1) 2984 msgstr = N_("more line"); 2985 else if (u_oldcount < 0) 2986 msgstr = N_("more lines"); 2987 else if (u_oldcount == 1) 2988 msgstr = N_("line less"); 2989 else if (u_oldcount > 1) 2990 msgstr = N_("fewer lines"); 2991 else 2992 { 2993 u_oldcount = u_newcount; 2994 if (u_newcount == 1) 2995 msgstr = N_("change"); 2996 else 2997 msgstr = N_("changes"); 2998 } 2999 3000 if (curbuf->b_u_curhead != NULL) 3001 { 3002 // For ":undo N" we prefer a "after #N" message. 3003 if (absolute && curbuf->b_u_curhead->uh_next.ptr != NULL) 3004 { 3005 uhp = curbuf->b_u_curhead->uh_next.ptr; 3006 did_undo = FALSE; 3007 } 3008 else if (did_undo) 3009 uhp = curbuf->b_u_curhead; 3010 else 3011 uhp = curbuf->b_u_curhead->uh_next.ptr; 3012 } 3013 else 3014 uhp = curbuf->b_u_newhead; 3015 3016 if (uhp == NULL) 3017 *msgbuf = NUL; 3018 else 3019 add_time(msgbuf, sizeof(msgbuf), uhp->uh_time); 3020 3021 #ifdef FEAT_CONCEAL 3022 { 3023 win_T *wp; 3024 3025 FOR_ALL_WINDOWS(wp) 3026 { 3027 if (wp->w_buffer == curbuf && wp->w_p_cole > 0) 3028 redraw_win_later(wp, NOT_VALID); 3029 } 3030 } 3031 #endif 3032 3033 smsg_attr_keep(0, _("%ld %s; %s #%ld %s"), 3034 u_oldcount < 0 ? -u_oldcount : u_oldcount, 3035 _(msgstr), 3036 did_undo ? _("before") : _("after"), 3037 uhp == NULL ? 0L : uhp->uh_seq, 3038 msgbuf); 3039 } 3040 3041 /* 3042 * u_sync: stop adding to the current entry list 3043 */ 3044 void 3045 u_sync( 3046 int force) // Also sync when no_u_sync is set. 3047 { 3048 // Skip it when already synced or syncing is disabled. 3049 if (curbuf->b_u_synced || (!force && no_u_sync > 0)) 3050 return; 3051 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 3052 if (p_imst == IM_ON_THE_SPOT && im_is_preediting()) 3053 return; // XIM is busy, don't break an undo sequence 3054 #endif 3055 if (get_undolevel() < 0) 3056 curbuf->b_u_synced = TRUE; // no entries, nothing to do 3057 else 3058 { 3059 u_getbot(); // compute ue_bot of previous u_save 3060 curbuf->b_u_curhead = NULL; 3061 } 3062 } 3063 3064 /* 3065 * ":undolist": List the leafs of the undo tree 3066 */ 3067 void 3068 ex_undolist(exarg_T *eap UNUSED) 3069 { 3070 garray_T ga; 3071 u_header_T *uhp; 3072 int mark; 3073 int nomark; 3074 int changes = 1; 3075 int i; 3076 3077 /* 3078 * 1: walk the tree to find all leafs, put the info in "ga". 3079 * 2: sort the lines 3080 * 3: display the list 3081 */ 3082 mark = ++lastmark; 3083 nomark = ++lastmark; 3084 ga_init2(&ga, (int)sizeof(char *), 20); 3085 3086 uhp = curbuf->b_u_oldhead; 3087 while (uhp != NULL) 3088 { 3089 if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark 3090 && uhp->uh_walk != mark) 3091 { 3092 if (ga_grow(&ga, 1) == FAIL) 3093 break; 3094 vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7d ", 3095 uhp->uh_seq, changes); 3096 add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff), 3097 uhp->uh_time); 3098 if (uhp->uh_save_nr > 0) 3099 { 3100 while (STRLEN(IObuff) < 33) 3101 STRCAT(IObuff, " "); 3102 vim_snprintf_add((char *)IObuff, IOSIZE, 3103 " %3ld", uhp->uh_save_nr); 3104 } 3105 ((char_u **)(ga.ga_data))[ga.ga_len++] = vim_strsave(IObuff); 3106 } 3107 3108 uhp->uh_walk = mark; 3109 3110 // go down in the tree if we haven't been there 3111 if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark 3112 && uhp->uh_prev.ptr->uh_walk != mark) 3113 { 3114 uhp = uhp->uh_prev.ptr; 3115 ++changes; 3116 } 3117 3118 // go to alternate branch if we haven't been there 3119 else if (uhp->uh_alt_next.ptr != NULL 3120 && uhp->uh_alt_next.ptr->uh_walk != nomark 3121 && uhp->uh_alt_next.ptr->uh_walk != mark) 3122 uhp = uhp->uh_alt_next.ptr; 3123 3124 // go up in the tree if we haven't been there and we are at the 3125 // start of alternate branches 3126 else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL 3127 && uhp->uh_next.ptr->uh_walk != nomark 3128 && uhp->uh_next.ptr->uh_walk != mark) 3129 { 3130 uhp = uhp->uh_next.ptr; 3131 --changes; 3132 } 3133 3134 else 3135 { 3136 // need to backtrack; mark this node as done 3137 uhp->uh_walk = nomark; 3138 if (uhp->uh_alt_prev.ptr != NULL) 3139 uhp = uhp->uh_alt_prev.ptr; 3140 else 3141 { 3142 uhp = uhp->uh_next.ptr; 3143 --changes; 3144 } 3145 } 3146 } 3147 3148 if (ga.ga_len == 0) 3149 msg(_("Nothing to undo")); 3150 else 3151 { 3152 sort_strings((char_u **)ga.ga_data, ga.ga_len); 3153 3154 msg_start(); 3155 msg_puts_attr(_("number changes when saved"), 3156 HL_ATTR(HLF_T)); 3157 for (i = 0; i < ga.ga_len && !got_int; ++i) 3158 { 3159 msg_putchar('\n'); 3160 if (got_int) 3161 break; 3162 msg_puts(((char **)ga.ga_data)[i]); 3163 } 3164 msg_end(); 3165 3166 ga_clear_strings(&ga); 3167 } 3168 } 3169 3170 /* 3171 * ":undojoin": continue adding to the last entry list 3172 */ 3173 void 3174 ex_undojoin(exarg_T *eap UNUSED) 3175 { 3176 if (curbuf->b_u_newhead == NULL) 3177 return; // nothing changed before 3178 if (curbuf->b_u_curhead != NULL) 3179 { 3180 emsg(_("E790: undojoin is not allowed after undo")); 3181 return; 3182 } 3183 if (!curbuf->b_u_synced) 3184 return; // already unsynced 3185 if (get_undolevel() < 0) 3186 return; // no entries, nothing to do 3187 else 3188 // Append next change to the last entry 3189 curbuf->b_u_synced = FALSE; 3190 } 3191 3192 /* 3193 * Called after writing or reloading the file and setting b_changed to FALSE. 3194 * Now an undo means that the buffer is modified. 3195 */ 3196 void 3197 u_unchanged(buf_T *buf) 3198 { 3199 u_unch_branch(buf->b_u_oldhead); 3200 buf->b_did_warn = FALSE; 3201 } 3202 3203 /* 3204 * After reloading a buffer which was saved for 'undoreload': Find the first 3205 * line that was changed and set the cursor there. 3206 */ 3207 void 3208 u_find_first_changed(void) 3209 { 3210 u_header_T *uhp = curbuf->b_u_newhead; 3211 u_entry_T *uep; 3212 linenr_T lnum; 3213 3214 if (curbuf->b_u_curhead != NULL || uhp == NULL) 3215 return; // undid something in an autocmd? 3216 3217 // Check that the last undo block was for the whole file. 3218 uep = uhp->uh_entry; 3219 if (uep->ue_top != 0 || uep->ue_bot != 0) 3220 return; 3221 3222 for (lnum = 1; lnum < curbuf->b_ml.ml_line_count 3223 && lnum <= uep->ue_size; ++lnum) 3224 { 3225 char_u *p = ml_get_buf(curbuf, lnum, FALSE); 3226 3227 if (uep->ue_array[lnum - 1].ul_len != curbuf->b_ml.ml_line_len 3228 || memcmp(p, uep->ue_array[lnum - 1].ul_line, uep->ue_array[lnum - 1].ul_len) != 0) 3229 { 3230 CLEAR_POS(&(uhp->uh_cursor)); 3231 uhp->uh_cursor.lnum = lnum; 3232 return; 3233 } 3234 } 3235 if (curbuf->b_ml.ml_line_count != uep->ue_size) 3236 { 3237 // lines added or deleted at the end, put the cursor there 3238 CLEAR_POS(&(uhp->uh_cursor)); 3239 uhp->uh_cursor.lnum = lnum; 3240 } 3241 } 3242 3243 /* 3244 * Increase the write count, store it in the last undo header, what would be 3245 * used for "u". 3246 */ 3247 void 3248 u_update_save_nr(buf_T *buf) 3249 { 3250 u_header_T *uhp; 3251 3252 ++buf->b_u_save_nr_last; 3253 buf->b_u_save_nr_cur = buf->b_u_save_nr_last; 3254 uhp = buf->b_u_curhead; 3255 if (uhp != NULL) 3256 uhp = uhp->uh_next.ptr; 3257 else 3258 uhp = buf->b_u_newhead; 3259 if (uhp != NULL) 3260 uhp->uh_save_nr = buf->b_u_save_nr_last; 3261 } 3262 3263 static void 3264 u_unch_branch(u_header_T *uhp) 3265 { 3266 u_header_T *uh; 3267 3268 for (uh = uhp; uh != NULL; uh = uh->uh_prev.ptr) 3269 { 3270 uh->uh_flags |= UH_CHANGED; 3271 if (uh->uh_alt_next.ptr != NULL) 3272 u_unch_branch(uh->uh_alt_next.ptr); // recursive 3273 } 3274 } 3275 3276 /* 3277 * Get pointer to last added entry. 3278 * If it's not valid, give an error message and return NULL. 3279 */ 3280 static u_entry_T * 3281 u_get_headentry(void) 3282 { 3283 if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL) 3284 { 3285 iemsg(_("E439: undo list corrupt")); 3286 return NULL; 3287 } 3288 return curbuf->b_u_newhead->uh_entry; 3289 } 3290 3291 /* 3292 * u_getbot(): compute the line number of the previous u_save 3293 * It is called only when b_u_synced is FALSE. 3294 */ 3295 static void 3296 u_getbot(void) 3297 { 3298 u_entry_T *uep; 3299 linenr_T extra; 3300 3301 uep = u_get_headentry(); // check for corrupt undo list 3302 if (uep == NULL) 3303 return; 3304 3305 uep = curbuf->b_u_newhead->uh_getbot_entry; 3306 if (uep != NULL) 3307 { 3308 /* 3309 * the new ue_bot is computed from the number of lines that has been 3310 * inserted (0 - deleted) since calling u_save. This is equal to the 3311 * old line count subtracted from the current line count. 3312 */ 3313 extra = curbuf->b_ml.ml_line_count - uep->ue_lcount; 3314 uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra; 3315 if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count) 3316 { 3317 iemsg(_("E440: undo line missing")); 3318 uep->ue_bot = uep->ue_top + 1; // assume all lines deleted, will 3319 // get all the old lines back 3320 // without deleting the current 3321 // ones 3322 } 3323 3324 curbuf->b_u_newhead->uh_getbot_entry = NULL; 3325 } 3326 3327 curbuf->b_u_synced = TRUE; 3328 } 3329 3330 /* 3331 * Free one header "uhp" and its entry list and adjust the pointers. 3332 */ 3333 static void 3334 u_freeheader( 3335 buf_T *buf, 3336 u_header_T *uhp, 3337 u_header_T **uhpp) // if not NULL reset when freeing this header 3338 { 3339 u_header_T *uhap; 3340 3341 // When there is an alternate redo list free that branch completely, 3342 // because we can never go there. 3343 if (uhp->uh_alt_next.ptr != NULL) 3344 u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp); 3345 3346 if (uhp->uh_alt_prev.ptr != NULL) 3347 uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; 3348 3349 // Update the links in the list to remove the header. 3350 if (uhp->uh_next.ptr == NULL) 3351 buf->b_u_oldhead = uhp->uh_prev.ptr; 3352 else 3353 uhp->uh_next.ptr->uh_prev.ptr = uhp->uh_prev.ptr; 3354 3355 if (uhp->uh_prev.ptr == NULL) 3356 buf->b_u_newhead = uhp->uh_next.ptr; 3357 else 3358 for (uhap = uhp->uh_prev.ptr; uhap != NULL; 3359 uhap = uhap->uh_alt_next.ptr) 3360 uhap->uh_next.ptr = uhp->uh_next.ptr; 3361 3362 u_freeentries(buf, uhp, uhpp); 3363 } 3364 3365 /* 3366 * Free an alternate branch and any following alternate branches. 3367 */ 3368 static void 3369 u_freebranch( 3370 buf_T *buf, 3371 u_header_T *uhp, 3372 u_header_T **uhpp) // if not NULL reset when freeing this header 3373 { 3374 u_header_T *tofree, *next; 3375 3376 // If this is the top branch we may need to use u_freeheader() to update 3377 // all the pointers. 3378 if (uhp == buf->b_u_oldhead) 3379 { 3380 while (buf->b_u_oldhead != NULL) 3381 u_freeheader(buf, buf->b_u_oldhead, uhpp); 3382 return; 3383 } 3384 3385 if (uhp->uh_alt_prev.ptr != NULL) 3386 uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL; 3387 3388 next = uhp; 3389 while (next != NULL) 3390 { 3391 tofree = next; 3392 if (tofree->uh_alt_next.ptr != NULL) 3393 u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp); // recursive 3394 next = tofree->uh_prev.ptr; 3395 u_freeentries(buf, tofree, uhpp); 3396 } 3397 } 3398 3399 /* 3400 * Free all the undo entries for one header and the header itself. 3401 * This means that "uhp" is invalid when returning. 3402 */ 3403 static void 3404 u_freeentries( 3405 buf_T *buf, 3406 u_header_T *uhp, 3407 u_header_T **uhpp) // if not NULL reset when freeing this header 3408 { 3409 u_entry_T *uep, *nuep; 3410 3411 // Check for pointers to the header that become invalid now. 3412 if (buf->b_u_curhead == uhp) 3413 buf->b_u_curhead = NULL; 3414 if (buf->b_u_newhead == uhp) 3415 buf->b_u_newhead = NULL; // freeing the newest entry 3416 if (uhpp != NULL && uhp == *uhpp) 3417 *uhpp = NULL; 3418 3419 for (uep = uhp->uh_entry; uep != NULL; uep = nuep) 3420 { 3421 nuep = uep->ue_next; 3422 u_freeentry(uep, uep->ue_size); 3423 } 3424 3425 #ifdef U_DEBUG 3426 uhp->uh_magic = 0; 3427 #endif 3428 vim_free((char_u *)uhp); 3429 --buf->b_u_numhead; 3430 } 3431 3432 /* 3433 * free entry 'uep' and 'n' lines in uep->ue_array[] 3434 */ 3435 static void 3436 u_freeentry(u_entry_T *uep, long n) 3437 { 3438 while (n > 0) 3439 vim_free(uep->ue_array[--n].ul_line); 3440 vim_free((char_u *)uep->ue_array); 3441 #ifdef U_DEBUG 3442 uep->ue_magic = 0; 3443 #endif 3444 vim_free((char_u *)uep); 3445 } 3446 3447 /* 3448 * invalidate the undo buffer; called when storage has already been released 3449 */ 3450 void 3451 u_clearall(buf_T *buf) 3452 { 3453 buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL; 3454 buf->b_u_synced = TRUE; 3455 buf->b_u_numhead = 0; 3456 buf->b_u_line_ptr.ul_line = NULL; 3457 buf->b_u_line_ptr.ul_len = 0; 3458 buf->b_u_line_lnum = 0; 3459 } 3460 3461 /* 3462 * Save the line "lnum" for the "U" command. 3463 */ 3464 static void 3465 u_saveline(linenr_T lnum) 3466 { 3467 if (lnum == curbuf->b_u_line_lnum) // line is already saved 3468 return; 3469 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) // should never happen 3470 return; 3471 u_clearline(); 3472 curbuf->b_u_line_lnum = lnum; 3473 if (curwin->w_cursor.lnum == lnum) 3474 curbuf->b_u_line_colnr = curwin->w_cursor.col; 3475 else 3476 curbuf->b_u_line_colnr = 0; 3477 if (u_save_line(&curbuf->b_u_line_ptr, lnum) == FAIL) 3478 do_outofmem_msg((long_u)0); 3479 } 3480 3481 /* 3482 * clear the line saved for the "U" command 3483 * (this is used externally for crossing a line while in insert mode) 3484 */ 3485 void 3486 u_clearline(void) 3487 { 3488 if (curbuf->b_u_line_ptr.ul_line != NULL) 3489 { 3490 VIM_CLEAR(curbuf->b_u_line_ptr.ul_line); 3491 curbuf->b_u_line_ptr.ul_len = 0; 3492 curbuf->b_u_line_lnum = 0; 3493 } 3494 } 3495 3496 /* 3497 * Implementation of the "U" command. 3498 * Differentiation from vi: "U" can be undone with the next "U". 3499 * We also allow the cursor to be in another line. 3500 * Careful: may trigger autocommands that reload the buffer. 3501 */ 3502 void 3503 u_undoline(void) 3504 { 3505 colnr_T t; 3506 undoline_T oldp; 3507 3508 if (undo_off) 3509 return; 3510 3511 if (curbuf->b_u_line_ptr.ul_line == NULL 3512 || curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count) 3513 { 3514 beep_flush(); 3515 return; 3516 } 3517 3518 // first save the line for the 'u' command 3519 if (u_savecommon(curbuf->b_u_line_lnum - 1, 3520 curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL) 3521 return; 3522 if (u_save_line(&oldp, curbuf->b_u_line_lnum) == FAIL) 3523 { 3524 do_outofmem_msg((long_u)0); 3525 return; 3526 } 3527 ml_replace_len(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr.ul_line, 3528 curbuf->b_u_line_ptr.ul_len, TRUE, FALSE); 3529 changed_bytes(curbuf->b_u_line_lnum, 0); 3530 curbuf->b_u_line_ptr = oldp; 3531 3532 t = curbuf->b_u_line_colnr; 3533 if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum) 3534 curbuf->b_u_line_colnr = curwin->w_cursor.col; 3535 curwin->w_cursor.col = t; 3536 curwin->w_cursor.lnum = curbuf->b_u_line_lnum; 3537 check_cursor_col(); 3538 } 3539 3540 /* 3541 * Free all allocated memory blocks for the buffer 'buf'. 3542 */ 3543 void 3544 u_blockfree(buf_T *buf) 3545 { 3546 while (buf->b_u_oldhead != NULL) 3547 u_freeheader(buf, buf->b_u_oldhead, NULL); 3548 vim_free(buf->b_u_line_ptr.ul_line); 3549 } 3550 3551 /* 3552 * Check if the 'modified' flag is set, or 'ff' has changed (only need to 3553 * check the first character, because it can only be "dos", "unix" or "mac"). 3554 * "nofile" and "scratch" type buffers are considered to always be unchanged. 3555 * Also considers a buffer changed when a terminal window contains a running 3556 * job. 3557 */ 3558 int 3559 bufIsChanged(buf_T *buf) 3560 { 3561 #ifdef FEAT_TERMINAL 3562 if (term_job_running(buf->b_term)) 3563 return TRUE; 3564 #endif 3565 return bufIsChangedNotTerm(buf); 3566 } 3567 3568 /* 3569 * Return TRUE if any buffer has changes. Also buffers that are not written. 3570 */ 3571 int 3572 anyBufIsChanged(void) 3573 { 3574 buf_T *buf; 3575 3576 FOR_ALL_BUFFERS(buf) 3577 if (bufIsChanged(buf)) 3578 return TRUE; 3579 return FALSE; 3580 } 3581 3582 /* 3583 * Like bufIsChanged() but ignoring a terminal window. 3584 */ 3585 int 3586 bufIsChangedNotTerm(buf_T *buf) 3587 { 3588 // In a "prompt" buffer we do respect 'modified', so that we can control 3589 // closing the window by setting or resetting that option. 3590 return (!bt_dontwrite(buf) || bt_prompt(buf)) 3591 && (buf->b_changed || file_ff_differs(buf, TRUE)); 3592 } 3593 3594 int 3595 curbufIsChanged(void) 3596 { 3597 return bufIsChanged(curbuf); 3598 } 3599 3600 #if defined(FEAT_EVAL) || defined(PROTO) 3601 3602 /* 3603 * For undotree(): Append the list of undo blocks at "first_uhp" to "list". 3604 * Recursive. 3605 */ 3606 static void 3607 u_eval_tree(u_header_T *first_uhp, list_T *list) 3608 { 3609 u_header_T *uhp = first_uhp; 3610 dict_T *dict; 3611 3612 while (uhp != NULL) 3613 { 3614 dict = dict_alloc(); 3615 if (dict == NULL) 3616 return; 3617 dict_add_number(dict, "seq", uhp->uh_seq); 3618 dict_add_number(dict, "time", (long)uhp->uh_time); 3619 if (uhp == curbuf->b_u_newhead) 3620 dict_add_number(dict, "newhead", 1); 3621 if (uhp == curbuf->b_u_curhead) 3622 dict_add_number(dict, "curhead", 1); 3623 if (uhp->uh_save_nr > 0) 3624 dict_add_number(dict, "save", uhp->uh_save_nr); 3625 3626 if (uhp->uh_alt_next.ptr != NULL) 3627 { 3628 list_T *alt_list = list_alloc(); 3629 3630 if (alt_list != NULL) 3631 { 3632 // Recursive call to add alternate undo tree. 3633 u_eval_tree(uhp->uh_alt_next.ptr, alt_list); 3634 dict_add_list(dict, "alt", alt_list); 3635 } 3636 } 3637 3638 list_append_dict(list, dict); 3639 uhp = uhp->uh_prev.ptr; 3640 } 3641 } 3642 3643 /* 3644 * "undofile(name)" function 3645 */ 3646 void 3647 f_undofile(typval_T *argvars UNUSED, typval_T *rettv) 3648 { 3649 rettv->v_type = VAR_STRING; 3650 #ifdef FEAT_PERSISTENT_UNDO 3651 { 3652 char_u *fname = tv_get_string(&argvars[0]); 3653 3654 if (*fname == NUL) 3655 { 3656 // If there is no file name there will be no undo file. 3657 rettv->vval.v_string = NULL; 3658 } 3659 else 3660 { 3661 char_u *ffname = FullName_save(fname, TRUE); 3662 3663 if (ffname != NULL) 3664 rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE); 3665 vim_free(ffname); 3666 } 3667 } 3668 #else 3669 rettv->vval.v_string = NULL; 3670 #endif 3671 } 3672 3673 /* 3674 * "undotree()" function 3675 */ 3676 void 3677 f_undotree(typval_T *argvars UNUSED, typval_T *rettv) 3678 { 3679 if (rettv_dict_alloc(rettv) == OK) 3680 { 3681 dict_T *dict = rettv->vval.v_dict; 3682 list_T *list; 3683 3684 dict_add_number(dict, "synced", (long)curbuf->b_u_synced); 3685 dict_add_number(dict, "seq_last", curbuf->b_u_seq_last); 3686 dict_add_number(dict, "save_last", (long)curbuf->b_u_save_nr_last); 3687 dict_add_number(dict, "seq_cur", curbuf->b_u_seq_cur); 3688 dict_add_number(dict, "time_cur", (long)curbuf->b_u_time_cur); 3689 dict_add_number(dict, "save_cur", (long)curbuf->b_u_save_nr_cur); 3690 3691 list = list_alloc(); 3692 if (list != NULL) 3693 { 3694 u_eval_tree(curbuf->b_u_oldhead, list); 3695 dict_add_list(dict, "entries", list); 3696 } 3697 } 3698 } 3699 3700 #endif 3701