[gtksourceview/wip/search] search: remove region_not_scanned and adapt doc



commit 51d236516f5a14668ba99b850e1e63e1f2a407d9
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sun Jun 23 12:54:39 2013 +0200

    search: remove region_not_scanned and adapt doc
    
    And rename region_to_scan -> scan_region.

 gtksourceview/gtksourcesearch.c |  130 ++++++++++++++++-----------------------
 1 files changed, 53 insertions(+), 77 deletions(-)
---
diff --git a/gtksourceview/gtksourcesearch.c b/gtksourceview/gtksourcesearch.c
index 0aa963d..6700e11 100644
--- a/gtksourceview/gtksourcesearch.c
+++ b/gtksourceview/gtksourcesearch.c
@@ -52,12 +52,24 @@
  *
  * Why highlighting the non-visible matches? What we want is to (1) highlight
  * the visible matches and (2) count the number of occurrences. The code would
- * indeed be simpler if these two tasks are clearly separated (in two different
+ * indeed be simpler if these two tasks were clearly separated (in two different
  * idle callbacks, with different regions to scan). With this simpler solution,
  * we would always use forward_search() and backward_search() to navigate
  * through the occurrences. But we can do better than that!
- * forward_to_tag_toggle() and backward_to_tag_toggle() are far more efficient.
- * We must just pay attention to contiguous matches.
+ * forward_to_tag_toggle() and backward_to_tag_toggle() are far more efficient:
+ * once the buffer has been scanned, going to the previous or the next
+ * occurrence is done in O(1). We must just pay attention to contiguous matches.
+ *
+ * While the user is typing the text in the search entry, the buffer is scanned
+ * to count the number of occurrences. And when the user wants to do an
+ * operation (go to the next occurrence for example), chances are that the
+ * buffer has already been scanned entirely, so almost all the operations will
+ * be really fast.
+ *
+ * Extreme example:
+ * <occurrence> [1 GB of text] <next-occurrence>
+ * Once the buffer is scanned, switching between the occurrences will be almost
+ * instantaneous.
  *
  * So how to count the number of occurrences then? Remember that the buffer
  * contents can be modified during the scan, and that we keep the old
@@ -69,27 +81,17 @@
  * state changes, even if old matches are still there. Because it is not
  * possible to count the old matches to decrement occurrences_count (and storing
  * the previous search text would not be sufficient, because even older matches
- * can still be there). To update correctly occurrences_count, there are two
- * maintained regions:
+ * can still be there). To increment and decrement occurrences_count, there is
+ * the scan_region, the region to scan. If an occurrence is contained in
+ * scan_region, it means that it has not already been scanned, so
+ * occurrences_count doesn't take into account this occurrence. On the other
+ * hand, if we find an occurrence outside scan_region, the occurrence is
+ * normally correctly highlighted, and occurrences_count take it into account.
  *
- * - The region_not_scanned, which contain the region not already scanned since
- *   the last search state update. region_not_scanned can potentially contain
- *   old matches. When we highlight the matches in this region, we first remove
- *   all the found_tag's, without decrementing occurrences_count, and then we
- *   search the new matches and increment occurrences_count.
- *
- * - The region_to_scan, which can contain subregions already scanned (and thus
- *   removed from region_not_scanned). If a modification occurs in a buffer
- *   region not present in region_not_scanned, the modified region will be
- *   present only in region_to_scan. Such a region can not contain old matches.
- *   Before the modification occurs, we remove the (good) matches, and we
- *   decrement occurrences_count. After the modification, the idle callback will
- *   highlight the matches and will increment occurrences_count.
- *
- * Example where forward_to_tag_toggle() is really nice:
- * <occurrence> [1 GB of text] <next-occurrence>
- * Once the buffer has been scanned once, switching between the occurrences is
- * almost instantaneous (O(1) complexity).
+ * So when we highlight or when we remove the highlight of an occurrence (on
+ * text insertion, deletion, when scanning, etc.), we increment or decrement
+ * occurrences_count depending on whether the occurrence was already taken into
+ * account by occurrences_count.
  *
  * If the code seems too complicated and contains strange bugs, you have two
  * choices:
@@ -120,13 +122,8 @@ struct _GtkSourceSearchPrivate
        gint text_nb_lines;
        GtkTextSearchFlags flags;
 
