diff options
-rwxr-xr-x | pluma/dialogs/pluma-search-dialog.c | 20 | ||||
-rwxr-xr-x | pluma/dialogs/pluma-search-dialog.h | 4 | ||||
-rw-r--r-- | pluma/dialogs/pluma-search-dialog.ui | 27 | ||||
-rw-r--r-- | pluma/pluma-commands-search.c | 41 | ||||
-rw-r--r-- | pluma/pluma-document.c | 109 | ||||
-rw-r--r-- | pluma/pluma-document.h | 8 | ||||
-rw-r--r-- | pluma/pluma-utils.c | 127 | ||||
-rw-r--r-- | pluma/pluma-utils.h | 10 |
8 files changed, 296 insertions, 50 deletions
diff --git a/pluma/dialogs/pluma-search-dialog.c b/pluma/dialogs/pluma-search-dialog.c index 329e1721..a77701c0 100755 --- a/pluma/dialogs/pluma-search-dialog.c +++ b/pluma/dialogs/pluma-search-dialog.c @@ -68,6 +68,7 @@ struct _PlumaSearchDialogPrivate GtkWidget *replace_entry; GtkWidget *replace_text_entry; GtkWidget *match_case_checkbutton; + GtkWidget *match_regex_checkbutton; GtkWidget *entire_word_checkbutton; GtkWidget *backwards_checkbutton; GtkWidget *wrap_around_checkbutton; @@ -352,6 +353,7 @@ pluma_search_dialog_init (PlumaSearchDialog *dlg) "search_label", &dlg->priv->search_label, "replace_with_label", &dlg->priv->replace_label, "match_case_checkbutton", &dlg->priv->match_case_checkbutton, + "match_regex_checkbutton",&dlg->priv->match_regex_checkbutton, "entire_word_checkbutton", &dlg->priv->entire_word_checkbutton, "search_backwards_checkbutton", &dlg->priv->backwards_checkbutton, "wrap_around_checkbutton", &dlg->priv->wrap_around_checkbutton, @@ -583,6 +585,24 @@ pluma_search_dialog_get_match_case (PlumaSearchDialog *dialog) } void +pluma_search_dialog_set_match_regex (PlumaSearchDialog *dialog, + gboolean match_case) +{ + g_return_if_fail (PLUMA_IS_SEARCH_DIALOG (dialog)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->match_regex_checkbutton), + match_case); +} + +gboolean +pluma_search_dialog_get_match_regex (PlumaSearchDialog *dialog) +{ + g_return_val_if_fail (PLUMA_IS_SEARCH_DIALOG (dialog), FALSE); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->match_regex_checkbutton)); +} + +void pluma_search_dialog_set_entire_word (PlumaSearchDialog *dialog, gboolean entire_word) { diff --git a/pluma/dialogs/pluma-search-dialog.h b/pluma/dialogs/pluma-search-dialog.h index fb92efba..e6ebe8dc 100755 --- a/pluma/dialogs/pluma-search-dialog.h +++ b/pluma/dialogs/pluma-search-dialog.h @@ -111,6 +111,10 @@ void pluma_search_dialog_set_match_case (PlumaSearchDialog *dialog, gboolean match_case); gboolean pluma_search_dialog_get_match_case (PlumaSearchDialog *dialog); +void pluma_search_dialog_set_match_regex (PlumaSearchDialog *dialog, + gboolean match_case); +gboolean pluma_search_dialog_get_match_regex (PlumaSearchDialog *dialog); + void pluma_search_dialog_set_entire_word (PlumaSearchDialog *dialog, gboolean entire_word); gboolean pluma_search_dialog_get_entire_word (PlumaSearchDialog *dialog); diff --git a/pluma/dialogs/pluma-search-dialog.ui b/pluma/dialogs/pluma-search-dialog.ui index a1a37b5d..b7b70aca 100644 --- a/pluma/dialogs/pluma-search-dialog.ui +++ b/pluma/dialogs/pluma-search-dialog.ui @@ -181,6 +181,22 @@ Author: Wolfgang Ulbrich </packing> </child> <child> + <object class="GtkCheckButton" id="match_regex_checkbutton"> + <property name="label" translatable="yes">Match _regular expression</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="halign">start</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> <object class="GtkCheckButton" id="entire_word_checkbutton"> <property name="label" translatable="yes">Match _entire word only</property> <property name="visible">True</property> @@ -193,7 +209,7 @@ Author: Wolfgang Ulbrich <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> <child> @@ -209,7 +225,7 @@ Author: Wolfgang Ulbrich <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">2</property> + <property name="position">3</property> </packing> </child> <child> @@ -226,7 +242,7 @@ Author: Wolfgang Ulbrich <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">3</property> + <property name="position">4</property> </packing> </child> <child> @@ -243,7 +259,7 @@ Author: Wolfgang Ulbrich <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">4</property> + <property name="position">5</property> </packing> </child> </object> @@ -268,5 +284,8 @@ Author: Wolfgang Ulbrich <action-widget response="0">replace_button</action-widget> <action-widget response="0">find_next_button</action-widget> </action-widgets> + <child> + <placeholder/> + </child> </object> </interface> diff --git a/pluma/pluma-commands-search.c b/pluma/pluma-commands-search.c index 1a75dbca..f4db2479 100644 --- a/pluma/pluma-commands-search.c +++ b/pluma/pluma-commands-search.c @@ -227,6 +227,7 @@ do_find (PlumaSearchDialog *dialog, gchar *search_text; const gchar *entry_text; gboolean match_case; + gboolean match_regex; gboolean entire_word; gboolean wrap_around; gboolean search_backwards; @@ -244,6 +245,7 @@ do_find (PlumaSearchDialog *dialog, doc = PLUMA_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view))); match_case = pluma_search_dialog_get_match_case (dialog); + match_regex = pluma_search_dialog_get_match_regex(dialog); entire_word = pluma_search_dialog_get_entire_word (dialog); search_backwards = pluma_search_dialog_get_backwards (dialog); wrap_around = pluma_search_dialog_get_wrap_around (dialog); @@ -257,6 +259,7 @@ do_find (PlumaSearchDialog *dialog, PLUMA_SEARCH_SET_CASE_SENSITIVE (flags, match_case); PLUMA_SEARCH_SET_ENTIRE_WORD (flags, entire_word); + PLUMA_SEARCH_SET_MATCH_REGEX (flags, match_regex); search_text = pluma_document_get_search_text (doc, &old_flags); @@ -342,7 +345,9 @@ do_replace (PlumaSearchDialog *dialog, gchar *unescaped_replace_text; gchar *selected_text = NULL; gboolean match_case; + gboolean match_regex; gboolean parse_escapes; + gboolean need_refind; doc = pluma_window_get_active_document (window); if (doc == NULL) @@ -372,17 +377,36 @@ do_replace (PlumaSearchDialog *dialog, NULL); match_case = pluma_search_dialog_get_match_case (dialog); + match_regex = pluma_search_dialog_get_match_regex(dialog); + + if (selected_text != NULL) + { + if(!match_regex) + { + need_refind = (match_case && (strcmp (selected_text,unescaped_search_text) != 0)) + || (!match_case && !g_utf8_caselessnmatch (selected_text, + unescaped_search_text, + strlen (selected_text), + strlen (unescaped_search_text)) != 0); + } + else + { + need_refind = !g_regex_match_simple(unescaped_search_text, + selected_text, + match_case ? 0 : GTK_TEXT_SEARCH_CASE_INSENSITIVE , + 0); + } + } + else + { + need_refind = TRUE; + } - if ((selected_text == NULL) || - (match_case && (strcmp (selected_text, unescaped_search_text) != 0)) || - (!match_case && !g_utf8_caselessnmatch (selected_text, - unescaped_search_text, - strlen (selected_text), - strlen (unescaped_search_text)) != 0)) + if (need_refind) { do_find (dialog, window); g_free (unescaped_search_text); - g_free (selected_text); + g_free (selected_text); return; } @@ -406,6 +430,7 @@ do_replace_all (PlumaSearchDialog *dialog, const gchar *search_entry_text; const gchar *replace_entry_text; gboolean match_case; + gboolean match_regex; gboolean entire_word; gboolean parse_escapes; guint flags = 0; @@ -435,9 +460,11 @@ do_replace_all (PlumaSearchDialog *dialog, g_return_if_fail ((replace_entry_text) != NULL); match_case = pluma_search_dialog_get_match_case (dialog); + match_regex = pluma_search_dialog_get_match_regex(dialog); entire_word = pluma_search_dialog_get_entire_word (dialog); PLUMA_SEARCH_SET_CASE_SENSITIVE (flags, match_case); + PLUMA_SEARCH_SET_MATCH_REGEX (flags, match_regex); PLUMA_SEARCH_SET_ENTIRE_WORD (flags, entire_word); count = pluma_document_replace_all (doc, diff --git a/pluma/pluma-document.c b/pluma/pluma-document.c index ed8ca1fa..8634636f 100644 --- a/pluma/pluma-document.c +++ b/pluma/pluma-document.c @@ -1922,13 +1922,24 @@ pluma_document_search_forward (PlumaDocument *doc, while (!found) { + 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); - + 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); + } + if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) { found = gtk_text_iter_starts_word (&m_start) && @@ -1960,23 +1971,23 @@ 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; gboolean found = FALSE; GtkTextIter m_start; GtkTextIter m_end; - + g_return_val_if_fail (PLUMA_IS_DOCUMENT (doc), FALSE); - g_return_val_if_fail ((start == NULL) || - (gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)), FALSE); - g_return_val_if_fail ((end == NULL) || + g_return_val_if_fail ((start == NULL) || +( gtk_text_iter_get_buffer (start) == GTK_TEXT_BUFFER (doc)), FALSE); + g_return_val_if_fail ((end == NULL) || (gtk_text_iter_get_buffer (end) == GTK_TEXT_BUFFER (doc)), FALSE); - + if (doc->priv->search_text == NULL) { pluma_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == NULL\n"); @@ -1984,7 +1995,7 @@ pluma_document_search_backward (PlumaDocument *doc, } else pluma_debug_message (DEBUG_DOCUMENT, "doc->priv->search_text == \"%s\"\n", doc->priv->search_text); - + if (end == NULL) gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter); else @@ -1999,32 +2010,45 @@ pluma_document_search_backward (PlumaDocument *doc, while (!found) { - found = gtk_text_iter_backward_search (&iter, - doc->priv->search_text, - search_flags, - &m_start, - &m_end, - start); - + if(!PLUMA_SEARCH_IS_MATCH_REGEX(doc->priv->search_flags)) + { + found = gtk_text_iter_backward_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + start); + } + else + { + found = pluma_gtk_text_iter_regex_search (&iter, + doc->priv->search_text, + search_flags, + &m_start, + &m_end, + end, + FALSE); + } + if (found && PLUMA_SEARCH_IS_ENTIRE_WORD (doc->priv->search_flags)) { - found = gtk_text_iter_starts_word (&m_start) && - gtk_text_iter_ends_word (&m_end); + found = gtk_text_iter_starts_word (&m_start) && + gtk_text_iter_ends_word (&m_end); - if (!found) + if (!found) iter = m_start; } else break; } - + if (found && (match_start != NULL)) *match_start = m_start; - + if (found && (match_end != NULL)) *match_end = m_end; - - return found; + + return found; } /* FIXME this is an issue for introspection regardning @find */ @@ -2089,12 +2113,23 @@ pluma_document_replace_all (PlumaDocument *doc, do { - found = gtk_text_iter_forward_search (&iter, - search_text, - search_flags, - &m_start, - &m_end, - NULL); + 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 (found && PLUMA_SEARCH_IS_ENTIRE_WORD (flags)) { @@ -2123,7 +2158,7 @@ pluma_document_replace_all (PlumaDocument *doc, replace_text_len); iter = m_start; - } + } } while (found); diff --git a/pluma/pluma-document.h b/pluma/pluma-document.h index 6d90323e..a8d64895 100644 --- a/pluma/pluma-document.h +++ b/pluma/pluma-document.h @@ -69,7 +69,8 @@ typedef enum PLUMA_SEARCH_DONT_SET_FLAGS = 1 << 0, PLUMA_SEARCH_ENTIRE_WORD = 1 << 1, PLUMA_SEARCH_CASE_SENSITIVE = 1 << 2, - PLUMA_SEARCH_PARSE_ESCAPES = 1 << 3 + PLUMA_SEARCH_PARSE_ESCAPES = 1 << 3, + PLUMA_SEARCH_MATCH_REGEX = 1 << 4, } PlumaSearchFlags; @@ -317,6 +318,11 @@ void _pluma_document_search_region (PlumaDocument *doc, #define PLUMA_SEARCH_SET_PARSE_ESCAPES(sflags,state) ((state == TRUE) ? \ (sflags |= PLUMA_SEARCH_PARSE_ESCAPES) : (sflags &= ~PLUMA_SEARCH_PARSE_ESCAPES)) +#define PLUMA_SEARCH_IS_MATCH_REGEX(sflags) ((sflags & PLUMA_SEARCH_MATCH_REGEX) != 0) +#define PLUMA_SEARCH_SET_MATCH_REGEX(sflags,state) ((state == TRUE) ? \ +(sflags |= PLUMA_SEARCH_MATCH_REGEX) : (sflags &= ~PLUMA_SEARCH_MATCH_REGEX)) + + typedef GMountOperation *(*PlumaMountOperationFactory)(PlumaDocument *doc, gpointer userdata); diff --git a/pluma/pluma-utils.c b/pluma/pluma-utils.c index a739401a..b8f081c0 100644 --- a/pluma/pluma-utils.c +++ b/pluma/pluma-utils.c @@ -1578,3 +1578,130 @@ pluma_utils_decode_uri (const gchar *uri, return TRUE; } + +gboolean +pluma_gtk_text_iter_regex_search (const GtkTextIter *iter, + const gchar *str, + GtkTextSearchFlags flags, + GtkTextIter *match_start, + GtkTextIter *match_end, + const GtkTextIter *limit, + gboolean forward_search) +{ + GRegex *regex; + GRegexCompileFlags compile_flags; + GMatchInfo *match_info; + gchar *text; + GtkTextIter *begin_iter; + GtkTextIter *end_iter; + gchar **all_matches; + gchar *match_string; + gboolean found; + gint non_null_result_number; + gboolean non_null_result_found; + guint result_size; + + compile_flags = 0; + if ((flags & GTK_TEXT_SEARCH_CASE_INSENSITIVE) != 0) + compile_flags |= G_REGEX_CASELESS; + + regex = g_regex_new (str,compile_flags,0,NULL); + if (regex == NULL) + return FALSE; + + begin_iter = gtk_text_iter_copy (iter); + if (limit == NULL) + { + end_iter = gtk_text_iter_copy (begin_iter); + if (forward_search) + { + gtk_text_buffer_get_end_iter (gtk_text_iter_get_buffer(begin_iter), + end_iter); + } + else + { + gtk_text_buffer_get_start_iter (gtk_text_iter_get_buffer (begin_iter), + end_iter); + } + } + else + { + end_iter = gtk_text_iter_copy (limit); + } + + if ((flags & GTK_TEXT_SEARCH_TEXT_ONLY) != 0) + { + if ((flags & GTK_TEXT_SEARCH_VISIBLE_ONLY) != 0) + text = gtk_text_iter_get_visible_text (begin_iter, end_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_all (regex,text,0,&match_info); + if (found) + { + 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); + } + } + +free_resources: + gtk_text_iter_free (begin_iter); + gtk_text_iter_free (end_iter); + g_match_info_free (match_info); + g_regex_unref (regex); + return found; +} diff --git a/pluma/pluma-utils.h b/pluma/pluma-utils.h index a73926d2..e9dd0a5b 100644 --- a/pluma/pluma-utils.h +++ b/pluma/pluma-utils.h @@ -149,8 +149,16 @@ gboolean pluma_utils_decode_uri (const gchar *uri, /* Turns data from a drop into a list of well formatted uris */ gchar **pluma_utils_drop_get_uris (GtkSelectionData *selection_data); +/* Provides regexp forward search */ +gboolean +pluma_gtk_text_iter_regex_search (const GtkTextIter *iter, + const gchar *str, + GtkTextSearchFlags flags, + GtkTextIter *match_start, + GtkTextIter *match_end, + const GtkTextIter *limit, gboolean forward_search); + G_END_DECLS #endif /* __PLUMA_UTILS_H__ */ - |