* src/modest-ui-actions.[ch]:
authorJose Dapena Paz <jdapena@igalia.com>
Wed, 2 May 2007 14:12:38 +0000 (14:12 +0000)
committerJose Dapena Paz <jdapena@igalia.com>
Wed, 2 May 2007 14:12:38 +0000 (14:12 +0000)
        * Run check names before sending email from editor.
        * New check names action, used to validate and
          search addresses in addressbook.
* src/modest-address-book.h:
        * Added new check_names method.
* src/modest-text-utils.[ch]:
        * Added ..._get_addresses_indexes. It finds the offset ranges
          of the addresses in a string.
        * ..._split_addresses_list now takes ";" into account, not only
          ",".
        * ..._split_addresses_list fixed offset calculations. Now uses
         utf8 characters.
        * ..._validate_recipient: strips the string before processing.
        * ..._validate_recipient: now counts utf8 characters. Also
          accepts spaces in left part of the address, even when they're
          not between quotes.
* src/maemo/modest-address-book.c:
        * ..._add_address: now the dialog title uses the logical id.
        * (ui_get_formatted_email_id): Now it adds quotes to address
          strings with spaces.
        * New ..._check_names method. It validates all addresses in
          the recipient editor. If address is valid, ok, if not valid,
          it checks if this is an email address attempt (shows error)
          or a generic string (searches in addressbook and replaces
          with matches).
* src/maemo/modest-msg-edit-window.c:
        * New ..._check_names method. Checks all recipient fields using
          new check names implementation in addressbook module.
* src/maemo/ui/modest-msg-edit-window-ui.xml:
        * Added "Check names" menu option.
* src/gnome/modest-address-book.c:
        * Added stubs for new functions.
* src/gnome/modest-msg-edit-window.c:
        * Added stubs for new functions.
* src/widgets/modest-msg-edit-window.h:
        * New _check_names method.
* src/widgets/modest-recpt-editor.[ch]:
        * Now , and ; inside quotes do not insert a CR.
        * New ..._replace_with_resolved_recipient method, to replace
          a range of the editor with a resolved recipient. It's used
          on _check_names implementation.
* src/widgets/modest-msg-edit-window-ui.h:
        * Added action for check names.

pmo-trunk-r1730

14 files changed:
src/gnome/modest-address-book.c
src/gnome/modest-msg-edit-window.c
src/maemo/modest-address-book.c
src/maemo/modest-msg-edit-window.c
src/maemo/ui/modest-msg-edit-window-ui.xml
src/modest-address-book.h
src/modest-text-utils.c
src/modest-text-utils.h
src/modest-ui-actions.c
src/modest-ui-actions.h
src/widgets/modest-msg-edit-window-ui.h
src/widgets/modest-msg-edit-window.h
src/widgets/modest-recpt-editor.c
src/widgets/modest-recpt-editor.h

index be2d292..e401a51 100644 (file)
@@ -42,3 +42,10 @@ modest_address_book_select_addresses (ModestRecptEditor *editor)
 {
        g_message (__FUNCTION__);
 }
 {
        g_message (__FUNCTION__);
 }
+
+gboolean
+modest_address_book_check_names (ModestRecptEditor *editor)
+{
+       g_message (__FUNCTION__);
+       return TRUE;
+}
index 51a4590..637d172 100644 (file)
@@ -555,6 +555,15 @@ modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
        g_message ("not implemented yet %s", __FUNCTION__);
 }
 
        g_message ("not implemented yet %s", __FUNCTION__);
 }
 
+gboolean
+modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
+{
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+
+       g_message ("not implemented yet %s", __FUNCTION__);
+       return TRUE;
+}
+
 void
 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
                                        gint file_format)
 void
 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
                                        gint file_format)
index 183034a..8554d1d 100644 (file)
@@ -56,6 +56,8 @@ static gchar *ui_get_formatted_email_id(gchar * current_given_name,
                                        gchar * current_sur_name, gchar * current_email_id);
 static gchar *run_add_email_addr_to_contact_dlg(const gchar * contact_name);
 static GSList *select_email_addrs_for_contact(GList * email_addr_list);
                                        gchar * current_sur_name, gchar * current_email_id);
 static gchar *run_add_email_addr_to_contact_dlg(const gchar * contact_name);
 static GSList *select_email_addrs_for_contact(GList * email_addr_list);
+static gboolean resolve_address (const gchar *address, GSList **resolved_addresses, gchar **contact_id);
+static gchar *unquote_string (const gchar *str);
 
 
 static void
 
 
 static void
@@ -102,6 +104,18 @@ open_addressbook ()
        return TRUE; /* FIXME */        
 }
 
        return TRUE; /* FIXME */        
 }
 
