Bonobo Unique Application v4.1



  Hi Michael, I just fixed the CORBA_any<->GValue conversion problems,
and got argc/argv forwarding working.

  Changes:

o Lots of bugs have been fixed (I probably shouldn't had sent the last
patch);

o There's a hook mechanism that calls user functions when
BonoboApplication instances are created, for plugging library-specific
standard messages;

o Multiple entities can connect to the 'message' signal, and emission
stops when the first returns non-NULL GValue, so that one signal handler
can ignore messages it is not interested without affecting the others.

o There's a new 'new-instance' standard message and signal, which allows
forwarding of argc/argv.

So now I'm going to look into bonobo closures, to see what I can come up
with.


-- 
Gustavo J. A. M. Carneiro
<gjc inescporto pt> <gustavo users sourceforge net>
? autom4te.cache
? stamp-h1
? activation-server/test-performance
? bonobo-activation/bonobo-activation-2.0.pc
? tests/test-uniqapp
Index: libbonobo.h
===================================================================
RCS file: /cvs/gnome/libbonobo/libbonobo.h,v
retrieving revision 1.60
diff -u -p -u -p -r1.60 libbonobo.h
--- libbonobo.h	19 Nov 2001 00:13:33 -0000	1.60
+++ libbonobo.h	30 Apr 2003 11:23:34 -0000
@@ -44,6 +44,8 @@ G_BEGIN_DECLS
 
 #include <bonobo/bonobo-storage.h>
 #include <bonobo/bonobo-storage-memory.h>
+#include <bonobo/bonobo-application.h>
+#include <bonobo/bonobo-app-client.h>
 
 G_END_DECLS
 
Index: bonobo/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/Makefile.am,v
retrieving revision 1.72
diff -u -p -u -p -r1.72 Makefile.am
--- bonobo/Makefile.am	16 Apr 2003 19:10:51 -0000	1.72
+++ bonobo/Makefile.am	30 Apr 2003 11:23:34 -0000
@@ -39,6 +39,7 @@ idls =							\
 	$(top_srcdir)/idl/Bonobo_UI.idl			\
 	$(top_srcdir)/idl/Bonobo_Zoomable.idl		\
 	$(top_srcdir)/idl/Bonobo_Exception.idl		\
+	$(top_srcdir)/idl/Bonobo_Application.idl	\
 	$(top_srcdir)/idl/Bonobo_Clipboard.idl
 
 idl_flags = -I$(top_srcdir)/idl -D__Bonobo_COMPILATION
@@ -88,6 +89,8 @@ libbonoboinclude_HEADERS =		\
 	bonobo-storage-memory.h		\
 	bonobo-xobject.h		\
 	bonobo-i18n.h			\
+	bonobo-application.h		\
+	bonobo-app-client.h		\
 	bonobo-types.h
 
 noinst_HEADERS =			\
@@ -125,6 +128,8 @@ libbonobo_src =				\
 	bonobo-stream-memory.c		\
 	bonobo-storage-memory.c		\
 	bonobo-running-context.c	\
+	bonobo-application.c		\
+	bonobo-app-client.c		\
 	bonobo-types.c			\
 	bonobo-debug.c			\
 	bonobo-debug.h
