gmime r1406 - in trunk: . docs/reference gmime tests



Author: fejj
Date: Tue Aug 19 14:58:39 2008
New Revision: 1406
URL: http://svn.gnome.org/viewvc/gmime?rev=1406&view=rev

Log:
2008-08-19  Jeffrey Stedfast  <fejj novell com>

	* gmime/internet-address.c: InternetAddress is now GObject with a
	"changed" signal. Split out InternetAddressMailbox and
	InternetAddressGroup subclasses of
	InternetAddress. InternetAddressList is now also a GObject with a
	"changed" signal. These changes were made so that manipulating an
	InternetAddress[List] of recipients will auto-magically update
	GMimeMessage's corresponding recipient header.

2008-08-18  Jeffrey Stedfast  <fejj novell com>

	* gmime/gmime-message.c (g_mime_message_get_recipients): Now
	returns a ref'd version of the InternetAddressList. You must now
	unref the list when you are done with it.



Modified:
   trunk/ChangeLog
   trunk/Makefile.am
   trunk/configure.in
   trunk/docs/reference/gmime-sections.txt
   trunk/gmime/Makefile.am
   trunk/gmime/gmime-message.c
   trunk/gmime/gmime-message.h
   trunk/gmime/internet-address.c
   trunk/gmime/internet-address.h
   trunk/tests/test-mime.c

Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am	(original)
+++ trunk/Makefile.am	Tue Aug 19 14:58:39 2008
@@ -28,6 +28,7 @@
 	iconv-detect.c		\
 	zentimer.h 		\
 	zenprofiler.h		\
+	marshal.mk		\
 	gtk-doc.make
 
 BUILD_EXTRA_DIST = 		\

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Tue Aug 19 14:58:39 2008
@@ -80,6 +80,9 @@
 
 AM_MAINTAINER_MODE
 
+GMIME_MARSHAL_RULE=$srcdir/marshal.mk
+AC_SUBST_FILE(GMIME_MARSHAL_RULE)
+
 dnl Checks for header files.
 AC_CHECK_HEADERS(sys/mman.h)
 AC_CHECK_HEADERS(sys/param.h)

Modified: trunk/docs/reference/gmime-sections.txt
==============================================================================
--- trunk/docs/reference/gmime-sections.txt	(original)
+++ trunk/docs/reference/gmime-sections.txt	Tue Aug 19 14:58:39 2008
@@ -933,26 +933,21 @@
 
 <SECTION>
 <FILE>internet-address</FILE>
-InternetAddressType
-InternetAddressList
 InternetAddress
-internet_address_new
-internet_address_new_mailbox
-internet_address_new_group
-internet_address_ref
-internet_address_unref
-internet_address_get_type
+InternetAddressMailbox
+InternetAddressGroup
+InternetAddressList
 internet_address_get_name
 internet_address_set_name
-internet_address_get_addr
-internet_address_set_addr
-internet_address_set_group
-internet_address_add_member
-internet_address_get_members
 internet_address_to_string
+internet_address_mailbox_new
+internet_address_mailbox_get_addr
+internet_address_mailbox_set_addr
+internet_address_group_new
+internet_address_group_get_members
+internet_address_group_set_members
+internet_address_group_add_member
 internet_address_list_new
-internet_address_list_ref
-internet_address_list_unref
 internet_address_list_length
 internet_address_list_clear
 internet_address_list_add
@@ -967,6 +962,39 @@
 internet_address_list_to_string
 internet_address_list_parse_string
 internet_address_list_writer
+
+<SUBSECTION Private>
+internet_address_get_type
+internet_address_list_get_type
+internet_address_group_get_type
+internet_address_mailbox_get_type
+
+<SUBSECTION Standard>
+INTERNET_ADDRESS
+INTERNET_ADDRESS_CLASS
+INTERNET_ADDRESS_GET_CLASS
+INTERNET_ADDRESS_GROUP
+INTERNET_ADDRESS_GROUP_CLASS
+INTERNET_ADDRESS_IS_GROUP
+INTERNET_ADDRESS_IS_GROUP_CLASS
+INTERNET_ADDRESS_IS_MAILBOX
+INTERNET_ADDRESS_IS_MAILBOX_CLASS
+INTERNET_ADDRESS_LIST
+INTERNET_ADDRESS_LIST_CLASS
+INTERNET_ADDRESS_LIST_TYPE
+INTERNET_ADDRESS_MAILBOX
+INTERNET_ADDRESS_MAILBOX_CLASS
+INTERNET_ADDRESS_TYPE
+INTERNET_ADDRESS_TYPE_GROUP
+INTERNET_ADDRESS_TYPE_MAILBOX
+IS_INTERNET_ADDRESS
+IS_INTERNET_ADDRESS_CLASS
+IS_INTERNET_ADDRESS_LIST
+IS_INTERNET_ADDRESS_LIST_CLASS
+InternetAddressClass
+InternetAddressGroupClass
+InternetAddressListClass
+InternetAddressMailboxClass
 </SECTION>
 
 <SECTION>

Modified: trunk/gmime/Makefile.am
==============================================================================
--- trunk/gmime/Makefile.am	(original)
+++ trunk/gmime/Makefile.am	Tue Aug 19 14:58:39 2008
@@ -48,6 +48,7 @@
 	gmime-header.c			\
 	gmime-iconv.c			\
 	gmime-iconv-utils.c		\
+	gmime-marshal.c			\
 	gmime-message.c			\
 	gmime-message-part.c		\
 	gmime-message-partial.c		\
@@ -99,6 +100,7 @@
 	gmime-header.h			\
 	gmime-iconv.h			\
 	gmime-iconv-utils.h		\
+	gmime-marshal.h			\
 	gmime-message.h			\
 	gmime-message-part.h		\
 	gmime-message-partial.h		\
@@ -129,6 +131,9 @@
 	gmime-table-private.h		\
 	gmime-charset-map-private.h
 
+MARSHAL_GENERATED = gmime-marshal.c gmime-marshal.h
+ GMIME_MARSHAL_RULE@
+
 install-data-local: install-libtool-import-lib
 
 uninstall-local: uninstall-libtool-import-lib
@@ -162,3 +167,11 @@
 charset_map_LDFLAGS = 
 charset_map_DEPENDENCIES = 
 charset_map_LDADD = $(top_builddir)/util/libutil.la $(GLIB_LIBS)
+
+BUILT_SOURCES = $(MARSHAL_GENERATED)
+CLEANFILES    = $(BUILT_SOURCES)
+
+EXTRA_DIST = gmime-marshal.list
+
+dist-hook:
+	cd $(distdir); rm -f $(BUILT_SOURCES)

Modified: trunk/gmime/gmime-message.c
==============================================================================
--- trunk/gmime/gmime-message.c	(original)
+++ trunk/gmime/gmime-message.c	Tue Aug 19 14:58:39 2008
@@ -170,7 +170,7 @@
 	InternetAddressList *recipients = value;
 	
 	if (recipients)
-		internet_address_list_unref (recipients);
+		g_object_unref (recipients);
 	
 	return TRUE;
 }
@@ -584,7 +584,7 @@
 	
 	if (value && (addrlist = internet_address_list_parse_string (value))) {
 		internet_address_list_writer (addrlist, str);
-		internet_address_list_unref (addrlist);
+		g_object_unref (addrlist);
 	}
 	
 	g_string_append_c (str, '\n');
@@ -637,7 +637,7 @@
 		g_free (message->from);
 		if ((addrlist = internet_address_list_parse_string (value))) {
 			message->from = internet_address_list_to_string (addrlist, FALSE);
-			internet_address_list_unref (addrlist);
+			g_object_unref (addrlist);
 		} else {
 			message->from = NULL;
 		}
@@ -646,7 +646,7 @@
 		g_free (message->reply_to);
 		if ((addrlist = internet_address_list_parse_string (value))) {
 			message->reply_to = internet_address_list_to_string (addrlist, FALSE);
-			internet_address_list_unref (addrlist);
+			g_object_unref (addrlist);
 		} else {
 			message->reply_to = NULL;
 		}
@@ -804,19 +804,19 @@
 		type = recipient_types[GMIME_RECIPIENT_TYPE_TO];
 		addrlist = g_hash_table_lookup (message->recipients, type);
 		g_hash_table_remove (message->recipients, type);
