[gtksourceview/wip/search: 3/36] search: add GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES flag



commit 68abef6836c457e593677c9ba45fe72df4c6d2a0
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Mon Jun 24 22:10:40 2013 +0200

    search: add GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES flag

 gtksourceview/gtksourcebuffer.h |    5 +++-
 gtksourceview/gtksourcesearch.c |   56 ++++++++++++++++++++++++++++++--------
 tests/test-search-ui.c          |   25 +++++++++++++++++
 tests/test-search-ui.ui         |   17 +++++++++++-
 4 files changed, 89 insertions(+), 14 deletions(-)
---
diff --git a/gtksourceview/gtksourcebuffer.h b/gtksourceview/gtksourcebuffer.h
index 9ce9b3e..fab8416 100644
--- a/gtksourceview/gtksourcebuffer.h
+++ b/gtksourceview/gtksourcebuffer.h
@@ -59,6 +59,8 @@ typedef enum
 /**
  * GtkSourceSearchFlags:
  * @GTK_SOURCE_SEARCH_CASE_SENSITIVE: Case sensitive search.
+ * @GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES: A search match must start and end a
+ * word. The match can span multiple words.
  *
  * Flags affecting how the search is done. Internally, GtkSourceView always
  * enables #GTK_TEXT_SEARCH_VISIBLE_ONLY and #GTK_TEXT_SEARCH_TEXT_ONLY.
@@ -67,7 +69,8 @@ typedef enum
  */
 typedef enum
 {
-       GTK_SOURCE_SEARCH_CASE_SENSITIVE        = 1 << 0
+       GTK_SOURCE_SEARCH_CASE_SENSITIVE        = 1 << 0,
+       GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES    = 1 << 1
 } GtkSourceSearchFlags;
 
 struct _GtkSourceBuffer
diff --git a/gtksourceview/gtksourcesearch.c b/gtksourceview/gtksourcesearch.c
index 2805f6d..bd9de6c 100644
--- a/gtksourceview/gtksourcesearch.c
+++ b/gtksourceview/gtksourcesearch.c
@@ -135,6 +135,8 @@ struct _GtkSourceSearchPrivate
        guint occurrences_count;
 
        GtkTextTag *found_tag;
+
+       guint at_word_boundaries : 1;
 };
 
 #define GTK_SOURCE_SEARCH_GET_PRIVATE(object) \
@@ -150,6 +152,39 @@ dispose_has_run (GtkSourceSearch *search)
        return search->priv->buffer == NULL;
 }
 
