cli: run uncrustify
[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 <stdbool.h>
20
21 #include "gmime-filter-reply.h"
22 #include "notmuch-client.h"
23
24 /**
25  * SECTION: gmime-filter-reply
26  * @title: GMimeFilterReply
27  * @short_description: Add/remove reply markers
28  *
29  * A #GMimeFilter for adding or removing reply markers
30  **/
31
32
33 static void g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass, void *class_data);
34 static void g_mime_filter_reply_init (GMimeFilterReply *filter, GMimeFilterReplyClass *klass);
35 static void g_mime_filter_reply_finalize (GObject *object);
36
37 static GMimeFilter *filter_copy (GMimeFilter *filter);
38 static void filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
39                            char **out, size_t *outlen, size_t *outprespace);
40 static void filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
41                              char **out, size_t *outlen, size_t *outprespace);
42 static void filter_reset (GMimeFilter *filter);
43
44
45 static GMimeFilterClass *parent_class = NULL;
46
47 GType
48 g_mime_filter_reply_get_type (void)
49 {
50     static GType type = 0;
51
52     if (! type) {
53         static const GTypeInfo info = {
54             .class_size = sizeof (GMimeFilterReplyClass),
55             .base_init = NULL,
56             .base_finalize = NULL,
57             .class_init = (GClassInitFunc) g_mime_filter_reply_class_init,
58             .class_finalize = NULL,
59             .class_data = NULL,
60             .instance_size = sizeof (GMimeFilterReply),
61             .n_preallocs = 0,
62             .instance_init = (GInstanceInitFunc) g_mime_filter_reply_init,
63             .value_table = NULL,
64         };
65
66         type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterReply", &info, (GTypeFlags) 0);
67     }
68
69     return type;
70 }
71
72
73 static void
74 g_mime_filter_reply_class_init (GMimeFilterReplyClass *klass, unused (void *class_data))
75 {
76     GObjectClass *object_class = G_OBJECT_CLASS (klass);
77     GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass);
78
79     parent_class = (GMimeFilterClass *) g_type_class_ref (GMIME_TYPE_FILTER);
80
81     object_class->finalize = g_mime_filter_reply_finalize;
82
83     filter_class->copy = filter_copy;
84     filter_class->filter = filter_filter;
85     filter_class->complete = filter_complete;
86     filter_class->reset = filter_reset;
87 }
88
89 static void
90 g_mime_filter_reply_init (GMimeFilterReply *filter, GMimeFilterReplyClass *klass)
91 {
92     (void) klass;
93     filter->saw_nl = true;
94     filter->saw_angle = false;
95 }
96
97 static void
98 g_mime_filter_reply_finalize (GObject *object)
99 {
100     G_OBJECT_CLASS (parent_class)->finalize (object);
101 }
102
103
104 static GMimeFilter *
105 filter_copy (GMimeFilter *filter)
106 {
107     GMimeFilterReply *reply = (GMimeFilterReply *) filter;
108
109     return g_mime_filter_reply_new (reply->encode);
110 }
111
112 static void
113 filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
114                char **outbuf, size_t *outlen, size_t *outprespace)
115 {
116     GMimeFilterReply *reply = (GMimeFilterReply *) filter;
117     const char *inptr = inbuf;
118     const char *inend = inbuf + inlen;
119     char *outptr;
120
121     (void) prespace;
122     if (reply->encode) {
123         g_mime_filter_set_size (filter, 3 * inlen, false);
124
125         outptr = filter->outbuf;
126         while (inptr < inend) {
127             if (reply->saw_nl) {
128                 *outptr++ = '>';
129                 *outptr++ = ' ';
130                 reply->saw_nl = false;
131             }
132             if (*inptr == '\n')
133                 reply->saw_nl = true;
134             else
135                 reply->saw_nl = false;
136             if (*inptr != '\r')
137                 *outptr++ = *inptr;
138             inptr++;
139         }
140     } else {
141         g_mime_filter_set_size (filter, inlen + 1, false);
142
143         outptr = filter->outbuf;
144         while (inptr < inend) {
145             if (reply->saw_nl) {
146                 if (*inptr == '>')
147                     reply->saw_angle = true;
148                 else
149                     *outptr++ = *inptr;
150                 reply->saw_nl = false;
151             } else if (reply->saw_angle) {
152                 if (*inptr == ' ')
153                     ;
154                 else
155                     *outptr++ = *inptr;
156                 reply->saw_angle = false;
157             } else if (*inptr != '\r') {
158                 if (*inptr == '\n')
159                     reply->saw_nl = true;
160                 *outptr++ = *inptr;
161             }
162
163             inptr++;
164         }
165     }
166
167     *outlen = outptr - filter->outbuf;
168     *outprespace = filter->outpre;
169     *outbuf = filter->outbuf;
170 }
171
172 static void
173 filter_complete (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
174                  char **outbuf, size_t *outlen, size_t *outprespace)
175 {
176     if (inbuf && inlen)
177         filter_filter (filter, inbuf, inlen, prespace, outbuf, outlen, outprespace);
178 }
179
180 static void
181 filter_reset (GMimeFilter *filter)
182 {
183     GMimeFilterReply *reply = (GMimeFilterReply *) filter;
184
185     reply->saw_nl = true;
186     reply->saw_angle = false;
187 }
188
189
190 /**
191  * g_mime_filter_reply_new:
192  * @encode: %true if the filter should encode or %false otherwise
193  * @dots: encode/decode dots (as for SMTP)
194  *
195  * Creates a new #GMimeFilterReply filter.
196  *
197  * If @encode is %true, then all lines will be prefixed by "> ",
198  * otherwise any lines starting with "> " will have that removed
199  *
200  * Returns: a new #GMimeFilterReply filter.
201  **/
202 GMimeFilter *
203 g_mime_filter_reply_new (gboolean encode)
204 {
205     GMimeFilterReply *new_reply;
206
207     new_reply = (GMimeFilterReply *) g_object_new (GMIME_TYPE_FILTER_REPLY, NULL);
208     new_reply->encode = encode;
209
210     return (GMimeFilter *) new_reply;
211 }
212