diff options
author | Sébastien Wilmet <swilmet@gnome.org> | 2015-08-20 14:34:32 +0200 |
---|---|---|
committer | Sébastien Wilmet <swilmet@gnome.org> | 2015-08-20 18:34:02 +0200 |
commit | c1039c448a7a501561b28c7708e50e400faf7c5e (patch) | |
tree | d6e8b1fe98d76284f5d59317d4312d7965e49793 /gtksourceview | |
parent | 3c52a3ea8bb41feea92f4ca68793d7411c982d23 (diff) | |
download | gtksourceview-c1039c448a7a501561b28c7708e50e400faf7c5e.tar.gz |
SearchContext: fix bug look-ahead regex
- Write unit tests.
- Adapt basic_forward_regex_search() to support partial matches.
The gedit code calls gtk_source_search_context_get_occurrence_position()
to know if the selected text matches. get_occerrence_position()
traverses the occurrences by first going to tag toggles, and then inside
the tagged text, find the exact matches with basic_forward_search().
Finding the exact matches is needed because when contiguous matches are
found, when applying the tag the previous match boundary is lost.
https://bugzilla.gnome.org/show_bug.cgi?id=752719
Diffstat (limited to 'gtksourceview')
-rw-r--r-- | gtksourceview/gtksourcesearchcontext.c | 112 |
1 files changed, 79 insertions, 33 deletions
diff --git a/gtksourceview/gtksourcesearchcontext.c b/gtksourceview/gtksourcesearchcontext.c index 8f9a92d6..3b97e6aa 100644 --- a/gtksourceview/gtksourcesearchcontext.c +++ b/gtksourceview/gtksourcesearchcontext.c @@ -715,13 +715,8 @@ basic_forward_regex_search (GtkSourceSearchContext *search, GtkTextIter real_start; GtkTextIter end; gint start_pos; - gchar *subject; - gssize subject_length; - GRegexMatchFlags match_options; - GMatchInfo *match_info; - GtkTextIter iter; - gint iter_byte_pos; - gboolean found; + gboolean found = FALSE; + gint nb_lines = 1; if (search->priv->regex == NULL || search->priv->regex_error != NULL) @@ -740,38 +735,89 @@ basic_forward_regex_search (GtkSourceSearchContext *search, end = *limit; } - match_options = regex_search_get_match_options (&real_start, &end); + while (TRUE) + { + GRegexMatchFlags match_options; + gchar *subject; + gssize subject_length; + GMatchInfo *match_info; + GtkTextIter iter; + gint iter_byte_pos; + GtkTextIter m_start; + GtkTextIter m_end; - subject = gtk_text_iter_get_visible_text (&real_start, &end); - subject_length = strlen (subject); + match_options = regex_search_get_match_options (&real_start, &end); - g_regex_match_full (search->priv->regex, - subject, - subject_length, - start_pos, - match_options, - &match_info, - &search->priv->regex_error); + if (!gtk_text_iter_is_end (&end)) + { + match_options |= G_REGEX_MATCH_PARTIAL_HARD; + } - iter = real_start; - iter_byte_pos = 0; + subject = gtk_text_iter_get_visible_text (&real_start, &end); + subject_length = strlen (subject); + + g_regex_match_full (search->priv->regex, + subject, + subject_length, + start_pos, + match_options, + &match_info, + &search->priv->regex_error); + + iter = real_start; + iter_byte_pos = 0; + + found = regex_search_fetch_match (match_info, + subject, + subject_length, + &iter, + &iter_byte_pos, + &m_start, + &m_end); + + if (!found && g_match_info_is_partial_match (match_info)) + { + gtk_text_iter_forward_lines (&end, nb_lines); + nb_lines <<= 1; - found = regex_search_fetch_match (match_info, - subject, - subject_length, - &iter, - &iter_byte_pos, - match_start, - match_end); + g_free (subject); + g_match_info_free (match_info); + continue; + } - if (search->priv->regex_error != NULL) - { - g_object_notify (G_OBJECT (search), "regex-error"); - found = FALSE; - } + /* Check that the match is not beyond the limit. This can happen + * if a partial match is found on the first iteration. Then the + * partial match was actually not a good match, but a second + * good match is found. + */ + if (found && limit != NULL && gtk_text_iter_compare (limit, &m_end) < 0) + { + found = FALSE; + } - g_free (subject); - g_match_info_free (match_info); + if (search->priv->regex_error != NULL) + { + g_object_notify (G_OBJECT (search), "regex-error"); + found = FALSE; + } + + if (found) + { + if (match_start != NULL) + { + *match_start = m_start; + } + + if (match_end != NULL) + { + *match_end = m_end; + } + } + + g_free (subject); + g_match_info_free (match_info); + break; + } return found; } |