gedit r6730 - in branches/message_system: . gedit gedit/smclient plugin-loaders/python/bindings



Author: jessevdk
Date: Sat Dec 27 13:07:00 2008
New Revision: 6730
URL: http://svn.gnome.org/viewvc/gedit?rev=6730&view=rev

Log:
Implemented new version of the message system. Messages now have to be registered
which results into a message type definition. Messages are then instantiated from
this message definition (so that argument types can be deduced from the type
specification). Bindings are properly implemented and a private message bus is
added to each GeditWindow


Added:
   branches/message_system/gedit/gedit-message-type.c
   branches/message_system/gedit/gedit-message-type.h
   branches/message_system/gedit/msgtest.c
   branches/message_system/gedit/smclient/eggsmclient-osx.c
      - copied unchanged from r6626, /trunk/gedit/smclient/eggsmclient-osx.c
   branches/message_system/gedit/smclient/eggsmclient-win32.c
      - copied unchanged from r6626, /trunk/gedit/smclient/eggsmclient-win32.c
Modified:
   branches/message_system/ChangeLog
   branches/message_system/configure.ac
   branches/message_system/gedit/Makefile.am
   branches/message_system/gedit/gedit-message-bus.c
   branches/message_system/gedit/gedit-message-bus.h
   branches/message_system/gedit/gedit-message.c
   branches/message_system/gedit/gedit-message.h
   branches/message_system/gedit/gedit-window-private.h
   branches/message_system/gedit/gedit-window.c
   branches/message_system/gedit/gedit-window.h
   branches/message_system/gedit/gedit.c
   branches/message_system/gedit/smclient/Makefile.am
   branches/message_system/plugin-loaders/python/bindings/Makefile.am
   branches/message_system/plugin-loaders/python/bindings/gedit.defs
   branches/message_system/plugin-loaders/python/bindings/geditmessage.override

Modified: branches/message_system/configure.ac
==============================================================================
--- branches/message_system/configure.ac	(original)
+++ branches/message_system/configure.ac	Sat Dec 27 13:07:00 2008
@@ -45,7 +45,7 @@
 AC_SUBST(ACLOCAL_AMFLAGS, "$ACLOCAL_FLAGS -I m4")
 
 dnl check for win32 platform
-AC_MSG_CHECKING([for some Win32 platform])
+AC_MSG_CHECKING([for Win32 platform])
 case "$host" in
   *-*-mingw*|*-*-cygwin*)
     platform_win32=yes
@@ -57,6 +57,23 @@
 AC_MSG_RESULT([$platform_win32])
 AM_CONDITIONAL(PLATFORM_WIN32, test "$platform_win32" = "yes")
 
+dnl check for osx platform
+AC_MSG_CHECKING([for Mac OS X platform])
+case "$host" in
+  *-*-darwin*)
+    platform_osx=yes
+    ;;
+  *)
+    platform_osx=no
+    ;;
+esac
+AC_MSG_RESULT([$platform_osx])
+AM_CONDITIONAL(PLATFORM_OSX, test "$platform_osx" = "yes")
+
+if test "$platform_osx" = "yes"; then
+	AC_DEFINE([PLATFORM_OSX],[1],[Defined if platform is Mac OSX])
+fi
+
 dnl ===============================================================
 dnl Expanded dirs
 dnl ===============================================================
@@ -176,7 +193,6 @@
 dnl ================================================================
 
 PKG_CHECK_MODULES(GEDIT, [
-	sm >= 1.0.0
 	libxml-2.0 >= 2.5.0
 	glib-2.0 >= 2.13.0
 	gthread-2.0 >= 2.13.0
@@ -189,6 +205,19 @@
 AC_SUBST(GEDIT_LIBS)
 AC_SUBST(GEDIT_CFLAGS)
 
+if test "$platform_osx" = "no"; then
+	PKG_CHECK_MODULES(EGG_SMCLIENT, [
+		sm >= 1.0.0
+	])
+	SM_LIBS="${EGG_SMCLIENT_LIBS}"
+else
+	EGG_SMCLIENT_CFLAGS=
+	EGG_SM_CLIENT_LIBS=
+fi
+
+AC_SUBST(EGG_SMCLIENT_CFLAGS)
+AC_SUBST(EGG_SMCLIENT_LIBS)
+
 dnl ================================================================
 dnl GConf related settings
 dnl ================================================================

Modified: branches/message_system/gedit/Makefile.am
==============================================================================
--- branches/message_system/gedit/Makefile.am	(original)
+++ branches/message_system/gedit/Makefile.am	Sat Dec 27 13:07:00 2008
@@ -4,6 +4,7 @@
 bin_PROGRAMS = gedit
 
 noinst_LTLIBRARIES = libgedit.la
+noinst_PROGRAMS = msgtest
 
 INCLUDES =								\
 	-I$(top_srcdir)							\
@@ -20,23 +21,35 @@
 	-DGEDIT_LOADERDIR=\""$(libdir)/gedit-2/plugin-loaders"\"	\
 	-DGEDIT_ICONDIR=\""$(datadir)/gedit-2/icons"\"
 
-gedit_SOURCES = \
-	gedit.c \
-	gedit-message.c \
-	gedit-message-bus.c
+gedit_SOURCES = 			\
+	gedit.c 			\
+	gedit-message.c 		\
+	gedit-message-bus.c		\
+	gedit-message-type.c
+
+gedit_LDADD = libgedit.la $(GEDIT_LIBS) $(EGG_SMCLIENT_LIBS)
+
+msgtest_SOURCES =			\
+	msgtest.c			\
+	gedit-message.c			\
+	gedit-message-bus.c		\
+	gedit-message-type.c
 
-gedit_LDADD = libgedit.la $(GEDIT_LIBS)
+msgtest_LDADD = $(GEDIT_LIBS)
  
 if PLATFORM_WIN32
 gedit_LDFLAGS = -Wl,--export-all-symbols -Wl,--out-implib,libgedit-$(GEDIT_API_VERSION).a
 else
-
 gedit_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
 endif
 
+if PLATFORM_OSX
+gedit_LDFLAGS += -framework Carbon
+endif
+
 libgedit_la_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
 
-libgedit_la_LIBADD = \
+libgedit_la_LIBADD = 			\
 	dialogs/libdialogs.la		\
 	smclient/libeggsmclient.la
 
@@ -89,6 +102,7 @@
 	gedit-message.h			\
 	gedit-message-area.h		\
 	gedit-message-bus.h		\
+	gedit-message-type.h		\
 	gedit-metadata-manager.h	\
 	gedit-notebook.h		\
 	gedit-panel.h			\

Modified: branches/message_system/gedit/gedit-message-bus.c
==============================================================================
--- branches/message_system/gedit/gedit-message-bus.c	(original)
+++ branches/message_system/gedit/gedit-message-bus.c	Sat Dec 27 13:07:00 2008
@@ -8,29 +8,14 @@
 
 typedef struct
 {
-	gchar *domain;
-	gchar *name;
+	gchar *object_path;
+	gchar *method;
 
 	GList *listeners;
 } Message;
 
 typedef struct
 {
-	gchar *key;
-	GType type;
-	gboolean required;
-} PolicyItem;
-
-typedef struct
-{
-	gchar *domain;
-	gchar *name;
-	
-	GList *policies; /* list of PolicyItem */
-} Policy;
-
-typedef struct
-{
 	guint id;
 	gboolean blocked;
 
@@ -55,13 +40,15 @@
 
 	guint next_id;
 	
-	GHashTable *policies;
+	GHashTable *types; /* mapping from identifier to GeditMessageType */
 };
 
 /* signals */
 enum
 {
 	DISPATCH,
+	REGISTERED,
+	UNREGISTERED,
 	LAST_SIGNAL
 };
 
@@ -73,28 +60,6 @@
 G_DEFINE_TYPE(GeditMessageBus, gedit_message_bus, G_TYPE_OBJECT)
 
 static void
-policy_item_free (PolicyItem *pitem)
-{
-	g_free (pitem->key);
-	g_free (pitem);
-}
-
-static void
-policy_free (Policy *policy)
-{
-	GList *item;
-	
-	g_free (policy->domain);
-	g_free (policy->name);
-	
-	for (item = policy->policies; item; item = item->next)
-		policy_item_free ((PolicyItem *)item->data);
-	
-	g_list_free (policy->policies);
-	g_free (policy);
-}
-
-static void
 listener_free (Listener *listener)
 {
 	if (listener->destroy_data)
@@ -106,8 +71,8 @@
 static void
 message_free (Message *message)
 {
-	g_free (message->name);
-	g_free (message->domain);
+	g_free (message->method);
+	g_free (message->object_path);
 	
 	g_list_foreach (message->listeners, (GFunc)listener_free, NULL);
 	g_list_free (message->listeners);
@@ -146,6 +111,17 @@
 	
 	klass->dispatch = gedit_message_bus_dispatch_real;
 
+	/**
+	 * GeditMessageBus::dispatch:
+	 * @bus: a #GeditMessageBus
+	 * @message: the #GeditMessage to dispatch
+	 *
+	 * The "dispatch" signal is emitted when a message is to be dispatched.
+	 * The message is dispatched in the default handler of this signal. 
+	 * Primary use of this signal is to customize the dispatch of a message
+	 * (for instance to automatically dispatch all messages over DBus).
+	 *2
+	 */
 	message_bus_signals[DISPATCH] =
    		g_signal_new ("dispatch",
 			      G_OBJECT_CLASS_TYPE (object_class),
@@ -157,43 +133,79 @@
 			      1,
 			      GEDIT_TYPE_MESSAGE);
 
-	g_type_class_add_private (object_class, sizeof(GeditMessageBusPrivate));
-}
+	/**
+	 * GeditMessageBus::registered:
+	 * @bus: a #GeditMessageBus
+	 * @object_path: the object path
+	 * @method: the registered method at @object_path
+	 *
+	 * The "registered" signal is emitted when a message has been registered
+	 * on the bus (@method has been registered at @object_path)
+	 *
+	 */
+	message_bus_signals[REGISTERED] =
+   		g_signal_new ("registered",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GeditMessageBusClass, registered),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__BOXED,
+			      G_TYPE_NONE,
+			      1,
+			      GEDIT_TYPE_MESSAGE_TYPE);
 
-inline static gchar *
-msg_identifier (const gchar *domain,
-		const gchar *name)
-{
-	return g_strconcat (domain, "::", name, NULL);
+	/**
+	 * GeditMessageBus::unregistered:
+	 * @bus: a #GeditMessageBus
+	 * @object_path: the object path
+	 * @method: the unregistered method at @object_path
+	 *
+	 * The "unregistered" signal is emitted when a message has been 
+	 * unregistered from the bus (@method has been unregistered from 
+	 * @object_path)
+	 *
+	 */
+	message_bus_signals[UNREGISTERED] =
+   		g_signal_new ("unregistered",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GeditMessageBusClass, unregistered),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__BOXED,
+			      G_TYPE_NONE,
+			      1,
+			      GEDIT_TYPE_MESSAGE_TYPE);
+
+	g_type_class_add_private (object_class, sizeof(GeditMessageBusPrivate));
 }
 
 static Message *
 message_new (GeditMessageBus *bus,
-	     const gchar     *domain,
-	     const gchar     *name)
+	     const gchar     *object_path,
+	     const gchar     *method)
 {
 	Message *message = g_new (Message, 1);
 	
-	message->domain = g_strdup (domain);
-	message->name = g_strdup (name);
+	message->object_path = g_strdup (object_path);
+	message->method = g_strdup (method);
 	message->listeners = NULL;
 
 	g_hash_table_insert (bus->priv->messages, 
-			     msg_identifier (domain, name),
+			     gedit_message_type_identifier (object_path, method),
 			     message);
 	return message;
 }
 
 static Message *
 lookup_message (GeditMessageBus *bus,
-	       const gchar      *domain,
-	       const gchar      *name,
+	       const gchar      *object_path,
+	       const gchar      *method,
 	       gboolean          create)
 {
 	gchar *identifier;
 	Message *message;
 	
-	identifier = msg_identifier (domain, name);
+	identifier = gedit_message_type_identifier (object_path, method);
 	message = (Message *)g_hash_table_lookup (bus->priv->messages, identifier);
 	g_free (identifier);
 
@@ -201,7 +213,7 @@
 		return NULL;
 	
 	if (!message)
-		message = message_new (bus, domain, name);
+		message = message_new (bus, object_path, method);
 	
 	return message;
 }
@@ -298,14 +310,14 @@
 gedit_message_bus_dispatch_real (GeditMessageBus *bus,
 				 GeditMessage    *message)
 {
-	const gchar *domain;
-	const gchar *name;
+	const gchar *object_path;
+	const gchar *method;
 	Message *msg;
 	
-	domain = gedit_message_get_domain (message);
-	name = gedit_message_get_name (message);
+	object_path = gedit_message_get_object_path (message);
+	method = gedit_message_get_method (message);
 
-	msg = lookup_message (bus, domain, name, FALSE);
+	msg = lookup_message (bus, object_path, method, FALSE);
 	
 	if (msg)
 		dispatch_message_real (bus, msg, message);
@@ -365,8 +377,8 @@
 
 static void
 process_by_match (GeditMessageBus      *bus,
-	          const gchar          *domain,
-	          const gchar          *name,
+	          const gchar          *object_path,
+	          const gchar          *method,
 	          GeditMessageCallback  callback,
 	          gpointer              userdata,
 	          MatchCallback         processor)
@@ -374,11 +386,11 @@
 	Message *message;
 	GList *item;
 	
-	message = lookup_message (bus, domain, name, FALSE);
+	message = lookup_message (bus, object_path, method, FALSE);
 	
 	if (!message)
 	{
-		g_warning ("No such handler registered for %s::%s", domain, name);
+		g_warning ("No such handler registered for %s.%s", object_path, method);
 		return;
 	}
 	
@@ -394,7 +406,7 @@
 		}
 	}
 	
-	g_warning ("No such handler registered for %s::%s", domain, name);
+	g_warning ("No such handler registered for %s.%s", object_path, method);
 }
 
 static void
@@ -412,12 +424,20 @@
 	 					   NULL,
 	 					   (GDestroyNotify)g_free);
 	 					   
-	self->priv->policies = g_hash_table_new_full (g_str_hash,
-						      g_str_equal,
-						      (GDestroyNotify)g_free,
-						      (GDestroyNotify)policy_free);
+	self->priv->types = g_hash_table_new_full (g_str_hash,
+						   g_str_equal,
+						   (GDestroyNotify)g_free,
+						   (GDestroyNotify)gedit_message_type_unref);
 }
 
