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;