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