2005-12-05 [paul] 1.9.100cvs61
[claws.git] / src / compose.c
index 877034d33793e6ebb00c7a00ada38722d24c665c..abb9a0ca1bee046b09bad50e0730f30ed0ddc354 100644 (file)
@@ -632,9 +632,6 @@ static GtkItemFactoryEntry compose_entries[] =
                                        NULL, compose_check_backwards , 0, NULL},
        {N_("/_Spelling/_Forward to next misspelled word"),
                                        NULL, compose_check_forwards_go, 0, NULL},
-       {N_("/_Spelling/---"),          NULL, NULL, 0, "<Separator>"},
-       {N_("/_Spelling/_Spelling Configuration"),
-                                       NULL, NULL, 0, "<Branch>"},
 #endif
        {N_("/_Options"),               NULL, NULL, 0, "<Branch>"},
        {N_("/_Options/Privacy System"),                NULL, NULL,   0, "<Branch>"},
@@ -673,6 +670,8 @@ static GtkItemFactoryEntry compose_entries[] =
         ENC_ACTION(C_ISO_8859_1)},
        {N_("/_Options/Character _encoding/Western European (ISO-8859-15)"),
         ENC_ACTION(C_ISO_8859_15)},
+       {N_("/_Options/Character _encoding/Western European (Windows-1252)"),
+        ENC_ACTION(C_WINDOWS_1252)},
        {N_("/_Options/Character _encoding/---"), NULL, NULL, 0, "<Separator>"},
 
        {N_("/_Options/Character _encoding/Central European (ISO-8859-_2)"),
@@ -1125,8 +1124,6 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        PrefsAccount *reply_account;
        GtkTextView *textview;
        GtkTextBuffer *textbuf;
-       GtkTextIter iter;
-       int cursor_pos;
 
        g_return_val_if_fail(msginfo != NULL, NULL);
        g_return_val_if_fail(msginfo->folder != NULL, NULL);
@@ -1210,11 +1207,6 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        if (account->auto_sig)
                compose_insert_sig(compose, FALSE);
 
-       cursor_pos = quote_fmt_get_cursor_pos();
-       gtk_text_buffer_get_start_iter(textbuf, &iter);
-       gtk_text_buffer_get_iter_at_offset(textbuf, &iter, cursor_pos);
-       gtk_text_buffer_place_cursor(textbuf, &iter);
-       
        compose_wrap_all(compose);
 
        gtk_widget_grab_focus(compose->text);
@@ -1427,7 +1419,7 @@ static gboolean compose_is_sig_separator(Compose *compose, GtkTextBuffer *textbu
        GtkTextIter start = *iter;
        GtkTextIter end_iter;
        int start_pos = gtk_text_iter_get_offset(&start);
-
+       gchar *str = NULL;
        if (!compose->account->sig_sep)
                return FALSE;
        
@@ -1435,19 +1427,23 @@ static gboolean compose_is_sig_separator(Compose *compose, GtkTextBuffer *textbu
                start_pos+strlen(compose->account->sig_sep));
 
        /* check sig separator */
-       if (!strcmp(gtk_text_iter_get_text(&start, &end_iter),
-                       compose->account->sig_sep)) {
+       str = gtk_text_iter_get_text(&start, &end_iter);
+       if (!strcmp(str, compose->account->sig_sep)) {
+               gchar *tmp = NULL;
                /* check end of line (\n) */
                gtk_text_buffer_get_iter_at_offset(textbuf, &start,
                        start_pos+strlen(compose->account->sig_sep));
                gtk_text_buffer_get_iter_at_offset(textbuf, &end_iter,
                        start_pos+strlen(compose->account->sig_sep)+1);
-
-               if (!strcmp(gtk_text_iter_get_text(&start, &end_iter),"\n"));
+               tmp = gtk_text_iter_get_text(&start, &end_iter);
+               if (!strcmp(tmp,"\n")) {
+                       g_free(str);
+                       g_free(tmp);
                        return TRUE;
-               
-
+               }
+               g_free(tmp);    
        }
+       g_free(str);
 
        return FALSE;
 }
@@ -1568,6 +1564,14 @@ void compose_reedit(MsgInfo *msginfo)
                        gtk_editable_delete_text(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
                        gtk_editable_insert_text(GTK_EDITABLE(compose->savemsg_entry), &queueheader_buf[4], strlen(&queueheader_buf[4]), &startpos);
                }
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "RRCPT:")) {
+                       gint active = atoi(&queueheader_buf[strlen("RRCPT:")]);
+                       if (active) {
+                               GtkItemFactory *ifactory;
+                               ifactory = gtk_item_factory_from_widget(compose->menubar);
+                               menu_set_active(ifactory, "/Options/Request Return Receipt", TRUE);
+                       }
+               }
        }
        
        if (compose_parse_header(compose, msginfo) < 0) return;
