To: vim_dev@googlegroups.com
Subject: Patch 7.3.880
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------

Patch 7.3.880
Problem:    When writing viminfo, old history lines may replace lines written
	    more recently by another Vim instance.
Solution:   Mark history entries that were read from viminfo and overwrite
	    them when merging with the current viminfo.
Files:	    src/ex_getln.c


*** ../vim-7.3.879/src/ex_getln.c	2013-03-19 16:46:59.000000000 +0100
--- src/ex_getln.c	2013-04-05 18:56:08.000000000 +0200
***************
*** 56,61 ****
--- 56,62 ----
  typedef struct hist_entry
  {
      int		hisnum;		/* identifying number */
+     int		viminfo;	/* when TRUE hisstr comes from viminfo */
      char_u	*hisstr;	/* actual entry, separator char after the NUL */
  } histentry_T;
  
***************
*** 113,118 ****
--- 114,120 ----
  static int	ExpandRTDir __ARGS((char_u *pat, int *num_file, char_u ***file, char *dirname[]));
  # ifdef FEAT_CMDHIST
  static char_u	*get_history_arg __ARGS((expand_T *xp, int idx));
+ static void	clear_hist_entry __ARGS((histentry_T *hisptr));
  # endif
  # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
  static int	ExpandUserDefined __ARGS((expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file));
***************
*** 5343,5352 ****
  		if (hisidx[type] < 0)		/* there are no entries yet */
  		{
  		    for (i = 0; i < newlen; ++i)
! 		    {
! 			temp[i].hisnum = 0;
! 			temp[i].hisstr = NULL;
! 		    }
  		}
  		else if (newlen > hislen)	/* array becomes bigger */
  		{
--- 5345,5351 ----
  		if (hisidx[type] < 0)		/* there are no entries yet */
  		{
  		    for (i = 0; i < newlen; ++i)
! 			clear_hist_entry(&temp[i]);
  		}
  		else if (newlen > hislen)	/* array becomes bigger */
  		{
***************
*** 5354,5363 ****
  			temp[i] = history[type][i];
  		    j = i;
  		    for ( ; i <= newlen - (hislen - hisidx[type]); ++i)
! 		    {
! 			temp[i].hisnum = 0;
! 			temp[i].hisstr = NULL;
! 		    }
  		    for ( ; j < hislen; ++i, ++j)
  			temp[i] = history[type][j];
  		}
--- 5353,5359 ----
  			temp[i] = history[type][i];
  		    j = i;
  		    for ( ; i <= newlen - (hislen - hisidx[type]); ++i)
! 			clear_hist_entry(&temp[i]);
  		    for ( ; j < hislen; ++i, ++j)
  			temp[i] = history[type][j];
  		}
***************
*** 5385,5390 ****
--- 5381,5395 ----
      }
  }
  
+     static void
+ clear_hist_entry(hisptr)
+     histentry_T	*hisptr;
+ {
+     hisptr->hisnum = 0;
+     hisptr->viminfo = FALSE;
+     hisptr->hisstr = NULL;
+ }
+ 
  /*
   * Check if command line 'str' is already in history.
   * If 'move_to_front' is TRUE, matching entry is moved to end of history.
***************
*** 5433,5440 ****
  	    history[type][last_i] = history[type][i];
  	    last_i = i;
  	}
- 	history[type][i].hisstr = str;
  	history[type][i].hisnum = ++hisnum[type];
  	return TRUE;
      }
      return FALSE;
--- 5438,5446 ----
  	    history[type][last_i] = history[type][i];
  	    last_i = i;
  	}
  	history[type][i].hisnum = ++hisnum[type];
+ 	history[type][i].viminfo = FALSE;
+ 	history[type][i].hisstr = str;
  	return TRUE;
      }
      return FALSE;
***************
*** 5498,5505 ****
  	    /* Current line is from the same mapping, remove it */
  	    hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]];
  	    vim_free(hisptr->hisstr);
! 	    hisptr->hisstr = NULL;
! 	    hisptr->hisnum = 0;
  	    --hisnum[histype];
  	    if (--hisidx[HIST_SEARCH] < 0)
  		hisidx[HIST_SEARCH] = hislen - 1;
--- 5504,5510 ----
  	    /* Current line is from the same mapping, remove it */
  	    hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]];
  	    vim_free(hisptr->hisstr);
! 	    clear_hist_entry(hisptr);
  	    --hisnum[histype];
  	    if (--hisidx[HIST_SEARCH] < 0)
  		hisidx[HIST_SEARCH] = hislen - 1;
