diff options
Diffstat (limited to 'mail')
-rw-r--r-- | mail/ChangeLog | 7 | ||||
-rw-r--r-- | mail/message-list.c | 165 |
2 files changed, 169 insertions, 3 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 93ef4c675d..09264e2616 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,10 @@ +2000-09-22 Jeffrey Stedfast <fejj@helixcode.com> + + * message-list.c (address_compare): New comparison function for + email addresses. + (subject_compare): New comparison function for message subjects. + (message_list_init_header): Updated to use the new compare funcs. + 2000-09-21 Jeffrey Stedfast <fejj@helixcode.com> * mail-format.c (mail_generate_reply): Fixed some memory diff --git a/mail/message-list.c b/mail/message-list.c index d33e11bc8f..32ad726cef 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -16,6 +16,9 @@ #include <camel/camel-exception.h> #include <camel/camel-folder.h> +#include <string.h> +#include <ctype.h> + #include "message-list.h" #include "message-thread.h" #include "mail-threads.h" @@ -105,6 +108,162 @@ static struct { { NULL, NULL } }; +typedef struct { + char *name; + char *address; +} InternetAddress; + + +static InternetAddress * +internet_address_new_from_string (const gchar *string) +{ + /* We have 3 possibilities... + 1. "Jeffrey Stedfast" <fejj@helixcode.com> + 2. fejj@helixcode.com + 3. <fejj@helixcode.com> (Jeffrey Stedfast) + */ + InternetAddress *ia; + gchar *name = NULL, *address = NULL; + gchar *ptr, *padding = NULL; + gboolean in_quotes = FALSE; + gboolean name_first = FALSE; + + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (*string != '\0', NULL); + + /* look for padding between parts... */ + for (ptr = (gchar *) string; *ptr; ptr++) { + if (*ptr == '"') { + in_quotes = !in_quotes; + name_first = TRUE; + } else if (!in_quotes && isspace (*ptr)) { + padding = ptr; + break; + } + } + + if (padding) { + padding--; + /* we have a type-one or a type-three address */ + if (name_first) { + name = g_strndup (string, (gint) (padding - string)); + g_strstrip (name); + + /* strip off the quotes */ + if (*name) { + *(name + strlen (name) - 1) = '\0'; + memmove (name, name + 1, strlen (name) - 1); + } else { + g_free (name); + name = NULL; + } + + address = strchr (padding, '<'); + if (address) { + address++; + for (ptr = address; *ptr && *ptr != '>'; ptr++); + + address = g_strndup (address, (gint) (ptr - address)); + } + } else { + address = g_strndup (string, (gint) (padding - string)); + g_strstrip (address); + + /* strip off the braces */ + if (*address) { + *(address + strlen (address) - 1) = '\0'; + memmove (address, address + 1, strlen (address) - 1); + } else { + g_free (address); + address = NULL; + } + + name = strchr (padding, '('); + if (name) { + name++; + in_quotes = FALSE; + ptr = name; + + while (*ptr) { + if (*ptr == '"') + in_quotes = !in_quotes; + else if (!in_quotes && *ptr == ')') + break; + } + + name = g_strndup (name, (gint) (ptr - name)); + } + } + } else { + /* we have a type-two address */ + address = g_strdup (string); + } + + if (!address) { + /* the address is the most important part! */ + g_free (name); + return NULL; + } + + ia = g_new (InternetAddress, 1); + ia->name = name; + ia->address = address; + + return ia; +} + +static void +internet_address_destroy (InternetAddress *ia) +{ + g_return_if_fail (ia != NULL); + + g_free (ia->name); + g_free (ia->address); + g_free (ia); +} + +static gint +address_compare (gconstpointer address1, gconstpointer address2) +{ + InternetAddress *ia1, *ia2; + gint retval; + + ia1 = internet_address_new_from_string ((const char *) address1); + ia2 = internet_address_new_from_string ((const char *) address2); + + if (!ia1->name || !ia2->name) { + /* if one or the other doesn't have a name we should compare addresses */ + retval = g_strcasecmp (ia1->address, ia2->address); + } else { + /* FIXME: compare last names...then first names if last names are the same? */ + retval = g_strcasecmp (ia1->name, ia2->name); + } + + internet_address_destroy (ia1); + internet_address_destroy (ia2); + + return retval; +} + +static gint +subject_compare (gconstpointer subject1, gconstpointer subject2) +{ + char *sub1; + char *sub2; + + /* trim off any "Re:"'s at the beginning of subject1 */ + sub1 = (char *) subject1; + while (!g_strncasecmp (sub1, "Re:", 3)) + sub1 += 3; + + /* trim off any "Re:"'s at the beginning of subject2 */ + sub2 = (char *) subject2; + while (!g_strncasecmp (sub2, "Re:", 3)) + sub2 += 3; + + return g_strcasecmp (sub1, sub2); +} + /* Gets the CamelMessageInfo for the message displayed at the given * view row. */ @@ -722,14 +881,14 @@ message_list_init_header (MessageList *message_list) COL_FROM, _("From"), COL_FROM_EXPANSION, COL_FROM_WIDTH_MIN, message_list->render_text, - g_str_compare, TRUE); + address_compare, TRUE); message_list->table_cols [COL_SUBJECT] = e_table_col_new ( COL_SUBJECT, _("Subject"), COL_SUBJECT_EXPANSION, COL_SUBJECT_WIDTH_MIN, message_list->render_tree, - g_str_compare, TRUE); + subject_compare, TRUE); message_list->table_cols [COL_SENT] = e_table_col_new ( @@ -750,7 +909,7 @@ message_list_init_header (MessageList *message_list) COL_TO, _("To"), COL_TO_EXPANSION, COL_TO_WIDTH_MIN, message_list->render_text, - g_str_compare, TRUE); + address_compare, TRUE); message_list->table_cols [COL_SIZE] = e_table_col_new ( |