2006-03-21 [colin] 2.0.0cvs161
[claws.git] / src / compose.c
index 71a2c0aaf75ef758231e89661b434d6b21137c08..aea95b2d214c8b3bb13bc68d4191e3ab9a8f8d6f 100644 (file)
@@ -1189,11 +1189,17 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        menu_set_active(ifactory, "/Options/Remove references", FALSE);
        menu_set_sensitive(ifactory, "/Options/Remove references", TRUE);
 
+       compose->updating = TRUE;
        compose->replyinfo = procmsg_msginfo_get_full_info(msginfo);
-
        if (!compose->replyinfo)
                compose->replyinfo = procmsg_msginfo_copy(msginfo);
-       
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return NULL;
+       }
+
        compose_extract_original_charset(compose);
        
        if (msginfo->folder && msginfo->folder->ret_rcpt)
@@ -1292,9 +1298,16 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 
        compose = compose_create(account, COMPOSE_FORWARD, batch);
 
+       compose->updating = TRUE;
        compose->fwdinfo = procmsg_msginfo_get_full_info(msginfo);
        if (!compose->fwdinfo)
                compose->fwdinfo = procmsg_msginfo_copy(msginfo);
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return NULL;
+       }
 
        compose_extract_original_charset(compose);
 
@@ -1332,9 +1345,16 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                gchar *qmark;
                MsgInfo *full_msginfo;
 
+               compose->updating = TRUE;
                full_msginfo = procmsg_msginfo_get_full_info(msginfo);
                if (!full_msginfo)
                        full_msginfo = procmsg_msginfo_copy(msginfo);
+               compose->updating = FALSE;
+
+               if (compose->deferred_destroy) {
+                       compose_destroy(compose);
+                       return NULL;
+               }
 
                if (prefs_common.fw_quotemark &&
                    *prefs_common.fw_quotemark)
@@ -1426,7 +1446,14 @@ Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_list)
        
        undo_block(compose->undostruct);
        for (msginfo = msginfo_list; msginfo != NULL; msginfo = msginfo->next) {
+               compose->updating = TRUE;
                msgfile = procmsg_get_message_file_path((MsgInfo *)msginfo->data);
+               compose->updating = FALSE;
+               if (compose->deferred_destroy) {
+                       compose_destroy(compose);
+                       g_free(msgfile);
+                       return NULL;
+               }
                if (!is_file_exist(msgfile))
                        g_warning("%s: file not exist\n", msgfile);
                else
@@ -1538,8 +1565,9 @@ void compose_reedit(MsgInfo *msginfo)
        g_return_if_fail(msginfo != NULL);
        g_return_if_fail(msginfo->folder != NULL);
 
-       if (compose_put_existing_to_front(msginfo)) 
+       if (compose_put_existing_to_front(msginfo)) {
                return;
+       }
 
         if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
            folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
@@ -1586,17 +1614,20 @@ void compose_reedit(MsgInfo *msginfo)
                        param = atoi(&queueheader_buf[strlen("X-Priority: ")]); /* mind the space */
                        compose->priority = param;
                }
-       } else 
+       } else {
                account = msginfo->folder->folder->account;
+       }
 
        if (!account && prefs_common.reedit_account_autosel) {
                        gchar from[BUFFSIZE];
-               if (!procheader_get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")){
+               if (!procheader_get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")) {
                        extract_address(from);
                        account = account_find_from_address(from);
                 }
        }
-        if (!account) account = cur_account;
+        if (!account) {
+               account = cur_account;
+        }
        g_return_if_fail(account != NULL);
 
        compose = compose_create(account, COMPOSE_REEDIT, FALSE);
@@ -1608,7 +1639,15 @@ void compose_reedit(MsgInfo *msginfo)
        } else {
                activate_privacy_system(compose, account, FALSE);
        }
+
+       compose->updating = TRUE;
        compose->targetinfo = procmsg_msginfo_copy(msginfo);
+       compose->updating = FALSE;
+       
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return;
+       }
 
        compose_extract_original_charset(compose);
 
@@ -1634,7 +1673,9 @@ void compose_reedit(MsgInfo *msginfo)
                }
        }
        
-       if (compose_parse_header(compose, msginfo) < 0) return;
+       if (compose_parse_header(compose, msginfo) < 0) {
+               return;
+       }
        compose_reedit_set_entry(compose, msginfo);
 
        textview = GTK_TEXT_VIEW(compose->text);
@@ -1650,12 +1691,15 @@ void compose_reedit(MsgInfo *msginfo)
        
        if (procmime_msginfo_is_encrypted(msginfo)) {
                fp = procmime_get_first_encrypted_text_content(msginfo);
-               if (fp) 
+               if (fp) {
                        compose_force_encryption(compose, account, TRUE);
-       } else
+               }
+       } else {
                fp = procmime_get_first_text_content(msginfo);
-       if (fp == NULL)
+       }
+       if (fp == NULL) {
                g_warning("Can't get text part\n");
+       }
 
        if (fp != NULL) {
                gboolean prev_autowrap = compose->autowrap;
@@ -1680,8 +1724,9 @@ void compose_reedit(MsgInfo *msginfo)
 
        gtk_widget_grab_focus(compose->text);
 
-        if (prefs_common.auto_exteditor)
+        if (prefs_common.auto_exteditor) {
                compose_exec_ext_editor(compose);
+       }
        compose->modified = FALSE;
        compose_set_title(compose);
 }
