comparison src/mark.c @ 9284:78712a2f687a v7.4.1925

commit https://github.com/vim/vim/commit/2d35899721da0e9359a9fe1059554f8c4ea7f0c1 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 12 21:20:54 2016 +0200 patch 7.4.1925 Problem: Viminfo does not merge file marks properly. Solution: Use a timestamp. Add the :clearjumps command.
author Christian Brabandt <cb@256bit.org>
date Sun, 12 Jun 2016 21:30:06 +0200
parents 41789f16d6b2
children 8000f0a44744
comparison
equal deleted inserted replaced
9283:0b359cb19c27 9284:78712a2f687a
104 /* Visual_mode has not yet been set, use a sane default. */ 104 /* Visual_mode has not yet been set, use a sane default. */
105 curbuf->b_visual.vi_mode = 'v'; 105 curbuf->b_visual.vi_mode = 'v';
106 return OK; 106 return OK;
107 } 107 }
108 108
109 #ifndef EBCDIC 109 if (ASCII_ISLOWER(c))
110 if (c > 'z') /* some islower() and isupper() cannot handle
111 characters above 127 */
112 return FAIL;
113 #endif
114 if (islower(c))
115 { 110 {
116 i = c - 'a'; 111 i = c - 'a';
117 curbuf->b_namedm[i] = *pos; 112 curbuf->b_namedm[i] = *pos;
118 return OK; 113 return OK;
119 } 114 }
120 if (isupper(c)) 115 if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c))
121 { 116 {
122 i = c - 'A'; 117 if (VIM_ISDIGIT(c))
118 i = c - '0' + NMARKS;
119 else
120 i = c - 'A';
123 namedfm[i].fmark.mark = *pos; 121 namedfm[i].fmark.mark = *pos;
124 namedfm[i].fmark.fnum = fnum; 122 namedfm[i].fmark.fnum = fnum;
125 vim_free(namedfm[i].fname); 123 vim_free(namedfm[i].fname);
126 namedfm[i].fname = NULL; 124 namedfm[i].fname = NULL;
125 #ifdef FEAT_VIMINFO
126 namedfm[i].time_set = vim_time();
127 #endif
127 return OK; 128 return OK;
128 } 129 }
129 return FAIL; 130 return FAIL;
130 } 131 }
131 132
182 fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1]; 183 fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
183 184
184 fm->fmark.mark = curwin->w_pcmark; 185 fm->fmark.mark = curwin->w_pcmark;
185 fm->fmark.fnum = curbuf->b_fnum; 186 fm->fmark.fnum = curbuf->b_fnum;
186 fm->fname = NULL; 187 fm->fname = NULL;
188 # ifdef FEAT_VIMINFO
189 fm->time_set = vim_time();
190 # endif
187 #endif 191 #endif
188 } 192 }
189 193
190 /* 194 /*
191 * To change context, call setpcmark(), then move the current position to 195 * To change context, call setpcmark(), then move the current position to
632 if (i == -1) /* first call ever: initialize */ 636 if (i == -1) /* first call ever: initialize */
633 for (i = 0; i < NMARKS + 1; i++) 637 for (i = 0; i < NMARKS + 1; i++)
634 { 638 {
635 namedfm[i].fmark.mark.lnum = 0; 639 namedfm[i].fmark.mark.lnum = 0;
636 namedfm[i].fname = NULL; 640 namedfm[i].fname = NULL;
641 #ifdef FEAT_VIMINFO
642 namedfm[i].time_set = 0;
643 #endif
637 } 644 }
638 645
639 for (i = 0; i < NMARKS; i++) 646 for (i = 0; i < NMARKS; i++)
640 buf->b_namedm[i].lnum = 0; 647 buf->b_namedm[i].lnum = 0;
641 buf->b_op_start.lnum = 0; /* start/end op mark cleared */ 648 buf->b_op_start.lnum = 0; /* start/end op mark cleared */
847 else 854 else
848 n = i - 'A'; 855 n = i - 'A';
849 namedfm[n].fmark.mark.lnum = 0; 856 namedfm[n].fmark.mark.lnum = 0;
850 vim_free(namedfm[n].fname); 857 vim_free(namedfm[n].fname);
851 namedfm[n].fname = NULL; 858 namedfm[n].fname = NULL;
859 #ifdef FEAT_VIMINFO
860 namedfm[n].time_set = 0;
861 #endif
852 } 862 }
853 } 863 }
854 } 864 }
855 else 865 else
856 switch (*p) 866 switch (*p)
914 } 924 }
915 out_flush(); 925 out_flush();
916 } 926 }
917 if (curwin->w_jumplistidx == curwin->w_jumplistlen) 927 if (curwin->w_jumplistidx == curwin->w_jumplistlen)
918 MSG_PUTS("\n>"); 928 MSG_PUTS("\n>");
929 }
930
931 void
932 ex_clearjumps(exarg_T *eap UNUSED)
933 {
934 free_jumplist(curwin);
935 curwin->w_jumplistlen = 0;
936 curwin->w_jumplistidx = 0;
919 } 937 }
920 938
921 /* 939 /*
922 * print the changelist 940 * print the changelist
923 */ 941 */
1398 fm->fmark.fnum = 0; 1416 fm->fmark.fnum = 0;
1399 str = skipwhite(str); 1417 str = skipwhite(str);
1400 vim_free(fm->fname); 1418 vim_free(fm->fname);
1401 fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line), 1419 fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line),
1402 FALSE); 1420 FALSE);
1421 fm->time_set = 0;
1403 } 1422 }
1404 } 1423 }
1405 return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd); 1424 return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
1425 }
1426
1427 static xfmark_T *vi_namedfm = NULL;
1428 #ifdef FEAT_JUMPLIST
1429 static xfmark_T *vi_jumplist = NULL;
1430 static int vi_jumplist_len = 0;
1431 #endif
1432
1433 /*
1434 * Prepare for reading viminfo marks when writing viminfo later.
1435 */
1436 void
1437 prepare_viminfo_marks(void)
1438 {
1439 vi_namedfm = (xfmark_T *)alloc_clear((NMARKS + EXTRA_MARKS)
1440 * (int)sizeof(xfmark_T));
1441 #ifdef FEAT_JUMPLIST
1442 vi_jumplist = (xfmark_T *)alloc_clear(JUMPLISTSIZE
1443 * (int)sizeof(xfmark_T));
1444 vi_jumplist_len = 0;
1445 #endif
1446 }
1447
1448 void
1449 finish_viminfo_marks(void)
1450 {
1451 int i;
1452
1453 if (vi_namedfm != NULL)
1454 {
1455 for (i = 0; i < NMARKS + EXTRA_MARKS; ++i)
1456 vim_free(vi_namedfm[i].fname);
1457 vim_free(vi_namedfm);
1458 vi_namedfm = NULL;
1459 }
1460 #ifdef FEAT_JUMPLIST
1461 if (vi_jumplist != NULL)
1462 {
1463 for (i = 0; i < vi_jumplist_len; ++i)
1464 vim_free(vi_jumplist[i].fname);
1465 vim_free(vi_jumplist);
1466 vi_jumplist = NULL;
1467 }
1468 #endif
1469 }
1470
1471 /*
1472 * Accept a new style mark line from the viminfo, store it when it's new.
1473 */
1474 void
1475 handle_viminfo_mark(garray_T *values, int force)
1476 {
1477 bval_T *vp = (bval_T *)values->ga_data;
1478 int name;
1479 linenr_T lnum;
1480 colnr_T col;
1481 time_t timestamp;
1482 xfmark_T *fm = NULL;
1483
1484 /* Check the format:
1485 * |{bartype},{name},{lnum},{col},{timestamp},{filename} */
1486 if (values->ga_len < 5
1487 || vp[0].bv_type != BVAL_NR
1488 || vp[1].bv_type != BVAL_NR
1489 || vp[2].bv_type != BVAL_NR
1490 || vp[3].bv_type != BVAL_NR
1491 || vp[4].bv_type != BVAL_STRING)
1492 return;
1493
1494 name = vp[0].bv_nr;
1495 if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name))
1496 return;
1497 lnum = vp[1].bv_nr;
1498 col = vp[2].bv_nr;
1499 if (lnum <= 0 || col < 0)
1500 return;
1501 timestamp = (time_t)vp[3].bv_nr;
1502
1503 if (name == '\'')
1504 {
1505 #ifdef FEAT_JUMPLIST
1506 if (vi_jumplist != NULL)
1507 {
1508 if (vi_jumplist_len < JUMPLISTSIZE)
1509 fm = &vi_jumplist[vi_jumplist_len++];
1510 }
1511 else
1512 {
1513 int idx;
1514 int i;
1515
1516 /* If we have a timestamp insert it in the right place. */
1517 if (timestamp != 0)
1518 {
1519 for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx)
1520 if (curwin->w_jumplist[idx].time_set < timestamp)
1521 break;
1522 }
1523 else if (curwin->w_jumplistlen < JUMPLISTSIZE)
1524 /* insert as oldest entry */
1525 idx = 0;
1526 else
1527 idx = -1;
1528
1529 if (idx >= 0)
1530 {
1531 if (curwin->w_jumplistlen == JUMPLISTSIZE)
1532 {
1533 /* Drop the oldest entry. */
1534 vim_free(curwin->w_jumplist[0].fname);
1535 for (i = 0; i < idx; ++i)
1536 curwin->w_jumplist[i] = curwin->w_jumplist[i + 1];
1537 }
1538 else
1539 {
1540 /* Move newer entries forward. */
1541 ++idx;
1542 for (i = curwin->w_jumplistlen; i > idx; --i)
1543 curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
1544 ++curwin->w_jumplistidx;
1545 ++curwin->w_jumplistlen;
1546 }
1547 fm = &curwin->w_jumplist[idx];
1548 fm->fmark.mark.lnum = 0;
1549 fm->fname = NULL;
1550 fm->time_set = 0;
1551 }
1552 }
1553 #endif
1554 }
1555 else
1556 {
1557 int idx;
1558
1559 if (VIM_ISDIGIT(name))
1560 {
1561 if (vi_namedfm != NULL)
1562 idx = name - '0' + NMARKS;
1563 else
1564 {
1565 int i;
1566
1567 /* Do not use the name from the viminfo file, insert in time
1568 * order. */
1569 for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx)
1570 if (namedfm[idx].time_set < timestamp)
1571 break;
1572 if (idx == NMARKS + EXTRA_MARKS)
1573 /* All existing entries are newer. */
1574 return;
1575 i = NMARKS + EXTRA_MARKS - 1;
1576
1577 vim_free(namedfm[i].fname);
1578 for ( ; i > idx; --i)
1579 namedfm[i] = namedfm[i - 1];
1580 namedfm[idx].fname = NULL;
1581 }
1582 }
1583 else
1584 idx = name - 'A';
1585 if (vi_namedfm != NULL)
1586 fm = &vi_namedfm[idx];
1587 else
1588 fm = &namedfm[idx];
1589 }
1590
1591 if (fm != NULL)
1592 {
1593 if (vi_namedfm != NULL || fm->time_set < timestamp || force)
1594 {
1595 fm->fmark.mark.lnum = lnum;
1596 fm->fmark.mark.col = col;
1597 #ifdef FEAT_VIRTUALEDIT
1598 fm->fmark.mark.coladd = 0;
1599 #endif
1600 fm->fmark.fnum = 0;
1601 vim_free(fm->fname);
1602 if (vp[4].bv_allocated)
1603 {
1604 fm->fname = vp[4].bv_string;
1605 vp[4].bv_string = NULL;
1606 }
1607 else
1608 fm->fname = vim_strsave(vp[4].bv_string);
1609 fm->time_set = timestamp;
1610 }
1611 }
1406 } 1612 }
1407 1613
1408 void 1614 void
1409 write_viminfo_filemarks(FILE *fp) 1615 write_viminfo_filemarks(FILE *fp)
1410 { 1616 {
1411 int i; 1617 int i;
1412 char_u *name; 1618 char_u *name;
1413 buf_T *buf; 1619 buf_T *buf;
1414 xfmark_T *fm; 1620 xfmark_T *fm;
1621 int vi_idx;
1622 int idx;
1415 1623
1416 if (get_viminfo_parameter('f') == 0) 1624 if (get_viminfo_parameter('f') == 0)
1417 return; 1625 return;
1418 1626
1419 fputs(_("\n# File marks:\n"), fp); 1627 fputs(_("\n# File marks:\n"), fp);
1628
1629 /* Write the filemarks 'A - 'Z */
1630 for (i = 0; i < NMARKS; i++)
1631 {
1632 if (vi_namedfm != NULL && (vi_namedfm[i].time_set > namedfm[i].time_set
1633 || namedfm[i].fmark.mark.lnum == 0))
1634 fm = &vi_namedfm[i];
1635 else
1636 fm = &namedfm[i];
1637 write_one_filemark(fp, fm, '\'', i + 'A');
1638 }
1420 1639
1421 /* 1640 /*
1422 * Find a mark that is the same file and position as the cursor. 1641 * Find a mark that is the same file and position as the cursor.
1423 * That one, or else the last one is deleted. 1642 * That one, or else the last one is deleted.
1424 * Move '0 to '1, '1 to '2, etc. until the matching one or '9 1643 * Move '0 to '1, '1 to '2, etc. until the matching one or '9
1425 * Set '0 mark to current cursor position. 1644 * Set the '0 mark to current cursor position.
1426 */ 1645 */
1427 if (curbuf->b_ffname != NULL && !removable(curbuf->b_ffname)) 1646 if (curbuf->b_ffname != NULL && !removable(curbuf->b_ffname))
1428 { 1647 {
1429 name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE); 1648 name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE);
1430 for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i) 1649 for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i)
1440 for ( ; i > NMARKS; --i) 1659 for ( ; i > NMARKS; --i)
1441 namedfm[i] = namedfm[i - 1]; 1660 namedfm[i] = namedfm[i - 1];
1442 namedfm[NMARKS].fmark.mark = curwin->w_cursor; 1661 namedfm[NMARKS].fmark.mark = curwin->w_cursor;
1443 namedfm[NMARKS].fmark.fnum = curbuf->b_fnum; 1662 namedfm[NMARKS].fmark.fnum = curbuf->b_fnum;
1444 namedfm[NMARKS].fname = NULL; 1663 namedfm[NMARKS].fname = NULL;
1445 } 1664 namedfm[NMARKS].time_set = vim_time();
1446 1665 }
1447 /* Write the filemarks '0 - '9 and 'A - 'Z */ 1666
1448 for (i = 0; i < NMARKS + EXTRA_MARKS; i++) 1667 /* Write the filemarks '0 - '9. Newest (highest timestamp) first. */
1449 write_one_filemark(fp, &namedfm[i], '\'', 1668 vi_idx = NMARKS;
1450 i < NMARKS ? i + 'A' : i - NMARKS + '0'); 1669 idx = NMARKS;
1670 for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++)
1671 {
1672 if (vi_namedfm != NULL
1673 && vi_namedfm[vi_idx].fmark.mark.lnum != 0
1674 && (vi_namedfm[vi_idx].time_set > namedfm[idx].time_set
1675 || namedfm[idx].fmark.mark.lnum == 0))
1676 fm = &vi_namedfm[vi_idx++];
1677 else
1678 fm = &namedfm[idx++];
1679 write_one_filemark(fp, fm, '\'', i - NMARKS + '0');
1680 }
1451 1681
1452 #ifdef FEAT_JUMPLIST 1682 #ifdef FEAT_JUMPLIST
1453 /* Write the jumplist with -' */ 1683 /* Write the jumplist with -' */
1454 fputs(_("\n# Jumplist (newest first):\n"), fp); 1684 fputs(_("\n# Jumplist (newest first):\n"), fp);
1455 setpcmark(); /* add current cursor position */ 1685 setpcmark(); /* add current cursor position */
1456 cleanup_jumplist(); 1686 cleanup_jumplist();
1687 /* TODO: when vi_jumplist != NULL merge the two lists. */
1457 for (fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1]; 1688 for (fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
1458 fm >= &curwin->w_jumplist[0]; --fm) 1689 fm >= &curwin->w_jumplist[0]; --fm)
1459 { 1690 {
1460 if (fm->fmark.fnum == 0 1691 if (fm->fmark.fnum == 0
1461 || ((buf = buflist_findnr(fm->fmark.fnum)) != NULL 1692 || ((buf = buflist_findnr(fm->fmark.fnum)) != NULL
1484 if (name != NULL && *name != NUL) 1715 if (name != NULL && *name != NUL)
1485 { 1716 {
1486 fprintf(fp, "%c%c %ld %ld ", c1, c2, (long)fm->fmark.mark.lnum, 1717 fprintf(fp, "%c%c %ld %ld ", c1, c2, (long)fm->fmark.mark.lnum,
1487 (long)fm->fmark.mark.col); 1718 (long)fm->fmark.mark.col);
1488 viminfo_writestring(fp, name); 1719 viminfo_writestring(fp, name);
1720
1721 /* Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename}
1722 * size up to filename: 8 + 3 * 20 */
1723 fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2,
1724 (long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col,
1725 (long)fm->time_set);
1726 barline_writestring(fp, name, LSIZE - 70);
1727 putc('\n', fp);
1489 } 1728 }
1490 1729
1491 if (fm->fmark.fnum != 0) 1730 if (fm->fmark.fnum != 0)
1492 vim_free(name); 1731 vim_free(name);
1493 } 1732 }