***************
*** 5520,5525 ****
--- 5525,5531 ----
  	    hisptr->hisstr[len + 1] = sep;
  
  	hisptr->hisnum = ++hisnum[histype];
+ 	hisptr->viminfo = FALSE;
  	if (histype == HIST_SEARCH && in_map)
  	    last_maptick = maptick;
      }
***************
*** 5709,5716 ****
  	for (i = hislen; i--;)
  	{
  	    vim_free(hisptr->hisstr);
! 	    hisptr->hisnum = 0;
! 	    hisptr++->hisstr = NULL;
  	}
  	hisidx[histype] = -1;	/* mark history as cleared */
  	hisnum[histype] = 0;	/* reset identifier counter */
--- 5715,5721 ----
  	for (i = hislen; i--;)
  	{
  	    vim_free(hisptr->hisstr);
! 	    clear_hist_entry(hisptr);
  	}
  	hisidx[histype] = -1;	/* mark history as cleared */
  	hisnum[histype] = 0;	/* reset identifier counter */
***************
*** 5755,5770 ****
  	    {
  		found = TRUE;
  		vim_free(hisptr->hisstr);
! 		hisptr->hisstr = NULL;
! 		hisptr->hisnum = 0;
  	    }
  	    else
  	    {
  		if (i != last)
  		{
  		    history[histype][last] = *hisptr;
! 		    hisptr->hisstr = NULL;
! 		    hisptr->hisnum = 0;
  		}
  		if (--last < 0)
  		    last += hislen;
--- 5760,5773 ----
  	    {
  		found = TRUE;
  		vim_free(hisptr->hisstr);
! 		clear_hist_entry(hisptr);
  	    }
  	    else
  	    {
  		if (i != last)
  		{
  		    history[histype][last] = *hisptr;
! 		    clear_hist_entry(hisptr);
  		}
  		if (--last < 0)
  		    last += hislen;
***************
*** 5808,5815 ****
  	history[histype][i] = history[histype][j];
  	i = j;
      }
!     history[histype][i].hisstr = NULL;
!     history[histype][i].hisnum = 0;
      if (--i < 0)
  	i += hislen;
      hisidx[histype] = i;
--- 5811,5817 ----
  	history[histype][i] = history[histype][j];
  	i = j;
      }
!     clear_hist_entry(&history[histype][i]);
      if (--i < 0)
  	i += hislen;
      hisidx[histype] = i;
***************
*** 6043,6054 ****
  
      for (type = 0; type < HIST_COUNT; ++type)
      {
! 	/*
! 	 * Count the number of empty spaces in the history list.  If there are
! 	 * more spaces available than we request, then fill them up.
! 	 */
  	for (i = 0, num = 0; i < hislen; i++)
! 	    if (history[type][i].hisstr == NULL)
  		num++;
  	len = asklen;
  	if (num > len)
--- 6045,6055 ----
  
      for (type = 0; type < HIST_COUNT; ++type)
      {
! 	/* Count the number of empty spaces in the history list.  Entries read
! 	 * from viminfo previously are also considered empty.  If there are
! 	 * more spaces available than we request, then fill them up. */
  	for (i = 0, num = 0; i < hislen; i++)
! 	    if (history[type][i].hisstr == NULL || history[type][i].viminfo)
  		num++;
  	len = asklen;
  	if (num > len)
***************
*** 6141,6147 ****
  		hisidx[type] = hislen - 1;
  	    do
  	    {
! 		if (history[type][idx].hisstr != NULL)
  		    break;
  		if (++idx == hislen)
  		    idx = 0;
--- 6142,6149 ----
  		hisidx[type] = hislen - 1;
  	    do
  	    {
! 		if (history[type][idx].hisstr != NULL
! 						|| history[type][idx].viminfo)
  		    break;
  		if (++idx == hislen)
  		    idx = 0;
***************
*** 6153,6158 ****
--- 6155,6161 ----
  	{
  	    vim_free(history[type][idx].hisstr);
  	    history[type][idx].hisstr = viminfo_history[type][i];
+ 	    history[type][idx].viminfo = TRUE;
  	    if (--idx < 0)
  		idx = hislen - 1;
  	}
*** ../vim-7.3.879/src/version.c	2013-04-05 17:43:10.000000000 +0200
--- src/version.c	2013-04-05 18:54:11.000000000 +0200
***************
*** 730,731 ****
--- 730,733 ----
  {   /* Add new patch number below this line */
+ /**/
+     880,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
122. You ask if the Netaholics Anonymous t-shirt you ordered can be
     sent to you via e-mail.

 /// 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    ///
