* modest-folder-view.c: change sorting for remote folders: make Inbox be the first...
[modest] / src / modest-text-utils.c
index 24d42de..3c32ada 100644 (file)
@@ -100,11 +100,16 @@ static int      get_breakpoint          (const gchar * s, const gint indent, con
 
 static gchar*   modest_text_utils_quote_plain_text (const gchar *text, 
                                                    const gchar *cite, 
+                                                   const gchar *signature,
+                                                   GList *attachments, 
                                                    int limit);
 
 static gchar*   modest_text_utils_quote_html       (const gchar *text, 
-                                                   const gchar *cite, 
+                                                   const gchar *cite,
+                                                   const gchar *signature,
+                                                   GList *attachments,
                                                    int limit);
+static gchar*   get_email_from_address (const gchar *address);
 
 
 /* ******************************************************************* */
@@ -117,6 +122,7 @@ modest_text_utils_quote (const gchar *text,
                         const gchar *signature,
                         const gchar *from,
                         const time_t sent_date, 
+                        GList *attachments,
                         int limit)
 {
        gchar *retval, *cited;
@@ -129,12 +135,12 @@ modest_text_utils_quote (const gchar *text,
        if (content_type && strcmp (content_type, "text/html") == 0)
                /* TODO: extract the <body> of the HTML and pass it to
                   the function */
-               retval = modest_text_utils_quote_html (text, cited, limit);
+               retval = modest_text_utils_quote_html (text, cited, signature, attachments, limit);
        else
-               retval = modest_text_utils_quote_plain_text (text, cited, limit);
+               retval = modest_text_utils_quote_plain_text (text, cited, signature, attachments, limit);
        
        g_free (cited);
-
+       
        return retval;
 }
 
@@ -146,28 +152,39 @@ modest_text_utils_cite (const gchar *text,
                        const gchar *from,
                        time_t sent_date)
 {
-       gchar *tmp, *retval;
+       gchar *retval;
        gchar *tmp_sig;
 
        g_return_val_if_fail (text, NULL);
        g_return_val_if_fail (content_type, NULL);
 
        if (!signature)
-               tmp_sig = g_strdup ("");
+               retval = g_strdup ("");
        else if (!strcmp(content_type, "text/html")) {
-               tmp_sig = modest_text_utils_convert_to_html_body(signature);
+               tmp_sig = g_strconcat ("\n", signature, NULL);
+               retval = modest_text_utils_convert_to_html_body(tmp_sig);
+               g_free (tmp_sig);
        } else {
-               tmp_sig = g_strdup (signature);
+               retval = g_strconcat ("\n", signature, NULL);
        }
 
-       tmp = cite (sent_date, from);
-       retval = g_strdup_printf ("%s%s%s\n", tmp_sig, tmp, text);
-       g_free (tmp_sig);
-       g_free (tmp);
-
        return retval;
 }
 
+static gchar *
+forward_cite (const gchar *from,
+                   const gchar *sent,
+                   const gchar *to,
+                   const gchar *subject)
+{
+       return g_strdup_printf ("%s\n%s %s\n%s %s\n%s %s\n%s %s\n", 
+                               FORWARD_STRING, 
+                               FROM_STRING, (from)?from:"",
+                               SENT_STRING, sent,
+                               TO_STRING, (to)?to:"",
+                               SUBJECT_STRING, (subject)?subject:"");
+}
+
 gchar * 
 modest_text_utils_inline (const gchar *text,
                          const gchar *content_type,
@@ -178,47 +195,23 @@ modest_text_utils_inline (const gchar *text,
                          const gchar *subject)
 {
        gchar sent_str[101];
-       gchar *formatted_signature;
-       const gchar *plain_format = "%s%s\n%s %s\n%s %s\n%s %s\n%s %s\n\n%s";
-       const gchar *html_format = \
-               "%s%s<br>\n<table width=\"100%\" border=\"0\" cellspacing=\"2\" cellpadding=\"2\">\n" \
-               "<tr><td>%s</td><td>%s</td></tr>\n" \
-               "<tr><td>%s</td><td>%s</td></tr>\n" \
-               "<tr><td>%s</td><td>%s</td></tr>\n" \
-               "<tr><td>%s</td><td>%s</td></tr>\n" \
-               "<br><br>%s";
-       const gchar *format;
-
+       gchar *cited;
+       gchar *retval;
+       
        g_return_val_if_fail (text, NULL);
        g_return_val_if_fail (content_type, NULL);
-       g_return_val_if_fail (text, NULL);
        
        modest_text_utils_strftime (sent_str, 100, "%c", sent_date);
 
-       if (!strcmp (content_type, "text/html"))
-               /* TODO: extract the <body> of the HTML and pass it to
-                  the function */
-               format = html_format;
+       cited = forward_cite (from, sent_str, to, subject);
+       
+       if (content_type && strcmp (content_type, "text/html") == 0)
+               retval = modest_text_utils_quote_html (text, cited, signature, NULL, 80);
        else
-               format = plain_format;
-
-       if (signature != NULL) {
-               if (!strcmp (content_type, "text/html")) {
-                       formatted_signature = g_strconcat (signature, "<br/>", NULL);
-               } else {
-                       formatted_signature = g_strconcat (signature, "\n", NULL);
-               }
-       } else {
-               formatted_signature = "";
-       }
-
-       return g_strdup_printf (format, formatted_signature, 
-                               FORWARD_STRING,
-                               FROM_STRING, (from) ? from : EMPTY_STRING,
-                               SENT_STRING, sent_str,
-                               TO_STRING, (to) ? to : EMPTY_STRING,
-                               SUBJECT_STRING, (subject) ? subject : EMPTY_STRING,
-                               text);
+               retval = modest_text_utils_quote_plain_text (text, cited, signature, NULL, 80);
+       
+       g_free (cited);
+       return retval;
 }
 
 /* just to prevent warnings:
@@ -233,7 +226,6 @@ modest_text_utils_strftime(char *s, gsize max, const char *fmt, time_t timet)
         *   g_date_set_time_t (&date, timet);
         */
        localtime_r (&timet, &tm);
-
        return strftime(s, max, fmt, &tm);
 }
 
@@ -262,15 +254,20 @@ modest_text_utils_remove_address (const gchar *address_list, const gchar *addres
 {
        gchar *dup, *token, *ptr, *result;
        GString *filtered_emails;
+       gchar *email_address;
 
        g_return_val_if_fail (address_list, NULL);
 
        if (!address)
                return g_strdup (address_list);
+
+       email_address = get_email_from_address (address);
        
        /* search for substring */
-       if (!strstr ((const char *) address_list, (const char *) address))
+       if (!strstr ((const char *) address_list, (const char *) email_address)) {
+               g_free (email_address);
                return g_strdup (address_list);
+       }
 
        dup = g_strdup (address_list);
        filtered_emails = g_string_new (NULL);
@@ -279,7 +276,7 @@ modest_text_utils_remove_address (const gchar *address_list, const gchar *addres
 
        while (token != NULL) {
                /* Add to list if not found */
-               if (!strstr ((const char *) token, (const char *) address)) {
+               if (!strstr ((const char *) token, (const char *) email_address)) {
                        if (filtered_emails->len == 0)
                                g_string_append_printf (filtered_emails, "%s", g_strstrip (token));
                        else
@@ -290,6 +287,7 @@ modest_text_utils_remove_address (const gchar *address_list, const gchar *addres
        result = filtered_emails->str;
 
        /* Clean */
+       g_free (email_address);
        g_free (dup);
        g_string_free (filtered_emails, FALSE);
 
@@ -302,6 +300,7 @@ modest_text_utils_convert_buffer_to_html (GString *html, const gchar *data)
        guint            i;
        gboolean        space_seen = FALSE;
        gsize           len;
+       guint           break_dist = 0; /* distance since last break point */
 
        len = strlen (data);
 
@@ -314,6 +313,15 @@ modest_text_utils_convert_buffer_to_html (GString *html, const gchar *data)
                        space_seen = FALSE;
                }
                
+               /* we artificially insert a breakpoint (newline)
+                * after 256, to make sure our lines are not so long
+                * they will DOS the regexping later
+                */
+               if (++break_dist == 256) {
+                       g_string_append_c (html, '\n');
+                       break_dist = 0;
+               }
+               
                switch (kar) {
                case 0:  break; /* ignore embedded \0s */       
                case '<'  : g_string_append (html, "&lt;");   break;
@@ -321,11 +329,12 @@ modest_text_utils_convert_buffer_to_html (GString *html, const gchar *data)
                case '&'  : g_string_append (html, "&amp;");  break;
                case '"'  : g_string_append (html, "&quot;");  break;
                case '\'' : g_string_append (html, "&apos;"); break;
-               case '\n' : g_string_append (html, "<br>\n");  break;
-               case '\t' : g_string_append (html, "&nbsp;&nbsp;&nbsp; "); break; /* note the space at the end*/
+               case '\n' : g_string_append (html, "<br>\n");              break_dist= 0; break;
+               case '\t' : g_string_append (html, "&nbsp;&nbsp;&nbsp; "); break_dist=0; break; /* note the space at the end*/
                case ' ':
+                       break_dist = 0;
                        if (space_seen) { /* second space in a row */
-                               g_string_append (html, "&nbsp ");
+                               g_string_append (html, "&nbsp; ");
                                space_seen = FALSE;
                        } else
                                space_seen = TRUE;
@@ -670,28 +679,40 @@ get_breakpoint (const gchar * s, const gint indent, const gint limit)
 static gchar *
 cite (const time_t sent_date, const gchar *from)
 {
-       gchar sent_str[101];
-
-       /* format sent_date */
-       modest_text_utils_strftime (sent_str, 100, "%c", sent_date);
-       return g_strdup_printf (N_("On %s, %s wrote:\n"), 
-                               sent_str, 
-                               (from) ? from : EMPTY_STRING);
+       return g_strdup (_("mcen_ia_editor_original_message"));
 }
 
+static gchar *
+quoted_attachments (GList *attachments)
+{
+       GList *node = NULL;
+       GString *result = g_string_new ("");
+       for (node = attachments; node != NULL; node = g_list_next (node)) {
+               gchar *filename = (gchar *) node->data;
+               g_string_append_printf ( result, "%s %s\n", _("mcen_ia_editor_attach_filename"), filename);
+       }
+
+       return g_string_free (result, FALSE);
+
+}
 
 static gchar *
 modest_text_utils_quote_plain_text (const gchar *text, 
                                    const gchar *cite, 
+                                   const gchar *signature,
+                                   GList *attachments,
                                    int limit)
 {
        const gchar *iter;
        gint indent, breakpoint, rem_indent = 0;
        GString *q, *l, *remaining;
        gsize len;
+       gchar *attachments_string = NULL;
 
        /* remaining will store the rest of the line if we have to break it */
-       q = g_string_new (cite);
+       q = g_string_new ("\n");
+       q = g_string_append (q, cite);
+       q = g_string_append_c (q, '\n');
        remaining = g_string_new ("");
 
        iter = text;
@@ -734,24 +755,56 @@ modest_text_utils_quote_plain_text (const gchar *text,
                g_string_free (l, TRUE);
        } while ((iter < text + len) || (remaining->str[0]));
 
+       attachments_string = quoted_attachments (attachments);
+       q = g_string_append (q, attachments_string);
+       g_free (attachments_string);
+
+       if (signature != NULL) {
+               q = g_string_append_c (q, '\n');
+               q = g_string_append (q, signature);
+       }
+
        return g_string_free (q, FALSE);
 }
 
 static gchar*
 modest_text_utils_quote_html (const gchar *text, 
                              const gchar *cite, 
+                             const gchar *signature,
+                             GList *attachments,
                              int limit)
 {
+       gchar *result = NULL;
+       gchar *signature_result = NULL;
        const gchar *format = \
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" \
                "<html>\n" \
                "<body>\n" \
-               "%s" \
-               "<blockquote type=\"cite\">\n%s\n</blockquote>\n" \
+               "<br/>%s<br/>" \
+               "<pre>%s<br/>%s<br/>%s</pre>\n" \
                "</body>\n" \
                "</html>\n";
+       gchar *attachments_string = NULL;
+       gchar *q_attachments_string = NULL;
+       gchar *q_cite = NULL;
+       gchar *html_text = NULL;
 
-       return g_strdup_printf (format, cite, text);
+       if (signature == NULL)
+               signature_result = g_strdup ("");
+       else
+               signature_result = modest_text_utils_convert_to_html_body (signature);
+
+       attachments_string = quoted_attachments (attachments);
+       q_attachments_string = modest_text_utils_convert_to_html_body (attachments_string);
+       q_cite = modest_text_utils_convert_to_html_body (cite);
+       html_text = modest_text_utils_convert_to_html_body (text);
+       result = g_strdup_printf (format, signature_result, q_cite, html_text, q_attachments_string);
+       g_free (q_cite);
+       g_free (html_text);
+       g_free (attachments_string);
+       g_free (q_attachments_string);
+       g_free (signature_result);
+       return result;
 }
 
 static gint 
@@ -907,10 +960,11 @@ modest_text_utils_get_subject_prefix_len (const gchar *sub)
 {
        gint i;
        static const gchar* prefix[] = {
-               "Re:", "RE:", "Fwd:", "FWD:", "FW:", NULL
+               "Re:", "RE:", "RV:", "re:"
+               "Fwd:", "FWD:", "FW:", "fwd:", "Fw:", "fw:", NULL
        };
                
-       if (!sub || (sub[0] != 'R' && sub[0] != 'F')) /* optimization */
+       if (!sub || (sub[0] != 'R' && sub[0] != 'F' && sub[0] != 'r' && sub[0] != 'f')) /* optimization */
                return 0;
 
        i = 0;
@@ -964,24 +1018,26 @@ modest_text_utils_get_display_date (time_t date)
        
        now = time (NULL);
 
-       modest_text_utils_strftime (date_buf, BUF_SIZE, "%d/%m/%Y", date);
-       modest_text_utils_strftime (now_buf,  BUF_SIZE, "%d/%m/%Y",  now); /* today */
-/*     modest_text_utils_strftime (date_buf, BUF_SIZE, "%x", date); */
-/*     modest_text_utils_strftime (now_buf,  BUF_SIZE, "%x",  now); /\* today *\/ */
+       /* use the localized dates */
+       modest_text_utils_strftime (date_buf, BUF_SIZE, "%x", date); 
+       modest_text_utils_strftime (now_buf,  BUF_SIZE, "%x", now); 
        
        /* if this is today, get the time instead of the date */
        if (strcmp (date_buf, now_buf) == 0)
-               modest_text_utils_strftime (date_buf, BUF_SIZE, "%H:%M %P", date);
+               modest_text_utils_strftime (date_buf, BUF_SIZE, "%X", date);
        
        return g_strdup(date_buf);
 }
 
-gboolean 
-modest_text_utils_validate_email_address (const gchar *email_address)
+gboolean
+modest_text_utils_validate_email_address (const gchar *email_address, const gchar **invalid_char_position)
 {
        int count = 0;
        const gchar *c = NULL, *domain = NULL;
-       static gchar *rfc822_specials = "()<>@,;:\\\"[]";
+       static gchar *rfc822_specials = "()<>@,;:\\\"[]&";
+
+       if (invalid_char_position != NULL)
+               *invalid_char_position = NULL;
 
        /* first we validate the name portion (name@domain) */
        for (c = email_address;  *c;  c++) {
@@ -1009,8 +1065,11 @@ modest_text_utils_validate_email_address (const gchar *email_address)
                        break;
                if (*c <= ' ' || *c >= 127) 
                        return FALSE;
-               if (strchr(rfc822_specials, *c)) 
+               if (strchr(rfc822_specials, *c)) {
+                       if (invalid_char_position)
+                               *invalid_char_position = c;
                        return FALSE;
+               }
        }
        if (c == email_address || *(c - 1) == '.') 
                return FALSE;
@@ -1026,21 +1085,24 @@ modest_text_utils_validate_email_address (const gchar *email_address)
                }
                if (*c <= ' ' || *c >= 127) 
                        return FALSE;
-               if (strchr(rfc822_specials, *c)) 
+               if (strchr(rfc822_specials, *c)) {
+                       if (invalid_char_position)
+                               *invalid_char_position = c;
                        return FALSE;
+               }
        } while (*++c);
 
        return (count >= 1) ? TRUE : FALSE;
 }
 
 gboolean 
-modest_text_utils_validate_recipient (const gchar *recipient)
+modest_text_utils_validate_recipient (const gchar *recipient, const gchar **invalid_char_position)
 {
        gchar *stripped, *current;
        gchar *right_part;
        gboolean has_error = FALSE;
 
-       if (modest_text_utils_validate_email_address (recipient))
+       if (modest_text_utils_validate_email_address (recipient, invalid_char_position))
                return TRUE;
        stripped = g_strdup (recipient);
        stripped = g_strstrip (stripped);
@@ -1097,7 +1159,7 @@ modest_text_utils_validate_recipient (const gchar *recipient)
 
                address = g_strndup (right_part+1, strlen (right_part) - 2);
                g_free (right_part);
-               valid = modest_text_utils_validate_email_address (address);
+               valid = modest_text_utils_validate_email_address (address, invalid_char_position);
                g_free (address);
                return valid;
        } else {
@@ -1121,11 +1183,38 @@ modest_text_utils_get_display_size (guint64 size)
        else if (KB <= size && size < 100 * KB)
                return g_strdup_printf (_FM("sfil_li_size_1kb_99kb"), size / KB);
        else if (100*KB <= size && size < MB)
-               return g_strdup_printf (_FM("sfil_li_size_100kb_1mb"), size / MB);
+               return g_strdup_printf (_FM("sfil_li_size_100kb_1mb"), (float) size / MB);
        else if (MB <= size && size < 10*MB)
-               return g_strdup_printf (_FM("sfil_li_size_1mb_10mb"), size / MB);
+               return g_strdup_printf (_FM("sfil_li_size_1mb_10mb"), (float) size / MB);
        else if (10*MB <= size && size < GB)
                return g_strdup_printf (_FM("sfil_li_size_10mb_1gb"), size / MB);
        else
-               return g_strdup_printf (_FM("sfil_li_size_1gb_or_greater"), size / GB); 
+               return g_strdup_printf (_FM("sfil_li_size_1gb_or_greater"), (float) size / GB); 
+}
+
+static gchar *
+get_email_from_address (const gchar * address)
+{
+       gchar *left_limit, *right_limit;
+
+       left_limit = strstr (address, "<");
+       right_limit = g_strrstr (address, ">");
+
+       if ((left_limit == NULL)||(right_limit == NULL)|| (left_limit > right_limit))
+               return g_strdup (address);
+       else
+               return g_strndup (left_limit + 1, (right_limit - left_limit) - 1);
+}
+
+gchar *      
+modest_text_utils_get_color_string (GdkColor *color)
+{
+
+       return g_strdup_printf ("#%x%x%x%x%x%x%x%x%x%x%x%x",
+                               (color->red >> 12)   & 0xf, (color->red >> 8)   & 0xf,
+                               (color->red >>  4)   & 0xf, (color->red)        & 0xf,
+                               (color->green >> 12) & 0xf, (color->green >> 8) & 0xf,
+                               (color->green >>  4) & 0xf, (color->green)      & 0xf,
+                               (color->blue >> 12)  & 0xf, (color->blue >> 8)  & 0xf,
+                               (color->blue >>  4)  & 0xf, (color->blue)       & 0xf);
 }