[PATCH 2/5] Reorder displayed names of thread authors

2010-04-24 Thread Dirk Hohndel
When displaying threads as result of a search it makes sense to list those
authors first who match the search. The matching authors are separated from the
non-matching ones with a '|' instead of a ','

Imagine the default "+inbox" query. Those mails in the thread that
match the query are actually "new" (whatever that means). And some
people seem to think that it would be much better to see those author
names first. For example, imagine a long and drawn out thread that once
was started by me; you have long read the older part of the thread and
removed the inbox tag. Whenever a new email comes in on this thread,
prior to this patch the author column in the search display will first show
"Dirk Hohndel" - I think it should first show the actual author(s) of the new
mail(s).

Signed-off-by: Dirk Hohndel 
---
 lib/thread.cc |   77 +
 1 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/lib/thread.cc b/lib/thread.cc
index e1da060..c80bb26 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,79 @@ _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;
+}
+
 /* Add 'message' as a message that belongs to 'thread'.
  *
  * The 'thread' will talloc_steal the 'message' and hold onto a
@@ -110,6 +184,7 @@ _thread_add_message (notmuch_thread_t *thread,
author = internet_address_mailbox_get_addr (mailbox);
}
_thread_add_author (thread, author);
+   notmuch_message_set_author (message, author);
}
g_object_unref (G_OBJECT (list));
 }
@@ -182,6 +257,7 @@ _thread_add_matched_message (notmuch_thread_t *thread,
notmuch_message_set_flag (hashed_message,

[PATCH 2/5] Reorder displayed names of thread authors

2010-04-24 Thread Dirk Hohndel
When displaying threads as result of a search it makes sense to list those
authors first who match the search. The matching authors are separated from the
non-matching ones with a '|' instead of a ','

Imagine the default +inbox query. Those mails in the thread that
match the query are actually new (whatever that means). And some
people seem to think that it would be much better to see those author
names first. For example, imagine a long and drawn out thread that once
was started by me; you have long read the older part of the thread and
removed the inbox tag. Whenever a new email comes in on this thread,
prior to this patch the author column in the search display will first show
Dirk Hohndel - I think it should first show the actual author(s) of the new
mail(s).

Signed-off-by: Dirk Hohndel hohn...@infradead.org
---
 lib/thread.cc |   77 +
 1 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/lib/thread.cc b/lib/thread.cc
index e1da060..c80bb26 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,79 @@ _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;
+}
+
 /* Add 'message' as a message that belongs to 'thread'.
  *
  * The 'thread' will talloc_steal the 'message' and hold onto a
@@ -110,6 +184,7 @@ _thread_add_message (notmuch_thread_t *thread,
author = internet_address_mailbox_get_addr (mailbox);
}
_thread_add_author (thread, author);
+   notmuch_message_set_author (message, author);
}
g_object_unref (G_OBJECT (list));
 }
@@ -182,6 +257,7 @@ _thread_add_matched_message (notmuch_thread_t *thread,
notmuch_message_set_flag (hashed_message,