patch 9.1.1857: Missing clipboard provider support

Commit: 
https://github.com/vim/vim/commit/67860efe5b8e5a8d2bf6169ebe3d9143837c55c4
Author: Foxe Chen <[email protected]>
Date:   Tue Oct 14 19:35:17 2025 +0000

    patch 9.1.1857: Missing clipboard provider support
    
    Problem:  Missing clipboard provider support
              (lilydjwg)
    Solution: Add clipboard provider feature
              (Foxe Chen)
    
    fixes: #12419
    closes: #17998
    
    Signed-off-by: Foxe Chen <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index fd88b71a9..7389a86b9 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1,4 +1,4 @@
-*builtin.txt*  For Vim version 9.1.  Last change: 2025 Oct 13
+*builtin.txt*  For Vim version 9.1.  Last change: 2025 Oct 14
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -13061,6 +13061,7 @@ channel                 Compiled with support for 
|channel| and |job|
 cindent                        Compiled with 'cindent' support. (always true)
 clientserver           Compiled with remote invocation support |clientserver|.
 clipboard              Compiled with 'clipboard' support.
+clipboard_provider     Compiled with |clipboard-providers| support
 clipboard_working      Compiled with 'clipboard' support and it can be used.
 cmdline_compl          Compiled with |cmdline-completion| support.
 cmdline_hist           Compiled with |cmdline-history| support.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 62f43912d..39dd397c9 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 Oct 12
+*eval.txt*     For Vim version 9.1.  Last change: 2025 Oct 14
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -38,6 +38,7 @@ a remark is given.
 12. The sandbox                        |eval-sandbox|
 13. Textlock                   |textlock|
 14. Vim script library         |vim-script-library|
+15. Clipboard providers                |clipboard-providers|
 
 Testing support is documented in |testing.txt|.
 Profiling is documented at |profiling|.
@@ -2251,6 +2252,11 @@ v:clipmethod     The current method of accessing the 
clipboard that is being
                                        unavailable.
                See 'clipmethod' for more details.
 
+                                       *v:clipproviders*
+v:clipproviders
+               A dictionary containing clipboard providers, see
+               |clipboard-providers| for more information.
+
                                        *v:cmdarg* *cmdarg-variable*
 v:cmdarg       This variable is used for two purposes:
                1. The extra arguments given to a file read/write command.
@@ -5263,5 +5269,133 @@ Usage: >vim
        :call dist#vim9#Launch(<args>)
        :Launch <app> <args>.
 <
