* src/modest-text-utils.[ch]:
[modest] / src / modest-text-utils.c
index 01e70d3..8deb5cc 100644 (file)
@@ -139,9 +139,9 @@ const guint USER_NAME_FORBIDDEN_CHARS_LENGTH = G_N_ELEMENTS (user_name_forbidden
 
 /* private */
 static gchar*   cite                    (const time_t sent_date, const gchar *from);
-static void     hyperlinkify_plain_text (GString *txt);
+static void     hyperlinkify_plain_text (GString *txt, gint offset);
 static gint     cmp_offsets_reverse     (const url_match_t *match1, const url_match_t *match2);
-static GSList*  get_url_matches         (GString *txt);
+static GSList*  get_url_matches         (GString *txt, gint offset);
 
 static GString* get_next_line           (const char *b, const gsize blen, const gchar * iter);
 static int      get_indent_level        (const char *l);
@@ -356,23 +356,27 @@ modest_text_utils_remove_duplicate_addresses (const gchar *address_list)
 {
        GSList *addresses, *cursor;
        GHashTable *table;
-       gchar *new_list;
+       gchar *new_list = NULL;
        
        g_return_val_if_fail (address_list, NULL);
 
        table = g_hash_table_new (g_str_hash, g_str_equal);
        addresses = modest_text_utils_split_addresses_list (address_list);
 
-       new_list = g_strdup("");
        cursor = addresses;
        while (cursor) {
                const gchar* address = (const gchar*)cursor->data;
 
                /* ignore the address if already seen */
                if (g_hash_table_lookup (table, address) == 0) {
-               
-                       gchar *tmp = g_strjoin (",", new_list, address, NULL);
-                       g_free (new_list);
+                       gchar *tmp;
+
+                       if (!new_list) {
+                               tmp = g_strdup (address);
+                       } else {
+                               tmp = g_strjoin (",", new_list, address, NULL);
+                               g_free (new_list);
+                       }
                        new_list = tmp;
                        
                        g_hash_table_insert (table, (gchar*)address, GINT_TO_POINTER(1));
@@ -487,7 +491,7 @@ modest_text_utils_convert_to_html (const gchar *data)
        g_string_append (html, "</body></html>");
 
        if (len <= HYPERLINKIFY_MAX_LENGTH)
-               hyperlinkify_plain_text (html);
+               hyperlinkify_plain_text (html, 0);
 
        modest_text_utils_convert_buffer_to_html_finish (html);
        
@@ -511,7 +515,7 @@ modest_text_utils_convert_to_html_body (const gchar *data, gssize n, gboolean hy
        modest_text_utils_convert_buffer_to_html_start (html, data, n);
 
        if (hyperlinkify && (n < HYPERLINKIFY_MAX_LENGTH))
-               hyperlinkify_plain_text (html);
+               hyperlinkify_plain_text (html, 0);
 
        modest_text_utils_convert_buffer_to_html_finish (html);
        
@@ -653,6 +657,30 @@ modest_text_utils_address_range_at_position (const gchar *recipients_list,
                *end = range_end;
 }
 
+gchar *
+modest_text_utils_address_with_standard_length (const gchar *recipients_list)
+{
+       gchar ** splitted;
+       gchar ** current;
+       GString *buffer = g_string_new ("");
+
+       splitted = g_strsplit (recipients_list, "\n", 0);
+       current = splitted;
+       while (*current) {
+               gchar *line;
+               if (current != splitted)
+                       buffer = g_string_append_c (buffer, '\n');
+               line = g_strndup (*splitted, 1000);
+               buffer = g_string_append (buffer, line);
+               g_free (line);
+               current++;
+       }
+
+       g_strfreev (splitted);
+
+       return g_string_free (buffer, FALSE);
+}
+
 
 /* ******************************************************************* */
 /* ************************* UTILIY FUNCTIONS ************************ */
@@ -990,10 +1018,10 @@ modest_text_utils_hyperlinkify_end (void)
 
 
 static GSList*
-get_url_matches (GString *txt)
+get_url_matches (GString *txt, gint offset)
 {
        regmatch_t rm;
-        guint rv, i, offset = 0;
+        guint rv, i, tmp_offset = 0;
         GSList *match_list = NULL;
 
        const size_t pattern_num = sizeof(patterns)/sizeof(url_match_pattern_t);
@@ -1003,13 +1031,13 @@ get_url_matches (GString *txt)
 
         /* find all the matches */
        for (i = 0; i != pattern_num; ++i) {
-               offset     = 0; 
+               tmp_offset     = offset;        
                while (1) {
                        url_match_t *match;
                        gboolean is_submatch;
                        GSList *cursor;
                        
-                       if ((rv = regexec (patterns[i].preg, txt->str + offset, 1, &rm, 0)) != 0) {
+                       if ((rv = regexec (patterns[i].preg, txt->str + tmp_offset, 1, &rm, 0)) != 0) {
                                g_return_val_if_fail (rv == REG_NOMATCH, NULL); /* this should not happen */
                                break; /* try next regexp */ 
                        }
@@ -1022,7 +1050,7 @@ get_url_matches (GString *txt)
                        while (cursor && !is_submatch) {
                                const url_match_t *old_match =
                                        (const url_match_t *) cursor->data;
-                               guint new_offset = offset + rm.rm_so;
+                               guint new_offset = tmp_offset + rm.rm_so;
                                is_submatch = (new_offset >  old_match->offset &&
                                               new_offset <  old_match->offset + old_match->len);
                                cursor = g_slist_next (cursor);
@@ -1031,12 +1059,12 @@ get_url_matches (GString *txt)
                        if (!is_submatch) {
                                /* make a list of our matches (<offset, len, prefix> tupels)*/
                                match = g_slice_new (url_match_t);
-                               match->offset = offset + rm.rm_so;
+                               match->offset = tmp_offset + rm.rm_so;
                                match->len    = rm.rm_eo - rm.rm_so;
                                match->prefix = patterns[i].prefix;
                                match_list = g_slist_prepend (match_list, match);
                        }               
-                       offset += rm.rm_eo;
+                       tmp_offset += rm.rm_eo;
                }
        }
 
@@ -1077,10 +1105,10 @@ replace_string (const gchar *haystack, const gchar *needle, gchar repl)
 }
 
 static void
-hyperlinkify_plain_text (GString *txt)
+hyperlinkify_plain_text (GString *txt, gint offset)
 {
        GSList *cursor;
-       GSList *match_list = get_url_matches (txt);
+       GSList *match_list = get_url_matches (txt, offset);
 
        /* we will work backwards, so the offsets stay valid */
        for (cursor = match_list; cursor; cursor = cursor->next) {
@@ -1116,6 +1144,18 @@ hyperlinkify_plain_text (GString *txt)
        g_slist_free (match_list);
 }
 
+void
+modest_text_utils_hyperlinkify (GString *string_buffer)
+{
+       gchar *after_body;
+       gint offset = 0;
+
+       after_body = strstr (string_buffer->str, "<body>");
+       if (after_body != NULL)
+               offset = after_body - string_buffer->str;
+       hyperlinkify_plain_text (string_buffer, offset);
+}
+
 
 /* for optimization reasons, we change the string in-place */
 void
@@ -1298,7 +1338,7 @@ modest_text_utils_validate_folder_name (const gchar *folder_name)
        const gchar *forbidden_names[] = { /* windows does not like these */
                "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6",
                "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
-               ".", "..", NULL
+               ".", "..", "cur", "tmp", "new", NULL /* cur, tmp new  are reserved for Maildir */
        };
        
        /* cannot be NULL */
@@ -1310,6 +1350,10 @@ modest_text_utils_validate_folder_name (const gchar *folder_name)
        if (len == 0)
                return FALSE;
        
+       /* cannot start with a dot, vfat does not seem to like that */
+       if (folder_name[0] == '.')
+               return FALSE;
+
        /* cannot start or end with a space */
        if (g_ascii_isspace(folder_name[0]) || g_ascii_isspace(folder_name[len - 1]))
                return FALSE;