@@ -2101,14 +2105,16 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
        gint len;
        gboolean prev_autowrap;
        const gchar *trimmed_body = body;
+       gint cursor_pos = 0;
        GtkTextView *text = GTK_TEXT_VIEW(compose->text);
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
+       GtkTextIter iter;
        
        if (!msginfo)
                msginfo = &dummyinfo;
 
        if (qmark != NULL) {
-               quote_fmt_init(msginfo, NULL, NULL);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE);
                quote_fmt_scan_string(qmark);
                quote_fmt_parse();
 
@@ -2124,7 +2130,7 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
                        && trimmed_body[0]=='\n')
                        *trimmed_body++;
 
-               quote_fmt_init(msginfo, quote_str, trimmed_body);
+               quote_fmt_init(msginfo, quote_str, trimmed_body, FALSE);
                quote_fmt_scan_string(fmt);
                quote_fmt_parse();
 
@@ -2147,8 +2153,6 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
                                compose);
        for (p = buf; *p != '\0'; ) {
                GtkTextMark *mark;
-               GtkTextIter iter;
-
                
                mark = gtk_text_buffer_get_insert(buffer);
                gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
@@ -2176,6 +2180,12 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
                        break;
        }
 
+       cursor_pos = quote_fmt_get_cursor_pos();
+       gtk_text_buffer_get_start_iter(buffer, &iter);
+       gtk_text_buffer_get_iter_at_offset(buffer, &iter, cursor_pos);
+       gtk_text_buffer_place_cursor(buffer, &iter);
+       
+
        compose->autowrap = prev_autowrap;
        if (compose->autowrap)
                compose_wrap_all(compose);
@@ -2191,6 +2201,59 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
        return buf;
 }
 
+/* if ml_post is of type addr@host and from is of type
+ * addr-anything@host, return TRUE
+ */
+static gboolean is_subscription(const gchar *ml_post, const gchar *from)
+{
+       gchar *left_ml = NULL;
+       gchar *right_ml = NULL;
+       gchar *left_from = NULL;
+       gchar *right_from = NULL;
+       gboolean result = FALSE;
+       
+       if (!ml_post || !from)
+               return FALSE;
+       
+       left_ml = g_strdup(ml_post);
+       if (strstr(left_ml, "@")) {
+               right_ml = strstr(left_ml, "@")+1;
+               *(strstr(left_ml, "@")) = '\0';
+       }
+       
+       left_from = g_strdup(from);
+       if (strstr(left_from, "@")) {
+               right_from = strstr(left_from, "@")+1;
+               *(strstr(left_from, "@")) = '\0';
+       }
+       
+       if (left_ml && left_from && right_ml && right_from
+       &&  !strncmp(left_from, left_ml, strlen(left_ml))
+       &&  !strcmp(right_from, right_ml)) {
+               result = TRUE;
+       }
+       g_free(left_ml);
+       g_free(left_from);
+       
+       return result;
+}
+
+static gboolean same_address(const gchar *addr1, const gchar *addr2)
+{
+       gchar *my_addr1, *my_addr2;
+       
+       if (!addr1 || !addr2)
+               return FALSE;
+
+       Xstrdup_a(my_addr1, addr1, return FALSE);
+       Xstrdup_a(my_addr2, addr2, return FALSE);
+       
+       extract_address(my_addr1);
+       extract_address(my_addr2);
+       
+       return !strcmp(my_addr1, my_addr2);
+}
+
 static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                    gboolean to_all, gboolean to_ml,
                                    gboolean to_sender,
@@ -2202,32 +2265,45 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
        gchar *replyto = NULL;
        GHashTable *to_table;
 
+       gboolean reply_to_ml = FALSE;
+       gboolean default_reply_to = FALSE;
+
        g_return_if_fail(compose->account != NULL);
        g_return_if_fail(msginfo != NULL);
 