+/**
+ * gedit_message_bus_get_default:
+ *
+ * Get the default application #GeditMessageBus
+ *
+ * Return value: the default #GeditMessageBus
+ *
+ */
 GeditMessageBus *
 gedit_message_bus_get_default (void)
 {
@@ -433,112 +453,239 @@
 	return default_bus;
 }
 
-void
+/**
+ * gedit_message_bus_new:
+ * 
+ * Create a new message bus. Use #gedit_message_bus_get_default to get the
+ * default, application wide, message bus. Creating a new bus is useful for
+ * associating a specific bus with for instance a #GeditWindow
+ *
+ * Return value: a new #GeditMessageBus
+ *
+ */
+GeditMessageBus *
+gedit_message_bus_new (void)
+{
+	return GEDIT_MESSAGE_BUS (g_object_new (GEDIT_TYPE_MESSAGE_BUS, NULL));
+}
+
+/**
+ * gedit_message_bus_lookup:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ *
+ * Get the registered #GeditMessageType for @method at @object_path. The 
+ * returned #GeditMessageType is owned by the bus and should not be unreffed.
+ *
+ * Return value: the registered #GeditMessageType or %NULL if no message type
+ *               is registered for @method at @object_path
+ *
+ */
+GeditMessageType *
+gedit_message_bus_lookup (GeditMessageBus *bus,
+			  const gchar	  *object_path,
+			  const gchar	  *method)
+{
+	gchar *identifier;
+	
+	g_return_val_if_fail (GEDIT_IS_MESSAGE_BUS (bus), NULL);
+	g_return_val_if_fail (object_path != NULL, NULL);
+	g_return_val_if_fail (method != NULL, NULL);
+
+	identifier = gedit_message_type_identifier (object_path, method);
+	return g_hash_table_lookup (bus->priv->types, identifier);
+}
+
+/**
+ * gedit_message_bus_register:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method to register
+ * @num_optional: the number of optional arguments
+ * @...: NULL terminated list of key/gtype method argument pairs
+ *
+ * Register a message on the bus. A message must be registered on the bus before
+ * it can be send. This function registers the type arguments for @method at 
+ * @object_path. The arguments are specified with @... which should contain
+ * pairs of const gchar *key and GType terminated by NULL. The last 
+ * @num_optional arguments are registered as optional (and are thus not
+ * required when sending a message).
+ *
+ * This function emits a #GeditMessageBus::registered signal
+ *
+ * Return value: the registered #GeditMessageType. The returned reference is
+ *               owned by the bus. If you want to keep it alive after
+ *               unregistering, use #gedit_message_type_ref
+ *
+ */
+GeditMessageType *
 gedit_message_bus_register (GeditMessageBus *bus,
-			    const gchar     *domain,
-			    const gchar	    *name,
+			    const gchar     *object_path,
+			    const gchar	    *method,
 			    guint	     num_optional,
 			    ...)
 {
 	gchar *identifier;
 	gpointer data;
-	Policy *policy;
 	va_list var_args;
-	const gchar *key;
-	GList *item;
-	
-	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
-	
-	identifier = msg_identifier (domain, name);
-	data = g_hash_table_lookup (bus->priv->policies, identifier);
+	GeditMessageType *message_type;
+
+	g_return_val_if_fail (GEDIT_IS_MESSAGE_BUS (bus), NULL);
 	
-	if (data != NULL)
+	if (gedit_message_bus_is_registered (bus, object_path, method))
 	{
-		/* policy is already registered */
-		g_free (identifier);
-		return;
+		g_warning ("Message type for '%s.%s' is already registered", object_path, method);
+		return NULL;
 	}
+
+	identifier = gedit_message_type_identifier (object_path, method);
+	data = g_hash_table_lookup (bus->priv->types, identifier);
 	
-	policy = g_new(Policy, 1);
-	policy->domain = g_strdup (domain);
-	policy->name = g_strdup (name);
-	policy->policies = NULL;
-	
-	/* construct policy items */
 	va_start (var_args, num_optional);
-
-	/* read in required items */
-	while ((key = va_arg (var_args, const gchar *)) != NULL)
-	{
-		GType gtype;
-		PolicyItem *pitem;
-		
-		gtype = va_arg (var_args, GType);
-		
-		if (!_gedit_message_gtype_supported (gtype))
-		{
-			g_warning ("Type `%s' is not supported on the message bus",
-				   g_type_name (gtype));
-			continue;
-		}
-		
-		pitem = g_new(PolicyItem, 1);
-		pitem->key = g_strdup (key);
-		pitem->type = gtype;
-
-		policy->policies = g_list_prepend (policy->policies, pitem);
-	}
+	message_type = gedit_message_type_new_valist (object_path, 
+						      method,
+						      num_optional,
+						      var_args);
+	va_end (var_args);
 	
-	for (item = policy->policies; num_optional-- > 0 && item; item = item->next)
-		((PolicyItem *)item->data)->required = FALSE;
+	if (message_type)
+		g_hash_table_insert (bus->priv->types, identifier, message_type);
+	else
+		g_free (identifier);
 	
-	policy->policies = g_list_reverse (policy->policies);
-	g_hash_table_insert (bus->priv->policies, identifier, policy);
+	g_signal_emit (bus, message_bus_signals[REGISTERED], 0, message_type);
+	return message_type;	
 }
 
+/**
+ * gedit_message_bus_unregister:
+ * @bus: a #GeditMessageBus
+ * @message_type: the #GeditMessageType to unregister
+ *
+ * Unregisters a previously registered message type. This is especially useful 
+ * for plugins which should unregister message types when they are deactivated.
+ *
+ * This function emits the #GeditMessageBus::unregistered signal
+ *
+ */
 void
-gedit_message_bus_unregister (GeditMessageBus *bus,
-			      const gchar     *domain,
-			      const gchar     *name)
+gedit_message_bus_unregister (GeditMessageBus  *bus,
+			      GeditMessageType *message_type)
 {
 	gchar *identifier;
 	
 	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
 
-	identifier = msg_identifier (domain, name);
-	g_hash_table_remove (bus->priv->policies, name);
+	identifier = gedit_message_type_identifier (gedit_message_type_get_object_path (message_type), 
+						    gedit_message_type_get_method (message_type));
+	
+	// Keep message type alive for signal emission
+	gedit_message_type_ref (message_type);
+
+	if (g_hash_table_remove (bus->priv->types, identifier))
+		g_signal_emit (bus, message_bus_signals[UNREGISTERED], 0, message_type);
+	
+	gedit_message_type_unref (message_type);
 	g_free (identifier);
 }
 
+typedef struct 
+{
+	GeditMessageBus *bus;
+	const gchar *object_path;
+} UnregisterInfo;
+
+static void
+unregister_each (const gchar      *identifier,
+		 GeditMessageType *message_type,
+		 UnregisterInfo   *info)
+{
+	if (strcmp (gedit_message_type_get_object_path (message_type),
+		    info->object_path) == 0)
+	{	
+		gedit_message_bus_unregister (info->bus, message_type);
+	}
+}
+
+/**
+ * gedit_message_bus_unregister_all:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ *
+ * Unregisters all message types for @object_path. This is especially useful for
+ * plugins which should unregister message types when they are deactivated.
+ *
+ * This function emits the #GeditMessageBus::unregistered signal for all
+ * unregistered message types
+ *
+ */
 void
 gedit_message_bus_unregister_all (GeditMessageBus *bus,
-			          const gchar     *domain)
+			          const gchar     *object_path)
 {
-	GList *pols;
-	GList *item;
+	UnregisterInfo info = {bus, object_path};
+
 	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+	g_return_if_fail (object_path != NULL);
 
-	pols = g_hash_table_get_values (bus->priv->policies);
-	
-	for (item = pols; item; item = item->next)
-	{
-		Policy *policy = (Policy *)item->data;
-		
-		if (strcmp (policy->domain, domain) == 0)
-		{
-			gchar *identifier = msg_identifier (policy->domain, policy->name);
-			g_hash_table_remove (bus->priv->policies, identifier);
-			g_free (identifier);
-		}
-	}
+	g_hash_table_foreach (bus->priv->types, 
+			      (GHFunc)unregister_each,
+			      &info);
+}
+
+/**
+ * gedit_message_bus_is_registered:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ *
+ * Check whether a message type @method at @object_path is registered on the 
+ * bus
+ *
+ * Return value: %TRUE if the @method at @object_path is a registered message 
+ *               type on the bus
+ *
+ */
+gboolean
+gedit_message_bus_is_registered (GeditMessageBus	*bus,
+				 const gchar	*object_path,
+				 const gchar	*method)
+{
+	gchar *identifier;
+	gboolean ret;
 	
-	g_list_free (pols);
-}
-
+	g_return_val_if_fail (GEDIT_IS_MESSAGE_BUS (bus), FALSE);
+	g_return_val_if_fail (object_path != NULL, FALSE);
+	g_return_val_if_fail (method != NULL, FALSE);
+
+	identifier = gedit_message_type_identifier (object_path, method);
+	ret = g_hash_table_lookup (bus->priv->types, identifier) != NULL;
+	
+	g_free(identifier);
+	return ret;
+}
+
+/**
+ * gedit_message_bus_connect:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ * @callback: function to be called when message @method at @object_path is sent
+ * @userdata: userdata to use for the callback
+ * @destroy_data: function to evoke with @userdata as argument when @userdata
+ *                needs to be freed
+ *
+ * Connect a callback handler to be evoked when message @method at @object_path
+ * is sent over the bus.
+ *
+ * Return value: the callback identifier
+ *
+ */
 guint
 gedit_message_bus_connect (GeditMessageBus	*bus, 
-		           const gchar		*domain,
-		           const gchar		*name,
+		           const gchar		*object_path,
+		           const gchar		*method,
 		           GeditMessageCallback  callback,
 		           gpointer		 userdata,
 		           GDestroyNotify	 destroy_data)
@@ -546,16 +693,24 @@
 	Message *message;
 
 	g_return_val_if_fail (GEDIT_IS_MESSAGE_BUS (bus), 0);
-	g_return_val_if_fail (domain != NULL, 0);
-	g_return_val_if_fail (name != NULL, 0);
+	g_return_val_if_fail (object_path != NULL, 0);
+	g_return_val_if_fail (method != NULL, 0);
 	g_return_val_if_fail (callback != NULL, 0);
 	
 	/* lookup the message and create if it does not exist yet */
-	message = lookup_message (bus, domain, name, TRUE);
+	message = lookup_message (bus, object_path, method, TRUE);
 	
 	return add_listener (bus, message, callback, userdata, destroy_data);
 }
 
+/**
+ * gedit_message_bus_disconnect:
+ * @bus: a #GeditMessageBus
+ * @id: the callback id as returned by #gedit_message_bus_connect
+ *
+ * Disconnects a previously connected message callback
+ *
+ */
 void
 gedit_message_bus_disconnect (GeditMessageBus *bus,
 			      guint            id)
@@ -565,18 +720,40 @@
 	process_by_id (bus, id, remove_listener);
 }
 
+/**
+ * gedit_message_bus_disconnect_by_func:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ * @callback: the connected callback
+ * @userdata: the userdata with which the callback was connected
+ *
+ * Disconnects a previously connected message callback by matching the 
+ * provided callback function and userdata. See also 
+ * #gedit_message_bus_disconnect
+ *
+ */
 void
 gedit_message_bus_disconnect_by_func (GeditMessageBus      *bus,
-				      const gchar	   *domain,
-				      const gchar	   *name,
+				      const gchar	   *object_path,
+				      const gchar	   *method,
 				      GeditMessageCallback  callback,
 				      gpointer		    userdata)
 {
 	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
 	
-	process_by_match (bus, domain, name, callback, userdata, remove_listener);
+	process_by_match (bus, object_path, method, callback, userdata, remove_listener);
 }
 
+/**
+ * gedit_message_bus_block:
+ * @bus: a #GeditMessageBus
+ * @id: the callback id
+ *
+ * Blocks evoking the callback specified by @id. Unblock the callback by
+ * using #gedit_message_bus_unblock
+ *
+ */
 void
 gedit_message_bus_block (GeditMessageBus *bus,
 			 guint		  id)
@@ -586,18 +763,38 @@
 	process_by_id (bus, id, block_listener);
 }
 
+/**
+ * gedit_message_bus_block_by_func:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ * @callback: the callback to block
+ * @userdata: the userdata with which the callback was connected
+ *
+ * Blocks evoking the callback that matches provided @callback and @userdata.
+ * Unblock the callback using #gedit_message_unblock_by_func
+ *
+ */
 void
 gedit_message_bus_block_by_func (GeditMessageBus      *bus,
-				 const gchar	      *domain,
-				 const gchar	      *name,
+				 const gchar	      *object_path,
+				 const gchar	      *method,
 				 GeditMessageCallback  callback,
 				 gpointer	       userdata)
 {
 	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
 	
-	process_by_match (bus, domain, name, callback, userdata, block_listener);
+	process_by_match (bus, object_path, method, callback, userdata, block_listener);
 }
 
+/**
+ * gedit_message_bus_unblock:
+ * @bus: a #GeditMessageBus
+ * @id: the callback id
+ *
+ * Unblocks the callback specified by @id
+ *
+ */
 void
 gedit_message_bus_unblock (GeditMessageBus *bus,
 			   guint	    id)
@@ -607,81 +804,50 @@
 	process_by_id (bus, id, unblock_listener);
 }
 
+/**
+ * gedit_message_bus_unblock_by_func:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ * @callback: the callback to block
+ * @userdata: the userdata with which the callback was connected
+ *
+ * Unblocks the callback that matches provided @callback and @userdata
+ *
+ */
 void
 gedit_message_bus_unblock_by_func (GeditMessageBus      *bus,
-				   const gchar	        *domain,
-				   const gchar	        *name,
+				   const gchar	        *object_path,
+				   const gchar	        *method,
 				   GeditMessageCallback  callback,
 				   gpointer	         userdata)
 {
 	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
 	
-	process_by_match (bus, domain, name, callback, userdata, unblock_listener);
+	process_by_match (bus, object_path, method, callback, userdata, unblock_listener);
 }
 
 static gboolean