Index: bonobo/bonobo-app-client.c
===================================================================
RCS file: bonobo/bonobo-app-client.c
diff -N bonobo/bonobo-app-client.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-app-client.c	30 Apr 2003 11:23:36 -0000
@@ -0,0 +1,316 @@
+  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#include <string.h>
+#include <gobject/gvaluecollector.h>
+#include "bonobo-app-client.h"
+#include "bonobo-arg.h"
+#include "bonobo-exception.h"
+#include "bonobo-types.h"
+
+
+static void bonobo_app_client_class_init    (BonoboAppClientClass *klass);
+static void bonobo_app_client_init          (BonoboAppClient      *app_client);
+static void bonobo_app_client_free_msgdescs (BonoboAppClient      *self);
+
+static gpointer parent_class;
+
+GType
+bonobo_app_client_get_type (void)
+{
+	static GType app_client_type = 0;
+
+	if (!app_client_type)
+	{
+		static const GTypeInfo app_client_info =
+			{
+				sizeof (BonoboAppClientClass),
+				NULL,		/* base_init */
+				NULL,		/* base_finalize */
+				(GClassInitFunc) bonobo_app_client_class_init,
+				NULL,		/* class_finalize */
+				NULL,		/* class_data */
+				sizeof (BonoboAppClient),
+				0,		/* n_preallocs */
+				(GInstanceInitFunc) bonobo_app_client_init,
+			};
+		
+		app_client_type = g_type_register_static
+			(G_TYPE_OBJECT, "BonoboAppClient", &app_client_info, 0);
+	}
+
+	return app_client_type;
+}
+
+
+static void
+bonobo_app_client_finalize (GObject *object)
+{
+	BonoboAppClient *self = BONOBO_APP_CLIENT (object);
+
+	if (self->msgdescs)
+		bonobo_app_client_free_msgdescs (self);
+
+	if (G_OBJECT_CLASS(parent_class)->finalize)
+		G_OBJECT_CLASS(parent_class)->finalize (object);
+}
+
+
+static void
+bonobo_app_client_class_init (BonoboAppClientClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+	parent_class = g_type_class_peek_parent (class);
+	object_class->finalize = bonobo_app_client_finalize;
+}
+
+
+static void
+bonobo_app_client_init (BonoboAppClient *app_client)
+{
+
+}
+
+
+/**
+ * bonobo_app_client_new:
+
+ * @app_server: object reference to a Bonobo::Application; this
+ * function takes ownership of this reference (use
+ * bonobo_object_dup_ref if you want to keep your own reference.)
+ * 
+ * Create an application client object connected to the remote (or
+ * local) Bonobo::Application object.
+ *
+ * Warning: Applications should not use this function. See
+ * bonobo_register_unique_application().
+ * 
+ * Return value: a #BonoboAppClient object.
+ **/
+BonoboAppClient *
+bonobo_app_client_new (Bonobo_Application app_server)
+{
+	BonoboAppClient *app_client;
+
+	app_client = g_object_new (BONOBO_TYPE_APP_CLIENT, NULL);
+	app_client->app_server = app_server;
+	return app_client;
+}
+
+
+GValue *
+bonobo_app_client_msg_send_valist (BonoboAppClient *app_client,
+				   const char      *message,
+				   va_list          var_args)
+{
+	CORBA_any                  *ret;
+	Bonobo_Application_ArgList *args;
+	GValue                     *value, *rv;
+	GPtrArray                  *argv;
+	GType                       type;
+	gchar                      *err;
+	CORBA_Environment           ev;
+	int                         i;
+
+	g_return_val_if_fail (app_client, NULL);
+	g_return_val_if_fail (BONOBO_IS_APP_CLIENT (app_client), NULL);
+
+	argv = g_ptr_array_new ();
+	while ((type = va_arg (var_args, GType)) != G_TYPE_NONE)
+	{
+		value = g_new0 (GValue, 1);
+		g_value_init (value, type);
+		G_VALUE_COLLECT(value, var_args, 0, &err);
+		if (err) g_error("error collecting value: %s", err);
+		g_ptr_array_add (argv, value);
+	}
+	args = Bonobo_Application_ArgList__alloc ();
+	args->_length = argv->len;
+	args->_buffer = Bonobo_Application_ArgList_allocbuf (argv->len);
+	for (i = 0; i < argv->len; ++i) {
+		value = g_ptr_array_index (argv, i);
+		bonobo_arg_from_gvalue (&args->_buffer[i], value);
+		g_value_unset (value);
+		g_free (value);
+	}
+	CORBA_sequence_set_release (args, CORBA_TRUE);
+	g_ptr_array_free (argv, TRUE);
+
+	CORBA_exception_init (&ev);
+	ret = Bonobo_Application_message (app_client->app_server, message, args, &ev);
+	CORBA_free (args);
+	if (ev._major != CORBA_NO_EXCEPTION) {
+		g_warning ("error while sending message to application server: %s",
+			   bonobo_exception_get_text (&ev));
+		CORBA_exception_free (&ev);
+		return NULL;
+	}
+	CORBA_exception_free (&ev);
+	
+	if (ret->_type != TC_void) {
+		rv = g_new0 (GValue, 1);
+		bonobo_arg_to_gvalue (rv, ret);
+	} else
+		rv = NULL;
+	CORBA_free (ret);
+	return rv;
+}
+
+
+/**
+ * bonobo_app_client_msg_send:
+ * @message: message name
+ * 
+ * Send a message to the application server. Takes a variable length
+ * argument list of GType, value pairs, terminated with
+ * G_TYPE_NONE. Values are direct C values, not GValues! Example:
+ * <informalexample><programlisting>
+ * GValue *retval;
+ * retval = bonobo_app_client_msg_send (app_client, "openURL",
+ *                                      G_TYPE_STRING, "http://www.gnome.org";,
+ *                                      G_TYPE_BOOLEAN, TRUE,
+ *                                      G_TYPE_NONE);
+ * </programlisting></informalexample>
+ * 
+ * Return value: a GValue containing the value returned from the
+ * aplication server.
+ **/
+GValue *
+bonobo_app_client_msg_send (BonoboAppClient *app_client,
+			    const char      *message,
+			    ...)
+{
+	GValue  *rv;
+	va_list  var_args;
+	
+	va_start (var_args, message);
+	rv = bonobo_app_client_msg_send_valist (app_client, message, var_args);
+	va_end (var_args);
+	return rv;
+}
+
+
+static __inline__ GType
+_typecode_to_gtype (CORBA_TypeCode tc)
+{
+	static GHashTable *hash = NULL;
+
+	if (!hash) {
+		hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+#define mapping(corba_type, gtype)\
+		g_hash_table_insert (hash, tc, GUINT_TO_POINTER(gtype));
+		
+		mapping(G_TYPE_NONE,    TC_void);
+		mapping(G_TYPE_BOOLEAN, TC_CORBA_boolean);
+		mapping(G_TYPE_INT,     TC_CORBA_long);
+		mapping(G_TYPE_UINT,    TC_CORBA_unsigned_long);
+		mapping(G_TYPE_LONG,    TC_CORBA_long);
+		mapping(G_TYPE_ULONG,   TC_CORBA_unsigned_long);
+		mapping(G_TYPE_FLOAT,   TC_CORBA_float);
+		mapping(G_TYPE_DOUBLE,  TC_CORBA_double);
+		mapping(G_TYPE_STRING,  TC_CORBA_string);
+
+		mapping(BONOBO_TYPE_CORBA_ANY,  TC_CORBA_any);
+#undef mapping
+	}
+	return GPOINTER_TO_UINT(g_hash_table_lookup (hash, tc));
+}
+
+static void
+bonobo_app_client_free_msgdescs (BonoboAppClient *self)
+{
+	int i;
+	
+	for (i = 0; self->msgdescs[i].name; ++i) {
+		g_free (self->msgdescs[i].name);
+		g_free (self->msgdescs[i].types);
+	}
+	g_free (self->msgdescs);
+	self->msgdescs = NULL;
+}
+
+static void
+bonobo_app_client_get_msgdescs (BonoboAppClient *self)
+{
+	Bonobo_Application_MessageList  *msglist;
+	CORBA_Environment                ev;
+	int                              i, j;
+
+	g_return_if_fail(!self->msgdescs);
+	CORBA_exception_init (&ev);
+	msglist = Bonobo_Application_listMessages (self->app_server, &ev);
+	if (ev._major != CORBA_NO_EXCEPTION) {
+		g_warning ("Bonobo::Application::listMessages: %s",
+			   bonobo_exception_get_text (&ev));
+		CORBA_exception_free (&ev);
+		return;
+	}
+	CORBA_exception_free (&ev);
+	g_return_if_fail (msglist);
+	self->msgdescs = g_new (BonoboAppClientMsgDesc, msglist->_length + 1);
+	for (i = 0; i < msglist->_length; ++i) {
+		self->msgdescs[i].name = g_strdup (msglist->_buffer[i].name);
+		self->msgdescs[i].return_type =
+			_typecode_to_gtype (msglist->_buffer[i].return_type);
+		self->msgdescs[i].types = g_new (GType, msglist->_buffer[i].types._length + 1);
+		for (j = 0; j < msglist->_length; ++j)
+			self->msgdescs[i].types[j] =
+				_typecode_to_gtype (msglist->_buffer[i].types._buffer[j]);
+		self->msgdescs[i].types[j] = G_TYPE_NONE;
+	}
+	self->msgdescs[i].name = NULL;
+	self->msgdescs[i].return_type = G_TYPE_NONE;
+	self->msgdescs[i].types = NULL;
+	CORBA_free (msglist);
+}
+
+
+/**
+ * bonobo_app_client_msg_list:
+ * 
+ * Obtain a list of messages supported by the application server.
+ * 
+ * Return value: a NULL terminated vector of strings; use g_strfreev()
+ * to free it.
+ **/
+BonoboAppClientMsgDesc const *
+bonobo_app_client_msg_list (BonoboAppClient *app_client)
+{
+
+	g_return_val_if_fail (BONOBO_IS_APP_CLIENT (app_client), NULL);
+
+	if (!app_client->msgdescs)
+		bonobo_app_client_get_msgdescs (app_client);
+	return app_client->msgdescs;
+}
+
+
+gint
+bonobo_app_client_new_instance (BonoboAppClient *app_client,
+				int              argc,
+				char            *argv[])
+{
+	CORBA_any                    any;
+	CORBA_sequence_CORBA_string *corba_argv;
+	int                          i;
+	GValue                      *rv;
+
+	corba_argv = CORBA_sequence_CORBA_string__alloc();
+	corba_argv->_buffer  = CORBA_sequence_CORBA_string_allocbuf (argc);
+	corba_argv->_length  = argc;
+	corba_argv->_maximum = argc;
+	for (i = 0; i < argc; ++i)
+		corba_argv->_buffer[i] = CORBA_string_dup (argv[i]);
+
+	any._type    = TC_CORBA_sequence_CORBA_string;
+	any._value   = corba_argv;
+	any._release = CORBA_TRUE;
+
+	rv = bonobo_app_client_msg_send (app_client, "new-instance",
+					 BONOBO_TYPE_CORBA_ANY, &any,
+					 G_TYPE_NONE);
+
+	CORBA_free (corba_argv);
+	return g_value_get_int (rv);
+}
+
+
Index: bonobo/bonobo-app-client.h
===================================================================
RCS file: bonobo/bonobo-app-client.h
diff -N bonobo/bonobo-app-client.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-app-client.h	30 Apr 2003 11:23:36 -0000
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef __BONOBO_APP_CLIENT_H__
+#define __BONOBO_APP_CLIENT_H__
+
+#include <glib-object.h>
+#include <bonobo/Bonobo.h>
+
+G_BEGIN_DECLS
+
+#define BONOBO_TYPE_APP_CLIENT            (bonobo_app_client_get_type ())
+#define BONOBO_APP_CLIENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+                                           BONOBO_TYPE_APP_CLIENT, BonoboAppClient))
+#define BONOBO_APP_CLIENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),\
+                                           BONOBO_TYPE_APP_CLIENT, BonoboAppClientClass))
+#define BONOBO_IS_APP_CLIENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+                                           BONOBO_TYPE_APP_CLIENT))
+#define BONOBO_IS_APP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+                                           BONOBO_TYPE_APP_CLIENT))
+#define BONOBO_APP_CLIENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+                                           BONOBO_TYPE_APP_CLIENT, BonoboAppClientClass))
+
+typedef struct _BonoboAppClient	       BonoboAppClient;
+typedef struct _BonoboAppClientClass   BonoboAppClientClass;
+typedef struct _BonoboAppClientMsgDesc BonoboAppClientMsgDesc;
+
+
+struct _BonoboAppClientMsgDesc {
+	gchar *name;
+	GType  return_type;
+	GType *types;		/* G_TYPE_NONE-terminated array */
+};
+
+
+struct _BonoboAppClient
+{
+	GObject                 parent_instance;
+	  /*< private >*/
+	Bonobo_Application      app_server;
+	BonoboAppClientMsgDesc *msgdescs;
+};
+
+struct _BonoboAppClientClass
+{
+	GObjectClass parent_class;
+  
+};
+
+
+GType	         bonobo_app_client_get_type        (void) G_GNUC_CONST;
+BonoboAppClient* bonobo_app_client_new             (Bonobo_Application  app_server);
+GValue*          bonobo_app_client_msg_send_valist (BonoboAppClient    *app_client,
+						    const char         *message,
+						    va_list             var_args);
+GValue*          bonobo_app_client_msg_send        (BonoboAppClient    *app_client,
+						    const char         *message,
+						    ...);
+gint             bonobo_app_client_new_instance    (BonoboAppClient    *app_client,
+						    int                 argc,
+						    char               *argv[]);
+BonoboAppClientMsgDesc const *
+                 bonobo_app_client_msg_list        (BonoboAppClient    *app_client);
+
+G_END_DECLS
+
+#endif /* __BONOBO_APP_CLIENT_H__ */
Index: bonobo/bonobo-application.c
===================================================================
RCS file: bonobo/bonobo-application.c
diff -N bonobo/bonobo-application.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-application.c	30 Apr 2003 11:23:37 -0000
@@ -0,0 +1,418 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#define ORBIT2_INTERNAL_API
+#include "config.h"
+#include "bonobo-application.h"
+#include "bonobo-app-client.h"
+#include <bonobo-exception.h>
+#include "bonobo-marshal.h"
+#include "bonobo-arg.h"
+#include "bonobo-main.h"
+#include "bonobo-types.h"
+#include <string.h>
+
+
+enum SIGNALS {
+	MESSAGE,
+	NEW_INSTANCE,
+	LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+typedef struct {
+	BonoboAppHookFunc func;
+	gpointer          data;
+} BonoboAppHook;
+
+static GArray *bonobo_application_hooks = NULL;
+
+/*
+ * A pointer to our parent object class
+ */
+static GObjectClass *bonobo_application_parent_class;
+
+
+
+static void bonobo_application_invoke_hooks (BonoboApplication *app);
+
+
+static gboolean
+_bonobo_application_message_accumulator(GSignalInvocationHint *ihint, 
+					GValue                *return_accu, 
+					const GValue          *handler_return, 
+					gpointer               dummy)
+{
+	gboolean null_gvalue;
+
+	  /* There is no good way to find out if a GValue contains a
+	   * NULL GValue as value, if you understand what I'm saying :) */
+	null_gvalue = (G_VALUE_HOLDS (handler_return, G_TYPE_VALUE) &&
+		       (g_value_peek_pointer (handler_return) == NULL));
+
+	if (!null_gvalue) {
+		g_value_copy (handler_return, return_accu);
+		return FALSE;	/* stop emission */
+	}
+	return TRUE;		/* continue emission */
+}
+
+
+
+static void
+bonobo_application_object_finalize (GObject *object)
+{
+	BonoboApplication *self = BONOBO_APPLICATION (object);
+
+	if (self->message_list) {
+		g_slist_foreach (self->message_list, (GFunc) CORBA_free, NULL);
+		g_slist_free (self->message_list);
+		self->message_list = NULL;
+	}
+
+	if (self->name) {
+		g_free (self->name);
+		self->name = NULL;
+	}
+
+	bonobo_application_parent_class->finalize (object);
+}
+
+
+static CORBA_any *
+impl_Bonobo_Application_message (PortableServer_Servant            servant,
+				 const CORBA_char                 *msg,
+				 const Bonobo_Application_ArgList *args,
+				 CORBA_Environment                *ev)
+{
+	BonoboApplication  *app = BONOBO_APPLICATION (bonobo_object (servant));
+	GValue             *signal_return = NULL;
+	GValueArray        *signal_args;
+	int                 i;
+	CORBA_any          *rv;
+	GValue              value;
+
+	signal_args = g_value_array_new (args->_length);
+	memset (&value, 0, sizeof (value));
+	for (i = 0; i < args->_length; ++i) {
+		bonobo_arg_to_gvalue (&value, &args->_buffer [i]);
+		g_value_array_append (signal_args, &value);
+		g_value_unset (&value);
+	}
+
+	g_signal_emit (app, signals [MESSAGE], 0,
+		       msg, signal_args, &signal_return);
+
+	g_value_array_free (signal_args);
+	rv = CORBA_any__alloc ();
+	if (signal_return) {
+		bonobo_arg_from_gvalue (rv, signal_return);
+		g_value_unset (signal_return);
+		g_free (signal_return);
+	} else
+		rv->_type = TC_void;
+
+	return rv;
+}
+
+gint bonobo_application_new_instance (BonoboApplication *app,
+				      gint               argc,
+				      gchar             *argv[])
+{
+	gint rv;
+	g_signal_emit (app, signals [NEW_INSTANCE], 0,
+		       argc, argv, &rv);
+	return rv;
+}
+
+    /* Handle the "new-instance" standard message */
+static GValue *
+bonobo_application_real_message (BonoboApplication *app,
+				 const char        *name,
+				 GValueArray       *args)
+{
+	CORBA_any                    *any;
+	GValue                       *retval;
+	int                           rv;
+	CORBA_sequence_CORBA_string  *argv;
+
+	if (strcmp (name, "new-instance") != 0)
+		return NULL;
+	g_return_val_if_fail (args->n_values == 1, NULL);
+	g_return_val_if_fail (BONOBO_VALUE_HOLDS_CORBA_ANY 
+			      (g_value_array_get_nth (args, 0)), NULL);
+	any = bonobo_value_get_corba_any (g_value_array_get_nth (args, 0));
+	if (!CORBA_TypeCode_equal (any->_type,
+				   TC_CORBA_sequence_CORBA_string, NULL)) {
+		CORBA_free (any);
+		g_return_val_if_reached (NULL);
+	}
+	argv = (CORBA_sequence_CORBA_string *) any->_value;
+	rv = bonobo_application_new_instance (app, argv->_length,
+					      argv->_buffer);
+	CORBA_free (any);
+	retval =  g_new0 (GValue, 1);
+	g_value_init (retval, G_TYPE_INT);
+	g_value_set_int (retval, rv);
+	return retval;
+}
+
+
+static __inline__ void
+message_desc_copy(Bonobo_Application_MessageDesc *dest,
+		  Bonobo_Application_MessageDesc *src)
+{
+	dest->name           = CORBA_string_dup (src->name);
+	dest->return_type    = src->return_type;
+	dest->types._buffer  = src->types._buffer;
+	dest->types._length  = src->types._length;
+	dest->types._maximum = src->types._maximum;
+	dest->types._release = CORBA_FALSE;
+}
+
+
+static Bonobo_Application_MessageList *
+impl_Bonobo_Application_listMessages (PortableServer_Servant  servant,
+				      CORBA_Environment      *ev)
+{
+	BonoboApplication *app = BONOBO_APPLICATION (bonobo_object (servant));
+	int                nmessages;
+	GSList            *l;
+	int                i;
+	Bonobo_Application_MessageList *msglist;
+
+	nmessages = g_slist_length (app->message_list);
+	msglist = Bonobo_Application_MessageList__alloc ();
+	msglist->_length = msglist->_maximum = nmessages;
+	msglist->_buffer = Bonobo_Application_MessageList_allocbuf (nmessages);
+	for (l = app->message_list, i = 0; l; l = l->next, ++i)
+		message_desc_copy(&msglist->_buffer[i],
+				  (Bonobo_Application_MessageDesc *) l->data);
+	CORBA_sequence_set_release (msglist, CORBA_TRUE);
+	return msglist;
+}
+
+
+static void
+bonobo_application_class_init (BonoboApplicationClass *klass)
+{
+	GObjectClass *object_class = (GObjectClass *) klass;
+	POA_Bonobo_Application__epv *epv = &klass->epv;
+
+	bonobo_application_parent_class = g_type_class_peek_parent (klass);
+
+	object_class->finalize = bonobo_application_object_finalize;
+
+
+	signals [MESSAGE] = g_signal_new (
+		"message", BONOBO_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (BonoboApplicationClass, message),
+		_bonobo_application_message_accumulator, NULL,	/* accumulator and accumulator data */
+		bonobo_marshal_BOXED__STRING_BOXED,
+		G_TYPE_VALUE, 2, /* return_type, nparams */
+		G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
+		G_TYPE_VALUE_ARRAY);
+
+	signals [NEW_INSTANCE] = g_signal_new (
+		"new-instance", BONOBO_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (BonoboApplicationClass, new_instance),
+		NULL, NULL,	/* accumulator and accumulator data */
+		bonobo_marshal_INT__INT_POINTER,
+		G_TYPE_INT, 2, /* return_type, nparams */
+		G_TYPE_INT, G_TYPE_POINTER);
+
+	klass->message = bonobo_application_real_message;
+
+	epv->message      = impl_Bonobo_Application_message;
+	epv->listMessages = impl_Bonobo_Application_listMessages;
+}
+
+static void
+bonobo_application_init (BonoboApplication *bonobo_application)
+{
+	  /* ... */
+}
+
+BONOBO_TYPE_FUNC_FULL (BonoboApplication,
+		       Bonobo_Application,
+		       BONOBO_TYPE_OBJECT,
+		       bonobo_application);
+
+
+BonoboApplication *
+bonobo_application_new (const char *name)
+{
+	GObject           *obj;
+	BonoboApplication *app;
+
+	obj = g_object_new (BONOBO_TYPE_APPLICATION,
+			    "poa", bonobo_poa_get_threaded (BONOBO_POA_ALL_AT_IDLE),
+			    NULL);
+	app = (BonoboApplication *) obj;
+	app->name = g_strdup (name);
+	bonobo_application_invoke_hooks (app);
+	return app;
+}
+
+static __inline__ CORBA_TypeCode
+_gtype_to_typecode (GType gtype)
+{
+	static GHashTable *hash = NULL;
+
+	if (!hash) {
+		hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+#define mapping(gtype, corba_type)\
+		g_hash_table_insert (hash, GUINT_TO_POINTER(gtype), corba_type);
+		
+		mapping(G_TYPE_NONE,    TC_void);
+		mapping(G_TYPE_BOOLEAN, TC_CORBA_boolean);
+		mapping(G_TYPE_INT,     TC_CORBA_long);
+		mapping(G_TYPE_UINT,    TC_CORBA_unsigned_long);
+		mapping(G_TYPE_LONG,    TC_CORBA_long);
+		mapping(G_TYPE_ULONG,   TC_CORBA_unsigned_long);
+		mapping(G_TYPE_FLOAT,   TC_CORBA_float);
+		mapping(G_TYPE_DOUBLE,  TC_CORBA_double);
+		mapping(G_TYPE_STRING,  TC_CORBA_string);
+		
+		mapping(BONOBO_TYPE_CORBA_ANY,  TC_CORBA_any);
+#undef mapping
+	}
+	return (CORBA_TypeCode) g_hash_table_lookup (hash, GUINT_TO_POINTER(G_TYPE_INT));
+}
+
+void
+bonobo_application_register_message_va (BonoboApplication *app,
+					const gchar       *name,
+					GType              return_type,
+					GType              first_arg_type,
+					va_list            var_args)
+{
+	Bonobo_Application_MessageDesc *msgdesc;
+	GType                           gtype;
+	GPtrArray                      *tmparray;
+
+	msgdesc = Bonobo_Application_MessageDesc__alloc();
+	msgdesc->return_type = _gtype_to_typecode(return_type);
+	msgdesc->name        = CORBA_string_dup (name);
+
+	tmparray = g_ptr_array_new ();
+	if (first_arg_type != G_TYPE_NONE) {
+		g_ptr_array_add (tmparray, _gtype_to_typecode (first_arg_type));
+		while ((gtype = va_arg (var_args, GType)) != G_TYPE_NONE)
+			g_ptr_array_add (tmparray, _gtype_to_typecode (gtype));
+	}
+	msgdesc->types._length = msgdesc->types._maximum = tmparray->len;
+	msgdesc->types._buffer = CORBA_sequence_CORBA_TypeCode_allocbuf (tmparray->len);
+	memcpy(msgdesc->types._buffer, tmparray->pdata, sizeof(gpointer)*tmparray->len);
+	g_ptr_array_free (tmparray, TRUE);
+
+	app->message_list = g_slist_append (app->message_list, msgdesc);
+}
+
+
+void
+bonobo_application_register_message (BonoboApplication *app,
+				     const gchar       *name,
+				     GType              return_type,
+				     GType              first_arg_type,
+				     ...)
+{
+	va_list var_args;
+
+	va_start (var_args, first_arg_type);
+	bonobo_application_register_message_va (app, name, return_type,
+						first_arg_type, var_args);
+	va_end (var_args);
+}
+
+
+/**
+ * bonobo_register_unique_application:
+ * @name: Unique name of the application, eg. "GNOME_Terminal".
+ * @first_message_name: first of a NULL terminated list of message
+ * names that the application supports.  This is just an optional hint
+ * to the client.
+ * 
+ * Try to register the running application, or check for an existing
+ * application already registered and get a reference to it.
+ * Applications already running but on different environments (that
+ * usually means different displays, or whatever is set with
+ * bonobo_activation_registration_env_set) than this one are ignored
+ * and do not interfere.
+ * 
+ * Return value: either a BonoboApplication object representing the
+ * current process, if this process was the first to register, or a
+ * BonoboAppClient which acts as client to another process that has
+ * registered earlier with the same name.
+ **/
+BonoboAppClient *
+bonobo_application_register_unique (BonoboApplication *app)
+{
+	Bonobo_RegistrationResult  reg_res;
+	gchar                     *iid;
+	CORBA_Object               remote_obj = CORBA_OBJECT_NIL;
+
+	iid     = g_strdup_printf ("OAFIID:%s", app->name);
+	reg_res = bonobo_activation_register_active_server_ext
+		(iid, bonobo_object_corba_objref (BONOBO_OBJECT (app)), NULL,
+		 Bonobo_REGISTRATION_FLAG_NO_SERVERINFO, &remote_obj);
+	g_free (iid);
+	if (reg_res == Bonobo_ACTIVATION_REG_SUCCESS)
+		return NULL;
+	else if (reg_res == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE) {
+		return bonobo_app_client_new ((Bonobo_Application) remote_obj);
+	} else {
+		g_warning ("bonobo_register_unique_application failed"
+			   " with error code %i", reg_res);
+		return NULL;
+	}
+}
+
+
+void bonobo_application_add_hook (BonoboAppHookFunc func, gpointer data)
+{
+	BonoboAppHook hook;
+
+	if (bonobo_application_hooks == NULL)
+		bonobo_application_hooks = g_array_new (FALSE, FALSE, sizeof (BonoboAppHook));
+	
+	hook.func = func;
+	hook.data = data;
+	g_array_append_val(bonobo_application_hooks, hook);
+}
+
+
+void bonobo_application_remove_hook (BonoboAppHookFunc func, gpointer data)
+{
+	BonoboAppHook *hook;
+	int            i;
+
+	g_return_if_fail (bonobo_application_hooks);
+
+	for (i = 0; i < bonobo_application_hooks->len; ++i) {
+		hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
+		if (hook->func == func && hook->data == data) {
+			g_array_remove_index (bonobo_application_hooks, i);
+			return;
+		}
+	}
+
+	g_warning ("bonobo_application_remove_hook: "
+		   "(func, data) == (%p, %p) not found.", func, data);
+}
+
+
+static void
+bonobo_application_invoke_hooks (BonoboApplication *app)
+{
+	BonoboAppHook *hook;
+	int            i;
+
+	if (!bonobo_application_hooks)
+		return;
+
+	for (i = 0; i < bonobo_application_hooks->len; ++i) {
+		hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
+		hook->func (app, hook->data);
+	}
+}
+
Index: bonobo/bonobo-application.h
===================================================================
RCS file: bonobo/bonobo-application.h
diff -N bonobo/bonobo-application.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-application.h	30 Apr 2003 11:23:37 -0000
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef _BONOBO_APPLICATION_H_
+#define _BONOBO_APPLICATION_H_
+
+#include <bonobo/bonobo-object.h>
+
+G_BEGIN_DECLS
+
+#define BONOBO_TYPE_APPLICATION        (bonobo_application_get_type ())
+#define BONOBO_APPLICATION(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o),\
+				        BONOBO_TYPE_APPLICATION, BonoboApplication))
+#define BONOBO_APPLICATION_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k),\
+                                        BONOBO_TYPE_APPLICATION, BonoboApplicationClass))
+#define BONOBO_IS_APPLICATION(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o),\
+				        BONOBO_TYPE_APPLICATION))
+#define BONOBO_IS_APPLICATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k),\
+					BONOBO_TYPE_APPLICATION))
+#define BONOBO_APPLICATION_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o),\
+				        BONOBO_TYPE_APPLICATION, BonoboApplicationClass))
+
+typedef struct _BonoboApplication      BonoboApplication;
+typedef struct _BonoboApplicationClass BonoboApplicationClass;
+
+typedef void (*BonoboAppHookFunc) (BonoboApplication *app, gpointer data);
+
+
+#include <bonobo/bonobo-app-client.h>
+
+
+struct _BonoboApplication {
+	BonoboObject  parent;
+	GSList       *message_list;
+	gchar        *name;
+};
+
+struct _BonoboApplicationClass {
+	BonoboObjectClass parent_class;
+
+	GValue* (*message)      (BonoboApplication *app, const char *name, GValueArray *args);
+	gint    (*new_instance) (BonoboApplication *app, gint argc, gchar *argv[]);
+
+	gpointer unimplemented[8];
+
+	POA_Bonobo_Application__epv epv;
+};
+
+
+GType              bonobo_application_get_type            (void) G_GNUC_CONST;
+BonoboApplication* bonobo_application_new                 (const char        *name);
+void               bonobo_application_register_message    (BonoboApplication *app,
+							   const gchar       *name,
+							   GType              return_type,
+							   GType              first_arg_type,
+							   ...);
+void               bonobo_application_register_message_va (BonoboApplication *app,
+							   const gchar       *name,
+							   GType              return_type,
+							   GType              first_arg_type,
+							   va_list            var_args);
+BonoboAppClient*   bonobo_application_register_unique     (BonoboApplication *app);
+void               bonobo_application_add_hook            (BonoboAppHookFunc  func,
+							   gpointer           data);
+void               bonobo_application_remove_hook         (BonoboAppHookFunc  func,
+							   gpointer           data);
+gint               bonobo_application_new_instance        (BonoboApplication *app,
+							   gint               argc,
+							   gchar             *argv[]);
+
+G_END_DECLS
+
+#endif /* _BONOBO_APPLICATION_H_ */
+
Index: bonobo/bonobo-arg.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-arg.c,v
retrieving revision 1.29
diff -u -p -u -p -r1.29 bonobo-arg.c
--- bonobo/bonobo-arg.c	23 Apr 2003 14:19:48 -0000	1.29
+++ bonobo/bonobo-arg.c	30 Apr 2003 11:23:37 -0000
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * bonobo-arg.c Bonobo argument support:
  *
