Mercurial > vim
comparison src/mark.c @ 17464:3e708b5c0509 v8.1.1730
patch 8.1.1730: wrong place for mark viminfo support
commit https://github.com/vim/vim/commit/1e78e69680a5f52970d9b1ef60710e556b09b8c2
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Jul 22 20:18:27 2019 +0200
patch 8.1.1730: wrong place for mark viminfo support
Problem: Wrong place for mark viminfo support.
Solution: Move it to viminfo.c. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/4716)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 22 Jul 2019 20:30:05 +0200 |
parents | ce04ebdf26b8 |
children | 0f7ae8010787 |
comparison
equal
deleted
inserted
replaced
17463:16f01738068b | 17464:3e708b5c0509 |
---|---|
22 * If a named file mark's fnum is non-zero, it is for an existing buffer, | 22 * If a named file mark's fnum is non-zero, it is for an existing buffer, |
23 * otherwise it is from .viminfo and namedfm[n].fname is the file name. | 23 * otherwise it is from .viminfo and namedfm[n].fname is the file name. |
24 * There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing | 24 * There are marks 'A - 'Z (set by user) and '0 to '9 (set when writing |
25 * viminfo). | 25 * viminfo). |
26 */ | 26 */ |
27 #define EXTRA_MARKS 10 /* marks 0-9 */ | |
28 static xfmark_T namedfm[NMARKS + EXTRA_MARKS]; /* marks with file nr */ | 27 static xfmark_T namedfm[NMARKS + EXTRA_MARKS]; /* marks with file nr */ |
29 | 28 |
30 static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf); | 29 static void fmarks_check_one(xfmark_T *fm, char_u *name, buf_T *buf); |
31 static char_u *mark_line(pos_T *mp, int lead_len); | 30 static char_u *mark_line(pos_T *mp, int lead_len); |
32 static void show_one_mark(int, char_u *, pos_T *, char_u *, int current); | 31 static void show_one_mark(int, char_u *, pos_T *, char_u *, int current); |
33 #ifdef FEAT_VIMINFO | |
34 static void write_one_filemark(FILE *fp, xfmark_T *fm, int c1, int c2); | |
35 #endif | |
36 static void mark_adjust_internal(linenr_T line1, linenr_T line2, long amount, | 32 static void mark_adjust_internal(linenr_T line1, linenr_T line2, long amount, |
37 long amount_after, int adjust_folds); | 33 long amount_after, int adjust_folds); |
38 | 34 |
39 /* | 35 /* |
40 * Set named mark "c" at current cursor position. | 36 * Set named mark "c" at current cursor position. |
1404 if (namedfm[i].fmark.mark.lnum != 0) | 1400 if (namedfm[i].fmark.mark.lnum != 0) |
1405 vim_free(namedfm[i].fname); | 1401 vim_free(namedfm[i].fname); |
1406 } | 1402 } |
1407 #endif | 1403 #endif |
1408 | 1404 |
1409 #if defined(FEAT_VIMINFO) || defined(PROTO) | 1405 /* |
1410 int | 1406 * Return a pointer to the named file marks. |
1411 read_viminfo_filemark(vir_T *virp, int force) | 1407 */ |
1412 { | 1408 xfmark_T * |
1413 char_u *str; | 1409 get_namedfm(void) |
1414 xfmark_T *fm; | 1410 { |
1415 int i; | 1411 return namedfm; |
1416 | 1412 } |
1417 /* We only get here if line[0] == '\'' or '-'. | |
1418 * Illegal mark names are ignored (for future expansion). */ | |
1419 str = virp->vir_line + 1; | |
1420 if ( | |
1421 #ifndef EBCDIC | |
1422 *str <= 127 && | |
1423 #endif | |
1424 ((*virp->vir_line == '\'' && (VIM_ISDIGIT(*str) || isupper(*str))) | |
1425 || (*virp->vir_line == '-' && *str == '\''))) | |
1426 { | |
1427 if (*str == '\'') | |
1428 { | |
1429 #ifdef FEAT_JUMPLIST | |
1430 /* If the jumplist isn't full insert fmark as oldest entry */ | |
1431 if (curwin->w_jumplistlen == JUMPLISTSIZE) | |
1432 fm = NULL; | |
1433 else | |
1434 { | |
1435 for (i = curwin->w_jumplistlen; i > 0; --i) | |
1436 curwin->w_jumplist[i] = curwin->w_jumplist[i - 1]; | |
1437 ++curwin->w_jumplistidx; | |
1438 ++curwin->w_jumplistlen; | |
1439 fm = &curwin->w_jumplist[0]; | |
1440 fm->fmark.mark.lnum = 0; | |
1441 fm->fname = NULL; | |
1442 } | |
1443 #else | |
1444 fm = NULL; | |
1445 #endif | |
1446 } | |
1447 else if (VIM_ISDIGIT(*str)) | |
1448 fm = &namedfm[*str - '0' + NMARKS]; | |
1449 else | |
1450 fm = &namedfm[*str - 'A']; | |
1451 if (fm != NULL && (fm->fmark.mark.lnum == 0 || force)) | |
1452 { | |
1453 str = skipwhite(str + 1); | |
1454 fm->fmark.mark.lnum = getdigits(&str); | |
1455 str = skipwhite(str); | |
1456 fm->fmark.mark.col = getdigits(&str); | |
1457 fm->fmark.mark.coladd = 0; | |
1458 fm->fmark.fnum = 0; | |
1459 str = skipwhite(str); | |
1460 vim_free(fm->fname); | |
1461 fm->fname = viminfo_readstring(virp, (int)(str - virp->vir_line), | |
1462 FALSE); | |
1463 fm->time_set = 0; | |
1464 } | |
1465 } | |
1466 return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd); | |
1467 } | |
1468 | |
1469 static xfmark_T *vi_namedfm = NULL; | |
1470 #ifdef FEAT_JUMPLIST | |
1471 static xfmark_T *vi_jumplist = NULL; | |
1472 static int vi_jumplist_len = 0; | |
1473 #endif | |
1474 | |
1475 /* | |
1476 * Prepare for reading viminfo marks when writing viminfo later. | |
1477 */ | |
1478 void | |
1479 prepare_viminfo_marks(void) | |
1480 { | |
1481 vi_namedfm = ALLOC_CLEAR_MULT(xfmark_T, NMARKS + EXTRA_MARKS); | |
1482 #ifdef FEAT_JUMPLIST | |
1483 vi_jumplist = ALLOC_CLEAR_MULT(xfmark_T, JUMPLISTSIZE); | |
1484 vi_jumplist_len = 0; | |
1485 #endif | |
1486 } | |
1487 | |
1488 void | |
1489 finish_viminfo_marks(void) | |
1490 { | |
1491 int i; | |
1492 | |
1493 if (vi_namedfm != NULL) | |
1494 { | |
1495 for (i = 0; i < NMARKS + EXTRA_MARKS; ++i) | |
1496 vim_free(vi_namedfm[i].fname); | |
1497 VIM_CLEAR(vi_namedfm); | |
1498 } | |
1499 #ifdef FEAT_JUMPLIST | |
1500 if (vi_jumplist != NULL) | |
1501 { | |
1502 for (i = 0; i < vi_jumplist_len; ++i) | |
1503 vim_free(vi_jumplist[i].fname); | |
1504 VIM_CLEAR(vi_jumplist); | |
1505 } | |
1506 #endif | |
1507 } | |
1508 | |
1509 /* | |
1510 * Accept a new style mark line from the viminfo, store it when it's new. | |
1511 */ | |
1512 void | |
1513 handle_viminfo_mark(garray_T *values, int force) | |
1514 { | |
1515 bval_T *vp = (bval_T *)values->ga_data; | |
1516 int name; | |
1517 linenr_T lnum; | |
1518 colnr_T col; | |
1519 time_t timestamp; | |
1520 xfmark_T *fm = NULL; | |
1521 | |
1522 /* Check the format: | |
1523 * |{bartype},{name},{lnum},{col},{timestamp},{filename} */ | |
1524 if (values->ga_len < 5 | |
1525 || vp[0].bv_type != BVAL_NR | |
1526 || vp[1].bv_type != BVAL_NR | |
1527 || vp[2].bv_type != BVAL_NR | |
1528 || vp[3].bv_type != BVAL_NR | |
1529 || vp[4].bv_type != BVAL_STRING) | |
1530 return; | |
1531 | |
1532 name = vp[0].bv_nr; | |
1533 if (name != '\'' && !VIM_ISDIGIT(name) && !ASCII_ISUPPER(name)) | |
1534 return; | |
1535 lnum = vp[1].bv_nr; | |
1536 col = vp[2].bv_nr; | |
1537 if (lnum <= 0 || col < 0) | |
1538 return; | |
1539 timestamp = (time_t)vp[3].bv_nr; | |
1540 | |
1541 if (name == '\'') | |
1542 { | |
1543 #ifdef FEAT_JUMPLIST | |
1544 if (vi_jumplist != NULL) | |
1545 { | |
1546 if (vi_jumplist_len < JUMPLISTSIZE) | |
1547 fm = &vi_jumplist[vi_jumplist_len++]; | |
1548 } | |
1549 else | |
1550 { | |
1551 int idx; | |
1552 int i; | |
1553 | |
1554 /* If we have a timestamp insert it in the right place. */ | |
1555 if (timestamp != 0) | |
1556 { | |
1557 for (idx = curwin->w_jumplistlen - 1; idx >= 0; --idx) | |
1558 if (curwin->w_jumplist[idx].time_set < timestamp) | |
1559 { | |
1560 ++idx; | |
1561 break; | |
1562 } | |
1563 /* idx cannot be zero now */ | |
1564 if (idx < 0 && curwin->w_jumplistlen < JUMPLISTSIZE) | |
1565 /* insert as the oldest entry */ | |
1566 idx = 0; | |
1567 } | |
1568 else if (curwin->w_jumplistlen < JUMPLISTSIZE) | |
1569 /* insert as oldest entry */ | |
1570 idx = 0; | |
1571 else | |
1572 idx = -1; | |
1573 | |
1574 if (idx >= 0) | |
1575 { | |
1576 if (curwin->w_jumplistlen == JUMPLISTSIZE) | |
1577 { | |
1578 /* Drop the oldest entry. */ | |
1579 --idx; | |
1580 vim_free(curwin->w_jumplist[0].fname); | |
1581 for (i = 0; i < idx; ++i) | |
1582 curwin->w_jumplist[i] = curwin->w_jumplist[i + 1]; | |
1583 } | |
1584 else | |
1585 { | |
1586 /* Move newer entries forward. */ | |
1587 for (i = curwin->w_jumplistlen; i > idx; --i) | |
1588 curwin->w_jumplist[i] = curwin->w_jumplist[i - 1]; | |
1589 ++curwin->w_jumplistidx; | |
1590 ++curwin->w_jumplistlen; | |
1591 } | |
1592 fm = &curwin->w_jumplist[idx]; | |
1593 fm->fmark.mark.lnum = 0; | |
1594 fm->fname = NULL; | |
1595 fm->time_set = 0; | |
1596 } | |
1597 } | |
1598 #endif | |
1599 } | |
1600 else | |
1601 { | |
1602 int idx; | |
1603 | |
1604 if (VIM_ISDIGIT(name)) | |
1605 { | |
1606 if (vi_namedfm != NULL) | |
1607 idx = name - '0' + NMARKS; | |
1608 else | |
1609 { | |
1610 int i; | |
1611 | |
1612 /* Do not use the name from the viminfo file, insert in time | |
1613 * order. */ | |
1614 for (idx = NMARKS; idx < NMARKS + EXTRA_MARKS; ++idx) | |
1615 if (namedfm[idx].time_set < timestamp) | |
1616 break; | |
1617 if (idx == NMARKS + EXTRA_MARKS) | |
1618 /* All existing entries are newer. */ | |
1619 return; | |
1620 i = NMARKS + EXTRA_MARKS - 1; | |
1621 | |
1622 vim_free(namedfm[i].fname); | |
1623 for ( ; i > idx; --i) | |
1624 namedfm[i] = namedfm[i - 1]; | |
1625 namedfm[idx].fname = NULL; | |
1626 } | |
1627 } | |
1628 else | |
1629 idx = name - 'A'; | |
1630 if (vi_namedfm != NULL) | |
1631 fm = &vi_namedfm[idx]; | |
1632 else | |
1633 fm = &namedfm[idx]; | |
1634 } | |
1635 | |
1636 if (fm != NULL) | |
1637 { | |
1638 if (vi_namedfm != NULL || fm->fmark.mark.lnum == 0 | |
1639 || fm->time_set < timestamp || force) | |
1640 { | |
1641 fm->fmark.mark.lnum = lnum; | |
1642 fm->fmark.mark.col = col; | |
1643 fm->fmark.mark.coladd = 0; | |
1644 fm->fmark.fnum = 0; | |
1645 vim_free(fm->fname); | |
1646 if (vp[4].bv_allocated) | |
1647 { | |
1648 fm->fname = vp[4].bv_string; | |
1649 vp[4].bv_string = NULL; | |
1650 } | |
1651 else | |
1652 fm->fname = vim_strsave(vp[4].bv_string); | |
1653 fm->time_set = timestamp; | |
1654 } | |
1655 } | |
1656 } | |
1657 | |
1658 /* | |
1659 * Return TRUE if marks for "buf" should not be written. | |
1660 */ | |
1661 static int | |
1662 skip_for_viminfo(buf_T *buf) | |
1663 { | |
1664 return | |
1665 #ifdef FEAT_TERMINAL | |
1666 bt_terminal(buf) || | |
1667 #endif | |
1668 removable(buf->b_ffname); | |
1669 } | |
1670 | |
1671 void | |
1672 write_viminfo_filemarks(FILE *fp) | |
1673 { | |
1674 int i; | |
1675 char_u *name; | |
1676 buf_T *buf; | |
1677 xfmark_T *fm; | |
1678 int vi_idx; | |
1679 int idx; | |
1680 | |
1681 if (get_viminfo_parameter('f') == 0) | |
1682 return; | |
1683 | |
1684 fputs(_("\n# File marks:\n"), fp); | |
1685 | |
1686 /* Write the filemarks 'A - 'Z */ | |
1687 for (i = 0; i < NMARKS; i++) | |
1688 { | |
1689 if (vi_namedfm != NULL && (vi_namedfm[i].time_set > namedfm[i].time_set | |
1690 || namedfm[i].fmark.mark.lnum == 0)) | |
1691 fm = &vi_namedfm[i]; | |
1692 else | |
1693 fm = &namedfm[i]; | |
1694 write_one_filemark(fp, fm, '\'', i + 'A'); | |
1695 } | |
1696 | |
1697 /* | |
1698 * Find a mark that is the same file and position as the cursor. | |
1699 * That one, or else the last one is deleted. | |
1700 * Move '0 to '1, '1 to '2, etc. until the matching one or '9 | |
1701 * Set the '0 mark to current cursor position. | |
1702 */ | |
1703 if (curbuf->b_ffname != NULL && !skip_for_viminfo(curbuf)) | |
1704 { | |
1705 name = buflist_nr2name(curbuf->b_fnum, TRUE, FALSE); | |
1706 for (i = NMARKS; i < NMARKS + EXTRA_MARKS - 1; ++i) | |
1707 if (namedfm[i].fmark.mark.lnum == curwin->w_cursor.lnum | |
1708 && (namedfm[i].fname == NULL | |
1709 ? namedfm[i].fmark.fnum == curbuf->b_fnum | |
1710 : (name != NULL | |
1711 && STRCMP(name, namedfm[i].fname) == 0))) | |
1712 break; | |
1713 vim_free(name); | |
1714 | |
1715 vim_free(namedfm[i].fname); | |
1716 for ( ; i > NMARKS; --i) | |
1717 namedfm[i] = namedfm[i - 1]; | |
1718 namedfm[NMARKS].fmark.mark = curwin->w_cursor; | |
1719 namedfm[NMARKS].fmark.fnum = curbuf->b_fnum; | |
1720 namedfm[NMARKS].fname = NULL; | |
1721 namedfm[NMARKS].time_set = vim_time(); | |
1722 } | |
1723 | |
1724 /* Write the filemarks '0 - '9. Newest (highest timestamp) first. */ | |
1725 vi_idx = NMARKS; | |
1726 idx = NMARKS; | |
1727 for (i = NMARKS; i < NMARKS + EXTRA_MARKS; i++) | |
1728 { | |
1729 xfmark_T *vi_fm = vi_namedfm != NULL ? &vi_namedfm[vi_idx] : NULL; | |
1730 | |
1731 if (vi_fm != NULL | |
1732 && vi_fm->fmark.mark.lnum != 0 | |
1733 && (vi_fm->time_set > namedfm[idx].time_set | |
1734 || namedfm[idx].fmark.mark.lnum == 0)) | |
1735 { | |
1736 fm = vi_fm; | |
1737 ++vi_idx; | |
1738 } | |
1739 else | |
1740 { | |
1741 fm = &namedfm[idx++]; | |
1742 if (vi_fm != NULL | |
1743 && vi_fm->fmark.mark.lnum == fm->fmark.mark.lnum | |
1744 && vi_fm->time_set == fm->time_set | |
1745 && ((vi_fm->fmark.fnum != 0 | |
1746 && vi_fm->fmark.fnum == fm->fmark.fnum) | |
1747 || (vi_fm->fname != NULL | |
1748 && fm->fname != NULL | |
1749 && STRCMP(vi_fm->fname, fm->fname) == 0))) | |
1750 ++vi_idx; /* skip duplicate */ | |
1751 } | |
1752 write_one_filemark(fp, fm, '\'', i - NMARKS + '0'); | |
1753 } | |
1754 | |
1755 #ifdef FEAT_JUMPLIST | |
1756 /* Write the jumplist with -' */ | |
1757 fputs(_("\n# Jumplist (newest first):\n"), fp); | |
1758 setpcmark(); /* add current cursor position */ | |
1759 cleanup_jumplist(curwin, FALSE); | |
1760 vi_idx = 0; | |
1761 idx = curwin->w_jumplistlen - 1; | |
1762 for (i = 0; i < JUMPLISTSIZE; ++i) | |
1763 { | |
1764 xfmark_T *vi_fm; | |
1765 | |
1766 fm = idx >= 0 ? &curwin->w_jumplist[idx] : NULL; | |
1767 vi_fm = vi_idx < vi_jumplist_len ? &vi_jumplist[vi_idx] : NULL; | |
1768 if (fm == NULL && vi_fm == NULL) | |
1769 break; | |
1770 if (fm == NULL || (vi_fm != NULL && fm->time_set < vi_fm->time_set)) | |
1771 { | |
1772 fm = vi_fm; | |
1773 ++vi_idx; | |
1774 } | |
1775 else | |
1776 --idx; | |
1777 if (fm->fmark.fnum == 0 | |
1778 || ((buf = buflist_findnr(fm->fmark.fnum)) != NULL | |
1779 && !skip_for_viminfo(buf))) | |
1780 write_one_filemark(fp, fm, '-', '\''); | |
1781 } | |
1782 #endif | |
1783 } | |
1784 | |
1785 static void | |
1786 write_one_filemark( | |
1787 FILE *fp, | |
1788 xfmark_T *fm, | |
1789 int c1, | |
1790 int c2) | |
1791 { | |
1792 char_u *name; | |
1793 | |
1794 if (fm->fmark.mark.lnum == 0) /* not set */ | |
1795 return; | |
1796 | |
1797 if (fm->fmark.fnum != 0) /* there is a buffer */ | |
1798 name = buflist_nr2name(fm->fmark.fnum, TRUE, FALSE); | |
1799 else | |
1800 name = fm->fname; /* use name from .viminfo */ | |
1801 if (name != NULL && *name != NUL) | |
1802 { | |
1803 fprintf(fp, "%c%c %ld %ld ", c1, c2, (long)fm->fmark.mark.lnum, | |
1804 (long)fm->fmark.mark.col); | |
1805 viminfo_writestring(fp, name); | |
1806 | |
1807 /* Barline: |{bartype},{name},{lnum},{col},{timestamp},{filename} | |
1808 * size up to filename: 8 + 3 * 20 */ | |
1809 fprintf(fp, "|%d,%d,%ld,%ld,%ld,", BARTYPE_MARK, c2, | |
1810 (long)fm->fmark.mark.lnum, (long)fm->fmark.mark.col, | |
1811 (long)fm->time_set); | |
1812 barline_writestring(fp, name, LSIZE - 70); | |
1813 putc('\n', fp); | |
1814 } | |
1815 | |
1816 if (fm->fmark.fnum != 0) | |
1817 vim_free(name); | |
1818 } | |
1819 | |
1820 /* | |
1821 * Return TRUE if "name" is on removable media (depending on 'viminfo'). | |
1822 */ | |
1823 int | |
1824 removable(char_u *name) | |
1825 { | |
1826 char_u *p; | |
1827 char_u part[51]; | |
1828 int retval = FALSE; | |
1829 size_t n; | |
1830 | |
1831 name = home_replace_save(NULL, name); | |
1832 if (name != NULL) | |
1833 { | |
1834 for (p = p_viminfo; *p; ) | |
1835 { | |
1836 copy_option_part(&p, part, 51, ", "); | |
1837 if (part[0] == 'r') | |
1838 { | |
1839 n = STRLEN(part + 1); | |
1840 if (MB_STRNICMP(part + 1, name, n) == 0) | |
1841 { | |
1842 retval = TRUE; | |
1843 break; | |
1844 } | |
1845 } | |
1846 } | |
1847 vim_free(name); | |
1848 } | |
1849 return retval; | |
1850 } | |
1851 | |
1852 static void | |
1853 write_one_mark(FILE *fp_out, int c, pos_T *pos) | |
1854 { | |
1855 if (pos->lnum != 0) | |
1856 fprintf(fp_out, "\t%c\t%ld\t%d\n", c, (long)pos->lnum, (int)pos->col); | |
1857 } | |
1858 | |
1859 | |
1860 static void | |
1861 write_buffer_marks(buf_T *buf, FILE *fp_out) | |
1862 { | |
1863 int i; | |
1864 pos_T pos; | |
1865 | |
1866 home_replace(NULL, buf->b_ffname, IObuff, IOSIZE, TRUE); | |
1867 fprintf(fp_out, "\n> "); | |
1868 viminfo_writestring(fp_out, IObuff); | |
1869 | |
1870 /* Write the last used timestamp as the lnum of the non-existing mark '*'. | |
1871 * Older Vims will ignore it and/or copy it. */ | |
1872 pos.lnum = (linenr_T)buf->b_last_used; | |
1873 pos.col = 0; | |
1874 write_one_mark(fp_out, '*', &pos); | |
1875 | |
1876 write_one_mark(fp_out, '"', &buf->b_last_cursor); | |
1877 write_one_mark(fp_out, '^', &buf->b_last_insert); | |
1878 write_one_mark(fp_out, '.', &buf->b_last_change); | |
1879 #ifdef FEAT_JUMPLIST | |
1880 /* changelist positions are stored oldest first */ | |
1881 for (i = 0; i < buf->b_changelistlen; ++i) | |
1882 { | |
1883 /* skip duplicates */ | |
1884 if (i == 0 || !EQUAL_POS(buf->b_changelist[i - 1], | |
1885 buf->b_changelist[i])) | |
1886 write_one_mark(fp_out, '+', &buf->b_changelist[i]); | |
1887 } | |
1888 #endif | |
1889 for (i = 0; i < NMARKS; i++) | |
1890 write_one_mark(fp_out, 'a' + i, &buf->b_namedm[i]); | |
1891 } | |
1892 | |
1893 /* | |
1894 * Write all the named marks for all buffers. | |
1895 * When "buflist" is not NULL fill it with the buffers for which marks are to | |
1896 * be written. | |
1897 */ | |
1898 void | |
1899 write_viminfo_marks(FILE *fp_out, garray_T *buflist) | |
1900 { | |
1901 buf_T *buf; | |
1902 int is_mark_set; | |
1903 int i; | |
1904 win_T *win; | |
1905 tabpage_T *tp; | |
1906 | |
1907 /* | |
1908 * Set b_last_cursor for the all buffers that have a window. | |
1909 */ | |
1910 FOR_ALL_TAB_WINDOWS(tp, win) | |
1911 set_last_cursor(win); | |
1912 | |
1913 fputs(_("\n# History of marks within files (newest to oldest):\n"), fp_out); | |
1914 FOR_ALL_BUFFERS(buf) | |
1915 { | |
1916 /* | |
1917 * Only write something if buffer has been loaded and at least one | |
1918 * mark is set. | |
1919 */ | |
1920 if (buf->b_marks_read) | |
1921 { | |
1922 if (buf->b_last_cursor.lnum != 0) | |
1923 is_mark_set = TRUE; | |
1924 else | |
1925 { | |
1926 is_mark_set = FALSE; | |
1927 for (i = 0; i < NMARKS; i++) | |
1928 if (buf->b_namedm[i].lnum != 0) | |
1929 { | |
1930 is_mark_set = TRUE; | |
1931 break; | |
1932 } | |
1933 } | |
1934 if (is_mark_set && buf->b_ffname != NULL | |
1935 && buf->b_ffname[0] != NUL | |
1936 && !skip_for_viminfo(buf)) | |
1937 { | |
1938 if (buflist == NULL) | |
1939 write_buffer_marks(buf, fp_out); | |
1940 else if (ga_grow(buflist, 1) == OK) | |
1941 ((buf_T **)buflist->ga_data)[buflist->ga_len++] = buf; | |
1942 } | |
1943 } | |
1944 } | |
1945 } | |
1946 | |
1947 /* | |
1948 * Compare functions for qsort() below, that compares b_last_used. | |
1949 */ | |
1950 static int | |
1951 buf_compare(const void *s1, const void *s2) | |
1952 { | |
1953 buf_T *buf1 = *(buf_T **)s1; | |
1954 buf_T *buf2 = *(buf_T **)s2; | |
1955 | |
1956 if (buf1->b_last_used == buf2->b_last_used) | |
1957 return 0; | |
1958 return buf1->b_last_used > buf2->b_last_used ? -1 : 1; | |
1959 } | |
1960 | |
1961 /* | |
1962 * Handle marks in the viminfo file: | |
1963 * fp_out != NULL: copy marks, in time order with buffers in "buflist". | |
1964 * fp_out == NULL && (flags & VIF_WANT_MARKS): read marks for curbuf only | |
1965 * fp_out == NULL && (flags & VIF_GET_OLDFILES | VIF_FORCEIT): fill v:oldfiles | |
1966 */ | |
1967 void | |
1968 copy_viminfo_marks( | |
1969 vir_T *virp, | |
1970 FILE *fp_out, | |
1971 garray_T *buflist, | |
1972 int eof, | |
1973 int flags) | |
1974 { | |
1975 char_u *line = virp->vir_line; | |
1976 buf_T *buf; | |
1977 int num_marked_files; | |
1978 int load_marks; | |
1979 int copy_marks_out; | |
1980 char_u *str; | |
1981 int i; | |
1982 char_u *p; | |
1983 char_u *name_buf; | |
1984 pos_T pos; | |
1985 #ifdef FEAT_EVAL | |
1986 list_T *list = NULL; | |
1987 #endif | |
1988 int count = 0; | |
1989 int buflist_used = 0; | |
1990 buf_T *buflist_buf = NULL; | |
1991 | |
1992 if ((name_buf = alloc(LSIZE)) == NULL) | |
1993 return; | |
1994 *name_buf = NUL; | |
1995 | |
1996 if (fp_out != NULL && buflist->ga_len > 0) | |
1997 { | |
1998 /* Sort the list of buffers on b_last_used. */ | |
1999 qsort(buflist->ga_data, (size_t)buflist->ga_len, | |
2000 sizeof(buf_T *), buf_compare); | |
2001 buflist_buf = ((buf_T **)buflist->ga_data)[0]; | |
2002 } | |
2003 | |
2004 #ifdef FEAT_EVAL | |
2005 if (fp_out == NULL && (flags & (VIF_GET_OLDFILES | VIF_FORCEIT))) | |
2006 { | |
2007 list = list_alloc(); | |
2008 if (list != NULL) | |
2009 set_vim_var_list(VV_OLDFILES, list); | |
2010 } | |
2011 #endif | |
2012 | |
2013 num_marked_files = get_viminfo_parameter('\''); | |
2014 while (!eof && (count < num_marked_files || fp_out == NULL)) | |
2015 { | |
2016 if (line[0] != '>') | |
2017 { | |
2018 if (line[0] != '\n' && line[0] != '\r' && line[0] != '#') | |
2019 { | |
2020 if (viminfo_error("E576: ", _("Missing '>'"), line)) | |
2021 break; /* too many errors, return now */ | |
2022 } | |
2023 eof = vim_fgets(line, LSIZE, virp->vir_fd); | |
2024 continue; /* Skip this dud line */ | |
2025 } | |
2026 | |
2027 /* | |
2028 * Handle long line and translate escaped characters. | |
2029 * Find file name, set str to start. | |
2030 * Ignore leading and trailing white space. | |
2031 */ | |
2032 str = skipwhite(line + 1); | |
2033 str = viminfo_readstring(virp, (int)(str - virp->vir_line), FALSE); | |
2034 if (str == NULL) | |
2035 continue; | |
2036 p = str + STRLEN(str); | |
2037 while (p != str && (*p == NUL || vim_isspace(*p))) | |
2038 p--; | |
2039 if (*p) | |
2040 p++; | |
2041 *p = NUL; | |
2042 | |
2043 #ifdef FEAT_EVAL | |
2044 if (list != NULL) | |
2045 list_append_string(list, str, -1); | |
2046 #endif | |
2047 | |
2048 /* | |
2049 * If fp_out == NULL, load marks for current buffer. | |
2050 * If fp_out != NULL, copy marks for buffers not in buflist. | |
2051 */ | |
2052 load_marks = copy_marks_out = FALSE; | |
2053 if (fp_out == NULL) | |
2054 { | |
2055 if ((flags & VIF_WANT_MARKS) && curbuf->b_ffname != NULL) | |
2056 { | |
2057 if (*name_buf == NUL) /* only need to do this once */ | |
2058 home_replace(NULL, curbuf->b_ffname, name_buf, LSIZE, TRUE); | |
2059 if (fnamecmp(str, name_buf) == 0) | |
2060 load_marks = TRUE; | |
2061 } | |
2062 } | |
2063 else /* fp_out != NULL */ | |
2064 { | |
2065 /* This is slow if there are many buffers!! */ | |
2066 FOR_ALL_BUFFERS(buf) | |
2067 if (buf->b_ffname != NULL) | |
2068 { | |
2069 home_replace(NULL, buf->b_ffname, name_buf, LSIZE, TRUE); | |
2070 if (fnamecmp(str, name_buf) == 0) | |
2071 break; | |
2072 } | |
2073 | |
2074 /* | |
2075 * Copy marks if the buffer has not been loaded. | |
2076 */ | |
2077 if (buf == NULL || !buf->b_marks_read) | |
2078 { | |
2079 int did_read_line = FALSE; | |
2080 | |
2081 if (buflist_buf != NULL) | |
2082 { | |
2083 /* Read the next line. If it has the "*" mark compare the | |
2084 * time stamps. Write entries from "buflist" that are | |
2085 * newer. */ | |
2086 if (!(eof = viminfo_readline(virp)) && line[0] == TAB) | |
2087 { | |
2088 did_read_line = TRUE; | |
2089 if (line[1] == '*') | |
2090 { | |
2091 long ltime; | |
2092 | |
2093 sscanf((char *)line + 2, "%ld ", <ime); | |
2094 while ((time_T)ltime < buflist_buf->b_last_used) | |
2095 { | |
2096 write_buffer_marks(buflist_buf, fp_out); | |
2097 if (++count >= num_marked_files) | |
2098 break; | |
2099 if (++buflist_used == buflist->ga_len) | |
2100 { | |
2101 buflist_buf = NULL; | |
2102 break; | |
2103 } | |
2104 buflist_buf = | |
2105 ((buf_T **)buflist->ga_data)[buflist_used]; | |
2106 } | |
2107 } | |
2108 else | |
2109 { | |
2110 /* No timestamp, must be written by an older Vim. | |
2111 * Assume all remaining buffers are older then | |
2112 * ours. */ | |
2113 while (count < num_marked_files | |
2114 && buflist_used < buflist->ga_len) | |
2115 { | |
2116 buflist_buf = ((buf_T **)buflist->ga_data) | |
2117 [buflist_used++]; | |
2118 write_buffer_marks(buflist_buf, fp_out); | |
2119 ++count; | |
2120 } | |
2121 buflist_buf = NULL; | |
2122 } | |
2123 | |
2124 if (count >= num_marked_files) | |
2125 { | |
2126 vim_free(str); | |
2127 break; | |
2128 } | |
2129 } | |
2130 } | |
2131 | |
2132 fputs("\n> ", fp_out); | |
2133 viminfo_writestring(fp_out, str); | |
2134 if (did_read_line) | |
2135 fputs((char *)line, fp_out); | |
2136 | |
2137 count++; | |
2138 copy_marks_out = TRUE; | |
2139 } | |
2140 } | |
2141 vim_free(str); | |
2142 | |
2143 pos.coladd = 0; | |
2144 while (!(eof = viminfo_readline(virp)) && line[0] == TAB) | |
2145 { | |
2146 if (load_marks) | |
2147 { | |
2148 if (line[1] != NUL) | |
2149 { | |
2150 unsigned u; | |
2151 | |
2152 sscanf((char *)line + 2, "%ld %u", &pos.lnum, &u); | |
2153 pos.col = u; | |
2154 switch (line[1]) | |
2155 { | |
2156 case '"': curbuf->b_last_cursor = pos; break; | |
2157 case '^': curbuf->b_last_insert = pos; break; | |
2158 case '.': curbuf->b_last_change = pos; break; | |
2159 case '+': | |
2160 #ifdef FEAT_JUMPLIST | |
2161 /* changelist positions are stored oldest | |
2162 * first */ | |
2163 if (curbuf->b_changelistlen == JUMPLISTSIZE) | |
2164 /* list is full, remove oldest entry */ | |
2165 mch_memmove(curbuf->b_changelist, | |
2166 curbuf->b_changelist + 1, | |
2167 sizeof(pos_T) * (JUMPLISTSIZE - 1)); | |
2168 else | |
2169 ++curbuf->b_changelistlen; | |
2170 curbuf->b_changelist[ | |
2171 curbuf->b_changelistlen - 1] = pos; | |
2172 #endif | |
2173 break; | |
2174 | |
2175 /* Using the line number for the last-used | |
2176 * timestamp. */ | |
2177 case '*': curbuf->b_last_used = pos.lnum; break; | |
2178 | |
2179 default: if ((i = line[1] - 'a') >= 0 && i < NMARKS) | |
2180 curbuf->b_namedm[i] = pos; | |
2181 } | |
2182 } | |
2183 } | |
2184 else if (copy_marks_out) | |
2185 fputs((char *)line, fp_out); | |
2186 } | |
2187 | |
2188 if (load_marks) | |
2189 { | |
2190 #ifdef FEAT_JUMPLIST | |
2191 win_T *wp; | |
2192 | |
2193 FOR_ALL_WINDOWS(wp) | |
2194 { | |
2195 if (wp->w_buffer == curbuf) | |
2196 wp->w_changelistidx = curbuf->b_changelistlen; | |
2197 } | |
2198 #endif | |
2199 break; | |
2200 } | |
2201 } | |
2202 | |
2203 if (fp_out != NULL) | |
2204 /* Write any remaining entries from buflist. */ | |
2205 while (count < num_marked_files && buflist_used < buflist->ga_len) | |
2206 { | |
2207 buflist_buf = ((buf_T **)buflist->ga_data)[buflist_used++]; | |
2208 write_buffer_marks(buflist_buf, fp_out); | |
2209 ++count; | |
2210 } | |
2211 | |
2212 vim_free(name_buf); | |
2213 } | |
2214 #endif /* FEAT_VIMINFO */ |