Re-implemented the search dialog for the syntax editor
authorJohn Darrington <john@cellform.com>
Fri, 16 Jun 2023 15:14:41 +0000 (17:14 +0200)
committerJohn Darrington <john@cellform.com>
Sat, 17 Jun 2023 17:12:45 +0000 (19:12 +0200)
This new dialog offers a lot more features, such as case insensitivity,
backward searching etc.   This change also removes the option to build
against gtksourceview-3 - gtksourceview-4 is now required.

NEWS
configure.ac
src/ui/gui/automake.mk
src/ui/gui/psppire-buttonbox.c
src/ui/gui/psppire-buttonbox.h
src/ui/gui/psppire-dialog.h
src/ui/gui/psppire-search-dialog.c [new file with mode: 0644]
src/ui/gui/psppire-search-dialog.h [new file with mode: 0644]
src/ui/gui/psppire-syntax-window.c
src/ui/gui/psppire-syntax-window.h

diff --git a/NEWS b/NEWS
index 8bcb526ffa3beba4b72ebaac5ececdb6f0975b7a..72e49029cf613d172b356ba4433a476f67e6d675 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ See the end for copying conditions.
 
 Please send PSPP bug reports to bug-gnu-pspp@gnu.org.
 
+Changes since 2.0.0-pre1:
+
+ * Improved the search options in the syntax editor.
+
 Changes from 1.6.2 to 2.0.0-pre1:
 
  * The CTABLES command is now implemented.
index 2af7cd4214a1ec86cd75630611d5d81d1f2d8bda..649217255a8ee4c2fc5798f82965ada714e6e35d 100644 (file)
@@ -130,9 +130,8 @@ if test "$with_gui" != "no"; then
   PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.22.0], [],
     [PSPP_REQUIRED_PREREQ([gtk+ 3.0 version 3.22.0 or later (or use --without-gui)])])
 
-  PKG_CHECK_MODULES([GTKSOURCEVIEW], [gtksourceview-4 >= 4.0], [],
-    [PKG_CHECK_MODULES([GTKSOURCEVIEW], [gtksourceview-3.0 >= 3.4.2], [],
-      [PSPP_REQUIRED_PREREQ([gtksourceview 4.x or gtksourceview 3.x version 3.4.2 or later (or use --without-gui)])])])
+  PKG_CHECK_MODULES([GTKSOURCEVIEW], [gtksourceview-4 >= 4.8], [],
+      [PSPP_REQUIRED_PREREQ([gtksourceview 4.8 or later (or use --without-gui)])])
 
   PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.44], [],
     [PSPP_REQUIRED_PREREQ([glib 2.0 version 2.44 or later (or use --without-gui)])])
index 18885bb16818e273d44c187a90ebba893773e643..e01090777c4e7df05a7dae4f492494888d5042ef 100644 (file)
@@ -329,6 +329,8 @@ src_ui_gui_libwidgets_essential_la_SOURCES = \
        src/ui/gui/psppire-dialog-action-weight.h \
        src/ui/gui/psppire-dialog.c \
        src/ui/gui/psppire-dialog.h \
+       src/ui/gui/psppire-search-dialog.c \
+       src/ui/gui/psppire-search-dialog.h \
        src/ui/gui/psppire-dict.c \
        src/ui/gui/psppire-dict.h \
        src/ui/gui/psppire-dictview.c \
index a01518994738513898083b8d878572224239548a..f47852211ae713789a900f5812ced94fde9a7179 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2007, 2010, 2011, 2012  Free Software Foundation
+   Copyright (C) 2007, 2010, 2011, 2012, 2023  Free Software Foundation
 
    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
@@ -133,11 +133,13 @@ psppire_button_box_class_init (PsppireButtonBoxClass *class)
                        "Buttons",
                        "The mask that decides what buttons appear in the button box",
                        PSPPIRE_TYPE_BUTTON_MASK,
