[gmime] use a custom event API



commit 8cb015a0a4cd4a54fc2ce55114966ae335ea75a0
Author: Jeffrey Stedfast <fejj gnome org>
Date:   Sat Apr 25 18:15:17 2009 -0400

    use a custom event API
    
    2009-04-25  Jeffrey Stedfast  <fejj novell com>
    
    	* gmime/gmime-parse-utils.h: Marked APIs as internal linkage only.
    
    	* gmime/gmime-common.h: Same.
    
    	* gmime/gmime-content-type.c: Use the new GMimeEvent API instead
    	of libgobject's g_signal API which is more than we need.
    
    	* gmime/gmime-disposition.c: Same.
    
    	* gmime/gmime-object.c: Updated to use the GMimeEvent API for
    	content-type and content-disposition.
    
    	* gmime/internet-address.c: Use the new GMimeEvent API instead of
    	our own.
    
    	* gmime/gmime-events.[c,h]: New source files implementing a simple
    	and performant event system needed internally within GMime. Based
    	on the event system that used to be in internet-address.c
---
 ChangeLog                         |   17 +++
 TODO                              |    2 +-
 build/vs2008/gmime.vcproj         |    8 ++
 docs/reference/Makefile.am        |    4 +-
 docs/reference/gmime-sections.txt |    4 +-
 gmime/Makefile.am                 |    8 +-
 gmime/gmime-common.h              |    4 +-
 gmime/gmime-content-type.c        |   29 +----
 gmime/gmime-content-type.h        |    3 +
 gmime/gmime-disposition.c         |   27 +----
 gmime/gmime-disposition.h         |    3 +
 gmime/gmime-events.c              |  220 +++++++++++++++++++++++++++++++++++++
 gmime/gmime-events.h              |   47 ++++++++
 gmime/gmime-message.c             |   26 ++---
 gmime/gmime-object.c              |   37 +++----
 gmime/gmime-parse-utils.h         |    8 +-
 gmime/internet-address.c          |  216 ++++++-------------------------------
 17 files changed, 384 insertions(+), 279 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4a275f9..4f5ce1a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2009-04-25  Jeffrey Stedfast  <fejj novell com>
+
+	* gmime/gmime-content-type.c: Use the new GMimeEvent API instead
+	of libgobject's g_signal API which is more than we need.
+
+	* gmime/gmime-disposition.c: Same.
+
+	* gmime/gmime-object.c: Updated to use the GMimeEvent API for
+	content-type and content-disposition.
+
+	* gmime/internet-address.c: Use the new GMimeEvent API instead of
+	our own.
+
+	* gmime/gmime-events.[c,h]: New source files implementing a simple
+	and performant event system needed internally within GMime. Based
+	on the event system that used to be in internet-address.c
+
 2009-04-24  Jeffrey Stedfast  <fejj novell com>
 
 	* gmime/gmime-parser.c (struct _GMimeParserPrivate): Added
diff --git a/TODO b/TODO
index c50a4b5..6eb9445 100644
--- a/TODO
+++ b/TODO
@@ -8,7 +8,7 @@ GMime 2.6 Planning:
 ===================
 
 - Replace all uses of g_signals with my own event stuff. None of this
-  needs to be public and my events are a lot more performant.
+  needs to be public and my events are a lot more performant. [ DONE ]
 
 - Need to add a Changed event to GMimeHeaderList so that GMimeMessage
   can listen to changes in the toplevel mime_part's headers. When they
diff --git a/build/vs2008/gmime.vcproj b/build/vs2008/gmime.vcproj
index 4d87f84..063121f 100644
--- a/build/vs2008/gmime.vcproj
+++ b/build/vs2008/gmime.vcproj
@@ -205,6 +205,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\gmime\gmime-events.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\gmime\gmime-filter-basic.h"
 				>
 			</File>