-check_message_policy (GeditMessageBus *bus,
-		      GeditMessage    *message)
+validate_message (GeditMessage *message)
 {
-	const gchar *domain = gedit_message_get_domain (message);
-	const gchar *name = gedit_message_get_name (message);
-	
-	gchar *identifier = msg_identifier (domain, name);
-	Policy *policy = (Policy *)g_hash_table_lookup (bus->priv->policies, identifier);
-	PolicyItem *pitem;
-	GList *item;
-	
-	g_free (identifier);
-
-	if (policy == NULL)
+	if (!gedit_message_validate (message))
 	{
-		g_warning ("Policy for '%s::%s' could not be found", domain, name);
+		g_warning ("Message '%s.%s' is invalid", gedit_message_get_object_path (message),
+							 gedit_message_get_method (message));
 		return FALSE;
 	}
 	
-	/* check all required and optional arguments */
-	for (item = policy->policies; item; item = item->next)
-	{
-		GType gtype;
-		gboolean haskey;
-		
-		pitem = (PolicyItem *)item->data;
-		
-		/* check if key exists */
-		haskey = gedit_message_has_key (message, pitem->key);
-		
-		if (pitem->required && !haskey)
-		{
-			g_warning ("Required key %s not found for %s::%s", pitem->key, domain, name);
-			return FALSE;
-		}
-		else if (!haskey && !pitem->required)
-		{
-			continue;
-		}
-		
-		gtype = gedit_message_get_key_type (message, pitem->key);
-		
-		if (!g_type_is_a (pitem->type, gtype) && 
-		    !g_value_type_transformable (pitem->type, gtype))
-		{
-			g_warning ("Invalid key type for %s::%s, expected %s, got %s", domain, name, g_type_name (pitem->type), g_type_name (gtype));
-			return FALSE;
-		}
-	}
-	
 	return TRUE;
 }
 
-void
-gedit_message_bus_send_message (GeditMessageBus *bus,
-			        GeditMessage    *message)
+static void
+send_message_real (GeditMessageBus *bus,
+		   GeditMessage    *message)
 {
-	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
-	g_return_if_fail (GEDIT_IS_MESSAGE (message));
-	
-	if (!check_message_policy (bus, message))
+	if (!validate_message (message))
+	{
 		return;
+	}
 	
 	bus->priv->message_queue = g_list_prepend (bus->priv->message_queue, 
 						   g_object_ref (message));
@@ -693,249 +859,153 @@
 						      NULL);
 }
 
+/**
+ * gedit_message_bus_send_message:
+ * @bus: a #GeditMessageBus
+ * @message: the message to send
+ *
+ * This sends the provided @message asynchronously over the bus. To send
+ * a message synchronously, use #gedit_message_bus_send_message_sync. The 
+ * convenience function #gedit_message_bus_send can be used to easily send
+ * a message without constructing the message object explicitly first.
+ *
+ */
 void
-gedit_message_bus_send_message_sync (GeditMessageBus *bus,
-			             GeditMessage    *message)
+gedit_message_bus_send_message (GeditMessageBus *bus,
+			        GeditMessage    *message)
 {
 	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
 	g_return_if_fail (GEDIT_IS_MESSAGE (message));
 	
-	if (!check_message_policy (bus, message))
-		return;
-
-	dispatch_message (bus, message);
+	send_message_real (bus, message);
 }
 
-static GType
-policy_find_type (Policy      *policy, 
-		  const gchar *key)
+static void
+send_message_sync_real (GeditMessageBus *bus,
+                        GeditMessage    *message)
 {
-	GList *item;
-	
-	for (item = policy->policies; item; item = item->next)
+	if (!validate_message (message))
 	{
-		PolicyItem *pitem = (PolicyItem *)item->data;
-		
-		if (strcmp (pitem->key, key) == 0)
-			return pitem->type;
+		return;
 	}
 	
-	return 0;
+	dispatch_message (bus, message);
+}
+
+/**
+ * gedit_message_bus_send_message:
+ * @bus: a #GeditMessageBus
+ * @message: the message to send
+ *
+ * This sends the provided @message synchronously over the bus. To send
+ * a message asynchronously, use #gedit_message_bus_send_message. The 
+ * convenience function #gedit_message_bus_send_sync can be used to easily send
+ * a message without constructing the message object explicitly first.
+ *
+ */
+void
+gedit_message_bus_send_message_sync (GeditMessageBus *bus,
+			             GeditMessage    *message)
+{
+	g_return_if_fail (GEDIT_IS_MESSAGE_BUS (bus));
+	g_return_if_fail (GEDIT_IS_MESSAGE (message));
+
+	send_message_sync_real (bus, message);	
 }
 
 static GeditMessage *
 create_message (GeditMessageBus *bus,
-		const gchar     *domain,
-		const gchar     *name,
+		const gchar     *object_path,
+		const gchar     *method,
 		va_list          var_args)
 {
-	const gchar **keys = NULL;
-	GType *types = NULL;
-	GValue *values = NULL;
-	gint num = 0;
-	const gchar *key;
-	gchar *identifier;
-	GeditMessage *message;
-	Policy *policy;
-	gint i;
+	GeditMessageType *message_type;
 	
-	identifier = msg_identifier (domain, name);
-	policy = g_hash_table_lookup (bus->priv->policies, identifier);
-	g_free (identifier);
+	message_type = gedit_message_bus_lookup (bus, object_path, method);
 	
-	if (policy == NULL)
+	if (!message_type)
 	{
-		g_warning ("Policy for %s::%s not found", domain, name);
+		g_warning ("Could not find message type for '%s.%s'", object_path, method);
 		return NULL;
 	}
-	
-	while ((key = va_arg (var_args, const gchar *)) != NULL)
-	{
-		gchar *error = NULL;
-		GType gtype;
-		GValue value = {0,};
-		
-		gtype = policy_find_type (policy, key);
-		
-		if (!gtype)
-		{
-			g_warning ("Key %s not registered in policy for %s::%s", key, domain, name);
-			return NULL;
-		}
-		
-		g_value_init (&value, gtype);
-		G_VALUE_COLLECT (&value, var_args, 0, &error);
-		
-		if (error)
-		{
-			g_warning ("%s: %s", G_STRLOC, error);
-			g_free (error);
-			
-			/* leak value, might have gone bad */
-			continue;
-		}
-		
-		num++;
-		
-		keys = g_realloc (keys, sizeof(gchar *) * num);
-		types = g_realloc (types, sizeof(GType) * num);
-		values = g_realloc (values, sizeof(GValue) * num);
-		
-		keys[num - 1] = key;
-		types[num - 1] = gtype;
-		
-		memset (&values[num - 1], 0, sizeof(GValue));
-		g_value_init (&values[num - 1], types[num - 1]);
-		g_value_copy (&value, &values[num - 1]);
-		
-		g_value_unset (&value);
-	}
-		
-	message = gedit_message_new (domain, name, NULL);
-	gedit_message_set_types (message, keys, types, num);
-	gedit_message_set_valuesv (message, keys, values, num);
-	
-	g_free (keys);
-	g_free (types);
-	
-	for (i = 0; i < num; i++)
-		g_value_unset (&values[i]);
 
-	g_free (values);
-	
-	return message;
+	return gedit_message_type_instantiate_valist (message_type, 
+						      var_args);
 }
 
+/**
+ * gedit_message_bus_send:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ * @...: NULL terminated list of key/value pairs
+ *
+ * This provides a convenient way to quickly send a message @method at 
+ * @object_path asynchronously over the bus. @... specifies key (string) value 
+ * pairs used to construct the message arguments. To send a message 
+ * synchronously use #gedit_message_bus_send_sync
+ *
+ */
 void
 gedit_message_bus_send (GeditMessageBus *bus,
-			const gchar     *domain,
-			const gchar     *name,
+			const gchar     *object_path,
+			const gchar     *method,
 			...)
 {
 	va_list var_args;
 	GeditMessage *message;
 	
-	va_start (var_args, name);
+	va_start (var_args, method);
 
-	message = create_message (bus, domain, name, var_args);
+	message = create_message (bus, object_path, method, var_args);
 	
 	if (message)
 	{
-		gedit_message_bus_send_message (bus, message);
+		send_message_real (bus, message);
 		g_object_unref (message);
 	}
+	else
+	{
+		g_warning ("Could not instantiate message");
+	}
 
 	va_end (var_args);
 }
 
+/**
+ * gedit_message_bus_send_sync:
+ * @bus: a #GeditMessageBus
+ * @object_path: the object path
+ * @method: the method
+ * @...: NULL terminated list of key/value pairs
+ *
+ * This provides a convenient way to quickly send a message @method at 
+ * @object_path synchronously over the bus. @... specifies key (string) value 
+ * pairs used to construct the message arguments. To send a message 
+ * asynchronously use #gedit_message_bus_send
+ *
+ * Return value: the constructed #GeditMessage. The caller owns a reference
+ *               to the #GeditMessage and should call g_object_unref when
+ *               it is no longer needed.
+ */
 GeditMessage *
 gedit_message_bus_send_sync (GeditMessageBus *bus,
-			     const gchar     *domain,
-			     const gchar     *name,
+			     const gchar     *object_path,
+			     const gchar     *method,
 			     ...)
 {
 	va_list var_args;
 	GeditMessage *message;
 	
-	va_start (var_args, name);
-	message = create_message (bus, domain, name, var_args);
+	va_start (var_args, method);
+	message = create_message (bus, object_path, method, var_args);
 	
 	if (message)
-		gedit_message_bus_send_message_sync (bus, message);
+		send_message_sync_real (bus, message);
 
 	va_end (var_args);
 	
 	return message;
 }
 
-typedef struct
-{
-	gchar *domain;
-	gchar *name;
-	GeditMessageBus *bus;
-} PropertyProxy;
-
-static void
-property_proxy_message (GObject         *object,
-			GParamSpec      *spec,
-			PropertyProxy   *proxy)
-{
-	GeditMessage *message;
-	GValue value = {0,};
-	
-	message = gedit_message_new (proxy->domain,
-				     proxy->name,
-				     spec->name, spec->value_type,
-				     NULL);
-
-	g_value_init (&value, spec->value_type);
-	g_object_get_property (object, spec->name, &value);
-	gedit_message_set_value (message, spec->name, &value);
-	    
-	gedit_message_bus_send_message (proxy->bus, message);
-
-	g_object_unref (message);
-	g_value_unset (&value);
-}
-
-static PropertyProxy *
-property_proxy_new (GeditMessageBus *bus,
-		    const gchar     *domain,
-		    const gchar     *name)
-{
-	PropertyProxy *proxy;
-	
-	proxy = g_new (PropertyProxy, 1);
-	proxy->domain = g_strdup (domain);
-	proxy->name = g_strdup (name);
-	proxy->bus = bus;
-	
-	return proxy;
-}
-
-static void
-property_proxy_free (PropertyProxy *proxy,
-		     GClosure      *closure)
-{
-	g_free (proxy->domain);
-	g_free (proxy->name);
-	g_free (proxy);
-}
-
-void 
-gedit_message_bus_proxy_property (GeditMessageBus *bus,
-				  const gchar     *domain,
-				  const gchar     *name,
-				  GObject	  *object,
-				  const gchar 	  *property)
-{
-	GParamSpec *spec;
-	gchar *detailed;
-	
-	spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), 
-					     property);
-
-	if (!spec)
-	{
-		g_warning ("Could not connect proxy because property `%s' does not exist for %s", 
-			   property,
-			   g_type_name (G_OBJECT_TYPE (object)));
-		return;
-	}
-	
-	if (!_gedit_message_gtype_supported (spec->value_type))
-	{
-		g_warning ("Type of property `%s' is not supported on the message bus",
-			   g_type_name (spec->value_type));
-		return;
-	}
-	
-	detailed = g_strconcat ("notify::", property, NULL);
-	g_signal_connect_data (object, 
-			       detailed, 
-			       G_CALLBACK (property_proxy_message), 
-			       property_proxy_new (bus, domain, name),
-			       (GClosureNotify)property_proxy_free,
-			       0);
-	g_free (detailed);
-}
+// ex:ts=8:noet:

Modified: branches/message_system/gedit/gedit-message-bus.h
==============================================================================
--- branches/message_system/gedit/gedit-message-bus.h	(original)
+++ branches/message_system/gedit/gedit-message-bus.h	Sat Dec 27 13:07:00 2008
@@ -3,6 +3,7 @@
 
 #include <glib-object.h>
 #include <gedit/gedit-message.h>
+#include <gedit/gedit-message-type.h>
 
 G_BEGIN_DECLS
 
@@ -27,36 +28,49 @@
 struct _GeditMessageBusClass {
 	GObjectClass parent_class;
 	
-	void (*dispatch)	(GeditMessageBus *bus,
-				 GeditMessage    *message);
+	void (*dispatch)			(GeditMessageBus  *bus,
+					 GeditMessage     *message);
+	void (*registered)		(GeditMessageBus  *bus,
+					 GeditMessageType *message_type);
+	void (*unregistered)		(GeditMessageBus  *bus,
+					 GeditMessageType *message_type);
 };
 
-typedef void (* GeditMessageCallback) 	(GeditMessageBus	*bus,
-					 GeditMessage		*message,
-					 gpointer		 userdata);
+typedef void (* GeditMessageCallback) 	(GeditMessageBus	 *bus,
+					 GeditMessage	 *message,
+					 gpointer	  userdata);
 
 GType gedit_message_bus_get_type (void) G_GNUC_CONST;
 
-GeditMessageBus *gedit_message_bus_get_default 	  (void);
+GeditMessageBus *gedit_message_bus_get_default	(void);
+GeditMessageBus *gedit_message_bus_new		(void);
 
 /* registering messages */
-void gedit_message_bus_register    	  (GeditMessageBus	*bus,
-					   const gchar 		*domain,
-					   const gchar		*name,
-					   guint		 num_optional,
-					   ...) G_GNUC_NULL_TERMINATED;
+GeditMessageType *gedit_message_bus_lookup	(GeditMessageBus 	*bus,
+						 const gchar		*object_path,
+						 const gchar		*method);
+GeditMessageType *gedit_message_bus_register	(GeditMessageBus		*bus,
+					   	 const gchar 		*object_path,
+					  	 const gchar		*method,
+					  	 guint		 	 num_optional,
+					  	 ...) G_GNUC_NULL_TERMINATED;
 
 void gedit_message_bus_unregister	  (GeditMessageBus	*bus,
-					   const gchar 		*domain,
-					   const gchar		*name);
+					   GeditMessageType	*message_type);
 
 void gedit_message_bus_unregister_all	  (GeditMessageBus	*bus,
-					   const gchar		*domain);
+					   const gchar		*object_path);
+
+gboolean gedit_message_bus_is_registered	  (GeditMessageBus	*bus,
+					   const gchar		*object_path,
+					   const gchar		*method);
+
+
 
 /* connecting to message events */		   
 guint gedit_message_bus_connect	 	  (GeditMessageBus	*bus, 
-					   const gchar		*domain,
-					   const gchar		*name,
+					   const gchar		*object_path,
+					   const gchar		*method,
 					   GeditMessageCallback	 callback,
 					   gpointer		 userdata,
 					   GDestroyNotify        destroy_data);
