forked from aniani/vim
patch 8.1.1736: viminfo support is spread out
Problem: Viminfo support is spread out. Solution: Move more viminfo code to viminfo.c. (Yegappan Lakshmanan, closes #4717) Reorder code to make most functions static.
This commit is contained in:
470
src/ops.c
470
src/ops.c
@@ -23,45 +23,6 @@
|
||||
* 37 = Selection register '*'. Only if FEAT_CLIPBOARD defined
|
||||
* 38 = Clipboard register '+'. Only if FEAT_CLIPBOARD and FEAT_X11 defined
|
||||
*/
|
||||
/*
|
||||
* Symbolic names for some registers.
|
||||
*/
|
||||
#define DELETION_REGISTER 36
|
||||
#ifdef FEAT_CLIPBOARD
|
||||
# define STAR_REGISTER 37
|
||||
# ifdef FEAT_X11
|
||||
# define PLUS_REGISTER 38
|
||||
# else
|
||||
# define PLUS_REGISTER STAR_REGISTER /* there is only one */
|
||||
# endif
|
||||
#endif
|
||||
#ifdef FEAT_DND
|
||||
# define TILDE_REGISTER (PLUS_REGISTER + 1)
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_CLIPBOARD
|
||||
# ifdef FEAT_DND
|
||||
# define NUM_REGISTERS (TILDE_REGISTER + 1)
|
||||
# else
|
||||
# define NUM_REGISTERS (PLUS_REGISTER + 1)
|
||||
# endif
|
||||
#else
|
||||
# define NUM_REGISTERS 37
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Each yank register has an array of pointers to lines.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char_u **y_array; /* pointer to array of line pointers */
|
||||
linenr_T y_size; /* number of lines in y_array */
|
||||
char_u y_type; /* MLINE, MCHAR or MBLOCK */
|
||||
colnr_T y_width; /* only set if y_type == MBLOCK */
|
||||
#ifdef FEAT_VIMINFO
|
||||
time_t y_time_set;
|
||||
#endif
|
||||
} yankreg_T;
|
||||
|
||||
static yankreg_T y_regs[NUM_REGISTERS];
|
||||
|
||||
@@ -160,6 +121,31 @@ static char opchars[][3] =
|
||||
{Ctrl_X, NUL, OPF_CHANGE}, // OP_NR_SUB
|
||||
};
|
||||
|
||||
yankreg_T *
|
||||
get_y_regs(void)
|
||||
{
|
||||
return y_regs;
|
||||
}
|
||||
|
||||
yankreg_T *
|
||||
get_y_current(void)
|
||||
{
|
||||
return y_current;
|
||||
}
|
||||
|
||||
yankreg_T *
|
||||
get_y_previous(void)
|
||||
{
|
||||
return y_previous;
|
||||
}
|
||||
|
||||
void
|
||||
set_y_previous(yankreg_T *yreg)
|
||||
{
|
||||
y_previous = yreg;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Translate a command name into an operator type.
|
||||
* Must only be called with a valid operator name!
|
||||
@@ -1192,6 +1178,18 @@ stuff_yank(int regname, char_u *p)
|
||||
|
||||
static int execreg_lastc = NUL;
|
||||
|
||||
int
|
||||
get_execreg_lastc(void)
|
||||
{
|
||||
return execreg_lastc;
|
||||
}
|
||||
|
||||
void
|
||||
set_execreg_lastc(int lastc)
|
||||
{
|
||||
execreg_lastc = lastc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a yank register: copy it into the stuff buffer.
|
||||
*
|
||||
@@ -5958,400 +5956,6 @@ theend:
|
||||
return did_change;
|
||||
}
|
||||
|
||||
#ifdef FEAT_VIMINFO
|
||||
|
||||
static yankreg_T *y_read_regs = NULL;
|
||||
|
||||
#define REG_PREVIOUS 1
|
||||
#define REG_EXEC 2
|
||||
|
||||
/*
|
||||
* Prepare for reading viminfo registers when writing viminfo later.
|
||||
*/
|
||||
void
|
||||
prepare_viminfo_registers(void)
|
||||
{
|
||||
y_read_regs = ALLOC_CLEAR_MULT(yankreg_T, NUM_REGISTERS);
|
||||
}
|
||||
|
||||
void
|
||||
finish_viminfo_registers(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (y_read_regs != NULL)
|
||||
{
|
||||
for (i = 0; i < NUM_REGISTERS; ++i)
|
||||
if (y_read_regs[i].y_array != NULL)
|
||||
{
|
||||
for (j = 0; j < y_read_regs[i].y_size; j++)
|
||||
vim_free(y_read_regs[i].y_array[j]);
|
||||
vim_free(y_read_regs[i].y_array);
|
||||
}
|
||||
VIM_CLEAR(y_read_regs);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
read_viminfo_register(vir_T *virp, int force)
|
||||
{
|
||||
int eof;
|
||||
int do_it = TRUE;
|
||||
int size;
|
||||
int limit;
|
||||
int i;
|
||||
int set_prev = FALSE;
|
||||
char_u *str;
|
||||
char_u **array = NULL;
|
||||
int new_type = MCHAR; /* init to shut up compiler */
|
||||
colnr_T new_width = 0; /* init to shut up compiler */
|
||||
|
||||
/* We only get here (hopefully) if line[0] == '"' */
|
||||
str = virp->vir_line + 1;
|
||||
|
||||
/* If the line starts with "" this is the y_previous register. */
|
||||
if (*str == '"')
|
||||
{
|
||||
set_prev = TRUE;
|
||||
str++;
|
||||
}
|
||||
|
||||
if (!ASCII_ISALNUM(*str) && *str != '-')
|
||||
{
|
||||
if (viminfo_error("E577: ", _("Illegal register name"), virp->vir_line))
|
||||
return TRUE; /* too many errors, pretend end-of-file */
|
||||
do_it = FALSE;
|
||||
}
|
||||
get_yank_register(*str++, FALSE);
|
||||
if (!force && y_current->y_array != NULL)
|
||||
do_it = FALSE;
|
||||
|
||||
if (*str == '@')
|
||||
{
|
||||
/* "x@: register x used for @@ */
|
||||
if (force || execreg_lastc == NUL)
|
||||
execreg_lastc = str[-1];
|
||||
}
|
||||
|
||||
size = 0;
|
||||
limit = 100; /* Optimized for registers containing <= 100 lines */
|
||||
if (do_it)
|
||||
{
|
||||
/*
|
||||
* Build the new register in array[].
|
||||
* y_array is kept as-is until done.
|
||||
* The "do_it" flag is reset when something is wrong, in which case
|
||||
* array[] needs to be freed.
|
||||
*/
|
||||
if (set_prev)
|
||||
y_previous = y_current;
|
||||
array = ALLOC_MULT(char_u *, limit);
|
||||
str = skipwhite(skiptowhite(str));
|
||||
if (STRNCMP(str, "CHAR", 4) == 0)
|
||||
new_type = MCHAR;
|
||||
else if (STRNCMP(str, "BLOCK", 5) == 0)
|
||||
new_type = MBLOCK;
|
||||
else
|
||||
new_type = MLINE;
|
||||
/* get the block width; if it's missing we get a zero, which is OK */
|
||||
str = skipwhite(skiptowhite(str));
|
||||
new_width = getdigits(&str);
|
||||
}
|
||||
|
||||
while (!(eof = viminfo_readline(virp))
|
||||
&& (virp->vir_line[0] == TAB || virp->vir_line[0] == '<'))
|
||||
{
|
||||
if (do_it)
|
||||
{
|
||||
if (size == limit)
|
||||
{
|
||||
char_u **new_array = (char_u **)
|
||||
alloc(limit * 2 * sizeof(char_u *));
|
||||
|
||||
if (new_array == NULL)
|
||||
{
|
||||
do_it = FALSE;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < limit; i++)
|
||||
new_array[i] = array[i];
|
||||
vim_free(array);
|
||||
array = new_array;
|
||||
limit *= 2;
|
||||
}
|
||||
str = viminfo_readstring(virp, 1, TRUE);
|
||||
if (str != NULL)
|
||||
array[size++] = str;
|
||||
else
|
||||
/* error, don't store the result */
|
||||
do_it = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_it)
|
||||
{
|
||||
/* free y_array[] */
|
||||
for (i = 0; i < y_current->y_size; i++)
|
||||
vim_free(y_current->y_array[i]);
|
||||
vim_free(y_current->y_array);
|
||||
|
||||
y_current->y_type = new_type;
|
||||
y_current->y_width = new_width;
|
||||
y_current->y_size = size;
|
||||
y_current->y_time_set = 0;
|
||||
if (size == 0)
|
||||
{
|
||||
y_current->y_array = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Move the lines from array[] to y_array[]. */
|
||||
y_current->y_array = ALLOC_MULT(char_u *, size);
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (y_current->y_array == NULL)
|
||||
vim_free(array[i]);
|
||||
else
|
||||
y_current->y_array[i] = array[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free array[] if it was filled. */
|
||||
for (i = 0; i < size; i++)
|
||||
vim_free(array[i]);
|
||||
}
|
||||
vim_free(array);
|
||||
|
||||
return eof;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a new style register line from the viminfo, store it when it's new.
|
||||
*/
|
||||
void
|
||||
handle_viminfo_register(garray_T *values, int force)
|
||||
{
|
||||
bval_T *vp = (bval_T *)values->ga_data;
|
||||
int flags;
|
||||
int name;
|
||||
int type;
|
||||
int linecount;
|
||||
int width;
|
||||
time_t timestamp;
|
||||
yankreg_T *y_ptr;
|
||||
int i;
|
||||
|
||||
/* Check the format:
|
||||
* |{bartype},{flags},{name},{type},
|
||||
* {linecount},{width},{timestamp},"line1","line2"
|
||||
*/
|
||||
if (values->ga_len < 6
|
||||
|| vp[0].bv_type != BVAL_NR
|
||||
|| vp[1].bv_type != BVAL_NR
|
||||
|| vp[2].bv_type != BVAL_NR
|
||||
|| vp[3].bv_type != BVAL_NR
|
||||
|| vp[4].bv_type != BVAL_NR
|
||||
|| vp[5].bv_type != BVAL_NR)
|
||||
return;
|
||||
flags = vp[0].bv_nr;
|
||||
name = vp[1].bv_nr;
|
||||
if (name < 0 || name >= NUM_REGISTERS)
|
||||
return;
|
||||
type = vp[2].bv_nr;
|
||||
if (type != MCHAR && type != MLINE && type != MBLOCK)
|
||||
return;
|
||||
linecount = vp[3].bv_nr;
|
||||
if (values->ga_len < 6 + linecount)
|
||||
return;
|
||||
width = vp[4].bv_nr;
|
||||
if (width < 0)
|
||||
return;
|
||||
|
||||
if (y_read_regs != NULL)
|
||||
/* Reading viminfo for merging and writing. Store the register
|
||||
* content, don't update the current registers. */
|
||||
y_ptr = &y_read_regs[name];
|
||||
else
|
||||
y_ptr = &y_regs[name];
|
||||
|
||||
/* Do not overwrite unless forced or the timestamp is newer. */
|
||||
timestamp = (time_t)vp[5].bv_nr;
|
||||
if (y_ptr->y_array != NULL && !force
|
||||
&& (timestamp == 0 || y_ptr->y_time_set > timestamp))
|
||||
return;
|
||||
|
||||
if (y_ptr->y_array != NULL)
|
||||
for (i = 0; i < y_ptr->y_size; i++)
|
||||
vim_free(y_ptr->y_array[i]);
|
||||
vim_free(y_ptr->y_array);
|
||||
|
||||
if (y_read_regs == NULL)
|
||||
{
|
||||
if (flags & REG_PREVIOUS)
|
||||
y_previous = y_ptr;
|
||||
if ((flags & REG_EXEC) && (force || execreg_lastc == NUL))
|
||||
execreg_lastc = get_register_name(name);
|
||||
}
|
||||
y_ptr->y_type = type;
|
||||
y_ptr->y_width = width;
|
||||
y_ptr->y_size = linecount;
|
||||
y_ptr->y_time_set = timestamp;
|
||||
if (linecount == 0)
|
||||
{
|
||||
y_ptr->y_array = NULL;
|
||||
return;
|
||||
}
|
||||
y_ptr->y_array = ALLOC_MULT(char_u *, linecount);
|
||||
if (y_ptr->y_array == NULL)
|
||||
{
|
||||
y_ptr->y_size = 0; // ensure object state is consistent
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < linecount; i++)
|
||||
{
|
||||
if (vp[i + 6].bv_allocated)
|
||||
{
|
||||
y_ptr->y_array[i] = vp[i + 6].bv_string;
|
||||
vp[i + 6].bv_string = NULL;
|
||||
}
|
||||
else
|
||||
y_ptr->y_array[i] = vim_strsave(vp[i + 6].bv_string);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
write_viminfo_registers(FILE *fp)
|
||||
{
|
||||
int i, j;
|
||||
char_u *type;
|
||||
char_u c;
|
||||
int num_lines;
|
||||
int max_num_lines;
|
||||
int max_kbyte;
|
||||
long len;
|
||||
yankreg_T *y_ptr;
|
||||
|
||||
fputs(_("\n# Registers:\n"), fp);
|
||||
|
||||
/* Get '<' value, use old '"' value if '<' is not found. */
|
||||
max_num_lines = get_viminfo_parameter('<');
|
||||
if (max_num_lines < 0)
|
||||
max_num_lines = get_viminfo_parameter('"');
|
||||
if (max_num_lines == 0)
|
||||
return;
|
||||
max_kbyte = get_viminfo_parameter('s');
|
||||
if (max_kbyte == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NUM_REGISTERS; i++)
|
||||
{
|
||||
#ifdef FEAT_CLIPBOARD
|
||||
/* Skip '*'/'+' register, we don't want them back next time */
|
||||
if (i == STAR_REGISTER || i == PLUS_REGISTER)
|
||||
continue;
|
||||
#endif
|
||||
#ifdef FEAT_DND
|
||||
/* Neither do we want the '~' register */
|
||||
if (i == TILDE_REGISTER)
|
||||
continue;
|
||||
#endif
|
||||
/* When reading viminfo for merging and writing: Use the register from
|
||||
* viminfo if it's newer. */
|
||||
if (y_read_regs != NULL
|
||||
&& y_read_regs[i].y_array != NULL
|
||||
&& (y_regs[i].y_array == NULL ||
|
||||
y_read_regs[i].y_time_set > y_regs[i].y_time_set))
|
||||
y_ptr = &y_read_regs[i];
|
||||
else if (y_regs[i].y_array == NULL)
|
||||
continue;
|
||||
else
|
||||
y_ptr = &y_regs[i];
|
||||
|
||||
/* Skip empty registers. */
|
||||
num_lines = y_ptr->y_size;
|
||||
if (num_lines == 0
|
||||
|| (num_lines == 1 && y_ptr->y_type == MCHAR
|
||||
&& *y_ptr->y_array[0] == NUL))
|
||||
continue;
|
||||
|
||||
if (max_kbyte > 0)
|
||||
{
|
||||
/* Skip register if there is more text than the maximum size. */
|
||||
len = 0;
|
||||
for (j = 0; j < num_lines; j++)
|
||||
len += (long)STRLEN(y_ptr->y_array[j]) + 1L;
|
||||
if (len > (long)max_kbyte * 1024L)
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (y_ptr->y_type)
|
||||
{
|
||||
case MLINE:
|
||||
type = (char_u *)"LINE";
|
||||
break;
|
||||
case MCHAR:
|
||||
type = (char_u *)"CHAR";
|
||||
break;
|
||||
case MBLOCK:
|
||||
type = (char_u *)"BLOCK";
|
||||
break;
|
||||
default:
|
||||
semsg(_("E574: Unknown register type %d"), y_ptr->y_type);
|
||||
type = (char_u *)"LINE";
|
||||
break;
|
||||
}
|
||||
if (y_previous == &y_regs[i])
|
||||
fprintf(fp, "\"");
|
||||
c = get_register_name(i);
|
||||
fprintf(fp, "\"%c", c);
|
||||
if (c == execreg_lastc)
|
||||
fprintf(fp, "@");
|
||||
fprintf(fp, "\t%s\t%d\n", type, (int)y_ptr->y_width);
|
||||
|
||||
/* If max_num_lines < 0, then we save ALL the lines in the register */
|
||||
if (max_num_lines > 0 && num_lines > max_num_lines)
|
||||
num_lines = max_num_lines;
|
||||
for (j = 0; j < num_lines; j++)
|
||||
{
|
||||
putc('\t', fp);
|
||||
viminfo_writestring(fp, y_ptr->y_array[j]);
|
||||
}
|
||||
|
||||
{
|
||||
int flags = 0;
|
||||
int remaining;
|
||||
|
||||
/* New style with a bar line. Format:
|
||||
* |{bartype},{flags},{name},{type},
|
||||
* {linecount},{width},{timestamp},"line1","line2"
|
||||
* flags: REG_PREVIOUS - register is y_previous
|
||||
* REG_EXEC - used for @@
|
||||
*/
|
||||
if (y_previous == &y_regs[i])
|
||||
flags |= REG_PREVIOUS;
|
||||
if (c == execreg_lastc)
|
||||
flags |= REG_EXEC;
|
||||
fprintf(fp, "|%d,%d,%d,%d,%d,%d,%ld", BARTYPE_REGISTER, flags,
|
||||
i, y_ptr->y_type, num_lines, (int)y_ptr->y_width,
|
||||
(long)y_ptr->y_time_set);
|
||||
/* 11 chars for type/flags/name/type, 3 * 20 for numbers */
|
||||
remaining = LSIZE - 71;
|
||||
for (j = 0; j < num_lines; j++)
|
||||
{
|
||||
putc(',', fp);
|
||||
--remaining;
|
||||
remaining = barline_writestring(fp, y_ptr->y_array[j],
|
||||
remaining);
|
||||
}
|
||||
putc('\n', fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* FEAT_VIMINFO */
|
||||
|
||||
#if defined(FEAT_CLIPBOARD) || defined(PROTO)
|
||||
/*
|
||||
* SELECTION / PRIMARY ('*')
|
||||
|
Reference in New Issue
Block a user