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