Mercurial > vim
comparison src/undo.c @ 753:ac005a544e24
updated for version 7.0223
author | vimboss |
---|---|
date | Mon, 13 Mar 2006 22:15:53 +0000 |
parents | f08390485cd3 |
children | d591d4ceeaee |
comparison
equal
deleted
inserted
replaced
752:7a6368b8edf6 | 753:ac005a544e24 |
---|---|
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. |
43 * | 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 * | |
44 * All data is allocated with U_ALLOC_LINE(), it will be freed as soon as the | 49 * All data is allocated with U_ALLOC_LINE(), it will be freed as soon as the |
45 * buffer is unloaded. | 50 * buffer is unloaded. |
46 */ | 51 */ |
47 | 52 |
48 #include "vim.h" | 53 #include "vim.h" |
55 static int undo_allowed __ARGS((void)); | 60 static int undo_allowed __ARGS((void)); |
56 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T)); | 61 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T)); |
57 static void u_doit __ARGS((int count)); | 62 static void u_doit __ARGS((int count)); |
58 static void u_undoredo __ARGS((void)); | 63 static void u_undoredo __ARGS((void)); |
59 static void u_undo_end __ARGS((void)); | 64 static void u_undo_end __ARGS((void)); |
60 static void u_freelist __ARGS((buf_T *buf, struct u_header *)); | 65 static void u_freelist __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)); | |
67 static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); | |
61 static void u_freeentry __ARGS((u_entry_T *, long)); | 68 static void u_freeentry __ARGS((u_entry_T *, long)); |
62 | 69 |
63 #ifdef U_USE_MALLOC | 70 #ifdef U_USE_MALLOC |
64 # define U_FREE_LINE(ptr) vim_free(ptr) | 71 # define U_FREE_LINE(ptr) vim_free(ptr) |
65 # define U_ALLOC_LINE(size) lalloc((long_u)((size) + 1), FALSE) | 72 # define U_ALLOC_LINE(size) lalloc((long_u)((size) + 1), FALSE) |
194 static int | 201 static int |
195 u_savecommon(top, bot, newbot) | 202 u_savecommon(top, bot, newbot) |
196 linenr_T top, bot; | 203 linenr_T top, bot; |
197 linenr_T newbot; | 204 linenr_T newbot; |
198 { | 205 { |
199 linenr_T lnum; | 206 linenr_T lnum; |
200 long i; | 207 long i; |
201 struct u_header *uhp; | 208 u_header_T *uhp; |
202 u_entry_T *uep; | 209 u_header_T *old_curhead; |
203 u_entry_T *prev_uep; | 210 u_entry_T *uep; |
204 long size; | 211 u_entry_T *prev_uep; |
212 long size; | |
205 | 213 |
206 /* When making changes is not allowed return FAIL. It's a crude way to | 214 /* When making changes is not allowed return FAIL. It's a crude way to |
207 * make all change commands fail. */ | 215 * make all change commands fail. */ |
208 if (!undo_allowed()) | 216 if (!undo_allowed()) |
209 return FAIL; | 217 return FAIL; |
248 #ifdef FEAT_JUMPLIST | 256 #ifdef FEAT_JUMPLIST |
249 /* Need to create new entry in b_changelist. */ | 257 /* Need to create new entry in b_changelist. */ |
250 curbuf->b_new_change = TRUE; | 258 curbuf->b_new_change = TRUE; |
251 #endif | 259 #endif |
252 | 260 |
261 if (p_ul >= 0) | |
262 { | |
263 /* | |
264 * Make a new header entry. Do this first so that we don't mess | |
265 * up the undo info when out of memory. | |
266 */ | |
267 uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T)); | |
268 if (uhp == NULL) | |
269 goto nomem; | |
270 } | |
271 | |
253 /* | 272 /* |
254 * if we undid more than we redid, free the entry lists before and | 273 * If we undid more than we redid, remove the entry lists before and |
255 * including curbuf->b_u_curhead | 274 * including curbuf->b_u_curhead to the alternate branch. |
256 */ | 275 */ |
257 while (curbuf->b_u_curhead != NULL) | 276 old_curhead = curbuf->b_u_curhead; |
258 u_freelist(curbuf, curbuf->b_u_newhead); | 277 if (old_curhead != NULL) |
278 { | |
279 curbuf->b_u_newhead = old_curhead->uh_next; | |
280 curbuf->b_u_curhead = NULL; | |
281 } | |
259 | 282 |
260 /* | 283 /* |
261 * free headers to keep the size right | 284 * free headers to keep the size right |
262 */ | 285 */ |
263 while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL) | 286 while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL) |
264 u_freelist(curbuf, curbuf->b_u_oldhead); | 287 { |
288 u_header_T *upfree = curbuf->b_u_oldhead; | |
289 | |
290 /* If there is no branch only free one header. */ | |
291 if (upfree->uh_alt_next == NULL) | |
292 u_freelist(curbuf, upfree, &old_curhead); | |
293 else | |
294 { | |
295 /* Free the oldest alternate branch as a whole. */ | |
296 while (upfree->uh_alt_next != NULL) | |
297 upfree = upfree->uh_alt_next; | |
298 u_freebranch(curbuf, upfree, &old_curhead); | |
299 } | |
300 } | |
265 | 301 |
266 if (p_ul < 0) /* no undo at all */ | 302 if (p_ul < 0) /* no undo at all */ |
267 { | 303 { |
304 if (old_curhead != NULL) | |
305 u_freebranch(curbuf, old_curhead, NULL); | |
268 curbuf->b_u_synced = FALSE; | 306 curbuf->b_u_synced = FALSE; |
269 return OK; | 307 return OK; |
270 } | 308 } |
271 | 309 |
272 /* | |
273 * make a new header entry | |
274 */ | |
275 uhp = (struct u_header *)U_ALLOC_LINE((unsigned) | |
276 sizeof(struct u_header)); | |
277 if (uhp == NULL) | |
278 goto nomem; | |
279 uhp->uh_prev = NULL; | 310 uhp->uh_prev = NULL; |
280 uhp->uh_next = curbuf->b_u_newhead; | 311 uhp->uh_next = curbuf->b_u_newhead; |
312 uhp->uh_alt_next = old_curhead; | |
313 if (old_curhead != NULL) | |
314 { | |
315 old_curhead->uh_alt_prev = uhp; | |
316 if (curbuf->b_u_oldhead == old_curhead) | |
317 curbuf->b_u_oldhead = uhp; | |
318 } | |
319 uhp->uh_alt_prev = NULL; | |
320 uhp->uh_seq = curbuf->b_u_seq_last++; | |
321 curbuf->b_u_seq_cur = curbuf->b_u_seq_last; | |
281 if (curbuf->b_u_newhead != NULL) | 322 if (curbuf->b_u_newhead != NULL) |
282 curbuf->b_u_newhead->uh_prev = uhp; | 323 curbuf->b_u_newhead->uh_prev = uhp; |
324 uhp->uh_walk = 0; | |
283 uhp->uh_entry = NULL; | 325 uhp->uh_entry = NULL; |
284 uhp->uh_getbot_entry = NULL; | 326 uhp->uh_getbot_entry = NULL; |
285 uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */ | 327 uhp->uh_cursor = curwin->w_cursor; /* save cursor pos. for undo */ |
286 #ifdef FEAT_VIRTUALEDIT | 328 #ifdef FEAT_VIRTUALEDIT |
287 if (virtual_active() && curwin->w_cursor.coladd > 0) | 329 if (virtual_active() && curwin->w_cursor.coladd > 0) |
288 uhp->uh_cursor_vcol = getviscol(); | 330 uhp->uh_cursor_vcol = getviscol(); |
289 else | 331 else |
290 uhp->uh_cursor_vcol = -1; | 332 uhp->uh_cursor_vcol = -1; |
291 #endif | 333 #endif |
334 uhp->uh_time = time(NULL); | |
292 | 335 |
293 /* save changed and buffer empty flag for undo */ | 336 /* save changed and buffer empty flag for undo */ |
294 uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) + | 337 uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) + |
295 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); | 338 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); |
296 | 339 |
530 beep_flush(); | 573 beep_flush(); |
531 break; | 574 break; |
532 } | 575 } |
533 | 576 |
534 u_undoredo(); | 577 u_undoredo(); |
578 curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_seq; | |
535 } | 579 } |
536 else | 580 else |
537 { | 581 { |
538 if (curbuf->b_u_curhead == NULL || p_ul <= 0) | 582 if (curbuf->b_u_curhead == NULL || p_ul <= 0) |
539 { | 583 { |
540 beep_flush(); /* nothing to redo */ | 584 beep_flush(); /* nothing to redo */ |
541 break; | 585 break; |
542 } | 586 } |
543 | 587 |
544 u_undoredo(); | 588 u_undoredo(); |
545 /* advance for next redo */ | 589 curbuf->b_u_seq_cur = curbuf->b_u_curhead->uh_seq + 1; |
590 | |
591 /* Advance for next redo. Set "newhead" when at the end of the | |
592 * redoable changes. */ | |
593 if (curbuf->b_u_curhead->uh_prev == NULL) | |
594 curbuf->b_u_newhead = curbuf->b_u_curhead; | |
546 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev; | 595 curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev; |
547 } | 596 } |
548 } | 597 } |
598 u_undo_end(); | |
599 } | |
600 | |
601 static int lastmark = 0; | |
602 | |
603 /* | |
604 * Undo or redo over the timeline. | |
605 * When "step" is negative go back in time, otherwise goes forward in time. | |
606 */ | |
607 void | |
608 undo_time(step) | |
609 int step; | |
610 { | |
611 long target; | |
612 long closest; | |
613 u_header_T *uhp; | |
614 u_header_T *last; | |
615 int mark; | |
616 int nomark; | |
617 int round; | |
618 | |
619 u_newcount = 0; | |
620 u_oldcount = 0; | |
549 if (curbuf->b_ml.ml_flags & ML_EMPTY) | 621 if (curbuf->b_ml.ml_flags & ML_EMPTY) |
550 --u_newcount; | 622 u_oldcount = -1; |
623 | |
624 /* "target" is the node below which we want to be. When going forward | |
625 * the current one also counts, thus do one less. */ | |
626 if (step < 0) | |
627 { | |
628 target = curbuf->b_u_seq_cur + step; | |
629 closest = -1; | |
630 } | |
631 else | |
632 { | |
633 target = curbuf->b_u_seq_cur + step - 1; | |
634 closest = curbuf->b_u_seq_last + 1; | |
635 } | |
636 | |
637 /* May do this twice: | |
638 * 1. Search for "target", update "closest" to the best match found. | |
639 * 2. If "target" not found search for "closest". */ | |
640 for (round = 1; round <= 2; ++round) | |
641 { | |
642 /* 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 | |
644 * it. We put "nomark" in uh_walk where we have been without success, | |
645 * "mark" where it could possibly be. */ | |
646 mark = ++lastmark; | |
647 nomark = ++lastmark; | |
648 | |
649 if (curbuf->b_u_curhead == NULL) /* at leaf of the tree */ | |
650 uhp = curbuf->b_u_newhead; | |
651 else | |
652 uhp = curbuf->b_u_curhead; | |
653 | |
654 while (uhp != NULL) | |
655 { | |
656 uhp->uh_walk = mark; | |
657 if (uhp->uh_seq == target) /* found it! */ | |
658 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 | |
665 /* go down in the tree if we haven't been there */ | |
666 if (uhp->uh_prev != NULL && uhp->uh_prev->uh_walk != nomark | |
667 && uhp->uh_prev->uh_walk != mark) | |
668 uhp = uhp->uh_prev; | |
669 | |
670 /* go to alternate branch if we haven't been there */ | |
671 else if (uhp->uh_alt_next != NULL | |
672 && uhp->uh_alt_next->uh_walk != nomark | |
673 && uhp->uh_alt_next->uh_walk != mark) | |
674 uhp = uhp->uh_alt_next; | |
675 | |
676 /* go up in the tree if we haven't been there and we are at the | |
677 * start of alternate branches */ | |
678 else if (uhp->uh_next != NULL && uhp->uh_alt_prev == NULL | |
679 && uhp->uh_next->uh_walk != nomark | |
680 && uhp->uh_next->uh_walk != mark) | |
681 uhp = uhp->uh_next; | |
682 | |
683 else | |
684 { | |
685 /* need to backtrack; mark this node as useless */ | |
686 uhp->uh_walk = nomark; | |
687 if (uhp->uh_alt_prev != NULL) | |
688 uhp = uhp->uh_alt_prev; | |
689 else | |
690 uhp = uhp->uh_next; | |
691 } | |
692 } | |
693 | |
694 if (uhp != NULL) /* found it */ | |
695 break; | |
696 if (step < 0 && closest == -1) | |
697 { | |
698 MSG(_("Already at oldest change")); | |
699 return; | |
700 } | |
701 if (step > 0 && closest == curbuf->b_u_seq_last + 1) | |
702 { | |
703 MSG(_("Already at newest change")); | |
704 return; | |
705 } | |
706 | |
707 target = closest; | |
708 } | |
709 | |
710 /* If we found it: Follow the path to go to where we want to be. */ | |
711 if (uhp != NULL) | |
712 { | |
713 /* | |
714 * First go up the tree as much as needed. | |
715 */ | |
716 for (;;) | |
717 { | |
718 uhp = curbuf->b_u_curhead; | |
719 if (uhp == NULL) | |
720 uhp = curbuf->b_u_newhead; | |
721 else | |
722 { | |
723 while (uhp->uh_alt_prev != NULL) | |
724 { | |
725 uhp->uh_walk = nomark; | |
726 uhp = uhp->uh_alt_prev; | |
727 } | |
728 uhp = uhp->uh_next; | |
729 } | |
730 if (uhp == NULL || uhp->uh_walk != mark) | |
731 break; | |
732 curbuf->b_u_curhead = uhp; | |
733 u_undoredo(); | |
734 uhp->uh_walk = nomark; /* don't go back down here */ | |
735 curbuf->b_u_seq_cur = uhp->uh_seq; | |
736 } | |
737 | |
738 /* | |
739 * And now go down the tree, branching off where needed. | |
740 */ | |
741 uhp = curbuf->b_u_curhead; | |
742 for (;;) | |
743 { | |
744 /* Find the last branch with a mark, that's the one. */ | |
745 last = uhp; | |
746 while (last->uh_alt_next != NULL | |
747 && last->uh_alt_next->uh_walk == mark) | |
748 last = last->uh_alt_next; | |
749 if (last != uhp) | |
750 { | |
751 /* Make the used branch the first entry in the list of | |
752 * alternatives to make "u" and CTRL-R take this branch. */ | |
753 if (last->uh_alt_next != NULL) | |
754 last->uh_alt_next->uh_alt_prev = last->uh_alt_prev; | |
755 last->uh_alt_prev->uh_alt_next = last->uh_alt_next; | |
756 last->uh_alt_prev = NULL; | |
757 last->uh_alt_next = uhp; | |
758 uhp->uh_alt_prev = last; | |
759 | |
760 uhp = last; | |
761 } | |
762 | |
763 if (uhp->uh_walk != mark) | |
764 break; /* must have reached the target */ | |
765 | |
766 curbuf->b_u_curhead = uhp; | |
767 u_undoredo(); | |
768 curbuf->b_u_seq_cur = uhp->uh_seq + 1; | |
769 | |
770 /* Advance "curhead" to below the header we last used. If it | |
771 * becomes NULL then we need to set "newhead" to this leaf. */ | |
772 if (uhp->uh_prev == NULL) | |
773 curbuf->b_u_newhead = uhp; | |
774 curbuf->b_u_curhead = uhp->uh_prev; | |
775 | |
776 if (uhp->uh_seq == target) /* found it! */ | |
777 break; | |
778 | |
779 uhp = uhp->uh_prev; | |
780 if (uhp == NULL || uhp->uh_walk != mark) | |
781 { | |
782 EMSG2(_(e_intern2), "undo_time()"); | |
783 break; | |
784 } | |
785 } | |
786 } | |
551 u_undo_end(); | 787 u_undo_end(); |
552 } | 788 } |
553 | 789 |
554 /* | 790 /* |
555 * u_undoredo: common code for undo and redo | 791 * u_undoredo: common code for undo and redo |
806 * in some cases, but it's better than nothing). | 1042 * in some cases, but it's better than nothing). |
807 */ | 1043 */ |
808 static void | 1044 static void |
809 u_undo_end() | 1045 u_undo_end() |
810 { | 1046 { |
811 if ((u_oldcount -= u_newcount) != 0) | 1047 long sec; |
812 msgmore(-u_oldcount); | 1048 char *msg; |
813 else if (u_newcount > p_report) | 1049 |
814 { | |
815 if (u_newcount == 1) | |
816 MSG(_("1 change")); | |
817 else | |
818 smsg((char_u *)_("%ld changes"), u_newcount); | |
819 } | |
820 #ifdef FEAT_FOLDING | 1050 #ifdef FEAT_FOLDING |
821 if ((fdo_flags & FDO_UNDO) && KeyTyped) | 1051 if ((fdo_flags & FDO_UNDO) && KeyTyped) |
822 foldOpenCursor(); | 1052 foldOpenCursor(); |
823 #endif | 1053 #endif |
1054 | |
1055 if (global_busy /* no messages now, wait until global is finished */ | |
1056 || !messaging()) /* 'lazyredraw' set, don't do messages now */ | |
1057 return; | |
1058 | |
1059 if (curbuf->b_ml.ml_flags & ML_EMPTY) | |
1060 --u_newcount; | |
1061 | |
1062 u_oldcount -= u_newcount; | |
1063 if (u_oldcount == -1) | |
1064 msg = N_("more line"); | |
1065 else if (u_oldcount < 0) | |
1066 msg = N_("more lines"); | |
1067 else if (u_oldcount == 1) | |
1068 msg = N_("line less"); | |
1069 else if (u_oldcount > 1) | |
1070 msg = N_("fewer lines"); | |
1071 else | |
1072 { | |
1073 u_oldcount = u_newcount; | |
1074 if (u_newcount == 1) | |
1075 msg = N_("change"); | |
1076 else | |
1077 msg = N_("changes"); | |
1078 } | |
1079 | |
1080 if (curbuf->b_u_curhead == 0) | |
1081 sec = 0; | |
1082 else | |
1083 sec = time(NULL) - curbuf->b_u_curhead->uh_time; | |
1084 | |
1085 smsg((char_u *)_("%ld %s; %ld seconds ago"), u_oldcount, _(msg), sec); | |
824 } | 1086 } |
825 | 1087 |
826 /* | 1088 /* |
827 * u_sync: stop adding to the current entry list | 1089 * u_sync: stop adding to the current entry list |
828 */ | 1090 */ |
872 */ | 1134 */ |
873 void | 1135 void |
874 u_unchanged(buf) | 1136 u_unchanged(buf) |
875 buf_T *buf; | 1137 buf_T *buf; |
876 { | 1138 { |
877 struct u_header *uh; | 1139 u_header_T *uh; |
878 | 1140 |
879 for (uh = buf->b_u_newhead; uh; uh = uh->uh_next) | 1141 for (uh = buf->b_u_newhead; uh; uh = uh->uh_next) |
880 uh->uh_flags |= UH_CHANGED; | 1142 uh->uh_flags |= UH_CHANGED; |
881 buf->b_did_warn = FALSE; | 1143 buf->b_did_warn = FALSE; |
882 } | 1144 } |
934 | 1196 |
935 curbuf->b_u_synced = TRUE; | 1197 curbuf->b_u_synced = TRUE; |
936 } | 1198 } |
937 | 1199 |
938 /* | 1200 /* |
939 * u_freelist: free one entry list and adjust the pointers | 1201 * Free one header and its entry list and adjust the pointers. |
940 */ | 1202 */ |
941 static void | 1203 static void |
942 u_freelist(buf, uhp) | 1204 u_freelist(buf, uhp, uhpp) |
943 buf_T *buf; | 1205 buf_T *buf; |
944 struct u_header *uhp; | 1206 u_header_T *uhp; |
945 { | 1207 u_header_T **uhpp; /* if not NULL reset when freeing this header */ |
946 u_entry_T *uep, *nuep; | 1208 { |
947 | 1209 /* When there is an alternate redo list free that branch completely, |
948 for (uep = uhp->uh_entry; uep != NULL; uep = nuep) | 1210 * because we can never go there. */ |
949 { | 1211 if (uhp->uh_alt_next != NULL) |
950 nuep = uep->ue_next; | 1212 u_freebranch(buf, uhp->uh_alt_next, uhpp); |
951 u_freeentry(uep, uep->ue_size); | 1213 |
952 } | 1214 if (uhp->uh_alt_prev != NULL) |
953 | 1215 uhp->uh_alt_prev->uh_alt_next = NULL; |
954 if (buf->b_u_curhead == uhp) | 1216 |
955 buf->b_u_curhead = NULL; | 1217 /* Update the links in the list to remove the header. */ |
956 | |
957 if (uhp->uh_next == NULL) | 1218 if (uhp->uh_next == NULL) |
958 buf->b_u_oldhead = uhp->uh_prev; | 1219 buf->b_u_oldhead = uhp->uh_prev; |
959 else | 1220 else |
960 uhp->uh_next->uh_prev = uhp->uh_prev; | 1221 uhp->uh_next->uh_prev = uhp->uh_prev; |
961 | 1222 |
962 if (uhp->uh_prev == NULL) | 1223 if (uhp->uh_prev == NULL) |
963 buf->b_u_newhead = uhp->uh_next; | 1224 buf->b_u_newhead = uhp->uh_next; |
964 else | 1225 else |
965 uhp->uh_prev->uh_next = uhp->uh_next; | 1226 uhp->uh_prev->uh_next = uhp->uh_next; |
1227 | |
1228 u_freeentries(buf, uhp, uhpp); | |
1229 } | |
1230 | |
1231 /* | |
1232 * Free an alternate branch and all following alternate branches. | |
1233 */ | |
1234 static void | |
1235 u_freebranch(buf, uhp, uhpp) | |
1236 buf_T *buf; | |
1237 u_header_T *uhp; | |
1238 u_header_T **uhpp; /* if not NULL reset when freeing this header */ | |
1239 { | |
1240 u_header_T *tofree, *next; | |
1241 | |
1242 if (uhp->uh_alt_prev != NULL) | |
1243 uhp->uh_alt_prev->uh_alt_next = NULL; | |
1244 | |
1245 next = uhp; | |
1246 while (next != NULL) | |
1247 { | |
1248 tofree = next; | |
1249 if (tofree->uh_alt_next != NULL) | |
1250 u_freebranch(buf, tofree->uh_alt_next, uhpp); /* recursive */ | |
1251 next = tofree->uh_prev; | |
1252 u_freeentries(buf, tofree, uhpp); | |
1253 } | |
1254 } | |
1255 | |
1256 /* | |
1257 * Free all the undo entries for one header and the header itself. | |
1258 * This means that "uhp" is invalid when returning. | |
1259 */ | |
1260 static void | |
1261 u_freeentries(buf, uhp, uhpp) | |
1262 buf_T *buf; | |
1263 u_header_T *uhp; | |
1264 u_header_T **uhpp; /* if not NULL reset when freeing this header */ | |
1265 { | |
1266 u_entry_T *uep, *nuep; | |
1267 | |
1268 /* Check for pointers to the header that become invalid now. */ | |
1269 if (buf->b_u_curhead == uhp) | |
1270 buf->b_u_curhead = NULL; | |
1271 if (uhpp != NULL && uhp == *uhpp) | |
1272 *uhpp = NULL; | |
1273 | |
1274 for (uep = uhp->uh_entry; uep != NULL; uep = nuep) | |
1275 { | |
1276 nuep = uep->ue_next; | |
1277 u_freeentry(uep, uep->ue_size); | |
1278 } | |
966 | 1279 |
967 U_FREE_LINE((char_u *)uhp); | 1280 U_FREE_LINE((char_u *)uhp); |
968 --buf->b_u_numhead; | 1281 --buf->b_u_numhead; |
969 } | 1282 } |
970 | 1283 |
1099 */ | 1412 */ |
1100 void | 1413 void |
1101 u_blockfree(buf) | 1414 u_blockfree(buf) |
1102 buf_T *buf; | 1415 buf_T *buf; |
1103 { | 1416 { |
1104 while (buf->b_u_newhead != NULL) | 1417 while (buf->b_u_oldhead != NULL) |
1105 u_freelist(buf, buf->b_u_newhead); | 1418 u_freelist(buf, buf->b_u_oldhead, NULL); |
1106 U_FREE_LINE(buf->b_u_line_ptr); | 1419 U_FREE_LINE(buf->b_u_line_ptr); |
1107 } | 1420 } |
1108 | 1421 |
1109 #else | 1422 #else |
1110 /* | 1423 /* |