diff src/memline.c @ 15138:9df130fd5e0d v8.1.0579

patch 8.1.0579: cannot attach properties to text commit https://github.com/vim/vim/commit/98aefe7c3250bb5d4153b994f878594d1745424e Author: Bram Moolenaar <Bram@vim.org> Date: Thu Dec 13 22:20:09 2018 +0100 patch 8.1.0579: cannot attach properties to text Problem: Cannot attach properties to text. Solution: First part of adding text properties.
author Bram Moolenaar <Bram@vim.org>
date Thu, 13 Dec 2018 22:30:08 +0100
parents c98810dfebaf
children 7713ceb8c593
line wrap: on
line diff
--- a/src/memline.c
+++ b/src/memline.c
@@ -2487,7 +2487,6 @@ ml_get_buf(
 {
     bhdr_T	*hp;
     DATA_BL	*dp;
-    char_u	*ptr;
     static int	recursive = 0;
 
     if (lnum > buf->b_ml.ml_line_count)	/* invalid line number */
@@ -2518,6 +2517,10 @@ errorret:
      */
     if (buf->b_ml.ml_line_lnum != lnum || mf_dont_release)
     {
+	unsigned    start, end;
+	colnr_T	    len;
+	int	    idx;
+
 	ml_flush_line(buf);
 
 	/*
@@ -2540,8 +2543,18 @@ errorret:
 
 	dp = (DATA_BL *)(hp->bh_data);
 
-	ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
-	buf->b_ml.ml_line_ptr = ptr;
+	idx = lnum - buf->b_ml.ml_locked_low;
+	start = ((dp->db_index[idx]) & DB_INDEX_MASK);
+	// The text ends where the previous line starts.  The first line ends
+	// at the end of the block.
+	if (idx == 0)
+	    end = dp->db_txt_end;
+	else
+	    end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
+	len = end - start;
+
+	buf->b_ml.ml_line_ptr = (char_u *)dp + start;
+	buf->b_ml.ml_line_len = len;
 	buf->b_ml.ml_line_lnum = lnum;
 	buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
     }
@@ -2614,20 +2627,21 @@ ml_append_buf(
     static int
 ml_append_int(
     buf_T	*buf,
-    linenr_T	lnum,		/* append after this line (can be 0) */
-    char_u	*line,		/* text of the new line */
-    colnr_T	len,		/* length of line, including NUL, or 0 */
-    int		newfile,	/* flag, see above */
-    int		mark)		/* mark the new line */
+    linenr_T	lnum,		// append after this line (can be 0)
+    char_u	*line,		// text of the new line
+    colnr_T	len_arg,	// length of line, including NUL, or 0
+    int		newfile,	// flag, see above
+    int		mark)		// mark the new line
 {
+    colnr_T	len = len_arg;	// length of line, including NUL, or 0
     int		i;
-    int		line_count;	/* number of indexes in current block */
+    int		line_count;	// number of indexes in current block
     int		offset;
     int		from, to;
-    int		space_needed;	/* space needed for new line */
+    int		space_needed;	// space needed for new line
     int		page_size;
     int		page_count;
-    int		db_idx;		/* index for lnum in data block */
+    int		db_idx;		// index for lnum in data block
     bhdr_T	*hp;
     memfile_T	*mfp;
     DATA_BL	*dp;
@@ -2642,8 +2656,8 @@ ml_append_int(
 	lowest_marked = lnum + 1;
 
     if (len == 0)
-	len = (colnr_T)STRLEN(line) + 1;	/* space needed for the text */
-    space_needed = len + INDEX_SIZE;	/* space needed for text + index */
+	len = (colnr_T)STRLEN(line) + 1;	// space needed for the text
+    space_needed = len + INDEX_SIZE;	// space needed for text + index
 
     mfp = buf->b_ml.ml_mfp;
     page_size = mfp->mf_page_size;
@@ -2728,7 +2742,8 @@ ml_append_int(
 		dp->db_index[i + 1] = dp->db_index[i] - len;
 	    dp->db_index[db_idx + 1] = offset - len;
 	}
-	else				    /* add line at the end */
+	else
+	    // add line at the end (which is the start of the text)
 	    dp->db_index[db_idx + 1] = dp->db_txt_start;
 
 	/*
@@ -3128,6 +3143,19 @@ ml_append_int(
     int
 ml_replace(linenr_T lnum, char_u *line, int copy)
 {
+    colnr_T len = -1;
+
+    if (line != NULL)
+	len = STRLEN(line);
+    return ml_replace_len(lnum, line, len, copy);
+}
+
+    int
+ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
+{
+    char_u *line = line_arg;
+    colnr_T len = len_arg;
+
     if (line == NULL)		/* just checking... */
 	return FAIL;
 
@@ -3135,7 +3163,7 @@ ml_replace(linenr_T lnum, char_u *line, 
     if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
 	return FAIL;
 
-    if (copy && (line = vim_strsave(line)) == NULL) /* allocate memory */
+    if (copy && (line = vim_strnsave(line, len)) == NULL) /* allocate memory */
 	return FAIL;
 #ifdef FEAT_NETBEANS_INTG
     if (netbeans_active())
@@ -3144,11 +3172,48 @@ ml_replace(linenr_T lnum, char_u *line, 
 	netbeans_inserted(curbuf, lnum, 0, line, (int)STRLEN(line));
     }
 #endif
-    if (curbuf->b_ml.ml_line_lnum != lnum)	    /* other line buffered */
-	ml_flush_line(curbuf);			    /* flush it */
-    else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */
+    if (curbuf->b_ml.ml_line_lnum != lnum)
+    {
+	// another line is buffered, flush it
+	ml_flush_line(curbuf);
+
+#ifdef FEAT_TEXT_PROP
+	curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
+	if (has_any_text_properties(curbuf))
+	    // Need to fetch the old line to copy over any text properties.
+	    ml_get_buf(curbuf, lnum, TRUE);
+#endif
+    }
+
+#ifdef FEAT_TEXT_PROP
+    if (has_any_text_properties(curbuf))
+    {
+	size_t	oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1;
+
+	if (oldtextlen < (size_t)curbuf->b_ml.ml_line_len)
+	{
+	    char_u *newline;
+	    size_t textproplen = curbuf->b_ml.ml_line_len - oldtextlen;
+
+	    // Need to copy over text properties, stored after the text.
+	    newline = alloc(len + 1 + textproplen);
+	    if (newline != NULL)
+	    {
+		mch_memmove(newline, line, len + 1);
+		mch_memmove(newline + len + 1, curbuf->b_ml.ml_line_ptr + oldtextlen, textproplen);
+		vim_free(line);
+		line = newline;
+		len += textproplen;
+	    }
+	}
+    }
+#endif
+
+    if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */
 	vim_free(curbuf->b_ml.ml_line_ptr);	    /* free it */
+
     curbuf->b_ml.ml_line_ptr = line;
+    curbuf->b_ml.ml_line_len = len + 1;
     curbuf->b_ml.ml_line_lnum = lnum;
     curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
 
@@ -3490,7 +3555,7 @@ ml_flush_line(buf_T *buf)
 		old_len = dp->db_txt_end - start;
 	    else		/* text of previous line follows */
 		old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
-	    new_len = (colnr_T)STRLEN(new_line) + 1;
+	    new_len = buf->b_ml.ml_line_len;
 	    extra = new_len - old_len;	    /* negative if lines gets smaller */
 
 	    /*
@@ -5009,8 +5074,7 @@ ml_updatechunk(
 	 */
 	buf->b_ml.ml_usedchunks = 1;
 	buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
-	buf->b_ml.ml_chunksize[0].mlcs_totalsize =
-				  (long)STRLEN(buf->b_ml.ml_line_ptr) + 1;
+	buf->b_ml.ml_chunksize[0].mlcs_totalsize = (long)buf->b_ml.ml_line_len;
 	return;
     }