diff --git a/pluma/dialogs/pluma-search-dialog.c b/pluma/dialogs/pluma-search-dialog.c
index ac7181d..993c92a 100755
--- a/pluma/dialogs/pluma-search-dialog.c
+++ b/pluma/dialogs/pluma-search-dialog.c
@@ -74,6 +74,7 @@ struct _PlumaSearchDialogPrivate
GtkWidget *entire_word_checkbutton;
GtkWidget *backwards_checkbutton;
GtkWidget *wrap_around_checkbutton;
+ GtkWidget *parse_escapes_checkbutton;
GtkWidget *find_button;
GtkWidget *replace_button;
GtkWidget *replace_all_button;
@@ -363,6 +364,7 @@ pluma_search_dialog_init (PlumaSearchDialog *dlg)
"entire_word_checkbutton", &dlg->priv->entire_word_checkbutton,
"search_backwards_checkbutton", &dlg->priv->backwards_checkbutton,
"wrap_around_checkbutton", &dlg->priv->wrap_around_checkbutton,
+ "parse_escapes_checkbutton", &dlg->priv->parse_escapes_checkbutton,
NULL);
g_free (file);
@@ -638,3 +640,21 @@ pluma_search_dialog_get_wrap_around (PlumaSearchDialog *dialog)
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->wrap_around_checkbutton));
}
+
+void
+pluma_search_dialog_set_parse_escapes (PlumaSearchDialog *dialog,
+ gboolean parse_escapes)
+{
+ g_return_if_fail (PLUMA_IS_SEARCH_DIALOG (dialog));
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->parse_escapes_checkbutton),
+ parse_escapes);
+}
+
+gboolean
+pluma_search_dialog_get_parse_escapes (PlumaSearchDialog *dialog)
+{
+ g_return_val_if_fail (PLUMA_IS_SEARCH_DIALOG (dialog), FALSE);
+
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->parse_escapes_checkbutton));
+}
diff --git a/pluma/dialogs/pluma-search-dialog.h b/pluma/dialogs/pluma-search-dialog.h
index 967f6a9..fb92efb 100755
--- a/pluma/dialogs/pluma-search-dialog.h
+++ b/pluma/dialogs/pluma-search-dialog.h
@@ -123,6 +123,11 @@ void pluma_search_dialog_set_wrap_around (PlumaSearchDialog *dialog,
gboolean wrap_around);
gboolean pluma_search_dialog_get_wrap_around (PlumaSearchDialog *dialog);
+
+void pluma_search_dialog_set_parse_escapes (PlumaSearchDialog *dialog,
+ gboolean parse_escapes);
+gboolean pluma_search_dialog_get_parse_escapes (PlumaSearchDialog *dialog);
+
G_END_DECLS
#endif /* __PLUMA_SEARCH_DIALOG_H__ */
diff --git a/pluma/dialogs/pluma-search-dialog.ui b/pluma/dialogs/pluma-search-dialog.ui
index 35b6c39..4f137b1 100755
--- a/pluma/dialogs/pluma-search-dialog.ui
+++ b/pluma/dialogs/pluma-search-dialog.ui
@@ -229,6 +229,24 @@
False
+
+
+
+ 0
+ False
+ False
+
+
0
diff --git a/pluma/pluma-commands-search.c b/pluma/pluma-commands-search.c
index 7e15357..01780f4 100644
--- a/pluma/pluma-commands-search.c
+++ b/pluma/pluma-commands-search.c
@@ -234,6 +234,7 @@ do_find (PlumaSearchDialog *dialog,
gboolean entire_word;
gboolean wrap_around;
gboolean search_backwards;
+ gboolean parse_escapes;
guint flags = 0;
guint old_flags = 0;
gboolean found;
@@ -246,12 +247,17 @@ do_find (PlumaSearchDialog *dialog,
doc = PLUMA_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
- entry_text = pluma_search_dialog_get_search_text (dialog);
-
match_case = pluma_search_dialog_get_match_case (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);
+ parse_escapes = pluma_search_dialog_get_parse_escapes (dialog);
+
+ if (!parse_escapes) {
+ entry_text = pluma_utils_escape_search_text (pluma_search_dialog_get_search_text (dialog));
+ } else {
+ entry_text = pluma_search_dialog_get_search_text (dialog);
+ }
PLUMA_SEARCH_SET_CASE_SENSITIVE (flags, match_case);
PLUMA_SEARCH_SET_ENTIRE_WORD (flags, entire_word);
@@ -273,8 +279,13 @@ do_find (PlumaSearchDialog *dialog,
if (found)
text_found (window, 0);
- else
- text_not_found (window, entry_text);
+ else {
+ if (!parse_escapes) {
+ text_not_found (window, pluma_utils_unescape_search_text (entry_text));
+ } else {
+ text_not_found (window, entry_text);
+ }
+ }
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
PLUMA_SEARCH_DIALOG_REPLACE_RESPONSE,
@@ -335,17 +346,27 @@ do_replace (PlumaSearchDialog *dialog,
gchar *unescaped_replace_text;
gchar *selected_text = NULL;
gboolean match_case;
+ gboolean parse_escapes;
doc = pluma_window_get_active_document (window);
if (doc == NULL)
return;
- search_entry_text = pluma_search_dialog_get_search_text (dialog);
+ parse_escapes = pluma_search_dialog_get_parse_escapes (dialog);
+ if (!parse_escapes) {
+ search_entry_text = pluma_utils_escape_search_text (pluma_search_dialog_get_search_text (dialog));
+ } else {
+ search_entry_text = pluma_search_dialog_get_search_text (dialog);
+ }
g_return_if_fail ((search_entry_text) != NULL);
g_return_if_fail ((*search_entry_text) != '\0');
/* replace text may be "", we just delete */
- replace_entry_text = pluma_search_dialog_get_replace_text (dialog);
+ if (!parse_escapes) {
+ replace_entry_text = pluma_utils_escape_search_text (pluma_search_dialog_get_replace_text (dialog));
+ } else {
+ replace_entry_text = pluma_search_dialog_get_replace_text (dialog);
+ }
g_return_if_fail ((replace_entry_text) != NULL);
unescaped_search_text = pluma_utils_unescape_search_text (search_entry_text);
@@ -390,6 +411,7 @@ do_replace_all (PlumaSearchDialog *dialog,
const gchar *replace_entry_text;
gboolean match_case;
gboolean entire_word;
+ gboolean parse_escapes;
guint flags = 0;
gint count;
@@ -399,12 +421,21 @@ do_replace_all (PlumaSearchDialog *dialog,
doc = PLUMA_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
- search_entry_text = pluma_search_dialog_get_search_text (dialog);
+ parse_escapes = pluma_search_dialog_get_parse_escapes (dialog);
+ if (!parse_escapes) {
+ search_entry_text = pluma_utils_escape_search_text(pluma_search_dialog_get_search_text (dialog));
+ } else {
+ search_entry_text = pluma_search_dialog_get_search_text (dialog);
+ }
g_return_if_fail ((search_entry_text) != NULL);
g_return_if_fail ((*search_entry_text) != '\0');
/* replace text may be "", we just delete all occurrencies */
- replace_entry_text = pluma_search_dialog_get_replace_text (dialog);
+ if (!parse_escapes) {
+ replace_entry_text = pluma_utils_escape_search_text (pluma_search_dialog_get_replace_text (dialog));
+ } else {
+ replace_entry_text = pluma_search_dialog_get_replace_text (dialog);
+ }
g_return_if_fail ((replace_entry_text) != NULL);
match_case = pluma_search_dialog_get_match_case (dialog);
@@ -424,7 +455,11 @@ do_replace_all (PlumaSearchDialog *dialog,
}
else
{
- text_not_found (window, search_entry_text);
+ if (!parse_escapes) {
+ text_not_found (window, pluma_utils_unescape_search_text (search_entry_text));
+ } else {
+ text_not_found (window, search_entry_text);
+ }
}
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
@@ -516,7 +551,9 @@ _pluma_cmd_search_find (GtkAction *action,
GtkWidget *search_dialog;
PlumaDocument *doc;
gboolean selection_exists;
+ gboolean parse_escapes;
gchar *find_text = NULL;
+ const gchar *search_text = NULL;
gint sel_len;
pluma_debug (DEBUG_COMMANDS);
@@ -548,8 +585,25 @@ _pluma_cmd_search_find (GtkAction *action,
if (selection_exists && find_text != NULL && sel_len < 80)
{
- pluma_search_dialog_set_search_text (PLUMA_SEARCH_DIALOG (search_dialog),
- find_text);
+ /*
+ * Special case: if the currently selected text
+ * is the same as the unescaped search text and
+ * escape sequence parsing is activated, use the
+ * same old search text. (Without this, if you e.g.
+ * search for '\n' in escaped mode and then open
+ * the search dialog again, you'll get an unprintable
+ * single-character literal '\n' in the "search for"
+ * box).
+ */
+ parse_escapes = pluma_search_dialog_get_parse_escapes (PLUMA_SEARCH_DIALOG (search_dialog));
+ search_text = pluma_search_dialog_get_search_text (PLUMA_SEARCH_DIALOG (search_dialog));
+ if (!(search_text != NULL
+ && !strcmp(pluma_utils_unescape_search_text(search_text), find_text)
+ && parse_escapes)) {
+ /* General case */
+ pluma_search_dialog_set_search_text (PLUMA_SEARCH_DIALOG (search_dialog),
+ find_text);
+ }
g_free (find_text);
}
else
@@ -571,7 +625,9 @@ _pluma_cmd_search_replace (GtkAction *action,
GtkWidget *replace_dialog;
PlumaDocument *doc;
gboolean selection_exists;
+ gboolean parse_escapes;
gchar *find_text = NULL;
+ const gchar *search_text = NULL;
gint sel_len;
pluma_debug (DEBUG_COMMANDS);
@@ -603,8 +659,25 @@ _pluma_cmd_search_replace (GtkAction *action,
if (selection_exists && find_text != NULL && sel_len < 80)
{
- pluma_search_dialog_set_search_text (PLUMA_SEARCH_DIALOG (replace_dialog),
- find_text);
+ /*
+ * Special case: if the currently selected text
+ * is the same as the unescaped search text and
+ * escape sequence parsing is activated, use the
+ * same old search text. (Without this, if you e.g.
+ * search for '\n' in escaped mode and then open
+ * the search dialog again, you'll get an unprintable
+ * single-character literal '\n' in the "search for"
+ * box).
+ */
+ parse_escapes = pluma_search_dialog_get_parse_escapes (PLUMA_SEARCH_DIALOG (replace_dialog));
+ search_text = pluma_search_dialog_get_search_text (PLUMA_SEARCH_DIALOG (replace_dialog));
+ if (!(search_text != NULL
+ && !strcmp(pluma_utils_unescape_search_text(search_text), find_text)
+ && parse_escapes)) {
+ /* General case */
+ pluma_search_dialog_set_search_text (PLUMA_SEARCH_DIALOG (replace_dialog),
+ find_text);
+ }
g_free (find_text);
}
else
diff --git a/pluma/pluma-document.h b/pluma/pluma-document.h
index a8cf502..099aaae 100644
--- a/pluma/pluma-document.h
+++ b/pluma/pluma-document.h
@@ -78,7 +78,8 @@ typedef enum
{
PLUMA_SEARCH_DONT_SET_FLAGS = 1 << 0,
PLUMA_SEARCH_ENTIRE_WORD = 1 << 1,
- PLUMA_SEARCH_CASE_SENSITIVE = 1 << 2
+ PLUMA_SEARCH_CASE_SENSITIVE = 1 << 2,
+ PLUMA_SEARCH_PARSE_ESCAPES = 1 << 3
} PlumaSearchFlags;
@@ -322,6 +323,10 @@ void _pluma_document_search_region (PlumaDocument *doc,
#define PLUMA_SEARCH_SET_CASE_SENSITIVE(sflags,state) ((state == TRUE) ? \
(sflags |= PLUMA_SEARCH_CASE_SENSITIVE) : (sflags &= ~PLUMA_SEARCH_CASE_SENSITIVE))
+#define PLUMA_SEARCH_IS_PARSE_ESCAPES(sflags) ((sflags & PLUMA_SEARCH_PARSE_ESCAPES) != 0)
+#define PLUMA_SEARCH_SET_PARSE_ESCAPES(sflags,state) ((state == TRUE) ? \
+(sflags |= PLUMA_SEARCH_PARSE_ESCAPES) : (sflags &= ~PLUMA_SEARCH_PARSE_ESCAPES))
+
typedef GMountOperation *(*PlumaMountOperationFactory)(PlumaDocument *doc,
gpointer userdata);
diff --git a/pluma/pluma-view.c b/pluma/pluma-view.c
index 5132e96..39f15fc 100644
--- a/pluma/pluma-view.c
+++ b/pluma/pluma-view.c
@@ -1213,6 +1213,14 @@ match_case_menu_item_toggled (GtkCheckMenuItem *checkmenuitem,
gtk_check_menu_item_get_active (checkmenuitem));
}
+static void
+parse_escapes_menu_item_toggled (GtkCheckMenuItem *checkmenuitem,
+ PlumaView *view)
+{
+ PLUMA_SEARCH_SET_PARSE_ESCAPES (view->priv->search_flags,
+ gtk_check_menu_item_get_active (checkmenuitem));
+}
+
static gboolean
real_search_enable_popdown (gpointer data)
{
@@ -1291,6 +1299,16 @@ search_entry_populate_popup (GtkEntry *entry,
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
PLUMA_SEARCH_IS_CASE_SENSITIVE (view->priv->search_flags));
gtk_widget_show (menu_item);
+
+ /* create "Parse escapes" menu item. */
+ menu_item = gtk_check_menu_item_new_with_mnemonic (_("_Parse escape sequences (e.g. \n)"));
+ g_signal_connect (G_OBJECT (menu_item), "toggled",
+ G_CALLBACK (parse_escapes_menu_item_toggled),
+ view);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
+ PLUMA_SEARCH_IS_PARSE_ESCAPES (view->priv->search_flags));
+ gtk_widget_show (menu_item);
}
static void