From 5600b80c1fcdf9d056bb7a0b5a74e5563dcb991f Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 18 Mar 2015 22:38:19 +0100 Subject: clipboard: show "* and "+ in :registers Helped-by: Robin Allen Helped-by: Scott Prager --- src/nvim/ops.c | 57 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 2714798368..e73868a0fa 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -57,10 +57,15 @@ * 1..9 = registers '1' to '9', for deletes * 10..35 = registers 'a' to 'z' * 36 = delete register '-' + * 37 = selection register '*' + * 38 = clipboard register '+' */ -#define NUM_REGISTERS 38 #define DELETION_REGISTER 36 -#define CLIP_REGISTER 37 +#define NUM_SAVED_REGISTERS 37 +// The following registers should not be saved in viminfo: +#define STAR_REGISTER 37 +#define PLUS_REGISTER 38 +#define NUM_REGISTERS 39 #define CB_UNNAMEDMASK (CB_UNNAMED | CB_UNNAMEDPLUS) #define CB_LATEST (-1) @@ -771,8 +776,10 @@ void get_yank_register(int regname, int writing) y_append = TRUE; } else if (regname == '-') i = DELETION_REGISTER; - else if (regname == '*' || regname == '+') - i = CLIP_REGISTER; + else if (regname == '*') + i = STAR_REGISTER; + else if (regname == '+') + i = PLUS_REGISTER; else /* not 0-9, a-z, A-Z or '-': use register 0 */ i = 0; y_current = &(y_regs[i]); @@ -792,7 +799,7 @@ get_register ( ) FUNC_ATTR_NONNULL_RET { get_yank_register(name, 0); - get_clipboard(name); + get_clipboard(name, false); struct yankreg *reg = xmalloc(sizeof(struct yankreg)); *reg = *y_current; @@ -960,7 +967,7 @@ do_execreg ( } execreg_lastc = regname; - get_clipboard(regname); + get_clipboard(regname, false); if (regname == '_') /* black hole: don't stuff anything */ return OK; @@ -1125,7 +1132,7 @@ insert_reg ( if (regname != NUL && !valid_yank_reg(regname, FALSE)) return FAIL; - get_clipboard(regname); + get_clipboard(regname, false); if (regname == '.') /* insert last inserted text */ retval = stuff_inserted(NUL, 1L, TRUE); @@ -2613,7 +2620,7 @@ do_put ( int allocated = FALSE; long cnt; - get_clipboard(regname); + get_clipboard(regname, false); if (flags & PUT_FIXINDENT) orig_indent = get_indent(); @@ -3190,6 +3197,10 @@ int get_register_name(int num) return num + '0'; else if (num == DELETION_REGISTER) return '-'; + else if (num == STAR_REGISTER) + return '*'; + else if (num == PLUS_REGISTER) + return '+'; else { return num + 'a' - 10; } @@ -3222,7 +3233,7 @@ void ex_display(exarg_T *eap) continue; /* did not ask for this register */ } - get_clipboard(name); + get_clipboard(name, true); if (i == -1) { if (y_previous != NULL) @@ -4566,12 +4577,11 @@ void write_viminfo_registers(FILE *fp) if (max_kbyte == 0) return; - for (i = 0; i < NUM_REGISTERS; i++) { + // don't include clipboard registers '*'/'+' + for (i = 0; i < NUM_SAVED_REGISTERS; i++) { if (y_regs[i].y_array == NULL) continue; - // Skip '*'/'+' register, we don't want them back next time - if (i == CLIP_REGISTER) - continue; + /* Skip empty registers. */ num_lines = y_regs[i].y_size; if (num_lines == 0 @@ -4651,7 +4661,7 @@ char_u get_reg_type(int regname, long *reglen) return MCHAR; } - get_clipboard(regname); + get_clipboard(regname, false); if (regname != NUL && !valid_yank_reg(regname, FALSE)) return MAUTO; @@ -4712,7 +4722,7 @@ void *get_reg_contents(int regname, int flags) if (regname != NUL && !valid_yank_reg(regname, FALSE)) return NULL; - get_clipboard(regname); + get_clipboard(regname, false); char_u *retval; int allocated; @@ -5292,16 +5302,17 @@ static void free_register(struct yankreg *reg) } // return target register -static struct yankreg* adjust_clipboard_name(int *name) { +static struct yankreg* adjust_clipboard_name(int *name, bool quiet) { if (*name == '*' || *name == '+') { if(!eval_has_provider("clipboard")) { - EMSG("clipboard: provider is not available"); - return NULL; + if (!quiet) { + EMSG("clipboard: provider is not available"); + } } - return &y_regs[CLIP_REGISTER]; + return &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER]; } else if ((*name == NUL || *name == CB_LATEST) && (cb_flags & CB_UNNAMEDMASK)) { if(!eval_has_provider("clipboard")) { - if (!clipboard_didwarn_unnamed) { + if (!quiet && !clipboard_didwarn_unnamed) { msg((char_u*)"clipboard: provider not available, ignoring clipboard=unnamed[plus]"); clipboard_didwarn_unnamed = true; } @@ -5324,9 +5335,9 @@ static struct yankreg* adjust_clipboard_name(int *name) { return NULL; } -static void get_clipboard(int name) +static void get_clipboard(int name, bool quiet) { - struct yankreg* reg = adjust_clipboard_name(&name); + struct yankreg* reg = adjust_clipboard_name(&name, quiet); if (reg == NULL) { return; } @@ -5417,7 +5428,7 @@ err: static void set_clipboard(int name) { - struct yankreg* reg = adjust_clipboard_name(&name); + struct yankreg* reg = adjust_clipboard_name(&name, false); if (reg == NULL) { return; } -- cgit From 34dba3d7cd43b4797d60f636dc9c7c3040a56f3c Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 18 Mar 2015 23:43:49 +0100 Subject: clipboard: reallow `:put` --- src/nvim/.screen.c.swn | Bin 0 -> 16384 bytes src/nvim/ex_docmd.c | 15 +++++---------- 2 files changed, 5 insertions(+), 10 deletions(-) create mode 100644 src/nvim/.screen.c.swn (limited to 'src') diff --git a/src/nvim/.screen.c.swn b/src/nvim/.screen.c.swn new file mode 100644 index 0000000000..5b9fe18630 Binary files /dev/null and b/src/nvim/.screen.c.swn differ diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index db4f3a54f1..cf22477dc9 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1699,16 +1699,11 @@ static char_u * do_one_cmd(char_u **cmdlinep, } /* accept numbered register only when no count allowed (:put) */ - if ( (ea.argt & REGSTR) - && *ea.arg != NUL - /* Do not allow register = for user commands */ - && (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=') - && !((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg))) { - /* check these explicitly for a more specific error message */ - if (*ea.arg == '*' || *ea.arg == '+') { - errormsg = (char_u *)_(e_invalidreg); - goto doend; - } + if ((ea.argt & REGSTR) + && *ea.arg != NUL + /* Do not allow register = for user commands */ + && (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=') + && !((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg))) { if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put && !IS_USER_CMDIDX(ea.cmdidx)))) { ea.regname = *ea.arg++; -- cgit From 7422843f5c86b0dc18e26e5a2436f9d8e7013e12 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 28 Mar 2015 20:57:06 +0100 Subject: clipboard: improve the handling of newlines in `get_clipboard` This makes the interpretion consistent with the way newlines are used in the VIMENC format, while keeping the same fallback behaviour when regtype is unspecified. Also check both cases explicitly in the tests. --- src/nvim/ops.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index e73868a0fa..f0caaad97b 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5360,10 +5360,13 @@ static void get_clipboard(int name, bool quiet) goto err; } char_u* regtype = res->lv_last->li_tv.vval.v_string; - if (regtype == NULL || strlen((char*)regtype) != 1) { + if (regtype == NULL || strlen((char*)regtype) > 1) { goto err; } switch (regtype[0]) { + case 0: + reg->y_type = MAUTO; + break; case 'v': case 'c': reg->y_type = MCHAR; break; @@ -5393,15 +5396,23 @@ static void get_clipboard(int name, bool quiet) reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string); } - if (reg->y_type == MAUTO) { - if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) { - reg->y_type = MLINE; + if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) { + // a known-to-be charwise yank might have a final linebreak + // but otherwise there is no line after the final newline + if (reg->y_type != MCHAR) { free(reg->y_array[reg->y_size-1]); reg->y_size--; - } else { + if (reg->y_type == MAUTO) { + reg->y_type = MLINE; + } + } + } else { + if (reg->y_type == MAUTO) { reg->y_type = MCHAR; } - } else if (reg->y_type == MBLOCK) { + } + + if (reg->y_type == MBLOCK) { int maxlen = 0; for (int i = 0; i < reg->y_size; i++) { int rowlen = STRLEN(reg->y_array[i]); @@ -5453,6 +5464,7 @@ static void set_clipboard(int name) break; case MBLOCK: regtype = 'b'; + list_append_string(lines, (char_u*)"", 0); break; } list_append_string(args, ®type, 1); -- cgit From adcf268a72827be38510b1830b67b287dec50c4a Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 29 Mar 2015 12:39:52 +0200 Subject: clipboard: handle clipboard reading directly in `get_yank_register` This makes :* work as expected and avoids clobbering zero register ("0) when pasting unnamed clipboard Helped-By: Scott Prager Helped-By: Michael Reed --- src/nvim/ops.c | 112 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index f0caaad97b..572b557ad3 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -53,7 +53,7 @@ /* * Registers: - * 0 = unnamed register, for normal yanks and puts + * 0 = register for latest (unnamed) yank * 1..9 = registers '1' to '9', for deletes * 10..35 = registers 'a' to 'z' * 36 = delete register '-' @@ -68,7 +68,6 @@ #define NUM_REGISTERS 39 #define CB_UNNAMEDMASK (CB_UNNAMED | CB_UNNAMEDPLUS) -#define CB_LATEST (-1) /* * Each yank register is an array of pointers to lines. */ @@ -748,21 +747,37 @@ valid_yank_reg ( return FALSE; } -/* - * Set y_current and y_append, according to the value of "regname". - * Cannot handle the '_' register. - * Must only be called with a valid register name! - * - * If regname is 0 and writing, use register 0 - * If regname is 0 and reading, use previous register - */ -void get_yank_register(int regname, int writing) +typedef enum { + YREG_PASTE, + YREG_YANK, + YREG_PUT, +} yreg_mode_t; + +/// Set y_current and y_append, according to the value of `regname`. +/// Cannot handle the '_' (black hole) register. +/// Must only be called with a valid register name! +/// +/// @param regname The name of the register used or 0 for the unnamed register +/// @param mode One of the following three flags: +/// +/// `YREG_PASTE`: +/// Prepare for pasting the register `regname`. With no regname specified, +/// read from last written register, or from unnamed clipboard (depending on the +/// `clipboard=unnamed` option). Queries the clipboard provider if necessary. +/// +/// `YREG_YANK`: +/// Preparare for yanking into `regname`. With no regname specified, +/// yank into `"0` register. Update `y_previous` for next unnamed paste. +/// +/// `YREG_PUT`: +/// Obtain the location that would be read when pasting `regname`. +void get_yank_register(int regname, int mode) { int i; y_append = FALSE; int unnamedclip = cb_flags & CB_UNNAMEDMASK; - if ((regname == 0 || regname == '"') && !unnamedclip && !writing && y_previous != NULL) { + if ((regname == 0 || regname == '"') && !unnamedclip && mode != YREG_YANK && y_previous != NULL) { y_current = y_previous; return; } @@ -783,8 +798,12 @@ void get_yank_register(int regname, int writing) else /* not 0-9, a-z, A-Z or '-': use register 0 */ i = 0; y_current = &(y_regs[i]); - if (writing) /* remember the register we write into for do_put() */ + if (mode == YREG_YANK) { + // remember the written register for unnamed paste y_previous = y_current; + } else if (mode == YREG_PASTE) { + get_clipboard(regname, &y_current, false); + } } @@ -798,8 +817,7 @@ get_register ( int copy /* make a copy, if FALSE make register empty. */ ) FUNC_ATTR_NONNULL_RET { - get_yank_register(name, 0); - get_clipboard(name, false); + get_yank_register(name, YREG_PASTE); struct yankreg *reg = xmalloc(sizeof(struct yankreg)); *reg = *y_current; @@ -823,7 +841,7 @@ get_register ( */ void put_register(int name, void *reg) { - get_yank_register(name, 0); + get_yank_register(name, YREG_PUT); free_yank_all(); *y_current = *(struct yankreg *)reg; free(reg); @@ -839,7 +857,7 @@ int yank_register_mline(int regname) return FALSE; if (regname == '_') /* black hole is always empty */ return FALSE; - get_yank_register(regname, FALSE); + get_yank_register(regname, YREG_PASTE); return y_current->y_type == MLINE; } @@ -913,7 +931,7 @@ static int stuff_yank(int regname, char_u *p) free(p); return OK; } - get_yank_register(regname, TRUE); + get_yank_register(regname, YREG_YANK); if (y_append && y_current->y_array != NULL) { char_u **pp = &(y_current->y_array[y_current->y_size - 1]); char_u *lp = xmalloc(STRLEN(*pp) + STRLEN(p) + 1); @@ -967,8 +985,6 @@ do_execreg ( } execreg_lastc = regname; - get_clipboard(regname, false); - if (regname == '_') /* black hole: don't stuff anything */ return OK; @@ -1007,7 +1023,7 @@ do_execreg ( retval = put_in_typebuf(p, FALSE, colon, silent); free(p); } else { - get_yank_register(regname, FALSE); + get_yank_register(regname, YREG_PASTE); if (y_current->y_array == NULL) return FAIL; @@ -1132,8 +1148,6 @@ insert_reg ( if (regname != NUL && !valid_yank_reg(regname, FALSE)) return FAIL; - get_clipboard(regname, false); - if (regname == '.') /* insert last inserted text */ retval = stuff_inserted(NUL, 1L, TRUE); else if (get_spec_reg(regname, &arg, &allocated, TRUE)) { @@ -1143,7 +1157,7 @@ insert_reg ( if (allocated) free(arg); } else { /* name or number register */ - get_yank_register(regname, FALSE); + get_yank_register(regname, YREG_PASTE); if (y_current->y_array == NULL) retval = FAIL; else { @@ -1290,7 +1304,7 @@ cmdline_paste_reg ( { long i; - get_yank_register(regname, FALSE); + get_yank_register(regname, YREG_PASTE); if (y_current->y_array == NULL) return FAIL; @@ -1397,7 +1411,7 @@ int op_delete(oparg_T *oap) beep_flush(); return OK; } - get_yank_register(oap->regname, TRUE); /* yank into specif'd reg. */ + get_yank_register(oap->regname, YREG_YANK); /* yank into specif'd reg. */ if (op_yank(oap, TRUE, FALSE) == OK) /* yank without message */ did_yank = TRUE; } @@ -1423,14 +1437,14 @@ int op_delete(oparg_T *oap) if (oap->regname == 0 && oap->motion_type != MLINE && oap->line_count == 1) { oap->regname = '-'; - get_yank_register(oap->regname, TRUE); + get_yank_register(oap->regname, YREG_YANK); if (op_yank(oap, TRUE, FALSE) == OK) did_yank = TRUE; oap->regname = 0; } if(oap->regname == 0 && did_yank) { - set_clipboard(CB_LATEST); + set_clipboard(0); } /* * If there's too much stuff to fit in the yank register, then get a @@ -2372,7 +2386,7 @@ int op_yank(oparg_T *oap, int deleting, int mess) return OK; if (!deleting) /* op_delete() already set y_current */ - get_yank_register(oap->regname, TRUE); + get_yank_register(oap->regname, YREG_YANK); curr = y_current; /* append to existing contents */ @@ -2620,8 +2634,6 @@ do_put ( int allocated = FALSE; long cnt; - get_clipboard(regname, false); - if (flags & PUT_FIXINDENT) orig_indent = get_indent(); @@ -2694,7 +2706,7 @@ do_put ( y_array = &insert_string; } } else { - get_yank_register(regname, FALSE); + get_yank_register(regname, YREG_PASTE); y_type = y_current->y_type; y_width = y_current->y_width; @@ -3233,7 +3245,6 @@ void ex_display(exarg_T *eap) continue; /* did not ask for this register */ } - get_clipboard(name, true); if (i == -1) { if (y_previous != NULL) @@ -3243,6 +3254,8 @@ void ex_display(exarg_T *eap) } else yb = &(y_regs[i]); + get_clipboard(name, &yb, true); + if (name == vim_tolower(redir_reg) || (redir_reg == '"' && yb == y_previous)) continue; /* do not list register being written to, the @@ -4500,7 +4513,7 @@ int read_viminfo_register(vir_T *virp, int force) return TRUE; /* too many errors, pretend end-of-file */ do_it = FALSE; } - get_yank_register(*str++, FALSE); + get_yank_register(*str++, YREG_PUT); if (!force && y_current->y_array != NULL) do_it = FALSE; @@ -4661,12 +4674,10 @@ char_u get_reg_type(int regname, long *reglen) return MCHAR; } - get_clipboard(regname, false); - if (regname != NUL && !valid_yank_reg(regname, FALSE)) return MAUTO; - get_yank_register(regname, FALSE); + get_yank_register(regname, YREG_PASTE); if (y_current->y_array != NULL) { if (reglen != NULL && y_current->y_type == MBLOCK) @@ -4722,8 +4733,6 @@ void *get_reg_contents(int regname, int flags) if (regname != NUL && !valid_yank_reg(regname, FALSE)) return NULL; - get_clipboard(regname, false); - char_u *retval; int allocated; if (get_spec_reg(regname, &retval, &allocated, FALSE)) { @@ -4735,7 +4744,7 @@ void *get_reg_contents(int regname, int flags) return get_reg_wrap_one_line(vim_strsave(retval), flags); } - get_yank_register(regname, FALSE); + get_yank_register(regname, YREG_PASTE); if (y_current->y_array == NULL) return NULL; @@ -4796,7 +4805,7 @@ static bool init_write_reg(int name, struct yankreg **old_y_previous, *old_y_previous = y_previous; *old_y_current = y_current; - get_yank_register(name, true); + get_yank_register(name, YREG_YANK); if (!y_append && !must_append) { free_yank_all(); } @@ -5302,7 +5311,7 @@ static void free_register(struct yankreg *reg) } // return target register -static struct yankreg* adjust_clipboard_name(int *name, bool quiet) { +static struct yankreg* adjust_clipboard_name(int *name, bool quiet, bool writing) { if (*name == '*' || *name == '+') { if(!eval_has_provider("clipboard")) { if (!quiet) { @@ -5310,7 +5319,7 @@ static struct yankreg* adjust_clipboard_name(int *name, bool quiet) { } } return &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER]; - } else if ((*name == NUL || *name == CB_LATEST) && (cb_flags & CB_UNNAMEDMASK)) { + } else if ((*name == NUL) && (cb_flags & CB_UNNAMEDMASK)) { if(!eval_has_provider("clipboard")) { if (!quiet && !clipboard_didwarn_unnamed) { msg((char_u*)"clipboard: provider not available, ignoring clipboard=unnamed[plus]"); @@ -5319,15 +5328,15 @@ static struct yankreg* adjust_clipboard_name(int *name, bool quiet) { return NULL; } struct yankreg* target; - if (*name == CB_LATEST) { - target = y_current; - } else { - target = &y_regs[0]; - } if (cb_flags & CB_UNNAMEDPLUS) { *name = '+'; + target = &y_regs[STAR_REGISTER]; } else { *name = '*'; + target = &y_regs[PLUS_REGISTER]; + } + if (writing) { + target = y_current; } return target; // unnamed register } @@ -5335,9 +5344,9 @@ static struct yankreg* adjust_clipboard_name(int *name, bool quiet) { return NULL; } -static void get_clipboard(int name, bool quiet) +static void get_clipboard(int name, struct yankreg** target, bool quiet) { - struct yankreg* reg = adjust_clipboard_name(&name, quiet); + struct yankreg* reg = adjust_clipboard_name(&name, quiet, false); if (reg == NULL) { return; } @@ -5423,6 +5432,7 @@ static void get_clipboard(int name, bool quiet) reg->y_width = maxlen-1; } + *target = reg; return; err: @@ -5439,7 +5449,7 @@ err: static void set_clipboard(int name) { - struct yankreg* reg = adjust_clipboard_name(&name, false); + struct yankreg* reg = adjust_clipboard_name(&name, false, true); if (reg == NULL) { return; } -- cgit