1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <glib/gi18n.h>
37 #include "modest-text-utils.h"
42 #endif /*HAVE_CONFIG_H */
45 static GString *get_next_line (const char *b, const gsize blen, const gchar * iter);
46 static int get_indent_level (const char *l);
47 static void unquote_line (GString * l);
48 static void append_quoted (GString * buf, const int indent,
49 const GString * str, const int cutpoint);
50 static int get_breakpoint_utf8 (const gchar * s, const gint indent,
52 static int get_breakpoint_ascii (const gchar * s, const gint indent,
54 static int get_breakpoint (const gchar * s, const gint indent,
58 get_next_line (const gchar * b, const gsize blen, const gchar * iter)
64 return g_string_new("");
72 gs = g_string_new_len (i0, iter - i0);
76 get_indent_level (const char *l)
93 /* if we hit the signature marker "-- ", we return -(indent + 1). This
96 if (strcmp (l, "-- ") == 0) {
104 unquote_line (GString * l)
119 g_string_erase (l, 0, p - l->str);
123 append_quoted (GString * buf, int indent, const GString * str,
128 indent = indent < 0 ? abs (indent) - 1 : indent;
129 for (i = 0; i <= indent; i++) {
130 g_string_append (buf, "> ");
133 g_string_append_len (buf, str->str, cutpoint);
135 g_string_append (buf, str->str);
137 g_string_append (buf, "\n");
141 get_breakpoint_utf8 (const gchar * s, gint indent, const gint limit)
144 const gchar *pos, *last;
147 indent = indent < 0 ? abs (indent) - 1 : indent;
151 uni = g_utf8_to_ucs4_fast (s, -1, NULL);
153 if ((index + 2 * indent > limit) && last) {
157 if (g_unichar_isspace (uni[index])) {
160 pos = g_utf8_next_char (pos);
168 get_breakpoint_ascii (const gchar * s, const gint indent, const gint limit)
173 if (last + 2 * indent < limit)
176 for (i = strlen (s); i > 0; i--) {
178 if (i + 2 * indent <= limit) {
189 get_breakpoint (const gchar * s, const gint indent, const gint limit)
192 if (g_utf8_validate (s, -1, NULL)) {
193 return get_breakpoint_utf8 (s, indent, limit);
194 } else { /* assume ASCII */
195 //g_warning("invalid UTF-8 in msg");
196 return get_breakpoint_ascii (s, indent, limit);
202 /* just to prevent warnings:
203 * warning: `%x' yields only last 2 digits of year in some locales
206 my_strftime(char *s, size_t max, const char *fmt, const
208 return strftime(s, max, fmt, tm);
212 cite (const time_t sent_date, const gchar *from) {
216 /* format sent_date */
217 my_strftime (sent_str, 100, "%c", localtime (&sent_date));
218 return g_strdup_printf (N_("On %s, %s wrote:\n"), sent_str, from);
223 modest_text_utils_quote (const gchar * to_quote, const gchar * from,
224 const time_t sent_date, const int limit)
227 gint indent, breakpoint, rem_indent = 0;
228 GString *q, *l, *remaining;
232 /* format sent_date */
233 tmp = cite (sent_date, from);
234 q = g_string_new (tmp);
237 /* remaining will store the rest of the line if we have to break it */
238 remaining = g_string_new ("");
241 len = strlen(to_quote);
243 l = get_next_line (to_quote, len, iter);
244 iter = iter + l->len + 1;
245 indent = get_indent_level (l->str);
248 if (remaining->len) {
249 if (l->len && indent == rem_indent) {
250 g_string_prepend (l, " ");
251 g_string_prepend (l, remaining->str);
255 get_breakpoint (remaining-> str,
258 append_quoted (q, rem_indent,
259 remaining, breakpoint);
260 g_string_erase (remaining, 0,
262 if (remaining->str[0] == ' ') {
263 g_string_erase (remaining, 0,
266 } while (remaining->len);
269 g_string_free (remaining, TRUE);
270 breakpoint = get_breakpoint (l->str, indent, limit);
271 remaining = g_string_new (l->str + breakpoint);
272 if (remaining->str[0] == ' ') {
273 g_string_erase (remaining, 0, 1);
276 append_quoted (q, indent, l, breakpoint);
277 g_string_free (l, TRUE);
278 } while ((iter < to_quote + len) || (remaining->str[0]));
280 return g_string_free (q, FALSE);
284 create_derivated_subject (const gchar *subject, const gchar *prefix)
289 return g_strdup_printf ("%s ", prefix);
291 tmp = g_strchug (g_strdup (subject));
293 if (!strncmp (tmp, prefix, strlen (prefix))) {
297 return g_strdup_printf ("%s %s", prefix, subject);
302 * modest_text_utils_create_reply_subject:
305 * creates a new subject with a reply prefix if not present before
307 * Returns: a new subject with the reply prefix
310 modest_text_utils_create_reply_subject (const gchar *subject)
312 return create_derivated_subject (subject, _("Re:"));
316 * modest_text_utils_create_forward_subject:
319 * creates a new subject with a forward prefix if not present before
321 * Returns: a new subject with the forward prefix
324 modest_text_utils_create_forward_subject (const gchar *subject)
326 return create_derivated_subject (subject, _("Fw:"));
330 modest_text_utils_create_cited_text (const gchar *from,
336 tmp = cite (sent_date, from);
337 retval = g_strdup_printf ("%s%s\n", tmp, text);
344 * modest_text_utils_create_inlined_text:
345 * @text: the original text
347 * creates a new string with the "Original message" text prepended to
348 * the text passed as argument and some data of the header
350 * Returns: a newly allocated text
353 modest_text_utils_create_inlined_text (const gchar *from,
356 const gchar *subject,
361 my_strftime (sent_str, 100, "%c", localtime (&sent_date));
363 return g_strdup_printf ("%s\n%s %s\n%s %s\n%s %s\n%s %s\n\n%s",
364 _("-----Forwarded Message-----"),
366 _("Sent:"), sent_str,
368 _("Subject:"), subject,
373 modest_text_utils_remove_mail_from_mail_list (const gchar *emails,
376 char *dup, *token, *ptr, *result;
377 GString *filtered_emails;
382 /* Search for substring */
383 if (!strstr ((const char *) emails, (const char *) email))
384 return g_strdup (emails);
386 dup = g_strdup (emails);
387 filtered_emails = g_string_new (NULL);
389 token = strtok_r (dup, ",", &ptr);
391 while (token != NULL) {
392 /* Add to list if not found */
393 if (!strstr ((const char *) token, (const char *) email)) {
394 if (G_UNLIKELY (filtered_emails->len) == 0)
395 g_string_append_printf (filtered_emails, "%s", token);
397 g_string_append_printf (filtered_emails, ",%s", token);
399 token = strtok_r (NULL, ",", &ptr);
401 result = filtered_emails->str;
405 g_string_free (filtered_emails, FALSE);