ruby: Add wrappers for maildir sync. interface
[notmuch] / bindings / ruby / message.c
1 /* The Ruby interface to the notmuch mail library
2  *
3  * Copyright © 2010 Ali Polatel
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see http://www.gnu.org/licenses/ .
17  *
18  * Author: Ali Polatel <alip@exherbo.org>
19  */
20
21 #include "defs.h"
22
23 /*
24  * call-seq: MESSAGE.destroy => nil
25  *
26  * Destroys the message, freeing all resources allocated for it.
27  */
28 VALUE
29 notmuch_rb_message_destroy(VALUE self)
30 {
31     notmuch_message_t *message;
32
33     Data_Get_Notmuch_Message(self, message);
34
35     notmuch_message_destroy(message);
36     DATA_PTR(self) = NULL;
37
38     return Qnil;
39 }
40
41 /*
42  * call-seq: MESSAGE.message_id => String
43  *
44  * Get the message ID of 'message'.
45  */
46 VALUE
47 notmuch_rb_message_get_message_id(VALUE self)
48 {
49     const char *msgid;
50     notmuch_message_t *message;
51
52     Data_Get_Notmuch_Message(self, message);
53
54     msgid = notmuch_message_get_message_id(message);
55
56     return rb_str_new2(msgid);
57 }
58
59 /*
60  * call-seq: MESSAGE.thread_id => String
61  *
62  * Get the thread ID of 'message'.
63  */
64 VALUE
65 notmuch_rb_message_get_thread_id(VALUE self)
66 {
67     const char *tid;
68     notmuch_message_t *message;
69
70     Data_Get_Notmuch_Message(self, message);
71
72     tid = notmuch_message_get_thread_id(message);
73
74     return rb_str_new2(tid);
75 }
76
77 /*
78  * call-seq: MESSAGE.replies => MESSAGES
79  *
80  * Get a Notmuch::Messages enumerable for all of the replies to 'message'.
81  */
82 VALUE
83 notmuch_rb_message_get_replies(VALUE self)
84 {
85     notmuch_messages_t *messages;
86     notmuch_message_t *message;
87
88     Data_Get_Notmuch_Message(self, message);
89
90     messages = notmuch_message_get_replies(message);
91
92     return Data_Wrap_Struct(notmuch_rb_cMessages, NULL, NULL, messages);
93 }
94
95 /*
96  * call-seq: MESSAGE.filename => String
97  *
98  * Get a filename for the email corresponding to 'message'
99  */
100 VALUE
101 notmuch_rb_message_get_filename(VALUE self)
102 {
103     const char *fname;
104     notmuch_message_t *message;
105
106     Data_Get_Notmuch_Message(self, message);
107
108     fname = notmuch_message_get_filename(message);
109
110     return rb_str_new2(fname);
111 }
112
113 /*
114  * call-seq: MESSAGE.get_flag(flag) => true or false
115  *
116  * Get a value of a flag for the email corresponding to 'message'
117  */
118 VALUE
119 notmuch_rb_message_get_flag(VALUE self, VALUE flagv)
120 {
121     notmuch_message_t *message;
122
123     Data_Get_Notmuch_Message(self, message);
124
125     if (!FIXNUM_P(flagv))
126         rb_raise(rb_eTypeError, "Flag not a Fixnum");
127
128     return notmuch_message_get_flag(message, FIX2INT(flagv)) ? Qtrue : Qfalse;
129 }
130
131 /*
132  * call-seq: MESSAGE.set_flag(flag, value) => nil
133  *
134  * Set a value of a flag for the email corresponding to 'message'
135  */
136 VALUE
137 notmuch_rb_message_set_flag(VALUE self, VALUE flagv, VALUE valuev)
138 {
139     notmuch_message_t *message;
140
141     Data_Get_Notmuch_Message(self, message);
142
143     if (!FIXNUM_P(flagv))
144         rb_raise(rb_eTypeError, "Flag not a Fixnum");
145
146     notmuch_message_set_flag(message, FIX2INT(flagv), RTEST(valuev));
147
148     return Qnil;
149 }
150
151 /*
152  * call-seq: MESSAGE.date => Fixnum
153  *
154  * Get the date of 'message'
155  */
156 VALUE
157 notmuch_rb_message_get_date(VALUE self)
158 {
159     notmuch_message_t *message;
160
161     Data_Get_Notmuch_Message(self, message);
162
163     return UINT2NUM(notmuch_message_get_date(message));
164 }
165
166 /*
167  * call-seq: MESSAGE.header(name) => String
168  *
169  * Get the value of the specified header from 'message'
170  */
171 VALUE
172 notmuch_rb_message_get_header(VALUE self, VALUE headerv)
173 {
174     const char *header, *value;
175     notmuch_message_t *message;
176
177     Data_Get_Notmuch_Message(self, message);
178
179 #if !defined(RSTRING_PTR)
180 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
181 #endif /* !defined(RSTRING_PTR) */
182
183     SafeStringValue(headerv);
184     header = RSTRING_PTR(headerv);
185
186     value = notmuch_message_get_header(message, header);
187     if (!value)
188         rb_raise(notmuch_rb_eMemoryError, "Out of memory");
189
190     return rb_str_new2(value);
191 }
192
193 /*
194  * call-seq: MESSAGE.tags => TAGS
195  *
196  * Get a Notmuch::Tags enumerable for all of the tags of 'message'.
197  */
198 VALUE
199 notmuch_rb_message_get_tags(VALUE self)
200 {
201     notmuch_message_t *message;
202     notmuch_tags_t *tags;
203
204     Data_Get_Notmuch_Message(self, message);
205
206     tags = notmuch_message_get_tags(message);
207     if (!tags)
208         rb_raise(notmuch_rb_eMemoryError, "Out of memory");
209
210     return Data_Wrap_Struct(notmuch_rb_cTags, NULL, NULL, tags);
211 }
212
213 /*
214  * call-seq: MESSAGE.add_tag(tag) => true
215  *
216  * Add a tag to the 'message'
217  */
218 VALUE
219 notmuch_rb_message_add_tag(VALUE self, VALUE tagv)
220 {
221     const char *tag;
222     notmuch_status_t ret;
223     notmuch_message_t *message;
224
225     Data_Get_Notmuch_Message(self, message);
226
227 #if !defined(RSTRING_PTR)
228 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
229 #endif /* !defined(RSTRING_PTR) */
230
231     SafeStringValue(tagv);
232     tag = RSTRING_PTR(tagv);
233
234     ret = notmuch_message_add_tag(message, tag);
235     notmuch_rb_status_raise(ret);
236
237     return Qtrue;
238 }
239
240 /*
241  * call-seq: MESSAGE.remove_tag(tag) => true
242  *
243  * Remove a tag from the 'message'
244  */
245 VALUE
246 notmuch_rb_message_remove_tag(VALUE self, VALUE tagv)
247 {
248     const char *tag;
249     notmuch_status_t ret;
250     notmuch_message_t *message;
251
252     Data_Get_Notmuch_Message(self, message);
253
254 #if !defined(RSTRING_PTR)
255 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
256 #endif /* !defined(RSTRING_PTR) */
257
258     SafeStringValue(tagv);
259     tag = RSTRING_PTR(tagv);
260
261     ret = notmuch_message_remove_tag(message, tag);
262     notmuch_rb_status_raise(ret);
263
264     return Qtrue;
265 }
266
267 /*
268  * call-seq: MESSAGE.remove_all_tags => true
269  *
270  * Remove all tags of the 'message'
271  */
272 VALUE
273 notmuch_rb_message_remove_all_tags(VALUE self)
274 {
275     notmuch_status_t ret;
276     notmuch_message_t *message;
277
278     Data_Get_Notmuch_Message(self, message);
279
280     ret = notmuch_message_remove_all_tags(message);
281     notmuch_rb_status_raise(ret);
282
283     return Qtrue;
284 }
285
286 /*
287  * call-seq: MESSAGE.maildir_flags_to_tags => true
288  *
289  * Add/remove tags according to maildir flags in the message filename(s)
290  */
291 VALUE
292 notmuch_rb_message_maildir_flags_to_tags(VALUE self)
293 {
294     notmuch_status_t ret;
295     notmuch_message_t *message;
296
297     Data_Get_Notmuch_Message(self, message);
298
299     ret = notmuch_message_maildir_flags_to_tags(message);
300     notmuch_rb_status_raise(ret);
301
302     return Qtrue;
303 }
304
305 /*
306  * call-seq: MESSAGE.tags_to_maildir_flags => true
307  *
308  * Rename message filename(s) to encode tags as maildir flags
309  */
310 VALUE
311 notmuch_rb_message_tags_to_maildir_flags(VALUE self)
312 {
313     notmuch_status_t ret;
314     notmuch_message_t *message;
315
316     Data_Get_Notmuch_Message(self, message);
317
318     ret = notmuch_message_tags_to_maildir_flags(message);
319     notmuch_rb_status_raise(ret);
320
321     return Qtrue;
322 }
323
324 /*
325  * call-seq: MESSAGE.freeze => true
326  *
327  * Freeze the 'message'
328  */
329 VALUE
330 notmuch_rb_message_freeze(VALUE self)
331 {
332     notmuch_status_t ret;
333     notmuch_message_t *message;
334
335     Data_Get_Notmuch_Message(self, message);
336
337     ret = notmuch_message_freeze(message);
338     notmuch_rb_status_raise(ret);
339
340     return Qtrue;
341 }
342
343 /*
344  * call-seq: MESSAGE.thaw => true
345  *
346  * Thaw a 'message'
347  */
348 VALUE
349 notmuch_rb_message_thaw(VALUE self)
350 {
351     notmuch_status_t ret;
352     notmuch_message_t *message;
353
354     Data_Get_Notmuch_Message(self, message);
355
356     ret = notmuch_message_thaw(message);
357     notmuch_rb_status_raise(ret);
358
359     return Qtrue;
360 }