Clone also proxy-related prefs in account_clone().
[claws.git] / src / account.c
index 2091d8f7b8ba062373ae2006012c006e75926179..b51e7b8943a53fc6292d4d772e2634bec6859d18 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
+ * Copyright (C) 1999-2015 Hiroyuki Yamamoto and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
+#include "claws-features.h"
 #endif
 
 #include "defs.h"
 #include "remotefolder.h"
 #include "manual.h"
 #include "filtering.h"
+#include "prefs_actions.h"
+#include "hooks.h"
+#include "passwordstore.h"
 
 enum {
-       ACCOUNT_IS_DEFAULT,             /* GDK_TYPE_PIXMAP! */
+       ACCOUNT_IS_DEFAULT,
        ACCOUNT_ENABLE_GET_ALL, 
        ACCOUNT_NAME,
        ACCOUNT_PROTOCOL,
@@ -74,8 +78,6 @@ typedef enum
 
 # define N_EDIT_ACCOUNT_COLS   5
 
-#define PREFSBUFSIZE           1024
-
 PrefsAccount *cur_account;
 
 static GList *account_list = NULL;
@@ -87,8 +89,6 @@ static struct EditAccount {
        GtkWidget *close_btn;
 } edit_account;
 
-static GdkPixbuf *mark_pixbuf;
-
 static void account_edit_create                (void);
 static void          account_destroy           (PrefsAccount   *ac_prefs);
 static void          account_set_as_default    (PrefsAccount   *ac_prefs);
@@ -113,7 +113,9 @@ static void account_size_allocate_cb(GtkWidget *widget,
 static gboolean account_key_pressed    (GtkWidget      *widget,
                                         GdkEventKey    *event,
                                         gpointer        data);
-
+static gboolean account_search_func_cb (GtkTreeModel *model, gint column, 
+                                               const gchar *key, GtkTreeIter *iter, 
+                                               gpointer search_data);
 static void account_list_view_add      (PrefsAccount   *ac_prefs);
 static void account_list_view_set      (void);
 
@@ -136,7 +138,6 @@ static void account_list_view_insert_account_item (GtkListStore     *list_store,
                                                   PrefsAccount *account_data);
 
 static GtkWidget *account_list_view_create     (void);
-static void account_create_list_view_images    (GtkWidget *list_view);
 static void account_create_list_view_columns   (GtkWidget *list_view);
 
 static gint account_list_view_get_selected_account_id          (GtkWidget *list_view);
@@ -181,7 +182,7 @@ static void account_row_changed_while_drag_drop     (GtkTreeModel *model,
                                                 gpointer      arg3,
                                                 GtkTreeView  *list_view);
 
-void account_flush_state(void)
+static void account_flush_state(void)
 {
        account_set_menu();
        main_window_reflect_prefs_all();
@@ -210,7 +211,7 @@ void account_read_config_all(void)
        while (fgets(buf, sizeof(buf), fp) != NULL) {
                if (!strncmp(buf, "[Account: ", 10)) {
                        strretchomp(buf);
-                       memmove(buf, buf + 1, strlen(buf));
+                       memmove(buf, buf + 1, sizeof(buf) - 1);
                        buf[strlen(buf) - 1] = '\0';
                        debug_print("Found label: %s\n", buf);
                        ac_label_list = g_slist_append(ac_label_list,
@@ -222,8 +223,7 @@ void account_read_config_all(void)
        /* read config data from file */
        cur_account = NULL;
        for (cur = ac_label_list; cur != NULL; cur = cur->next) {
-               ac_prefs = prefs_account_new();
-               prefs_account_read_config(ac_prefs, (gchar *)cur->data);
+               ac_prefs = prefs_account_new_from_config((gchar *)cur->data);
                account_list = g_list_append(account_list, ac_prefs);
                if (ac_prefs->is_default)
                        cur_account = ac_prefs;
@@ -283,8 +283,8 @@ PrefsAccount *account_find_from_smtp_server(const gchar *address,
        GList *cur;
        PrefsAccount *ac;
 
-       g_return_val_if_fail(address != NULL, NULL);
-       g_return_val_if_fail(smtp_server != NULL, NULL);
+       cm_return_val_if_fail(address != NULL, NULL);
+       cm_return_val_if_fail(smtp_server != NULL, NULL);
 
        for (cur = account_list; cur != NULL; cur = cur->next) {
                ac = (PrefsAccount *)cur->data;
@@ -300,20 +300,20 @@ PrefsAccount *account_find_from_smtp_server(const gchar *address,
  * account_find_from_address:
  * @address: Email address string.
  *
- * Find a mail (not news) account with the specified email address.
+ * Find a mail (not news if newsgroups_ok is FALSE) account with the specified email address.
  *
  * Return value: The found account, or NULL if not found.
  */
-PrefsAccount *account_find_from_address(const gchar *address)
+PrefsAccount *account_find_from_address(const gchar *address, gboolean newsgroups_ok)
 {
        GList *cur;
        PrefsAccount *ac;
 
-       g_return_val_if_fail(address != NULL, NULL);
+       cm_return_val_if_fail(address != NULL, NULL);
 
        for (cur = account_list; cur != NULL; cur = cur->next) {
                ac = (PrefsAccount *)cur->data;
-               if (ac->protocol != A_NNTP && ac->address &&
+               if ((ac->protocol != A_NNTP || newsgroups_ok) && ac->address &&
                    g_ascii_strcasecmp(address, ac->address) == 0)
                        return ac;
        }
@@ -339,7 +339,7 @@ PrefsAccount *account_find_from_item(FolderItem *item)
 {
        PrefsAccount *ac;
 
-       g_return_val_if_fail(item != NULL, NULL);
+       cm_return_val_if_fail(item != NULL, NULL);
 
        ac = item->account;
        if (!ac) {
@@ -373,7 +373,19 @@ GList *account_get_list(void)
        return account_list;
 }
 
-void account_edit_open(void)
+void account_edit_focus(void)
+{
+       if (edit_account.window == NULL) {
+               return;
+       }
+       manage_window_set_transient(GTK_WINDOW(edit_account.window));
+       gtk_widget_grab_focus(edit_account.close_btn);
+       gtk_widget_show(edit_account.window);
+       gtk_window_set_modal(GTK_WINDOW(edit_account.window), TRUE);
+       manage_window_focus_in(edit_account.window, NULL, NULL);
+}
+
+void account_edit_open(gpointer a, gpointer b)
 {
        inc_lock();
 
@@ -382,7 +394,7 @@ void account_edit_open(void)
        if (compose_get_compose_list()) {
                alertpanel_error(_("Some composing windows are open.\n"
                                   "Please close all the composing "
-                                  "windows before editing the accounts."));
+                                  "windows before editing accounts."));
                inc_unlock();
                return;
        }
@@ -394,11 +406,7 @@ void account_edit_open(void)
 
        account_list_view_set();
 
-       manage_window_set_transient(GTK_WINDOW(edit_account.window));
-       gtk_widget_grab_focus(edit_account.close_btn);
-       gtk_widget_show(edit_account.window);
-
-       manage_window_focus_in(edit_account.window, NULL, NULL);
+       account_edit_focus();
 }
 
 void account_add(void)
@@ -409,6 +417,8 @@ void account_add(void)
 
        if (!ac_prefs) return;
 
+       account_edit_focus();
+
        account_list = g_list_append(account_list, ac_prefs);
 
        if (ac_prefs->is_default)
@@ -440,13 +450,20 @@ void account_add(void)
        }
 }
 
-void account_open(PrefsAccount *ac_prefs)
+void account_open(PrefsAccount *ac_prefs, gboolean called_from_acc_list)
 {
        gboolean prev_default;
-       gchar *ac_name;
+       gchar *ac_name, *old_prefix, *new_prefix;
        gboolean account_dirty = FALSE;
 
-       g_return_if_fail(ac_prefs != NULL);
+       cm_return_if_fail(ac_prefs != NULL);
+
+       if (compose_get_compose_list()) {
+               alertpanel_error(_("Some composing windows are open.\n"
+                                  "Please close all the composing "
+                                  "windows before editing accounts."));
+               return;
+       }
 
        prev_default = ac_prefs->is_default;
        Xstrdup_a(ac_name, ac_prefs->account_name ? ac_prefs->account_name : "",
@@ -454,14 +471,27 @@ void account_open(PrefsAccount *ac_prefs)
 
        prefs_account_open(ac_prefs, &account_dirty);
 
+       if (called_from_acc_list)
+               account_edit_focus();
+
        if (account_dirty) {
                if (!prev_default && ac_prefs->is_default)
                        account_set_as_default(ac_prefs);
 
                if (ac_prefs->folder && strcmp2(ac_name, ac_prefs->account_name) != 0) {
+                       old_prefix = folder_get_identifier(FOLDER(ac_prefs->folder));
                        folder_set_name(FOLDER(ac_prefs->folder),
                                        ac_prefs->account_name);
                        folderview_set_all();
+                       folder_prefs_save_config_recursive(FOLDER(ac_prefs->folder));
+                       new_prefix = folder_get_identifier(FOLDER(ac_prefs->folder));
+
+                       account_rename_path(old_prefix, new_prefix);
+                       prefs_filtering_rename_path(old_prefix, new_prefix);
+                       prefs_actions_rename_path(old_prefix, new_prefix);
+                       
+                       g_free(old_prefix);
+                       g_free(new_prefix);
                }
 
                account_write_config_all();
@@ -558,14 +588,12 @@ void account_rename_path(const gchar *old_id, const gchar *new_id)
        }
 }
 
-#undef CHECK_CHANGE_FOLDER
-
 FolderItem *account_get_special_folder(PrefsAccount *ac_prefs,
                                       SpecialFolderItemType type)
 {
        FolderItem *item = NULL;
 
-       g_return_val_if_fail(ac_prefs != NULL, NULL);
+       cm_return_val_if_fail(ac_prefs != NULL, NULL);
 
        switch (type) {
        case F_INBOX:
@@ -639,11 +667,10 @@ FolderItem *account_get_special_folder(PrefsAccount *ac_prefs,
 
 void account_destroy(PrefsAccount *ac_prefs)
 {
-       g_return_if_fail(ac_prefs != NULL);
+       cm_return_if_fail(ac_prefs != NULL);
 
        folder_unref_account_all(ac_prefs);
 
-       prefs_account_free(ac_prefs);
        account_list = g_list_remove(account_list, ac_prefs);
 
        if (cur_account == ac_prefs) cur_account = NULL;
@@ -663,7 +690,7 @@ void account_destroy(PrefsAccount *ac_prefs)
 static void account_size_allocate_cb(GtkWidget *widget,
                                         GtkAllocation *allocation)
 {
-       g_return_if_fail(allocation != NULL);
+       cm_return_if_fail(allocation != NULL);
 
        prefs_common.accountswin_width = allocation->width;
        prefs_common.accountswin_height = allocation->height;
@@ -688,7 +715,7 @@ static void account_edit_create(void)
 
        GtkWidget *default_btn;
 
-       GtkWidget *hbbox;
+       GtkWidget *confirm_area;
        GtkWidget *help_btn;
        GtkWidget *close_btn;
 
@@ -699,15 +726,10 @@ static void account_edit_create(void)
        window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "account");
        gtk_container_set_border_width (GTK_CONTAINER (window), 8);
        gtk_window_set_title (GTK_WINDOW (window), _("Edit accounts"));
-       gtk_window_set_modal (GTK_WINDOW (window), TRUE);
        g_signal_connect (G_OBJECT (window), "delete_event",
                          G_CALLBACK (account_delete_event), NULL);
-#ifdef MAEMO
-       maemo_connect_key_press_to_mainwindow(GTK_WINDOW(window));
-#else
        g_signal_connect (G_OBJECT (window), "key_press_event",
                          G_CALLBACK (account_key_pressed), NULL);
-#endif                   
        MANAGE_WINDOW_SIGNALS_CONNECT (window);
        gtk_widget_realize(window);
 
@@ -721,9 +743,11 @@ static void account_edit_create(void)
 
        label = gtk_label_new
                (_("Using 'Get Mail' will retrieve messages from your Accounts "
-                  "in the order given, the checkbox in the 'G' column indicates "
-                  "which accounts will be included."));
+                  "in the order given, the checkbox indicates which accounts "
+                  "will be included. Bold text indicates the default account."));
        gtk_widget_show (label);
+       gtk_widget_set_size_request(GTK_WIDGET(label), 
+                                   prefs_common.accountswin_width-8, -1);
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
        gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
        gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
@@ -788,27 +812,19 @@ static void account_edit_create(void)
        gtk_widget_show (hbox);
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
-       vbox2 = gtk_vbox_new(FALSE, 0);
-       gtk_widget_show (vbox2);
-       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
-
        default_btn = gtk_button_new_with_mnemonic
                (_(" _Set as default account "));
        gtk_widget_show (default_btn);
-       gtk_box_pack_start (GTK_BOX (vbox2), default_btn, TRUE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (hbox), default_btn, FALSE, FALSE, 0);
        g_signal_connect (G_OBJECT(default_btn), "clicked",
                          G_CALLBACK (account_set_default), NULL);
 
-       hbbox = gtk_hbutton_box_new();
-       gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_END);
-       gtk_box_set_spacing(GTK_BOX(hbbox), 5);
-
-       gtkut_stock_button_set_create_with_help(&hbbox, &help_btn,
+       gtkut_stock_button_set_create_with_help(&confirm_area, &help_btn,
                        &close_btn, GTK_STOCK_CLOSE,
                        NULL, NULL, NULL, NULL);
-       gtk_widget_show(hbbox);
+       gtk_widget_show(confirm_area);
 
-       gtk_box_pack_end (GTK_BOX (hbox), hbbox, FALSE, FALSE, 0);
+       gtk_box_pack_end (GTK_BOX (hbox), confirm_area, FALSE, FALSE, 0);
        gtk_widget_grab_default (close_btn);
 
        g_signal_connect (G_OBJECT (close_btn), "clicked",
@@ -818,7 +834,6 @@ static void account_edit_create(void)
                        G_CALLBACK(manual_open_with_anchor_cb),
                        MANUAL_ANCHOR_ACCOUNTPREFS);
 
-       account_create_list_view_images(list_view);
 
        g_signal_connect(G_OBJECT(window), "size_allocate",
                         G_CALLBACK(account_size_allocate_cb), NULL);
@@ -832,13 +847,13 @@ static void account_edit_create(void)
                                      GDK_HINT_MIN_SIZE);
        gtk_widget_set_size_request(window, prefs_common.accountswin_width,
                                    prefs_common.accountswin_height);
+#ifdef G_OS_WIN32
+       gtk_window_move(GTK_WINDOW(window), 48, 48);
+#endif
 
        edit_account.window    = window;
        edit_account.list_view = list_view;
        edit_account.close_btn = close_btn;
-#ifdef MAEMO
-       maemo_window_full_screen_if_needed(GTK_WINDOW(edit_account.window));
-#endif
 }
 
 static void account_edit_prefs(GtkWidget *widget, gpointer data)
@@ -848,7 +863,7 @@ static void account_edit_prefs(GtkWidget *widget, gpointer data)
        ac_prefs = account_list_view_get_selected_account(edit_account.list_view);
        
        if (ac_prefs) {
-               account_open(ac_prefs);
+               account_open(ac_prefs, TRUE);
                account_list_view_set();
        }               
 }
@@ -858,7 +873,7 @@ static gboolean account_delete_references_func(GNode *node, gpointer data)
        FolderItem *item;
        gint account;
 
-       g_return_val_if_fail(node->data != NULL, FALSE);
+       cm_return_val_if_fail(node->data != NULL, FALSE);
 
        item = FOLDER_ITEM(node->data);
        account = GPOINTER_TO_INT(data);
@@ -924,12 +939,11 @@ static void account_clone(GtkWidget *widget, gpointer data)
        ACP_FASSIGN(ssl_smtp);
        ACP_FASSIGN(use_nonblocking_ssl);
        
-       ac_clon->tmp_pass = NULL;
-
        /* receive */
        ACP_FASSIGN(use_apop_auth);
        ACP_FASSIGN(rmmail);
        ACP_FASSIGN(msg_leave_time);
+       ACP_FASSIGN(msg_leave_hour);
        ACP_FASSIGN(recv_at_getall);
        ACP_FASSIGN(sd_rmmail_on_download);
        ACP_FASSIGN(enable_size_limit);
@@ -944,14 +958,13 @@ static void account_clone(GtkWidget *widget, gpointer data)
 
        /* send */
        ACP_FASSIGN(gen_msgid);
+       ACP_FASSIGN(gen_xmailer);
        ACP_FASSIGN(add_customhdr);
        ACP_FASSIGN(use_smtp_auth);
        ACP_FASSIGN(smtp_auth_type);
        ACP_FDUP(smtp_userid);
        ACP_FDUP(smtp_passwd);
 
-       ac_clon->tmp_smtp_pass = NULL;
-
        ACP_FASSIGN(pop_before_smtp);
        ACP_FASSIGN(pop_before_smtp_timeout);
        ACP_FASSIGN(last_pop_login_time);
@@ -1001,6 +1014,7 @@ static void account_clone(GtkWidget *widget, gpointer data)
         ACP_FASSIGN(default_encrypt);
        ACP_FASSIGN(default_encrypt_reply);
         ACP_FASSIGN(default_sign);
+       ACP_FASSIGN(default_sign_reply);
        ACP_FASSIGN(save_encrypted_as_clear_text);
        ACP_FASSIGN(encrypt_to_self);
        
@@ -1018,8 +1032,10 @@ static void account_clone(GtkWidget *widget, gpointer data)
         ACP_FASSIGN(mark_crosspost_read);
         ACP_FASSIGN(crosspost_col);
 
+#ifndef G_OS_WIN32
         ACP_FASSIGN(set_tunnelcmd);
         ACP_FDUP(tunnelcmd);
+#endif
 
         ACP_FDUP(imap_dir);
        ACP_FASSIGN(imap_subsonly);
@@ -1037,12 +1053,45 @@ static void account_clone(GtkWidget *widget, gpointer data)
        ac_clon->is_default = FALSE;
        ACP_FASSIGN(folder);
 
+       ACP_FASSIGN(config_version);
+
+       ACP_FASSIGN(use_proxy);
+       ACP_FASSIGN(use_default_proxy);
+       ACP_FASSIGN(use_proxy_for_send);
+       ACP_FASSIGN(proxy_info.proxy_type);
+       ACP_FDUP(proxy_info.proxy_host);
+       ACP_FASSIGN(proxy_info.proxy_port);
+       ACP_FASSIGN(proxy_info.use_proxy_auth);
+       ACP_FDUP(proxy_info.proxy_name);
+       ACP_FDUP(proxy_info.proxy_pass);
+
        account_list = g_list_append(account_list, ac_clon);
        account_list_view_set();
 }
 #undef ACP_FDUP
 #undef ACP_FASSIGN
 
+static void account_empty_cache(PrefsAccount *ac_prefs)
+{
+       gchar *cache_dir;
+
+       cache_dir = prefs_account_cache_dir(ac_prefs, FALSE);
+       if (cache_dir == NULL)
+               return; /* no cache dir, nothing to do */
+
+       if (is_dir_exist(cache_dir) && remove_dir_recursive(cache_dir) < 0) {
+               g_warning("can't remove directory '%s'", cache_dir);
+       } else {
+               gchar *server_dir =  prefs_account_cache_dir(ac_prefs, TRUE);
+               if (g_rmdir(server_dir) == 0)
+                       debug_print("Removed empty cache server directory\n");
+               else
+                       debug_print("Cache server directory not empty: not removed\n");
+               g_free(server_dir);
+       }
+       g_free(cache_dir);
+}
+
 static void account_delete(GtkWidget *widget, gpointer data)
 {
        PrefsAccount *ac_prefs;
@@ -1050,7 +1099,7 @@ static void account_delete(GtkWidget *widget, gpointer data)
        GList *list;
        Folder *folder;
        GSList *cur;
+
        ac_prefs = account_list_view_get_selected_account(edit_account.list_view);
        if (ac_prefs == NULL)
                return;
@@ -1060,8 +1109,8 @@ static void account_delete(GtkWidget *widget, gpointer data)
                   ac_prefs->account_name ? ac_prefs->account_name :
                   _("(Untitled)"));
        if (alertpanel_full(_("Delete account"), buf,
-                           GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
-                           NULL, ALERT_WARNING, G_ALERTDEFAULT) != G_ALERTALTERNATE)
+                           GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, ALERTFOCUS_FIRST, FALSE,
+                           NULL, ALERT_WARNING) != G_ALERTALTERNATE)
                return;
        account_list_dirty = TRUE;
 
@@ -1088,6 +1137,10 @@ static void account_delete(GtkWidget *widget, gpointer data)
                                GINT_TO_POINTER(ac_prefs->account_id));
        }
 
+       gchar *uid = g_strdup_printf("%d", ac_prefs->account_id);
+       passwd_store_delete_block(PWS_ACCOUNT, uid);
+       g_free(uid);
+
        debug_print("Removing filter rules relative to this account...\n");
        for(cur = filtering_rules ; cur != NULL ;) {
                FilteringProp * prop = (FilteringProp *) cur->data;
@@ -1103,6 +1156,10 @@ static void account_delete(GtkWidget *widget, gpointer data)
                        cur = g_slist_next(cur);
                }
        }
+
+       debug_print("Removing cache directory of this account...\n");
+       account_empty_cache(ac_prefs);
+
        folder_write_list();
 }
 
@@ -1220,7 +1277,7 @@ static void account_edit_close(GtkWidget *widget, gpointer data)
                account_flush_state();
 
        gtk_widget_hide(edit_account.window);
-
+       gtk_window_set_modal(GTK_WINDOW(edit_account.window), FALSE);
        inc_unlock();
 }
 
@@ -1234,11 +1291,28 @@ static gint account_delete_event(GtkWidget *widget, GdkEventAny *event,
 static gboolean account_key_pressed(GtkWidget *widget, GdkEventKey *event,
                                    gpointer data)
 {
-       if (event && event->keyval == GDK_Escape)
+       if (event && event->keyval == GDK_KEY_Escape)
                account_edit_close(NULL, NULL);
        return FALSE;
 }
 
+static gboolean account_search_func_cb (GtkTreeModel *model, gint column, const gchar *key, 
+                                               GtkTreeIter *iter, gpointer search_data) 
+{
+       gboolean retval;
+       PrefsAccount *ac;
+
+       gtk_tree_model_get (model, iter, ACCOUNT_DATA, &ac, -1);
+
+       if (!ac->name || !key) return FALSE;
+
+       retval = (strncmp (key, ac->account_name, strlen(key)) != 0);
+
+       debug_print("selecting row\n");
+       account_list_view_select_account(edit_account.list_view, ac->account_id);
+
+       return retval;
+}
 static void account_list_view_add(PrefsAccount *ac_prefs)
 {
        GtkTreeView *list_view = GTK_TREE_VIEW(edit_account.list_view);
@@ -1248,29 +1322,33 @@ static void account_list_view_add(PrefsAccount *ac_prefs)
        gboolean getall;
 
        name = ac_prefs->account_name;
-#if USE_OPENSSL
+#ifdef USE_GNUTLS
        protocol = ac_prefs->protocol == A_POP3 ?
                  (ac_prefs->ssl_pop == SSL_TUNNEL ?
-                  "POP3 (SSL)" :
+                  "POP (SSL/TLS)" :
                   ac_prefs->ssl_pop == SSL_STARTTLS ?
-                  "POP3 (TLS)" : "POP3") :
+                  "POP (STARTTLS)" : "POP") :
                   ac_prefs->protocol == A_IMAP4 ?
                  (ac_prefs->ssl_imap == SSL_TUNNEL ?
-                  "IMAP4 (SSL)" :
+                  "IMAP (SSL/TLS)" :
                   ac_prefs->ssl_imap == SSL_STARTTLS ?
-                  "IMAP4 (TLS)" : "IMAP4") :
+                  "IMAP (STARTTLS)" : "IMAP") :
                   ac_prefs->protocol == A_NNTP ?
                  (ac_prefs->ssl_nntp == SSL_TUNNEL ?
-                  "NNTP (SSL)" : "NNTP") :
-                  "";
+                  "NNTP (SSL/TLS)" : "NNTP") :
+                  ac_prefs->protocol == A_LOCAL ? "Local" :
+                  ac_prefs->protocol == A_NONE ?  "SMTP" : "-";
 #else
