summaryrefslogtreecommitdiff
path: root/src/ops.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-05-17 19:56:34 +0200
committerBram Moolenaar <Bram@vim.org>2019-05-17 19:56:34 +0200
commit80e737cc6ab6b68948f6765348b6881be861b200 (patch)
tree695802f3be12c07911c64618e8bb8978367b1469 /src/ops.c
parentbfd451283f8c37926f4b0aa22b74b534bd84e482 (diff)
downloadvim-git-80e737cc6ab6b68948f6765348b6881be861b200.tar.gz
patch 8.1.1341: text properties are lost when joining linesv8.1.1341
Problem: Text properties are lost when joining lines. Solution: Move the text properties to the joined line.
Diffstat (limited to 'src/ops.c')
-rw-r--r--src/ops.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/src/ops.c b/src/ops.c
index 2aa18c437..d77aa2ef5 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -1211,7 +1211,8 @@ do_execreg(
int retval = OK;
int remap;
- if (regname == '@') /* repeat previous one */
+ // repeat previous one
+ if (regname == '@')
{
if (execreg_lastc == NUL)
{
@@ -1220,7 +1221,7 @@ do_execreg(
}
regname = execreg_lastc;
}
- /* check for valid regname */
+ // check for valid regname
if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
{
emsg_invreg(regname);
@@ -1232,11 +1233,13 @@ do_execreg(
regname = may_get_selection(regname);
#endif
- if (regname == '_') /* black hole: don't stuff anything */
+ // black hole: don't stuff anything
+ if (regname == '_')
return OK;
#ifdef FEAT_CMDHIST
- if (regname == ':') /* use last command line */
+ // use last command line
+ if (regname == ':')
{
if (last_cmdline == NULL)
{
@@ -4438,7 +4441,10 @@ do_join(
&& has_format_option(FO_REMOVE_COMS);
int prev_was_comment;
#endif
-
+#ifdef FEAT_TEXT_PROP
+ textprop_T **prop_lines = NULL;
+ int *prop_lengths = NULL;
+#endif
if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1),
(linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
@@ -4463,8 +4469,9 @@ do_join(
#endif
/*
- * Don't move anything, just compute the final line length
+ * Don't move anything yet, just compute the final line length
* and setup the array of space strings lengths
+ * This loops forward over the joined lines.
*/
for (t = 0; t < count; ++t)
{
@@ -4556,8 +4563,24 @@ do_join(
cend = newp + sumsize;
*cend = 0;
+#ifdef FEAT_TEXT_PROP
+ // We need to move properties of the lines that are going to be deleted to
+ // the new long one.
+ if (curbuf->b_has_textprop && !text_prop_frozen)
+ {
+ // Allocate an array to copy the text properties of joined lines into.
+ // And another array to store the number of properties in each line.
+ prop_lines = (textprop_T **)alloc_clear(
+ (int)(count - 1) * sizeof(textprop_T *));
+ prop_lengths = (int *)alloc_clear((int)(count - 1) * sizeof(int));
+ if (prop_lengths == NULL)
+ VIM_CLEAR(prop_lines);
+ }
+#endif
+
/*
* Move affected lines to the new long one.
+ * This loops backwards over the joined lines, including the original line.
*
* Move marks from each deleted line to the joined line, adjusting the
* column. This is not Vi compatible, but Vi deletes the marks, thus that
@@ -4583,8 +4606,15 @@ do_join(
(long)(cend - newp - spaces_removed), spaces_removed);
if (t == 0)
break;
+#ifdef FEAT_TEXT_PROP
+ if (prop_lines != NULL)
+ adjust_props_for_join(curwin->w_cursor.lnum + t,
+ prop_lines + t - 1, prop_lengths + t - 1,
+ (long)(cend - newp - spaces_removed), spaces_removed);
+#endif
+
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
-#if defined(FEAT_COMMENTS) || defined(PROTO)
+#if defined(FEAT_COMMENTS)
if (remove_comments)
curr += comments[t - 1];
#endif
@@ -4592,7 +4622,14 @@ do_join(
curr = skipwhite(curr);
currsize = (int)STRLEN(curr);
}
- ml_replace(curwin->w_cursor.lnum, newp, FALSE);
+
+#ifdef FEAT_TEXT_PROP
+ if (prop_lines != NULL)
+ join_prop_lines(curwin->w_cursor.lnum, newp,
+ prop_lines, prop_lengths, count);
+ else
+#endif
+ ml_replace(curwin->w_cursor.lnum, newp, FALSE);
if (setmark)
{
@@ -4605,7 +4642,6 @@ do_join(
* the deleted line. */
changed_lines(curwin->w_cursor.lnum, currsize,
curwin->w_cursor.lnum + 1, 0L);
-
/*
* Delete following lines. To do this we move the cursor there
* briefly, and then move it back. After del_lines() the cursor may