@@ -1711,7 +1756,16 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
 
        gtk_widget_grab_focus(compose->header_last->entry);
 
+       compose->updating = TRUE;
        filename = procmsg_get_message_file_path(msginfo);
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               g_free(filename);
+               return NULL;
+       }
+
        if (filename == NULL)
                return NULL;
 
@@ -4523,7 +4577,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                gchar *folderid;
                
                folderid = folder_item_get_identifier(compose->replyinfo->folder);
-               fprintf(fp, "RMID:%s\x7f%d\x7f%s\n", folderid, compose->replyinfo->msgnum, compose->replyinfo->msgid);
+               fprintf(fp, "RMID:%s\t%d\t%s\n", folderid, compose->replyinfo->msgnum, compose->replyinfo->msgid);
                g_free(folderid);
        }
        /* Message-ID of message forwarding to */
@@ -4531,7 +4585,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                gchar *folderid;
                
                folderid = folder_item_get_identifier(compose->fwdinfo->folder);
-               fprintf(fp, "FMID:%s\x7f%d\x7f%s\n", folderid, compose->fwdinfo->msgnum, compose->fwdinfo->msgid);
+               fprintf(fp, "FMID:%s\t%d\t%s\n", folderid, compose->fwdinfo->msgnum, compose->fwdinfo->msgid);
                g_free(folderid);
        }
        fprintf(fp, "\n");
@@ -5320,7 +5374,7 @@ static void compose_savemsg_select_cb(GtkWidget *widget, Compose *compose)
 }
 
 static void entry_paste_clipboard(Compose *compose, GtkWidget *entry, gboolean wrap,
-                                 GdkAtom clip);
+                                 GdkAtom clip, GtkTextIter *insert_place);
 
 #define BLOCK_WRAP() {                                                 \
        prev_autowrap = compose->autowrap;                              \
@@ -5383,10 +5437,20 @@ static gboolean text_clicked(GtkWidget *text, GdkEventButton *event,
        }
 #endif
        if (event->button == 2) {
+               GtkTextIter iter;
+               gint x, y;
                BLOCK_WRAP();
-               entry_paste_clipboard(compose, compose->focused_editable, 
+               
+               /* get the middle-click position to paste at the correct place */
+               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);
+               
+               entry_paste_clipboard(compose, text, 
                                prefs_common.linewrap_pastes,
-                               GDK_SELECTION_PRIMARY);
+                               GDK_SELECTION_PRIMARY, &iter);
                UNBLOCK_WRAP();
                return TRUE;
        }