@@ -65,8 +79,8 @@
 					   guint		 id);
 
 void gedit_message_bus_disconnect_by_func (GeditMessageBus	*bus,
-					   const gchar		*domain,
-					   const gchar		*name,
+					   const gchar		*object_path,
+					   const gchar		*method,
 					   GeditMessageCallback	 callback,
 					   gpointer		 userdata);
 
@@ -74,42 +88,36 @@
 void gedit_message_bus_block		  (GeditMessageBus	*bus,
 					   guint		 id);
 void gedit_message_bus_block_by_func	  (GeditMessageBus	*bus,
-					   const gchar		*domain,
-					   const gchar		*name,
+					   const gchar		*object_path,
+					   const gchar		*method,
 					   GeditMessageCallback	 callback,
 					   gpointer		 userdata);
 
 void gedit_message_bus_unblock		  (GeditMessageBus	*bus,
 					   guint		 id);
 void gedit_message_bus_unblock_by_func	  (GeditMessageBus	*bus,
-					   const gchar		*domain,
-					   const gchar		*name,
+					   const gchar		*object_path,
+					   const gchar		*method,
 					   GeditMessageCallback	 callback,
 					   gpointer		 userdata);
 
 /* sending messages */
 void gedit_message_bus_send_message	  (GeditMessageBus	*bus,
 					   GeditMessage		*message);
-
 void gedit_message_bus_send_message_sync  (GeditMessageBus	*bus,
 					   GeditMessage		*message);
 					  
 void gedit_message_bus_send		  (GeditMessageBus	*bus,
-					   const gchar		*domain,
-					   const gchar		*name,
+					   const gchar		*object_path,
+					   const gchar		*method,
 					   ...) G_GNUC_NULL_TERMINATED;
 GeditMessage *gedit_message_bus_send_sync (GeditMessageBus	*bus,
-					   const gchar		*domain,
-					   const gchar		*name,
+					   const gchar		*object_path,
+					   const gchar		*method,
 					   ...) G_GNUC_NULL_TERMINATED;
 
-/* automatic property proxy over the bus */
-void gedit_message_bus_proxy_property	  (GeditMessageBus 	*bus,
-					   const gchar          *domain,
-					   const gchar          *name,
-					   GObject		*object,
-					   const gchar 		*property);
-
 G_END_DECLS
 
 #endif /* __GEDIT_MESSAGE_BUS_H__ */
+
+// ex:ts=8:noet:

Added: branches/message_system/gedit/gedit-message-type.c
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/gedit-message-type.c	Sat Dec 27 13:07:00 2008
@@ -0,0 +1,428 @@
+#include "gedit-message-type.h"
+
+typedef struct
+{
+	GType type;
+	gboolean required;
+} ArgumentInfo;
+
+struct _GeditMessageType
+{
+	gint ref_count;
+
+	gchar *object_path;
+	gchar *method;
+	
+	guint num_arguments;
+	guint num_required;
+	
+	GHashTable *arguments; // mapping of key -> ArgumentInfo
+};
+
+/**
+ * gedit_message_type_unref:
+ * @message_type: the #GeditMessageType
+ *
+ * Increases the reference count on @message_type
+ *
+ * Return value: @message_type
+ *
+ */
+GeditMessageType *
+gedit_message_type_ref (GeditMessageType *message_type)
+{
+	g_return_val_if_fail (message_type != NULL, NULL);
+	g_atomic_int_inc (&message_type->ref_count);
+	
+	return message_type;
+}
+
+/**
+ * gedit_message_type_unref:
+ * @message_type: the #GeditMessageType
+ *
+ * Decreases the reference count on @message_type. When the reference count
+ * drops to 0, @message_type is destroyed
+ *
+ */
+void 
+gedit_message_type_unref (GeditMessageType *message_type)
+{
+	g_return_if_fail (message_type != NULL);
+
+	if (!g_atomic_int_dec_and_test (&message_type->ref_count))
+		return;
+	
+	g_free (message_type->object_path);
+	g_free (message_type->method);
+	
+	g_hash_table_destroy (message_type->arguments);
+	g_free (message_type);
+}
+
+/**
+ * gedit_message_type_get_type:
+ * 
+ * Retrieves the GType object which is associated with the
+ * #GeditMessageType class.
+ * 
+ * Return value: the GType associated with #GeditMessageType.
+ **/
+GType 
+gedit_message_type_get_type (void)
+{
+	static GType our_type = 0;
+
+	if (!our_type)
+		our_type = g_boxed_type_register_static (
+			"GeditMessageType",
+			(GBoxedCopyFunc) gedit_message_type_ref,
+			(GBoxedFreeFunc) gedit_message_type_unref);
+
+	return our_type;
+}
+
+/**
+ * gedit_message_type_identifier:
+ * @object_path: the object path
+ * @method: the method
+ *
+ * Get the string identifier for @method at @object_path
+ *
+ * Return value: the identifier for @method at @object_path
+ *
+ */
+gchar *
+gedit_message_type_identifier (const gchar *object_path,
+			       const gchar *method)
+{
+	return g_strconcat (object_path, ".", method, NULL);
+}
+
+/**
+ * gedit_message_type_is_supported:
+ * @type: the #GType
+ *
+ * Returns if @type is #GType supported by the message system
+ *
+ * Return value: %TRUE if @type is a supported #GType
+ *
+ */
+gboolean
+gedit_message_type_is_supported (GType type)
+{
+	gint i = 0;
+  
+	static const GType type_list[] =
+	{
+		G_TYPE_BOOLEAN,
+		G_TYPE_CHAR,
+		G_TYPE_UCHAR,
+		G_TYPE_INT,
+		G_TYPE_UINT,
+		G_TYPE_LONG,
+		G_TYPE_ULONG,
+		G_TYPE_INT64,
+		G_TYPE_UINT64,
+		G_TYPE_ENUM,
+		G_TYPE_FLAGS,
+		G_TYPE_FLOAT,
+		G_TYPE_DOUBLE,
+		G_TYPE_STRING,
+		G_TYPE_POINTER,
+		G_TYPE_BOXED,
+		G_TYPE_OBJECT,
+		G_TYPE_INVALID
+	};
+
+	if (!G_TYPE_IS_VALUE_TYPE (type))
+		return FALSE;
+
+	while (type_list[i] != G_TYPE_INVALID)
+	{
+		if (g_type_is_a (type, type_list[i]))
+			return TRUE;
+		i++;
+	}
+
+	return FALSE;
+}
+
+/**
+ * gedit_message_type_newv:
+ * @object_path: the object path
+ * @method: the method
+ * @num_optional: number of optional arguments
+ * @var_args: key/gtype pair variable argument list
+ *
+ * Create a new #GeditMessageType for @method at @object_path. Argument names
+ * and values are supplied by the NULL terminated variable argument list.
+ * The last @num_optional provided arguments are considered optional
+ *
+ * Return value: the newly constructed #GeditMessageType
+ *
+ */
+GeditMessageType *
+gedit_message_type_new_valist (const gchar *object_path,
+			       const gchar *method,
+			       guint        num_optional,
+			       va_list      var_args)
+{
+	GeditMessageType *message_type;
+
+	g_return_val_if_fail (object_path != NULL, NULL);
+	g_return_val_if_fail (method != NULL, NULL);
+
+	message_type = g_new(GeditMessageType, 1);
+	
+	message_type->object_path = g_strdup(object_path);
+	message_type->method = g_strdup(method);
+	message_type->num_arguments = 0;
+	message_type->arguments = g_hash_table_new_full (g_str_hash,
+							 g_str_equal,
+							 (GDestroyNotify)g_free,
+							 (GDestroyNotify)g_free);
+
+	gedit_message_type_set_valist (message_type, num_optional, var_args);
+	return message_type;
+}
+
+/**
+ * gedit_message_type_newv:
+ * @object_path: the object path
+ * @method: the method
+ * @num_optional: number of optional arguments
+ * @...: key/gtype pair variable argument list
+ *
+ * Create a new #GeditMessageType for @method at @object_path. Argument names
+ * and values are supplied by the NULL terminated variable argument list.
+ * The last @num_optional provided arguments are considered optional
+ *
+ * Return value: the newly constructed #GeditMessageType
+ *
+ */
+GeditMessageType *
+gedit_message_type_new (const gchar *object_path,
+			const gchar *method,
+			guint        num_optional,
+			...)
+{
+	GeditMessageType *message_type;
+	va_list var_args;
+	
+	va_start(var_args, num_optional);
+	message_type = gedit_message_type_new_valist (object_path, method, num_optional, var_args);
+	va_end(var_args);
+	
+	return message_type;
+}
+
+void
+gedit_message_type_set (GeditMessageType *message_type,
+			guint		 num_optional,
+			...)
+{
+	va_list va_args;
+	
+	va_start (va_args, num_optional);
+	gedit_message_type_set_valist (message_type, num_optional, va_args);
+	va_end (va_args);
+}
+
+void 
+gedit_message_type_set_valist (GeditMessageType *message_type,
+			       guint             num_optional,
+			       va_list	         var_args)
+{
+	const gchar *key;
+	ArgumentInfo **optional = g_new0(ArgumentInfo *, num_optional);
+	guint i;
+	guint added = 0;
+
+	// parse key -> gtype pair arguments
+	while ((key = va_arg (var_args, const gchar *)) != NULL)
+	{
+		// get corresponding GType
+		GType gtype = va_arg (var_args, GType);
+		ArgumentInfo *info;
+		
+		if (!gedit_message_type_is_supported (gtype))
+		{
+			g_error ("Message type '%s' is not supported", g_type_name (gtype));
+
+			gedit_message_type_unref (message_type);
+			g_free (optional);
+			
+			return;
+		}
+		
+		info = g_new(ArgumentInfo, 1);
+		info->type = gtype;
+		info->required = TRUE;
+
+		g_hash_table_insert (message_type->arguments, g_strdup (key), info);
+		
+		++message_type->num_arguments;
+		++added;
+		
+		if (num_optional > 0)
+		{
+			for (i = 0; i < num_optional - 1; ++i)
+			{
+				optional[i + 1] = optional[i];
+			}
+		
+			*optional = info;
+		}
+	}
+	
+	message_type->num_required += added;
+
+	// set required for last num_optional arguments
+	for (i = 0; i < num_optional; ++i)
+	{
+		if (optional[i])
+		{
+			optional[i]->required = FALSE;
+			--message_type->num_required;
+		}
+	}
+	
+	g_free (optional);
+}
+
+/**
+ * gedit_message_type_instantiate:
+ * @message_type: the #GeditMessageType
+ * @va_args: NULL terminated variable list of key/value pairs
+ *
+ * Instantiate a new message from the message type with specific values
+ * for the message arguments
+ *
+ * Return value: the newly created message
+ *
+ */
+GeditMessage *
+gedit_message_type_instantiate_valist (GeditMessageType *message_type,
+				       va_list		 va_args)
+{
+	GeditMessage *message;
+	
+	g_return_val_if_fail (message_type != NULL, NULL);
+	
+	message = GEDIT_MESSAGE (g_object_new (GEDIT_TYPE_MESSAGE, "type", message_type, NULL));
+	gedit_message_set_valist (message, va_args);
+	
+	return message;
+}
+
+/**
+ * gedit_message_type_instantiate:
+ * @message_type: the #GeditMessageType
+ * @...: NULL terminated variable list of key/value pairs
+ *
+ * Instantiate a new message from the message type with specific values
+ * for the message arguments
+ *
+ * Return value: the newly created message
+ *
+ */
+GeditMessage *
+gedit_message_type_instantiate (GeditMessageType *message_type,
+				...)
+{
+	GeditMessage *message;
+	va_list va_args;
+	
+	va_start (va_args, message_type);
+	message = gedit_message_type_instantiate_valist (message_type, va_args);
+	va_end (va_args);
+	
+	return message;
+}
+
+/**
+ * gedit_message_type_get_object_path:
+ * @message_type: the #GeditMessageType
+ *
+ * Get the message type object path
+ *
+ * Return value: the message type object path
+ *
+ */
+const gchar *
+gedit_message_type_get_object_path (GeditMessageType *message_type)
+{
+	return message_type->object_path;
+}
+
+/**
+ * gedit_message_type_get_method:
+ * @message_type: the #GeditMessageType
+ *
+ * Get the message type method
+ *
+ * Return value: the message type method
+ *
+ */
+const gchar *
+gedit_message_type_get_method (GeditMessageType *message_type)
+{
+	return message_type->method;
+}
+
+/**
+ * gedit_message_type_lookup:
+ * @message_type: the #GeditMessageType
+ * @key: the argument key
+ *
+ * Get the argument key #GType
+ *
+ * Return value: the #GType of @key
+ *
+ */
+GType
+gedit_message_type_lookup (GeditMessageType *message_type,
+			   const gchar      *key)
+{
+	ArgumentInfo *info = g_hash_table_lookup (message_type->arguments, key);
+	
+	if (!info)
+		return G_TYPE_INVALID;
+	
+	return info->type;
+}
+
+typedef struct
+{
+	GeditMessageTypeForeach func;
+	gpointer user_data;
+} ForeachInfo;
+
+static void
+foreach_gtype (const gchar  *key,
+	       ArgumentInfo *info,
+	       ForeachInfo  *finfo)
+{
+	finfo->func (key, info->type, info->required, finfo->user_data);
+}
+
+/**
+ * gedit_message_type_foreach:
+ * @message_type: the #GeditMessageType
+ * @func: the callback function
+ * @user_data: user data supplied to the callback function
+ *
+ * Calls @func for each argument in the message type
+ *
+ */
+void 
+gedit_message_type_foreach (GeditMessageType 	    *message_type,
+			    GeditMessageTypeForeach  func,
+			    gpointer		     user_data)
+{
+	ForeachInfo info = {func, user_data};
+	g_hash_table_foreach (message_type->arguments, (GHFunc)foreach_gtype, &info);
+}
+
+// ex:ts=8:noet:

Added: branches/message_system/gedit/gedit-message-type.h
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/gedit-message-type.h	Sat Dec 27 13:07:00 2008
@@ -0,0 +1,66 @@
+#ifndef __GEDIT_MESSAGE_TYPE_H__
+#define __GEDIT_MESSAGE_TYPE_H__
+
+#include <glib-object.h>
+#include <stdarg.h>
+
+#include "gedit-message.h"
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_MESSAGE_TYPE			(gedit_message_type_get_type ())
+#define GEDIT_MESSAGE_TYPE(x)			((GeditMessageType *)(x))
+
+typedef void (*GeditMessageTypeForeach)		(const gchar *key, 
+						 GType 	      type, 
+						 gboolean     required, 
+						 gpointer     user_data);
+
+typedef struct _GeditMessageType			GeditMessageType;
+
+GType gedit_message_type_get_type 		(void) G_GNUC_CONST;
+
+gboolean gedit_message_type_is_supported 	(GType type);
+gchar *gedit_message_type_identifier		(const gchar *object_path,
+						 const gchar *method);
+
+GeditMessageType *gedit_message_type_new		(const gchar *object_path, 
+						 const gchar *method,
+						 guint	      num_optional,
+						 ...) G_GNUC_NULL_TERMINATED;
+GeditMessageType *gedit_message_type_new_valist	(const gchar *object_path,
+						 const gchar *method,
+						 guint	      num_optional,
+						 va_list      va_args);
+
+void gedit_message_type_set			(GeditMessageType *message_type,
+						 guint		   num_optional,
+						 ...) G_GNUC_NULL_TERMINATED;
+void gedit_message_type_set_valist		(GeditMessageType *message_type,
+						 guint		   num_optional,
+						 va_list	           va_args);
+
+GeditMessageType *gedit_message_type_ref 	(GeditMessageType *message_type);
+void gedit_message_type_unref			(GeditMessageType *message_type);
+
+
+GeditMessage *gedit_message_type_instantiate_valist (GeditMessageType *message_type,
+				       		     va_list	      va_args);
+GeditMessage *gedit_message_type_instantiate 	(GeditMessageType *message_type,
+				       		 ...) G_GNUC_NULL_TERMINATED;
+
+const gchar *gedit_message_type_get_object_path	(GeditMessageType *message_type);
+const gchar *gedit_message_type_get_method	(GeditMessageType *message_type);
+
+GType gedit_message_type_lookup			(GeditMessageType *message_type,
+						 const gchar      *key);
+						 
+void gedit_message_type_foreach 			(GeditMessageType 	 *message_type,
+						 GeditMessageTypeForeach  func,
+						 gpointer	   	  user_data);
+
+G_END_DECLS
+
+#endif /* __GEDIT_MESSAGE_TYPE_H__ */
+
+// ex:ts=8:noet:

Modified: branches/message_system/gedit/gedit-message.c
==============================================================================
--- branches/message_system/gedit/gedit-message.c	(original)
+++ branches/message_system/gedit/gedit-message.c	Sat Dec 27 13:07:00 2008
@@ -1,4 +1,5 @@
 #include "gedit-message.h"
+#include "gedit-message-type.h"
 
 #include <string.h>
 #include <gobject/gvaluecollector.h>
@@ -8,15 +9,16 @@
 enum {
 	PROP_0,
 
-	PROP_DOMAIN,
-	PROP_NAME
+	PROP_OBJECT_PATH,
+	PROP_METHOD,
+	PROP_TYPE
 };
 
 struct _GeditMessagePrivate
 {
-	gchar *domain;
-	gchar *name;
-	
+	GeditMessageType *type;
+	gboolean valid;
+
 	GHashTable *values;
 };
 
@@ -27,9 +29,7 @@
 {
 	GeditMessage *message = GEDIT_MESSAGE (object);
 	
-	g_free (message->priv->domain);
-	g_free (message->priv->name);
-	
+	gedit_message_type_unref (message->priv->type);
 	g_hash_table_destroy (message->priv->values);
 
 	G_OBJECT_CLASS (gedit_message_parent_class)->finalize (object);
@@ -45,11 +45,14 @@
 
 	switch (prop_id)
 	{
-		case PROP_DOMAIN:
-			g_value_set_string (value, msg->priv->domain);
+		case PROP_OBJECT_PATH:
+			g_value_set_string (value, gedit_message_type_get_object_path (msg->priv->type));
 			break;
-		case PROP_NAME:
-			g_value_set_string (value, msg->priv->name);
+		case PROP_METHOD:
+			g_value_set_string (value, gedit_message_type_get_method (msg->priv->type));
+			break;
+		case PROP_TYPE:
+			g_value_set_boxed (value, msg->priv->type);
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -67,11 +70,8 @@
 
 	switch (prop_id)
 	{
-		case PROP_DOMAIN:
-			msg->priv->domain = g_strdup (g_value_get_string (value));
-			break;
-		case PROP_NAME:
-			msg->priv->name = g_strdup (g_value_get_string (value));
+		case PROP_TYPE:
+			msg->priv->type = GEDIT_MESSAGE_TYPE (g_value_dup_boxed (value));
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -79,6 +79,25 @@
 	}
 }
 
+static GValue *
+add_value (GeditMessage *message,
+	   const gchar  *key)
+{
+	GValue *value;
+	GType type = gedit_message_type_lookup (message->priv->type, key);
+	
+	if (type == G_TYPE_INVALID)
+		return NULL;
+	
+	value = g_new0 (GValue, 1);
+	g_value_init (value, type);
+	g_value_reset (value);
+
+	g_hash_table_insert (message->priv->values, g_strdup (key), value);
+	
+	return value;
+}
+
 static void
 gedit_message_class_init (GeditMessageClass *klass)
 {
@@ -88,23 +107,48 @@
 	object_class->get_property = gedit_message_get_property;
 	object_class->set_property = gedit_message_set_property;
 	
-	g_object_class_install_property (object_class, PROP_DOMAIN,
-					 g_param_spec_string ("domain",
-							      "DOMAIN",
-							      "The message domain",
+	/**
+	 * GeditMessage:object_path:
+	 *
+	 * The messages object path (e.g. /gedit/object/path)
+	 *
+	 */
+	g_object_class_install_property (object_class, PROP_OBJECT_PATH,
+					 g_param_spec_string ("object-path",
+							      "OBJECT_PATH",
+							      "The message object path",
 							      NULL,
-							      G_PARAM_READWRITE |
-							      G_PARAM_STATIC_STRINGS |
-							      G_PARAM_CONSTRUCT_ONLY));
-
-	g_object_class_install_property (object_class, PROP_NAME,
-					 g_param_spec_string ("name",
-							      "NAME",
-							      "The message name",
+							      G_PARAM_READABLE |
+							      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * GeditMessage:method:
+	 *
+	 * The messages method
+	 *
+	 */
+	g_object_class_install_property (object_class, PROP_METHOD,
+					 g_param_spec_string ("method",
+							      "METHOD",
+							      "The message method",
 							      NULL,
-							      G_PARAM_READWRITE |
-							      G_PARAM_STATIC_STRINGS |
-							      G_PARAM_CONSTRUCT_ONLY));
+							      G_PARAM_READABLE |
+							      G_PARAM_STATIC_STRINGS));
+	
+	/**
+	 * GeditMEssage:type:
+	 *
+	 * The message type
+	 *
+	 */
+	g_object_class_install_property (object_class, PROP_TYPE,
+					 g_param_spec_boxed ("type",
+					 		     "TYPE",
+					 		     "The message type",
+					 		     GEDIT_TYPE_MESSAGE_TYPE,
+					 		     G_PARAM_READWRITE |
+					 		     G_PARAM_CONSTRUCT_ONLY |
+					 		     G_PARAM_STATIC_STRINGS));
 
 	g_type_class_add_private (object_class, sizeof(GeditMessagePrivate));
 }
@@ -127,60 +171,6 @@
 						    (GDestroyNotify)destroy_value);
 }
 
-gboolean
-_gedit_message_gtype_supported (GType type)
-{
-	gint i = 0;
-  
-	static const GType type_list[] =
-	{
-		G_TYPE_BOOLEAN,
-		G_TYPE_CHAR,
-		G_TYPE_UCHAR,
-		G_TYPE_INT,
-		G_TYPE_UINT,
-		G_TYPE_LONG,
-		G_TYPE_ULONG,
-		G_TYPE_INT64,
-		G_TYPE_UINT64,
-		G_TYPE_ENUM,
-		G_TYPE_FLAGS,
-		G_TYPE_FLOAT,
-		G_TYPE_DOUBLE,
-		G_TYPE_STRING,
-		G_TYPE_POINTER,
-		G_TYPE_BOXED,
-		G_TYPE_OBJECT,
-		G_TYPE_INVALID
-	};
-
-	if (!G_TYPE_IS_VALUE_TYPE (type))
-		return FALSE;
-
-	while (type_list[i] != G_TYPE_INVALID)
-	{
-		if (g_type_is_a (type, type_list[i]))
-			return TRUE;
-		i++;
-	}
-
-	return FALSE;
-}
-
-static void
-add_value (GeditMessage *message,
-	   const gchar 	*key,
-	   GType	 gtype)
-{
-	GValue *value;
-	
-	value = g_new0 (GValue, 1);
-	g_value_init (value, gtype);
-	g_value_reset (value);
-
-	g_hash_table_insert (message->priv->values, g_strdup (key), value);
-}
-
 static gboolean
 set_value_real (GValue 	     *to, 
 		const GValue *from)
@@ -211,141 +201,60 @@
 
 inline static GValue *
 value_lookup (GeditMessage *message,
-	      const gchar  *key)
-{
-	return (GValue *)g_hash_table_lookup (message->priv->values, key);
-}
-
-GeditMessage*
-gedit_message_new (const gchar *domain,
-		   const gchar *name,
-		   ...)
-{
-	va_list var_args;
-	GeditMessage *message;
-	
-	va_start (var_args, name);
-	message = gedit_message_new_valist (domain, name, var_args);
-	va_end (var_args);
-	
-	return message;
-}
-
-GeditMessage *
-gedit_message_new_valist (const gchar *domain,
-			  const gchar *name,
-			  va_list      var_args)
-{
-	GeditMessage *message;
-	const gchar *key;
-	GArray *keys;
-	GArray *types;
-
-	message = g_object_new (GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);
-	
-	keys = g_array_new (FALSE, FALSE, sizeof (const gchar *));
-	types = g_array_new (FALSE, FALSE, sizeof (GType));
-
-	while ((key = va_arg (var_args, const gchar *)) != NULL)
-	{
-		/* get corresponding GType */
-		GType gtype = va_arg (var_args, GType);
-		
-		g_array_append_val (keys, key);
-		g_array_append_val (types, gtype);
-	}
-	
-	gedit_message_set_types (message, 
-				 (const gchar **)keys->data,
-				 (GType *)types->data,
-				 keys->len);
-	
-	g_array_free (keys, TRUE);
-	g_array_free (types, TRUE);
-	
-	return message;
-}
-
-GeditMessage *
-gedit_message_new_hash (const gchar *domain,
-			const gchar *name,
-			GHashTable  *values)
+	      const gchar  *key,
+	      gboolean	    create)
 {
-	GeditMessage *message;
-	const gchar *key;
-	GList *keys;
-	GList *item;
-	GValue *value;
+	GValue *ret = (GValue *)g_hash_table_lookup (message->priv->values, key);
 	
-	message = g_object_new (GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);	
-	keys = g_hash_table_get_keys (values);
+	if (!ret && create)
+		ret = add_value (message, key);
 	
-	for (item = keys; item; item = item->next)
-	{
-		key = (const gchar *)(item->data);
-		value = g_hash_table_lookup (values, key);
-		
-		if (value == NULL)
-			continue;
-		
-		if (!_gedit_message_gtype_supported (G_VALUE_TYPE (value)))
-		{
-			g_warning ("GType %s is not supported, ignoring key %s", 
-				   g_type_name (G_VALUE_TYPE (value)), 
-				   key);
-			continue;
-		}
-		
-		add_value (message, key, G_VALUE_TYPE (value));
-		gedit_message_set_value (message, key, value); 
-	}
-	
-	g_list_free (keys);
-	
-	return message;
-}
-
-void
-gedit_message_set_types (GeditMessage  *message,
-			 const gchar  **keys,
-			 GType	       *types,
-			 gint		n_types)
-{
-	gint i;
-
-	g_return_if_fail (GEDIT_IS_MESSAGE (message));
-	
-	g_hash_table_ref (message->priv->values);
-	g_hash_table_destroy (message->priv->values);
-	
-	for (i = 0; i < n_types; i++)
-	{
-		if (!_gedit_message_gtype_supported (types[i]))
-		{
-			g_warning ("GType %s is not supported, ignoring key %s", g_type_name (types[i]), keys[i]);
-			continue;
-		}
-		
-		add_value (message, keys[i], types[i]);
-	}	
-}
-
+	return ret;
+}
+
+/**
+ * gedit_message_get_method:
+ * @message: the #GeditMessage
+ *
+ * Get the message method
+ *
+ * Return value: the message method
+ *
+ */
 const gchar *
-gedit_message_get_name (GeditMessage *message)
+gedit_message_get_method (GeditMessage *message)
 {
 	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
 	
-	return message->priv->name;
+	return gedit_message_type_get_method (message->priv->type);
 }
 
+/**
+ * gedit_message_get_object_path:
+ * @message: the #GeditMessage
+ *
+ * Get the message object path
+ *
+ * Return value: the message object path
+ *
+ */
 const gchar *
-gedit_message_get_domain (GeditMessage *message)
+gedit_message_get_object_path (GeditMessage *message)
 {
 	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
 	
-	return message->priv->domain;
+	return gedit_message_type_get_object_path (message->priv->type);
 }
 
+/**
+ * gedit_message_set_value:
+ * @message: the #GeditMessage
+ * @...: a NULL terminated variable list of key/value pairs
+ *
+ * Set values of message arguments. The supplied @var_args should contain
+ * pairs of keys and argument values
+ *
+ */
 void
 gedit_message_set (GeditMessage *message,
 		   ...)
@@ -359,6 +268,15 @@
 	va_end (ap);
 }
 
+/**
+ * gedit_message_set_value:
+ * @message: the #GeditMessage
+ * @var_args: a NULL terminated variable list of key/value pairs
+ *
+ * Set values of message arguments. The supplied @var_args should contain
+ * pairs of keys and argument values
+ *
+ */
 void
 gedit_message_set_valist (GeditMessage *message,
 			  va_list	var_args)