@@ -13,6 +14,7 @@
 #include <bonobo/bonobo-main.h>
 #include <bonobo/bonobo-exception.h>
 #include <bonobo/bonobo-arg.h>
+#include "bonobo-types.h"
 
 /**
  * bonobo_arg_new:
@@ -219,6 +221,16 @@ bonobo_arg_from_gvalue (BonoboArg *a, co
 
 	id = G_VALUE_TYPE (value);
 
+	if (id == BONOBO_TYPE_CORBA_ANY) {
+		CORBA_any *any;
+
+		any = bonobo_value_get_corba_any (value);
+		*a = *any;
+		any->_release = CORBA_FALSE;
+		CORBA_free (any);
+		return;
+	}
+
 	switch (id) {
 
 	case G_TYPE_INVALID:
@@ -237,6 +249,8 @@ bonobo_arg_from_gvalue (BonoboArg *a, co
 		MAKE_FROM_GVALUE (DOUBLE,  double,  TC_CORBA_double, double_data, CORBA_double,         CORBA_tk_double);
 
 	case G_TYPE_STRING:
+		a->_type    = TC_CORBA_string;
+		a->_release = CORBA_TRUE;
 		if (G_VALUE_HOLDS_STRING (value))
 			*((CORBA_char **)a->_value) = CORBA_string_dup (g_value_get_string (value));
 		else
@@ -249,14 +263,14 @@ bonobo_arg_from_gvalue (BonoboArg *a, co
 
 	case G_TYPE_OBJECT:
 		g_warning ("All objects can be mapped to base gtk types"
-			   "in due course");
+			   " in due course");
 		break;
 
 	case G_TYPE_ENUM:
 	case G_TYPE_FLAGS:
 	case G_TYPE_BOXED:
 	default:
-		g_warning ("Unmapped GValue type %d", id);
+		g_warning ("Unmapped GValue type %d (%s)", id, g_type_name (id));
 		break;
 	}
 }
@@ -303,12 +317,13 @@ bonobo_arg_to_gvalue (GValue *value, con
 		MAKE_TO_GVALUE (DOUBLE,  double,  TC_CORBA_double, double_data, CORBA_double,         CORBA_tk_double);
 
 	case CORBA_tk_string:
+		g_value_init (value, G_TYPE_STRING);
 		g_value_set_string (value, BONOBO_ARG_GET_STRING (arg));
 		break;
 
 	case CORBA_tk_objref:
 		g_warning ("All objects can be mapped to base gtk types"
-			   "in due course");
+			   " in due course");
 		break;
 
 	case CORBA_tk_sequence:
@@ -316,7 +331,8 @@ bonobo_arg_to_gvalue (GValue *value, con
 	case CORBA_tk_enum:
 	case CORBA_tk_array:
 	case CORBA_tk_union:
-		g_warning ("Clever things can be done for these");
+		g_value_init (value, BONOBO_TYPE_CORBA_ANY);
+		bonobo_value_set_corba_any (value, arg);
 		break;
 
 	default:
Index: bonobo/bonobo-marshal.list
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-marshal.list,v
retrieving revision 1.10
diff -u -p -u -p -r1.10 bonobo-marshal.list
--- bonobo/bonobo-marshal.list	30 Oct 2001 02:32:09 -0000	1.10
+++ bonobo/bonobo-marshal.list	30 Apr 2003 11:23:38 -0000
@@ -2,3 +2,5 @@ BOXED:STRING,BOOLEAN,BOXED
 VOID:STRING,BOXED,BOXED
 VOID:BOXED,UINT,BOXED
 OBJECT:STRING
+BOXED:STRING,BOXED
+INT:INT,POINTER
Index: bonobo-activation/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo-activation/Makefile.am,v
retrieving revision 1.47
diff -u -p -u -p -r1.47 Makefile.am
--- bonobo-activation/Makefile.am	16 Apr 2003 19:10:51 -0000	1.47
+++ bonobo-activation/Makefile.am	30 Apr 2003 11:23:38 -0000
@@ -12,7 +12,7 @@ INCLUDES=					\
 	-DG_DISABLE_DEPRECATED			\
 	$(NULL)
 
-LDFLAGS=					\
+AM_LDFLAGS=					\
 	$(LIBBONOBO_LIBS)			\
 	$(BONOBO_ACTIVATION_LT_VERSION_INFO)	\
 	-no-undefined				\
Index: idl/Bonobo.idl
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Bonobo.idl,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 Bonobo.idl
--- idl/Bonobo.idl	7 Mar 2003 12:09:42 -0000	1.55
+++ idl/Bonobo.idl	30 Apr 2003 11:23:38 -0000
@@ -49,6 +49,8 @@
 /* Clipboard */
 #include <Bonobo_Clipboard.idl>
 
