fixed compilation bug in prefs_common.c
[claws.git] / src / compose.c
index eeeea48030fe5988be3473d4706a8cb0a451305f..2a72431cd94b6620f052ea81a5d6d345da924803 100644 (file)
@@ -98,6 +98,7 @@
 #include "gtkshruler.h"
 #include "folder.h"
 #include "addr_compl.h"
+#include "template_select.h"
 
 #if USE_GPGME
 #  include "rfc2015.h"
@@ -241,6 +242,10 @@ static void toolbar_linewrap_cb            (GtkWidget      *widget,
                                         gpointer        data);
 static void toolbar_address_cb         (GtkWidget      *widget,
                                         gpointer        data);
+static void template_select_cb         (gpointer        daat,
+                                        guint           action,
+                                        GtkWidget      *widget);
+
 
 static void select_account(Compose * compose, PrefsAccount * ac);
 static void account_activated          (GtkMenuItem    *menuitem,
@@ -388,6 +393,10 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                                  gboolean ignore_replyto,
                                  gboolean followup_and_reply_to);
 
+Compose * compose_generic_new (PrefsAccount    *account,
+                              const gchar      *to,
+                              FolderItem       *item);
+
 static GtkItemFactoryEntry compose_popup_entries[] =
 {
        {N_("/_Add..."),        NULL, compose_attach_cb, 0, NULL},
@@ -444,6 +453,7 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_Tool"),                  NULL, NULL,     0, "<Branch>"},
        {N_("/_Tool/Show _ruler"),      NULL, compose_toggle_ruler_cb,  0, "<ToggleItem>"},
        {N_("/_Tool/_Address book"),    "<alt>A",       compose_address_cb, 0, NULL},
+       {N_("/_Tool/_Templates ..."),   NULL, template_select_cb, 0, NULL},
        {N_("/_Help"),                  NULL, NULL,     0, "<LastBranch>"},
        {N_("/_Help/_About"),           NULL,           about_show,     0, NULL}
 };
@@ -455,10 +465,20 @@ static GtkTargetEntry compose_mime_types[] =
 
 Compose * compose_new(PrefsAccount *account)
 {
-       return compose_new_with_recipient(account, NULL);
+       return compose_generic_new(account, NULL, NULL);
 }
 
 Compose * compose_new_with_recipient(PrefsAccount *account, const gchar *to)
