Reply all - issue
[notmuch-archives.git] / 8f / c6c710ae65f5ac58dbcc24c74365ae221d9114
1 Return-Path: <Sebastian@SSpaeth.de>\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 D209D4196F3\r
6         for <notmuch@notmuchmail.org>; Wed, 21 Apr 2010 07:11:22 -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 svf-4VNHV8ST for <notmuch@notmuchmail.org>;\r
16         Wed, 21 Apr 2010 07:11:17 -0700 (PDT)\r
17 Received: from homiemail-a13.g.dreamhost.com (caiajhbdcagg.dreamhost.com\r
18         [208.97.132.66])\r
19         by olra.theworths.org (Postfix) with ESMTP id 7F2CB431FC1\r
20         for <notmuch@notmuchmail.org>; Wed, 21 Apr 2010 07:11:17 -0700 (PDT)\r
21 Received: from sspaeth.de (unknown [195.190.188.219])\r
22         by homiemail-a13.g.dreamhost.com (Postfix) with ESMTPA id B3EA06A806B; \r
23         Wed, 21 Apr 2010 07:11:13 -0700 (PDT)\r
24 Received: by sspaeth.de (sSMTP sendmail emulation);\r
25         Wed, 21 Apr 2010 16:11:09 +0200\r
26 From: "Sebastian Spaeth" <Sebastian@SSpaeth.de>\r
27 To: Dirk Hohndel <hohndel@infradead.org>,\r
28         Notmuch development list <notmuch@notmuchmail.org>\r
29 Subject: Re: Address completion\r
30 In-Reply-To: <871ve9jkhy.fsf@SSpaeth.de>\r
31 References: <87bpddg67c.fsf@SSpaeth.de> <m3zl0xtqhf.fsf@x200.gr8dns.org>\r
32         <871ve9jkhy.fsf@SSpaeth.de>\r
33 Date: Wed, 21 Apr 2010 16:11:09 +0200\r
34 Message-ID: <878w8gj3pe.fsf@SSpaeth.de>\r
35 MIME-Version: 1.0\r
36 Content-Type: multipart/mixed; boundary="=-=-="\r
37 X-BeenThere: notmuch@notmuchmail.org\r
38 X-Mailman-Version: 2.1.13\r
39 Precedence: list\r
40 List-Id: "Use and development of the notmuch mail system."\r
41         <notmuch.notmuchmail.org>\r
42 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
43         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
44 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
45 List-Post: <mailto:notmuch@notmuchmail.org>\r
46 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
47 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
48         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
49 X-List-Received-Date: Wed, 21 Apr 2010 14:11:23 -0000\r
50 \r
51 --=-=-=\r
52 \r
53 David improved the notmuch-address.el glue today, and I improved my\r
54 addrlookup tool also. It is much more intelligent now:\r
55 \r
56 We parse the notmuch db in up to 3 passes now where each find from\r
57 the previous pass is sorted with heigher weight, ie we will first output\r
58 addresses in our "address book" then addresses we have mailed to\r
59 previously and only than at mails we have received.\r
60     \r
61 1st pass: Find all 'from' addresses that are in messages tagged as\r
62       'addressbook' (this tag is configurable in .notmuch-config under\r
63       [user] addrbook_tag=foo but uses addressbook by default)\r
64     \r
65 2nd pass: Find all 'to','cc','bcc' addresses that match our criteria and\r
66       that we ever sent a mail from our primary mail address\r
67     \r
68 3rd pass: If pass1 + 2 lead to less than 10 message hits, perform a pass\r
69       3.  Look at all email 'from' headers that match our criteria and\r
70       use those.  We limit this, because notmuch opens all mail files\r
71       that might match, to read the header out of them, potentially\r
72       hurting performance a lot. So don't do pass 3 if pass 1 & 2 lead\r
73       to likely results already.\r
74     \r
75 Using the address book feature, you can implement simple 'blacklisting'\r
76 of emails.  If you have friends at Sun for example, you might want to\r
77 'notmuch tag +addressbook from:"oracle.com"' to give those addresses\r
78 priority over the sun.com addresses you have previously used.\r
79 \r
80 Performance is still good enough. Doing a "addrlookup" which returns everyone\r
81 in my "addressbook" and all mail addresses I ever sent mail to (just\r
82 165), takes real 0m0.095s with a warm file cache. If the file cache is\r
83 cold, a search for e.g. "he" can take real      0m2.385s. The reason is\r
84 that notmuch opens all possibly matching mail files in order to retrieve\r
85 the headers.\r
86 \r
87 Compile directly from vala or the attached c source. Compiling the c source works with glib2.0-dev installed:\r
88 \r
89 cc -o addrlookup addrlookup.c `pkg-config --cflags --libs gobject-2.0`\r
90 -lnotmuch\r
91 \r
92 \r
93 --=-=-=\r
94 Content-Type: text/x-csrc\r
95 Content-Disposition: attachment; filename=addrlookup.c\r
96 Content-Description: c source file\r
97 \r
98 /* addrlookup.c generated by valac, the Vala compiler\r
99  * generated from addrlookup.vala, do not modify */\r
100 \r
101 \r
102 #include <glib.h>\r
103 #include <glib-object.h>\r
104 #include <notmuch.h>\r
105 #include <stdlib.h>\r
106 #include <string.h>\r
107 #include <stdio.h>\r
108 #include <gobject/gvaluecollector.h>\r
109 \r
110 \r
111 #define TYPE_ADDRESS_MATCHER (address_matcher_get_type ())\r
112 #define ADDRESS_MATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ADDRESS_MATCHER, AddressMatcher))\r
113 #define ADDRESS_MATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ADDRESS_MATCHER, AddressMatcherClass))\r
114 #define IS_ADDRESS_MATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ADDRESS_MATCHER))\r
115 #define IS_ADDRESS_MATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ADDRESS_MATCHER))\r
116 #define ADDRESS_MATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ADDRESS_MATCHER, AddressMatcherClass))\r
117 \r
118 typedef struct _AddressMatcher AddressMatcher;\r
119 typedef struct _AddressMatcherClass AddressMatcherClass;\r
120 typedef struct _AddressMatcherPrivate AddressMatcherPrivate;\r
121 #define _notmuch_database_close0(var) ((var == NULL) ? NULL : (var = (notmuch_database_close (var), NULL)))\r
122 #define _g_free0(var) (var = (g_free (var), NULL))\r
123 #define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))\r
124 #define _g_key_file_free0(var) ((var == NULL) ? NULL : (var = (g_key_file_free (var), NULL)))\r
125 \r
126 #define ADDRESS_MATCHER_TYPE_MAILADDRESS_FREQ (address_matcher_mailaddress_freq_get_type ())\r
127 typedef struct _AddressMatcherMailAddress_freq AddressMatcherMailAddress_freq;\r
128 #define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL)))\r
129 #define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))\r
130 #define _g_regex_unref0(var) ((var == NULL) ? NULL : (var = (g_regex_unref (var), NULL)))\r
131 #define _g_match_info_free0(var) ((var == NULL) ? NULL : (var = (g_match_info_free (var), NULL)))\r
132 #define _0(var) ((var == NULL) ? NULL : (var = ( (var), NULL)))\r
133 #define _address_matcher_mailaddress_freq_free0(var) ((var == NULL) ? NULL : (var = (address_matcher_mailaddress_freq_free (var), NULL)))\r
134 #define __g_list_free_address_matcher_mailaddress_freq_free0(var) ((var == NULL) ? NULL : (var = (_g_list_free_address_matcher_mailaddress_freq_free (var), NULL)))\r
135 #define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))\r
136 typedef struct _ParamSpecAddressMatcher ParamSpecAddressMatcher;\r
137 #define _address_matcher_unref0(var) ((var == NULL) ? NULL : (var = (address_matcher_unref (var), NULL)))\r
138 \r
139 struct _AddressMatcher {\r
140         GTypeInstance parent_instance;\r
141         volatile int ref_count;\r
142         AddressMatcherPrivate * priv;\r
143 };\r
144 \r
145 struct _AddressMatcherClass {\r
146         GTypeClass parent_class;\r
147         void (*finalize) (AddressMatcher *self);\r
148 };\r
149 \r
150 struct _AddressMatcherPrivate {\r
151         notmuch_database_t* db;\r
152         char* user_db_path;\r
153         char* user_primary_email;\r
154         char* user_addrbook_tag;\r
155 };\r
156 \r
157 struct _AddressMatcherMailAddress_freq {\r
158         char* address;\r
159         guint* occurances;\r
160         gint occurances_length1;\r
161         gint _occurances_size_;\r
162 };\r
163 \r
164 struct _ParamSpecAddressMatcher {\r
165         GParamSpec parent_instance;\r
166 };\r
167 \r
168 \r
169 static gpointer address_matcher_parent_class = NULL;\r
170 \r
171 gpointer address_matcher_ref (gpointer instance);\r
172 void address_matcher_unref (gpointer instance);\r
173 GParamSpec* param_spec_address_matcher (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);\r
174 void value_set_address_matcher (GValue* value, gpointer v_object);\r
175 void value_take_address_matcher (GValue* value, gpointer v_object);\r
176 gpointer value_get_address_matcher (const GValue* value);\r
177 GType address_matcher_get_type (void);\r
178 #define ADDRESS_MATCHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_ADDRESS_MATCHER, AddressMatcherPrivate))\r
179 enum  {\r
180         ADDRESS_MATCHER_DUMMY_PROPERTY\r
181 };\r
182 AddressMatcher* address_matcher_new (void);\r
183 AddressMatcher* address_matcher_construct (GType object_type);\r
184 static GType address_matcher_mailaddress_freq_get_type (void) G_GNUC_UNUSED;\r
185 static AddressMatcherMailAddress_freq* address_matcher_mailaddress_freq_dup (const AddressMatcherMailAddress_freq* self);\r
186 static void address_matcher_mailaddress_freq_free (AddressMatcherMailAddress_freq* self);\r
187 static void address_matcher_mailaddress_freq_copy (const AddressMatcherMailAddress_freq* self, AddressMatcherMailAddress_freq* dest);\r
188 static void address_matcher_mailaddress_freq_destroy (AddressMatcherMailAddress_freq* self);\r
189 static gint address_matcher_sort_by_freq (AddressMatcherMailAddress_freq* mail1, AddressMatcherMailAddress_freq* mail2);\r
190 char* address_matcher_frequent_fullname (AddressMatcher* self, GHashTable* frequencies);\r
191 GHashTable* address_matcher_addresses_by_frequency (AddressMatcher* self, notmuch_messages_t* msgs, const char* name, guint pass, GHashTable** addr2realname);\r
192 static void _vala_array_add1 (char*** array, int* length, int* size, char* value);\r
193 static void _g_list_free_address_matcher_mailaddress_freq_free (GList* self);\r
194 char** address_matcher_search_address_passes (AddressMatcher* self, notmuch_query_t** queries, int queries_length1, const char* name, int* result_length1);\r
195 static void _vala_array_add2 (notmuch_query_t*** array, int* length, int* size, notmuch_query_t* value);\r
196 static void _vala_array_add3 (notmuch_query_t*** array, int* length, int* size, notmuch_query_t* value);\r
197 static void _vala_array_add4 (notmuch_query_t*** array, int* length, int* size, notmuch_query_t* value);\r
198 void address_matcher_run (AddressMatcher* self, const char* name);\r
199 static guint* _vala_array_dup1 (guint* self, int length);\r
200 static void address_matcher_finalize (AddressMatcher* obj);\r
201 gint _vala_main (char** args, int args_length1);\r
202 static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func);\r
203 static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func);\r
204 \r
205 \r
206 \r
207 AddressMatcher* address_matcher_construct (GType object_type) {\r
208         GError * _inner_error_;\r
209         AddressMatcher* self;\r
210         GKeyFile* config;\r
211         char* home;\r
212         _inner_error_ = NULL;\r
213         self = (AddressMatcher*) g_type_create_instance (object_type);\r
214         config = g_key_file_new ();\r
215         home = g_strdup (g_getenv ("NOTMUCH_CONFIG"));\r
216         if (home == NULL) {\r
217                 char* _tmp0_;\r
218                 home = (_tmp0_ = g_strdup (g_get_home_dir ()), _g_free0 (home), _tmp0_);\r
219         }\r
220         {\r
221                 char* _tmp1_;\r
222                 char* _tmp2_;\r
223                 char* _tmp3_;\r
224                 g_key_file_load_from_file (config, _tmp1_ = g_strconcat (home, "/.notmuch-config", NULL), G_KEY_FILE_NONE, &_inner_error_);\r
225                 _g_free0 (_tmp1_);\r
226                 if (_inner_error_ != NULL) {\r
227                         goto __catch0_g_error;\r
228                 }\r
229                 _tmp2_ = g_key_file_get_string (config, "database", "path", &_inner_error_);\r
230                 if (_inner_error_ != NULL) {\r
231                         goto __catch0_g_error;\r
232                 }\r
233                 self->priv->user_db_path = (_tmp3_ = _tmp2_, _g_free0 (self->priv->user_db_path), _tmp3_);\r
234         }\r
235         goto __finally0;\r
236         __catch0_g_error:\r
237         {\r
238                 GError * ex;\r
239                 ex = _inner_error_;\r
240                 _inner_error_ = NULL;\r
241                 {\r
242                         _g_error_free0 (ex);\r
243                 }\r
244         }\r
245         __finally0:\r
246         if (_inner_error_ != NULL) {\r
247                 _g_key_file_free0 (config);\r
248                 _g_free0 (home);\r
249                 g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);\r
250                 g_clear_error (&_inner_error_);\r
251                 return NULL;\r
252         }\r
253         {\r
254                 char* _tmp4_;\r
255                 char* _tmp5_;\r
256                 _tmp4_ = g_key_file_get_string (config, "user", "primary_email", &_inner_error_);\r
257                 if (_inner_error_ != NULL) {\r
258                         goto __catch1_g_error;\r
259                 }\r
260                 self->priv->user_primary_email = (_tmp5_ = _tmp4_, _g_free0 (self->priv->user_primary_email), _tmp5_);\r
261         }\r
262         goto __finally1;\r
263         __catch1_g_error:\r
264         {\r
265                 GError * ex;\r
266                 ex = _inner_error_;\r
267                 _inner_error_ = NULL;\r
268                 {\r
269                         _g_error_free0 (ex);\r
270                 }\r
271         }\r
272         __finally1:\r
273         if (_inner_error_ != NULL) {\r
274                 _g_key_file_free0 (config);\r
275                 _g_free0 (home);\r
276                 g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);\r
277                 g_clear_error (&_inner_error_);\r
278                 return NULL;\r
279         }\r
280         {\r
281                 char* _tmp6_;\r
282                 char* _tmp7_;\r
283                 _tmp6_ = g_key_file_get_string (config, "user", "addrbook_tag", &_inner_error_);\r
284                 if (_inner_error_ != NULL) {\r
285                         goto __catch2_g_error;\r
286                 }\r
287                 self->priv->user_addrbook_tag = (_tmp7_ = _tmp6_, _g_free0 (self->priv->user_addrbook_tag), _tmp7_);\r
288         }\r
289         goto __finally2;\r
290         __catch2_g_error:\r
291         {\r
292                 GError * ex;\r
293                 ex = _inner_error_;\r
294                 _inner_error_ = NULL;\r
295                 {\r
296                         char* _tmp8_;\r
297                         self->priv->user_addrbook_tag = (_tmp8_ = g_strdup ("addressbook"), _g_free0 (self->priv->user_addrbook_tag), _tmp8_);\r
298                         _g_error_free0 (ex);\r
299                 }\r
300         }\r
301         __finally2:\r
302         if (_inner_error_ != NULL) {\r
303                 _g_key_file_free0 (config);\r
304                 _g_free0 (home);\r
305                 g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);\r
306                 g_clear_error (&_inner_error_);\r
307                 return NULL;\r
308         }\r
309         _g_key_file_free0 (config);\r
310         _g_free0 (home);\r
311         return self;\r
312 }\r
313 \r
314 \r
315 AddressMatcher* address_matcher_new (void) {\r
316         return address_matcher_construct (TYPE_ADDRESS_MATCHER);\r
317 }\r
318 \r
319 \r
320 static gint address_matcher_sort_by_freq (AddressMatcherMailAddress_freq* mail1, AddressMatcherMailAddress_freq* mail2) {\r
321         gint result = 0;\r
322         gboolean _tmp0_ = FALSE;\r
323         gboolean _tmp1_ = FALSE;\r
324         gboolean _tmp2_ = FALSE;\r
325         gboolean _tmp3_ = FALSE;\r
326         if ((*mail1).occurances[0] == (*mail2).occurances[0]) {\r
327                 _tmp1_ = (*mail1).occurances[1] == (*mail2).occurances[1];\r
328         } else {\r
329                 _tmp1_ = FALSE;\r
330         }\r
331         if (_tmp1_) {\r
332                 _tmp0_ = (*mail1).occurances[2] == (*mail2).occurances[2];\r
333         } else {\r
334                 _tmp0_ = FALSE;\r
335         }\r
336         if (_tmp0_) {\r
337                 result = 0;\r
338                 return result;\r
339         }\r
340         if ((*mail1).occurances[0] > (*mail2).occurances[0]) {\r
341                 _tmp3_ = TRUE;\r
342         } else {\r
343                 gboolean _tmp4_ = FALSE;\r
344                 if ((*mail1).occurances[0] == (*mail2).occurances[0]) {\r
345                         _tmp4_ = (*mail1).occurances[1] > (*mail2).occurances[1];\r
346                 } else {\r
347                         _tmp4_ = FALSE;\r
348                 }\r
349                 _tmp3_ = _tmp4_;\r
350         }\r
351         if (_tmp3_) {\r
352                 _tmp2_ = TRUE;\r
353         } else {\r
354                 gboolean _tmp5_ = FALSE;\r
355                 gboolean _tmp6_ = FALSE;\r
356                 if ((*mail1).occurances[0] == (*mail2).occurances[0]) {\r
357                         _tmp6_ = (*mail1).occurances[1] == (*mail2).occurances[1];\r
358                 } else {\r
359                         _tmp6_ = FALSE;\r
360                 }\r
361                 if (_tmp6_) {\r
362                         _tmp5_ = (*mail1).occurances[2] > (*mail2).occurances[2];\r
363                 } else {\r
364                         _tmp5_ = FALSE;\r
365                 }\r
366                 _tmp2_ = _tmp5_;\r
367         }\r
368         if (_tmp2_) {\r
369                 result = -1;\r
370                 return result;\r
371         }\r
372         result = 1;\r
373         return result;\r
374 }\r
375 \r
376 \r
377 static gboolean string_contains (const char* self, const char* needle) {\r
378         gboolean result = FALSE;\r
379         g_return_val_if_fail (self != NULL, FALSE);\r
380         g_return_val_if_fail (needle != NULL, FALSE);\r
381         result = strstr (self, needle) != NULL;\r
382         return result;\r
383 }\r
384 \r
385 \r
386 char* address_matcher_frequent_fullname (AddressMatcher* self, GHashTable* frequencies) {\r
387         char* result = NULL;\r
388         guint maxfreq;\r
389         char* fullname;\r
390         g_return_val_if_fail (self != NULL, NULL);\r
391         g_return_val_if_fail (frequencies != NULL, NULL);\r
392         maxfreq = (guint) 0;\r
393         fullname = NULL;\r
394         {\r
395                 GList* mail_collection;\r
396                 GList* mail_it;\r
397                 mail_collection = g_hash_table_get_keys (frequencies);\r
398                 for (mail_it = mail_collection; mail_it != NULL; mail_it = mail_it->next) {\r
399                         const char* mail;\r
400                         mail = (const char*) mail_it->data;\r
401                         {\r
402                                 guint freq;\r
403                                 gboolean _tmp0_ = FALSE;\r
404                                 gboolean _tmp1_ = FALSE;\r
405                                 freq = GPOINTER_TO_UINT (g_hash_table_lookup (frequencies, mail));\r
406                                 if (freq > maxfreq) {\r
407                                         _tmp1_ = string_contains (mail, " ");\r
408                                 } else {\r
409                                         _tmp1_ = FALSE;\r
410                                 }\r
411                                 if (_tmp1_) {\r
412                                         _tmp0_ = TRUE;\r
413                                 } else {\r
414                                         _tmp0_ = g_hash_table_size (frequencies) == 1;\r
415                                 }\r
416                                 if (_tmp0_) {\r
417                                         char* _tmp2_;\r
418                                         maxfreq = freq;\r
419                                         fullname = (_tmp2_ = g_strdup (mail), _g_free0 (fullname), _tmp2_);\r
420                                 }\r
421                         }\r
422                 }\r
423                 _g_list_free0 (mail_collection);\r
424         }\r
425         result = fullname;\r
426         return result;\r
427 }\r
428 \r
429 \r
430 static gpointer _g_hash_table_ref0 (gpointer self) {\r
431         return self ? g_hash_table_ref (self) : NULL;\r
432 }\r
433 \r
434 \r
435 GHashTable* address_matcher_addresses_by_frequency (AddressMatcher* self, notmuch_messages_t* msgs, const char* name, guint pass, GHashTable** addr2realname) {\r
436         GHashTable* result = NULL;\r
437         GError * _inner_error_;\r
438         GHashTable* ht;\r
439         GRegex* re;\r
440         char** _tmp3_;\r
441         gint _headers_size_;\r
442         gint headers_length1;\r
443         char** _tmp2_ = NULL;\r
444         char** headers;\r
445         g_return_val_if_fail (self != NULL, NULL);\r
446         g_return_val_if_fail (msgs != NULL, NULL);\r
447         g_return_val_if_fail (name != NULL, NULL);\r
448         g_return_val_if_fail (addr2realname != NULL, NULL);\r
449         _inner_error_ = NULL;\r
450         ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);\r
451         re = NULL;\r
452         {\r
453                 GRegex* _tmp0_;\r
454                 GRegex* _tmp1_;\r
455                 _tmp0_ = g_regex_new ("\\s*((\\\"(\\\\.|[^\\\\\"])*\\\"|[^,])*" "<?(?P<mail>\\b\\w+([-+.]\\w+)*\\@\\w+[-\\.\\w]*\\.([-\\.\\w]+)*\\w\\b)" \\r
456 ">?)", 0, 0, &_inner_error_);\r
457                 if (_inner_error_ != NULL) {\r
458                         if (_inner_error_->domain == G_REGEX_ERROR) {\r
459                                 goto __catch3_g_regex_error;\r
460                         }\r
461                         _g_hash_table_unref0 (ht);\r
462                         _g_regex_unref0 (re);\r
463                         g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);\r
464                         g_clear_error (&_inner_error_);\r
465                         return NULL;\r
466                 }\r
467                 re = (_tmp1_ = _tmp0_, _g_regex_unref0 (re), _tmp1_);\r
468         }\r
469         goto __finally3;\r
470         __catch3_g_regex_error:\r
471         {\r
472                 GError * ex;\r
473                 ex = _inner_error_;\r
474                 _inner_error_ = NULL;\r
475                 {\r
476                         _g_error_free0 (ex);\r
477                 }\r
478         }\r
479         __finally3:\r
480         if (_inner_error_ != NULL) {\r
481                 _g_hash_table_unref0 (ht);\r
482                 _g_regex_unref0 (re);\r
483                 g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);\r
484                 g_clear_error (&_inner_error_);\r
485                 return NULL;\r
486         }\r
487         headers = (_tmp3_ = (_tmp2_ = g_new0 (char*, 1 + 1), _tmp2_[0] = g_strdup ("from"), _tmp2_), headers_length1 = 1, _headers_size_ = headers_length1, _tmp3_);\r
488         if (pass == 1) {\r
489                 char** _tmp5_;\r
490                 char** _tmp4_ = NULL;\r
491                 headers = (_tmp5_ = (_tmp4_ = g_new0 (char*, 3 + 1), _tmp4_[0] = g_strdup ("to"), _tmp4_[1] = g_strdup ("cc"), _tmp4_[2] = g_strdup ("bcc"), _tmp4_), headers = (_vala_array_free (headers, headers_length1, (GDestroyNotify) g_free), NULL), headers_length1 = 3, _headers_size_ = headers_length1, _tmp5_);\r
492         }\r
493         while (TRUE) {\r
494                 GMatchInfo* matches;\r
495                 notmuch_message_t* msg;\r
496                 if (!notmuch_messages_valid (msgs)) {\r
497                         break;\r
498                 }\r
499                 matches = NULL;\r
500                 msg = notmuch_messages_get (msgs);\r
501                 {\r
502                         char** header_collection;\r
503                         int header_collection_length1;\r
504                         int header_it;\r
505                         header_collection = headers;\r
506                         header_collection_length1 = headers_length1;\r
507                         for (header_it = 0; header_it < headers_length1; header_it = header_it + 1) {\r
508                                 char* header;\r
509                                 header = g_strdup (header_collection[header_it]);\r
510                                 {\r
511                                         char* froms;\r
512                                         GMatchInfo* _tmp8_;\r
513                                         gboolean _tmp7_;\r
514                                         GMatchInfo* _tmp6_ = NULL;\r
515                                         gboolean found;\r
516                                         froms = g_strdup ((const char*) notmuch_message_get_header (msg, header));\r
517                                         found = (_tmp7_ = g_regex_match (re, froms, 0, &_tmp6_), matches = (_tmp8_ = _tmp6_, _g_match_info_free0 (matches), _tmp8_), _tmp7_);\r
518                                         while (TRUE) {\r
519                                                 char* from;\r
520                                                 char* addr;\r
521                                                 char* _tmp9_;\r
522                                                 char* _tmp11_;\r
523                                                 gboolean _tmp12_;\r
524                                                 gboolean is_match;\r
525                                                 guint occurs;\r
526                                                 GHashTable* realname_freq;\r
527                                                 if (!found) {\r
528                                                         break;\r
529                                                 }\r
530                                                 from = g_match_info_fetch (matches, 1);\r
531                                                 addr = g_match_info_fetch_named (matches, "mail");\r
532                                                 addr = (_tmp9_ = g_utf8_strdown (addr, -1), _g_free0 (addr), _tmp9_);\r
533                                                 {\r
534                                                         gboolean _tmp10_;\r
535                                                         _tmp10_ = g_match_info_next (matches, &_inner_error_);\r
536                                                         if (_inner_error_ != NULL) {\r
537                                                                 if (_inner_error_->domain == G_REGEX_ERROR) {\r
538                                                                         goto __catch4_g_regex_error;\r
539                                                                 }\r
540                                                                 _g_free0 (from);\r
541                                                                 _g_free0 (addr);\r
542                                                                 _g_free0 (header);\r
543                                                                 _g_free0 (froms);\r
544                                                                 _g_match_info_free0 (matches);\r
545                                                                 _0 (msg);\r
546                                                                 _g_hash_table_unref0 (ht);\r
547                                                                 _g_regex_unref0 (re);\r
548                                                                 headers = (_vala_array_free (headers, headers_length1, (GDestroyNotify) g_free), NULL);\r
549                                                                 g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);\r
550                                                                 g_clear_error (&_inner_error_);\r
551                                                                 return NULL;\r
552                                                         }\r
553                                                         found = _tmp10_;\r
554                                                 }\r
555                                                 goto __finally4;\r
556                                                 __catch4_g_regex_error:\r
557                                                 {\r
558                                                         GError * ex;\r
559                                                         ex = _inner_error_;\r
560                                                         _inner_error_ = NULL;\r
561                                                         {\r
562                                                                 _g_error_free0 (ex);\r
563                                                         }\r
564                                                 }\r
565                                                 __finally4:\r
566                                                 if (_inner_error_ != NULL) {\r
567                                                         _g_free0 (from);\r
568                                                         _g_free0 (addr);\r
569                                                         _g_free0 (header);\r
570                                                         _g_free0 (froms);\r
571                                                         _g_match_info_free0 (matches);\r
572                                                         _0 (msg);\r
573                                                         _g_hash_table_unref0 (ht);\r
574                                                         _g_regex_unref0 (re);\r
575                                                         headers = (_vala_array_free (headers, headers_length1, (GDestroyNotify) g_free), NULL);\r
576                                                         g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);\r
577                                                         g_clear_error (&_inner_error_);\r
578                                                         return NULL;\r
579                                                 }\r
580                                                 is_match = (_tmp12_ = g_regex_match_simple (_tmp11_ = g_strconcat ("\\b", name, NULL), from, G_REGEX_CASELESS, 0), _g_free0 (_tmp11_), _tmp12_);\r
581                                                 if (!is_match) {\r
582                                                         _g_free0 (from);\r
583                                                         _g_free0 (addr);\r
584                                                         continue;\r
585                                                 }\r
586                                                 occurs = GPOINTER_TO_UINT (g_hash_table_lookup (ht, addr)) + 1;\r
587                                                 g_hash_table_replace (ht, g_strdup (addr), GUINT_TO_POINTER (occurs));\r
588                                                 realname_freq = _g_hash_table_ref0 ((GHashTable*) g_hash_table_lookup (*addr2realname, addr));\r
589                                                 if (realname_freq == NULL) {\r
590                                                         GHashTable* _tmp13_;\r
591                                                         realname_freq = (_tmp13_ = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL), _g_hash_table_unref0 (realname_freq), _tmp13_);\r
592                                                         g_hash_table_insert (*addr2realname, g_strdup (addr), _g_hash_table_ref0 (realname_freq));\r
593                                                 }\r
594                                                 occurs = GPOINTER_TO_UINT (g_hash_table_lookup (realname_freq, from)) + 1;\r
595                                                 g_hash_table_replace (realname_freq, g_strdup (from), GUINT_TO_POINTER (occurs));\r
596                                                 _g_free0 (from);\r
597                                                 _g_free0 (addr);\r
598                                                 _g_hash_table_unref0 (realname_freq);\r
599                                         }\r
600                                         _g_free0 (header);\r
601                                         _g_free0 (froms);\r
602                                 }\r
603                         }\r
604                 }\r
605                 notmuch_message_destroy (msg);\r
606                 notmuch_messages_move_to_next (msgs);\r
607                 _g_match_info_free0 (matches);\r
608                 _0 (msg);\r
609         }\r
610         result = ht;\r
611         _g_regex_unref0 (re);\r
612         headers = (_vala_array_free (headers, headers_length1, (GDestroyNotify) g_free), NULL);\r
613         return result;\r
614 }\r
615 \r
616 \r
617 static gpointer _address_matcher_mailaddress_freq_dup0 (gpointer self) {\r
618         return self ? address_matcher_mailaddress_freq_dup (self) : NULL;\r
619 }\r
620 \r
621 \r
622 static void _vala_array_add1 (char*** array, int* length, int* size, char* value) {\r
623         if ((*length) == (*size)) {\r
624                 *size = (*size) ? (2 * (*size)) : 4;\r
625                 *array = g_renew (char*, *array, (*size) + 1);\r
626         }\r
627         (*array)[(*length)++] = value;\r
628         (*array)[*length] = NULL;\r
629 }\r
630 \r
631 \r
632 static void _g_list_free_address_matcher_mailaddress_freq_free (GList* self) {\r
633         g_list_foreach (self, (GFunc) address_matcher_mailaddress_freq_free, NULL);\r
634         g_list_free (self);\r
635 }\r
636 \r
637 \r
638 char** address_matcher_search_address_passes (AddressMatcher* self, notmuch_query_t** queries, int queries_length1, const char* name, int* result_length1) {\r
639         char** result = NULL;\r
640         char** _tmp0_;\r
641         gint _return_value_size_;\r
642         gint return_value_length1;\r
643         char** return_value;\r
644         GHashTable* addrfreq;\r
645         GHashTable* addr2realname;\r
646         guint pass;\r
647         GList* addrs;\r
648         char** _tmp6_;\r
649         g_return_val_if_fail (self != NULL, NULL);\r
650         g_return_val_if_fail (name != NULL, NULL);\r
651         return_value = (_tmp0_ = NULL, return_value_length1 = 0, _return_value_size_ = return_value_length1, _tmp0_);\r
652         addrfreq = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);\r
653         addr2realname = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);\r
654         pass = (guint) 0;\r
655         {\r
656                 notmuch_query_t** q_collection;\r
657                 int q_collection_length1;\r
658                 int q_it;\r
659                 q_collection = queries;\r
660                 q_collection_length1 = queries_length1;\r
661                 for (q_it = 0; q_it < queries_length1; q_it = q_it + 1) {\r
662                         notmuch_query_t* q;\r
663                         q = q_collection[q_it];\r
664                         {\r
665                                 notmuch_messages_t* msgs;\r
666                                 GHashTable* ht;\r
667                                 msgs = notmuch_query_search_messages (q);\r
668                                 ht = address_matcher_addresses_by_frequency (self, msgs, name, pass, &addr2realname);\r
669                                 {\r
670                                         GList* addr_collection;\r
671                                         GList* addr_it;\r
672                                         addr_collection = g_hash_table_get_keys (ht);\r
673                                         for (addr_it = addr_collection; addr_it != NULL; addr_it = addr_it->next) {\r
674                                                 const char* addr;\r
675                                                 addr = (const char*) addr_it->data;\r
676                                                 {\r
677                                                         AddressMatcherMailAddress_freq* freq;\r
678                                                         freq = _address_matcher_mailaddress_freq_dup0 ((AddressMatcherMailAddress_freq*) g_hash_table_lookup (addrfreq, addr));\r
679                                                         if (freq == NULL) {\r
680                                                                 AddressMatcherMailAddress_freq* _tmp5_;\r
681                                                                 AddressMatcherMailAddress_freq _tmp4_;\r
682                                                                 AddressMatcherMailAddress_freq _tmp3_;\r
683                                                                 guint* _tmp1_ = NULL;\r
684                                                                 AddressMatcherMailAddress_freq _tmp2_ = {0};\r
685                                                                 freq = (_tmp5_ = _address_matcher_mailaddress_freq_dup0 ((_tmp4_ = _tmp3_ = (memset (&_tmp2_, 0, sizeof (AddressMatcherMailAddress_freq)), _tmp2_.address = g_strdup (addr), _tmp2_.occurances = (_tmp1_ = g_new0 (guint, 3), _tmp1_[0] = (guint) 0, _tmp1_[1] = (guint) 0, _tmp1_[2] = (guint) 0, _tmp1_), _tmp2_.occurances_length1 = 3, _tmp2_), &_tmp4_)), _address_matcher_mailaddress_freq_free0 (freq), _tmp5_);\r
686                                                                 address_matcher_mailaddress_freq_destroy (&_tmp3_);\r
687                                                         }\r
688                                                         (*freq).occurances[pass] = GPOINTER_TO_UINT (g_hash_table_lookup (ht, addr));\r
689                                                         g_hash_table_replace (addrfreq, g_strdup (addr), _address_matcher_mailaddress_freq_dup0 (freq));\r
690                                                         _address_matcher_mailaddress_freq_free0 (freq);\r
691                                                 }\r
692                                         }\r
693                                         _g_list_free0 (addr_collection);\r
694                                 }\r
695                                 notmuch_messages_destroy (msgs);\r
696                                 pass = pass + ((guint) 1);\r
697                                 _0 (msgs);\r
698                                 _g_hash_table_unref0 (ht);\r
699                         }\r
700                 }\r
701         }\r
702         addrs = g_hash_table_get_values (addrfreq);\r
703         addrs = g_list_sort (addrs, (GCompareFunc) address_matcher_sort_by_freq);\r
704         {\r
705                 GList* addr_collection;\r
706                 GList* addr_it;\r
707                 addr_collection = addrs;\r
708                 for (addr_it = addr_collection; addr_it != NULL; addr_it = addr_it->next) {\r
709                         AddressMatcherMailAddress_freq* addr;\r
710                         addr = _address_matcher_mailaddress_freq_dup0 ((AddressMatcherMailAddress_freq*) addr_it->data);\r
711                         {\r
712                                 GHashTable* freqs;\r
713                                 freqs = _g_hash_table_ref0 ((GHashTable*) g_hash_table_lookup (addr2realname, (*addr).address));\r
714                                 _vala_array_add1 (&return_value, &return_value_length1, &_return_value_size_, address_matcher_frequent_fullname (self, freqs));\r
715                                 _address_matcher_mailaddress_freq_free0 (addr);\r
716                                 _g_hash_table_unref0 (freqs);\r
717                         }\r
718                 }\r
719         }\r
720         result = (_tmp6_ = return_value, *result_length1 = return_value_length1, _tmp6_);\r
721         _g_hash_table_unref0 (addrfreq);\r
722         _g_hash_table_unref0 (addr2realname);\r
723         __g_list_free_address_matcher_mailaddress_freq_free0 (addrs);\r
724         return result;\r
725         return_value = (_vala_array_free (return_value, return_value_length1, (GDestroyNotify) g_free), NULL);\r
726         _g_hash_table_unref0 (addrfreq);\r
727         _g_hash_table_unref0 (addr2realname);\r
728         __g_list_free_address_matcher_mailaddress_freq_free0 (addrs);\r
729 }\r
730 \r
731 \r
732 static void _vala_array_add2 (notmuch_query_t*** array, int* length, int* size, notmuch_query_t* value) {\r
733         if ((*length) == (*size)) {\r
734                 *size = (*size) ? (2 * (*size)) : 4;\r
735                 *array = g_renew (notmuch_query_t*, *array, *size);\r
736         }\r
737         (*array)[(*length)++] = value;\r
738 }\r
739 \r
740 \r
741 static void _vala_array_add3 (notmuch_query_t*** array, int* length, int* size, notmuch_query_t* value) {\r
742         if ((*length) == (*size)) {\r
743                 *size = (*size) ? (2 * (*size)) : 4;\r
744                 *array = g_renew (notmuch_query_t*, *array, *size);\r
745         }\r
746         (*array)[(*length)++] = value;\r
747 }\r
748 \r
749 \r
750 static void _vala_array_add4 (notmuch_query_t*** array, int* length, int* size, notmuch_query_t* value) {\r
751         if ((*length) == (*size)) {\r
752                 *size = (*size) ? (2 * (*size)) : 4;\r
753                 *array = g_renew (notmuch_query_t*, *array, *size);\r
754         }\r
755         (*array)[(*length)++] = value;\r
756 }\r
757 \r
758 \r
759 void address_matcher_run (AddressMatcher* self, const char* name) {\r
760         notmuch_query_t** _tmp1_;\r
761         gint _queries_size_;\r
762         gint queries_length1;\r
763         notmuch_query_t** _tmp0_ = NULL;\r
764         notmuch_query_t** queries;\r
765         notmuch_database_t* _tmp2_;\r
766         char* _tmp3_;\r
767         GString* _tmp4_;\r
768         GString* querystr;\r
769         GString* _tmp7_;\r
770         char** _tmp15_;\r
771         gint __result__size_;\r
772         gint _result__length1;\r
773         gint _tmp14_;\r
774         char** _result_;\r
775         g_return_if_fail (self != NULL);\r
776         queries = (_tmp1_ = (_tmp0_ = g_new0 (notmuch_query_t*, 0), _tmp0_), queries_length1 = 0, _queries_size_ = queries_length1, _tmp1_);\r
777         self->priv->db = (_tmp2_ = notmuch_database_open (self->priv->user_db_path, NOTMUCH_DATABASE_MODE_READ_ONLY), _notmuch_database_close0 (self->priv->db), _tmp2_);\r
778         querystr = (_tmp4_ = g_string_new (_tmp3_ = g_strconcat ("tag:", self->priv->user_addrbook_tag, NULL)), _g_free0 (_tmp3_), _tmp4_);\r
779         if (name != NULL) {\r
780                 char* _tmp6_;\r
781                 char* _tmp5_;\r
782                 g_string_append (querystr, _tmp6_ = g_strconcat (_tmp5_ = g_strconcat (" and from:", name, NULL), "*", NULL));\r
783                 _g_free0 (_tmp6_);\r
784                 _g_free0 (_tmp5_);\r
785         } else {\r
786                 name = "";\r
787         }\r
788         _vala_array_add2 (&queries, &queries_length1, &_queries_size_, notmuch_query_create (self->priv->db, querystr->str));\r
789         querystr = (_tmp7_ = g_string_new (""), _g_string_free0 (querystr), _tmp7_);\r
790         if (name != NULL) {\r
791                 char* _tmp9_;\r
792                 char* _tmp8_;\r
793                 g_string_append (querystr, _tmp9_ = g_strconcat (_tmp8_ = g_strconcat ("to:", name, NULL), "*", NULL));\r
794                 _g_free0 (_tmp9_);\r
795                 _g_free0 (_tmp8_);\r
796         }\r
797         if (self->priv->user_primary_email != NULL) {\r
798                 char* _tmp10_;\r
799                 g_string_append (querystr, _tmp10_ = g_strconcat (" from:", self->priv->user_primary_email, NULL));\r
800                 _g_free0 (_tmp10_);\r
801         }\r
802         _vala_array_add3 (&queries, &queries_length1, &_queries_size_, notmuch_query_create (self->priv->db, querystr->str));\r
803         if ((notmuch_query_count_messages (queries[0]) + notmuch_query_count_messages (queries[1])) < 10) {\r
804                 GString* _tmp11_;\r
805                 querystr = (_tmp11_ = g_string_new (""), _g_string_free0 (querystr), _tmp11_);\r
806                 if (name != NULL) {\r
807                         char* _tmp13_;\r
808                         char* _tmp12_;\r
809                         g_string_append (querystr, _tmp13_ = g_strconcat (_tmp12_ = g_strconcat ("from:", name, NULL), "*", NULL));\r
810                         _g_free0 (_tmp13_);\r
811                         _g_free0 (_tmp12_);\r
812                 }\r
813                 _vala_array_add4 (&queries, &queries_length1, &_queries_size_, notmuch_query_create (self->priv->db, querystr->str));\r
814         }\r
815         _result_ = (_tmp15_ = address_matcher_search_address_passes (self, queries, queries_length1, name, &_tmp14_), _result__length1 = _tmp14_, __result__size_ = _result__length1, _tmp15_);\r
816         {\r
817                 char** name_collection;\r
818                 int name_collection_length1;\r
819                 int name_it;\r
820                 name_collection = _result_;\r
821                 name_collection_length1 = _result__length1;\r
822                 for (name_it = 0; name_it < _result__length1; name_it = name_it + 1) {\r
823                         char* name;\r
824                         name = g_strdup (name_collection[name_it]);\r
825                         {\r
826                                 fprintf (stdout, "%s\n", name);\r
827                                 _g_free0 (name);\r
828                         }\r
829                 }\r
830         }\r
831         queries = (g_free (queries), NULL);\r
832         _g_string_free0 (querystr);\r
833         _result_ = (_vala_array_free (_result_, _result__length1, (GDestroyNotify) g_free), NULL);\r
834 }\r
835 \r
836 \r
837 static guint* _vala_array_dup1 (guint* self, int length) {\r
838         return g_memdup (self, length * sizeof (guint));\r
839 }\r
840 \r
841 \r
842 static void address_matcher_mailaddress_freq_copy (const AddressMatcherMailAddress_freq* self, AddressMatcherMailAddress_freq* dest) {\r
843         guint* _tmp0_;\r
844         dest->address = g_strdup (self->address);\r
845         dest->occurances = (_tmp0_ = self->occurances, (_tmp0_ == NULL) ? ((gpointer) _tmp0_) : _vala_array_dup1 (_tmp0_, (*self).occurances_length1));\r
846         dest->occurances_length1 = self->occurances_length1;\r
847 }\r
848 \r
849 \r
850 static void address_matcher_mailaddress_freq_destroy (AddressMatcherMailAddress_freq* self) {\r
851         _g_free0 (self->address);\r
852         self->occurances = (g_free (self->occurances), NULL);\r
853 }\r
854 \r
855 \r
856 static AddressMatcherMailAddress_freq* address_matcher_mailaddress_freq_dup (const AddressMatcherMailAddress_freq* self) {\r
857         AddressMatcherMailAddress_freq* dup;\r
858         dup = g_new0 (AddressMatcherMailAddress_freq, 1);\r
859         address_matcher_mailaddress_freq_copy (self, dup);\r
860         return dup;\r
861 }\r
862 \r
863 \r
864 static void address_matcher_mailaddress_freq_free (AddressMatcherMailAddress_freq* self) {\r
865         address_matcher_mailaddress_freq_destroy (self);\r
866         g_free (self);\r
867 }\r
868 \r
869 \r
870 static GType address_matcher_mailaddress_freq_get_type (void) {\r
871         static volatile gsize address_matcher_mailaddress_freq_type_id__volatile = 0;\r
872         if (g_once_init_enter (&address_matcher_mailaddress_freq_type_id__volatile)) {\r
873                 GType address_matcher_mailaddress_freq_type_id;\r
874                 address_matcher_mailaddress_freq_type_id = g_boxed_type_register_static ("AddressMatcherMailAddress_freq", (GBoxedCopyFunc) address_matcher_mailaddress_freq_dup, (GBoxedFreeFunc) address_matcher_mailaddress_freq_free);\r
875                 g_once_init_leave (&address_matcher_mailaddress_freq_type_id__volatile, address_matcher_mailaddress_freq_type_id);\r
876         }\r
877         return address_matcher_mailaddress_freq_type_id__volatile;\r
878 }\r
879 \r
880 \r
881 static void value_address_matcher_init (GValue* value) {\r
882         value->data[0].v_pointer = NULL;\r
883 }\r
884 \r
885 \r
886 static void value_address_matcher_free_value (GValue* value) {\r
887         if (value->data[0].v_pointer) {\r
888                 address_matcher_unref (value->data[0].v_pointer);\r
889         }\r
890 }\r
891 \r
892 \r
893 static void value_address_matcher_copy_value (const GValue* src_value, GValue* dest_value) {\r
894         if (src_value->data[0].v_pointer) {\r
895                 dest_value->data[0].v_pointer = address_matcher_ref (src_value->data[0].v_pointer);\r
896         } else {\r
897                 dest_value->data[0].v_pointer = NULL;\r
898         }\r
899 }\r
900 \r
901 \r
902 static gpointer value_address_matcher_peek_pointer (const GValue* value) {\r
903         return value->data[0].v_pointer;\r
904 }\r
905 \r
906 \r
907 static gchar* value_address_matcher_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {\r
908         if (collect_values[0].v_pointer) {\r
909                 AddressMatcher* object;\r
910                 object = collect_values[0].v_pointer;\r
911                 if (object->parent_instance.g_class == NULL) {\r
912                         return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);\r
913                 } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {\r
914                         return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);\r
915                 }\r
916                 value->data[0].v_pointer = address_matcher_ref (object);\r
917         } else {\r
918                 value->data[0].v_pointer = NULL;\r
919         }\r
920         return NULL;\r
921 }\r
922 \r
923 \r
924 static gchar* value_address_matcher_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {\r
925         AddressMatcher** object_p;\r
926         object_p = collect_values[0].v_pointer;\r
927         if (!object_p) {\r
928                 return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));\r
929         }\r
930         if (!value->data[0].v_pointer) {\r
931                 *object_p = NULL;\r
932         } else if (collect_flags && G_VALUE_NOCOPY_CONTENTS) {\r
933                 *object_p = value->data[0].v_pointer;\r
934         } else {\r
935                 *object_p = address_matcher_ref (value->data[0].v_pointer);\r
936         }\r
937         return NULL;\r
938 }\r
939 \r
940 \r
941 GParamSpec* param_spec_address_matcher (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {\r
942         ParamSpecAddressMatcher* spec;\r
943         g_return_val_if_fail (g_type_is_a (object_type, TYPE_ADDRESS_MATCHER), NULL);\r
944         spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);\r
945         G_PARAM_SPEC (spec)->value_type = object_type;\r
946         return G_PARAM_SPEC (spec);\r
947 }\r
948 \r
949 \r
950 gpointer value_get_address_matcher (const GValue* value) {\r
951         g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_ADDRESS_MATCHER), NULL);\r
952         return value->data[0].v_pointer;\r
953 }\r
954 \r
955 \r
956 void value_set_address_matcher (GValue* value, gpointer v_object) {\r
957         AddressMatcher* old;\r
958         g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_ADDRESS_MATCHER));\r
959         old = value->data[0].v_pointer;\r
960         if (v_object) {\r
961                 g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_ADDRESS_MATCHER));\r
962                 g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));\r
963                 value->data[0].v_pointer = v_object;\r
964                 address_matcher_ref (value->data[0].v_pointer);\r
965         } else {\r
966                 value->data[0].v_pointer = NULL;\r
967         }\r
968         if (old) {\r
969                 address_matcher_unref (old);\r
970         }\r
971 }\r
972 \r
973 \r
974 void value_take_address_matcher (GValue* value, gpointer v_object) {\r
975         AddressMatcher* old;\r
976         g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_ADDRESS_MATCHER));\r
977         old = value->data[0].v_pointer;\r
978         if (v_object) {\r
979                 g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_ADDRESS_MATCHER));\r
980                 g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));\r
981                 value->data[0].v_pointer = v_object;\r
982         } else {\r
983                 value->data[0].v_pointer = NULL;\r
984         }\r
985         if (old) {\r
986                 address_matcher_unref (old);\r
987         }\r
988 }\r
989 \r
990 \r
991 static void address_matcher_class_init (AddressMatcherClass * klass) {\r
992         address_matcher_parent_class = g_type_class_peek_parent (klass);\r
993         ADDRESS_MATCHER_CLASS (klass)->finalize = address_matcher_finalize;\r
994         g_type_class_add_private (klass, sizeof (AddressMatcherPrivate));\r
995 }\r
996 \r
997 \r
998 static void address_matcher_instance_init (AddressMatcher * self) {\r
999         self->priv = ADDRESS_MATCHER_GET_PRIVATE (self);\r
1000         self->priv->user_db_path = NULL;\r
1001         self->priv->user_primary_email = NULL;\r
1002         self->priv->user_addrbook_tag = NULL;\r
1003         self->ref_count = 1;\r
1004 }\r
1005 \r
1006 \r
1007 static void address_matcher_finalize (AddressMatcher* obj) {\r
1008         AddressMatcher * self;\r
1009         self = ADDRESS_MATCHER (obj);\r
1010         _notmuch_database_close0 (self->priv->db);\r
1011         _g_free0 (self->priv->user_db_path);\r
1012         _g_free0 (self->priv->user_primary_email);\r
1013         _g_free0 (self->priv->user_addrbook_tag);\r
1014 }\r
1015 \r
1016 \r
1017 GType address_matcher_get_type (void) {\r
1018         static volatile gsize address_matcher_type_id__volatile = 0;\r
1019         if (g_once_init_enter (&address_matcher_type_id__volatile)) {\r
1020                 static const GTypeValueTable g_define_type_value_table = { value_address_matcher_init, value_address_matcher_free_value, value_address_matcher_copy_value, value_address_matcher_peek_pointer, "p", value_address_matcher_collect_value, "p", value_address_matcher_lcopy_value };\r
1021                 static const GTypeInfo g_define_type_info = { sizeof (AddressMatcherClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) address_matcher_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (AddressMatcher), 0, (GInstanceInitFunc) address_matcher_instance_init, &g_define_type_value_table };\r
1022                 static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };\r
1023                 GType address_matcher_type_id;\r
1024                 address_matcher_type_id = g_type_register_fundamental (g_type_fundamental_next (), "AddressMatcher", &g_define_type_info, &g_define_type_fundamental_info, 0);\r
1025                 g_once_init_leave (&address_matcher_type_id__volatile, address_matcher_type_id);\r
1026         }\r
1027         return address_matcher_type_id__volatile;\r
1028 }\r
1029 \r
1030 \r
1031 gpointer address_matcher_ref (gpointer instance) {\r
1032         AddressMatcher* self;\r
1033         self = instance;\r
1034         g_atomic_int_inc (&self->ref_count);\r
1035         return instance;\r
1036 }\r
1037 \r
1038 \r
1039 void address_matcher_unref (gpointer instance) {\r
1040         AddressMatcher* self;\r
1041         self = instance;\r
1042         if (g_atomic_int_dec_and_test (&self->ref_count)) {\r
1043                 ADDRESS_MATCHER_GET_CLASS (self)->finalize (self);\r
1044                 g_type_free_instance ((GTypeInstance *) self);\r
1045         }\r
1046 }\r
1047 \r
1048 \r
1049 gint _vala_main (char** args, int args_length1) {\r
1050         gint result = 0;\r
1051         AddressMatcher* app;\r
1052         app = address_matcher_new ();\r
1053         address_matcher_run (app, args[1]);\r
1054         result = 0;\r
1055         _address_matcher_unref0 (app);\r
1056         return result;\r
1057 }\r
1058 \r
1059 \r
1060 int main (int argc, char ** argv) {\r
1061         g_type_init ();\r
1062         return _vala_main (argv, argc);\r
1063 }\r
1064 \r
1065 \r
1066 static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) {\r
1067         if ((array != NULL) && (destroy_func != NULL)) {\r
1068                 int i;\r
1069                 for (i = 0; i < array_length; i = i + 1) {\r
1070                         if (((gpointer*) array)[i] != NULL) {\r
1071                                 destroy_func (((gpointer*) array)[i]);\r
1072                         }\r
1073                 }\r
1074         }\r
1075 }\r
1076 \r
1077 \r
1078 static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {\r
1079         _vala_array_destroy (array, array_length, destroy_func);\r
1080         g_free (array);\r
1081 }\r
1082 \r
1083 \r
1084 \r
1085 \r
1086 \r
1087 --=-=-=\r
1088 \r
1089 \r
1090 Sebastian\r
1091 \r
1092 --=-=-=--\r