[gnome-builder] sourceview: don't stash GtkTextIter in the private structure



commit e01d4eede7602218f7b0b67cfdf12b85d1b93227
Author: Christian Hergert <christian hergert me>
Date:   Mon Mar 7 21:57:12 2016 -0800

    sourceview: don't stash GtkTextIter in the private structure
    
    I happened to have missed this during previous review of the mouse-over
    click-to-jump feature.
    
    We were stashing GtkTextIter in the private structure and then using them
    for comparisons in the future. Obviously, if an edit came in during that
    process, we'd have some fun bugs to track down.
    
    The data used for the lookup was also leaked, which is now fixed.
    
    This keeps a couple of marks around to surround the word to be highlighted.
    It also uses new marks during the lookup process.
    
    Afterwards, we discard our temp marks, and update the persistent mark
    locations.

 libide/ide-source-view.c |  170 +++++++++++++++++++++++++++++----------------
 1 files changed, 109 insertions(+), 61 deletions(-)
---
diff --git a/libide/ide-source-view.c b/libide/ide-source-view.c
index aa0f7e4..eb7f2ba 100644
--- a/libide/ide-source-view.c
+++ b/libide/ide-source-view.c
@@ -154,9 +154,9 @@ typedef struct
   guint                        delay_size_allocate_chainup;
   GtkAllocation                delay_size_allocation;
 
-  GtkTextIter                  definition_highlight_start;
-  GtkTextIter                  definition_highlight_end;
   IdeSourceLocation           *definition_src_location;
+  GtkTextMark                 *definition_highlight_start_mark;
+  GtkTextMark                 *definition_highlight_end_mark;
 
   guint                        auto_indent : 1;
   guint                        completion_blocked : 1;
@@ -194,8 +194,8 @@ typedef struct
 typedef struct
 {
   IdeSourceView    *self;
-  GtkTextIter       word_start;
-  GtkTextIter       word_end;
+  GtkTextMark      *word_start_mark;
+  GtkTextMark      *word_end_mark;
 } DefinitionHighlightData;
 
 G_DEFINE_TYPE_WITH_PRIVATE (IdeSourceView, ide_source_view, GTK_SOURCE_TYPE_VIEW)
@@ -341,7 +341,28 @@ search_movement_unref (SearchMovement *movement)
     }
 }
 
+static void
+definition_highlight_data_free (DefinitionHighlightData *data)
+{
+  if (data != NULL)
+    {
+      GtkTextBuffer *buffer;
+
+      buffer = gtk_text_mark_get_buffer (data->word_start_mark);
+
+      gtk_text_buffer_delete_mark (buffer, data->word_start_mark);
+      gtk_text_buffer_delete_mark (buffer, data->word_end_mark);
+
+      g_clear_object (&data->self);
+      g_clear_object (&data->word_start_mark);
+      g_clear_object (&data->word_end_mark);
+
+      g_slice_free (DefinitionHighlightData, data);
+    }
+}
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SearchMovement, search_movement_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (DefinitionHighlightData, definition_highlight_data_free)
 
 static SearchMovement *
 search_movement_new (IdeSourceView *self,
@@ -1444,26 +1465,18 @@ ide_source_view_reset_definition_highlight (IdeSourceView *self)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
 
+  g_assert (IDE_IS_SOURCE_VIEW (self));
+
   if (priv->definition_src_location)
-    {
-      ide_source_location_unref (priv->definition_src_location);
-      priv->definition_src_location = NULL;
-    }
+    g_clear_pointer (&priv->definition_src_location, ide_source_location_unref);
 
-  if (!gtk_text_iter_equal (&priv->definition_highlight_start,
-                            &priv->definition_highlight_end))
+  if (priv->buffer != NULL)
     {
-      gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER (priv->buffer),
-                                          TAG_DEFINITION,
-                                          &priv->definition_highlight_start,
-                                          &priv->definition_highlight_end);
-    }
+      GtkTextIter begin;
+      GtkTextIter end;
 