@@ -370,7 +288,7 @@
 	while ((key = va_arg (var_args, const gchar *)) != NULL)
 	{
 		/* lookup the key */
-		GValue *container = value_lookup (message, key);
+		GValue *container = value_lookup (message, key, TRUE);
 		GValue value = {0,};
 		gchar *error = NULL;
 		
@@ -399,6 +317,15 @@
 	}
 }
 
+/**
+ * gedit_message_set_value:
+ * @message: the #GeditMessage
+ * @key: the argument key
+ * @value: the argument value
+ *
+ * Set value of message argument @key to @value
+ *
+ */
 void
 gedit_message_set_value (GeditMessage *message,
 			 const gchar  *key,
@@ -407,7 +334,7 @@
 	GValue *container;
 	g_return_if_fail (GEDIT_IS_MESSAGE (message));
 	
-	container = value_lookup (message, key);
+	container = value_lookup (message, key, TRUE);
 	
 	if (!container)
 	{
@@ -420,6 +347,16 @@
 	set_value_real (container, value);
 }
 
+/**
+ * gedit_message_set_valuesv:
+ * @message: the #GeditMessage
+ * @keys: keys to set values for
+ * @values: values to set
+ * @n_values: number of arguments to set values for
+ *
+ * Set message argument values.
+ *
+ */
 void
 gedit_message_set_valuesv (GeditMessage	 *message,
 			   const gchar	**keys,
@@ -436,6 +373,16 @@
 	}
 }
 
+/**
+ * gedit_message_get_valist:
+ * @message: the #GeditMessage
+ * @...: a NULL variable argument list of key/value container pairs
+ *
+ * Get values of message arguments. The supplied @var_args should contain
+ * pairs of keys and pointers to variables which are set to the argument
+ * value for the specified key
+ *
+ */
 void 
 gedit_message_get (GeditMessage	*message,
 		   ...)
@@ -449,6 +396,16 @@
 	va_end (ap);
 }
 
+/**
+ * gedit_message_get_valist:
+ * @message: the #GeditMessage
+ * @var_args: a NULL variable argument list of key/value container pairs
+ *
+ * Get values of message arguments. The supplied @var_args should contain
+ * pairs of keys and pointers to variables which are set to the argument
+ * value for the specified key
+ *
+ */
 void
 gedit_message_get_valist (GeditMessage *message,
 			  va_list 	var_args)
@@ -463,7 +420,7 @@
 		GValue copy = {0,};
 		gchar *error = NULL;
 
-		container = value_lookup (message, key);
+		container = value_lookup (message, key, FALSE);
 	
 		if (!container)
 		{		
@@ -492,6 +449,16 @@
 	}
 }
 
+/**
+ * gedit_message_get_value:
+ * @message: the #GeditMessage
+ * @key: the argument key
+ * @value: value return container
+ *
+ * Get the value of a specific message argument. @value will be initialized
+ * with the correct type
+ *
+ */
 void 
 gedit_message_get_value (GeditMessage *message,
 			 const gchar  *key,
@@ -501,7 +468,7 @@
 	
 	g_return_if_fail (GEDIT_IS_MESSAGE (message));
 	
-	container = value_lookup (message, key);
+	container = value_lookup (message, key, FALSE);
 	
 	if (!container)
 	{
@@ -515,64 +482,95 @@
 	set_value_real (value, container);
 }
 
+/**
+ * gedit_message_get_key_type:
+ * @message: the #GeditMessage
+ * @key: the argument key
+ *
+ * Get the type of a message argument
+ *
+ * Return value: the type of @key
+ *
+ */
 GType 
 gedit_message_get_key_type (GeditMessage    *message,
 			    const gchar	    *key)
 {
-	GValue *container;
+	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), G_TYPE_INVALID);
+	g_return_val_if_fail (message->priv->type != NULL, G_TYPE_INVALID);
 
-	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), 0);
-	
-	container = value_lookup (message, key);
-	
-	if (!container)
-	{
-		g_warning ("%s: Invalid key `%s'",
-			   G_STRLOC,
-			   key);
-		return 0;
-	}
-	
-	return G_VALUE_TYPE (container);
+	return gedit_message_type_lookup (message->priv->type, key);
 }
 
-GStrv
-gedit_message_get_keys (GeditMessage *message)
+/**
+ * gedit_message_has_key:
+ * @message: the #GeditMessage
+ * @key: the argument key
+ *
+ * Check whether the message has a specific key
+ *
+ * Return value: %TRUE if @message has argument @key
+ *
+ */
+gboolean
+gedit_message_has_key (GeditMessage *message,
+		       const gchar  *key)
 {
-	GList *keys;
-	GList *item;
-	GStrv result;
-	gint i = 0;
-	
-	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
-	
-	result = g_new0 (gchar *, g_hash_table_size (message->priv->values) + 1);
-	
-	keys = g_hash_table_get_keys (message->priv->values);
-	
-	for (item = keys; item; item = item->next)
-		result[i++] = g_strdup ((gchar *)(item->data));
+	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), FALSE);
 	
-	g_list_free (keys);
-	return result;
+	return value_lookup (message, key, FALSE) != NULL;
 }
 
-GHashTable *
-gedit_message_get_hash (GeditMessage *message)
+typedef struct
 {
-	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), NULL);
-	return message->priv->values;
+	GeditMessage *message;
+	gboolean valid;	
+} ValidateInfo;
+
+static void
+validate_key (const gchar  *key,
+	      GType         type,
+	      gboolean	    required,
+	      ValidateInfo *info)
+{
+	GValue *value;
+	
+	if (!info->valid || !required)
+		return;
+	
+	value = value_lookup (info->message, key, FALSE);
+	
+	if (!value)
+		info->valid = FALSE;
 }
 
+/**
+ * gedit_message_validate:
+ * @message: the #GeditMessage
+ *
+ * Validates the message arguments according to the message type
+ *
+ * Return value: %TRUE if the message is valid
+ *
+ */
 gboolean
-gedit_message_has_key (GeditMessage *message,
-		       const gchar  *key)
+gedit_message_validate (GeditMessage *message)
 {
-	GValue *container;
-	
+	ValidateInfo info = {message, TRUE};
+
 	g_return_val_if_fail (GEDIT_IS_MESSAGE (message), FALSE);
+	g_return_val_if_fail (message->priv->type != NULL, FALSE);
 	
-	container = value_lookup (message, key);
+	if (!message->priv->valid)
+	{
+		gedit_message_type_foreach (message->priv->type, 
+					    (GeditMessageTypeForeach)validate_key,
+					    &info);
+
+		message->priv->valid = info.valid;
+	}
 	
-	return container != NULL;
+	return message->priv->valid;
 }
+
+// ex:ts=8:noet:

Modified: branches/message_system/gedit/gedit-message.h
==============================================================================
--- branches/message_system/gedit/gedit-message.h	(original)
+++ branches/message_system/gedit/gedit-message.h	Sat Dec 27 13:07:00 2008
@@ -14,6 +14,9 @@
 #define GEDIT_IS_MESSAGE_CLASS(klass)		(G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_MESSAGE))
 #define GEDIT_MESSAGE_GET_CLASS(obj)		(G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_MESSAGE, GeditMessageClass))
 
+/* forward declaration of GeditMessageType */
+struct _GeditMessageType;
+
 typedef struct _GeditMessage		GeditMessage;
 typedef struct _GeditMessageClass	GeditMessageClass;
 typedef struct _GeditMessagePrivate	GeditMessagePrivate;
@@ -30,23 +33,7 @@
 
 GType gedit_message_get_type (void) G_GNUC_CONST;
 
-GeditMessage *gedit_message_new		(const gchar 	 *domain,
-					 const gchar	 *name,
-					 ...) G_GNUC_NULL_TERMINATED; 
-GeditMessage *gedit_message_new_valist  (const gchar 	 *domain,
-					 const gchar 	 *name,
-					 va_list	  var_args);
-GeditMessage *gedit_message_new_hash	(const gchar	 *domain,
-					 const gchar	 *name,
-					 GHashTable	 *values);
-
-void gedit_message_set_types		(GeditMessage	 *message,
-					 const gchar 	**keys,
-					 GType		 *types,
-					 gint		  n_types);
-
-const gchar *gedit_message_get_domain	(GeditMessage	 *message);
-const gchar *gedit_message_get_name	(GeditMessage	 *message);
+struct _GeditMessageType gedit_message_get_message_type (GeditMessage *message);
 
 void gedit_message_get			(GeditMessage	 *message,
 					 ...) G_GNUC_NULL_TERMINATED;
@@ -59,7 +46,7 @@
 void gedit_message_set			(GeditMessage	 *message,
 					 ...) G_GNUC_NULL_TERMINATED;
 void gedit_message_set_valist		(GeditMessage	 *message,
-					 va_list	  var_args);
+					 va_list	  	  var_args);
 void gedit_message_set_value		(GeditMessage	 *message,
 					 const gchar 	 *key,
 					 GValue		 *value);
@@ -68,16 +55,22 @@
 					 GValue		 *values,
 					 gint		  n_values);
 
+const gchar *gedit_message_get_object_path (GeditMessage	*message);
+const gchar *gedit_message_get_method	(GeditMessage	 *message);
+
 gboolean gedit_message_has_key		(GeditMessage	 *message,
 					 const gchar     *key);
 
-GStrv gedit_message_get_keys		(GeditMessage	 *message);
-GType gedit_message_get_key_type	(GeditMessage    *message,
+//GStrv gedit_message_get_keys		(GeditMessage	 *message);
+GType gedit_message_get_key_type		(GeditMessage    *message,
 					 const gchar	 *key);
 
-GHashTable *gedit_message_get_hash	(GeditMessage	 *message);
-gboolean _gedit_message_gtype_supported (GType type);
+gboolean gedit_message_validate		(GeditMessage	 *message);
+
+//GHashTable *gedit_message_get_hash	(GeditMessage	 *message);
 
 G_END_DECLS
 
 #endif /* __GEDIT_MESSAGE_H__ */
+
+// ex:ts=8:noet:

Modified: branches/message_system/gedit/gedit-window-private.h
==============================================================================
--- branches/message_system/gedit/gedit-window-private.h	(original)
+++ branches/message_system/gedit/gedit-window-private.h	Sat Dec 27 13:07:00 2008
@@ -46,7 +46,9 @@
 	GtkWidget      *bottom_panel;
 
 	GtkWidget      *hpaned;
-	GtkWidget      *vpaned;	
+	GtkWidget      *vpaned;
+	
+	GeditMessageBus *message_bus;
 
 	/* statusbar and context ids for statusbar messages */
 	GtkWidget      *statusbar;	

Modified: branches/message_system/gedit/gedit-window.c
==============================================================================
--- branches/message_system/gedit/gedit-window.c	(original)
+++ branches/message_system/gedit/gedit-window.c	Sat Dec 27 13:07:00 2008
@@ -155,6 +155,12 @@
 		window->priv->window_group = NULL;
 	}
 	
+	if (window->priv->message_bus != NULL)
+	{
+		g_object_unref (window->priv->message_bus);
+		window->priv->message_bus = NULL;
+	}
+	
 	/* Now that there have broken some reference loops,
 	 * force collection again.
 	 */
@@ -3077,6 +3083,7 @@
 	window->priv->state = GEDIT_WINDOW_STATE_NORMAL;
 	window->priv->destroy_has_run = FALSE;
 	window->priv->dispose_has_run = FALSE;
+	window->priv->message_bus = gedit_message_bus_new ();
 
 	window->priv->window_group = gtk_window_group_new ();
 	gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window));
@@ -3674,6 +3681,24 @@
 	return ret;
 }
 
+/**
+ * gedit_window_get_message_bus:
+ * @window: a #GeditWindow
+ *
+ * Gets the #GeditMessageBus associated with @window. The returned reference
+ * is owned by the window and should not be unreffed.
+ *
+ * Return value: the #GeditMessageBus associated with @window
+ */
+GeditMessageBus	*
+gedit_window_get_message_bus (GeditWindow *window)
+{
+	g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
+	
+	return window->priv->message_bus;
+}
+
+
 /* for backward compat since it is public api */
 GeditTab *
 gedit_window_get_tab_from_uri (GeditWindow *window,
@@ -3691,4 +3716,3 @@
 
 	return tab;
 }
-

Modified: branches/message_system/gedit/gedit-window.h
==============================================================================
--- branches/message_system/gedit/gedit-window.h	(original)
+++ branches/message_system/gedit/gedit-window.h	Sat Dec 27 13:07:00 2008
@@ -36,6 +36,7 @@
 
 #include <gedit/gedit-tab.h>
 #include <gedit/gedit-panel.h>
+#include <gedit/gedit-message-bus.h>
 
 G_BEGIN_DECLS
 
@@ -155,6 +156,10 @@
 
 GeditTab        *gedit_window_get_tab_from_uri		(GeditWindow         *window,
 							 const gchar         *uri);
+
+/* Message bus */
+GeditMessageBus	*gedit_window_get_message_bus		(GeditWindow         *window);
+
 /*
  * Non exported functions
  */

Modified: branches/message_system/gedit/gedit.c
==============================================================================
--- branches/message_system/gedit/gedit.c	(original)
+++ branches/message_system/gedit/gedit.c	Sat Dec 27 13:07:00 2008
@@ -39,7 +39,10 @@
 
 #include <glib/gi18n.h>
 #include <glib/goption.h>
+
+#ifndef PLATFORM_OSX
 #include <gdk/gdkx.h>
+#endif
 
 #include "gedit-app.h"
 #include "gedit-commands.h"
@@ -325,11 +328,13 @@
 	if (!GTK_WIDGET_REALIZED (window))
 		gtk_widget_realize (GTK_WIDGET (window));
 
+#ifdef GDK_WINDOWING_X11
 	if (startup_timestamp <= 0)
 		startup_timestamp = gdk_x11_get_server_time (GTK_WIDGET (window)->window);
 
 	gdk_x11_window_set_user_time (GTK_WIDGET (window)->window,
 				      startup_timestamp);
+#endif
 
 	gtk_window_present (GTK_WINDOW (window));
 
@@ -485,7 +490,7 @@
 
 	gedit_debug_message (DEBUG_APP, "Create bacon connection");
 
-	connection = bacon_message_connection_new ("gedit");
+	connection = bacon_message_connection_new ("gedit-message-system");
 
 	if (connection != NULL)
 	{
@@ -529,7 +534,9 @@
 					   GEDIT_ICONDIR);
 
 	/* Set the associated .desktop file */
