Mercurial > vim
comparison src/search.c @ 15239:db5d2429bda3 v8.1.0629
patch 8.1.0629: "gn" selects the wrong text with a multi-line match
commit https://github.com/vim/vim/commit/5d24a2257e597fd752e33b2c1e9c19cf9114a517
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Dec 23 19:10:09 2018 +0100
patch 8.1.0629: "gn" selects the wrong text with a multi-line match
Problem: "gn" selects the wrong text with a multi-line match.
Solution: Get the end position from searchit() directly. (closes https://github.com/vim/vim/issues/3695)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 23 Dec 2018 19:15:05 +0100 |
parents | e8fdc71f3ea0 |
children | 55ccc2d353bd |
comparison
equal
deleted
inserted
replaced
15238:85705008bb7a | 15239:db5d2429bda3 |
---|---|
608 } | 608 } |
609 #endif | 609 #endif |
610 | 610 |
611 /* | 611 /* |
612 * Lowest level search function. | 612 * Lowest level search function. |
613 * Search for 'count'th occurrence of pattern 'pat' in direction 'dir'. | 613 * Search for 'count'th occurrence of pattern "pat" in direction "dir". |
614 * Start at position 'pos' and return the found position in 'pos'. | 614 * Start at position "pos" and return the found position in "pos". |
615 * | 615 * |
616 * if (options & SEARCH_MSG) == 0 don't give any messages | 616 * if (options & SEARCH_MSG) == 0 don't give any messages |
617 * if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages | 617 * if (options & SEARCH_MSG) == SEARCH_NFMSG don't give 'notfound' messages |
618 * if (options & SEARCH_MSG) == SEARCH_MSG give all messages | 618 * if (options & SEARCH_MSG) == SEARCH_MSG give all messages |
619 * if (options & SEARCH_HIS) put search pattern in history | 619 * if (options & SEARCH_HIS) put search pattern in history |
632 searchit( | 632 searchit( |
633 win_T *win, /* window to search in; can be NULL for a | 633 win_T *win, /* window to search in; can be NULL for a |
634 buffer without a window! */ | 634 buffer without a window! */ |
635 buf_T *buf, | 635 buf_T *buf, |
636 pos_T *pos, | 636 pos_T *pos, |
637 pos_T *end_pos, // set to end of the match, unless NULL | |
637 int dir, | 638 int dir, |
638 char_u *pat, | 639 char_u *pat, |
639 long count, | 640 long count, |
640 int options, | 641 int options, |
641 int pat_use, /* which pattern to use when "pat" is empty */ | 642 int pat_use, /* which pattern to use when "pat" is empty */ |
1033 ptr = ml_get_buf(buf, pos->lnum, FALSE); | 1034 ptr = ml_get_buf(buf, pos->lnum, FALSE); |
1034 pos->col -= (*mb_head_off)(ptr, ptr + pos->col); | 1035 pos->col -= (*mb_head_off)(ptr, ptr + pos->col); |
1035 } | 1036 } |
1036 #endif | 1037 #endif |
1037 } | 1038 } |
1039 if (end_pos != NULL) | |
1040 { | |
1041 end_pos->lnum = lnum + matchpos.lnum; | |
1042 end_pos->col = matchpos.col; | |
1043 } | |
1038 } | 1044 } |
1039 else | 1045 else |
1040 { | 1046 { |
1041 pos->lnum = lnum + matchpos.lnum; | 1047 pos->lnum = lnum + matchpos.lnum; |
1042 pos->col = matchpos.col; | 1048 pos->col = matchpos.col; |
1049 if (end_pos != NULL) | |
1050 { | |
1051 end_pos->lnum = lnum + endpos.lnum; | |
1052 end_pos->col = endpos.col; | |
1053 } | |
1043 } | 1054 } |
1044 #ifdef FEAT_VIRTUALEDIT | 1055 #ifdef FEAT_VIRTUALEDIT |
1045 pos->coladd = 0; | 1056 pos->coladd = 0; |
1057 if (end_pos != NULL) | |
1058 end_pos->coladd = 0; | |
1046 #endif | 1059 #endif |
1047 found = 1; | 1060 found = 1; |
1048 first_match = FALSE; | 1061 first_match = FALSE; |
1049 | 1062 |
1050 /* Set variables used for 'incsearch' highlighting. */ | 1063 /* Set variables used for 'incsearch' highlighting. */ |
1494 #ifdef FEAT_FKMAP /* when in Farsi mode, reverse the character flow */ | 1507 #ifdef FEAT_FKMAP /* when in Farsi mode, reverse the character flow */ |
1495 if (p_altkeymap && curwin->w_p_rl) | 1508 if (p_altkeymap && curwin->w_p_rl) |
1496 lrFswap(searchstr,0); | 1509 lrFswap(searchstr,0); |
1497 #endif | 1510 #endif |
1498 | 1511 |
1499 c = searchit(curwin, curbuf, &pos, dirc == '/' ? FORWARD : BACKWARD, | 1512 c = searchit(curwin, curbuf, &pos, NULL, dirc == '/' ? FORWARD : BACKWARD, |
1500 searchstr, count, spats[0].off.end + (options & | 1513 searchstr, count, spats[0].off.end + (options & |
1501 (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS | 1514 (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS |
1502 + SEARCH_MSG + SEARCH_START | 1515 + SEARCH_MSG + SEARCH_START |
1503 + ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))), | 1516 + ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))), |
1504 RE_LAST, (linenr_T)0, tm, timed_out); | 1517 RE_LAST, (linenr_T)0, tm, timed_out); |
4663 * Used while an operator is pending, and in Visual mode. | 4676 * Used while an operator is pending, and in Visual mode. |
4664 */ | 4677 */ |
4665 int | 4678 int |
4666 current_search( | 4679 current_search( |
4667 long count, | 4680 long count, |
4668 int forward) /* move forward or backwards */ | 4681 int forward) // TRUE for forward, FALSE for backward |
4669 { | 4682 { |
4670 pos_T start_pos; /* position before the pattern */ | 4683 pos_T start_pos; // start position of the pattern match |
4671 pos_T orig_pos; /* position of the cursor at beginning */ | 4684 pos_T end_pos; // end position of the pattern match |
4672 pos_T first_match; /* position of first match */ | 4685 pos_T orig_pos; // position of the cursor at beginning |
4673 pos_T pos; /* position after the pattern */ | 4686 pos_T pos; // position after the pattern |
4674 int i; | 4687 int i; |
4675 int dir; | 4688 int dir; |
4676 int result; /* result of various function calls */ | 4689 int result; // result of various function calls |
4677 char_u old_p_ws = p_ws; | 4690 char_u old_p_ws = p_ws; |
4678 int flags = 0; | 4691 int flags = 0; |
4679 pos_T save_VIsual = VIsual; | 4692 pos_T save_VIsual = VIsual; |
4680 int one_char; | 4693 int one_char; |
4681 int direction = forward ? FORWARD : BACKWARD; | |
4682 | 4694 |
4683 /* wrapping should not occur */ | 4695 /* wrapping should not occur */ |
4684 p_ws = FALSE; | 4696 p_ws = FALSE; |
4685 | 4697 |
4686 /* Correct cursor when 'selection' is exclusive */ | 4698 /* Correct cursor when 'selection' is exclusive */ |
4728 dir = !i; | 4740 dir = !i; |
4729 | 4741 |
4730 flags = 0; | 4742 flags = 0; |
4731 if (!dir && !one_char) | 4743 if (!dir && !one_char) |
4732 flags = SEARCH_END; | 4744 flags = SEARCH_END; |
4733 | 4745 end_pos = pos; |
4734 result = searchit(curwin, curbuf, &pos, (dir ? FORWARD : BACKWARD), | 4746 |
4747 result = searchit(curwin, curbuf, &pos, &end_pos, | |
4748 (dir ? FORWARD : BACKWARD), | |
4735 spats[last_idx].pat, (long) (i ? count : 1), | 4749 spats[last_idx].pat, (long) (i ? count : 1), |
4736 SEARCH_KEEP | flags, RE_SEARCH, 0, NULL, NULL); | 4750 SEARCH_KEEP | flags, RE_SEARCH, 0, NULL, NULL); |
4737 | 4751 |
4738 /* First search may fail, but then start searching from the | 4752 /* First search may fail, but then start searching from the |
4739 * beginning of the file (cursor might be on the search match) | 4753 * beginning of the file (cursor might be on the search match) |
4740 * except when Visual mode is active, so that extending the visual | 4754 * except when Visual mode is active, so that extending the visual |
4741 * selection works. */ | 4755 * selection works. */ |
4742 if (!result && i) /* not found, abort */ | 4756 if (i == 1 && !result) /* not found, abort */ |
4743 { | 4757 { |
4744 curwin->w_cursor = orig_pos; | 4758 curwin->w_cursor = orig_pos; |
4745 if (VIsual_active) | 4759 if (VIsual_active) |
4746 VIsual = save_VIsual; | 4760 VIsual = save_VIsual; |
4747 p_ws = old_p_ws; | 4761 p_ws = old_p_ws; |
4748 return FAIL; | 4762 return FAIL; |
4749 } | 4763 } |
4750 else if (!i && !result) | 4764 else if (i == 0 && !result) |
4751 { | 4765 { |
4752 if (forward) | 4766 if (forward) |
4753 { | 4767 { |
4754 /* try again from start of buffer */ | 4768 /* try again from start of buffer */ |
4755 CLEAR_POS(&pos); | 4769 CLEAR_POS(&pos); |
4761 pos.lnum = curwin->w_buffer->b_ml.ml_line_count; | 4775 pos.lnum = curwin->w_buffer->b_ml.ml_line_count; |
4762 pos.col = (colnr_T)STRLEN( | 4776 pos.col = (colnr_T)STRLEN( |
4763 ml_get(curwin->w_buffer->b_ml.ml_line_count)); | 4777 ml_get(curwin->w_buffer->b_ml.ml_line_count)); |
4764 } | 4778 } |
4765 } | 4779 } |
4766 if (i == 0) | |
4767 first_match = pos; | |
4768 p_ws = old_p_ws; | 4780 p_ws = old_p_ws; |
4769 } | 4781 } |
4770 | 4782 |
4771 start_pos = pos; | 4783 start_pos = pos; |
4772 flags = forward ? SEARCH_END : SEARCH_START; | |
4773 | |
4774 /* Check again from the current cursor position, | |
4775 * since the next match might actually by only one char wide */ | |
4776 one_char = is_one_char(spats[last_idx].pat, FALSE, &pos, direction); | |
4777 if (one_char < 0) | |
4778 /* search failed, abort */ | |
4779 return FAIL; | |
4780 | |
4781 /* move to match, except for zero-width matches, in which case, we are | |
4782 * already on the next match */ | |
4783 if (!one_char) | |
4784 { | |
4785 p_ws = FALSE; | |
4786 for (i = 0; i < 2; i++) | |
4787 { | |
4788 result = searchit(curwin, curbuf, &pos, direction, | |
4789 spats[last_idx].pat, 0L, flags | SEARCH_KEEP, RE_SEARCH, 0, | |
4790 NULL, NULL); | |
4791 /* Search successfull, break out from the loop */ | |
4792 if (result) | |
4793 break; | |
4794 /* search failed, try again from the last search position match */ | |
4795 pos = first_match; | |
4796 } | |
4797 } | |
4798 | |
4799 p_ws = old_p_ws; | 4784 p_ws = old_p_ws; |
4800 /* not found */ | |
4801 if (!result) | |
4802 return FAIL; | |
4803 | 4785 |
4804 if (!VIsual_active) | 4786 if (!VIsual_active) |
4805 VIsual = start_pos; | 4787 VIsual = start_pos; |
4806 | 4788 |
4807 curwin->w_cursor = pos; | 4789 // put cursor on last character of match |
4790 curwin->w_cursor = end_pos; | |
4791 if (LT_POS(VIsual, end_pos)) | |
4792 dec_cursor(); | |
4808 VIsual_active = TRUE; | 4793 VIsual_active = TRUE; |
4809 VIsual_mode = 'v'; | 4794 VIsual_mode = 'v'; |
4810 | 4795 |
4811 if (VIsual_active) | 4796 if (VIsual_active) |
4812 { | 4797 { |
4878 pos = *cur; | 4863 pos = *cur; |
4879 /* accept a match at the cursor position */ | 4864 /* accept a match at the cursor position */ |
4880 flag = SEARCH_START; | 4865 flag = SEARCH_START; |
4881 } | 4866 } |
4882 | 4867 |
4883 if (searchit(curwin, curbuf, &pos, direction, pattern, 1, | 4868 if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1, |
4884 SEARCH_KEEP + flag, RE_SEARCH, 0, NULL, NULL) != FAIL) | 4869 SEARCH_KEEP + flag, RE_SEARCH, 0, NULL, NULL) != FAIL) |
4885 { | 4870 { |
4886 /* Zero-width pattern should match somewhere, then we can check if | 4871 /* Zero-width pattern should match somewhere, then we can check if |
4887 * start and end are in the same position. */ | 4872 * start and end are in the same position. */ |
4888 called_emsg = FALSE; | 4873 called_emsg = FALSE; |