Commit: patch 9.1.1999: clipboard provider does not respect 'clipboard' option

1 view
Skip to first unread message

Christian Brabandt

unread,
Dec 18, 2025, 4:00:54 PM (13 hours ago) Dec 18
to vim...@googlegroups.com
patch 9.1.1999: clipboard provider does not respect 'clipboard' option

Commit: https://github.com/vim/vim/commit/96ce55331f5920653b7fa5346a0765d8c0050002
Author: Foxe Chen <chen...@gmail.com>
Date: Thu Dec 18 21:47:34 2025 +0100

patch 9.1.1999: clipboard provider does not respect 'clipboard' option

Problem: clipboard provider does not respect 'clipboard' option
(Satoru Kitaguchi, after v9.1.1972)
Solution: make clipboard provider register respect "unnamed/unnamedplus"
from the 'clipboard' option value

fixes: #18930
closes: #18952

Signed-off-by: Foxe Chen <chen...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index 732046061..172bf494a 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -1,4 +1,4 @@
-*change.txt* For Vim version 9.1. Last change: 2025 Nov 09
+*change.txt* For Vim version 9.1. Last change: 2025 Dec 18


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1094,7 +1094,8 @@ inside of strings can change! Also see 'softtabstop' option. >
*:y* *:yank* *E850*
:[range]y[ank] [x] Yank [range] lines [into register x]. Yanking to the
"* or "+ registers is possible only when the
- |+clipboard| feature is included.
+ |+clipboard| or |+clipboard_provider| features are
+ included.

:[range]y[ank] [x] {count}
Yank {count} lines, starting with last line number
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 54a0cb67b..439e45291 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 9.1. Last change: 2025 Dec 17
+*eval.txt* For Vim version 9.1. Last change: 2025 Dec 18


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -5286,9 +5286,14 @@ Usage: >vim
The clipboard provider feature allows the "+" |quoteplus| and "*" |quotestar|
registers to be overridden by custom Vimscript functions. There can be
multiple providers, and Vim chooses which one to use based on 'clipmethod'.
-Despite the name, it does not use the 'clipboard' option and should be treated
-separate from the clipboard functionality. It essentially overrides the
-existing behaviour of the clipboard registers.
+
+Despite the name, it should be treated separate from the clipboard
+functionality. It essentially overrides the existing behaviour of the
+clipboard registers.
+
+ *clipboard-providers-clipboard*
+The clipboard provider feature will respect the "unnamed" and "unnamedplus"
+values in the 'clipboard' option. Any other value will be ignored.

*clipboard-providers-no-clipboard*
If the |+clipboard| feature is not enabled, then the "+" and "*" registers
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 010b9a389..a8dbab912 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt* For Vim version 9.1. Last change: 2025 Dec 13
+*options.txt* For Vim version 9.1. Last change: 2025 Dec 18


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1815,13 +1815,19 @@ A jump table for the options with a short description can be found at |Q_op|.
for X-windows, "" otherwise)
global
{only in GUI versions or when the |+xterm_clipboard|
- or |+wayland_clipboard| features are included}
+ or |+wayland_clipboard| features or
+ |+clipboard_provider| features are included}
This option is a list of comma-separated names.
Note: if one of the items is "exclude:", then you can't add an item
after that. Therefore do not append an item with += but use ^= to
prepend, e.g.: >
set clipboard^=unnamed
< When using the GUI see |'go-A'|.
+ When using the |clipboard-providers| feature, only the "unamed" and
+ "unnamedplus" features will be recognized If compiled without the
+ |+clipboard| feature but compiled with the |+clipboard_provider|
+ feature, then they will be the only values allowed and the other
+ values will be invalid.
These names are recognized:

*clipboard-unnamed*
@@ -1845,9 +1851,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'*'. If Wayland is being used and the compositor does
not support the primary selection then the regular
selection is used in its place. Only available with
- the |+X11| or
- |+wayland_clipboard| feature. Availability can be
- checked with: >
+ the |+X11| or |+wayland_clipboard| feature.
+ Availability can be checked with: >
if has('unnamedplus')
<
*clipboard-autoselect*
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 2f83c8a28..684f392d5 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -6698,6 +6698,7 @@ clipboard-exclude options.txt /*clipboard-exclude*
clipboard-html options.txt /*clipboard-html*
clipboard-providers eval.txt /*clipboard-providers*
clipboard-providers-available eval.txt /*clipboard-providers-available*
+clipboard-providers-clipboard eval.txt /*clipboard-providers-clipboard*
clipboard-providers-clipmethod eval.txt /*clipboard-providers-clipmethod*
clipboard-providers-copy eval.txt /*clipboard-providers-copy*
clipboard-providers-define eval.txt /*clipboard-providers-define*
diff --git a/src/clipboard.c b/src/clipboard.c
index 6d321e5c0..1d46b56f0 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -1428,104 +1428,6 @@ clip_gen_owner_exists(Clipboard_T *cbd UNUSED)
}
#endif

-/*
- * Extract the items in the 'clipboard' option and set global values.
- * Return an error message or NULL for success.
- */
- char *
-did_set_clipboard(optset_T *args UNUSED)
-{
- int new_unnamed = 0;
- int new_autoselect_star = FALSE;
- int new_autoselect_plus = FALSE;
- int new_autoselectml = FALSE;
- int new_html = FALSE;
- regprog_T *new_exclude_prog = NULL;
- char *errmsg = NULL;
- char_u *p;
-
- for (p = p_cb; *p != NUL; )
- {
- // Note: Keep this in sync with p_cb_values.
- if (STRNCMP(p, "unnamed", 7) == 0 && (p[7] == ',' || p[7] == NUL))
- {
- new_unnamed |= CLIP_UNNAMED;
- p += 7;
- }
- else if (STRNCMP(p, "unnamedplus", 11) == 0
- && (p[11] == ',' || p[11] == NUL))
- {
- new_unnamed |= CLIP_UNNAMED_PLUS;
- p += 11;
- }
- else if (STRNCMP(p, "autoselect", 10) == 0
- && (p[10] == ',' || p[10] == NUL))
- {
- new_autoselect_star = TRUE;
- p += 10;
- }
- else if (STRNCMP(p, "autoselectplus", 14) == 0
- && (p[14] == ',' || p[14] == NUL))
- {
- new_autoselect_plus = TRUE;
- p += 14;
- }
- else if (STRNCMP(p, "autoselectml", 12) == 0
- && (p[12] == ',' || p[12] == NUL))
- {
- new_autoselectml = TRUE;
- p += 12;
- }
- else if (STRNCMP(p, "html", 4) == 0 && (p[4] == ',' || p[4] == NUL))
- {
- new_html = TRUE;
- p += 4;
- }
- else if (STRNCMP(p, "exclude:", 8) == 0 && new_exclude_prog == NULL)
- {
- p += 8;
- new_exclude_prog = vim_regcomp(p, RE_MAGIC);
- if (new_exclude_prog == NULL)
- errmsg = e_invalid_argument;
- break;
- }
- else
- {
- errmsg = e_invalid_argument;
- break;
- }
- if (*p == ',')
- ++p;
- }
- if (errmsg == NULL)
- {
- if (global_busy)
- // clip_unnamed will be reset to clip_unnamed_saved
- // at end_global_changes
- clip_unnamed_saved = new_unnamed;
- else
- clip_unnamed = new_unnamed;
- clip_autoselect_star = new_autoselect_star;
- clip_autoselect_plus = new_autoselect_plus;
- clip_autoselectml = new_autoselectml;
- clip_html = new_html;
- vim_regfree(clip_exclude_prog);
- clip_exclude_prog = new_exclude_prog;
-#ifdef FEAT_GUI_GTK
- if (gui.in_use)
- {
- gui_gtk_set_selection_targets((GdkAtom)GDK_SELECTION_PRIMARY);
- gui_gtk_set_selection_targets((GdkAtom)clip_plus.gtk_sel_atom);
- gui_gtk_set_dnd_targets();
- }
-#endif
- }
- else
- vim_regfree(new_exclude_prog);
-
- return errmsg;
-}
-
/*
* Stuff for the X clipboard. Shared between VMS and Unix.
*/
@@ -2394,32 +2296,6 @@ may_set_selection(void)
}
}