@@ -429,6 +433,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\gmime\gmime-events.c"
+				>
+			</File>
+			<File
 				RelativePath="..\..\gmime\gmime-filter-basic.c"
 				>
 			</File>
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 5628403..0e71d49 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -59,7 +59,9 @@ CFILE_GLOB=$(top_srcdir)/gmime/*.c
 IGNORE_HFILES = 			\
 	gmime-charset-map-private.h	\
 	gmime-table-private.h		\
-	gmime-type-utils.h
+	gmime-parse-utils.h		\
+	gmime-common.h			\
+	gmime-events.h
 
 # Extra options to supply to gtkdoc-fixref
 FIXXREF_OPTIONS = 
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index 137f7e7..c2db0f2 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -602,8 +602,8 @@ g_mime_header_list_foreach
 g_mime_header_list_register_writer
 g_mime_header_list_write_to_stream
 g_mime_header_list_to_string
-g_mime_header_list_has_raw
-g_mime_header_list_set_raw
+g_mime_header_list_get_stream
+g_mime_header_list_set_stream
 </SECTION>
 
 <SECTION>
diff --git a/gmime/Makefile.am b/gmime/Makefile.am
index 9c4295e..f8037dd 100644
--- a/gmime/Makefile.am
+++ b/gmime/Makefile.am
@@ -25,6 +25,7 @@ libgmime_2_6_la_SOURCES = 		\
 	gmime-data-wrapper.c		\
 	gmime-disposition.c		\
 	gmime-encodings.c		\
+	gmime-events.c			\
 	gmime-filter.c			\
 	gmime-filter-basic.c		\
 	gmime-filter-best.c		\
@@ -101,7 +102,6 @@ gmimeinclude_HEADERS = 			\
 	gmime-multipart-signed.h	\
 	gmime-object.h			\
 	gmime-param.h			\
-	gmime-parse-utils.h		\
 	gmime-parser.h			\
 	gmime-part.h			\
 	gmime-session.h			\
@@ -119,9 +119,11 @@ gmimeinclude_HEADERS = 			\
 	internet-address.h
 
 noinst_HEADERS = 			\
-	gmime-common.h			\
+	gmime-charset-map-private.h	\
 	gmime-table-private.h		\
-	gmime-charset-map-private.h
+	gmime-parse-utils.h		\
+	gmime-common.h			\
+	gmime-events.h
 
 install-data-local: install-libtool-import-lib
 
diff --git a/gmime/gmime-common.h b/gmime/gmime-common.h
index 5465cd2..26590eb 100644
--- a/gmime/gmime-common.h
+++ b/gmime/gmime-common.h
@@ -26,9 +26,9 @@
 
 G_BEGIN_DECLS
 
-int g_mime_strcase_equal (gconstpointer v, gconstpointer v2);
+G_GNUC_INTERNAL int g_mime_strcase_equal (gconstpointer v, gconstpointer v2);
 
-guint g_mime_strcase_hash (gconstpointer key);
+G_GNUC_INTERNAL guint g_mime_strcase_hash (gconstpointer key);
 
 G_END_DECLS
 
diff --git a/gmime/gmime-content-type.c b/gmime/gmime-content-type.c
index 86bf3fd..987c63e 100644
--- a/gmime/gmime-content-type.c
+++ b/gmime/gmime-content-type.c
@@ -30,6 +30,7 @@
 #include "gmime-common.h"
 #include "gmime-content-type.h"
 #include "gmime-parse-utils.h"
+#include "gmime-events.h"
 
 
 #ifdef ENABLE_WARNINGS
@@ -52,13 +53,6 @@
  **/
 
 
-enum {
-	CHANGED,
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
 static void g_mime_content_type_class_init (GMimeContentTypeClass *klass);
 static void g_mime_content_type_init (GMimeContentType *content_type, GMimeContentTypeClass *klass);
 static void g_mime_content_type_finalize (GObject *object);
@@ -100,23 +94,13 @@ g_mime_content_type_class_init (GMimeContentTypeClass *klass)
 	parent_class = g_type_class_ref (G_TYPE_OBJECT);
 	
 	object_class->finalize = g_mime_content_type_finalize;
-	
-	/* signals */
-	signals[CHANGED] =
-		g_signal_new ("changed",
-			      GMIME_TYPE_CONTENT_TYPE,
-			      G_SIGNAL_RUN_LAST,
-			      0,
-			      NULL,
-			      NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
 }
 
 static void
 g_mime_content_type_init (GMimeContentType *content_type, GMimeContentTypeClass *klass)
 {
 	content_type->param_hash = g_hash_table_new (g_mime_strcase_hash, g_mime_strcase_equal);
+	content_type->priv = g_mime_event_new ((GObject *) content_type);
 	content_type->params = NULL;
 	content_type->subtype = NULL;
 	content_type->type = NULL;
@@ -129,6 +113,7 @@ g_mime_content_type_finalize (GObject *object)
 	
 	g_hash_table_destroy (content_type->param_hash);
 	g_mime_param_destroy (content_type->params);
+	g_mime_event_destroy (content_type->priv);
 	g_free (content_type->subtype);
 	g_free (content_type->type);
 	
@@ -303,7 +288,7 @@ g_mime_content_type_set_media_type (GMimeContentType *mime_type, const char *typ
 	g_free (mime_type->type);
 	mime_type->type = buf;
 	
-	g_signal_emit (mime_type, signals[CHANGED], 0);
+	g_mime_event_emit (mime_type->priv, NULL);
 }
 
 
@@ -343,7 +328,7 @@ g_mime_content_type_set_media_subtype (GMimeContentType *mime_type, const char *
 	g_free (mime_type->subtype);
 	mime_type->subtype = buf;
 	
-	g_signal_emit (mime_type, signals[CHANGED], 0);
+	g_mime_event_emit (mime_type->priv, NULL);
 }
 
 
@@ -386,7 +371,7 @@ g_mime_content_type_set_params (GMimeContentType *mime_type, GMimeParam *params)
 		params = params->next;
 	}
 	
-	g_signal_emit (mime_type, signals[CHANGED], 0);
+	g_mime_event_emit (mime_type->priv, NULL);
 }
 
 
@@ -433,7 +418,7 @@ g_mime_content_type_set_parameter (GMimeContentType *mime_type, const char *attr
 		g_hash_table_insert (mime_type->param_hash, param->name, param);
 	}
 	
-	g_signal_emit (mime_type, signals[CHANGED], 0);
+	g_mime_event_emit (mime_type->priv, NULL);
 }
 
 
diff --git a/gmime/gmime-content-type.h b/gmime/gmime-content-type.h
index 42950a2..d29e730 100644
--- a/gmime/gmime-content-type.h
+++ b/gmime/gmime-content-type.h
@@ -54,6 +54,9 @@ struct _GMimeContentType {
 	
 	GHashTable *param_hash;
 	GMimeParam *params;
+	
+	gpointer priv;
+	
 	char *type;
 	char *subtype;
 };
