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