+static const char *
+gtk2_debool (const char *s)
+{
+ if (strcmp (s, "BOOL") == 0)
+ return "BOOLEAN";
+ else
+ return s;
+}
+
+static void
+print_signal_marsal_args_gtk2 (Method *m)
+{
+ if (strcmp (m->gtktypes->next->data, "NONE") != 0) {
+ GList *li;
+ int i;
+ for (i = 0, li = m->gtktypes->next;
+ li != NULL;
+ i++, li = li->next) {
+ char *get_func = g_strdup_printf
+ ("g_value_get_%s",
+ (char *)gtk2_debool (li->data));
+ g_strdown (get_func);
+ out_printf (out, ",\n\t\t(%s) "
+ "%s (param_values + %d)",
+ get_cast (li->data, FALSE),
+ get_func, i + 1);
+ g_free (get_func);
+ }
+ }
+ out_printf (out, ",\n\t\tdata2);\n");
+}
+
+static void
+add_marshal_gtk2 (Method *m, const char *mname)
+{
+ gboolean ret_none;
+ gboolean arglist_none;
+ const char *retcast;
+
+ ret_none = strcmp (m->gtktypes->data, "NONE") == 0;
+ arglist_none = strcmp (m->gtktypes->next->data, "NONE") == 0;
+
+ if (ret_none)
+ retcast = NULL;
+ else
+ retcast = get_cast (m->gtktypes->data, FALSE);
+
+ out_printf (out, "\nstatic void\n"
+ "___marshal_%s (GClosure *closure,\n"
+ "\tGValue *return_value,\n"
+ "\tguint n_param_values,\n"
+ "\tconst GValue *param_values,\n"
+ "\tgpointer invocation_hint,\n"
+ "\tgpointer marshal_data)\n"
+ "{\n", mname);
+
+ if ( ! ret_none)
+ out_printf (out, "\t%s v_return;\n", retcast);
+
+ out_printf (out, "\tregister ___%s callback;\n"
+ "\tregister GCClosure *cc = (GCClosure*) closure;\n"
+ "\tregister gpointer data1, data2;\n\n",
+ mname);
+
+ out_printf (out, "\tg_return_if_fail (n_param_values == %d);\n\n",
+ arglist_none ? 1 : g_list_length (m->gtktypes));
+
+ out_printf (out,
+ "\tif (G_CCLOSURE_SWAP_DATA (closure)) {\n"
+ "\t\tdata1 = closure->data;\n"
+ "\t\tdata2 = g_value_peek_pointer (param_values + 0);\n"
+ "\t} else {\n"
+ "\t\tdata1 = g_value_peek_pointer (param_values + 0);\n"
+ "\t\tdata2 = closure->data;\n"
+ "\t}\n\n");
+
+ out_printf (out, "\tcallback = (___%s) "
+ "(marshal_data != NULL ? marshal_data : cc->callback);"
+ "\n\n", mname);
+
+ if (ret_none) {
+ out_printf (out, "\tcallback ((%s *)data1", typebase);
+ } else {
+ out_printf (out, "\tv_return = callback ((%s *)data1",
+ typebase);
+ }
+
+ print_signal_marsal_args_gtk2 (m);
+
+ if ( ! ret_none) {
+ /* FIXME: This code is so fucking ugly it hurts */
+ gboolean take_ownership =
+ (strcmp ((char *)m->gtktypes->data, "STRING") == 0 ||
+ strcmp ((char *)m->gtktypes->data, "BOXED") == 0);
+ char *set_func = g_strdup_printf ("g_value_set_%s%s",
+ (char *)gtk2_debool (m->gtktypes->data),
+ take_ownership ?
+ "_take_ownership" : "");
+ g_strdown (set_func);
+
+ out_printf (out, "\n\t%s (return_value, v_return);\n",
+ set_func);
+
+ g_free (set_func);
+ }
+ out_printf (out, "}\n\n");
+}
+
+
+
+static void
+add_signal_prots(Method *m)
+{
+ GList *li;
+ static int sig = 1;
+ char *s;
+ Method *mm;
+
+ if(m->method != SIGNAL_LAST_METHOD &&
+ m->method != SIGNAL_FIRST_METHOD)
+ return;
+
+ if(!marsh)
+ marsh = g_hash_table_new(NULL, NULL);
+
+ if(strcmp(m->gtktypes->data, "NONE")==0 &&
+ strcmp(m->gtktypes->next->data, "NONE")==0)
+ return;
+
+ /* if we already did a signal prototype just use that */
+ mm = find_same_type_signal(m);
+ if(mm) {
+ s = g_hash_table_lookup(marsh, mm);
+ g_hash_table_insert(marsh, m, s);
+ return;
+ }
+
+ s = g_strdup_printf("Sig%d", sig++);
+
+ g_hash_table_insert(marsh, m, s);
+ eq_signal_methods = g_list_prepend(eq_signal_methods, m);
+
+ /* we know that we'll know all the gtktypes (so get_cast can't fail) */
+ out_printf(out, "\ntypedef %s (*___%s) (%s *, ",
+ get_cast(m->gtktypes->data, FALSE), s, typebase);
+
+ if (strcmp (m->gtktypes->next->data, "NONE") != 0) {
+ for (li = m->gtktypes->next; li != NULL; li = li->next)
+ out_printf(out, "%s, ", get_cast(li->data, FALSE));
+ }
+ out_printf (out, "gpointer);\n");
+
+
+ out_printf (out, "\n#ifdef G_OBJECT_CLASS\n");
+ add_marshal_gtk2 (m, s);
+ out_printf (out, "#else /* ! G_OBJECT_CLASS */\n");
+ add_marshal_gtk1 (m, s);
+ out_printf (out, "#endif /* G_OBJECT_CLASS */\n\n");
+}
+
+static void
+add_enums(Class *c)