-  if (priv->buffer)
-    {
-      gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (priv->buffer),
-                                    &priv->definition_highlight_end);
-      priv->definition_highlight_start = priv->definition_highlight_end;
+      gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (priv->buffer), &begin, &end);
+      gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER (priv->buffer), TAG_DEFINITION, &begin, &end);
     }
 
   ide_source_view_set_cursor_from_name (self, "text");
@@ -1556,6 +1569,12 @@ ide_source_view_bind_buffer (IdeSourceView  *self,
   priv->rubberband_insert_mark =
     gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer), NULL, &iter, TRUE);
 
+  /* Marks used for definition highlights */
+  priv->definition_highlight_start_mark =
+    gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer), NULL, &iter, TRUE);
+  priv->definition_highlight_end_mark =
+    gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer), NULL, &iter, TRUE);
+
   ide_source_view__buffer_notify_language_cb (self, NULL, buffer);
   ide_source_view__buffer_notify_file_cb (self, NULL, buffer);
   ide_source_view__buffer_notify_highlight_diagnostics_cb (self, NULL, buffer);
@@ -1612,6 +1631,9 @@ ide_source_view_unbind_buffer (IdeSourceView  *self,
   g_clear_object (&priv->indenter_adapter);
   g_clear_object (&priv->completion_providers);
 
+  priv->definition_highlight_start_mark = NULL;
+  priv->definition_highlight_end_mark = NULL;
+
   ide_buffer_release (priv->buffer);
 }
 
@@ -2414,10 +2436,14 @@ ide_source_view_process_press_on_definition (IdeSourceView  *self,
                                              GdkEventButton *event)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkTextView *text_view = (GtkTextView *) self;
+  GtkTextView *text_view = (GtkTextView *)self;
   GtkTextIter iter;
   GtkTextWindowType window_type;
-  gint buffer_x, buffer_y;
+  gint buffer_x;
+  gint buffer_y;
+
+  g_assert (IDE_IS_SOURCE_VIEW (self));
+  g_assert (event != NULL);
 
   window_type = gtk_text_view_get_window_type (text_view, event->window);
   gtk_text_view_window_to_buffer_coords (text_view,
@@ -2431,23 +2457,26 @@ ide_source_view_process_press_on_definition (IdeSourceView  *self,
                                       buffer_x,
                                       buffer_y);
 
-  if (priv->definition_src_location)
+  if (priv->definition_src_location != NULL)
     {
-      if (gtk_text_iter_in_range (&iter,
-                                  &priv->definition_highlight_start,
-                                  &priv->definition_highlight_end))
-        {
-          IdeSourceLocation *src_location = priv->definition_src_location;
-          ide_source_location_ref (src_location);
+      GtkTextIter definition_highlight_start;
+      GtkTextIter definition_highlight_end;
 
-          ide_source_view_reset_definition_highlight (self);
+      gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                        &definition_highlight_start,
+                                        priv->definition_highlight_start_mark);
+
+      gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                        &definition_highlight_end,
+                                        priv->definition_highlight_end_mark);
 
-          g_signal_emit (self,
-                         signals [FOCUS_LOCATION],
-                         0,
-                         src_location);
+      if (gtk_text_iter_in_range (&iter, &definition_highlight_start, &definition_highlight_end))
+        {
+          g_autoptr(IdeSourceLocation) src_location = NULL;
 
-          ide_source_location_unref (src_location);
+          src_location = ide_source_location_ref (priv->definition_src_location);
+          ide_source_view_reset_definition_highlight (self);
+          g_signal_emit (self, signals [FOCUS_LOCATION], 0, src_location);
         }
 
       return TRUE;
@@ -2556,17 +2585,20 @@ ide_source_view_get_definition_on_mouse_over_cb (GObject      *object,
                                                  GAsyncResult *result,
                                                  gpointer      user_data)
 {
-  DefinitionHighlightData *data = (DefinitionHighlightData *) user_data;
-  IdeBuffer *buffer = (IdeBuffer *) object;
-  g_autoptr(IdeSourceView) self = data->self;
+  g_autoptr(DefinitionHighlightData) data = user_data;
+  IdeSourceViewPrivate *priv;
+  IdeBuffer *buffer = (IdeBuffer *)object;
   g_autoptr(IdeSymbol) symbol = NULL;
   g_autoptr(GError) error = NULL;
   IdeSourceLocation *srcloc;
 
   IDE_ENTRY;
 
+  g_assert (data != NULL);
   g_assert (IDE_IS_BUFFER (buffer));
-  g_assert (IDE_IS_SOURCE_VIEW (self));
+  g_assert (IDE_IS_SOURCE_VIEW (data->self));
+
+  priv = ide_source_view_get_instance_private (data->self);
 
   symbol = ide_buffer_get_symbol_at_location_finish (buffer, result, &error);
 
@@ -2580,32 +2612,35 @@ ide_source_view_get_definition_on_mouse_over_cb (GObject      *object,
 
   if (srcloc != NULL)
     {
-      IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+      GtkTextIter word_start;
+      GtkTextIter word_end;
 
       if (priv->definition_src_location &&
-          priv->definition_src_location != srcloc)
-        {
-          ide_source_location_unref (priv->definition_src_location);
-          priv->definition_src_location = NULL;
-        }
+          (priv->definition_src_location != srcloc))
+        g_clear_pointer (&priv->definition_src_location, ide_source_location_unref);
 
-      priv->definition_highlight_start = data->word_start;
-      priv->definition_highlight_end = data->word_end;
+      if (priv->definition_src_location == NULL)
+        priv->definition_src_location = ide_source_location_ref (srcloc);
 
-      priv->definition_src_location = srcloc;
-      ide_source_location_ref (priv->definition_src_location);
+      gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer),
+                                        &word_start, data->word_start_mark);
+      gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer),
+                                        &word_end, data->word_end_mark);
 
       gtk_text_buffer_apply_tag_by_name (GTK_TEXT_BUFFER (priv->buffer),
-                                         TAG_DEFINITION,
-                                         &priv->definition_highlight_start,
-                                         &priv->definition_highlight_end);
+                                         TAG_DEFINITION, &word_start, &word_end);
+
+      gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                 priv->definition_highlight_start_mark,
+                                 &word_start);
+      gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                 priv->definition_highlight_end_mark,
+                                 &word_end);
 