+static gboolean
+open_addressbook_sync ()
+{
+       book = e_book_new_system_addressbook (NULL);
+       if (!book)
+               return FALSE;
+
+       e_book_open (book, FALSE, NULL);
+
+       return TRUE;
+}
+
 void
 modest_address_book_add_address (const gchar *address)
 {
 void
 modest_address_book_add_address (const gchar *address)
 {
@@ -160,6 +174,7 @@ modest_address_book_select_addresses (ModestRecptEditor *recpt_editor)
 
        contact_dialog = osso_abook_select_dialog_new (OSSO_ABOOK_TREE_VIEW (contact_view));
        osso_abook_select_dialog_set_new_contact (OSSO_ABOOK_SELECT_DIALOG (contact_dialog), TRUE);
 
        contact_dialog = osso_abook_select_dialog_new (OSSO_ABOOK_TREE_VIEW (contact_view));
        osso_abook_select_dialog_set_new_contact (OSSO_ABOOK_SELECT_DIALOG (contact_dialog), TRUE);
+       gtk_window_set_title (GTK_WINDOW (contact_dialog), _("mcen_ti_select_recipients"));
 
        gtk_widget_show (contact_dialog);
 
 
        gtk_widget_show (contact_dialog);
 
@@ -365,27 +380,23 @@ ui_get_formatted_email_id(gchar * current_given_name,
                          gchar * current_sur_name, gchar * current_email_id)
 {
        GString *email_id_str = NULL;
                          gchar * current_sur_name, gchar * current_email_id)
 {
        GString *email_id_str = NULL;
-       gchar *email_id = NULL;
 
        email_id_str = g_string_new(NULL);
 
        if ((current_given_name != NULL) && ((strlen(current_given_name) != 0))
            && (current_sur_name != NULL) && ((strlen(current_sur_name) != 0))) {
 
        email_id_str = g_string_new(NULL);
 
        if ((current_given_name != NULL) && ((strlen(current_given_name) != 0))
            && (current_sur_name != NULL) && ((strlen(current_sur_name) != 0))) {
-               g_string_printf(email_id_str, "%s %s %c%s%c", current_given_name,
-                               current_sur_name, '<', current_email_id, '>');
-               email_id = g_strdup(email_id_str->str);
+               g_string_append_printf(email_id_str, "%s %s", current_given_name, current_sur_name);
        } else if ((current_given_name != NULL) && (strlen(current_given_name) != 0)) {
        } else if ((current_given_name != NULL) && (strlen(current_given_name) != 0)) {
-               g_string_printf(email_id_str, "%s %c%s%c", current_given_name, '<',
-                               current_email_id, '>');
-               email_id = g_strdup(email_id_str->str);
+               g_string_append_printf(email_id_str, "%s", current_given_name);
        } else if ((current_sur_name != NULL) && (strlen(current_sur_name) != 0)) {
        } else if ((current_sur_name != NULL) && (strlen(current_sur_name) != 0)) {
-               g_string_printf(email_id_str, "%s %c%s%c", current_sur_name, '<',
-                               current_email_id, '>');
-               email_id = g_strdup(email_id_str->str);
+               g_string_append_printf(email_id_str, "%s", current_sur_name);
        }
        }
-       g_string_free(email_id_str, TRUE);
-       email_id_str = NULL;
-       return (email_id);
+       if (g_utf8_strchr (email_id_str->str, -1, ' ')) {
+               g_string_prepend_c (email_id_str, '\"');
+               g_string_append_c (email_id_str, '\"');
+       }
+       g_string_append_printf (email_id_str, " %c%s%c", '<', current_email_id, '>');
+       return g_string_free (email_id_str, FALSE);
 }
 
 /**
 }
 
 /**
@@ -542,3 +553,245 @@ select_email_addrs_for_contact(GList * email_addr_list)
        gtk_widget_destroy(select_email_addr_dlg);
        return selected_email_addr_list;
 }
        gtk_widget_destroy(select_email_addr_dlg);
        return selected_email_addr_list;
 }
+
+gboolean
+modest_address_book_check_names (ModestRecptEditor *recpt_editor)
+{
+       const gchar *recipients = NULL;
+       GSList *start_indexes = NULL, *end_indexes = NULL;
+       GSList *current_start, *current_end;
+       gboolean result = TRUE;
+       GtkTextBuffer *buffer;
+       gint offset_delta = 0;
+       gint last_length;
+       GtkTextIter start_iter, end_iter;
+       GtkWidget *banner;
+
+       g_return_val_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor), FALSE);
+
+       banner = hildon_banner_show_animation (NULL, NULL, _("mail_ib_checking_names"));
+       g_object_ref (G_OBJECT (banner));
+
+       recipients = modest_recpt_editor_get_recipients (recpt_editor);
+       last_length = g_utf8_strlen (recipients, -1);
+       g_message ("LENGTH %d", last_length);
+       modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
+
+       if (start_indexes == NULL) {
+               gtk_widget_destroy (banner);
+               g_object_unref (G_OBJECT(banner));
+               return TRUE;
+       }
+
+       current_start = start_indexes;
+       current_end = end_indexes;
+       buffer = modest_recpt_editor_get_buffer (recpt_editor);
+
+       while (current_start != NULL) {
+               gchar *address;
+               gchar *start_ptr, *end_ptr;
+               gint start_pos, end_pos;
+
+               start_pos = (*((gint*) current_start->data)) + offset_delta;
+               end_pos = (*((gint*) current_end->data)) + offset_delta;
+              
+               start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
+               end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
+
+               address = g_strndup (start_ptr, end_ptr - start_ptr);
+               gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start_pos);
+               gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end_pos);
+               gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
+
+               g_message ("RANGE %d - %d", start_pos, end_pos);
+
+               g_message ("ADDRESS %s", address);
+               if (!modest_text_utils_validate_recipient (address)) {
+                       if (strstr (address, "@") == NULL) {
+                               /* here goes searching in addressbook */
+                               gchar *contact_id = NULL;;
+                               GSList *resolved_addresses = NULL;
+                               result = resolve_address (address, &resolved_addresses, &contact_id);
+
+                               if (result) {
+                                       gint new_length;
+                                       /* replace string */
+                                       modest_recpt_editor_replace_with_resolved_recipient (recpt_editor,
+                                                                                            &start_iter, &end_iter,
+                                                                                            resolved_addresses, 
+                                                                                            contact_id);
+                                       g_free (contact_id);
+                                       g_slist_foreach (resolved_addresses, (GFunc) g_free, NULL);
+                                       g_slist_free (resolved_addresses);
+
+                                       /* update offset delta */
+                                       recipients = modest_recpt_editor_get_recipients (recpt_editor);
+                                       new_length = g_utf8_strlen (recipients, -1);
+                                       offset_delta = offset_delta + new_length - last_length;
+                                       last_length = new_length;
+                                       g_message ("LENGTH %d", last_length);
+                               }
+                       } else {
+                               /* this address is not valid, select it and return control to user showing banner */
+
+                               hildon_banner_show_information (NULL, NULL, _("mcen_ib_invalid_mail"));
+                               result = FALSE;
+                       }
+               }
+               g_free (address);
+               if (result == FALSE)
+                       break;
+
+               current_start = g_slist_next (current_start);
+               current_end = g_slist_next (current_end);
+       }
+
+       if (current_start == NULL) {
+               gtk_text_buffer_get_end_iter (buffer, &end_iter);
+               gtk_text_buffer_place_cursor (buffer, &end_iter);
+       }
+
+       gtk_widget_destroy (banner);
+       g_object_unref (G_OBJECT (banner));
+       modest_recpt_editor_grab_focus (recpt_editor);
+
+       g_slist_foreach (start_indexes, (GFunc) g_free, NULL);
+       g_slist_foreach (end_indexes, (GFunc) g_free, NULL);
+       g_slist_free (start_indexes);
+       g_slist_free (end_indexes);
+
+       return result;
+
+}
+
+static GList *
+get_contacts_for_name (const gchar *name)
+{
+       EBookQuery *full_name_book_query = NULL;
+       GList *result;
+       gchar *unquoted;
+
+       if (name == NULL)
+               return NULL;
+
+       unquoted = unquote_string (name);
+       full_name_book_query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_CONTAINS, unquoted);
+       g_free (unquoted);
+
+       e_book_get_contacts (book, full_name_book_query, &result, NULL);
+       e_book_query_unref (full_name_book_query);
+
+       return result;
+}
+
+static GList *
+select_contacts_for_name_dialog (const gchar *name)
+{
+       EBookQuery *full_name_book_query = NULL;
+       EBookView *book_view = NULL;
+       GList *result = NULL;
+       gchar *unquoted;
+
+       unquoted = unquote_string (name);
+       full_name_book_query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_CONTAINS, unquoted);
+       g_free (unquoted);
+       e_book_get_book_view (book, full_name_book_query, NULL, -1, &book_view, NULL);
+       e_book_query_unref (full_name_book_query);
+
+       if (book_view) {
+               GtkWidget *contact_view = NULL;
+               GtkWidget *contact_dialog = NULL;
+               osso_abook_tree_model_set_book_view (OSSO_ABOOK_TREE_MODEL (contact_model), book_view);
+               e_book_view_start (book_view);
+               
+               contact_view = osso_abook_contact_view_new_basic (contact_model);
+               contact_dialog = osso_abook_select_dialog_new (OSSO_ABOOK_TREE_VIEW (contact_view));
+
+               if (gtk_dialog_run (GTK_DIALOG (contact_dialog)) == GTK_RESPONSE_OK) {
+                       result = osso_abook_contact_view_get_selection (OSSO_ABOOK_CONTACT_VIEW (contact_view));
+               }
+               e_book_view_stop (book_view);
+               g_object_unref (book_view);
+               gtk_widget_destroy (contact_dialog);
+       }
+
+       return result;
+}
+
+static gboolean
+resolve_address (const gchar *address, GSList **resolved_addresses, gchar **contact_id)
+{
+       GList *resolved_contacts;
+
+       contact_model = osso_abook_contact_model_new ();
+       if (!open_addressbook_sync ()) {
+               if (contact_model) {
+                       g_object_unref (contact_model);
+                       contact_model = NULL;
+               }
+               return FALSE;
+       }
+
+       resolved_contacts = get_contacts_for_name (address);
+
+       if (resolved_contacts == NULL) {
+               /* no matching contacts for the search string */
+               hildon_banner_show_information (NULL, NULL, _("mcen_nc_no_matching_contacts"));
+               return FALSE;
+       }
+
+       if (g_list_length (resolved_contacts) > 1) {
+               /* show a dialog to select the contact from the resolved ones */
+               g_list_free (resolved_contacts);
+
+               resolved_contacts = select_contacts_for_name_dialog (address);
+       }
+       
+       /* get the resolved contacts (can be no contact) */
+       if (resolved_contacts) {
+               EContact *contact = (EContact *) resolved_contacts->data;
+
+               *resolved_addresses = get_recipients_for_given_contact (contact);
+               if (*resolved_addresses) {
+                       *contact_id = g_strdup (e_contact_get_const (contact, E_CONTACT_UID));
+               }
+               /* TODO: free the resolved_contacts list */
+               return TRUE;
+       } else {
+               /* cancelled dialog to select more than one contact or
+                * selected no contact */
+               return FALSE;
+       }
+
+}
+
+static gchar *
+unquote_string (const gchar *str)
+{
+       GString *buffer;
+       gchar *p;
+
+       if (str == NULL)
+               return NULL;
+
+       buffer = g_string_new_len (NULL, strlen (str));
+       for (p = (gchar *) str; *p != '\0'; p = g_utf8_next_char (p)) {
+               if (*p == '"') {
+                       p = g_utf8_next_char (p);
+                       while ((*p != '\0')&&(*p != '"')) {
+                               if (*p == '\\') {
+                                       g_string_append_unichar (buffer, g_utf8_get_char (p));
+                                       p = g_utf8_next_char (p);
+                                       
+                               }
+                               g_string_append_unichar (buffer, g_utf8_get_char (p));
+                               p = g_utf8_next_char (p);
+                       }
+               } else {
+                       g_string_append_unichar (buffer, g_utf8_get_char (p));
+               }
+       }
+
+       return g_string_free (buffer, FALSE);
+
+}
index ff31676..e3f16cc 100644 (file)
@@ -2030,3 +2030,32 @@ is_modified (ModestMsgEditWindow *editor)
        return FALSE;
 }
 
        return FALSE;
 }
 
