Mercurial > vim
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 } |