-       /* The region not already scanned since the last search state update. */
-       GtkTextRegion *region_not_scanned;
-
-       /* The region to scan and highlight. If NULL, the scan is finished. It
-        * can contains regions already scanned, but must be rescanned.
-        */
-       GtkTextRegion *region_to_scan;
+       /* The region to scan and highlight. If NULL, the scan is finished. */
+       GtkTextRegion *scan_region;
 
        /* The region to scan and highlight in priority. I.e. the visible part
         * of the buffer on the screen.
@@ -281,16 +278,10 @@ get_first_subregion (GtkTextRegion *region,
 static void
 clear_search (GtkSourceSearch *search)
 {
-       if (search->priv->region_not_scanned != NULL)
-       {
-               gtk_text_region_destroy (search->priv->region_not_scanned, TRUE);
-               search->priv->region_not_scanned = NULL;
-       }
-
-       if (search->priv->region_to_scan != NULL)
+       if (search->priv->scan_region != NULL)
        {
-               gtk_text_region_destroy (search->priv->region_to_scan, TRUE);
-               search->priv->region_to_scan = NULL;
+               gtk_text_region_destroy (search->priv->scan_region, TRUE);
+               search->priv->scan_region = NULL;
        }
 
        if (search->priv->high_priority_region != NULL)
@@ -345,7 +336,7 @@ adjust_subregion (GtkSourceSearch *search,
 
        if (gtk_text_iter_has_tag (start, search->priv->found_tag))
        {
-               if (is_text_region_empty (search->priv->region_to_scan))
+               if (is_text_region_empty (search->priv->scan_region))
                {
                        /* 'start' is in a correct match, we can skip it. */
 
@@ -370,7 +361,7 @@ adjust_subregion (GtkSourceSearch *search,
                                gtk_text_iter_forward_to_tag_toggle (&tag_end, search->priv->found_tag);
                        }
 
