comparison src/undo.c @ 758:d591d4ceeaee

updated for version 7.0224
author vimboss
date Tue, 14 Mar 2006 23:00:46 +0000
parents ac005a544e24
children f0d0d3d3a1e2
comparison
equal deleted inserted replaced
757:8b0484fd9119 758:d591d4ceeaee
37 * V 37 * V
38 * etc. 38 * etc.
39 * 39 *
40 * Each u_entry list contains the information for one undo or redo. 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), 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. 42 * or is NULL if nothing has been undone (end of the branch).
43 * 43 *
44 * For keeping alternate undo/redo branches the uh_alt field is used. Thus at 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 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 46 * uh_seq field is numbered sequentially to be able to find a newer or older
47 * branch. 47 * branch.
48 * 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 *
49 * All data is allocated with U_ALLOC_LINE(), it will be freed as soon as the 75 * All data is allocated with U_ALLOC_LINE(), it will be freed as soon as the
50 * buffer is unloaded. 76 * buffer is unloaded.
51 */ 77 */
52 78
53 #include "vim.h" 79 #include "vim.h"
54 80
55 /* See below: use malloc()/free() for memory management. */ 81 /* See below: use malloc()/free() for memory management. */
56 #define U_USE_MALLOC 1 82 #define U_USE_MALLOC 1
57 83
84 static void u_unch_branch __ARGS((u_header_T *uhp));
58 static u_entry_T *u_get_headentry __ARGS((void)); 85 static u_entry_T *u_get_headentry __ARGS((void));
59 static void u_getbot __ARGS((void)); 86 static void u_getbot __ARGS((void));
60 static int undo_allowed __ARGS((void)); 87 static int undo_allowed __ARGS((void));
61 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T)); 88 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T));
62 static void u_doit __ARGS((int count)); 89 static void u_doit __ARGS((int count));
63 static void u_undoredo __ARGS((void)); 90 static void u_undoredo __ARGS((void));
64 static void u_undo_end __ARGS((void)); 91 static void u_undo_end __ARGS((void));
65 static void u_freelist __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); 92 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
66 static void u_freebranch __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); 93 static void u_freebranch __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
67 static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); 94 static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
68 static void u_freeentry __ARGS((u_entry_T *, long)); 95 static void u_freeentry __ARGS((u_entry_T *, long));
69 96
70 #ifdef U_USE_MALLOC 97 #ifdef U_USE_MALLOC
268 if (uhp == NULL) 295 if (uhp == NULL)
269 goto nomem; 296 goto nomem;
270 } 297 }
271 298
272 /* 299 /*
273 * If we undid more than we redid, remove the entry lists before and 300 * If we undid more than we redid, move the entry lists before and
274 * including curbuf->b_u_curhead to the alternate branch. 301 * including curbuf->b_u_curhead to an alternate branch.
275 */ 302 */
276 old_curhead = curbuf->b_u_curhead; 303 old_curhead = curbuf->b_u_curhead;
277 if (old_curhead != NULL) 304 if (old_curhead != NULL)
278 { 305 {
279 curbuf->b_u_newhead = old_curhead->uh_next; 306 curbuf->b_u_newhead = old_curhead->uh_next;
283 /* 310 /*
284 * free headers to keep the size right 311 * free headers to keep the size right
285 */ 312 */
286 while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL) 313 while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL)
287 { 314 {
288 u_header_T *upfree = curbuf->b_u_oldhead; 315 u_header_T *uhfree = curbuf->b_u_oldhead;
289 316
290 /* If there is no branch only free one header. */ 317 /* If there is no branch only free one header. */
291 if (upfree->uh_alt_next == NULL) 318 if (uhfree->uh_alt_next == NULL)
292 u_freelist(curbuf, upfree, &old_curhead); 319 u_freeheader(curbuf, uhfree, &old_curhead);
293 else 320 else
294 { 321 {
295 /* Free the oldest alternate branch as a whole. */ 322 /* Free the oldest alternate branch as a whole. */
296 while (upfree->uh_alt_next != NULL) 323 while (uhfree->uh_alt_next != NULL)
297 upfree = upfree->uh_alt_next; 324 uhfree = uhfree->uh_alt_next;
298 u_freebranch(curbuf, upfree, &old_curhead); 325 u_freebranch(curbuf, uhfree, &old_curhead);
299 } 326 }
300 } 327 }
301 328
302 if (p_ul < 0) /* no undo at all */ 329 if (p_ul < 0) /* no undo at all */
303 { 330 {
315 old_curhead->uh_alt_prev = uhp; 342 old_curhead->uh_alt_prev = uhp;
316 if (curbuf->b_u_oldhead == old_curhead) 343 if (curbuf->b_u_oldhead == old_curhead)
317 curbuf->b_u_oldhead = uhp; 344 curbuf->b_u_oldhead = uhp;
318 } 345 }
319 uhp->uh_alt_prev = NULL; 346 uhp->uh_alt_prev = NULL;
347 if (curbuf->b_u_newhead != NULL)
348 curbuf->b_u_newhead->uh_prev = uhp;
349
320 uhp->uh_seq = curbuf->b_u_seq_last++; 350 uhp->uh_seq = curbuf->b_u_seq_last++;
321 curbuf->b_u_seq_cur = curbuf->b_u_seq_last; 351 curbuf->b_u_seq_cur = curbuf->b_u_seq_last;
322 if (curbuf->b_u_newhead != NULL) 352 uhp->uh_time = time(NULL);
323 curbuf->b_u_newhead->uh_prev = uhp; 353 curbuf->b_u_seq_time = uhp->uh_time + 1;
354
324 uhp->uh_walk = 0; 355 uhp->uh_walk = 0;
325 uhp->uh_entry = NULL; 356 uhp->uh_entry = NULL;
326 uhp->uh_getbot_entry = NULL; 357 uhp->uh_getbot_entry = NULL;
327 uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */ 358 uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */
328 #ifdef FEAT_VIRTUALEDIT 359 #ifdef FEAT_VIRTUALEDIT
329 if (virtual_active() && curwin->w_cursor.coladd > 0) 360 if (virtual_active() && curwin->w_cursor.coladd > 0)
330 uhp->uh_cursor_vcol = getviscol(); 361 uhp->uh_cursor_vcol = getviscol();
331 else 362 else
332 uhp->uh_cursor_vcol = -1; 363 uhp->uh_cursor_vcol = -1;
333 #endif 364 #endif
334 uhp->uh_time = time(NULL);
335 365
336 /* save changed and buffer empty flag for undo */ 366 /* save changed and buffer empty flag for undo */
337 uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 367 uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
338 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); 368 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
339 369
573 beep_flush(); 603 beep_flush();
574 break; 604 break;
575 } 605 }
576 606
577 u_undoredo(); 607 u_undoredo();
578 curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_seq;
579 } 608 }
580 else 609 else
581 { 610 {
582 if (curbuf->b_u_curhead == NULL || p_ul <= 0) 611 if (curbuf->b_u_curhead == NULL || p_ul <= 0)
583 { 612 {
584 beep_flush(); /* nothing to redo */ 613 beep_flush(); /* nothing to redo */
585 break; 614 break;
586 } 615 }
587 616
588 u_undoredo(); 617 u_undoredo();
589 curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_seq + 1; 618 ++curbuf->b_u_seq_cur;
619 ++curbuf->b_u_seq_time;
590 620
591 /* Advance for next redo. Set "newhead" when at the end of the 621 /* Advance for next redo. Set "newhead" when at the end of the
592 * redoable changes. */ 622 * redoable changes. */
593 if (curbuf->b_u_curhead->uh_prev == NULL) 623 if (curbuf->b_u_curhead->uh_prev == NULL)
594 curbuf->b_u_newhead = curbuf->b_u_curhead; 624 curbuf->b_u_newhead = curbuf->b_u_curhead;
601 static int lastmark = 0; 631 static int lastmark = 0;
602 632
603 /* 633 /*
604 * Undo or redo over the timeline. 634 * Undo or redo over the timeline.
605 * When "step" is negative go back in time, otherwise goes forward in time. 635 * When "step" is negative go back in time, otherwise goes forward in time.
636 * When "sec" is FALSE make "step" steps, when "sec" is TRUE use "step" as
637 * seconds.
606 */ 638 */
607 void 639 void
608 undo_time(step) 640 undo_time(step, sec)
609 int step; 641 long step;
642 int sec;
610 { 643 {
611 long target; 644 long target;
612 long closest; 645 long closest;
646 long closest_start;
647 long closest_seq = 0;
648 long val;
649 long limit;
613 u_header_T *uhp; 650 u_header_T *uhp;
614 u_header_T *last; 651 u_header_T *last;
615 int mark; 652 int mark;
616 int nomark; 653 int nomark;
617 int round; 654 int round;
655 int dosec = sec;
656 int above = FALSE;
618 657
619 u_newcount = 0; 658 u_newcount = 0;
620 u_oldcount = 0; 659 u_oldcount = 0;
621 if (curbuf->b_ml.ml_flags & ML_EMPTY) 660 if (curbuf->b_ml.ml_flags & ML_EMPTY)
622 u_oldcount = -1; 661 u_oldcount = -1;
623 662
624 /* "target" is the node below which we want to be. When going forward 663 /* "target" is the node below which we want to be. When going forward
625 * the current one also counts, thus do one less. */ 664 * the current one also counts, thus do one less. */
626 if (step < 0) 665 if (step < 0)
627 { 666 {
628 target = curbuf->b_u_seq_cur + step; 667 if (sec)
629 closest = -1; 668 target = (long)curbuf->b_u_seq_time + step;
669 else
670 target = curbuf->b_u_seq_cur + step;
671 if (target < 0)
672 target = -1;
673 closest = -2;
630 } 674 }
631 else 675 else
632 { 676 {
633 target = curbuf->b_u_seq_cur + step - 1; 677 if (sec)
634 closest = curbuf->b_u_seq_last + 1; 678 {
635 } 679 target = curbuf->b_u_seq_time + step - 1;
636 680 closest = time(NULL) + 1;
637 /* May do this twice: 681 }
682 else
683 {
684 target = curbuf->b_u_seq_cur + step - 1;
685 closest = curbuf->b_u_seq_last + 1;
686 }
687 if (target >= closest)
688 target = closest - 1;
689 }
690 closest_start = closest;
691 if (sec)
692 limit = curbuf->b_u_seq_time + (step > 0 ? -1 : 1);
693 else
694 limit = curbuf->b_u_seq_cur;
695
696 /*
697 * May do this twice:
638 * 1. Search for "target", update "closest" to the best match found. 698 * 1. Search for "target", update "closest" to the best match found.
639 * 2. If "target" not found search for "closest". */ 699 * 2. If "target" not found search for "closest".
700 *
701 * When using the closest time we use the sequence number in the second
702 * round, because there may be several entries with the same time.
703 */
640 for (round = 1; round <= 2; ++round) 704 for (round = 1; round <= 2; ++round)
641 { 705 {
642 /* Find the path from the current state to where we want to go. The 706 /* Find the path from the current state to where we want to go. The
643 * desired state can be anywhere in the undo tree, need to go all over 707 * desired state can be anywhere in the undo tree, need to go all over
644 * it. We put "nomark" in uh_walk where we have been without success, 708 * it. We put "nomark" in uh_walk where we have been without success,
652 uhp = curbuf->b_u_curhead; 716 uhp = curbuf->b_u_curhead;
653 717
654 while (uhp != NULL) 718 while (uhp != NULL)
655 { 719 {
656 uhp->uh_walk = mark; 720 uhp->uh_walk = mark;
657 if (uhp->uh_seq == target) /* found it! */ 721 val = (dosec ? uhp->uh_time : uhp->uh_seq);
722
723 if (round == 1)
724 {
725 /* Remember the header that is closest to the target.
726 * It must be at least in the right direction (checked with
727 * "limit"). When the timestamp is equal find the
728 * highest/lowest sequence number. */
729 if ((dosec && val == closest)
730 ? (step < 0
731 ? uhp->uh_seq < closest_seq
732 : uhp->uh_seq > closest_seq)
733 : (step < 0
734 ? (val < limit
735 && (closest > target
736 ? (val <= closest)
737 : (val >= closest)))
738 : (val > limit
739 && (closest < target
740 ? val >= closest
741 : val <= closest))))
742 {
743 closest = val;
744 closest_seq = uhp->uh_seq;
745 }
746 }
747
748 /* Quit searching when we found a match. But when searching for a
749 * time we need to continue looking for the best uh_seq. */
750 if (target == val && !dosec)
658 break; 751 break;
659
660 if (round == 1 && (step < 0
661 ? (uhp->uh_seq < target && uhp->uh_seq > closest)
662 : (uhp->uh_seq > target && uhp->uh_seq < closest)))
663 closest = uhp->uh_seq;
664 752
665 /* go down in the tree if we haven't been there */ 753 /* go down in the tree if we haven't been there */
666 if (uhp->uh_prev != NULL && uhp->uh_prev->uh_walk != nomark 754 if (uhp->uh_prev != NULL && uhp->uh_prev->uh_walk != nomark
667 && uhp->uh_prev->uh_walk != mark) 755 && uhp->uh_prev->uh_walk != mark)
668 uhp = uhp->uh_prev; 756 uhp = uhp->uh_prev;
691 } 779 }
692 } 780 }
693 781
694 if (uhp != NULL) /* found it */ 782 if (uhp != NULL) /* found it */
695 break; 783 break;
696 if (step < 0 && closest == -1) 784 if (closest == closest_start)
697 { 785 {
698 MSG(_("Already at oldest change")); 786 if (step < 0)
787 MSG(_("Already at oldest change"));
788 else
789 MSG(_("Already at newest change"));
699 return; 790 return;
700 } 791 }
701 if (step > 0 && closest == curbuf->b_u_seq_last + 1) 792
702 { 793 target = closest_seq;
703 MSG(_("Already at newest change")); 794 dosec = FALSE;
704 return; 795 if (step < 0)
705 } 796 above = TRUE; /* stop above the header */
706
707 target = closest;
708 } 797 }
709 798
710 /* If we found it: Follow the path to go to where we want to be. */ 799 /* If we found it: Follow the path to go to where we want to be. */
711 if (uhp != NULL) 800 if (uhp != NULL)
712 { 801 {
718 uhp = curbuf->b_u_curhead; 807 uhp = curbuf->b_u_curhead;
719 if (uhp == NULL) 808 if (uhp == NULL)
720 uhp = curbuf->b_u_newhead; 809 uhp = curbuf->b_u_newhead;
721 else 810 else
722 { 811 {
723 while (uhp->uh_alt_prev != NULL) 812 while (uhp->uh_alt_prev != NULL
813 && uhp->uh_alt_prev->uh_walk == mark)
724 { 814 {
725 uhp->uh_walk = nomark; 815 uhp->uh_walk = nomark;
726 uhp = uhp->uh_alt_prev; 816 uhp = uhp->uh_alt_prev;
727 } 817 }
728 uhp = uhp->uh_next; 818 uhp = uhp->uh_next;
730 if (uhp == NULL || uhp->uh_walk != mark) 820 if (uhp == NULL || uhp->uh_walk != mark)
731 break; 821 break;
732 curbuf->b_u_curhead = uhp; 822 curbuf->b_u_curhead = uhp;
733 u_undoredo(); 823 u_undoredo();
734 uhp->uh_walk = nomark; /* don't go back down here */ 824 uhp->uh_walk = nomark; /* don't go back down here */
735 curbuf->b_u_seq_cur = uhp->uh_seq;
736 } 825 }
737 826
738 /* 827 /*
739 * And now go down the tree, branching off where needed. 828 * And now go down the tree (redo), branching off where needed.
740 */ 829 */
741 uhp = curbuf->b_u_curhead; 830 uhp = curbuf->b_u_curhead;
742 for (;;) 831 for (;;)
743 { 832 {
744 /* Find the last branch with a mark, that's the one. */ 833 /* Find the last branch with a mark, that's the one. */
757 last->uh_alt_next = uhp; 846 last->uh_alt_next = uhp;
758 uhp->uh_alt_prev = last; 847 uhp->uh_alt_prev = last;
759 848
760 uhp = last; 849 uhp = last;
761 } 850 }
851 curbuf->b_u_curhead = uhp;
852 curbuf->b_u_seq_cur = uhp->uh_seq;
853 curbuf->b_u_seq_time = uhp->uh_time;
762 854
763 if (uhp->uh_walk != mark) 855 if (uhp->uh_walk != mark)
764 break; /* must have reached the target */ 856 break; /* must have reached the target */
765 857
766 curbuf->b_u_curhead = uhp; 858 /* Stop when going backwards in time and didn't find the exact
859 * header we were looking for. */
860 if (uhp->uh_seq == target && above)
861 break;
862
767 u_undoredo(); 863 u_undoredo();
768 curbuf->b_u_seq_cur = uhp->uh_seq + 1; 864 ++curbuf->b_u_seq_cur;
865 ++curbuf->b_u_seq_time;
769 866
770 /* Advance "curhead" to below the header we last used. If it 867 /* Advance "curhead" to below the header we last used. If it
771 * becomes NULL then we need to set "newhead" to this leaf. */ 868 * becomes NULL then we need to set "newhead" to this leaf. */
772 if (uhp->uh_prev == NULL) 869 if (uhp->uh_prev == NULL)
773 curbuf->b_u_newhead = uhp; 870 curbuf->b_u_newhead = uhp;
811 pos_T namedm[NMARKS]; 908 pos_T namedm[NMARKS];
812 #ifdef FEAT_VISUAL 909 #ifdef FEAT_VISUAL
813 visualinfo_T visualinfo; 910 visualinfo_T visualinfo;
814 #endif 911 #endif
815 int empty_buffer; /* buffer became empty */ 912 int empty_buffer; /* buffer became empty */
816 913 u_header_T *curhead = curbuf->b_u_curhead;
817 old_flags = curbuf->b_u_curhead->uh_flags; 914
915 old_flags = curhead->uh_flags;
818 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 916 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
819 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); 917 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
820 setpcmark(); 918 setpcmark();
821 919
822 /* 920 /*
829 curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count; 927 curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count;
830 curbuf->b_op_start.col = 0; 928 curbuf->b_op_start.col = 0;
831 curbuf->b_op_end.lnum = 0; 929 curbuf->b_op_end.lnum = 0;
832 curbuf->b_op_end.col = 0; 930 curbuf->b_op_end.col = 0;
833 931
834 for (uep = curbuf->b_u_curhead->uh_entry; uep != NULL; uep = nuep) 932 for (uep = curhead->uh_entry; uep != NULL; uep = nuep)
835 { 933 {
836 top = uep->ue_top; 934 top = uep->ue_top;
837 bot = uep->ue_bot; 935 bot = uep->ue_bot;
838 if (bot == 0) 936 if (bot == 0)
839 bot = curbuf->b_ml.ml_line_count + 1; 937 bot = curbuf->b_ml.ml_line_count + 1;
851 if (top < newlnum) 949 if (top < newlnum)
852 { 950 {
853 /* If the saved cursor is somewhere in this undo block, move it to 951 /* If the saved cursor is somewhere in this undo block, move it to
854 * the remembered position. Makes "gwap" put the cursor back 952 * the remembered position. Makes "gwap" put the cursor back
855 * where it was. */ 953 * where it was. */
856 lnum = curbuf->b_u_curhead->uh_cursor.lnum; 954 lnum = curhead->uh_cursor.lnum;
857 if (lnum >= top && lnum <= top + newsize + 1) 955 if (lnum >= top && lnum <= top + newsize + 1)
858 { 956 {
859 curwin->w_cursor = curbuf->b_u_curhead->uh_cursor; 957 curwin->w_cursor = curhead->uh_cursor;
860 newlnum = curwin->w_cursor.lnum - 1; 958 newlnum = curwin->w_cursor.lnum - 1;
861 } 959 }
862 else 960 else
863 { 961 {
864 /* Use the first line that actually changed. Avoids that 962 /* Use the first line that actually changed. Avoids that
968 nuep = uep->ue_next; 1066 nuep = uep->ue_next;
969 uep->ue_next = newlist; 1067 uep->ue_next = newlist;
970 newlist = uep; 1068 newlist = uep;
971 } 1069 }
972 1070
973 curbuf->b_u_curhead->uh_entry = newlist; 1071 curhead->uh_entry = newlist;
974 curbuf->b_u_curhead->uh_flags = new_flags; 1072 curhead->uh_flags = new_flags;
975 if ((old_flags & UH_EMPTYBUF) && bufempty()) 1073 if ((old_flags & UH_EMPTYBUF) && bufempty())
976 curbuf->b_ml.ml_flags |= ML_EMPTY; 1074 curbuf->b_ml.ml_flags |= ML_EMPTY;
977 if (old_flags & UH_CHANGED) 1075 if (old_flags & UH_CHANGED)
978 changed(); 1076 changed();
979 else 1077 else
985 1083
986 /* 1084 /*
987 * restore marks from before undo/redo 1085 * restore marks from before undo/redo
988 */ 1086 */
989 for (i = 0; i < NMARKS; ++i) 1087 for (i = 0; i < NMARKS; ++i)
990 if (curbuf->b_u_curhead->uh_namedm[i].lnum != 0) 1088 if (curhead->uh_namedm[i].lnum != 0)
991 { 1089 {
992 curbuf->b_namedm[i] = curbuf->b_u_curhead->uh_namedm[i]; 1090 curbuf->b_namedm[i] = curhead->uh_namedm[i];
993 curbuf->b_u_curhead->uh_namedm[i] = namedm[i]; 1091 curhead->uh_namedm[i] = namedm[i];
994 } 1092 }
995 #ifdef FEAT_VISUAL 1093 #ifdef FEAT_VISUAL
996 if (curbuf->b_u_curhead->uh_visual.vi_start.lnum != 0) 1094 if (curhead->uh_visual.vi_start.lnum != 0)
997 { 1095 {
998 curbuf->b_visual = curbuf->b_u_curhead->uh_visual; 1096 curbuf->b_visual = curhead->uh_visual;
999 curbuf->b_u_curhead->uh_visual = visualinfo; 1097 curhead->uh_visual = visualinfo;
1000 } 1098 }
1001 #endif 1099 #endif
1002 1100
1003 /* 1101 /*
1004 * If the cursor is only off by one line, put it at the same position as 1102 * If the cursor is only off by one line, put it at the same position as
1005 * before starting the change (for the "o" command). 1103 * before starting the change (for the "o" command).
1006 * Otherwise the cursor should go to the first undone line. 1104 * Otherwise the cursor should go to the first undone line.
1007 */ 1105 */
1008 if (curbuf->b_u_curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum 1106 if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum
1009 && curwin->w_cursor.lnum > 1) 1107 && curwin->w_cursor.lnum > 1)
1010 --curwin->w_cursor.lnum; 1108 --curwin->w_cursor.lnum;
1011 if (curbuf->b_u_curhead->uh_cursor.lnum == curwin->w_cursor.lnum) 1109 if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum)
1012 { 1110 {
1013 curwin->w_cursor.col = curbuf->b_u_curhead->uh_cursor.col; 1111 curwin->w_cursor.col = curhead->uh_cursor.col;
1014 #ifdef FEAT_VIRTUALEDIT 1112 #ifdef FEAT_VIRTUALEDIT
1015 if (virtual_active() && curbuf->b_u_curhead->uh_cursor_vcol >= 0) 1113 if (virtual_active() && curhead->uh_cursor_vcol >= 0)
1016 coladvance((colnr_T)curbuf->b_u_curhead->uh_cursor_vcol); 1114 coladvance((colnr_T)curhead->uh_cursor_vcol);
1017 else 1115 else
1018 curwin->w_cursor.coladd = 0; 1116 curwin->w_cursor.coladd = 0;
1019 #endif 1117 #endif
1020 } 1118 }
1021 else if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count) 1119 else if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count)
1032 #endif 1130 #endif
1033 } 1131 }
1034 1132
1035 /* Make sure the cursor is on an existing line and column. */ 1133 /* Make sure the cursor is on an existing line and column. */
1036 check_cursor(); 1134 check_cursor();
1135
1136 /* Remember where we are for "g-" and ":earlier 10s". */
1137 curbuf->b_u_seq_cur = curhead->uh_seq;
1138 curbuf->b_u_seq_time = curhead->uh_time;
1037 } 1139 }
1038 1140
1039 /* 1141 /*
1040 * If we deleted or added lines, report the number of less/more lines. 1142 * If we deleted or added lines, report the number of less/more lines.
1041 * Otherwise, report the number of changes (this may be incorrect 1143 * Otherwise, report the number of changes (this may be incorrect
1134 */ 1236 */
1135 void 1237 void
1136 u_unchanged(buf) 1238 u_unchanged(buf)
1137 buf_T *buf; 1239 buf_T *buf;
1138 { 1240 {
1241 u_unch_branch(buf->b_u_oldhead);
1242 buf->b_did_warn = FALSE;
1243 }
1244
1245 static void
1246 u_unch_branch(uhp)
1247 u_header_T *uhp;
1248 {
1139 u_header_T *uh; 1249 u_header_T *uh;
1140 1250
1141 for (uh = buf->b_u_newhead; uh; uh = uh->uh_next) 1251 for (uh = uhp; uh != NULL; uh = uh->uh_prev)
1252 {
1142 uh->uh_flags |= UH_CHANGED; 1253 uh->uh_flags |= UH_CHANGED;
1143 buf->b_did_warn = FALSE; 1254 if (uh->uh_alt_next != NULL)
1255 u_unch_branch(uh->uh_alt_next); /* recursive */
1256 }
1144 } 1257 }
1145 1258
1146 /* 1259 /*
1147 * Get pointer to last added entry. 1260 * Get pointer to last added entry.
1148 * If it's not valid, give an error message and return NULL. 1261 * If it's not valid, give an error message and return NULL.
1199 1312
1200 /* 1313 /*
1201 * Free one header and its entry list and adjust the pointers. 1314 * Free one header and its entry list and adjust the pointers.
1202 */ 1315 */
1203 static void 1316 static void
1204 u_freelist(buf, uhp, uhpp) 1317 u_freeheader(buf, uhp, uhpp)
1205 buf_T *buf; 1318 buf_T *buf;
1206 u_header_T *uhp; 1319 u_header_T *uhp;
1207 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 1320 u_header_T **uhpp; /* if not NULL reset when freeing this header */
1208 { 1321 {
1209 /* When there is an alternate redo list free that branch completely, 1322 /* When there is an alternate redo list free that branch completely,
1227 1340
1228 u_freeentries(buf, uhp, uhpp); 1341 u_freeentries(buf, uhp, uhpp);
1229 } 1342 }
1230 1343
1231 /* 1344 /*
1232 * Free an alternate branch and all following alternate branches. 1345 * Free an alternate branch and any following alternate branches.
1233 */ 1346 */
1234 static void 1347 static void
1235 u_freebranch(buf, uhp, uhpp) 1348 u_freebranch(buf, uhp, uhpp)
1236 buf_T *buf; 1349 buf_T *buf;
1237 u_header_T *uhp; 1350 u_header_T *uhp;
1413 void 1526 void
1414 u_blockfree(buf) 1527 u_blockfree(buf)
1415 buf_T *buf; 1528 buf_T *buf;
1416 { 1529 {
1417 while (buf->b_u_oldhead != NULL) 1530 while (buf->b_u_oldhead != NULL)
1418 u_freelist(buf, buf->b_u_oldhead, NULL); 1531 u_freeheader(buf, buf->b_u_oldhead, NULL);
1419 U_FREE_LINE(buf->b_u_line_ptr); 1532 U_FREE_LINE(buf->b_u_line_ptr);
1420 } 1533 }
1421 1534
1422 #else 1535 #else
1423 /* 1536 /*