2004-11-08 [colin] 0.9.12cvs142.2
[claws.git] / src / compose.c
index c55dddec7eb262f260f7d05e602dd6c6b1663b35..37511f280492e1c15eeeb020b12adcbfb46691ec 100644 (file)
@@ -154,6 +154,19 @@ typedef enum
        COMPOSE_INSERT_NO_FILE
 } ComposeInsertResult;
 
+typedef enum
+{
+       COMPOSE_QUIT_EDITING,
+       COMPOSE_KEEP_EDITING,
+       COMPOSE_AUTO_SAVE
+} ComposeDraftAction;
+
+typedef enum
+{
+       COMPOSE_WRITE_FOR_SEND,
+       COMPOSE_WRITE_FOR_STORE
+} ComposeWriteType;
+
 #define B64_LINE_SIZE          57
 #define B64_BUFFSIZE           77
 
@@ -229,7 +242,8 @@ static gboolean compose_check_for_valid_recipient
 static gboolean compose_check_entries          (Compose        *compose,
                                                 gboolean       check_subject);
 static gint compose_write_to_file              (Compose        *compose,
-                                                FILE           *fp);
+                                                FILE           *fp,
+                                                gint            action);
 static gint compose_write_body_to_file         (Compose        *compose,
                                                 const gchar    *file);
 static gint compose_remove_reedit_target       (Compose        *compose);
@@ -250,8 +264,6 @@ static void compose_convert_header          (gchar          *dest,
                                                 gchar          *src,
                                                 gint            header_len,
                                                 gboolean        addr_field);
-static void compose_generate_msgid             (gchar          *buf,
-                                                gint            len);
 
 static void compose_attach_info_free           (AttachInfo     *ainfo);
 static void compose_attach_remove_selected     (Compose        *compose);
@@ -511,7 +523,7 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_Message/Insert si_gnature"),     "<control>G", compose_insert_sig_cb,  0, NULL},
        {N_("/_Message/---"),                   NULL, NULL, 0, "<Separator>"},
        {N_("/_Message/_Save"),
-                                               "<control>S", compose_draft_cb, 1, NULL},
+                                               "<control>S", compose_draft_cb, COMPOSE_KEEP_EDITING, NULL},
        {N_("/_Message/---"),                   NULL, NULL, 0, "<Separator>"},
        {N_("/_Message/_Close"),                        "<control>W", compose_close_cb, 0, NULL},
 
@@ -625,7 +637,6 @@ static GtkItemFactoryEntry compose_entries[] =
                                        NULL, NULL, 0, "<Branch>"},
 #endif
        {N_("/_Options"),               NULL, NULL, 0, "<Branch>"},
-       {N_("/_Options/---"),           NULL, NULL, 0, "<Separator>"},
        {N_("/_Options/Privacy System"),                NULL, NULL,   0, "<Branch>"},
        {N_("/_Options/Privacy System/None"),   NULL, compose_set_privacy_system_cb,   0, "<RadioItem>"},
        {N_("/_Options/Si_gn"),         NULL, compose_toggle_sign_cb   , 0, "<ToggleItem>"},
@@ -925,8 +936,8 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        compose = compose_create(account, COMPOSE_REPLY);
        ifactory = gtk_item_factory_from_widget(compose->menubar);
 
-       menu_set_active(ifactory, "/Message/Remove references", FALSE);
-       menu_set_sensitive(ifactory, "/Message/Remove references", TRUE);
+       menu_set_active(ifactory, "/Options/Remove references", FALSE);
+       menu_set_sensitive(ifactory, "/Options/Remove references", TRUE);
 
        compose->replyinfo = procmsg_msginfo_get_full_info(msginfo);
        if (!compose->replyinfo)
