#include "customheader.h"
#include "prefs_common.h"
#include "prefs_account.h"
+#include "prefs_actions.h"
#include "account.h"
#include "filesel.h"
#include "procheader.h"
#include "template.h"
#include "undo.h"
#include "foldersel.h"
-#include "prefs_actions.h"
#if USE_GPGME
# include "rfc2015.h"
Compose *compose_generic_new (PrefsAccount *account,
const gchar *to,
- FolderItem *item);
+ FolderItem *item,
+ GPtrArray *attach_files);
static Compose *compose_create (PrefsAccount *account,
ComposeMode mode);
MsgInfo *msginfo);
static void compose_wrap_line (Compose *compose);
static void compose_wrap_line_all (Compose *compose);
+static void compose_wrap_line_all_full (Compose *compose,
+ gboolean autowrap);
static void compose_set_title (Compose *compose);
static PrefsAccount *compose_current_mail_account(void);
static gint compose_write_body_to_file (Compose *compose,
const gchar *file);
static gint compose_remove_reedit_target (Compose *compose);
+void compose_remove_draft (Compose *compose);
static gint compose_queue (Compose *compose,
gint *msgnum,
FolderItem **item);
static void compose_cut_cb (Compose *compose);
static void compose_copy_cb (Compose *compose);
static void compose_paste_cb (Compose *compose);
+static void compose_paste_as_quote_cb (Compose *compose);
static void compose_allsel_cb (Compose *compose);
static void compose_gtk_stext_action_cb (Compose *compose,
Compose *compose);
static void newsgroups_activated (GtkWidget *widget,
Compose *compose);
-static void subject_activated (GtkWidget *widget,
- Compose *compose);
static void cc_activated (GtkWidget *widget,
Compose *compose);
static void bcc_activated (GtkWidget *widget,
Compose *compose);
static void followupto_activated (GtkWidget *widget,
Compose *compose);
+static void subject_activated (GtkWidget *widget,
+ Compose *compose);
#endif
+static void text_activated (GtkWidget *widget,
+ Compose *compose);
+static void text_inserted (GtkWidget *widget,
+ const gchar *text,
+ gint length,
+ gint *position,
+ Compose *compose);
static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
gboolean to_all,
gboolean ignore_replyto,
static void compose_show_first_last_header (Compose *compose, gboolean show_first);
-#if USE_PSPELL
+#if USE_ASPELL
static void compose_check_all (Compose *compose);
static void compose_highlight_all (Compose *compose);
static void compose_check_backwards (Compose *compose);
static void compose_check_forwards_go (Compose *compose);
#endif
-static gboolean compose_send_control_enter (Compose *compose);
-static void text_activated (GtkWidget *widget,
- Compose *compose);
+static gboolean compose_send_control_enter (Compose *compose);
static GtkItemFactoryEntry compose_popup_entries[] =
{
{N_("/_Edit/Cu_t"), "<control>X", compose_cut_cb, 0, NULL},
{N_("/_Edit/_Copy"), "<control>C", compose_copy_cb, 0, NULL},
{N_("/_Edit/_Paste"), "<control>V", compose_paste_cb, 0, NULL},
+ {N_("/_Edit/Paste as _quotation"),
+ NULL, compose_paste_as_quote_cb, 0, NULL},
{N_("/_Edit/Select _all"), "<control>A", compose_allsel_cb, 0, NULL},
{N_("/_Edit/A_dvanced"), NULL, NULL, 0, "<Branch>"},
{N_("/_Edit/A_dvanced/Move a character backward"),
"<control><alt>L", compose_wrap_line_all, 0, NULL},
{N_("/_Edit/Edit with e_xternal editor"),
"<shift><control>X", compose_ext_editor_cb, 0, NULL},
-#if USE_PSPELL
+#if USE_ASPELL
{N_("/_Spelling"), NULL, NULL, 0, "<Branch>"},
{N_("/_Spelling/_Check all or check selection"),
NULL, compose_check_all, 0, NULL},
{N_("/_Message/_Encrypt"), NULL, compose_toggle_encrypt_cb, 0, "<ToggleItem>"},
#endif /* USE_GPGME */
{N_("/_Message/---"), NULL, NULL, 0, "<Separator>"},
- {N_("/_Message/Priority"), NULL, NULL, 0, "<Branch>"},
- {N_("/_Message/Priority/Highest"), NULL, compose_set_priority_cb, PRIORITY_HIGHEST, "<RadioItem>"},
- {N_("/_Message/Priority/High"), NULL, compose_set_priority_cb, PRIORITY_HIGH, "/Message/Priority/Highest"},
- {N_("/_Message/Priority/Normal"), NULL, compose_set_priority_cb, PRIORITY_NORMAL, "/Message/Priority/Highest"},
- {N_("/_Message/Priority/Low"), NULL, compose_set_priority_cb, PRIORITY_LOW, "/Message/Priority/Highest"},
- {N_("/_Message/Priority/Lowest"), NULL, compose_set_priority_cb, PRIORITY_LOWEST, "/Message/Priority/Highest"},
+ {N_("/_Message/_Priority"), NULL, NULL, 0, "<Branch>"},
+ {N_("/_Message/Priority/_Highest"), NULL, compose_set_priority_cb, PRIORITY_HIGHEST, "<RadioItem>"},
+ {N_("/_Message/Priority/Hi_gh"), NULL, compose_set_priority_cb, PRIORITY_HIGH, "/Message/Priority/Highest"},
+ {N_("/_Message/Priority/_Normal"), NULL, compose_set_priority_cb, PRIORITY_NORMAL, "/Message/Priority/Highest"},
+ {N_("/_Message/Priority/Lo_w"), NULL, compose_set_priority_cb, PRIORITY_LOW, "/Message/Priority/Highest"},
+ {N_("/_Message/Priority/_Lowest"), NULL, compose_set_priority_cb, PRIORITY_LOWEST, "/Message/Priority/Highest"},
{N_("/_Message/---"), NULL, NULL, 0, "<Separator>"},
{N_("/_Message/_Request Return Receipt"), NULL, compose_toggle_return_receipt_cb, 0, "<ToggleItem>"},
{N_("/_Tools"), NULL, NULL, 0, "<Branch>"},
{"text/uri-list", 0, 0}
};
-Compose *compose_new(PrefsAccount *account)
-{
- return compose_generic_new(account, NULL, NULL);
-}
-
-Compose *compose_bounce(PrefsAccount *account, MsgInfo *msginfo)
+Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
{
Compose *c;
gchar *filename;
GtkItemFactory *ifactory;
- c = compose_generic_new(account, NULL, NULL);
+ c = compose_generic_new(account, NULL, NULL, NULL);
filename = procmsg_get_message_file(msginfo);
if (filename == NULL)
return NULL;
- c->bounce_filename = filename;
+ c->redirect_filename = filename;
if (msginfo->subject)
gtk_entry_set_text(GTK_ENTRY(c->subject_entry),
return c;
}
-Compose *compose_new_with_recipient(PrefsAccount *account, const gchar *mailto)
+Compose *compose_new(PrefsAccount *account, const gchar *mailto,
+ GPtrArray *attach_files)
{
- return compose_generic_new(account, mailto, NULL);
+ return compose_generic_new(account, mailto, NULL, attach_files);
}
Compose *compose_new_with_folderitem(PrefsAccount *account, FolderItem *item)
{
- return compose_generic_new(account, NULL, item);
+ return compose_generic_new(account, NULL, item, NULL);
}
-Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderItem *item)
+Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderItem *item,
+ GPtrArray *attach_files)
{
Compose *compose;
+ GtkSText *text;
+ GtkItemFactory *ifactory;
+ gboolean grab_focus_on_last = TRUE;
if (item && item->prefs && item->prefs->enable_default_account)
account = account_find_from_id(item->prefs->default_account);
g_return_val_if_fail(account != NULL, NULL);
compose = compose_create(account, COMPOSE_NEW);
+ ifactory = gtk_item_factory_from_widget(compose->menubar);
+
compose->replyinfo = NULL;
+ text = GTK_STEXT(compose->text);
+ gtk_stext_freeze(text);
+
if (prefs_common.auto_sig)
compose_insert_sig(compose);
- gtk_editable_set_position(GTK_EDITABLE(compose->text), 0);
- gtk_stext_set_point(GTK_STEXT(compose->text), 0);
+ gtk_editable_set_position(GTK_EDITABLE(text), 0);
+ gtk_stext_set_point(text, 0);
+
+ gtk_stext_thaw(text);
+
+ /* workaround for initial XIM problem */
+ gtk_widget_grab_focus(compose->text);
+ gtkut_widget_wait_for_draw(compose->text);
if (account->protocol != A_NNTP) {
- if (mailto) {
+ if (mailto && *mailto != '\0') {
compose_entries_set(compose, mailto);
} else if(item && item->prefs->enable_default_to) {
compose_entry_append(compose, item->prefs->default_to, COMPOSE_TO);
+ compose_entry_select(compose, item->prefs->default_to);
+ grab_focus_on_last = FALSE;
}
if (item && item->ret_rcpt) {
- GtkItemFactory *ifactory;
-
- ifactory = gtk_item_factory_from_widget(compose->menubar);
menu_set_toggle(ifactory, "/Message/Request Return Receipt", TRUE);
}
} else {
if (mailto) {
compose_entry_append(compose, mailto, COMPOSE_NEWSGROUPS);
}
+ /*
+ * CLAWS: just don't allow return receipt request, even if the user
+ * may want to send an email. simple but foolproof.
+ */
+ menu_set_sensitive(ifactory, "/Message/Request Return Receipt", FALSE);
}
+
+ if (attach_files) {
+ gint i;
+ gchar *file;
+
+ for (i = 0; i < attach_files->len; i++) {
+ file = g_ptr_array_index(attach_files, i);
+ compose_attach_append(compose, file, file, NULL);
+ }
+ }
+
compose_show_first_last_header(compose, TRUE);
/* Set save folder */
gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
g_free(folderidentifier);
}
-
- gtk_widget_grab_focus(compose->header_last->entry);
+
+ /* Grab focus on last header only if no default_to was set */
+ if(grab_focus_on_last)
+ gtk_widget_grab_focus(compose->header_last->entry);
if (prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
} else
reply_account = account;
- MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_FORWARDED);
- MSG_SET_PERM_FLAGS(msginfo->flags, MSG_REPLIED);
- if (MSG_IS_IMAP(msginfo->flags))
- imap_msg_set_perm_flags(msginfo, MSG_REPLIED);
- CHANGE_FLAGS(msginfo);
-
compose = compose_create(account, COMPOSE_REPLY);
- compose->replyinfo = procmsg_msginfo_copy(msginfo);
+ compose->replyinfo = procmsg_msginfo_new_ref(msginfo);
#if 0 /* NEW COMPOSE GUI */
if (followup_and_reply_to) {
static void set_toolbar_style(Compose *compose);
-static gchar *procmime_get_file_name(MimeInfo *mimeinfo)
-{
- gchar *base;
- gchar *filename;
-
- g_return_val_if_fail(mimeinfo != NULL, NULL);
-
- base = mimeinfo->filename ? mimeinfo->filename
- : mimeinfo->name ? mimeinfo->name : NULL;
-
- if (MIME_TEXT_HTML == mimeinfo->mime_type && base == NULL){
- filename = g_strdup_printf("%s%smimetmp.%08x.html",
- get_mime_tmp_dir(),
- G_DIR_SEPARATOR_S,
- (gint)mimeinfo);
- return filename;
- }
- else {
- base = base ? base : "";
- base = g_basename(base);
- if (*base == '\0') {
- filename = g_strdup_printf("%s%smimetmp.%08x",
- get_mime_tmp_dir(),
- G_DIR_SEPARATOR_S,
- (gint)mimeinfo);
- return filename;
- }
- }
-
- filename = g_strconcat(get_mime_tmp_dir(), G_DIR_SEPARATOR_S,
- base, NULL);
-
- return filename;
-}
-
-static gchar *mime_extract_file(gchar *source, MimeInfo *partinfo)
-{
- gchar *filename;
-
- if (!partinfo) return NULL;
-
- filename = procmime_get_file_name(partinfo);
-
- if (procmime_get_part(filename, source, partinfo) < 0)
- alertpanel_error
- (_("Can't get the part of multipart message."));
-
- return filename;
-}
-
-
-
#define INSERT_FW_HEADER(var, hdr) \
if (msginfo->var && *msginfo->var) { \
gtk_stext_insert(text, NULL, NULL, NULL, hdr, -1); \
gtk_stext_set_point(GTK_STEXT(compose->text), 0);
gtk_stext_thaw(text);
+ gtk_widget_grab_focus(compose->header_last->entry);
+
#if 0 /* NEW COMPOSE GUI */
if (account->protocol != A_NNTP)
gtk_widget_grab_focus(compose->to_entry);
void compose_entry_append(Compose *compose, const gchar *address,
ComposeEntryType type)
{
- GtkEntry *entry;
- const gchar *text;
gchar *header;
if (!address || *address == '\0') return;
compose_add_header_entry(compose, header, (gchar *)address);
}
+void compose_entry_select (Compose *compose, const gchar *mailto)
+{
+ GSList *header_list;
+
+ for (header_list = compose->header_list; header_list != NULL; header_list = header_list->next) {
+ GtkEntry * entry = GTK_ENTRY(((ComposeHeaderEntry *)header_list->data)->entry);
+
+ if (gtk_entry_get_text(entry) && !g_strcasecmp(gtk_entry_get_text(entry), mailto)) {
+ gtk_entry_select_region(entry, 0, -1);
+ gtk_widget_grab_focus(GTK_WIDGET(entry));
+ }
+ }
+}
+
static void compose_entries_set(Compose *compose, const gchar *mailto)
{
gchar *subject = NULL;
const gchar *body)
{
GtkSText *text = GTK_STEXT(compose->text);
+ static MsgInfo dummyinfo;
gchar *quote_str = NULL;
gchar *buf;
gchar *p, *lastp;
gint len;
+ if (!msginfo)
+ msginfo = &dummyinfo;
+
if (qmark != NULL) {
quote_fmt_init(msginfo, NULL, NULL);
quote_fmt_scan_string(qmark);
static void compose_exec_sig(Compose *compose, gchar *sigfile)
{
- FILE *tmpfp;
- pid_t thepid;
- gchar *sigtext;
FILE *sigprg;
gchar *buf;
size_t buf_len = 128;
(_("Message: %s"),
g_basename(filename ? filename : file));
} else {
- ainfo->encoding = ENC_BASE64;
+ if (!g_strncasecmp(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));
}
} else {
ainfo->content_type = procmime_get_mime_type(file);
- if (!ainfo->content_type)
+ if (!ainfo->content_type) {
ainfo->content_type =
g_strdup("application/octet-stream");
- ainfo->encoding = ENC_BASE64;
+ ainfo->encoding = ENC_BASE64;
+ } else if (!g_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));
}
ainfo->size = size;
/* Darko: used when I debug wrapping */
void dump_text(GtkSText *text, int pos, int tlen, int breakoncr)
{
- gint i;
- gchar ch;
+ gint i, clen;
+ gchar cbuf[MB_LEN_MAX];
printf("%d [", pos);
for (i = pos; i < tlen; i++) {
- ch = GTK_STEXT_INDEX(text, i);
- if (breakoncr && ch == '\n')
+ GET_CHAR(i, cbuf, clen);
+ if (clen < 0) break;
+ if (breakoncr && clen == 1 && cbuf[0] == '\n')
break;
- printf("%c", ch);
+ fwrite(cbuf, clen, 1, stdout);
}
printf("]\n");
}
guint prev_line_pos, guint text_len,
gchar *quote_fmt)
{
- guint i, ins_len;
+ guint i, ins_len = 0;
gchar ch;
if (indent_len) {
/* check if we should join the next line */
static gboolean join_next_line(GtkSText *text, guint start_pos, guint tlen,
- guint prev_ilen)
+ guint prev_ilen, gboolean autowrap)
{
guint indent_len, ch_len;
gboolean do_join = FALSE;
indent_len = get_indent_length(text, start_pos, tlen);
- if ((indent_len > 0) && (indent_len == prev_ilen)) {
+ if ((autowrap || indent_len > 0) && indent_len == prev_ilen) {
GET_CHAR(start_pos + indent_len, cbuf, ch_len);
if (ch_len > 0 && (cbuf[0] != '\n'))
do_join = TRUE;
}
static void compose_wrap_line_all(Compose *compose)
+{
+ compose_wrap_line_all_full(compose, FALSE);
+}
+
+#define STEXT_FREEZE() \
+ if (!frozen) { gtk_stext_freeze(text); frozen = TRUE; }
+
+static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
{
GtkSText *text = GTK_STEXT(compose->text);
guint tlen;
gboolean is_new_line = TRUE, do_delete = FALSE;
guint i_len = 0;
gboolean linewrap_quote = TRUE;
+ gboolean set_editable_pos = FALSE;
+ gint editable_pos = 0;
+ gboolean frozen = FALSE;
guint linewrap_len = prefs_common.linewrap_len;
gchar *qfmt = prefs_common.quotemark;
gchar cbuf[MB_LEN_MAX];
- gtk_stext_freeze(text);
-
- /* make text buffer contiguous */
- /* gtk_stext_compact_buffer(text); */
-
tlen = gtk_stext_get_length(text);
for (; cur_pos < tlen; cur_pos++) {
is_new_line = FALSE;
p_pos = cur_pos;
#ifdef WRAP_DEBUG
- printf("new line i_len=%d p_pos=", i_len);
+ g_print("new line i_len=%d p_pos=", i_len);
dump_text(text, p_pos, tlen, 1);
#endif
}
guint tab_offset = line_len % tab_width;
#ifdef WRAP_DEBUG
- printf("found tab at pos=%d line_len=%d ", cur_pos,
+ g_print("found tab at pos=%d line_len=%d ", cur_pos,
line_len);
#endif
if (tab_offset) {
/* we have encountered line break */
if (ch_len == 1 && *cbuf == '\n') {
gint clen;
- gchar cb[MB_CUR_MAX];
+ gchar cb[MB_LEN_MAX];
/* should we join the next line */
- if ((i_len != cur_len) && do_delete &&
- join_next_line(text, cur_pos + 1, tlen, i_len))
+ if ((autowrap || i_len != cur_len) && do_delete &&
+ join_next_line
+ (text, cur_pos + 1, tlen, i_len, autowrap))
do_delete = TRUE;
else
do_delete = FALSE;
#ifdef WRAP_DEBUG
- printf("found CR at %d do_del is %d next line is ",
+ g_print("found CR at %d do_del is %d next line is ",
cur_pos, do_delete);
dump_text(text, cur_pos + 1, tlen, 1);
#endif
do_delete = FALSE;
#ifdef WRAP_DEBUG
- printf("l_len=%d wrap_len=%d do_del=%d\n",
+ g_print("l_len=%d wrap_len=%d do_del=%d\n",
line_len, linewrap_len, do_delete);
#endif
/* should we delete to perform smart wrapping */
if (line_len < linewrap_len && do_delete) {
+ STEXT_FREEZE();
/* get rid of newline */
gtk_stext_set_point(text, cur_pos);
gtk_stext_forward_delete(text, 1);
((clen > 1) || isalnum(cb[0]))) {
gtk_stext_insert(text, NULL, NULL,
NULL, " ", 1);
- /* gtk_stext_compact_buffer(text); */
tlen++;
}
do_delete = FALSE;
is_new_line = TRUE;
#ifdef WRAP_DEBUG
- printf("after delete l_pos=");
+ g_print("after delete l_pos=");
dump_text(text, line_pos, tlen, 1);
#endif
continue;
gint clen;
#ifdef WRAP_DEBUG
- printf("should wrap cur_pos=%d ", cur_pos);
+ g_print("should wrap cur_pos=%d ", cur_pos);
dump_text(text, p_pos, tlen, 1);
dump_text(text, line_pos, tlen, 1);
#endif
(text, line_pos, tlen))
line_pos = cur_pos - 1;
#ifdef WRAP_DEBUG
- printf("new line_pos=%d\n", line_pos);
+ g_print("new line_pos=%d\n", line_pos);
#endif
GET_CHAR(line_pos - 1, cbuf, clen);
/* if next character is space delete it */
- if (clen == 1 && isspace(*cbuf)) {
+ if (clen == 1 && isspace(*cbuf)) {
if (p_pos + i_len != line_pos ||
!gtkut_stext_is_uri_string
(text, line_pos, tlen)) {
+ STEXT_FREEZE();
+ /* workaround for correct cursor
+ position */
+ if (set_editable_pos == FALSE) {
+ editable_pos = gtk_editable_get_position(GTK_EDITABLE(text));
+ if (editable_pos == line_pos)
+ set_editable_pos = TRUE;
+ }
gtk_stext_set_point(text, line_pos);
gtk_stext_backward_delete(text, 1);
tlen--;
if (p_pos + i_len == line_pos &&
gtkut_stext_is_uri_string(text, line_pos, tlen)) {
#ifdef WRAP_DEBUG
- printf("found URL at ");
+ g_print("found URL at ");
dump_text(text, line_pos, tlen, 1);
#endif
continue;
}
/* insert CR */
+ STEXT_FREEZE();
gtk_stext_set_point(text, line_pos);
gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
/* gtk_stext_compact_buffer(text); */
cur_pos = line_pos - 1;
/* start over with current line */
is_new_line = TRUE;
- line_len = 0;
- cur_len = 0;
- if (i_len)
+ line_len = cur_len = 0;
+ if (autowrap || i_len > 0)
do_delete = TRUE;
else
do_delete = FALSE;
#ifdef WRAP_DEBUG
- printf("after CR insert ");
+ g_print("after CR insert ");
dump_text(text, line_pos, tlen, 1);
dump_text(text, cur_pos, tlen, 1);
#endif
ins_len = ins_quote
(text, i_len, p_pos,
tlen, qfmt);
-
- /* gtk_stext_compact_buffer(text); */
tlen += ins_len;
}
#ifdef WRAP_DEBUG
- printf("after quote insert ");
+ g_print("after quote insert ");
dump_text(text, line_pos, tlen, 1);
#endif
}
cur_len += ch_len;
}
- gtk_stext_thaw(text);
+ if (frozen)
+ gtk_stext_thaw(text);
+
+ if (set_editable_pos && editable_pos <= tlen)
+ gtk_editable_set_position(GTK_EDITABLE(text), editable_pos);
}
+#undef STEXT_FREEZE
#undef GET_CHAR
static void compose_set_title(Compose *compose)
for(list = compose->header_list; list; list = list->next) {
gchar *header;
gchar *entry;
- header = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry));
+ header = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry), 0, -1);
entry = gtk_editable_get_chars(GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
g_strstrip(entry);
if(entry[0] != '\0') {
}
}
}
+ g_free(header);
g_free(entry);
}
return recipient_found;
}
/* write to temporary file */
- g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg%d",
- get_rc_dir(), G_DIR_SEPARATOR, (gint)compose);
+ g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg.%08x",
+ get_tmp_dir(), G_DIR_SEPARATOR, (gint)compose);
if (prefs_common.linewrap_at_send)
compose_wrap_line_all(compose);
return(gtk_clist_get_row_data(GTK_CLIST(compose->attach_clist), 0) != NULL);
}
-static gint compose_bounce_write_headers_from_headerlist(Compose *compose,
- FILE *fp)
+static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
+ FILE *fp)
{
gchar buf[BUFFSIZE];
gchar *str;
GSList *list;
ComposeHeaderEntry *headerentry;
gchar *headerentryname;
- gchar *header_w_colon;
gchar *cc_hdr;
gchar *to_hdr;
- debug_print(_("Writing bounce header\n"));
+ debug_print("Writing redirect header\n");
+
+ cc_hdr = prefs_common.trans_hdr ? _("Cc:") : "Cc:";
+ to_hdr = prefs_common.trans_hdr ? _("To:") : "To:";
- header_w_colon = g_strconcat("To:", NULL);
- to_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
- header_w_colon = g_strconcat("Cc:", NULL);
- cc_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
-
first_address = TRUE;
for(list = compose->header_list; list; list = list->next) {
headerentry = ((ComposeHeaderEntry *)list->data);
return(0);
}
-static gint compose_bounce_write_headers(Compose *compose, FILE *fp)
+static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
{
gchar buf[BUFFSIZE];
gchar *str;
g_return_val_if_fail(compose->account != NULL, -1);
g_return_val_if_fail(compose->account->address != NULL, -1);
- /* Date */
+ /* Resent-Date */
get_rfc822_date(buf, sizeof(buf));
fprintf(fp, "Resent-Date: %s\n", buf);
- /* From */
+ /* Resent-From */
if (compose->account->name && *compose->account->name) {
compose_convert_header
(buf, sizeof(buf), compose->account->name,
} else
fprintf(fp, "Resent-From: %s\n", compose->account->address);
- /* To */
- compose_bounce_write_headers_from_headerlist(compose, fp);
+ /* Subject */
+ str = gtk_entry_get_text(GTK_ENTRY(compose->subject_entry));
+ if (*str != '\0') {
+ Xstrdup_a(str, str, return -1);
+ g_strstrip(str);
+ if (*str != '\0') {
+ compose_convert_header(buf, sizeof(buf), str,
+ strlen("Subject: "));
+ fprintf(fp, "Subject: %s\n", buf);
+ }
+ }
+
+ /* Resent-Message-ID */
+ if (compose->account->gen_msgid) {
+ compose_generate_msgid(compose, buf, sizeof(buf));
+ fprintf(fp, "Resent-Message-Id: <%s>\n", buf);
+ compose->msgid = g_strdup(buf);
+ }
+
+ compose_redirect_write_headers_from_headerlist(compose, fp);
/* separator between header and body */
fputs("\n", fp);
return 0;
}
-static gint compose_bounce_write_to_file(Compose *compose, const gchar *file)
+static gint compose_redirect_write_to_file(Compose *compose, const gchar *file)
{
FILE *fp;
FILE *fdest;
size_t len;
gchar buf[BUFFSIZE];
- if ((fp = fopen(compose->bounce_filename, "rb")) == NULL) {
+ if ((fp = fopen(compose->redirect_filename, "rb")) == NULL) {
FILE_OP_ERROR(file, "fopen");
return -1;
}
while (procheader_get_unfolded_line(buf, sizeof(buf), fp)) {
/* should filter returnpath, delivered-to */
- if ((g_strncasecmp(buf, "Return-Path:",
- strlen("Return-Path:")) == 0)
- || (g_strncasecmp(buf, "Delivered-To:",
- strlen("Delivered-To:")) == 0))
+ 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)
continue;
if (fputs(buf, fdest) == -1)
goto error;
- if (!prefs_common.bounce_keep_from) {
+ if (!prefs_common.redirect_keep_from) {
if (g_strncasecmp(buf, "From:",
strlen("From:")) == 0) {
fputs(" (by way of ", fdest);
goto error;
}
- compose_bounce_write_headers(compose, fdest);
+ compose_redirect_write_headers(compose, fdest);
- while ((len = fread(buf, sizeof(gchar), BUFFSIZE, fp)) > 0) {
- if (fwrite(buf, sizeof(gchar), len, fdest) == -1)
+ while ((len = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
+ if (fwrite(buf, sizeof(gchar), len, fdest) != len) {
+ FILE_OP_ERROR(file, "fwrite");
goto error;
+ }
}
- fclose(fdest);
fclose(fp);
+ if (fclose(fdest) == EOF) {
+ FILE_OP_ERROR(file, "fclose");
+ unlink(file);
+ return -1;
+ }
return 0;
error:
- fclose(fdest);
fclose(fp);
+ fclose(fdest);
+ unlink(file);
return -1;
}
-#ifdef USE_GPGME
-/*
- * interfaces to rfc2015 to keep out the prefs stuff there.
+#if USE_GPGME
+/* interfaces to rfc2015 to keep out the prefs stuff there.
* returns 0 on success and -1 on error. */
-static int compose_create_signers_list (Compose *compose, GSList **pkey_list)
+static gint compose_create_signers_list(Compose *compose, GSList **pkey_list)
{
- const char *keyid = NULL;
+ const gchar *key_id = NULL;
GSList *key_list;
switch (compose->account->sign_key) {
case SIGN_KEY_DEFAULT:
*pkey_list = NULL;
- return 0; /* nothing to do */
-
+ return 0;
case SIGN_KEY_BY_FROM:
- keyid = compose->account->address;
+ key_id = compose->account->address;
break;
-
case SIGN_KEY_CUSTOM:
- keyid = compose->account->sign_key_id;
+ key_id = compose->account->sign_key_id;
break;
-
default:
- g_assert_not_reached ();
+ break;
}
- key_list = rfc2015_create_signers_list(keyid);
+ key_list = rfc2015_create_signers_list(key_id);
if (!key_list) {
- alertpanel_error("Could not find any key associated with currently "
- "selected keyid `%s'!", keyid);
- return -1;
+ alertpanel_error(_("Could not find any key associated with "
+ "currently selected key id `%s'."), key_id);
+ return -1;
}
-
+
*pkey_list = key_list;
return 0;
}
+
+/* clearsign message body text */
+static gint compose_clearsign_text(Compose *compose, gchar **text)
+{
+ GSList *key_list;
+ gchar *tmp_file;
+
+ tmp_file = get_tmp_file();
+ if (str_write_to_file(*text, tmp_file) < 0) {
+ g_free(tmp_file);
+ return -1;
+ }
+
+ if (canonicalize_file_replace(tmp_file) < 0 ||
+ compose_create_signers_list(compose, &key_list) < 0 ||
+ rfc2015_clearsign(tmp_file, key_list) < 0) {
+ unlink(tmp_file);
+ g_free(tmp_file);
+ return -1;
+ }
+
+ g_free(*text);
+ *text = file_read_to_str(tmp_file);
+ unlink(tmp_file);
+ g_free(tmp_file);
+ if (*text == NULL)
+ return -1;
+
+ return 0;
+}
#endif /* USE_GPGME */
static gint compose_write_to_file(Compose *compose, const gchar *file,
chars = gtk_editable_get_chars(GTK_EDITABLE(compose->text), 0, -1);
len = strlen(chars);
if (is_ascii_str(chars)) {
- buf = g_strdup(chars);
+ buf = chars;
+ chars = NULL;
out_codeset = CS_US_ASCII;
encoding = ENC_7BIT;
} else {
unlink(file);
return -1;
} else {
- buf = g_strdup(chars);
+ buf = chars;
+ chars = NULL;
}
}
}
g_free(chars);
+#if USE_GPGME
+ if (!is_draft && compose->use_signing && compose->account->clearsign) {
+ if (compose_clearsign_text(compose, &buf) < 0) {
+ g_warning("clearsign failed\n");
+ fclose(fp);
+ unlink(file);
+ g_free(buf);
+ return -1;
+ }
+ }
+#endif
+
/* write headers */
if (compose_write_headers
(compose, fp, out_codeset, encoding, is_draft) < 0) {
for (i = 0; i < len; i += B64_LINE_SIZE) {
l = MIN(B64_LINE_SIZE, len - i);
- to64frombits(outbuf, buf + i, l);
+ base64_encode(outbuf, buf + i, l);
fputs(outbuf, fp);
fputc('\n', fp);
}
}
#if USE_GPGME
- if (compose->use_signing) {
+ if (is_draft)
+ return 0;
+
+ if ((compose->use_signing && !compose->account->clearsign) ||
+ compose->use_encryption) {
+ if (canonicalize_file_replace(file) < 0) {
+ unlink(file);
+ return -1;
+ }
+ }
+
+ if (compose->use_signing && !compose->account->clearsign) {
GSList *key_list;
-
- if (compose_create_signers_list(compose, &key_list) == -1 ||
- rfc2015_sign(file, key_list) < 0) {
-
+
+ if (compose_create_signers_list(compose, &key_list) < 0 ||
+ rfc2015_sign(file, key_list) < 0) {
unlink(file);
return -1;
}
}
if (compose->use_encryption) {
- if (rfc2015_encrypt(file, compose->to_list, compose->account->ascii_armored) < 0) {
+ if (rfc2015_encrypt(file, compose->to_list,
+ compose->account->ascii_armored) < 0) {
unlink(file);
return -1;
}
item = msginfo->folder;
g_return_val_if_fail(item != NULL, -1);
- folder_item_scan(item);
if (procmsg_msg_exist(msginfo) &&
(item->stype == F_DRAFT || item->stype == F_QUEUE)) {
if (folder_item_remove_msg(item, msginfo->msgnum) < 0) {
return 0;
}
+void compose_remove_draft(Compose *compose)
+{
+ FolderItem *drafts;
+ MsgInfo *msginfo = compose->targetinfo;
+ drafts = account_get_special_folder(compose->account, F_DRAFT);
+
+ if (procmsg_msg_exist(msginfo)) {
+ folder_item_remove_msg(drafts, msginfo->msgnum);
+ folderview_update_item(drafts, TRUE);
+ }
+
+}
+
static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item)
{
return compose_queue_sub (compose, msgnum, item, FALSE);
GSList *cur;
gchar buf[BUFFSIZE];
gint num;
- MsgFlags flag = {0, 0};
static gboolean lock = FALSE;
PrefsAccount *mailac = NULL, *newsac = NULL;
- debug_print(_("queueing message...\n"));
+ debug_print("queueing message...\n");
g_return_val_if_fail(compose->account != NULL, -1);
g_return_val_if_fail(compose->orig_account != NULL, -1);
tmp2 = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(),
G_DIR_SEPARATOR, (gint)compose);
- if (compose->bounce_filename != NULL) {
- if (compose_bounce_write_to_file(compose, tmp2) < 0) {
+ if (compose->redirect_filename != NULL) {
+ if (compose_redirect_write_to_file(compose, tmp2) < 0) {
unlink(tmp2);
lock = FALSE;
return -1;
}
/* Save copy folder */
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn))) {
- gchar *str;
+ gchar *savefolderid;
+
+ savefolderid = gtk_editable_get_chars(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
+ fprintf(fp, "SCF:%s\n", savefolderid);
+ g_free(savefolderid);
+ }
+ /* Message-ID of message replying to */
+ if((compose->replyinfo != NULL) && (compose->replyinfo->msgid != NULL)) {
+ gchar *folderid;
- str = gtk_editable_get_chars(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
- fprintf(fp, "SCF:%s\n", str);
- g_free(str);
+ folderid = folder_item_get_identifier(compose->replyinfo->folder);
+ fprintf(fp, "RMID:%s\x7f%d\x7f%s\n", folderid, compose->replyinfo->msgnum, compose->replyinfo->msgid);
+ g_free(folderid);
}
fprintf(fp, "\n");
(compose->targetinfo->folder, TRUE);
}
- procmsg_add_flags(queue, num, flag);
- folder_item_scan(queue);
folderview_update_item(queue, TRUE);
if((msgnum != NULL) && (item != NULL)) {
while ((len = fread(inbuf, sizeof(gchar),
B64_LINE_SIZE, attach_fp))
== B64_LINE_SIZE) {
- to64frombits(outbuf, inbuf, B64_LINE_SIZE);
+ base64_encode(outbuf, inbuf, B64_LINE_SIZE);
fputs(outbuf, fp);
fputc('\n', fp);
}
if (len > 0 && feof(attach_fp)) {
- to64frombits(outbuf, inbuf, len);
+ base64_encode(outbuf, inbuf, len);
fputs(outbuf, fp);
fputc('\n', fp);
}
#define QUOTE_IF_REQUIRED(out, str) \
{ \
- if (*str != '"' && strchr(str, ',')) { \
+ if (*str != '"' && (strchr(str, ',') \
+ || strchr(str, '.'))) { \
gchar *__tmp; \
gint len; \
\
return 0;
}
- debug_print(_("Writing %s-header\n"), header);
+ debug_print("Writing %s-header\n", header);
header_w_colon = g_strconcat(header, ":", NULL);
trans_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
fprintf(fp, "X-Mailer: %s (GTK+ %d.%d.%d; %s)\n",
prog_version,
gtk_major_version, gtk_minor_version, gtk_micro_version,
- HOST_ALIAS);
+ TARGET_ALIAS);
/* utsbuf.sysname, utsbuf.release, utsbuf.machine); */
}
if (g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
fprintf(fp, "X-Newsreader: %s (GTK+ %d.%d.%d; %s)\n",
prog_version,
gtk_major_version, gtk_minor_version, gtk_micro_version,
- HOST_ALIAS);
+ TARGET_ALIAS);
/* utsbuf.sysname, utsbuf.release, utsbuf.machine); */
}
case PRIORITY_LOWEST: fprintf(fp, "Importance: low\n"
"X-Priority: 5 (Lowest)\n");
break;
- default: debug_print(_("compose: priority unknown : %d\n"),
+ default: debug_print("compose: priority unknown : %d\n",
compose->priority);
}
lt->tm_min, lt->tm_sec,
(guint)random(), addr);
- debug_print(_("generated Message-ID: %s\n"), buf);
+ debug_print("generated Message-ID: %s\n", buf);
g_free(addr);
}
-static void compose_add_entry_field(GtkWidget *table, GtkWidget **hbox,
- GtkWidget **entry, gint *count,
- const gchar *label_str,
- gboolean is_addr_entry)
-{
- GtkWidget *label;
-
- if (GTK_TABLE(table)->nrows < (*count) + 1)
- gtk_table_resize(GTK_TABLE(table), (*count) + 1, 2);
-
- *hbox = gtk_hbox_new(FALSE, 0);
- label = gtk_label_new
- (prefs_common.trans_hdr ? gettext(label_str) : label_str);
- gtk_box_pack_end(GTK_BOX(*hbox), label, FALSE, FALSE, 0);
- gtk_table_attach(GTK_TABLE(table), *hbox, 0, 1, *count, (*count) + 1,
- GTK_FILL, 0, 2, 0);
- *entry = gtk_entry_new_with_max_length(MAX_ENTRY_LENGTH);
- gtk_table_attach
- (GTK_TABLE(table), *entry, 1, 2, *count, (*count) + 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0);
-#if 0 /* NEW COMPOSE GUI */
- if (GTK_TABLE(table)->nrows > (*count) + 1)
- gtk_table_set_row_spacing(GTK_TABLE(table), *count, 4);
-#endif
-
- if (is_addr_entry)
- address_completion_register_entry(GTK_ENTRY(*entry));
-
- (*count)++;
-}
-
static void compose_create_header_entry(Compose *compose)
{
gchar *headers[] = {"To:", "Cc:", "Bcc:", "Newsgroups:", "Reply-To:", "Followup-To:", NULL};
GtkWidget *scrolledwin;
GtkWidget *text;
- GtkWidget *table;
-
UndoMain *undostruct;
gchar *titles[N_ATTACH_COLS];
GtkWidget *tmpl_menu;
gint n_entries;
-#if USE_PSPELL
- GtkPspell * gtkpspell = NULL;
+#if USE_ASPELL
+ GtkAspell * gtkaspell = NULL;
#endif
static GdkGeometry geometry;
g_return_val_if_fail(account != NULL, NULL);
- debug_print(_("Creating compose window...\n"));
+ debug_print("Creating compose window...\n");
compose = g_new0(Compose, 1);
titles[COL_MIMETYPE] = _("MIME type");
GTK_SIGNAL_FUNC(compose_grab_focus_cb), compose);
gtk_signal_connect(GTK_OBJECT(text), "activate",
GTK_SIGNAL_FUNC(text_activated), compose);
+ gtk_signal_connect(GTK_OBJECT(text), "insert_text",
+ GTK_SIGNAL_FUNC(text_inserted), compose);
gtk_signal_connect_after(GTK_OBJECT(text), "button_press_event",
GTK_SIGNAL_FUNC(compose_button_press_cb),
edit_vbox);
new_style = gtk_style_copy(style);
if (prefs_common.textfont) {
- CharSet charset;
-
- charset = conv_get_current_charset();
if (MB_CUR_MAX == 1) {
gchar *fontstr, *p;
compose->modified = FALSE;
compose->return_receipt = FALSE;
+ compose->paste_as_quotation = FALSE;
compose->to_list = NULL;
compose->newsgroup_list = NULL;
compose->exteditor_readdes = -1;
compose->exteditor_tag = -1;
- compose->bounce_filename = NULL;
+ compose->redirect_filename = NULL;
compose->undostruct = undostruct;
-#if USE_PSPELL
+#if USE_ASPELL
menu_set_sensitive(ifactory, "/Spelling", FALSE);
- if (prefs_common.enable_pspell) {
- gtkpspell = gtkpspell_new((const gchar*)prefs_common.dictionary,
+ if (prefs_common.enable_aspell) {
+ gtkaspell = gtkaspell_new((const gchar*)prefs_common.dictionary,
conv_get_current_charset_str(),
prefs_common.misspelled_col,
prefs_common.check_while_typing,
prefs_common.use_alternate,
GTK_STEXT(text));
- if (!gtkpspell) {
- alertpanel_error(_("Spell checker could not be started.\n%s"), gtkpspellcheckers->error_message);
- gtkpspell_checkers_reset_error();
+ if (!gtkaspell) {
+ alertpanel_error(_("Spell checker could not be started.\n%s"), gtkaspellcheckers->error_message);
+ gtkaspell_checkers_reset_error();
} else {
GtkWidget *menuitem;
- if (!gtkpspell_set_sug_mode(gtkpspell, prefs_common.pspell_sugmode)) {
- debug_print(_("Pspell: could not set suggestion mode %s"),
- gtkpspellcheckers->error_message);
- gtkpspell_checkers_reset_error();
+ if (!gtkaspell_set_sug_mode(gtkaspell, prefs_common.aspell_sugmode)) {
+ debug_print("Aspell: could not set suggestion mode %s\n",
+ gtkaspellcheckers->error_message);
+ gtkaspell_checkers_reset_error();
}
menuitem = gtk_item_factory_get_item(ifactory, "/Spelling/Spelling Configuration");
- gtkpspell_populate_submenu(gtkpspell, menuitem);
+ gtkaspell_populate_submenu(gtkaspell, menuitem);
menu_set_sensitive(ifactory, "/Spelling", TRUE);
}
}
compose->use_followupto = FALSE;
#endif
-#if USE_PSPELL
- compose->gtkpspell = gtkpspell;
+#if USE_ASPELL
+ compose->gtkaspell = gtkaspell;
#endif
#if 0 /* NEW COMPOSE GUI */
static void compose_update_priority_menu_item(Compose * compose)
{
GtkItemFactory *ifactory;
- GtkWidget *menuitem;
+ GtkWidget *menuitem = NULL;
ifactory = gtk_item_factory_from_widget(compose->menubar);
gtk_stext_clear(GTK_STEXT(compose->text));
if (compose->replyinfo == NULL) {
- MsgInfo dummyinfo;
-
- memset(&dummyinfo, 0, sizeof(MsgInfo));
- parsed_str = compose_quote_fmt(compose, &dummyinfo,
- tmpl->value, NULL, NULL);
+ parsed_str = compose_quote_fmt(compose, NULL, tmpl->value,
+ NULL, NULL);
} else {
if (prefs_common.quotemark && *prefs_common.quotemark)
qmark = prefs_common.quotemark;
g_free(compose->msgid);
g_free(compose->boundary);
- if (compose->bounce_filename)
- g_free(compose->bounce_filename);
+ if (compose->redirect_filename)
+ g_free(compose->redirect_filename);
g_free(compose->exteditor_file);
if (addressbook_get_target_compose() == compose)
addressbook_set_target_compose(NULL);
-#if USE_PSPELL
- if (compose->gtkpspell) {
- gtkpspell_delete(compose->gtkpspell);
+#if USE_ASPELL
+ if (compose->gtkaspell) {
+ gtkaspell_delete(compose->gtkaspell);
}
#endif
static void compose_exec_ext_editor(Compose *compose)
{
- gchar tmp[64];
+ gchar *tmp;
pid_t pid;
gint pipe_fds[2];
- g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg.%08x",
- g_get_tmp_dir(), G_DIR_SEPARATOR, (gint)compose);
+ tmp = g_strdup_printf("%s%ctmpmsg.%08x", get_tmp_dir(),
+ G_DIR_SEPARATOR, (gint)compose);
if (pipe(pipe_fds) < 0) {
perror("pipe");
+ g_free(tmp);
return;
}
if ((pid = fork()) < 0) {
perror("fork");
+ g_free(tmp);
return;
}
close(pipe_fds[1]);
_exit(0);
}
+
+ g_free(tmp);
}
static gint compose_exec_ext_editor_real(const gchar *file)
Compose *compose = (Compose *)data;
gint i = 0;
- debug_print(_("Compose: input from monitoring process\n"));
+ debug_print("Compose: input from monitoring process\n");
gdk_input_remove(compose->exteditor_tag);
FolderItem *draft;
gchar *tmp;
gint msgnum;
- MsgFlags flag = {0, 0};
static gboolean lock = FALSE;
-
+ MsgInfo *newmsginfo;
+
if (lock) return;
draft = account_get_special_folder(compose->account, F_DRAFT);
lock = TRUE;
- tmp = g_strdup_printf("%s%cdraft.%d", g_get_tmp_dir(),
+ tmp = g_strdup_printf("%s%cdraft.%08x", get_tmp_dir(),
G_DIR_SEPARATOR, (gint)compose);
if (compose_write_to_file(compose, tmp, TRUE) < 0) {
return;
}
- folder_item_scan(draft);
if ((msgnum = folder_item_add_msg(draft, tmp, TRUE)) < 0) {
unlink(tmp);
g_free(tmp);
TRUE);
}
- procmsg_add_flags(draft, msgnum, flag);
- folder_item_scan(draft);
+ newmsginfo = folder_item_fetch_msginfo(draft, msgnum);
+ procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
folderview_update_item(draft, TRUE);
-
+ procmsg_msginfo_free(newmsginfo);
+
lock = FALSE;
/* 0: quit editing 1: keep editing */
g_free(path);
procmsg_msginfo_free(compose->targetinfo);
- compose->targetinfo = g_new0(MsgInfo, 1);
+ compose->targetinfo = procmsg_msginfo_new();
compose->targetinfo->msgnum = msgnum;
compose->targetinfo->size = s.st_size;
compose->targetinfo->mtime = s.st_mtime;
Compose *compose = (Compose *)data;
GList *file_list;
- if (compose->bounce_filename != NULL)
+ if (compose->redirect_filename != NULL)
return;
file_list = filesel_select_multiple_files(_("Select file"), NULL);
{
Compose *compose = (Compose *)data;
AlertValue val;
-
+
if (compose->exteditor_tag != -1) {
if (!compose_ext_editor_kill(compose))
return;
switch (val) {
case G_ALERTDEFAULT:
+ if (prefs_common.autosave)
+ compose_remove_draft(compose);
break;
case G_ALERTALTERNATE:
compose_draft_cb(data, 0, NULL);
return;
}
}
+
gtk_widget_destroy(compose->window);
}
(GTK_EDITABLE(compose->focused_editable));
}
+static void compose_paste_as_quote_cb(Compose *compose)
+{
+ if (compose->focused_editable &&
+ GTK_WIDGET_HAS_FOCUS(compose->focused_editable)) {
+ compose->paste_as_quotation = TRUE;
+ gtk_editable_paste_clipboard
+ (GTK_EDITABLE(compose->focused_editable));
+ compose->paste_as_quotation = FALSE;
+ }
+}
+
static void compose_allsel_cb(Compose *compose)
{
if (compose->focused_editable &&
(GTK_EDITABLE(compose->focused_editable), 0, -1);
}
-static void compose_move_beginning_of_line_cb(Compose *compose)
+static void compose_gtk_stext_action_cb(Compose *compose,
+ ComposeCallGtkSTextAction action)
{
- if (compose->focused_editable &&
- GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
- gtk_stext_move_beginning_of_line(GTK_STEXT(compose->focused_editable));
-}
+ GtkSText *text = GTK_STEXT(compose->text);
+ static struct {
+ void (*do_action) (GtkSText *text);
+ } action_table[] = {
+ {gtk_stext_move_beginning_of_line},
+ {gtk_stext_move_forward_character},
+ {gtk_stext_move_backward_character},
+ {gtk_stext_move_forward_word},
+ {gtk_stext_move_backward_word},
+ {gtk_stext_move_end_of_line},
+ {gtk_stext_move_next_line},
+ {gtk_stext_move_previous_line},
+ {gtk_stext_delete_forward_character},
+ {gtk_stext_delete_backward_character},
+ {gtk_stext_delete_forward_word},
+ {gtk_stext_delete_backward_word},
+ {gtk_stext_delete_line},
+ {gtk_stext_delete_line}, /* gtk_stext_delete_line_n */
+ {gtk_stext_delete_to_line_end}
+ };
-static void compose_gtk_stext_action_cb(Compose *compose, ComposeCallGtkSTextAction action)
-{
- if (!(compose->focused_editable && GTK_WIDGET_HAS_FOCUS(compose->focused_editable))) return;
-
- switch (action) {
- case COMPOSE_CALL_GTK_STEXT_MOVE_BEGINNING_OF_LINE:
- gtk_stext_move_beginning_of_line(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_MOVE_FORWARD_CHARACTER:
- gtk_stext_move_forward_character(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_MOVE_BACKWARD_CHARACTER:
- gtk_stext_move_backward_character(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_MOVE_FORWARD_WORD:
- gtk_stext_move_forward_word(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_MOVE_BACKWARD_WORD:
- gtk_stext_move_backward_word(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_MOVE_END_OF_LINE:
- gtk_stext_move_end_of_line(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_MOVE_NEXT_LINE:
- gtk_stext_move_next_line(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_MOVE_PREVIOUS_LINE:
- gtk_stext_move_previous_line(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_DELETE_FORWARD_CHARACTER:
- gtk_stext_delete_forward_character(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_DELETE_BACKWARD_CHARACTER:
- gtk_stext_delete_backward_character(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_DELETE_FORWARD_WORD:
- gtk_stext_delete_forward_word(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_DELETE_BACKWARD_WORD:
- gtk_stext_delete_backward_word(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_DELETE_LINE:
- gtk_stext_delete_line(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_DELETE_LINE_N:
- gtk_stext_delete_line(GTK_STEXT(compose->focused_editable));
- gtk_stext_delete_forward_character(GTK_STEXT(compose->focused_editable));
- break;
- case COMPOSE_CALL_GTK_STEXT_DELETE_TO_LINE_END:
- gtk_stext_delete_to_line_end(GTK_STEXT(compose->focused_editable));
- break;
- default:
- break;
- }
+ if (!GTK_WIDGET_HAS_FOCUS(text)) return;
+
+ if (action >= COMPOSE_CALL_GTK_STEXT_MOVE_BEGINNING_OF_LINE &&
+ action <= COMPOSE_CALL_GTK_STEXT_DELETE_TO_LINE_END)
+ action_table[action].do_action(text);
}
static void compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
compose_send_control_enter(compose);
}
+#define EDITABLE_LENGTH(x) \
+ strlen(gtk_editable_get_chars(x,0,-1))
+
+static void text_inserted(GtkWidget *widget, const gchar *text,
+ gint length, gint *position, Compose *compose)
+{
+ GtkEditable *editable = GTK_EDITABLE(widget);
+
+ gtk_signal_handler_block_by_func(GTK_OBJECT(widget),
+ GTK_SIGNAL_FUNC(text_inserted),
+ compose);
+ if (compose->paste_as_quotation) {
+ gchar *new_text;
+ gchar *qmark;
+ gint pos;
+
+ new_text = g_strndup(text, length);
+ if (prefs_common.quotemark && *prefs_common.quotemark)
+ qmark = prefs_common.quotemark;
+ else
+ qmark = "> ";
+ gtk_stext_set_point(GTK_STEXT(widget), *position);
+ compose_quote_fmt(compose, NULL, "%Q", qmark, new_text);
+ pos = gtk_stext_get_point(GTK_STEXT(widget));
+ gtk_editable_set_position(editable, pos);
+ *position = pos;
+ g_free(new_text);
+ } else
+ gtk_editable_insert_text(editable, text, length, position);
+
+ if (prefs_common.autowrap)
+ compose_wrap_line_all_full(compose, TRUE);
+
+ gtk_signal_handler_unblock_by_func(GTK_OBJECT(widget),
+ GTK_SIGNAL_FUNC(text_inserted),
+ compose);
+ gtk_signal_emit_stop_by_name(GTK_OBJECT(editable), "insert_text");
+
+
+ if (prefs_common.autosave &&
+ EDITABLE_LENGTH(editable) % prefs_common.autosave_length == 0)
+ compose_draft_cb((gpointer)compose, 1, NULL);
+}
+
static gboolean compose_send_control_enter(Compose *compose)
{
GdkEvent *ev;
return FALSE;
}
-#if USE_PSPELL
+#if USE_ASPELL
static void compose_check_all(Compose *compose)
{
- if (compose->gtkpspell)
- gtkpspell_check_all(compose->gtkpspell);
+ if (compose->gtkaspell)
+ gtkaspell_check_all(compose->gtkaspell);
}
static void compose_highlight_all(Compose *compose)
{
- if (compose->gtkpspell)
- gtkpspell_highlight_all(compose->gtkpspell);
+ if (compose->gtkaspell)
+ gtkaspell_highlight_all(compose->gtkaspell);
}
static void compose_check_backwards(Compose *compose)
{
- if (compose->gtkpspell)
- gtkpspell_check_backwards(compose->gtkpspell);
+ if (compose->gtkaspell)
+ gtkaspell_check_backwards(compose->gtkaspell);
else {
GtkItemFactory *ifactory;
ifactory = gtk_item_factory_from_widget(compose->popupmenu);
static void compose_check_forwards_go(Compose *compose)
{
- if (compose->gtkpspell)
- gtkpspell_check_forwards_go(compose->gtkpspell);
+ if (compose->gtkaspell)
+ gtkaspell_check_forwards_go(compose->gtkaspell);
else {
GtkItemFactory *ifactory;
ifactory = gtk_item_factory_from_widget(compose->popupmenu);