+#include <Bonobo_Application.idl>
+
 #ifndef __Bonobo_COMPILATION
 #ifdef __ORBIT_IDL__
 #pragma inhibit pop
Index: idl/Bonobo_Application.idl
===================================================================
RCS file: idl/Bonobo_Application.idl
diff -N idl/Bonobo_Application.idl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ idl/Bonobo_Application.idl	30 Apr 2003 11:23:38 -0000
@@ -0,0 +1,46 @@
+/* -*- Mode: idl; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Bonobo_Application.idl: Unique application support (some would call
+ * it--or can be used for--Automation).
+ *
+ */
+
+#ifndef BONOBO_APPLICATION_IDL
+#define BONOBO_APPLICATION_IDL
+
+#include "Bonobo_Unknown.idl"
+
+module Bonobo {
+  
+	interface Application : Bonobo::Unknown {
+
+                typedef sequence<any> ArgList;
+
+                struct MessageDesc {
+                        string             name;
+                        sequence<TypeCode> types;
+                        TypeCode           return_type;
+                };
+
+                typedef sequence<MessageDesc> MessageList;
+
+                  // Send a message (message) to the application
+	        any         message      (in string  msg,
+                                          in ArgList args);
+                MessageList listMessages ();
+
+
+                void unimplemented1 ();
+                void unimplemented2 ();
+                void unimplemented3 ();
+                void unimplemented4 ();
+                void unimplemented5 ();
+                void unimplemented6 ();
+                void unimplemented7 ();
+                void unimplemented8 ();
+  	};
+
+};
+
+#endif /* BONOBO_APPLICATION_IDL */
+
Index: idl/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Makefile.am,v
retrieving revision 1.52
diff -u -p -u -p -r1.52 Makefile.am
--- idl/Makefile.am	16 Apr 2003 19:10:52 -0000	1.52
+++ idl/Makefile.am	30 Apr 2003 11:23:39 -0000
@@ -20,6 +20,7 @@ idl_DATA =				\
 	Bonobo_Zoomable.idl		\
 	Bonobo_Exception.idl		\
 	Bonobo_Clipboard.idl		\