@@ -1458,7 +1469,7 @@ void compose_entry_mark_default_to(Compose *compose, const gchar *mailto)
        for (h_list = compose->header_list; h_list != NULL; h_list = h_list->next) {
                entry = GTK_ENTRY(((ComposeHeaderEntry *)h_list->data)->entry);
                if (gtk_entry_get_text(entry) && 
-                   !g_strcasecmp(gtk_entry_get_text(entry), mailto)) {
+                   !g_utf8_collate(gtk_entry_get_text(entry), mailto)) {
                        gtk_widget_ensure_style(GTK_WIDGET(entry));
                        if (!bold_style) {
                                PangoFontDescription *font_desc = NULL;
@@ -1497,7 +1508,7 @@ void compose_toolbar_cb(gint action, gpointer data)
                compose_send_later_cb(compose, 0, NULL);
                break;
        case A_DRAFT:
-               compose_draft_cb(compose, 0, NULL);
+               compose_draft_cb(compose, COMPOSE_QUIT_EDITING, NULL);
                break;
        case A_INSERT:
                compose_insert_file_cb(compose, 0, NULL);
@@ -1731,7 +1742,7 @@ static gchar *compose_parse_references(const gchar *ref, const gchar *msgid)
        for (cur = ref_id_list; cur != NULL; cur = cur->next) {
                if (new_ref->len > 0)
                        g_string_append(new_ref, "\n\t");
-               g_string_sprintfa(new_ref, "<%s>", (gchar *)cur->data);
+               g_string_append_printf(new_ref, "<%s>", (gchar *)cur->data);
        }
 
        slist_free_strings(ref_id_list);
@@ -2194,7 +2205,7 @@ static void compose_attach_append(Compose *compose, const gchar *file,
 
        if (content_type) {
                ainfo->content_type = g_strdup(content_type);
-               if (!strcasecmp(content_type, "message/rfc822")) {
+               if (!g_ascii_strcasecmp(content_type, "message/rfc822")) {
                        MsgInfo *msginfo;
                        MsgFlags flags = {0, 0};
                        const gchar *name;
@@ -2214,7 +2225,7 @@ static void compose_attach_append(Compose *compose, const gchar *file,
 
                        procmsg_msginfo_free(msginfo);
                } else {
-                       if (!g_strncasecmp(content_type, "text", 4))
+                       if (!g_ascii_strncasecmp(content_type, "text", 4))
                                ainfo->encoding =
                                        procmime_get_encoding_for_file(file);
                        else
@@ -2228,12 +2239,18 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                        ainfo->content_type =
                                g_strdup("application/octet-stream");
                        ainfo->encoding = ENC_BASE64;
-               } else if (!g_strncasecmp(ainfo->content_type, "text", 4))
+               } else if (!g_ascii_strncasecmp(ainfo->content_type, "text", 4))
                        ainfo->encoding = procmime_get_encoding_for_file(file);
                else
                        ainfo->encoding = ENC_BASE64;
                ainfo->name = g_strdup(g_basename(filename ? filename : file)); 
        }
+
+       if (!strcmp(ainfo->content_type, "unknown")) {
+               g_free(ainfo->content_type);
+               ainfo->content_type = g_strdup("application/octet-stream");
+       }
+
        ainfo->size = size;
 
        text[COL_MIMETYPE] = ainfo->content_type;
@@ -2307,7 +2324,7 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
                debug_print("First text part found\n");
        } else if (compose->mode == COMPOSE_REEDIT &&
                 child->type == MIMETYPE_APPLICATION &&
-                !strcasecmp(child->subtype, "pgp-encrypted")) {
+                !g_ascii_strcasecmp(child->subtype, "pgp-encrypted")) {
                AlertValue val;
                val = alertpanel(_("Encrypted message"),
                                 _("Cannot re-edit an encrypted message. \n"
@@ -3332,8 +3349,8 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
                headerentry = ((ComposeHeaderEntry *)list->data);
                headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
 
-               if (g_strcasecmp(headerentryname, cc_hdr) == 0 
-                  || g_strcasecmp(headerentryname, to_hdr) == 0) {
+               if (g_utf8_collate(headerentryname, cc_hdr) == 0 
+                  || g_utf8_collate(headerentryname, to_hdr) == 0) {
                        const gchar *entstr = gtk_entry_get_text(GTK_ENTRY(headerentry->entry));
                        Xstrdup_a(str, entstr, return -1);
                        g_strstrip(str);
@@ -3341,7 +3358,7 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
                                compose_convert_header
                                        (buf, sizeof(buf), str,
                                        strlen("Resent-To") + 2, TRUE);
-                               if (g_strcasecmp(headerentryname, to_hdr) == 0) {
+                               if (g_utf8_collate(headerentryname, to_hdr) == 0) {
                                        if (first_to_address) {
                                                fprintf(fp, "Resent-To: ");
                                                first_to_address = FALSE;
@@ -3349,7 +3366,7 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
                                                fprintf(fp, ",");
                                        }
                                }
-                               if (g_strcasecmp(headerentryname, cc_hdr) == 0) {
+                               if (g_utf8_collate(headerentryname, cc_hdr) == 0) {
                                        if (first_cc_address) {
                                                fprintf(fp, "\n");
                                                fprintf(fp, "Resent-Cc: ");
@@ -3409,7 +3426,7 @@ static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
 
        /* Resent-Message-ID */
        if (compose->account->gen_msgid) {
-               compose_generate_msgid(buf, sizeof(buf));
+               generate_msgid(compose->account->address, buf, sizeof(buf));
                fprintf(fp, "Resent-Message-ID: <%s>\n", buf);
                compose->msgid = g_strdup(buf);
        }
@@ -3435,23 +3452,23 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest)
 
        while (procheader_get_one_field_asis(buf, sizeof(buf), fp) != -1) {
                /* should filter returnpath, delivered-to */
-               if (g_strncasecmp(buf, "Return-Path:",
-                                  strlen("Return-Path:")) == 0 ||
-                   g_strncasecmp(buf, "Delivered-To:",
-                                 strlen("Delivered-To:")) == 0 ||
-                   g_strncasecmp(buf, "Received:",
-                                 strlen("Received:")) == 0 ||
-                   g_strncasecmp(buf, "Subject:",
-                                 strlen("Subject:")) == 0 ||
-                   g_strncasecmp(buf, "X-UIDL:",
-                                 strlen("X-UIDL:")) == 0)
+               if (g_ascii_strncasecmp(buf, "Return-Path:",
+                                       strlen("Return-Path:")) == 0 ||
+                   g_ascii_strncasecmp(buf, "Delivered-To:",
+                                       strlen("Delivered-To:")) == 0 ||
+                   g_ascii_strncasecmp(buf, "Received:",
+                                       strlen("Received:")) == 0 ||
+                   g_ascii_strncasecmp(buf, "Subject:",
+                                       strlen("Subject:")) == 0 ||
+                   g_ascii_strncasecmp(buf, "X-UIDL:",
+                                       strlen("X-UIDL:")) == 0)
                        continue;
 
                if (fputs(buf, fdest) == -1)
                        goto error;
 
                if (!prefs_common.redirect_keep_from) {
-                       if (g_strncasecmp(buf, "From:",
+                       if (g_ascii_strncasecmp(buf, "From:",
                                          strlen("From:")) == 0) {
                                fputs(" (by way of ", fdest);
                                if (compose->account->name
@@ -3491,7 +3508,7 @@ error:
        return -1;
 }
 
-static gint compose_write_to_file(Compose *compose, FILE *fp)
+static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
 {
        GtkTextBuffer *buffer;
        GtkTextIter start, end;
@@ -3506,7 +3523,7 @@ static gint compose_write_to_file(Compose *compose, FILE *fp)
         mimemsg->type = MIMETYPE_MESSAGE;
         mimemsg->subtype = g_strdup("rfc822");
        mimemsg->content = MIMECONTENT_MEM;
-       mimemsg->data = compose_get_header(compose);
+       mimemsg->data.mem = compose_get_header(compose);
 
        /* Create text part MimeInfo */
        /* get all composed text */
@@ -3523,7 +3540,7 @@ static gint compose_write_to_file(Compose *compose, FILE *fp)
                const gchar *src_codeset;
 
                out_codeset = conv_get_outgoing_charset_str();
-               if (!strcasecmp(out_codeset, CS_US_ASCII))
+               if (!g_ascii_strcasecmp(out_codeset, CS_US_ASCII))
                        out_codeset = CS_ISO_8859_1;
 
                if (prefs_common.encoding_method == CTE_BASE64)
@@ -3535,47 +3552,54 @@ static gint compose_write_to_file(Compose *compose, FILE *fp)
                else
                        encoding = procmime_get_encoding_for_charset(out_codeset);
 
-               src_codeset = conv_get_current_charset_str();
+               src_codeset = CS_UTF_8;
                /* if current encoding is US-ASCII, set it the same as
                   outgoing one to prevent code conversion failure */
-               if (!strcasecmp(src_codeset, CS_US_ASCII))
+               if (!g_ascii_strcasecmp(src_codeset, CS_US_ASCII))
                        src_codeset = out_codeset;
 
                debug_print("src encoding = %s, out encoding = %s, transfer encoding = %s\n",
                            src_codeset, out_codeset, procmime_get_encoding_str(encoding));
 
-               buf = conv_codeset_strdup(chars, src_codeset, out_codeset);
-               if (!buf) {
-                       AlertValue aval;
-                       gchar *msg;
-
-                       msg = g_strdup_printf(_("Can't convert the character encoding of the message from\n"
-                                               "%s to %s.\n"
-                                               "Send it anyway?"), src_codeset, out_codeset);
-                       aval = alertpanel_with_type
-                               (_("Error"), msg, _("Yes"), _("+No"), NULL, NULL, ALERT_ERROR);
-                       g_free(msg);
-
-                       if (aval != G_ALERTDEFAULT) {
-                               g_free(chars);
-                               return -1;
-                       } else {
-                               buf = chars;
-                               out_codeset = src_codeset;
-                               chars = NULL;
+               if (action == COMPOSE_WRITE_FOR_SEND) {
+                       buf = conv_codeset_strdup(chars, src_codeset, out_codeset);
+                       if (!buf) {
+                               AlertValue aval;
+                               gchar *msg;
+
+                               msg = g_strdup_printf(_("Can't convert the character encoding of the message from\n"
+                                                       "%s to %s.\n"
+                                                       "Send it anyway?"), src_codeset, out_codeset);
+                               aval = alertpanel_with_type
+                                       (_("Error"), msg, _("Yes"), _("+No"), NULL, NULL, ALERT_ERROR);
+                               g_free(msg);
+
+                               if (aval != G_ALERTDEFAULT) {
+                                       g_free(chars);
+                                       return -1;
+                               } else {
+                                       buf = chars;
+                                       out_codeset = src_codeset;
+                                       chars = NULL;
+                               }
                        }
+               } else {
+                       buf = chars;
+                       out_codeset = src_codeset;
+                       chars = NULL;
                }
        }
        g_free(chars);
 
        mimetext = procmime_mimeinfo_new();
        mimetext->content = MIMECONTENT_MEM;
-       mimetext->data = buf;
+       mimetext->data.mem = buf;
        mimetext->type = MIMETYPE_TEXT;
        mimetext->subtype = g_strdup("plain");
        g_hash_table_insert(mimetext->typeparameters, g_strdup("charset"),
                            g_strdup(out_codeset));
-       /* procmime_encode_content(mimetext, encoding); */
+       if (encoding != ENC_UNKNOWN)
+               procmime_encode_content(mimetext, encoding);
 
        /* append attachment parts */
        if (compose_use_attach(compose)) {
@@ -3597,8 +3621,9 @@ static gint compose_write_to_file(Compose *compose, FILE *fp)
        } else
                g_node_append(mimemsg->node, mimetext->node);
 
-       /* sign message */
-       if (compose->use_signing && privacy_system_can_sign(compose->privacy_system))
+       /* sign message if sending */
+       if (action == COMPOSE_WRITE_FOR_SEND && compose->use_signing && 
+           privacy_system_can_sign(compose->privacy_system))
                if (!privacy_sign(compose->privacy_system, mimemsg))
                        return -1;
 
@@ -3856,7 +3881,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                        return -1;
                }
        } else {
-               if (compose_write_to_file(compose, fp) < 0) {
+               if (compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_SEND) < 0) {
                        lock = FALSE;
                        fclose(fp);
                        unlink(tmp);
@@ -3914,13 +3939,19 @@ static void compose_add_attachments(Compose *compose, MimeInfo *parent)
             row++) {
                mimepart = procmime_mimeinfo_new();
                mimepart->content = MIMECONTENT_FILE;
-               mimepart->filename = g_strdup(ainfo->file);
+               mimepart->data.filename = g_strdup(ainfo->file);
                mimepart->offset = 0;
 
                stat(ainfo->file, &statbuf);
                mimepart->length = statbuf.st_size;
 
                type = g_strdup(ainfo->content_type);
+
+               if (!strchr(type, '/')) {
+                       g_free(type);
+                       type = g_strdup("application/octet-stream");
+               }
+
                subtype = strchr(type, '/') + 1;
                *(subtype - 1) = '\0';
                mimepart->type = procmime_get_media_type(type);
@@ -3928,7 +3959,7 @@ static void compose_add_attachments(Compose *compose, MimeInfo *parent)
                g_free(type);
 
                if (mimepart->type == MIMETYPE_MESSAGE && 
-                   !g_strcasecmp(mimepart->subtype, "rfc822")) {
+                   !g_ascii_strcasecmp(mimepart->subtype, "rfc822")) {
                        mimepart->disposition = DISPOSITIONTYPE_INLINE;
                } else {
                        g_hash_table_insert(mimepart->typeparameters,
@@ -4002,7 +4033,7 @@ static void compose_add_headerfield_from_headerlist(Compose *compose,
                headerentry = ((ComposeHeaderEntry *)list->data);
                headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
 
-               if (!g_strcasecmp(trans_fieldname, headerentryname)) {
+               if (!g_utf8_collate(trans_fieldname, headerentryname)) {
                        str = gtk_editable_get_chars(GTK_EDITABLE(headerentry->entry), 0, -1);
                        g_strstrip(str);
                        if (str[0] != '\0') {
@@ -4021,7 +4052,7 @@ static void compose_add_headerfield_from_headerlist(Compose *compose,
                compose_convert_header
                        (buf, fieldstr->len * 4  + 256, fieldstr->str,
                        strlen(fieldname) + 2, TRUE);
-               g_string_sprintfa(header, "%s: %s\n", fieldname, buf);
+               g_string_append_printf(header, "%s: %s\n", fieldname, buf);
                g_free(buf);
        }
 
@@ -4051,7 +4082,7 @@ static gchar *compose_get_header(Compose *compose)
        /* Date */
        if (compose->account->add_date) {
                get_rfc822_date(buf, sizeof(buf));
-               g_string_sprintfa(header, "Date: %s\n", buf);
+               g_string_append_printf(header, "Date: %s\n", buf);
        }
 
        /* From */
@@ -4060,10 +4091,10 @@ static gchar *compose_get_header(Compose *compose)
                        (buf, sizeof(buf), compose->account->name,
                         strlen("From: "), TRUE);
                QUOTE_IF_REQUIRED(name, buf);
-               g_string_sprintfa(header, "From: %s <%s>\n",
+               g_string_append_printf(header, "From: %s <%s>\n",
                        name, compose->account->address);
        } else
-               g_string_sprintfa(header, "From: %s\n", compose->account->address);
+               g_string_append_printf(header, "From: %s\n", compose->account->address);
        
        /* To */
        compose_add_headerfield_from_headerlist(compose, header, "To", ", ");
@@ -4091,26 +4122,26 @@ static gchar *compose_get_header(Compose *compose)
                if (*str != '\0') {
                        compose_convert_header(buf, sizeof(buf), str,
                                               strlen("Subject: "), FALSE);
-                       g_string_sprintfa(header, "Subject: %s\n", buf);
+                       g_string_append_printf(header, "Subject: %s\n", buf);
                }
                g_free(tmpstr);
        }
 
        /* Message-ID */
        if (compose->account->gen_msgid) {
-               compose_generate_msgid(buf, sizeof(buf));
-               g_string_sprintfa(header, "Message-ID: <%s>\n", buf);
+               generate_msgid(compose->account->address, buf, sizeof(buf));
+               g_string_append_printf(header, "Message-ID: <%s>\n", buf);
                compose->msgid = g_strdup(buf);
        }
 
        if (compose->remove_references == FALSE) {
                /* In-Reply-To */
                if (compose->inreplyto && compose->to_list)
-                       g_string_sprintfa(header, "In-Reply-To: <%s>\n", compose->inreplyto);
+                       g_string_append_printf(header, "In-Reply-To: <%s>\n", compose->inreplyto);
        
                /* References */
                if (compose->references)
-                       g_string_sprintfa(header, "References: %s\n", compose->references);
+                       g_string_append_printf(header, "References: %s\n", compose->references);
        }
 
        /* Followup-To */
@@ -4126,21 +4157,21 @@ static gchar *compose_get_header(Compose *compose)
                compose_convert_header(buf, sizeof(buf),
                                       compose->account->organization,
                                       strlen("Organization: "), FALSE);
-               g_string_sprintfa(header, "Organization: %s\n", buf);
+               g_string_append_printf(header, "Organization: %s\n", buf);
        }
 
        /* Program version and system info */
        /* uname(&utsbuf); */
        if (g_slist_length(compose->to_list) && !IS_IN_CUSTOM_HEADER("X-Mailer") &&
            !compose->newsgroup_list) {
-               g_string_sprintfa(header, "X-Mailer: %s (GTK+ %d.%d.%d; %s)\n",
+               g_string_append_printf(header, "X-Mailer: %s (GTK+ %d.%d.%d; %s)\n",
                        prog_version,
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
                        TARGET_ALIAS);
                        /* utsbuf.sysname, utsbuf.release, utsbuf.machine); */
        }
        if (g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
-               g_string_sprintfa(header, "X-Newsreader: %s (GTK+ %d.%d.%d; %s)\n",
+               g_string_append_printf(header, "X-Newsreader: %s (GTK+ %d.%d.%d; %s)\n",
                        prog_version,
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
                        TARGET_ALIAS);
@@ -4160,24 +4191,24 @@ static gchar *compose_get_header(Compose *compose)
                                        (buf, sizeof(buf),
                                         chdr->value ? chdr->value : "",
                                         strlen(chdr->name) + 2, FALSE);
-                               g_string_sprintfa(header, "%s: %s\n", chdr->name, buf);
+                               g_string_append_printf(header, "%s: %s\n", chdr->name, buf);
                        }
                }
        }
 
        /* PRIORITY */
        switch (compose->priority) {
-               case PRIORITY_HIGHEST: g_string_sprintfa(header, "Importance: high\n"
+               case PRIORITY_HIGHEST: g_string_append_printf(header, "Importance: high\n"
                                                   "X-Priority: 1 (Highest)\n");
                        break;
-               case PRIORITY_HIGH: g_string_sprintfa(header, "Importance: high\n"
+               case PRIORITY_HIGH: g_string_append_printf(header, "Importance: high\n"
                                                "X-Priority: 2 (High)\n");
                        break;
                case PRIORITY_NORMAL: break;
-               case PRIORITY_LOW: g_string_sprintfa(header, "Importance: low\n"
+               case PRIORITY_LOW: g_string_append_printf(header, "Importance: low\n"
                                               "X-Priority: 4 (Low)\n");
                        break;
-               case PRIORITY_LOWEST: g_string_sprintfa(header, "Importance: low\n"
+               case PRIORITY_LOWEST: g_string_append_printf(header, "Importance: low\n"
                                                  "X-Priority: 5 (Lowest)\n");
                        break;
                default: debug_print("compose: priority unknown : %d\n",
@@ -4193,9 +4224,9 @@ static gchar *compose_get_header(Compose *compose)
                                                       compose->account->name, 
                                                       strlen("Disposition-Notification-To: "),
                                                       TRUE);
-                               g_string_sprintfa(header, "Disposition-Notification-To: %s <%s>\n", buf, compose->account->address);
+                               g_string_append_printf(header, "Disposition-Notification-To: %s <%s>\n", buf, compose->account->address);
                        } else
-                               g_string_sprintfa(header, "Disposition-Notification-To: %s\n", compose->account->address);
+                               g_string_append_printf(header, "Disposition-Notification-To: %s\n", compose->account->address);
                }
        }
 
@@ -4239,7 +4270,7 @@ static gchar *compose_get_header(Compose *compose)
                        string++;
                }
                if (!standard_header && !IS_IN_CUSTOM_HEADER(headername))
-                       g_string_sprintfa(header, "%s %s\n", headername_wcolon, headervalue);
+                       g_string_append_printf(header, "%s %s\n", headername_wcolon, headervalue);
                                
                g_free(headername);
                g_free(headername_wcolon);              
@@ -4273,28 +4304,6 @@ static void compose_convert_header(gchar *dest, gint len, gchar *src,
        g_free(tmpstr);
 }
 
-static void compose_generate_msgid(gchar *buf, gint len)
-{
-       struct tm *lt;
-       time_t t;
-       gchar *addr;
-
-       t = time(NULL);
-       lt = localtime(&t);
-
-       addr = g_strconcat("@", get_domain_name(), NULL);
-
-       g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x%s",
-                  lt->tm_year + 1900, lt->tm_mon + 1,
-                  lt->tm_mday, lt->tm_hour,
-                  lt->tm_min, lt->tm_sec,
-                  (guint)random(), addr);
-
-       debug_print("generated Message-ID: %s\n", buf);
-
-       g_free(addr);
-}
-
 static void compose_create_header_entry(Compose *compose) 
 {
        gchar *headers[] = {"To:", "Cc:", "Bcc:", "Newsgroups:", "Reply-To:", "Followup-To:", NULL};
@@ -4726,6 +4735,12 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        }
        gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL,
                                      &geometry, GDK_HINT_MAX_SIZE);
+       if (!geometry.min_width) {
+               geometry.min_width = 600;
+               geometry.min_height = 480;
+       }
+       gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL,
+                                     &geometry, GDK_HINT_MIN_SIZE);
        gtk_widget_set_uposition(window, prefs_common.compose_x, 
                                 prefs_common.compose_y);
 
@@ -4820,6 +4835,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
 
        text = gtk_text_view_new();
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
+       gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD_CHAR);
        gtk_text_view_set_editable(GTK_TEXT_VIEW(text), TRUE);
        clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
        gtk_text_buffer_add_selection_clipboard(buffer, clipboard);
@@ -5144,7 +5160,7 @@ static void compose_set_privacy_system_cb(gpointer data,
        GtkItemFactory *ifactory;
        gboolean can_sign = FALSE, can_encrypt = FALSE;
 
-       systemid = gtk_object_get_data(GTK_OBJECT(widget), "privacy_system");
+       systemid = g_object_get_data(G_OBJECT(widget), "privacy_system");
        g_free(compose->privacy_system);
        compose->privacy_system = NULL;
        if (systemid != NULL) {
@@ -5180,7 +5196,7 @@ static void compose_update_privacy_system_menu_item(Compose * compose)
                while (amenu != NULL) {
                        GList *alist = amenu->next;
 
-                       systemid = gtk_object_get_data(GTK_OBJECT(amenu->data), "privacy_system");
+                       systemid = g_object_get_data(G_OBJECT(amenu->data), "privacy_system");
                        if (systemid != NULL)
                                if (strcmp(systemid, compose->privacy_system) == 0) {
                                        menuitem = GTK_WIDGET(amenu->data);
@@ -6216,7 +6232,7 @@ static void compose_send_later_cb(gpointer data, guint action,
 
 void compose_draft (gpointer data) 
 {
-       compose_draft_cb(data, 0, NULL);        
+       compose_draft_cb(data, COMPOSE_QUIT_EDITING, NULL);     
 }
 
 static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
@@ -6265,7 +6281,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        fprintf(fp, "X-Sylpheed-Gnupg-Mode:%s\n", compose->privacy_system);
        fprintf(fp, "\n");
 
-       if (compose_write_to_file(compose, fp) < 0) {
+       if (compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_STORE) < 0) {
                fclose(fp);
                unlink(tmp);
                g_free(tmp);
@@ -6303,8 +6319,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        
        lock = FALSE;
 
-       /* 0: quit editing  1: keep editing  2: keep editing (autosave) */
-       if (action == 0)
+       if (action == COMPOSE_QUIT_EDITING)
                gtk_widget_destroy(compose->window);
        else {
                struct stat s;
@@ -6328,7 +6343,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                compose->targetinfo->folder = draft;
                compose->mode = COMPOSE_REEDIT;
                
-               if (action == 2) {
+               if (action == COMPOSE_AUTO_SAVE) {
                        compose->autosaved_draft = compose->targetinfo;
                }
        }
@@ -6433,7 +6448,7 @@ static void compose_close_cb(gpointer data, guint action, GtkWidget *widget)
                                compose_remove_draft(compose);                  
                        break;
                case G_ALERTALTERNATE:
-                       compose_draft_cb(data, 0, NULL);
+                       compose_draft_cb(data, COMPOSE_QUIT_EDITING, NULL);
                        return;
                default:
                        return;
@@ -7207,7 +7222,7 @@ static void text_inserted(GtkTextBuffer *buffer, GtkTextIter *iter,
        } else
                gtk_text_buffer_insert(buffer, iter, text, len);
 
-       if (prefs_common.autowrap)
+       if (compose->autowrap)
                compose_wrap_line_all_full(compose, TRUE);
 
        g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
@@ -7224,7 +7239,7 @@ static void text_inserted(GtkTextBuffer *buffer, GtkTextIter *iter,
 static gint compose_defer_auto_save_draft(Compose *compose)
 {
        compose->draft_timeout_tag = -1;
-       compose_draft_cb((gpointer)compose, 2, NULL);
+       compose_draft_cb((gpointer)compose, COMPOSE_AUTO_SAVE, NULL);
        return FALSE;
 }