-                       PSPPIRE_BUTTON_OK_MASK |
-                       PSPPIRE_BUTTON_CANCEL_MASK |
-                       PSPPIRE_BUTTON_RESET_MASK |
-                       PSPPIRE_BUTTON_HELP_MASK |
-                       PSPPIRE_BUTTON_PASTE_MASK,
+                       PSPPIRE_BUTTON_OK_MASK
+                       | PSPPIRE_BUTTON_CANCEL_MASK
+                       | PSPPIRE_BUTTON_CLOSE_MASK
+                       | PSPPIRE_BUTTON_RESET_MASK
+                       | PSPPIRE_BUTTON_HELP_MASK
+                       | PSPPIRE_BUTTON_PASTE_MASK
+                       | PSPPIRE_BUTTON_FIND_MASK,
                        G_PARAM_READWRITE);
   g_object_class_install_property (object_class,
                                   PROP_BUTTONS,
@@ -219,7 +221,6 @@ goto_button_clicked (GtkWidget *w, gpointer data)
     close_and_respond (w, PSPPIRE_RESPONSE_GOTO);
 }
 
-
 static void
 refresh_clicked (GtkWidget *w, gpointer data)
 {
@@ -330,6 +331,10 @@ psppire_button_box_init (PsppireButtonBox *bb)
   psppire_box_pack_start_defaults (GTK_BOX (bb), bb->button[PSPPIRE_BUTTON_PASTE]);
   g_object_set (bb->button[PSPPIRE_BUTTON_PASTE], "no-show-all", TRUE, NULL);
 
+  bb->button[PSPPIRE_BUTTON_FIND] = gtk_button_new_with_label (_("Find"));
+  psppire_box_pack_start_defaults (GTK_BOX (bb), bb->button[PSPPIRE_BUTTON_FIND]);
+  g_object_set (bb->button[PSPPIRE_BUTTON_FIND], "no-show-all", TRUE, NULL);
+
   bb->button[PSPPIRE_BUTTON_CANCEL] = gtk_button_new_with_label (_("Cancel"));
   g_signal_connect (bb->button[PSPPIRE_BUTTON_CANCEL], "clicked",
                    G_CALLBACK (close_dialog), NULL);
@@ -394,6 +399,7 @@ psppire_button_flags_get_type (void)
          { PSPPIRE_BUTTON_HELP_MASK,    "PSPPIRE_BUTTON_HELP_MASK",     "Invoke context sensitive help" },
          { PSPPIRE_BUTTON_RESET_MASK,   "PSPPIRE_BUTTON_RESET_MASK",    "Restore dialog to its default settings" },
          { PSPPIRE_BUTTON_PASTE_MASK,   "PSPPIRE_BUTTON_PASTE_MASK",    "Accept dialog and paste syntax" },
+         { PSPPIRE_BUTTON_FIND_MASK,    "PSPPIRE_BUTTON_FIND_MASK",     "Find something" },
          { 0, NULL, NULL }
        };
 
index 3cc25e945013f236cf23877648d7aa4114a7951d..5d20470cfe9faf6286aba5297500b8e21daf28bb 100644 (file)
@@ -46,6 +46,7 @@ enum
     PSPPIRE_BUTTON_HELP,
     PSPPIRE_BUTTON_RESET,
     PSPPIRE_BUTTON_PASTE,
+    PSPPIRE_BUTTON_FIND,
     n_PsppireButtonBoxButtons
   };
 
@@ -58,7 +59,8 @@ typedef enum
     PSPPIRE_BUTTON_CLOSE_MASK  = (1 << PSPPIRE_BUTTON_CLOSE),
     PSPPIRE_BUTTON_HELP_MASK   = (1 << PSPPIRE_BUTTON_HELP),
     PSPPIRE_BUTTON_RESET_MASK  = (1 << PSPPIRE_BUTTON_RESET),
