diff src/ops.c @ 5798:9f8fa56f1906 v7.4.243

updated for version 7.4.243 Problem: Cannot use setreg() to add text that includes a NUL. Solution: Make setreg() accept a list.
author Bram Moolenaar <bram@vim.org>
date Wed, 02 Apr 2014 22:17:10 +0200
parents f084024c0ddb
children 17903ded5e9a
line wrap: on
line diff
--- a/src/ops.c
+++ b/src/ops.c
@@ -113,7 +113,7 @@ static char_u	*skip_comment __ARGS((char
 #endif
 static void	block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int));
 #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
-static void	str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len, long blocklen));
+static void	str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len, long blocklen, int str_list));
 #endif
 static int	ends_in_white __ARGS((linenr_T lnum));
 #ifdef FEAT_COMMENTS
@@ -6005,7 +6005,7 @@ clip_yank_selection(type, str, len, cbd)
 
     clip_free_selection(cbd);
 
-    str_to_reg(y_ptr, type, str, len, 0L);
+    str_to_reg(y_ptr, type, str, len, 0L, FALSE);
 }
 
 /*
@@ -6113,7 +6113,7 @@ dnd_yank_drag_data(str, len)
     curr = y_current;
     y_current = &y_regs[TILDE_REGISTER];
     free_yank_all();
-    str_to_reg(y_current, MCHAR, str, len, 0L);
+    str_to_reg(y_current, MCHAR, str, len, 0L, FALSE);
     y_current = curr;
 }
 #endif
@@ -6308,6 +6308,47 @@ get_reg_contents(regname, flags)
     return retval;
 }
 
+    static int
+init_write_reg(name, old_y_previous, old_y_current, must_append, yank_type)
+    int		    name;
+    struct yankreg  **old_y_previous;
+    struct yankreg  **old_y_current;
+    int		    must_append;
+    int		    *yank_type UNUSED;
+{
+    if (!valid_yank_reg(name, TRUE))	    /* check for valid reg name */
+    {
+	emsg_invreg(name);
+	return FAIL;
+    }
+
+    /* Don't want to change the current (unnamed) register */
+    *old_y_previous = y_previous;
+    *old_y_current = y_current;
+
+    get_yank_register(name, TRUE);
+    if (!y_append && !must_append)
+	free_yank_all();
+    return OK;
+}
+
+    static void
+finish_write_reg(name, old_y_previous, old_y_current)
+    int		    name;
+    struct yankreg  *old_y_previous;
+    struct yankreg  *old_y_current;
+{
+# ifdef FEAT_CLIPBOARD
+    /* Send text of clipboard register to the clipboard. */
+    may_set_selection();
+# endif
+
+    /* ':let @" = "val"' should change the meaning of the "" register */
+    if (name != '"')
+	y_previous = old_y_previous;
+    y_current = old_y_current;
+}
+
 /*
  * Store string "str" in register "name".
  * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
@@ -6328,6 +6369,51 @@ write_reg_contents(name, str, maxlen, mu
 }
 
     void
+write_reg_contents_lst(name, strings, maxlen, must_append, yank_type, block_len)
+    int		name;
+    char_u	**strings;
+    int		maxlen UNUSED;
+    int		must_append;
+    int		yank_type;
+    long	block_len;
+{
+    struct yankreg  *old_y_previous, *old_y_current;
+
+    if (name == '/'
+#ifdef FEAT_EVAL
+	    || name == '='
+#endif
+	    )
+    {
+	char_u	*s;
+
+	if (strings[0] == NULL)
+	    s = (char_u *)"";
+	else if (strings[1] != NULL)
+	{
+	    EMSG(_("E883: search pattern and expression register may not "
+			"contain two or more lines"));
+	    return;
+	}
+	else
+	    s = strings[0];
+	write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
+	return;
+    }
+
+    if (name == '_')	    /* black hole: nothing to do */
+	return;
+
+    if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
+		&yank_type) == FAIL)
+	return;
+
+    str_to_reg(y_current, yank_type, (char_u *) strings, -1, block_len, TRUE);
+
+    finish_write_reg(name, old_y_previous, old_y_current);
+}
+
+    void
 write_reg_contents_ex(name, str, maxlen, must_append, yank_type, block_len)
     int		name;
     char_u	*str;
@@ -6364,40 +6450,22 @@ write_reg_contents_ex(name, str, maxlen,
 	    s = concat_str(get_expr_line_src(), p);
 	    vim_free(p);
 	    p = s;
-
 	}
 	set_expr_line(p);
 	return;
     }
 #endif
 
-    if (!valid_yank_reg(name, TRUE))	    /* check for valid reg name */
-    {
-	emsg_invreg(name);
-	return;
-    }
-
     if (name == '_')	    /* black hole: nothing to do */
 	return;
 
-    /* Don't want to change the current (unnamed) register */
-    old_y_previous = y_previous;
-    old_y_current = y_current;
-
-    get_yank_register(name, TRUE);
-    if (!y_append && !must_append)
-	free_yank_all();
-    str_to_reg(y_current, yank_type, str, len, block_len);
-
-# ifdef FEAT_CLIPBOARD
-    /* Send text of clipboard register to the clipboard. */
-    may_set_selection();
-# endif
-
-    /* ':let @" = "val"' should change the meaning of the "" register */
-    if (name != '"')
-	y_previous = old_y_previous;
-    y_current = old_y_current;
+    if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
+		&yank_type) == FAIL)
+	return;
+
+    str_to_reg(y_current, yank_type, str, len, block_len, FALSE);
+
+    finish_write_reg(name, old_y_previous, old_y_current);
 }
 #endif	/* FEAT_EVAL */
 
