aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/normal.c5
-rw-r--r--src/nvim/ops.c125
-rw-r--r--src/nvim/option.c6
-rw-r--r--src/nvim/option_defs.h2
-rw-r--r--src/nvim/os/provider.c7
5 files changed, 140 insertions, 5 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index fc5073b177..5a4c3a326a 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -923,6 +923,7 @@ getcount:
/* Adjust the register according to 'clipboard', so that when
* "unnamed" is present it becomes '*' or '+' instead of '"'. */
+ adjust_clipboard_register(&regname);
set_reg_var(regname);
}
}
@@ -5101,6 +5102,7 @@ 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(&regname);
prep_redo_cmd(cap);
do_put(regname, dir, cap->count1, PUT_FIXINDENT);
if (was_visual) {
@@ -7267,9 +7269,10 @@ static void nv_put(cmdarg_T *cap)
*/
was_visual = TRUE;
regname = cap->oap->regname;
+ bool adjusted = adjust_clipboard_register(&regname);
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 4432116193..3008af94f3 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -47,6 +47,9 @@
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
+#include "nvim/os/provider.h"
+#include "nvim/os/msgpack_rpc_helpers.h"
+#include "nvim/api/private/helpers.h"
/*
* Registers:
@@ -55,8 +58,9 @@
* 10..35 = registers 'a' to 'z'
* 36 = delete register '-'
*/
-#define NUM_REGISTERS 37
+#define NUM_REGISTERS 38
#define DELETION_REGISTER 36
+#define CLIP_REGISTER 37
/*
* Each yank register is an array of pointers to lines.
@@ -711,6 +715,8 @@ valid_yank_reg (
|| regname == '"'
|| regname == '-'
|| regname == '_'
+ || regname == '*'
+ || regname == '+'
)
return TRUE;
return FALSE;
@@ -743,6 +749,8 @@ 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 /* not 0-9, a-z, A-Z or '-': use register 0 */
i = 0;
y_current = &(y_regs[i]);
@@ -762,6 +770,7 @@ get_register (
) FUNC_ATTR_NONNULL_RET
{
get_yank_register(name, 0);
+ get_clipboard(name);
struct yankreg *reg = xmalloc(sizeof(struct yankreg));
*reg = *y_current;
@@ -789,7 +798,7 @@ void put_register(int name, void *reg)
free_yank_all();
*y_current = *(struct yankreg *)reg;
free(reg);
-
+ set_clipboard(name);
}
/*
@@ -929,6 +938,7 @@ do_execreg (
}
execreg_lastc = regname;
+ get_clipboard(regname);
if (regname == '_') /* black hole: don't stuff anything */
return OK;
@@ -1093,6 +1103,7 @@ insert_reg (
if (regname != NUL && !valid_yank_reg(regname, FALSE))
return FAIL;
+ get_clipboard(regname);
if (regname == '.') /* insert last inserted text */
retval = stuff_inserted(NUL, 1L, TRUE);
@@ -1278,6 +1289,17 @@ 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 && provider_has_feature("clipboard")) {
+ *rp = '+';
+ return true;
+ }
+
+ return false;
+}
/*
* Handle a delete operation.
@@ -1307,6 +1329,7 @@ int op_delete(oparg_T *oap)
return FAIL;
}
+ bool adjusted = adjust_clipboard_register(&oap->regname);
if (has_mbyte)
mb_adjust_opend(oap);
@@ -1389,6 +1412,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
&& oap->line_count == 1) {
oap->regname = '-';
@@ -2336,7 +2360,6 @@ int op_yank(oparg_T *oap, int deleting, int mess)
if (oap->regname == '_') /* black hole: nothing to do */
return OK;
-
if (!deleting) /* op_delete() already set y_current */
get_yank_register(oap->regname, TRUE);
@@ -2519,6 +2542,8 @@ int op_yank(oparg_T *oap, int deleting, int mess)
curbuf->b_op_end.col = MAXCOL;
}
+ set_clipboard(oap->regname);
+
return OK;
}
@@ -2581,6 +2606,8 @@ do_put (
int allocated = FALSE;
long cnt;
+ adjust_clipboard_register(&regname);
+ get_clipboard(regname);
if (flags & PUT_FIXINDENT)
orig_indent = get_indent();
@@ -3171,6 +3198,8 @@ void ex_display(exarg_T *eap)
)
continue; /* did not ask for this register */
+ adjust_clipboard_register(&name);
+ get_clipboard(name);
if (i == -1) {
if (y_previous != NULL)
@@ -4528,6 +4557,9 @@ void write_viminfo_registers(FILE *fp)
for (i = 0; i < NUM_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
@@ -4607,6 +4639,7 @@ char_u get_reg_type(int regname, long *reglen)
return MCHAR;
}
+ get_clipboard(regname);
if (regname != NUL && !valid_yank_reg(regname, FALSE))
return MAUTO;
@@ -4654,6 +4687,7 @@ get_reg_contents (
if (regname != NUL && !valid_yank_reg(regname, FALSE))
return NULL;
+ get_clipboard(regname);
if (get_spec_reg(regname, &retval, &allocated, FALSE)) {
if (retval == NULL)
@@ -5162,3 +5196,88 @@ void cursor_pos_info(void)
}
}
+static void free_register(struct yankreg *reg)
+{
+ // Save 'y_current' into 'curr'
+ struct yankreg *curr = y_current;
+ // Set it to 'y_current' since 'free_yank_all' operates on it
+ y_current = reg;
+ free_yank_all();
+ // Restore 'y_current'
+ 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]);
+ }
+}
+
+static void get_clipboard(int name)
+{
+ if (!(name == '*' || name == '+'
+ || (p_unc && !name && provider_has_feature("clipboard")))) {
+ return;
+ }
+
+ struct yankreg *reg = &y_regs[CLIP_REGISTER];
+ free_register(reg);
+ Object result = provider_call("clipboard_get", NIL);
+
+ if (result.type != kObjectTypeArray) {
+ goto err;
+ }
+
+ Array lines = result.data.array;
+ reg->y_array = xcalloc(lines.size, sizeof(uint8_t *));
+ reg->y_size = lines.size;
+
+ for (size_t i = 0; i < lines.size; i++) {
+ if (lines.items[i].type != kObjectTypeString) {
+ goto err;
+ }
+ reg->y_array[i] = (uint8_t *)lines.items[i].data.string.data;
+ }
+
+ if (!name && p_unc) {
+ // copy to the unnamed register
+ copy_register(&y_regs[0], reg);
+ }
+
+ return;
+
+err:
+ msgpack_rpc_free_object(result);
+ free(reg->y_array);
+ reg->y_array = NULL;
+ reg->y_size = 0;
+ EMSG("Clipboard provider returned invalid data");
+}
+
+static void set_clipboard(int name)
+{
+ if (!(name == '*' || name == '+'
+ || (p_unc && !name && provider_has_feature("clipboard")))) {
+ return;
+ }
+
+ struct yankreg *reg = &y_regs[CLIP_REGISTER];
+
+ if (!name && p_unc) {
+ // copy from the unnamed register
+ copy_register(reg, &y_regs[0]);
+ }
+
+ Array lines = {0, 0, 0};
+
+ for (int i = 0; i < reg->y_size; i++) {
+ ADD(lines, STRING_OBJ(cstr_to_string((char *)reg->y_array[i])));
+ }
+
+ Object result = provider_call("clipboard_set", ARRAY_OBJ(lines));
+ msgpack_rpc_free_object(result);
+}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 5b3f0d5612..28bbfb41e7 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -963,6 +963,9 @@ static struct vimoption
{"infercase", "inf", P_BOOL|P_VI_DEF,
(char_u *)&p_inf, PV_INF,
{(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
+ {"initclipboard","icpb",P_STRING|P_VI_DEF|P_SECURE,
+ (char_u *)&p_icpb, PV_NONE,
+ {(char_u *)NULL, (char_u *)0L} SCRIPTID_INIT},
{"initpython","ipy",P_STRING|P_VI_DEF|P_SECURE,
(char_u *)&p_ipy, PV_NONE,
{(char_u *)NULL, (char_u *)0L} SCRIPTID_INIT},
@@ -1628,6 +1631,9 @@ 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},
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 401cf3d200..f75824ec03 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -586,6 +586,7 @@ 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' */
@@ -631,6 +632,7 @@ EXTERN int p_wa; /* 'writeany' */
EXTERN int p_wb; /* 'writebackup' */
EXTERN long p_wd; /* 'writedelay' */
EXTERN char *p_ipy; // 'initpython'
+EXTERN char *p_icpb; // 'initclipboard'
/*
* "indir" values for buffer-local opions.
diff --git a/src/nvim/os/provider.c b/src/nvim/os/provider.c
index 9bd1c82569..2e42cbb8f2 100644
--- a/src/nvim/os/provider.c
+++ b/src/nvim/os/provider.c
@@ -36,7 +36,12 @@ static struct feature {
"python_execute",
"python_execute_file",
"python_do_range",
- "python_eval")
+ "python_eval"),
+
+ FEATURE("clipboard",
+ &p_icpb,
+ "clipboard_get",
+ "clipboard_set")
};
static Map(cstr_t, uint64_t) *registered_providers = NULL;