diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c index 6ade3e31..5ef0cc8d 100644 --- a/gmime/gmime-header.c +++ b/gmime/gmime-header.c @@ -1151,6 +1151,7 @@ g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const ch g_hash_table_replace (headers->hash, header->name, header); if (headers->array->len > 0) { + args.action = GMIME_HEADER_LIST_CHANGED_ACTION_INSERTED; g_ptr_array_set_size (headers->array, headers->array->len + 1); dest = ((unsigned char *) headers->array->pdata) + sizeof (void *); @@ -1160,10 +1161,10 @@ g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const ch memmove (dest, src, (sizeof (void *) * n)); headers->array->pdata[0] = header; } else { + args.action = GMIME_HEADER_LIST_CHANGED_ACTION_ADDED; g_ptr_array_add (headers->array, header); } - args.action = GMIME_HEADER_LIST_CHANGED_ACTION_ADDED; args.header = header; g_mime_event_emit (headers->changed, &args); @@ -1388,6 +1389,9 @@ g_mime_header_list_remove (GMimeHeaderList *headers, const char *name) g_mime_event_remove (header->changed, (GMimeEventCallback) header_changed, headers); g_ptr_array_remove_index (headers->array, i); g_hash_table_remove (headers->hash, name); + + args.action = GMIME_HEADER_LIST_CHANGED_ACTION_REMOVED; + args.header = header; /* look for another header with the same name... */ while (i < headers->array->len) { @@ -1402,9 +1406,6 @@ g_mime_header_list_remove (GMimeHeaderList *headers, const char *name) i++; } - args.action = GMIME_HEADER_LIST_CHANGED_ACTION_REMOVED; - args.header = header; - g_mime_event_emit (headers->changed, &args); g_object_unref (header); diff --git a/gmime/gmime-internal.h b/gmime/gmime-internal.h index 07701894..5dba77b4 100644 --- a/gmime/gmime-internal.h +++ b/gmime/gmime-internal.h @@ -32,6 +32,7 @@ G_BEGIN_DECLS typedef enum { GMIME_HEADER_LIST_CHANGED_ACTION_ADDED, + GMIME_HEADER_LIST_CHANGED_ACTION_INSERTED, GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED, GMIME_HEADER_LIST_CHANGED_ACTION_REMOVED, GMIME_HEADER_LIST_CHANGED_ACTION_CLEARED diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c index 259e6190..1456a85b 100644 --- a/gmime/gmime-message.c +++ b/gmime/gmime-message.c @@ -259,6 +259,24 @@ static const char *message_headers[] = { "MIME-Version" }; +static void +message_add_addresses (GMimeMessage *message, GMimeParserOptions *options, GMimeHeader *header, GMimeAddressType type) +{ + InternetAddressList *addrlist; + const char *value; + + block_changed_event (message, type); + + addrlist = message->addrlists[type]; + + internet_address_list_clear (addrlist); + + if ((value = g_mime_header_get_raw_value (header))) + _internet_address_list_append_parse (addrlist, options, value, header->offset); + + unblock_changed_event (message, type); +} + static void message_update_addresses (GMimeMessage *message, GMimeParserOptions *options, GMimeAddressType type) { @@ -289,8 +307,21 @@ message_update_addresses (GMimeMessage *message, GMimeParserOptions *options, GM unblock_changed_event (message, type); } +static gboolean +header_was_appended (GMimeObject *object, GMimeHeaderListChangedAction action, GMimeHeader *header) +{ + // Note: This is a hack until we can have a message_header_inserted() API. + if (action == GMIME_HEADER_LIST_CHANGED_ACTION_ADDED) { + int count = g_mime_header_list_get_count (object->headers); + GMimeHeader *last = g_mime_header_list_get_header_at (object->headers, count - 1); + return header == last; + } + + return FALSE; +} + static void -process_header (GMimeObject *object, GMimeHeader *header) +process_header (GMimeObject *object, GMimeHeaderListChangedAction action, GMimeHeader *header) { GMimeParserOptions *options = _g_mime_header_list_get_options (object->headers); GMimeMessage *message = (GMimeMessage *) object; @@ -306,22 +337,40 @@ process_header (GMimeObject *object, GMimeHeader *header) switch (i) { case HEADER_SENDER: - message_update_addresses (message, options, GMIME_ADDRESS_TYPE_SENDER); + if (header_was_appended (object, action, header)) + message_add_addresses (message, options, header, GMIME_ADDRESS_TYPE_SENDER); + else + message_update_addresses (message, options, GMIME_ADDRESS_TYPE_SENDER); break; case HEADER_FROM: - message_update_addresses (message, options, GMIME_ADDRESS_TYPE_FROM); + if (header_was_appended (object, action, header)) + message_add_addresses (message, options, header, GMIME_ADDRESS_TYPE_FROM); + else + message_update_addresses (message, options, GMIME_ADDRESS_TYPE_FROM); break; case HEADER_REPLY_TO: - message_update_addresses (message, options, GMIME_ADDRESS_TYPE_REPLY_TO); + if (header_was_appended (object, action, header)) + message_add_addresses (message, options, header, GMIME_ADDRESS_TYPE_REPLY_TO); + else + message_update_addresses (message, options, GMIME_ADDRESS_TYPE_REPLY_TO); break; case HEADER_TO: - message_update_addresses (message, options, GMIME_ADDRESS_TYPE_TO); + if (header_was_appended (object, action, header)) + message_add_addresses (message, options, header, GMIME_ADDRESS_TYPE_TO); + else + message_update_addresses (message, options, GMIME_ADDRESS_TYPE_TO); break; case HEADER_CC: - message_update_addresses (message, options, GMIME_ADDRESS_TYPE_CC); + if (header_was_appended (object, action, header)) + message_add_addresses (message, options, header, GMIME_ADDRESS_TYPE_CC); + else + message_update_addresses (message, options, GMIME_ADDRESS_TYPE_CC); break; case HEADER_BCC: - message_update_addresses (message, options, GMIME_ADDRESS_TYPE_BCC); + if (header_was_appended (object, action, header)) + message_add_addresses (message, options, header, GMIME_ADDRESS_TYPE_BCC); + else + message_update_addresses (message, options, GMIME_ADDRESS_TYPE_BCC); break; case HEADER_SUBJECT: g_free (message->subject); @@ -353,7 +402,7 @@ process_header (GMimeObject *object, GMimeHeader *header) static void message_header_added (GMimeObject *object, GMimeHeader *header) { - process_header (object, header); + process_header (object, GMIME_HEADER_LIST_CHANGED_ACTION_ADDED, header); GMIME_OBJECT_CLASS (parent_class)->header_added (object, header); } @@ -361,7 +410,7 @@ message_header_added (GMimeObject *object, GMimeHeader *header) static void message_header_changed (GMimeObject *object, GMimeHeader *header) { - process_header (object, header); + process_header (object, GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED, header); GMIME_OBJECT_CLASS (parent_class)->header_changed (object, header); } diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c index 5860baff..f9da047d 100644 --- a/gmime/gmime-object.c +++ b/gmime/gmime-object.c @@ -291,8 +291,10 @@ object_headers_cleared (GMimeObject *object) static void header_list_changed (GMimeHeaderList *headers, GMimeHeaderListChangedEventArgs *args, GMimeObject *object) { + // FIXME: add a header_inserted() API so that header_added() can be better optimized. See gmime-message.c:message_header_added()/process_header(). switch (args->action) { case GMIME_HEADER_LIST_CHANGED_ACTION_ADDED: + case GMIME_HEADER_LIST_CHANGED_ACTION_INSERTED: GMIME_OBJECT_GET_CLASS (object)->header_added (object, args->header); break; case GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED: