#define MAX_REFERENCES_LEN 999
+#define COMPOSE_DRAFT_TIMEOUT_UNSET -1
+#define COMPOSE_DRAFT_TIMEOUT_FORBIDDEN -2
+
static GList *compose_list = NULL;
static GSList *extra_headers = NULL;
if (prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
- compose->draft_timeout_tag = -1;
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET;
+
SCROLL_TO_CURSOR(compose);
compose->modified = FALSE;
compose_set_title(compose);
compose->updating = FALSE;
- compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
SCROLL_TO_CURSOR(compose);
if (compose->deferred_destroy) {
compose_set_title(compose);
compose->updating = FALSE;
- compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
SCROLL_TO_CURSOR(compose);
if (compose->deferred_destroy) {
compose_set_title(compose);
compose->updating = FALSE;
- compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
SCROLL_TO_CURSOR(compose);
if (compose->deferred_destroy) {
G_CALLBACK(text_inserted), \
compose); \
}
-#define UNBLOCK_WRAP() { \
- compose->autowrap = prev_autowrap; \
- if (compose->autowrap) { \
- gint old = compose->draft_timeout_tag; \
- compose->draft_timeout_tag = -2; \
- compose_wrap_all(compose); \
- compose->draft_timeout_tag = old; \
- } \
- \
- 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); \
+#define UNBLOCK_WRAP() { \
+ compose->autowrap = prev_autowrap; \
+ if (compose->autowrap) { \
+ gint old = compose->draft_timeout_tag; \
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_FORBIDDEN; \
+ compose_wrap_all(compose); \
+ compose->draft_timeout_tag = old; \
+ } \
+ \
+ 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); \
}
Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
compose_set_title(compose);
compose->updating = FALSE;
- compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
SCROLL_TO_CURSOR(compose);
if (compose->deferred_destroy) {
compose->modified = FALSE;
compose_set_title(compose);
compose->updating = FALSE;
- compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
SCROLL_TO_CURSOR(compose);
if (compose->deferred_destroy) {
case A_SIG:
compose_insert_sig(compose, FALSE);
break;
+ case A_REP_SIG:
+ compose_insert_sig(compose, TRUE);
+ break;
case A_EXTEDITOR:
compose_ext_editor_cb(NULL, compose);
break;
gchar *tmp1 = NULL;
if (!msginfo->from)
return;
- Xstrdup_a(tmp1, msginfo->from, return);
- extract_address(tmp1);
- if (to_all || to_sender ||
- !account_find_from_address(tmp1, FALSE))
+ if (to_sender)
+ compose_entry_append(compose, msginfo->from,
+ COMPOSE_TO, PREF_NONE);
+ else if (to_all) {
+ Xstrdup_a(tmp1, msginfo->from, return);
+ extract_address(tmp1);
compose_entry_append(compose,
- (compose->replyto && !to_sender)
- ? compose->replyto :
- msginfo->from ? msginfo->from : "",
+ (!account_find_from_address(tmp1, FALSE))
+ ? msginfo->from :
+ msginfo->to,
COMPOSE_TO, PREF_NONE);
- else if (!to_all && !to_sender) {
+ } else {
if (!folder_has_parent_of_type(msginfo->folder, F_QUEUE) &&
!folder_has_parent_of_type(msginfo->folder, F_OUTBOX) &&
!folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
alertpanel_error("Can't get file size of %s\n", filename);
return FALSE;
}
- if (size == 0) {
- alertpanel_error(_("File %s is empty."), filename);
- return FALSE;
+
+ /* In batch mode, we allow 0-length files to be attached no questions asked */
+ if (size == 0 && !compose->batch) {
+ gchar * msg = g_strdup_printf(_("File %s is empty."), filename);
+ AlertValue aval = alertpanel_full(_("Empty file"), msg,
+ GTK_STOCK_CANCEL, _("+_Attach anyway"), NULL, FALSE,
+ NULL, ALERT_WARNING, G_ALERTDEFAULT);
+ g_free(msg);
+
+ if (aval != G_ALERTALTERNATE) {
+ return FALSE;
+ }
}
if ((fp = g_fopen(file, "rb")) == NULL) {
alertpanel_error(_("Can't read %s."), filename);
if (force) {
modified = TRUE;
}
- if (compose->draft_timeout_tag == -2) {
+ if (compose->draft_timeout_tag == COMPOSE_DRAFT_TIMEOUT_FORBIDDEN) {
modified = TRUE;
}
}
- if (compose->draft_timeout_tag == -2) {
+ if (compose->draft_timeout_tag == COMPOSE_DRAFT_TIMEOUT_FORBIDDEN) {
if (gtk_text_iter_ends_line(&iter)) {
while (gtk_text_iter_ends_line(&iter) &&
gtk_text_iter_forward_line(&iter))
}
generate_msgid(buf, sizeof(buf), addr);
err |= (fprintf(fp, "Resent-Message-ID: <%s>\n", buf) < 0);
+ if (compose->msgid)
+ g_free(compose->msgid);
compose->msgid = g_strdup(buf);
} else {
compose->msgid = NULL;
}
generate_msgid(buf, sizeof(buf), addr);
g_string_append_printf(header, "Message-ID: <%s>\n", buf);
+ if (compose->msgid)
+ g_free(compose->msgid);
compose->msgid = g_strdup(buf);
} else {
compose->msgid = NULL;
gtk_major_version, gtk_minor_version, gtk_micro_version,
TARGET_ALIAS);
}
- if (g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
+ if (compose->account->gen_xmailer &&
+ g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
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,
gtk_table_attach(GTK_TABLE(compose->header_table), combo, 0, 1,
compose->header_nextrow, compose->header_nextrow+1,
GTK_SHRINK, GTK_FILL, 0, 0);
- if (compose->header_last && (compose->draft_timeout_tag != -2)) {
+ if (compose->header_last && (compose->draft_timeout_tag != COMPOSE_DRAFT_TIMEOUT_FORBIDDEN)) {
const gchar *last_header_entry = gtk_entry_get_text(
GTK_ENTRY(gtk_bin_get_child(GTK_BIN((compose->header_last->combo)))));
string = headers;
/* Notebook */
notebook = gtk_notebook_new();
- gtk_widget_set_size_request(notebook, -1, prefs_common.compose_notebook_height);
gtk_widget_show(notebook);
/* header labels and entries */
gtk_container_set_border_width(GTK_CONTAINER(subject), 0);
gtk_widget_show(subject);
- label = gtk_label_new(_("Subject:"));
+ label = gtk_label_new_with_mnemonic(_("Subject:"));
gtk_box_pack_start(GTK_BOX(subject), label, FALSE, FALSE, 0);
gtk_widget_show(label);
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_label_set_mnemonic_widget(GTK_LABEL(label), subject_entry);
gtk_widget_show(subject_entry);
compose->subject_entry = subject_entry;
gtk_container_add(GTK_CONTAINER(subject_frame), subject);
/* pane between attach clist and text */
paned = gtk_vpaned_new();
gtk_container_add(GTK_CONTAINER(vbox2), paned);
- gtk_paned_add1(GTK_PANED(paned), notebook);
- gtk_paned_add2(GTK_PANED(paned), edit_vbox);
+ gtk_paned_pack1(GTK_PANED(paned), notebook, FALSE, FALSE);
+ gtk_paned_pack2(GTK_PANED(paned), edit_vbox, TRUE, FALSE);
+ gtk_paned_set_position(GTK_PANED(paned), prefs_common.compose_notebook_height);
gtk_widget_show_all(paned);
compose->exteditor_file = NULL;
compose->exteditor_pid = -1;
compose->exteditor_tag = -1;
- compose->draft_timeout_tag = -2; /* inhibit auto-drafting while loading */
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_FORBIDDEN; /* inhibit auto-drafting while loading */
#if USE_ENCHANT
cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Spelling", FALSE);
if (compose->draft_timeout_tag >= 0) { /* CLAWS: disable draft timeout */
g_source_remove(compose->draft_timeout_tag);
- compose->draft_timeout_tag = -1;
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET;
}
compose_send(compose);
goto warn_err;
}
+ flag.perm_flags = MSG_NEW|MSG_UNREAD;
if (compose->targetinfo) {
target_locked = MSG_IS_LOCKED(compose->targetinfo->flags);
- flag.perm_flags = target_locked?MSG_LOCKED:0;
+ if (target_locked)
+ flag.perm_flags |= MSG_LOCKED;
}
flag.tmp_flags = MSG_DRAFT;
if (newmsginfo) {
procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
if (target_locked)
- procmsg_msginfo_set_flags(newmsginfo, MSG_LOCKED, MSG_DRAFT);
+ procmsg_msginfo_set_flags(newmsginfo, MSG_NEW|MSG_UNREAD|MSG_LOCKED, MSG_DRAFT);
else
- procmsg_msginfo_set_flags(newmsginfo, 0, MSG_DRAFT);
+ procmsg_msginfo_set_flags(newmsginfo, MSG_NEW|MSG_UNREAD, MSG_DRAFT);
if (compose_use_attach(compose) && action != COMPOSE_AUTO_SAVE)
procmsg_msginfo_set_flags(newmsginfo, 0,
MSG_HAS_ATTACHMENT);
compose_close_cb(NULL, compose);
}
+static gboolean compose_can_autosave(Compose *compose)
+{
+ if (compose->privacy_system && compose->use_encryption)
+ return prefs_common.autosave && prefs_common.autosave_encrypted;
+ else
+ return prefs_common.autosave;
+}
+
static void compose_close_cb(GtkAction *action, gpointer data)
{
Compose *compose = (Compose *)data;
g_mutex_unlock(compose->mutex);
switch (val) {
case G_ALERTDEFAULT:
- if (prefs_common.autosave && !reedit)
- compose_remove_draft(compose);
+ if (compose_can_autosave(compose) && !reedit)
+ compose_remove_draft(compose);
break;
case G_ALERTALTERNATE:
compose_draft(data, COMPOSE_QUIT_EDITING);
GdkEventKey *event,
Compose *compose)
{
+ GtkTextBuffer *buffer;
+ GtkTextMark *mark;
+ GtkTextIter iter;
+
cm_return_val_if_fail(compose != NULL, FALSE);
/* make backtab move to subject field */
gtk_widget_grab_focus(compose->subject_entry);
return TRUE;
}
+
+ // Up key should also move the focus to subject field, if the cursor
+ // is on the first line.
+ if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up) {
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+ g_return_val_if_fail(buffer != NULL, FALSE);
+
+ mark = gtk_text_buffer_get_mark(buffer, "insert");
+ g_return_val_if_fail(mark != NULL, FALSE);
+
+ gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
+
+ if (gtk_text_iter_get_line(&iter) == 0) {
+ gtk_widget_grab_focus(compose->subject_entry);
+ return TRUE;
+ }
+ }
+
return FALSE;
}
{
Compose *compose = (Compose *)data;
- cm_return_val_if_fail(!compose->batch, FALSE);
+ if (compose->batch)
+ return FALSE;
GTK_EVENTS_FLUSH();
compose_show_first_last_header(compose, FALSE);
static gboolean compose_defer_auto_save_draft(Compose *compose)
{
- compose->draft_timeout_tag = -1;
+ compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET;
compose_draft((gpointer)compose, COMPOSE_AUTO_SAVE);
return FALSE;
}
GtkAdjustment *vadj;
cm_return_if_fail(compose);
- cm_return_if_fail(!compose->batch);
+
+ if(compose->batch)
+ return;
+
cm_return_if_fail(GTK_IS_WIDGET(compose->header_table));
cm_return_if_fail(GTK_IS_VIEWPORT(gtk_widget_get_parent(compose->header_table)));
vadj = gtk_viewport_get_vadjustment(GTK_VIEWPORT(
compose);
g_signal_stop_emission_by_name(G_OBJECT(buffer), "insert-text");
- if (prefs_common.autosave &&
+ if (compose_can_autosave(compose) &&
gtk_text_buffer_get_char_count(buffer) % prefs_common.autosave_length == 0 &&
- compose->draft_timeout_tag != -2 /* disabled while loading */)
+ compose->draft_timeout_tag != COMPOSE_DRAFT_TIMEOUT_FORBIDDEN /* disabled while loading */)
compose->draft_timeout_tag = g_timeout_add
(500, (GSourceFunc) compose_defer_auto_save_draft, compose);
}
{
gint x, y;
+ cm_return_val_if_fail(compose, FALSE);
+
if (!g_mutex_trylock(compose->mutex)) {
/* we have to wait for the (possibly deferred by auto-save)
* drafting to be done, before destroying the compose under
* it. */
debug_print("waiting for drafting to finish...\n");
compose_allow_user_actions(compose, FALSE);
- g_timeout_add (500, (GSourceFunc) compose_close, compose);
+ if (compose->close_timeout_tag == 0) {
+ compose->close_timeout_tag =
+ g_timeout_add (500, (GSourceFunc) compose_close,
+ compose);
+ }
return FALSE;
}
- cm_return_val_if_fail(compose, FALSE);
+
+ if (compose->close_timeout_tag) {
+ /* let the close be done by the deferred callback */
+ g_mutex_unlock(compose->mutex);
+ return FALSE;
+ }
+
gtkut_widget_get_uposition(compose->window, &x, &y);
if (!compose->batch) {
prefs_common.compose_x = x;