+==============================================================================
+15. Clipboard providers                                        
*clipboard-providers*
+
+When Vim is compiled with the |+clipboard_provider| feature, which requires
+the |+eval| feature, creating custom clipboards is possible.  These providers
+handle the "+" and "*" registers.  Note that on non-Unix or non-VMS systems,
+only the "*" register will be available for use.
+
+To add a provider, add a new entry to the |v:clipproviders| dictionary, in the
+format of: >
+       let v:clipproviders["name"] = {
+            \   "available": function("Available"),
+            \   "paste": {
+            \       '+': function("Paste"), " For the + register
+            \       '*': function("Paste"), " For the * register
+            \   },
+            \   "copy": {
+            \       '+': function("Copy"), " Same thing as above
+            \       '*': function("Copy"),
+            \   },
+            \ }
+
+The key is the provider name, which should be used in 'clipmethod', for
+example in the following example, you would add "name" to 'clipmethod' in
+order to use it. >
+       set clipmethod=name,wayland,x11,gui
+
+Each callback can either be a name of a function in a string, a |Funcref|, or
+a |lambda| expression.
+
+Note that these dictionary entries are optional, for example, if you don't
+care about the "copy" functions, then you can simply exclude them.  When Vim
+yanks/copies something, then simply nothing will be done.
+
+                                               *clipboard-provider-available*
+The "available" callback should return a string, which should contain which
+clipboard registers are available.  For example, if the "+" register is only
+available, then the function would return "+", or if both "+" and "*" are
+available, then return "+*".
+
+                                               *clipboard-provider-paste*
+The "paste" callback takes a first argument which is the register being put
+(string), and a second argument which is the type of access (string).  It
+should return either a tuple/list or string.  If a tuple/list is returned, it
+should have two elements:
+       - The register type conforming to |setreg()|.
+       - A list of strings
+If the register type is an empty string, then the type is automatically
+chosen, see |setreg()|.  If a string is returned, then it can either be "clear"
+or "previous".  "clear" makes Vim clear the register, and "previous" makes Vim
+use the previous register contents (or current depending on how you view it).
+
+The second argument, the access type, can either be "explicit" or "implicit".
+"explicit" means that the user is directly accessing the clipboard, such as
+putting text, or calling |getreg()|;  "implicit" means that the clipboard is
+being accessed indirectly, such when |:registers| is called, or when an
+unrelated operation causes Vim to access the clipboard.
+
+This is useful since some operations in Vim implicity access the clipboard
+indirectly.  For example, if when you want to create a provider for the OSC52
+command (accessing the clipboard via an escape code).  Many terminals show a
+confirmation if you want Vim to access the clipboard.  This can be very
+annoying with the terminal asking for permission everytime you do something
+that accesses the clipboard behind the scenes.  A good way to handle implicit
+access is to return "previous", which leaves the register contents unchanged.
+
+                                               *clipboard-provider-copy*
+The "copy" callback returns nothing, and takes the given arguments in order:
+       - The register being operated on
+       - The register type, conforming to |getregtype()|
+       - A list of strings to copy
+
+The provider can do whatever it wants with the given information.  This
+function is called on every request to change the clipboard register(s).
+
+                                               *clipboard-provider-textlock*
+In both the "paste" and "copy" callbacks, it is not allowed to change the
+buffer text, see |textlock|.
+
+                                               *clipboard-provider-example*
+Here is an example script that uses the clipboard provider feature through the
+OSC52 command: >vim
+
+       func Available()
+         return "+"
+       endfunc
+       
+       func Paste(reg, type)
+         " If implicit access, don't do anything
+         if a:type == "implicit"
+           return "previous"
+         endif
+       
+         augroup OSC
+           autocmd!
+           autocmd TermResponseAll osc ++once call feedkeys("\<F30>", '!')
+         augroup END
+       
+         " Send command
+         call echoraw("\<Esc>]52;c;?\<Esc>\")
+       
+         " Wait until autocmd is triggered
+         while getchar(-1) != "\<F30>"
+         endwhile
+       
+         autocmd! OSC
+       
+         " Extract the base64 stuff
+         let l:stuff = matchstr(v:termosc, '52;c;\zs[A-Za-z0-9+/=]\+')
+       
+         return ("", blob2str(base64_decode(l:stuff)))
+       endfunc
+
+       func Copy(reg, type, lines)
+         call echoraw("\<Esc>]52;c;" ..
+           \ base64_encode(str2blob(a:lines)) .. "\<Esc>\")
+       endfunc
+       let v:clipproviders["myosc"] = {
+           \   "available": function("Available"),
+           \   "paste": {
+           \     '+': function("Paste"),
+           \   },
+           \   "copy": {
+           \     '+': function("Copy"),
+           \   },
+           \ }
+       set clipmethod=myosc
 
+<
  vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index f4fd5ed80..798e50471 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1919,10 +1919,15 @@ A jump table for the options with a short description 
can be found at |Q_op|.
                x11             X11 selections
                gui             GUI specific method
                other           Some other method
+               *               Clipboard provider method
 
        Note: "other" is used on systems without X11/Wayland, such as
        MS-Windows or MacOS, when running Vim without the GUI.
 
+       Note that the name of the clipboard provider should be used when you
+       want to use a clipboard provider.  See |clipboard-providers| for more
+       information.
+
        The option value is a list of comma separated items.  The list is
        parsed left to right in order, and the first method that Vim
        determines is available or is working is used as the actual method for
diff --git a/runtime/doc/tags b/runtime/doc/tags
index a3e862521..787e59ed8 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -1411,6 +1411,7 @@ $quote    eval.txt        /*$quote*
 +cindent       various.txt     /*+cindent*
 +clientserver  various.txt     /*+clientserver*
 +clipboard     various.txt     /*+clipboard*
++clipboard_provider    various.txt     /*+clipboard_provider*
 +clipboard_working     various.txt     /*+clipboard_working*
 +cmd   editing.txt     /*+cmd*
 +cmdline_compl various.txt     /*+cmdline_compl*
@@ -6691,6 +6692,12 @@ clipboard-autoselectml   options.txt     
/*clipboard-autoselectml*
 clipboard-autoselectplus       options.txt     /*clipboard-autoselectplus*
 clipboard-exclude      options.txt     /*clipboard-exclude*
 clipboard-html options.txt     /*clipboard-html*
+clipboard-provider-available   eval.txt        /*clipboard-provider-available*
+clipboard-provider-copy        eval.txt        /*clipboard-provider-copy*
+clipboard-provider-example     eval.txt        /*clipboard-provider-example*
+clipboard-provider-paste       eval.txt        /*clipboard-provider-paste*
+clipboard-provider-textlock    eval.txt        /*clipboard-provider-textlock*
+clipboard-providers    eval.txt        /*clipboard-providers*
 clipboard-unnamed      options.txt     /*clipboard-unnamed*
 clipboard-unnamedplus  options.txt     /*clipboard-unnamedplus*
 clojure-indent indent.txt      /*clojure-indent*
@@ -11254,6 +11261,7 @@ v:char  eval.txt        /*v:char*
 v:charconvert_from     eval.txt        /*v:charconvert_from*
 v:charconvert_to       eval.txt        /*v:charconvert_to*
 v:clipmethod   eval.txt        /*v:clipmethod*
+v:clipproviders        eval.txt        /*v:clipproviders*
 v:cmdarg       eval.txt        /*v:cmdarg*
 v:cmdbang      eval.txt        /*v:cmdbang*
 v:collate      eval.txt        /*v:collate*
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index fa9be58a1..78777eef5 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -1,4 +1,4 @@
-*various.txt*   For Vim version 9.1.  Last change: 2025 Oct 12
+*various.txt*   For Vim version 9.1.  Last change: 2025 Oct 14
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -378,6 +378,7 @@ m  *+channel*               inter process communication 
|channel|
 T  *+cindent*          'cindent', C indenting; Always enabled
 N  *+clientserver*     Unix and Win32: Remote invocation |clientserver|
    *+clipboard*                |clipboard| support compiled-in
+N  *+clipboard_provider*  |clipboard-providers| support compiled-in
    *+clipboard_working*        |clipboard| support compiled-in and working
 T  *+cmdline_compl*    command line completion |cmdline-completion|
 T  *+cmdline_hist*     command line history |cmdline-history|
@@ -807,7 +808,10 @@ K                  Run a program to lookup the keyword 
under the
 :clip[reset]           Attempts to choose a new method for accessing the
                        clipboard, using the 'clipmethod' option.  This is
                        useful when the current method has become unavailable,
-                       and you want to try using another method.
+                       and you want to try using another method.  If the
+                       |+clipboard_provider| feature is being used, this
+                       command should be called after the availability of one
+                       of the clipboard registers changes.
                        {only available when compiled with the |+clipboard|
                        feature}
 
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index ef7762253..b2a1f96b2 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2025 Oct 12
+*version9.txt*  For Vim version 9.1.  Last change: 2025 Oct 14
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41653,6 +41653,8 @@ Other new features ~
 
 - |items()| function now supports Blob.
 
+- |clipboard-providers| support.
+
                                                        *changed-9.2*
 Changed~
 -------
@@ -41900,13 +41902,29 @@ Options: ~
                        compositor
 
 Vim Variables: ~
+|v:clipmethod|         The current 'clipmethod'.
+|v:clipproviders|      A dictionary containing clipboard providers
+                       information.
+|v:stacktrace|         The most recent caught exception.
+|v:t_enumvalue|                Value of |enumvalue|.
+|v:t_enum|             Value of |enum| type.
+|v:t_tuple|            Value of |Tuple| type.
 |v:termda1|            The escape sequence returned for the primary device
                        attribute query (DA1).
+|v:termosc|            The most recent received OSC response.
+|v:wayland_display|    The name of the Wayland display Vim is connected to.
 
 Vim Arguments: ~
 |-Y|                   Do not connect to the |wayland| compositor.
 |--clientserver|       Specify backend for clientserver functionality.
 
+Configure Switches: ~
+--with-wayland                 Enable the |wayland| feature.
+--enable-wayland-focus-steal   Enable the |wayland-focus-steal| feature.
+--enable-socketserver          Enable the |socketserver-clientserver|
+                               feature.
+--enable-clipboard-provider    Enable the |clipboard-providers| feature.
+
 
 ==============================================================================
 INCOMPATIBLE CHANGES                                   *incompatible-9.2*
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 89940ab30..bd2458f5b 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -2,7 +2,7 @@
 " Language:       Vim script
 " Maintainer:     Hirohito Higashi <h.east.727 ATMARK gmail.com>
 "         Doug Kearns <[email protected]>
-" Last Change:    2025 Oct 11
+" Last Change:    2025 Oct 14
 " Former Maintainer: Charles E. Campbell
 
 " DO NOT CHANGE DIRECTLY.
@@ -166,7 +166,7 @@ syn keyword vimFuncName contained win_execute win_findbuf 
win_getid win_gettype
 " Predefined variable names {{{2
 " GEN_SYN_VIM: vimVarName, START_STR='syn keyword vimVimVarName contained', 
END_STR=''
 syn keyword vimVimVarName contained count count1 prevcount errmsg warningmsg 
statusmsg shell_error this_session version lnum termresponse fname lang lc_time 
ctype charconvert_from charconvert_to fname_in fname_out fname_new fname_diff 
cmdarg foldstart foldend folddashes foldlevel progname servername dying 
exception throwpoint register cmdbang insertmode val key profiling fcs_reason 
fcs_choice beval_bufnr beval_winnr beval_winid beval_lnum beval_col beval_text 
scrollstart swapname swapchoice swapcommand char mouse_win mouse_winid 
mouse_lnum mouse_col operator searchforward hlsearch oldfiles windowid progpath 
completed_item option_new option_old option_oldlocal option_oldglobal 
option_command option_type errors false true none null numbermax numbermin 
numbersize
-syn keyword vimVimVarName contained vim_did_enter testing t_number t_string 
t_func t_list t_dict t_float t_bool t_none t_job t_channel t_blob t_class 
t_object termrfgresp termrbgresp termu7resp termstyleresp termblinkresp event 
versionlong echospace argv collate exiting colornames sizeofint sizeoflong 
sizeofpointer maxcol python3_version t_typealias t_enum t_enumvalue stacktrace 
t_tuple wayland_display clipmethod termda1 termosc
+syn keyword vimVimVarName contained vim_did_enter testing t_number t_string 
t_func t_list t_dict t_float t_bool t_none t_job t_channel t_blob t_class 
t_object termrfgresp termrbgresp termu7resp termstyleresp termblinkresp event 
versionlong echospace argv collate exiting colornames sizeofint sizeoflong 
sizeofpointer maxcol python3_version t_typealias t_enum t_enumvalue stacktrace 
t_tuple wayland_display clipmethod termda1 termosc clipproviders
 
 "--- syntax here and above generated by 
runtime/syntax/generator/gen_syntax_vim.vim ---
 
diff --git a/src/auto/configure b/src/auto/configure
index 7cf35d66d..525584d1d 100755
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -857,6 +857,7 @@ enable_arabic
 enable_farsi
 enable_xim
 enable_fontset
+enable_clipboard_provider
 with_wayland
 enable_wayland_focus_steal
 with_x
@@ -1539,6 +1540,7 @@ Optional Features:
   --disable-farsi         Deprecated.
   --enable-xim            Include XIM input support.
   --enable-fontset        Include X fontset output support.
+  --enable-clipboard-provider  Include clipboard provider support.
   --enable-wayland-focus-steal
                           Include focus stealing support for Wayland
                           clipboard.
@@ -9208,6 +9210,35 @@ fi
 { printf "%s
" "$as_me:${as_lineno-$LINENO}: result: $enable_fontset" >&5
 printf "%s
" "$enable_fontset" >&6; }
 
+{ printf "%s
" "$as_me:${as_lineno-$LINENO}: checking --enable-clipboard-provider" >&5
+printf %s "checking --enable-clipboard-provider... " >&6; }
+# Check whether --enable-clipboard-provider was given.
+if test ${enable_clipboard_provider+y}
+then :
+  enableval=$enable_clipboard_provider; enable_clipboard_provider=$enableval
+        { printf "%s
" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
+printf "%s
" "$enableval" >&6; }
+else case e in #(
+  e) if test "x$features" = xtiny
+then :
+  enable_clipboard_provider="no"
+                        { printf "%s
" "$as_me:${as_lineno-$LINENO}: result: cannot use clipboard provider with tiny 
features" >&5
+printf "%s
" "cannot use clipboard provider with tiny features" >&6; }
+else case e in #(
+  e) enable_clipboard_provider="yes"
+                        { printf "%s
" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s
" "yes" >&6; } ;;
+esac
+fi ;;
+esac
+fi
+
+if test "$enable_clipboard_provider" = "yes"; then
+  printf "%s
" "#define FEAT_CLIPBOARD_PROVIDER 1" >>confdefs.h
+
+fi
+
+
 { printf "%s
" "$as_me:${as_lineno-$LINENO}: checking if shm_open is available" >&5
 printf %s "checking if shm_open is available... " >&6; }
 cppflags_save=$CPPFLAGS
diff --git a/src/clipboard.c b/src/clipboard.c
index 232566d7d..736682b23 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -134,6 +134,12 @@ static bool clip_wl_owner_exists(Clipboard_T *cbd);
 
 #endif // FEAT_WAYLAND_CLIPBOARD
 
+#ifdef FEAT_CLIPBOARD_PROVIDER
+static int clip_provider_is_available(Clipboard_T *cbd, char_u *provider);
+static void clip_provider_set_selection(Clipboard_T *cbd, char_u *provider);
+static void clip_provider_request_selection(Clipboard_T *cbd, char_u 
*provider);
+#endif
+
 /*
  * Selection stuff using Visual mode, for cutting and pasting text to other
  * windows.
@@ -254,7 +260,7 @@ clip_gen_own_selection(Clipboard_T *cbd UNUSED)
     }
     else if (clipmethod == CLIPMETHOD_OTHER)
     {
-#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
+#ifndef UNIX
        return clip_mch_own_selection(cbd);
 #endif
     }
@@ -321,7 +327,7 @@ clip_gen_lose_selection(Clipboard_T *cbd UNUSED)
     }
     else if (clipmethod == CLIPMETHOD_OTHER)
     {
-#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
+#ifndef UNIX
        clip_mch_lose_selection(cbd);
 #endif
     }
@@ -1354,7 +1360,7 @@ clip_gen_set_selection(Clipboard_T *cbd)
     {
 #ifdef FEAT_GUI
        if (gui.in_use)
-       clip_mch_set_selection(cbd);
+           clip_mch_set_selection(cbd);
 #endif
     }
     else if (clipmethod == CLIPMETHOD_WAYLAND)
@@ -1371,8 +1377,14 @@ clip_gen_set_selection(Clipboard_T *cbd)
     }
     else if (clipmethod == CLIPMETHOD_OTHER)
     {
-#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
+#ifndef UNIX
        clip_mch_set_selection(cbd);
+#endif
+    }
+    else if (clipmethod == CLIPMETHOD_PROVIDER)
+    {
+#ifdef FEAT_CLIPBOARD_PROVIDER
+       clip_provider_set_selection(cbd, clipprovider_name);
 #endif
     }
 }
@@ -1401,8 +1413,14 @@ clip_gen_request_selection(Clipboard_T *cbd UNUSED)
     }
     else if (clipmethod == CLIPMETHOD_OTHER)
     {
-#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
+#ifndef UNIX
        clip_mch_request_selection(cbd);
+#endif
+    }
+    else if (clipmethod == CLIPMETHOD_PROVIDER)
+    {
+#ifdef FEAT_CLIPBOARD_PROVIDER
+       clip_provider_request_selection(cbd, clipprovider_name);
 #endif
     }
 }
@@ -2266,10 +2284,18 @@ clip_get_selection(Clipboard_T *cbd)
     }
     else if (!is_clipboard_needs_update())
     {
-       clip_free_selection(cbd);
+#ifdef FEAT_CLIPBOARD_PROVIDER
+       // We will choose if we want to the free the selection if using provider
+       if (clipmethod != CLIPMETHOD_PROVIDER)
+           clip_free_selection(cbd);
+#endif
 
        // Try to get selected text from another window
        clip_gen_request_selection(cbd);
+#ifdef FEAT_CLIPBOARD_PROVIDER
+       if (clipmethod == CLIPMETHOD_PROVIDER)
+           clip_access_type = CLIP_ACCESS_IMPLICIT;
+#endif
     }
 }
 
@@ -3507,15 +3533,34 @@ get_clipmethod(char_u *str, bool *regular, bool 
*primary)
        }
        else if (STRCMP(buf, "other") == 0)
        {
-#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD)
+#ifndef UNIX
                method = CLIPMETHOD_OTHER;
                *regular = *primary = true;
 #endif
        }
        else
        {
-           ret = CLIPMETHOD_FAIL;
-           goto exit;
+#ifdef FEAT_CLIPBOARD_PROVIDER
+           // Check if it is the name of a provider
+           int reg = clip_provider_is_available(&clip_plus, buf);
+           int pri = clip_provider_is_available(&clip_star, buf);
+
+           if (reg == 1 || pri == 1)
+           {
+               method = CLIPMETHOD_PROVIDER;
+
+               vim_free(clipprovider_name);
+               clipprovider_name = vim_strsave(buf);
+
+               *regular = reg == 1;
+               *primary = pri == 1;
+           }
+           else if (reg == -1)
+#endif
+           {
+               ret = CLIPMETHOD_FAIL;
+               goto exit;
+           }
        }
 
        // Keep on going in order to catch errors
@@ -3548,6 +3593,15 @@ clipmethod_to_str(clipmethod_T method)
            return (char_u *)"gui";
        case CLIPMETHOD_OTHER:
            return (char_u *)"other";
+       case CLIPMETHOD_PROVIDER:
+#ifdef FEAT_CLIPBOARD_PROVIDER
+           if (clipprovider_name == NULL)
+               return (char_u *)"none";
+           else
+               return clipprovider_name;
+#else
+           return (char_u *)"none";
+#endif
        default:
            return (char_u *)"none";
     }
@@ -3584,16 +3638,26 @@ choose_clipmethod(void)
        clip_plus.did_warn = false;
        clip_star.did_warn = false;
     }
-    // Disown clipboard if we are switching to a new method
-    else if (clipmethod != CLIPMETHOD_NONE && method != clipmethod)
+    else if ((clipmethod != CLIPMETHOD_NONE && method != clipmethod))
     {
+       // Disown clipboard if we are switching to a new method
        if (clip_star.owned)
            clip_lose_selection(&clip_star);
        if (clip_plus.owned)
            clip_lose_selection(&clip_plus);
+
        clip_init_single(&clip_plus, regular);
        clip_init_single(&clip_star, primary);
     }
+    else
+    {
+       // If availability of a clipboard changed, then update the clipboard
+       // structure.
+       if (regular != clip_plus.available)
+           clip_init_single(&clip_plus, regular);
+       if (primary != clip_star.available)
+           clip_init_single(&clip_star, primary);
+    }
 
     clipmethod = method;
 
@@ -3621,4 +3685,321 @@ ex_clipreset(exarg_T *eap UNUSED)
                clipmethod_to_str(clipmethod));
 }
 
+#ifdef FEAT_CLIPBOARD_PROVIDER
+
+/*
+ * Check if a clipboard provider with given name exists and is available for 
the
+ * given clipboard. Returns 1 if the provider exists and the 'available'
+ * function returned true, 0 if the provider exists but the function returned
+ * false, and -1 on error.
+ */
+    static int
+clip_provider_is_available(Clipboard_T *cbd, char_u *provider)
+{
+    dict_T     *providers = get_vim_var_dict(VV_CLIPPROVIDERS);
+    typval_T   provider_tv = {0};
+    callback_T callback = {0};
+    typval_T   rettv = {0};
+    typval_T   func_tv = {0};
+    char_u     *avail;
+    int                res = 0;
+
+    if (dict_get_tv(providers, (char *)provider, &provider_tv) == FAIL
+           || provider_tv.v_type != VAR_DICT)
+       return -1;
+
+    if (dict_get_tv(provider_tv.vval.v_dict, "available", &func_tv) == FAIL)
+    {
+       clear_tv(&provider_tv);
+       // If "available" functon not specified assume always TRUE
+       return 1;
+    }
+
+    if ((callback = get_callback(&func_tv)).cb_name == NULL)
+       goto fail;
+
+    if (call_callback(&callback, -1, &rettv, 0, NULL) == FAIL ||
+           rettv.v_type != VAR_STRING)
+       goto fail;
+
+    avail = rettv.vval.v_string;
+
+    if ((vim_strchr(avail, '+') != NULL && cbd == &clip_plus)
+           || (vim_strchr(avail, '*') != NULL && cbd == &clip_star))
+       res = 1;
+
+    if (FALSE)
+fail:
+       res = -1;
+
+    free_callback(&callback);
+    clear_tv(&func_tv);
+    clear_tv(&rettv);
+    clear_tv(&provider_tv);
+
+    return res;
+}
+
+/*
+ * Get the specified callback "function" from the provider dictionary of for
+ * register "reg".
+ */
+    static int
+clip_provider_get_callback(
+       char_u *reg,
+       char_u *provider,
+       char_u *function,
+       callback_T *callback)
+{
+    dict_T     *providers = get_vim_var_dict(VV_CLIPPROVIDERS);
+    typval_T   provider_tv;
+    typval_T   action_tv;
+    typval_T   func_tv;
+    callback_T cb;
+
+    if (dict_get_tv(providers, (char *)provider, &provider_tv) == FAIL)
+       return FAIL;
+    else if (provider_tv.v_type != VAR_DICT)
+    {
+       clear_tv(&provider_tv);
+       return FAIL;
+    }
+    else if (dict_get_tv(
+               provider_tv.vval.v_dict,
+               (char *)function,
+               &action_tv) == FAIL)
+    {
+       clear_tv(&provider_tv);
+       return FAIL;
+    }
+    else if (action_tv.v_type != VAR_DICT)
+    {
+       clear_tv(&provider_tv);
+       clear_tv(&action_tv);
+       return FAIL;
+    }
+    else if (dict_get_tv(action_tv.vval.v_dict, (char *)reg, &func_tv) == FAIL)
+    {
+       clear_tv(&provider_tv);
+       clear_tv(&action_tv);
+       return FAIL;
+    }
+    else if ((cb = get_callback(&func_tv)).cb_name == NULL)
+    {
+       clear_tv(&provider_tv);
+       clear_tv(&action_tv);
+       clear_tv(&func_tv);
+       return FAIL;
+    }
+    clear_tv(&provider_tv);
+    clear_tv(&action_tv);
+
+    // func_tv owns the function name, so we must make a copy for the callback
+    set_callback(callback, &cb);
+    free_callback(&cb);
+    clear_tv(&func_tv);
+    return OK;
+}
+
+    static void
+clip_provider_set_selection(Clipboard_T *cbd, char_u *provider)
+{
+    char_u     *reg = (char_u *)(cbd == &clip_star ? "*" : "+");
+    callback_T callback;
+    typval_T   rettv;
+    typval_T   argvars[4];
+    yankreg_T  *y_ptr;
+    char_u     type[2 + NUMBUFLEN] = {0};
+    list_T     *list = NULL;
+
+    if (clip_provider_get_callback(
+               reg,
+               provider,
+               (char_u *)"copy",
+               &callback) == FAIL)
+       return;
+
+    // Possibly get selected text, if using autoselect for 'clipboard'
+    cbd->owned = TRUE;
+    clip_get_selection(cbd);
+    cbd->owned = FALSE;
+
+    // Convert register type into a string
+    if (cbd == &clip_plus)
+       y_ptr = get_y_register(PLUS_REGISTER);
+    else
+       y_ptr = get_y_register(STAR_REGISTER);
+
+    switch (y_ptr->y_type)
+    {
+       case MCHAR:
+           type[0] = 'v';
+           break;
+       case MLINE:
+           type[0] = 'V';
+           break;
+       case MBLOCK:
+           sprintf((char *)type, "%c%d", Ctrl_V, y_ptr->y_width + 1);
+           break;
+       default:
+           type[0] = 0;
+           break;
+    }
+
+    argvars[0].v_type = VAR_STRING;
+    argvars[0].vval.v_string = reg;
+
+    argvars[1].v_type = VAR_STRING;
+    argvars[1].vval.v_string = type;
+
+    // Get register contents by creating a list of lines
+    list = list_alloc();
+
+    if (list == NULL)
+    {
+       free_callback(&callback);
+       return;
+    }
+
+    for (int i = 0; i < y_ptr->y_size; i++)
+       if (list_append_string(list, y_ptr->y_array[i].string, -1) == FAIL)
+       {
+           free_callback(&callback);
+           list_unref(list);
+           return;
+       }
+
+    list->lv_refcount++;
+
+    argvars[2].v_type = VAR_LIST;
+    argvars[2].v_lock = VAR_FIXED;
+    argvars[2].vval.v_list = list;
+
+    argvars[3].v_type = VAR_UNKNOWN;
+
+    textlock++;
+    call_callback(&callback, -1, &rettv, 3, argvars);
+    clear_tv(&rettv);
+    textlock--;
+
+    free_callback(&callback);
+    list_unref(list);
+}
+
+    static void
+clip_provider_request_selection(Clipboard_T *cbd, char_u *provider)
+{
+    char_u     *reg = (char_u *)(cbd == &clip_star ? "*" : "+");
+    callback_T callback;
+    typval_T   argvars[3];
+    typval_T   rettv;
+    int                ret;
+    char_u     *reg_type;
+    list_T     *lines;
+
+    if (clip_provider_get_callback(
+               reg,
+               provider,
+               (char_u *)"paste",
+               &callback) == FAIL)
+       return;
+
+    argvars[0].v_type = VAR_STRING;
+    argvars[0].vval.v_string = reg;
+
+    argvars[1].v_type = VAR_STRING;
+    argvars[1].vval.v_string = (char_u *)
+       (clip_access_type == CLIP_ACCESS_EXPLICIT ? "explicit" : "implicit");
+
+    argvars[2].v_type = VAR_UNKNOWN;
+
+    textlock++;
+    ret = call_callback(&callback, -1, &rettv, 2, argvars);
+    textlock--;
+
+    if (ret == FAIL)
+       goto exit;
+    else if (rettv.v_type == VAR_STRING
+           && STRCMP(rettv.vval.v_string, "clear") == 0)
+    {
+       clip_free_selection(cbd);
+       goto exit;
+    }
+    else if (rettv.v_type == VAR_STRING
+           && STRCMP(rettv.vval.v_string, "previous") == 0)
+       goto exit;
+    else if (rettv.v_type == VAR_TUPLE
+           && TUPLE_LEN(rettv.vval.v_tuple) == 2
+           && TUPLE_ITEM(rettv.vval.v_tuple, 0)->v_type == VAR_STRING
+           && TUPLE_ITEM(rettv.vval.v_tuple, 1)->v_type == VAR_LIST)
+    {
+       reg_type = TUPLE_ITEM(rettv.vval.v_tuple, 0)->vval.v_string;
+       lines = TUPLE_ITEM(rettv.vval.v_tuple, 1)->vval.v_list;
+    }
+    else if (rettv.v_type == VAR_LIST
+           && rettv.vval.v_list->lv_len == 2
+           && rettv.vval.v_list->lv_first->li_tv.v_type == VAR_STRING
+           && rettv.vval.v_list->lv_first->li_next->li_tv.v_type == VAR_LIST)
+    {
+       reg_type = rettv.vval.v_list->lv_first->li_tv.vval.v_string;
+       lines = rettv.vval.v_list->lv_first->li_next->li_tv.vval.v_list;
+    }
+    else
+       goto exit;
+
+    {
+       char_u      yank_type = MAUTO;
+       long        block_len = -1;
+       yankreg_T   *y_ptr;
+       char_u      **contents;
+       listitem_T  *li;
+       int         i = 0;
+
+       contents = ALLOC_MULT(char_u *, lines->lv_len + 1); // Ends with a NULL
+
+       if (contents == NULL)
+           goto exit;
+
+       // Convert strings in list to type char_u **
+       FOR_ALL_LIST_ITEMS(lines, li)
+       {
+           char_u *str = tv_get_string_chk(&li->li_tv);
+
+           if (str == NULL)
+               goto exit;
+
+           contents[i++] = vim_strsave(str);
+       }
+       contents[i] = NULL;
+
+       if (STRLEN(reg_type) > 0
+               && get_yank_type(&reg_type, &yank_type, &block_len) == FAIL)
+           goto exit;
+
+       if (cbd == &clip_plus)
+           y_ptr = get_y_register(PLUS_REGISTER);
+       else
+           y_ptr = get_y_register(STAR_REGISTER);
+
+       clip_free_selection(cbd);
+
+       str_to_reg(y_ptr,
+               yank_type,
+               (char_u *)contents,
+               STRLEN(contents),
+               block_len,
+               TRUE);
+
+       for (int k = 0; k < i; k++)
+           vim_free(contents[k]);
+       vim_free(contents);
+    }
+
+exit:
+    free_callback(&callback);
+    clear_tv(&rettv);
+}
+
+#endif // FEAT_CLIPBOARD_PROVIDER
+
 #endif // FEAT_CLIPBOARD
diff --git a/src/config.h.in b/src/config.h.in
index 983f186b8..eb0937d39 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -528,3 +528,6 @@
 
 /* Define if you want to load libgpm dynamically */
 #undef DYNAMIC_GPM
+
+/* Define if you want to have clipboard provider functionality*/
+#undef FEAT_CLIPBOARD_PROVIDER
diff --git a/src/configure.ac b/src/configure.ac
index fa6757d69..635b5f722 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -2434,6 +2434,21 @@ AC_ARG_ENABLE(fontset,
 AC_MSG_RESULT($enable_fontset)
 dnl defining FEAT_XFONTSET is delayed, so that it can be disabled for no GUI
 
+AC_MSG_CHECKING(--enable-clipboard-provider)
+AC_ARG_ENABLE(clipboard-provider,
+       [  --enable-clipboard-provider  Include clipboard provider support.],
+       [enable_clipboard_provider=$enableval
+        AC_MSG_RESULT($enableval)],
+       AS_IF([test "x$features" = xtiny], 
+                       [enable_clipboard_provider="no"
+                        AC_MSG_RESULT([cannot use clipboard provider with tiny 
features])],
+                       [enable_clipboard_provider="yes"
+                        AC_MSG_RESULT([yes])]))
+if test "$enable_clipboard_provider" = "yes"; then
+  AC_DEFINE(FEAT_CLIPBOARD_PROVIDER)
+fi
+
+
 AC_MSG_CHECKING(if shm_open is available)
 cppflags_save=$CPPFLAGS
 CPPFLAGS="$CPPFLAGS $X_CFLAGS"
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 7c3139edc..e2e9bcbef 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -6500,6 +6500,11 @@ f_getreg(typval_T *argvars, typval_T *rettv)
            return;
     }
 
+#ifdef FEAT_CLIPBOARD_PROVIDER
+    if (clipmethod == CLIPMETHOD_PROVIDER)
+       clip_access_type = CLIP_ACCESS_EXPLICIT;
+#endif
+
     if (return_list)
     {
        rettv->v_type = VAR_LIST;
@@ -6866,6 +6871,13 @@ f_has(typval_T *argvars, typval_T *rettv)
                1
 #else
                0
+#endif
+               },
+       {"clipboard_provider",
+#ifdef FEAT_CLIPBOARD_PROVIDER
+               1
+#else
+               0
 #endif
                },
        {"cmdline_compl", 1},
@@ -11493,7 +11505,7 @@ f_setpos(typval_T *argvars, typval_T *rettv)
 /*
  * Translate a register type string to the yank type and block length
  */
-    static int
+    int
 get_yank_type(char_u **pp, char_u *yank_type, long *block_len)
 {
     char_u *stropt = *pp;
diff --git a/src/evalvars.c b/src/evalvars.c
index c840d872b..1bf41e85c 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -166,7 +166,8 @@ static struct vimvar
     {VV_NAME("wayland_display",  VAR_STRING), NULL, VV_RO},
     {VV_NAME("clipmethod",      VAR_STRING), NULL, VV_RO},
     {VV_NAME("termda1",                 VAR_STRING), NULL, VV_RO},
-    {VV_NAME("termosc",         VAR_STRING), NULL, VV_RO},
+    {VV_NAME("termosc",                 VAR_STRING), NULL, VV_RO},
+    {VV_NAME("clipproviders",   VAR_DICT), &t_dict_string, VV_RO}
 };
 
 // shorthand
diff --git a/src/feature.h b/src/feature.h
index 11700a060..6860cbd98 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -905,6 +905,19 @@
 # define FEAT_CLIPBOARD
 #endif
 
+/*
+ * +clipboard_provider Allow Vim to use clipboard providers
+ */
+#if defined(FEAT_CLIPBOARD_PROVIDER)
+# ifndef FEAT_EVAL
+#  undef FEAT_CLIPBOARD_PROVIDER
+# else
+#  ifndef FEAT_CLIPBOARD
+#   define FEAT_CLIPBOARD
+#  endif
+# endif
+#endif
+
 #ifdef FEAT_GUI
 # ifndef FEAT_CLIPBOARD
 #  define FEAT_CLIPBOARD
diff --git a/src/globals.h b/src/globals.h
index 6eba836d4..0a705ef25 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -972,7 +972,8 @@ EXTERN int  gui_win_y INIT(= -1);
 
 #ifdef FEAT_CLIPBOARD
 EXTERN Clipboard_T clip_star;  // PRIMARY selection in X11/Wayland
-# if defined(FEAT_X11) || defined(FEAT_WAYLAND_CLIPBOARD)
+# if defined(FEAT_X11) || defined(FEAT_WAYLAND_CLIPBOARD) \
+    || ((defined(UNIX) || defined(VMS)) && defined(FEAT_CLIPBOARD_PROVIDER))
 EXTERN Clipboard_T clip_plus;  // CLIPBOARD selection in X11/Wayland
 # else
 #  define clip_plus clip_star  // there is only one clipboard
@@ -2067,6 +2068,9 @@ EXTERN int        p_tgc_set INIT(= FALSE);
 
 #ifdef FEAT_CLIPBOARD
 EXTERN clipmethod_T clipmethod INIT(= CLIPMETHOD_NONE);
+# ifdef FEAT_CLIPBOARD_PROVIDER
+EXTERN char_u *clipprovider_name INIT(= NULL);
+# endif
 #endif
 
 #ifdef FEAT_WAYLAND
@@ -2116,3 +2120,16 @@ INIT(= CLIENTSERVER_METHOD_NONE);
 // Path to socket of last client that communicated with us
 EXTERN char_u *client_socket INIT(= NULL);
 #endif
+
+#ifdef FEAT_CLIPBOARD_PROVIDER
+typedef enum
+{
+    CLIP_ACCESS_IMPLICIT,
+    CLIP_ACCESS_EXPLICIT,
+} clip_access_T;
+
+// Only relevant for the clipboard provider feature. This indicates if the
+// clipboard request is implicit (ex. access when doing :registers),
+// explicit (ex. typing "+p). Always defaults to implicit.
+EXTERN clip_access_T clip_access_type INIT(= CLIP_ACCESS_IMPLICIT);
+#endif
diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro
index 627af17a8..dad8c6771 100644
--- a/src/proto/evalfunc.pro
+++ b/src/proto/evalfunc.pro
@@ -28,4 +28,5 @@ void f_len(typval_T *argvars, typval_T *rettv);
 void mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv);
 void range_list_materialize(list_T *list);
 long do_searchpair(char_u *spat, char_u *mpat, char_u *epat, int dir, typval_T 
*skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit);
+int get_yank_type(char_u **pp, char_u *yank_type, long *block_len);
 /* vim: set ft=c : */
diff --git a/src/register.c b/src/register.c
index 1b3f60ec5..8d0ed7ace 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1559,6 +1559,10 @@ do_put(
 #ifdef FEAT_CLIPBOARD
     // Adjust register name for "unnamed" in 'clipboard'.
     adjust_clip_reg(&regname);
+# ifdef FEAT_CLIPBOARD_PROVIDER
+    if (clipmethod == CLIPMETHOD_PROVIDER)
+       clip_access_type = CLIP_ACCESS_EXPLICIT;
+# endif
     (void)may_get_selection(regname);
 #endif
 
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 0d4aeb043..61ce33a0a 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -105,6 +105,7 @@ NEW_TESTS = \
        test_cjk_linebreak \
        test_clientserver \
        test_clipmethod \
+       test_clipboard_provider \
        test_close_count \
        test_cmd_lists \
        test_cmdline \
@@ -395,6 +396,7 @@ NEW_TESTS_RES = \
        test_cjk_linebreak.res \
        test_clientserver.res \
        test_clipmethod.res \
+       test_clipboard_provider.res \
        test_close_count.res \
        test_cmd_lists.res \
        test_cmdline.res \
diff --git a/src/testdir/test_clipboard_provider.vim 
b/src/testdir/test_clipboard_provider.vim
new file mode 100644
index 000000000..8cc55c3e3
--- /dev/null
+++ b/src/testdir/test_clipboard_provider.vim
@@ -0,0 +1,170 @@
+" Test for clipboard provider feature
+
+CheckFeature clipboard_provider
+
+func! AvailableBoth()
+    return "+*"
+endfunc
+
+func! AvailablePlus()
+    return "+"
+endfunc
+
+func! PasteList(reg, type)
+    return ["c", ["list"]]
+endfunc
+
+func! PasteTuple(reg, type)
+    return ("", ["tuple", "of", "strings"])
+endfunc
+
+func! PasteType(reg, type)
+    let g:vim_test_type = a:type
+    return ("c", [a:type])
+endfunc
+
+func! PasteRegType(reg, type)
+    return (g:vim_test_reg_type, ["7 chars"])
+endfunc
+
+func! Copy(reg, type, lines)
+    let g:vim_test_stuff = {
+                \ "type": a:type,
+                \ "lines": a:lines
+                \ }
+endfunc
+
+" Test if "available" function works properly for provider
+func Test_clipboard_provider_available()
+    CheckUnix
+    let v:clipproviders["test"] = {
+                \ "available": function("AvailablePlus"),
+                \ "paste": {
+                \       '+': function("PasteList"),
+                \       '*': function("PasteList")
+                \   }
+                \ }
+
+    set clipmethod=test
+    call assert_equal("test", v:clipmethod)
+
+    call assert_equal("list", getreg("+"))
+    " Test if star register is unavailable
+    call assert_equal("", getreg("*"))
+
+    let v:clipproviders["test"] = {
+                \ "available": function("AvailableBoth"),
+                \ "paste": {
+                \       '+': function("PasteList"),
+                \       '*': function("PasteList")
+                \   }
+                \ }
+
+    clipreset
+
+    call assert_equal("list", getreg("+"))
+    call assert_equal("list", getreg("*"))
+
+    let v:clipproviders["test"] = {
+                \ "paste": {
+                \       '+': function("PasteList"),
+                \       '*': function("PasteList")
+                \   }
+                \ }
+
+    " Should default to TRUE
+    call assert_equal("list", getreg("+"))
+    call assert_equal("list", getreg("*"))
+
+    set clipmethod&
+endfunc
+
+" Test if "paste" functions work properly for provider
+func Test_clipboard_provider_paste()
+    " Test if tuples and lists work the same
+    let v:clipproviders["test"] = {
+                \ "paste": {
+                \       '*': function("PasteList")
+                \   }
+                \ }
+
+    set clipmethod=test
+    call assert_equal("test", v:clipmethod)
+
+    call assert_equal("list", getreg("*"))
+
+    let v:clipproviders["test"] = {
+                \ "paste": {
+                \       '*': function("PasteTuple")
+                \   }
+                \ }
+
+    call assert_equal("tuple
of
strings
", getreg("*"))
+
+    " Test if "implicit" and "explicit" arguments are correctly used
+    let v:clipproviders["test"] = {
+                \ "paste": {
+                \       '*': function("PasteType")
+                \   }
+                \ }
+
+    call assert_equal("explicit", getreg("*"))
+
+    :registers
+
+    call assert_equal("implicit", g:vim_test_type)
+    unlet g:vim_test_type
+
+    " Test if correct register type is used
+    let v:clipproviders["test"] = {
+                \ "paste": {
+                \       '*': function("PasteRegType")
+                \   }
+                \ }
+
+    let g:vim_test_reg_type = "v"
+    call assert_equal("v", getregtype("*"))
+    let g:vim_test_reg_type = "c"
+    call assert_equal("v", getregtype("*"))
+
+    let g:vim_test_reg_type = "l"
+    call assert_equal("V", getregtype("*"))
+    let g:vim_test_reg_type = "l"
+    call assert_equal("V", getregtype("*"))
+
+    let g:vim_test_reg_type = "b"
+    call assert_equal(" 7", getregtype("*"))
+    let g:vim_test_reg_type = " "
+    call assert_equal(" 7", getregtype("*"))
+
+    let g:vim_test_reg_type = "b40"
+    call assert_equal(" 40", getregtype("*"))
+
+    set clipmethod&
+endfunc
+
+" Test if "copy" functions work properly for provider
+func Test_clipboard_provider_copy()
+    let v:clipproviders["test"] = {
+                \ "copy": {
+                \       '*': function("Copy")
+                \   }
+                \ }
+
+    set clipmethod=test
+    call assert_equal("test", v:clipmethod)
+
+    call setreg("*", ["hello", "world", "!"], "c")
+    call assert_equal(["hello", "world", "!"], g:vim_test_stuff.lines)
+    call assert_equal("v", g:vim_test_stuff.type)
+
+    call setreg("*", ["hello", "world", "!"], "l")
+    call assert_equal(["hello", "world", "!"], g:vim_test_stuff.lines)
+    call assert_equal("V", g:vim_test_stuff.type)
+
+    call setreg("*", ["hello", "world", "!"], "b40")
+    call assert_equal(["hello", "world", "!"], g:vim_test_stuff.lines)
+    call assert_equal(" 40", g:vim_test_stuff.type)
+
+    set clipmethod&
+endfunc
diff --git a/src/version.c b/src/version.c
index 6e8ea1bdf..bf98e2d61 100644
--- a/src/version.c
+++ b/src/version.c
@@ -155,6 +155,11 @@ static char *(features[]) =
        "+clipboard",
 #else
        "-clipboard",
+#endif
+#ifdef FEAT_CLIPBOARD_PROVIDER
+       "+clipboard_provider",
+#else
+       "-clipboard_provider",
 #endif
        "+cmdline_compl",
        "+cmdline_hist",
@@ -729,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1857,
 /**/
     1856,
 /**/
diff --git a/src/vim.h b/src/vim.h
index 69be64270..6c35fe1ef 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2256,7 +2256,8 @@ typedef int sock_T;
 #define VV_CLIPMETHOD 113
 #define VV_TERMDA1 114
 #define VV_TERMOSC 115
-#define VV_LEN         116     // number of v: vars
+#define VV_CLIPPROVIDERS 116
+#define VV_LEN         117     // number of v: vars
 
 // used for v_number in VAR_BOOL and VAR_SPECIAL
 #define VVAL_FALSE     0L      // VAR_BOOL
@@ -2318,6 +2319,7 @@ typedef enum {
     CLIPMETHOD_X11,
     CLIPMETHOD_GUI,
     CLIPMETHOD_OTHER,
+    CLIPMETHOD_PROVIDER
 } clipmethod_T;
 
 // Info about selected text

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1v8kxG-00EoDj-KE%40256bit.org.

Raspunde prin e-mail lui