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().
   *  <BS>    resulting <Del>
*** ../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 -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui