To: vim_dev@googlegroups.com Subject: Patch 8.1.1730 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 ", <ime); ! 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 ", <ime); + 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 -- 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 ///