-       protocol = ac_prefs->protocol == A_POP3  ? "POP3" :
-                  ac_prefs->protocol == A_IMAP4 ? "IMAP4" :
+       protocol = ac_prefs->protocol == A_POP3  ? "POP" :
+                  ac_prefs->protocol == A_IMAP4 ? "IMAP" :
                   ac_prefs->protocol == A_LOCAL ? "Local" :
-                  ac_prefs->protocol == A_NNTP  ? "NNTP" : "";
+                  ac_prefs->protocol == A_NNTP  ? "NNTP" :
+                  ac_prefs->protocol == A_NONE ?  "SMTP" : "-";
 #endif
-       server= ac_prefs->protocol == A_NNTP
-               ? ac_prefs->nntp_server : ac_prefs->recv_server;
+       server= ac_prefs->protocol == A_NNTP ? ac_prefs->nntp_server :
+                  ac_prefs->protocol == A_LOCAL ?  "-" :
+                  ac_prefs->protocol == A_NONE ? ac_prefs->smtp_server :
+                  ac_prefs->recv_server;
 
        has_getallbox = (ac_prefs->protocol == A_POP3  ||
                         ac_prefs->protocol == A_IMAP4 ||
@@ -1331,7 +1409,7 @@ static void account_list_set(void)
                GtkTreeIter iter;
 
                if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) {
-                       g_warning("%s(%d) - no iter found???\n", __FILE__, __LINE__);                                         
+                       g_warning("%s(%d) - no iter found???", __FILE__, __LINE__);
                        continue;
                }
        
