To: vim_dev@googlegroups.com Subject: Patch 7.4.1919 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1919 Problem: Register contents is not merged when writing viminfo. Solution: Use timestamps for register contents. Files: src/ops.c, src/ex_getln.c, src/ex_cmds.c, src/proto/ex_cmds.pro, src/proto/ex_getln.pro, src/proto/ops.pro, src/vim.h *** ../vim-7.4.1918/src/ops.c 2016-06-04 20:14:00.302000092 +0200 --- src/ops.c 2016-06-11 20:45:08.396494246 +0200 *************** *** 50,68 **** #endif /* ! * Each yank register is an array of pointers to lines. */ ! static struct yankreg { 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 */ static int y_append; /* TRUE when appending */ ! static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */ /* * structure used by block_prep, op_delete and op_yank for blockwise operators --- 50,73 ---- #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]; ! static yankreg_T *y_current; /* ptr to current yankreg */ static int y_append; /* TRUE when appending */ ! 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,110 **** 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 may_set_selection(void); #endif static void dis_msg(char_u *p, int skip_esc); --- 109,115 ---- 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(yankreg_T *reg); static void may_set_selection(void); #endif static void dis_msg(char_u *p, int skip_esc); *************** *** 114,120 **** 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); #endif static int ends_in_white(linenr_T lnum); #ifdef FEAT_COMMENTS --- 119,125 ---- 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(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,971 **** int name, int copy) /* make a copy, if FALSE make register empty. */ { ! struct yankreg *reg; ! int i; #ifdef FEAT_CLIPBOARD /* When Visual area changed, may have to update selection. Obtain the --- 969,976 ---- int name, int copy) /* make a copy, if FALSE make register empty. */ { ! yankreg_T *reg; ! int i; #ifdef FEAT_CLIPBOARD /* When Visual area changed, may have to update selection. Obtain the *************** *** 985,991 **** #endif get_yank_register(name, 0); ! reg = (struct yankreg *)alloc((unsigned)sizeof(struct yankreg)); if (reg != NULL) { *reg = *y_current; --- 990,996 ---- #endif get_yank_register(name, 0); ! reg = (yankreg_T *)alloc((unsigned)sizeof(yankreg_T)); if (reg != NULL) { *reg = *y_current; *************** *** 1017,1023 **** { get_yank_register(name, 0); free_yank_all(); ! *y_current = *(struct yankreg *)reg; vim_free(reg); #ifdef FEAT_CLIPBOARD --- 1022,1028 ---- { get_yank_register(name, 0); free_yank_all(); ! *y_current = *(yankreg_T *)reg; vim_free(reg); #ifdef FEAT_CLIPBOARD *************** *** 1029,1038 **** void free_register(void *reg) { ! struct yankreg tmp; tmp = *y_current; ! *y_current = *(struct yankreg *)reg; free_yank_all(); vim_free(reg); *y_current = tmp; --- 1034,1043 ---- void free_register(void *reg) { ! yankreg_T tmp; tmp = *y_current; ! *y_current = *(yankreg_T *)reg; free_yank_all(); vim_free(reg); *y_current = tmp; *************** *** 1064,1070 **** { char_u *p; static int regname; ! struct yankreg *old_y_previous, *old_y_current; int retval; if (Recording == FALSE) /* start recording */ --- 1069,1075 ---- { char_u *p; static int regname; ! yankreg_T *old_y_previous, *old_y_current; int retval; if (Recording == FALSE) /* start recording */ *************** *** 1164,1169 **** --- 1169,1177 ---- 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,2914 **** 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 */ char_u **new_ptr; linenr_T lnum; /* current line number */ long j; --- 2915,2922 ---- op_yank(oparg_T *oap, int deleting, int mess) { long y_idx; /* index in y_array[] */ ! 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,2981 **** 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; } y_idx = 0; lnum = oap->start.lnum; --- 2978,2991 ---- 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,3107 **** --- 3112,3120 ---- 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,3261 **** * Make a copy of the y_current register to register "reg". */ static void ! copy_yank_reg(struct yankreg *reg) { ! struct yankreg *curr = y_current; ! long j; y_current = reg; free_yank_all(); --- 3265,3274 ---- * Make a copy of the y_current register to register "reg". */ static void ! copy_yank_reg(yankreg_T *reg) { ! yankreg_T *curr = y_current; ! long j; y_current = reg; free_yank_all(); *************** *** 4013,4019 **** } #endif ! /* Return the character name of the register with the given number */ int get_register_name(int num) { --- 4026,4034 ---- } #endif ! /* ! * Return the character name of the register with the given number. ! */ int get_register_name(int num) { *************** *** 4053,4067 **** 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; #ifdef FEAT_MBYTE ! int clen; #else # define clen 1 #endif --- 4068,4082 ---- void ex_display(exarg_T *eap) { ! 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; #else # define clen 1 #endif *************** *** 5794,5799 **** --- 5809,5850 ---- } #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,5905 **** --- 5951,5957 ---- 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,5944 **** return eof; } 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; fputs(_("\n# Registers:\n"), fp); --- 5981,6086 ---- 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; ! yankreg_T *y_ptr; fputs(_("\n# Registers:\n"), fp); *************** *** 5954,5961 **** 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) --- 6096,6101 ---- *************** *** 5966,5976 **** if (i == TILDE_REGISTER) continue; #endif /* Skip empty registers. */ ! num_lines = y_regs[i].y_size; if (num_lines == 0 ! || (num_lines == 1 && y_regs[i].y_type == MCHAR ! && *y_regs[i].y_array[0] == NUL)) continue; if (max_kbyte > 0) --- 6106,6128 ---- 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) *************** *** 5978,5989 **** /* 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; if (len > (long)max_kbyte * 1024L) continue; } ! switch (y_regs[i].y_type) { case MLINE: type = (char_u *)"LINE"; --- 6130,6141 ---- /* 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"; *************** *** 5996,6002 **** break; default: sprintf((char *)IObuff, _("E574: Unknown register type %d"), ! y_regs[i].y_type); emsg(IObuff); type = (char_u *)"LINE"; break; --- 6148,6154 ---- break; default: sprintf((char *)IObuff, _("E574: Unknown register type %d"), ! y_ptr->y_type); emsg(IObuff); type = (char_u *)"LINE"; break; *************** *** 6007,6013 **** fprintf(fp, "\"%c", c); if (c == execreg_lastc) fprintf(fp, "@"); ! fprintf(fp, "\t%s\t%d\n", type, (int)y_regs[i].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) --- 6159,6165 ---- 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) *************** *** 6015,6021 **** for (j = 0; j < num_lines; j++) { putc('\t', fp); ! viminfo_writestring(fp, y_regs[i].y_array[j]); } } } --- 6167,6202 ---- 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); } } } *************** *** 6133,6139 **** void clip_free_selection(VimClipboard *cbd) { ! struct yankreg *y_ptr = y_current; if (cbd == &clip_plus) y_current = &y_regs[PLUS_REGISTER]; --- 6314,6320 ---- void clip_free_selection(VimClipboard *cbd) { ! yankreg_T *y_ptr = y_current; if (cbd == &clip_plus) y_current = &y_regs[PLUS_REGISTER]; *************** *** 6150,6156 **** void clip_get_selection(VimClipboard *cbd) { ! struct yankreg *old_y_previous, *old_y_current; pos_T old_cursor; pos_T old_visual; int old_visual_mode; --- 6331,6337 ---- void clip_get_selection(VimClipboard *cbd) { ! yankreg_T *old_y_previous, *old_y_current; pos_T old_cursor; pos_T old_visual; int old_visual_mode; *************** *** 6215,6221 **** long len, VimClipboard *cbd) { ! struct yankreg *y_ptr; if (cbd == &clip_plus) y_ptr = &y_regs[PLUS_REGISTER]; --- 6396,6402 ---- long len, VimClipboard *cbd) { ! yankreg_T *y_ptr; if (cbd == &clip_plus) y_ptr = &y_regs[PLUS_REGISTER]; *************** *** 6239,6245 **** int lnum; int i, j; int_u eolsize; ! struct yankreg *y_ptr; if (cbd == &clip_plus) y_ptr = &y_regs[PLUS_REGISTER]; --- 6420,6426 ---- int lnum; int i, j; int_u eolsize; ! yankreg_T *y_ptr; if (cbd == &clip_plus) y_ptr = &y_regs[PLUS_REGISTER]; *************** *** 6322,6328 **** void dnd_yank_drag_data(char_u *str, long len) { ! struct yankreg *curr; curr = y_current; y_current = &y_regs[TILDE_REGISTER]; --- 6503,6509 ---- void dnd_yank_drag_data(char_u *str, long len) { ! yankreg_T *curr; curr = y_current; y_current = &y_regs[TILDE_REGISTER]; *************** *** 6518,6528 **** static int init_write_reg( ! int name, ! struct yankreg **old_y_previous, ! struct yankreg **old_y_current, ! int must_append, ! int *yank_type UNUSED) { if (!valid_yank_reg(name, TRUE)) /* check for valid reg name */ { --- 6699,6709 ---- static int init_write_reg( ! 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,6550 **** static void finish_write_reg( ! int name, ! struct yankreg *old_y_previous, ! struct yankreg *old_y_current) { # ifdef FEAT_CLIPBOARD /* Send text of clipboard register to the clipboard. */ --- 6723,6731 ---- static void finish_write_reg( ! int name, ! yankreg_T *old_y_previous, ! yankreg_T *old_y_current) { # ifdef FEAT_CLIPBOARD /* Send text of clipboard register to the clipboard. */ *************** *** 6585,6591 **** int yank_type, long block_len) { ! struct yankreg *old_y_previous, *old_y_current; if (name == '/' #ifdef FEAT_EVAL --- 6766,6772 ---- int yank_type, long block_len) { ! yankreg_T *old_y_previous, *old_y_current; if (name == '/' #ifdef FEAT_EVAL *************** *** 6630,6637 **** int yank_type, long block_len) { ! struct yankreg *old_y_previous, *old_y_current; ! long len; if (maxlen >= 0) len = maxlen; --- 6811,6818 ---- int yank_type, long block_len) { ! yankreg_T *old_y_previous, *old_y_current; ! long len; if (maxlen >= 0) len = maxlen; *************** *** 6705,6716 **** */ 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 ** */ { int type; /* MCHAR, MLINE or MBLOCK */ int lnum; --- 6886,6897 ---- */ static void str_to_reg( ! 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,6845 **** --- 7021,7029 ---- 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 */ *** ../vim-7.4.1918/src/ex_getln.c 2016-06-11 15:31:44.079937578 +0200 --- src/ex_getln.c 2016-06-11 16:56:44.496230647 +0200 *************** *** 5408,5427 **** 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 --- 5408,5413 ---- *************** *** 6280,6313 **** */ void handle_viminfo_history( ! bval_T *values, ! int count, ! int writing) { int type; long_u len; char_u *val; char_u *p; /* 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) return; ! type = values[0].bv_nr; if (type >= HIST_COUNT) return; if (viminfo_hisidx[type] < viminfo_hislen[type]) { ! val = values[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 idx; int overwrite = FALSE; --- 6266,6299 ---- */ void handle_viminfo_history( ! 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 (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 = vp[0].bv_nr; if (type >= HIST_COUNT) return; if (viminfo_hisidx[type] < viminfo_hislen[type]) { ! val = vp[3].bv_string; if (val != NULL && *val != NUL) { ! int sep = type == HIST_SEARCH && vp[2].bv_type == BVAL_NR ! ? vp[2].bv_nr : NUL; int idx; int overwrite = FALSE; *************** *** 6329,6340 **** if (!overwrite) { /* Need to re-allocate to append the separator byte. */ ! len = values[3].bv_len; p = lalloc(len + 2, TRUE); } if (p != NULL) { ! viminfo_history[type][idx].time_set = values[1].bv_nr; if (!overwrite) { mch_memmove(p, val, (size_t)len + 1); --- 6315,6326 ---- if (!overwrite) { /* Need to re-allocate to append the separator byte. */ ! len = vp[3].bv_len; p = lalloc(len + 2, TRUE); } if (p != NULL) { ! viminfo_history[type][idx].time_set = vp[1].bv_nr; if (!overwrite) { mch_memmove(p, val, (size_t)len + 1); *** ../vim-7.4.1918/src/ex_cmds.c 2016-06-11 15:31:44.075937621 +0200 --- src/ex_cmds.c 2016-06-11 21:04:08.932042575 +0200 *************** *** 1750,1756 **** #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 void write_viminfo_version(FILE *fp_out); static void write_viminfo_barlines(vir_T *virp, FILE *fp_out); static int viminfo_errcnt; --- 1750,1756 ---- #if defined(FEAT_VIMINFO) || defined(PROTO) static int no_viminfo(void); ! 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,2169 **** --- 2164,2173 ---- { 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,2196 **** --- 2195,2201 ---- 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,2234 **** --- 2234,2240 ---- #ifdef FEAT_CMDHIST prepare_viminfo_history(forceit ? 9999 : 0, writing); #endif + eof = viminfo_readline(virp); while (!eof && virp->vir_line[0] != '>') { *************** *** 2246,2252 **** eof = viminfo_readline(virp); break; case '|': ! eof = read_viminfo_barline(virp, got_encoding, writing); break; case '*': /* "*encoding=value" */ got_encoding = TRUE; --- 2252,2259 ---- eof = viminfo_readline(virp); break; case '|': ! eof = read_viminfo_barline(virp, got_encoding, ! forceit, writing); break; case '*': /* "*encoding=value" */ got_encoding = TRUE; *************** *** 2263,2269 **** eof = read_viminfo_bufferlist(virp, writing); break; case '"': ! eof = read_viminfo_register(virp, forceit); break; case '/': /* Search string */ case '&': /* Substitute search string */ --- 2270,2284 ---- eof = read_viminfo_bufferlist(virp, writing); break; case '"': ! /* 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,2546 **** } } putc('"', fd); ! return remaining; } /* * Parse a viminfo line starting with '|'. ! * Put each decoded value in "values" and return the number of values found. */ ! static int ! barline_parse(vir_T *virp, char_u *text, bval_T *values) { char_u *p = text; char_u *nextp = NULL; char_u *buf = NULL; ! int count = 0; int i; int allocated = FALSE; #ifdef FEAT_MBYTE --- 2542,2561 ---- } } putc('"', fd); ! return remaining - 2; } /* * Parse a viminfo line starting with '|'. ! * Add each decoded value to "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; ! bval_T *value; int i; int allocated = FALSE; #ifdef FEAT_MBYTE *************** *** 2550,2576 **** while (*p == ',') { - if (count == BVAL_MAX) - { - EMSG2(e_intern2, "barline_parse()"); - break; - } ++p; if (*p == '>') { ! /* Need to read a continuation line. Need to 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) { ! values[i].bv_string = vim_strnsave( ! values[i].bv_string, values[i].bv_len); ! values[i].bv_allocated = TRUE; } allocated = TRUE; } --- 2565,2591 ---- while (*p == ',') { ++p; + if (ga_grow(values, 1) == FAIL) + break; + value = (bval_T *)(values->ga_data) + values->ga_len; if (*p == '>') { ! /* Need to read a continuation line. Put strings in allocated ! * memory, because virp->vir_line is overwritten. */ if (!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) { ! vp->bv_string = vim_strnsave(vp->bv_string, vp->bv_len); ! vp->bv_allocated = TRUE; } + } allocated = TRUE; } *************** *** 2590,2596 **** len = getdigits(&p); buf = alloc((int)(len + 1)); if (buf == NULL) ! return count; p = buf; for (todo = len; todo > 0; todo -= n) { --- 2605,2611 ---- len = getdigits(&p); buf = alloc((int)(len + 1)); if (buf == NULL) ! return; p = buf; for (todo = len; todo > 0; todo -= n) { *************** *** 2599,2605 **** { /* file was truncated or garbled */ vim_free(buf); ! return count; } /* Get length of text, excluding |< and NL chars. */ n = STRLEN(virp->vir_line); --- 2614,2620 ---- { /* file was truncated or garbled */ vim_free(buf); ! return; } /* Get length of text, excluding |< and NL chars. */ n = STRLEN(virp->vir_line); *************** *** 2628,2643 **** if (viminfo_readline(virp) || virp->vir_line[0] != '|' || virp->vir_line[1] != '<') /* file was truncated or garbled */ ! return count; p = virp->vir_line + 2; } } if (isdigit(*p)) { ! values[count].bv_type = BVAL_NR; ! values[count].bv_nr = getdigits(&p); ! ++count; } else if (*p == '"') { --- 2643,2658 ---- if (viminfo_readline(virp) || virp->vir_line[0] != '|' || virp->vir_line[1] != '<') /* file was truncated or garbled */ ! return; p = virp->vir_line + 2; } } if (isdigit(*p)) { ! value->bv_type = BVAL_NR; ! value->bv_nr = getdigits(&p); ! ++values->ga_len; } else if (*p == '"') { *************** *** 2649,2655 **** while (*p != '"') { if (*p == NL || *p == NUL) ! return count; /* syntax error, drop the value */ if (*p == '\\') { ++p; --- 2664,2670 ---- while (*p != '"') { if (*p == NL || *p == NUL) ! return; /* syntax error, drop the value */ if (*p == '\\') { ++p; *************** *** 2662,2667 **** --- 2677,2683 ---- else s[len++] = *p++; } + ++p; s[len] = NUL; #ifdef FEAT_MBYTE *************** *** 2683,2697 **** * 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 #ifdef FEAT_MBYTE || converted #endif ; ! ++count; if (nextp != NULL) { /* values following a long string */ --- 2699,2713 ---- * above and we did allocate before, thus vir_line may change. */ if (s != buf && allocated) s = vim_strsave(s); ! value->bv_string = s; ! value->bv_type = BVAL_STRING; ! value->bv_len = len; ! value->bv_allocated = allocated #ifdef FEAT_MBYTE || converted #endif ; ! ++values->ga_len; if (nextp != NULL) { /* values following a long string */ *************** *** 2701,2723 **** } else if (*p == ',') { ! values[count].bv_type = BVAL_EMPTY; ! ++count; } else break; } - - return count; } static int ! read_viminfo_barline(vir_T *virp, int got_encoding, int writing) { char_u *p = virp->vir_line + 1; int bartype; ! bval_T values[BVAL_MAX]; ! int count = 0; int i; /* The format is: |{bartype},{value},... --- 2717,2737 ---- } else if (*p == ',') { ! value->bv_type = BVAL_EMPTY; ! ++values->ga_len; } else break; } } static int ! read_viminfo_barline(vir_T *virp, int got_encoding, int force, int writing) { char_u *p = virp->vir_line + 1; int bartype; ! garray_T values; ! bval_T *vp; int i; /* The format is: |{bartype},{value},... *************** *** 2737,2742 **** --- 2751,2757 ---- } else { + ga_init2(&values, sizeof(bval_T), 20); bartype = getdigits(&p); switch (bartype) { *************** *** 2746,2760 **** * 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; } break; case BARTYPE_HISTORY: ! count = barline_parse(virp, p, values); ! handle_viminfo_history(values, count, writing); break; default: --- 2761,2781 ---- * doesn't understand the version. */ if (!got_encoding) { ! 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: ! 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,2773 **** 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); - return viminfo_readline(virp); } --- 2783,2797 ---- if (writing) ga_add_string(&virp->vir_barlines, virp->vir_line); } + 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,2799 **** --- 2818,2839 ---- } #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 *** ../vim-7.4.1918/src/proto/ex_cmds.pro 2016-06-06 21:07:48.387578685 +0200 --- src/proto/ex_cmds.pro 2016-06-11 15:58:10.398859944 +0200 *************** *** 17,22 **** --- 17,23 ---- 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); *** ../vim-7.4.1918/src/proto/ex_getln.pro 2016-06-09 20:24:24.312049004 +0200 --- src/proto/ex_getln.pro 2016-06-11 16:56:49.496175792 +0200 *************** *** 50,56 **** 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 finish_viminfo_history(vir_T *virp); void write_viminfo_history(FILE *fp, int merge); void cmd_pchar(int c, int offset); --- 50,56 ---- 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(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); *** ../vim-7.4.1918/src/proto/ops.pro 2016-01-19 13:21:55.845334290 +0100 --- src/proto/ops.pro 2016-06-11 17:29:22.775506503 +0200 *************** *** 44,50 **** --- 44,53 ---- 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); *** ../vim-7.4.1918/src/vim.h 2016-06-09 20:24:24.312049004 +0200 --- src/vim.h 2016-06-11 20:59:19.275176065 +0200 *************** *** 1075,1083 **** /* The type numbers are fixed for backwards compatibility. */ #define BARTYPE_VERSION 1 #define BARTYPE_HISTORY 2 ! #define VIMINFO_VERSION 2 #define VIMINFO_VERSION_WITH_HISTORY 2 typedef enum { BVAL_NR, --- 1075,1085 ---- /* The type numbers are fixed for backwards compatibility. */ #define BARTYPE_VERSION 1 #define BARTYPE_HISTORY 2 + #define BARTYPE_REGISTER 3 ! #define VIMINFO_VERSION 3 #define VIMINFO_VERSION_WITH_HISTORY 2 + #define VIMINFO_VERSION_WITH_REGISTERS 3 typedef enum { BVAL_NR, *************** *** 1085,1092 **** BVAL_EMPTY } btype_T; - #define BVAL_MAX 4 /* Maximum number of fields in a barline. */ - typedef struct { btype_T bv_type; long bv_nr; --- 1087,1092 ---- *** ../vim-7.4.1918/src/version.c 2016-06-11 15:31:44.083937535 +0200 --- src/version.c 2016-06-11 20:54:32.610282009 +0200 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 1919, /**/ -- From "know your smileys": O:-) Saint /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///