# HG changeset patch # User Christian Brabandt # Date 1465672505 -7200 # Node ID f5d9eb512f8b3dcc0b238f0e469b98a37dfefb51 # Parent d10d373d488e59d716a0bdb83c816b75c9752837 commit https://github.com/vim/vim/commit/46bbb0c4ba27395859dfeaa26938483946bb4ec2 Author: Bram Moolenaar Date: Sat Jun 11 21:04:39 2016 +0200 patch 7.4.1919 Problem: Register contents is not merged when writing viminfo. Solution: Use timestamps for register contents. diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -1750,7 +1750,7 @@ append_redir( #if defined(FEAT_VIMINFO) || defined(PROTO) static int no_viminfo(void); -static int read_viminfo_barline(vir_T *virp, int got_encoding, int writing); +static int read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing); static void write_viminfo_version(FILE *fp_out); static void write_viminfo_barlines(vir_T *virp, FILE *fp_out); static int viminfo_errcnt; @@ -2164,6 +2164,10 @@ do_viminfo(FILE *fp_in, FILE *fp_out, in { if (flags & VIF_WANT_INFO) { + /* Registers are read and newer ones are used when writing. */ + if (fp_out != NULL) + prepare_viminfo_registers(); + eof = read_viminfo_up_to_marks(&vir, flags & VIF_FORCEIT, fp_out != NULL); merge = TRUE; @@ -2191,6 +2195,7 @@ do_viminfo(FILE *fp_in, FILE *fp_out, in write_viminfo_history(fp_out, merge); #endif write_viminfo_registers(fp_out); + finish_viminfo_registers(); #ifdef FEAT_EVAL write_viminfo_varlist(fp_out); #endif @@ -2229,6 +2234,7 @@ read_viminfo_up_to_marks( #ifdef FEAT_CMDHIST prepare_viminfo_history(forceit ? 9999 : 0, writing); #endif + eof = viminfo_readline(virp); while (!eof && virp->vir_line[0] != '>') { @@ -2246,7 +2252,8 @@ read_viminfo_up_to_marks( eof = viminfo_readline(virp); break; case '|': - eof = read_viminfo_barline(virp, got_encoding, writing); + eof = read_viminfo_barline(virp, got_encoding, + forceit, writing); break; case '*': /* "*encoding=value" */ got_encoding = TRUE; @@ -2263,7 +2270,15 @@ read_viminfo_up_to_marks( eof = read_viminfo_bufferlist(virp, writing); break; case '"': - eof = read_viminfo_register(virp, forceit); + /* When registers are in bar lines skip the old style register + * lines. */ + if (virp->vir_version < VIMINFO_VERSION_WITH_REGISTERS) + eof = read_viminfo_register(virp, forceit); + else + do { + eof = viminfo_readline(virp); + } while (!eof && (virp->vir_line[0] == TAB + || virp->vir_line[0] == '<')); break; case '/': /* Search string */ case '&': /* Substitute search string */ @@ -2527,20 +2542,20 @@ barline_writestring(FILE *fd, char_u *s, } } putc('"', fd); - return remaining; + return remaining - 2; } /* * Parse a viminfo line starting with '|'. - * Put each decoded value in "values" and return the number of values found. + * Add each decoded value to "values". */ - static int -barline_parse(vir_T *virp, char_u *text, bval_T *values) + static void +barline_parse(vir_T *virp, char_u *text, garray_T *values) { char_u *p = text; char_u *nextp = NULL; char_u *buf = NULL; - int count = 0; + bval_T *value; int i; int allocated = FALSE; #ifdef FEAT_MBYTE @@ -2550,27 +2565,27 @@ barline_parse(vir_T *virp, char_u *text, while (*p == ',') { - if (count == BVAL_MAX) - { - EMSG2(e_intern2, "barline_parse()"); + ++p; + if (ga_grow(values, 1) == FAIL) break; - } - ++p; + value = (bval_T *)(values->ga_data) + values->ga_len; if (*p == '>') { - /* Need to read a continuation line. Need to put strings in - * allocated memory, because virp->vir_line is overwritten. */ + /* Need to read a continuation line. Put strings in allocated + * memory, because virp->vir_line is overwritten. */ if (!allocated) { - for (i = 0; i < count; ++i) - if (values[i].bv_type == BVAL_STRING - && !values[i].bv_allocated) + for (i = 0; i < values->ga_len; ++i) + { + bval_T *vp = (bval_T *)(values->ga_data) + i; + + if (vp->bv_type == BVAL_STRING && !vp->bv_allocated) { - values[i].bv_string = vim_strnsave( - values[i].bv_string, values[i].bv_len); - values[i].bv_allocated = TRUE; + vp->bv_string = vim_strnsave(vp->bv_string, vp->bv_len); + vp->bv_allocated = TRUE; } + } allocated = TRUE; } @@ -2590,7 +2605,7 @@ barline_parse(vir_T *virp, char_u *text, len = getdigits(&p); buf = alloc((int)(len + 1)); if (buf == NULL) - return count; + return; p = buf; for (todo = len; todo > 0; todo -= n) { @@ -2599,7 +2614,7 @@ barline_parse(vir_T *virp, char_u *text, { /* file was truncated or garbled */ vim_free(buf); - return count; + return; } /* Get length of text, excluding |< and NL chars. */ n = STRLEN(virp->vir_line); @@ -2628,16 +2643,16 @@ barline_parse(vir_T *virp, char_u *text, if (viminfo_readline(virp) || virp->vir_line[0] != '|' || virp->vir_line[1] != '<') /* file was truncated or garbled */ - return count; + return; p = virp->vir_line + 2; } } if (isdigit(*p)) { - values[count].bv_type = BVAL_NR; - values[count].bv_nr = getdigits(&p); - ++count; + value->bv_type = BVAL_NR; + value->bv_nr = getdigits(&p); + ++values->ga_len; } else if (*p == '"') { @@ -2649,7 +2664,7 @@ barline_parse(vir_T *virp, char_u *text, while (*p != '"') { if (*p == NL || *p == NUL) - return count; /* syntax error, drop the value */ + return; /* syntax error, drop the value */ if (*p == '\\') { ++p; @@ -2662,6 +2677,7 @@ barline_parse(vir_T *virp, char_u *text, else s[len++] = *p++; } + ++p; s[len] = NUL; #ifdef FEAT_MBYTE @@ -2683,15 +2699,15 @@ barline_parse(vir_T *virp, char_u *text, * above and we did allocate before, thus vir_line may change. */ if (s != buf && allocated) s = vim_strsave(s); - values[count].bv_string = s; - values[count].bv_type = BVAL_STRING; - values[count].bv_len = len; - values[count].bv_allocated = allocated + value->bv_string = s; + value->bv_type = BVAL_STRING; + value->bv_len = len; + value->bv_allocated = allocated #ifdef FEAT_MBYTE || converted #endif ; - ++count; + ++values->ga_len; if (nextp != NULL) { /* values following a long string */ @@ -2701,23 +2717,21 @@ barline_parse(vir_T *virp, char_u *text, } else if (*p == ',') { - values[count].bv_type = BVAL_EMPTY; - ++count; + value->bv_type = BVAL_EMPTY; + ++values->ga_len; } else break; } - - return count; } static int -read_viminfo_barline(vir_T *virp, int got_encoding, int writing) +read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing) { char_u *p = virp->vir_line + 1; int bartype; - bval_T values[BVAL_MAX]; - int count = 0; + garray_T values; + bval_T *vp; int i; /* The format is: |{bartype},{value},... @@ -2737,6 +2751,7 @@ read_viminfo_barline(vir_T *virp, int go } else { + ga_init2(&values, sizeof(bval_T), 20); bartype = getdigits(&p); switch (bartype) { @@ -2746,15 +2761,21 @@ read_viminfo_barline(vir_T *virp, int go * doesn't understand the version. */ if (!got_encoding) { - count = barline_parse(virp, p, values); - if (count > 0 && values[0].bv_type == BVAL_NR) - virp->vir_version = values[0].bv_nr; + barline_parse(virp, p, &values); + vp = (bval_T *)values.ga_data; + if (values.ga_len > 0 && vp->bv_type == BVAL_NR) + virp->vir_version = vp->bv_nr; } break; case BARTYPE_HISTORY: - count = barline_parse(virp, p, values); - handle_viminfo_history(values, count, writing); + barline_parse(virp, p, &values); + handle_viminfo_history(&values, writing); + break; + + case BARTYPE_REGISTER: + barline_parse(virp, p, &values); + handle_viminfo_register(&values, force); break; default: @@ -2762,11 +2783,14 @@ read_viminfo_barline(vir_T *virp, int go if (writing) ga_add_string(&virp->vir_barlines, virp->vir_line); } - } - - for (i = 0; i < count; ++i) - if (values[i].bv_type == BVAL_STRING && values[i].bv_allocated) - vim_free(values[i].bv_string); + for (i = 0; i < values.ga_len; ++i) + { + vp = (bval_T *)values.ga_data + i; + if (vp->bv_type == BVAL_STRING && vp->bv_allocated) + vim_free(vp->bv_string); + } + ga_clear(&values); + } return viminfo_readline(virp); } @@ -2794,6 +2818,22 @@ write_viminfo_barlines(vir_T *virp, FILE } #endif /* FEAT_VIMINFO */ +#if defined(FEAT_VIMINFO) || defined(PROTO) +/* + * Return the current time in seconds. Calls time(), unless test_settime() + * was used. + */ + time_t +vim_time(void) +{ +# ifdef FEAT_EVAL + return time_for_testing == 0 ? time(NULL) : time_for_testing; +# else + return time(NULL); +# endif +} +#endif + /* * Implementation of ":fixdel", also used by get_stty(). * resulting diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -5408,20 +5408,6 @@ static char *(history_names[]) = NULL }; -/* - * Return the current time in seconds. Calls time(), unless test_settime() - * was used. - */ - static time_t -vim_time(void) -{ -#ifdef FEAT_EVAL - return time_for_testing == 0 ? time(NULL) : time_for_testing; -#else - return time(NULL); -#endif -} - #if defined(FEAT_CMDL_COMPL) || defined(PROTO) /* * Function given to ExpandGeneric() to obtain the possible first @@ -6280,34 +6266,34 @@ read_viminfo_history(vir_T *virp, int wr */ void handle_viminfo_history( - bval_T *values, - int count, - int writing) + garray_T *values, + int writing) { int type; long_u len; char_u *val; char_u *p; + bval_T *vp = (bval_T *)values->ga_data; /* Check the format: * |{bartype},{histtype},{timestamp},{separator},"text" */ - if (count < 4 - || values[0].bv_type != BVAL_NR - || values[1].bv_type != BVAL_NR - || (values[2].bv_type != BVAL_NR && values[2].bv_type != BVAL_EMPTY) - || values[3].bv_type != BVAL_STRING) + if (values->ga_len < 4 + || vp[0].bv_type != BVAL_NR + || vp[1].bv_type != BVAL_NR + || (vp[2].bv_type != BVAL_NR && vp[2].bv_type != BVAL_EMPTY) + || vp[3].bv_type != BVAL_STRING) return; - type = values[0].bv_nr; + type = vp[0].bv_nr; if (type >= HIST_COUNT) return; if (viminfo_hisidx[type] < viminfo_hislen[type]) { - val = values[3].bv_string; + val = vp[3].bv_string; if (val != NULL && *val != NUL) { - int sep = type == HIST_SEARCH && values[2].bv_type == BVAL_NR - ? values[2].bv_nr : NUL; + int sep = type == HIST_SEARCH && vp[2].bv_type == BVAL_NR + ? vp[2].bv_nr : NUL; int idx; int overwrite = FALSE; @@ -6329,12 +6315,12 @@ handle_viminfo_history( if (!overwrite) { /* Need to re-allocate to append the separator byte. */ - len = values[3].bv_len; + len = vp[3].bv_len; p = lalloc(len + 2, TRUE); } if (p != NULL) { - viminfo_history[type][idx].time_set = values[1].bv_nr; + viminfo_history[type][idx].time_set = vp[1].bv_nr; if (!overwrite) { mch_memmove(p, val, (size_t)len + 1); diff --git a/src/ops.c b/src/ops.c --- a/src/ops.c +++ b/src/ops.c @@ -50,19 +50,24 @@ #endif /* - * Each yank register is an array of pointers to lines. + * Each yank register has an array of pointers to lines. */ -static struct yankreg +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 */ -} y_regs[NUM_REGISTERS]; - -static struct yankreg *y_current; /* ptr to current yankreg */ +#ifdef FEAT_VIMINFO + time_t y_time_set; +#endif +} yankreg_T; + +static yankreg_T y_regs[NUM_REGISTERS]; + +static yankreg_T *y_current; /* ptr to current yankreg */ static int y_append; /* TRUE when appending */ -static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */ +static yankreg_T *y_previous = NULL; /* ptr to last written yankreg */ /* * structure used by block_prep, op_delete and op_yank for blockwise operators @@ -104,7 +109,7 @@ static void free_yank(long); static void free_yank_all(void); static int yank_copy_line(struct block_def *bd, long y_idx); #ifdef FEAT_CLIPBOARD -static void copy_yank_reg(struct yankreg *reg); +static void copy_yank_reg(yankreg_T *reg); static void may_set_selection(void); #endif static void dis_msg(char_u *p, int skip_esc); @@ -114,7 +119,7 @@ static char_u *skip_comment(char_u *line static void block_prep(oparg_T *oap, struct block_def *, linenr_T, int); static int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1); #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL) -static void str_to_reg(struct yankreg *y_ptr, int yank_type, char_u *str, long len, long blocklen, int str_list); +static void str_to_reg(yankreg_T *y_ptr, int yank_type, char_u *str, long len, long blocklen, int str_list); #endif static int ends_in_white(linenr_T lnum); #ifdef FEAT_COMMENTS @@ -964,8 +969,8 @@ get_register( int name, int copy) /* make a copy, if FALSE make register empty. */ { - struct yankreg *reg; - int i; + yankreg_T *reg; + int i; #ifdef FEAT_CLIPBOARD /* When Visual area changed, may have to update selection. Obtain the @@ -985,7 +990,7 @@ get_register( #endif get_yank_register(name, 0); - reg = (struct yankreg *)alloc((unsigned)sizeof(struct yankreg)); + reg = (yankreg_T *)alloc((unsigned)sizeof(yankreg_T)); if (reg != NULL) { *reg = *y_current; @@ -1017,7 +1022,7 @@ put_register(int name, void *reg) { get_yank_register(name, 0); free_yank_all(); - *y_current = *(struct yankreg *)reg; + *y_current = *(yankreg_T *)reg; vim_free(reg); #ifdef FEAT_CLIPBOARD @@ -1029,10 +1034,10 @@ put_register(int name, void *reg) void free_register(void *reg) { - struct yankreg tmp; + yankreg_T tmp; tmp = *y_current; - *y_current = *(struct yankreg *)reg; + *y_current = *(yankreg_T *)reg; free_yank_all(); vim_free(reg); *y_current = tmp; @@ -1064,7 +1069,7 @@ do_record(int c) { char_u *p; static int regname; - struct yankreg *old_y_previous, *old_y_current; + yankreg_T *old_y_previous, *old_y_current; int retval; if (Recording == FALSE) /* start recording */ @@ -1164,6 +1169,9 @@ stuff_yank(int regname, char_u *p) y_current->y_array[0] = p; y_current->y_size = 1; y_current->y_type = MCHAR; /* used to be MLINE, why? */ +#ifdef FEAT_VIMINFO + y_current->y_time_set = vim_time(); +#endif } return OK; } @@ -2907,8 +2915,8 @@ free_yank_all(void) op_yank(oparg_T *oap, int deleting, int mess) { long y_idx; /* index in y_array[] */ - struct yankreg *curr; /* copy of y_current */ - struct yankreg newreg; /* new yank register when appending */ + yankreg_T *curr; /* copy of y_current */ + yankreg_T newreg; /* new yank register when appending */ char_u **new_ptr; linenr_T lnum; /* current line number */ long j; @@ -2970,12 +2978,14 @@ op_yank(oparg_T *oap, int deleting, int y_current->y_width = 0; y_current->y_array = (char_u **)lalloc_clear((long_u)(sizeof(char_u *) * yanklines), TRUE); - if (y_current->y_array == NULL) { y_current = curr; return FAIL; } +#ifdef FEAT_VIMINFO + y_current->y_time_set = vim_time(); +#endif y_idx = 0; lnum = oap->start.lnum; @@ -3102,6 +3112,9 @@ op_yank(oparg_T *oap, int deleting, int new_ptr[j] = curr->y_array[j]; vim_free(curr->y_array); curr->y_array = new_ptr; +#ifdef FEAT_VIMINFO + curr->y_time_set = vim_time(); +#endif if (yanktype == MLINE) /* MLINE overrides MCHAR and MBLOCK */ curr->y_type = MLINE; @@ -3252,10 +3265,10 @@ yank_copy_line(struct block_def *bd, lon * Make a copy of the y_current register to register "reg". */ static void -copy_yank_reg(struct yankreg *reg) +copy_yank_reg(yankreg_T *reg) { - struct yankreg *curr = y_current; - long j; + yankreg_T *curr = y_current; + long j; y_current = reg; free_yank_all(); @@ -4013,7 +4026,9 @@ preprocs_left(void) } #endif -/* Return the character name of the register with the given number */ +/* + * Return the character name of the register with the given number. + */ int get_register_name(int num) { @@ -4053,15 +4068,15 @@ get_register_name(int num) void ex_display(exarg_T *eap) { - int i, n; - long j; - char_u *p; - struct yankreg *yb; - int name; - int attr; - char_u *arg = eap->arg; + int i, n; + long j; + char_u *p; + yankreg_T *yb; + int name; + int attr; + char_u *arg = eap->arg; #ifdef FEAT_MBYTE - int clen; + int clen; #else # define clen 1 #endif @@ -5794,6 +5809,42 @@ theend: } #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() +{ + y_read_regs = (yankreg_T *)alloc_clear(NUM_REGISTERS + * (int)sizeof(yankreg_T)); +} + + void +finish_viminfo_registers() +{ + 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_free(y_read_regs); + y_read_regs = NULL; + } +} + int read_viminfo_register(vir_T *virp, int force) { @@ -5900,6 +5951,7 @@ read_viminfo_register(vir_T *virp, int f 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; @@ -5929,16 +5981,106 @@ read_viminfo_register(vir_T *virp, int f 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; + + 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; + else + { + y_ptr->y_array = + (char_u **)alloc((unsigned)(linecount * sizeof(char_u *))); + 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; + 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); @@ -5954,8 +6096,6 @@ write_viminfo_registers(FILE *fp) for (i = 0; i < NUM_REGISTERS; i++) { - if (y_regs[i].y_array == NULL) - continue; #ifdef FEAT_CLIPBOARD /* Skip '*'/'+' register, we don't want them back next time */ if (i == STAR_REGISTER || i == PLUS_REGISTER) @@ -5966,11 +6106,23 @@ write_viminfo_registers(FILE *fp) 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_regs[i].y_size; + num_lines = y_ptr->y_size; if (num_lines == 0 - || (num_lines == 1 && y_regs[i].y_type == MCHAR - && *y_regs[i].y_array[0] == NUL)) + || (num_lines == 1 && y_ptr->y_type == MCHAR + && *y_ptr->y_array[0] == NUL)) continue; if (max_kbyte > 0) @@ -5978,12 +6130,12 @@ write_viminfo_registers(FILE *fp) /* Skip register if there is more text than the maximum size. */ len = 0; for (j = 0; j < num_lines; j++) - len += (long)STRLEN(y_regs[i].y_array[j]) + 1L; + len += (long)STRLEN(y_ptr->y_array[j]) + 1L; if (len > (long)max_kbyte * 1024L) continue; } - switch (y_regs[i].y_type) + switch (y_ptr->y_type) { case MLINE: type = (char_u *)"LINE"; @@ -5996,7 +6148,7 @@ write_viminfo_registers(FILE *fp) break; default: sprintf((char *)IObuff, _("E574: Unknown register type %d"), - y_regs[i].y_type); + y_ptr->y_type); emsg(IObuff); type = (char_u *)"LINE"; break; @@ -6007,7 +6159,7 @@ write_viminfo_registers(FILE *fp) fprintf(fp, "\"%c", c); if (c == execreg_lastc) fprintf(fp, "@"); - fprintf(fp, "\t%s\t%d\n", type, (int)y_regs[i].y_width); + 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) @@ -6015,7 +6167,36 @@ write_viminfo_registers(FILE *fp) for (j = 0; j < num_lines; j++) { putc('\t', fp); - viminfo_writestring(fp, y_regs[i].y_array[j]); + 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); } } } @@ -6133,7 +6314,7 @@ x11_export_final_selection(void) void clip_free_selection(VimClipboard *cbd) { - struct yankreg *y_ptr = y_current; + yankreg_T *y_ptr = y_current; if (cbd == &clip_plus) y_current = &y_regs[PLUS_REGISTER]; @@ -6150,7 +6331,7 @@ clip_free_selection(VimClipboard *cbd) void clip_get_selection(VimClipboard *cbd) { - struct yankreg *old_y_previous, *old_y_current; + yankreg_T *old_y_previous, *old_y_current; pos_T old_cursor; pos_T old_visual; int old_visual_mode; @@ -6215,7 +6396,7 @@ clip_yank_selection( long len, VimClipboard *cbd) { - struct yankreg *y_ptr; + yankreg_T *y_ptr; if (cbd == &clip_plus) y_ptr = &y_regs[PLUS_REGISTER]; @@ -6239,7 +6420,7 @@ clip_convert_selection(char_u **str, lon int lnum; int i, j; int_u eolsize; - struct yankreg *y_ptr; + yankreg_T *y_ptr; if (cbd == &clip_plus) y_ptr = &y_regs[PLUS_REGISTER]; @@ -6322,7 +6503,7 @@ may_set_selection(void) void dnd_yank_drag_data(char_u *str, long len) { - struct yankreg *curr; + yankreg_T *curr; curr = y_current; y_current = &y_regs[TILDE_REGISTER]; @@ -6518,11 +6699,11 @@ get_reg_contents(int regname, int flags) static int init_write_reg( - int name, - struct yankreg **old_y_previous, - struct yankreg **old_y_current, - int must_append, - int *yank_type UNUSED) + int name, + yankreg_T **old_y_previous, + yankreg_T **old_y_current, + int must_append, + int *yank_type UNUSED) { if (!valid_yank_reg(name, TRUE)) /* check for valid reg name */ { @@ -6542,9 +6723,9 @@ init_write_reg( static void finish_write_reg( - int name, - struct yankreg *old_y_previous, - struct yankreg *old_y_current) + int name, + yankreg_T *old_y_previous, + yankreg_T *old_y_current) { # ifdef FEAT_CLIPBOARD /* Send text of clipboard register to the clipboard. */ @@ -6585,7 +6766,7 @@ write_reg_contents_lst( int yank_type, long block_len) { - struct yankreg *old_y_previous, *old_y_current; + yankreg_T *old_y_previous, *old_y_current; if (name == '/' #ifdef FEAT_EVAL @@ -6630,8 +6811,8 @@ write_reg_contents_ex( int yank_type, long block_len) { - struct yankreg *old_y_previous, *old_y_current; - long len; + yankreg_T *old_y_previous, *old_y_current; + long len; if (maxlen >= 0) len = maxlen; @@ -6705,12 +6886,12 @@ write_reg_contents_ex( */ static void str_to_reg( - struct yankreg *y_ptr, /* pointer to yank register */ - int yank_type, /* MCHAR, MLINE, MBLOCK, MAUTO */ - char_u *str, /* string to put in register */ - long len, /* length of string */ - long blocklen, /* width of Visual block */ - int str_list) /* TRUE if str is char_u ** */ + yankreg_T *y_ptr, /* pointer to yank register */ + int yank_type, /* MCHAR, MLINE, MBLOCK, MAUTO */ + char_u *str, /* string to put in register */ + long len, /* length of string */ + long blocklen, /* width of Visual block */ + int str_list) /* TRUE if str is char_u ** */ { int type; /* MCHAR, MLINE or MBLOCK */ int lnum; @@ -6840,6 +7021,9 @@ str_to_reg( y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen); else y_ptr->y_width = 0; +#ifdef FEAT_VIMINFO + y_ptr->y_time_set = vim_time(); +#endif } #endif /* FEAT_CLIPBOARD || FEAT_EVAL || PROTO */ diff --git a/src/proto/ex_cmds.pro b/src/proto/ex_cmds.pro --- a/src/proto/ex_cmds.pro +++ b/src/proto/ex_cmds.pro @@ -17,6 +17,7 @@ int viminfo_readline(vir_T *virp); char_u *viminfo_readstring(vir_T *virp, int off, int convert); void viminfo_writestring(FILE *fd, char_u *p); int barline_writestring(FILE *fd, char_u *s, int remaining_start); +time_t vim_time(void); void do_fixdel(exarg_T *eap); void print_line_no_prefix(linenr_T lnum, int use_number, int list); void print_line(linenr_T lnum, int use_number, int list); diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -50,7 +50,7 @@ int get_list_range(char_u **str, int *nu void ex_history(exarg_T *eap); void prepare_viminfo_history(int asklen, int writing); int read_viminfo_history(vir_T *virp, int writing); -void handle_viminfo_history(bval_T *values, int count, int writing); +void handle_viminfo_history(garray_T *values, int writing); void finish_viminfo_history(vir_T *virp); void write_viminfo_history(FILE *fp, int merge); void cmd_pchar(int c, int offset); diff --git a/src/proto/ops.pro b/src/proto/ops.pro --- a/src/proto/ops.pro +++ b/src/proto/ops.pro @@ -44,7 +44,10 @@ int fex_format(linenr_T lnum, long count void format_lines(linenr_T line_count, int avoid_fex); int paragraph_start(linenr_T lnum); void op_addsub(oparg_T *oap, linenr_T Prenum1, int g_cmd); +void prepare_viminfo_registers(void); +void finish_viminfo_registers(void); int read_viminfo_register(vir_T *virp, int force); +void handle_viminfo_register(garray_T *values, int writing); void write_viminfo_registers(FILE *fp); void x11_export_final_selection(void); void clip_free_selection(VimClipboard *cbd); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1919, +/**/ 1918, /**/ 1917, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -1075,9 +1075,11 @@ extern char *(*dyn_libintl_textdomain)(c /* The type numbers are fixed for backwards compatibility. */ #define BARTYPE_VERSION 1 #define BARTYPE_HISTORY 2 +#define BARTYPE_REGISTER 3 -#define VIMINFO_VERSION 2 +#define VIMINFO_VERSION 3 #define VIMINFO_VERSION_WITH_HISTORY 2 +#define VIMINFO_VERSION_WITH_REGISTERS 3 typedef enum { BVAL_NR, @@ -1085,8 +1087,6 @@ typedef enum { BVAL_EMPTY } btype_T; -#define BVAL_MAX 4 /* Maximum number of fields in a barline. */ - typedef struct { btype_T bv_type; long bv_nr;