-		internet_address_list_unref (addrlist);
+		g_object_unref (addrlist);
 		break;
 	case HEADER_CC:
 		type = recipient_types[GMIME_RECIPIENT_TYPE_CC];
 		addrlist = g_hash_table_lookup (message->recipients, type);
 		g_hash_table_remove (message->recipients, type);
-		internet_address_list_unref (addrlist);
+		g_object_unref (addrlist);
 		break;
 	case HEADER_BCC:
 		type = recipient_types[GMIME_RECIPIENT_TYPE_BCC];
 		addrlist = g_hash_table_lookup (message->recipients, type);
 		g_hash_table_remove (message->recipients, type);
-		internet_address_list_unref (addrlist);
+		g_object_unref (addrlist);
 		break;
 	case HEADER_SUBJECT:
 		g_free (message->subject);
@@ -961,13 +961,16 @@
 	
 	g_free (message->from);
 	
-	addrlist = internet_address_list_parse_string (sender);
-	message->from = internet_address_list_to_string (addrlist, FALSE);
-	encoded = internet_address_list_to_string (addrlist, TRUE);
-	internet_address_list_unref (addrlist);
-	
-	g_mime_header_list_set (GMIME_OBJECT (message)->headers, "From", encoded);
-	g_free (encoded);
+	if ((addrlist = internet_address_list_parse_string (sender))) {
+		message->from = internet_address_list_to_string (addrlist, FALSE);
+		encoded = internet_address_list_to_string (addrlist, TRUE);
+		g_mime_header_list_set (GMIME_OBJECT (message)->headers, "From", encoded);
+		g_object_unref (addrlist);
+		g_free (encoded);
+	} else {
+		g_mime_header_list_set (GMIME_OBJECT (message)->headers, "From", "");
+		message->from = NULL;
+	}
 }
 
 
