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