diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 20 | ||||
-rw-r--r-- | src/nvim/normal.c | 12 | ||||
-rw-r--r-- | src/nvim/ops.c | 163 | ||||
-rw-r--r-- | src/nvim/option.c | 10 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 8 |
5 files changed, 141 insertions, 72 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index be69bdbe61..b4d1677520 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5119,6 +5119,20 @@ void list_append_tv(list_T *l, typval_T *tv) } /* + * Add a list to a list. + */ +void list_append_list(list_T *list, list_T *itemlist) +{ + listitem_T *li = listitem_alloc(); + + li->li_tv.v_type = VAR_LIST; + li->li_tv.v_lock = 0; + li->li_tv.vval.v_list = itemlist; + list_append(list, li); + ++list->lv_refcount; +} + +/* * Add a dictionary to a list. Used by getqflist(). */ void list_append_dict(list_T *list, dict_T *dict) @@ -19815,16 +19829,12 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments) bool eval_has_provider(char *name) { -#define source_provider(name) \ - do_source((uint8_t *)"$VIMRUNTIME/autoload/provider/" name ".vim", \ - false, \ - false) #define check_provider(name) \ if (has_##name == -1) { \ has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \ if (!has_##name) { \ - source_provider(#name); \ + script_autoload((uint8_t *)"provider#" #name "#Call", false); \ has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \ } \ } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 1b21100933..192633a996 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -915,14 +915,7 @@ getcount: && !oap->op_type && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) { clearop(oap); - { - int regname = 0; - - /* Adjust the register according to 'clipboard', so that when - * "unnamed" is present it becomes '*' or '+' instead of '"'. */ - adjust_clipboard_register(®name); - set_reg_var(regname); - } + set_reg_var(0); } /* Get the length of mapped chars again after typing a count, second @@ -5105,7 +5098,6 @@ static void nv_brackets(cmdarg_T *cap) end = equalpos(start, VIsual) ? curwin->w_cursor : VIsual; curwin->w_cursor = (dir == BACKWARD ? start : end); } - adjust_clipboard_register(®name); prep_redo_cmd(cap); do_put(regname, dir, cap->count1, PUT_FIXINDENT); if (was_visual) { @@ -7272,10 +7264,8 @@ static void nv_put(cmdarg_T *cap) */ was_visual = true; regname = cap->oap->regname; - bool adjusted = adjust_clipboard_register(®name); if (regname == 0 || regname == '"' || VIM_ISDIGIT(regname) || regname == '-' - || adjusted ) { /* The delete is going to overwrite the register we want to * put, save it first. */ diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 6bf3f6036f..c20a017088 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -60,6 +60,7 @@ #define DELETION_REGISTER 36 #define CLIP_REGISTER 37 +# define CB_UNNAMEDMASK (CB_UNNAMED | CB_UNNAMEDPLUS) /* * Each yank register is an array of pointers to lines. */ @@ -74,6 +75,7 @@ static struct yankreg *y_current; /* ptr to current yankreg */ static int y_append; /* TRUE when appending */ static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */ +static bool clipboard_didwarn_unnamed = false; /* * structure used by block_prep, op_delete and op_yank for blockwise operators * also op_change, op_shift, op_insert, op_replace - AKelly @@ -751,7 +753,8 @@ void get_yank_register(int regname, int writing) int i; y_append = FALSE; - if ((regname == 0 || regname == '"') && !writing && y_previous != NULL) { + int unnamedclip = cb_flags & CB_UNNAMEDMASK; + if ((regname == 0 || regname == '"') && !unnamedclip && !writing && y_previous != NULL) { y_current = y_previous; return; } @@ -1302,18 +1305,6 @@ cmdline_paste_reg ( return OK; } -bool adjust_clipboard_register(int *rp) -{ - // If no reg. specified and 'unnamedclip' is set, use the - // clipboard register. - if (*rp == 0 && p_unc && eval_has_provider("clipboard")) { - *rp = '+'; - return true; - } - - return false; -} - /* * Handle a delete operation. * @@ -1328,7 +1319,6 @@ int op_delete(oparg_T *oap) struct block_def bd; linenr_T old_lcount = curbuf->b_ml.ml_line_count; int did_yank = FALSE; - int orig_regname = oap->regname; if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to do */ return OK; @@ -1342,8 +1332,6 @@ int op_delete(oparg_T *oap) return FAIL; } - bool adjusted = adjust_clipboard_register(&oap->regname); - if (has_mbyte) mb_adjust_opend(oap); @@ -1393,9 +1381,10 @@ int op_delete(oparg_T *oap) * register. For the black hole register '_' don't yank anything. */ if (oap->regname != '_') { - if (oap->regname != 0) { + bool unnamedclip = oap->regname == 0 && (cb_flags & CB_UNNAMEDMASK); + if (oap->regname != 0 || unnamedclip) { /* check for read-only register */ - if (!valid_yank_reg(oap->regname, TRUE)) { + if (!( valid_yank_reg(oap->regname, TRUE) || unnamedclip )) { beep_flush(); return OK; } @@ -1407,10 +1396,8 @@ int op_delete(oparg_T *oap) /* * Put deleted text into register 1 and shift number registers if the * delete contains a line break, or when a regname has been specified. - * Use the register name from before adjust_clip_reg() may have - * changed it. */ - if (orig_regname != 0 || oap->motion_type == MLINE + if (oap->regname != 0 || oap->motion_type == MLINE || oap->line_count > 1 || oap->use_reg_one) { y_current = &y_regs[9]; free_yank_all(); /* free register nine */ @@ -1424,9 +1411,7 @@ int op_delete(oparg_T *oap) /* Yank into small delete register when no named register specified * and the delete is within one line. */ - if (( - adjusted || - oap->regname == 0) && oap->motion_type != MLINE + if (oap->regname == 0 && oap->motion_type != MLINE && oap->line_count == 1) { oap->regname = '-'; get_yank_register(oap->regname, TRUE); @@ -2623,7 +2608,6 @@ do_put ( int allocated = FALSE; long cnt; - adjust_clipboard_register(®name); get_clipboard(regname); if (flags & PUT_FIXINDENT) @@ -3215,7 +3199,6 @@ void ex_display(exarg_T *eap) ) continue; /* did not ask for this register */ - adjust_clipboard_register(&name); get_clipboard(name); if (i == -1) { @@ -4842,6 +4825,7 @@ void write_reg_contents_ex(int name, if (!y_append && !must_append) free_yank_all(); str_to_reg(y_current, yank_type, str, len, block_len); + set_clipboard(name); /* ':let @" = "val"' should change the meaning of the "" register */ @@ -5225,33 +5209,82 @@ static void free_register(struct yankreg *reg) y_current = curr; } -static void copy_register(struct yankreg *dest, struct yankreg *src) -{ - free_register(dest); - *dest = *src; - dest->y_array = xcalloc(src->y_size, sizeof(uint8_t *)); - for (int j = 0; j < src->y_size; ++j) { - dest->y_array[j] = (uint8_t *)xstrdup((char *)src->y_array[j]); +// return target register +static int adjust_clipboard_name(int *name) { + if (*name == '*' || *name == '+') { + if(!eval_has_provider("clipboard")) { + EMSG("clipboard: provider is not available"); + return -1; + } + return CLIP_REGISTER; + } else if (*name == NUL && (cb_flags & (CB_UNNAMED | CB_UNNAMEDPLUS))) { + if(!eval_has_provider("clipboard")) { + if (!clipboard_didwarn_unnamed) { + msg((char_u*)"clipboard: provider not available, ignoring clipboard=unnamed[plus]"); + clipboard_didwarn_unnamed = true; + } + return -1; + } + if (cb_flags & CB_UNNAMEDPLUS) { + *name = '+'; + } else { + *name = '*'; + } + return 0; //unnamed } + // don't do anything for other register names + return -1; } static void get_clipboard(int name) { - if (!(name == '*' || name == '+' - || (p_unc && !name && eval_has_provider("clipboard")))) { + int ireg = adjust_clipboard_name(&name); + if (ireg < 0) { return; } - struct yankreg *reg = &y_regs[CLIP_REGISTER]; + struct yankreg *reg = &y_regs[ireg]; free_register(reg); + list_T *args = list_alloc(); + char_u regname = name; + list_append_string(args, ®name, 1); + typval_T result = eval_call_provider("clipboard", "get", args); if (result.v_type != VAR_LIST) { goto err; } - list_T *lines = result.vval.v_list; + list_T *res = result.vval.v_list, *lines = NULL; + if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) { + lines = res->lv_first->li_tv.vval.v_list; + if (res->lv_last->li_tv.v_type != VAR_STRING) { + goto err; + } + char_u* regtype = res->lv_last->li_tv.vval.v_string; + if (regtype == NULL || strlen((char*)regtype) != 1) { + goto err; + } + switch (regtype[0]) { + case 'v': case 'c': + reg->y_type = MCHAR; + break; + case 'V': case 'l': + reg->y_type = MLINE; + break; + case 'b': case Ctrl_V: + reg->y_type = MBLOCK; + break; + default: + goto err; + } + } else { + lines = res; + // provider did not specify regtype, calculate it below + reg->y_type = MAUTO; + } + reg->y_array = xcalloc(lines->lv_len, sizeof(uint8_t *)); reg->y_size = lines->lv_len; @@ -5263,9 +5296,23 @@ static void get_clipboard(int name) reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string); } - if (!name && p_unc) { - // copy to the unnamed register - copy_register(&y_regs[0], reg); + if (reg->y_type == MAUTO) { + if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) { + reg->y_type = MLINE; + free(reg->y_array[reg->y_size-1]); + reg->y_size--; + } else { + reg->y_type = MCHAR; + } + } else if (reg->y_type == MBLOCK) { + int maxlen = 0; + for (int i = 0; i < reg->y_size; i++) { + int rowlen = STRLEN(reg->y_array[i]); + if (rowlen > maxlen) { + maxlen = rowlen; + } + } + reg->y_width = maxlen-1; } return; @@ -5279,22 +5326,17 @@ err: } reg->y_array = NULL; reg->y_size = 0; - EMSG("Clipboard provider returned invalid data"); + EMSG("clipboard: provider returned invalid data"); } static void set_clipboard(int name) { - if (!(name == '*' || name == '+' - || (p_unc && !name && eval_has_provider("clipboard")))) { + int ireg = adjust_clipboard_name(&name); + if (ireg < 0) { return; } - struct yankreg *reg = &y_regs[CLIP_REGISTER]; - - if (!name && p_unc) { - // copy from the unnamed register - copy_register(reg, &y_regs[0]); - } + struct yankreg *reg = &y_regs[ireg]; list_T *lines = list_alloc(); @@ -5302,5 +5344,26 @@ static void set_clipboard(int name) list_append_string(lines, reg->y_array[i], -1); } - (void)eval_call_provider("clipboard", "set", lines); + list_T *args = list_alloc(); + list_append_list(args, lines); + + char_u regtype; + switch (reg->y_type) { + case MLINE: + regtype = 'V'; + list_append_string(lines, (char_u*)"", 0); + break; + case MCHAR: + regtype = 'v'; + break; + case MBLOCK: + regtype = 'b'; + break; + } + list_append_string(args, ®type, 1); + + char_u regname = name; + list_append_string(args, ®name, 1); + + (void)eval_call_provider("clipboard", "set", args); } diff --git a/src/nvim/option.c b/src/nvim/option.c index 2882d7a511..fd0978f3a6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -527,7 +527,7 @@ static struct vimoption (char_u *)0L} SCRIPTID_INIT}, {"clipboard", "cb", P_STRING|P_VI_DEF|P_COMMA|P_NODUP, - (char_u *)NULL, PV_NONE, + (char_u *)&p_cb, PV_NONE, {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, {"cmdheight", "ch", P_NUM|P_VI_DEF|P_RALL, @@ -1620,9 +1620,6 @@ static struct vimoption {"undoreload", "ur", P_NUM|P_VI_DEF, (char_u *)&p_ur, PV_NONE, { (char_u *)10000L, (char_u *)0L} SCRIPTID_INIT}, - {"unnamedclip", "ucp", P_BOOL|P_VI_DEF|P_VIM, - (char_u *)&p_unc, PV_NONE, - {(char_u *)FALSE, (char_u *)FALSE} SCRIPTID_INIT}, {"updatecount", "uc", P_NUM|P_VI_DEF, (char_u *)&p_uc, PV_NONE, {(char_u *)200L, (char_u *)0L} SCRIPTID_INIT}, @@ -4279,6 +4276,10 @@ did_set_string_option ( if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK) errmsg = e_invarg; } + else if (varp == &p_cb) { + if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, TRUE) != OK) + errmsg = e_invarg; + } /* When 'spelllang' or 'spellfile' is set and there is a window for this * buffer in which 'spell' is set load the wordlists. */ else if (varp == &(curbuf->b_s.b_p_spl) || varp == &(curbuf->b_s.b_p_spf)) { @@ -4846,7 +4847,6 @@ char_u *check_stl_option(char_u *s) return NULL; } - /* * Set curbuf->b_cap_prog to the regexp program for 'spellcapcheck'. * Return error message when failed, NULL when OK. diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 89264f8982..39dfbe8b88 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -317,6 +317,13 @@ EXTERN char_u *p_enc; /* 'encoding' */ EXTERN int p_deco; /* 'delcombine' */ EXTERN char_u *p_ccv; /* 'charconvert' */ EXTERN char_u *p_cedit; /* 'cedit' */ +EXTERN char_u *p_cb; /* 'clipboard' */ +EXTERN unsigned cb_flags; +#ifdef IN_OPTION_C +static char *(p_cb_values[]) = {"unnamed", "unnamedplus", NULL}; +#endif +# define CB_UNNAMED 0x001 +# define CB_UNNAMEDPLUS 0x002 EXTERN long p_cwh; /* 'cmdwinheight' */ EXTERN long p_ch; /* 'cmdheight' */ EXTERN int p_confirm; /* 'confirm' */ @@ -582,7 +589,6 @@ static char *(p_ttym_values[]) = EXTERN char_u *p_udir; /* 'undodir' */ EXTERN long p_ul; /* 'undolevels' */ EXTERN long p_ur; /* 'undoreload' */ -EXTERN int p_unc; /* 'unnamedclip' */ EXTERN long p_uc; /* 'updatecount' */ EXTERN long p_ut; /* 'updatetime' */ EXTERN char_u *p_fcs; /* 'fillchar' */ |