-    PSPPIRE_BUTTON_PASTE_MASK  = (1 << PSPPIRE_BUTTON_PASTE)
+    PSPPIRE_BUTTON_PASTE_MASK  = (1 << PSPPIRE_BUTTON_PASTE),
+    PSPPIRE_BUTTON_FIND_MASK  = (1 << PSPPIRE_BUTTON_FIND)
   } PsppireButtonMask;
 
 struct _PsppireButtonBox
@@ -84,4 +86,3 @@ GtkWidget*     psppire_button_box_new (void);
 G_END_DECLS
 
 #endif /* __PSPPIRE_BUTTON_BOX_H__ */
-
index 012a3e8944db19091502ba0ef58bcbe302c8f1c6..2c353b3d9931a3d90fe93fb3e83283ed0afd8d9b 100644 (file)
@@ -55,7 +55,6 @@ struct _PsppireDialog
   gpointer acceptable_data;
   gboolean slidable;
   gchar *help_page;
-
 };
 
 struct _PsppireDialogClass
diff --git a/src/ui/gui/psppire-search-dialog.c b/src/ui/gui/psppire-search-dialog.c
new file mode 100644 (file)
index 0000000..8a42ab5
--- /dev/null
@@ -0,0 +1,194 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2023  Free Software Foundation
+
+   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 3 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 <gtk/gtk.h>
+#include "psppire-search-dialog.h"
+#include "psppire-buttonbox.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+static void psppire_search_dialog_class_init    (PsppireSearchDialogClass *);
+static void psppire_search_dialog_init          (PsppireSearchDialog      *);
+
+enum  {FIND,
+  n_SIGNALS};
+
+static guint signals [n_SIGNALS];
+
+
+static GObjectClass     *parent_class = NULL;
+
+static void
+psppire_search_dialog_finalize (GObject *object)
+{
+  //  PsppireSearchDialog *dialog = PSPPIRE_SEARCH_DIALOG (object);
+
+  if (G_OBJECT_CLASS (parent_class)->finalize)
+    G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+G_DEFINE_TYPE (PsppireSearchDialog, psppire_search_dialog, PSPPIRE_TYPE_DIALOG);
+
+
+static void
+psppire_search_dialog_get_property (GObject         *object,
+                            guint            prop_id,
+                            GValue          *value,
+                            GParamSpec      *pspec)
+{
+  //  PsppireSearchDialog *dialog = PSPPIRE_SEARCH_DIALOG (object);
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+static void
+psppire_search_dialog_set_property (GObject         *object,
+                            guint            prop_id,
+                            const GValue    *value,
+                            GParamSpec      *pspec)
+
+{
+  //  PsppireSearchDialog *dialog = PSPPIRE_SEARCH_DIALOG (object);
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+static void
+psppire_search_dialog_class_init (PsppireSearchDialogClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = psppire_search_dialog_finalize;
+
+  object_class->set_property = psppire_search_dialog_set_property;
+  object_class->get_property = psppire_search_dialog_get_property;
+
+  signals [FIND] =
+    g_signal_new ("find",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_FIRST,
+                 0,
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__BOOLEAN,
+                 G_TYPE_NONE,
+                 1,
+                 G_TYPE_BOOLEAN);
+
+  parent_class = g_type_class_peek_parent (class);
+}
+
+static void
+search_forward (PsppireSearchDialog *dialog)
+{
+  g_signal_emit (dialog, signals [FIND], 0, FALSE);
+}
+
+static void
+search_backward (PsppireSearchDialog *dialog)
+{
+  g_signal_emit (dialog, signals [FIND], 0, TRUE);
+}
+
+static void
+on_find (PsppireSearchDialog *sd)
+{
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (sd->backward)))
+    search_backward (sd);
+  else
+    search_forward (sd);
+}
+
+static void
+psppire_search_dialog_init (PsppireSearchDialog *dialog)
+{
+  GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
+
+  GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
+  GtkWidget *label = gtk_label_new ( _("Search Text:"));
+  dialog->entry = gtk_search_entry_new ();
+
+  g_signal_connect_swapped (dialog->entry, "next-match", G_CALLBACK (search_forward),
+                            dialog);
+  g_signal_connect_swapped (dialog->entry, "previous-match", G_CALLBACK (search_backward),
+                            dialog);
+
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
+  gtk_box_pack_start (GTK_BOX (hbox), dialog->entry, TRUE, TRUE, 5);
+
+  gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, TRUE, 5);
+
+  GtkWidget *bbo = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
+  dialog->ignore_case = gtk_check_button_new_with_label ( _("Ignore case"));
+  gtk_box_pack_start (GTK_BOX (bbo), dialog->ignore_case, FALSE, TRUE, 5);
+
+  dialog->wrap = gtk_check_button_new_with_label ( _("Wrap around"));
+  gtk_box_pack_start (GTK_BOX (bbo), dialog->wrap, FALSE, TRUE, 5);
+
+  dialog->whole = gtk_check_button_new_with_label ( _("Match whole words only"));
+  gtk_box_pack_start (GTK_BOX (bbo), dialog->whole, FALSE, TRUE, 5);
+
+  dialog->forward = gtk_radio_button_new_with_label (NULL, _("Search forward"));
+  gtk_box_pack_start (GTK_BOX (bbo), dialog->forward, FALSE, TRUE, 5);
+
+  dialog->backward = gtk_radio_button_new_with_label (NULL, _("Search backward"));
+  gtk_box_pack_start (GTK_BOX (bbo), dialog->backward, FALSE, TRUE, 5);
+
+  gtk_radio_button_join_group (GTK_RADIO_BUTTON (dialog->backward),
+                               GTK_RADIO_BUTTON (dialog->forward));
+
+  gtk_box_pack_start (GTK_BOX (box), bbo, FALSE, TRUE, 5);
+
+  GtkWidget *bb = psppire_button_box_new ();
+  g_object_set (bb,
+                "buttons", PSPPIRE_BUTTON_FIND_MASK | PSPPIRE_BUTTON_CLOSE_MASK,
+                "layout-style", GTK_BUTTONBOX_SPREAD,
+                NULL);
+
+  gtk_box_pack_start (GTK_BOX (box), bb, FALSE, TRUE, 5);
+
+  g_signal_connect_swapped (PSPPIRE_BUTTON_BOX (bb)->button[PSPPIRE_BUTTON_FIND],
+                            "clicked", G_CALLBACK (on_find), dialog);
+
+  gtk_widget_show_all (box);
+  gtk_container_add (GTK_CONTAINER (dialog), box);
+}
+
+GtkWidget*
+psppire_search_dialog_new (void)
+{
+  PsppireSearchDialog *dialog
+    = g_object_new (psppire_search_dialog_get_type (),
+                    "title", _("PSPPIRE Search Syntax"),
+                    NULL);
+
+  return GTK_WIDGET (dialog) ;
+}
diff --git a/src/ui/gui/psppire-search-dialog.h b/src/ui/gui/psppire-search-dialog.h
new file mode 100644 (file)
index 0000000..2ca2cd0
--- /dev/null
@@ -0,0 +1,61 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2023  Free Software Foundation
+
+   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 3 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/>. */
+
+#ifndef __PSPPIRE_SEARCH_DIALOG_H__
+#define __PSPPIRE_SEARCH_DIALOG_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "psppire-dialog.h"
+
+
+G_BEGIN_DECLS
+
+#define PSPPIRE_TYPE_SEARCH_DIALOG            (psppire_search_dialog_get_type ())
+#define PSPPIRE_SEARCH_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPPIRE_TYPE_SEARCH_DIALOG, PsppireSearchDialog))
+#define PSPPIRE_SEARCH_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PSPPIRE_TYPE_SEARCH_DIALOG, PsppireSearchDialogClass))
+#define PSPPIRE_IS_SEARCH_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_SEARCH_DIALOG))
+#define PSPPIRE_IS_SEARCH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_SEARCH_DIALOG))
+
+
+typedef struct _PsppireSearchDialog       PsppireSearchDialog;
+typedef struct _PsppireSearchDialogClass  PsppireSearchDialogClass;
+
+struct _PsppireSearchDialog
+{
+  PsppireDialog parent;
+
+  GtkWidget *entry;
+  GtkWidget *bbo;
+  GtkWidget *ignore_case;
+  GtkWidget *wrap;
+  GtkWidget *whole;
+  GtkWidget *forward;
+  GtkWidget *backward;
+};
+
+struct _PsppireSearchDialogClass
+{
+  PsppireDialogClass parent_class;
+};
+
+GType          psppire_search_dialog_get_type        (void);
+GtkWidget*     psppire_search_dialog_new             (void);
+
+G_END_DECLS
+
+#endif /* __PSPPIRE_SEARCH_DIALOG_H__ */
index 4f244a82062ef7fcb58de16adbecf2633c555ce5..302940d93195d71f471d1d77c4e113249924d7ec 100644 (file)
@@ -36,6 +36,7 @@
 #include "ui/gui/psppire-lex-reader.h"
 #include "ui/gui/psppire-syntax-window.h"
 #include "ui/gui/psppire.h"
