From a1545443a5d2abedb97fb75632f96331c2659cb2 Mon Sep 17 00:00:00 2001 From: Vadim Barkov Date: Wed, 6 Dec 2017 16:13:21 +0300 Subject: Fixes for regexp replacement with backreferences (e.g. "\0") (#259) fixes https://github.com/mate-desktop/pluma/issues/254 --- pluma/pluma-commands-search.c | 33 +++++++---- pluma/pluma-document.c | 124 ++++++++++++++++++++++++++++-------------- pluma/pluma-document.h | 11 +++- pluma/pluma-utils.c | 105 +++++++++++++++++------------------ pluma/pluma-utils.h | 4 +- 5 files changed, 165 insertions(+), 112 deletions(-) diff --git a/pluma/pluma-commands-search.c b/pluma/pluma-commands-search.c index bd30c184..d3c47803 100644 --- a/pluma/pluma-commands-search.c +++ b/pluma/pluma-commands-search.c @@ -176,10 +176,10 @@ run_search (PlumaView *view, NULL); found = pluma_document_search_backward (doc, - NULL, - &start_iter, - &match_start, - &match_end); + NULL, + &start_iter, + &match_start, + &match_end); } if (!found && wrap_around) @@ -192,12 +192,12 @@ run_search (PlumaView *view, &match_end); else found = pluma_document_search_backward (doc, - NULL, /* FIXME: set the start_inter */ - NULL, - &match_start, - &match_end); + NULL, /* FIXME: set the start_inter */ + NULL, + &match_start, + &match_end); } - + if (found) { gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), @@ -271,7 +271,11 @@ do_find (PlumaSearchDialog *dialog, } g_free (search_text); - + if (match_regex) + { + pluma_document_set_last_replace_text (doc, pluma_search_dialog_get_replace_text (dialog)); + } + found = run_search (active_view, wrap_around, search_backwards); @@ -404,6 +408,7 @@ do_replace (PlumaSearchDialog *dialog, if (need_refind) { + pluma_document_set_last_replace_text (doc, replace_entry_text); do_find (dialog, window); g_free (unescaped_search_text); g_free (selected_text); @@ -411,13 +416,17 @@ do_replace (PlumaSearchDialog *dialog, return; } - unescaped_replace_text = pluma_utils_unescape_search_text (replace_entry_text); + if(!match_regex) + unescaped_replace_text = pluma_utils_unescape_search_text (replace_entry_text); + else + unescaped_replace_text = g_strdup (pluma_document_get_last_replace_text (doc)); + replace_selected_text (GTK_TEXT_BUFFER (doc), unescaped_replace_text); g_free (unescaped_search_text); g_free (selected_text); g_free (unescaped_replace_text); - + do_find (dialog, window); } diff --git a/pluma/pluma-document.c b/pluma/pluma-document.c index 8634636f..ecc7f424 100644 --- a/pluma/pluma-document.c +++ b/pluma/pluma-document.c @@ -116,6 +116,7 @@ struct _PlumaDocumentPrivate guint search_flags; gchar *search_text; + gchar *last_replace_text; gint num_of_lines_search_text; PlumaDocumentNewlineType newline_type; @@ -301,6 +302,7 @@ pluma_document_finalize (GObject *object) g_free (doc->priv->uri); g_free (doc->priv->content_type); g_free (doc->priv->search_text); + g_free (doc->priv->last_replace_text); if (doc->priv->to_search_region != NULL) { @@ -1864,6 +1866,35 @@ pluma_document_get_search_text (PlumaDocument *doc, return pluma_utils_escape_search_text (doc->priv->search_text); } +/** + * pluma_document_set_last_replace_text: + * @doc: + * @text: (allow-none): + **/ +void +pluma_document_set_last_replace_text (PlumaDocument *doc, + const gchar *text) +{ + g_return_if_fail (PLUMA_IS_DOCUMENT (doc)); + + g_free(doc->priv->last_replace_text); + + pluma_debug_message (DEBUG_SEARCH, "last_replace_text = %s", text == NULL ? "NULL" : text); + doc->priv->last_replace_text = g_strdup(text); +} + +/** + * pluma_document_get_last_replace_text: + * @doc: + */ +gchar * +pluma_document_get_last_replace_text (PlumaDocument *doc) +{ + g_return_val_if_fail (PLUMA_IS_DOCUMENT (doc), NULL); + + return doc->priv->last_replace_text; +} + gboolean pluma_document_get_can_search_again (PlumaDocument *doc) { @@ -1922,22 +1953,23 @@ pluma_document_search_forward (PlumaDocument *doc, while (!found) { - if(!PLUMA_SEARCH_IS_MATCH_REGEX(doc->priv->search_flags)) + if(!PLUMA_SEARCH_IS_MATCH_REGEX(doc->priv->search_flags)) { - found = gtk_text_iter_forward_search (&iter, - doc->priv->search_text, - search_flags, - &m_start, - &m_end, - end); - }else{ - found = pluma_gtk_text_iter_regex_search (&iter, - doc->priv->search_text, - search_flags, - &m_start, - &m_end, - end, - TRUE); + found = gtk_text_iter_forward_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + end); + } else { + found = pluma_gtk_text_iter_regex_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + end, + TRUE, + &doc->priv->last_replace_text); } if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) @@ -1971,10 +2003,10 @@ pluma_document_search_forward (PlumaDocument *doc, **/ gboolean pluma_document_search_backward (PlumaDocument *doc, - const GtkTextIter *start, - const GtkTextIter *end, - GtkTextIter *match_start, - GtkTextIter *match_end) + const GtkTextIter *start, + const GtkTextIter *end, + GtkTextIter *match_start, + GtkTextIter *match_end) { GtkTextIter iter; GtkTextSearchFlags search_flags; @@ -2027,7 +2059,8 @@ pluma_document_search_backward (PlumaDocument *doc, &m_start, &m_end, end, - FALSE); + FALSE, + &doc->priv->last_replace_text); } if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) @@ -2065,7 +2098,7 @@ pluma_document_replace_all (PlumaDocument *doc, gboolean found = TRUE; gint cont = 0; gchar *search_text; - gchar *replace_text; + gchar *replace_text = NULL; gint replace_text_len; GtkTextBuffer *buffer; gboolean brackets_highlighting; @@ -2082,7 +2115,11 @@ pluma_document_replace_all (PlumaDocument *doc, else search_text = pluma_utils_unescape_search_text (find); - replace_text = pluma_utils_unescape_search_text (replace); + if(!PLUMA_SEARCH_IS_MATCH_REGEX(flags)) + { + replace_text = pluma_utils_unescape_search_text (replace); + replace_text_len = strlen (replace_text); + } gtk_text_buffer_get_start_iter (buffer, &iter); @@ -2093,7 +2130,6 @@ pluma_document_replace_all (PlumaDocument *doc, search_flags = search_flags | GTK_TEXT_SEARCH_CASE_INSENSITIVE; } - replace_text_len = strlen (replace_text); /* disable cursor_moved emission until the end of the * replace_all so that we don't spend all the time @@ -2113,23 +2149,28 @@ pluma_document_replace_all (PlumaDocument *doc, do { - if(!PLUMA_SEARCH_IS_MATCH_REGEX(flags)) - { - found = gtk_text_iter_forward_search (&iter, - search_text, - search_flags, - &m_start, - &m_end, - NULL); - }else{ - found = pluma_gtk_text_iter_regex_search (&iter, - search_text, - search_flags, - &m_start, - &m_end, - NULL, - TRUE); - } + if(!PLUMA_SEARCH_IS_MATCH_REGEX(flags)) + { + found = gtk_text_iter_forward_search (&iter, + search_text, + search_flags, + &m_start, + &m_end, + NULL); + } else { + if(replace_text != NULL) + g_free (replace_text); + replace_text = g_strdup (replace); + found = pluma_gtk_text_iter_regex_search (&iter, + search_text, + search_flags, + &m_start, + &m_end, + NULL, + TRUE, + &replace_text); + replace_text_len = strlen (replace_text); + } if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (flags)) { @@ -2175,7 +2216,8 @@ pluma_document_replace_all (PlumaDocument *doc, pluma_document_set_enable_search_highlighting (doc, search_highliting); g_free (search_text); - g_free (replace_text); + if(replace_text != NULL) + g_free (replace_text); return cont; } diff --git a/pluma/pluma-document.h b/pluma/pluma-document.h index a8d64895..1b6f187f 100644 --- a/pluma/pluma-document.h +++ b/pluma/pluma-document.h @@ -232,10 +232,17 @@ gboolean pluma_document_goto_line_offset(PlumaDocument *doc, void pluma_document_set_search_text (PlumaDocument *doc, const gchar *text, guint flags); - + gchar *pluma_document_get_search_text (PlumaDocument *doc, guint *flags); +gchar *pluma_document_get_last_replace_text + (PlumaDocument *doc); + +void pluma_document_set_last_replace_text + (PlumaDocument *doc, + const gchar *text); + gboolean pluma_document_get_can_search_again (PlumaDocument *doc); @@ -244,7 +251,7 @@ gboolean pluma_document_search_forward (PlumaDocument *doc, const GtkTextIter *end, GtkTextIter *match_start, GtkTextIter *match_end); - + gboolean pluma_document_search_backward (PlumaDocument *doc, const GtkTextIter *start, const GtkTextIter *end, diff --git a/pluma/pluma-utils.c b/pluma/pluma-utils.c index b8f081c0..771bcfce 100644 --- a/pluma/pluma-utils.c +++ b/pluma/pluma-utils.c @@ -1586,7 +1586,8 @@ pluma_gtk_text_iter_regex_search (const GtkTextIter *iter, GtkTextIter *match_start, GtkTextIter *match_end, const GtkTextIter *limit, - gboolean forward_search) + gboolean forward_search, + gchar **replace_text) { GRegex *regex; GRegexCompileFlags compile_flags; @@ -1636,66 +1637,58 @@ pluma_gtk_text_iter_regex_search (const GtkTextIter *iter, else text = gtk_text_iter_get_text (begin_iter, end_iter); } + else if ((flags & GTK_TEXT_SEARCH_VISIBLE_ONLY) != 0) + text = gtk_text_iter_get_visible_slice (begin_iter, end_iter); else + text = gtk_text_iter_get_slice (begin_iter, end_iter); + + found = g_regex_match (regex, text, 0, &match_info); + if (!found) + goto free_resources; + + if((replace_text != NULL) && (*replace_text != NULL)) { - if ((flags & GTK_TEXT_SEARCH_VISIBLE_ONLY) != 0) - text = gtk_text_iter_get_visible_slice (begin_iter, end_iter); - else - text = gtk_text_iter_get_slice (begin_iter, end_iter); + *replace_text = g_match_info_expand_references (match_info, + *replace_text, + NULL); } + all_matches = g_match_info_fetch_all (match_info); - found = g_regex_match_all (regex,text,0,&match_info); - if (found) + result_size = (gint) g_strv_length (all_matches); + non_null_result_number = (forward_search) ? 0 : (result_size -1); + + non_null_result_found = FALSE; + while((non_null_result_number >= 0) + && (non_null_result_number < result_size) ) { - all_matches = g_match_info_fetch_all (match_info); - result_size = (gint) g_strv_length (all_matches); - - if(forward_search){ - non_null_result_number = 0; - } else { - non_null_result_number = result_size - 1 ; - } - non_null_result_found = FALSE; - while((non_null_result_number >= 0) - && (non_null_result_number < result_size) ) { - - if(g_utf8_strlen (all_matches [non_null_result_number], G_MAXSSIZE) != 0) { - non_null_result_found = TRUE; - break; - } else { - if(forward_search) { - non_null_result_number++; - } else { - non_null_result_number--; - } - } - - } - - if(!non_null_result_found) { - found = FALSE; - goto free_resources; - } - - match_string = all_matches [non_null_result_number]; - if (forward_search) - { - gtk_text_iter_forward_search (begin_iter, - match_string, - flags, - match_start, - match_end, - limit); - } - else - { - gtk_text_iter_backward_search (begin_iter, - match_string, - flags, - match_start, - match_end, - limit); - } + non_null_result_found = g_utf8_strlen (all_matches [non_null_result_number], G_MAXSSIZE) != 0; + if (non_null_result_found) + break; + + non_null_result_number += (forward_search) ? 1 : -1; + } + + if(!non_null_result_found) { + found = FALSE; + goto free_resources; + } + + match_string = all_matches [non_null_result_number]; + if (forward_search) + { + gtk_text_iter_forward_search (begin_iter, + match_string, + flags, + match_start, + match_end, + limit); + } else { + gtk_text_iter_backward_search (begin_iter, + match_string, + flags, + match_start, + match_end, + limit); } free_resources: diff --git a/pluma/pluma-utils.h b/pluma/pluma-utils.h index e9dd0a5b..e3b1f387 100644 --- a/pluma/pluma-utils.h +++ b/pluma/pluma-utils.h @@ -156,7 +156,9 @@ pluma_gtk_text_iter_regex_search (const GtkTextIter *iter, GtkTextSearchFlags flags, GtkTextIter *match_start, GtkTextIter *match_end, - const GtkTextIter *limit, gboolean forward_search); + const GtkTextIter *limit, + gboolean forward_search, + gchar **replace_text); G_END_DECLS -- cgit v1.2.1