summaryrefslogtreecommitdiff
path: root/src/mark.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-06-12 21:20:54 +0200
committerBram Moolenaar <Bram@vim.org>2016-06-12 21:20:54 +0200
commit2d35899721da0e9359a9fe1059554f8c4ea7f0c1 (patch)
treefcb24c8186d9b23277948cb097e1807830737781 /src/mark.c
parentcf089463492fab53b2a5d81517829d22f882f82e (diff)
downloadvim-git-2d35899721da0e9359a9fe1059554f8c4ea7f0c1.tar.gz
patch 7.4.1925v7.4.1925
Problem: Viminfo does not merge file marks properly. Solution: Use a timestamp. Add the :clearjumps command.
Diffstat (limited to 'src/mark.c')
-rw-r--r--src/mark.c265
1 files changed, 252 insertions, 13 deletions
diff --git a/src/mark.c b/src/mark.c
index 346594773..34825a657 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -106,24 +106,25 @@ setmark_pos(int c, pos_T *pos, int fnum)
return OK;
}
-#ifndef EBCDIC
- if (c > 'z') /* some islower() and isupper() cannot handle
- characters above 127 */
- return FAIL;
-#endif
- if (islower(c))
+ if (ASCII_ISLOWER(c))
{
i = c - 'a';
curbuf->b_namedm[i] = *pos;
return OK;
}
- if (isupper(c))
+ if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c))
{
- i = c - 'A';
+ if (VIM_ISDIGIT(c))
+ i = c - '0' + NMARKS;
+ else
+ i = c - 'A';
namedfm[i].fmark.mark = *pos;
namedfm[i].fmark.fnum = fnum;
vim_free(namedfm[i].fname);
namedfm[i].fname = NULL;
+#ifdef FEAT_VIMINFO
+ namedfm[i].time_set = vim_time();
+#endif
return OK;
}
return FAIL;
@@ -184,6 +185,9 @@ setpcmark(void)
fm->fmark.mark = curwin->w_pcmark;
fm->fmark.fnum = curbuf->b_fnum;
fm->fname = NULL;
+# ifdef FEAT_VIMINFO
+ fm->time_set = vim_time();
+# endif
#endif
}
@@ -634,6 +638,9 @@ clrallmarks(buf_T *buf)
{
namedfm[i].fmark.mark.lnum = 0;
namedfm[i].fname = NULL;
+#ifdef FEAT_VIMINFO
+ namedfm[i].time_set = 0;
+#endif
}
for (i = 0; i < NMARKS; i++)
@@ -849,6 +856,9 @@ ex_delmarks(exarg_T *eap)
namedfm[n].fmark.mark.lnum = 0;
vim_free(namedfm[n].fname);
namedfm[n].fname = NULL;
+#ifdef FEAT_VIMINFO
+ namedfm[n].time_set = 0;
+#endif
}
}
}
@@ -918,6 +928,14 @@ ex_jumps(exarg_T *eap UNUSED)
MSG_PUTS("\n>");
}
+ void
+ex_clearjumps(exarg_T *eap UNUSED)
+{
+ free_jumplist(curwin);
+ curwin->w_jumplistlen = 0;
+ curwin->w_jumplistidx = 0;
+}
+
/*
* print the changelist
*/
@@ -1400,11 +1418,199 @@ read_viminfo_filemark(vir_T *virp, int force)
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 = (xfmark_T *)alloc_clear((NMARKS + EXTRA_MARKS)
+ * (int)sizeof(xfmark_T));
+#ifdef FEAT_JUMPLIST
+ vi_jumplist = (xfmark_T *)alloc_clear(JUMPLISTSIZE
+ * (int)sizeof(xfmark_T));
+ 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_free(vi_namedfm);
+ vi_namedfm = NULL;
+ }
+#ifdef FEAT_JUMPLIST
+ if (vi_jumplist != NULL)
+ {
+ for (i = 0; i < vi_jumplist_len; ++i)
+ vim_free(vi_jumplist[i].fname);
+ vim_free(vi_jumplist);
+ vi_jumplist = NULL;
+ }
+#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)
+ break;
+ }
+ 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. */
+ 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. */
+ ++idx;
+ 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->time_set < timestamp || force)
+ {
+ fm->fmark.mark.lnum = lnum;
+ fm->fmark.mark.col = col;
+#ifdef FEAT_VIRTUALEDIT
+ fm->fmark.mark.coladd = 0;
+#endif
+ 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;
+ }
+ }
+}
+
void
write_viminfo_filemarks(FILE *fp)
{
@@ -1412,17 +1618,30 @@ write_viminfo_filemarks(FILE *fp)
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 '0 mark to current cursor position.
+ * Set the '0 mark to current cursor position.
*/
if (curbuf->b_ffname != NULL && !removable(curbuf->b_ffname))
{
@@ -1442,18 +1661,30 @@ write_viminfo_filemarks(FILE *fp)
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 and 'A - 'Z */
- for (i = 0; i < NMARKS + EXTRA_MARKS; i++)
- write_one_filemark(fp, &namedfm[i], '\'',
- i < NMARKS ? i + 'A' : i - NMARKS + '0');
+ /* Write the filemarks '0 - '9. Newest (highest timestamp) first. */
+ vi_idx = NMARKS;
+ idx = NMARKS;
+ for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
+ {
+ if (vi_namedfm != NULL
+ && vi_namedfm[vi_idx].fmark.mark.lnum != 0
+ && (vi_namedfm[vi_idx].time_set > namedfm[idx].time_set
+ || namedfm[idx].fmark.mark.lnum == 0))
+ fm = &vi_namedfm[vi_idx++];
+ else
+ fm = &namedfm[idx++];
+ 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();
+ /* TODO: when vi_jumplist != NULL merge the two lists. */
for (fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
fm >= &curwin->w_jumplist[0]; --fm)
{
@@ -1486,6 +1717,14 @@ write_one_filemark(
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)