comparison src/undo.c @ 1415:20b52d44daaf v7.1.130

updated for version 7.1-130
author vimboss
date Mon, 01 Oct 2007 20:54:15 +0000
parents 302520c08584
children 93ffa40b5320
comparison
equal deleted inserted replaced
1414:1f099ff4f6fb 1415:20b52d44daaf
74 * 74 *
75 * 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
76 * buffer is unloaded. 76 * buffer is unloaded.
77 */ 77 */
78 78
79 /* Uncomment the next line for including the u_check() function. This warns
80 * for errors in the debug information. */
81 /* #define U_DEBUG 1 */
82 #define UH_MAGIC 0x18dade /* value for uh_magic when in use */
83 #define UE_MAGIC 0xabc123 /* value for ue_magic when in use */
84
79 #include "vim.h" 85 #include "vim.h"
80 86
81 /* See below: use malloc()/free() for memory management. */ 87 /* See below: use malloc()/free() for memory management. */
82 #define U_USE_MALLOC 1 88 #define U_USE_MALLOC 1
83 89
111 * When 'u' flag included in 'cpoptions', we behave like vi. Need to remember 117 * When 'u' flag included in 'cpoptions', we behave like vi. Need to remember
112 * the action that "u" should do. 118 * the action that "u" should do.
113 */ 119 */
114 static int undo_undoes = FALSE; 120 static int undo_undoes = FALSE;
115 121
122 #ifdef U_DEBUG
123 /*
124 * Check the undo structures for being valid. Print a warning when something
125 * looks wrong.
126 */
127 static int seen_b_u_curhead;
128 static int seen_b_u_newhead;
129 static int header_count;
130
131 static void
132 u_check_tree(u_header_T *uhp,
133 u_header_T *exp_uh_next,
134 u_header_T *exp_uh_alt_prev)
135 {
136 u_entry_T *uep;
137
138 if (uhp == NULL)
139 return;
140 ++header_count;
141 if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1)
142 {
143 EMSG("b_u_curhead found twice (looping?)");
144 return;
145 }
146 if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1)
147 {
148 EMSG("b_u_newhead found twice (looping?)");
149 return;
150 }
151
152 if (uhp->uh_magic != UH_MAGIC)
153 EMSG("uh_magic wrong (may be using freed memory)");
154 else
155 {
156 /* Check pointers back are correct. */
157 if (uhp->uh_next != exp_uh_next)
158 {
159 EMSG("uh_next wrong");
160 smsg((char_u *)"expected: 0x%x, actual: 0x%x",
161 exp_uh_next, uhp->uh_next);
162 }
163 if (uhp->uh_alt_prev != exp_uh_alt_prev)
164 {
165 EMSG("uh_alt_prev wrong");
166 smsg((char_u *)"expected: 0x%x, actual: 0x%x",
167 exp_uh_alt_prev, uhp->uh_alt_prev);
168 }
169
170 /* Check the undo tree at this header. */
171 for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
172 {
173 if (uep->ue_magic != UE_MAGIC)
174 {
175 EMSG("ue_magic wrong (may be using freed memory)");
176 break;
177 }
178 }
179
180 /* Check the next alt tree. */
181 u_check_tree(uhp->uh_alt_next, uhp->uh_next, uhp);
182
183 /* Check the next header in this branch. */
184 u_check_tree(uhp->uh_prev, uhp, NULL);
185 }
186 }
187
188 void
189 u_check(int newhead_may_be_NULL)
190 {
191 seen_b_u_newhead = 0;
192 seen_b_u_curhead = 0;
193 header_count = 0;
194
195 u_check_tree(curbuf->b_u_oldhead, NULL, NULL);
196
197 if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL
198 && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL))
199 EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead);
200 if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0)
201 EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead);
202 if (header_count != curbuf->b_u_numhead)
203 {
204 EMSG("b_u_numhead invalid");
205 smsg((char_u *)"expected: %ld, actual: %ld",
206 (long)header_count, (long)curbuf->b_u_numhead);
207 }
208 }
209 #endif
210
116 /* 211 /*
117 * Save the current line for both the "u" and "U" command. 212 * Save the current line for both the "u" and "U" command.
118 * Returns OK or FAIL. 213 * Returns OK or FAIL.
119 */ 214 */
120 int 215 int
241 /* When making changes is not allowed return FAIL. It's a crude way to 336 /* When making changes is not allowed return FAIL. It's a crude way to
242 * make all change commands fail. */ 337 * make all change commands fail. */
243 if (!undo_allowed()) 338 if (!undo_allowed())
244 return FAIL; 339 return FAIL;
245 340
341 #ifdef U_DEBUG
342 u_check(FALSE);
343 #endif
246 #ifdef FEAT_NETBEANS_INTG 344 #ifdef FEAT_NETBEANS_INTG
247 /* 345 /*
248 * Netbeans defines areas that cannot be modified. Bail out here when 346 * Netbeans defines areas that cannot be modified. Bail out here when
249 * trying to change text in a guarded area. 347 * trying to change text in a guarded area.
250 */ 348 */
292 * up the undo info when out of memory. 390 * up the undo info when out of memory.
293 */ 391 */
294 uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T)); 392 uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T));
295 if (uhp == NULL) 393 if (uhp == NULL)
296 goto nomem; 394 goto nomem;
395 #ifdef U_DEBUG
396 uhp->uh_magic = UH_MAGIC;
397 #endif
297 } 398 }
298 else 399 else
299 uhp = NULL; 400 uhp = NULL;
300 401
301 /* 402 /*
314 */ 415 */
315 while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL) 416 while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL)
316 { 417 {
317 u_header_T *uhfree = curbuf->b_u_oldhead; 418 u_header_T *uhfree = curbuf->b_u_oldhead;
318 419
319 /* If there is no branch only free one header. */ 420 if (uhfree == old_curhead)
320 if (uhfree->uh_alt_next == NULL) 421 /* Can't reconnect the branch, delete all of it. */
422 u_freebranch(curbuf, uhfree, &old_curhead);
423 else if (uhfree->uh_alt_next == NULL)
424 /* There is no branch, only free one header. */
321 u_freeheader(curbuf, uhfree, &old_curhead); 425 u_freeheader(curbuf, uhfree, &old_curhead);
322 else 426 else
323 { 427 {
324 /* Free the oldest alternate branch as a whole. */ 428 /* Free the oldest alternate branch as a whole. */
325 while (uhfree->uh_alt_next != NULL) 429 while (uhfree->uh_alt_next != NULL)
326 uhfree = uhfree->uh_alt_next; 430 uhfree = uhfree->uh_alt_next;
327 u_freebranch(curbuf, uhfree, &old_curhead); 431 u_freebranch(curbuf, uhfree, &old_curhead);
328 } 432 }
433 #ifdef U_DEBUG
434 u_check(TRUE);
435 #endif
329 } 436 }
330 437
331 if (uhp == NULL) /* no undo at all */ 438 if (uhp == NULL) /* no undo at all */
332 { 439 {
333 if (old_curhead != NULL) 440 if (old_curhead != NULL)
476 * add lines in front of entry list 583 * add lines in front of entry list
477 */ 584 */
478 uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T)); 585 uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
479 if (uep == NULL) 586 if (uep == NULL)
480 goto nomem; 587 goto nomem;
588 #ifdef U_DEBUG
589 uep->ue_magic = UE_MAGIC;
590 #endif
481 591
482 uep->ue_size = size; 592 uep->ue_size = size;
483 uep->ue_top = top; 593 uep->ue_top = top;
484 if (newbot != 0) 594 if (newbot != 0)
485 uep->ue_bot = newbot; 595 uep->ue_bot = newbot;
523 uep->ue_next = curbuf->b_u_newhead->uh_entry; 633 uep->ue_next = curbuf->b_u_newhead->uh_entry;
524 curbuf->b_u_newhead->uh_entry = uep; 634 curbuf->b_u_newhead->uh_entry = uep;
525 curbuf->b_u_synced = FALSE; 635 curbuf->b_u_synced = FALSE;
526 undo_undoes = FALSE; 636 undo_undoes = FALSE;
527 637
638 #ifdef U_DEBUG
639 u_check(FALSE);
640 #endif
528 return OK; 641 return OK;
529 642
530 nomem: 643 nomem:
531 msg_silent = 0; /* must display the prompt */ 644 msg_silent = 0; /* must display the prompt */
532 if (ask_yesno((char_u *)_("No undo possible; continue anyway"), TRUE) 645 if (ask_yesno((char_u *)_("No undo possible; continue anyway"), TRUE)
953 visualinfo_T visualinfo; 1066 visualinfo_T visualinfo;
954 #endif 1067 #endif
955 int empty_buffer; /* buffer became empty */ 1068 int empty_buffer; /* buffer became empty */
956 u_header_T *curhead = curbuf->b_u_curhead; 1069 u_header_T *curhead = curbuf->b_u_curhead;
957 1070
1071 #ifdef U_DEBUG
1072 u_check(FALSE);
1073 #endif
958 old_flags = curhead->uh_flags; 1074 old_flags = curhead->uh_flags;
959 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) + 1075 new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
960 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0); 1076 ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
961 setpcmark(); 1077 setpcmark();
962 1078
1184 --curbuf->b_u_seq_cur; 1300 --curbuf->b_u_seq_cur;
1185 1301
1186 /* The timestamp can be the same for multiple changes, just use the one of 1302 /* The timestamp can be the same for multiple changes, just use the one of
1187 * the undone/redone change. */ 1303 * the undone/redone change. */
1188 curbuf->b_u_seq_time = curhead->uh_time; 1304 curbuf->b_u_seq_time = curhead->uh_time;
1305 #ifdef U_DEBUG
1306 u_check(FALSE);
1307 #endif
1189 } 1308 }
1190 1309
1191 /* 1310 /*
1192 * If we deleted or added lines, report the number of less/more lines. 1311 * If we deleted or added lines, report the number of less/more lines.
1193 * Otherwise, report the number of changes (this may be incorrect 1312 * Otherwise, report the number of changes (this may be incorrect
1513 1632
1514 curbuf->b_u_synced = TRUE; 1633 curbuf->b_u_synced = TRUE;
1515 } 1634 }
1516 1635
1517 /* 1636 /*
1518 * Free one header and its entry list and adjust the pointers. 1637 * Free one header "uhp" and its entry list and adjust the pointers.
1519 */ 1638 */
1520 static void 1639 static void
1521 u_freeheader(buf, uhp, uhpp) 1640 u_freeheader(buf, uhp, uhpp)
1522 buf_T *buf; 1641 buf_T *buf;
1523 u_header_T *uhp; 1642 u_header_T *uhp;
1524 u_header_T **uhpp; /* if not NULL reset when freeing this header */ 1643 u_header_T **uhpp; /* if not NULL reset when freeing this header */
1525 { 1644 {
1645 u_header_T *uhap;
1646
1526 /* When there is an alternate redo list free that branch completely, 1647 /* When there is an alternate redo list free that branch completely,
1527 * because we can never go there. */ 1648 * because we can never go there. */
1528 if (uhp->uh_alt_next != NULL) 1649 if (uhp->uh_alt_next != NULL)
1529 u_freebranch(buf, uhp->uh_alt_next, uhpp); 1650 u_freebranch(buf, uhp->uh_alt_next, uhpp);
1530 1651
1538 uhp->uh_next->uh_prev = uhp->uh_prev; 1659 uhp->uh_next->uh_prev = uhp->uh_prev;
1539 1660
1540 if (uhp->uh_prev == NULL) 1661 if (uhp->uh_prev == NULL)
1541 buf->b_u_newhead = uhp->uh_next; 1662 buf->b_u_newhead = uhp->uh_next;
1542 else 1663 else
1543 uhp->uh_prev->uh_next = uhp->uh_next; 1664 for (uhap = uhp->uh_prev; uhap != NULL; uhap = uhap->uh_alt_next)
1665 uhap->uh_next = uhp->uh_next;
1544 1666
1545 u_freeentries(buf, uhp, uhpp); 1667 u_freeentries(buf, uhp, uhpp);
1546 } 1668 }
1547 1669
1548 /* 1670 /*
1583 u_entry_T *uep, *nuep; 1705 u_entry_T *uep, *nuep;
1584 1706
1585 /* Check for pointers to the header that become invalid now. */ 1707 /* Check for pointers to the header that become invalid now. */
1586 if (buf->b_u_curhead == uhp) 1708 if (buf->b_u_curhead == uhp)
1587 buf->b_u_curhead = NULL; 1709 buf->b_u_curhead = NULL;
1710 if (buf->b_u_newhead == uhp)
1711 buf->b_u_newhead = NULL; /* freeing the newest entry */
1588 if (uhpp != NULL && uhp == *uhpp) 1712 if (uhpp != NULL && uhp == *uhpp)
1589 *uhpp = NULL; 1713 *uhpp = NULL;
1590 1714
1591 for (uep = uhp->uh_entry; uep != NULL; uep = nuep) 1715 for (uep = uhp->uh_entry; uep != NULL; uep = nuep)
1592 { 1716 {
1593 nuep = uep->ue_next; 1717 nuep = uep->ue_next;
1594 u_freeentry(uep, uep->ue_size); 1718 u_freeentry(uep, uep->ue_size);
1595 } 1719 }
1596 1720
1721 #ifdef U_DEBUG
1722 uhp->uh_magic = 0;
1723 #endif
1597 U_FREE_LINE((char_u *)uhp); 1724 U_FREE_LINE((char_u *)uhp);
1598 --buf->b_u_numhead; 1725 --buf->b_u_numhead;
1599 } 1726 }
1600 1727
1601 /* 1728 /*
1607 long n; 1734 long n;
1608 { 1735 {
1609 while (n > 0) 1736 while (n > 0)
1610 U_FREE_LINE(uep->ue_array[--n]); 1737 U_FREE_LINE(uep->ue_array[--n]);
1611 U_FREE_LINE((char_u *)uep->ue_array); 1738 U_FREE_LINE((char_u *)uep->ue_array);
1739 #ifdef U_DEBUG
1740 uep->ue_magic = 0;
1741 #endif
1612 U_FREE_LINE((char_u *)uep); 1742 U_FREE_LINE((char_u *)uep);
1613 } 1743 }
1614 1744
1615 /* 1745 /*
1616 * invalidate the undo buffer; called when storage has already been released 1746 * invalidate the undo buffer; called when storage has already been released