Patch 8.1.1730
Problem:    Wrong place for mark viminfo support.
Solution:   Move it to viminfo.c. (Yegappan Lakshmanan, closes #4716)
Files:      src/README.md, src/mark.c, src/proto/mark.pro,
            src/proto/viminfo.pro, src/structs.h, src/viminfo.c


*** ../vim-8.1.1729/src/README.md       2019-07-14 21:29:04.554965965 +0200
--- src/README.md       2019-07-22 20:12:07.955124438 +0200
***************
*** 62,67 ****
--- 62,68 ----
  undo.c                | undo and redo
  usercmd.c     | user defined commands
  userfunc.c    | user defined functions
+ viminfo.c     | viminfo handling
  window.c      | handling split windows
  
  
*** ../vim-8.1.1729/src/mark.c  2019-05-28 23:08:12.068648696 +0200
--- src/mark.c  2019-07-22 20:14:44.844884080 +0200
***************
*** 24,38 ****
   * There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing
   * viminfo).
   */
- #define EXTRA_MARKS 10                                        /* marks 0-9 */
  static xfmark_T namedfm[NMARKS + EXTRA_MARKS];                /* marks with 
file nr */
  
  static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf);
  static char_u *mark_line(pos_T *mp, int lead_len);
  static void show_one_mark(int, char_u *, pos_T *, char_u *, int current);
- #ifdef FEAT_VIMINFO
- static void write_one_filemark(FILE *fp, xfmark_T *fm, int c1, int c2);
- #endif
  static void mark_adjust_internal(linenr_T line1, linenr_T line2, long amount,
      long amount_after, int adjust_folds);
  
--- 24,34 ----
***************
*** 1406,2214 ****
  }
  #endif
  
- #if defined(FEAT_VIMINFO) || defined(PROTO)
-     int
- read_viminfo_filemark(vir_T *virp, int force)
- {
-     char_u    *str;
-     xfmark_T  *fm;
-     int               i;
- 
-     /* We only get here if line[0] == '\'' or '-'.
-      * Illegal mark names are ignored (for future expansion). */
-     str = virp->vir_line + 1;
-     if (
- #ifndef EBCDIC
-           *str <= 127 &&
- #endif
-           ((*virp->vir_line == '\'' && (VIM_ISDIGIT(*str) || isupper(*str)))
-            || (*virp->vir_line == '-' && *str == '\'')))
-     {
-       if (*str == '\'')
-       {
- #ifdef FEAT_JUMPLIST
-           /* If the jumplist isn't full insert fmark as oldest entry */
-           if (curwin->w_jumplistlen == JUMPLISTSIZE)
-               fm = NULL;
-           else
-           {
-               for (i = curwin->w_jumplistlen; i > 0; --i)
-                   curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
-               ++curwin->w_jumplistidx;
-               ++curwin->w_jumplistlen;
-               fm = &curwin->w_jumplist[0];
-               fm->fmark.mark.lnum = 0;
-               fm->fname = NULL;
-           }
- #else
-           fm = NULL;
- #endif
-       }
-       else if (VIM_ISDIGIT(*str))
-           fm = &namedfm[*str - '0' + NMARKS];
-       else
-           fm = &namedfm[*str - 'A'];
-       if (fm != NULL && (fm->fmark.mark.lnum == 0 || force))
-       {
-           str = skipwhite(str + 1);
-           fm->fmark.mark.lnum = getdigits(&str);
-           str = skipwhite(str);
-           fm->fmark.mark.col = getdigits(&str);
-           fm->fmark.mark.coladd = 0;
-           fm->fmark.fnum = 0;
-           str = skipwhite(str);
-           vim_free(fm->fname);
-           fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line),
-                                                                      FALSE);
-           fm->time_set = 0;
-       }
-     }
-     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
- }
- 
- static xfmark_T *vi_namedfm = NULL;
- #ifdef FEAT_JUMPLIST
- static xfmark_T *vi_jumplist = NULL;
- static int vi_jumplist_len = 0;
- #endif
- 
  /*
!  * Prepare for reading viminfo marks when writing viminfo later.
   */
