forked from aniani/vim
updated for version 7.1-130
This commit is contained in:
@@ -278,6 +278,9 @@ struct u_entry
|
|||||||
linenr_T ue_lcount; /* linecount when u_save called */
|
linenr_T ue_lcount; /* linecount when u_save called */
|
||||||
char_u **ue_array; /* array of lines in undo block */
|
char_u **ue_array; /* array of lines in undo block */
|
||||||
long ue_size; /* number of lines in ue_array */
|
long ue_size; /* number of lines in ue_array */
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
int ue_magic; /* magic number to check allocation */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct u_header
|
struct u_header
|
||||||
@@ -300,6 +303,9 @@ struct u_header
|
|||||||
visualinfo_T uh_visual; /* Visual areas before undo/after redo */
|
visualinfo_T uh_visual; /* Visual areas before undo/after redo */
|
||||||
#endif
|
#endif
|
||||||
time_t uh_time; /* timestamp when the change was made */
|
time_t uh_time; /* timestamp when the change was made */
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
int uh_magic; /* magic number to check allocation */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* values for uh_flags */
|
/* values for uh_flags */
|
||||||
|
138
src/undo.c
138
src/undo.c
@@ -76,6 +76,12 @@
|
|||||||
* buffer is unloaded.
|
* buffer is unloaded.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Uncomment the next line for including the u_check() function. This warns
|
||||||
|
* for errors in the debug information. */
|
||||||
|
/* #define U_DEBUG 1 */
|
||||||
|
#define UH_MAGIC 0x18dade /* value for uh_magic when in use */
|
||||||
|
#define UE_MAGIC 0xabc123 /* value for ue_magic when in use */
|
||||||
|
|
||||||
#include "vim.h"
|
#include "vim.h"
|
||||||
|
|
||||||
/* See below: use malloc()/free() for memory management. */
|
/* See below: use malloc()/free() for memory management. */
|
||||||
@@ -113,6 +119,95 @@ static long u_newcount, u_oldcount;
|
|||||||
*/
|
*/
|
||||||
static int undo_undoes = FALSE;
|
static int undo_undoes = FALSE;
|
||||||
|
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
/*
|
||||||
|
* Check the undo structures for being valid. Print a warning when something
|
||||||
|
* looks wrong.
|
||||||
|
*/
|
||||||
|
static int seen_b_u_curhead;
|
||||||
|
static int seen_b_u_newhead;
|
||||||
|
static int header_count;
|
||||||
|
|
||||||
|
static void
|
||||||
|
u_check_tree(u_header_T *uhp,
|
||||||
|
u_header_T *exp_uh_next,
|
||||||
|
u_header_T *exp_uh_alt_prev)
|
||||||
|
{
|
||||||
|
u_entry_T *uep;
|
||||||
|
|
||||||
|
if (uhp == NULL)
|
||||||
|
return;
|
||||||
|
++header_count;
|
||||||
|
if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1)
|
||||||
|
{
|
||||||
|
EMSG("b_u_curhead found twice (looping?)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1)
|
||||||
|
{
|
||||||
|
EMSG("b_u_newhead found twice (looping?)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uhp->uh_magic != UH_MAGIC)
|
||||||
|
EMSG("uh_magic wrong (may be using freed memory)");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check pointers back are correct. */
|
||||||
|
if (uhp->uh_next != exp_uh_next)
|
||||||
|
{
|
||||||
|
EMSG("uh_next wrong");
|
||||||
|
smsg((char_u *)"expected: 0x%x, actual: 0x%x",
|
||||||
|
exp_uh_next, uhp->uh_next);
|
||||||
|
}
|
||||||
|
if (uhp->uh_alt_prev != exp_uh_alt_prev)
|
||||||
|
{
|
||||||
|
EMSG("uh_alt_prev wrong");
|
||||||
|
smsg((char_u *)"expected: 0x%x, actual: 0x%x",
|
||||||
|
exp_uh_alt_prev, uhp->uh_alt_prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the undo tree at this header. */
|
||||||
|
for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
|
||||||
|
{
|
||||||
|
if (uep->ue_magic != UE_MAGIC)
|
||||||
|
{
|
||||||
|
EMSG("ue_magic wrong (may be using freed memory)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the next alt tree. */
|
||||||
|
u_check_tree(uhp->uh_alt_next, uhp->uh_next, uhp);
|
||||||
|
|
||||||
|
/* Check the next header in this branch. */
|
||||||
|
u_check_tree(uhp->uh_prev, uhp, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
u_check(int newhead_may_be_NULL)
|
||||||
|
{
|
||||||
|
seen_b_u_newhead = 0;
|
||||||
|
seen_b_u_curhead = 0;
|
||||||
|
header_count = 0;
|
||||||
|
|
||||||
|
u_check_tree(curbuf->b_u_oldhead, NULL, NULL);
|
||||||
|
|
||||||
|
if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL
|
||||||
|
&& !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL))
|
||||||
|
EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead);
|
||||||
|
if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0)
|
||||||
|
EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead);
|
||||||
|
if (header_count != curbuf->b_u_numhead)
|
||||||
|
{
|
||||||
|
EMSG("b_u_numhead invalid");
|
||||||
|
smsg((char_u *)"expected: %ld, actual: %ld",
|
||||||
|
(long)header_count, (long)curbuf->b_u_numhead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the current line for both the "u" and "U" command.
|
* Save the current line for both the "u" and "U" command.
|
||||||
* Returns OK or FAIL.
|
* Returns OK or FAIL.
|
||||||
@@ -243,6 +338,9 @@ u_savecommon(top, bot, newbot)
|
|||||||
if (!undo_allowed())
|
if (!undo_allowed())
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
u_check(FALSE);
|
||||||
|
#endif
|
||||||
#ifdef FEAT_NETBEANS_INTG
|
#ifdef FEAT_NETBEANS_INTG
|
||||||
/*
|
/*
|
||||||
* Netbeans defines areas that cannot be modified. Bail out here when
|
* Netbeans defines areas that cannot be modified. Bail out here when
|
||||||
@@ -294,6 +392,9 @@ u_savecommon(top, bot, newbot)
|
|||||||
uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T));
|
uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T));
|
||||||
if (uhp == NULL)
|
if (uhp == NULL)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
uhp->uh_magic = UH_MAGIC;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
uhp = NULL;
|
uhp = NULL;
|
||||||
@@ -316,8 +417,11 @@ u_savecommon(top, bot, newbot)
|
|||||||
{
|
{
|
||||||
u_header_T *uhfree = curbuf->b_u_oldhead;
|
u_header_T *uhfree = curbuf->b_u_oldhead;
|
||||||
|
|
||||||
/* If there is no branch only free one header. */
|
if (uhfree == old_curhead)
|
||||||
if (uhfree->uh_alt_next == NULL)
|
/* Can't reconnect the branch, delete all of it. */
|
||||||
|
u_freebranch(curbuf, uhfree, &old_curhead);
|
||||||
|
else if (uhfree->uh_alt_next == NULL)
|
||||||
|
/* There is no branch, only free one header. */
|
||||||
u_freeheader(curbuf, uhfree, &old_curhead);
|
u_freeheader(curbuf, uhfree, &old_curhead);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -326,6 +430,9 @@ u_savecommon(top, bot, newbot)
|
|||||||
uhfree = uhfree->uh_alt_next;
|
uhfree = uhfree->uh_alt_next;
|
||||||
u_freebranch(curbuf, uhfree, &old_curhead);
|
u_freebranch(curbuf, uhfree, &old_curhead);
|
||||||
}
|
}
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
u_check(TRUE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uhp == NULL) /* no undo at all */
|
if (uhp == NULL) /* no undo at all */
|
||||||
@@ -478,6 +585,9 @@ u_savecommon(top, bot, newbot)
|
|||||||
uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
|
uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
|
||||||
if (uep == NULL)
|
if (uep == NULL)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
uep->ue_magic = UE_MAGIC;
|
||||||
|
#endif
|
||||||
|
|
||||||
uep->ue_size = size;
|
uep->ue_size = size;
|
||||||
uep->ue_top = top;
|
uep->ue_top = top;
|
||||||
@@ -525,6 +635,9 @@ u_savecommon(top, bot, newbot)
|
|||||||
curbuf->b_u_synced = FALSE;
|
curbuf->b_u_synced = FALSE;
|
||||||
undo_undoes = FALSE;
|
undo_undoes = FALSE;
|
||||||
|
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
u_check(FALSE);
|
||||||
|
#endif
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
nomem:
|
nomem:
|
||||||
@@ -955,6 +1068,9 @@ u_undoredo(undo)
|
|||||||
int empty_buffer; /* buffer became empty */
|
int empty_buffer; /* buffer became empty */
|
||||||
u_header_T *curhead = curbuf->b_u_curhead;
|
u_header_T *curhead = curbuf->b_u_curhead;
|
||||||
|
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
u_check(FALSE);
|
||||||
|
#endif
|
||||||
old_flags = curhead->uh_flags;
|
old_flags = curhead->uh_flags;
|
||||||
new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
|
new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
|
||||||
((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
|
((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
|
||||||
@@ -1186,6 +1302,9 @@ u_undoredo(undo)
|
|||||||
/* The timestamp can be the same for multiple changes, just use the one of
|
/* The timestamp can be the same for multiple changes, just use the one of
|
||||||
* the undone/redone change. */
|
* the undone/redone change. */
|
||||||
curbuf->b_u_seq_time = curhead->uh_time;
|
curbuf->b_u_seq_time = curhead->uh_time;
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
u_check(FALSE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1515,7 +1634,7 @@ u_getbot()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free one header and its entry list and adjust the pointers.
|
* Free one header "uhp" and its entry list and adjust the pointers.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
u_freeheader(buf, uhp, uhpp)
|
u_freeheader(buf, uhp, uhpp)
|
||||||
@@ -1523,6 +1642,8 @@ u_freeheader(buf, uhp, uhpp)
|
|||||||
u_header_T *uhp;
|
u_header_T *uhp;
|
||||||
u_header_T **uhpp; /* if not NULL reset when freeing this header */
|
u_header_T **uhpp; /* if not NULL reset when freeing this header */
|
||||||
{
|
{
|
||||||
|
u_header_T *uhap;
|
||||||
|
|
||||||
/* When there is an alternate redo list free that branch completely,
|
/* When there is an alternate redo list free that branch completely,
|
||||||
* because we can never go there. */
|
* because we can never go there. */
|
||||||
if (uhp->uh_alt_next != NULL)
|
if (uhp->uh_alt_next != NULL)
|
||||||
@@ -1540,7 +1661,8 @@ u_freeheader(buf, uhp, uhpp)
|
|||||||
if (uhp->uh_prev == NULL)
|
if (uhp->uh_prev == NULL)
|
||||||
buf->b_u_newhead = uhp->uh_next;
|
buf->b_u_newhead = uhp->uh_next;
|
||||||
else
|
else
|
||||||
uhp->uh_prev->uh_next = uhp->uh_next;
|
for (uhap = uhp->uh_prev; uhap != NULL; uhap = uhap->uh_alt_next)
|
||||||
|
uhap->uh_next = uhp->uh_next;
|
||||||
|
|
||||||
u_freeentries(buf, uhp, uhpp);
|
u_freeentries(buf, uhp, uhpp);
|
||||||
}
|
}
|
||||||
@@ -1585,6 +1707,8 @@ u_freeentries(buf, uhp, uhpp)
|
|||||||
/* Check for pointers to the header that become invalid now. */
|
/* Check for pointers to the header that become invalid now. */
|
||||||
if (buf->b_u_curhead == uhp)
|
if (buf->b_u_curhead == uhp)
|
||||||
buf->b_u_curhead = NULL;
|
buf->b_u_curhead = NULL;
|
||||||
|
if (buf->b_u_newhead == uhp)
|
||||||
|
buf->b_u_newhead = NULL; /* freeing the newest entry */
|
||||||
if (uhpp != NULL && uhp == *uhpp)
|
if (uhpp != NULL && uhp == *uhpp)
|
||||||
*uhpp = NULL;
|
*uhpp = NULL;
|
||||||
|
|
||||||
@@ -1594,6 +1718,9 @@ u_freeentries(buf, uhp, uhpp)
|
|||||||
u_freeentry(uep, uep->ue_size);
|
u_freeentry(uep, uep->ue_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
uhp->uh_magic = 0;
|
||||||
|
#endif
|
||||||
U_FREE_LINE((char_u *)uhp);
|
U_FREE_LINE((char_u *)uhp);
|
||||||
--buf->b_u_numhead;
|
--buf->b_u_numhead;
|
||||||
}
|
}
|
||||||
@@ -1609,6 +1736,9 @@ u_freeentry(uep, n)
|
|||||||
while (n > 0)
|
while (n > 0)
|
||||||
U_FREE_LINE(uep->ue_array[--n]);
|
U_FREE_LINE(uep->ue_array[--n]);
|
||||||
U_FREE_LINE((char_u *)uep->ue_array);
|
U_FREE_LINE((char_u *)uep->ue_array);
|
||||||
|
#ifdef U_DEBUG
|
||||||
|
uep->ue_magic = 0;
|
||||||
|
#endif
|
||||||
U_FREE_LINE((char_u *)uep);
|
U_FREE_LINE((char_u *)uep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -666,6 +666,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
130,
|
||||||
/**/
|
/**/
|
||||||
129,
|
129,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user