Patch 7.4.1911
Problem:    Recent history lines may be lost when exiting Vim.
Solution:   Merge history using the timestamp.
Files:      src/ex_getln.c, src/ex_cmds.c, src/vim.h, src/proto/ex_getln.pro,
            src/testdir/test_viminfo.vim


*** ../vim-7.4.1910/src/ex_getln.c      2016-06-06 21:07:48.383578685 +0200
--- src/ex_getln.c      2016-06-09 20:16:07.292055840 +0200
***************
*** 5536,5541 ****
--- 5536,5542 ----
      hisptr->hisnum = 0;
      hisptr->viminfo = FALSE;
      hisptr->hisstr = NULL;
+     hisptr->time_set = 0;
  }
  
  /*
***************
*** 6262,6267 ****
--- 6263,6270 ----
                    }
                    viminfo_history[type][viminfo_hisidx[type]].hisstr = p;
                    viminfo_history[type][viminfo_hisidx[type]].time_set = 0;
+                   viminfo_history[type][viminfo_hisidx[type]].viminfo = TRUE;
+                   viminfo_history[type][viminfo_hisidx[type]].hisnum = 0;
                    viminfo_hisidx[type]++;
                }
            }
***************
*** 6338,6343 ****
--- 6341,6348 ----
                        /* Put the separator after the NUL. */
                        p[len + 1] = sep;
                        viminfo_history[type][idx].hisstr = p;
+                       viminfo_history[type][idx].hisnum = 0;
+                       viminfo_history[type][idx].viminfo = TRUE;
                        viminfo_hisidx[type]++;
                    }
                }
***************
*** 6347,6403 ****
  }
  
  /*
!  * Finish reading history lines from viminfo.  Not used when writing viminfo.
   */
