return hash;
}
+static int
+_notmuch_message_file_destructor (notmuch_message_file_t *message)
+{
+ if (message->line)
+ free (message->line);
+
+ if (message->value.size)
+ free (message->value.str);
+
+ if (message->headers)
+ g_hash_table_destroy (message->headers);
+
+ if (message->file)
+ fclose (message->file);
+
+ return 0;
+}
+
+/* Create a new notmuch_message_file_t for 'filename' with 'ctx' as
+ * the talloc owner. */
notmuch_message_file_t *
-notmuch_message_file_open (const char *filename)
+_notmuch_message_file_open_ctx (void *ctx, const char *filename)
{
notmuch_message_file_t *message;
- message = talloc_zero (NULL, notmuch_message_file_t);
+ message = talloc_zero (ctx, notmuch_message_file_t);
+ if (unlikely (message == NULL))
+ return NULL;
+
+ talloc_set_destructor (message, _notmuch_message_file_destructor);
message->file = fopen (filename, "r");
if (message->file == NULL)
return NULL;
}
+notmuch_message_file_t *
+notmuch_message_file_open (const char *filename)
+{
+ return _notmuch_message_file_open_ctx (NULL, filename);
+}
+
void
notmuch_message_file_close (notmuch_message_file_t *message)
{
- if (message == NULL)
- return;
-
- if (message->line)
- free (message->line);
-
- if (message->value.size)
- free (message->value.str);
-
- if (message->headers)
- g_hash_table_destroy (message->headers);
-
- if (message->file)
- fclose (message->file);
-
talloc_free (message);
}
char *message_id;
char *thread_id;
char *filename;
+ notmuch_message_file_t *message_file;
Xapian::Document doc;
};
message->notmuch = notmuch;
message->doc_id = doc_id;
- message->message_id = NULL; /* lazily created */
- message->thread_id = NULL; /* lazily created */
- message->filename = NULL; /* lazily created */
+
+ /* Each of these will be lazily created as needed. */
+ message->message_id = NULL;
+ message->thread_id = NULL;
+ message->filename = NULL;
+ message->message_file = NULL;
/* This is C++'s creepy "placement new", which is really just an
* ugly way to call a constructor for a pre-allocated object. So
return message->message_id;
}
+const char *
+_notmuch_message_get_subject (notmuch_message_t *message)
+{
+ if (! message->message_file) {
+ notmuch_message_file_t *message_file;
+ const char *filename;
+
+ filename = notmuch_message_get_filename (message);
+ if (unlikely (filename == NULL))
+ return NULL;
+
+ message_file = _notmuch_message_file_open_ctx (message, filename);
+ if (unlikely (message_file == NULL))
+ return NULL;
+
+ message->message_file = message_file;
+ }
+
+ return notmuch_message_file_get_header (message->message_file,
+ "subject");
+}
+
const char *
notmuch_message_get_thread_id (notmuch_message_t *message)
{
: \
(notmuch_status_t) private_status)
+/* database.cc */
+
+/* Lookup a prefix value by name.
+ *
+ * XXX: This should really be static inside of message.cc, and we can
+ * do that once we convert database.cc to use the
+ * _notmuch_message_add/remove_term functions. */
+const char *
+_find_prefix (const char *name);
+
/* thread.cc */
notmuch_thread_t *
void
_notmuch_thread_add_tag (notmuch_thread_t *thread, const char *tag);
+void
+_notmuch_thread_set_subject (notmuch_thread_t *thread, const char *subject);
+
+const char *
+_notmuch_thread_get_subject (notmuch_thread_t *thread);
+
/* message.cc */
notmuch_message_t *
const char *message_id,
notmuch_status_t *status);
-/* Lookup a prefix value by name.
- *
- * XXX: This should really be static inside of message.cc, and we can
- * do that once we convert database.cc to use the
- * _notmuch_message_add/remove_term functions. */
const char *
-_find_prefix (const char *name);
+_notmuch_message_get_subject (notmuch_message_t *message);
notmuch_private_status_t
_notmuch_message_add_term (notmuch_message_t *message,
notmuch_message_file_t *
notmuch_message_file_open (const char *filename);
+/* Like notmuch_message_file_open but with 'ctx' as the talloc owner. */
+notmuch_message_file_t *
+_notmuch_message_file_open_ctx (void *ctx, const char *filename);
+
/* Close a notmuch message preivously opened with notmuch_message_open. */
void
notmuch_message_file_close (notmuch_message_file_t *message);
thread = notmuch_thread_results_get (results);
- printf ("%s (", notmuch_thread_get_thread_id (thread));
+ printf ("%s %s",
+ notmuch_thread_get_thread_id (thread),
+ _notmuch_thread_get_subject (thread));
+ printf (" (");
for (tags = notmuch_thread_get_tags (thread);
notmuch_tags_has_more (tags);
notmuch_tags_advance (tags))
printf ("%s", notmuch_tags_get (tags));
first = 0;
}
-
printf (")\n");
notmuch_thread_destroy (thread);
const char *
notmuch_thread_get_thread_id (notmuch_thread_t *thread);
+/* Get the subject of 'thread'
+ *
+ * The subject is taken from the first message (according to the query
+ * order---see notmuch_query_set_sort) in the query results that
+ * belongs to this thread.
+ *
+ * The returned string belongs to 'thread' and as such, should not be
+ * modified by the caller and will only be valid for as long as the
+ * thread is valid, (which is until notmuch_thread_destroy or until
+ * the query from which it derived is destroyed).
+ */
+const char *
+notmuch_thread_get_subject (notmuch_thread_t *thread);
+
/* Get the tags for 'thread', returning a notmuch_tags_t object which
* can be used to iterate over all tags.
*
thread_id, NULL,
(void **) &thread))
{
+ const char *subject;
+
thread = _notmuch_thread_create (query, query->notmuch,
thread_id);
+ subject = _notmuch_message_get_subject (message);
+
+ _notmuch_thread_set_subject (thread, subject);
+
g_hash_table_insert (seen, xstrdup (thread_id), thread);
g_ptr_array_add (thread_results->threads, thread);
tag = notmuch_tags_get (tags);
_notmuch_thread_add_tag (thread, tag);
}
+
+ notmuch_message_destroy (message);
}
g_hash_table_unref (seen);
struct _notmuch_thread {
notmuch_database_t *notmuch;
char *thread_id;
+ char *subject;
GHashTable *tags;
};
thread->notmuch = notmuch;
thread->thread_id = talloc_strdup (thread, thread_id);
+ thread->subject = NULL;
thread->tags = g_hash_table_new_full (g_str_hash, g_str_equal,
free, NULL);
g_hash_table_insert (thread->tags, xstrdup (tag), NULL);
}
+void
+_notmuch_thread_set_subject (notmuch_thread_t *thread, const char *subject)
+{
+ thread->subject = talloc_strdup (thread, subject);
+}
+
+const char *
+_notmuch_thread_get_subject (notmuch_thread_t *thread)
+{
+ return thread->subject;
+}
+
notmuch_tags_t *
notmuch_thread_get_tags (notmuch_thread_t *thread)
{