+	Bonobo_Application.idl		\
 	$(NULL)
 
 activation_idldir=$(datadir)/idl/bonobo-activation-2.0
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/tests/Makefile.am,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 Makefile.am
--- tests/Makefile.am	7 Apr 2003 10:31:12 -0000	1.18
+++ tests/Makefile.am	30 Apr 2003 11:23:39 -0000
@@ -7,7 +7,8 @@ noinst_PROGRAMS =		\
 	test-event-source	\
 	test-object		\
 	test-stream-mem		\
-	test-storage-mem
+	test-storage-mem	\
+	test-uniqapp
 
 INCLUDES =	\
         -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
@@ -32,6 +33,8 @@ test_event_source_SOURCES = test-event-s
 test_stream_mem_SOURCES = test-stream-mem.c
 
 test_storage_mem_SOURCES = test-storage-mem.c
+
+test_uniqapp_SOURCES = test-uniqapp.c
 
 TESTS_ENVIRONMENT =					\
 	LD_LIBRARY_PATH="$(top_builddir)/bonobo/.libs:$$LD_LIBRARY_PATH"	\
Index: tests/test-uniqapp.c
===================================================================
RCS file: tests/test-uniqapp.c
diff -N tests/test-uniqapp.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/test-uniqapp.c	30 Apr 2003 11:23:39 -0000
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#include <config.h>
+#include <libbonobo.h>
+#include <string.h>
+
+#define TEST_MESSAGE "test-message"
+
+
+static GValue *
+message_cb (BonoboAppClient *app_client, const gchar *message, GValueArray *args)
+{
+	GValue *retval = g_new0 (GValue, 1);
+
+	g_message ("message_cb: %s", message);
+
+	if (strcmp (message, TEST_MESSAGE) != 0)
+		return NULL;
+
+	g_value_init (retval, G_TYPE_FLOAT);
+	if (args->n_values == 1) {
+		g_value_set_float (retval, 2*g_value_get_float (
+					   g_value_array_get_nth (args, 0)));
+	} else {
+		g_warning ("Wrong arity!");
+		g_value_set_float (retval, 0);
+	}
+	return retval;
+}
+
+static void
+test_app_hook (BonoboApplication *app, gpointer data)
+{
+	g_message ("App '%s' created; data == %p", app->name, data);
+}
+
+static gint
+new_instance_cb (BonoboApplication *app, gint argc, char *argv[])
+{
+	int i;
+
+	g_message ("new-instance received. argc = %i; argv follows:", argc);
+	for (i = 0; i < argc; ++i)
+		g_message ("argv[%i] = \"%s\"", i, argv[i]);
+	g_message ("new-instance: returning argc (%i)", argc);
+	return argc;
+}
+
+int
+main (int argc, char *argv [])
+{
+	BonoboApplication *app;
+	BonoboAppClient   *client;
+	float              msg_arg = 3.141592654;
+
+	if (bonobo_init (&argc, argv) == FALSE)
+		g_error ("Can not bonobo_init");
+	bonobo_activate ();
+
+	bonobo_application_add_hook (test_app_hook, (gpointer) 0xdeadbeef);
+
+	app = bonobo_application_new ("Libbonobo-Test-Uniqapp");
+	bonobo_application_register_message (app, TEST_MESSAGE, G_TYPE_FLOAT,
+					     G_TYPE_FLOAT, G_TYPE_NONE);
+	client = bonobo_application_register_unique (app);
+
+	if (client)
+	{
+		BonoboAppClientMsgDesc const *msgdescs;
+		GValue                       *retval;
+		int                           i;
+
+		g_message ("I am an application client.");
+		bonobo_object_unref (BONOBO_OBJECT (app));
+
+		msgdescs = bonobo_app_client_msg_list (client);
+		g_assert (msgdescs);
+
+		for (i = 0; msgdescs[i].name; ++i)
+			g_message ("Application supports message '%s'", msgdescs[i].name);
+
+		g_message ("Sending message string '%s' with argument %f",
+			   TEST_MESSAGE, msg_arg);
+		retval = bonobo_app_client_msg_send (client, TEST_MESSAGE,
+						     G_TYPE_FLOAT, msg_arg,
+						     G_TYPE_NONE);
+		g_message ("Return value: %f", g_value_get_float (retval));
+
+		i = bonobo_app_client_new_instance (client, argc, argv);
+		g_message ("new-instance returned %i", i);
+
+	} else if (g_type_is_a (G_OBJECT_TYPE (app), BONOBO_TYPE_APPLICATION)) {
+		g_message ("I am an application server");
+		g_signal_connect (app, "message",
+				  G_CALLBACK (message_cb), NULL);
+		g_signal_connect (app, "new-instance",
+				  G_CALLBACK (new_instance_cb), NULL);
+		bonobo_application_new_instance (app, argc, argv);
+	} else
+		g_assert_not_reached ();
+
+	bonobo_main ();
+
+	return bonobo_debug_shutdown ();
+}


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