summaryrefslogtreecommitdiff
path: root/gtksourceview
diff options
context:
space:
mode:
authorSébastien Wilmet <swilmet@gnome.org>2015-08-20 14:34:32 +0200
committerSébastien Wilmet <swilmet@gnome.org>2015-08-20 18:34:02 +0200
commitc1039c448a7a501561b28c7708e50e400faf7c5e (patch)
treed6e8b1fe98d76284f5d59317d4312d7965e49793 /gtksourceview
parent3c52a3ea8bb41feea92f4ca68793d7411c982d23 (diff)
downloadgtksourceview-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.c112
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;
}