-/*
- * Adjust the register name pointed to with "rp" for the clipboard being
- * used always and the clipboard being available.
- */
- void
-adjust_clip_reg(int *rp)
-{
- // If no reg. specified, and "unnamed" or "unnamedplus" is in 'clipboard',
- // use '*' or '+' reg, respectively. "unnamedplus" prevails.
- if (*rp == 0 && (clip_unnamed != 0 || clip_unnamed_saved != 0))
- {
- if (clip_unnamed != 0)
- *rp = ((clip_unnamed & CLIP_UNNAMED_PLUS) && clip_plus.available)
- ? '+' : '*';
- else
- *rp = ((clip_unnamed_saved & CLIP_UNNAMED_PLUS)
- && clip_plus.available) ? '+' : '*';
- }
- if ((!clip_star.available && *rp == '*') ||
- (!clip_plus.available && *rp == '+'))
- {
- msg_warn_missing_clipboard();
- *rp = 0;
- }
-}
-
#if defined(FEAT_WAYLAND_CLIPBOARD)

static clip_wl_selection_T *
@@ -3483,7 +3359,7 @@ get_clipmethod(char_u *str)
}
else
{
-#ifdef FEAT_EVAL
+#ifdef FEAT_CLIPBOARD_PROVIDER
// Check if name matches a clipboard provider
int r = clip_provider_is_available(buf);

@@ -3501,7 +3377,7 @@ get_clipmethod(char_u *str)
else if (r == -1)
#endif
{
-#ifdef FEAT_EVAL
+#ifdef FEAT_CLIPBOARD_PROVIDER
fail:
#endif
ret = CLIPMETHOD_FAIL;
@@ -3648,6 +3524,148 @@ ex_clipreset(exarg_T *eap UNUSED)
clipmethod_to_str(clipmethod));
}

+/*
+ * Adjust the register name pointed to with "rp" for the clipboard being
+ * used always and the clipboard being available.
+ */
+ void
+adjust_clip_reg(int *rp)
+{
+#ifdef FEAT_CLIPBOARD_PROVIDER
+ if (clipmethod == CLIPMETHOD_PROVIDER)
+ {
+ if (clip_unnamed != 0)
+ *rp = ((clip_unnamed & CLIP_UNNAMED_PLUS)) ? '+' : '*';
+ return;
+ }
+#endif
+#ifdef FEAT_CLIPBOARD
+ // If no reg. specified, and "unnamed" or "unnamedplus" is in 'clipboard',
+ // use '*' or '+' reg, respectively. "unnamedplus" prevails.
+ if (*rp == 0 && (clip_unnamed != 0 || clip_unnamed_saved != 0))
+ {
+ if (clip_unnamed != 0)
+ *rp = ((clip_unnamed & CLIP_UNNAMED_PLUS) && clip_plus.available)
+ ? '+' : '*';
+ else
+ *rp = ((clip_unnamed_saved & CLIP_UNNAMED_PLUS)
+ && clip_plus.available) ? '+' : '*';
+ }
+ if ((!clip_star.available && *rp == '*') ||
+ (!clip_plus.available && *rp == '+'))
+ {
+ msg_warn_missing_clipboard();
+ *rp = 0;
+ }
+#endif
+}
+
+/*
+ * Extract the items in the 'clipboard' option and set global values.
+ * Return an error message or NULL for success.
+ */
+ char *
+did_set_clipboard(optset_T *args UNUSED)
+{
+ int new_unnamed = 0;
+#ifdef FEAT_CLIPBOARD
+ int new_autoselect_star = FALSE;
+ int new_autoselect_plus = FALSE;
+ int new_autoselectml = FALSE;
+ int new_html = FALSE;
+#endif
+ regprog_T *new_exclude_prog = NULL;
+ char *errmsg = NULL;
+ char_u *p;
+
+ for (p = p_cb; *p != NUL; )
+ {
+ // Note: Keep this in sync with p_cb_values.
+ if (STRNCMP(p, "unnamed", 7) == 0 && (p[7] == ',' || p[7] == NUL))
+ {
+ new_unnamed |= CLIP_UNNAMED;
+ p += 7;
+ }
+ else if (STRNCMP(p, "unnamedplus", 11) == 0
+ && (p[11] == ',' || p[11] == NUL))
+ {
+ new_unnamed |= CLIP_UNNAMED_PLUS;
+ p += 11;
+ }
+#ifdef FEAT_CLIPBOARD
+ else if (STRNCMP(p, "autoselect", 10) == 0
+ && (p[10] == ',' || p[10] == NUL))
+ {
+ new_autoselect_star = TRUE;
+ p += 10;
+ }
+ else if (STRNCMP(p, "autoselectplus", 14) == 0
+ && (p[14] == ',' || p[14] == NUL))
+ {
+ new_autoselect_plus = TRUE;
+ p += 14;
+ }
+ else if (STRNCMP(p, "autoselectml", 12) == 0
+ && (p[12] == ',' || p[12] == NUL))
+ {
+ new_autoselectml = TRUE;
+ p += 12;
+ }
+ else if (STRNCMP(p, "html", 4) == 0 && (p[4] == ',' || p[4] == NUL))
+ {
+ new_html = TRUE;
+ p += 4;
+ }
+ else if (STRNCMP(p, "exclude:", 8) == 0 && new_exclude_prog == NULL)
+ {
+ p += 8;
+ new_exclude_prog = vim_regcomp(p, RE_MAGIC);
+ if (new_exclude_prog == NULL)
+ errmsg = e_invalid_argument;
+ break;
+ }
+#endif
+ else
+ {
+ errmsg = e_invalid_argument;
+ break;
+ }
+ if (*p == ',')
+ ++p;
+ }
+ if (errmsg == NULL)
+ {
+#ifdef FEAT_CLIPBOARD
+ if (global_busy)
+ // clip_unnamed will be reset to clip_unnamed_saved
+ // at end_global_changes
+ clip_unnamed_saved = new_unnamed;
+ else
+#endif
+ clip_unnamed = new_unnamed;
+#ifdef FEAT_CLIPBOARD
+ clip_autoselect_star = new_autoselect_star;
+ clip_autoselect_plus = new_autoselect_plus;
+ clip_autoselectml = new_autoselectml;
+ clip_html = new_html;
+ vim_regfree(clip_exclude_prog);
+ clip_exclude_prog = new_exclude_prog;
+#endif
+#ifdef FEAT_GUI_GTK
+ if (gui.in_use)
+ {
+ gui_gtk_set_selection_targets((GdkAtom)GDK_SELECTION_PRIMARY);
+ gui_gtk_set_selection_targets((GdkAtom)clip_plus.gtk_sel_atom);
+ gui_gtk_set_dnd_targets();
+ }
+#endif
+ }
+ else
+ vim_regfree(new_exclude_prog);
+
+ return errmsg;
+}
+
#endif // HAVE_CLIPMETHOD