!     void
! prepare_viminfo_marks(void)
  {
!     vi_namedfm = ALLOC_CLEAR_MULT(xfmark_T, NMARKS + EXTRA_MARKS);
! #ifdef FEAT_JUMPLIST
!     vi_jumplist = ALLOC_CLEAR_MULT(xfmark_T, JUMPLISTSIZE);
!     vi_jumplist_len = 0;
! #endif
! }
! 
!     void
! finish_viminfo_marks(void)
! {
!     int               i;
! 
!     if (vi_namedfm != NULL)
!     {
!       for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
!           vim_free(vi_namedfm[i].fname);
!       VIM_CLEAR(vi_namedfm);
!     }
! #ifdef FEAT_JUMPLIST
!     if (vi_jumplist != NULL)
!     {
!       for (i = 0; i < vi_jumplist_len; ++i)
!           vim_free(vi_jumplist[i].fname);
!       VIM_CLEAR(vi_jumplist);
!     }
! #endif
! }
! 
! /*
!  * Accept a new style mark line from the viminfo, store it when it's new.
!  */
!     void
! handle_viminfo_mark(garray_T *values, int force)
! {
!     bval_T    *vp = (bval_T *)values->ga_data;
!     int               name;
!     linenr_T  lnum;
!     colnr_T   col;
!     time_t    timestamp;
!     xfmark_T  *fm = NULL;
! 
!     /* Check the format:
!      * |{bartype},{name},{lnum},{col},{timestamp},{filename} */
!     if (values->ga_len < 5
!           || 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_STRING)
!       return;
! 
!     name = vp[0].bv_nr;
!     if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name))
!       return;
!     lnum = vp[1].bv_nr;
!     col = vp[2].bv_nr;
!     if (lnum <= 0 || col < 0)
!       return;
!     timestamp = (time_t)vp[3].bv_nr;
! 
!     if (name == '\'')
!     {
! #ifdef FEAT_JUMPLIST
!       if (vi_jumplist != NULL)
!       {
!           if (vi_jumplist_len < JUMPLISTSIZE)
!               fm = &vi_jumplist[vi_jumplist_len++];
!       }
!       else
!       {
!           int idx;
!           int i;
! 
!           /* If we have a timestamp insert it in the right place. */
!           if (timestamp != 0)
!           {
!               for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx)
!                   if (curwin->w_jumplist[idx].time_set < timestamp)
!                   {
!                       ++idx;
!                       break;
!                   }
!               /* idx cannot be zero now */
!               if (idx < 0 && curwin->w_jumplistlen < JUMPLISTSIZE)
!                   /* insert as the oldest entry */
!                   idx = 0;
!           }
!           else if (curwin->w_jumplistlen < JUMPLISTSIZE)
!               /* insert as oldest entry */
!               idx = 0;
!           else
!               idx = -1;
! 
!           if (idx >= 0)
!           {
!               if (curwin->w_jumplistlen == JUMPLISTSIZE)
!               {
!                   /* Drop the oldest entry. */
!                   --idx;
!                   vim_free(curwin->w_jumplist[0].fname);
!                   for (i = 0; i < idx; ++i)
!                       curwin->w_jumplist[i] = curwin->w_jumplist[i + 1];
!               }
!               else
!               {
!                   /* Move newer entries forward. */
!                   for (i = curwin->w_jumplistlen; i > idx; --i)
!                       curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
!                   ++curwin->w_jumplistidx;
!                   ++curwin->w_jumplistlen;
!               }
!               fm = &curwin->w_jumplist[idx];
!               fm->fmark.mark.lnum = 0;
!               fm->fname = NULL;
!               fm->time_set = 0;
!           }
!       }
! #endif
!     }
!     else
!     {
!       int idx;
! 
!       if (VIM_ISDIGIT(name))
!       {
!           if (vi_namedfm != NULL)
!               idx = name - '0' + NMARKS;
!           else
!           {
!               int i;
! 
!               /* Do not use the name from the viminfo file, insert in time
!                * order. */
!               for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx)
!                   if (namedfm[idx].time_set < timestamp)
!                       break;
!               if (idx == NMARKS + EXTRA_MARKS)
!                   /* All existing entries are newer. */
!                   return;
!               i = NMARKS + EXTRA_MARKS - 1;
! 
!               vim_free(namedfm[i].fname);
!               for ( ; i > idx; --i)
!                   namedfm[i] = namedfm[i - 1];
!               namedfm[idx].fname = NULL;
!           }
!       }
!       else
!           idx = name - 'A';
!       if (vi_namedfm != NULL)
!           fm = &vi_namedfm[idx];
!       else
!           fm = &namedfm[idx];
!     }
! 
!     if (fm != NULL)
!     {
!       if (vi_namedfm != NULL || fm->fmark.mark.lnum == 0
!                                         || fm->time_set < timestamp || force)
!       {
!           fm->fmark.mark.lnum = lnum;
!           fm->fmark.mark.col = col;
!           fm->fmark.mark.coladd = 0;
!           fm->fmark.fnum = 0;
!           vim_free(fm->fname);
!           if (vp[4].bv_allocated)
!           {
!               fm->fname = vp[4].bv_string;
!               vp[4].bv_string = NULL;
!           }
!           else
!               fm->fname = vim_strsave(vp[4].bv_string);
!           fm->time_set = timestamp;
!       }
!     }
! }
! 
! /*
!  * Return TRUE if marks for "buf" should not be written.
!  */
!     static int
! skip_for_viminfo(buf_T *buf)
! {
!     return
! #ifdef FEAT_TERMINAL
!           bt_terminal(buf) ||
! #endif
!           removable(buf->b_ffname);
! }
! 
!     void
! write_viminfo_filemarks(FILE *fp)
! {
!     int               i;
!     char_u    *name;
!     buf_T     *buf;
!     xfmark_T  *fm;
!     int               vi_idx;
!     int               idx;
! 
!     if (get_viminfo_parameter('f') == 0)
!       return;
! 
!     fputs(_("\n# File marks:\n"), fp);
! 
!     /* Write the filemarks 'A - 'Z */
!     for (i = 0; i < NMARKS; i++)
!     {
!       if (vi_namedfm != NULL && (vi_namedfm[i].time_set > namedfm[i].time_set
!                                         || namedfm[i].fmark.mark.lnum == 0))
!           fm = &vi_namedfm[i];
!       else
!           fm = &namedfm[i];
!       write_one_filemark(fp, fm, '\'', i + 'A');
!     }
! 
!     /*
!      * Find a mark that is the same file and position as the cursor.
!      * That one, or else the last one is deleted.
!      * Move '0 to '1, '1 to '2, etc. until the matching one or '9
!      * Set the '0 mark to current cursor position.
!      */
!     if (curbuf->b_ffname != NULL && !skip_for_viminfo(curbuf))
!     {
!       name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE);
!       for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i)
!           if (namedfm[i].fmark.mark.lnum == curwin->w_cursor.lnum
!                   && (namedfm[i].fname == NULL
!                           ? namedfm[i].fmark.fnum == curbuf->b_fnum
!                           : (name != NULL
!                                   && STRCMP(name, namedfm[i].fname) == 0)))
!               break;
!       vim_free(name);
! 
!       vim_free(namedfm[i].fname);
!       for ( ; i > NMARKS; --i)
!           namedfm[i] = namedfm[i - 1];
!       namedfm[NMARKS].fmark.mark = curwin->w_cursor;
!       namedfm[NMARKS].fmark.fnum = curbuf->b_fnum;
!       namedfm[NMARKS].fname = NULL;
!       namedfm[NMARKS].time_set = vim_time();
!     }
! 
!     /* Write the filemarks '0 - '9.  Newest (highest timestamp) first. */
!     vi_idx = NMARKS;
!     idx = NMARKS;
!     for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
!     {
!       xfmark_T *vi_fm = vi_namedfm != NULL ? &vi_namedfm[vi_idx] : NULL;
! 
!       if (vi_fm != NULL
!               && vi_fm->fmark.mark.lnum != 0
!               && (vi_fm->time_set > namedfm[idx].time_set
!                   || namedfm[idx].fmark.mark.lnum == 0))
!       {
!           fm = vi_fm;
!           ++vi_idx;
!       }
!       else
!       {
!           fm = &namedfm[idx++];
!           if (vi_fm != NULL
!                 && vi_fm->fmark.mark.lnum == fm->fmark.mark.lnum
!                 && vi_fm->time_set == fm->time_set
!                 && ((vi_fm->fmark.fnum != 0
!                         && vi_fm->fmark.fnum == fm->fmark.fnum)
!                     || (vi_fm->fname != NULL
!                         && fm->fname != NULL
!                         && STRCMP(vi_fm->fname, fm->fname) == 0)))
!               ++vi_idx;  /* skip duplicate */
!       }
!       write_one_filemark(fp, fm, '\'', i - NMARKS + '0');
!     }
! 
! #ifdef FEAT_JUMPLIST
!     /* Write the jumplist with -' */
!     fputs(_("\n# Jumplist (newest first):\n"), fp);
!     setpcmark();      /* add current cursor position */
!     cleanup_jumplist(curwin, FALSE);
!     vi_idx = 0;
!     idx = curwin->w_jumplistlen - 1;
!     for (i = 0; i < JUMPLISTSIZE; ++i)
!     {
!       xfmark_T        *vi_fm;
! 
!       fm = idx >= 0 ? &curwin->w_jumplist[idx] : NULL;
!       vi_fm = vi_idx < vi_jumplist_len ? &vi_jumplist[vi_idx] : NULL;
!       if (fm == NULL && vi_fm == NULL)
!           break;
!       if (fm == NULL || (vi_fm != NULL && fm->time_set < vi_fm->time_set))
!       {
!           fm = vi_fm;
!           ++vi_idx;
!       }
!       else
!           --idx;
!       if (fm->fmark.fnum == 0
!               || ((buf = buflist_findnr(fm->fmark.fnum)) != NULL
!                   && !skip_for_viminfo(buf)))
!           write_one_filemark(fp, fm, '-', '\'');
!     }
! #endif
! }
! 
!     static void
! write_one_filemark(
!     FILE      *fp,
!     xfmark_T  *fm,
!     int               c1,
!     int               c2)
! {
!     char_u    *name;
! 
!     if (fm->fmark.mark.lnum == 0)     /* not set */
!       return;
! 
!     if (fm->fmark.fnum != 0)          /* there is a buffer */
!       name = buflist_nr2name(fm->fmark.fnum, TRUE, FALSE);
!     else
!       name = fm->fname;               /* use name from .viminfo */
!     if (name != NULL && *name != NUL)
!     {
!       fprintf(fp, "%c%c  %ld  %ld  ", c1, c2, (long)fm->fmark.mark.lnum,
!                                                   (long)fm->fmark.mark.col);
!       viminfo_writestring(fp, name);
! 
!       /* Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename}
!        * size up to filename: 8 + 3 * 20 */
!       fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2,
!               (long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col,
!               (long)fm->time_set);
!       barline_writestring(fp, name, LSIZE - 70);
!       putc('\n', fp);
!     }
! 
!     if (fm->fmark.fnum != 0)
!       vim_free(name);
! }
! 
! /*
!  * Return TRUE if "name" is on removable media (depending on 'viminfo').
!  */
!     int
! removable(char_u *name)
! {
!     char_u  *p;
!     char_u  part[51];
!     int           retval = FALSE;
!     size_t  n;
! 
!     name = home_replace_save(NULL, name);
!     if (name != NULL)
!     {
!       for (p = p_viminfo; *p; )
!       {
!           copy_option_part(&p, part, 51, ", ");
!           if (part[0] == 'r')
!           {
!               n = STRLEN(part + 1);
!               if (MB_STRNICMP(part + 1, name, n) == 0)
!               {
!                   retval = TRUE;
!                   break;
!               }
!           }
!       }
!       vim_free(name);
!     }
!     return retval;
! }
! 
!     static void
! write_one_mark(FILE *fp_out, int c, pos_T *pos)
! {
!     if (pos->lnum != 0)
!       fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col);
! }
! 
! 
!     static void
! write_buffer_marks(buf_T *buf, FILE *fp_out)
! {
!     int               i;
!     pos_T     pos;
! 
!     home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
!     fprintf(fp_out, "\n> ");
!     viminfo_writestring(fp_out, IObuff);
! 
!     /* Write the last used timestamp as the lnum of the non-existing mark '*'.
!      * Older Vims will ignore it and/or copy it. */
!     pos.lnum = (linenr_T)buf->b_last_used;
!     pos.col = 0;
!     write_one_mark(fp_out, '*', &pos);
! 
!     write_one_mark(fp_out, '"', &buf->b_last_cursor);
!     write_one_mark(fp_out, '^', &buf->b_last_insert);
!     write_one_mark(fp_out, '.', &buf->b_last_change);
! #ifdef FEAT_JUMPLIST
!     /* changelist positions are stored oldest first */
!     for (i = 0; i < buf->b_changelistlen; ++i)
!     {
!       /* skip duplicates */
!       if (i == 0 || !EQUAL_POS(buf->b_changelist[i - 1],
!                                                        buf->b_changelist[i]))
!           write_one_mark(fp_out, '+', &buf->b_changelist[i]);
!     }
! #endif
!     for (i = 0; i < NMARKS; i++)
!       write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
! }
! 
! /*
!  * Write all the named marks for all buffers.
!  * When "buflist" is not NULL fill it with the buffers for which marks are to
!  * be written.
!  */
!     void
! write_viminfo_marks(FILE *fp_out, garray_T *buflist)
! {
!     buf_T     *buf;
!     int               is_mark_set;
!     int               i;
!     win_T     *win;
!     tabpage_T *tp;
! 
!     /*
!      * Set b_last_cursor for the all buffers that have a window.
!      */
!     FOR_ALL_TAB_WINDOWS(tp, win)
!       set_last_cursor(win);
! 
!     fputs(_("\n# History of marks within files (newest to oldest):\n"), 
fp_out);
!     FOR_ALL_BUFFERS(buf)
!     {
!       /*
!        * Only write something if buffer has been loaded and at least one
!        * mark is set.
!        */
!       if (buf->b_marks_read)
!       {
!           if (buf->b_last_cursor.lnum != 0)
!               is_mark_set = TRUE;
!           else
!           {
!               is_mark_set = FALSE;
!               for (i = 0; i < NMARKS; i++)
!                   if (buf->b_namedm[i].lnum != 0)
!                   {
!                       is_mark_set = TRUE;
!                       break;
!                   }
!           }
!           if (is_mark_set && buf->b_ffname != NULL
!                     && buf->b_ffname[0] != NUL
!                     && !skip_for_viminfo(buf))
!           {
!               if (buflist == NULL)
!                   write_buffer_marks(buf, fp_out);
!               else if (ga_grow(buflist, 1) == OK)
!                   ((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf;
!           }
!       }
!     }
! }
! 
! /*
!  * Compare functions for qsort() below, that compares b_last_used.
!  */
!     static int
! buf_compare(const void *s1, const void *s2)
! {
!     buf_T *buf1 = *(buf_T **)s1;
!     buf_T *buf2 = *(buf_T **)s2;
! 
!     if (buf1->b_last_used == buf2->b_last_used)
!       return 0;
!     return buf1->b_last_used > buf2->b_last_used ? -1 : 1;
! }
! 
! /*
!  * Handle marks in the viminfo file:
!  * fp_out != NULL: copy marks, in time order with buffers in "buflist".
!  * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
!  * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
!  */
!     void
! copy_viminfo_marks(
!     vir_T     *virp,
!     FILE      *fp_out,
!     garray_T  *buflist,
!     int               eof,
!     int               flags)
! {
!     char_u    *line = virp->vir_line;
!     buf_T     *buf;
!     int               num_marked_files;
!     int               load_marks;
!     int               copy_marks_out;
!     char_u    *str;
!     int               i;
!     char_u    *p;
!     char_u    *name_buf;
!     pos_T     pos;
! #ifdef FEAT_EVAL
!     list_T    *list = NULL;
! #endif
!     int               count = 0;
!     int               buflist_used = 0;
!     buf_T     *buflist_buf = NULL;
! 
!     if ((name_buf = alloc(LSIZE)) == NULL)
!       return;
!     *name_buf = NUL;
! 
!     if (fp_out != NULL && buflist->ga_len > 0)
!     {
!       /* Sort the list of buffers on b_last_used. */
!       qsort(buflist->ga_data, (size_t)buflist->ga_len,
!                                               sizeof(buf_T *), buf_compare);
!       buflist_buf = ((buf_T **)buflist->ga_data)[0];
!     }
! 
! #ifdef FEAT_EVAL
!     if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT)))
!     {
!       list = list_alloc();
!       if (list != NULL)
!           set_vim_var_list(VV_OLDFILES, list);
!     }
! #endif
! 
!     num_marked_files = get_viminfo_parameter('\'');
!     while (!eof && (count < num_marked_files || fp_out == NULL))
!     {
!       if (line[0] != '>')
!       {
!           if (line[0] != '\n' && line[0] != '\r' && line[0] != '#')
!           {
!               if (viminfo_error("E576: ", _("Missing '>'"), line))
!                   break;      /* too many errors, return now */
!           }
!           eof = vim_fgets(line, LSIZE, virp->vir_fd);
!           continue;           /* Skip this dud line */
!       }
! 
!       /*
!        * Handle long line and translate escaped characters.
!        * Find file name, set str to start.
!        * Ignore leading and trailing white space.
!        */
!       str = skipwhite(line + 1);
!       str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE);
!       if (str == NULL)
!           continue;
!       p = str + STRLEN(str);
!       while (p != str && (*p == NUL || vim_isspace(*p)))
!           p--;
!       if (*p)
!           p++;
!       *p = NUL;
! 
! #ifdef FEAT_EVAL
!       if (list != NULL)
!           list_append_string(list, str, -1);
! #endif
! 
!       /*
!        * If fp_out == NULL, load marks for current buffer.
!        * If fp_out != NULL, copy marks for buffers not in buflist.
!        */
!       load_marks = copy_marks_out = FALSE;
!       if (fp_out == NULL)
!       {
!           if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL)
!           {
!               if (*name_buf == NUL)       /* only need to do this once */
!                   home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
!               if (fnamecmp(str, name_buf) == 0)
!                   load_marks = TRUE;
!           }
!       }
!       else /* fp_out != NULL */
!       {
!           /* This is slow if there are many buffers!! */
!           FOR_ALL_BUFFERS(buf)
!               if (buf->b_ffname != NULL)
!               {
!                   home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
!                   if (fnamecmp(str, name_buf) == 0)
!                       break;
!               }
! 
!           /*
!            * Copy marks if the buffer has not been loaded.
!            */
!           if (buf == NULL || !buf->b_marks_read)
!           {
!               int     did_read_line = FALSE;
! 
!               if (buflist_buf != NULL)
!               {
!                   /* Read the next line.  If it has the "*" mark compare the
!                    * time stamps.  Write entries from "buflist" that are
!                    * newer. */
!                   if (!(eof = viminfo_readline(virp)) && line[0] == TAB)
!                   {
!                       did_read_line = TRUE;
!                       if (line[1] == '*')
!                       {
!                           long        ltime;
! 
!                           sscanf((char *)line + 2, "%ld ", &ltime);
!                           while ((time_T)ltime < buflist_buf->b_last_used)
!                           {
!                               write_buffer_marks(buflist_buf, fp_out);
!                               if (++count >= num_marked_files)
!                                   break;
!                               if (++buflist_used == buflist->ga_len)
!                               {
!                                   buflist_buf = NULL;
!                                   break;
!                               }
!                               buflist_buf =
!                                  ((buf_T **)buflist->ga_data)[buflist_used];
!                           }
!                       }
!                       else
!                       {
!                           /* No timestamp, must be written by an older Vim.
!                            * Assume all remaining buffers are older then
!                            * ours.  */
!                           while (count < num_marked_files
!                                           && buflist_used < buflist->ga_len)
!                           {
!                               buflist_buf = ((buf_T **)buflist->ga_data)
!                                                            [buflist_used++];
!                               write_buffer_marks(buflist_buf, fp_out);
!                               ++count;
!                           }
!                           buflist_buf = NULL;
!                       }
! 
!                       if (count >= num_marked_files)
!                       {
!                           vim_free(str);
!                           break;
!                       }
!                   }
!               }
! 
!               fputs("\n> ", fp_out);
!               viminfo_writestring(fp_out, str);
!               if (did_read_line)
!                   fputs((char *)line, fp_out);
! 
!               count++;
!               copy_marks_out = TRUE;
!           }
!       }
!       vim_free(str);
! 
!       pos.coladd = 0;
!       while (!(eof = viminfo_readline(virp)) && line[0] == TAB)
!       {
!           if (load_marks)
!           {
!               if (line[1] != NUL)
!               {
!                   unsigned u;
! 
!                   sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u);
!                   pos.col = u;
!                   switch (line[1])
!                   {
!                       case '"': curbuf->b_last_cursor = pos; break;
!                       case '^': curbuf->b_last_insert = pos; break;
!                       case '.': curbuf->b_last_change = pos; break;
!                       case '+':
! #ifdef FEAT_JUMPLIST
!                                 /* changelist positions are stored oldest
!                                  * first */
!                                 if (curbuf->b_changelistlen == JUMPLISTSIZE)
!                                     /* list is full, remove oldest entry */
!                                     mch_memmove(curbuf->b_changelist,
!                                           curbuf->b_changelist + 1,
!                                           sizeof(pos_T) * (JUMPLISTSIZE - 1));
!                                 else
!                                     ++curbuf->b_changelistlen;
!                                 curbuf->b_changelist[
!                                          curbuf->b_changelistlen - 1] = pos;
! #endif
!                                 break;
! 
!                                 /* Using the line number for the last-used
!                                  * timestamp. */
!                       case '*': curbuf->b_last_used = pos.lnum; break;
! 
!                       default:  if ((i = line[1] - 'a') >= 0 && i < NMARKS)
!                                     curbuf->b_namedm[i] = pos;
!                   }
!               }
!           }
!           else if (copy_marks_out)
!               fputs((char *)line, fp_out);
!       }
! 
!       if (load_marks)
!       {
! #ifdef FEAT_JUMPLIST
!           win_T       *wp;
! 
!           FOR_ALL_WINDOWS(wp)
!           {
!               if (wp->w_buffer == curbuf)
!                   wp->w_changelistidx = curbuf->b_changelistlen;
!           }
! #endif
!           break;
!       }
!     }
! 
!     if (fp_out != NULL)
!       /* Write any remaining entries from buflist. */
!       while (count < num_marked_files && buflist_used < buflist->ga_len)
!       {
!           buflist_buf = ((buf_T **)buflist->ga_data)[buflist_used++];
!           write_buffer_marks(buflist_buf, fp_out);
!           ++count;
!       }
! 
!     vim_free(name_buf);
  }