@@ -1029,7 +1032,7 @@
 sync_recipient_header (GMimeMessage *message, GMimeRecipientType type)
 {
 	const char *name = recipient_types[type];
-	const InternetAddressList *recipients;
+	InternetAddressList *recipients;
 	char *string;
 	
 	/* sync the specified recipient header */
@@ -1046,7 +1049,7 @@
  * g_mime_message_add_recipient:
  * @message: MIME Message to change
  * @type: A #GMimeRecipientType
- * @name: The recipient's name
+ * @name: The recipient's name (or %NULL)
  * @address: The recipient's address
  *
  * Add a recipient of a chosen type to the MIME Message.
@@ -1059,10 +1062,9 @@
 	
 	g_return_if_fail (GMIME_IS_MESSAGE (message));
 	g_return_if_fail (type < N_RECIPIENT_TYPES);
-	g_return_if_fail (name != NULL);
 	g_return_if_fail (address != NULL);
 	
-	ia = internet_address_new_mailbox (name, address);
+	ia = internet_address_mailbox_new (name, address);
 	
 	if ((recipients = g_hash_table_lookup (message->recipients, recipient_types[type])))
 		g_hash_table_remove (message->recipients, recipient_types[type]);
@@ -1070,7 +1072,7 @@
 		recipients = internet_address_list_new ();
 	
 	internet_address_list_add (recipients, ia);
-	internet_address_unref (ia);
+	g_object_unref (ia);
 	
 	g_hash_table_insert (message->recipients, (char *) recipient_types[type], recipients);
 	sync_recipient_header (message, type);
@@ -1088,7 +1090,7 @@
 	if ((addrlist = internet_address_list_parse_string (str))) {
 		if (recipients != NULL) {
 			internet_address_list_concat (recipients, addrlist);
-			internet_address_list_unref (addrlist);
+			g_object_unref (addrlist);
 		} else {
 			recipients = addrlist;
 		}
@@ -1131,13 +1133,18 @@
  * Returns: a list of recipients of a chosen type from the MIME
  * Message.
  **/
-const InternetAddressList *
+InternetAddressList *
 g_mime_message_get_recipients (GMimeMessage *message, GMimeRecipientType type)
 {
+	InternetAddressList *list;
+	
 	g_return_val_if_fail (GMIME_IS_MESSAGE (message), NULL);
 	g_return_val_if_fail (type < N_RECIPIENT_TYPES, NULL);
 	
-	return g_hash_table_lookup (message->recipients, recipient_types[type]);
+	if ((list = g_hash_table_lookup (message->recipients, recipient_types[type])))
+		g_object_ref (list);
+	
+	return list;
 }
 
 

Modified: trunk/gmime/gmime-message.h
==============================================================================
--- trunk/gmime/gmime-message.h	(original)
+++ trunk/gmime/gmime-message.h	Tue Aug 19 14:58:39 2008
@@ -104,7 +104,7 @@
 
 void g_mime_message_add_recipient (GMimeMessage *message, GMimeRecipientType type, const char *name, const char *address);
 void g_mime_message_add_recipients_from_string (GMimeMessage *message, GMimeRecipientType type, const char *str);
-const InternetAddressList *g_mime_message_get_recipients (GMimeMessage *message, GMimeRecipientType type);
+InternetAddressList *g_mime_message_get_recipients (GMimeMessage *message, GMimeRecipientType type);
 InternetAddressList *g_mime_message_get_all_recipients (GMimeMessage *message);
 
 void g_mime_message_set_subject (GMimeMessage *message, const char *subject);

Modified: trunk/gmime/internet-address.c
==============================================================================
--- trunk/gmime/internet-address.c	(original)
+++ trunk/gmime/internet-address.c	Tue Aug 19 14:58:39 2008
@@ -43,6 +43,8 @@
 
 #define d(x)
 
+#define MATCH_ID_FUNC_DATA (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)
+
 
 /**
  * SECTION: internet-address
@@ -55,371 +57,578 @@
  **/
 
 
-/**
- * internet_address_new:
- *
- * Creates a new #InternetAddress object
- * 
- * Returns: a new #InternetAddress object.
- **/
-InternetAddress *
-internet_address_new (void)
+enum {
+	INTERNET_ADDRESS_ENCODE = 1 << 0,
+	INTERNET_ADDRESS_FOLD   = 1 << 1,
+};
+
+enum {
+	CHANGED,
+	LAST_SIGNAL
+};
+
+static guint address_signals[LAST_SIGNAL] = { 0 };
+static guint list_signals[LAST_SIGNAL] = { 0 };
+
+
+static void internet_address_class_init (InternetAddressClass *klass);
+static void internet_address_init (InternetAddress *ia, InternetAddressClass *klass);
+static void internet_address_finalize (GObject *object);
+
+
+static GObjectClass *parent_class = NULL;
+
+
+GType
+internet_address_get_type (void)
 {
-	InternetAddress *ia;
+	static GType type = 0;
+	
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (InternetAddressClass),
+			NULL, /* base_class_init */
+			NULL, /* base_class_finalize */
+			(GClassInitFunc) internet_address_class_init,
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof (InternetAddress),
+			0,    /* n_preallocs */
+			(GInstanceInitFunc) internet_address_init,
+		};
+		
+		type = g_type_register_static (G_TYPE_OBJECT, "InternetAddress", &info, 0);
+	}
 	
-	ia = g_new (InternetAddress, 1);
-	ia->type = INTERNET_ADDRESS_NONE;
-	ia->refcount = 1;
+	return type;
+}
+
+
+static void
+internet_address_class_init (InternetAddressClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	
+	parent_class = g_type_class_ref (G_TYPE_OBJECT);
+	
+	object_class->finalize = internet_address_finalize;
+	
+	klass->to_string = NULL;
+	
+	/* signals */
+	address_signals[CHANGED] =
+		g_signal_new ("changed",
+			      INTERNET_ADDRESS_TYPE,
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (InternetAddressClass, changed),
+			      NULL,
+			      NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+}
+
+static void
+internet_address_init (InternetAddress *ia, InternetAddressClass *klass)
+{
 	ia->name = NULL;
-	ia->value.addr = NULL;
+}
+
+static void
+internet_address_finalize (GObject *object)
+{
+	InternetAddress *ia = (InternetAddress *) object;
 	
-	return ia;
+	g_free (ia->name);
+	
+	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 
 /**
- * internet_address_destroy:
+ * internet_address_set_name:
  * @ia: a #InternetAddress
- * 
- * Destroy the #InternetAddress object pointed to by @ia.
+ * @name: the display name for the address group or mailbox
+ *
+ * Set the display name of the #InternetAddress.
  **/
-static void
-internet_address_destroy (InternetAddress *ia)
+void
+internet_address_set_name (InternetAddress *ia, const char *name)
 {
-	g_free (ia->name);
+	char *buf;
 	
-	if (ia->type == INTERNET_ADDRESS_GROUP) {
-		internet_address_list_unref (ia->value.members);
+	g_return_if_fail (IS_INTERNET_ADDRESS (ia));
+	
+	if (ia->name == name)
+		return;
+	
+	if (name) {
+		buf = g_mime_utils_header_decode_phrase (name);
+		g_mime_utils_unquote_string (buf);
+		g_free (ia->name);
+		ia->name = buf;
 	} else {
-		g_free (ia->value.addr);
+		g_free (ia->name);
+		ia->name = NULL;
 	}
 	
-	g_free (ia);
+	g_signal_emit (ia, address_signals[CHANGED], 0);
 }
 
 
 /**
- * internet_address_ref:
+ * internet_address_get_name:
  * @ia: a #InternetAddress
  *
- * Ref's the internet address.
+ * Gets the display name of the #InternetAddress.
+ *
+ * Returns: the display name of @ia.
  **/
-void
-internet_address_ref (InternetAddress *ia)
+const char *
+internet_address_get_name (InternetAddress *ia)
 {
-	g_return_if_fail (ia != NULL);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS (ia), NULL);
 	
-	ia->refcount++;
+	return ia->name;
+}
+
+
+static void
+_internet_address_to_string (InternetAddress *ia, guint32 flags, size_t *linelen, GString *out)
+{
+	;
 }
 
 
 /**
- * internet_address_unref:
- * @ia: a #InternetAddress
+ * internet_address_to_string:
+ * @ia: Internet Address object
+ * @encode: %TRUE if the address should be rfc2047 encoded
  *
- * Unref's the internet address.
+ * Allocates a string containing the contents of the #InternetAddress
+ * object.
+ * 
+ * Returns: the #InternetAddress object as an allocated string in
+ * rfc822 format.
  **/
-void
-internet_address_unref (InternetAddress *ia)
+char *
+internet_address_to_string (InternetAddress *ia, gboolean encode)
 {
-	g_return_if_fail (ia != NULL);
+	guint32 flags = encode ? INTERNET_ADDRESS_ENCODE : 0;
+	size_t linelen = 0;
+	GString *string;
+	char *str;
 	
-	if (ia->refcount <= 1) {
-		internet_address_destroy (ia);
-	} else {
-		ia->refcount--;
+	string = g_string_new ("");
+	INTERNET_ADDRESS_GET_CLASS (ia)->to_string (ia, flags, &linelen, string);
+	str = string->str;
+	
+	g_string_free (string, FALSE);
+	
+	return str;
+}
+
+
+static void internet_address_mailbox_class_init (InternetAddressMailboxClass *klass);
+static void internet_address_mailbox_init (InternetAddressMailbox *mailbox, InternetAddressMailboxClass *klass);
+static void internet_address_mailbox_finalize (GObject *object);
+
+static void mailbox_to_string (InternetAddress *ia, guint32 flags, size_t *linelen, GString *out);
+
+
+static GObjectClass *mailbox_parent_class = NULL;
+
+
+GType
+internet_address_mailbox_get_type (void)
+{
+	static GType type = 0;
+	
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (InternetAddressMailboxClass),
+			NULL, /* base_class_init */
+			NULL, /* base_class_finalize */
+			(GClassInitFunc) internet_address_mailbox_class_init,
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof (InternetAddressMailbox),
+			0,    /* n_preallocs */
+			(GInstanceInitFunc) internet_address_mailbox_init,
+		};
+		
+		type = g_type_register_static (INTERNET_ADDRESS_TYPE, "InternetAddressMailbox", &info, 0);
 	}
+	
+	return type;
+}
+
+
+static void
+internet_address_mailbox_class_init (InternetAddressMailboxClass *klass)
+{
+	InternetAddressClass *address_class = INTERNET_ADDRESS_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	
+	mailbox_parent_class = g_type_class_ref (INTERNET_ADDRESS_TYPE);
+	
+	object_class->finalize = internet_address_mailbox_finalize;
+	
+	address_class->to_string = mailbox_to_string;
+}
+
+static void
+internet_address_mailbox_init (InternetAddressMailbox *mailbox, InternetAddressMailboxClass *klass)
+{
+	mailbox->addr = NULL;
+}
+
+static void
+internet_address_mailbox_finalize (GObject *object)
+{
+	InternetAddressMailbox *mailbox = (InternetAddressMailbox *) object;
+	
+	g_free (mailbox->addr);
+	
+	G_OBJECT_CLASS (mailbox_parent_class)->finalize (object);
 }
 
 
 /**
- * internet_address_new_mailbox:
+ * internet_address_mailbox_new:
  * @name: person's name
  * @addr: person's address
  *
  * Creates a new #InternetAddress object with name @name and address
  * @addr.
  * 
- * Returns: a new #InternetAddress object.
+ * Returns: a new #InternetAddressMailbox object.
  **/
 InternetAddress *
-internet_address_new_mailbox (const char *name, const char *addr)
+internet_address_mailbox_new (const char *name, const char *addr)
 {
-	InternetAddress *ia;
+	InternetAddressMailbox *mailbox;
 	
 	g_return_val_if_fail (addr != NULL, NULL);
 	
-	ia = internet_address_new ();
-	ia->type = INTERNET_ADDRESS_MAILBOX;
-	if (name) {
-		ia->name = g_mime_utils_header_decode_phrase (name);
-		g_mime_utils_unquote_string (ia->name);
-	}
-	ia->value.addr = g_strdup (addr);
+	mailbox = g_object_new (INTERNET_ADDRESS_TYPE_MAILBOX, NULL);
+	internet_address_mailbox_set_addr (mailbox, addr);
 	
-	return ia;
+	if (name != NULL)
+		internet_address_set_name ((InternetAddress *) mailbox, name);
+	
+	return (InternetAddress *) mailbox;
 }
 
 
 /**
- * internet_address_new_group:
- * @name: group name
+ * internet_address_mailbox_set_addr:
+ * @mailbox: a #InternetAddressMailbox
+ * @addr: contact's email address
  *
- * Creates a new #InternetAddress object with group name @name.
- * 
- * Returns: a new #InternetAddress object.
+ * Set the mailbox address.
  **/
-InternetAddress *
-internet_address_new_group (const char *name)
+void
+internet_address_mailbox_set_addr (InternetAddressMailbox *mailbox, const char *addr)
 {
-	InternetAddress *ia;
+	g_return_if_fail (INTERNET_ADDRESS_IS_MAILBOX (mailbox));
 	
-	ia = internet_address_new ();
-	ia->value.members = internet_address_list_new ();
-	ia->type = INTERNET_ADDRESS_GROUP;
-	if (name) {
-		ia->name = g_mime_utils_header_decode_phrase (name);
-		g_mime_utils_unquote_string (ia->name);
-	}
+	if (mailbox->addr == addr)
+		return;
 	
-	return ia;
+	g_free (mailbox->addr);
+	mailbox->addr = g_strdup (addr);
+	
+	g_signal_emit (mailbox, address_signals[CHANGED], 0);
 }
 
 
 /**
- * internet_address_set_name:
- * @ia: internet address
- * @name: group or contact's name
+ * internet_address_mailbox_get_addr:
+ * @mailbox: a #InternetAddressMailbox
  *
- * Set the name of the internet address.
+ * Gets the addr-spec of the internet address mailbox.
+ *
+ * Returns: the address of the mailbox.
  **/
-void
-internet_address_set_name (InternetAddress *ia, const char *name)
+const char *
+internet_address_mailbox_get_addr (InternetAddressMailbox *mailbox)
 {
-	g_return_if_fail (ia != NULL);
+	g_return_if_fail (INTERNET_ADDRESS_IS_MAILBOX (mailbox));
 	
-	g_free (ia->name);
-	if (name) {
-		ia->name = g_mime_utils_header_decode_phrase (name);
-		g_mime_utils_unquote_string (ia->name);
-	} else
-		ia->name = NULL;
+	return mailbox->addr;
 }
 
 
-/**
- * internet_address_set_addr:
- * @ia: internet address
- * @addr: contact's email address
- *
- * Set the internet address's address.
- **/
-void
-internet_address_set_addr (InternetAddress *ia, const char *addr)
+static void internet_address_group_class_init (InternetAddressGroupClass *klass);
+static void internet_address_group_init (InternetAddressGroup *group, InternetAddressGroupClass *klass);
+static void internet_address_group_finalize (GObject *object);
+
+static void group_to_string (InternetAddress *ia, guint32 flags, size_t *linelen, GString *out);
+
+
+static GObjectClass *group_parent_class = NULL;
+
+
+GType
+internet_address_group_get_type (void)
 {
-	g_return_if_fail (ia != NULL);
-	g_return_if_fail (ia->type != INTERNET_ADDRESS_GROUP);
+	static GType type = 0;
 	
-	ia->type = INTERNET_ADDRESS_MAILBOX;
-	g_free (ia->value.addr);
-	ia->value.addr = g_strdup (addr);
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (InternetAddressGroupClass),
+			NULL, /* base_class_init */
+			NULL, /* base_class_finalize */
+			(GClassInitFunc) internet_address_group_class_init,
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof (InternetAddressGroup),
+			0,    /* n_preallocs */
+			(GInstanceInitFunc) internet_address_group_init,
+		};
+		
+		type = g_type_register_static (INTERNET_ADDRESS_TYPE, "InternetAddressGroup", &info, 0);
+	}
+	
+	return type;
 }
 
 
