Added the functions notmuch_messages_move_to_prevoius, notmuch_messages_move_to_last and notmuch_messages_move_to_first to notmuch library. With them is possible to iterate backwards on messages. * notmuch_messages_move_to_prevoius do the opposite than notmuch_messages_move_to_next, getting the messages iterator one position backwards. * notmuch_messages_move_to_last move the iterator to the first last message. * notmuch_messages_move_to_first move the iterator to the first valid message. --- lib/messages.c | 31 +++++++++++++++++++++++++++++ lib/notmuch-private.h | 10 +++++++++ lib/notmuch.h | 28 ++++++++++++++++++++++++++ lib/query.cc | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 0 deletions(-) diff --git a/lib/messages.c b/lib/messages.c index 2a85774..975e4b1 100644 --- a/lib/messages.c +++ b/lib/messages.c @@ -90,6 +90,7 @@ _notmuch_messages_create (notmuch_message_list_t *list) messages->is_of_list_type = TRUE; messages->iterator = list->head; + messages->list = list; return messages; } @@ -134,6 +135,15 @@ notmuch_messages_get (notmuch_messages_t *messages) } void +notmuch_messages_move_to_first (notmuch_messages_t *messages) +{ + if (! messages->is_of_list_type) + return _notmuch_mset_messages_move_to_first (messages); + + messages->iterator = messages->list->head; +} + +void notmuch_messages_move_to_next (notmuch_messages_t *messages) { if (! messages->is_of_list_type) @@ -146,6 +156,27 @@ notmuch_messages_move_to_next (notmuch_messages_t *messages) } void +notmuch_messages_move_to_last (notmuch_messages_t *messages) +{ + if (! messages->is_of_list_type) + return _notmuch_mset_messages_move_to_last (messages); + + messages->iterator = messages->list->tail; +} + +void +notmuch_messages_move_to_previous (notmuch_messages_t *messages) +{ + if (! messages->is_of_list_type) + return _notmuch_mset_messages_move_to_previous (messages); + + if (messages->iterator == NULL) + return; + + messages->iterator = messages->iterator->prev; +} + +void notmuch_messages_destroy (notmuch_messages_t *messages) { talloc_free (messages); diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 3b3f0eb..2269d2b 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -364,6 +364,7 @@ typedef struct _notmuch_message_list { struct _notmuch_messages { notmuch_bool_t is_of_list_type; notmuch_message_node_t *iterator; + notmuch_message_list_t *list; }; notmuch_message_list_t * @@ -389,8 +390,17 @@ notmuch_message_t * _notmuch_mset_messages_get (notmuch_messages_t *messages); void +_notmuch_mset_messages_move_to_first (notmuch_messages_t *messages); + +void _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages); +void +_notmuch_mset_messages_move_to_last (notmuch_messages_t *messages); + +void +_notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages); + /* message.cc */ void diff --git a/lib/notmuch.h b/lib/notmuch.h index 0d9cb0f..753f3bb 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -645,6 +645,15 @@ notmuch_messages_valid (notmuch_messages_t *messages); notmuch_message_t * notmuch_messages_get (notmuch_messages_t *messages); +/* Move the 'messages' iterator to the first message. + * + * After that the 'messages' iterator will be set to the first valid + * message, so it can be use to iterate with + * notmuch_messages_move_to_next. + */ +void +notmuch_messages_move_to_first (notmuch_messages_t *messages); + /* Move the 'messages' iterator to the next message. * * If 'messages' is already pointing at the last message then the @@ -658,6 +667,25 @@ notmuch_messages_get (notmuch_messages_t *messages); void notmuch_messages_move_to_next (notmuch_messages_t *messages); +/* Move the 'messages' iterator to the last message. + * + * After that the 'messages' iterator will be set to the last valid + * message, so it can be use to iterate with + * notmuch_messages_move_to_previous. + */ +void +notmuch_messages_move_to_last (notmuch_messages_t *messages); + +/* Move the 'messages' iterator to the previous message. + * + * If 'messages' is already pointing at the first message then the + * iterator will be moved to a point just beyond that first message, + * (where notmuch_messages_valid will return FALSE and + * notmuch_messages_get will return NULL). + */ +void +notmuch_messages_move_to_previous (notmuch_messages_t *messages); + /* Destroy a notmuch_messages_t object. * * It's not strictly necessary to call this function. All memory from diff --git a/lib/query.cc b/lib/query.cc index 9266d35..970c35a 100644 --- a/lib/query.cc +++ b/lib/query.cc @@ -35,6 +35,7 @@ typedef struct _notmuch_mset_messages { notmuch_messages_t base; notmuch_database_t *notmuch; Xapian::MSetIterator iterator; + Xapian::MSetIterator iterator_begin; Xapian::MSetIterator iterator_end; } notmuch_mset_messages_t; @@ -86,6 +87,7 @@ static int _notmuch_messages_destructor (notmuch_mset_messages_t *messages) { messages->iterator.~MSetIterator (); + messages->iterator_begin.~MSetIterator (); messages->iterator_end.~MSetIterator (); return 0; @@ -108,6 +110,7 @@ notmuch_query_search_messages (notmuch_query_t *query) messages->base.iterator = NULL; messages->notmuch = notmuch; new (&messages->iterator) Xapian::MSetIterator (); + new (&messages->iterator_begin) Xapian::MSetIterator (); new (&messages->iterator_end) Xapian::MSetIterator (); talloc_set_destructor (messages, _notmuch_messages_destructor); @@ -157,6 +160,7 @@ notmuch_query_search_messages (notmuch_query_t *query) mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ()); messages->iterator = mset.begin (); + messages->iterator_begin = mset.begin (); messages->iterator_end = mset.end (); } catch (const Xapian::Error &error) { @@ -208,6 +212,16 @@ _notmuch_mset_messages_get (notmuch_messages_t *messages) } void +_notmuch_mset_messages_move_to_first (notmuch_messages_t *messages) +{ + notmuch_mset_messages_t *mset_messages; + + mset_messages = (notmuch_mset_messages_t *) messages; + + mset_messages->iterator = mset_messages->iterator_begin; +} + +void _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages) { notmuch_mset_messages_t *mset_messages; @@ -217,6 +231,44 @@ _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages) mset_messages->iterator++; } +void +_notmuch_mset_messages_move_to_last (notmuch_messages_t *messages) +{ + notmuch_mset_messages_t *mset_messages; + + mset_messages = (notmuch_mset_messages_t *) messages; + + mset_messages->iterator = mset_messages->iterator_end; + mset_messages->iterator--; +} + +void +_notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages) +{ + notmuch_mset_messages_t *mset_messages; + + mset_messages = (notmuch_mset_messages_t *) messages; + + if (mset_messages->iterator == mset_messages->iterator_begin) + { + /* + * Xapian iterators can not be beyond the first element, so we + * assign the iterator_end to mark the iterator as invalid in case + * of move_to_previous with the iterator at the beginning + */ + mset_messages->iterator = mset_messages->iterator_end; + } + else if (_notmuch_mset_messages_valid (messages)) + { + /* + * If is valid move the iterator. To emulate the same behavior + * than notmuch_messages_t the iterator won't be updated if is + * not valid + */ + mset_messages->iterator--; + } +} + /* Glib objects force use to use a talloc destructor as well, (but not * nearly as ugly as the for messages due to C++ objects). At * this point, I'd really like to have some talloc-friendly -- 1.7.0