Re: [PATCH] Fix typo in Message.maildir_flags_to_tags
[notmuch-archives.git] / a1 / 530409d7ccf7cee13973f877e3acf5be66e980
1 Return-Path: <meskio@sindominio.net>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 35759431FC1\r
6         for <notmuch@notmuchmail.org>; Sun, 21 Mar 2010 14:30:21 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -1.9\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5\r
12         tests=[BAYES_00=-1.9] autolearn=ham\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id ltOgh+LzfcdW for <notmuch@notmuchmail.org>;\r
16         Sun, 21 Mar 2010 14:30:19 -0700 (PDT)\r
17 Received: from flatline.sindominio.net (flatline.sindominio.net [82.144.4.26])\r
18         by olra.theworths.org (Postfix) with ESMTP id D11A44196F0\r
19         for <notmuch@notmuchmail.org>; Sun, 21 Mar 2010 14:30:16 -0700 (PDT)\r
20 Received: from localhost (localhost.localdomain [127.0.0.1])\r
21         by flatline.sindominio.net (Postfix) with ESMTP id E98DC348046;\r
22         Sun, 21 Mar 2010 22:30:15 +0100 (CET)\r
23 X-Virus-Scanned: Debian amavisd-new at sindominio.net\r
24 Received: from flatline.sindominio.net ([127.0.0.1])\r
25         by localhost (flatline.sindominio.net [127.0.0.1]) (amavisd-new,\r
26         port 10024)\r
27         with ESMTP id CoFItUAt1ChR; Sun, 21 Mar 2010 22:30:13 +0100 (CET)\r
28 Received: from blackspot (heal.cauterized.net [89.140.131.167])\r
29         by flatline.sindominio.net (Postfix) with ESMTPA id BBABF348095;\r
30         Sun, 21 Mar 2010 22:29:28 +0100 (CET)\r
31 Received: by blackspot (Postfix, from userid 1000)\r
32         id 78F448BDFD; Sun, 21 Mar 2010 22:32:42 +0100 (CET)\r
33 From: Ruben Pollan <meskio@sindominio.net>\r
34 To: notmuch@notmuchmail.org\r
35 Date: Sun, 21 Mar 2010 22:32:33 +0100\r
36 Message-Id: <1269207153-3687-3-git-send-email-meskio@sindominio.net>\r
37 X-Mailer: git-send-email 1.7.0\r
38 In-Reply-To: <1269080605-5617-1-git-send-email-meskio@sindominio.net>\r
39 References: <1269080605-5617-1-git-send-email-meskio@sindominio.net>\r
40 Subject: [notmuch] [PATCH 2/2] Added backwards iterator to threads\r
41 X-BeenThere: notmuch@notmuchmail.org\r
42 X-Mailman-Version: 2.1.13\r
43 Precedence: list\r
44 List-Id: "Use and development of the notmuch mail system."\r
45         <notmuch.notmuchmail.org>\r
46 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
47         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
48 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
49 List-Post: <mailto:notmuch@notmuchmail.org>\r
50 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
51 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
52         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
53 X-List-Received-Date: Sun, 21 Mar 2010 21:30:21 -0000\r
54 \r
55 Added the functions notmuch_threads_move_to_prevoius,\r
56 notmuch_threads_move_to_last and  notmuch_threads_move_to_first to\r
57 notmuch library. With them is possible to iterate backwards on threads.\r
58 \r
59 * notmuch_threads_move_to_prevoius do the opposite than\r
60   notmuch_threads_move_to_next, getting the threads iterator one\r
61   position backwards.\r
62 \r
63 * notmuch_threads_move_to_last move the iterator to the first last\r
64 thread.\r
65 \r
66 * notmuch_threads_move_to_first move the iterator to the first valid\r
67   thread.\r
68 \r
69 For it has been implemented notmuch_thread_list_t structur that stores\r
70 the thread_ids so the backwards iteration gets the thread_id in the same\r
71 order that was show on forward iteration.\r
72 ---\r
73  lib/notmuch.h |   28 ++++++++\r
74  lib/query.cc  |  209 ++++++++++++++++++++++++++++++++++++++++++++++++++++----\r
75  2 files changed, 222 insertions(+), 15 deletions(-)\r
76 \r
77 diff --git a/lib/notmuch.h b/lib/notmuch.h\r
78 index 0d9cb0f..62f4ad4 100644\r
79 --- a/lib/notmuch.h\r
80 +++ b/lib/notmuch.h\r
81 @@ -466,6 +466,15 @@ notmuch_threads_valid (notmuch_threads_t *threads);\r
82  notmuch_thread_t *\r
83  notmuch_threads_get (notmuch_threads_t *threads);\r
84  \r
85 +/* Move the 'threads' iterator to the first thread.          \r
86 + *\r
87 + * After that the 'threads' iterator will be set to the first valid\r
88 + * thread, so it can be use to iterate with\r
89 + * notmuch_threads_move_to_next.\r
90 + */\r
91 +void\r
92 +notmuch_threads_move_to_first (notmuch_threads_t *threads);\r
93 +\r
94  /* Move the 'threads' iterator to the next thread.\r
95   *\r
96   * If 'threads' is already pointing at the last thread then the\r
97 @@ -479,6 +488,25 @@ notmuch_threads_get (notmuch_threads_t *threads);\r
98  void\r
99  notmuch_threads_move_to_next (notmuch_threads_t *threads);\r
100  \r
101 +/* Move the 'threads' iterator to the last thread.\r
102 + *\r
103 + * After that the 'threads' iterator will be set to the last valid\r
104 + * thread, so it can be use to iterate with\r
105 + * notmuch_threads_move_to_previous.\r
106 + */\r
107 +void\r
108 +notmuch_threads_move_to_last (notmuch_threads_t *threads);\r
109 +\r
110 +/* Move the 'threads' iterator to the previous thread.\r
111 + *\r
112 + * If 'threads' is already pointing at the first thread then the\r
113 + * iterator will be moved to a point just beyond that first thread,\r
114 + * (where notmuch_threads_valid will return FALSE and\r
115 + * notmuch_threads_get will return NULL).\r
116 + */\r
117 +void\r
118 +notmuch_threads_move_to_previous (notmuch_threads_t *threads);\r
119 +\r
120  /* Destroy a notmuch_threads_t object.\r
121   *\r
122   * It's not strictly necessary to call this function. All memory from\r
123 diff --git a/lib/query.cc b/lib/query.cc\r
124 index 514a156..727f449 100644\r
125 --- a/lib/query.cc\r
126 +++ b/lib/query.cc\r
127 @@ -35,16 +35,29 @@ typedef struct _notmuch_mset_messages {\r
128      notmuch_messages_t base;\r
129      notmuch_database_t *notmuch;\r
130      Xapian::MSetIterator iterator;\r
131 +    Xapian::MSetIterator iterator_begin;\r
132      Xapian::MSetIterator iterator_end;\r
133  } notmuch_mset_messages_t;\r
134  \r
135 +typedef struct _notmuch_thread_node {\r
136 +    const char *thread_id;\r
137 +    struct _notmuch_thread_node *next;\r
138 +    struct _notmuch_thread_node *prev;\r
139 +} notmuch_thread_node_t;\r
140 +\r
141 +typedef struct _notmuch_thread_list {\r
142 +    notmuch_thread_node_t *head;\r
143 +    notmuch_thread_node_t *tail;\r
144 +    notmuch_thread_node_t *iterator;\r
145 +} notmuch_thread_list_t;\r
146 +\r
147  struct _notmuch_threads {\r
148      notmuch_query_t *query;\r
149      GHashTable *threads;\r
150      notmuch_messages_t *messages;\r
151  \r
152 -    /* This thread ID is our iterator state. */\r
153 -    const char *thread_id;\r
154 +    /* thread list with the thread_id of the showed messages */\r
155 +    notmuch_thread_list_t *list;\r
156  };\r
157  \r
158  notmuch_query_t *\r
159 @@ -86,6 +99,7 @@ static int\r
160  _notmuch_messages_destructor (notmuch_mset_messages_t *messages)\r
161  {\r
162      messages->iterator.~MSetIterator ();\r
163 +    messages->iterator_begin.~MSetIterator ();\r
164      messages->iterator_end.~MSetIterator ();\r
165  \r
166      return 0;\r
167 @@ -108,6 +122,7 @@ notmuch_query_search_messages (notmuch_query_t *query)\r
168         messages->base.iterator = NULL;\r
169         messages->notmuch = notmuch;\r
170         new (&messages->iterator) Xapian::MSetIterator ();\r
171 +       new (&messages->iterator_begin) Xapian::MSetIterator ();\r
172         new (&messages->iterator_end) Xapian::MSetIterator ();\r
173  \r
174         talloc_set_destructor (messages, _notmuch_messages_destructor);\r
175 @@ -157,6 +172,7 @@ notmuch_query_search_messages (notmuch_query_t *query)\r
176         mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());\r
177  \r
178         messages->iterator = mset.begin ();\r
179 +       messages->iterator_begin = mset.begin ();\r
180         messages->iterator_end = mset.end ();\r
181  \r
182      } catch (const Xapian::Error &error) {\r
183 @@ -208,6 +224,16 @@ _notmuch_mset_messages_get (notmuch_messages_t *messages)\r
184  }\r
185  \r
186  void\r
187 +_notmuch_mset_messages_move_to_first (notmuch_messages_t *messages)\r
188 +{\r
189 +    notmuch_mset_messages_t *mset_messages;\r
190 +\r
191 +    mset_messages = (notmuch_mset_messages_t *) messages;\r
192 +\r
193 +    mset_messages->iterator = mset_messages->iterator_begin;\r
194 +}\r
195 +\r
196 +void\r
197  _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)\r
198  {\r
199      notmuch_mset_messages_t *mset_messages;\r
200 @@ -217,6 +243,113 @@ _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages)\r
201      mset_messages->iterator++;\r
202  }\r
203  \r
204 +void\r
205 +_notmuch_mset_messages_move_to_last (notmuch_messages_t *messages)\r
206 +{\r
207 +    notmuch_mset_messages_t *mset_messages;\r
208 +\r
209 +    mset_messages = (notmuch_mset_messages_t *) messages;\r
210 +\r
211 +    mset_messages->iterator = mset_messages->iterator_end;\r
212 +    mset_messages->iterator--;\r
213 +}\r
214 +\r
215 +void\r
216 +_notmuch_mset_messages_move_to_previous (notmuch_messages_t *messages)\r
217 +{\r
218 +    notmuch_mset_messages_t *mset_messages;\r
219 +\r
220 +    mset_messages = (notmuch_mset_messages_t *) messages;\r
221 +\r
222 +    if (mset_messages->iterator == mset_messages->iterator_begin)\r
223 +    {\r
224 +        /*\r
225 +         * Xapian iterators can not be beyond the first element, so we\r
226 +         * assign the iterator_end to mark the iterator as invalid in case\r
227 +         * of move_to_previous with the iterator at the beginning\r
228 +         */\r
229 +        mset_messages->iterator = mset_messages->iterator_end;\r
230 +    }\r
231 +    else if (_notmuch_mset_messages_valid (messages))\r
232 +    {\r
233 +        /*\r
234 +         * If is valid move the iterator. To emulate the same behavior \r
235 +         * than notmuch_messages_t the iterator won't be updated if is \r
236 +         * not valid\r
237 +         */\r
238 +        mset_messages->iterator--;\r
239 +    }\r
240 +}\r
241 +\r
242 +static notmuch_thread_list_t *\r
243 +_notmuch_thread_list_create (void *ctx)\r
244 +{\r
245 +    notmuch_thread_list_t *list;\r
246 +\r
247 +    list = talloc (ctx, notmuch_thread_list_t);\r
248 +    list->tail = NULL;\r
249 +    list->head = NULL;\r
250 +    list->iterator = NULL;\r
251 +\r
252 +    return list;\r
253 +}\r
254 +\r
255 +static void\r
256 +_notmuch_thread_list_append (notmuch_thread_list_t *list, const char *thread_id)\r
257 +{\r
258 +    list->iterator = talloc (list, notmuch_thread_node_t);\r
259 +    if (list->head == NULL)\r
260 +    {\r
261 +        list->head = list->iterator;\r
262 +        list->iterator->prev = NULL;\r
263 +    }\r
264 +    else\r
265 +    {\r
266 +        list->tail->next = list->iterator;\r
267 +        list->iterator->prev = list->tail;\r
268 +    }\r
269 +\r
270 +    list->iterator->thread_id = thread_id;\r
271 +    list->iterator->next = NULL;\r
272 +    list->tail = list->iterator;\r
273 +}\r
274 +\r
275 +static const char *\r
276 +_notmuch_thread_list_get_id (notmuch_thread_list_t *list)\r
277 +{\r
278 +    return list->iterator->thread_id;\r
279 +}\r
280 +\r
281 +static notmuch_bool_t\r
282 +_notmuch_thread_list_valid (notmuch_thread_list_t *list)\r
283 +{\r
284 +    return (list->iterator != NULL);\r
285 +}\r
286 +\r
287 +static void\r
288 +_notmuch_thread_list_move_to_first (notmuch_thread_list_t *list)\r
289 +{\r
290 +    list->iterator = list->head;\r
291 +}\r
292 +\r
293 +static void\r
294 +_notmuch_thread_list_move_to_next (notmuch_thread_list_t *list)\r
295 +{\r
296 +    list->iterator = list->iterator->next;\r
297 +}\r
298 +\r
299 +static void\r
300 +_notmuch_thread_list_move_to_last (notmuch_thread_list_t *list)\r
301 +{\r
302 +    list->iterator = list->tail;\r
303 +}\r
304 +\r
305 +static void\r
306 +_notmuch_thread_list_move_to_previous (notmuch_thread_list_t *list)\r
307 +{\r
308 +    list->iterator = list->iterator->prev;\r
309 +}\r
310 +\r
311  /* Glib objects force use to use a talloc destructor as well, (but not\r
312   * nearly as ugly as the for messages due to C++ objects). At\r
313   * this point, I'd really like to have some talloc-friendly\r
314 @@ -244,16 +377,15 @@ notmuch_query_search_threads (notmuch_query_t *query)\r
315                                               free, NULL);\r
316  \r
317      threads->messages = notmuch_query_search_messages (query);\r
318 +    threads->list = _notmuch_thread_list_create (threads);\r
319      if (!notmuch_messages_valid (threads->messages))\r
320 -    {\r
321 -        threads->thread_id = NULL;\r
322          return threads;\r
323 -    }\r
324  \r
325      message = notmuch_messages_get (threads->messages);\r
326 -    threads->thread_id = notmuch_message_get_thread_id (message);\r
327 +    _notmuch_thread_list_append (threads->list,\r
328 +                                 notmuch_message_get_thread_id (message));\r
329      g_hash_table_insert (threads->threads,\r
330 -                         xstrdup (threads->thread_id),\r
331 +                         xstrdup (_notmuch_thread_list_get_id (threads->list)),\r
332                           NULL);\r
333  \r
334      talloc_set_destructor (threads, _notmuch_threads_destructor);\r
335 @@ -270,7 +402,7 @@ notmuch_query_destroy (notmuch_query_t *query)\r
336  notmuch_bool_t\r
337  notmuch_threads_valid (notmuch_threads_t *threads)\r
338  {\r
339 -    return (threads->thread_id != NULL);\r
340 +    return _notmuch_thread_list_valid (threads->list);\r
341  }\r
342  \r
343  notmuch_thread_t *\r
344 @@ -281,35 +413,82 @@ notmuch_threads_get (notmuch_threads_t *threads)\r
345  \r
346      return _notmuch_thread_create (threads->query,\r
347                                    threads->query->notmuch,\r
348 -                                  threads->thread_id,\r
349 +                                  _notmuch_thread_list_get_id (threads->list),\r
350                                    threads->query->query_string);\r
351  }\r
352  \r
353  void\r
354 +notmuch_threads_move_to_first (notmuch_threads_t *threads)\r
355 +{\r
356 +    _notmuch_thread_list_move_to_first (threads->list);\r
357 +}\r
358 +\r
359 +void\r
360  notmuch_threads_move_to_next (notmuch_threads_t *threads)\r
361  {\r
362 -    notmuch_message_t *message;\r
363 +    if (!_notmuch_thread_list_valid (threads->list))\r
364 +        return;\r
365 +\r
366 +    _notmuch_thread_list_move_to_next (threads->list);\r
367 +    if (_notmuch_thread_list_valid (threads->list))\r
368 +        return;\r
369  \r
370      while (notmuch_messages_valid (threads->messages))\r
371      {\r
372 -       message = notmuch_messages_get (threads->messages);\r
373 +        notmuch_message_t *message;\r
374 +        const char *thread_id;\r
375  \r
376 -       threads->thread_id = notmuch_message_get_thread_id (message);\r
377 +       message = notmuch_messages_get (threads->messages);\r
378 +       thread_id = notmuch_message_get_thread_id (message);\r
379  \r
380         if (! g_hash_table_lookup_extended (threads->threads,\r
381 -                                           threads->thread_id,\r
382 +                                           thread_id,\r
383                                             NULL, NULL))\r
384         {\r
385             g_hash_table_insert (threads->threads,\r
386 -                                xstrdup (threads->thread_id), NULL);\r
387 +                                xstrdup (thread_id), NULL);\r
388 +            _notmuch_thread_list_append (threads->list, thread_id);\r
389             notmuch_messages_move_to_next (threads->messages);\r
390             return;\r
391         }\r
392  \r
393         notmuch_messages_move_to_next (threads->messages);\r
394      }\r
395 +}\r
396 +\r
397 +void\r
398 +notmuch_threads_move_to_last (notmuch_threads_t *threads)\r
399 +{\r
400 +    _notmuch_thread_list_move_to_last (threads->list);\r
401 +\r
402 +    while (notmuch_messages_valid (threads->messages))\r
403 +    {\r
404 +        notmuch_message_t *message;\r
405 +        const char *thread_id;\r
406 +\r
407 +       message = notmuch_messages_get (threads->messages);\r
408 +       thread_id = notmuch_message_get_thread_id (message);\r
409 +\r
410 +       if (! g_hash_table_lookup_extended (threads->threads,\r
411 +                                           thread_id,\r
412 +                                           NULL, NULL))\r
413 +       {\r
414 +           g_hash_table_insert (threads->threads,\r
415 +                                xstrdup (thread_id), NULL);\r
416 +            _notmuch_thread_list_append (threads->list, thread_id);\r
417 +        }\r
418 +\r
419 +       notmuch_messages_move_to_next (threads->messages);\r
420 +    }\r
421 +}\r
422 +\r
423 +void\r
424 +notmuch_threads_move_to_previous (notmuch_threads_t *threads)\r
425 +{\r
426 +    if (!_notmuch_thread_list_valid (threads->list))\r
427 +        return;\r
428  \r
429 -    threads->thread_id = NULL;\r
430 +    _notmuch_thread_list_move_to_previous (threads->list);\r
431  }\r
432  \r
433  void\r
434 -- \r
435 1.7.0\r
436 \r