diff --git a/gmime/gmime-disposition.c b/gmime/gmime-disposition.c
index a24e2b9..9710c45 100644
--- a/gmime/gmime-disposition.c
+++ b/gmime/gmime-disposition.c
@@ -28,6 +28,7 @@
 
 #include "gmime-common.h"
 #include "gmime-disposition.h"
+#include "gmime-events.h"
 
 
 /**
@@ -41,13 +42,6 @@
  **/
 
 
-enum {
-	CHANGED,
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
 static void g_mime_content_disposition_class_init (GMimeContentDispositionClass *klass);
 static void g_mime_content_disposition_init (GMimeContentDisposition *disposition, GMimeContentDispositionClass *klass);
 static void g_mime_content_disposition_finalize (GObject *object);
@@ -89,23 +83,13 @@ g_mime_content_disposition_class_init (GMimeContentDispositionClass *klass)
 	parent_class = g_type_class_ref (G_TYPE_OBJECT);
 	
 	object_class->finalize = g_mime_content_disposition_finalize;
-	
-	/* signals */
-	signals[CHANGED] =
-		g_signal_new ("changed",
-			      GMIME_TYPE_CONTENT_DISPOSITION,
-			      G_SIGNAL_RUN_LAST,
-			      0,
-			      NULL,
-			      NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
 }
 
 static void
 g_mime_content_disposition_init (GMimeContentDisposition *disposition, GMimeContentDispositionClass *klass)
 {
 	disposition->param_hash = g_hash_table_new (g_mime_strcase_hash, g_mime_strcase_equal);
+	disposition->priv = g_mime_event_new ((GObject *) disposition);
 	disposition->disposition = NULL;
 	disposition->params = NULL;
 }
@@ -117,6 +101,7 @@ g_mime_content_disposition_finalize (GObject *object)
 	
 	g_hash_table_destroy (disposition->param_hash);
 	g_mime_param_destroy (disposition->params);
+	g_mime_event_destroy (disposition->priv);
 	g_free (disposition->disposition);
 	
 	G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -208,7 +193,7 @@ g_mime_content_disposition_set_disposition (GMimeContentDisposition *disposition
 	g_free (disposition->disposition);
 	disposition->disposition = buf;
 	
-	g_signal_emit (disposition, signals[CHANGED], 0);
+	g_mime_event_emit (disposition->priv, NULL);
 }
 
 
@@ -252,7 +237,7 @@ g_mime_content_disposition_set_params (GMimeContentDisposition *disposition, GMi
 		params = params->next;
 	}
 	
-	g_signal_emit (disposition, signals[CHANGED], 0);
+	g_mime_event_emit (disposition->priv, NULL);
 }
 
 
@@ -299,7 +284,7 @@ g_mime_content_disposition_set_parameter (GMimeContentDisposition *disposition,
 		g_hash_table_insert (disposition->param_hash, param->name, param);
 	}
 	
-	g_signal_emit (disposition, signals[CHANGED], 0);
+	g_mime_event_emit (disposition->priv, NULL);
 }
 
 
diff --git a/gmime/gmime-disposition.h b/gmime/gmime-disposition.h
index 32a84dd..728821f 100644
--- a/gmime/gmime-disposition.h
+++ b/gmime/gmime-disposition.h
@@ -69,6 +69,9 @@ struct _GMimeContentDisposition {
 	
 	GHashTable *param_hash;
 	GMimeParam *params;
+	
+	gpointer priv;
+	
 	char *disposition;
 };
 
