X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;f=lib%2Fthread.cc;h=b8be3e1b5e889f5b873fe21fe50c6a0c6038db44;hb=5b8b0377cb68904eac8fc58a933d47f605a81725;hp=1cc22acd98cbb709b4426a4b95a63c9a5b5046c5;hpb=7c421b87b05d2513540a75bbe1841e226072ad7c;p=notmuch diff --git a/lib/thread.cc b/lib/thread.cc index 1cc22acd..b8be3e1b 100644 --- a/lib/thread.cc +++ b/lib/thread.cc @@ -32,6 +32,7 @@ struct _notmuch_thread { char *subject; GHashTable *authors_hash; char *authors; + char *nonmatched_authors; GHashTable *tags; notmuch_message_list_t *message_list; @@ -73,6 +74,124 @@ _thread_add_author (notmuch_thread_t *thread, thread->authors = talloc_strdup (thread, author); } +/* + * move authors of matched messages in the thread to + * the front of the authors list, but keep them in + * existing order within their group + */ +static void +_thread_move_matched_author (notmuch_thread_t *thread, + const char *author) +{ + char *authors_copy; + char *current_author; + char *last_pipe,*next_pipe; + int idx,nm_start,author_len,authors_len; + + if (thread->authors == NULL || author == NULL) + return; + if (thread->nonmatched_authors == NULL) + thread->nonmatched_authors = thread->authors; + author_len = strlen(author); + authors_len = strlen(thread->authors); + if (author_len == authors_len) { + /* just one author */ + thread->nonmatched_authors += author_len; + return; + } + current_author = strcasestr(thread->authors, author); + if (current_author == NULL) + return; + /* how far inside the nonmatched authors is our author? */ + idx = current_author - thread->nonmatched_authors; + if (idx < 0) { + /* already among matched authors */ + return; + } + /* are there any authors in the list after our author? */ + if (thread->nonmatched_authors + author_len < thread->authors + authors_len) { + /* we have to make changes, so let's get a temp copy */ + authors_copy = talloc_strdup(thread,thread->authors); + /* nm_start is the offset into where the non-matched authors start */ + nm_start = thread->nonmatched_authors - thread->authors; + /* copy this author and add the "| " - the if clause above tells us there's more */ + strncpy(thread->nonmatched_authors,author,author_len); + strncpy(thread->nonmatched_authors+author_len,"| ",2); + thread->nonmatched_authors += author_len+2; + if (idx > 0) { + /* we are actually moving authors around, not just changing the separator + * first copy the authors that came BEFORE our author */ + strncpy(thread->nonmatched_authors, authors_copy+nm_start, idx-2); + /* finally, if there are authors AFTER our author, copy those */ + if(author_len+nm_start+idx < authors_len) { + strncpy(thread->nonmatched_authors + idx - 2,", ",2); + strncpy(thread->nonmatched_authors + idx, authors_copy+nm_start + idx + author_len + 2, + authors_len - (nm_start + idx + author_len + 2)); + } + } + /* finally let's make sure there's just one '|' in the authors string */ + last_pipe = strchr(thread->authors,'|'); + while (last_pipe) { + next_pipe = strchr(last_pipe+1,'|'); + if (next_pipe) + *last_pipe = ','; + last_pipe = next_pipe; + } + } else { + thread->nonmatched_authors += author_len; + /* so now all authors are matched - let's remove the '|' */ + last_pipe = strchr(thread->authors,'|'); + if (last_pipe) + *last_pipe = ','; + } + return; +} + +/* clean up the uggly "Lastname, Firstname" format that some mail systems + * (most notably, Exchange) are creating to be "Firstname Lastname" + * To make sure that we don't change other potential situations where a + * comma is in the name, we check that we match one of these patterns + * "Last, First" + * "Last, First MI" + */ +char * +_thread_cleanup_author (notmuch_thread_t *thread, + const char *author, const char *from) +{ + char *clean_author,*test_author; + const char *comma; + char *blank; + int fname,lname; + + clean_author = talloc_strdup(thread, author); + if (clean_author == NULL) + return NULL; + comma = strchr(author,','); + if (comma) { + /* let's assemble what we think is the correct name */ + lname = comma - author; + fname = strlen(author) - lname - 2; + strncpy(clean_author, comma + 2, fname); + *(clean_author+fname) = ' '; + strncpy(clean_author + fname + 1, author, lname); + *(clean_author+fname+1+lname) = '\0'; + /* make a temporary copy and see if it matches the email */ + test_author = talloc_strdup(thread,clean_author); + + blank=strchr(test_author,' '); + while (blank != NULL) { + *blank = '.'; + blank=strchr(test_author,' '); + } + if (strcasestr(from, test_author) == NULL) + /* we didn't identify this as part of the email address + * so let's punt and return the original author */ + strcpy (clean_author, author); + + } + return clean_author; +} + /* Add 'message' as a message that belongs to 'thread'. * * The 'thread' will talloc_steal the 'message' and hold onto a @@ -84,9 +203,10 @@ _thread_add_message (notmuch_thread_t *thread, { notmuch_tags_t *tags; const char *tag; - InternetAddressList *list; + InternetAddressList *list = NULL; InternetAddress *address; const char *from, *author; + char *clean_author; _notmuch_message_list_add_message (thread->message_list, talloc_steal (thread, message)); @@ -97,7 +217,9 @@ _thread_add_message (notmuch_thread_t *thread, message); from = notmuch_message_get_header (message, "from"); - list = internet_address_list_parse_string (from); + if (from) + list = internet_address_list_parse_string (from); + if (list) { address = internet_address_list_get_address (list, 0); if (address) { @@ -107,7 +229,9 @@ _thread_add_message (notmuch_thread_t *thread, mailbox = INTERNET_ADDRESS_MAILBOX (address); author = internet_address_mailbox_get_addr (mailbox); } - _thread_add_author (thread, author); + clean_author = _thread_cleanup_author (thread, author, from); + _thread_add_author (thread, clean_author); + notmuch_message_set_author (message, clean_author); } g_object_unref (G_OBJECT (list)); } @@ -115,7 +239,7 @@ _thread_add_message (notmuch_thread_t *thread, if (! thread->subject) { const char *subject; subject = notmuch_message_get_header (message, "subject"); - thread->subject = talloc_strdup (thread, subject); + thread->subject = talloc_strdup (thread, subject ? subject : ""); } for (tags = notmuch_message_get_tags (message); @@ -135,6 +259,8 @@ _thread_set_subject_from_message (notmuch_thread_t *thread, const char *cleaned_subject; subject = notmuch_message_get_header (message, "subject"); + if (! subject) + return; if ((strncasecmp (subject, "Re: ", 4) == 0) || (strncasecmp (subject, "Aw: ", 4) == 0) || @@ -178,6 +304,7 @@ _thread_add_matched_message (notmuch_thread_t *thread, notmuch_message_set_flag (hashed_message, NOTMUCH_MESSAGE_FLAG_MATCH, 1); } + _thread_move_matched_author (thread,notmuch_message_get_author(hashed_message)); if ((sort == NOTMUCH_SORT_OLDEST_FIRST && date <= thread->newest) || (sort != NOTMUCH_SORT_OLDEST_FIRST && date == thread->newest)) @@ -305,6 +432,7 @@ _notmuch_thread_create (void *ctx, thread->authors_hash = g_hash_table_new_full (g_str_hash, g_str_equal, free, NULL); thread->authors = NULL; + thread->nonmatched_authors = NULL; thread->tags = g_hash_table_new_full (g_str_hash, g_str_equal, free, NULL);