+gboolean
+modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = NULL;
+
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       /* check if there's no recipient added */
+       if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
+           (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
+           (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
+               /* no recipient contents, then select contacts */
+               modest_msg_edit_window_open_addressbook (window, NULL);
+               return FALSE;
+       }
+
+       if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
+               return FALSE;
+       if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
+               return FALSE;
+       if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
+               return FALSE;
+
+       modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
+
+       return TRUE;
+
+}
index a156210..4d27342 100644 (file)
@@ -37,6 +37,7 @@
       <menuitem name="SaveToDraftsMenu" action="ActionsSaveToDrafts"/>
       <separator/>
       <menuitem name="SelectContactsMenu" action="SelectContacts"/>
       <menuitem name="SaveToDraftsMenu" action="ActionsSaveToDrafts"/>
       <separator/>
       <menuitem name="SelectContactsMenu" action="SelectContacts"/>
+      <menuitem name="CheckNamesMenu" action="CheckNames"/>
       <separator/>
       <menuitem name="NewMessageMenu" action="ActionsNewMessage"/>
       <separator/>
       <separator/>
       <menuitem name="NewMessageMenu" action="ActionsNewMessage"/>
       <separator/>
index 9231f96..4f55ee0 100644 (file)
@@ -54,5 +54,18 @@ modest_address_book_add_address (const gchar *address);
 void
 modest_address_book_select_addresses (ModestRecptEditor *editor);
 
 void
 modest_address_book_select_addresses (ModestRecptEditor *editor);
 