@@ -1358,41 +1436,54 @@ PrefsAccount *account_get_reply_account(MsgInfo *msginfo, gboolean reply_autosel
        /* select the account set in folderitem's property (if enabled) */
        if (msginfo->folder->prefs && msginfo->folder->prefs->enable_default_account)
                account = account_find_from_id(msginfo->folder->prefs->default_account);
-       
+       else if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
+                folder_has_parent_of_type(msginfo->folder, F_OUTBOX) ||
+                folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
+                       gchar *from = NULL;
+                       if (!procheader_get_header_from_msginfo
+                               (msginfo, &from, "From:")) {
+                               gchar *buf = from + strlen("From:");
+                               extract_address(buf);
+                               account = account_find_from_address(buf, FALSE);
+                       g_free(from);
+                       }
+       }
        /* select account by to: and cc: header if enabled */
        if (reply_autosel) {
                gchar * field = NULL;
                int fieldno = 0;
                for (field = msginfo->to; fieldno++ < 2; field = msginfo->cc) {
                        if (!account && field) {
-                               gchar *to = NULL;
-                               if (!strchr(field, ',')) {
-                                       Xstrdup_a(to, field, return NULL);
-                                       extract_address(to);
-                                       account = account_find_from_address(to);
-                               } else {
-                                       gchar **split = g_strsplit(field, ",", -1);
-                                       int i = -1;
+                               gchar *f = g_strdup(field);
+                               if (f) {
+                                       gchar *cur = f;
+                                       gchar *next = NULL;
+                                       gchar *to = NULL;
                                        do {
-                                               i++;
-                                               if (!split[i])
-                                                       break;
-                                               Xstrdup_a(to, split[i], return NULL);
+                                               next = strchr_with_skip_quote(cur, '"', ',');
+                                               if (next)
+                                                       (*next) = 0;
+                                               Xstrdup_a(to, cur, return NULL);
                                                extract_address(to);
-                                               account = account_find_from_address(to);
+                                               account = account_find_from_address(to, FALSE);
+                                               if (next)
+                                                       cur = next + 1;
+                                               else
+                                                       break;
                                        } while (!account);
-                                       g_strfreev(split);
+                                       g_free(f);
                                }
                        }
                }
                if (!account) {
-                       gchar deliveredto[BUFFSIZE];
+                       gchar *deliveredto = NULL;
                        if (!procheader_get_header_from_msginfo
-                               (msginfo, deliveredto,sizeof deliveredto , "Delivered-To:")) { 
+                               (msginfo, &deliveredto, "Delivered-To:")) {
                                gchar *buf = deliveredto + strlen("Delivered-To:");
                                extract_address(buf);
-                               account = account_find_from_address(buf);
-                       }
+                               account = account_find_from_address(buf, FALSE);
+                       g_free(deliveredto);
+                       }
                }
        }
 