+#ifndef PLATFORM_OSX
 	egg_set_desktop_file (DATADIR "/applications/gedit.desktop");
+#endif
 
 	/* Load user preferences */
 	gedit_debug_message (DEBUG_APP, "Init prefs manager");

Added: branches/message_system/gedit/msgtest.c
==============================================================================
--- (empty file)
+++ branches/message_system/gedit/msgtest.c	Sat Dec 27 13:07:00 2008
@@ -0,0 +1,37 @@
+#include "gedit-message-bus.h"
+
+static void
+fb_set_root_cb (GeditMessageBus *bus, GeditMessage *message, gpointer user_data)
+{
+	gchar *uri = NULL;
+
+	gedit_message_get (message, "uri", &uri, NULL);
+	g_message ("Setting root to: %s", uri);
+	
+	g_free (uri);
+}
+
+int
+main (int argc, char *argv[])
+{
+	GeditMessageBus *bus;
+	
+	g_type_init ();
+	
+	bus = gedit_message_bus_get_default ();
+
+	/* registering a new message on the bus */
+	GeditMessageType *message_type = gedit_message_bus_register (bus, "/plugins/filebrowser", "set_root", 0, "uri", G_TYPE_STRING, NULL);
+	
+	/* register callback for the message type */
+	gedit_message_bus_connect (bus, "/plugins/filebrowser", "set_root", fb_set_root_cb, NULL, NULL);
+
+	/* sending the set_root message */
+	gedit_message_bus_send_sync (bus, "/plugins/filebrowser", "set_root", "uri", "/hello/world", NULL);
+	
+	/* unregister message type */
+	gedit_message_bus_unregister (bus, message_type);
+	g_object_unref (bus);
+	
+	return 0;
+}

Modified: branches/message_system/gedit/smclient/Makefile.am
==============================================================================
--- branches/message_system/gedit/smclient/Makefile.am	(original)
+++ branches/message_system/gedit/smclient/Makefile.am	Sat Dec 27 13:07:00 2008
@@ -1,23 +1,36 @@
+if PLATFORM_WIN32
+platform_sources = eggsmclient-win32.c
+platform_logout_test_ldflags = -mwindows
+else
+if PLATFORM_OSX
+platform_defines = -xobjective-c
+platform_ldflags = -framework Carbon
+platform_sources = eggsmclient-osx.c
+else
 platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
-platform_ltlibraries = libeggdesktopfile.la
 platform_libs = libeggdesktopfile.la -lSM -lICE
+platform_ltlibraries = libeggdesktopfile.la
 platform_sources = eggsmclient-xsmp.c
-platform_app_ldflags =
-platform_programs = egg-launch
+endif
+endif
 
 INCLUDES =                               \
 	-DG_LOG_DOMAIN=\""EggSMClient"\" \
+	$(GEDIT_CFLAGS)			 \
 	$(platform_defines)              \
-	$(GEDIT_CFLAGS)
+	$(EGG_SMCLIENT_CFLAGS)
 
 noinst_LTLIBRARIES =                     \
 	libeggsmclient.la                \
 	$(platform_ltlibraries)
 
 libeggsmclient_la_LIBADD =               \
-	$(GEDIT_LIBS)                    \
+	$(EGG_SMCLIENT_LIBS)             \
 	$(platform_libs)
 
+libeggsmclient_la_LDFLAGS =              \
+	$(platform_ldflags)
+
 libeggsmclient_la_SOURCES =              \
 	eggsmclient.c                    \
 	eggsmclient.h                    \
@@ -25,11 +38,13 @@
 	$(platform_sources)
 
 libeggdesktopfile_la_LIBADD =            \
-	$(GEDIT_LIBS)
+	$(EGG_LIBS)
 
 libeggdesktopfile_la_SOURCES =           \
 	eggdesktopfile.c                 \
 	eggdesktopfile.h
 
 EXTRA_DIST =                             \
+	eggsmclient-osx.c                \
+	eggsmclient-win32.c              \
 	eggsmclient-xsmp.c

Modified: branches/message_system/plugin-loaders/python/bindings/Makefile.am
==============================================================================
--- branches/message_system/plugin-loaders/python/bindings/Makefile.am	(original)
+++ branches/message_system/plugin-loaders/python/bindings/Makefile.am	Sat Dec 27 13:07:00 2008
@@ -3,9 +3,9 @@
 noinst_LTLIBRARIES = \
 	gedit.la
 
-nodist_gedit_la_SOURCES = \
+nodist_gedit_la_SOURCES = 	\
 	gedit.c			\
-	geditutils.c	\
+	geditutils.c		\
 	geditcommands.c
 
 gedit_la_LDFLAGS = \
@@ -59,7 +59,7 @@
 	gedit/gedit-document.h		\
 	gedit/gedit-encodings.h		\
 	gedit/gedit-plugin.h		\
-	$(srcdir)/../gedit-plugin-python.h \
+	plugin-loaders/python/gedit-plugin-python.h \
 	gedit/gedit-view.h		\
 	gedit/gedit-statusbar.h		\
 	gedit/gedit-tab.h 		\
@@ -67,6 +67,9 @@
 	gedit/gedit-window.h 		\
 	gedit/gedit-help.h		\
 	gedit/gedit-debug.h		\
+	gedit/gedit-message-type.h	\
+	gedit/gedit-message.h		\
+	gedit/gedit-message-bus.h	\
 	gedit/gedit-language-manager.h
 
 BINDING_UTILS_HEADERS_SRCDIR_IN = \
@@ -100,6 +103,7 @@
 	geditutils.defs		\
 	geditcommands.override 	\
 	geditcommands.defs	\
+	geditmessage.override	\
 	geditplugin.override
 
 CLEANFILES = $(BUILT_SOURCES)

Modified: branches/message_system/plugin-loaders/python/bindings/gedit.defs
==============================================================================
--- branches/message_system/plugin-loaders/python/bindings/gedit.defs	(original)
+++ branches/message_system/plugin-loaders/python/bindings/gedit.defs	Sat Dec 27 13:07:00 2008
@@ -163,6 +163,13 @@
 ;;  )
 )
 
+(define-boxed MessageType
+  (in-module "Gedit")
+  (c-name "GeditMessageType")
+  (gtype-id "GEDIT_TYPE_MESSAGE_TYPE")
+  (copy-func "gedit_message_type_ref")
+  (release-func "gedit_message_type_unref")
+)
 
 ;; From ../../gedit/gedit-app.h
 
@@ -971,6 +978,12 @@
   (return-type "GeditWindowState")
 )
 
+(define-method get_message_bus
+  (of-object "GeditWindow")
+  (c-name "gedit_window_get_message_bus")
+  (return-type "GeditMessageBus*")
+)
+
 (define-method get_tab_from_uri
   (of-object "GeditWindow")
   (c-name "gedit_window_get_tab_from_uri")
@@ -1018,15 +1031,72 @@
   (return-type "GeditMessageBus*")
 )
 
+(define-function gedit_message_bus_new
+  (c-name "gedit_message_bus_new")
+  (is-constructor-of "GeditMessageBus")
+  (return-type "GeditMessageBus*")
+)
+
+(define-method lookup
+  (of-object "GeditMessageBus")
+  (c-name "gedit_message_bus_lookup")
+  (return-type "GeditMessageType*")
+  (parameters
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
+  )
+)
+
+(define-method register
+  (of-object "GeditMessageBus")
+  (c-name "gedit_message_bus_register")
+  (return-type "GeditMessageType*")
+  (parameters
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
+    '("guint" "num_optional")
+  )
+  (varargs #t)
+)
+
+(define-method unregister
+  (of-object "GeditMessageBus")
+  (c-name "gedit_message_bus_unregister")
+  (return-type "none")
+  (parameters
+    '("GeditMessageType*" "message_type")
+  )
+)
+
+(define-method unregister_all
+  (of-object "GeditMessageBus")
+  (c-name "gedit_message_bus_unregister_all")
+  (return-type "none")
+  (parameters
+    '("const-gchar*" "object_path")
+  )
+)
+
+(define-method is_registered
+  (of-object "GeditMessageBus")
+  (c-name "gedit_message_bus_is_registered")
+  (return-type "gboolean")
+  (parameters
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
+  )
+)
+
 (define-method connect
   (of-object "GeditMessageBus")
   (c-name "gedit_message_bus_connect")
   (return-type "guint")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
     '("GeditMessageCallback" "callback")
     '("gpointer" "userdata")
+    '("GDestroyNotify" "destroy_data")
   )
 )
 
@@ -1044,8 +1114,8 @@
   (c-name "gedit_message_bus_disconnect_by_func")
   (return-type "none")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
     '("GeditMessageCallback" "callback")
     '("gpointer" "userdata")
   )
@@ -1065,8 +1135,8 @@
   (c-name "gedit_message_bus_block_by_func")
   (return-type "none")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
     '("GeditMessageCallback" "callback")
     '("gpointer" "userdata")
   )
@@ -1086,8 +1156,8 @@
   (c-name "gedit_message_bus_unblock_by_func")
   (return-type "none")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
     '("GeditMessageCallback" "callback")
     '("gpointer" "userdata")
   )
@@ -1116,8 +1186,8 @@
   (c-name "gedit_message_bus_send")
   (return-type "none")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
   )
   (varargs #t)
 )
@@ -1127,65 +1197,129 @@
   (c-name "gedit_message_bus_send_sync")
   (return-type "GeditMessage*")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
   )
   (varargs #t)
 )
 
 
+;; From gedit-message-type.h
 
