"<alt>X", compose_ext_editor_cb, 0, NULL},
{N_("/_Message"), NULL, NULL, 0, "<Branch>"},
- {N_("/_Message/_Send"), "<shift><control>S",
+ {N_("/_Message/_Send"), "<control>Return",
compose_send_cb, 0, NULL},
{N_("/_Message/Send _later"), "<shift><alt>S",
compose_send_later_cb, 0, NULL},
{
Compose *compose;
+ if (item && item->prefs && item->prefs->enable_default_account)
+ account = account_find_from_id(item->prefs->default_account);
+
if (!account) account = cur_account;
g_return_val_if_fail(account != NULL, NULL);
if (account->protocol != A_NNTP) {
if (to) {
compose_entry_append(compose, to, COMPOSE_TO);
- gtk_widget_grab_focus(compose->subject_entry);
- } else {
- if(item && item->prefs->enable_default_to) {
- compose_entry_append(compose, item->prefs->default_to, COMPOSE_TO);
- } else {
- gtk_widget_grab_focus(compose->header_last->entry);
- }
+ } else if(item && item->prefs->enable_default_to) {
+ compose_entry_append(compose, item->prefs->default_to, COMPOSE_TO);
}
if (item && item->ret_rcpt) {
GtkItemFactory *ifactory;
} else {
if (to) {
compose_entry_append(compose, to, COMPOSE_NEWSGROUPS);
- gtk_widget_grab_focus(compose->subject_entry);
- } else
- gtk_widget_grab_focus(compose->header_last->entry);
+ }
}
+ gtk_widget_grab_focus(compose->subject_entry);
if (prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
g_return_if_fail(msginfo != NULL);
g_return_if_fail(msginfo->folder != NULL);
- account = msginfo->folder->folder->account;
- if (!account && msginfo->to && prefs_common.reply_account_autosel) {
- gchar *to;
- Xstrdup_a(to, msginfo->to, return);
- extract_address(to);
- account = account_find_from_address(to);
- }
- if(!account&& prefs_common.reply_account_autosel) {
- gchar cc[BUFFSIZE];
- if(!get_header_from_msginfo(msginfo,cc,sizeof(cc),"CC:")){ /* Found a CC header */
- extract_address(cc);
- account = account_find_from_address(cc);
- }
+ account = NULL;
+ /* select the account set in folderitem's property (if enabled) */
+ if (msginfo->folder->prefs && msginfo->folder->prefs->enable_default_account)
+ account = account_find_from_id(msginfo->folder->prefs->default_account);
+
+ /* select the account for the whole folder (IMAP / NNTP) */
+ if (!account)
+ account = msginfo->folder->folder->account;
+
+ /* select account by to: and cc: header if enabled */
+ if (prefs_common.reply_account_autosel) {
+ if (!account && msginfo->to) {
+ gchar *to;
+ Xstrdup_a(to, msginfo->to, return);
+ extract_address(to);
+ account = account_find_from_address(to);
+ }
+ if (!account) {
+ gchar cc[BUFFSIZE];
+ if(!get_header_from_msginfo(msginfo, cc, sizeof(cc), "CC:")) { /* Found a CC header */
+ extract_address(cc);
+ account = account_find_from_address(cc);
+ }
+ }
}
+ /* select current account */
if (!account) account = cur_account;
g_return_if_fail(account != NULL);
return;
} else
reply_account = account;
+
MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_FORWARDED);
MSG_SET_PERM_FLAGS(msginfo->flags, MSG_REPLIED);
gtk_editable_set_position(GTK_EDITABLE(text), 0);
gtk_stext_set_point(text, 0);
+ if (quote && prefs_common.linewrap_quote) {
+ compose_wrap_line_all(compose);
+ }
+
gtk_stext_thaw(text);
gtk_widget_grab_focus(compose->text);
else
gtk_widget_grab_focus(compose->newsgroups_entry);
#endif
+ gtk_widget_grab_focus(compose->header_last->entry);
if (prefs_common.auto_exteditor)
compose_exec_ext_editor(compose);
static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
{
- static HeaderEntry hentry[] = {{"Reply-To:", NULL, TRUE},
- {"Cc:", NULL, FALSE},
- {"References:", NULL, FALSE},
- {"Bcc:", NULL, FALSE},
- {"Newsgroups:", NULL, FALSE},
- {"Followup-To:", NULL, FALSE},
- {NULL, NULL, FALSE}};
+ static HeaderEntry hentry[] = {{"Reply-To:", NULL, TRUE},
+ {"Cc:", NULL, FALSE},
+ {"References:", NULL, FALSE},
+ {"Bcc:", NULL, FALSE},
+ {"Newsgroups:", NULL, FALSE},
+ {"Followup-To:", NULL, FALSE},
+ {"X-Mailing-List:", NULL, FALSE},
+ {"X-BeenThere:", NULL, FALSE},
+ {NULL, NULL, FALSE}};
enum
{
- H_REPLY_TO = 0,
- H_CC = 1,
- H_REFERENCES = 2,
- H_BCC = 3,
- H_NEWSGROUPS = 4,
- H_FOLLOWUP_TO = 5
+ H_REPLY_TO = 0,
+ H_CC = 1,
+ H_REFERENCES = 2,
+ H_BCC = 3,
+ H_NEWSGROUPS = 4,
+ H_FOLLOWUP_TO = 5,
+ H_X_MAILING_LIST = 6,
+ H_X_BEENTHERE = 7
};
FILE *fp;
compose->cc = hentry[H_CC].body;
hentry[H_CC].body = NULL;
}
+ if (hentry[H_X_MAILING_LIST].body != NULL) {
+ /* this is good enough to parse debian-devel */
+ char * buf = g_malloc(strlen(hentry[H_X_MAILING_LIST].body) + 1);
+ g_return_val_if_fail(buf != NULL, -1 );
+ if (1 == sscanf(hentry[H_X_MAILING_LIST].body, "<%[^>]>", buf))
+ compose->mailinglist = g_strdup(buf);
+ g_free(buf);
+ g_free(hentry[H_X_MAILING_LIST].body);
+ hentry[H_X_MAILING_LIST].body = NULL ;
+ }
+ if (hentry[H_X_BEENTHERE].body != NULL) {
+ /* this is good enough to parse the sylpheed-claws lists */
+ char * buf = g_malloc(strlen(hentry[H_X_BEENTHERE].body) + 1);
+ g_return_val_if_fail(buf != NULL, -1 );
+ if (1 == sscanf(hentry[H_X_BEENTHERE].body, "%[^>]", buf))
+ compose->mailinglist = g_strdup(buf);
+ g_free(buf);
+ g_free(hentry[H_X_BEENTHERE].body);
+ hentry[H_X_BEENTHERE].body = NULL ;
+ }
if (hentry[H_REFERENCES].body != NULL) {
if (compose->mode == COMPOSE_REEDIT)
compose->references = hentry[H_REFERENCES].body;
if ((compose->account->protocol != A_NNTP) || followup_and_reply_to)
compose_entry_append(compose,
- ((compose->replyto && !ignore_replyto)
+ ((compose->mailinglist && !ignore_replyto)
+ ? compose->mailinglist
+ : (compose->replyto && !ignore_replyto)
? compose->replyto
: msginfo->from ? msginfo->from : ""),
COMPOSE_TO);
{
GtkSText *text = GTK_STEXT(compose->text);
gchar buf[BUFFSIZE];
+ gint len;
FILE *fp;
g_return_if_fail(file != NULL);
gtk_stext_freeze(text);
- while (fgets(buf, sizeof(buf), fp) != NULL)
- gtk_stext_insert(text, NULL, NULL, NULL, buf, -1);
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ /* Strip <CR> if DOS/Windoze file, replace <CR> with <LF> if MAC file */
+ len = strlen(buf);
+ if (len > 1 && buf[len - 2] == '\r' && buf[len - 1] == '\n') {
+ buf[len - 2] = '\n';
+ buf[len - 1] = '\0';
+ } else {
+ while (--len > 0)
+ if (buf[len] == '\r')
+ buf[len] = '\n';
+ }
+
+ gtk_stext_insert(text, NULL, NULL, NULL, buf, -1);
+ }
gtk_stext_thaw(text);
{
GtkSText *text = GTK_STEXT(compose->text);
gint ch_len, last_ch_len;
- gchar cbuf[MB_CUR_MAX], last_ch;
+ gchar cbuf[MB_LEN_MAX], last_ch;
guint text_len;
guint line_end;
guint quoted;
#undef GET_STEXT
}
-/* return str length if text at start_pos matches str else return zero */
-static gint is_gtkstext_string(GtkSText *text, guint start_pos,
- guint text_len, gchar *str) {
- gint is_str, i, str_len;
- gchar str_ch;
+/* return indent length */
+static guint get_indent_length(GtkSText *text, guint start_pos,
+ guint text_len) {
+ gint indent_len = 0;
+ gint i, ch_len;
+ gchar cbuf[MB_CUR_MAX];
- is_str = 0;
- if (str) {
- str_len = strlen(str);
- is_str = 1;
- for (i = 0; (i < str_len) && (start_pos + i < text_len); i++) {
- str_ch = GTK_STEXT_INDEX(text, start_pos + i);
- if (*(str + i) != str_ch) {
- break;
- }
+ for (i = start_pos; i < text_len; i++) {
+ if (text->use_wchar)
+ ch_len = wctomb
+ (cbuf, (wchar_t)GTK_STEXT_INDEX(text, i));
+ else {
+ cbuf[0] = GTK_STEXT_INDEX(text, i);
+ ch_len = 1;
}
- if (i == 0 || i < str_len)
- is_str = 0;
+ if (ch_len > 1)
+ break;
+ /* allow space, tab, > or | */
+ if (cbuf[0] != ' ' && cbuf[0] != '\t' &&
+ cbuf[0] != '>' && cbuf[0] != '|')
+ break;
+ indent_len++;
}
- return is_str ? str_len : 0;
+ return indent_len;
+}
+
+/* insert quotation string when line was wrapped, we know these
+ are single byte characters */
+static guint insert_quote(GtkSText *text, guint quote_len, guint indent_len,
+ guint prev_line_pos, guint text_len,
+ gchar *quote_fmt) {
+ guint i, ins_len;
+ gchar ch;
+
+ if (indent_len) {
+ for (i = 0; i < indent_len; i++) {
+ ch = GTK_STEXT_INDEX(text, prev_line_pos + i);
+ gtk_stext_insert(text, NULL, NULL, NULL, &ch, 1);
+ }
+ ins_len = indent_len;
+ }
+ else {
+ gtk_stext_insert(text, NULL, NULL, NULL, quote_fmt, quote_len);
+ ins_len = quote_len;
+ }
+
+ return ins_len;
+}
+
+/* compare gtkstext string at pos1 with string at pos2 for equality
+ (max. len chars) - we treat characters as single byte */
+static gint gtkstext_strncmp(GtkSText *text, guint pos1, guint pos2, guint len,
+ guint tlen)
+{
+ guint i = 0;
+ gchar ch1, ch2;
+
+ for (; (i < len) && (pos1 + i < tlen) && (pos2 + i < tlen); i++) {
+ ch1 = GTK_STEXT_INDEX(text, pos1 + i);
+ ch2 = GTK_STEXT_INDEX(text, pos2 + i);
+ if (ch1 != ch2)
+ break;
+ }
+
+ return i;
}
static void compose_wrap_line_all(Compose *compose)
{
GtkSText *text = GTK_STEXT(compose->text);
guint text_len;
- guint line_pos = 0, cur_pos = 0;
+ guint line_pos = 0, cur_pos = 0, prev_line_pos = 0;
gint line_len = 0, cur_len = 0;
gint ch_len;
- gint is_new_line = 1;
- guint quote_len = 0;
+ gint is_new_line = 1, do_delete = 0;
+ guint quote_len = 0, indent_len = 0;
guint linewrap_quote = prefs_common.linewrap_quote;
+ guint linewrap_len = prefs_common.linewrap_len;
gchar *quote_fmt = prefs_common.quotemark;
- gchar cbuf[MB_CUR_MAX];
+ gchar cbuf[MB_LEN_MAX];
gtk_stext_freeze(text);
for (; cur_pos < text_len; cur_pos++) {
if (linewrap_quote && is_new_line) {
- quote_len = is_gtkstext_string(text, cur_pos,
- text_len, quote_fmt);
+ quote_len = gtkstext_str_strcmp(text, cur_pos,
+ text_len, quote_fmt);
is_new_line = 0;
+ if (quote_len) {
+ indent_len = get_indent_length(text, cur_pos,
+ text_len);
+ }
+ else
+ indent_len = 0;
+ prev_line_pos = cur_pos;
}
if (text->use_wchar)
ch_len = wctomb
ch_len = 1;
}
+ /* fix line length for tabs */
+ if (ch_len == 1 && *cbuf == '\t') {
+ guint tab_width = text->default_tab_width;
+ guint tab_offset = line_len % tab_width;
+
+ if (tab_offset) {
+ line_len += tab_width - tab_offset - 1;
+ cur_len = line_len;
+ }
+ }
+
if (ch_len == 1 && *cbuf == '\n') {
+ gint clen;
+ guint ilen;
+ gchar cb[MB_CUR_MAX];
+
+ /* if it's just quotation + newline skip it */
+ if (indent_len && (cur_pos + 1 < text_len)) {
+ ilen = gtkstext_strncmp(text,
+ cur_pos + 1,
+ prev_line_pos,
+ indent_len,
+ text_len);
+ if (cur_pos + ilen < text_len) {
+ if (text->use_wchar)
+ clen = wctomb
+ (cb, (wchar_t)GTK_STEXT_INDEX(text, cur_pos + ilen + 1));
+ else {
+ cb[0] = GTK_STEXT_INDEX(text,
+ cur_pos + ilen + 1);
+ clen = 1;
+ }
+ if ((clen == 1) && (cb[0] == '\n'))
+ do_delete = 0;
+ }
+ }
+
+ /* should we delete to perform smart wrapping */
+ if (quote_len && line_len < linewrap_len && do_delete) {
+ /* get rid of newline */
+ gtk_stext_set_point(text, cur_pos);
+ gtk_stext_forward_delete(text, 1);
+
+ /* if text starts with quote_fmt or with
+ indent string, delete them */
+ if (indent_len) {
+ ilen = gtkstext_strncmp(text, cur_pos,
+ prev_line_pos,
+ indent_len,
+ text_len);
+ if (ilen) {
+ gtk_stext_forward_delete(text,
+ ilen);
+ text_len -= ilen;
+ }
+ }
+ else if (quote_len) {
+ if (gtkstext_str_strcmp(text, cur_pos,
+ text_len,
+ quote_fmt)) {
+ gtk_stext_forward_delete(text,
+ quote_len);
+ text_len-=quote_len;
+ }
+ }
+
+ if (text->use_wchar)
+ clen = wctomb
+ (cb, (wchar_t)GTK_STEXT_INDEX(text, cur_pos));
+ else {
+ cb[0] = GTK_STEXT_INDEX(text, cur_pos);
+ clen = 1;
+ }
+ /* insert space if it's alphanumeric */
+ if ((cur_pos != line_pos) &&
+ ((clen > 1) || isalnum(cb[0]))) {
+ gtk_stext_insert(text, NULL, NULL,
+ NULL, " ", 1);
+ gtk_stext_compact_buffer(text);
+ text_len++;
+ }
+
+ /* and start over with current line */
+ cur_pos = prev_line_pos - 1;
+ line_pos = cur_pos;
+ line_len = cur_len = 0;
+ quote_len = 0;
+ do_delete = 0;
+ is_new_line = 1;
+ continue;
+ }
+
line_pos = cur_pos + 1;
line_len = cur_len = 0;
quote_len = 0;
+ do_delete = 0;
is_new_line = 1;
continue;
}
line_len = cur_len + ch_len;
}
- if (cur_len + ch_len > prefs_common.linewrap_len &&
- line_len > 0) {
+ if (cur_len + ch_len > linewrap_len) {
gint tlen;
+ if (line_len == 0) {
+ /* don't wrap URLs */
+ if (is_url_string(text, line_pos, text_len))
+ continue;
+ line_len = cur_pos - line_pos;
+ line_pos = cur_pos;
+ }
+
if (text->use_wchar)
tlen = wctomb(cbuf, (wchar_t)GTK_STEXT_INDEX(text, line_pos - 1));
else {
gtk_stext_set_point(text, line_pos);
gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
+ gtk_stext_compact_buffer(text);
text_len++;
cur_pos++;
line_pos++;
line_len = 0;
if (linewrap_quote && quote_len) {
/* only if line is not already quoted */
- if (!is_gtkstext_string(text, line_pos,
- text_len, quote_fmt)) {
- gtk_stext_insert(text, NULL, NULL, NULL,
- quote_fmt, quote_len);
+ if (!gtkstext_str_strcmp(text, line_pos,
+ text_len, quote_fmt)) {
+ guint i_len;
+
+ i_len = insert_quote(text, quote_len,
+ indent_len,
+ prev_line_pos,
+ text_len,
+ quote_fmt);
+
gtk_stext_compact_buffer(text);
- text_len += quote_len;
- cur_pos += quote_len;
- cur_len += quote_len;
- line_len = quote_len;
+ text_len += i_len;
+ /* for loop above will increase it */
+ cur_pos = line_pos - 1;
+ cur_len = 0;
+ line_len = 0;
+ /* start over with current line */
+ is_new_line = 1;
+ do_delete = 1;
}
}
continue;
gchar *header;
gchar *entry;
header = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(((compose_headerentry *)list->data)->combo)->entry));
- entry = gtk_entry_get_text(GTK_ENTRY(((compose_headerentry *)list->data)->entry));
- if(strlen(entry)) {
+ entry = gtk_editable_get_chars(GTK_EDITABLE(((compose_headerentry *)list->data)->entry), 0, -1);
+ g_strstrip(entry);
+ if(entry[0] != '\0') {
for(strptr = recipient_headers; *strptr != NULL; strptr++) {
if(!strcmp(header, (prefs_common.trans_hdr ? gettext(*strptr) : *strptr))) {
recipient_found = TRUE;
}
}
}
+ g_free(entry);
}
return recipient_found;
}
len = strlen(chars);
if (is_ascii_str(chars)) {
buf = g_strdup(chars);
- out_codeset = "US-ASCII";
+ out_codeset = CS_US_ASCII;
encoding = ENC_7BIT;
} else {
const gchar *src_codeset;
out_codeset = conv_get_outgoing_charset_str();
- if (!strcasecmp(out_codeset, "US-ASCII"))
- out_codeset = "ISO-8859-1";
+ if (!strcasecmp(out_codeset, CS_US_ASCII))
+ out_codeset = CS_ISO_8859_1;
encoding = procmime_get_encoding_for_charset(out_codeset);
+
src_codeset = conv_get_current_charset_str();
- if (!strcasecmp(src_codeset, "US-ASCII"))
- src_codeset = "ISO-8859-1";
+ /* 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))
+ 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));
str = gtk_entry_get_text(GTK_ENTRY(headerentry->entry));
Xstrdup_a(str, str, return -1);
g_strstrip(str);
- if(list_append_func)
- *dest_list = list_append_func(*dest_list, str);
- compose_convert_header
- (buf, sizeof(buf), str,
- strlen(header) + 2);
- if(first_address) {
- fprintf(fp, "%s: ", header);
- first_address = FALSE;
- } else {
- fprintf(fp, ", ");
+ if(str[0] != '\0') {
+ if(list_append_func)
+ *dest_list = list_append_func(*dest_list, str);
+ compose_convert_header
+ (buf, sizeof(buf), str,
+ strlen(header) + 2);
+ if(first_address) {
+ fprintf(fp, "%s: ", header);
+ first_address = FALSE;
+ } else {
+ fprintf(fp, ", ");
+ }
+ fprintf(fp, "%s", buf);
}
- fprintf(fp, "%s", buf);
}
}
if(!first_address) {
compose->mode = mode;
compose->replyto = NULL;
+ compose->mailinglist = NULL;
compose->cc = NULL;
compose->bcc = NULL;
compose->followup_to = NULL;
account->auto_replyto);
#endif
}
+ if (account->protocol != A_NNTP) {
+ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry), _("To:"));
+ } else {
+ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry), _("Newsgroups:"));
+ }
+
menuitem = gtk_item_factory_get_item(ifactory, "/Tool/Show ruler");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
prefs_common.show_ruler);
sensitive);
menu_set_sensitive(ifactory, "/File/Insert file", sensitive);
menu_set_sensitive(ifactory, "/File/Insert signature", sensitive);
- menu_set_sensitive(ifactory, "/Edit/Wrap long lines", sensitive);
+ menu_set_sensitive(ifactory, "/Edit/Wrap current paragraph", sensitive);
+ menu_set_sensitive(ifactory, "/Edit/Wrap all long lines", sensitive);
menu_set_sensitive(ifactory, "/Edit/Edit with external editor",
sensitive);