#endif
#include <signal.h>
#include <errno.h>
+#ifndef G_OS_WIN32 /* fixme we should have a configure test. */
#include <libgen.h>
+#endif
#if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
# include <wchar.h>
MsgInfo *msginfo,
const gchar *fmt,
const gchar *qmark,
- const gchar *body);
+ const gchar *body,
+ gboolean rewrap);
static void compose_reply_set_entry (Compose *compose,
MsgInfo *msginfo,
gint action);
static gint compose_write_body_to_file (Compose *compose,
const gchar *file);
-static gint compose_remove_reedit_target (Compose *compose);
+static gint compose_remove_reedit_target (Compose *compose,
+ gboolean force);
void compose_remove_draft (Compose *compose);
static gint compose_queue (Compose *compose,
gint *msgnum,
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>"},
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)"),
"foreground-gdk", &uri_color,
NULL);
compose->no_wrap_tag = gtk_text_buffer_create_tag(buffer, "no_wrap", NULL);
+ compose->no_join_tag = gtk_text_buffer_create_tag(buffer, "no_join", NULL);
}
Compose *compose_new(PrefsAccount *account, const gchar *mailto,
if (prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
+ compose->modified = FALSE;
compose_set_title(compose);
return compose;
}
}
}
+#define SIGNAL_BLOCK(buffer) { \
+ g_signal_handlers_block_by_func(G_OBJECT(buffer), \
+ G_CALLBACK(compose_changed_cb), \
+ compose); \
+ g_signal_handlers_block_by_func(G_OBJECT(buffer), \
+ G_CALLBACK(text_inserted), \
+ compose); \
+}
+
+#define SIGNAL_UNBLOCK(buffer) { \
+ g_signal_handlers_unblock_by_func(G_OBJECT(buffer), \
+ G_CALLBACK(compose_changed_cb), \
+ compose); \
+ g_signal_handlers_unblock_by_func(G_OBJECT(buffer), \
+ G_CALLBACK(text_inserted), \
+ compose); \
+}
+
static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
gboolean to_all, gboolean to_ml,
gboolean to_sender,
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);
compose_quote_fmt(compose, compose->replyinfo,
prefs_common.quotefmt,
- qmark, body);
+ qmark, body, FALSE);
}
if (procmime_msginfo_is_encrypted(compose->replyinfo)) {
compose_force_encryption(compose, account, FALSE);
}
+ SIGNAL_BLOCK(textbuf);
+
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);
+ SIGNAL_UNBLOCK(textbuf);
+
gtk_widget_grab_focus(compose->text);
undo_unblock(compose->undostruct);
if (prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
+ compose->modified = FALSE;
compose_set_title(compose);
return compose;
}
textview = GTK_TEXT_VIEW(compose->text);
textbuf = gtk_text_view_get_buffer(textview);
compose_create_tags(textview, compose);
-
+
+ undo_block(compose->undostruct);
if (as_attach) {
gchar *msgfile;
compose_quote_fmt(compose, full_msginfo,
prefs_common.fw_quotefmt,
- qmark, body);
+ qmark, body, FALSE);
compose_attach_parts(compose, msginfo);
procmsg_msginfo_free(full_msginfo);
}
+ SIGNAL_BLOCK(textbuf);
+
if (account->auto_sig)
compose_insert_sig(compose, FALSE);
compose_wrap_all(compose);
+ SIGNAL_UNBLOCK(textbuf);
+
gtk_text_buffer_get_start_iter(textbuf, &iter);
gtk_text_buffer_place_cursor(textbuf, &iter);
g_free(folderidentifier);
}
+ undo_unblock(compose->undostruct);
+
+ compose->modified = FALSE;
compose_set_title(compose);
return compose;
}
textview = GTK_TEXT_VIEW(compose->text);
textbuf = gtk_text_view_get_buffer(textview);
compose_create_tags(textview, compose);
-
+
+ undo_block(compose->undostruct);
for (msginfo = msginfo_list; msginfo != NULL; msginfo = msginfo->next) {
msgfile = procmsg_get_message_file_path((MsgInfo *)msginfo->data);
if (!is_file_exist(msgfile))
_("Fw: multiple emails"));
}
+ SIGNAL_BLOCK(textbuf);
+
if (account->auto_sig)
compose_insert_sig(compose, FALSE);
compose_wrap_all(compose);
+ SIGNAL_UNBLOCK(textbuf);
+
gtk_text_buffer_get_start_iter(textbuf, &iter);
gtk_text_buffer_place_cursor(textbuf, &iter);
gtk_widget_grab_focus(compose->header_last->entry);
-
+ undo_unblock(compose->undostruct);
+ compose->modified = FALSE;
compose_set_title(compose);
return compose;
}
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;
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;
}
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;
if (prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
+ compose->modified = FALSE;
compose_set_title(compose);
}
msginfo->subject);
gtk_editable_set_editable(GTK_EDITABLE(compose->subject_entry), FALSE);
- compose_quote_fmt(compose, msginfo, "%M", NULL, NULL);
+ compose_quote_fmt(compose, msginfo, "%M", NULL, NULL, FALSE);
gtk_text_view_set_editable(GTK_TEXT_VIEW(compose->text), FALSE);
compose_colorize_signature(compose);
gtk_widget_set_sensitive(compose->toolbar->linewrap_current_btn, FALSE);
gtk_widget_set_sensitive(compose->toolbar->linewrap_all_btn, FALSE);
+ compose->modified = FALSE;
compose_set_title(compose);
return compose;
}
static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
const gchar *fmt, const gchar *qmark,
- const gchar *body)
+ const gchar *body, gboolean rewrap)
{
static MsgInfo dummyinfo;
gchar *quote_str = NULL;
gchar *buf;
- gchar *p, *lastp;
- gint len;
gboolean prev_autowrap;
const gchar *trimmed_body = body;
+ gint cursor_pos = -1;
GtkTextView *text = GTK_TEXT_VIEW(compose->text);
GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
+ GtkTextIter iter;
+ GtkTextMark *mark;
+
+ SIGNAL_BLOCK(buffer);
+
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();
if (buf == NULL)
alertpanel_error(_("Quote mark format error."));
else
- Xstrdup_a(quote_str, buf, return NULL)
+ Xstrdup_a(quote_str, buf, goto error)
}
if (fmt && *fmt != '\0') {
&& 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();
buf = quote_fmt_get_buffer();
if (buf == NULL) {
alertpanel_error(_("Message reply/forward format error."));
- return NULL;
+ goto error;
}
} else
buf = "";
prev_autowrap = compose->autowrap;
compose->autowrap = FALSE;
- g_signal_handlers_block_by_func(G_OBJECT(buffer),
- G_CALLBACK(compose_changed_cb),
- compose);
- g_signal_handlers_block_by_func(G_OBJECT(buffer),
- G_CALLBACK(text_inserted),
- 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);
-
- lastp = strchr(p, '\n');
- len = lastp ? lastp - p + 1 : -1;
-
- if (g_utf8_validate(p, -1, NULL)) {
- gtk_text_buffer_insert(buffer, &iter, p, len);
- } else {
- gchar *tmpin = g_strdup(p);
- gchar *tmpout = NULL;
- tmpin[len] = '\0';
- tmpout = conv_codeset_strdup
- (tmpin, conv_get_locale_charset_str(),
- CS_INTERNAL);
- gtk_text_buffer_insert(buffer, &iter, tmpout, -1);
- g_free(tmpin);
+ mark = gtk_text_buffer_get_insert(buffer);
+ gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
+ if (g_utf8_validate(buf, -1, NULL)) {
+ gtk_text_buffer_insert(buffer, &iter, buf, -1);
+ } else {
+ gchar *tmpout = NULL;
+ tmpout = conv_codeset_strdup
+ (buf, conv_get_locale_charset_str(),
+ CS_INTERNAL);
+ if (!tmpout || !g_utf8_validate(tmpout, -1, NULL)) {
g_free(tmpout);
+ tmpout = g_malloc(strlen(buf)*2+1);
+ conv_localetodisp(tmpout, strlen(buf)*2+1, buf);
}
+ gtk_text_buffer_insert(buffer, &iter, tmpout, -1);
+ g_free(tmpout);
+ }
- if (lastp)
- p = lastp + 1;
- else
- break;
+ cursor_pos = quote_fmt_get_cursor_pos();
+ compose->set_cursor_pos = cursor_pos;
+ if (cursor_pos == -1) {
+ cursor_pos = 0;
}
+ 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)
+ if (compose->autowrap && rewrap)
compose_wrap_all(compose);
- g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
- G_CALLBACK(compose_changed_cb),
- compose);
- g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
- G_CALLBACK(text_inserted),
- compose);
+ goto ok;
+
+error:
+ buf = NULL;
+ok:
+ SIGNAL_UNBLOCK(buffer);
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,
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);
if (cur_pos > gtk_text_buffer_get_char_count (buffer))
cur_pos = gtk_text_buffer_get_char_count (buffer);
- gtk_text_buffer_get_iter_at_offset(buffer, &iter, cur_pos);
+ /* put the cursor where it should be
+ * either where the quote_fmt says, either before the signature */
+ if (compose->set_cursor_pos < 0)
+ gtk_text_buffer_get_iter_at_offset(buffer, &iter, cur_pos);
+ else
+ gtk_text_buffer_get_iter_at_offset(buffer, &iter,
+ compose->set_cursor_pos);
+
gtk_text_buffer_place_cursor(buffer, &iter);
-
g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
G_CALLBACK(compose_changed_cb),
compose);
if (quote_len > 0)
gtk_text_buffer_delete(buffer, &iter_, &end);
- /* delete linebreak and extra spaces */
+ /* don't join line breaks put by the user */
prev = cur = iter_;
+ gtk_text_iter_backward_char(&cur);
+ if (gtk_text_iter_has_tag(&cur, compose->no_join_tag)) {
+ return FALSE;
+ }
+ gtk_text_iter_forward_char(&cur);
+ /* delete linebreak and extra spaces */
while (gtk_text_iter_backward_char(&cur)) {
wc1 = gtk_text_iter_get_char(&cur);
if (!g_unichar_isspace(wc1))
g_warning("alloc error scanning URIs\n"); \
}
+static gboolean automatic_break = FALSE;
static void compose_beautify_paragraph(Compose *compose, GtkTextIter *par_iter, gboolean force)
{
GtkTextView *text = GTK_TEXT_VIEW(compose->text);
compose->autowrap = FALSE;
buffer = gtk_text_view_get_buffer(text);
-
- undo_block(compose->undostruct);
-
+ undo_wrapping(compose->undostruct, TRUE);
if (par_iter) {
iter = *par_iter;
} else {
}
/* go until paragraph end (empty line) */
+
while (!gtk_text_iter_ends_line(&iter)) {
gchar *scanpos = NULL;
/* parse table - in order of priority */
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);
gchar *o_walk = NULL, *walk = NULL, *bp = NULL, *ep = NULL;
gint walk_pos;
+ if (!prev_autowrap)
+ g_signal_handlers_block_by_func(G_OBJECT(buffer),
+ G_CALLBACK(text_inserted),
+ compose);
+
if (gtk_text_iter_has_tag(&iter, compose->no_wrap_tag) && !force)
goto colorize;
quote_len)) {
GtkTextIter prev, next, cur;
- if (prev_autowrap != FALSE || force)
+ if (prev_autowrap != FALSE || force) {
+ automatic_break = TRUE;
gtk_text_buffer_insert(buffer, &break_pos, "\n", 1);
- else if (quote_str && wrap_quote)
+ automatic_break = FALSE;
+ } else if (quote_str && wrap_quote) {
+ automatic_break = TRUE;
gtk_text_buffer_insert(buffer, &break_pos, "\n", 1);
- else
+ automatic_break = FALSE;
+ } else
goto colorize;
/* remove trailing spaces */
cur = break_pos;
/* move iter to current line start */
gtk_text_iter_set_line_offset(&iter, 0);
+ if (quote_str) {
+ g_free(quote_str);
+ quote_str = NULL;
+ }
continue;
} else {
/* move iter to next line start */
}
colorize:
+ if (!prev_autowrap)
+ g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
+ G_CALLBACK(text_inserted),
+ compose);
end_of_line = iter;
while (!gtk_text_iter_ends_line(&end_of_line)) {
gtk_text_iter_forward_char(&end_of_line);
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
if (par_iter)
*par_iter = iter;
-
- undo_unblock(compose->undostruct);
+ undo_wrapping(compose->undostruct, FALSE);
compose->autowrap = prev_autowrap;
}
+void compose_action_cb(void *data)
+{
+ Compose *compose = (Compose *)data;
+ compose_wrap_all(compose);
+}
+
static void compose_wrap_all(Compose *compose)
{
compose_wrap_all_full(compose, FALSE);
buffer = gtk_text_view_get_buffer(text);
- undo_block(compose->undostruct);
-
gtk_text_buffer_get_start_iter(buffer, &iter);
while (!gtk_text_iter_is_end(&iter))
compose_beautify_paragraph(compose, &iter, force);
- undo_unblock(compose->undostruct);
}
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);
"the main window to retry."));
if (prefs_common.send_dialog_mode == SEND_DIALOG_ALWAYS) {
compose->sending = FALSE;
+ compose->modified = TRUE;
compose_allow_user_actions (compose, TRUE);
}
return 0;
"the main window to retry."));
if (prefs_common.send_dialog_mode == SEND_DIALOG_ALWAYS) {
compose_allow_user_actions (compose, TRUE);
+ compose->modified = TRUE;
compose->sending = FALSE;
}
return -1;
bail:
compose_allow_user_actions (compose, TRUE);
compose->sending = FALSE;
+ compose->modified = TRUE;
return -1;
}
mimemsg->type = MIMETYPE_MESSAGE;
mimemsg->subtype = g_strdup("rfc822");
mimemsg->content = MIMECONTENT_MEM;
+ mimemsg->tmp = TRUE; /* must free content later */
mimemsg->data.mem = compose_get_header(compose);
/* Create text part MimeInfo */
mimetext = procmime_mimeinfo_new();
mimetext->content = MIMECONTENT_MEM;
+ mimetext->tmp = TRUE; /* must free content later */
mimetext->data.mem = buf;
mimetext->type = MIMETYPE_TEXT;
mimetext->subtype = g_strdup("plain");
return 0;
}
-static gint compose_remove_reedit_target(Compose *compose)
+static gint compose_remove_reedit_target(Compose *compose, gboolean force)
{
FolderItem *item;
MsgInfo *msginfo = compose->targetinfo;
g_return_val_if_fail(compose->mode == COMPOSE_REEDIT, -1);
if (!msginfo) return -1;
+ if (!force && MSG_IS_LOCKED(msginfo->flags))
+ return 0;
+
item = msginfo->folder;
g_return_val_if_fail(item != NULL, -1);
}
}
- if (prefs_common.linewrap_at_send)
- compose_wrap_all(compose);
-
/* write queue header */
tmp = g_strdup_printf("%s%cqueue.%p", get_tmp_dir(),
G_DIR_SEPARATOR, compose);
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;
g_free(tmp);
if (compose->mode == COMPOSE_REEDIT) {
- compose_remove_reedit_target(compose);
+ compose_remove_reedit_target(compose, FALSE);
}
if ((msgnum != NULL) && (item != NULL)) {
mimepart = procmime_mimeinfo_new();
mimepart->content = MIMECONTENT_FILE;
mimepart->data.filename = g_strdup(ainfo->file);
+ mimepart->tmp = FALSE; /* or we destroy our attachment */
mimepart->offset = 0;
stat(ainfo->file, &statbuf);
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",
{
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,
compose->account = account;
compose->mutex = g_mutex_new();
-
+ compose->set_cursor_pos = -1;
+
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
gtk_widget_set_size_request(window, -1, prefs_common.compose_height);
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();
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);
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 "
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);
}
}
if ((compose->replyinfo == NULL) && (compose->fwdinfo == NULL)) {
parsed_str = compose_quote_fmt(compose, NULL, tmpl->value,
- NULL, NULL);
+ NULL, NULL, FALSE);
} else {
if (prefs_common.quotemark && *prefs_common.quotemark)
qmark = prefs_common.quotemark;
if (compose->replyinfo != NULL)
parsed_str = compose_quote_fmt(compose, compose->replyinfo,
- tmpl->value, qmark, NULL);
+ tmpl->value, qmark, NULL, FALSE);
else if (compose->fwdinfo != NULL)
parsed_str = compose_quote_fmt(compose, compose->fwdinfo,
- tmpl->value, qmark, NULL);
+ tmpl->value, qmark, NULL, FALSE);
else
parsed_str = NULL;
}
if (parsed_str) {
cursor_pos = quote_fmt_get_cursor_pos();
+ compose->set_cursor_pos = cursor_pos;
+ if (cursor_pos == -1)
+ cursor_pos = 0;
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);
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);
strlist = NULL;
for (; mime_type_list != NULL; mime_type_list = mime_type_list->next) {
MimeType *type = (MimeType *) mime_type_list->data;
- strlist = g_list_append(strlist,
- g_strdup_printf("%s/%s",
- type->type, type->sub_type));
+ gchar *tmp;
+
+ tmp = g_strdup_printf("%s/%s", type->type, type->sub_type);
+
+ if (g_list_find_custom(strlist, tmp, (GCompareFunc)strcmp2))
+ g_free(tmp);
+ else
+ strlist = g_list_insert_sorted(strlist, (gpointer)tmp,
+ (GCompareFunc)strcmp2);
}
-
+
gtk_combo_set_popdown_strings(GTK_COMBO(mimetype_entry), strlist);
for (mime_type_list = strlist; mime_type_list != NULL;
static gboolean lock = FALSE;
MsgInfo *newmsginfo;
FILE *fp;
+ gboolean target_locked = FALSE;
if (lock) return;
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);
goto unlock;
}
fclose(fp);
+
+ if (compose->targetinfo) {
+ target_locked = MSG_IS_LOCKED(compose->targetinfo->flags);
+ flag.perm_flags = target_locked?MSG_LOCKED:0;
+ }
folder_item_scan(draft);
if ((msgnum = folder_item_add_msg(draft, tmp, &flag, TRUE)) < 0) {
draft->mtime = 0; /* force updating */
if (compose->mode == COMPOSE_REEDIT) {
- compose_remove_reedit_target(compose);
+ compose_remove_reedit_target(compose, TRUE);
}
newmsginfo = folder_item_get_msginfo(draft, msgnum);
if (newmsginfo) {
procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
- procmsg_msginfo_set_flags(newmsginfo, 0, MSG_DRAFT);
+ if (target_locked)
+ procmsg_msginfo_set_flags(newmsginfo, MSG_LOCKED, MSG_DRAFT);
+ else
+ procmsg_msginfo_set_flags(newmsginfo, 0, MSG_DRAFT);
if (compose_use_attach(compose))
procmsg_msginfo_set_flags(newmsginfo, 0,
MSG_HAS_ATTACHMENT);
gchar *path;
path = folder_item_fetch_msg(draft, msgnum);
- g_return_if_fail(path != NULL);
+ if (path == NULL) {
+ debug_print("can't fetch %s:%d\n",draft->path, msgnum);
+ goto unlock;
+ }
if (g_stat(path, &s) < 0) {
FILE_OP_ERROR(path, "stat");
g_free(path);
compose->targetinfo->size = s.st_size;
compose->targetinfo->mtime = s.st_mtime;
compose->targetinfo->folder = draft;
+ if (target_locked)
+ procmsg_msginfo_set_flags(compose->targetinfo, MSG_LOCKED, 0);
compose->mode = COMPOSE_REEDIT;
if (action == COMPOSE_AUTO_SAVE) {
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);
mark = gtk_text_buffer_create_mark(buffer, NULL, iter, FALSE);
gtk_text_buffer_place_cursor(buffer, iter);
- compose_quote_fmt(compose, NULL, "%Q", qmark, new_text);
+ compose_quote_fmt(compose, NULL, "%Q", qmark, new_text, TRUE);
g_free(new_text);
g_object_set_data(G_OBJECT(compose->text), "paste_as_quotation",
GINT_TO_POINTER(paste_as_quotation - 1));
gtk_text_buffer_get_iter_at_mark(buffer, iter, mark);
- } else
- gtk_text_buffer_insert(buffer, iter, text, len);
-
+ gtk_text_buffer_place_cursor(buffer, iter);
+ } else {
+ if (strcmp(text, "\n") || automatic_break)
+ gtk_text_buffer_insert(buffer, iter, text, len);
+ else {
+ debug_print("insert nowrap \\n\n");
+ gtk_text_buffer_insert_with_tags_by_name(buffer,
+ iter, text, len, "no_join", NULL);
+ }
+ }
+
mark = gtk_text_buffer_create_mark(buffer, NULL, iter, FALSE);
compose_beautify_paragraph(compose, iter, FALSE);