- #endif /* FEAT_VIMINFO */
--- 1402,1412 ----
  }
  #endif
  
  /*
!  * Return a pointer to the named file marks.
   */
!     xfmark_T *
! get_namedfm(void)
  {
!     return namedfm;
  }
*** ../vim-8.1.1729/src/proto/mark.pro  2018-12-31 23:58:20.246887218 +0100
--- src/proto/mark.pro  2019-07-22 20:15:15.496488344 +0200
***************
*** 27,38 ****
  void free_jumplist(win_T *wp);
  void set_last_cursor(win_T *win);
  void free_all_marks(void);
! int read_viminfo_filemark(vir_T *virp, int force);
! void prepare_viminfo_marks(void);
! void finish_viminfo_marks(void);
! void handle_viminfo_mark(garray_T *values, int force);
! void write_viminfo_filemarks(FILE *fp);
! int removable(char_u *name);
! void write_viminfo_marks(FILE *fp_out, garray_T *buflist);
! void copy_viminfo_marks(vir_T *virp, FILE *fp_out, garray_T *buflist, int 
eof, int flags);
  /* vim: set ft=c : */
--- 27,31 ----
  void free_jumplist(win_T *wp);
  void set_last_cursor(win_T *win);
  void free_all_marks(void);
! xfmark_T *get_namedfm(void);
  /* vim: set ft=c : */
