[gtk+] Fixed crashes when GtkEntry's internal buffer is not available (bug 588395)



commit 51149246c04ba21010892c5e349564ef9893c926
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Thu Jul 16 23:19:03 2009 -0400

    Fixed crashes when GtkEntry's internal buffer is not available (bug 588395)
    
    To fix this I replaced the code that creates an internal buffer
    at init and construction time with code that creates a buffer
    at _get_buffer() time, this is the same as GtkTextView does and
    fixes the crashes for me.

 gtk/gtkentry.c |  136 +++++++++++++++++++++++---------------------------------
 1 files changed, 56 insertions(+), 80 deletions(-)
---
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index d82d687..c490f4d 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -237,9 +237,6 @@ typedef enum
  */
 static void   gtk_entry_editable_init        (GtkEditableClass     *iface);
 static void   gtk_entry_cell_editable_init   (GtkCellEditableIface *iface);
-static GObject* gtk_entry_constructor        (GType                  type,
-                                              guint                  n_props,
-                                              GObjectConstructParam *props);
 static void   gtk_entry_set_property         (GObject          *object,
                                               guint             prop_id,
                                               const GValue     *value,
@@ -524,6 +521,8 @@ static void         buffer_notify_max_length           (GtkEntryBuffer *buffer,
                                                         GtkEntry       *entry);
 static void         buffer_connect_signals             (GtkEntry       *entry);
 static void         buffer_disconnect_signals          (GtkEntry       *entry);
+static GtkEntryBuffer *get_buffer                      (GtkEntry       *entry);
+
 
 G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
@@ -565,7 +564,6 @@ gtk_entry_class_init (GtkEntryClass *class)
   widget_class = (GtkWidgetClass*) class;
   gtk_object_class = (GtkObjectClass *)class;
 
-  gobject_class->constructor = gtk_entry_constructor;
   gobject_class->dispose = gtk_entry_dispose;
   gobject_class->finalize = gtk_entry_finalize;
   gobject_class->set_property = gtk_entry_set_property;
@@ -2023,7 +2021,7 @@ gtk_entry_get_property (GObject         *object,
       break;
 
     case PROP_MAX_LENGTH:
-      g_value_set_int (value, gtk_entry_buffer_get_max_length (priv->buffer));
+      g_value_set_int (value, gtk_entry_buffer_get_max_length (get_buffer (entry)));
       break;
 
     case PROP_VISIBILITY:
@@ -2075,7 +2073,7 @@ gtk_entry_get_property (GObject         *object,
       break;
 
     case PROP_TEXT_LENGTH:
-      g_value_set_uint (value, gtk_entry_buffer_get_length (priv->buffer));
+      g_value_set_uint (value, gtk_entry_buffer_get_length (get_buffer (entry)));
       break;
 
     case PROP_INVISIBLE_CHAR_SET:
@@ -2253,34 +2251,10 @@ find_invisible_char (GtkWidget *widget)
   return '*';
 }
 
-static GObject*
-gtk_entry_constructor (GType                  type,
-                       guint                  n_props,
-                       GObjectConstructParam *props)
-{
-  GObject *obj = G_OBJECT_CLASS (gtk_entry_parent_class)->constructor (type, n_props, props);
-  GtkEntryPrivate *priv;
-  GtkEntryBuffer *buffer;
-
-  if (obj != NULL)
-    {
-      priv = GTK_ENTRY_GET_PRIVATE (obj);
-      if (!priv->buffer)
-        {
-          buffer = gtk_entry_buffer_new (NULL, 0);
-          gtk_entry_set_buffer (GTK_ENTRY (obj), buffer);
-          g_object_unref (buffer);
-        }
-    }
-
-  return obj;
-}
-
 static void
 gtk_entry_init (GtkEntry *entry)
 {
   GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
-  GtkEntryBuffer *buffer;
 
   GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
 
@@ -2320,13 +2294,6 @@ gtk_entry_init (GtkEntry *entry)
   g_signal_connect (entry->im_context, "delete-surrounding",
 		    G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
 
-  /* need to set a buffer here, so GtkEntry subclasses can do anything
-   * in their init() functions, just as it used to be before
-   * GtkEntryBuffer
-   */
-  buffer = gtk_entry_buffer_new (NULL, 0);
-  gtk_entry_set_buffer (entry, buffer);
-  g_object_unref (buffer);
 }
 
 static gint
@@ -2543,8 +2510,8 @@ gtk_entry_get_display_text (GtkEntry *entry,
   gint i;
 
   priv = GTK_ENTRY_GET_PRIVATE (entry);
-  text = gtk_entry_buffer_get_text (priv->buffer);
-  length = gtk_entry_buffer_get_length (priv->buffer);
+  text = gtk_entry_buffer_get_text (get_buffer (entry));
+  length = gtk_entry_buffer_get_length (get_buffer (entry));
 
   if (end_pos < 0)
     end_pos = length;
@@ -4001,7 +3968,7 @@ gtk_entry_motion_notify (GtkWidget      *widget,
       if (event->y < 0)
 	tmp_pos = 0;
       else if (event->y >= height)
-	tmp_pos = gtk_entry_buffer_get_length (priv->buffer);
+	tmp_pos = gtk_entry_buffer_get_length (get_buffer (entry));
       else
 	tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset);
       
@@ -4319,13 +4286,12 @@ gtk_entry_get_chars      (GtkEditable   *editable,
 			  gint           end_pos)
 {
   GtkEntry *entry = GTK_ENTRY (editable);
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
   const gchar *text;
   gint text_length;
   gint start_index, end_index;
 
-  text = gtk_entry_buffer_get_text (priv->buffer);
-  text_length = gtk_entry_buffer_get_length (priv->buffer);
+  text = gtk_entry_buffer_get_text (get_buffer (entry));
+  text_length = gtk_entry_buffer_get_length (get_buffer (entry));
 
   if (end_pos < 0)
     end_pos = text_length;
@@ -4344,11 +4310,10 @@ gtk_entry_real_set_position (GtkEditable *editable,
 			     gint         position)
 {
   GtkEntry *entry = GTK_ENTRY (editable);
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
 
   guint length;
 
-  length = gtk_entry_buffer_get_length (priv->buffer);
+  length = gtk_entry_buffer_get_length (get_buffer (entry));
   if (position < 0 || position > length)
     position = length;
 
@@ -4372,10 +4337,9 @@ gtk_entry_set_selection_bounds (GtkEditable *editable,
 				gint         end)
 {
   GtkEntry *entry = GTK_ENTRY (editable);
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
   guint length;
 
-  length = gtk_entry_buffer_get_length (priv->buffer);
+  length = gtk_entry_buffer_get_length (get_buffer (entry));
   if (start < 0)
     start = length;
   if (end < 0)
@@ -4704,23 +4668,21 @@ buffer_notify_max_length (GtkEntryBuffer *buffer,
 static void
 buffer_connect_signals (GtkEntry *entry)
 {
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
-  g_signal_connect (priv->buffer, "inserted-text", G_CALLBACK (buffer_inserted_text), entry);
-  g_signal_connect (priv->buffer, "deleted-text", G_CALLBACK (buffer_deleted_text), entry);
-  g_signal_connect (priv->buffer, "notify::text", G_CALLBACK (buffer_notify_text), entry);
-  g_signal_connect (priv->buffer, "notify::length", G_CALLBACK (buffer_notify_length), entry);
-  g_signal_connect (priv->buffer, "notify::max-length", G_CALLBACK (buffer_notify_max_length), entry);
+  g_signal_connect (get_buffer (entry), "inserted-text", G_CALLBACK (buffer_inserted_text), entry);
+  g_signal_connect (get_buffer (entry), "deleted-text", G_CALLBACK (buffer_deleted_text), entry);
+  g_signal_connect (get_buffer (entry), "notify::text", G_CALLBACK (buffer_notify_text), entry);
+  g_signal_connect (get_buffer (entry), "notify::length", G_CALLBACK (buffer_notify_length), entry);
+  g_signal_connect (get_buffer (entry), "notify::max-length", G_CALLBACK (buffer_notify_max_length), entry);
 }
 
 static void
 buffer_disconnect_signals (GtkEntry *entry)
 {
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
-  g_signal_handlers_disconnect_by_func (priv->buffer, buffer_inserted_text, entry);
-  g_signal_handlers_disconnect_by_func (priv->buffer, buffer_deleted_text, entry);
-  g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_text, entry);
-  g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_length, entry);
-  g_signal_handlers_disconnect_by_func (priv->buffer, buffer_notify_max_length, entry);
+  g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_inserted_text, entry);
+  g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_deleted_text, entry);
+  g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_text, entry);
+  g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_length, entry);
+  g_signal_handlers_disconnect_by_func (get_buffer (entry), buffer_notify_max_length, entry);
 }
 
 /* Compute the X position for an offset that corresponds to the "more important
@@ -4794,7 +4756,7 @@ gtk_entry_move_cursor (GtkEntry       *entry,
 	case GTK_MOVEMENT_PARAGRAPH_ENDS:
 	case GTK_MOVEMENT_BUFFER_ENDS:
 	  priv = GTK_ENTRY_GET_PRIVATE (entry);
-	  new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (priv->buffer);
+	  new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
 	  break;
 	case GTK_MOVEMENT_DISPLAY_LINES:
 	case GTK_MOVEMENT_PARAGRAPHS:
@@ -4852,7 +4814,7 @@ gtk_entry_move_cursor (GtkEntry       *entry,
 	case GTK_MOVEMENT_PARAGRAPH_ENDS:
 	case GTK_MOVEMENT_BUFFER_ENDS:
 	  priv = GTK_ENTRY_GET_PRIVATE (entry);
-	  new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (priv->buffer);
+	  new_pos = count < 0 ? 0 : gtk_entry_buffer_get_length (get_buffer (entry));
           if (entry->current_pos == new_pos)
             gtk_widget_error_bell (GTK_WIDGET (entry));
 	  break;
@@ -4894,10 +4856,9 @@ gtk_entry_delete_from_cursor (GtkEntry       *entry,
 			      gint            count)
 {
   GtkEditable *editable = GTK_EDITABLE (entry);
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
   gint start_pos = entry->current_pos;
   gint end_pos = entry->current_pos;
-  gint old_n_bytes = gtk_entry_buffer_get_bytes (priv->buffer);
+  gint old_n_bytes = gtk_entry_buffer_get_bytes (get_buffer (entry));
   
   _gtk_entry_reset_im_context (entry);
 
@@ -4963,7 +4924,7 @@ gtk_entry_delete_from_cursor (GtkEntry       *entry,
       break;
     }
 
-  if (gtk_entry_buffer_get_bytes (priv->buffer) == old_n_bytes)
+  if (gtk_entry_buffer_get_bytes (get_buffer (entry)) == old_n_bytes)
     gtk_widget_error_bell (GTK_WIDGET (entry));
 
   gtk_entry_pend_cursor_blink (entry);
@@ -5848,7 +5809,6 @@ gtk_entry_get_cursor_locations (GtkEntry   *entry,
 				gint       *weak_x)
 {
   DisplayMode mode = gtk_entry_get_display_mode (entry);
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
 
   /* Nothing to display at all, so no cursor is relevant */
   if (mode == DISPLAY_BLANK)
@@ -5880,7 +5840,7 @@ gtk_entry_get_cursor_locations (GtkEntry   *entry,
 		index += entry->preedit_length;
 	      else
 		{
-		  gint preedit_len_chars = g_utf8_strlen (text, -1) - gtk_entry_buffer_get_length (priv->buffer);
+		  gint preedit_len_chars = g_utf8_strlen (text, -1) - gtk_entry_buffer_get_length (get_buffer (entry));
 		  index += preedit_len_chars * g_unichar_to_utf8 (entry->invisible_char, NULL);
 		}
 	    }
@@ -6084,11 +6044,10 @@ gtk_entry_move_logically (GtkEntry *entry,
 			  gint      start,
 			  gint      count)
 {
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
   gint new_pos = start;
   guint length;
 
-  length = gtk_entry_buffer_get_length (priv->buffer);
+  length = gtk_entry_buffer_get_length (get_buffer (entry));
 
   /* Prevent any leak of information */
   if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
@@ -6131,11 +6090,10 @@ gtk_entry_move_forward_word (GtkEntry *entry,
 			     gint      start,
                              gboolean  allow_whitespace)
 {
-  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
   gint new_pos = start;
   guint length;
 
-  length = gtk_entry_buffer_get_length (priv->buffer);
+  length = gtk_entry_buffer_get_length (get_buffer (entry));
 
   /* Prevent any leak of information */
   if (gtk_entry_get_display_mode (entry) != DISPLAY_NORMAL)
@@ -6279,7 +6237,7 @@ paste_received (GtkClipboard *clipboard,
         length = truncate_multiline (text);
 
       /* only complete if the selection is at the end */
-      popup_completion = (gtk_entry_buffer_get_length (priv->buffer) ==
+      popup_completion = (gtk_entry_buffer_get_length (get_buffer (entry)) ==
                           MAX (entry->current_pos, entry->selection_bound));
 
       if (completion)
@@ -6609,11 +6567,28 @@ gtk_entry_new_with_max_length (gint max)
   max = CLAMP (max, 0, GTK_ENTRY_BUFFER_MAX_SIZE);
 
   entry = g_object_new (GTK_TYPE_ENTRY, NULL);
-  gtk_entry_buffer_set_max_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer, max);
+  gtk_entry_buffer_set_max_length (get_buffer (entry), max);
 
   return GTK_WIDGET (entry);
 }
 
+
+static GtkEntryBuffer*
+get_buffer (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  if (priv->buffer == NULL)
+    {
+      GtkEntryBuffer *buffer;
+      buffer = gtk_entry_buffer_new (NULL, 0);
+      gtk_entry_set_buffer (entry, buffer);
+      g_object_unref (buffer);
+    }
+
+  return priv->buffer;
+}
+
 /**
  * gtk_entry_get_buffer:
  * @entry: a #GtkEntry
@@ -6629,7 +6604,8 @@ GtkEntryBuffer*
 gtk_entry_get_buffer (GtkEntry *entry)
 {
   g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
-  return GTK_ENTRY_GET_PRIVATE (entry)->buffer;
+
+  return get_buffer (entry);
 }
 
 /**
@@ -6719,7 +6695,7 @@ gtk_entry_set_text (GtkEntry    *entry,
   /* Actually setting the text will affect the cursor and selection;
    * if the contents don't actually change, this will look odd to the user.
    */
-  if (strcmp (gtk_entry_buffer_get_text (priv->buffer), text) == 0)
+  if (strcmp (gtk_entry_buffer_get_text (get_buffer (entry)), text) == 0)
     return;
 
   completion = gtk_entry_get_completion (entry);
@@ -6758,7 +6734,7 @@ gtk_entry_append_text (GtkEntry *entry,
   g_return_if_fail (text != NULL);
   priv = GTK_ENTRY_GET_PRIVATE (entry);
 
-  tmp_pos = gtk_entry_buffer_get_length (priv->buffer);
+  tmp_pos = gtk_entry_buffer_get_length (get_buffer (entry));
   gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &tmp_pos);
 }
 
@@ -7030,7 +7006,7 @@ G_CONST_RETURN gchar*
 gtk_entry_get_text (GtkEntry *entry)
 {
   g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
-  return gtk_entry_buffer_get_text (GTK_ENTRY_GET_PRIVATE (entry)->buffer);
+  return gtk_entry_buffer_get_text (get_buffer (entry));
 }
 
 /**
@@ -7077,7 +7053,7 @@ gtk_entry_set_max_length (GtkEntry     *entry,
                           gint          max)
 {
   g_return_if_fail (GTK_IS_ENTRY (entry));
-  gtk_entry_buffer_set_max_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer, max);
+  gtk_entry_buffer_set_max_length (get_buffer (entry), max);
 }
 
 /**
@@ -7100,7 +7076,7 @@ gint
 gtk_entry_get_max_length (GtkEntry *entry)
 {
   g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
-  return gtk_entry_buffer_get_max_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer);
+  return gtk_entry_buffer_get_max_length (get_buffer (entry));
 }
 
 /**
@@ -7125,7 +7101,7 @@ guint16
 gtk_entry_get_text_length (GtkEntry *entry)
 {
   g_return_val_if_fail (GTK_IS_ENTRY (entry), 0);
-  return gtk_entry_buffer_get_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer);
+  return gtk_entry_buffer_get_length (get_buffer (entry));
 }
 
 /**
@@ -9524,7 +9500,7 @@ accept_completion_callback (GtkEntry *entry)
 
   if (completion->priv->has_completion)
     gtk_editable_set_position (GTK_EDITABLE (entry),
-			       gtk_entry_buffer_get_length (GTK_ENTRY_GET_PRIVATE (entry)->buffer));
+			       gtk_entry_buffer_get_length (get_buffer (entry)));
 
   return FALSE;
 }



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