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