@@ -5816,7 +5880,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
 static GtkWidget *compose_account_option_menu_create(Compose *compose)
 {
        GList *accounts;
-       GtkWidget *hbox;
        GtkWidget *optmenu;
        GtkWidget *menu;
        gint num = 0, def_menu = 0;
@@ -5824,9 +5887,7 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        accounts = account_get_list();
        g_return_val_if_fail(accounts != NULL, NULL);
 
-       hbox = gtk_hbox_new(FALSE, 0);
        optmenu = gtk_option_menu_new();
-       gtk_box_pack_start(GTK_BOX(hbox), optmenu, FALSE, FALSE, 0);
        menu = gtk_menu_new();
 
        for (; accounts != NULL; accounts = accounts->next, num++) {
@@ -5837,13 +5898,16 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
                if (ac == compose->account) def_menu = num;
 
                if (ac->name)
-                       name = g_strdup_printf("%s: %s <%s>",
+                       name = g_markup_printf_escaped("<i>%s</i> : %s &lt;<b>%s</b>&gt;",
                                               ac->account_name,
                                               ac->name, ac->address);
                else
-                       name = g_strdup_printf("%s: %s",
+                       name = g_markup_printf_escaped("<i>%s</i> : &lt;<b>%s</b>&gt;",
                                               ac->account_name, ac->address);
                MENUITEM_ADD(menu, menuitem, name, ac->account_id);
+               gtk_label_set_use_markup (
+                               GTK_LABEL (gtk_bin_get_child (GTK_BIN (menuitem))),
+                               TRUE);
                g_free(name);
                g_signal_connect(G_OBJECT(menuitem), "activate",
                                 G_CALLBACK(account_activated),
@@ -5853,7 +5917,7 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
        gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), def_menu);
 
-       return hbox;
+       return optmenu;
 }
 
 static void compose_set_priority_cb(gpointer data,
@@ -6263,6 +6327,11 @@ static void compose_destroy(Compose *compose)
 {
        compose_list = g_list_remove(compose_list, compose);
 
+       if (compose->updating) {
+               debug_print("danger, not destroying anything now\n");
+               compose->deferred_destroy = TRUE;
+               return;
+       }
        /* NOTE: address_completion_end() does nothing with the window
         * however this may change. */
        address_completion_end(compose->window);
@@ -7132,7 +7201,10 @@ static void compose_send_cb(gpointer data, guint action, GtkWidget *widget)
 {
        Compose *compose = (Compose *)data;
        
-       if (prefs_common.work_offline && !inc_offline_should_override())
+       if (prefs_common.work_offline && 
+           !inc_offline_should_override(
+               _("Sylpheed-Claws needs network access in order "
+                 "to send this email.")))
                return;
        
        if (compose->draft_timeout_tag != -1) { /* CLAWS: disable draft timeout */
@@ -7510,7 +7582,7 @@ static void entry_copy_clipboard(GtkWidget *entry)
 }
 
 static void entry_paste_clipboard(Compose *compose, GtkWidget *entry, 
-                                 gboolean wrap, GdkAtom clip)
+                                 gboolean wrap, GdkAtom clip, GtkTextIter *insert_place)
 {
        if (GTK_IS_TEXT_VIEW(entry)) {
                GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry));
@@ -7523,19 +7595,32 @@ static void entry_paste_clipboard(Compose *compose, GtkWidget *entry,
                if (contents == NULL)
                        return;
 
-               gtk_text_buffer_delete_selection(buffer, FALSE, TRUE);
-               gtk_text_buffer_get_iter_at_mark(buffer, &start_iter, mark_start);
+               /* we shouldn't delete the selection when middle-click-pasting, or we
+                * can't mid-click-paste our own selection */
+               if (clip != GDK_SELECTION_PRIMARY)
+                       gtk_text_buffer_delete_selection(buffer, FALSE, TRUE);
                
-               start = gtk_text_iter_get_offset(&start_iter);
-
-               gtk_text_buffer_insert(buffer, &start_iter, contents, strlen(contents));
+               if (insert_place == NULL) {
+                       /* if insert_place isn't specified, insert at the cursor.
+                        * used for Ctrl-V pasting */
+                       gtk_text_buffer_get_iter_at_mark(buffer, &start_iter, mark_start);
+                       start = gtk_text_iter_get_offset(&start_iter);
+                       gtk_text_buffer_insert(buffer, &start_iter, contents, strlen(contents));
+               } else {
+                       /* if insert_place is specified, paste here.
+                        * used for mid-click-pasting */
+                       start = gtk_text_iter_get_offset(insert_place);
+                       gtk_text_buffer_insert(buffer, insert_place, contents, strlen(contents));
+               }
                
                if (!wrap) {
+                       /* paste unwrapped: mark the paste so it's not wrapped later */
                        end = start + strlen(contents);
                        gtk_text_buffer_get_iter_at_offset(buffer, &start_iter, start);
                        gtk_text_buffer_get_iter_at_offset(buffer, &end_iter, end);
                        gtk_text_buffer_apply_tag_by_name(buffer, "no_wrap", &start_iter, &end_iter);
                } else if (wrap && clip == GDK_SELECTION_PRIMARY) {
+                       /* rewrap paragraph now (after a mid-click-paste) */
                        mark_start = gtk_text_buffer_get_insert(buffer);
                        gtk_text_buffer_get_iter_at_mark(buffer, &start_iter, mark_start);
                        gtk_text_iter_backward_char(&start_iter);
@@ -7589,7 +7674,7 @@ static void compose_paste_cb(Compose *compose)
            GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
                entry_paste_clipboard(compose, compose->focused_editable, 
                                prefs_common.linewrap_pastes,
-                               GDK_SELECTION_CLIPBOARD);
+                               GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
 }
 
@@ -7611,7 +7696,7 @@ static void compose_paste_as_quote_cb(Compose *compose)
                prefs_common.linewrap_quote = prefs_common.linewrap_pastes;
                entry_paste_clipboard(compose, compose->focused_editable, 
                                prefs_common.linewrap_pastes,
-                               GDK_SELECTION_CLIPBOARD);
+                               GDK_SELECTION_CLIPBOARD, NULL);
                prefs_common.linewrap_quote = wrap_quote;
        }
 }
@@ -7624,7 +7709,7 @@ static void compose_paste_no_wrap_cb(Compose *compose)
        if (compose->focused_editable &&
            GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
                entry_paste_clipboard(compose, compose->focused_editable, FALSE,
-                       GDK_SELECTION_CLIPBOARD);
+                       GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
 }
 
@@ -7636,7 +7721,7 @@ static void compose_paste_wrap_cb(Compose *compose)
        if (compose->focused_editable &&
            GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
                entry_paste_clipboard(compose, compose->focused_editable, TRUE,
-                       GDK_SELECTION_CLIPBOARD);
+                       GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
 }