-      ide_source_view_set_cursor_from_name (self, "pointer");
+      ide_source_view_set_cursor_from_name (data->self, "pointer");
     }
   else
-    {
-      ide_source_view_reset_definition_highlight (self);
-    }
+    ide_source_view_reset_definition_highlight (data->self);
 
   IDE_EXIT;
 }
@@ -2657,17 +2692,30 @@ ide_source_view_real_motion_notify_event (GtkWidget      *widget,
 
   if (priv->definition_src_location)
     {
-      if (gtk_text_iter_equal (&priv->definition_highlight_start, &start_iter)
-          && gtk_text_iter_equal (&priv->definition_highlight_end, &end_iter))
+      GtkTextIter definition_highlight_start;
+      GtkTextIter definition_highlight_end;
+
+      gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                        &definition_highlight_start,
+                                        priv->definition_highlight_start_mark);
+
+      gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                        &definition_highlight_end,
+                                        priv->definition_highlight_end_mark);
+
+      if (gtk_text_iter_equal (&definition_highlight_start, &start_iter) &&
+          gtk_text_iter_equal (&definition_highlight_end, &end_iter))
         return ret;
 
       ide_source_view_reset_definition_highlight (self);
     }
 
-  data = g_slice_new (DefinitionHighlightData);
+  data = g_slice_new0 (DefinitionHighlightData);
   data->self = g_object_ref (self);
-  gtk_text_iter_assign (&data->word_start, &start_iter);
-  gtk_text_iter_assign (&data->word_end, &end_iter);
+  data->word_start_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                                       NULL, &start_iter, TRUE);
+  data->word_end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (priv->buffer),
+                                                     NULL, &end_iter, TRUE);
 
   ide_buffer_get_symbol_at_location_async (priv->buffer,
                                            &iter,


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