summaryrefslogtreecommitdiff
path: root/src/textprop.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/textprop.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/textprop.c')
-rw-r--r--src/textprop.c107
1 files changed, 106 insertions, 1 deletions
diff --git a/src/textprop.c b/src/textprop.c
index 4c78ff11c..8c86d0143 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -13,8 +13,8 @@
* TODO:
* - Adjust text property column and length when text is inserted/deleted.
* -> a :substitute with a multi-line match
- * -> join two lines, also with BS in Insert mode
* -> search for changed_bytes() from misc1.c
+ * -> search for mark_col_adjust()
* - Perhaps we only need TP_FLAG_CONT_NEXT and can drop TP_FLAG_CONT_PREV?
* - Add an arrray for global_proptypes, to quickly lookup a prop type by ID
* - Add an arrray for b_proptypes, to quickly lookup a prop type by ID
@@ -1097,4 +1097,109 @@ adjust_props_for_split(
ga_clear(&nextprop);
}
+/*
+ * Line "lnum" has been joined and will end up at column "col" in the new line.
+ * "removed" bytes have been removed from the start of the line, properties
+ * there are to be discarded.
+ * Move the adjusted text properties to an allocated string, store it in
+ * "prop_line" and adjust the columns.
+ */
+ void
+adjust_props_for_join(
+ linenr_T lnum,
+ textprop_T **prop_line,
+ int *prop_length,
+ long col,
+ int removed)
+{
+ int proplen;
+ char_u *props;
+ int ri;
+ int wi = 0;
+
+ proplen = get_text_props(curbuf, lnum, &props, FALSE);
+ if (proplen > 0)
+ {
+ *prop_line = (textprop_T *)alloc(proplen * (int)sizeof(textprop_T));
+ if (*prop_line != NULL)
+ {
+ for (ri = 0; ri < proplen; ++ri)
+ {
+ textprop_T *cp = *prop_line + wi;
+
+ mch_memmove(cp, props + ri * sizeof(textprop_T),
+ sizeof(textprop_T));
+ if (cp->tp_col + cp->tp_len > removed)
+ {
+ if (cp->tp_col > removed)
+ cp->tp_col += col;
+ else
+ {
+ // property was partly deleted, make it shorter
+ cp->tp_len -= removed - cp->tp_col;
+ cp->tp_col = col;
+ }
+ ++wi;
+ }
+ }
+ }
+ *prop_length = wi;
+ }
+}
+
+/*
+ * After joining lines: concatenate the text and the properties of all joined
+ * lines into one line and replace the line.
+ */
+ void
+join_prop_lines(
+ linenr_T lnum,
+ char_u *newp,
+ textprop_T **prop_lines,
+ int *prop_lengths,
+ int count)
+{
+ size_t proplen = 0;
+ size_t oldproplen;
+ char_u *props;
+ int i;
+ int len;
+ char_u *line;
+ size_t l;
+
+ for (i = 0; i < count - 1; ++i)
+ proplen += prop_lengths[i];
+ if (proplen == 0)
+ {
+ ml_replace(lnum, newp, FALSE);
+ return;
+ }
+
+ // get existing properties of the joined line
+ oldproplen = get_text_props(curbuf, lnum, &props, FALSE);
+
+ len = (int)STRLEN(newp) + 1;
+ line = alloc(len + (oldproplen + proplen) * (int)sizeof(textprop_T));
+ if (line == NULL)
+ return;
+ mch_memmove(line, newp, len);
+ l = oldproplen * sizeof(textprop_T);
+ mch_memmove(line + len, props, l);
+ len += l;
+
+ for (i = 0; i < count - 1; ++i)
+ if (prop_lines[i] != NULL)
+ {
+ l = prop_lengths[i] * sizeof(textprop_T);
+ mch_memmove(line + len, prop_lines[i], l);
+ len += l;
+ vim_free(prop_lines[i]);
+ }
+
+ ml_replace_len(lnum, line, len, TRUE, FALSE);
+ vim_free(newp);
+ vim_free(prop_lines);
+ vim_free(prop_lengths);
+}
+
#endif // FEAT_TEXT_PROP