+       reply_to_ml = to_ml && compose->ml_post;
+
+       default_reply_to = msginfo->folder && 
+               msginfo->folder->prefs->enable_default_reply_to;
+
        if (compose->account->protocol != A_NNTP) {
-               if (to_ml && compose->ml_post
-                   && !(msginfo->folder && 
-                        msginfo->folder->prefs->enable_default_reply_to)) {
-                       compose_entry_append(compose,
+               if (reply_to_ml && !default_reply_to) {
+                       
+                       gboolean is_subscr = is_subscription(compose->ml_post,
+                                                            msginfo->from);
+                       if (!is_subscr) {
+                               /* normal answer to ml post with a reply-to */
+                               compose_entry_append(compose,
                                           compose->ml_post,
                                           COMPOSE_TO);
-                       if (compose->replyto) {
-                               gchar *tmp1 = NULL, *tmp2 = NULL;
-                               Xstrdup_a(tmp1, compose->replyto, return);
-                               if (compose->ml_post)
-                                       Xstrdup_a(tmp2, compose->ml_post, return);
-                               extract_address(tmp1);
-                               extract_address(tmp2);
-                               if (tmp1 && tmp2 && strcmp(tmp1, tmp2))
+                               if (compose->replyto
+                               &&  !same_address(compose->ml_post, compose->replyto))
                                        compose_entry_append(compose,
-                                                       compose->replyto,
-                                                       COMPOSE_CC);
+                                               compose->replyto,
+                                               COMPOSE_CC);
+                       } else {
+                               /* answer to subscription confirmation */
+                               if (compose->replyto)
+                                       compose_entry_append(compose,
+                                               compose->replyto,
+                                               COMPOSE_TO);
+                               else if (msginfo->from)
+                                       compose_entry_append(compose,
+                                               msginfo->from,
+                                               COMPOSE_TO);
                        }
                }
-               else if (!(to_all || to_sender)
-                        && msginfo->folder
-                        && msginfo->folder->prefs->enable_default_reply_to) {
+               else if (!(to_all || to_sender) && default_reply_to) {
                        compose_entry_append(compose,
                            msginfo->folder->prefs->default_reply_to,
                            COMPOSE_TO);
@@ -3189,7 +3265,8 @@ static void compose_beautify_paragraph(Compose *compose, GtkTextIter *par_iter,
                        gboolean  (*parse)      (const gchar *start,
                                                 const gchar *scanpos,
                                                 const gchar **bp_,
-                                                const gchar **ep_);
+                                                const gchar **ep_,
+                                                gboolean hdr);
                        /* part to URI function */
                        gchar    *(*build_uri)  (const gchar *bp,
                                                 const gchar *ep);
@@ -3305,7 +3382,8 @@ colorize:
                bp = ep = 0;
                if (scanpos) {
                        /* check if URI can be parsed */
-                       if (parser[last_index].parse(walk, scanpos, (const gchar **)&bp,(const gchar **)&ep)
+                       if (parser[last_index].parse(walk, scanpos, (const gchar **)&bp,
+                                       (const gchar **)&ep, FALSE)
                            && (size_t) (ep - bp - 1) > strlen(parser[last_index].needle)) {
                                        walk = ep;
                        } else
@@ -3402,11 +3480,8 @@ static void compose_set_title(Compose *compose)
        if (subject && strlen(subject))
                str = g_strdup_printf(_("%s - Compose message%s"),
                                      subject, edited); 
-       else if (compose->account && compose->account->address)
-               str = g_strdup_printf(_("%s - Compose message%s"),
-                                     compose->account->address, edited);
        else
-               str = g_strdup_printf(_("Compose message%s"), edited);
+               str = g_strdup_printf(_("[no subject] - Compose message%s"), edited);
        gtk_window_set_title(GTK_WINDOW(compose->window), str);
        g_free(str);
        g_free(subject);
@@ -4315,6 +4390,10 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                fprintf(fp, "SCF:%s\n", savefolderid);
                g_free(savefolderid);
        }
+       /* Save copy folder */
+       if (compose->return_receipt) {
+               fprintf(fp, "RRCPT:1\n");
+       }
        /* Message-ID of message replying to */
        if ((compose->replyinfo != NULL) && (compose->replyinfo->msgid != NULL)) {
                gchar *folderid;
@@ -5076,7 +5155,7 @@ static GtkWidget *compose_create_others(Compose *compose)
                g_free(folderidentifier);
        }
 
-       savemsg_select = gtk_button_new_with_label (_("Select ..."));
+       savemsg_select = gtkut_get_browse_file_btn(_("_Browse"));
        gtk_widget_show(savemsg_select);
        gtk_table_attach(GTK_TABLE(table), savemsg_select, 2, 3, rowcount, rowcount + 1, GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
        g_signal_connect(G_OBJECT(savemsg_select), "clicked",
@@ -5146,6 +5225,21 @@ static gboolean text_clicked(GtkWidget *text, GdkEventButton *event,
 {
        gint prev_autowrap;
        GtkTextBuffer *buffer;
+#if USE_ASPELL
+       if (event->button == 3) {
+               GtkTextIter iter;
+               gint x, y;
+               /* move the cursor to allow GtkAspell to check the word
+                * under the mouse */
+               gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(text),
+                       GTK_TEXT_WINDOW_TEXT, event->x, event->y,
+                       &x, &y);
+               gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW(text),
+                       &iter, x, y);
+               gtk_text_buffer_place_cursor (GTK_TEXT_VIEW(text)->buffer, &iter);
+               return FALSE; /* pass the event so that the right-click goes through */
+       }
+#endif
        if (event->button == 2) {
                BLOCK_WRAP();
                entry_paste_clipboard(compose, compose->focused_editable, 
@@ -5265,7 +5359,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
 
        vbox2 = gtk_vbox_new(FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 0);
-       gtk_container_set_border_width(GTK_CONTAINER(vbox2), BORDER_WIDTH);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox2), 0);
        
        /* Notebook */
        notebook = gtk_notebook_new();
@@ -5284,20 +5378,20 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        gtk_widget_show(subject_hbox);
 
        subject_frame = gtk_frame_new(NULL);
-       gtk_frame_set_shadow_type(GTK_FRAME(subject_frame), GTK_SHADOW_OUT);
-       gtk_box_pack_start(GTK_BOX(subject_hbox), subject_frame, TRUE, TRUE, BORDER_WIDTH+1);
+       gtk_frame_set_shadow_type(GTK_FRAME(subject_frame), GTK_SHADOW_NONE);
+       gtk_box_pack_start(GTK_BOX(subject_hbox), subject_frame, TRUE, TRUE, 0);
        gtk_widget_show(subject_frame);
 
        subject = gtk_hbox_new(FALSE, 0);
-       gtk_container_set_border_width(GTK_CONTAINER(subject), BORDER_WIDTH);
+       gtk_container_set_border_width(GTK_CONTAINER(subject), 0);
        gtk_widget_show(subject);
 
        label = gtk_label_new(_("Subject:"));
-       gtk_box_pack_start(GTK_BOX(subject), label, FALSE, FALSE, 4);
+       gtk_box_pack_start(GTK_BOX(subject), label, FALSE, FALSE, 0);
        gtk_widget_show(label);
 
        subject_entry = gtk_entry_new();
-       gtk_box_pack_start(GTK_BOX(subject), subject_entry, TRUE, TRUE, 2);
+       gtk_box_pack_start(GTK_BOX(subject), subject_entry, TRUE, TRUE, 0);
        g_signal_connect_after(G_OBJECT(subject_entry), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        gtk_widget_show(subject_entry);
@@ -5491,9 +5585,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                                                gtkaspell_checkers_strerror());
                                gtkaspell_checkers_reset_error();
                        } else {
-
-                               GtkWidget *menuitem;
-
                                if (!gtkaspell_set_sug_mode(gtkaspell,
                                                prefs_common.aspell_sugmode)) {
                                        debug_print("Aspell: could not set "
@@ -5502,9 +5593,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                                        gtkaspell_checkers_reset_error();
                                }
 
-                               menuitem = gtk_item_factory_get_item(ifactory,
-                                       "/Spelling/Spelling Configuration");
-                               gtkaspell_populate_submenu(gtkaspell, menuitem);
                                menu_set_sensitive(ifactory, "/Spelling", TRUE);
                        }
                }
@@ -5991,6 +6079,9 @@ static void compose_destroy(Compose *compose)
        g_free(compose->exteditor_file);
 
        g_free(compose->orig_charset);
+
+       g_free(compose->privacy_system);
+
        if (addressbook_get_target_compose() == compose)
                addressbook_set_target_compose(NULL);
 
@@ -6886,6 +6977,9 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                fprintf(fp, "SCF:%s\n", savefolderid);
                g_free(savefolderid);
        }
+       if (compose->return_receipt) {
+               fprintf(fp, "RRCPT:1\n");
+       }
        if (compose->privacy_system) {
                fprintf(fp, "X-Sylpheed-Sign:%d\n", compose->use_signing);
                fprintf(fp, "X-Sylpheed-Encrypt:%d\n", compose->use_encryption);
@@ -7772,19 +7866,23 @@ static void compose_insert_drag_received_cb (GtkWidget          *widget,
        if (gdk_atom_name(data->type) && !strcmp(gdk_atom_name(data->type), "text/uri-list")) {
                list = uri_list_extract_filenames((const gchar *)data->data);
                for (tmp = list; tmp != NULL; tmp = tmp->next) {
-                               compose_insert_file(compose, (const gchar *)tmp->data);
+                       compose_insert_file(compose, (const gchar *)tmp->data);
                }
                list_free_strings(list);
                g_list_free(list);
                gtk_drag_finish(drag_context, TRUE, FALSE, time);
                return;
        } else {
+#if GTK_CHECK_VERSION(2, 8, 0)
+               /* do nothing, handled by GTK */
+#else
                gchar *tmpfile = get_tmp_file();
                str_write_to_file((const gchar *)data->data, tmpfile);
                compose_insert_file(compose, tmpfile);
                g_unlink(tmpfile);
                g_free(tmpfile);
                gtk_drag_finish(drag_context, TRUE, FALSE, time);
+#endif
                return;
        }
        gtk_drag_finish(drag_context, TRUE, FALSE, time);