+/**
+ * modest_address_book_check_names:
+ * @editor: a #ModestRecptEditor
+ *
+ * Performs verification of addresses in a recipient editor.
+ *
+ * Returns: %TRUE if all recipients are valid or there are
+ * no recipients, %FALSE otherwise.
+ */
+gboolean
+modest_address_book_check_names (ModestRecptEditor *editor);
+
+
 
 #endif /* __MODEST_ADDRESS_BOOK_H__ */
 
 #endif /* __MODEST_ADDRESS_BOOK_H__ */
index de8b38f..2c09387 100644 (file)
@@ -381,6 +381,63 @@ modest_text_utils_convert_to_html_body (const gchar *data)
        return g_string_free (html, FALSE);
 }
 
        return g_string_free (html, FALSE);
 }
 
+void
+modest_text_utils_get_addresses_indexes (const gchar *addresses, GSList **start_indexes, GSList **end_indexes)
+{
+       gchar *current, *start, *last_blank;
+       gint start_offset = 0, current_offset = 0;
+
+       g_return_if_fail (start_indexes != NULL);
+       g_return_if_fail (end_indexes != NULL);
+
+       start = (gchar *) addresses;
+       current = start;
+       last_blank = start;
+
+       while (*current != '\0') {
+               if ((start == current)&&((*current == ' ')||(*current == ',')||(*current == ';'))) {
+                       start = g_utf8_next_char (start);
+                       start_offset++;
+                       last_blank = current;
+               } else if ((*current == ',')||(*current == ';')) {
+                       gint *start_index, *end_index;
+                       start_index = g_new0(gint, 1);
+                       end_index = g_new0(gint, 1);
+                       *start_index = start_offset;
+                       *end_index = current_offset;
+                       *start_indexes = g_slist_prepend (*start_indexes, start_index);
+                       *end_indexes = g_slist_prepend (*end_indexes, end_index);
+                       start = g_utf8_next_char (current);
+                       start_offset = current_offset + 1;
+                       last_blank = start;
+               } else if (*current == '"') {
+                       current = g_utf8_next_char (current);
+                       current_offset ++;
+                       while ((*current != '"')&&(*current != '\0')) {
+                               current = g_utf8_next_char (current);
+                               current_offset ++;
+                       }
+               }
+                               
+               current = g_utf8_next_char (current);
+               current_offset ++;
+       }
+
+       if (start != current) {
+                       gint *start_index, *end_index;
+                       start_index = g_new0(gint, 1);
+                       end_index = g_new0(gint, 1);
+                       *start_index = start_offset;
+                       *end_index = current_offset;
+                       *start_indexes = g_slist_prepend (*start_indexes, start_index);
+                       *end_indexes = g_slist_prepend (*end_indexes, end_index);
+       }
+       
+       *start_indexes = g_slist_reverse (*start_indexes);
+       *end_indexes = g_slist_reverse (*end_indexes);
+
+       return;
+}
 
 GSList *
 modest_text_utils_split_addresses_list (const gchar *addresses)
 
 GSList *
 modest_text_utils_split_addresses_list (const gchar *addresses)
