aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ops.c
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2015-03-29 12:39:52 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2015-04-05 11:34:14 +0200
commitadcf268a72827be38510b1830b67b287dec50c4a (patch)
treee427da7ecc32909e3ef31f97b3bb3b146f1fad84 /src/nvim/ops.c
parentdb92fcdba3f596838f524a049efe1c7e82bb734f (diff)
downloadrneovim-adcf268a72827be38510b1830b67b287dec50c4a.tar.gz
rneovim-adcf268a72827be38510b1830b67b287dec50c4a.tar.bz2
rneovim-adcf268a72827be38510b1830b67b287dec50c4a.zip
clipboard: handle clipboard reading directly in `get_yank_register`
This makes :<c-r>* work as expected and avoids clobbering zero register ("0) when pasting unnamed clipboard Helped-By: Scott Prager <splinterofchaos@gmail.com> Helped-By: Michael Reed <m.reed@mykolab.com>
Diffstat (limited to 'src/nvim/ops.c')
-rw-r--r--src/nvim/ops.c112
1 files changed, 61 insertions, 51 deletions
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;
}