!     void
! finish_viminfo_history(void)
  {
      int idx;
      int i;
      int       type;
  
      for (type = 0; type < HIST_COUNT; ++type)
      {
        if (history[type] == NULL)
            continue;
!       idx = hisidx[type] + viminfo_hisidx[type];
!       if (idx >= hislen)
!           idx -= hislen;
!       else if (idx < 0)
!           idx = hislen - 1;
!       if (viminfo_add_at_front)
!           hisidx[type] = idx;
        else
!       {
!           if (hisidx[type] == -1)
!               hisidx[type] = hislen - 1;
!           do
!           {
!               if (history[type][idx].hisstr != NULL
!                                               || history[type][idx].viminfo)
!                   break;
!               if (++idx == hislen)
!                   idx = 0;
!           } while (idx != hisidx[type]);
!           if (idx != hisidx[type] && --idx < 0)
!               idx = hislen - 1;
!       }
!       for (i = 0; i < viminfo_hisidx[type]; i++)
!       {
!           vim_free(history[type][idx].hisstr);
!           history[type][idx].hisstr = viminfo_history[type][i].hisstr;
!           history[type][idx].viminfo = TRUE;
!           history[type][idx].time_set = viminfo_history[type][i].time_set;
!           if (--idx < 0)
!               idx = hislen - 1;
!       }
!       idx += 1;
!       idx %= hislen;
!       for (i = 0; i < viminfo_hisidx[type]; i++)
!       {
!           history[type][idx++].hisnum = ++hisnum[type];
!           idx %= hislen;
!       }
        vim_free(viminfo_history[type]);
        viminfo_history[type] = NULL;
        viminfo_hisidx[type] = 0;
--- 6352,6497 ----
  }
  
  /*
!  * Concatenate history lines from viminfo after the lines typed in this Vim.
   */
!     static void
! concat_history(int type)
  {
      int idx;
      int i;
+ 
+     idx = hisidx[type] + viminfo_hisidx[type];
+     if (idx >= hislen)
+       idx -= hislen;
+     else if (idx < 0)
+       idx = hislen - 1;
+     if (viminfo_add_at_front)
+       hisidx[type] = idx;
+     else
+     {
+       if (hisidx[type] == -1)
+           hisidx[type] = hislen - 1;
+       do
+       {
+           if (history[type][idx].hisstr != NULL
+                                           || history[type][idx].viminfo)
+               break;
+           if (++idx == hislen)
+               idx = 0;
+       } while (idx != hisidx[type]);
+       if (idx != hisidx[type] && --idx < 0)
+           idx = hislen - 1;
+     }
+     for (i = 0; i < viminfo_hisidx[type]; i++)
+     {
+       vim_free(history[type][idx].hisstr);
+       history[type][idx].hisstr = viminfo_history[type][i].hisstr;
+       history[type][idx].viminfo = TRUE;
+       history[type][idx].time_set = viminfo_history[type][i].time_set;
+       if (--idx < 0)
+           idx = hislen - 1;
+     }
+     idx += 1;
+     idx %= hislen;
+     for (i = 0; i < viminfo_hisidx[type]; i++)
+     {
+       history[type][idx++].hisnum = ++hisnum[type];
+       idx %= hislen;
+     }
+ }
+ 
+ #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
+     static int
+ #ifdef __BORLANDC__
+ _RTLENTRYF
+ #endif
+ sort_hist(const void *s1, const void *s2)
+ {
+     histentry_T *p1 = *(histentry_T **)s1;
+     histentry_T *p2 = *(histentry_T **)s2;
+ 
+     if (p1->time_set < p2->time_set) return -1;
+     if (p1->time_set > p2->time_set) return 1;
+     return 0;
+ }
+ #endif
+ 
+ /*
+  * Merge history lines from viminfo and lines typed in this Vim based on the
+  * timestamp;
+  */
+     static void
+ merge_history(int type)
+ {
+     int               max_len;
+     histentry_T **tot_hist;
+     histentry_T *new_hist;
+     int               i;
+     int               len;
+ 
+     /* Make one long list with all entries. */
+     max_len = hislen + viminfo_hisidx[type];
+     tot_hist = (histentry_T **)alloc(max_len * (int)sizeof(histentry_T *));
+     new_hist = (histentry_T *)alloc(hislen * (int)sizeof(histentry_T));
+     if (tot_hist == NULL || new_hist == NULL)
+     {
+       vim_free(tot_hist);
+       vim_free(new_hist);
+       return;
+     }
+     for (i = 0; i < viminfo_hisidx[type]; i++)
+       tot_hist[i] = &viminfo_history[type][i];
+     len = i;
+     for (i = 0; i < hislen; i++)
+       if (history[type][i].hisstr != NULL)
+           tot_hist[len++] = &history[type][i];
+ 
+     /* Sort the list on timestamp. */
+     qsort((void *)tot_hist, (size_t)len, sizeof(histentry_T *), sort_hist);
+ 
+     /* Keep the newest ones. */
+     for (i = 0; i < hislen; i++)
+     {
+       if (i < len)
+       {
+           new_hist[i] = *tot_hist[i];
+           tot_hist[i]->hisstr = NULL;
+           if (new_hist[i].hisnum == 0)
+               new_hist[i].hisnum = ++hisnum[type];
+       }
+       else
+           clear_hist_entry(&new_hist[i]);
+     }
+     hisidx[type] = len - 1;
+ 
+     /* Free what is not kept. */
+     for (i = 0; i < viminfo_hisidx[type]; i++)
+       vim_free(viminfo_history[type][i].hisstr);
+     for (i = 0; i < hislen; i++)
+       vim_free(history[type][i].hisstr);
+     vim_free(history[type]);
+     history[type] = new_hist;
+ }
+ 
+ /*
+  * Finish reading history lines from viminfo.  Not used when writing viminfo.
+  */
+     void
+ finish_viminfo_history(vir_T *virp)
+ {
      int       type;
+     int merge = virp->vir_version >= VIMINFO_VERSION_WITH_HISTORY;
  
      for (type = 0; type < HIST_COUNT; ++type)
      {
        if (history[type] == NULL)
            continue;
! 
!       if (merge)
!           merge_history(type);
        else
!           concat_history(type);
! 
        vim_free(viminfo_history[type]);
        viminfo_history[type] = NULL;
        viminfo_hisidx[type] = 0;
*** ../vim-7.4.1910/src/ex_cmds.c       2016-06-07 22:49:57.754305870 +0200
--- src/ex_cmds.c       2016-06-08 22:30:44.681133231 +0200
***************
*** 1755,1763 ****
  static void write_viminfo_barlines(vir_T *virp, FILE *fp_out);
  static int  viminfo_errcnt;
  
- #define VIMINFO_VERSION 2
- #define VIMINFO_VERSION_WITH_HISTORY 2
- 
      static int
  no_viminfo(void)
  {
--- 1755,1760 ----
***************
*** 2306,2312 ****
  #ifdef FEAT_CMDHIST
      /* Finish reading history items. */
      if (!writing)
!       finish_viminfo_history();
  #endif
  
      /* Change file names to buffer numbers for fmarks. */
--- 2303,2309 ----
  #ifdef FEAT_CMDHIST
      /* Finish reading history items. */
      if (!writing)
!       finish_viminfo_history(virp);
  #endif
  
      /* Change file names to buffer numbers for fmarks. */
*** ../vim-7.4.1910/src/vim.h   2016-06-06 21:20:05.927568540 +0200
--- src/vim.h   2016-06-08 22:31:01.521132999 +0200
***************
*** 1076,1081 ****
--- 1076,1084 ----
  #define BARTYPE_VERSION 1
  #define BARTYPE_HISTORY 2
  
+ #define VIMINFO_VERSION 2
+ #define VIMINFO_VERSION_WITH_HISTORY 2
+ 
  typedef enum {
      BVAL_NR,
      BVAL_STRING,
*** ../vim-7.4.1910/src/proto/ex_getln.pro      2016-06-06 21:07:48.387578685 
+0200
--- src/proto/ex_getln.pro      2016-06-08 22:22:23.377140126 +0200
***************
*** 51,57 ****
  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(void);
  void write_viminfo_history(FILE *fp, int merge);
  void cmd_pchar(int c, int offset);
  int cmd_gchar(int offset);
--- 51,57 ----
  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);
  int cmd_gchar(int offset);
*** ../vim-7.4.1910/src/testdir/test_viminfo.vim        2016-06-06 
21:07:48.387578685 +0200
--- src/testdir/test_viminfo.vim        2016-06-09 20:22:09.512050858 +0200
***************
*** 116,118 ****
--- 116,181 ----
  
    call delete('Xviminfo')
  endfunc
+ 
+ func Test_cmdline_history_order()
+   call histdel(':')
+   call test_settime(11)
+   call histadd(':', "echo '11'")
+   call test_settime(22)
+   call histadd(':', "echo '22'")
+   call test_settime(33)
+   call histadd(':', "echo '33'")
+   wviminfo Xviminfo
+ 
+   call histdel(':')
+   " items go in between
+   call test_settime(15)
+   call histadd(':', "echo '15'")
+   call test_settime(27)
+   call histadd(':', "echo '27'")
+ 
+   rviminfo Xviminfo
+   call assert_equal("echo '33'", histget(':', -1))
+   call assert_equal("echo '27'", histget(':', -2))
+   call assert_equal("echo '22'", histget(':', -3))
+   call assert_equal("echo '15'", histget(':', -4))
+   call assert_equal("echo '11'", histget(':', -5))
+ 
+   call histdel(':')
+   " items go before and after
+   call test_settime(8)
+   call histadd(':', "echo '8'")
+   call test_settime(39)
+   call histadd(':', "echo '39'")
+ 
+   rviminfo Xviminfo
+   call assert_equal("echo '39'", histget(':', -1))
+   call assert_equal("echo '33'", histget(':', -2))
+   call assert_equal("echo '22'", histget(':', -3))
+   call assert_equal("echo '11'", histget(':', -4))
+   call assert_equal("echo '8'", histget(':', -5))
+ 
+   " Check sorting works when writing with merge.
+   call histdel(':')
+   call test_settime(8)
+   call histadd(':', "echo '8'")
+   call test_settime(15)
+   call histadd(':', "echo '15'")
+   call test_settime(27)
+   call histadd(':', "echo '27'")
+   call test_settime(39)
+   call histadd(':', "echo '39'")
+   wviminfo Xviminfo
+   
+   call histdel(':')
+   rviminfo Xviminfo
+   call assert_equal("echo '39'", histget(':', -1))
+   call assert_equal("echo '33'", histget(':', -2))
+   call assert_equal("echo '27'", histget(':', -3))
+   call assert_equal("echo '22'", histget(':', -4))
+   call assert_equal("echo '15'", histget(':', -5))
+   call assert_equal("echo '11'", histget(':', -6))
+   call assert_equal("echo '8'", histget(':', -7))
+ 
+   call delete('Xviminfo')
+ endfunc
*** ../vim-7.4.1910/src/version.c       2016-06-08 21:48:47.201167860 +0200
--- src/version.c       2016-06-08 22:31:23.885132691 +0200
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     1911,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
81. At social functions you introduce your husband as "my domain server."

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