@@ -393,25 +450,25 @@ modest_text_utils_split_addresses_list (const gchar *addresses)
        last_blank = start;
 
        while (*current != '\0') {
        last_blank = start;
 
        while (*current != '\0') {
-               if ((start == current)&&((*current == ' ')||(*current == ','))) {
-                       start++;
+               if ((start == current)&&((*current == ' ')||(*current == ',')||(*current == ';'))) {
+                       start = g_utf8_next_char (start);
                        last_blank = current;
                        last_blank = current;
-               } else if (*current == ',') {
+               } else if ((*current == ',')||(*current == ';')) {
                        gchar *new_address = NULL;
                        new_address = g_strndup (start, current - last_blank);
                        result = g_slist_prepend (result, new_address);
                        gchar *new_address = NULL;
                        new_address = g_strndup (start, current - last_blank);
                        result = g_slist_prepend (result, new_address);
-                       start = current + 1;
+                       start = g_utf8_next_char (current);
                        last_blank = start;
                } else if (*current == '\"') {
                        if (current == start) {
                        last_blank = start;
                } else if (*current == '\"') {
                        if (current == start) {
-                               current++;
-                               start++;
+                               current = g_utf8_next_char (current);
+                               start = g_utf8_next_char (start);
                        }
                        while ((*current != '\"')&&(*current != '\0'))
                        }
                        while ((*current != '\"')&&(*current != '\0'))
-                               current++;
+                               current = g_utf8_next_char (current);
                }
                                
                }
                                
-               current++;
+               current = g_utf8_next_char (current);
        }
 
        if (start != current) {
        }
 
        if (start != current) {
@@ -979,42 +1036,41 @@ modest_text_utils_validate_email_address (const gchar *email_address)
 gboolean 
 modest_text_utils_validate_recipient (const gchar *recipient)
 {
 gboolean 
 modest_text_utils_validate_recipient (const gchar *recipient)
 {
-       gchar *stripped;
+       gchar *stripped, *current;
        gchar *right_part;
        gchar *right_part;
-       gint i = 0;
        gboolean has_error = FALSE;
 
        if (modest_text_utils_validate_email_address (recipient))
                return TRUE;
        stripped = g_strdup (recipient);
        stripped = g_strstrip (stripped);
        gboolean has_error = FALSE;
 
        if (modest_text_utils_validate_email_address (recipient))
                return TRUE;
        stripped = g_strdup (recipient);
        stripped = g_strstrip (stripped);
+       current = stripped;
 
 
-       if (stripped[0] == '\0') {
+       if (*current == '\0') {
                g_free (stripped);
                return FALSE;
        }
 
        /* quoted string */
                g_free (stripped);
                return FALSE;
        }
 
        /* quoted string */
-       if (stripped[0] == '\"') {
-               i = 1;
+       if (*current == '\"') {
+               current = g_utf8_next_char (current);
                has_error = TRUE;
                has_error = TRUE;
-               for (i = 1; stripped[i] != '\0'; i++) {
-                       if (stripped[i] == '\\') {
-                               if (stripped[i+1] >=0) {
-                                       i++;
-                               } else {
+               for (; *current != '\0'; current = g_utf8_next_char (current)) {
+                       if (*current == '\\') {
+                               if (current[1] <0) {
                                        has_error = TRUE;
                                        break;
                                }
                                        has_error = TRUE;
                                        break;
                                }
-                       } else if (stripped[i] == '\"') {
+                       } else if (*current == '\"') {
                                has_error = FALSE;
                                has_error = FALSE;
+                               current = g_utf8_next_char (current);
                                break;
                        }
                }
        } else {
                has_error = TRUE;
                                break;
                        }
                }
        } else {
                has_error = TRUE;
-               for (i = 0; stripped[i] != '\0'; i++) {
-                       if (stripped[i] == ' ') {
+               for (current = stripped ; *current != '\0'; current = g_utf8_next_char (current)) {
+                       if (*current == '<') {
                                has_error = FALSE;
                                break;
                        }
                                has_error = FALSE;
                                break;
                        }
@@ -1026,9 +1082,10 @@ modest_text_utils_validate_recipient (const gchar *recipient)
                return FALSE;
        }
 
                return FALSE;
        }
 
-       right_part = g_strdup (stripped + i);
+       right_part = g_strdup (current);
        g_free (stripped);
        right_part = g_strstrip (right_part);
        g_free (stripped);
        right_part = g_strstrip (right_part);
+
        if (g_str_has_prefix (right_part, "<") &&
            g_str_has_suffix (right_part, ">")) {
                gchar *address;
        if (g_str_has_prefix (right_part, "<") &&
            g_str_has_suffix (right_part, ">")) {
                gchar *address;
@@ -1053,8 +1110,6 @@ modest_text_utils_get_display_size (guint size)
        const guint MB=1024 * KB;
        const guint GB=1024 * MB;
 
        const guint MB=1024 * KB;
        const guint GB=1024 * MB;
 
-       g_message ("SIZE: %d",size);
-
        if (0 < size && size < KB)
                return g_strdup_printf (_FM("sfil_li_size_kb"), 1);
        else if (KB <= size && size < 100 * KB)
        if (0 < size && size < KB)
                return g_strdup_printf (_FM("sfil_li_size_kb"), 1);
        else if (KB <= size && size < 100 * KB)
index 80e12a0..555e08c 100644 (file)
@@ -279,4 +279,17 @@ gboolean     modest_text_utils_validate_recipient (const gchar *recipient);
  **/
 GSList      *modest_text_utils_split_addresses_list (const gchar *addresses);
 
  **/
 GSList      *modest_text_utils_split_addresses_list (const gchar *addresses);
 
+/**
+ * modest_text_utils_get_addresses_indexes:
+ * @addresses: a string
+ * @start_indexes: a #GSList pointer
+ * @end_indexes: a #GSList pointer
+ *
+ * obtains two #GSList of @addresses with the range offsets of the addresses in
+ * the string
+ *
+ * Returns: a GSList of strings
+ **/
+void         modest_text_utils_get_addresses_indexes (const gchar *addresses, GSList **start_indexes, GSList **end_indexes);
+
 #endif /* __MODEST_TEXT_UTILS_H__ */
 #endif /* __MODEST_TEXT_UTILS_H__ */
index 748ceb2..2fd335f 100644 (file)
@@ -1227,6 +1227,9 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
        ModestAccountMgr *account_mgr;
 
        g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
        ModestAccountMgr *account_mgr;
 
        g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
+
+       if (!modest_msg_edit_window_check_names (edit_window))
+               return;
        
        data = modest_msg_edit_window_get_msg_data (edit_window);
 
        
        data = modest_msg_edit_window_get_msg_data (edit_window);
 
@@ -2034,6 +2037,13 @@ modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *wi
        modest_msg_edit_window_select_contacts (window);
 }
 
        modest_msg_edit_window_select_contacts (window);
 }
 
+void
+modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
+{
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       modest_msg_edit_window_check_names (window);
+}
+
 
 static GtkWidget*
 create_move_to_dialog (ModestWindow *win,
 
 static GtkWidget*
 create_move_to_dialog (ModestWindow *win,
index 5341e71..3723ace 100644 (file)
@@ -53,6 +53,8 @@ void     modest_ui_actions_on_add_to_contacts   (GtkAction *action, ModestWindow
 
 void     modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *win);
 
 
 void     modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *win);
 
+void     modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *win);
+
 void     modest_ui_actions_on_new_msg       (GtkAction *action, ModestWindow *win);
 
 void     modest_ui_actions_on_open           (GtkAction *action, ModestWindow *win);
 void     modest_ui_actions_on_new_msg       (GtkAction *action, ModestWindow *win);
 
 void     modest_ui_actions_on_open           (GtkAction *action, ModestWindow *win);
index c216ef8..274096f 100644 (file)
@@ -68,6 +68,7 @@ static const GtkActionEntry modest_msg_edit_action_entries [] = {
        { "SelectAll", NULL, N_("mcen_me_viewer_selectall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_select_all)},
        { "SelectFont", NULL, N_("mcen_me_editor_font"), NULL, NULL, G_CALLBACK (modest_ui_actions_msg_edit_on_select_font)},
        { "SelectContacts", NULL, N_("mcen_me_editor_selectrecipients"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_select_contacts)},
        { "SelectAll", NULL, N_("mcen_me_viewer_selectall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_select_all)},
        { "SelectFont", NULL, N_("mcen_me_editor_font"), NULL, NULL, G_CALLBACK (modest_ui_actions_msg_edit_on_select_font)},
        { "SelectContacts", NULL, N_("mcen_me_editor_selectrecipients"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_select_contacts)},
+       { "CheckNames", NULL, N_("mcen_me_editor_checknames"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_check_names)},
        { "CloseWindow", NULL, N_("mcen_me_inbox_close_window"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_close_window)},
        { "CloseAllWindows", NULL, N_("mcen_me_inbox_close_windows"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_quit) },
 
        { "CloseWindow", NULL, N_("mcen_me_inbox_close_window"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_close_window)},
        { "CloseAllWindows", NULL, N_("mcen_me_inbox_close_windows"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_quit) },
 
index 2fad497..597cfd7 100644 (file)
@@ -269,6 +269,17 @@ void            modest_msg_edit_window_undo               (ModestMsgEditWindow *
  */
 void            modest_msg_edit_window_select_contacts    (ModestMsgEditWindow *window);
 
  */
 void            modest_msg_edit_window_select_contacts    (ModestMsgEditWindow *window);
 
+/**
+ * modest_msg_edit_window_check_names:
+ * @window: a #ModestMsgEditWindow
+ *
+ * Validates all the recipients, and shows (if required) dialogs for adding contacts
+ * or fixing problems in specific fields.
+ *
+ * Returns: %TRUE if all fields were validated, %FALSE otherwise
+ */
+gboolean        modest_msg_edit_window_check_names    (ModestMsgEditWindow *window);
+
 G_END_DECLS
 
 #endif /* __MODEST_MSG_EDIT_WINDOW_H__ */
 G_END_DECLS
 
 #endif /* __MODEST_MSG_EDIT_WINDOW_H__ */
index 6f4d1a1..643c2ac 100644 (file)
@@ -99,7 +99,7 @@ static gunichar iter_previous_char (GtkTextIter *iter);
 static GtkTextTag *prev_iter_has_recipient (GtkTextIter *iter);
 /* static GtkTextTag *next_iter_has_recipient (GtkTextIter *iter); */
 static void select_tag_of_iter (GtkTextIter *iter, GtkTextTag *tag);
 static GtkTextTag *prev_iter_has_recipient (GtkTextIter *iter);
 /* static GtkTextTag *next_iter_has_recipient (GtkTextIter *iter); */
 static void select_tag_of_iter (GtkTextIter *iter, GtkTextTag *tag);
-
+static gboolean quote_opened (GtkTextIter *iter);
 
 /**
  * modest_recpt_editor_new:
 
 /**
  * modest_recpt_editor_new:
@@ -231,6 +231,52 @@ modest_recpt_editor_add_resolved_recipient (ModestRecptEditor *recpt_editor, GSL
 
 }
 
 
 }
 
+void 
+modest_recpt_editor_replace_with_resolved_recipient (ModestRecptEditor *recpt_editor, 
+                                                    GtkTextIter *start, GtkTextIter *end,
+                                                    GSList *email_list, const gchar * recipient_id)
+{
+       ModestRecptEditorPrivate *priv;
+       GtkTextBuffer *buffer;
+       GtkTextTag *tag;
+       GSList *node;
+       gboolean is_first_recipient = TRUE;
+
+       g_return_if_fail (MODEST_IS_RECPT_EDITOR (recpt_editor));
+       priv = MODEST_RECPT_EDITOR_GET_PRIVATE (recpt_editor);
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+       g_signal_handlers_block_by_func (buffer, modest_recpt_editor_on_insert_text, recpt_editor);
+
+       gtk_text_buffer_delete (buffer, start, end);
+
+       tag = gtk_text_buffer_create_tag (buffer, NULL, 
+                                         "underline", PANGO_UNDERLINE_SINGLE,
+                                         "wrap-mode", GTK_WRAP_NONE,
+                                         "editable", TRUE, NULL);
+
+       g_object_set_data (G_OBJECT (tag), "recipient-tag-id", GINT_TO_POINTER (RECIPIENT_TAG_ID));
+       g_object_set_data_full (G_OBJECT (tag), "recipient-id", g_strdup (recipient_id), (GDestroyNotify) g_free);
+
+       for (node = email_list; node != NULL; node = g_slist_next (node)) {
+               gchar *recipient = (gchar *) node->data;
+
+               if ((recipient) && (strlen (recipient) != 0)) {
+
+                       if (!is_first_recipient)
+                       gtk_text_buffer_insert (buffer, start, "\n", -1);
+
+                       gtk_text_buffer_insert_with_tags (buffer, start, recipient, -1, tag, NULL);
+
+                       if (node->next != NULL)
+                               gtk_text_buffer_insert (buffer, start, ";", -1);
+                       is_first_recipient = FALSE;
+               }
+       }
+       g_signal_handlers_unblock_by_func (buffer, modest_recpt_editor_on_insert_text, recpt_editor);
+
+}
+
 
 const gchar *
 modest_recpt_editor_get_recipients (ModestRecptEditor *recpt_editor)
 
 const gchar *
 modest_recpt_editor_get_recipients (ModestRecptEditor *recpt_editor)
@@ -254,9 +300,10 @@ modest_recpt_editor_get_recipients (ModestRecptEditor *recpt_editor)
        gtk_text_buffer_get_end_iter (buffer, &end);
 
        priv->recipients = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
        gtk_text_buffer_get_end_iter (buffer, &end);
 
        priv->recipients = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
-       for (c = priv->recipients; *c == '\0'; c++) {
-               if (*c == '\n')
+       for (c = priv->recipients; *c != '\0'; c = g_utf8_next_char (c)) {
+               if (*c == '\n') {
                        *c = ' ';
                        *c = ' ';
+               }
        }
 
        return priv->recipients;
        }
 
        return priv->recipients;
@@ -388,7 +435,6 @@ modest_recpt_editor_on_focus_in (GtkTextView *text_view,
                                 ModestRecptEditor *editor)
 {
        ModestRecptEditorPrivate *priv = MODEST_RECPT_EDITOR_GET_PRIVATE (editor);
                                 ModestRecptEditor *editor)
 {
        ModestRecptEditorPrivate *priv = MODEST_RECPT_EDITOR_GET_PRIVATE (editor);
-       modest_recpt_editor_move_cursor_to_end (editor);
        gtk_text_view_place_cursor_onscreen (GTK_TEXT_VIEW (priv->text_view));
 }
 
        gtk_text_view_place_cursor_onscreen (GTK_TEXT_VIEW (priv->text_view));
 }
 
@@ -417,7 +463,7 @@ modest_recpt_editor_on_insert_text (GtkTextBuffer *buffer,
                        return;
                prev_char = gtk_text_iter_get_char (&prev);
                g_signal_handlers_block_by_func (buffer, modest_recpt_editor_on_insert_text, editor);
                        return;
                prev_char = gtk_text_iter_get_char (&prev);
                g_signal_handlers_block_by_func (buffer, modest_recpt_editor_on_insert_text, editor);
-               if (prev_char == ';'||prev_char == ',') {
+               if ((prev_char == ';'||prev_char == ',')&&(!quote_opened(location))) {
                        GtkTextMark *insert;
                        gtk_text_buffer_insert (buffer, location, "\n",-1);
                        insert = gtk_text_buffer_get_insert (buffer);
                        GtkTextMark *insert;
                        gtk_text_buffer_insert (buffer, location, "\n",-1);
                        insert = gtk_text_buffer_get_insert (buffer);
@@ -502,6 +548,31 @@ select_tag_of_iter (GtkTextIter *iter, GtkTextTag *tag)
        gtk_text_buffer_select_range (gtk_text_iter_get_buffer (iter), &start, &end);
 }
 
        gtk_text_buffer_select_range (gtk_text_iter_get_buffer (iter), &start, &end);
 }
 
+static gboolean 
+quote_opened (GtkTextIter *iter)
+{
+       GtkTextIter start;
+       GtkTextBuffer *buffer;
+       gboolean opened = FALSE;
+
+       buffer = gtk_text_iter_get_buffer (iter);
+       gtk_text_buffer_get_start_iter (buffer, &start);
+
+       while (!gtk_text_iter_equal (&start, iter)) {
+               gunichar current_char = gtk_text_iter_get_char (&start);
+               if (current_char == '"')
+                       opened = !opened;
+               else if (current_char == '\\')
+                       gtk_text_iter_forward_char (&start);
+               if (!gtk_text_iter_equal (&start, iter))
+                       gtk_text_iter_forward_char (&start);
+                       
+       }
+       return opened;
+
+}
+
+
 static gboolean
 modest_recpt_editor_on_key_press_event (GtkTextView *text_view,
                                          GdkEventKey *key,
 static gboolean
 modest_recpt_editor_on_key_press_event (GtkTextView *text_view,
                                          GdkEventKey *key,
index f84dae8..0956a50 100644 (file)
@@ -68,7 +68,13 @@ GtkWidget* modest_recpt_editor_new (void);
 void modest_recpt_editor_set_recipients (ModestRecptEditor *recpt_editor, const gchar *recipients);
 const gchar *modest_recpt_editor_get_recipients (ModestRecptEditor *repct_editor);
 void modest_recpt_editor_add_recipients (ModestRecptEditor *recpt_editor, const gchar *recipients);
 void modest_recpt_editor_set_recipients (ModestRecptEditor *recpt_editor, const gchar *recipients);
 const gchar *modest_recpt_editor_get_recipients (ModestRecptEditor *repct_editor);
 void modest_recpt_editor_add_recipients (ModestRecptEditor *recpt_editor, const gchar *recipients);
-void modest_recpt_editor_add_resolved_recipient (ModestRecptEditor *recpt_editor, GSList *email_list, const gchar * recipient_id);
+void modest_recpt_editor_add_resolved_recipient (ModestRecptEditor *recpt_editor, 
+                                                GSList *email_list, 
+                                                const gchar * recipient_id);
+void modest_recpt_editor_replace_with_resolved_recipient (ModestRecptEditor *recpt_editor, 
+                                                         GtkTextIter *start, GtkTextIter *end,
+                                                         GSList *email_list, 
+                                                         const gchar *recipient_id);
 
 void modest_recpt_editor_set_field_size_group (ModestRecptEditor *recpt_editor, GtkSizeGroup *size_group);
 GtkTextBuffer *modest_recpt_editor_get_buffer (ModestRecptEditor *recpt_editor);
 
 void modest_recpt_editor_set_field_size_group (ModestRecptEditor *recpt_editor, GtkSizeGroup *size_group);
 GtkTextBuffer *modest_recpt_editor_get_buffer (ModestRecptEditor *recpt_editor);