mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.1.0688: text properties are not restored by undo
Problem: Text properties are not restored by undo. Solution: Also save text properties for undo.
This commit is contained in:
parent
6d3a1940be
commit
ccae4672fd
@ -3217,11 +3217,22 @@ ml_replace(linenr_T lnum, char_u *line, int copy)
|
|||||||
|
|
||||||
if (line != NULL)
|
if (line != NULL)
|
||||||
len = (colnr_T)STRLEN(line);
|
len = (colnr_T)STRLEN(line);
|
||||||
return ml_replace_len(lnum, line, len, copy);
|
return ml_replace_len(lnum, line, len, FALSE, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace a line for the current buffer. Like ml_replace() with:
|
||||||
|
* "len_arg" is the length of the text, excluding NUL.
|
||||||
|
* If "has_props" is TRUE then "line_arg" includes the text properties and
|
||||||
|
* "len_arg" includes the NUL of the text.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
|
ml_replace_len(
|
||||||
|
linenr_T lnum,
|
||||||
|
char_u *line_arg,
|
||||||
|
colnr_T len_arg,
|
||||||
|
int has_props,
|
||||||
|
int copy)
|
||||||
{
|
{
|
||||||
char_u *line = line_arg;
|
char_u *line = line_arg;
|
||||||
colnr_T len = len_arg;
|
colnr_T len = len_arg;
|
||||||
@ -3233,8 +3244,21 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
|
|||||||
if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
|
if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
if (copy && (line = vim_strnsave(line, len)) == NULL) /* allocate memory */
|
if (!has_props)
|
||||||
return FAIL;
|
++len; // include the NUL after the text
|
||||||
|
if (copy)
|
||||||
|
{
|
||||||
|
// copy the line to allocated memory
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if (has_props)
|
||||||
|
line = vim_memsave(line, len);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
line = vim_strnsave(line, len - 1);
|
||||||
|
if (line == NULL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FEAT_NETBEANS_INTG
|
#ifdef FEAT_NETBEANS_INTG
|
||||||
if (netbeans_active())
|
if (netbeans_active())
|
||||||
{
|
{
|
||||||
@ -3249,14 +3273,14 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
|
|||||||
curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
|
curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
if (curbuf->b_has_textprop)
|
if (curbuf->b_has_textprop && !has_props)
|
||||||
// Need to fetch the old line to copy over any text properties.
|
// Need to fetch the old line to copy over any text properties.
|
||||||
ml_get_buf(curbuf, lnum, TRUE);
|
ml_get_buf(curbuf, lnum, TRUE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
if (curbuf->b_has_textprop)
|
if (curbuf->b_has_textprop && !has_props)
|
||||||
{
|
{
|
||||||
size_t oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1;
|
size_t oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1;
|
||||||
|
|
||||||
@ -3266,11 +3290,11 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
|
|||||||
size_t textproplen = curbuf->b_ml.ml_line_len - oldtextlen;
|
size_t textproplen = curbuf->b_ml.ml_line_len - oldtextlen;
|
||||||
|
|
||||||
// Need to copy over text properties, stored after the text.
|
// Need to copy over text properties, stored after the text.
|
||||||
newline = alloc(len + 1 + (int)textproplen);
|
newline = alloc(len + (int)textproplen);
|
||||||
if (newline != NULL)
|
if (newline != NULL)
|
||||||
{
|
{
|
||||||
mch_memmove(newline, line, len + 1);
|
mch_memmove(newline, line, len);
|
||||||
mch_memmove(newline + len + 1, curbuf->b_ml.ml_line_ptr + oldtextlen, textproplen);
|
mch_memmove(newline + len, curbuf->b_ml.ml_line_ptr + oldtextlen, textproplen);
|
||||||
vim_free(line);
|
vim_free(line);
|
||||||
line = newline;
|
line = newline;
|
||||||
len += (colnr_T)textproplen;
|
len += (colnr_T)textproplen;
|
||||||
@ -3279,11 +3303,11 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */
|
if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) // same line allocated
|
||||||
vim_free(curbuf->b_ml.ml_line_ptr); /* free it */
|
vim_free(curbuf->b_ml.ml_line_ptr); // free it
|
||||||
|
|
||||||
curbuf->b_ml.ml_line_ptr = line;
|
curbuf->b_ml.ml_line_ptr = line;
|
||||||
curbuf->b_ml.ml_line_len = len + 1;
|
curbuf->b_ml.ml_line_len = len;
|
||||||
curbuf->b_ml.ml_line_lnum = lnum;
|
curbuf->b_ml.ml_line_lnum = lnum;
|
||||||
curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
|
curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ int ml_line_alloced(void);
|
|||||||
int ml_append(linenr_T lnum, char_u *line, colnr_T len, int newfile);
|
int ml_append(linenr_T lnum, char_u *line, colnr_T len, int newfile);
|
||||||
int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, int newfile);
|
int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, int newfile);
|
||||||
int ml_replace(linenr_T lnum, char_u *line, int copy);
|
int ml_replace(linenr_T lnum, char_u *line, int copy);
|
||||||
int ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy);
|
int ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int has_props, int copy);
|
||||||
int ml_delete(linenr_T lnum, int message);
|
int ml_delete(linenr_T lnum, int message);
|
||||||
void ml_setmarked(linenr_T lnum);
|
void ml_setmarked(linenr_T lnum);
|
||||||
linenr_T ml_firstmarked(void);
|
linenr_T ml_firstmarked(void);
|
||||||
|
@ -347,6 +347,14 @@ typedef struct
|
|||||||
* structures used for undo
|
* structures used for undo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// One line saved for undo. After the NUL terminated text there might be text
|
||||||
|
// properties, thus ul_len can be larger than STRLEN(ul_line) + 1.
|
||||||
|
typedef struct {
|
||||||
|
char_u *ul_line; // text of the line
|
||||||
|
long ul_len; // length of the line including NUL, plus text
|
||||||
|
// properties
|
||||||
|
} undoline_T;
|
||||||
|
|
||||||
typedef struct u_entry u_entry_T;
|
typedef struct u_entry u_entry_T;
|
||||||
typedef struct u_header u_header_T;
|
typedef struct u_header u_header_T;
|
||||||
struct u_entry
|
struct u_entry
|
||||||
@ -355,7 +363,7 @@ struct u_entry
|
|||||||
linenr_T ue_top; /* number of line above undo block */
|
linenr_T ue_top; /* number of line above undo block */
|
||||||
linenr_T ue_bot; /* number of line below undo block */
|
linenr_T ue_bot; /* number of line below undo block */
|
||||||
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 */
|
undoline_T *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
|
#ifdef U_DEBUG
|
||||||
int ue_magic; /* magic number to check allocation */
|
int ue_magic; /* magic number to check allocation */
|
||||||
@ -2167,7 +2175,7 @@ struct file_buffer
|
|||||||
/*
|
/*
|
||||||
* variables for "U" command in undo.c
|
* variables for "U" command in undo.c
|
||||||
*/
|
*/
|
||||||
char_u *b_u_line_ptr; /* saved line for "U" command */
|
undoline_T b_u_line_ptr; /* saved line for "U" command */
|
||||||
linenr_T b_u_line_lnum; /* line number of line in u_line */
|
linenr_T b_u_line_lnum; /* line number of line in u_line */
|
||||||
colnr_T b_u_line_colnr; /* optional column number */
|
colnr_T b_u_line_colnr; /* optional column number */
|
||||||
|
|
||||||
|
146
src/undo.c
146
src/undo.c
@ -125,7 +125,6 @@ static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define U_ALLOC_LINE(size) lalloc((long_u)(size), FALSE)
|
#define U_ALLOC_LINE(size) lalloc((long_u)(size), FALSE)
|
||||||
static char_u *u_save_line(linenr_T);
|
|
||||||
|
|
||||||
/* used in undo_end() to report number of added and deleted lines */
|
/* used in undo_end() to report number of added and deleted lines */
|
||||||
static long u_newcount, u_oldcount;
|
static long u_newcount, u_oldcount;
|
||||||
@ -352,6 +351,28 @@ get_undolevel(void)
|
|||||||
return curbuf->b_p_ul;
|
return curbuf->b_p_ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* u_save_line(): save an allocated copy of line "lnum" into "ul".
|
||||||
|
* Returns FAIL when out of memory.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
u_save_line(undoline_T *ul, linenr_T lnum)
|
||||||
|
{
|
||||||
|
char_u *line = ml_get(lnum);
|
||||||
|
|
||||||
|
if (curbuf->b_ml.ml_line_len == 0)
|
||||||
|
{
|
||||||
|
ul->ul_len = 1;
|
||||||
|
ul->ul_line = vim_strsave((char_u *)"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ul->ul_len = curbuf->b_ml.ml_line_len;
|
||||||
|
ul->ul_line = vim_memsave(line, ul->ul_len);
|
||||||
|
}
|
||||||
|
return ul->ul_line == NULL ? FAIL : OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common code for various ways to save text before a change.
|
* Common code for various ways to save text before a change.
|
||||||
* "top" is the line above the first changed line.
|
* "top" is the line above the first changed line.
|
||||||
@ -664,8 +685,8 @@ u_savecommon(
|
|||||||
|
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
{
|
{
|
||||||
if ((uep->ue_array = (char_u **)U_ALLOC_LINE(
|
if ((uep->ue_array = (undoline_T *)U_ALLOC_LINE(
|
||||||
sizeof(char_u *) * size)) == NULL)
|
sizeof(undoline_T) * size)) == NULL)
|
||||||
{
|
{
|
||||||
u_freeentry(uep, 0L);
|
u_freeentry(uep, 0L);
|
||||||
goto nomem;
|
goto nomem;
|
||||||
@ -678,7 +699,7 @@ u_savecommon(
|
|||||||
u_freeentry(uep, i);
|
u_freeentry(uep, i);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if ((uep->ue_array[i] = u_save_line(lnum++)) == NULL)
|
if (u_save_line(&uep->ue_array[i], lnum++) == FAIL)
|
||||||
{
|
{
|
||||||
u_freeentry(uep, i);
|
u_freeentry(uep, i);
|
||||||
goto nomem;
|
goto nomem;
|
||||||
@ -1111,6 +1132,8 @@ read_string_decrypt(bufinfo_T *bi, int len)
|
|||||||
vim_free(ptr);
|
vim_free(ptr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// In case there are text properties there already is a NUL, but
|
||||||
|
// checking for that is more expensive than just adding a dummy byte.
|
||||||
ptr[len] = NUL;
|
ptr[len] = NUL;
|
||||||
#ifdef FEAT_CRYPT
|
#ifdef FEAT_CRYPT
|
||||||
if (bi->bi_state != NULL && bi->bi_buffer == NULL)
|
if (bi->bi_state != NULL && bi->bi_buffer == NULL)
|
||||||
@ -1126,7 +1149,7 @@ read_string_decrypt(bufinfo_T *bi, int len)
|
|||||||
static int
|
static int
|
||||||
serialize_header(bufinfo_T *bi, char_u *hash)
|
serialize_header(bufinfo_T *bi, char_u *hash)
|
||||||
{
|
{
|
||||||
int len;
|
long len;
|
||||||
buf_T *buf = bi->bi_buf;
|
buf_T *buf = bi->bi_buf;
|
||||||
FILE *fp = bi->bi_fp;
|
FILE *fp = bi->bi_fp;
|
||||||
char_u time_buf[8];
|
char_u time_buf[8];
|
||||||
@ -1148,7 +1171,7 @@ serialize_header(bufinfo_T *bi, char_u *hash)
|
|||||||
buf->b_p_key, &header, &header_len);
|
buf->b_p_key, &header, &header_len);
|
||||||
if (bi->bi_state == NULL)
|
if (bi->bi_state == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
len = (int)fwrite(header, (size_t)header_len, (size_t)1, fp);
|
len = (long)fwrite(header, (size_t)header_len, (size_t)1, fp);
|
||||||
vim_free(header);
|
vim_free(header);
|
||||||
if (len != 1)
|
if (len != 1)
|
||||||
{
|
{
|
||||||
@ -1181,9 +1204,10 @@ serialize_header(bufinfo_T *bi, char_u *hash)
|
|||||||
|
|
||||||
/* buffer-specific data */
|
/* buffer-specific data */
|
||||||
undo_write_bytes(bi, (long_u)buf->b_ml.ml_line_count, 4);
|
undo_write_bytes(bi, (long_u)buf->b_ml.ml_line_count, 4);
|
||||||
len = buf->b_u_line_ptr != NULL ? (int)STRLEN(buf->b_u_line_ptr) : 0;
|
len = buf->b_u_line_ptr.ul_line == NULL
|
||||||
|
? 0 : STRLEN(buf->b_u_line_ptr.ul_line);
|
||||||
undo_write_bytes(bi, (long_u)len, 4);
|
undo_write_bytes(bi, (long_u)len, 4);
|
||||||
if (len > 0 && fwrite_crypt(bi, buf->b_u_line_ptr, (size_t)len) == FAIL)
|
if (len > 0 && fwrite_crypt(bi, buf->b_u_line_ptr.ul_line, (size_t)len) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
undo_write_bytes(bi, (long_u)buf->b_u_line_lnum, 4);
|
undo_write_bytes(bi, (long_u)buf->b_u_line_lnum, 4);
|
||||||
undo_write_bytes(bi, (long_u)buf->b_u_line_colnr, 4);
|
undo_write_bytes(bi, (long_u)buf->b_u_line_colnr, 4);
|
||||||
@ -1360,10 +1384,12 @@ serialize_uep(
|
|||||||
undo_write_bytes(bi, (long_u)uep->ue_size, 4);
|
undo_write_bytes(bi, (long_u)uep->ue_size, 4);
|
||||||
for (i = 0; i < uep->ue_size; ++i)
|
for (i = 0; i < uep->ue_size; ++i)
|
||||||
{
|
{
|
||||||
len = STRLEN(uep->ue_array[i]);
|
// Text is written without the text properties, since we cannot restore
|
||||||
|
// the text property types.
|
||||||
|
len = STRLEN(uep->ue_array[i].ul_line);
|
||||||
if (undo_write_bytes(bi, (long_u)len, 4) == FAIL)
|
if (undo_write_bytes(bi, (long_u)len, 4) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
if (len > 0 && fwrite_crypt(bi, uep->ue_array[i], len) == FAIL)
|
if (len > 0 && fwrite_crypt(bi, uep->ue_array[i].ul_line, len) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
@ -1374,7 +1400,7 @@ unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u_entry_T *uep;
|
u_entry_T *uep;
|
||||||
char_u **array = NULL;
|
undoline_T *array = NULL;
|
||||||
char_u *line;
|
char_u *line;
|
||||||
int line_len;
|
int line_len;
|
||||||
|
|
||||||
@ -1392,13 +1418,13 @@ unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name)
|
|||||||
if (uep->ue_size > 0)
|
if (uep->ue_size > 0)
|
||||||
{
|
{
|
||||||
if (uep->ue_size < LONG_MAX / (int)sizeof(char_u *))
|
if (uep->ue_size < LONG_MAX / (int)sizeof(char_u *))
|
||||||
array = (char_u **)U_ALLOC_LINE(sizeof(char_u *) * uep->ue_size);
|
array = (undoline_T *)U_ALLOC_LINE(sizeof(undoline_T) * uep->ue_size);
|
||||||
if (array == NULL)
|
if (array == NULL)
|
||||||
{
|
{
|
||||||
*error = TRUE;
|
*error = TRUE;
|
||||||
return uep;
|
return uep;
|
||||||
}
|
}
|
||||||
vim_memset(array, 0, sizeof(char_u *) * uep->ue_size);
|
vim_memset(array, 0, sizeof(undoline_T) * uep->ue_size);
|
||||||
}
|
}
|
||||||
uep->ue_array = array;
|
uep->ue_array = array;
|
||||||
|
|
||||||
@ -1417,7 +1443,8 @@ unserialize_uep(bufinfo_T *bi, int *error, char_u *file_name)
|
|||||||
*error = TRUE;
|
*error = TRUE;
|
||||||
return uep;
|
return uep;
|
||||||
}
|
}
|
||||||
array[i] = line;
|
array[i].ul_line = line;
|
||||||
|
array[i].ul_len = line_len + 1;
|
||||||
}
|
}
|
||||||
return uep;
|
return uep;
|
||||||
}
|
}
|
||||||
@ -1610,7 +1637,7 @@ u_write_undo(
|
|||||||
|
|
||||||
/* If there is no undo information at all, quit here after deleting any
|
/* If there is no undo information at all, quit here after deleting any
|
||||||
* existing undo file. */
|
* existing undo file. */
|
||||||
if (buf->b_u_numhead == 0 && buf->b_u_line_ptr == NULL)
|
if (buf->b_u_numhead == 0 && buf->b_u_line_ptr.ul_line == NULL)
|
||||||
{
|
{
|
||||||
if (p_verbose > 0)
|
if (p_verbose > 0)
|
||||||
verb_msg((char_u *)_("Skipping undo file write, nothing to undo"));
|
verb_msg((char_u *)_("Skipping undo file write, nothing to undo"));
|
||||||
@ -1771,7 +1798,7 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
|
|||||||
char_u *file_name;
|
char_u *file_name;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
long version, str_len;
|
long version, str_len;
|
||||||
char_u *line_ptr = NULL;
|
undoline_T line_ptr;
|
||||||
linenr_T line_lnum;
|
linenr_T line_lnum;
|
||||||
colnr_T line_colnr;
|
colnr_T line_colnr;
|
||||||
linenr_T line_count;
|
linenr_T line_count;
|
||||||
@ -1798,6 +1825,9 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
|
|||||||
bufinfo_T bi;
|
bufinfo_T bi;
|
||||||
|
|
||||||
vim_memset(&bi, 0, sizeof(bi));
|
vim_memset(&bi, 0, sizeof(bi));
|
||||||
|
line_ptr.ul_len = 0;
|
||||||
|
line_ptr.ul_line = NULL;
|
||||||
|
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
{
|
{
|
||||||
file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE);
|
file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE);
|
||||||
@ -1917,7 +1947,10 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
|
|||||||
if (str_len < 0)
|
if (str_len < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (str_len > 0)
|
if (str_len > 0)
|
||||||
line_ptr = read_string_decrypt(&bi, str_len);
|
{
|
||||||
|
line_ptr.ul_line = read_string_decrypt(&bi, str_len);
|
||||||
|
line_ptr.ul_len = str_len + 1;
|
||||||
|
}
|
||||||
line_lnum = (linenr_T)undo_read_4c(&bi);
|
line_lnum = (linenr_T)undo_read_4c(&bi);
|
||||||
line_colnr = (colnr_T)undo_read_4c(&bi);
|
line_colnr = (colnr_T)undo_read_4c(&bi);
|
||||||
if (line_lnum < 0 || line_colnr < 0)
|
if (line_lnum < 0 || line_colnr < 0)
|
||||||
@ -2098,7 +2131,7 @@ u_read_undo(char_u *name, char_u *hash, char_u *orig_name)
|
|||||||
goto theend;
|
goto theend;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
vim_free(line_ptr);
|
vim_free(line_ptr.ul_line);
|
||||||
if (uhp_table != NULL)
|
if (uhp_table != NULL)
|
||||||
{
|
{
|
||||||
for (i = 0; i < num_read_uhps; i++)
|
for (i = 0; i < num_read_uhps; i++)
|
||||||
@ -2596,7 +2629,7 @@ target_zero:
|
|||||||
static void
|
static void
|
||||||
u_undoredo(int undo)
|
u_undoredo(int undo)
|
||||||
{
|
{
|
||||||
char_u **newarray = NULL;
|
undoline_T *newarray = NULL;
|
||||||
linenr_T oldsize;
|
linenr_T oldsize;
|
||||||
linenr_T newsize;
|
linenr_T newsize;
|
||||||
linenr_T top, bot;
|
linenr_T top, bot;
|
||||||
@ -2669,8 +2702,13 @@ u_undoredo(int undo)
|
|||||||
* undoing auto-formatting puts the cursor in the previous
|
* undoing auto-formatting puts the cursor in the previous
|
||||||
* line. */
|
* line. */
|
||||||
for (i = 0; i < newsize && i < oldsize; ++i)
|
for (i = 0; i < newsize && i < oldsize; ++i)
|
||||||
if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0)
|
{
|
||||||
|
char_u *p = ml_get(top + 1 + i);
|
||||||
|
|
||||||
|
if (curbuf->b_ml.ml_line_len != uep->ue_array[i].ul_len
|
||||||
|
|| memcmp(uep->ue_array[i].ul_line, p, curbuf->b_ml.ml_line_len) != 0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL)
|
if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL)
|
||||||
{
|
{
|
||||||
newlnum = top;
|
newlnum = top;
|
||||||
@ -2689,10 +2727,10 @@ u_undoredo(int undo)
|
|||||||
/* delete the lines between top and bot and save them in newarray */
|
/* delete the lines between top and bot and save them in newarray */
|
||||||
if (oldsize > 0)
|
if (oldsize > 0)
|
||||||
{
|
{
|
||||||
if ((newarray = (char_u **)U_ALLOC_LINE(
|
if ((newarray = (undoline_T *)U_ALLOC_LINE(
|
||||||
sizeof(char_u *) * oldsize)) == NULL)
|
sizeof(undoline_T) * oldsize)) == NULL)
|
||||||
{
|
{
|
||||||
do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize));
|
do_outofmem_msg((long_u)(sizeof(undoline_T) * oldsize));
|
||||||
/*
|
/*
|
||||||
* We have messed up the entry list, repair is impossible.
|
* We have messed up the entry list, repair is impossible.
|
||||||
* we have to free the rest of the list.
|
* we have to free the rest of the list.
|
||||||
@ -2709,7 +2747,7 @@ u_undoredo(int undo)
|
|||||||
for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum)
|
for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum)
|
||||||
{
|
{
|
||||||
/* what can we do when we run out of memory? */
|
/* what can we do when we run out of memory? */
|
||||||
if ((newarray[i] = u_save_line(lnum)) == NULL)
|
if (u_save_line(&newarray[i], lnum) == FAIL)
|
||||||
do_outofmem_msg((long_u)0);
|
do_outofmem_msg((long_u)0);
|
||||||
/* remember we deleted the last line in the buffer, and a
|
/* remember we deleted the last line in the buffer, and a
|
||||||
* dummy empty line will be inserted */
|
* dummy empty line will be inserted */
|
||||||
@ -2726,15 +2764,13 @@ u_undoredo(int undo)
|
|||||||
{
|
{
|
||||||
for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
|
for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
|
||||||
{
|
{
|
||||||
/*
|
// If the file is empty, there is an empty line 1 that we
|
||||||
* If the file is empty, there is an empty line 1 that we
|
// should get rid of, by replacing it with the new line.
|
||||||
* should get rid of, by replacing it with the new line
|
|
||||||
*/
|
|
||||||
if (empty_buffer && lnum == 0)
|
if (empty_buffer && lnum == 0)
|
||||||
ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
|
ml_replace_len((linenr_T)1, uep->ue_array[i].ul_line, uep->ue_array[i].ul_len, TRUE, TRUE);
|
||||||
else
|
else
|
||||||
ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
|
ml_append(lnum, uep->ue_array[i].ul_line, (colnr_T)uep->ue_array[i].ul_len, FALSE);
|
||||||
vim_free(uep->ue_array[i]);
|
vim_free(uep->ue_array[i].ul_line);
|
||||||
}
|
}
|
||||||
vim_free((char_u *)uep->ue_array);
|
vim_free((char_u *)uep->ue_array);
|
||||||
}
|
}
|
||||||
@ -3172,13 +3208,17 @@ u_find_first_changed(void)
|
|||||||
|
|
||||||
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
|
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
|
||||||
&& lnum <= uep->ue_size; ++lnum)
|
&& lnum <= uep->ue_size; ++lnum)
|
||||||
if (STRCMP(ml_get_buf(curbuf, lnum, FALSE),
|
{
|
||||||
uep->ue_array[lnum - 1]) != 0)
|
char_u *p = ml_get_buf(curbuf, lnum, FALSE);
|
||||||
|
|
||||||
|
if (uep->ue_array[lnum - 1].ul_len != curbuf->b_ml.ml_line_len
|
||||||
|
|| memcmp(p, uep->ue_array[lnum - 1].ul_line, uep->ue_array[lnum - 1].ul_len) != 0)
|
||||||
{
|
{
|
||||||
CLEAR_POS(&(uhp->uh_cursor));
|
CLEAR_POS(&(uhp->uh_cursor));
|
||||||
uhp->uh_cursor.lnum = lnum;
|
uhp->uh_cursor.lnum = lnum;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (curbuf->b_ml.ml_line_count != uep->ue_size)
|
if (curbuf->b_ml.ml_line_count != uep->ue_size)
|
||||||
{
|
{
|
||||||
/* lines added or deleted at the end, put the cursor there */
|
/* lines added or deleted at the end, put the cursor there */
|
||||||
@ -3383,7 +3423,7 @@ u_freeentries(
|
|||||||
u_freeentry(u_entry_T *uep, long n)
|
u_freeentry(u_entry_T *uep, long n)
|
||||||
{
|
{
|
||||||
while (n > 0)
|
while (n > 0)
|
||||||
vim_free(uep->ue_array[--n]);
|
vim_free(uep->ue_array[--n].ul_line);
|
||||||
vim_free((char_u *)uep->ue_array);
|
vim_free((char_u *)uep->ue_array);
|
||||||
#ifdef U_DEBUG
|
#ifdef U_DEBUG
|
||||||
uep->ue_magic = 0;
|
uep->ue_magic = 0;
|
||||||
@ -3400,12 +3440,13 @@ u_clearall(buf_T *buf)
|
|||||||
buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL;
|
buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL;
|
||||||
buf->b_u_synced = TRUE;
|
buf->b_u_synced = TRUE;
|
||||||
buf->b_u_numhead = 0;
|
buf->b_u_numhead = 0;
|
||||||
buf->b_u_line_ptr = NULL;
|
buf->b_u_line_ptr.ul_line = NULL;
|
||||||
|
buf->b_u_line_ptr.ul_len = 0;
|
||||||
buf->b_u_line_lnum = 0;
|
buf->b_u_line_lnum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* save the line "lnum" for the "U" command
|
* Save the line "lnum" for the "U" command.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
u_saveline(linenr_T lnum)
|
u_saveline(linenr_T lnum)
|
||||||
@ -3420,7 +3461,7 @@ u_saveline(linenr_T lnum)
|
|||||||
curbuf->b_u_line_colnr = curwin->w_cursor.col;
|
curbuf->b_u_line_colnr = curwin->w_cursor.col;
|
||||||
else
|
else
|
||||||
curbuf->b_u_line_colnr = 0;
|
curbuf->b_u_line_colnr = 0;
|
||||||
if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL)
|
if (u_save_line(&curbuf->b_u_line_ptr, lnum) == FAIL)
|
||||||
do_outofmem_msg((long_u)0);
|
do_outofmem_msg((long_u)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3431,9 +3472,10 @@ u_saveline(linenr_T lnum)
|
|||||||
void
|
void
|
||||||
u_clearline(void)
|
u_clearline(void)
|
||||||
{
|
{
|
||||||
if (curbuf->b_u_line_ptr != NULL)
|
if (curbuf->b_u_line_ptr.ul_line != NULL)
|
||||||
{
|
{
|
||||||
VIM_CLEAR(curbuf->b_u_line_ptr);
|
VIM_CLEAR(curbuf->b_u_line_ptr.ul_line);
|
||||||
|
curbuf->b_u_line_ptr.ul_len = 0;
|
||||||
curbuf->b_u_line_lnum = 0;
|
curbuf->b_u_line_lnum = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3447,32 +3489,30 @@ u_clearline(void)
|
|||||||
void
|
void
|
||||||
u_undoline(void)
|
u_undoline(void)
|
||||||
{
|
{
|
||||||
colnr_T t;
|
colnr_T t;
|
||||||
char_u *oldp;
|
undoline_T oldp;
|
||||||
|
|
||||||
if (undo_off)
|
if (undo_off)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (curbuf->b_u_line_ptr == NULL
|
if (curbuf->b_u_line_ptr.ul_line == NULL
|
||||||
|| curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
|
|| curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
|
||||||
{
|
{
|
||||||
beep_flush();
|
beep_flush();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first save the line for the 'u' command */
|
// first save the line for the 'u' command
|
||||||
if (u_savecommon(curbuf->b_u_line_lnum - 1,
|
if (u_savecommon(curbuf->b_u_line_lnum - 1,
|
||||||
curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
|
curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
|
||||||
return;
|
return;
|
||||||
oldp = u_save_line(curbuf->b_u_line_lnum);
|
if (u_save_line(&oldp, curbuf->b_u_line_lnum) == FAIL)
|
||||||
if (oldp == NULL)
|
|
||||||
{
|
{
|
||||||
do_outofmem_msg((long_u)0);
|
do_outofmem_msg((long_u)0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE);
|
ml_replace_len(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr.ul_line, curbuf->b_u_line_ptr.ul_len, TRUE, FALSE);
|
||||||
changed_bytes(curbuf->b_u_line_lnum, 0);
|
changed_bytes(curbuf->b_u_line_lnum, 0);
|
||||||
vim_free(curbuf->b_u_line_ptr);
|
|
||||||
curbuf->b_u_line_ptr = oldp;
|
curbuf->b_u_line_ptr = oldp;
|
||||||
|
|
||||||
t = curbuf->b_u_line_colnr;
|
t = curbuf->b_u_line_colnr;
|
||||||
@ -3491,17 +3531,7 @@ u_blockfree(buf_T *buf)
|
|||||||
{
|
{
|
||||||
while (buf->b_u_oldhead != NULL)
|
while (buf->b_u_oldhead != NULL)
|
||||||
u_freeheader(buf, buf->b_u_oldhead, NULL);
|
u_freeheader(buf, buf->b_u_oldhead, NULL);
|
||||||
vim_free(buf->b_u_line_ptr);
|
vim_free(buf->b_u_line_ptr.ul_line);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* u_save_line(): allocate memory and copy line 'lnum' into it.
|
|
||||||
* Returns NULL when out of memory.
|
|
||||||
*/
|
|
||||||
static char_u *
|
|
||||||
u_save_line(linenr_T lnum)
|
|
||||||
{
|
|
||||||
return vim_strsave(ml_get(lnum));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -799,6 +799,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 */
|
||||||
|
/**/
|
||||||
|
688,
|
||||||
/**/
|
/**/
|
||||||
687,
|
687,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user