summaryrefslogtreecommitdiffstats
path: root/gedit/gedit-replace-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'gedit/gedit-replace-dialog.c')
-rw-r--r--gedit/gedit-replace-dialog.c819
1 files changed, 819 insertions, 0 deletions
diff --git a/gedit/gedit-replace-dialog.c b/gedit/gedit-replace-dialog.c
new file mode 100644
index 0000000..3197ae1
--- /dev/null
+++ b/gedit/gedit-replace-dialog.c
@@ -0,0 +1,819 @@
+/*
+ * gedit-replace-dialog.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 Paolo Maggi
+ * Copyright (C) 2013 Sébastien Wilmet
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gedit-replace-dialog.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gedit-history-entry.h"
+#include "gedit-document.h"
+
+#define GEDIT_SEARCH_CONTEXT_KEY "gedit-search-context-key"
+
+struct _GeditReplaceDialog
+{
+ GtkDialog parent_instance;
+
+ GtkWidget *grid;
+ GtkWidget *search_label;
+ GtkWidget *search_entry;
+ GtkWidget *search_text_entry;
+ GtkWidget *replace_label;
+ GtkWidget *replace_entry;
+ GtkWidget *replace_text_entry;
+ GtkWidget *match_case_checkbutton;
+ GtkWidget *entire_word_checkbutton;
+ GtkWidget *regex_checkbutton;
+ GtkWidget *backwards_checkbutton;
+ GtkWidget *wrap_around_checkbutton;
+ GtkWidget *close_button;
+
+ GeditDocument *active_document;
+
+ guint idle_update_sensitivity_id;
+};
+
+G_DEFINE_TYPE (GeditReplaceDialog, gedit_replace_dialog, GTK_TYPE_DIALOG)
+
+static GtkSourceSearchContext *
+get_search_context (GeditReplaceDialog *dialog,
+ GeditDocument *doc)
+{
+ GtkSourceSearchContext *search_context;
+
+ if (doc == NULL)
+ {
+ return NULL;
+ }
+
+ search_context = gedit_document_get_search_context (doc);
+
+ if (search_context != NULL &&
+ g_object_get_data (G_OBJECT (search_context), GEDIT_SEARCH_CONTEXT_KEY) == dialog)
+ {
+ return search_context;
+ }
+
+ return NULL;
+}
+
+/* The search settings between the dialog's widgets (checkbuttons and the text
+ * entry) and the SearchSettings object are not bound. Instead, this function is
+ * called to set the search settings from the widgets to the SearchSettings
+ * object.
+ *
+ * The reason: the search and replace dialog is not an incremental search. You
+ * have to press the buttons to have an effect. The SearchContext is created
+ * only when a button is pressed, not before. If the SearchContext was created
+ * directly when the dialog window is shown, or when the document tab is
+ * switched, there would be a problem. When we switch betweeen tabs to find on
+ * which tab(s) we want to do the search, we may have older searches (still
+ * highlighted) that we don't want to lose, and we don't want the new search to
+ * appear on each tab that we open. Only when we press a button. So when the
+ * SearchContext is not already created, this is not an incremental search. Once
+ * the SearchContext is created, it's better to be consistent, and therefore we
+ * don't want the incremental search: we have to always press a button to
+ * execute the search.
+ *
+ * Likewise, each created SearchContext (from the GeditReplaceDialog) contains a
+ * different SearchSettings. When set_search_settings() is called for one
+ * document tab (and thus one SearchSettings), it doesn't have an effect on the
+ * other tabs. But the dialog widgets don't change.
+ */
+static void
+set_search_settings (GeditReplaceDialog *dialog)
+{
+ GtkSourceSearchContext *search_context;
+ GtkSourceSearchSettings *search_settings;
+ gboolean case_sensitive;
+ gboolean at_word_boundaries;
+ gboolean regex_enabled;
+ gboolean wrap_around;
+ const gchar *search_text;
+
+ search_context = get_search_context (dialog, dialog->active_document);
+
+ if (search_context == NULL)
+ {
+ return;
+ }
+
+ search_settings = gtk_source_search_context_get_settings (search_context);
+
+ case_sensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->match_case_checkbutton));
+ gtk_source_search_settings_set_case_sensitive (search_settings, case_sensitive);
+
+ at_word_boundaries = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->entire_word_checkbutton));
+ gtk_source_search_settings_set_at_word_boundaries (search_settings, at_word_boundaries);
+
+ regex_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->regex_checkbutton));
+ gtk_source_search_settings_set_regex_enabled (search_settings, regex_enabled);
+
+ wrap_around = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->wrap_around_checkbutton));
+ gtk_source_search_settings_set_wrap_around (search_settings, wrap_around);
+
+ search_text = gtk_entry_get_text (GTK_ENTRY (dialog->search_text_entry));
+
+ if (regex_enabled)
+ {
+ gtk_source_search_settings_set_search_text (search_settings, search_text);
+ }
+ else
+ {
+ gchar *unescaped_search_text = gtk_source_utils_unescape_search_text (search_text);
+ gtk_source_search_settings_set_search_text (search_settings, unescaped_search_text);
+ g_free (unescaped_search_text);
+ }
+}
+
+static GeditWindow *
+get_gedit_window (GeditReplaceDialog *dialog)
+{
+ GtkWindow *transient_for = gtk_window_get_transient_for (GTK_WINDOW (dialog));
+
+ return transient_for != NULL ? GEDIT_WINDOW (transient_for) : NULL;
+}
+
+static GeditDocument *
+get_active_document (GeditReplaceDialog *dialog)
+{
+ GeditWindow *window = get_gedit_window (dialog);
+
+ return window != NULL ? gedit_window_get_active_document (window) : NULL;
+}
+
+void
+gedit_replace_dialog_present_with_time (GeditReplaceDialog *dialog,
+ guint32 timestamp)
+{
+ g_return_if_fail (GEDIT_REPLACE_DIALOG (dialog));
+
+ gtk_window_present_with_time (GTK_WINDOW (dialog), timestamp);
+
+ gtk_widget_grab_focus (dialog->search_text_entry);
+}
+
+static gboolean
+gedit_replace_dialog_delete_event (GtkWidget *widget,
+ GdkEventAny *event)
+{
+ /* prevent destruction */
+ return TRUE;
+}
+
+static void
+set_error (GtkEntry *entry,
+ const gchar *error_msg)
+{
+ if (error_msg == NULL || error_msg[0] == '\0')
+ {
+ gtk_entry_set_icon_from_gicon (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
+ gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, NULL);
+ }
+ else
+ {
+ GIcon *icon = g_themed_icon_new_with_default_fallbacks ("dialog-error-symbolic");
+
+ gtk_entry_set_icon_from_gicon (entry, GTK_ENTRY_ICON_SECONDARY, icon);
+ gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, error_msg);
+
+ g_object_unref (icon);
+ }
+}
+
+static void
+set_search_error (GeditReplaceDialog *dialog,
+ const gchar *error_msg)
+{
+ set_error (GTK_ENTRY (dialog->search_text_entry), error_msg);
+}
+
+void
+gedit_replace_dialog_set_replace_error (GeditReplaceDialog *dialog,
+ const gchar *error_msg)
+{
+ set_error (GTK_ENTRY (dialog->replace_text_entry), error_msg);
+}
+
+static gboolean
+has_search_error (GeditReplaceDialog *dialog)
+{
+ GIcon *icon;
+
+ icon = gtk_entry_get_icon_gicon (GTK_ENTRY (dialog->search_text_entry),
+ GTK_ENTRY_ICON_SECONDARY);
+
+ return icon != NULL;
+}
+
+static gboolean
+has_replace_error (GeditReplaceDialog *dialog)
+{
+ GIcon *icon;
+
+ icon = gtk_entry_get_icon_gicon (GTK_ENTRY (dialog->replace_text_entry),
+ GTK_ENTRY_ICON_SECONDARY);
+
+ return icon != NULL;
+}
+
+static void
+update_regex_error (GeditReplaceDialog *dialog)
+{
+ GtkSourceSearchContext *search_context;
+ GError *regex_error;
+
+ set_search_error (dialog, NULL);
+
+ search_context = get_search_context (dialog, dialog->active_document);
+
+ if (search_context == NULL)
+ {
+ return;
+ }
+
+ regex_error = gtk_source_search_context_get_regex_error (search_context);
+
+ if (regex_error != NULL)
+ {
+ set_search_error (dialog, regex_error->message);
+ g_error_free (regex_error);
+ }
+}
+
+static gboolean
+update_replace_response_sensitivity_cb (GeditReplaceDialog *dialog)
+{
+ GtkSourceSearchContext *search_context;
+ GtkTextIter start;
+ GtkTextIter end;
+ gint pos;
+
+ if (has_replace_error (dialog))
+ {
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ GEDIT_REPLACE_DIALOG_REPLACE_RESPONSE,
+ FALSE);
+
+ dialog->idle_update_sensitivity_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+
+ search_context = get_search_context (dialog, dialog->active_document);
+
+ if (search_context == NULL)
+ {
+ dialog->idle_update_sensitivity_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+
+ gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (dialog->active_document),
+ &start,
+ &end);
+
+ pos = gtk_source_search_context_get_occurrence_position (search_context,
+ &start,
+ &end);
+
+ if (pos < 0)
+ {
+ return G_SOURCE_CONTINUE;
+ }
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ GEDIT_REPLACE_DIALOG_REPLACE_RESPONSE,
+ pos > 0);
+
+ dialog->idle_update_sensitivity_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+install_idle_update_sensitivity (GeditReplaceDialog *dialog)
+{
+ if (dialog->idle_update_sensitivity_id != 0)
+ {
+ return;
+ }
+
+ dialog->idle_update_sensitivity_id =
+ g_idle_add ((GSourceFunc)update_replace_response_sensitivity_cb,
+ dialog);
+}
+
+static void
+mark_set_cb (GtkTextBuffer *buffer,
+ GtkTextIter *location,
+ GtkTextMark *mark,
+ GeditReplaceDialog *dialog)
+{
+ GtkTextMark *insert;
+ GtkTextMark *selection_bound;
+
+ insert = gtk_text_buffer_get_insert (buffer);
+ selection_bound = gtk_text_buffer_get_selection_bound (buffer);
+
+ if (mark == insert || mark == selection_bound)
+ {
+ install_idle_update_sensitivity (dialog);
+ }
+}
+
+static void
+update_responses_sensitivity (GeditReplaceDialog *dialog)
+{
+ const gchar *search_text;
+ gboolean sensitive = TRUE;
+
+ install_idle_update_sensitivity (dialog);
+
+ search_text = gtk_entry_get_text (GTK_ENTRY (dialog->search_text_entry));
+
+ if (search_text[0] == '\0')
+ {
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ GEDIT_REPLACE_DIALOG_FIND_RESPONSE,
+ FALSE);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ GEDIT_REPLACE_DIALOG_REPLACE_ALL_RESPONSE,
+ FALSE);
+
+ return;
+ }
+
+ sensitive = !has_search_error (dialog);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ GEDIT_REPLACE_DIALOG_FIND_RESPONSE,
+ sensitive);
+
+ if (has_replace_error (dialog))
+ {
+ sensitive = FALSE;
+ }
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ GEDIT_REPLACE_DIALOG_REPLACE_ALL_RESPONSE,
+ sensitive);
+}
+
+static void
+regex_error_notify_cb (GeditReplaceDialog *dialog)
+{
+ update_regex_error (dialog);
+ update_responses_sensitivity (dialog);
+}
+
+static void
+disconnect_document (GeditReplaceDialog *dialog)
+{
+ GtkSourceSearchContext *search_context;
+
+ if (dialog->active_document == NULL)
+ {
+ return;
+ }
+
+ search_context = get_search_context (dialog, dialog->active_document);
+
+ if (search_context != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (search_context,
+ regex_error_notify_cb,
+ dialog);
+ }
+
+ g_signal_handlers_disconnect_by_func (dialog->active_document,
+ mark_set_cb,
+ dialog);
+
+ g_clear_object (&dialog->active_document);
+}
+
+static void
+connect_active_document (GeditReplaceDialog *dialog)
+{
+ GeditDocument *doc;
+ GtkSourceSearchContext *search_context;
+
+ disconnect_document (dialog);
+
+ doc = get_active_document (dialog);
+
+ if (doc == NULL)
+ {
+ return;
+ }
+
+ dialog->active_document = g_object_ref (doc);
+
+ search_context = get_search_context (dialog, doc);
+
+ if (search_context == NULL)
+ {
+ GtkSourceSearchSettings *settings = gtk_source_search_settings_new ();
+
+ search_context = gtk_source_search_context_new (GTK_SOURCE_BUFFER (doc),
+ settings);
+
+ /* Mark the search context that it comes from the search and
+ * replace dialog. Search contexts can be created also from the
+ * GeditViewFrame.
+ */
+ g_object_set_data (G_OBJECT (search_context),
+ GEDIT_SEARCH_CONTEXT_KEY,
+ dialog);
+
+ gedit_document_set_search_context (doc, search_context);
+
+ g_object_unref (settings);
+ g_object_unref (search_context);
+ }
+
+ g_signal_connect_object (search_context,
+ "notify::regex-error",
+ G_CALLBACK (regex_error_notify_cb),
+ dialog,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (doc,
+ "mark-set",
+ G_CALLBACK (mark_set_cb),
+ dialog,
+ 0);
+
+ update_regex_error (dialog);
+ update_responses_sensitivity (dialog);
+}
+
+static void
+response_cb (GtkDialog *dialog,
+ gint response_id)
+{
+ GeditReplaceDialog *dlg = GEDIT_REPLACE_DIALOG (dialog);
+ const gchar *str;
+
+ switch (response_id)
+ {
+ case GEDIT_REPLACE_DIALOG_REPLACE_RESPONSE:
+ case GEDIT_REPLACE_DIALOG_REPLACE_ALL_RESPONSE:
+ str = gtk_entry_get_text (GTK_ENTRY (dlg->replace_text_entry));
+ if (*str != '\0')
+ {
+ gedit_history_entry_prepend_text
+ (GEDIT_HISTORY_ENTRY (dlg->replace_entry),
+ str);
+ }
+ /* fall through, so that we also save the find entry */
+ case GEDIT_REPLACE_DIALOG_FIND_RESPONSE:
+ str = gtk_entry_get_text (GTK_ENTRY (dlg->search_text_entry));
+ if (*str != '\0')
+ {
+ gedit_history_entry_prepend_text
+ (GEDIT_HISTORY_ENTRY (dlg->search_entry),
+ str);
+ }
+ }
+
+ switch (response_id)
+ {
+ case GEDIT_REPLACE_DIALOG_REPLACE_RESPONSE:
+ case GEDIT_REPLACE_DIALOG_REPLACE_ALL_RESPONSE:
+ case GEDIT_REPLACE_DIALOG_FIND_RESPONSE:
+ connect_active_document (GEDIT_REPLACE_DIALOG (dialog));
+ set_search_settings (GEDIT_REPLACE_DIALOG (dialog));
+ }
+}
+
+static void
+gedit_replace_dialog_dispose (GObject *object)
+{
+ GeditReplaceDialog *dialog = GEDIT_REPLACE_DIALOG (object);
+
+ g_clear_object (&dialog->active_document);
+
+ if (dialog->idle_update_sensitivity_id != 0)
+ {
+ g_source_remove (dialog->idle_update_sensitivity_id);
+ dialog->idle_update_sensitivity_id = 0;
+ }
+
+ G_OBJECT_CLASS (gedit_replace_dialog_parent_class)->dispose (object);
+}
+
+static void
+gedit_replace_dialog_class_init (GeditReplaceDialogClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->dispose = gedit_replace_dialog_dispose;
+ widget_class->delete_event = gedit_replace_dialog_delete_event;
+
+ /* Bind class to template */
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/gedit/ui/gedit-replace-dialog.ui");
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, grid);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, search_label);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, replace_label);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, match_case_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, entire_word_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, regex_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, backwards_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, wrap_around_checkbutton);
+ gtk_widget_class_bind_template_child (widget_class, GeditReplaceDialog, close_button);
+}
+
+static void
+search_text_entry_changed (GtkEditable *editable,
+ GeditReplaceDialog *dialog)
+{
+ set_search_error (dialog, NULL);
+
+ update_responses_sensitivity (dialog);
+}
+
+static void
+replace_text_entry_changed (GtkEditable *editable,
+ GeditReplaceDialog *dialog)
+{
+ gedit_replace_dialog_set_replace_error (dialog, NULL);
+
+ update_responses_sensitivity (dialog);
+}
+
+static void
+regex_checkbutton_toggled (GtkToggleButton *checkbutton,
+ GeditReplaceDialog *dialog)
+{
+ if (!gtk_toggle_button_get_active (checkbutton))
+ {
+ /* Remove the regex error state so the user can search again */
+ set_search_error (dialog, NULL);
+ update_responses_sensitivity (dialog);
+ }
+}
+
+/* TODO: move in gedit-document.c and share it with gedit-view-frame */
+static gboolean
+get_selected_text (GtkTextBuffer *doc,
+ gchar **selected_text,
+ gint *len)
+{
+ GtkTextIter start, end;
+
+ g_return_val_if_fail (selected_text != NULL, FALSE);
+ g_return_val_if_fail (*selected_text == NULL, FALSE);
+
+ if (!gtk_text_buffer_get_selection_bounds (doc, &start, &end))
+ {
+ if (len != NULL)
+ {
+ len = 0;
+ }
+
+ return FALSE;
+ }
+
+ *selected_text = gtk_text_buffer_get_slice (doc, &start, &end, TRUE);
+
+ if (len != NULL)
+ {
+ *len = g_utf8_strlen (*selected_text, -1);
+ }
+
+ return TRUE;
+}
+
+static void
+show_cb (GeditReplaceDialog *dialog)
+{
+ GeditWindow *window;
+ GeditDocument *doc;
+ gboolean selection_exists;
+ gchar *selection = NULL;
+ gint selection_length;
+
+ window = get_gedit_window (dialog);
+
+ if (window == NULL)
+ {
+ return;
+ }
+
+ doc = get_active_document (dialog);
+
+ if (doc == NULL)
+ {
+ return;
+ }
+
+ selection_exists = get_selected_text (GTK_TEXT_BUFFER (doc),
+ &selection,
+ &selection_length);
+
+ if (selection_exists && selection != NULL && selection_length < 80)
+ {
+ gboolean regex_enabled;
+ gchar *escaped_selection;
+
+ regex_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->regex_checkbutton));
+
+ if (regex_enabled)
+ {
+ escaped_selection = g_regex_escape_string (selection, -1);
+ }
+ else
+ {
+ escaped_selection = gtk_source_utils_escape_search_text (selection);
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_text_entry),
+ escaped_selection);
+
+ g_free (escaped_selection);
+ }
+
+ g_free (selection);
+}
+
+static void
+hide_cb (GeditReplaceDialog *dialog)
+{
+ disconnect_document (dialog);
+}
+
+static void
+gedit_replace_dialog_init (GeditReplaceDialog *dlg)
+{
+ gtk_widget_init_template (GTK_WIDGET (dlg));
+
+ dlg->search_entry = gedit_history_entry_new ("search-for-entry", TRUE);
+ gtk_widget_set_size_request (dlg->search_entry, 300, -1);
+ gtk_widget_set_hexpand (GTK_WIDGET (dlg->search_entry), TRUE);
+ dlg->search_text_entry = gedit_history_entry_get_entry (GEDIT_HISTORY_ENTRY (dlg->search_entry));
+ gtk_entry_set_activates_default (GTK_ENTRY (dlg->search_text_entry), TRUE);
+ gtk_grid_attach_next_to (GTK_GRID (dlg->grid),
+ dlg->search_entry,
+ dlg->search_label,
+ GTK_POS_RIGHT, 1, 1);
+ gtk_widget_show_all (dlg->search_entry);
+
+ dlg->replace_entry = gedit_history_entry_new ("replace-with-entry", TRUE);
+ gtk_widget_set_hexpand (GTK_WIDGET (dlg->replace_entry), TRUE);
+ dlg->replace_text_entry = gedit_history_entry_get_entry (GEDIT_HISTORY_ENTRY (dlg->replace_entry));
+ gtk_entry_set_placeholder_text (GTK_ENTRY (dlg->replace_text_entry), _("Nothing"));
+ gtk_entry_set_activates_default (GTK_ENTRY (dlg->replace_text_entry), TRUE);
+ gtk_grid_attach_next_to (GTK_GRID (dlg->grid),
+ dlg->replace_entry,
+ dlg->replace_label,
+ GTK_POS_RIGHT, 1, 1);
+ gtk_widget_show_all (dlg->replace_entry);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->search_label),
+ dlg->search_entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->replace_label),
+ dlg->replace_entry);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dlg),
+ GEDIT_REPLACE_DIALOG_FIND_RESPONSE);
+
+ /* insensitive by default */
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
+ GEDIT_REPLACE_DIALOG_FIND_RESPONSE,
+ FALSE);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
+ GEDIT_REPLACE_DIALOG_REPLACE_RESPONSE,
+ FALSE);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
+ GEDIT_REPLACE_DIALOG_REPLACE_ALL_RESPONSE,
+ FALSE);
+
+ g_signal_connect (dlg->search_text_entry,
+ "changed",
+ G_CALLBACK (search_text_entry_changed),
+ dlg);
+
+ g_signal_connect (dlg->replace_text_entry,
+ "changed",
+ G_CALLBACK (replace_text_entry_changed),
+ dlg);
+
+ g_signal_connect (dlg->regex_checkbutton,
+ "toggled",
+ G_CALLBACK (regex_checkbutton_toggled),
+ dlg);
+
+ g_signal_connect (dlg,
+ "show",
+ G_CALLBACK (show_cb),
+ NULL);
+
+ g_signal_connect (dlg,
+ "hide",
+ G_CALLBACK (hide_cb),
+ NULL);
+
+ /* We connect here to make sure this handler runs before the others so
+ * that the search context is created.
+ */
+ g_signal_connect (dlg,
+ "response",
+ G_CALLBACK (response_cb),
+ NULL);
+}
+
+GtkWidget *
+gedit_replace_dialog_new (GeditWindow *window)
+{
+ GeditReplaceDialog *dialog;
+ gboolean use_header;
+
+ g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
+
+ dialog = g_object_new (GEDIT_TYPE_REPLACE_DIALOG,
+ "transient-for", window,
+ "destroy-with-parent", TRUE,
+ "use-header-bar", FALSE,
+ NULL);
+
+ /* We want the Find/Replace/ReplaceAll buttons at the bottom,
+ * so we turn off the automatic header bar, but we check the
+ * setting and if a header bar should be used, we create it
+ * manually and use it for the close button.
+ */
+ g_object_get (gtk_settings_get_default (),
+ "gtk-dialogs-use-header", &use_header,
+ NULL);
+
+ if (use_header)
+ {
+ GtkWidget *header_bar;
+
+ header_bar = gtk_header_bar_new ();
+ gtk_header_bar_set_title (GTK_HEADER_BAR (header_bar), _("Find and Replace"));
+ gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (header_bar), TRUE);
+ gtk_widget_show (header_bar);
+ gtk_window_set_titlebar (GTK_WINDOW (dialog), header_bar);
+ }
+ else
+ {
+ gtk_widget_set_no_show_all (dialog->close_button, FALSE);
+ gtk_widget_show (dialog->close_button);
+ }
+
+ return GTK_WIDGET (dialog);
+}
+
+const gchar *
+gedit_replace_dialog_get_replace_text (GeditReplaceDialog *dialog)
+{
+ g_return_val_if_fail (GEDIT_IS_REPLACE_DIALOG (dialog), NULL);
+
+ return gtk_entry_get_text (GTK_ENTRY (dialog->replace_text_entry));
+}
+
+gboolean
+gedit_replace_dialog_get_backwards (GeditReplaceDialog *dialog)
+{
+ g_return_val_if_fail (GEDIT_IS_REPLACE_DIALOG (dialog), FALSE);
+
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->backwards_checkbutton));
+}
+
+/* This function returns the original search text. The search text from the
+ * search settings has been unescaped, and the escape function is not
+ * reciprocal. So to avoid bugs, we have to deal with the original search text.
+ */
+const gchar *
+gedit_replace_dialog_get_search_text (GeditReplaceDialog *dialog)
+{
+ g_return_val_if_fail (GEDIT_IS_REPLACE_DIALOG (dialog), NULL);
+
+ return gtk_entry_get_text (GTK_ENTRY (dialog->search_text_entry));
+}
+
+/* ex:set ts=8 noet: */