-/**
- * internet_address_set_group:
- * @ia: internet address
- * @group: a list of internet addresses
- *
- * Set the members of the internet address group.
- **/
-void
-internet_address_set_group (InternetAddress *ia, InternetAddressList *group)
+static void
+internet_address_group_class_init (InternetAddressGroupClass *klass)
 {
-	g_return_if_fail (ia != NULL);
-	g_return_if_fail (ia->type != INTERNET_ADDRESS_MAILBOX);
-	
-	ia->type = INTERNET_ADDRESS_GROUP;
+	InternetAddressClass *address_class = INTERNET_ADDRESS_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	
-	if (group)
-		internet_address_list_ref (group);
+	group_parent_class = g_type_class_ref (INTERNET_ADDRESS_TYPE);
 	
-	if (ia->value.members)
-		internet_address_list_unref (ia->value.members);
+	object_class->finalize = internet_address_group_finalize;
 	
-	ia->value.members = group;
+	address_class->to_string = group_to_string;
 }
 
+static void
+members_changed (InternetAddressList *members, InternetAddress *group)
+{
+	g_signal_emit (group, address_signals[CHANGED], 0);
+}
 
-/**
- * internet_address_add_member:
- * @ia: internet address
- * @member: group member's internet address
- *
- * Add a contact to the internet address group.
- **/
-void
-internet_address_add_member (InternetAddress *ia, InternetAddress *member)
+static void
+internet_address_group_init (InternetAddressGroup *group, InternetAddressGroupClass *klass)
 {
-	g_return_if_fail (ia != NULL);
-	g_return_if_fail (ia->type != INTERNET_ADDRESS_MAILBOX);
-	g_return_if_fail (member != NULL);
-	
-	ia->type = INTERNET_ADDRESS_GROUP;
-	if (ia->value.members == NULL)
-		ia->value.members = internet_address_list_new ();
+	group->members = internet_address_list_new ();
 	
-	internet_address_list_add (ia->value.members, member);
+	g_signal_connect (group->members, "changed", G_CALLBACK (members_changed), group);
 }
 
-
-/**
- * internet_address_get_type:
- * @ia: internet address
- *
- * Gets the type of the internet address, which will either be
- * #INTERNET_ADDRESS_MAILBOX or #INTERNET_ADDRESS_GROUP.
- *
- * Returns: the type of @ia.
- **/
-InternetAddressType
-internet_address_get_type (const InternetAddress *ia)
+static void
+internet_address_group_finalize (GObject *object)
 {
-	g_return_val_if_fail (ia != NULL, INTERNET_ADDRESS_NONE);
+	InternetAddressGroup *group = (InternetAddressGroup *) object;
 	
-	return ia->type;
+	g_signal_handlers_disconnect_matched (group->members, MATCH_ID_FUNC_DATA,
+					      list_signals[CHANGED], 0, NULL,
+					      G_CALLBACK (members_changed), group);
+	
+	g_object_unref (group->members);
+	
+	G_OBJECT_CLASS (group_parent_class)->finalize (object);
 }
 
 
 /**
- * internet_address_get_name:
- * @ia: internet address
- *
- * Gets the name component of the internet address. If the internet
- * address is a group, it will get the group name.
+ * internet_address_group_new:
+ * @name: group name
  *
- * Returns: the name of @ia.
+ * Creates a new #InternetAddressGroup object with a display name of
+ * @name.
+ * 
+ * Returns: a new #InternetAddressGroup object.
  **/
-const char *
-internet_address_get_name (const InternetAddress *ia)
+InternetAddress *
+internet_address_group_new (const char *name)
 {
-	g_return_val_if_fail (ia != NULL, NULL);
+	InternetAddress *group;
 	
-	return ia->name;
+	group = g_object_new (INTERNET_ADDRESS_TYPE_GROUP, NULL);
+	internet_address_set_name (group, name);
+	
+	return group;
 }
 
 
 /**
- * internet_address_get_addr:
- * @ia: a #InternetAddress of type #INTERNET_ADDRESS_MAILBOX
- *
- * Gets the addr-spec of the internet address.
+ * internet_address_group_set_members:
+ * @group: a #InternetAddressGroup
+ * @members: a #InternetAddressList
  *
- * Returns: the address of @ia.
+ * Set the members of the internet address group.
  **/
-const char *
-internet_address_get_addr (const InternetAddress *ia)
+void
+internet_address_group_set_members (InternetAddressGroup *group, InternetAddressList *members)
 {
-	g_return_val_if_fail (ia != NULL, NULL);
-	g_return_val_if_fail (ia->type != INTERNET_ADDRESS_GROUP, NULL);
+	g_return_if_fail (INTERNET_ADDRESS_IS_GROUP (group));
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (members));
+	
+	if (group->members == members)
+		return;
+	
+	if (group->members) {
+		g_signal_handlers_disconnect_matched (group->members, MATCH_ID_FUNC_DATA,
+						      list_signals[CHANGED], 0, NULL,
+						      G_CALLBACK (members_changed), group);
+		
+		g_object_unref (group->members);
+	}
 	
-	return ia->value.addr;
+	if (members) {
+		g_signal_connect (members, "changed", G_CALLBACK (members_changed), group);
+		g_object_ref (members);
+	}
+	
+	group->members = members;
+	
+	g_signal_emit (group, address_signals[CHANGED], 0);
 }
 
 
 /**
- * internet_address_get_members:
- * @ia: a #InternetAddress of type #INTERNET_ADDRESS_GROUP
+ * internet_address_group_get_members:
+ * @group: a #InternetAddressGroup
  *
  * Gets the #InternetAddressList containing the group members of an
  * rfc822 group address.
  *
- * Returns: a ref'd #InternetAddressList containing the members of
- * @ia.
+ * Returns: a #InternetAddressList containing the members of @group.
  **/
 InternetAddressList *
-internet_address_get_members (const InternetAddress *ia)
+internet_address_group_get_members (InternetAddressGroup *group)
 {
-	g_return_val_if_fail (ia != NULL, NULL);
-	g_return_val_if_fail (ia->type != INTERNET_ADDRESS_MAILBOX, NULL);
+	g_return_val_if_fail (INTERNET_ADDRESS_IS_GROUP (group), NULL);
 	
-	if (ia->value.members)
-		internet_address_list_ref (ia->value.members);
+	g_object_ref (group->members);
 	
-	return ia->value.members;
+	return group->members;
 }
 
 
 /**
- * internet_address_list_new:
- *
- * Creates a new #InternetAddressList.
+ * internet_address_group_add_member:
+ * @group: a #InternetAddressGroup
+ * @member: a #InternetAddress
  *
- * Returns: a new #InternetAddressList.
+ * Add a contact to the internet address group.
  **/
