On May 18, 2008, at 10:19 PM, Daniel Kasak wrote:

> I'm trying to fix the long-standing data-loss bug at:
> http://bugzilla.gnome.org/show_bug.cgi?id=156017
>
> The problem is that I'm only learning C. In fact this is my first C  
> code
> at all; I'm a Perl programmer.

We'll try to be gentle.

I can speak only about the crash and the code; as for whether this is  
the right way to solve the bug, i can't really say.


> Anyway, here is my attempt at fixing
> gtk_combo_box_entry_contents_changed in gtkcomboboxentry.c ( below ).
>
> It compiles,

 From what you pasted, it *had* to be spitting some warnings at you.   
Don't ignore the warnings.  ;-)


> but when I test typing into a GtkComboBoxEntry, I get:
>
> GLib-GObject-WARNING **: gvalue.c:89: cannot initialize GValue with  
> type
> `gchararray', the value has already been initialized as `(null)'
> at .posting/posting.pl line 364.
> GLib-GObject-CRITICAL **: g_value_set_string: assertion
> `G_VALUE_HOLDS_STRING (value)' failed at .posting/posting.pl line 364.
> Segmentation fault
>
> I'm testing with a Gtk2-Perl app.
>
> Can someone please tell me all the mistakes I've made? :)


The basic problem is that you are using GValue incorrectly.  You've  
declared on the stack a pointer to a GValue (this_str), but have not  
made it point to an actual GValue.  Then you pass the address of this  
pointer to gtk_tree_model_get_value(), which follows your value  
pointer into invalid memory,

The proper idiom for GValue is to declare the object on the stack,  
with an initializer that sets the type field to 0.

     GValue value = { 0, };

The comma followed by nothing means "we don't really care about the  
rest of the object.  (Some compilers, including gcc in stricter modes,  
will warn about missing initializers here, but gtk+ code uses this  
idiom pervasively.)

Then, call g_value_init() to set the value's type:

     g_value_init (&value, G_TYPE_STRING);

Notice we're passing the address of the stack object to the function,  
so the function modifies our object.

You pass the address of the value to gtk_tree_model_get_value(), who  
stores a copy of the string in our value object.  You can fetch that  
with g_value_get_string().  And, then, when you're finished with the  
value, you must call g_value_unset() to free the copy of the string.

Most of the rest of the function looked okay.

Compare this with your original:

static void
gtk_combo_box_entry_contents_changed (GtkEntry *entry,
                                       gpointer  user_data)
{
   GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);

   GtkTreeModel *model;
   GtkTreeIter iter;
   const gchar * str;
   gboolean have_iter;
   gboolean found_match = FALSE;
   gint text_column;

   g_signal_handlers_block_by_func (combo_box,
                                    gtk_combo_box_entry_active_changed,
                                    NULL);

   str = gtk_entry_get_text (entry);

   text_column = gtk_combo_box_entry_get_text_column  
(GTK_COMBO_BOX_ENTRY (combo_box));
   model = gtk_combo_box_get_model(combo_box);
   have_iter = gtk_tree_model_get_iter_first(model, &iter);

   while (have_iter)
     {
       GValue value = {0, };
       g_value_init (&value, G_TYPE_STRING);
       gtk_tree_model_get_value (model, &iter, text_column, &value);
       found_match = g_str_equal (str, g_value_get_string (&value));
       g_value_unset (&value);

       if (found_match)
         {
           gtk_combo_box_set_active_iter (combo_box, &iter);
           break;
         }

       have_iter = gtk_tree_model_iter_next (model, &iter);
     }

   if (!found_match)
     gtk_combo_box_set_active (combo_box, -1);

   g_signal_handlers_unblock_by_func (combo_box,
                                       
gtk_combo_box_entry_active_changed,
                                      NULL);
}


--
The Master in the art of living makes little distinction between his  
work and his play, his labor and his leisure, his mind and his body,  
his education and his recreation, his love and his religion. He hardly  
knows which is which. He simply pursues his vision of excellence in  
whatever he does, leaving others to decide whether he is working or  
playing. To him he is always doing both.

   -- Zen Philosophy



_______________________________________________
gtk-devel-list mailing list
gtk-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-devel-list

Reply via email to