-;; From gedit-message.h
-
-(define-function gedit_message_get_type
-  (c-name "gedit_message_get_type")
+(define-function gedit_message_type_get_type
+  (c-name "gedit_message_type_get_type")
   (return-type "GType")
 )
 
-(define-function gedit_message_new
-  (c-name "gedit_message_new")
-  (is-constructor-of "GeditMessage")
-  (return-type "GeditMessage*")
+(define-function gedit_message_type_is_supported
+  (c-name "gedit_message_type_is_supported")
+  (return-type "gboolean")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
+    '("GType" "type")
+  )
+)
+
+(define-function gedit_message_type_identifier
+  (c-name "gedit_message_type_identifier")
+  (return-type "gchar*")
+  (parameters
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
+  )
+)
+
+(define-function gedit_message_type_new
+  (c-name "gedit_message_type_new")
+  (is-constructor-of "GeditMessageType")
+  (return-type "GeditMessageType*")
+  (parameters
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
+    '("guint" "num_optional")
   )
   (varargs #t)
 )
 
-(define-function gedit_message_new_valist
-  (c-name "gedit_message_new_valist")
-  (return-type "GeditMessage*")
+(define-function gedit_message_type_new_valist
+  (c-name "gedit_message_type_new_valist")
+  (return-type "GeditMessageType*")
   (parameters
-    '("const-gchar*" "domain")
-    '("const-gchar*" "name")
-    '("va_list" "var_args")
+    '("const-gchar*" "object_path")
+    '("const-gchar*" "method")
+    '("guint" "num_optional")
+    '("va_list" "va_args")
   )
 )
 
-(define-method set_types
-  (of-object "GeditMessage")
-  (c-name "gedit_message_set_types")
+(define-method ref
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_ref")
+  (return-type "GeditMessageType*")
+)
+
+(define-method unref
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_unref")
   (return-type "none")
+)
+
+(define-method instantiate_valist
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_instantiate_valist")
+  (return-type "GeditMessage*")
   (parameters
-    '("const-gchar**" "keys")
-    '("GType*" "types")
-    '("gint" "n_types")
+    '("va_list" "va_args")
   )
 )
 
-(define-method get_domain
-  (of-object "GeditMessage")
-  (c-name "gedit_message_get_domain")
+(define-method instantiate
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_instantiate")
+  (return-type "GeditMessage*")
+  (parameters
+  )
+  (varargs #t)
+)
+
+(define-method get_object_path
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_get_object_path")
   (return-type "const-gchar*")
 )
 
-(define-method get_name
-  (of-object "GeditMessage")
-  (c-name "gedit_message_get_name")
+(define-method get_method
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_get_method")
   (return-type "const-gchar*")
 )
 
+(define-method lookup
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_lookup")
+  (return-type "GType")
+  (parameters
+    '("const-gchar*" "key")
+  )
+)
+
+(define-method foreach
+  (of-object "GeditMessageType")
+  (c-name "gedit_message_type_foreach")
+  (return-type "none")
+  (parameters
+    '("GeditMessageTypeForeach" "func")
+    '("gpointer" "user_data")
+  )
+)
+
+
+;; From gedit-message.h
+
+(define-function gedit_message_get_type
+  (c-name "gedit_message_get_type")
+  (return-type "GType")
+)
+
 (define-method get
   (of-object "GeditMessage")
   (c-name "gedit_message_get")
@@ -1253,6 +1387,18 @@
   )
 )
 
+(define-method get_object_path
+  (of-object "GeditMessage")
+  (c-name "gedit_message_get_object_path")
+  (return-type "const-gchar*")
+)
+
+(define-method get_method
+  (of-object "GeditMessage")
+  (c-name "gedit_message_get_method")
+  (return-type "const-gchar*")
+)
+
 (define-method has_key
   (of-object "GeditMessage")
   (c-name "gedit_message_has_key")
@@ -1262,14 +1408,22 @@
   )
 )
 
-(define-method get_keys
+(define-method get_key_type
   (of-object "GeditMessage")
-  (c-name "gedit_message_get_keys")
-  (return-type "gchar**")
+  (c-name "gedit_message_get_key_type")
+  (return-type "GType")
   (parameters
+    '("const-gchar*" "key")
   )
 )
 
+(define-method validate
+  (of-object "GeditMessage")
+  (c-name "gedit_message_validate")
+  (return-type "gboolean")
+)
+
+
 ;; From ../../gedit/gedit-debug.h
 
 (define-function debug

Modified: branches/message_system/plugin-loaders/python/bindings/geditmessage.override
==============================================================================
--- branches/message_system/plugin-loaders/python/bindings/geditmessage.override	(original)
+++ branches/message_system/plugin-loaders/python/bindings/geditmessage.override	Sat Dec 27 13:07:00 2008
@@ -33,80 +33,6 @@
 }
 
 static int
-_helper_wrap_message_types(PyObject *args, gchar ***keys, GType **types, gint *num, gboolean direct)
-{
-    guint len, i;
-    Py_ssize_t pos;
-    
-    len = PyTuple_Size(args);
-
-    if (len == 1 && PyDict_Check(PyTuple_GetItem(args, 0)))
-    {
-    	/* get key -> gtype from mapping */
-    	PyObject *dict = PyTuple_GetItem(args, 0);
-    	PyObject *key;
-    	PyObject *value;
-
-    	*num = PyDict_Size(dict);
-    	*types = g_new0(GType, *num);
-        *keys = g_new0(gchar *, *num + 1);
-        pos = 0;
-        i = 0;
-        
-        while (PyDict_Next(dict, &pos, &key, &value)) {
-            (*keys)[i] = _helper_wrap_get_string (key);
-            
-            if (direct) {
-                (*types)[i] = _helper_wrap_get_gtype_from_pytype(value);
-            } else {
-                (*types)[i] = _helper_wrap_get_gtype_from_pytype((PyObject *)value->ob_type);
-            }
-            
-            if ((*types)[i] == 0 || (*keys)[i] == NULL) {
-                g_free(*types);
-                g_strfreev(*keys);
-                return 0;
-            }
-            
-            i++;
-        }
-    }
-    else
-    {
-        if (len % 2 != 0) {
-            PyErr_SetString(PyExc_TypeError,
-                            "Even number of arguments expected (name/type pairs)");
-            return 0;
-        }
-
-        *num = len / 2;
-        *types = g_new(GType, *num);
-        *keys = g_new0(gchar *, *num + 1);
-
-        for (i = 0; i < *num; i++) {
-            PyObject *key = PyTuple_GetItem(args, i * 2);
-            PyObject *value = PyTuple_GetItem(args, i * 2 + 1);
-    
-            (*keys)[i] = _helper_wrap_get_string (key);
-            
-            if (direct) {
-                (*types)[i] = _helper_wrap_get_gtype_from_pytype(value);
-            } else {
-                (*types)[i] = _helper_wrap_get_gtype_from_pytype((PyObject *)value->ob_type);
-            }
-
-            if ((*types)[i] == 0 || (*keys)[i] == NULL) {
-                g_free(*types);
-                g_strfreev(*keys);
-                return 0;
-            }
-        }
-    }
-    
-    return 1;
-}
-
-static int
 _helper_wrap_list_to_gvalue (GValue *gvalue, PyObject *pyvalue)
 {
 	int num;
@@ -178,94 +104,82 @@
     return 1;
 }
 
-static int
-_helper_wrap_message_set_values(GeditMessage *message, PyObject *args)
+typedef void (*ParsePairFunc)(PyObject *key, PyObject *value, gpointer user_data);
+
+static void
+_helper_parse_pairs_dict (PyObject *dict, ParsePairFunc func, gpointer user_data)
 {
-    guint len;
+    if (!dict)
+        return;
+    
+    PyObject *key, *value;
     Py_ssize_t i;
+
+    while (PyDict_Next(dict, &i, &key, &value))
+    {
+        func(key, value, user_data);
+    }
+}
+
+static void
+_helper_parse_pairs(PyObject *args, PyObject *kwargs, ParsePairFunc func, gpointer user_data)
+{
+    guint len;
+    guint i;
     
     len = PyTuple_Size(args);
-
-    if (len == 1 && PyDict_Check(PyTuple_GetItem(args, 0)))
+    
+    for (i = 0; i < len; ++i)
     {
-    	/* do key -> value from mapping */
-    	PyObject *dict = PyTuple_GetItem(args, 0);
-    	PyObject *pykey, *pyvalue;
+    	PyObject *d = PyTuple_GetItem(args, i);
     	
-    	i = 0;
-
-        while (PyDict_Next(dict, &i, &pykey, &pyvalue)) {
-            if (!_helper_wrap_message_set_value(message, pykey, pyvalue))
-                return 0;
-        }
-    } else {
-        if (len % 2 != 0) {
-            PyErr_SetString(PyExc_TypeError,
-                            "Even number of arguments expected (name/type pairs)");
-            return 0;
-        }
-
-        for (i = 0; i < len / 2; i++) {
-            PyObject *pykey = PyTuple_GetItem(args, i * 2);
-            PyObject *pyvalue = PyTuple_GetItem(args, i * 2 + 1);
-            
-            if (!_helper_wrap_message_set_value(message, pykey, pyvalue))
-                return 0;
-        }
+    	if (PyDict_Check(d))
+            _helper_parse_pairs_dict(d, func, user_data);
     }
-    
-    return 1;
+  
+    _helper_parse_pairs_dict(kwargs, func, user_data);  
 }
 
-static GeditMessage *
-_helper_wrap_create_message(PyObject *args)
+static void
+_helper_message_set(PyObject *key, PyObject *value, GeditMessage *message)
 {
-    guint len;
-    gint num;
-    gchar *domain;
-    gchar *name;
-    GType *types;
-    gchar **keys;
-    PyObject *slice;
-    GeditMessage *message;
+    _helper_wrap_message_set_value(message, key, value);
+}
 
-    len = PyTuple_Size(args);
+static void
+_helper_message_set_values(GeditMessage *message, PyObject *args, PyObject *kwargs)
+{
+    _helper_parse_pairs(args, kwargs, (ParsePairFunc)_helper_message_set, message);
+}
 
-    if (len < 2) {
-        PyErr_SetString(PyExc_TypeError,
-                        "GeditMessage requires at least two arguments");
+static GeditMessage *
+_helper_wrap_create_message(GeditMessageBus *bus, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "object_path", "method", NULL };
+    PyObject *pypath, *pymethod;
+    
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO:GeditMessage.create", kwlist, &pypath, &pymethod))
         return NULL;
-    }
     
-    domain = _helper_wrap_get_string(PyTuple_GetItem(args, 0));
-    name = _helper_wrap_get_string(PyTuple_GetItem(args, 1));
+    gchar *object_path = _helper_wrap_get_string(pypath);
+    gchar *method = _helper_wrap_get_string(pymethod);
     
-    if (!domain || !name) {
-        PyErr_SetString(PyExc_TypeError,
-                        "First two arguments need to be strings");
-        g_free (domain);
-        g_free (name);
-        return NULL;
+    GeditMessageType *message_type = gedit_message_bus_lookup (bus, object_path, method);
+    GeditMessage *message;
+     
+    if (message_type)
+    {
+        message = gedit_message_type_instantiate(message_type, NULL);
+        _helper_wrap_message_set_value(message, args, kwargs);
     }
-    
-    slice = PyTuple_GetSlice (args, 2, len);
-
-    if (!_helper_wrap_message_types (slice, &keys, &types, &num, FALSE)) {
-        Py_DECREF(slice);
-    	return NULL;
+    else
+    {
+        message = NULL;
     }
-
-    message = g_object_new(GEDIT_TYPE_MESSAGE, "domain", domain, "name", name, NULL);
-    gedit_message_set_types (message, (const gchar **)keys, types, num);
-
-    g_free(types);
-    g_strfreev(keys);
-    g_free (name);
-    g_free (domain);
     
-    _helper_wrap_message_set_values(message, slice);
-    Py_DECREF(slice);
-
+    g_free(object_path);
+    g_free(method);
+    
     return message;
 }
 
@@ -291,7 +205,9 @@
 %%
 ignore-glob
   *_get_type
-  gedit_message_new_valist
+  gedit_message_type_foreach
+  gedit_message_type_instantiate_valist
+  gedit_message_type_new_valist
   gedit_message_get_valist
   gedit_message_set_valist
   gedit_message_set_valuesv
@@ -299,41 +215,59 @@
   gedit_message_bus_block_by_func
   gedit_message_bus_unblock_by_func
 %%
-override gedit_message_new
+override gedit_message_type_new kwargs
+
+typedef struct
+{
+    GeditMessageType *message_type;
+    PyObject *optional;
+} MessageTypeSetInfo;
+
+static void
+_message_type_set(PyObject *key, PyObject *value, MessageTypeSetInfo *info)
+{
+    GType gtype;
+    
+    gchar *k = _helper_wrap_get_string(key);
+    
+    if (!k)
+        return;
+
+    gtype = _helper_wrap_get_gtype_from_pytype(value);
+            
+    gedit_message_type_set(info->message_type, PySequence_Index(info->optional, key) != -1, k, gtype, NULL);
+    g_free(k);
+}
+
 static int
-_wrap_gedit_message_new(PyGObject *self, PyObject *args)
+_wrap_gedit_message_type_new(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
-    self->obj = (GObject *)_helper_wrap_create_message(args);
+    static char *kwlist[] = { "object_path", "method", "optional", NULL };
+    PyObject *pypath, *pymethod, *optional;
+    guint len;
     
-    if (!self->obj) {
-        PyErr_SetString(PyExc_RuntimeError,
-                        "could not create GeditMessage object");
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOO:GeditMessageType.new", kwlist, &pypath, &pymethod, &optional))
         return -1;
-    }
-    pygobject_register_wrapper((PyObject *)self);
-
-    return 0;
+    
+    GeditMessageType *message_type = GEDIT_MESSAGE_TYPE(g_object_new(pyg_type_from_object((PyObject *) self), NULL));
+    
+    MessageTypeSetInfo info = {message_type, optional};
+    _helper_parse_pairs (args, kwargs, (ParsePairFunc)_message_type_set, &info);
+    
+    self->obj = (GObject *)message_type;    
+    pygobject_register_wrapper((PyObject *) self);
 }
 %%
-override gedit_message_set_types args
+override gedit_message_type_instantiate kwargs
 static PyObject *
-_wrap_gedit_message_set_types(PyGObject *self, PyObject *args)
+_wrap_gedit_message_type_instantiate(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
-    gint num;
-    GType *types;
-    gchar **keys;
-
-    if (!_helper_wrap_message_types (args, &keys, &types, &num, TRUE)) {
-    	return NULL;
-    }
- 
-    gedit_message_set_types (GEDIT_MESSAGE(self->obj), (const gchar **)keys, types, num);
-
-    g_free(types);
-    g_strfreev(keys);
-
-    Py_INCREF (Py_None);
-    return Py_None;
+    GeditMessageType *message_type = GEDIT_MESSAGE_TYPE (self->obj);
+    GeditMessage *message = gedit_message_type_instantiate(message_type, NULL);
+    
+    _wrap_helper_message_set_value(message, args, kwargs);
+    
+    return pygobject_new((GObject *)message);
 }
 %%
 override gedit_message_get args
@@ -406,41 +340,56 @@
     return Py_None;
 }
 %%
-override gedit_message_set args
+override gedit_message_set kwargs
 static PyObject *
-_wrap_gedit_message_set (PyGObject *self, PyObject *args) {
-    if (!_helper_wrap_message_set_values(GEDIT_MESSAGE(self->obj), args))
-        return NULL;
-    
+_wrap_gedit_message_set (PyGObject *self, PyObject *args, PyObject *kwargs) {
+    _helper_wrap_message_set_values(GEDIT_MESSAGE(self->obj), args, kwargs);
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 %%
-override gedit_message_get_keys args
-static PyObject *
-_wrap_gedit_message_get_keys (PyGObject *self, PyObject *args) {
-    PyObject *py_list;
-    gchar **keys;
-    gchar **ptr;
+override gedit_message_bus_new
+static int
+_wrap_gedit_message_bus_new(PyGObject *self)
+{
+    pygobject_construct (self, NULL);
     
-    if ((py_list = PyList_New(0)) == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
+    if (!self->obj) {
+        PyErr_SetString (PyExc_RuntimeError, "could not create gedit.MessageBus object");
+        return -1;
     }
+
+    return 0;
+}
+%%
+new-constructor GEDIT_TYPE_MESSAGE_BUS
+%%
+override gedit_message_bus_register kwargs
+static PyObject *
+_wrap_gedit_message_bus_register(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "object_path", "method", "optional", NULL };
+    PyObject *pypath, *pymethod, *optional;
+    guint len;
+    GeditMessageBus *bus = GEDIT_MESSAGE_BUS(self->obj);
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOO:GeditMessageBus.register", kwlist, &pypath, &pymethod, &optional))
+        return NULL;
     
-    keys = gedit_message_get_keys (GEDIT_MESSAGE (self->obj));
-    ptr = keys;
+    gchar *object_path = _helper_wrap_get_string(pypath);
+    gchar *method = _helper_wrap_get_string(pymethod);
     
-    if (!keys)
-    	return py_list;
+    GeditMessageType *message_type = gedit_message_bus_register(bus, object_path, method, 0, NULL);
     
-    while (*ptr)
-    	PyList_Append(py_list, PyString_FromString (*ptr));
-
-    g_strfreev (keys);
-    return py_list;
+    g_free(object_path);
+    g_free(method);
+    
+    MessageTypeSetInfo info = {message_type, optional};
+    _helper_parse_pairs (args, kwargs, (ParsePairFunc)_message_type_set, &info);
+    
+    return pyg_boxed_new(GEDIT_TYPE_MESSAGE_TYPE, message_type, TRUE, TRUE);
 }
-
 %%
 override gedit_message_bus_connect kwargs
 static void
@@ -507,19 +456,19 @@
     return Py_None;
 }
 %%
-override gedit_message_bus_send args
+override gedit_message_bus_send kwargs
 static PyObject *
-_wrap_gedit_message_bus_send (PyGObject *self, PyObject *args)
+_wrap_gedit_message_bus_send(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
     /* create a new message object */
     GeditMessage *message;
-    
-    message = _helper_wrap_create_message(args);
+    GeditMessageBus *bus = GEDIT_MESSAGE_BUS(self->obj);
+    message = _helper_wrap_create_message(bus, args, kwargs);
     
     if (!message)
         return NULL;
     
-    gedit_message_bus_send_message(GEDIT_MESSAGE_BUS(self->obj), message);
+    gedit_message_bus_send_message(bus, message);
     g_object_unref (message);
     
     Py_INCREF(Py_None);
@@ -528,17 +477,18 @@
 %%
 override gedit_message_bus_send_sync args
 static PyObject *
-_wrap_gedit_message_bus_send_sync (PyGObject *self, PyObject *args)
+_wrap_gedit_message_bus_send_sync(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
     /* create a new message object */
     GeditMessage *message;
+    GeditMessageBus *bus = GEDIT_MESSAGE_BUS(self->obj);
     
-    message = _helper_wrap_create_message(args);
+    message = _helper_wrap_create_message(bus, args, kwargs);
     
     if (!message)
         return NULL;
     
-    gedit_message_bus_send_message_sync(GEDIT_MESSAGE_BUS(self->obj), message);
+    gedit_message_bus_send_message_sync(bus, message);
     return pygobject_new((GObject *)message);
 }
 %%



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