diff --git a/gmime/gmime-events.c b/gmime/gmime-events.c
new file mode 100644
index 0000000..305079c
--- /dev/null
+++ b/gmime/gmime-events.c
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  GMime
+ *  Copyright (C) 2000-2009 Jeffrey Stedfast
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gmime-events.h"
+#include "list.h"
+
+typedef struct _EventListener {
+	struct _EventListener *next;
+	struct _EventListener *prev;
+	GMimeEventCallback callback;
+	gpointer user_data;
+	int blocked;
+} EventListener;
+
+static EventListener *
+event_listener_new (GMimeEventCallback callback, gpointer user_data)
+{
+	EventListener *listener;
+	
+	listener = g_slice_new (EventListener);
+	listener->user_data = user_data;
+	listener->callback = callback;
+	listener->prev = NULL;
+	listener->next = NULL;
+	listener->blocked = 0;
+	
+	return listener;
+}
+
+static void
+event_listener_free (EventListener *listener)
+{
+	g_slice_free (EventListener, listener);
+}
+
+
+struct _GMimeEvent {
+	GObject *owner;
+	List list;
+};
+
+
+/**
+ * g_mime_event_new:
+ * @owner: a #GObject; typically the one that will own this event
+ *
+ * Creates a new #GMimeEvent context.
+ *
+ * Returns: a newly allocated #GMimeEvent context.
+ **/
+GMimeEvent *
+g_mime_event_new (GObject *owner)
+{
+	GMimeEvent *event;
+	
+	event = g_slice_new (GMimeEvent);
+	list_init (&event->list);
+	event->owner = owner;
+	
+	return event;
+}
+
+
+/**
+ * g_mime_event_destroy:
+ * @event: a #GMimeEvent
+ *
+ * Destroys an event context.
+ **/
+void
+g_mime_event_destroy (GMimeEvent *event)
+{
+	EventListener *node, *next;
+	
+	node = (EventListener *) &event->list.head;
+	while (node->next) {
+		next = node->next;
+		event_listener_free (node);
+		node = next;
+	}
+	
+	g_slice_free (GMimeEvent, event);
+}
+
+
+static EventListener *
+g_mime_event_find_listener (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data)
+{
+	EventListener *node;
+	
+	node = (EventListener *) &event->list.head;
+	while (node->next) {
+		if (node->callback == callback && node->user_data == user_data)
+			return node;
+		node = node->next;
+	}
+	
+	return NULL;
+}
+
+
+/**
+ * g_mime_event_block:
+ * @event: a #GMimeEvent
+ * @callback: a #GMimeEventCallback
+ * @user_data: user context data
+ *
+ * Blocks the specified callback from being called when @event is emitted.
+ **/
+void
+g_mime_event_block (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data)
+{
+	EventListener *listener;
+	
+	if ((listener = g_mime_event_find_listener (event, callback, user_data)))
+		listener->blocked++;
+}
+
+
+/**
+ * g_mime_event_unblock:
+ * @event: a #GMimeEvent
+ * @callback: a #GMimeEventCallback
+ * @user_data: user context data
+ *
+ * Unblocks the specified callback from being called when @event is
+ * emitted.
+ **/
+void
+g_mime_event_unblock (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data)
+{
+	EventListener *listener;
+	
+	if ((listener = g_mime_event_find_listener (event, callback, user_data)))
+		listener->blocked--;
+}
+
+
+/**
+ * g_mime_event_add:
+ * @event: a #GMimeEvent
+ * @callback: a #GMimeEventCallback
+ * @user_data: user context data
+ *
+ * Adds a callback function that will get called with the specified
+ * @user_data whenever @event is emitted.
+ **/
+void
+g_mime_event_add (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data)
+{
+	EventListener *listener;
+	
+	listener = event_listener_new (callback, user_data);
+	list_append (&event->list, (ListNode *) listener);
+}
+
+
+/**
+ * g_mime_event_remove:
+ * @event: a #GMimeEvent
+ * @callback: a #GMimeEventCallback
+ * @user_data: user context data
+ *
+ * Removes the specified callback function from the list of callbacks
+ * that will be called when the @event is emitted.
+ **/
+void
+g_mime_event_remove (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data)
+{
+	EventListener *listener;
+	
+	if ((listener = g_mime_event_find_listener (event, callback, user_data))) {
+		list_unlink ((ListNode *) listener);
+		event_listener_free (listener);
+	}
+}
+
+
+/**
+ * g_mime_event_emit:
+ * @event: a #GMimeEvent
+ * @args: an argument pointer
+ *
+ * Calls each callback registered with this @event with the specified
+ * @args.
+ **/
+void
+g_mime_event_emit (GMimeEvent *event, gpointer args)
+{
+	EventListener *node;
+	
+	node = (EventListener *) &event->list.head;
+	while (node->next) {
+		if (node->blocked <= 0)
+			node->callback (event->owner, args, node->user_data);
+		node = node->next;
+	}
+}
diff --git a/gmime/gmime-events.h b/gmime/gmime-events.h
new file mode 100644
index 0000000..1755075
--- /dev/null
+++ b/gmime/gmime-events.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  GMime
+ *  Copyright (C) 2000-2009 Jeffrey Stedfast
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#ifndef __GMIME_EVENTS_H__
+#define __GMIME_EVENTS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef void (* GMimeEventCallback) (GObject *sender, gpointer args, gpointer user_data);
+
+typedef struct _GMimeEvent GMimeEvent;
+
+G_GNUC_INTERNAL GMimeEvent *g_mime_event_new (GObject *owner);
+G_GNUC_INTERNAL void g_mime_event_destroy (GMimeEvent *event);
+
+G_GNUC_INTERNAL void g_mime_event_add (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data);
+G_GNUC_INTERNAL void g_mime_event_remove (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data);
+
+G_GNUC_INTERNAL void g_mime_event_block (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data);
+G_GNUC_INTERNAL void g_mime_event_unblock (GMimeEvent *event, GMimeEventCallback callback, gpointer user_data);
+
+G_GNUC_INTERNAL void g_mime_event_emit (GMimeEvent *event, gpointer args);
+
+G_END_DECLS
+
+#endif /* __GMIME_EVENTS_H__ */
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index b9ab70b..3db85f4 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -34,6 +34,7 @@
 #include "gmime-stream-mem.h"
 #include "gmime-table-private.h"
 #include "gmime-parse-utils.h"
+#include "gmime-events.h"
 
 
 /**
@@ -46,14 +47,6 @@
  **/
 
 
-typedef void (* EventCallback) (gpointer sender, gpointer args);
-
-extern void _internet_address_list_block_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
-extern void _internet_address_list_unblock_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
-extern void _internet_address_list_add_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
-extern void _internet_address_list_remove_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
-
-
 static void g_mime_message_class_init (GMimeMessageClass *klass);
 static void g_mime_message_init (GMimeMessage *message, GMimeMessageClass *klass);
 static void g_mime_message_finalize (GObject *object);