#ifdef FEAT_CLIPBOARD_PROVIDER
diff --git a/src/evalvars.c b/src/evalvars.c
index 2e0108534..406417771 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -2986,7 +2986,7 @@ reset_reg_var(void)

// Adjust the register according to 'clipboard', so that when
// "unnamed" is present it becomes '*' or '+' instead of '"'.
-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
adjust_clip_reg(&regname);
#endif
set_reg_var(regname);
diff --git a/src/globals.h b/src/globals.h
index ed4affa8c..9b101d8f2 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -980,17 +980,21 @@ EXTERN Clipboard_T clip_plus; // CLIPBOARD selection in X11/Wayland
# define clip_plus clip_star // there is only one clipboard
# define ONE_CLIPBOARD
# endif
+#endif

+#ifdef HAVE_CLIPMETHOD
# define CLIP_UNNAMED 1
# define CLIP_UNNAMED_PLUS 2
EXTERN int clip_unnamed INIT(= 0); // above two values or'ed

+# ifdef FEAT_CLIPBOARD
EXTERN int clip_autoselect_star INIT(= FALSE);
EXTERN int clip_autoselect_plus INIT(= FALSE);
EXTERN int clip_autoselectml INIT(= FALSE);
EXTERN int clip_html INIT(= FALSE);
EXTERN regprog_T *clip_exclude_prog INIT(= NULL);
EXTERN int clip_unnamed_saved INIT(= 0);
+# endif
#endif