+#include "ui/gui/psppire-search-dialog.h"
 #include "ui/gui/windows-menu.h"
 
 #include "gl/localcharset.h"
@@ -124,8 +125,6 @@ psppire_syntax_window_dispose (GObject *obj)
   if (sw->dispose_has_run)
     return;
 
-  g_object_unref (sw->search_text_buffer);
-
   g_free (sw->encoding);
   sw->encoding = NULL;
 
@@ -211,7 +210,9 @@ editor_execute_syntax (const PsppireSyntaxWindow *sw, GtkTextIter start,
 
   execute_syntax (psppire_default_data_window (), reader);
 }
+
 \f
+
 /* Delete the currently selected text */
 static void
 on_edit_delete (PsppireSyntaxWindow *sw)
@@ -223,84 +224,65 @@ on_edit_delete (PsppireSyntaxWindow *sw)
     gtk_text_buffer_delete (buffer, &begin, &end);
 }
 
-/* Create and run a dialog to collect the search string.
-   In future this might be expanded to include options, for example
-   backward searching, case sensitivity etc.  */
-static const char *
-get_search_text (PsppireSyntaxWindow *parent)
-{
-  const char *search_text = NULL;
-  GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL;
-  GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Text Search"),
-                                                   GTK_WINDOW (parent),
-                                                   flags,
-                                                   _("_OK"),
-                                                   GTK_RESPONSE_OK,
-                                                   _("_Cancel"),
-                                                   GTK_RESPONSE_CANCEL,
-                                                   NULL);
-
-  GtkWidget *content_area =
-    gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-
-  GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-  GtkWidget *label = gtk_label_new (_("Text to search for:"));
-  GtkWidget *entry = gtk_entry_new_with_buffer (parent->search_text_buffer);
-
-  /* Add the label, and show everything we have added.  */
-  gtk_container_add (GTK_CONTAINER (content_area), box);
-  gtk_container_add (GTK_CONTAINER (box), label);
-  gtk_container_add (GTK_CONTAINER (box), entry);
-  gtk_widget_show_all (content_area);
-
-  int result = gtk_dialog_run (GTK_DIALOG (dialog));
-  switch (result)
-    {
-    case GTK_RESPONSE_OK:
-      search_text = gtk_entry_get_text (GTK_ENTRY (entry));
-      break;
-    default:
-      search_text = NULL;
-    };
-
-  gtk_widget_destroy (dialog);
-  return search_text;
-}
+typedef gboolean search_function (GtkSourceSearchContext *search,
+                                  const GtkTextIter *iter,
+                                  GtkTextIter *match_start,
+                                  GtkTextIter *match_end,
+                                   gboolean *has_wrapped_around);
 
 
-/* What to do when the Find menuitem is called.  */
-static void
-on_edit_find (PsppireSyntaxWindow *sw)
+/* This function is called when the user clicks the Find button */
+static void on_find (PsppireSyntaxWindow *sw, gboolean backwards, gpointer data, gpointer junk)
 {
+  PsppireSearchDialog *dialog = PSPPIRE_SEARCH_DIALOG (data);
+
+  const char *search_text = gtk_entry_get_text (GTK_ENTRY (dialog->entry));
+  if (search_text == NULL)
+    return;
+
   GtkTextBuffer *buffer = GTK_TEXT_BUFFER (sw->buffer);
   GtkTextIter begin;
   GtkTextIter loc;
-  const char *target = get_search_text (sw);
 
-  if (target == NULL)
-    return;
-
-  /* This is a wrap-around search.  So start searching one
-     character after the current char.  */
   GtkTextMark *mark = gtk_text_buffer_get_insert (buffer);
+
+  GtkSourceSearchSettings *sss = gtk_source_search_context_get_settings (sw->search_context);
+  gtk_source_search_settings_set_search_text (sss, search_text);
+  gtk_source_search_settings_set_case_sensitive (sss,
+                                                 !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->ignore_case)));
+
+  gtk_source_search_settings_set_at_word_boundaries (sss,
+                                                     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->whole)));
+
+  gtk_source_search_settings_set_wrap_around (sss,
+                                              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->wrap)));
+
+  search_function *func = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->forward))
+                                                        ? gtk_source_search_context_forward
+                                                        : gtk_source_search_context_backward;
+
   gtk_text_buffer_get_iter_at_mark (buffer, &begin, mark);
   gtk_text_iter_forward_char (&begin);