@@ -80,13 +73,14 @@ static void bcc_list_changed (InternetAddressList *list, GMimeMessage *message);
 
 static GMimeObjectClass *parent_class = NULL;
 
+
 static struct {
 	const char *name;
-	EventCallback changed_cb;
+	GMimeEventCallback changed_cb;
 } recipient_types[] = {
-	{ "To",  (EventCallback) to_list_changed  },
-	{ "Cc",  (EventCallback) cc_list_changed  },
-	{ "Bcc", (EventCallback) bcc_list_changed }
+	{ "To",  (GMimeEventCallback) to_list_changed  },
+	{ "Cc",  (GMimeEventCallback) cc_list_changed  },
+	{ "Bcc", (GMimeEventCallback) bcc_list_changed }
 };
 
 #define N_RECIPIENT_TYPES G_N_ELEMENTS (recipient_types)
@@ -155,7 +149,7 @@ connect_changed_event (GMimeMessage *message, GMimeRecipientType type)
 	
 	list = message->recipients[type];
 	
-	_internet_address_list_add_event_handler (list, recipient_types[type].changed_cb, message);
+	g_mime_event_add (list->priv, recipient_types[type].changed_cb, message);
 }
 
 static void
@@ -165,7 +159,7 @@ disconnect_changed_event (GMimeMessage *message, GMimeRecipientType type)
 	
 	list = message->recipients[type];
 	
-	_internet_address_list_remove_event_handler (list, recipient_types[type].changed_cb, message);
+	g_mime_event_remove (list->priv, recipient_types[type].changed_cb, message);
 }
 
 static void
@@ -175,7 +169,7 @@ block_changed_event (GMimeMessage *message, GMimeRecipientType type)
 	
 	list = message->recipients[type];
 	
-	_internet_address_list_block_event_handler (list, recipient_types[type].changed_cb, message);
+	g_mime_event_block (list->priv, recipient_types[type].changed_cb, message);
 }
 
 static void
@@ -185,7 +179,7 @@ unblock_changed_event (GMimeMessage *message, GMimeRecipientType type)
 	
 	list = message->recipients[type];
 	
-	_internet_address_list_block_event_handler (list, recipient_types[type].changed_cb, message);
+	g_mime_event_unblock (list->priv, recipient_types[type].changed_cb, message);
 }
 
 static void
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index 6b32093..44a5381 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -29,6 +29,7 @@
 #include "gmime-common.h"
 #include "gmime-object.h"
 #include "gmime-stream-mem.h"
+#include "gmime-events.h"
 #include "gmime-utils.h"
 
 
@@ -73,8 +74,8 @@ static ssize_t write_to_stream (GMimeObject *object, GMimeStream *stream);
 static ssize_t write_content_type (GMimeStream *stream, const char *name, const char *value);
 static ssize_t write_disposition (GMimeStream *stream, const char *name, const char *value);
 
-static void content_type_changed (GMimeContentType *content_type, GMimeObject *object);
-static void content_disposition_changed (GMimeContentDisposition *disposition, GMimeObject *object);
+static void content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object);
+static void content_disposition_changed (GMimeContentDisposition *disposition, gpointer args, GMimeObject *object);
 
 static void type_registry_init (void);
 
@@ -149,16 +150,12 @@ g_mime_object_finalize (GObject *object)
 	GMimeObject *mime = (GMimeObject *) object;
 	
 	if (mime->content_type) {
-		g_signal_handlers_disconnect_matched (mime->content_type,
-						      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-						      0, 0, NULL, content_type_changed, object);
+		g_mime_event_remove (mime->content_type->priv, (GMimeEventCallback) content_type_changed, object);
 		g_object_unref (mime->content_type);
 	}
 	
 	if (mime->disposition) {
-		g_signal_handlers_disconnect_matched (mime->disposition,
-						      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-						      0, 0, NULL, content_disposition_changed, object);
+		g_mime_event_remove (mime->disposition->priv, (GMimeEventCallback) content_disposition_changed, object);
 		g_object_unref (mime->disposition);
 	}
 	
@@ -198,7 +195,7 @@ write_content_type (GMimeStream *stream, const char *name, const char *value)
 }
 
 static void
-content_type_changed (GMimeContentType *content_type, GMimeObject *object)
+content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object)
 {
 	GMimeParam *params;
 	GString *string;
@@ -244,7 +241,7 @@ write_disposition (GMimeStream *stream, const char *name, const char *value)
 }
 
 static void
-content_disposition_changed (GMimeContentDisposition *disposition, GMimeObject *object)
+content_disposition_changed (GMimeContentDisposition *disposition, gpointer args, GMimeObject *object)
 {
 	char *str;
 	
@@ -408,13 +405,11 @@ static void
 set_content_type (GMimeObject *object, GMimeContentType *content_type)
 {
 	if (object->content_type) {
-		g_signal_handlers_disconnect_matched (object->content_type,
-						      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-						      0, 0, NULL, content_type_changed, object);
+		g_mime_event_remove (object->content_type->priv, (GMimeEventCallback) content_type_changed, object);
 		g_object_unref (object->content_type);
 	}
 	
-	g_signal_connect (content_type, "changed", G_CALLBACK (content_type_changed), object);
+	g_mime_event_add (content_type->priv, (GMimeEventCallback) content_type_changed, object);
 	object->content_type = content_type;
 	g_object_ref (content_type);
 }
@@ -456,7 +451,7 @@ g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_t
 	
 	GMIME_OBJECT_GET_CLASS (object)->set_content_type (object, content_type);
 	
-	content_type_changed (content_type, object);
+	content_type_changed (content_type, NULL, object);
 }
 
 