#ifdef FEAT_CLIPBOARD_PROVIDER
diff --git a/src/normal.c b/src/normal.c
index 59843293e..2f2a56017 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -7425,7 +7425,7 @@ nv_put_opt(cmdarg_T *cap, int fix_indent)
was_visual = TRUE;
regname = cap->oap->regname;
keep_registers = cap->cmdchar == 'P';
-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
adjust_clip_reg(&regname);
#endif
if (regname == 0 || regname == '"'
diff --git a/src/ops.c b/src/ops.c
index 7e1bb1bfb..a7f0f041d 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -800,7 +800,7 @@ op_delete(oparg_T *oap)
// use register given with CTRL_R, defaults to zero
oap->regname = VIsual_select_reg;

-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
adjust_clip_reg(&oap->regname);
#endif

@@ -857,12 +857,18 @@ op_delete(oparg_T *oap)
*/
if (oap->regname != '_')
{
+#ifdef FEAT_CLIPBOARD_PROVIDER
+ inc_clip_provider();
+#endif
if (oap->regname != 0)
{
// check for read-only register
if (!valid_yank_reg(oap->regname, TRUE))
{
beep_flush();
+#ifdef FEAT_CLIPBOARD_PROVIDER
+ dec_clip_provider();
+#endif
return OK;
}
get_yank_register(oap->regname, TRUE); // yank into specif'd reg.
@@ -888,7 +894,7 @@ op_delete(oparg_T *oap)
// Yank into small delete register when no named register specified
// and the delete is within one line.
if ((
-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
((clip_unnamed & CLIP_UNNAMED) && oap->regname == '*') ||
((clip_unnamed & CLIP_UNNAMED_PLUS) && oap->regname == '+') ||
#endif
@@ -918,6 +924,9 @@ op_delete(oparg_T *oap)
if (n != 'y')
{
emsg(_(e_command_aborted));
+#ifdef FEAT_CLIPBOARD_PROVIDER
+ dec_clip_provider();
+#endif
return FAIL;
}
}
@@ -925,6 +934,9 @@ op_delete(oparg_T *oap)
#if defined(FEAT_EVAL)
if (did_yank && has_textyankpost())
yank_do_autocmd(oap, get_y_current());
+#endif
+#ifdef FEAT_CLIPBOARD_PROVIDER
+ dec_clip_provider();
#endif
}

diff --git a/src/option.h b/src/option.h
index 87096fa60..55dbf8a56 100644
--- a/src/option.h
+++ b/src/option.h
@@ -505,10 +505,8 @@ EXTERN int p_cdh; // 'cdhome'
EXTERN char_u *p_cino; // 'cinoptions'
EXTERN char_u *p_cedit; // 'cedit'
EXTERN long p_cwh; // 'cmdwinheight'
-#ifdef FEAT_CLIPBOARD
-EXTERN char_u *p_cb; // 'clipboard'
-#endif
#ifdef HAVE_CLIPMETHOD
+EXTERN char_u *p_cb; // 'clipboard'
EXTERN char_u *p_cpm; // 'clipmethod'
#endif
EXTERN long p_ch; // 'cmdheight'
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 81d9ff76e..d888615f5 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -618,7 +618,7 @@ static struct vimoption options[] =
(char_u *)0L}
SCTX_INIT},
{"clipboard", "cb", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
(char_u *)&p_cb, PV_NONE, did_set_clipboard, expand_set_clipboard,
# if defined(FEAT_XCLIPBOARD) || defined(FEAT_WAYLAND_CLIPBOARD)
{(char_u *)"autoselect,exclude:cons\|linux",
diff --git a/src/optionstr.c b/src/optionstr.c
index 42e09b3c9..84f973442 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -41,9 +41,13 @@ static char *(p_dip_inline_values[]) = {"none", "simple", "char", "word", NULL};
#endif
static char *(p_nf_values[]) = {"bin", "octal", "hex", "alpha", "unsigned", "blank", NULL};
static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL};
-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
// Note: Keep this in sync with did_set_clipboard()
-static char *(p_cb_values[]) = {"unnamed", "unnamedplus", "autoselect", "autoselectplus", "autoselectml", "html", "exclude:", NULL};
+static char *(p_cb_values[]) = {"unnamed", "unnamedplus",
+# ifdef FEAT_CLIPBOARD
+ "autoselect", "autoselectplus", "autoselectml", "html", "exclude:",
+# endif
+ NULL};
#endif
#ifdef FEAT_CRYPT
static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2",
@@ -1389,7 +1393,7 @@ expand_set_casemap(optexpand_T *args, int *numMatches, char_u ***matches)
matches);
}

