lib&cli: use g_object_new instead of g_object_newv
[notmuch] / gmime-filter-reply.c
1 /*
2  * Copyright © 2009 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "gmime-filter-reply.h"
20
21 /**
22  * SECTION: gmime-filter-reply
23  * @title: GMimeFilterReply
24  * @short_description: Add/remove reply markers
25  *
26  * A #GMimeFilter for adding or removing reply markers
27  **/
28
29
30 static void g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass);
31 static void g_mime_filter_reply_init (GMimeFilterReply *filter, GMimeFilterReplyClass *klass);
32 static void g_mime_filter_reply_finalize (GObject *object);
33
34 static GMimeFilter *filter_copy (GMimeFilter *filter);
35 static void filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
36                            char **out, size_t *outlen, size_t *outprespace);
37 static void filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
38                              char **out, size_t *outlen, size_t *outprespace);
39 static void filter_reset (GMimeFilter *filter);
40
41
42 static GMimeFilterClass *parent_class = NULL;
43
44 GType
45 g_mime_filter_reply_get_type (void)
46 {
47         static GType type = 0;
48
49         if (!type) {
50                 static const GTypeInfo info = {
51                         sizeof (GMimeFilterReplyClass),
52                         NULL, /* base_class_init */
53                         NULL, /* base_class_finalize */
54                         (GClassInitFunc) g_mime_filter_reply_class_init,
55                         NULL, /* class_finalize */
56                         NULL, /* class_data */
57                         sizeof (GMimeFilterReply),
58                         0,    /* n_preallocs */
59                         (GInstanceInitFunc) g_mime_filter_reply_init,
60                         NULL    /* value_table */
61                 };
62
63                 type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterReply", &info, (GTypeFlags) 0);
64         }
65
66         return type;
67 }
68
69
70 static void
71 g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass)
72 {
73         GObjectClass *object_class = G_OBJECT_CLASS (klass);
74         GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass);
75
76         parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER);
77
78         object_class->finalize = g_mime_filter_reply_finalize;
79
80         filter_class->copy = filter_copy;
81         filter_class->filter = filter_filter;
82         filter_class->complete = filter_complete;
83         filter_class->reset = filter_reset;
84 }
85
86 static void
87 g_mime_filter_reply_init (GMimeFilterReply *filter, GMimeFilterReplyClass *klass)
88 {
89         (void) klass;
90         filter->saw_nl = TRUE;
91         filter->saw_angle = FALSE;
92 }
93
94 static void
95 g_mime_filter_reply_finalize (GObject *object)
96 {
97         G_OBJECT_CLASS (parent_class)->finalize (object);
98 }
99
100
101 static GMimeFilter *
102 filter_copy (GMimeFilter *filter)
103 {
104         GMimeFilterReply *reply = (GMimeFilterReply *) filter;
105
106         return g_mime_filter_reply_new (reply->encode);
107 }
108
109 static void
110 filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
111                char **outbuf, size_t *outlen, size_t *outprespace)
112 {
113         GMimeFilterReply *reply = (GMimeFilterReply *) filter;
114         register const char *inptr = inbuf;
115         const char *inend = inbuf + inlen;
116         char *outptr;
117
118         (void) prespace;
119         if (reply->encode) {
120                 g_mime_filter_set_size (filter, 3 * inlen, FALSE);
121
122                 outptr = filter->outbuf;
123                 while (inptr < inend) {
124                         if (reply->saw_nl) {
125                                 *outptr++ = '>';
126                                 *outptr++ = ' ';
127                                 reply->saw_nl = FALSE;
128                         }
129                         if (*inptr == '\n')
130                                 reply->saw_nl = TRUE;
131                         else
132                                 reply->saw_nl = FALSE;
133                         if (*inptr != '\r')
134                                 *outptr++ = *inptr;
135                         inptr++;
136                 }
137         } else {
138                 g_mime_filter_set_size (filter, inlen + 1, FALSE);
139
140                 outptr = filter->outbuf;
141                 while (inptr < inend) {
142                         if (reply->saw_nl) {
143                                 if (*inptr == '>')
144                                         reply->saw_angle = TRUE;
145                                 else
146                                         *outptr++ = *inptr;
147                                 reply->saw_nl = FALSE;
148                         } else if (reply->saw_angle) {
149                                 if (*inptr == ' ')
150                                         ;
151                                 else
152                                         *outptr++ = *inptr;
153                                 reply->saw_angle = FALSE;
154                         } else if (*inptr != '\r') {
155                                 if (*inptr == '\n')
156                                         reply->saw_nl = TRUE;
157                                 *outptr++ = *inptr;
158                         }
159
160                         inptr++;
161                 }
162         }
163
164         *outlen = outptr - filter->outbuf;
165         *outprespace = filter->outpre;
166         *outbuf = filter->outbuf;
167 }
168
169 static void
170 filter_complete (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
171                  char **outbuf, size_t *outlen, size_t *outprespace)
172 {
173         if (inbuf && inlen)
174                 filter_filter (filter, inbuf, inlen, prespace, outbuf, outlen, outprespace);
175 }
176
177 static void
178 filter_reset (GMimeFilter *filter)
179 {
180         GMimeFilterReply *reply = (GMimeFilterReply *) filter;
181
182         reply->saw_nl = TRUE;
183         reply->saw_angle = FALSE;
184 }
185
186
187 /**
188  * g_mime_filter_reply_new:
189  * @encode: %TRUE if the filter should encode or %FALSE otherwise
190  * @dots: encode/decode dots (as for SMTP)
191  *
192  * Creates a new #GMimeFilterReply filter.
193  *
194  * If @encode is %TRUE, then all lines will be prefixed by "> ",
195  * otherwise any lines starting with "> " will have that removed
196  *
197  * Returns: a new #GMimeFilterReply filter.
198  **/
199 GMimeFilter *
200 g_mime_filter_reply_new (gboolean encode)
201 {
202         GMimeFilterReply *new_reply;
203
204         new_reply = (GMimeFilterReply *) g_object_new (GMIME_TYPE_FILTER_REPLY, NULL);
205         new_reply->encode = encode;
206
207         return (GMimeFilter *) new_reply;
208 }
209