+static gboolean
+forward_search (GtkSourceSearch   *search,
+               const GtkTextIter *iter,
+               GtkTextIter       *match_start,
+               GtkTextIter       *match_end,
+               const GtkTextIter *limit)
+{
+       GtkTextIter begin_search = *iter;
+
+       while (TRUE)
+       {
+               gboolean found = gtk_text_iter_forward_search (&begin_search,
+                                                              search->priv->text,
+                                                              search->priv->flags,
+                                                              match_start,
+                                                              match_end,
+                                                              limit);
+
+               if (!found || !search->priv->at_word_boundaries)
+               {
+                       return found;
+               }
+
+               if (gtk_text_iter_starts_word (match_start) &&
+                   gtk_text_iter_ends_word (match_end))
+               {
+                       return TRUE;
+               }
+
+               begin_search = *match_end;
+       }
+}
+
 static void
 sync_found_tag (GtkSourceSearch *search)
 {
@@ -493,12 +528,7 @@ remove_occurrences_in_range (GtkSourceSearch *search,
        iter = *start;
 
        /* TODO optimization: search with forward_to_tag_toggle() */
-       while (gtk_text_iter_forward_search (&iter,
-                                            search->priv->text,
-                                            search->priv->flags,
-                                            &match_start,
-                                            &match_end,
-                                            end))
+       while (forward_search (search, &iter, &match_start, &match_end, end))
        {
                if (search->priv->scan_region == NULL)
                {
@@ -586,12 +616,7 @@ scan_subregion (GtkSourceSearch *search,
                GtkTextIter match_start;
                GtkTextIter match_end;
 
-               found = gtk_text_iter_forward_search (&iter,
-                                                     search->priv->text,
-                                                     search->priv->flags,
-                                                     &match_start,
-                                                     &match_end,
-                                                     limit);
+               found = forward_search (search, &iter, &match_start, &match_end, limit);
 
                if (found)
                {
@@ -1011,6 +1036,8 @@ _gtk_source_search_set_flags (GtkSourceSearch      *search,
                search->priv->flags |= GTK_TEXT_SEARCH_CASE_INSENSITIVE;
        }
 
+       search->priv->at_word_boundaries = (flags & GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES) != 0;
+
        update (search);
 }
 
@@ -1026,6 +1053,11 @@ _gtk_source_search_get_flags (GtkSourceSearch *search)
                source_flags |= GTK_SOURCE_SEARCH_CASE_SENSITIVE;
        }
 
+       if (search->priv->at_word_boundaries)
+       {
+               source_flags |= GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES;
+       }
+
        return source_flags;
 }
 
diff --git a/tests/test-search-ui.c b/tests/test-search-ui.c
index 97d2272..b907e84 100644
--- a/tests/test-search-ui.c
+++ b/tests/test-search-ui.c
@@ -88,6 +88,24 @@ on_match_case_toggled_cb (GtkToggleButton *button,
 }
 
 static void
+on_at_word_boundaries_toggled_cb (GtkToggleButton *button,
+                                 GtkSourceBuffer *buffer)
+{
+       GtkSourceSearchFlags flags = gtk_source_buffer_get_search_flags (buffer);
+
+       if (gtk_toggle_button_get_active (button))
+       {
+               flags |= GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES;
+       }
+       else
+       {
+               flags &= ~GTK_SOURCE_SEARCH_AT_WORD_BOUNDARIES;
+       }
+
+       gtk_source_buffer_set_search_flags (buffer, flags);
+}
+
+static void
 create_window (void)
 {
        GtkBuilder *builder;
@@ -98,6 +116,7 @@ create_window (void)
        GtkSearchEntry *search_entry;
        GtkLabel *label_occurrences_count;
        GtkCheckButton *match_case;
+       GtkCheckButton *at_word_boundaries;
        PangoFontDescription *font;
 
        builder = gtk_builder_new ();
@@ -116,6 +135,7 @@ create_window (void)
        search_entry = GTK_SEARCH_ENTRY (gtk_builder_get_object (builder, "search_entry"));
        label_occurrences_count = GTK_LABEL (gtk_builder_get_object (builder, "label_occurrences_count"));
        match_case = GTK_CHECK_BUTTON (gtk_builder_get_object (builder, "checkbutton_match_case"));
+       at_word_boundaries = GTK_CHECK_BUTTON (gtk_builder_get_object (builder, 
"checkbutton_at_word_boundaries"));
 
        font = pango_font_description_from_string ("Monospace 10");
        gtk_widget_override_font (GTK_WIDGET (source_view), font);
@@ -154,6 +174,11 @@ create_window (void)
                          G_CALLBACK (on_match_case_toggled_cb),
                          source_buffer);
 
+       g_signal_connect (at_word_boundaries,
+                         "toggled",
+                         G_CALLBACK (on_at_word_boundaries_toggled_cb),
+                         source_buffer);
+
        g_object_unref (builder);
 }
 
diff --git a/tests/test-search-ui.ui b/tests/test-search-ui.ui
index 0a43de8..8bf9f72 100644
--- a/tests/test-search-ui.ui
+++ b/tests/test-search-ui.ui
@@ -109,7 +109,6 @@
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
                 <property name="xalign">0</property>
-                <property name="active">True</property>
                 <property name="draw_indicator">True</property>
               </object>
               <packing>
@@ -119,6 +118,22 @@
                 <property name="height">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkCheckButton" id="checkbutton_at_word_boundaries">
+                <property name="label">At word boundaries</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="xalign">0</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="left_attach">0</property>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]