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