mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:9.1.0824: too many strlen() calls in register.c (#31022)
Problem: too many strlen() calls in register.c
Solution: refactor code, add string_T struct to keep track
of string lengths (John Marriott)
closes: vim/vim#15952
79f6ffd388
Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
parent
9b357e30fd
commit
cbd8b2c162
@ -111,6 +111,12 @@ typedef kvec_withinit_t(Object, 16) ArrayBuilder;
|
|||||||
#define STATIC_CSTR_AS_OBJ(s) STRING_OBJ(STATIC_CSTR_AS_STRING(s))
|
#define STATIC_CSTR_AS_OBJ(s) STRING_OBJ(STATIC_CSTR_AS_STRING(s))
|
||||||
#define STATIC_CSTR_TO_OBJ(s) STRING_OBJ(STATIC_CSTR_TO_STRING(s))
|
#define STATIC_CSTR_TO_OBJ(s) STRING_OBJ(STATIC_CSTR_TO_STRING(s))
|
||||||
|
|
||||||
|
#define API_CLEAR_STRING(s) \
|
||||||
|
do { \
|
||||||
|
XFREE_CLEAR(s.data); \
|
||||||
|
s.size = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
// Helpers used by the generated msgpack-rpc api wrappers
|
// Helpers used by the generated msgpack-rpc api wrappers
|
||||||
#define api_init_boolean
|
#define api_init_boolean
|
||||||
#define api_init_integer
|
#define api_init_integer
|
||||||
|
@ -1317,15 +1317,15 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow,
|
|||||||
return; // Nothing to do.
|
return; // Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
reg->y_array = arena_alloc(arena, lines.size * sizeof(uint8_t *), true);
|
reg->y_array = arena_alloc(arena, lines.size * sizeof(String), true);
|
||||||
reg->y_size = lines.size;
|
reg->y_size = lines.size;
|
||||||
for (size_t i = 0; i < lines.size; i++) {
|
for (size_t i = 0; i < lines.size; i++) {
|
||||||
VALIDATE_T("line", kObjectTypeString, lines.items[i].type, {
|
VALIDATE_T("line", kObjectTypeString, lines.items[i].type, {
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
String line = lines.items[i].data.string;
|
String line = lines.items[i].data.string;
|
||||||
reg->y_array[i] = arena_memdupz(arena, line.data, line.size);
|
reg->y_array[i] = copy_string(line, arena);
|
||||||
memchrsub(reg->y_array[i], NUL, NL, line.size);
|
memchrsub(reg->y_array[i].data, NUL, NL, line.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_yankreg_from_object(reg, false);
|
finish_yankreg_from_object(reg, false);
|
||||||
|
246
src/nvim/ops.c
246
src/nvim/ops.c
@ -12,6 +12,7 @@
|
|||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/ascii_defs.h"
|
#include "nvim/ascii_defs.h"
|
||||||
#include "nvim/assert_defs.h"
|
#include "nvim/assert_defs.h"
|
||||||
#include "nvim/autocmd.h"
|
#include "nvim/autocmd.h"
|
||||||
@ -841,9 +842,9 @@ yankreg_T *copy_register(int name)
|
|||||||
if (copy->y_size == 0) {
|
if (copy->y_size == 0) {
|
||||||
copy->y_array = NULL;
|
copy->y_array = NULL;
|
||||||
} else {
|
} else {
|
||||||
copy->y_array = xcalloc(copy->y_size, sizeof(char *));
|
copy->y_array = xcalloc(copy->y_size, sizeof(String));
|
||||||
for (size_t i = 0; i < copy->y_size; i++) {
|
for (size_t i = 0; i < copy->y_size; i++) {
|
||||||
copy->y_array[i] = xstrdup(reg->y_array[i]);
|
copy->y_array[i] = copy_string(reg->y_array[i], NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
@ -946,23 +947,24 @@ static int stuff_yank(int regname, char *p)
|
|||||||
xfree(p);
|
xfree(p);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t plen = strlen(p);
|
||||||
yankreg_T *reg = get_yank_register(regname, YREG_YANK);
|
yankreg_T *reg = get_yank_register(regname, YREG_YANK);
|
||||||
if (is_append_register(regname) && reg->y_array != NULL) {
|
if (is_append_register(regname) && reg->y_array != NULL) {
|
||||||
char **pp = &(reg->y_array[reg->y_size - 1]);
|
String *pp = &(reg->y_array[reg->y_size - 1]);
|
||||||
const size_t ppl = strlen(*pp);
|
const size_t tmplen = pp->size + plen;
|
||||||
const size_t pl = strlen(p);
|
char *tmp = xmalloc(tmplen + 1);
|
||||||
char *lp = xmalloc(ppl + pl + 1);
|
memcpy(tmp, pp->data, pp->size);
|
||||||
memcpy(lp, *pp, ppl);
|
memcpy(tmp + pp->size, p, plen);
|
||||||
memcpy(lp + ppl, p, pl);
|
*(tmp + tmplen) = NUL;
|
||||||
*(lp + ppl + pl) = NUL;
|
|
||||||
xfree(p);
|
xfree(p);
|
||||||
xfree(*pp);
|
xfree(pp->data);
|
||||||
*pp = lp;
|
*pp = cbuf_as_string(tmp, tmplen);
|
||||||
} else {
|
} else {
|
||||||
free_register(reg);
|
free_register(reg);
|
||||||
reg->additional_data = NULL;
|
reg->additional_data = NULL;
|
||||||
reg->y_array = xmalloc(sizeof(char *));
|
reg->y_array = xmalloc(sizeof(String));
|
||||||
reg->y_array[0] = p;
|
reg->y_array[0] = cbuf_as_string(p, plen);
|
||||||
reg->y_size = 1;
|
reg->y_size = 1;
|
||||||
reg->y_type = kMTCharWise;
|
reg->y_type = kMTCharWise;
|
||||||
}
|
}
|
||||||
@ -983,7 +985,7 @@ static int execreg_lastc = NUL;
|
|||||||
/// with a \. Lines that start with a comment "\ character are ignored.
|
/// with a \. Lines that start with a comment "\ character are ignored.
|
||||||
/// @returns the concatenated line. The index of the line that should be
|
/// @returns the concatenated line. The index of the line that should be
|
||||||
/// processed next is returned in idx.
|
/// processed next is returned in idx.
|
||||||
static char *execreg_line_continuation(char **lines, size_t *idx)
|
static char *execreg_line_continuation(String *lines, size_t *idx)
|
||||||
{
|
{
|
||||||
size_t i = *idx;
|
size_t i = *idx;
|
||||||
assert(i > 0);
|
assert(i > 0);
|
||||||
@ -996,7 +998,7 @@ static char *execreg_line_continuation(char **lines, size_t *idx)
|
|||||||
// Any line not starting with \ or "\ is the start of the
|
// Any line not starting with \ or "\ is the start of the
|
||||||
// command.
|
// command.
|
||||||
while (--i > 0) {
|
while (--i > 0) {
|
||||||
char *p = skipwhite(lines[i]);
|
char *p = skipwhite(lines[i].data);
|
||||||
if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) {
|
if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1004,9 +1006,9 @@ static char *execreg_line_continuation(char **lines, size_t *idx)
|
|||||||
const size_t cmd_start = i;
|
const size_t cmd_start = i;
|
||||||
|
|
||||||
// join all the lines
|
// join all the lines
|
||||||
ga_concat(&ga, lines[cmd_start]);
|
ga_concat(&ga, lines[cmd_start].data);
|
||||||
for (size_t j = cmd_start + 1; j <= cmd_end; j++) {
|
for (size_t j = cmd_start + 1; j <= cmd_end; j++) {
|
||||||
char *p = skipwhite(lines[j]);
|
char *p = skipwhite(lines[j].data);
|
||||||
if (*p == '\\') {
|
if (*p == '\\') {
|
||||||
// Adjust the growsize to the current length to
|
// Adjust the growsize to the current length to
|
||||||
// speed up concatenating many lines.
|
// speed up concatenating many lines.
|
||||||
@ -1017,7 +1019,7 @@ static char *execreg_line_continuation(char **lines, size_t *idx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ga_append(&ga, NUL);
|
ga_append(&ga, NUL);
|
||||||
char *str = xstrdup(ga.ga_data);
|
char *str = xmemdupz(ga.ga_data, (size_t)ga.ga_len);
|
||||||
ga_clear(&ga);
|
ga_clear(&ga);
|
||||||
|
|
||||||
*idx = i;
|
*idx = i;
|
||||||
@ -1110,7 +1112,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle line-continuation for :@<register>
|
// Handle line-continuation for :@<register>
|
||||||
char *str = reg->y_array[i];
|
char *str = reg->y_array[i].data;
|
||||||
bool free_str = false;
|
bool free_str = false;
|
||||||
if (colon && i > 0) {
|
if (colon && i > 0) {
|
||||||
char *p = skipwhite(str);
|
char *p = skipwhite(str);
|
||||||
@ -1248,7 +1250,7 @@ int insert_reg(int regname, bool literally_arg)
|
|||||||
if (u_save_cursor() == FAIL) {
|
if (u_save_cursor() == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
del_chars(mb_charlen(reg->y_array[0]), true);
|
del_chars(mb_charlen(reg->y_array[0].data), true);
|
||||||
curpos = curwin->w_cursor;
|
curpos = curwin->w_cursor;
|
||||||
if (oneright() == FAIL) {
|
if (oneright() == FAIL) {
|
||||||
// hit end of line, need to put forward (after the current position)
|
// hit end of line, need to put forward (after the current position)
|
||||||
@ -1261,7 +1263,7 @@ int insert_reg(int regname, bool literally_arg)
|
|||||||
AppendCharToRedobuff(regname);
|
AppendCharToRedobuff(regname);
|
||||||
do_put(regname, NULL, dir, 1, PUT_CURSEND);
|
do_put(regname, NULL, dir, 1, PUT_CURSEND);
|
||||||
} else {
|
} else {
|
||||||
stuffescaped(reg->y_array[i], literally);
|
stuffescaped(reg->y_array[i].data, literally);
|
||||||
}
|
}
|
||||||
// Insert a newline between lines and after last line if
|
// Insert a newline between lines and after last line if
|
||||||
// y_type is kMTLineWise.
|
// y_type is kMTLineWise.
|
||||||
@ -1384,7 +1386,7 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
cmdline_paste_str(reg->y_array[i], literally);
|
cmdline_paste_str(reg->y_array[i].data, literally);
|
||||||
|
|
||||||
// Insert ^M between lines, unless `remcr` is true.
|
// Insert ^M between lines, unless `remcr` is true.
|
||||||
if (i < reg->y_size - 1 && !remcr) {
|
if (i < reg->y_size - 1 && !remcr) {
|
||||||
@ -2504,7 +2506,7 @@ void free_register(yankreg_T *reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
|
for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
|
||||||
xfree(reg->y_array[i]);
|
API_CLEAR_STRING(reg->y_array[i]);
|
||||||
}
|
}
|
||||||
XFREE_CLEAR(reg->y_array);
|
XFREE_CLEAR(reg->y_array);
|
||||||
}
|
}
|
||||||
@ -2533,7 +2535,6 @@ bool op_yank(oparg_T *oap, bool message)
|
|||||||
op_yank_reg(oap, message, reg, is_append_register(oap->regname));
|
op_yank_reg(oap, message, reg, is_append_register(oap->regname));
|
||||||
set_clipboard(oap->regname, reg);
|
set_clipboard(oap->regname, reg);
|
||||||
do_autocmd_textyankpost(oap, reg);
|
do_autocmd_textyankpost(oap, reg);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2569,7 +2570,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
|
|||||||
reg->y_size = yanklines;
|
reg->y_size = yanklines;
|
||||||
reg->y_type = yank_type; // set the yank register type
|
reg->y_type = yank_type; // set the yank register type
|
||||||
reg->y_width = 0;
|
reg->y_width = 0;
|
||||||
reg->y_array = xcalloc(yanklines, sizeof(char *));
|
reg->y_array = xcalloc(yanklines, sizeof(String));
|
||||||
reg->additional_data = NULL;
|
reg->additional_data = NULL;
|
||||||
reg->timestamp = os_time();
|
reg->timestamp = os_time();
|
||||||
|
|
||||||
@ -2593,11 +2594,16 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case kMTLineWise:
|
case kMTLineWise:
|
||||||
reg->y_array[y_idx] = xstrdup(ml_get(lnum));
|
reg->y_array[y_idx] = cbuf_to_string(ml_get(lnum), (size_t)ml_get_len(lnum));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kMTCharWise:
|
case kMTCharWise:
|
||||||
charwise_block_prep(oap->start, oap->end, &bd, lnum, oap->inclusive);
|
charwise_block_prep(oap->start, oap->end, &bd, lnum, oap->inclusive);
|
||||||
|
// make sure bd.textlen is not longer than the text
|
||||||
|
int tmp = (int)strlen(bd.textstart);
|
||||||
|
if (tmp < bd.textlen) {
|
||||||
|
bd.textlen = tmp;
|
||||||
|
}
|
||||||
yank_copy_line(reg, &bd, y_idx, false);
|
yank_copy_line(reg, &bd, y_idx, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2609,7 +2615,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
|
|||||||
|
|
||||||
if (curr != reg) { // append the new block to the old block
|
if (curr != reg) { // append the new block to the old block
|
||||||
size_t j;
|
size_t j;
|
||||||
char **new_ptr = xmalloc(sizeof(char *) * (curr->y_size + reg->y_size));
|
String *new_ptr = xmalloc(sizeof(String) * (curr->y_size + reg->y_size));
|
||||||
for (j = 0; j < curr->y_size; j++) {
|
for (j = 0; j < curr->y_size; j++) {
|
||||||
new_ptr[j] = curr->y_array[j];
|
new_ptr[j] = curr->y_array[j];
|
||||||
}
|
}
|
||||||
@ -2625,13 +2631,16 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
|
|||||||
// the new block, unless being Vi compatible.
|
// the new block, unless being Vi compatible.
|
||||||
if (curr->y_type == kMTCharWise
|
if (curr->y_type == kMTCharWise
|
||||||
&& vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) {
|
&& vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) {
|
||||||
char *pnew = xmalloc(strlen(curr->y_array[curr->y_size - 1])
|
char *pnew = xmalloc(curr->y_array[curr->y_size - 1].size
|
||||||
+ strlen(reg->y_array[0]) + 1);
|
+ reg->y_array[0].size + 1);
|
||||||
STRCPY(pnew, curr->y_array[--j]);
|
j--;
|
||||||
strcat(pnew, reg->y_array[0]);
|
STRCPY(pnew, curr->y_array[j].data);
|
||||||
xfree(curr->y_array[j]);
|
STRCPY(pnew + curr->y_array[j].size, reg->y_array[0].data);
|
||||||
xfree(reg->y_array[0]);
|
xfree(curr->y_array[j].data);
|
||||||
curr->y_array[j++] = pnew;
|
curr->y_array[j] = cbuf_as_string(pnew,
|
||||||
|
curr->y_array[j].size + reg->y_array[0].size);
|
||||||
|
j++;
|
||||||
|
API_CLEAR_STRING(reg->y_array[0]);
|
||||||
y_idx = 1;
|
y_idx = 1;
|
||||||
} else {
|
} else {
|
||||||
y_idx = 0;
|
y_idx = 0;
|
||||||
@ -2698,7 +2707,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
|
|||||||
int size = bd->startspaces + bd->endspaces + bd->textlen;
|
int size = bd->startspaces + bd->endspaces + bd->textlen;
|
||||||
assert(size >= 0);
|
assert(size >= 0);
|
||||||
char *pnew = xmallocz((size_t)size);
|
char *pnew = xmallocz((size_t)size);
|
||||||
reg->y_array[y_idx] = pnew;
|
reg->y_array[y_idx].data = pnew;
|
||||||
memset(pnew, ' ', (size_t)bd->startspaces);
|
memset(pnew, ' ', (size_t)bd->startspaces);
|
||||||
pnew += bd->startspaces;
|
pnew += bd->startspaces;
|
||||||
memmove(pnew, bd->textstart, (size_t)bd->textlen);
|
memmove(pnew, bd->textstart, (size_t)bd->textlen);
|
||||||
@ -2714,6 +2723,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*pnew = NUL;
|
*pnew = NUL;
|
||||||
|
reg->y_array[y_idx].size = (size_t)(pnew - reg->y_array[y_idx].data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute autocommands for TextYankPost.
|
/// Execute autocommands for TextYankPost.
|
||||||
@ -2739,7 +2749,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
|
|||||||
// The yanked text contents.
|
// The yanked text contents.
|
||||||
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
|
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
tv_list_append_string(list, reg->y_array[i], -1);
|
tv_list_append_string(list, reg->y_array[i].data, -1);
|
||||||
}
|
}
|
||||||
tv_list_set_lock(list, VAR_FIXED);
|
tv_list_set_lock(list, VAR_FIXED);
|
||||||
tv_dict_add_list(dict, S_LEN("regcontents"), list);
|
tv_dict_add_list(dict, S_LEN("regcontents"), list);
|
||||||
@ -2792,25 +2802,13 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
size_t y_size;
|
size_t y_size;
|
||||||
int y_width = 0;
|
int y_width = 0;
|
||||||
colnr_T vcol = 0;
|
colnr_T vcol = 0;
|
||||||
int incr = 0;
|
String *y_array = NULL;
|
||||||
struct block_def bd;
|
|
||||||
char **y_array = NULL;
|
|
||||||
linenr_T nr_lines = 0;
|
linenr_T nr_lines = 0;
|
||||||
int indent;
|
|
||||||
int orig_indent = 0; // init for gcc
|
|
||||||
int indent_diff = 0; // init for gcc
|
|
||||||
bool first_indent = true;
|
|
||||||
int lendiff = 0;
|
|
||||||
char *insert_string = NULL;
|
|
||||||
bool allocated = false;
|
bool allocated = false;
|
||||||
const pos_T orig_start = curbuf->b_op_start;
|
const pos_T orig_start = curbuf->b_op_start;
|
||||||
const pos_T orig_end = curbuf->b_op_end;
|
const pos_T orig_end = curbuf->b_op_end;
|
||||||
unsigned cur_ve_flags = get_ve_flags(curwin);
|
unsigned cur_ve_flags = get_ve_flags(curwin);
|
||||||
|
|
||||||
if (flags & PUT_FIXINDENT) {
|
|
||||||
orig_indent = get_indent();
|
|
||||||
}
|
|
||||||
|
|
||||||
curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
|
curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
|
||||||
curbuf->b_op_end = curwin->w_cursor; // default for '] mark
|
curbuf->b_op_end = curwin->w_cursor; // default for '] mark
|
||||||
|
|
||||||
@ -2898,8 +2896,9 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
|
|
||||||
// For special registers '%' (file name), '#' (alternate file name) and
|
// For special registers '%' (file name), '#' (alternate file name) and
|
||||||
// ':' (last command line), etc. we have to create a fake yank register.
|
// ':' (last command line), etc. we have to create a fake yank register.
|
||||||
if (!reg && get_spec_reg(regname, &insert_string, &allocated, true)) {
|
String insert_string = STRING_INIT;
|
||||||
if (insert_string == NULL) {
|
if (!reg && get_spec_reg(regname, &insert_string.data, &allocated, true)) {
|
||||||
|
if (insert_string.data == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2912,7 +2911,8 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insert_string != NULL) {
|
if (insert_string.data != NULL) {
|
||||||
|
insert_string.size = strlen(insert_string.data);
|
||||||
y_type = kMTCharWise;
|
y_type = kMTCharWise;
|
||||||
if (regname == '=') {
|
if (regname == '=') {
|
||||||
// For the = register we need to split the string at NL
|
// For the = register we need to split the string at NL
|
||||||
@ -2920,29 +2920,37 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
// Loop twice: count the number of lines and save them.
|
// Loop twice: count the number of lines and save them.
|
||||||
while (true) {
|
while (true) {
|
||||||
y_size = 0;
|
y_size = 0;
|
||||||
char *ptr = insert_string;
|
char *ptr = insert_string.data;
|
||||||
|
size_t ptrlen = insert_string.size;
|
||||||
while (ptr != NULL) {
|
while (ptr != NULL) {
|
||||||
if (y_array != NULL) {
|
if (y_array != NULL) {
|
||||||
y_array[y_size] = ptr;
|
y_array[y_size].data = ptr;
|
||||||
}
|
}
|
||||||
y_size++;
|
y_size++;
|
||||||
ptr = vim_strchr(ptr, '\n');
|
char *tmp = vim_strchr(ptr, '\n');
|
||||||
if (ptr != NULL) {
|
if (tmp == NULL) {
|
||||||
if (y_array != NULL) {
|
if (y_array != NULL) {
|
||||||
*ptr = NUL;
|
y_array[y_size - 1].size = ptrlen;
|
||||||
}
|
}
|
||||||
ptr++;
|
} else {
|
||||||
|
if (y_array != NULL) {
|
||||||
|
*tmp = NUL;
|
||||||
|
y_array[y_size - 1].size = (size_t)(tmp - ptr);
|
||||||
|
ptrlen -= y_array[y_size - 1].size + 1;
|
||||||
|
}
|
||||||
|
tmp++;
|
||||||
// A trailing '\n' makes the register linewise.
|
// A trailing '\n' makes the register linewise.
|
||||||
if (*ptr == NUL) {
|
if (*tmp == NUL) {
|
||||||
y_type = kMTLineWise;
|
y_type = kMTLineWise;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ptr = tmp;
|
||||||
}
|
}
|
||||||
if (y_array != NULL) {
|
if (y_array != NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
y_array = xmalloc(y_size * sizeof(char *));
|
y_array = xmalloc(y_size * sizeof(String));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
y_size = 1; // use fake one-line yank register
|
y_size = 1; // use fake one-line yank register
|
||||||
@ -2976,14 +2984,16 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
char *curline = get_cursor_line_ptr();
|
char *curline = get_cursor_line_ptr();
|
||||||
char *p = curline + curwin->w_cursor.col;
|
char *p = get_cursor_pos_ptr();
|
||||||
|
char *const p_orig = p;
|
||||||
|
const size_t plen = (size_t)get_cursor_pos_len();
|
||||||
if (dir == FORWARD && *p != NUL) {
|
if (dir == FORWARD && *p != NUL) {
|
||||||
MB_PTR_ADV(p);
|
MB_PTR_ADV(p);
|
||||||
}
|
}
|
||||||
// we need this later for the correct extmark_splice() event
|
// we need this later for the correct extmark_splice() event
|
||||||
split_pos = (colnr_T)(p - curline);
|
split_pos = (colnr_T)(p - curline);
|
||||||
|
|
||||||
char *ptr = xstrdup(p);
|
char *ptr = xmemdupz(p, plen - (size_t)(p - p_orig));
|
||||||
ml_append(curwin->w_cursor.lnum, ptr, 0, false);
|
ml_append(curwin->w_cursor.lnum, ptr, 0, false);
|
||||||
xfree(ptr);
|
xfree(ptr);
|
||||||
|
|
||||||
@ -3047,8 +3057,6 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
int yanklen = (int)strlen(y_array[0]);
|
|
||||||
|
|
||||||
if (cur_ve_flags == VE_ALL && y_type == kMTCharWise) {
|
if (cur_ve_flags == VE_ALL && y_type == kMTCharWise) {
|
||||||
if (gchar_cursor() == TAB) {
|
if (gchar_cursor() == TAB) {
|
||||||
int viscol = getviscol();
|
int viscol = getviscol();
|
||||||
@ -3072,6 +3080,8 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
|
|
||||||
// Block mode
|
// Block mode
|
||||||
if (y_type == kMTBlockWise) {
|
if (y_type == kMTBlockWise) {
|
||||||
|
int incr = 0;
|
||||||
|
struct block_def bd;
|
||||||
int c = gchar_cursor();
|
int c = gchar_cursor();
|
||||||
colnr_T endcol2 = 0;
|
colnr_T endcol2 = 0;
|
||||||
|
|
||||||
@ -3164,14 +3174,14 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yanklen = (int)strlen(y_array[i]);
|
const int yanklen = (int)y_array[i].size;
|
||||||
|
|
||||||
if ((flags & PUT_BLOCK_INNER) == 0) {
|
if ((flags & PUT_BLOCK_INNER) == 0) {
|
||||||
// calculate number of spaces required to fill right side of block
|
// calculate number of spaces required to fill right side of block
|
||||||
spaces = y_width + 1;
|
spaces = y_width + 1;
|
||||||
|
|
||||||
cstype = init_charsize_arg(&csarg, curwin, 0, y_array[i]);
|
cstype = init_charsize_arg(&csarg, curwin, 0, y_array[i].data);
|
||||||
ci = utf_ptr2StrCharInfo(y_array[i]);
|
ci = utf_ptr2StrCharInfo(y_array[i].data);
|
||||||
while (*ci.ptr != NUL) {
|
while (*ci.ptr != NUL) {
|
||||||
spaces -= win_charsize(cstype, 0, ci.ptr, ci.chr.value, &csarg).width;
|
spaces -= win_charsize(cstype, 0, ci.ptr, ci.chr.value, &csarg).width;
|
||||||
ci = utfc_next(ci);
|
ci = utfc_next(ci);
|
||||||
@ -3202,7 +3212,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
|
|
||||||
// insert the new text
|
// insert the new text
|
||||||
for (int j = 0; j < count; j++) {
|
for (int j = 0; j < count; j++) {
|
||||||
memmove(ptr, y_array[i], (size_t)yanklen);
|
memmove(ptr, y_array[i].data, (size_t)yanklen);
|
||||||
ptr += yanklen;
|
ptr += yanklen;
|
||||||
|
|
||||||
// insert block's trailing spaces only if there's text behind
|
// insert block's trailing spaces only if there's text behind
|
||||||
@ -3254,6 +3264,8 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
curwin->w_cursor.lnum = lnum;
|
curwin->w_cursor.lnum = lnum;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const int yanklen = (int)y_array[0].size;
|
||||||
|
|
||||||
// Character or Line mode
|
// Character or Line mode
|
||||||
if (y_type == kMTCharWise) {
|
if (y_type == kMTCharWise) {
|
||||||
// if type is kMTCharWise, FORWARD is the same as BACKWARD on the next
|
// if type is kMTCharWise, FORWARD is the same as BACKWARD on the next
|
||||||
@ -3326,10 +3338,10 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
memmove(newp, oldp, (size_t)col);
|
memmove(newp, oldp, (size_t)col);
|
||||||
char *ptr = newp + col;
|
char *ptr = newp + col;
|
||||||
for (size_t i = 0; i < (size_t)count; i++) {
|
for (size_t i = 0; i < (size_t)count; i++) {
|
||||||
memmove(ptr, y_array[0], (size_t)yanklen);
|
memmove(ptr, y_array[0].data, (size_t)yanklen);
|
||||||
ptr += yanklen;
|
ptr += yanklen;
|
||||||
}
|
}
|
||||||
STRMOVE(ptr, oldp + col);
|
memmove(ptr, oldp + col, (size_t)(oldlen - col) + 1); // +1 for NUL
|
||||||
ml_replace(lnum, newp, false);
|
ml_replace(lnum, newp, false);
|
||||||
|
|
||||||
// compute the byte offset for the last character
|
// compute the byte offset for the last character
|
||||||
@ -3367,6 +3379,15 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
linenr_T new_lnum = new_cursor.lnum;
|
linenr_T new_lnum = new_cursor.lnum;
|
||||||
|
int indent;
|
||||||
|
int orig_indent = 0;
|
||||||
|
int indent_diff = 0; // init for gcc
|
||||||
|
bool first_indent = true;
|
||||||
|
int lendiff = 0;
|
||||||
|
|
||||||
|
if (flags & PUT_FIXINDENT) {
|
||||||
|
orig_indent = get_indent();
|
||||||
|
}
|
||||||
|
|
||||||
// Insert at least one line. When y_type is kMTCharWise, break the first
|
// Insert at least one line. When y_type is kMTCharWise, break the first
|
||||||
// line in two.
|
// line in two.
|
||||||
@ -3378,10 +3399,11 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
// Then append y_array[0] to first line.
|
// Then append y_array[0] to first line.
|
||||||
lnum = new_cursor.lnum;
|
lnum = new_cursor.lnum;
|
||||||
char *ptr = ml_get(lnum) + col;
|
char *ptr = ml_get(lnum) + col;
|
||||||
totlen = strlen(y_array[y_size - 1]);
|
size_t ptrlen = (size_t)ml_get_len(lnum) - (size_t)col;
|
||||||
char *newp = xmalloc((size_t)ml_get_len(lnum) - (size_t)col + totlen + 1);
|
totlen = y_array[y_size - 1].size;
|
||||||
STRCPY(newp, y_array[y_size - 1]);
|
char *newp = xmalloc(ptrlen + totlen + 1);
|
||||||
strcat(newp, ptr);
|
STRCPY(newp, y_array[y_size - 1].data);
|
||||||
|
STRCPY(newp + totlen, ptr);
|
||||||
// insert second line
|
// insert second line
|
||||||
ml_append(lnum, newp, 0, false);
|
ml_append(lnum, newp, 0, false);
|
||||||
new_lnum++;
|
new_lnum++;
|
||||||
@ -3392,7 +3414,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
// copy first part of line
|
// copy first part of line
|
||||||
memmove(newp, oldp, (size_t)col);
|
memmove(newp, oldp, (size_t)col);
|
||||||
// append to first line
|
// append to first line
|
||||||
memmove(newp + col, y_array[0], (size_t)yanklen + 1);
|
memmove(newp + col, y_array[0].data, (size_t)yanklen + 1);
|
||||||
ml_replace(lnum, newp, false);
|
ml_replace(lnum, newp, false);
|
||||||
|
|
||||||
curwin->w_cursor.lnum = lnum;
|
curwin->w_cursor.lnum = lnum;
|
||||||
@ -3401,7 +3423,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
|
|
||||||
for (; i < y_size; i++) {
|
for (; i < y_size; i++) {
|
||||||
if ((y_type != kMTCharWise || i < y_size - 1)) {
|
if ((y_type != kMTCharWise || i < y_size - 1)) {
|
||||||
if (ml_append(lnum, y_array[i], 0, false) == FAIL) {
|
if (ml_append(lnum, y_array[i].data, 0, false) == FAIL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
new_lnum++;
|
new_lnum++;
|
||||||
@ -3440,9 +3462,9 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
|||||||
if (y_type == kMTCharWise
|
if (y_type == kMTCharWise
|
||||||
|| (y_type == kMTLineWise && (flags & PUT_LINE_SPLIT))) {
|
|| (y_type == kMTLineWise && (flags & PUT_LINE_SPLIT))) {
|
||||||
for (i = 0; i < y_size - 1; i++) {
|
for (i = 0; i < y_size - 1; i++) {
|
||||||
totsize += (bcount_t)strlen(y_array[i]) + 1;
|
totsize += (bcount_t)y_array[i].size + 1;
|
||||||
}
|
}
|
||||||
lastsize = (int)strlen(y_array[y_size - 1]);
|
lastsize = (int)y_array[y_size - 1].size;
|
||||||
totsize += lastsize;
|
totsize += lastsize;
|
||||||
}
|
}
|
||||||
if (y_type == kMTCharWise) {
|
if (y_type == kMTCharWise) {
|
||||||
@ -3486,13 +3508,13 @@ error:
|
|||||||
// Put the '] mark on the first byte of the last inserted character.
|
// Put the '] mark on the first byte of the last inserted character.
|
||||||
// Correct the length for change in indent.
|
// Correct the length for change in indent.
|
||||||
curbuf->b_op_end.lnum = new_lnum;
|
curbuf->b_op_end.lnum = new_lnum;
|
||||||
size_t len = strlen(y_array[y_size - 1]);
|
col = (colnr_T)y_array[y_size - 1].size - lendiff;
|
||||||
col = (colnr_T)len - lendiff;
|
|
||||||
if (col > 1) {
|
if (col > 1) {
|
||||||
curbuf->b_op_end.col = col - 1;
|
curbuf->b_op_end.col = col - 1;
|
||||||
if (len > 0) {
|
if (y_array[y_size - 1].size > 0) {
|
||||||
curbuf->b_op_end.col -= utf_head_off(y_array[y_size - 1],
|
curbuf->b_op_end.col -= utf_head_off(y_array[y_size - 1].data,
|
||||||
y_array[y_size - 1] + len - 1);
|
y_array[y_size - 1].data
|
||||||
|
+ y_array[y_size - 1].size - 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
curbuf->b_op_end.col = 0;
|
curbuf->b_op_end.col = 0;
|
||||||
@ -3550,7 +3572,7 @@ end:
|
|||||||
curbuf->b_op_end = orig_end;
|
curbuf->b_op_end = orig_end;
|
||||||
}
|
}
|
||||||
if (allocated) {
|
if (allocated) {
|
||||||
xfree(insert_string);
|
xfree(insert_string.data);
|
||||||
}
|
}
|
||||||
if (regname == '=') {
|
if (regname == '=') {
|
||||||
xfree(y_array);
|
xfree(y_array);
|
||||||
@ -3672,7 +3694,7 @@ void ex_display(exarg_T *eap)
|
|||||||
bool do_show = false;
|
bool do_show = false;
|
||||||
|
|
||||||
for (size_t j = 0; !do_show && j < yb->y_size; j++) {
|
for (size_t j = 0; !do_show && j < yb->y_size; j++) {
|
||||||
do_show = !message_filtered(yb->y_array[j]);
|
do_show = !message_filtered(yb->y_array[j].data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_show || yb->y_size == 0) {
|
if (do_show || yb->y_size == 0) {
|
||||||
@ -3690,7 +3712,7 @@ void ex_display(exarg_T *eap)
|
|||||||
msg_puts_attr("^J", attr);
|
msg_puts_attr("^J", attr);
|
||||||
n -= 2;
|
n -= 2;
|
||||||
}
|
}
|
||||||
for (p = yb->y_array[j];
|
for (p = yb->y_array[j].data;
|
||||||
*p != NUL && (n -= ptr2cells(p)) >= 0; p++) {
|
*p != NUL && (n -= ptr2cells(p)) >= 0; p++) {
|
||||||
int clen = utfc_ptr2len(p);
|
int clen = utfc_ptr2len(p);
|
||||||
msg_outtrans_len(p, clen, 0);
|
msg_outtrans_len(p, clen, 0);
|
||||||
@ -4849,7 +4871,7 @@ void *get_reg_contents(int regname, int flags)
|
|||||||
if (flags & kGRegList) {
|
if (flags & kGRegList) {
|
||||||
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
|
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
tv_list_append_string(list, reg->y_array[i], -1);
|
tv_list_append_string(list, reg->y_array[i].data, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
@ -4858,9 +4880,8 @@ void *get_reg_contents(int regname, int flags)
|
|||||||
// Compute length of resulting string.
|
// Compute length of resulting string.
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
len += strlen(reg->y_array[i]);
|
len += reg->y_array[i].size;
|
||||||
// Insert a newline between lines and after last line if
|
// Insert a newline between lines and after last line if y_type is kMTLineWise.
|
||||||
// y_type is kMTLineWise.
|
|
||||||
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
|
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
@ -4871,11 +4892,10 @@ void *get_reg_contents(int regname, int flags)
|
|||||||
// Copy the lines of the yank register into the string.
|
// Copy the lines of the yank register into the string.
|
||||||
len = 0;
|
len = 0;
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
STRCPY(retval + len, reg->y_array[i]);
|
STRCPY(retval + len, reg->y_array[i].data);
|
||||||
len += strlen(retval + len);
|
len += reg->y_array[i].size;
|
||||||
|
|
||||||
// Insert a NL between lines and after the last line if y_type is
|
// Insert a newline between lines and after the last line if y_type is kMTLineWise.
|
||||||
// kMTLineWise.
|
|
||||||
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
|
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
|
||||||
retval[len++] = '\n';
|
retval[len++] = '\n';
|
||||||
}
|
}
|
||||||
@ -4993,8 +5013,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app
|
|||||||
semsg(_(e_nobufnr), (int64_t)num);
|
semsg(_(e_nobufnr), (int64_t)num);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buf = buflist_findnr(buflist_findpat(str, str + strlen(str),
|
buf = buflist_findnr(buflist_findpat(str, str + len, true, false, false));
|
||||||
true, false, false));
|
|
||||||
}
|
}
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
return;
|
return;
|
||||||
@ -5090,7 +5109,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grow the register array to hold the pointers to the new lines.
|
// Grow the register array to hold the pointers to the new lines.
|
||||||
char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char *));
|
String *pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(String));
|
||||||
y_ptr->y_array = pp;
|
y_ptr->y_array = pp;
|
||||||
|
|
||||||
size_t lnum = y_ptr->y_size; // The current line number.
|
size_t lnum = y_ptr->y_size; // The current line number.
|
||||||
@ -5102,7 +5121,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
|
|||||||
if (str_list) {
|
if (str_list) {
|
||||||
for (char **ss = (char **)str; *ss != NULL; ss++, lnum++) {
|
for (char **ss = (char **)str; *ss != NULL; ss++, lnum++) {
|
||||||
size_t ss_len = strlen(*ss);
|
size_t ss_len = strlen(*ss);
|
||||||
pp[lnum] = xmemdupz(*ss, ss_len);
|
pp[lnum] = cbuf_to_string(*ss, ss_len);
|
||||||
maxlen = MAX(maxlen, ss_len);
|
maxlen = MAX(maxlen, ss_len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -5115,22 +5134,22 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
|
|||||||
maxlen = MAX(maxlen, line_len);
|
maxlen = MAX(maxlen, line_len);
|
||||||
|
|
||||||
// When appending, copy the previous line and free it after.
|
// When appending, copy the previous line and free it after.
|
||||||
size_t extra = append ? strlen(pp[--lnum]) : 0;
|
size_t extra = append ? pp[--lnum].size : 0;
|
||||||
char *s = xmallocz(line_len + extra);
|
char *s = xmallocz(line_len + extra);
|
||||||
if (extra > 0) {
|
if (extra > 0) {
|
||||||
memcpy(s, pp[lnum], extra);
|
memcpy(s, pp[lnum].data, extra);
|
||||||
}
|
}
|
||||||
memcpy(s + extra, start, line_len);
|
memcpy(s + extra, start, line_len);
|
||||||
size_t s_len = extra + line_len;
|
size_t s_len = extra + line_len;
|
||||||
|
|
||||||
if (append) {
|
if (append) {
|
||||||
xfree(pp[lnum]);
|
xfree(pp[lnum].data);
|
||||||
append = false; // only first line is appended
|
append = false; // only first line is appended
|
||||||
}
|
}
|
||||||
pp[lnum] = s;
|
pp[lnum] = cbuf_as_string(s, s_len);
|
||||||
|
|
||||||
// Convert NULs to '\n' to prevent truncation.
|
// Convert NULs to '\n' to prevent truncation.
|
||||||
memchrsub(pp[lnum], NUL, '\n', s_len);
|
memchrsub(pp[lnum].data, NUL, '\n', s_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y_ptr->y_type = yank_type;
|
y_ptr->y_type = yank_type;
|
||||||
@ -6421,7 +6440,7 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines)
|
|||||||
|
|
||||||
void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
|
void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
|
||||||
{
|
{
|
||||||
if (reg->y_size > 0 && strlen(reg->y_array[reg->y_size - 1]) == 0) {
|
if (reg->y_size > 0 && reg->y_array[reg->y_size - 1].size == 0) {
|
||||||
// a known-to-be charwise yank might have a final linebreak
|
// a known-to-be charwise yank might have a final linebreak
|
||||||
// but otherwise there is no line after the final newline
|
// but otherwise there is no line after the final newline
|
||||||
if (reg->y_type != kMTCharWise) {
|
if (reg->y_type != kMTCharWise) {
|
||||||
@ -6441,7 +6460,7 @@ void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
|
|||||||
if (reg->y_type == kMTBlockWise) {
|
if (reg->y_type == kMTBlockWise) {
|
||||||
size_t maxlen = 0;
|
size_t maxlen = 0;
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
size_t rowlen = strlen(reg->y_array[i]);
|
size_t rowlen = reg->y_array[i].size;
|
||||||
maxlen = MAX(maxlen, rowlen);
|
maxlen = MAX(maxlen, rowlen);
|
||||||
}
|
}
|
||||||
assert(maxlen <= INT_MAX);
|
assert(maxlen <= INT_MAX);
|
||||||
@ -6511,7 +6530,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
|||||||
reg->y_type = kMTUnknown;
|
reg->y_type = kMTUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg->y_array = xcalloc((size_t)tv_list_len(lines), sizeof(char *));
|
reg->y_array = xcalloc((size_t)tv_list_len(lines), sizeof(String));
|
||||||
reg->y_size = (size_t)tv_list_len(lines);
|
reg->y_size = (size_t)tv_list_len(lines);
|
||||||
reg->additional_data = NULL;
|
reg->additional_data = NULL;
|
||||||
reg->timestamp = 0;
|
reg->timestamp = 0;
|
||||||
@ -6523,14 +6542,15 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
|||||||
if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
|
if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
reg->y_array[tv_idx++] = xstrdupnul(TV_LIST_ITEM_TV(li)->vval.v_string);
|
const char *s = TV_LIST_ITEM_TV(li)->vval.v_string;
|
||||||
|
reg->y_array[tv_idx++] = cstr_to_string(s != NULL ? s : "");
|
||||||
});
|
});
|
||||||
|
|
||||||
if (reg->y_size > 0 && strlen(reg->y_array[reg->y_size - 1]) == 0) {
|
if (reg->y_size > 0 && reg->y_array[reg->y_size - 1].size == 0) {
|
||||||
// a known-to-be charwise yank might have a final linebreak
|
// a known-to-be charwise yank might have a final linebreak
|
||||||
// but otherwise there is no line after the final newline
|
// but otherwise there is no line after the final newline
|
||||||
if (reg->y_type != kMTCharWise) {
|
if (reg->y_type != kMTCharWise) {
|
||||||
xfree(reg->y_array[reg->y_size - 1]);
|
xfree(reg->y_array[reg->y_size - 1].data);
|
||||||
reg->y_size--;
|
reg->y_size--;
|
||||||
if (reg->y_type == kMTUnknown) {
|
if (reg->y_type == kMTUnknown) {
|
||||||
reg->y_type = kMTLineWise;
|
reg->y_type = kMTLineWise;
|
||||||
@ -6545,7 +6565,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
|||||||
if (reg->y_type == kMTBlockWise) {
|
if (reg->y_type == kMTBlockWise) {
|
||||||
size_t maxlen = 0;
|
size_t maxlen = 0;
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
size_t rowlen = strlen(reg->y_array[i]);
|
size_t rowlen = reg->y_array[i].size;
|
||||||
maxlen = MAX(maxlen, rowlen);
|
maxlen = MAX(maxlen, rowlen);
|
||||||
}
|
}
|
||||||
assert(maxlen <= INT_MAX);
|
assert(maxlen <= INT_MAX);
|
||||||
@ -6558,7 +6578,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
|||||||
err:
|
err:
|
||||||
if (reg->y_array) {
|
if (reg->y_array) {
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
xfree(reg->y_array[i]);
|
xfree(reg->y_array[i].data);
|
||||||
}
|
}
|
||||||
xfree(reg->y_array);
|
xfree(reg->y_array);
|
||||||
}
|
}
|
||||||
@ -6582,7 +6602,7 @@ static void set_clipboard(int name, yankreg_T *reg)
|
|||||||
list_T *const lines = tv_list_alloc((ptrdiff_t)reg->y_size + (reg->y_type != kMTCharWise));
|
list_T *const lines = tv_list_alloc((ptrdiff_t)reg->y_size + (reg->y_type != kMTCharWise));
|
||||||
|
|
||||||
for (size_t i = 0; i < reg->y_size; i++) {
|
for (size_t i = 0; i < reg->y_size; i++) {
|
||||||
tv_list_append_string(lines, reg->y_array[i], -1);
|
tv_list_append_string(lines, reg->y_array[i].data, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
char regtype;
|
char regtype;
|
||||||
@ -6666,7 +6686,7 @@ static inline bool reg_empty(const yankreg_T *const reg)
|
|||||||
|| reg->y_size == 0
|
|| reg->y_size == 0
|
||||||
|| (reg->y_size == 1
|
|| (reg->y_size == 1
|
||||||
&& reg->y_type == kMTCharWise
|
&& reg->y_type == kMTCharWise
|
||||||
&& *(reg->y_array[0]) == NUL));
|
&& reg->y_array[0].size == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over global registers.
|
/// Iterate over global registers.
|
||||||
|
@ -105,7 +105,7 @@ enum GRegFlags {
|
|||||||
|
|
||||||
/// Definition of one register
|
/// Definition of one register
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char **y_array; ///< Pointer to an array of line pointers.
|
String *y_array; ///< Pointer to an array of Strings.
|
||||||
size_t y_size; ///< Number of lines in y_array.
|
size_t y_size; ///< Number of lines in y_array.
|
||||||
MotionType y_type; ///< Register type
|
MotionType y_type; ///< Register type
|
||||||
colnr_T y_width; ///< Register width (only valid for y_type == kBlockWise).
|
colnr_T y_width; ///< Register width (only valid for y_type == kBlockWise).
|
||||||
|
@ -246,7 +246,7 @@ typedef struct {
|
|||||||
struct reg { // yankreg_T
|
struct reg { // yankreg_T
|
||||||
char name;
|
char name;
|
||||||
MotionType type;
|
MotionType type;
|
||||||
char **contents;
|
String *contents;
|
||||||
bool is_unnamed;
|
bool is_unnamed;
|
||||||
size_t contents_size;
|
size_t contents_size;
|
||||||
size_t width;
|
size_t width;
|
||||||
@ -1491,7 +1491,7 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
|
|||||||
PACK_KEY(REG_KEY_CONTENTS);
|
PACK_KEY(REG_KEY_CONTENTS);
|
||||||
mpack_array(&sbuf.ptr, (uint32_t)entry.data.reg.contents_size);
|
mpack_array(&sbuf.ptr, (uint32_t)entry.data.reg.contents_size);
|
||||||
for (size_t i = 0; i < entry.data.reg.contents_size; i++) {
|
for (size_t i = 0; i < entry.data.reg.contents_size; i++) {
|
||||||
mpack_bin(cstr_as_string(entry.data.reg.contents[i]), &sbuf);
|
mpack_bin(entry.data.reg.contents[i], &sbuf);
|
||||||
}
|
}
|
||||||
PACK_KEY(KEY_NAME_CHAR);
|
PACK_KEY(KEY_NAME_CHAR);
|
||||||
mpack_uint(&sbuf.ptr, (uint8_t)entry.data.reg.name);
|
mpack_uint(&sbuf.ptr, (uint8_t)entry.data.reg.name);
|
||||||
@ -2930,7 +2930,7 @@ static void shada_free_shada_entry(ShadaEntry *const entry)
|
|||||||
break;
|
break;
|
||||||
case kSDItemRegister:
|
case kSDItemRegister:
|
||||||
for (size_t i = 0; i < entry->data.reg.contents_size; i++) {
|
for (size_t i = 0; i < entry->data.reg.contents_size; i++) {
|
||||||
xfree(entry->data.reg.contents[i]);
|
api_free_string(entry->data.reg.contents[i]);
|
||||||
}
|
}
|
||||||
xfree(entry->data.reg.contents);
|
xfree(entry->data.reg.contents);
|
||||||
break;
|
break;
|
||||||
@ -3312,9 +3312,9 @@ shada_read_next_item_start:
|
|||||||
goto shada_read_next_item_error;
|
goto shada_read_next_item_error;
|
||||||
}
|
}
|
||||||
entry->data.reg.contents_size = it.rc.size;
|
entry->data.reg.contents_size = it.rc.size;
|
||||||
entry->data.reg.contents = xmalloc(it.rc.size * sizeof(char *));
|
entry->data.reg.contents = xmalloc(it.rc.size * sizeof(String));
|
||||||
for (size_t j = 0; j < it.rc.size; j++) {
|
for (size_t j = 0; j < it.rc.size; j++) {
|
||||||
entry->data.reg.contents[j] = xmemdupz(it.rc.items[j].data, it.rc.items[j].size);
|
entry->data.reg.contents[j] = copy_string(it.rc.items[j], NULL);
|
||||||
}
|
}
|
||||||
kv_destroy(it.rc);
|
kv_destroy(it.rc);
|
||||||
|
|
||||||
|
@ -895,13 +895,13 @@ static bool is_filter_char(int c)
|
|||||||
return !!(tpf_flags & flag);
|
return !!(tpf_flags & flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_paste(int count, char **y_array, size_t y_size)
|
void terminal_paste(int count, String *y_array, size_t y_size)
|
||||||
{
|
{
|
||||||
if (y_size == 0) {
|
if (y_size == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vterm_keyboard_start_paste(curbuf->terminal->vt);
|
vterm_keyboard_start_paste(curbuf->terminal->vt);
|
||||||
size_t buff_len = strlen(y_array[0]);
|
size_t buff_len = y_array[0].size;
|
||||||
char *buff = xmalloc(buff_len);
|
char *buff = xmalloc(buff_len);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
// feed the lines to the terminal
|
// feed the lines to the terminal
|
||||||
@ -914,13 +914,13 @@ void terminal_paste(int count, char **y_array, size_t y_size)
|
|||||||
terminal_send(curbuf->terminal, "\n", 1);
|
terminal_send(curbuf->terminal, "\n", 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
size_t len = strlen(y_array[j]);
|
size_t len = y_array[j].size;
|
||||||
if (len > buff_len) {
|
if (len > buff_len) {
|
||||||
buff = xrealloc(buff, len);
|
buff = xrealloc(buff, len);
|
||||||
buff_len = len;
|
buff_len = len;
|
||||||
}
|
}
|
||||||
char *dst = buff;
|
char *dst = buff;
|
||||||
char *src = y_array[j];
|
char *src = y_array[j].data;
|
||||||
while (*src != NUL) {
|
while (*src != NUL) {
|
||||||
len = (size_t)utf_ptr2len(src);
|
len = (size_t)utf_ptr2len(src);
|
||||||
int c = utf_ptr2char(src);
|
int c = utf_ptr2char(src);
|
||||||
|
Loading…
Reference in New Issue
Block a user