*** ../vim-8.1.1729/src/proto/viminfo.pro       2019-07-21 19:25:16.654609424 
+0200
--- src/proto/viminfo.pro       2019-07-22 20:12:07.955124438 +0200
***************
*** 7,10 ****
--- 7,18 ----
  void viminfo_writestring(FILE *fd, char_u *p);
  int barline_writestring(FILE *fd, char_u *s, int remaining_start);
  void ex_viminfo(exarg_T *eap);
+ int read_viminfo_filemark(vir_T *virp, int force);
+ void prepare_viminfo_marks(void);
+ void finish_viminfo_marks(void);
+ void handle_viminfo_mark(garray_T *values, int force);
+ void write_viminfo_filemarks(FILE *fp);
+ int removable(char_u *name);
+ void write_viminfo_marks(FILE *fp_out, garray_T *buflist);
+ void copy_viminfo_marks(vir_T *virp, FILE *fp_out, garray_T *buflist, int 
eof, int flags);
  /* vim: set ft=c : */
*** ../vim-8.1.1729/src/structs.h       2019-07-21 21:51:56.027609355 +0200
--- src/structs.h       2019-07-22 20:12:07.955124438 +0200
***************
*** 123,128 ****
--- 123,129 ----
  // alphabet coding.  To minimize changes to the code, I decided to just
  // increase the number of possible marks.
  #define NMARKS                ('z' - 'a' + 1) // max. # of named marks