-InternetAddressList *
-internet_address_list_new (void)
+void
+internet_address_group_add_member (InternetAddressGroup *group, InternetAddress *member)
 {
-	InternetAddressList *list;
+	g_return_if_fail (INTERNET_ADDRESS_IS_GROUP (group));
+	g_return_if_fail (IS_INTERNET_ADDRESS (member));
 	
-	list = g_new (InternetAddressList, 1);
-	list->array = g_ptr_array_new ();
-	list->refcount = 1;
+	internet_address_list_add (group->members, member);
+}
+
+
+static void internet_address_list_class_init (InternetAddressListClass *klass);
+static void internet_address_list_init (InternetAddressList *list, InternetAddressListClass *klass);
+static void internet_address_list_finalize (GObject *object);
+
+
+static GObjectClass *list_parent_class = NULL;
+
+
+GType
+internet_address_list_get_type (void)
+{
+	static GType type = 0;
 	
-	return list;
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (InternetAddressListClass),
+			NULL, /* base_class_init */
+			NULL, /* base_class_finalize */
+			(GClassInitFunc) internet_address_list_class_init,
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof (InternetAddressList),
+			0,    /* n_preallocs */
+			(GInstanceInitFunc) internet_address_list_init,
+		};
+		
+		type = g_type_register_static (G_TYPE_OBJECT, "InternetAddressList", &info, 0);
+	}
+	
+	return type;
 }
 
 
-/**
- * internet_address_list_destroy:
- * @list: a #InternetAddressList
- *
- * Destroys the list of #InternetAddress objects.
- **/
 static void
-internet_address_list_destroy (InternetAddressList *list)
+internet_address_list_class_init (InternetAddressListClass *klass)
 {
-	guint i;
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	
-	for (i = 0; i < list->array->len; i++)
-		internet_address_unref (list->array->pdata[i]);
+	list_parent_class = g_type_class_ref (G_TYPE_OBJECT);
 	
-	g_ptr_array_free (list->array, TRUE);
-	g_free (list);
+	object_class->finalize = internet_address_list_finalize;
+	
+	/* signals */
+	list_signals[CHANGED] =
+		g_signal_new ("changed",
+			      internet_address_list_get_type (),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (InternetAddressListClass, changed),
+			      NULL,
+			      NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+}
+
+static void
+internet_address_list_init (InternetAddressList *list, InternetAddressListClass *klass)
+{
+	list->array = g_ptr_array_new ();
 }
 
+static void
+address_changed (InternetAddress *ia, InternetAddressList *list)
+{
+	g_signal_emit (list, list_signals[CHANGED], 0);
+}
 
-/**
- * internet_address_list_ref:
- * @list: a #InternetAddressList
- *
- * Ref's the internet address list.
- **/
-void
-internet_address_list_ref (InternetAddressList *list)
+static void
+internet_address_list_finalize (GObject *object)
 {
-	g_return_if_fail (list != NULL);
+	InternetAddressList *list = (InternetAddressList *) object;
+	InternetAddress *ia;
+	guint i;
 	
-	list->refcount++;
+	for (i = 0; i < list->array->len; i++) {
+		ia = (InternetAddress *) list->array->pdata[i];
+		
+		g_signal_handlers_disconnect_matched (ia, MATCH_ID_FUNC_DATA,
+						      address_signals[CHANGED], 0, NULL,
+						      G_CALLBACK (address_changed), list);
+		
+		g_object_unref (ia);
+	}
+	
+	g_ptr_array_free (list->array, TRUE);
+	
+	G_OBJECT_CLASS (list_parent_class)->finalize (object);
 }
 
 
 /**
- * internet_address_list_unref:
- * @list: a #InternetAddressList
+ * internet_address_list_new:
  *
- * Unref's the internet address list.
+ * Creates a new #InternetAddressList.
+ *
+ * Returns: a new #InternetAddressList.
  **/
-void
-internet_address_list_unref (InternetAddressList *list)
+InternetAddressList *
+internet_address_list_new (void)
 {
-	g_return_if_fail (list != NULL);
-	
-	if (list->refcount <= 1) {
-		internet_address_list_destroy (list);
-	} else {
-		list->refcount--;
-	}
+	return g_object_new (INTERNET_ADDRESS_LIST_TYPE, NULL);
 }
 
 
@@ -432,9 +641,9 @@
  * Returns: the number of #InternetAddress objects in the list.
  **/
 int
-internet_address_list_length (const InternetAddressList *list)
+internet_address_list_length (InternetAddressList *list)
 {
-	g_return_val_if_fail (list != NULL, -1);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), -1);
 	
 	return list->array->len;
 }
@@ -449,14 +658,24 @@
 void
 internet_address_list_clear (InternetAddressList *list)
 {
+	InternetAddress *ia;
 	guint i;
 	
-	g_return_if_fail (list != NULL);
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (list));
 	
-	for (i = 0; i < list->array->len; i++)
-		internet_address_unref (list->array->pdata[i]);
+	for (i = 0; i < list->array->len; i++) {
+		ia = (InternetAddress *) list->array->pdata[i];
+		
+		g_signal_handlers_disconnect_matched (ia, MATCH_ID_FUNC_DATA,
+						      address_signals[CHANGED], 0, NULL,
+						      G_CALLBACK (address_changed), list);
+		
+		g_object_unref (ia);
+	}
 	
 	g_ptr_array_set_size (list->array, 0);
+	
+	g_signal_emit (list, list_signals[CHANGED], 0);
 }
 
 
@@ -472,13 +691,18 @@
 int
 internet_address_list_add (InternetAddressList *list, InternetAddress *ia)
 {
-	g_return_val_if_fail (list != NULL, -1);
-	g_return_val_if_fail (ia != NULL, -1);
+	int index;
 	
+	g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), -1);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS (ia), -1);
+	
+	index = list->array->len;
 	g_ptr_array_add (list->array, ia);
-	internet_address_ref (ia);
+	g_object_ref (ia);
+	
+	g_signal_emit (list, list_signals[CHANGED], 0);
 	
-	return list->array->len - 1;
+	return index;
 }
 
 
@@ -495,14 +719,17 @@
 	InternetAddress *ia;
 	guint i;
 	
-	g_return_if_fail (concat != NULL);
-	g_return_if_fail (list != NULL);
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (concat));
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (list));
 	
 	for (i = 0; i < concat->array->len; i++) {
 		ia = (InternetAddress *) concat->array->pdata[i];
+		g_signal_connect (ia, "changed", G_CALLBACK (address_changed), list);
 		g_ptr_array_add (list->array, ia);
-		internet_address_ref (ia);
+		g_object_ref (ia);
 	}
+	
+	g_signal_emit (list, list_signals[CHANGED], 0);
 }
 
 
@@ -521,26 +748,28 @@
 	char *dest, *src;
 	size_t n;
 	
-	g_return_if_fail (list != NULL);
-	g_return_if_fail (ia != NULL);
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (list));
+	g_return_if_fail (IS_INTERNET_ADDRESS (ia));
 	g_return_if_fail (index < 0);
 	
-	internet_address_ref (ia);
+	g_signal_connect (ia, "changed", G_CALLBACK (address_changed), list);
+	g_object_ref (ia);
 	
-	if ((guint) index >= list->array->len) {
+	if ((guint) index < list->array->len) {
+		g_ptr_array_set_size (list->array, list->array->len + 1);
+		
+		dest = ((char *) list->array->pdata) + (sizeof (void *) * (index + 1));
+		src = ((char *) list->array->pdata) + (sizeof (void *) * index);
+		n = list->array->len - index - 1;
+		
+		g_memmove (dest, src, (sizeof (void *) * n));
+		list->array->pdata[index] = ia;
+	} else {
 		/* the easy case */
 		g_ptr_array_add (list->array, ia);
-		return;
 	}
 	
-	g_ptr_array_set_size (list->array, list->array->len + 1);
-	
-	dest = ((char *) list->array->pdata) + (sizeof (void *) * (index + 1));
-	src = ((char *) list->array->pdata) + (sizeof (void *) * index);
-	n = list->array->len - index - 1;
-	
-	g_memmove (dest, src, (sizeof (void *) * n));
-	list->array->pdata[index] = ia;
+	g_signal_emit (list, list_signals[CHANGED], 0);
 }
 
 