+{
+       return compose_generic_new(account, to, NULL);
+}
+
+Compose * compose_new_with_folderitem(PrefsAccount *account, FolderItem *item)
+{
+       return compose_generic_new(account, NULL, item);
+}
+
+Compose * compose_generic_new(PrefsAccount *account, const gchar *to, FolderItem *item)
 {
        Compose *compose;
 
@@ -467,6 +487,7 @@ Compose * compose_new_with_recipient(PrefsAccount *account, const gchar *to)
 
        compose = compose_create(account);
        compose->mode = COMPOSE_NEW;
+       compose->replyinfo = NULL;
 
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
@@ -477,8 +498,19 @@ Compose * compose_new_with_recipient(PrefsAccount *account, const gchar *to)
                if (to) {
                        compose_entry_append(compose, to, COMPOSE_TO);
                        gtk_widget_grab_focus(compose->subject_entry);
-               } else
-                       gtk_widget_grab_focus(compose->to_entry);
+               } else {
+                       if(item && item->prefs->enable_default_to) {
+                               compose_entry_append(compose, item->prefs->default_to, COMPOSE_TO);
+                       } else {
+                               gtk_widget_grab_focus(compose->to_entry);
+                       }
+               }
+               if(item && item->prefs->request_return_receipt) {
+                       GtkItemFactory *ifactory;
+               
+                       ifactory = gtk_item_factory_from_widget(compose->menubar);
+                       menu_set_toggle(ifactory, "/Message/Request Return Receipt", TRUE);
+               }
        } else {
                if (to) {
                        compose_entry_append(compose, to, COMPOSE_NEWSGROUPS);
@@ -551,13 +583,11 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        g_return_if_fail(msginfo->folder != NULL);
 
        account = msginfo->folder->folder->account;
-       if (!account && msginfo->to && prefs_common.reply_account_autoselect) {
+       if (!account && msginfo->to && prefs_common.reply_account_autosel) {
                gchar *to;
-
-               to = g_strdup(msginfo->to);
+               Xstrdup_a(to, msginfo->to, return);
                extract_address(to);
-               account = account_find_mail_from_address(to);
-               g_free(to);
+               account = account_find_from_address(to);
        }
        if (!account) account = cur_account;
        g_return_if_fail(account != NULL);
@@ -565,21 +595,21 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        if (ignore_replyto && account->protocol == A_NNTP &&
            !followup_and_reply_to) {
                reply_account =
-                       account_find_mail_from_address(account->address);
+                       account_find_from_address(account->address);
                if (!reply_account)
                        reply_account = compose_current_mail_account();
                if (!reply_account)
                        return;
        } else
                reply_account = account;
-
-       MSG_UNSET_FLAGS(msginfo->flags, MSG_FORWARDED);
-       MSG_SET_FLAGS(msginfo->flags, MSG_REPLIED);
+       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_FORWARDED);
+       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_REPLIED);
 
        CHANGE_FLAGS(msginfo);
 
        compose = compose_create(reply_account);
        compose->mode = COMPOSE_REPLY;
+       compose->replyinfo = msginfo;
 
 
        if (followup_and_reply_to) {
@@ -715,7 +745,7 @@ static void compose_attach_parts(Compose * compose,
 
                if (!MSG_IS_ENCRYPTED(msginfo->flags) &&
                    rfc2015_is_encrypted(mimeinfo)) {
-                       MSG_SET_FLAGS(msginfo->flags, MSG_ENCRYPTED);
+                       MSG_SET_TMP_FLAGS(msginfo->flags, MSG_ENCRYPTED);
                }
                if (MSG_IS_ENCRYPTED(msginfo->flags) &&
                    !msginfo->plaintext_file  &&
@@ -881,9 +911,8 @@ Compose * compose_forward(PrefsAccount * account, MsgInfo *msginfo,
        }
        g_return_val_if_fail(account != NULL, NULL);
 
-       MSG_UNSET_FLAGS(msginfo->flags, MSG_REPLIED);
-       MSG_SET_FLAGS(msginfo->flags, MSG_FORWARDED);
-
+       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_REPLIED);
+       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_FORWARDED);
        CHANGE_FLAGS(msginfo);
 
        compose = compose_create(account);
@@ -1409,6 +1438,10 @@ static gchar *compose_quote_parse_fmt(Compose *compose, MsgInfo *msginfo,
                                str = msginfo->to;
                                sp++;
                                break;
+                       case 'c':
+                               str = msginfo->cc;
+                               sp++;
+                               break;
                        case 'i':
                                if (!msginfo->msgid) {sp++; break;}
                                Xalloca(str, strlen(msginfo->msgid) + 3,
@@ -1596,6 +1629,49 @@ static void compose_reedit_set_entry(Compose *compose, MsgInfo *msginfo)
 
 #undef SET_ENTRY
 
+static void compose_exec_sig(Compose *compose, gchar *sigfile)
+{
+       FILE *tmpfp;
+       pid_t thepid;
+       gchar *sigtext;
+       FILE  *sigprg;
+       gchar  *buf;
+       size_t buf_len = 128;
+       if (strlen(sigfile) < 2)
+         return;
+       sigprg = popen(sigfile+1, "r");
+       if (sigprg) {
+
+               buf = g_malloc(buf_len);
+
+               if (!buf) {
+                       gtk_stext_insert(GTK_STEXT(compose->text), NULL, NULL, NULL, \
+                       "Unable to insert signature (malloc failed)\n", -1);
+
+                       pclose(sigprg);
+                       return;
+               }
+
+               while (!feof(sigprg)) {
+                       bzero(buf, buf_len);
+                       fread(buf, buf_len-1, 1, sigprg);
+                       gtk_stext_insert(GTK_STEXT(compose->text), NULL, NULL, NULL, buf, -1);
+               }
+
+               g_free(buf);
+               pclose(sigprg);
+       }
+       else
+       {
+               gtk_stext_insert(GTK_STEXT(compose->text), NULL, NULL, NULL, \
+               "Can't exec file: ", -1);
+               gtk_stext_insert(GTK_STEXT(compose->text), NULL, NULL, NULL, \
+               sigfile+1, -1);
+       }
+}
+
 static void compose_insert_sig(Compose *compose)
 {
        gchar *sigfile;
@@ -1607,7 +1683,7 @@ static void compose_insert_sig(Compose *compose)
                                      DEFAULT_SIGNATURE, NULL);
        }
 
-       if (!is_file_or_fifo_exist(sigfile)) {
+       if (!is_file_or_fifo_exist(sigfile) & (sigfile[0] != '|')) {
                g_free(sigfile);
                return;
        }
@@ -1620,7 +1696,14 @@ static void compose_insert_sig(Compose *compose)
                                "\n", 1);
        }
 
-       compose_insert_file(compose, sigfile);
+       if (sigfile[0] == '|')
+       {
+               compose_exec_sig(compose, sigfile);
+       }
+       else
+       {
+               compose_insert_file(compose, sigfile);
+       }
        g_free(sigfile);
 }
 
@@ -1936,6 +2019,8 @@ gint compose_send(Compose *compose)
                        ac = compose->account;
                else if (compose->orig_account->protocol != A_NNTP)
                        ac = compose->orig_account;
+               else if (cur_account && cur_account->protocol != A_NNTP)
+                       ac = cur_account;
                else {
                        ac = compose_current_mail_account();
                        if (!ac) {
@@ -2191,7 +2276,8 @@ static gint compose_save_to_outbox(Compose *compose, const gchar *file)
                MsgInfo newmsginfo;
 
                newmsginfo.msgnum = num;
-               newmsginfo.flags = 0;
+               newmsginfo.flags.perm_flags = 0;
+               newmsginfo.flags.tmp_flags = 0;
                procmsg_write_flags(&newmsginfo, fp);
                fclose(fp);
        }
@@ -2301,7 +2387,8 @@ static gint compose_queue(Compose *compose, const gchar *file)
                MsgInfo newmsginfo;
 
                newmsginfo.msgnum = num;
-               newmsginfo.flags = 0;
+               newmsginfo.flags.perm_flags = 0;
+               newmsginfo.flags.tmp_flags = 0;
                procmsg_write_flags(&newmsginfo, fp);
                fclose(fp);
        }
@@ -2404,7 +2491,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                get_rfc822_date(buf, sizeof(buf));
                fprintf(fp, "Date: %s\n", buf);
        }
