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