-                       region = gtk_text_region_intersect (search->priv->region_to_scan,
+                       region = gtk_text_region_intersect (search->priv->scan_region,
                                                            &tag_start,
                                                            &tag_end);
 
@@ -401,7 +392,7 @@ adjust_subregion (GtkSourceSearch *search,
 
        if (gtk_text_iter_has_tag (end, search->priv->found_tag))
        {
-               if (is_text_region_empty (search->priv->region_to_scan))
+               if (is_text_region_empty (search->priv->scan_region))
                {
                        /* 'end' is in a correct match, we can skip it. */
 
@@ -426,7 +417,7 @@ adjust_subregion (GtkSourceSearch *search,
                                gtk_text_iter_forward_to_tag_toggle (&tag_end, search->priv->found_tag);
                        }
 
-                       region = gtk_text_region_intersect (search->priv->region_to_scan,
+                       region = gtk_text_region_intersect (search->priv->scan_region,
                                                            &tag_start,
                                                            &tag_end);
 
@@ -504,7 +495,7 @@ remove_occurrences_in_range (GtkSourceSearch *search,
                                             &match_end,
                                             end))
        {
-               if (search->priv->region_to_scan == NULL)
+               if (search->priv->scan_region == NULL)
                {
                        /* The occurrence has already been scanned, and thus
                         * occurrence_count take it into account. */
@@ -512,7 +503,7 @@ remove_occurrences_in_range (GtkSourceSearch *search,
                }
                else
                {
-                       GtkTextRegion *region = gtk_text_region_intersect (search->priv->region_to_scan,
+                       GtkTextRegion *region = gtk_text_region_intersect (search->priv->scan_region,
                                                                           &match_start,
                                                                           &match_end);
 
@@ -553,23 +544,18 @@ scan_subregion (GtkSourceSearch *search,
        adjust_subregion (search, start, end);
        remove_occurrences_in_range (search, start, end);
 
-       if (search->priv->region_not_scanned != NULL)
-       {
-               gtk_text_region_subtract (search->priv->region_not_scanned, start, end);
-       }
-
-       if (search->priv->region_to_scan != NULL)
+       if (search->priv->scan_region != NULL)
        {
                DEBUG ({
                        g_print ("Region to scan, before:\n");
-                       gtk_text_region_debug_print (search->priv->region_to_scan);
+                       gtk_text_region_debug_print (search->priv->scan_region);
                });
 
-               gtk_text_region_subtract (search->priv->region_to_scan, start, end);
+               gtk_text_region_subtract (search->priv->scan_region, start, end);
 
                DEBUG ({
                        g_print ("Region to scan, after:\n");
-                       gtk_text_region_debug_print (search->priv->region_to_scan);
+                       gtk_text_region_debug_print (search->priv->scan_region);
                });
        }
 
@@ -657,7 +643,7 @@ scan_chunk_region (GtkSourceSearch *search)
        GtkTextIter end;
 
        while (nb_remaining_lines > 0 &&
-              get_first_subregion (search->priv->region_to_scan, &start, &end))
+              get_first_subregion (search->priv->scan_region, &start, &end))
        {
                GtkTextIter limit = start;
                gint start_line;
@@ -700,27 +686,20 @@ idle_scan_cb (GtkSourceSearch *search)
                scan_chunk_region (search);
        }
 
-       if (is_text_region_empty (search->priv->region_to_scan))
+       if (is_text_region_empty (search->priv->scan_region))
        {
                finished = TRUE;
                search->priv->idle_scan_id = 0;
 
                g_object_notify (G_OBJECT (search->priv->buffer), "search-occurrences-count");
 
-               if (search->priv->region_to_scan != NULL)
+               if (search->priv->scan_region != NULL)
                {
-                       gtk_text_region_destroy (search->priv->region_to_scan, TRUE);
-                       search->priv->region_to_scan = NULL;
+                       gtk_text_region_destroy (search->priv->scan_region, TRUE);
+                       search->priv->scan_region = NULL;
                }
        }
 
-       if (is_text_region_empty (search->priv->region_not_scanned) &&
-           search->priv->region_not_scanned != NULL)
-       {
-               gtk_text_region_destroy (search->priv->region_not_scanned, TRUE);
-               search->priv->region_not_scanned = NULL;
-       }
-
        return !finished;
 }
 
@@ -741,21 +720,21 @@ add_subregion_to_scan (GtkSourceSearch   *search,
        GtkTextIter start = *subregion_start;
        GtkTextIter end = *subregion_end;
 
-       if (search->priv->region_to_scan == NULL)
+       if (search->priv->scan_region == NULL)
        {
-               search->priv->region_to_scan = gtk_text_region_new (search->priv->buffer);
+               search->priv->scan_region = gtk_text_region_new (search->priv->buffer);
        }
 
        DEBUG ({
                g_print ("add_subregion_to_scan(): region to scan, before:\n");
-               gtk_text_region_debug_print (search->priv->region_to_scan);
+               gtk_text_region_debug_print (search->priv->scan_region);
        });
 
-       gtk_text_region_add (search->priv->region_to_scan, &start, &end);
+       gtk_text_region_add (search->priv->scan_region, &start, &end);
 
        DEBUG ({
                g_print ("add_subregion_to_scan(): region to scan, after:\n");
-               gtk_text_region_debug_print (search->priv->region_to_scan);
+               gtk_text_region_debug_print (search->priv->scan_region);
        });
 
        install_idle_scan (search);
@@ -782,12 +761,9 @@ update (GtkSourceSearch *search)
 
        clear_search (search);
 
-       search->priv->region_not_scanned = gtk_text_region_new (search->priv->buffer);
-       search->priv->region_to_scan = gtk_text_region_new (search->priv->buffer);
+       search->priv->scan_region = gtk_text_region_new (search->priv->buffer);
 
        gtk_text_buffer_get_bounds (search->priv->buffer, &start, &end);
-
-       gtk_text_region_add (search->priv->region_not_scanned, &start, &end);
        add_subregion_to_scan (search, &start, &end);
 }
 
@@ -1033,12 +1009,12 @@ _gtk_source_search_update_highlight (GtkSourceSearch   *search,
        g_return_if_fail (end != NULL);
 
        if (dispose_has_run (search) ||
-           is_text_region_empty (search->priv->region_to_scan))
+           is_text_region_empty (search->priv->scan_region))
        {
                return;
        }
 
-       region_to_highlight = gtk_text_region_intersect (search->priv->region_to_scan,
+       region_to_highlight = gtk_text_region_intersect (search->priv->scan_region,
                                                         start,
                                                         end);
 


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