-#if defined(FEAT_CLIPBOARD)
+#if defined(HAVE_CLIPMETHOD)
int
expand_set_clipboard(optexpand_T *args, int *numMatches, char_u ***matches)
{
diff --git a/src/proto/clipboard.pro b/src/proto/clipboard.pro
index 6ada18c9e..5bcaf2ce9 100644
--- a/src/proto/clipboard.pro
+++ b/src/proto/clipboard.pro
@@ -18,7 +18,6 @@ void clip_scroll_selection(int rows);
void clip_copy_modeless_selection(int both);
void clip_gen_set_selection(Clipboard_T *cbd);
int clip_gen_owner_exists(Clipboard_T *cbd);
-char *did_set_clipboard(optset_T *args);
void open_app_context(void);
void x11_setup_atoms(Display *dpy);
void x11_setup_selection(Widget w);
@@ -34,12 +33,13 @@ void clip_yank_selection(int type, char_u *str, long len, Clipboard_T *cbd);
int clip_convert_selection(char_u **str, long_u *len, Clipboard_T *cbd);
int may_get_selection(int regname);
void may_set_selection(void);
-void adjust_clip_reg(int *rp);
int clip_init_wayland(void);
void clip_uninit_wayland(void);
int clip_reset_wayland(void);
char *choose_clipmethod(void);
void ex_clipreset(exarg_T *eap);
+void adjust_clip_reg(int *rp);
+char *did_set_clipboard(optset_T *args);
void call_clip_provider_request(int reg);
void call_clip_provider_set(int reg);
void inc_clip_provider(void);
diff --git a/src/register.c b/src/register.c
index 12fe8ebb1..90abbcc54 100644
--- a/src/register.c
+++ b/src/register.c
@@ -33,7 +33,7 @@ static int stuff_yank(int, char_u *);
static void put_reedit_in_typebuf(int silent);
static int put_in_typebuf(char_u *s, int esc, int colon, int silent);
static int yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space);
-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
static void copy_yank_reg(yankreg_T *reg);
#endif
static void dis_msg(char_u *p, int skip_esc);
@@ -1421,10 +1421,20 @@ op_yank(oparg_T *oap, int deleting, int mess)

#ifdef FEAT_CLIPBOARD_PROVIDER
inc_clip_provider();
- if (curr == &y_regs[REAL_PLUS_REGISTER])
+ if (curr == &y_regs[REAL_PLUS_REGISTER] || (!deleting && oap->regname == 0
+ && (clip_unnamed & CLIP_UNNAMED_PLUS)))
+ {
+ if (curr != &(y_regs[REAL_PLUS_REGISTER]))
+ copy_yank_reg(&(y_regs[REAL_PLUS_REGISTER]));
call_clip_provider_set('+');
- else if (curr == &y_regs[STAR_REGISTER])
+ }
+ if (curr == &y_regs[STAR_REGISTER] || (!deleting && oap->regname == 0
+ && (clip_unnamed & CLIP_UNNAMED)))
+ {
+ if (curr != &(y_regs[STAR_REGISTER]))
+ copy_yank_reg(&(y_regs[STAR_REGISTER]));
call_clip_provider_set('*');
+ }
#endif

#ifdef FEAT_CLIPBOARD
@@ -1518,7 +1528,7 @@ yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space)
return OK;
}

-#ifdef FEAT_CLIPBOARD
+#ifdef HAVE_CLIPMETHOD
/*
* Make a copy of the y_current register to register "reg".
*/
@@ -1589,16 +1599,16 @@ do_put(
pos_T orig_end = curbuf->b_op_end;
unsigned int cur_ve_flags = get_ve_flags();

+#ifdef HAVE_CLIPMETHOD
+ adjust_clip_reg(&regname);
+#endif
#ifdef FEAT_CLIPBOARD_PROVIDER
call_clip_provider_request(regname);
#endif
#ifdef FEAT_CLIPBOARD
if (clipmethod != CLIPMETHOD_PROVIDER)
- {
// Adjust register name for "unnamed" in 'clipboard'.
- adjust_clip_reg(&regname);
(void)may_get_selection(regname);
- }
#endif


@@ -2458,18 +2468,18 @@ ex_display(exarg_T *eap)
)
continue; // did not ask for this register

+#ifdef HAVE_CLIPMETHOD
+ adjust_clip_reg(&name);
+#endif
#ifdef FEAT_CLIPBOARD_PROVIDER
call_clip_provider_request(name);
#endif
#ifdef FEAT_CLIPBOARD
if (clipmethod != CLIPMETHOD_PROVIDER)
- {
// Adjust register name for "unnamed" in 'clipboard'.
// When it's a clipboard register, fill it with the current contents
// of the clipboard.
- adjust_clip_reg(&name);
(void)may_get_selection(name);
- }
#endif

