diff src/ops.c @ 16678:6f453673eb19 v8.1.1341

patch 8.1.1341: text properties are lost when joining lines commit https://github.com/vim/vim/commit/80e737cc6ab6b68948f6765348b6881be861b200 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 17 19:56:34 2019 +0200 patch 8.1.1341: text properties are lost when joining lines Problem: Text properties are lost when joining lines. Solution: Move the text properties to the joined line.
author Bram Moolenaar <Bram@vim.org>
date Fri, 17 May 2019 20:00:06 +0200
parents a1229400434a
children c263acbbd961
line wrap: on
line diff
--- 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