@@ -6407,12 +6475,13 @@ write_reg_contents_ex(name, str, maxlen,
  * is appended.
  */
     static void
-str_to_reg(y_ptr, yank_type, str, len, blocklen)
+str_to_reg(y_ptr, yank_type, str, len, blocklen, str_list)
     struct yankreg	*y_ptr;		/* pointer to yank register */
     int			yank_type;	/* MCHAR, MLINE, MBLOCK, MAUTO */
     char_u		*str;		/* string to put in register */
     long		len;		/* length of string */
     long		blocklen;	/* width of Visual block */
+    int			str_list;	/* TRUE if str is char_u ** */
 {
     int		type;			/* MCHAR, MLINE or MBLOCK */
     int		lnum;
@@ -6423,6 +6492,7 @@ str_to_reg(y_ptr, yank_type, str, len, b
     int		extraline = 0;		/* extra line at the end */
     int		append = FALSE;		/* append to last line in register */
     char_u	*s;
+    char_u	**ss;
     char_u	**pp;
     long	maxlen;
 
@@ -6430,7 +6500,8 @@ str_to_reg(y_ptr, yank_type, str, len, b
 	y_ptr->y_size = 0;
 
     if (yank_type == MAUTO)
-	type = ((len > 0 && (str[len - 1] == NL || str[len - 1] == CAR))
+	type = ((str_list || (len > 0 && (str[len - 1] == NL
+					    || str[len - 1] == CAR)))
 							     ? MLINE : MCHAR);
     else
 	type = yank_type;
@@ -6439,18 +6510,26 @@ str_to_reg(y_ptr, yank_type, str, len, b
      * Count the number of lines within the string
      */
     newlines = 0;
-    for (i = 0; i < len; i++)
-	if (str[i] == '\n')
+    if (str_list)
+    {
+	for (ss = (char_u **) str; *ss != NULL; ++ss)
 	    ++newlines;
-    if (type == MCHAR || len == 0 || str[len - 1] != '\n')
-    {
-	extraline = 1;
-	++newlines;	/* count extra newline at the end */
-    }
-    if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
-    {
-	append = TRUE;
-	--newlines;	/* uncount newline when appending first line */
+    }
+    else
+    {
+	for (i = 0; i < len; i++)
+	    if (str[i] == '\n')
+		++newlines;
+	if (type == MCHAR || len == 0 || str[len - 1] != '\n')
+	{
+	    extraline = 1;
+	    ++newlines;	/* count extra newline at the end */
+	}
+	if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
+	{
+	    append = TRUE;
+	    --newlines;	/* uncount newline when appending first line */
+	}
     }
 
     /*
@@ -6470,40 +6549,53 @@ str_to_reg(y_ptr, yank_type, str, len, b
     /*
      * Find the end of each line and save it into the array.
      */
-    for (start = 0; start < len + extraline; start += i + 1)
-    {
-	for (i = start; i < len; ++i)	/* find the end of the line */
-	    if (str[i] == '\n')
-		break;
-	i -= start;			/* i is now length of line */
-	if (i > maxlen)
-	    maxlen = i;
-	if (append)
+    if (str_list)
+    {
+	for (ss = (char_u **) str; *ss != NULL; ++ss, ++lnum)
 	{
-	    --lnum;
-	    extra = (int)STRLEN(y_ptr->y_array[lnum]);
+	    i = STRLEN(*ss);
+	    pp[lnum] = vim_strnsave(*ss, i);
+	    if (i > maxlen)
+		maxlen = i;
 	}
-	else
-	    extra = 0;
-	s = alloc((unsigned)(i + extra + 1));
-	if (s == NULL)
-	    break;
-	if (extra)
-	    mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
-	if (append)
-	    vim_free(y_ptr->y_array[lnum]);
-	if (i)
-	    mch_memmove(s + extra, str + start, (size_t)i);
-	extra += i;
-	s[extra] = NUL;
-	y_ptr->y_array[lnum++] = s;
-	while (--extra >= 0)
+    }
+    else
+    {
+	for (start = 0; start < len + extraline; start += i + 1)
 	{
-	    if (*s == NUL)
-		*s = '\n';	    /* replace NUL with newline */
-	    ++s;
+	    for (i = start; i < len; ++i)	/* find the end of the line */
+		if (str[i] == '\n')
+		    break;
+	    i -= start;			/* i is now length of line */
+	    if (i > maxlen)
+		maxlen = i;
+	    if (append)
+	    {
+		--lnum;
+		extra = (int)STRLEN(y_ptr->y_array[lnum]);
+	    }
+	    else
+		extra = 0;
+	    s = alloc((unsigned)(i + extra + 1));
+	    if (s == NULL)
+		break;
+	    if (extra)
+		mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
+	    if (append)
+		vim_free(y_ptr->y_array[lnum]);
+	    if (i)
+		mch_memmove(s + extra, str + start, (size_t)i);
+	    extra += i;
+	    s[extra] = NUL;
+	    y_ptr->y_array[lnum++] = s;
+	    while (--extra >= 0)
+	    {
+		if (*s == NUL)
+		    *s = '\n';	    /* replace NUL with newline */
+		++s;
+	    }
+	    append = FALSE;		    /* only first line is appended */
 	}
-	append = FALSE;		    /* only first line is appended */
     }
     y_ptr->y_type = type;
     y_ptr->y_size = lnum;