if (i == -1)
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index c1a27abba..3da9ee303 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -1100,7 +1100,31 @@ func Test_clipboard_provider_accessed_once()
call assert_equal(0, g:vim_paste_count['*'])

bw!
+
+ new
+ " Test same for changing and deleting text when 'clipboard' is
+ " unnamed/unnamedplus.
+ let g:vim_paste_count = {'*': 0, '+': 0}
+ let g:vim_copy_count = {'*': 0, '+': 0}
+
+ set clipboard=unnamed
+ call setline(1, "testing")
+ normal cw
+
+ call assert_equal(0, g:vim_paste_count['*'])
+ call assert_equal(1, g:vim_copy_count['*'])
+
+ set clipboard=unnamedplus
+ call setline(1, "testing")
+ normal dw
+
+ call assert_equal(0, g:vim_paste_count['+'])
+ call assert_equal(1, g:vim_copy_count['+'])
+
+ bw!
+
set clipmethod&
+ set clipboard&
endfunc

" Test if the copying does not call the paste callback, and pasting does not all
@@ -1194,4 +1218,73 @@ func Test_clipboard_provider_redir_execute()
set clipmethod&
endfunc

+" Test if clipboard provider feature respects the "unnamed" and "unnamedplus"
+" values in the 'clipboard' option
+func Test_clipboard_provider_clipboard_option()
+ CheckFeature clipboard_provider
+
+ let v:clipproviders["test"] = {
+ \ "paste": {
+ \ '+': function("s:Paste"),
+ \ '*': function("s:Paste")
+ \ },
+ \ "copy": {
+ \ '+': function("s:Copy"),
+ \ '*': function("s:Copy")
+ \ }
+ \ }
+ set clipmethod=test
+ let g:vim_paste = "tuple"
+
+ new
+
+ call setline(1, "hello world!")
+
+ set clipboard=unnamed
+
+ yank
+ call assert_equal("*",g:vim_copy.reg)
+ call assert_equal(["hello world!"], g:vim_copy.lines)
+ call assert_equal("V", g:vim_copy.type)
+
+ put
+ call assert_equal(["a", "tuple", "*"], getline(2, 4))
+
+ set clipboard=unnamedplus
+
+ call cursor(1, 0)
+ yank
+ call assert_equal("+",g:vim_copy.reg)
+ call assert_equal(["hello world!"], g:vim_copy.lines)
+ call assert_equal("V", g:vim_copy.type)
+
+ put
+ call assert_equal(["a", "tuple", "+"], getline(2, 4))
+
+ set clipboard=unnamed,unnamedplus
+
+ call setline(1, "testing")
+ call cursor(1, 0)
+ yank
+ call assert_equal(["testing"], g:vim_copy.lines)
+ call assert_equal(["testing"], g:vim_copy.lines)
+
+ " Change and delete operations are tested in
+ " Test_clipboard_provider_accessed_once()
+ bw!
+
+ " Check if only "unnamed" and "unnamedplus" values are allowed when no
+ " +clipboard feature (including cmdline expansion).
+ if !has('clipboard')
+ call assert_fails("set clipboard=autoselect", "E474:")
+
+ call assert_equal(["unnamed,unnamedplus", "unnamed", "unnamedplus"],
+ \ getcompletion('set clipboard=', 'cmdline'))
+ endif
+
+ set clipmethod&
+ set clipboard&
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/util/gen_opt_test.vim b/src/testdir/util/gen_opt_test.vim
index 7c7a0ce47..51ff726d3 100644
--- a/src/testdir/util/gen_opt_test.vim
+++ b/src/testdir/util/gen_opt_test.vim
@@ -370,6 +370,15 @@ let test_values = {
\ 'otherstring': [['', 'xxx'], []],
\}

+if !has('clipboard')
+ " If +clipboard isn't enabled but +clipboard_provider is, then 'clipboard' is
+ " limited to "unnamed" and "unnamedplus"
+ let test_values['clipboard'] = [
+ \ ['', 'unnamed', 'unnamedplus'],
+ \ ['xxx', 'autoselect', 'exclude:\%(']
+ \ ]
+endif
+
" Two lists with values: values that pre- and post-processing in test.
" Clear out t_WS: we don't want to resize the actual terminal.
let test_prepost = {
diff --git a/src/version.c b/src/version.c
index 39b6496e3..c7d4d4732 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1999,
/**/
1998,
/**/
Reply all
Reply to author
Forward
0 new messages