clipboard: handle linewise/charwise selections correctly

This commit is contained in:
Björn Linse 2014-11-22 19:16:04 +01:00
parent c1854d2433
commit 63efb9b1f1
2 changed files with 65 additions and 3 deletions

View File

@ -5,7 +5,7 @@ let s:copy = {}
let s:paste = {}
function! s:try_cmd(cmd, ...)
let out = a:0 ? systemlist(a:cmd, a:1) : systemlist(a:cmd)
let out = a:0 ? systemlist(a:cmd, a:1, 1) : systemlist(a:cmd, [''], 1)
if v:shell_error
echo "clipboard: error: ".(len(out) ? out[0] : '')
return ''
@ -39,7 +39,7 @@ function! s:clipboard.get(reg)
return s:try_cmd(s:paste[a:reg])
endfunction
function! s:clipboard.set(lines, reg)
function! s:clipboard.set(lines, regtype, reg)
call s:try_cmd(s:copy[a:reg], a:lines)
endfunction

View File

@ -5255,7 +5255,35 @@ static void get_clipboard(int name)
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;
@ -5267,6 +5295,25 @@ static void get_clipboard(int name)
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;
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;
}
if (!name && p_unc) {
// copy to the unnamed register
copy_register(&y_regs[0], reg);
@ -5310,6 +5357,21 @@ static void set_clipboard(int name)
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, &regtype, 1);
char_u regname = (char_u)name;
list_append_string(args, &regname, 1);