-  if (gtk_text_iter_forward_search (&begin, target, 0,
-                                    &loc, 0, 0))
+  if (func (sw->search_context, &begin, &loc, NULL, NULL))
     {
       gtk_text_buffer_place_cursor (buffer, &loc);
     }
-  else
-    {
-      /* If not found, then continue the search from the top
-         of the buffer.  */
-      gtk_text_buffer_get_start_iter (buffer, &begin);
-      if (gtk_text_iter_forward_search (&begin, target, 0,
-                                        &loc, 0, 0))
-        {
-          gtk_text_buffer_place_cursor (buffer, &loc);
-        }
-    }
+}
+
+/* What to do when the Find menuitem is called.  */
+static void
+on_edit_find (PsppireSyntaxWindow *sw)
+{
+  GtkWidget *ww = psppire_search_dialog_new ();
+  gtk_window_set_transient_for (GTK_WINDOW (ww), GTK_WINDOW (sw));
+
+  g_signal_connect_swapped (ww, "find", G_CALLBACK (on_find), sw);
+
+  sw->search_context = gtk_source_search_context_new (sw->buffer, NULL);
+
+  psppire_dialog_run (PSPPIRE_DIALOG (ww));
+
+  g_object_unref (sw->search_context);
 }
 
 
@@ -858,7 +840,7 @@ psppire_syntax_window_init (PsppireSyntaxWindow *window)
   window->cliptext = NULL;
   window->dispose_has_run = FALSE;
 
-  window->search_text_buffer = gtk_entry_buffer_new (NULL, -1);
+  window->search_context = NULL;
 
   window->edit_delete = g_simple_action_new ("delete", NULL);
   g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (window->edit_delete));
index 161b374597998e861e1421f7f290bd3ec256e5d3..61b6cc4ec5c89804bada3ca77dc23c3b5454e976 100644 (file)
@@ -68,7 +68,7 @@ struct _PsppireSyntaxWindow
   GSimpleAction *edit_paste;
   GSimpleAction *edit_find;
 
-  GtkEntryBuffer *search_text_buffer;
+  GtkSourceSearchContext *search_context;
 
   gulong ps_handler;
   gulong sel_handler;