* Copyright (C) 1999,2000 the Free Software Foundation.
* Copyright (C) 2000 Eazel, Inc.
* Copyright (C) 2001-2011 George (Jiri) Lebl
+ * Copyright © 2019-2020 Nick Bowler
*
* Author: George (Jiri) Lebl
*
out_printf (out, "}\n\n");
}
+static char *
+interface_type(const char *if_name)
+{
+ char *rawtype = remove_sep(if_name);
+ char *end = "", *typename;
+
+ if (!gtk3_ok) {
+ /*
+ * EEEK! evil, we should have some sort of option
+ * to force this for arbitrary interfaces, since
+ * some are Class and some are Iface. Glib is shite
+ * in consistency.
+ */
+
+ if (strcmp (rawtype, "GtkEditable") == 0
+ || strcmp (rawtype, "GTypePlugin") == 0)
+ {
+ end = "Class";
+ } else {
+ /* We'll assume Iface is the standard ending */
+ end = "Iface";
+ }
+ } else {
+ /* GTK3 doesn't need Iface end */
+ end = "Interface";
+ }
+
+ typename = g_strconcat(rawtype, end, (char *)NULL);
+ g_free(rawtype);
+
+ return typename;
+}
+
+static void
+define_parent_interface_refs(Class *c)
+{
+ GList *li;
+
+ if (!c->interfaces)
+ return;
+
+ out_printf(out, "\n/* parent class interface implementations */\n");
+ for (li = c->interfaces; li != NULL; li = li->next) {
+ char *name = replace_sep(li->data, '_');
+ char *type = interface_type(li->data);
+
+ out_printf (out, "static %s *%s_parent_iface;\n", type, name);
+
+ g_free(name);
+ g_free(type);
+ }
+}
+
static void
add_enums(Class *c)
{
"static guint object_signals[LAST_SIGNAL] = {0};\n\n");
out_printf(out, "/* pointer to the class of our parent */\n");
- out_printf(out, "static %sClass *parent_class = NULL;\n\n", ptypebase);
+ out_printf(out, "static %sClass *parent_class = NULL;\n", ptypebase);
+ define_parent_interface_refs(c);
+ out_printf(out, "\n");
}
static void
}
static void
-add_interface_inits (Class *c)
+add_interface_inits(Class *c)
{
GList *li;
out_printf(out, "\n");
for (li = c->interfaces; li != NULL; li = li->next) {
- const char *interface = li->data;
- const char *end;
- char *name = replace_sep (interface, '_');
- char *type = remove_sep (interface);
+ char *name = replace_sep(li->data, '_');
+ char *type = interface_type(li->data);
- if(!gtk3_ok)
- {
- /* EEEK! evil, we should have some sort of option
- * to force this for arbitrary interfaces, since
- * some are Class and some are Iface. Glib is shite
- * in consistency. */
-
- if (strcmp (type, "GtkEditable") == 0 ||
- strcmp (type, "GTypePlugin") == 0)
- end = "Class";
- else
- // We'll assume Iface is the standard ending
- end = "Iface";
- }
- else
- {
- /*GTK3 doesn't need Iface end*/
- end="Interface";
- }
-
- out_printf (out, "\nstatic void\n"
- "___%s_init (%s%s *iface)\n"
- "{\n",
- name, type, end);
+ out_printf(out, "static void\n"
+ "___%s_init (%s *iface)\n"
+ "{\n", name, type);
- add_interface_methods (c, interface);
+ add_interface_methods(c, li->data);
- out_printf (out, "}\n\n");
+ out_printf(out, "\t%s_parent_iface\n", name);
+ out_printf(out, for_cpp ? "\t\t= (%s *)" : "\t\t= ", type);
+ out_printf(out, "g_type_interface_peek_parent(iface);\n"
+ "}\n\n");
g_free (name);
g_free (type);
static void
add_dynamic_interfaces(void)
{
- GList *li;
- for (li = ((Class *)class)->interfaces;
- li != NULL;
- li = li ->next) {
- char *name = replace_sep (li->data, '_');
- char *type = make_pre_macro (li->data, "TYPE");
+ GList *li = ((Class *)class)->interfaces;
- out_printf(out,
- "\t\tg_type_module_add_interface(\n"
- "\t\t\ttype_module,\n"
- "\t\t\t%s_type_id,\n"
- "\t\t\t%s,\n"
- "\t\t\t&%s_info);\n",
- funcbase, type, name);
+ if (li) {
+ /*
+ * Hack to work around bug in g_type_module_add_interface,
+ * which will fail to add an interface to types that derive
+ * from something that also implements the same interface.
+ *
+ * The actual GType system does not have any such problem,
+ * and the GTypeModule implementation details relied upon
+ * here have not changed once since the feature was first
+ * implemented almost 20 years ago.
+ */
+ out_printf(out, "\t\tstruct _ModuleInterfaceInfo {\n"
+ "\t\t\tgboolean loaded;\n"
+ "\t\t\tGType instance_type;\n"
+ "\t\t\tGType interface_type;\n"
+ "\t\t\tGInterfaceInfo info;\n"
+ "\t\t} *modinfo;\n");
+ }
+
+ for (; li; li = li->next) {
+ char *name = replace_sep(li->data, '_');
+ char *type = make_pre_macro(li->data, "TYPE");
+
+ out_printf(out, "\n"
+ "\t\tmodinfo = g_malloc(sizeof *modinfo);\n"
+ "\t\tmodinfo->loaded = TRUE;\n"
+ "\t\tmodinfo->instance_type = %s_type_id;\n"
+ "\t\tmodinfo->interface_type = %s;\n"
+ "\t\tmodinfo->info = %s_info;\n"
+ "\t\tg_type_add_interface_dynamic\n"
+ "\t\t\t( modinfo->instance_type\n"
+ "\t\t\t, modinfo->interface_type\n"
+ "\t\t\t, G_TYPE_PLUGIN(type_module)\n"
+ "\t\t\t);\n"
+ "\t\ttype_module->interface_infos = g_slist_prepend\n"
+ "\t\t\t( type_module->interface_infos\n"
+ "\t\t\t, modinfo\n"
+ "\t\t\t);\n", funcbase, type, name);
g_free(type);
g_free(name);
return g_string_free (gs, FALSE);
}
+static gboolean method_is_void(Method *m)
+{
+ return !strcmp(m->mtype->name, "void") && !m->mtype->pointer;
+}
+
+static const char *method_err_retval(Method *m)
+{
+ if (method_is_void(m))
+ return "(void)0";
+ if (m->onerror)
+ return m->onerror;
+ return "0";
+}
+
+static void
+put_interface_parent_handler(Method *m)
+{
+ const char *errval = method_err_retval(m);
+ char *name = replace_sep(m->interface, '_');
+ char *args = get_arg_names_for_macro(m);
+
+ out_printf(out, "#define PARENT_HANDLER(%s) (%s_parent_iface \\\n"
+ "\t? %s_parent_iface->%s(%s) \\\n"
+ "\t: %s)\n", args, name, name, m->id, args, errval);
+
+ g_free(name);
+ g_free(args);
+}
+
static void
put_method(Method *m)
{
g_free(doc);
}
}
+
switch(m->method) {
case REGULAR_METHOD:
if(m->line_no > 0)
else /* PUBLIC, PROTECTED */
print_method(out, "", "\n", "", " ", "", "\n",
m, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE);
+
+ if (m->interface) {
+ out_addline_outfile(out);
+ put_interface_parent_handler(m);
+ }
+
print_method_body(m, TRUE, TRUE);
+
+ if (m->interface) {
+ out_printf(out, "#undef PARENT_HANDLER\n");
+ }
+
/* the outfile line was added above */
break;
case SIGNAL_FIRST_METHOD: