Initial ruby bindings
[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.message_id => String
25  *
26  * Get the message ID of 'message'.
27  */
28 VALUE
29 notmuch_rb_message_get_message_id(VALUE self)
30 {
31     const char *msgid;
32     notmuch_rb_message_t *message;
33
34     Data_Get_Struct(self, notmuch_rb_message_t, message);
35
36     msgid = notmuch_message_get_message_id(message->nm_message);
37     return msgid ? rb_str_new2(msgid) : Qnil;
38 }
39
40 /*
41  * call-seq: MESSAGE.thread_id => String
42  *
43  * Get the thread ID of 'message'.
44  */
45 VALUE
46 notmuch_rb_message_get_thread_id(VALUE self)
47 {
48     const char *tid;
49     notmuch_rb_message_t *message;
50
51     Data_Get_Struct(self, notmuch_rb_message_t, message);
52
53     tid = notmuch_message_get_thread_id(message->nm_message);
54     return tid ? rb_str_new2(tid) : Qnil;
55 }
56
57 /*
58  * call-seq: MESSAGE.replies => MESSAGES
59  *
60  * Get a Notmuch::Messages enumerable for all of the replies to 'message'.
61  */
62 VALUE
63 notmuch_rb_message_get_replies(VALUE self)
64 {
65     notmuch_rb_messages_t *messages;
66     notmuch_rb_message_t *message;
67     VALUE messagesv;
68
69     Data_Get_Struct(self, notmuch_rb_message_t, message);
70
71     messagesv = Data_Make_Struct(notmuch_rb_cMessages, notmuch_rb_messages_t,
72             notmuch_rb_messages_mark, notmuch_rb_messages_free, messages);
73     messages->nm_messages = notmuch_message_get_replies(message->nm_message);
74     messages->parent = self;
75
76     return messages->nm_messages ? messagesv : Qnil;
77 }
78
79 /*
80  * call-seq: MESSAGE.filename => String
81  *
82  * Get a filename for the email corresponding to 'message'
83  */
84 VALUE
85 notmuch_rb_message_get_filename(VALUE self)
86 {
87     const char *fname;
88     notmuch_rb_message_t *message;
89
90     Data_Get_Struct(self, notmuch_rb_message_t, message);
91
92     fname = notmuch_message_get_filename(message->nm_message);
93     return fname ? rb_str_new2(fname) : Qnil;
94 }
95
96 /*
97  * call-seq: MESSAGE.get_flag(flag) => true or false
98  *
99  * Get a value of a flag for the email corresponding to 'message'
100  */
101 VALUE
102 notmuch_rb_message_get_flag(VALUE self, VALUE flagv)
103 {
104     notmuch_rb_message_t *message;
105
106     Data_Get_Struct(self, notmuch_rb_message_t, message);
107
108     if (!FIXNUM_P(flagv))
109         rb_raise(rb_eTypeError, "Flag not a Fixnum");
110
111     return notmuch_message_get_flag(message->nm_message, FIX2INT(flagv)) ? Qtrue : Qfalse;
112 }
113
114 /*
115  * call-seq: MESSAGE.set_flag(flag, value) => nil
116  *
117  * Set a value of a flag for the email corresponding to 'message'
118  */
119 VALUE
120 notmuch_rb_message_set_flag(VALUE self, VALUE flagv, VALUE valuev)
121 {
122     notmuch_rb_message_t *message;
123
124     Data_Get_Struct(self, notmuch_rb_message_t, message);
125
126     if (!FIXNUM_P(flagv))
127         rb_raise(rb_eTypeError, "Flag not a Fixnum");
128
129     notmuch_message_set_flag(message->nm_message, FIX2INT(flagv), RTEST(valuev));
130     return Qnil;
131 }
132
133 /*
134  * call-seq: MESSAGE.date => Fixnum
135  *
136  * Get the date of 'message'
137  */
138 VALUE
139 notmuch_rb_message_get_date(VALUE self)
140 {
141     notmuch_rb_message_t *message;
142
143     Data_Get_Struct(self, notmuch_rb_message_t, message);
144
145     return UINT2NUM(notmuch_message_get_date(message->nm_message));
146 }
147
148 /*
149  * call-seq: MESSAGE.header(name) => String
150  *
151  * Get the value of the specified header from 'message'
152  */
153 VALUE
154 notmuch_rb_message_get_header(VALUE self, VALUE headerv)
155 {
156     const char *header, *value;
157     notmuch_rb_message_t *message;
158
159     Data_Get_Struct(self, notmuch_rb_message_t, message);
160
161 #if !defined(RSTRING_PTR)
162 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
163 #endif /* !defined(RSTRING_PTR) */
164
165     SafeStringValue(headerv);
166     header = RSTRING_PTR(headerv);
167
168     value = notmuch_message_get_header(message->nm_message, header);
169     if (!value)
170         rb_raise(notmuch_rb_eMemoryError, "out of memory");
171
172     return rb_str_new2(value);
173 }
174
175 /*
176  * call-seq: MESSAGE.tags => TAGS
177  *
178  * Get a Notmuch::Tags enumerable for all of the tags of 'message'.
179  */
180 VALUE
181 notmuch_rb_message_get_tags(VALUE self)
182 {
183     notmuch_rb_message_t *message;
184     notmuch_rb_tags_t *tags;
185     VALUE tagsv;
186
187     Data_Get_Struct(self, notmuch_rb_message_t, message);
188
189     tagsv = Data_Make_Struct(notmuch_rb_cTags, notmuch_rb_tags_t,
190             notmuch_rb_tags_mark, notmuch_rb_tags_free, tags);
191     tags->nm_tags = notmuch_message_get_tags(message->nm_message);
192     tags->parent = self;
193     if (!tags->nm_tags)
194         rb_raise(notmuch_rb_eMemoryError, "out of memory");
195
196     return tagsv;
197 }
198
199 /*
200  * call-seq: MESSAGE.add_tag(tag) => true
201  *
202  * Add a tag to the 'message'
203  */
204 VALUE
205 notmuch_rb_message_add_tag(VALUE self, VALUE tagv)
206 {
207     const char *tag;
208     notmuch_status_t ret;
209     notmuch_rb_message_t *message;
210
211     Data_Get_Struct(self, notmuch_rb_message_t, message);
212
213 #if !defined(RSTRING_PTR)
214 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
215 #endif /* !defined(RSTRING_PTR) */
216
217     SafeStringValue(tagv);
218     tag = RSTRING_PTR(tagv);
219
220     ret = notmuch_message_add_tag(message->nm_message, tag);
221     notmuch_rb_status_raise(ret);
222     return Qtrue;
223 }
224
225 /*
226  * call-seq: MESSAGE.remove_tag(tag) => true
227  *
228  * Remove a tag from the 'message'
229  */
230 VALUE
231 notmuch_rb_message_remove_tag(VALUE self, VALUE tagv)
232 {
233     const char *tag;
234     notmuch_status_t ret;
235     notmuch_rb_message_t *message;
236
237     Data_Get_Struct(self, notmuch_rb_message_t, message);
238
239 #if !defined(RSTRING_PTR)
240 #define RSTRING_PTR(v) (RSTRING((v))->ptr)
241 #endif /* !defined(RSTRING_PTR) */
242
243     SafeStringValue(tagv);
244     tag = RSTRING_PTR(tagv);
245
246     ret = notmuch_message_remove_tag(message->nm_message, tag);
247     notmuch_rb_status_raise(ret);
248     return Qtrue;
249 }
250
251 /*
252  * call-seq: MESSAGE.remove_all_tags => true
253  *
254  * Remove all tags of the 'message'
255  */
256 VALUE
257 notmuch_rb_message_remove_all_tags(VALUE self)
258 {
259     notmuch_status_t ret;
260     notmuch_rb_message_t *message;
261
262     Data_Get_Struct(self, notmuch_rb_message_t, message);
263
264     ret = notmuch_message_remove_all_tags(message->nm_message);
265     notmuch_rb_status_raise(ret);
266     return Qtrue;
267 }
268
269 /*
270  * call-seq: MESSAGE.freeze => true
271  *
272  * Freeze the 'message'
273  */
274 VALUE
275 notmuch_rb_message_freeze(VALUE self)
276 {
277     notmuch_status_t ret;
278     notmuch_rb_message_t *message;
279
280     Data_Get_Struct(self, notmuch_rb_message_t, message);
281
282     ret = notmuch_message_freeze(message->nm_message);
283     notmuch_rb_status_raise(ret);
284     return Qtrue;
285 }
286
287 /*
288  * call-seq: MESSAGE.thaw => true
289  *
290  * Thaw a 'message'
291  */
292 VALUE
293 notmuch_rb_message_thaw(VALUE self)
294 {
295     notmuch_status_t ret;
296     notmuch_rb_message_t *message;
297
298     Data_Get_Struct(self, notmuch_rb_message_t, message);
299
300     ret = notmuch_message_thaw(message->nm_message);
301     notmuch_rb_status_raise(ret);
302     return Qtrue;
303 }