From: Foxe Chen Date: Thu, 18 Dec 2025 20:47:34 +0000 (+0100) Subject: patch 9.1.1999: clipboard provider does not respect 'clipboard' option X-Git-Tag: v9.1.1999^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96ce55331f5920653b7fa5346a0765d8c0050002;p=thirdparty%2Fvim.git 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 Signed-off-by: Christian Brabandt --- diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 7320460615..172bf494a6 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 54a0cb67b1..439e452919 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 010b9a389f..a8dbab912b 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 2f83c8a28d..684f392d56 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 6d321e5c0b..1d46b56f0b 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 2e01085342..406417771a 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(®name); #endif set_reg_var(regname); diff --git a/src/globals.h b/src/globals.h index ed4affa8c0..9b101d8f20 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 59843293e5..2f2a560179 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(®name); #endif if (regname == 0 || regname == '"' diff --git a/src/ops.c b/src/ops.c index 7e1bb1bfb4..a7f0f041d0 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 87096fa60b..55dbf8a566 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 81d9ff76e7..d888615f53 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 42e09b3c94..84f9734428 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 6ada18c9e7..5bcaf2ce99 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 12fe8ebb14..90abbcc54b 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(®name); +#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(®name); (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 c1a27abba5..3da9ee303e 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 7c7a0ce472..51ff726d34 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 39b6496e3b..c7d4d47322 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, /**/