+ #define EXTRA_MARKS   10              // marks 0-9
  #define JUMPLISTSIZE  100             // max. # of marks in jump list
  #define TAGSTACKSIZE  20              // max. # of tags in tag stack
  
*** ../vim-8.1.1729/src/viminfo.c       2019-07-21 21:51:56.027609355 +0200
--- src/viminfo.c       2019-07-22 20:15:09.120569650 +0200
***************
*** 1908,1911 ****
--- 1908,2707 ----
      p_viminfo = save_viminfo;
  }
  
+     int
+ read_viminfo_filemark(vir_T *virp, int force)
+ {
+     char_u    *str;
+     xfmark_T  *namedfm_p = get_namedfm();
+     xfmark_T  *fm;
+     int               i;
+ 
+     // We only get here if line[0] == '\'' or '-'.
+     // Illegal mark names are ignored (for future expansion).
+     str = virp->vir_line + 1;
+     if (
+ #ifndef EBCDIC
+           *str <= 127 &&
+ #endif
+           ((*virp->vir_line == '\'' && (VIM_ISDIGIT(*str) || isupper(*str)))
+            || (*virp->vir_line == '-' && *str == '\'')))
+     {
+       if (*str == '\'')
+       {
+ #ifdef FEAT_JUMPLIST
+           // If the jumplist isn't full insert fmark as oldest entry
+           if (curwin->w_jumplistlen == JUMPLISTSIZE)
+               fm = NULL;
+           else
+           {
+               for (i = curwin->w_jumplistlen; i > 0; --i)
+                   curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
+               ++curwin->w_jumplistidx;
+               ++curwin->w_jumplistlen;
+               fm = &curwin->w_jumplist[0];
+               fm->fmark.mark.lnum = 0;
+               fm->fname = NULL;
+           }
+ #else
+           fm = NULL;
+ #endif
+       }
+       else if (VIM_ISDIGIT(*str))
+           fm = &namedfm_p[*str - '0' + NMARKS];
+       else
+           fm = &namedfm_p[*str - 'A'];
+       if (fm != NULL && (fm->fmark.mark.lnum == 0 || force))
+       {
+           str = skipwhite(str + 1);
+           fm->fmark.mark.lnum = getdigits(&str);
+           str = skipwhite(str);
+           fm->fmark.mark.col = getdigits(&str);
+           fm->fmark.mark.coladd = 0;
+           fm->fmark.fnum = 0;
+           str = skipwhite(str);
+           vim_free(fm->fname);
+           fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line),
+                                                                      FALSE);
+           fm->time_set = 0;
+       }
+     }
+     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
+ }
+ 
+ static xfmark_T *vi_namedfm = NULL;
+ #ifdef FEAT_JUMPLIST
+ static xfmark_T *vi_jumplist = NULL;
+ static int vi_jumplist_len = 0;
+ #endif
+ 
+ /*
+  * Prepare for reading viminfo marks when writing viminfo later.
+  */
+     void
+ prepare_viminfo_marks(void)
+ {
+     vi_namedfm = ALLOC_CLEAR_MULT(xfmark_T, NMARKS + EXTRA_MARKS);
+ #ifdef FEAT_JUMPLIST
+     vi_jumplist = ALLOC_CLEAR_MULT(xfmark_T, JUMPLISTSIZE);
+     vi_jumplist_len = 0;
+ #endif
+ }
+ 
+     void
+ finish_viminfo_marks(void)
+ {
+     int               i;
+ 
+     if (vi_namedfm != NULL)
+     {
+       for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
+           vim_free(vi_namedfm[i].fname);
+       VIM_CLEAR(vi_namedfm);
+     }
+ #ifdef FEAT_JUMPLIST
+     if (vi_jumplist != NULL)
+     {
+       for (i = 0; i < vi_jumplist_len; ++i)
+           vim_free(vi_jumplist[i].fname);
+       VIM_CLEAR(vi_jumplist);
+     }
+ #endif
+ }
+ 
+ /*
+  * Accept a new style mark line from the viminfo, store it when it's new.
+  */
+     void
+ handle_viminfo_mark(garray_T *values, int force)
+ {
+     bval_T    *vp = (bval_T *)values->ga_data;
+     int               name;
+     linenr_T  lnum;
+     colnr_T   col;
+     time_t    timestamp;
+     xfmark_T  *fm = NULL;
+ 
+     // Check the format:
+     // |{bartype},{name},{lnum},{col},{timestamp},{filename}
+     if (values->ga_len < 5
+           || 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_STRING)
+       return;
+ 
+     name = vp[0].bv_nr;
+     if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name))
+       return;
+     lnum = vp[1].bv_nr;
+     col = vp[2].bv_nr;
+     if (lnum <= 0 || col < 0)
+       return;
+     timestamp = (time_t)vp[3].bv_nr;
+ 
+     if (name == '\'')
+     {
+ #ifdef FEAT_JUMPLIST
+       if (vi_jumplist != NULL)
+       {
+           if (vi_jumplist_len < JUMPLISTSIZE)
+               fm = &vi_jumplist[vi_jumplist_len++];
+       }
+       else
+       {
+           int idx;
+           int i;
+ 
+           // If we have a timestamp insert it in the right place.
+           if (timestamp != 0)
+           {
+               for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx)
+                   if (curwin->w_jumplist[idx].time_set < timestamp)
+                   {
+                       ++idx;
+                       break;
+                   }
+               // idx cannot be zero now
+               if (idx < 0 && curwin->w_jumplistlen < JUMPLISTSIZE)
+                   // insert as the oldest entry
+                   idx = 0;
+           }
+           else if (curwin->w_jumplistlen < JUMPLISTSIZE)
+               // insert as oldest entry
+               idx = 0;
+           else
+               idx = -1;
+ 
+           if (idx >= 0)
+           {
+               if (curwin->w_jumplistlen == JUMPLISTSIZE)
+               {
+                   // Drop the oldest entry.
+                   --idx;
+                   vim_free(curwin->w_jumplist[0].fname);
+                   for (i = 0; i < idx; ++i)
+                       curwin->w_jumplist[i] = curwin->w_jumplist[i + 1];
+               }
+               else
+               {
+                   // Move newer entries forward.
+                   for (i = curwin->w_jumplistlen; i > idx; --i)
+                       curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
+                   ++curwin->w_jumplistidx;
+                   ++curwin->w_jumplistlen;
+               }
+               fm = &curwin->w_jumplist[idx];
+               fm->fmark.mark.lnum = 0;
+               fm->fname = NULL;
+               fm->time_set = 0;
+           }
+       }
+ #endif
+     }
+     else
+     {
+       int             idx;
+       xfmark_T        *namedfm_p = get_namedfm();
+ 
+       if (VIM_ISDIGIT(name))
+       {
+           if (vi_namedfm != NULL)
+               idx = name - '0' + NMARKS;
+           else
+           {
+               int i;
+ 
+               // Do not use the name from the viminfo file, insert in time
+               // order.
+               for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx)
+                   if (namedfm_p[idx].time_set < timestamp)
+                       break;
+               if (idx == NMARKS + EXTRA_MARKS)
+                   // All existing entries are newer.
+                   return;
+               i = NMARKS + EXTRA_MARKS - 1;
+ 
+               vim_free(namedfm_p[i].fname);
+               for ( ; i > idx; --i)
+                   namedfm_p[i] = namedfm_p[i - 1];
+               namedfm_p[idx].fname = NULL;
+           }
+       }
+       else
+           idx = name - 'A';
+       if (vi_namedfm != NULL)
+           fm = &vi_namedfm[idx];
+       else
+           fm = &namedfm_p[idx];
+     }
+ 
+     if (fm != NULL)
+     {
+       if (vi_namedfm != NULL || fm->fmark.mark.lnum == 0
+                                         || fm->time_set < timestamp || force)
+       {
+           fm->fmark.mark.lnum = lnum;
+           fm->fmark.mark.col = col;
+           fm->fmark.mark.coladd = 0;
+           fm->fmark.fnum = 0;
+           vim_free(fm->fname);
+           if (vp[4].bv_allocated)
+           {
+               fm->fname = vp[4].bv_string;
+               vp[4].bv_string = NULL;
+           }
+           else
+               fm->fname = vim_strsave(vp[4].bv_string);
+           fm->time_set = timestamp;
+       }
+     }
+ }
+ 
+ /*
+  * Return TRUE if marks for "buf" should not be written.
+  */
+     static int
+ skip_for_viminfo(buf_T *buf)
+ {
+     return
+ #ifdef FEAT_TERMINAL
+           bt_terminal(buf) ||
+ #endif
+           removable(buf->b_ffname);
+ }
+ 
+     static void
+ write_one_filemark(
+     FILE      *fp,
+     xfmark_T  *fm,
+     int               c1,
+     int               c2)
+ {
+     char_u    *name;
+ 
+     if (fm->fmark.mark.lnum == 0)     // not set
+       return;
+ 
+     if (fm->fmark.fnum != 0)          // there is a buffer
+       name = buflist_nr2name(fm->fmark.fnum, TRUE, FALSE);
+     else
+       name = fm->fname;               // use name from .viminfo
+     if (name != NULL && *name != NUL)
+     {
+       fprintf(fp, "%c%c  %ld  %ld  ", c1, c2, (long)fm->fmark.mark.lnum,
+                                                   (long)fm->fmark.mark.col);
+       viminfo_writestring(fp, name);
+ 
+       // Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename}
+       // size up to filename: 8 + 3 * 20
+       fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2,
+               (long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col,
+               (long)fm->time_set);
+       barline_writestring(fp, name, LSIZE - 70);
+       putc('\n', fp);
+     }
+ 
+     if (fm->fmark.fnum != 0)
+       vim_free(name);
+ }
+ 
+     void
+ write_viminfo_filemarks(FILE *fp)
+ {
+     int               i;
+     char_u    *name;
+     buf_T     *buf;
+     xfmark_T  *namedfm_p = get_namedfm();
+     xfmark_T  *fm;
+     int               vi_idx;
+     int               idx;
+ 
+     if (get_viminfo_parameter('f') == 0)
+       return;
+ 
+     fputs(_("\n# File marks:\n"), fp);
+ 
+     // Write the filemarks 'A - 'Z
+     for (i = 0; i < NMARKS; i++)
+     {
+       if (vi_namedfm != NULL
+                       && (vi_namedfm[i].time_set > namedfm_p[i].time_set
+                           || namedfm_p[i].fmark.mark.lnum == 0))
+           fm = &vi_namedfm[i];
+       else
+           fm = &namedfm_p[i];
+       write_one_filemark(fp, fm, '\'', i + 'A');
+     }
+ 
+     // Find a mark that is the same file and position as the cursor.
+     // That one, or else the last one is deleted.
+     // Move '0 to '1, '1 to '2, etc. until the matching one or '9
+     // Set the '0 mark to current cursor position.
+     if (curbuf->b_ffname != NULL && !skip_for_viminfo(curbuf))
+     {
+       name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE);
+       for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i)
+           if (namedfm_p[i].fmark.mark.lnum == curwin->w_cursor.lnum
+                   && (namedfm_p[i].fname == NULL
+                           ? namedfm_p[i].fmark.fnum == curbuf->b_fnum
+                           : (name != NULL
+                                   && STRCMP(name, namedfm_p[i].fname) == 0)))
+               break;
+       vim_free(name);
+ 
+       vim_free(namedfm_p[i].fname);
+       for ( ; i > NMARKS; --i)
+           namedfm_p[i] = namedfm_p[i - 1];
+       namedfm_p[NMARKS].fmark.mark = curwin->w_cursor;
+       namedfm_p[NMARKS].fmark.fnum = curbuf->b_fnum;
+       namedfm_p[NMARKS].fname = NULL;
+       namedfm_p[NMARKS].time_set = vim_time();
+     }
+ 
+     // Write the filemarks '0 - '9.  Newest (highest timestamp) first.
+     vi_idx = NMARKS;
+     idx = NMARKS;
+     for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
+     {
+       xfmark_T *vi_fm = vi_namedfm != NULL ? &vi_namedfm[vi_idx] : NULL;
+ 
+       if (vi_fm != NULL
+               && vi_fm->fmark.mark.lnum != 0
+               && (vi_fm->time_set > namedfm_p[idx].time_set
+                   || namedfm_p[idx].fmark.mark.lnum == 0))
+       {
+           fm = vi_fm;
+           ++vi_idx;
+       }
+       else
+       {
+           fm = &namedfm_p[idx++];
+           if (vi_fm != NULL
+                 && vi_fm->fmark.mark.lnum == fm->fmark.mark.lnum
+                 && vi_fm->time_set == fm->time_set
+                 && ((vi_fm->fmark.fnum != 0
+                         && vi_fm->fmark.fnum == fm->fmark.fnum)
+                     || (vi_fm->fname != NULL
+                         && fm->fname != NULL
+                         && STRCMP(vi_fm->fname, fm->fname) == 0)))
+               ++vi_idx;  // skip duplicate
+       }
+       write_one_filemark(fp, fm, '\'', i - NMARKS + '0');
+     }
+ 
+ #ifdef FEAT_JUMPLIST
+     // Write the jumplist with -'
+     fputs(_("\n# Jumplist (newest first):\n"), fp);
+     setpcmark();      // add current cursor position
+     cleanup_jumplist(curwin, FALSE);
+     vi_idx = 0;
+     idx = curwin->w_jumplistlen - 1;
+     for (i = 0; i < JUMPLISTSIZE; ++i)
+     {
+       xfmark_T        *vi_fm;
+ 
+       fm = idx >= 0 ? &curwin->w_jumplist[idx] : NULL;
+       vi_fm = vi_idx < vi_jumplist_len ? &vi_jumplist[vi_idx] : NULL;
+       if (fm == NULL && vi_fm == NULL)
+           break;
+       if (fm == NULL || (vi_fm != NULL && fm->time_set < vi_fm->time_set))
+       {
+           fm = vi_fm;
+           ++vi_idx;
+       }
+       else
+           --idx;
+       if (fm->fmark.fnum == 0
+               || ((buf = buflist_findnr(fm->fmark.fnum)) != NULL
+                   && !skip_for_viminfo(buf)))
+           write_one_filemark(fp, fm, '-', '\'');
+     }
+ #endif
+ }
+ 
+ /*
+  * Return TRUE if "name" is on removable media (depending on 'viminfo').
+  */
+     int
+ removable(char_u *name)
+ {
+     char_u  *p;
+     char_u  part[51];
+     int           retval = FALSE;
+     size_t  n;
+ 
+     name = home_replace_save(NULL, name);
+     if (name != NULL)
+     {
+       for (p = p_viminfo; *p; )
+       {
+           copy_option_part(&p, part, 51, ", ");
+           if (part[0] == 'r')
+           {
+               n = STRLEN(part + 1);
+               if (MB_STRNICMP(part + 1, name, n) == 0)
+               {
+                   retval = TRUE;
+                   break;
+               }
+           }
+       }
+       vim_free(name);
+     }
+     return retval;
+ }
+ 
+     static void
+ write_one_mark(FILE *fp_out, int c, pos_T *pos)
+ {
+     if (pos->lnum != 0)
+       fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col);
+ }
+ 
+ 
+     static void
+ write_buffer_marks(buf_T *buf, FILE *fp_out)
+ {
+     int               i;
+     pos_T     pos;
+ 
+     home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE);
+     fprintf(fp_out, "\n> ");
+     viminfo_writestring(fp_out, IObuff);
+ 
+     // Write the last used timestamp as the lnum of the non-existing mark '*'.
+     // Older Vims will ignore it and/or copy it.
+     pos.lnum = (linenr_T)buf->b_last_used;
+     pos.col = 0;
+     write_one_mark(fp_out, '*', &pos);
+ 
+     write_one_mark(fp_out, '"', &buf->b_last_cursor);
+     write_one_mark(fp_out, '^', &buf->b_last_insert);
+     write_one_mark(fp_out, '.', &buf->b_last_change);
+ #ifdef FEAT_JUMPLIST
+     // changelist positions are stored oldest first
+     for (i = 0; i < buf->b_changelistlen; ++i)
+     {
+       // skip duplicates
+       if (i == 0 || !EQUAL_POS(buf->b_changelist[i - 1],
+                                                        buf->b_changelist[i]))
+           write_one_mark(fp_out, '+', &buf->b_changelist[i]);
+     }
+ #endif
+     for (i = 0; i < NMARKS; i++)
+       write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]);
+ }
+ 
+ /*
+  * Write all the named marks for all buffers.
+  * When "buflist" is not NULL fill it with the buffers for which marks are to
+  * be written.
+  */
+     void
+ write_viminfo_marks(FILE *fp_out, garray_T *buflist)
+ {
+     buf_T     *buf;
+     int               is_mark_set;
+     int               i;
+     win_T     *win;
+     tabpage_T *tp;
+ 
+     // Set b_last_cursor for the all buffers that have a window.
+     FOR_ALL_TAB_WINDOWS(tp, win)
+       set_last_cursor(win);
+ 
+     fputs(_("\n# History of marks within files (newest to oldest):\n"), 
fp_out);
+     FOR_ALL_BUFFERS(buf)
+     {
+       // Only write something if buffer has been loaded and at least one
+       // mark is set.
+       if (buf->b_marks_read)
+       {
+           if (buf->b_last_cursor.lnum != 0)
+               is_mark_set = TRUE;
+           else
+           {
+               is_mark_set = FALSE;
+               for (i = 0; i < NMARKS; i++)
+                   if (buf->b_namedm[i].lnum != 0)
+                   {
+                       is_mark_set = TRUE;
+                       break;
+                   }
+           }
+           if (is_mark_set && buf->b_ffname != NULL
+                     && buf->b_ffname[0] != NUL
+                     && !skip_for_viminfo(buf))
+           {
+               if (buflist == NULL)
+                   write_buffer_marks(buf, fp_out);
+               else if (ga_grow(buflist, 1) == OK)
+                   ((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf;
+           }
+       }
+     }
+ }
+ 
+ /*
+  * Compare functions for qsort() below, that compares b_last_used.
+  */
+     static int
+ buf_compare(const void *s1, const void *s2)
+ {
+     buf_T *buf1 = *(buf_T **)s1;
+     buf_T *buf2 = *(buf_T **)s2;
+ 
+     if (buf1->b_last_used == buf2->b_last_used)
+       return 0;
+     return buf1->b_last_used > buf2->b_last_used ? -1 : 1;
+ }
+ 
+ /*
+  * Handle marks in the viminfo file:
+  * fp_out != NULL: copy marks, in time order with buffers in "buflist".
+  * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only
+  * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles
+  */
+     void
+ copy_viminfo_marks(
+     vir_T     *virp,
+     FILE      *fp_out,
+     garray_T  *buflist,
+     int               eof,
+     int               flags)
+ {
+     char_u    *line = virp->vir_line;
+     buf_T     *buf;
+     int               num_marked_files;
+     int               load_marks;
+     int               copy_marks_out;
+     char_u    *str;
+     int               i;
+     char_u    *p;
+     char_u    *name_buf;
+     pos_T     pos;
+ #ifdef FEAT_EVAL
+     list_T    *list = NULL;
+ #endif
+     int               count = 0;
+     int               buflist_used = 0;
+     buf_T     *buflist_buf = NULL;
+ 
+     if ((name_buf = alloc(LSIZE)) == NULL)
+       return;
+     *name_buf = NUL;
+ 
+     if (fp_out != NULL && buflist->ga_len > 0)
+     {
+       // Sort the list of buffers on b_last_used.
+       qsort(buflist->ga_data, (size_t)buflist->ga_len,
+                                               sizeof(buf_T *), buf_compare);
+       buflist_buf = ((buf_T **)buflist->ga_data)[0];
+     }
+ 
+ #ifdef FEAT_EVAL
+     if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT)))
+     {
+       list = list_alloc();
+       if (list != NULL)
+           set_vim_var_list(VV_OLDFILES, list);
+     }
+ #endif
+ 
+     num_marked_files = get_viminfo_parameter('\'');
+     while (!eof && (count < num_marked_files || fp_out == NULL))
+     {
+       if (line[0] != '>')
+       {
+           if (line[0] != '\n' && line[0] != '\r' && line[0] != '#')
+           {
+               if (viminfo_error("E576: ", _("Missing '>'"), line))
+                   break;      // too many errors, return now
+           }
+           eof = vim_fgets(line, LSIZE, virp->vir_fd);
+           continue;           // Skip this dud line
+       }
+ 
+       // Handle long line and translate escaped characters.
+       // Find file name, set str to start.
+       // Ignore leading and trailing white space.
+       str = skipwhite(line + 1);
+       str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE);
+       if (str == NULL)
+           continue;
+       p = str + STRLEN(str);
+       while (p != str && (*p == NUL || vim_isspace(*p)))
+           p--;
+       if (*p)
+           p++;
+       *p = NUL;
+ 
+ #ifdef FEAT_EVAL
+       if (list != NULL)
+           list_append_string(list, str, -1);
+ #endif
+ 
+       // If fp_out == NULL, load marks for current buffer.
+       // If fp_out != NULL, copy marks for buffers not in buflist.
+       load_marks = copy_marks_out = FALSE;
+       if (fp_out == NULL)
+       {
+           if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL)
+           {
+               if (*name_buf == NUL)       // only need to do this once
+                   home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE);
+               if (fnamecmp(str, name_buf) == 0)
+                   load_marks = TRUE;
+           }
+       }
+       else // fp_out != NULL
+       {
+           // This is slow if there are many buffers!!
+           FOR_ALL_BUFFERS(buf)
+               if (buf->b_ffname != NULL)
+               {
+                   home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE);
+                   if (fnamecmp(str, name_buf) == 0)
+                       break;
+               }
+ 
+           // Copy marks if the buffer has not been loaded.
+           if (buf == NULL || !buf->b_marks_read)
+           {
+               int     did_read_line = FALSE;
+ 
+               if (buflist_buf != NULL)
+               {
+                   // Read the next line.  If it has the "*" mark compare the
+                   // time stamps.  Write entries from "buflist" that are
+                   // newer.
+                   if (!(eof = viminfo_readline(virp)) && line[0] == TAB)
+                   {
+                       did_read_line = TRUE;
+                       if (line[1] == '*')
+                       {
+                           long        ltime;
+ 
+                           sscanf((char *)line + 2, "%ld ", &ltime);
+                           while ((time_T)ltime < buflist_buf->b_last_used)
+                           {
+                               write_buffer_marks(buflist_buf, fp_out);
+                               if (++count >= num_marked_files)
+                                   break;
+                               if (++buflist_used == buflist->ga_len)
+                               {
+                                   buflist_buf = NULL;
+                                   break;
+                               }
+                               buflist_buf =
+                                  ((buf_T **)buflist->ga_data)[buflist_used];
+                           }
+                       }
+                       else
+                       {
+                           // No timestamp, must be written by an older Vim.
+                           // Assume all remaining buffers are older then
+                           // ours.
+                           while (count < num_marked_files
+                                           && buflist_used < buflist->ga_len)
+                           {
+                               buflist_buf = ((buf_T **)buflist->ga_data)
+                                                            [buflist_used++];
+                               write_buffer_marks(buflist_buf, fp_out);
+                               ++count;
+                           }
+                           buflist_buf = NULL;
+                       }
+ 
+                       if (count >= num_marked_files)
+                       {
+                           vim_free(str);
+                           break;
+                       }
+                   }
+               }
+ 
+               fputs("\n> ", fp_out);
+               viminfo_writestring(fp_out, str);
+               if (did_read_line)
+                   fputs((char *)line, fp_out);
+ 
+               count++;
+               copy_marks_out = TRUE;
+           }
+       }
+       vim_free(str);
+ 
+       pos.coladd = 0;
+       while (!(eof = viminfo_readline(virp)) && line[0] == TAB)
+       {
+           if (load_marks)
+           {
+               if (line[1] != NUL)
+               {
+                   unsigned u;
+ 
+                   sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u);
+                   pos.col = u;
+                   switch (line[1])
+                   {
+                       case '"': curbuf->b_last_cursor = pos; break;
+                       case '^': curbuf->b_last_insert = pos; break;
+                       case '.': curbuf->b_last_change = pos; break;
+                       case '+':
+ #ifdef FEAT_JUMPLIST
+                                 // changelist positions are stored oldest
+                                 // first
+                                 if (curbuf->b_changelistlen == JUMPLISTSIZE)
+                                     // list is full, remove oldest entry
+                                     mch_memmove(curbuf->b_changelist,
+                                           curbuf->b_changelist + 1,
+                                           sizeof(pos_T) * (JUMPLISTSIZE - 1));
+                                 else
+                                     ++curbuf->b_changelistlen;
+                                 curbuf->b_changelist[
+                                          curbuf->b_changelistlen - 1] = pos;
+ #endif
+                                 break;
+ 
+                                 // Using the line number for the last-used
+                                 // timestamp.
+                       case '*': curbuf->b_last_used = pos.lnum; break;
+ 
+                       default:  if ((i = line[1] - 'a') >= 0 && i < NMARKS)
+                                     curbuf->b_namedm[i] = pos;
+                   }
+               }
+           }
+           else if (copy_marks_out)
+               fputs((char *)line, fp_out);
+       }
+ 
+       if (load_marks)
+       {
+ #ifdef FEAT_JUMPLIST
+           win_T       *wp;
+ 
+           FOR_ALL_WINDOWS(wp)
+           {
+               if (wp->w_buffer == curbuf)
+                   wp->w_changelistidx = curbuf->b_changelistlen;
+           }
+ #endif
+           break;
+       }
+     }
+ 
+     if (fp_out != NULL)
+       // Write any remaining entries from buflist.
+       while (count < num_marked_files && buflist_used < buflist->ga_len)
+       {
+           buflist_buf = ((buf_T **)buflist->ga_data)[buflist_used++];
+           write_buffer_marks(buflist_buf, fp_out);
+           ++count;
+       }
+ 
+     vim_free(name_buf);
+ }
  #endif // FEAT_VIMINFO
*** ../vim-8.1.1729/src/version.c       2019-07-21 23:04:14.079123854 +0200
--- src/version.c       2019-07-22 20:13:19.346056979 +0200
***************
*** 779,780 ****
--- 779,782 ----
  {   /* Add new patch number below this line */
+ /**/
+     1730,
  /**/

-- 
The Characters and incidents portrayed and the names used are fictitious and
any similarity to the names, characters, or history of any person is entirely
accidental and unintentional.
                                  Signed RICHARD M. NIXON
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201907221818.x6MIIgW8030450%40masaka.moolenaar.net.

Raspunde prin e-mail lui