Re: Help newbie with gtk+ patch




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





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