-       
+
        /* From */
        if (!IS_IN_CUSTOM_HEADER("From")) {
                if (compose->account->name && *compose->account->name) {
@@ -2439,7 +2526,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                        }
                }
        }
-       
+
        slist_free_strings(compose->newsgroup_list);
        g_slist_free(compose->newsgroup_list);
        compose->newsgroup_list = NULL;
@@ -2483,7 +2570,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                        }
                }
        }
-       
+
        /* Bcc */
        if (compose->use_bcc) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->bcc_entry));
@@ -2613,7 +2700,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                                fprintf(fp, "%s: %s\n", chdr->name, buf);
                }
        }
-       
+
        /* MIME */
        fprintf(fp, "Mime-Version: 1.0\n");
        if (compose->use_attach) {
@@ -2962,9 +3049,12 @@ static Compose *compose_create(PrefsAccount *account)
                            (GTK_SCROLLED_WINDOW(scrolledwin)),
                            gtk_scrolled_window_get_vadjustment
                            (GTK_SCROLLED_WINDOW(scrolledwin)));
+       GTK_STEXT(text)->default_tab_width = 8;
        gtk_stext_set_editable(GTK_STEXT(text), TRUE);
-       gtk_stext_set_word_wrap(GTK_STEXT(text), TRUE);
-       gtk_stext_set_wrap_rmargin(GTK_STEXT(text), prefs_common.linewrap_len);
+       if (prefs_common.smart_wrapping) {      
+               gtk_stext_set_word_wrap(GTK_STEXT(text), TRUE);
+               gtk_stext_set_wrap_rmargin(GTK_STEXT(text), prefs_common.linewrap_len);
+       }               
 
        gtk_container_add(GTK_CONTAINER(scrolledwin), text);
 
@@ -2995,7 +3085,7 @@ static Compose *compose_create(PrefsAccount *account)
 
        style = gtk_widget_get_style(text);
 
-       /* workaround for the slow down of GtkSText when using Pixmap theme */
+       /* workaround for the slow down of GtkText when using Pixmap theme */
        if (style->engine) {
                GtkThemeEngine *engine;
 
@@ -3246,12 +3336,12 @@ static Compose *compose_create(PrefsAccount *account)
 }
 
 #include "pixmaps/stock_mail_send.xpm"
+#include "pixmaps/stock_mail_send_queue.xpm"
 #include "pixmaps/stock_mail.xpm"
 #include "pixmaps/stock_paste.xpm"
 #include "pixmaps/stock_mail_attach.xpm"
 #include "pixmaps/stock_mail_compose.xpm"
 #include "pixmaps/linewrap.xpm"
-//#include "pixmaps/tb_mail_queue_send.xpm"
 #include "pixmaps/tb_address_book.xpm"
 
 #define CREATE_TOOLBAR_ICON(xpm_d) \
@@ -3293,8 +3383,8 @@ static void compose_toolbar_create(Compose *compose, GtkWidget *container)
                                           "Send",
                                           icon_wid, toolbar_send_cb, compose);
 
-       CREATE_TOOLBAR_ICON(stock_mail_send_xpm);
-       //CREATE_TOOLBAR_ICON(tb_mail_queue_send_xpm);
+       CREATE_TOOLBAR_ICON(stock_mail_send_queue_xpm);
+       /* CREATE_TOOLBAR_ICON(tb_mail_queue_send_xpm); */
        sendl_btn = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
                                           _("Send later"),
                                           _("Put into queue folder and send later"),
