Skip to content

Commit ccae467

Browse files
committed
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.
1 parent 6d3a194 commit ccae467

5 files changed

Lines changed: 137 additions & 73 deletions

File tree

src/memline.c

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3217,11 +3217,22 @@ ml_replace(linenr_T lnum, char_u *line, int copy)
32173217

32183218
if (line != NULL)
32193219
len = (colnr_T)STRLEN(line);
3220-
return ml_replace_len(lnum, line, len, copy);
3220+
return ml_replace_len(lnum, line, len, FALSE, copy);
32213221
}
32223222

3223+
/*
3224+
* Replace a line for the current buffer. Like ml_replace() with:
3225+
* "len_arg" is the length of the text, excluding NUL.
3226+
* If "has_props" is TRUE then "line_arg" includes the text properties and
3227+
* "len_arg" includes the NUL of the text.
3228+
*/
32233229
int
3224-
ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
3230+
ml_replace_len(
3231+
linenr_T lnum,
3232+
char_u *line_arg,
3233+
colnr_T len_arg,
3234+
int has_props,
3235+
int copy)
32253236
{
32263237
char_u *line = line_arg;
32273238
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)
32333244
if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
32343245
return FAIL;
32353246

3236-
if (copy && (line = vim_strnsave(line, len)) == NULL) /* allocate memory */
3237-
return FAIL;
3247+
if (!has_props)
3248+
++len; // include the NUL after the text
3249+
if (copy)
3250+
{
3251+
// copy the line to allocated memory
3252+
#ifdef FEAT_TEXT_PROP
3253+
if (has_props)
3254+
line = vim_memsave(line, len);
3255+
else
3256+
#endif
3257+
line = vim_strnsave(line, len - 1);
3258+
if (line == NULL)
3259+
return FAIL;
3260+
}
3261+
32383262
#ifdef FEAT_NETBEANS_INTG
32393263
if (netbeans_active())
32403264
{
@@ -3249,14 +3273,14 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
32493273
curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
32503274

32513275
#ifdef FEAT_TEXT_PROP
3252-
if (curbuf->b_has_textprop)
3276+
if (curbuf->b_has_textprop && !has_props)
32533277
// Need to fetch the old line to copy over any text properties.
32543278
ml_get_buf(curbuf, lnum, TRUE);
32553279
#endif
32563280
}
32573281

32583282
#ifdef FEAT_TEXT_PROP
3259-
if (curbuf->b_has_textprop)
3283+
if (curbuf->b_has_textprop && !has_props)
32603284
{
32613285
size_t oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1;
32623286

@@ -3266,11 +3290,11 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
32663290
size_t textproplen = curbuf->b_ml.ml_line_len - oldtextlen;
32673291

32683292
// Need to copy over text properties, stored after the text.
3269-
newline = alloc(len + 1 + (int)textproplen);
3293+
newline = alloc(len + (int)textproplen);
32703294
if (newline != NULL)
32713295
{
3272-
mch_memmove(newline, line, len + 1);
3273-
mch_memmove(newline + len + 1, curbuf->b_ml.ml_line_ptr + oldtextlen, textproplen);
3296+
mch_memmove(newline, line, len);
3297+
mch_memmove(newline + len, curbuf->b_ml.ml_line_ptr + oldtextlen, textproplen);
32743298
vim_free(line);
32753299
line = newline;
32763300
len += (colnr_T)textproplen;
@@ -3279,11 +3303,11 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
32793303
}
32803304
#endif
32813305

3282-
if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */
3283-
vim_free(curbuf->b_ml.ml_line_ptr); /* free it */
3306+
if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) // same line allocated
3307+
vim_free(curbuf->b_ml.ml_line_ptr); // free it
32843308

32853309
curbuf->b_ml.ml_line_ptr = line;
3286-
curbuf->b_ml.ml_line_len = len + 1;
3310+
curbuf->b_ml.ml_line_len = len;
32873311
curbuf->b_ml.ml_line_lnum = lnum;
32883312
curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
32893313

src/proto/memline.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ int ml_line_alloced(void);
2424
int ml_append(linenr_T lnum, char_u *line, colnr_T len, int newfile);
2525
int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, int newfile);
2626
int ml_replace(linenr_T lnum, char_u *line, int copy);
27-
int ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy);
27+
int ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int has_props, int copy);
2828
int ml_delete(linenr_T lnum, int message);
2929
void ml_setmarked(linenr_T lnum);
3030
linenr_T ml_firstmarked(void);

src/structs.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,14 @@ typedef struct
347347
* structures used for undo
348348
*/
349349

350+
// One line saved for undo. After the NUL terminated text there might be text
351+
// properties, thus ul_len can be larger than STRLEN(ul_line) + 1.
352+
typedef struct {
353+
char_u *ul_line; // text of the line
354+
long ul_len; // length of the line including NUL, plus text
355+
// properties
356+
} undoline_T;
357+
350358
typedef struct u_entry u_entry_T;
351359
typedef struct u_header u_header_T;
352360
struct u_entry
@@ -355,7 +363,7 @@ struct u_entry
355363
linenr_T ue_top; /* number of line above undo block */
356364
linenr_T ue_bot; /* number of line below undo block */
357365
linenr_T ue_lcount; /* linecount when u_save called */
358-
char_u **ue_array; /* array of lines in undo block */
366+
undoline_T *ue_array; /* array of lines in undo block */
359367
long ue_size; /* number of lines in ue_array */
360368
#ifdef U_DEBUG
361369
int ue_magic; /* magic number to check allocation */
@@ -2167,7 +2175,7 @@ struct file_buffer
21672175
/*
21682176
* variables for "U" command in undo.c
21692177
*/
2170-
char_u *b_u_line_ptr; /* saved line for "U" command */
2178+
undoline_T b_u_line_ptr; /* saved line for "U" command */
21712179
linenr_T b_u_line_lnum; /* line number of line in u_line */
21722180
colnr_T b_u_line_colnr; /* optional column number */
21732181

0 commit comments

Comments
 (0)