@@ -548,13 +543,11 @@ static void
 _g_mime_object_set_content_disposition (GMimeObject *object, GMimeContentDisposition *disposition)
 {
 	if (object->disposition) {
-		g_signal_handlers_disconnect_matched (object->disposition,
-						      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-						      0, 0, NULL, content_disposition_changed, object);
+		g_mime_event_remove (object->disposition->priv, (GMimeEventCallback) content_disposition_changed, object);
 		g_object_unref (object->disposition);
 	}
 	
-	g_signal_connect (disposition, "changed", G_CALLBACK (content_disposition_changed), object);
+	g_mime_event_add (disposition->priv, (GMimeEventCallback) content_disposition_changed, object);
 	object->disposition = disposition;
 	g_object_ref (disposition);
 }
@@ -579,7 +572,7 @@ g_mime_object_set_content_disposition (GMimeObject *object, GMimeContentDisposit
 	
 	_g_mime_object_set_content_disposition (object, disposition);
 	
-	content_disposition_changed (disposition, object);
+	content_disposition_changed (disposition, NULL, object);
 }
 
 
@@ -893,9 +886,7 @@ remove_header (GMimeObject *object, const char *header)
 	switch (i) {
 	case HEADER_CONTENT_DISPOSITION:
 		if (object->disposition) {
-			g_signal_handlers_disconnect_matched (object->disposition,
-							      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-							      0, 0, NULL, content_disposition_changed, object);
+			g_mime_event_remove (object->disposition->priv, (GMimeEventCallback) content_disposition_changed, object);
 			g_object_unref (object->disposition);
 			object->disposition = NULL;
 		}
diff --git a/gmime/gmime-parse-utils.h b/gmime/gmime-parse-utils.h
index 96e361f..9ecbef3 100644
--- a/gmime/gmime-parse-utils.h
+++ b/gmime/gmime-parse-utils.h
@@ -24,15 +24,15 @@
 
 G_BEGIN_DECLS
 
-gboolean g_mime_parse_content_type (const char **in, char **type, char **subtype);
+G_GNUC_INTERNAL gboolean g_mime_parse_content_type (const char **in, char **type, char **subtype);
 
-void g_mime_decode_lwsp (const char **in);
+G_GNUC_INTERNAL void g_mime_decode_lwsp (const char **in);
 #define decode_lwsp(in) g_mime_decode_lwsp (in)
 
-const char *g_mime_decode_word (const char **in);
+G_GNUC_INTERNAL const char *g_mime_decode_word (const char **in);
 #define decode_word(in) g_mime_decode_word (in)
 
-gboolean g_mime_decode_domain (const char **in, GString *domain);
+G_GNUC_INTERNAL gboolean g_mime_decode_domain (const char **in, GString *domain);
 #define decode_domain(in, domain) g_mime_decode_domain (in, domain)
 
 G_END_DECLS
diff --git a/gmime/internet-address.c b/gmime/internet-address.c
index 7dbba42..6309447 100644
--- a/gmime/internet-address.c
+++ b/gmime/internet-address.c
@@ -32,6 +32,7 @@
 #include "gmime-table-private.h"
 #include "gmime-parse-utils.h"
 #include "gmime-iconv-utils.h"
+#include "gmime-events.h"
 #include "gmime-utils.h"
 #include "list.h"
 
@@ -91,131 +92,6 @@ enum {
 };
 
 
-typedef void (* EventCallback) (gpointer sender, gpointer args);
-
-typedef struct _EventListener {
-	struct _EventListener *next;
-	struct _EventListener *prev;
-	EventCallback callback;
-	gpointer user_data;
-	int blocked;
-} EventListener;
-
-static EventListener *
-event_listener_new (EventCallback callback, gpointer user_data)
-{
-	EventListener *listener;
-	
-	listener = g_slice_new (EventListener);
-	listener->user_data = user_data;
-	listener->callback = callback;
-	listener->prev = NULL;
-	listener->next = NULL;
-	listener->blocked = 0;
-	
-	return listener;
-}
-
-static void
-event_listener_free (EventListener *listener)
-{
-	g_slice_free (EventListener, listener);
-}
-
-
-static List *
-event_list_new (void)
-{
-	List *list;
-	
-	list = g_slice_new (List);
-	list_init (list);
-	
-	return list;
-}
-
-static void
-event_list_free (List *list)
-{
-	EventListener *node, *next;
-	
-	node = (EventListener *) list->head;
-	while (node->next) {
-		next = node->next;
-		event_listener_free (node);
-		node = next;
-	}
-	
-	g_slice_free (List, list);
-}
-
-static EventListener *
-event_list_find_listener (List *list, EventCallback callback, gpointer user_data)
-{
-	EventListener *node;
-	
-	node = (EventListener *) list->head;
-	while (node->next) {
-		if (node->callback == callback && node->user_data == user_data)
-			return node;
-		node = node->next;
-	}
-	
-	return NULL;
-}
-
-static void
-event_list_block (List *list, EventCallback callback, gpointer user_data)
-{
-	EventListener *listener;
-	
-	if ((listener = event_list_find_listener (list, callback, user_data)))
-		listener->blocked++;
-}
-
-static void
-event_list_unblock (List *list, EventCallback callback, gpointer user_data)
-{
-	EventListener *listener;
-	
-	if ((listener = event_list_find_listener (list, callback, user_data)))
-		listener->blocked--;
-}
-
-static void
-event_list_add (List *list, EventCallback callback, gpointer user_data)
-{
-	EventListener *listener;
-	
-	listener = event_listener_new (callback, user_data);
-	list_append (list, (ListNode *) listener);
-}
-
-static void
-event_list_remove (List *list, EventCallback callback, gpointer user_data)
-{
-	EventListener *listener;
-	
-	if ((listener = event_list_find_listener (list, callback, user_data))) {
-		list_unlink ((ListNode *) listener);
-		event_listener_free (listener);
-	}
-}
-
-static void
-event_list_emit (List *list, gpointer sender)
-{
-	EventListener *node;
-	
-	node = (EventListener *) list->head;
-	while (node->next) {
-		if (node->blocked <= 0)
-			node->callback (sender, node->user_data);
-		node = node->next;
-	}
-}
-
-
 static void internet_address_class_init (InternetAddressClass *klass);
 static void internet_address_init (InternetAddress *ia, InternetAddressClass *klass);
 static void internet_address_finalize (GObject *object);
@@ -265,7 +141,7 @@ internet_address_class_init (InternetAddressClass *klass)
 static void
 internet_address_init (InternetAddress *ia, InternetAddressClass *klass)
 {
-	ia->priv = event_list_new ();
+	ia->priv = g_mime_event_new ((GObject *) ia);
 	ia->name = NULL;
 }
 
@@ -274,7 +150,7 @@ internet_address_finalize (GObject *object)
 {
 	InternetAddress *ia = (InternetAddress *) object;
 	
-	event_list_free (ia->priv);
+	g_mime_event_destroy (ia->priv);
 	g_free (ia->name);
 	
 	G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -311,7 +187,7 @@ internet_address_set_name (InternetAddress *ia, const char *name)
 	
 	_internet_address_set_name (ia, name);
 	
-	event_list_emit (ia->priv, ia);
+	g_mime_event_emit (ia->priv, NULL);
 }
 
 
@@ -471,7 +347,7 @@ internet_address_mailbox_set_addr (InternetAddressMailbox *mailbox, const char *
 	g_free (mailbox->addr);
 	mailbox->addr = g_strdup (addr);
 	
-	event_list_emit (((InternetAddress *) mailbox)->priv, mailbox);
+	g_mime_event_emit (((InternetAddress *) mailbox)->priv, NULL);
 }
 
 
@@ -541,9 +417,9 @@ internet_address_group_class_init (InternetAddressGroupClass *klass)
 }
 
 static void