@@ -559,8 +788,8 @@
 {
 	int index;
 	
-	g_return_val_if_fail (list != NULL, FALSE);
-	g_return_val_if_fail (ia != NULL, FALSE);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), FALSE);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS (ia), FALSE);
 	
 	if ((index = internet_address_list_index_of (list, ia)) == -1)
 		return FALSE;
@@ -585,16 +814,24 @@
 gboolean
 internet_address_list_remove_at (InternetAddressList *list, int index)
 {
-	g_return_val_if_fail (list != NULL, FALSE);
+	InternetAddress *ia;
+	
+	g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), FALSE);
 	g_return_val_if_fail (index < 0, FALSE);
 	
 	if (index >= list->array->len)
 		return FALSE;
 	
-	internet_address_unref (list->array->pdata[index]);
+	ia = list->array->pdata[index];
+	g_signal_handlers_disconnect_matched (ia, MATCH_ID_FUNC_DATA,
+					      address_signals[CHANGED], 0, NULL,
+					      G_CALLBACK (address_changed), list);
+	g_object_unref (ia);
 	
 	g_ptr_array_remove_index (list->array, index);
 	
+	g_signal_emit (list, list_signals[CHANGED], 0);
+	
 	return TRUE;
 }
 
@@ -611,7 +848,7 @@
  * within the specified #InternetAddressList or %FALSE otherwise.
  **/
 gboolean
-internet_address_list_contains (const InternetAddressList *list, const InternetAddress *ia)
+internet_address_list_contains (InternetAddressList *list, InternetAddress *ia)
 {
 	return internet_address_list_index_of (list, ia) != -1;
 }
@@ -630,12 +867,12 @@
  * #InternetAddressList.
  **/
 int
-internet_address_list_index_of (const InternetAddressList *list, const InternetAddress *ia)
+internet_address_list_index_of (InternetAddressList *list, InternetAddress *ia)
 {
 	guint i;
 	
-	g_return_val_if_fail (list != NULL, -1);
-	g_return_val_if_fail (ia != NULL, -1);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), -1);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS (ia), -1);
 	
 	for (i = 0; i < list->array->len; i++) {
 		if (list->array->pdata[i] == ia)
@@ -657,18 +894,18 @@
  * the index is out of range.
  **/
 InternetAddress *
-internet_address_list_get_address (const InternetAddressList *list, int index)
+internet_address_list_get_address (InternetAddressList *list, int index)
 {
 	InternetAddress *ia;
 	
-	g_return_val_if_fail (list != NULL, NULL);
+	g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), NULL);
 	g_return_val_if_fail (index < 0, NULL);
 	
 	if ((guint) index >= list->array->len)
 		return NULL;
 	
 	ia = list->array->pdata[index];
-	internet_address_ref (ia);
+	g_object_ref (ia);
 	
 	return ia;
 }
@@ -685,8 +922,10 @@
 void
 internet_address_list_set_address (InternetAddressList *list, int index, InternetAddress *ia)
 {
-	g_return_if_fail (list != NULL);
-	g_return_if_fail (ia != NULL);
+	InternetAddress *old;
+	
+	g_return_if_fail (IS_INTERNET_ADDRESS_LIST (list));
+	g_return_if_fail (IS_INTERNET_ADDRESS (ia));
 	g_return_if_fail (index < 0);
 	
 	if ((guint) index > list->array->len)
@@ -697,10 +936,19 @@
 		return;
 	}
 	
-	internet_address_ref (ia);
+	if ((old = list->array->pdata[index]) == ia)
+		return;
+	
+	g_signal_handlers_disconnect_matched (old, MATCH_ID_FUNC_DATA,
+					      address_signals[CHANGED], 0, NULL,
+					      G_CALLBACK (address_changed), list);
+	g_object_unref (old);
 	
-	internet_address_unref (list->array->pdata[index]);
+	g_signal_connect (ia, "changed", G_CALLBACK (address_changed), list);
 	list->array->pdata[index] = ia;
+	g_object_ref (ia);
+	
+	g_signal_emit (list, list_signals[CHANGED], 0);
 }
 
 
@@ -720,13 +968,6 @@
 	return name;
 }
 
-enum {
-	INTERNET_ADDRESS_ENCODE = 1 << 0,
-	INTERNET_ADDRESS_FOLD   = 1 << 1,
-};
-
-static void _internet_address_list_to_string (const InternetAddressList *list, guint32 flags, size_t *linelen, GString *string);
-
 static void
 linewrap (GString *string)
 {
@@ -790,95 +1031,77 @@
 }
 
 static void