@@ -1415,7 +1506,7 @@ PrefsAccount *account_get_reply_account(MsgInfo *msginfo, gboolean reply_autosel
 static GtkListStore* account_create_data_store(void)
 {
        return gtk_list_store_new(N_ACCOUNT_COLUMNS,
-                                GDK_TYPE_PIXBUF,       /* ACCOUNT_IS_DEFAULT */
+                                G_TYPE_INT,            /* ACCOUNT_IS_DEFAULT */
                                 G_TYPE_BOOLEAN,        /* ACCOUNT_ENABLE_GET_ALL */
                                 G_TYPE_STRING,         /* ACCOUNT_NAME */
                                 G_TYPE_STRING,         /* ACCOUNT_PROTOCOL */
@@ -1442,7 +1533,7 @@ static void account_list_view_insert_account_item(GtkListStore *list_store,
        
        gtk_list_store_append(list_store, &iter);
        gtk_list_store_set(list_store, &iter, 
-                          ACCOUNT_IS_DEFAULT,     is_default ? mark_pixbuf : NULL,
+                          ACCOUNT_IS_DEFAULT,     is_default ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
                           ACCOUNT_ENABLE_GET_ALL, is_get_all,
                           ACCOUNT_NAME,           account_name,
                           ACCOUNT_PROTOCOL,       protocol,
@@ -1454,7 +1545,6 @@ static void account_list_view_insert_account_item(GtkListStore *list_store,
 /*!
  *\brief       Create and set up account list view, including tasks like
  *             creating the data store (\ref account_create_data_store()),
- *             creating images for the list view (\ref account_create_list_view_images()),
  *             and setting up the account list's individual columns (\ref 
  *             account_create_list_view_columns()).
  *
@@ -1468,7 +1558,9 @@ static GtkWidget *account_list_view_create(void)
 
        list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)));
        g_object_unref(G_OBJECT(store));
-
+#ifdef GENERIC_UMPC
+       g_object_set(list_view, "allow-checkbox-mode", FALSE, NULL);
+#endif
        gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
        gtk_tree_view_set_reorderable(list_view, TRUE);
        
@@ -1495,26 +1587,10 @@ static GtkWidget *account_list_view_create(void)
        return GTK_WIDGET(list_view);
 }
 
-static void account_create_list_view_images(GtkWidget *list_view)
-{
-       stock_pixbuf_gdk(list_view, STOCK_PIXMAP_MARK, &mark_pixbuf);
-}
-
 static void account_create_list_view_columns(GtkWidget *list_view)
 {
        GtkTreeViewColumn *column;
        GtkCellRenderer *renderer;
-       GtkTooltips *tooltips = gtk_tooltips_new();
-
-       renderer = gtk_cell_renderer_pixbuf_new();
-       column = gtk_tree_view_column_new_with_attributes
-               (Q_("Accounts List Default Column Name|D"), renderer,
-                "pixbuf", ACCOUNT_IS_DEFAULT,
-                NULL);
-       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);           
-       gtk_tree_view_column_set_alignment (column, 0.5);
-       gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), column->button,
-                       _("Default account"), NULL);
 
        renderer = gtk_cell_renderer_toggle_new();
        g_object_set(renderer, 
@@ -1522,13 +1598,13 @@ static void account_create_list_view_columns(GtkWidget *list_view)
                     "activatable", TRUE,
                      NULL);
        column = gtk_tree_view_column_new_with_attributes
-               (Q_("Accounts List Get Column Name|G"), renderer,
+               (C_("Accounts List Get Column Name", "G"), renderer,
                 "active", ACCOUNT_ENABLE_GET_ALL,
                 NULL);
        gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
        gtk_tree_view_column_set_alignment (column, 0.5);
-       gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), column->button,
-                       _("'Get Mail' retrieves mail from the checked accounts"), NULL);
+       CLAWS_SET_TIP(gtk_tree_view_column_get_widget(column),
+                       _("'Get Mail' retrieves mail from the checked accounts"));
        g_signal_connect(G_OBJECT(renderer), "toggled",                      
                         G_CALLBACK(account_get_all_toggled),
                         list_view);
@@ -1537,6 +1613,7 @@ static void account_create_list_view_columns(GtkWidget *list_view)
        column = gtk_tree_view_column_new_with_attributes
                (_("Name"), renderer,
                 "text", ACCOUNT_NAME,
+                "weight", ACCOUNT_IS_DEFAULT,
                 NULL);
        gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
        
@@ -1544,6 +1621,7 @@ static void account_create_list_view_columns(GtkWidget *list_view)
        column = gtk_tree_view_column_new_with_attributes
                (_("Protocol"), renderer,
                 "text", ACCOUNT_PROTOCOL,
+                "weight", ACCOUNT_IS_DEFAULT,
                 NULL);
        gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);           
        
@@ -1551,7 +1629,10 @@ static void account_create_list_view_columns(GtkWidget *list_view)
        column = gtk_tree_view_column_new_with_attributes
                (_("Server"), renderer,
                 "text", ACCOUNT_SERVER,
+                "weight", ACCOUNT_IS_DEFAULT,
                 NULL);
+       gtk_tree_view_set_search_column(GTK_TREE_VIEW(list_view), ACCOUNT_NAME);
+       gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(list_view), account_search_func_cb , NULL, NULL);
        gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);           
 }
 
@@ -1560,19 +1641,13 @@ static void account_create_list_view_columns(GtkWidget *list_view)
  */
 static gint account_list_view_get_selected_account_id(GtkWidget *list_view)
 {
-       GtkTreeSelection *selector;
-       GtkTreeModel *model;
-       GtkTreeIter iter;
        PrefsAccount *res = NULL;
 
-       selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view));
-       
-       if (!gtk_tree_selection_get_selected(selector, &model, &iter))
-               return -1;
-
-       gtk_tree_model_get(model, &iter, ACCOUNT_DATA, &res, -1);
+       res = (PrefsAccount *)gtkut_tree_view_get_selected_pointer(
+                       GTK_TREE_VIEW(list_view), ACCOUNT_DATA,
+                       NULL, NULL, NULL);
 
-       return res->account_id;                    
+       return (res != NULL ? res->account_id : -1);
 }
 
 /*!
@@ -1598,19 +1673,12 @@ static GtkTreePath *account_list_view_get_selected_account_path(GtkWidget *list_
  */
 static PrefsAccount *account_list_view_get_selected_account(GtkWidget *list_view)
 {
-       GtkTreeSelection *selector;
-       GtkTreeModel *model;
-       GtkTreeIter iter;
-       PrefsAccount *res = NULL;
+       PrefsAccount *res =
+               (PrefsAccount *)gtkut_tree_view_get_selected_pointer(
+                       GTK_TREE_VIEW(list_view), ACCOUNT_DATA,
+                       NULL, NULL, NULL);
 
-       selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view));
-       
-       if (!gtk_tree_selection_get_selected(selector, &model, &iter))
-               return NULL;
-
-       gtk_tree_model_get(model, &iter, ACCOUNT_DATA, &res, -1);
-
-       return res;                        
+       return res;
 }
 
 /*!
@@ -1666,20 +1734,19 @@ static gboolean set_new_default_account(GtkTreeModel *model,
                                        gint         *account_id)
 {
        PrefsAccount *account = NULL;
-       GdkPixbuf *pixbuf;
+       PangoWeight weight;
        
        gtk_tree_model_get(model, iter, 
                           ACCOUNT_DATA, &account, 
                           -1);
 
        if (*account_id == account->account_id)
-               pixbuf = NULL;
+               weight = PANGO_WEIGHT_NORMAL;
        else
-               pixbuf = mark_pixbuf;
-       
+               weight = PANGO_WEIGHT_BOLD;
+
        gtk_list_store_set(GTK_LIST_STORE(model), iter, 
-                          ACCOUNT_IS_DEFAULT, pixbuf,
-                          -1);
+                          ACCOUNT_IS_DEFAULT, weight, -1);
 
        return FALSE;
 }
@@ -1778,3 +1845,165 @@ static void account_row_changed_while_drag_drop(GtkTreeModel *model,
 {      
        account_list_set();     
 }
+
+gchar *account_get_signature_str(PrefsAccount *account)
+{
+       gchar *sig_body = NULL;
+       gchar *sig_str = NULL;
+       gchar *utf8_sig_str = NULL;
+
+       cm_return_val_if_fail(account != NULL, NULL);
+
+       if (!account->sig_path)
+               return NULL;
+
+       if (account->sig_type == SIG_FILE) {
+               gchar *sig_full_path;
+               if (!g_path_is_absolute(account->sig_path)) {
+                       sig_full_path = g_build_filename(get_home_dir(), account->sig_path, NULL);
+               } else {
+                       sig_full_path = g_strdup(account->sig_path);
+               }
+
+               if (!is_file_or_fifo_exist(sig_full_path)) {
+                       g_warning("can't open signature file: '%s'", sig_full_path);
+                       g_free(sig_full_path);
+                       return NULL;
+               }
+
+               debug_print("Reading signature from file '%s'\n", sig_full_path);
+               gchar *tmp = file_read_to_str(sig_full_path);
+               g_free(sig_full_path);
+
+               if (!tmp)
+                       return NULL;
+
+               sig_body = normalize_newlines(tmp);
+               g_free(tmp);
+       } else {
+               sig_body = get_command_output(account->sig_path);
+       }
+
+       if (account->sig_sep) {
+               sig_str = g_strconcat("\n", account->sig_sep, "\n", sig_body,
+                                     NULL);
+               g_free(sig_body);
+       } else
+               sig_str = g_strconcat("\n", sig_body, NULL);
+
+       if (sig_str) {
+               if (g_utf8_validate(sig_str, -1, NULL) == TRUE)
+                       utf8_sig_str = sig_str;
+               else {
+                       utf8_sig_str = conv_codeset_strdup
+                               (sig_str, conv_get_locale_charset_str_no_utf8(),
+                                CS_INTERNAL);
+                       g_free(sig_str);
+               }
+       }
+
+       return utf8_sig_str;
+}
+
+PrefsAccount *account_get_cur_account (void)
+{
+       return cur_account;
+}
+
+gboolean password_get(const gchar *user,
+                   const gchar *server,
+                   const gchar *protocol,
+                   guint16 port,
+                   gchar **password)
+{
+       PasswordRequest req;
+
+       /* all have to be set */
+       cm_return_val_if_fail(user != NULL, FALSE);
+       cm_return_val_if_fail(server != NULL, FALSE);
+       cm_return_val_if_fail(protocol != NULL, FALSE);
+       cm_return_val_if_fail(port != 0, FALSE);
+
+       req.user = user;
+       req.server = server;
+       req.protocol = protocol;
+       req.port = port;
+
+       if (hooks_invoke(PASSWORD_GET_HOOKLIST, &req)) {
+               *password = req.password;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static GSList *account_signatures_list = NULL;
+
+/* create a list of unique signatures from accounts list */
+void account_signatures_matchlist_create(void)
+{
+       GList *cur_ac = NULL;
+       PrefsAccount *ac_prefs = NULL;
+
+       if (account_signatures_list)
+               return;
+
+       account_signatures_list = g_slist_prepend(account_signatures_list, g_strdup("-- "));
+       for (cur_ac = account_get_list();
+                cur_ac != NULL;
+                cur_ac = g_list_next(cur_ac)) {
+               ac_prefs = (PrefsAccount *)cur_ac->data;
+
+               if (ac_prefs->sig_sep && *ac_prefs->sig_sep != '\0') {
+                       if (!g_slist_find_custom(account_signatures_list, ac_prefs->sig_sep,
+                                       (GCompareFunc)strcmp2)) {
+                               account_signatures_list = g_slist_prepend(account_signatures_list,
+                                               g_strdup(ac_prefs->sig_sep));
+                       }
+               }
+       }
+}
+
+/* delete the list of signatures created by account_signatures_matchlist_create() */
+void account_signatures_matchlist_delete(void)
+{
+       if (account_signatures_list) {
+               slist_free_strings_full(account_signatures_list);
+               account_signatures_list = NULL;
+       }
+}
+
+/* match a string against all signatures in list, using the specified format */
+gboolean account_signatures_matchlist_str_found(const gchar *str, const gchar *format)
+{
+       gchar *tmp = NULL;
+       gboolean found = FALSE;
+       GSList *item;
+
+       for (item = account_signatures_list;
+                item != NULL && !found;
+                item = g_slist_next(item)) {
+               tmp = g_strdup_printf(format, (gchar *)item->data);
+               found = (strcmp(tmp, str) == 0);
+               g_free(tmp);
+       }
+       return found;
+}
+
+/* match M first char of a string against all signatures in list, using the specified format */
+gboolean account_signatures_matchlist_nchar_found(const gchar *str, const gchar *format)
+{
+       gchar *tmp = NULL;
+       gboolean found = FALSE;
+       GSList *item;
+       gint len;
+
+       for (item = account_signatures_list;
+                item != NULL && !found;
+                item = g_slist_next(item)) {
+               tmp = g_strdup_printf(format, (gchar *)item->data);
+               len = strlen(tmp);
+               found = (strncmp(tmp, str, len) == 0);
+               g_free(tmp);
+       }
+       return found;
+}