-members_changed (InternetAddressList *members, InternetAddress *group)
+members_changed (InternetAddressList *members, gpointer args, InternetAddress *group)
 {
-	event_list_emit (((InternetAddress *) group)->priv, group);
+	g_mime_event_emit (((InternetAddress *) group)->priv, NULL);
 }
 
 static void
@@ -551,7 +427,7 @@ internet_address_group_init (InternetAddressGroup *group, InternetAddressGroupCl
 {
 	group->members = internet_address_list_new ();
 	
-	event_list_add (group->members->priv, (EventCallback) members_changed, group);
+	g_mime_event_add (group->members->priv, (GMimeEventCallback) members_changed, group);
 }
 
 static void
@@ -559,7 +435,7 @@ internet_address_group_finalize (GObject *object)
 {
 	InternetAddressGroup *group = (InternetAddressGroup *) object;
 	
-	event_list_remove (group->members->priv, (EventCallback) members_changed, group);
+	g_mime_event_remove (group->members->priv, (GMimeEventCallback) members_changed, group);
 	
 	g_object_unref (group->members);
 	
@@ -605,18 +481,18 @@ internet_address_group_set_members (InternetAddressGroup *group, InternetAddress
 		return;
 	
 	if (group->members) {
-		event_list_remove (group->members->priv, (EventCallback) members_changed, group);
+		g_mime_event_remove (group->members->priv, (GMimeEventCallback) members_changed, group);
 		g_object_unref (group->members);
 	}
 	
 	if (members) {
-		event_list_add (members->priv, (EventCallback) members_changed, group);
+		g_mime_event_add (members->priv, (GMimeEventCallback) members_changed, group);
 		g_object_ref (members);
 	}
 	
 	group->members = members;
 	
-	event_list_emit (((InternetAddress *) group)->priv, group);
+	g_mime_event_emit (((InternetAddress *) group)->priv, NULL);
 }
 
 
@@ -705,14 +581,14 @@ internet_address_list_class_init (InternetAddressListClass *klass)
 static void
 internet_address_list_init (InternetAddressList *list, InternetAddressListClass *klass)
 {
-	list->priv = event_list_new ();
+	list->priv = g_mime_event_new ((GObject *) list);
 	list->array = g_ptr_array_new ();
 }
 
 static void
-address_changed (InternetAddress *ia, InternetAddressList *list)
+address_changed (InternetAddress *ia, gpointer args, InternetAddressList *list)
 {
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 }
 
 static void
@@ -724,11 +600,11 @@ internet_address_list_finalize (GObject *object)
 	
 	for (i = 0; i < list->array->len; i++) {
 		ia = (InternetAddress *) list->array->pdata[i];
-		event_list_remove (ia->priv, (EventCallback) address_changed, list);
+		g_mime_event_remove (ia->priv, (GMimeEventCallback) address_changed, list);
 		g_object_unref (ia);
 	}
 	
-	event_list_free (list->priv);
+	g_mime_event_destroy (list->priv);
 	
 	g_ptr_array_free (list->array, TRUE);
 	
@@ -783,13 +659,13 @@ internet_address_list_clear (InternetAddressList *list)
 	
 	for (i = 0; i < list->array->len; i++) {
 		ia = (InternetAddress *) list->array->pdata[i];
-		event_list_remove (ia->priv, (EventCallback) address_changed, list);
+		g_mime_event_remove (ia->priv, (GMimeEventCallback) address_changed, list);
 		g_object_unref (ia);
 	}
 	
 	g_ptr_array_set_size (list->array, 0);
 	
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 }
 
 
@@ -798,7 +674,7 @@ _internet_address_list_add (InternetAddressList *list, InternetAddress *ia)
 {
 	int index;
 	
-	event_list_add (ia->priv, (EventCallback) address_changed, list);
+	g_mime_event_add (ia->priv, (GMimeEventCallback) address_changed, list);
 	
 	index = list->array->len;
 	g_ptr_array_add (list->array, ia);
@@ -827,7 +703,7 @@ internet_address_list_add (InternetAddressList *list, InternetAddress *ia)
 	index = _internet_address_list_add (list, ia);
 	g_object_ref (ia);
 	
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 	
 	return index;
 }
@@ -863,12 +739,12 @@ internet_address_list_prepend (InternetAddressList *list, InternetAddressList *p
 	
 	for (i = 0; i < prepend->array->len; i++) {
 		ia = (InternetAddress *) prepend->array->pdata[i];
-		event_list_add (ia->priv, (EventCallback) address_changed, list);
+		g_mime_event_add (ia->priv, (GMimeEventCallback) address_changed, list);
 		list->array->pdata[i] = ia;
 		g_object_ref (ia);
 	}
 	
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 }
 
 
@@ -893,12 +769,12 @@ internet_address_list_append (InternetAddressList *list, InternetAddressList *ap
 	
 	for (i = 0; i < append->array->len; i++) {
 		ia = (InternetAddress *) append->array->pdata[i];
-		event_list_add (ia->priv, (EventCallback) address_changed, list);
+		g_mime_event_add (ia->priv, (GMimeEventCallback) address_changed, list);
 		list->array->pdata[len + i] = ia;
 		g_object_ref (ia);
 	}
 	
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 }
 
 
@@ -921,7 +797,7 @@ internet_address_list_insert (InternetAddressList *list, int index, InternetAddr
 	g_return_if_fail (IS_INTERNET_ADDRESS (ia));
 	g_return_if_fail (index >= 0);
 	
-	event_list_add (ia->priv, (EventCallback) address_changed, list);
+	g_mime_event_add (ia->priv, (GMimeEventCallback) address_changed, list);
 	g_object_ref (ia);
 	
 	if ((guint) index < list->array->len) {
@@ -938,7 +814,7 @@ internet_address_list_insert (InternetAddressList *list, int index, InternetAddr
 		g_ptr_array_add (list->array, ia);
 	}
 	
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 }
 
 
@@ -992,12 +868,12 @@ internet_address_list_remove_at (InternetAddressList *list, int index)
 		return FALSE;
 	
 	ia = list->array->pdata[index];
-	event_list_remove (ia->priv, (EventCallback) address_changed, list);
+	g_mime_event_remove (ia->priv, (GMimeEventCallback) address_changed, list);
 	g_object_unref (ia);
 	
 	g_ptr_array_remove_index (list->array, index);
 	
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 	
 	return TRUE;
 }
@@ -1101,14 +977,14 @@ internet_address_list_set_address (InternetAddressList *list, int index, Interne
 	if ((old = list->array->pdata[index]) == ia)
 		return;
 	
-	event_list_remove (old->priv, (EventCallback) address_changed, list);
+	g_mime_event_remove (old->priv, (GMimeEventCallback) address_changed, list);
 	g_object_unref (old);
 	
-	event_list_add (ia->priv, (EventCallback) address_changed, list);
+	g_mime_event_add (ia->priv, (GMimeEventCallback) address_changed, list);
 	list->array->pdata[index] = ia;
 	g_object_ref (ia);
 	
-	event_list_emit (list->priv, list);
+	g_mime_event_emit (list->priv, NULL);
 }
 
 
@@ -1636,31 +1512,3 @@ internet_address_list_parse_string (const char *str)
 	
 	return addrlist;
 }
-
-
-void
-_internet_address_list_block_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data)
-{
-	event_list_block (list->priv, callback, user_data);
-}
-
-
-void
-_internet_address_list_unblock_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data)
-{
-	event_list_unblock (list->priv, callback, user_data);
-}
-
-
-void
-_internet_address_list_add_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data)
-{
-	event_list_add (list->priv, callback, user_data);
-}
-
-
-void
-_internet_address_list_remove_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data)
-{
-	event_list_remove (list->priv, callback, user_data);
-}



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