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