-_internet_address_to_string (const InternetAddress *ia, guint32 flags, size_t *linelen, GString *string)
+mailbox_to_string (InternetAddress *ia, guint32 flags, size_t *linelen, GString *string)
 {
+	InternetAddressMailbox *mailbox = (InternetAddressMailbox *) ia;
 	gboolean encode = flags & INTERNET_ADDRESS_ENCODE;
 	gboolean fold = flags & INTERNET_ADDRESS_FOLD;
 	char *name;
 	size_t len;
 	
-	if (ia->type == INTERNET_ADDRESS_MAILBOX) {
-		if (ia->name && *ia->name) {
-			name = encoded_name (ia->name, encode);
-			len = strlen (name);
-			
-			if (fold && (*linelen + len) > GMIME_FOLD_LEN) {
-				if (len > GMIME_FOLD_LEN) {
-					/* we need to break up the name */
-					append_folded_name (string, linelen, name);
-				} else {
-					/* the name itself is short enough to fit on a single
-					 * line, but only if we write it on a line by itself */
-					if (*linelen > 1) {
-						linewrap (string);
-						*linelen = 1;
-					}
-					
-					g_string_append_len (string, name, len);
-					*linelen += len;
-				}
+	if (ia->name && *ia->name) {
+		name = encoded_name (ia->name, encode);
+		len = strlen (name);
+		
+		if (fold && (*linelen + len) > GMIME_FOLD_LEN) {
+			if (len > GMIME_FOLD_LEN) {
+				/* we need to break up the name */
+				append_folded_name (string, linelen, name);
 			} else {
-				/* we can safly fit the name on this line */
+				/* the name itself is short enough to fit on a single
+				 * line, but only if we write it on a line by itself */
+				if (*linelen > 1) {
+					linewrap (string);
+					*linelen = 1;
+				}
+				
 				g_string_append_len (string, name, len);
 				*linelen += len;
 			}
-			
-			g_free (name);
-			
-			len = strlen (ia->value.addr);
-			
-			if (fold && (*linelen + len + 3) >= GMIME_FOLD_LEN) {
-				g_string_append_len (string, "\n\t<", 3);
-				*linelen = 2;
-			} else {
-				g_string_append_len (string, " <", 2);
-				*linelen += 2;
-			}
-			
-			g_string_append_len (string, ia->value.addr, len);
-			g_string_append_c (string, '>');
-			*linelen += len + 1;
 		} else {
-			len = strlen (ia->value.addr);
-			
-			if (fold && (*linelen + len) > GMIME_FOLD_LEN) {
-				linewrap (string);
-				*linelen = 1;
-			}
-			
-			g_string_append_len (string, ia->value.addr, len);
+			/* we can safly fit the name on this line */
+			g_string_append_len (string, name, len);
 			*linelen += len;
 		}
-	} else if (ia->type == INTERNET_ADDRESS_GROUP) {
-		InternetAddressList *members;
 		
-		name = encoded_name (ia->name, encode);
-		len = strlen (name);
+		g_free (name);
+		
+		len = strlen (mailbox->addr);
+		
+		if (fold && (*linelen + len + 3) >= GMIME_FOLD_LEN) {
+			g_string_append_len (string, "\n\t<", 3);
+			*linelen = 2;
+		} else {
+			g_string_append_len (string, " <", 2);
+			*linelen += 2;
+		}
+		
+		g_string_append_len (string, mailbox->addr, len);
+		g_string_append_c (string, '>');
+		*linelen += len + 1;
+	} else {
+		len = strlen (mailbox->addr);
 		
-		if (fold && *linelen > 1 && (*linelen + len + 1) > GMIME_FOLD_LEN) {
+		if (fold && (*linelen + len) > GMIME_FOLD_LEN) {
 			linewrap (string);
 			*linelen = 1;
 		}
 		
-		g_string_append_len (string, name, len);
-		g_string_append_len (string, ": ", 2);
-		*linelen += len + 2;
-		g_free (name);
-		
-		members = ia->value.members;
-		_internet_address_list_to_string (members, flags, linelen, string);
-		g_string_append_c (string, ';');
-		*linelen += 1;
+		g_string_append_len (string, mailbox->addr, len);
+		*linelen += len;
 	}
 }
 
 static void
 _internet_address_list_to_string (const InternetAddressList *list, guint32 flags, size_t *linelen, GString *string)
 {
+	InternetAddress *ia;
 	guint i;
 	
 	for (i = 0; i < list->array->len; i++) {
-		_internet_address_to_string (list->array->pdata[i], flags, linelen, string);
+		ia = (InternetAddress *) list->array->pdata[i];
+		
+		INTERNET_ADDRESS_GET_CLASS (ia)->to_string (ia, flags, linelen, string);
 		
 		if (i + 1 < list->array->len) {
 			g_string_append (string, ", ");
@@ -887,33 +1110,31 @@
 	}
 }
 
-
-/**
- * internet_address_to_string:
- * @ia: Internet Address object
- * @encode: TRUE if the address should be rfc2047 encoded
- *
- * Allocates a string containing the contents of the #InternetAddress
- * object.
- * 
- * Returns: the #InternetAddress object as an allocated string in
- * rfc822 format.
- **/
-char *
-internet_address_to_string (const InternetAddress *ia, gboolean encode)
+static void
+group_to_string (InternetAddress *ia, guint32 flags, size_t *linelen, GString *string)
 {
-	guint32 flags = encode ? INTERNET_ADDRESS_ENCODE : 0;
-	size_t linelen = 0;
-	GString *string;
-	char *str;
-	
-	string = g_string_new ("");
-	_internet_address_to_string (ia, flags, &linelen, string);
-	str = string->str;
+	InternetAddressGroup *group = (InternetAddressGroup *) ia;
+	gboolean encode = flags & INTERNET_ADDRESS_ENCODE;
+	gboolean fold = flags & INTERNET_ADDRESS_FOLD;
+	char *name;
+	size_t len;
 	
-	g_string_free (string, FALSE);
+	name = encoded_name (ia->name, encode);
+	len = strlen (name);
 	
-	return str;
+	if (fold && *linelen > 1 && (*linelen + len + 1) > GMIME_FOLD_LEN) {
+		linewrap (string);
+		*linelen = 1;
+	}
+	
+	g_string_append_len (string, name, len);
+	g_string_append_len (string, ": ", 2);
+	*linelen += len + 2;
+	g_free (name);
+	
+	_internet_address_list_to_string (group->members, flags, linelen, string);
+	g_string_append_c (string, ';');
+	*linelen += 1;
 }
 
 
@@ -928,7 +1149,7 @@
  * Returns: a string containing the list of addresses in rfc822 format.
  **/
 char *
-internet_address_list_to_string (const InternetAddressList *list, gboolean encode)
+internet_address_list_to_string (InternetAddressList *list, gboolean encode)
 {
 	guint32 flags = encode ? INTERNET_ADDRESS_ENCODE : 0;
 	size_t linelen = 0;
@@ -954,7 +1175,7 @@
  * @string, folding appropriately.
  **/
 void
-internet_address_list_writer (const InternetAddressList *list, GString *str)
+internet_address_list_writer (InternetAddressList *list, GString *str)
 {
 	guint32 flags = INTERNET_ADDRESS_ENCODE | INTERNET_ADDRESS_FOLD;
 	size_t linelen = str->len;
@@ -1121,7 +1342,7 @@
 			g_free (utf8);
 		}
 		
-		mailbox = internet_address_new_mailbox (name ? name->str : NULL, addr->str);
+		mailbox = internet_address_mailbox_new (name ? name->str : NULL, addr->str);
 	}
 	
 	g_string_free (addr, TRUE);
@@ -1134,6 +1355,7 @@
 static InternetAddress *
 decode_address (const char **in)
 {
+	InternetAddressGroup *group;
 	InternetAddress *addr = NULL;
 	const char *inptr, *start;
 	const char *word;
@@ -1154,7 +1376,8 @@
 	
 	decode_lwsp (&inptr);
 	if (*inptr == ':') {
-		addr = internet_address_new_group (name->str);
+		addr = internet_address_group_new (name->str);
+		group = (InternetAddressGroup *) addr;
 		inptr++;
 		
 		decode_lwsp (&inptr);
@@ -1162,8 +1385,8 @@
 			InternetAddress *member;
 			
 			if ((member = decode_mailbox (&inptr))) {
-				internet_address_add_member (addr, member);
-				internet_address_unref (member);
+				internet_address_group_add_member (group, member);
+				g_object_unref (member);
 			}
 			
 			decode_lwsp (&inptr);
@@ -1171,8 +1394,8 @@
 				inptr++;
 				decode_lwsp (&inptr);
 				if ((member = decode_mailbox (&inptr))) {
-					internet_address_add_member (addr, member);
-					internet_address_unref (member);
+					internet_address_group_add_member (group, member);
+					g_object_unref (member);
 				}
 				
 				decode_lwsp (&inptr);
@@ -1222,7 +1445,7 @@
 		
 		if ((addr = decode_address (&inptr))) {
 			internet_address_list_add (addrlist, addr);
-			internet_address_unref (addr);
+			g_object_unref (addr);
 		} else {
 			w(g_warning ("Invalid or incomplete address: %.*s",
 				     inptr - start, start));
@@ -1240,7 +1463,7 @@
 	}
 	
 	if (addrlist->array->len == 0) {
-		internet_address_list_unref (addrlist);
+		g_object_unref (addrlist);
 		addrlist = NULL;
 	}
 	

Modified: trunk/gmime/internet-address.h
==============================================================================
--- trunk/gmime/internet-address.h	(original)
+++ trunk/gmime/internet-address.h	Tue Aug 19 14:58:39 2008
@@ -23,88 +23,163 @@
 #define __INTERNET_ADDRESS_H__
 
 #include <glib.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
+#define INTERNET_ADDRESS_TYPE                  (internet_address_get_type ())
+#define INTERNET_ADDRESS(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), internet_address_get_type (), InternetAddress))
+#define INTERNET_ADDRESS_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), internet_address_get_type (), InternetAddressClass))
+#define IS_INTERNET_ADDRESS(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), internet_address_get_type ()))
+#define IS_INTERNET_ADDRESS_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), internet_address_get_type ()))
+#define INTERNET_ADDRESS_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), internet_address_get_type (), InternetAddressClass))
+
+#define INTERNET_ADDRESS_TYPE_GROUP            (internet_address_group_get_type ())
+#define INTERNET_ADDRESS_GROUP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), INTERNET_ADDRESS_TYPE_GROUP, InternetAddressGroup))
+#define INTERNET_ADDRESS_GROUP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), INTERNET_ADDRESS_TYPE_GROUP, InternetAddressGroupClass))
+#define INTERNET_ADDRESS_IS_GROUP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INTERNET_ADDRESS_TYPE_GROUP))
+#define INTERNET_ADDRESS_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INTERNET_ADDRESS_TYPE_GROUP))
+
+#define INTERNET_ADDRESS_TYPE_MAILBOX          (internet_address_mailbox_get_type ())
+#define INTERNET_ADDRESS_MAILBOX(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), INTERNET_ADDRESS_TYPE_MAILBOX, InternetAddressMailbox))
+#define INTERNET_ADDRESS_MAILBOX_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), INTERNET_ADDRESS_TYPE_MAILBOX, InternetAddressMailboxClass))
+#define INTERNET_ADDRESS_IS_MAILBOX(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INTERNET_ADDRESS_TYPE_MAILBOX))
+#define INTERNET_ADDRESS_IS_MAILBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INTERNET_ADDRESS_TYPE_MAILBOX))
+
+#define INTERNET_ADDRESS_LIST_TYPE             (internet_address_list_get_type ())
+#define INTERNET_ADDRESS_LIST(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), INTERNET_ADDRESS_LIST_TYPE, InternetAddressList))
+#define INTERNET_ADDRESS_LIST_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), INTERNET_ADDRESS_LIST_TYPE, InternetAddressListClass))
+#define IS_INTERNET_ADDRESS_LIST(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INTERNET_ADDRESS_LIST_TYPE))
+#define IS_INTERNET_ADDRESS_LIST_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), INTERNET_ADDRESS_LIST_TYPE))
 
 
+typedef struct _InternetAddress InternetAddress;
+typedef struct _InternetAddressClass InternetAddressClass;
 
-/**
- * InternetAddressType:
- * @INTERNET_ADDRESS_NONE: No type.
- * @INTERNET_ADDRESS_MAILBOX: A typical internet address type.
- * @INTERNET_ADDRESS_GROUP: An rfc2822 group type address.
- *
- * The type of #InternetAddress.
- **/
-typedef enum {
-	INTERNET_ADDRESS_NONE,
-	INTERNET_ADDRESS_MAILBOX,
-	INTERNET_ADDRESS_GROUP
-} InternetAddressType;
+typedef struct _InternetAddressGroup InternetAddressGroup;
+typedef struct _InternetAddressGroupClass InternetAddressGroupClass;
+
+typedef struct _InternetAddressMailbox InternetAddressMailbox;
+typedef struct _InternetAddressMailboxClass InternetAddressMailboxClass;
 
 typedef struct _InternetAddressList InternetAddressList;
-typedef struct _InternetAddress InternetAddress;
+typedef struct _InternetAddressListClass InternetAddressListClass;
 
 
 /**
  * InternetAddress:
- * @type: The type of internet address.
- * @refcount: The reference count.
- * @name: The name component of the internet address.
+ * @parent_object: parent #GObject
+ * @name: display name
  *
- * A structure representing an rfc2822 address.
+ * An RFC 2822 Address object.
  **/
 struct _InternetAddress {
-	InternetAddressType type;
-	unsigned int refcount;
+	GObject parent_object;
+	
 	char *name;
-	union {
-		char *addr;
-		InternetAddressList *members;
-	} value;
 };
 
+struct _InternetAddressClass {
+	GObjectClass parent_class;
+	
+	/* internal signals */
+	void (* changed) (InternetAddress *ia);
+	
+	/* public virtual methods */
+	void (* to_string) (InternetAddress *ia, guint32 flags, size_t *linelen, GString *out);
+};
 
-InternetAddress *internet_address_new (void);
-InternetAddress *internet_address_new_mailbox (const char *name, const char *addr);
-InternetAddress *internet_address_new_group (const char *name);
 
-void internet_address_ref (InternetAddress *ia);
-void internet_address_unref (InternetAddress *ia);
+GType internet_address_get_type (void);
 
 void internet_address_set_name (InternetAddress *ia, const char *name);
-void internet_address_set_addr (InternetAddress *ia, const char *addr);
-void internet_address_set_group (InternetAddress *ia, InternetAddressList *group);
-void internet_address_add_member (InternetAddress *ia, InternetAddress *member);
-
-InternetAddressType internet_address_get_type (const InternetAddress *ia);
-const char *internet_address_get_name (const InternetAddress *ia);
-const char *internet_address_get_addr (const InternetAddress *ia);
-InternetAddressList *internet_address_get_members (const InternetAddress *ia);
+const char *internet_address_get_name (InternetAddress *ia);
+
+char *internet_address_to_string (InternetAddress *ia, gboolean encode);
+
+
+/**
+ * InternetAddressMailbox:
+ * @parent_object: parent #InternetAddress
+ * @addr: address string
+ *
+ * An RFC 2822 Mailbox address.
+ **/
+struct _InternetAddressMailbox {
+	InternetAddress parent_object;
+	
+	char *addr;
+};
+
+struct _InternetAddressMailboxClass {
+	InternetAddressClass parent_class;
+	
+};
+
+
+GType internet_address_mailbox_get_type (void);
+
+InternetAddress *internet_address_mailbox_new (const char *name, const char *addr);
 
-char *internet_address_to_string (const InternetAddress *ia, gboolean encode);
+void internet_address_mailbox_set_addr (InternetAddressMailbox *mailbox, const char *addr);
+const char *internet_address_mailbox_get_addr (InternetAddressMailbox *mailbox);
+
+
+/**
+ * InternetAddressGroup:
+ * @parent_object: parent #InternetAddress
+ * @members: a #InternetAddressList of group members
+ *
+ * An RFC 2822 Group address.
+ **/
+struct _InternetAddressGroup {
+	InternetAddress parent_object;
+	
+	InternetAddressList *members;
+};
+
+struct _InternetAddressGroupClass {
+	InternetAddressClass parent_class;
+	
+};
+
+
+GType internet_address_group_get_type (void);
+
+InternetAddress *internet_address_group_new (const char *name);
+
+void internet_address_group_set_members (InternetAddressGroup *group, InternetAddressList *members);
+InternetAddressList *internet_address_group_get_members (InternetAddressGroup *group);
+
+void internet_address_group_add_member (InternetAddressGroup *group, InternetAddress *member);
 
 
 /**
  * InternetAddressList:
- * @refcount: The reference count.
+ * @parent_object: parent #GObject
  * @array: The array of #InternetAddress objects.
  *
  * A collection of #InternetAddress objects.
  **/
 struct _InternetAddressList {
-	unsigned int refcount;
+	GObject parent_object;
+	
 	GPtrArray *array;
 };
 
+struct _InternetAddressListClass {
+	GObjectClass parent_class;
+	
+	/* internal signals */
+	void (* changed) (InternetAddressList *list);
+};
 
-InternetAddressList *internet_address_list_new (void);
 
-void internet_address_list_ref (InternetAddressList *list);
-void internet_address_list_unref (InternetAddressList *list);
+GType internet_address_list_get_type (void);
 
-int internet_address_list_length (const InternetAddressList *list);
+InternetAddressList *internet_address_list_new (void);
+
+int internet_address_list_length (InternetAddressList *list);
 
 void internet_address_list_clear (InternetAddressList *list);
 
@@ -114,17 +189,17 @@
 gboolean internet_address_list_remove (InternetAddressList *list, InternetAddress *ia);
 gboolean internet_address_list_remove_at (InternetAddressList *list, int index);
 
-gboolean internet_address_list_contains (const InternetAddressList *list, const InternetAddress *ia);
-int internet_address_list_index_of (const InternetAddressList *list, const InternetAddress *ia);
+gboolean internet_address_list_contains (InternetAddressList *list, InternetAddress *ia);
+int internet_address_list_index_of (InternetAddressList *list, InternetAddress *ia);
 
-InternetAddress *internet_address_list_get_address (const InternetAddressList *list, int index);
+InternetAddress *internet_address_list_get_address (InternetAddressList *list, int index);
 void internet_address_list_set_address (InternetAddressList *list, int index, InternetAddress *ia);
 
-InternetAddressList *internet_address_list_parse_string (const char *str);
+char *internet_address_list_to_string (InternetAddressList *list, gboolean encode);
 
-char *internet_address_list_to_string (const InternetAddressList *list, gboolean encode);
+InternetAddressList *internet_address_list_parse_string (const char *str);
 
-void internet_address_list_writer (const InternetAddressList *list, GString *str);
+void internet_address_list_writer (InternetAddressList *list, GString *str);
 
 G_END_DECLS
 

Modified: trunk/tests/test-mime.c
==============================================================================
--- trunk/tests/test-mime.c	(original)
+++ trunk/tests/test-mime.c	Tue Aug 19 14:58:39 2008
@@ -193,7 +193,7 @@
 		
 		g_free (str);
 		if (addrlist)
-			internet_address_list_unref (addrlist);
+			g_object_unref (addrlist);
 	}
 }
 



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