+/* list of methods with different signal prototypes,
+ we check this list if we can use a signal prototype of a
+ previous signal method, there are only uniques here */
+static GList *eq_signal_methods = NULL;
+
+/* compare a list of strings */
+static gboolean
+is_list_equal(GList *a, GList *b)
+{
+ for(;a && b; a=a->next, b=b->next) {
+ if(strcmp(a->data, b->data)!=0) {
+ return FALSE;
+ }
+ }
+ /* the the lists were different length */
+ if(a || b)
+ return FALSE;
+ return TRUE;
+}
+
+static Method *
+find_same_type_signal(Method *m)
+{
+ GList *li;
+ for(li=eq_signal_methods;li;li=li->next) {
+ Method *mm = li->data;
+ if(is_list_equal(mm->gtktypes, m->gtktypes))
+ return mm;
+ }
+ return NULL;
+}
+
+static void
+print_signal_marsal_args_gtk1 (Method *m)
+{
+ if(strcmp(m->gtktypes->next->data, "NONE")!=0) {
+ GList *li;
+ int i;
+ for(i=0, li=m->gtktypes->next;li;
+ i++, li=g_list_next(li)) {
+ if(!for_cpp)
+ out_printf(out, ",\n\t\tGTK_VALUE_%s(args[%d])",
+ (char *)li->data, i);
+ else {
+ out_printf(out, ",\n\t\t(%s)"
+ "GTK_VALUE_%s(args[%d])",
+ get_cast(li->data, FALSE),
+ (char *)li->data, i);
+ }
+ }
+ }
+ out_printf(out, ",\n\t\tfunc_data);\n}\n\n");
+}
+
+static void
+add_marshal_gtk1 (Method *m, const char *mname)
+{
+ out_printf(out, "\nstatic void\n"
+ "___marshal_%s (GtkObject * object,\n"
+ "\tGtkSignalFunc func,\n"
+ "\tgpointer func_data,\n"
+ "\tGtkArg * args)\n"
+ "{\n", mname);
+
+ if(strcmp(m->gtktypes->data, "NONE")==0) {
+ out_printf(out, "\t___%s rfunc;\n\n"
+ "\trfunc = (___%s)func;\n\n"
+ "\t(*rfunc)((%s *)object", mname, mname, typebase);
+ } else {
+ const char *retcast = get_cast(m->gtktypes->data, FALSE);
+ gboolean is_none = (strcmp(m->gtktypes->next->data, "NONE")==0);
+ out_printf(out,
+ "\t___%s rfunc;\n\t"
+ "%s *retval;\n\n"
+ "\trfunc = (___%s)func;\n\n"
+ "\tretval = GTK_RETLOC_%s(args[%d]);\n\n"
+ "\t*retval = (*rfunc)((%s *)object",
+ mname, retcast, mname,
+ (char *)m->gtktypes->data,
+ g_list_length(m->gtktypes) - (is_none ? 2 : 1),
+ typebase);
+ }
+ print_signal_marsal_args_gtk1 (m);
+}
+
+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");
+}
+
+
+