@@ -3406,8 +3496,8 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
 
                if (ac == compose->account) def_menu = num;
 
-               name = g_strdup_printf("%s <%s> (%s)",
-                                      ac->name, ac->address, ac->account_name);
+               name = g_strdup_printf("%s: %s <%s>",
+                                      ac->account_name, ac->name, ac->address);
                MENUITEM_ADD(menu, menuitem, name, ac);
                g_free(name);
                gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
@@ -4316,7 +4406,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
 
        g_free(tmp);
 
-       //folderview_scan_folder_a(DRAFT_DIR, TRUE);
+       /* folderview_scan_folder_a(DRAFT_DIR, TRUE); */
 
        gtk_widget_destroy(compose->window);
 }
@@ -4324,24 +4414,40 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
 static void compose_attach_cb(gpointer data, guint action, GtkWidget *widget)
 {
        Compose *compose = (Compose *)data;
-       gchar *file;
+       GList *file_list;
 
-       file = filesel_select_file(_("Select file"), NULL);
+       file_list = filesel_select_multiple_files(_("Select file"), NULL);
 
-       if (file)
-               compose_attach_append(compose, file, MIME_UNKNOWN);
+       if (file_list) {
+               GList *tmp;
+
+               for ( tmp = file_list; tmp; tmp = tmp->next) {
+                       gchar *file = (gchar *) tmp->data;
+                       compose_attach_append(compose, file, MIME_UNKNOWN);
+                       g_free(file);
+               }
+               g_list_free(file_list);
+       }               
 }
 
 static void compose_insert_file_cb(gpointer data, guint action,
                                   GtkWidget *widget)
 {
        Compose *compose = (Compose *)data;
-       gchar *file;
+       GList *file_list;
 
-       file = filesel_select_file(_("Select file"), NULL);
+       file_list = filesel_select_multiple_files(_("Select file"), NULL);
 
-       if (file)
-               compose_insert_file(compose, file);
+       if (file_list) {
+               GList *tmp;
+
+               for ( tmp = file_list; tmp; tmp = tmp->next) {
+                       gchar *file = (gchar *) tmp->data;
+                       compose_insert_file(compose, file);
+                       g_free(file);
+               }
+               g_list_free(file_list);
+       }
 }
 
 static gint compose_delete_cb(GtkWidget *widget, GdkEventAny *event,
@@ -4788,3 +4894,62 @@ static gchar *compose_quote_fmt          (Compose        *compose,
 
        return quote_fmt_get_buffer();
 }
+
+static void template_apply_cb(gchar *s, gpointer data)
+{
+       Compose *compose = (Compose*)data;
+       GtkSText *text = GTK_STEXT(compose->text);
+       gchar *quote_str;
+       gchar *qmark;
+       gchar *parsed_text;
+       gchar *tmpl;
+       gchar *old_tmpl = s;
+
+       if(!s) return;
+       
+       if(compose->replyinfo == NULL) {
+               gtk_stext_freeze(text);
+               gtk_stext_set_point(text, 0);
+               gtk_stext_forward_delete(text, gtk_stext_get_length(text));
+               gtk_stext_insert(text, NULL, NULL, NULL, s, -1);
+               gtk_stext_thaw(text);
+               g_free(old_tmpl);
+               return;
+       }
+
+       parsed_text = g_new(gchar, strlen(s)*2 + 1);
+       tmpl = parsed_text;
+       while(*s) {
+               if (*s == '\n') {
+                       *parsed_text++ = '\\';
+                       *parsed_text++ = 'n';
+                       s++;
+               } else {
+                       *parsed_text++ = *s++;
+               }
+       }
+       *parsed_text = '\0';
+
+       if (prefs_common.quotemark && *prefs_common.quotemark)
+               qmark = prefs_common.quotemark;
+       else
+               qmark = "> ";
+
+       quote_str = compose_quote_fmt(compose, compose->replyinfo, tmpl, qmark);
+       if (quote_str != NULL) {
+               gtk_stext_freeze(text);
+               gtk_stext_set_point(text, 0);
+               gtk_stext_forward_delete(text, gtk_stext_get_length(text));
+               gtk_stext_insert(text, NULL, NULL, NULL, quote_str, -1);
+               gtk_stext_thaw(text);
+       }
+
+       g_free(old_tmpl);
+       g_free(tmpl);
+}
+
+static void template_select_cb(gpointer data, guint action,
+                              GtkWidget *widget)
+{
+       template_select(&template_apply_cb, data);
+}