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