2011-08-30 [colin] 3.7.10cvs8
[claws.git] / src / quote_fmt.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2011 Hiroyuki Yamamoto and the Claws Mail team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  * 
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <glib.h>
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27 #include <gdk/gdkkeysyms.h>
28
29 #include "manage_window.h"
30 #include "description_window.h"
31 #include "gtkutils.h"
32
33 #include "prefs_gtk.h"
34 #include "prefs_common.h"
35 #include "quote_fmt.h"
36 #include "alertpanel.h"
37 #include "prefs_template.h"
38
39
40 /*
41  * Strings describing quote format strings
42  * 
43  * When adding new lines, remember to put 2 strings for each line
44  */
45 static gchar *quote_desc_strings[] = {
46         N_("<span weight=\"bold\">symbols:</span>"),                            NULL,
47         "%date_fmt{<span style=\"oblique\">fmt</span>} (%D{<span style=\"oblique\">fmt</span>})",       N_("customized date format (see 'man strftime')"), /* date expression */
48         "%date (%d)",                           N_("Date"), /* date */
49         "%from (%f)",                           N_("From"), /* from */
50         "%email (%A)",                          N_("email address of sender"), /* email address */
51         "%fullname (%N)",                       N_("full name of sender"), /* full name */
52         "%firstname (%F)",                      N_("first name of sender"), /* first name */
53         "%lastname (%L)",                       N_("last name of sender"), /* last name */
54         "%initials (%I)",                       N_("initials of sender"), /* initial of sender */
55         "%subject (%s)",                        N_("Subject"), /* subject */ 
56         "%to (%t)",                                     N_("To"), /* to */ 
57         "%cc (%c)",                                     N_("Cc"), /* cc */ 
58         "%newsgroups (%n)",                     N_("Newsgroups"), /* newsgroups */ 
59         "%references (%r)",                     N_("References"), /* references */ 
60         "%messageid (%i)",                      N_("Message-ID"), /* message-id */ 
61         "%msg (%M)",                            N_("message body"), /* message */
62         "%quoted_msg (%Q)",                     N_("quoted message body"), /* quoted message */
63         "%msg_no_sig (%m)",                     N_("message body without signature"), /* message with no signature */
64         "%quoted_msg_no_sig (%q)",      N_("quoted message body without signature"), /* quoted message with no signature */
65         "%tags",                                N_("message tags"), /* message tags */
66         "%dict (%T)",                           N_("current dictionary"), /* current dictionary */
67         "%cursor (%X)",                         N_("cursor position"), /* X marks the cursor spot */
68         "%account_fullname (%af)",      N_("account property: your name"), /* full name in compose account */
69         "%account_email (%am)",         N_("account property: your email address"), /* mail address in compose account */
70         "%account_name (%an)",          N_("account property: account name"), /* compose account name itself */
71         "%account_org (%ao)",           N_("account property: organization"), /* organization in compose account */
72         "%account_sig (%as)",           N_("account property: signature"), /* signature set in account prefs */
73         "%account_sigpath (%asp)",      N_("account property: signature path"), /* signature path set in account prefs */
74         "%account_dict (%aT)",          N_("account property: default dictionary"), /* main dict (if enabled) in account */
75         "%addrbook_cc (%ABc)",          N_("address book <span style=\"oblique\">completion</span>: Cc"), /* completion of 'Cc' from address book */
76         "%addrbook_from (%ABf)",        N_("address book <span style=\"oblique\">completion</span>: From"), /* completion of 'From' from address book */
77         "%addrbook_to (%ABt)",          N_("address book <span style=\"oblique\">completion</span>: To"), /* completion of 'To' from address book */
78         "\\%",                          N_("literal %"),
79         "\\\\",                         N_("literal backslash"),
80         "\\?",                          N_("literal question mark"),
81         "\\!",                          N_("literal exclamation mark"),
82         "\\|",                          N_("literal pipe"),
83         "\\{",                          N_("literal opening curly brace"),
84         "\\}",                          N_("literal closing curly brace"),
85         "\\t",                          N_("tab"),
86         "\\n",                          N_("new line"),
87         "",                                     NULL,
88         N_("<span weight=\"bold\">commands:</span>"),           NULL,
89         "?x{<span style=\"oblique\">expr</span>}\n\n",          N_("insert <span style=\"oblique\">expr</span> if x is set, where x is one of\nthe [dfNFLIstcnriT, ad, af, ao, as, asp, aT, ABc, ABf, ABt]\nsymbols (or their long equivalent)"),
90         "!x{<span style=\"oblique\">expr</span>}\n\n",          N_("insert <span style=\"oblique\">expr</span> if x is not set, where x is one of\nthe [dfNFLIstcnriT, ad, af, ao, as, asp, aT, ABc, ABf, ABt]\nsymbols (or their long equivalent)"),
91         "|file{<span style=\"oblique\">sub_expr</span>}\n(|f{<span style=\"oblique\">sub_expr</span>})",                N_("insert file:\n<span style=\"oblique\">sub_expr</span> is evaluated as the path of the file to insert"), /* insert file */
92         "|program{<span style=\"oblique\">sub_expr</span>}\n(|p{<span style=\"oblique\">sub_expr</span>})\n",   N_("insert program output:\n<span style=\"oblique\">sub_expr</span> is evaluated as a command-line to get\nthe output from"), /* insert program output */
93         "|input{<span style=\"oblique\">sub_expr</span>}\n(|i{<span style=\"oblique\">sub_expr</span>})\n",             N_("insert user input:\n<span style=\"oblique\">sub_expr</span> is a variable to be replaced by\nuser-entered text"), /* insert user input */
94         "|attach{<span style=\"oblique\">sub_expr</span>}\n(|a{<span style=\"oblique\">sub_expr</span>})",              N_("attach file:\n<span style=\"oblique\">sub_expr</span> is evaluated as the path of the file to attach"), /* attach file */
95         "",                                     NULL,
96         N_("<span weight=\"bold\">definition of terms:</span>"),        NULL,
97         "<span style=\"oblique\">expr</span>\n",                        N_("text that can contain any of the symbols or\ncommands above"),
98         "<span style=\"oblique\">sub_expr</span>\n",            N_("text that can contain any of the symbols (no\ncommands) above"),
99         "<span style=\"oblique\">completion</span>\n\n\n",      N_("completion from address book only works with the first\naddress of the header, it outputs the full name\nof the contact if that address matches exactly\none contact in the address book"),
100         NULL,NULL
101 };
102
103 static DescriptionWindow quote_desc_win = { 
104         NULL,
105         NULL,
106         2,
107         N_("Description of symbols"),
108         N_("The following symbols and commands can be used:"),
109         quote_desc_strings
110 };
111
112
113 void quote_fmt_quote_description(GtkWidget *widget, GtkWidget *pref_window)
114 {
115         quote_desc_win.parent = pref_window;
116         description_window_create(&quote_desc_win);
117 }
118
119 static void quote_fmt_add_buttons(GtkWindow* parent_window, GtkWidget *parent_box,
120                         gboolean add_info_button, void(*set_defaults_func)(void)) {
121         GtkWidget *hbox_btns;
122         
123         if (!add_info_button && !set_defaults_func)
124                 return;
125         
126         hbox_btns = gtk_hbox_new(FALSE, 0);
127         gtk_box_pack_end (GTK_BOX(parent_box), hbox_btns, FALSE, TRUE, 0);      
128
129         if (add_info_button)
130                 quotefmt_add_info_button(parent_window, hbox_btns);
131         if (set_defaults_func)
132                 quotefmt_add_defaults_button(parent_window, hbox_btns, set_defaults_func);
133
134         gtk_widget_show(GTK_WIDGET(hbox_btns));
135 }
136
137 void quotefmt_create_new_msg_fmt_widgets(GtkWindow *parent_window,
138                                                 GtkWidget *parent_box,
139                                                 GtkWidget **checkbtn_compose_with_format,
140                                                 GtkWidget **override_from_format,
141                                                 GtkWidget **edit_subject_format,
142                                                 GtkWidget **edit_body_format,
143                                                 gboolean add_info_button,
144                                                 void(*set_defaults_func)(void))
145 {
146         GtkWidget *checkbtn_use_format = NULL;
147         GtkWidget *vbox_format;
148         GtkWidget *hbox_format;
149         GtkWidget *hbox2_format;
150         GtkWidget *label_from = NULL;
151         GtkWidget *entry_from = NULL;
152         GtkWidget *label_subject;
153         GtkWidget *entry_subject;
154         GtkWidget *scrolledwin_format;
155         GtkWidget *text_format;
156         GtkSizeGroup *size_group;
157
158         if (add_info_button)
159                 cm_return_if_fail(parent_window != NULL);
160         cm_return_if_fail(parent_box != NULL);
161         if (checkbtn_compose_with_format)
162                 cm_return_if_fail(checkbtn_compose_with_format != NULL);
163
164         cm_return_if_fail(edit_subject_format != NULL);
165         cm_return_if_fail(edit_body_format != NULL);
166
167         size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
168
169         if (checkbtn_compose_with_format)
170                 PACK_CHECK_BUTTON (parent_box, checkbtn_use_format, 
171                                    _("Use template when composing new messages"));
172
173         vbox_format = gtk_vbox_new (FALSE, 4);
174         gtk_widget_show(vbox_format);
175         gtk_container_add(GTK_CONTAINER (parent_box), vbox_format);
176         gtk_container_set_border_width (GTK_CONTAINER (vbox_format), 8);
177
178         if (override_from_format) {
179                 CLAWS_TIP_DECL();
180
181                 hbox2_format = gtk_hbox_new (FALSE, 8);
182                 gtk_widget_show (hbox2_format);
183                 gtk_box_pack_start (GTK_BOX (vbox_format), hbox2_format, FALSE, FALSE, 0);
184
185                 label_from = gtk_label_new (prefs_common_translated_header_name("From"));
186                 gtk_misc_set_alignment(GTK_MISC(label_from), 1, 0.5);
187                 gtk_widget_show (label_from);
188                 gtk_box_pack_start (GTK_BOX (hbox2_format), label_from, FALSE, FALSE, 0);
189                 gtk_size_group_add_widget(size_group, label_from);
190
191                 entry_from = gtk_entry_new ();
192                 gtk_widget_show (entry_from);
193                 gtk_box_pack_start (GTK_BOX (hbox2_format), entry_from, TRUE, TRUE, 0);
194                 gtk_widget_set_size_request (entry_from, 100, -1);
195
196                 CLAWS_SET_TIP(entry_from,
197                                 _("Override From header. This doesn't change the account used to compose the new message."));
198         }
199
200         hbox_format = gtk_hbox_new (FALSE, 8);
201         gtk_widget_show (hbox_format);
202         gtk_box_pack_start (GTK_BOX (vbox_format), hbox_format, FALSE, FALSE, 0);
203
204         label_subject = gtk_label_new (prefs_common_translated_header_name("Subject"));
205         gtk_misc_set_alignment(GTK_MISC(label_subject), 1, 0.5);
206         gtk_widget_show (label_subject);
207         gtk_box_pack_start (GTK_BOX (hbox_format), label_subject, FALSE, FALSE, 0);
208         gtk_size_group_add_widget(size_group, label_subject);
209
210         entry_subject = gtk_entry_new ();
211         gtk_widget_show (entry_subject);
212         gtk_box_pack_start (GTK_BOX (hbox_format), entry_subject, TRUE, TRUE, 0);
213         gtk_widget_set_size_request (entry_subject, 100, -1);
214
215         scrolledwin_format = gtk_scrolled_window_new (NULL, NULL);
216         gtk_widget_show (scrolledwin_format);
217         gtk_box_pack_start (GTK_BOX (vbox_format), scrolledwin_format,
218                             TRUE, TRUE, 0);
219         gtk_scrolled_window_set_policy
220                 (GTK_SCROLLED_WINDOW (scrolledwin_format),
221                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
222         gtk_scrolled_window_set_shadow_type
223                 (GTK_SCROLLED_WINDOW (scrolledwin_format), GTK_SHADOW_IN);
224
225         text_format = gtk_text_view_new ();
226         if (prefs_common.textfont) {
227                 PangoFontDescription *font_desc;
228
229                 font_desc = pango_font_description_from_string
230                                                 (prefs_common.textfont);
231                 if (font_desc) {
232                         gtk_widget_modify_font(text_format, font_desc);
233                         pango_font_description_free(font_desc);
234                 }
235         }
236         gtk_widget_show(text_format);
237         gtk_container_add(GTK_CONTAINER(scrolledwin_format), text_format);
238         gtk_text_view_set_editable (GTK_TEXT_VIEW (text_format), TRUE);
239         gtk_widget_set_size_request(text_format, -1, 100);
240
241         if (checkbtn_compose_with_format) {
242                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, label_subject);
243                 if (override_from_format) {
244                         SET_TOGGLE_SENSITIVITY(checkbtn_use_format, entry_from);
245                         SET_TOGGLE_SENSITIVITY(checkbtn_use_format, label_from);
246                 }
247                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, entry_subject);
248                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, text_format);
249         }
250
251         quote_fmt_add_buttons(parent_window, vbox_format,
252                                 add_info_button, set_defaults_func);
253
254         if (checkbtn_compose_with_format)
255                 *checkbtn_compose_with_format = checkbtn_use_format;
256         if (override_from_format)
257                 *override_from_format = entry_from;
258         *edit_subject_format = entry_subject;
259         *edit_body_format = text_format;
260 }
261
262 void quotefmt_create_reply_fmt_widgets(GtkWindow *parent_window,
263                                                 GtkWidget *parent_box,
264                                                 GtkWidget **checkbtn_reply_with_format,
265                                                 GtkWidget **override_from_format,
266                                                 GtkWidget **edit_reply_quotemark,
267                                                 GtkWidget **edit_reply_format,
268                                                 gboolean add_info_button,
269                                                 void(*set_defaults_func)(void))
270 {
271         GtkWidget *checkbtn_use_format = NULL;
272         GtkWidget *vbox_quote;
273         GtkWidget *hbox1;
274         GtkWidget *hbox2;
275         GtkWidget *hbox3;
276         GtkWidget *label_quotemark;
277         GtkWidget *entry_quotemark;
278         GtkWidget *label_from = NULL;
279         GtkWidget *entry_from = NULL;
280         GtkWidget *scrolledwin_quotefmt;
281         GtkWidget *text_quotefmt;
282         GtkSizeGroup *size_group;
283
284         if (add_info_button)
285                 cm_return_if_fail(parent_window != NULL);
286         cm_return_if_fail(parent_box != NULL);
287         if (checkbtn_reply_with_format)
288                 cm_return_if_fail(checkbtn_reply_with_format != NULL);
289
290         cm_return_if_fail(edit_reply_quotemark != NULL);
291         cm_return_if_fail(edit_reply_format != NULL);
292
293         size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
294
295         if (checkbtn_reply_with_format)
296                 PACK_CHECK_BUTTON (parent_box, checkbtn_use_format,
297                                    _("Use template when replying to messages"));
298
299         vbox_quote = gtk_vbox_new (FALSE, 4);
300         gtk_widget_show(vbox_quote);
301         gtk_container_add(GTK_CONTAINER (parent_box), vbox_quote);
302         gtk_container_set_border_width (GTK_CONTAINER (vbox_quote), 8);
303
304         if (override_from_format) {
305                 CLAWS_TIP_DECL();
306
307                 hbox3 = gtk_hbox_new (FALSE, 8);
308                 gtk_widget_show (hbox3);
309                 gtk_box_pack_start (GTK_BOX (vbox_quote), hbox3, FALSE, FALSE, 0);
310
311                 label_from = gtk_label_new (prefs_common_translated_header_name("From"));
312                 gtk_misc_set_alignment(GTK_MISC(label_from), 1, 0.5);
313                 gtk_widget_show (label_from);
314                 gtk_box_pack_start (GTK_BOX (hbox3), label_from, FALSE, FALSE, 0);
315                 gtk_size_group_add_widget(size_group, label_from);
316
317                 entry_from = gtk_entry_new ();
318                 gtk_widget_show (entry_from);
319                 gtk_box_pack_start (GTK_BOX (hbox3), entry_from, TRUE, TRUE, 0);
320                 gtk_widget_set_size_request (entry_from, 100, -1);
321
322                 CLAWS_SET_TIP(entry_from,
323                                 _("Override From header. This doesn't change the account used to reply."));
324         }
325
326         hbox1 = gtk_hbox_new (FALSE, 32);
327         gtk_widget_show (hbox1);
328         gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, FALSE, FALSE, 0);
329
330         hbox2 = gtk_hbox_new (FALSE, 8);
331         gtk_widget_show (hbox2);
332         gtk_box_pack_start (GTK_BOX (hbox1), hbox2, FALSE, FALSE, 0);
333
334         label_quotemark = gtk_label_new (_("Quotation mark"));
335         gtk_misc_set_alignment(GTK_MISC(label_quotemark), 1, 0.5);
336         gtk_widget_show (label_quotemark);
337         gtk_box_pack_start (GTK_BOX (hbox2), label_quotemark, FALSE, FALSE, 0);
338         gtk_size_group_add_widget(size_group, label_quotemark);
339
340         entry_quotemark = gtk_entry_new ();
341         gtk_widget_show (entry_quotemark);
342         gtk_box_pack_start (GTK_BOX (hbox2), entry_quotemark, FALSE, FALSE, 0);
343         gtk_widget_set_size_request (entry_quotemark, 64, -1);
344
345         scrolledwin_quotefmt = gtk_scrolled_window_new (NULL, NULL);
346         gtk_widget_show (scrolledwin_quotefmt);
347         gtk_box_pack_start (GTK_BOX (vbox_quote), scrolledwin_quotefmt,
348                             TRUE, TRUE, 0);
349         gtk_scrolled_window_set_policy
350                 (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt),
351                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
352         gtk_scrolled_window_set_shadow_type
353                 (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt), GTK_SHADOW_IN);
354
355         text_quotefmt = gtk_text_view_new ();
356         if (prefs_common.textfont) {
357                 PangoFontDescription *font_desc;
358
359                 font_desc = pango_font_description_from_string
360                                                 (prefs_common.textfont);
361                 if (font_desc) {
362                         gtk_widget_modify_font(text_quotefmt, font_desc);
363                         pango_font_description_free(font_desc);
364                 }
365         }
366         gtk_widget_show(text_quotefmt);
367         gtk_container_add(GTK_CONTAINER(scrolledwin_quotefmt), text_quotefmt);
368         gtk_text_view_set_editable (GTK_TEXT_VIEW (text_quotefmt), TRUE);
369         gtk_widget_set_size_request(text_quotefmt, -1, 100);
370
371         if (checkbtn_reply_with_format) {
372                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, label_quotemark);
373                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, entry_quotemark);
374                 if (override_from_format) {
375                         SET_TOGGLE_SENSITIVITY(checkbtn_use_format, entry_from);
376                         SET_TOGGLE_SENSITIVITY(checkbtn_use_format, label_from);
377                 }
378                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, text_quotefmt);
379         }
380
381         quote_fmt_add_buttons(parent_window, vbox_quote,
382                                 add_info_button, set_defaults_func);
383
384         if (checkbtn_reply_with_format)
385                 *checkbtn_reply_with_format = checkbtn_use_format;
386         *edit_reply_quotemark = entry_quotemark;
387         if (override_from_format)
388                 *override_from_format = entry_from;
389         *edit_reply_format = text_quotefmt;
390 }
391
392 void quotefmt_create_forward_fmt_widgets(GtkWindow *parent_window,
393                                                 GtkWidget *parent_box,
394                                                 GtkWidget **checkbtn_forward_with_format,
395                                                 GtkWidget **override_from_format,
396                                                 GtkWidget **edit_fw_quotemark,
397                                                 GtkWidget **edit_fw_format,
398                                                 gboolean add_info_button,
399                                                 void(*set_defaults_func)(void))
400 {
401         GtkWidget *checkbtn_use_format = NULL;
402         GtkWidget *vbox_quote;
403         GtkWidget *hbox1;
404         GtkWidget *hbox2;
405         GtkWidget *hbox3;
406         GtkWidget *label_quotemark;
407         GtkWidget *entry_fw_quotemark;
408         GtkWidget *label_from = NULL;
409         GtkWidget *entry_from = NULL;
410         GtkWidget *scrolledwin_quotefmt;
411         GtkWidget *text_fw_quotefmt;
412         GtkSizeGroup *size_group;
413
414         if (add_info_button)
415                 cm_return_if_fail(parent_window != NULL);
416         cm_return_if_fail(parent_box != NULL);
417         if (checkbtn_forward_with_format) {
418                 cm_return_if_fail(checkbtn_forward_with_format != NULL);
419         }
420         cm_return_if_fail(edit_fw_quotemark != NULL);
421         cm_return_if_fail(edit_fw_format != NULL);
422
423         size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
424
425         if (checkbtn_forward_with_format)
426                 PACK_CHECK_BUTTON (parent_box, checkbtn_use_format,
427                                    _("Use template when forwarding messages"));
428
429         vbox_quote = gtk_vbox_new (FALSE, 4);
430         gtk_widget_show(vbox_quote);
431         gtk_container_add(GTK_CONTAINER (parent_box), vbox_quote);
432         gtk_container_set_border_width (GTK_CONTAINER (vbox_quote), 8);
433
434         if (override_from_format) {
435                 CLAWS_TIP_DECL();
436
437                 hbox3 = gtk_hbox_new (FALSE, 8);
438                 gtk_widget_show (hbox3);
439                 gtk_box_pack_start (GTK_BOX (vbox_quote), hbox3, FALSE, FALSE, 0);
440
441                 label_from = gtk_label_new (prefs_common_translated_header_name("From"));
442                 gtk_misc_set_alignment(GTK_MISC(label_from), 1, 0.5);
443                 gtk_widget_show (label_from);
444                 gtk_box_pack_start (GTK_BOX (hbox3), label_from, FALSE, FALSE, 0);
445                 gtk_size_group_add_widget(size_group, label_from);
446
447                 entry_from = gtk_entry_new ();
448                 gtk_widget_show (entry_from);
449                 gtk_box_pack_start (GTK_BOX (hbox3), entry_from, TRUE, TRUE, 0);
450                 gtk_widget_set_size_request (entry_from, 100, -1);
451
452                 CLAWS_SET_TIP(entry_from,
453                                 _("Override From header. This doesn't change the account used to forward."));
454         }
455
456         hbox1 = gtk_hbox_new (FALSE, 32);
457         gtk_widget_show (hbox1);
458         gtk_box_pack_start (GTK_BOX (vbox_quote), hbox1, FALSE, FALSE, 0);
459
460         hbox2 = gtk_hbox_new (FALSE, 8);
461         gtk_widget_show (hbox2);
462         gtk_box_pack_start (GTK_BOX (hbox1), hbox2, FALSE, FALSE, 0);
463
464         label_quotemark = gtk_label_new (_("Quotation mark"));
465         gtk_misc_set_alignment(GTK_MISC(label_quotemark), 1, 0.5);
466         gtk_widget_show (label_quotemark);
467         gtk_box_pack_start (GTK_BOX (hbox2), label_quotemark, FALSE, FALSE, 0);
468         gtk_size_group_add_widget(size_group, label_quotemark);
469
470         entry_fw_quotemark = gtk_entry_new ();
471         gtk_widget_show (entry_fw_quotemark);
472         gtk_box_pack_start (GTK_BOX (hbox2), entry_fw_quotemark,
473                             FALSE, FALSE, 0);
474         gtk_widget_set_size_request (entry_fw_quotemark, 64, -1);
475
476         scrolledwin_quotefmt = gtk_scrolled_window_new (NULL, NULL);
477         gtk_widget_show (scrolledwin_quotefmt);
478         gtk_box_pack_start (GTK_BOX (vbox_quote), scrolledwin_quotefmt,
479                             TRUE, TRUE, 0);
480         gtk_scrolled_window_set_policy
481                 (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt),
482                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
483         gtk_scrolled_window_set_shadow_type
484                 (GTK_SCROLLED_WINDOW (scrolledwin_quotefmt), GTK_SHADOW_IN);
485
486         text_fw_quotefmt = gtk_text_view_new ();
487         if (prefs_common.textfont) {
488                 PangoFontDescription *font_desc;
489
490                 font_desc = pango_font_description_from_string
491                                                 (prefs_common.textfont);
492                 if (font_desc) {
493                         gtk_widget_modify_font(text_fw_quotefmt, font_desc);
494                         pango_font_description_free(font_desc);
495                 }
496         }
497         gtk_widget_show(text_fw_quotefmt);
498         gtk_container_add(GTK_CONTAINER(scrolledwin_quotefmt),
499                           text_fw_quotefmt);
500         gtk_text_view_set_editable (GTK_TEXT_VIEW (text_fw_quotefmt), TRUE);
501         gtk_widget_set_size_request (text_fw_quotefmt, -1, 100);
502
503         if (checkbtn_forward_with_format) {
504                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, label_quotemark);
505                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, entry_fw_quotemark);
506                 if (override_from_format) {
507                         SET_TOGGLE_SENSITIVITY(checkbtn_use_format, entry_from);
508                         SET_TOGGLE_SENSITIVITY(checkbtn_use_format, label_from);
509                 }
510                 SET_TOGGLE_SENSITIVITY(checkbtn_use_format, text_fw_quotefmt);
511         }
512
513         quote_fmt_add_buttons(parent_window, vbox_quote,
514                                 add_info_button, set_defaults_func);
515
516         if (checkbtn_forward_with_format)
517                 *checkbtn_forward_with_format = checkbtn_use_format;
518         *edit_fw_quotemark = entry_fw_quotemark;
519         if (override_from_format)
520                 *override_from_format = entry_from;
521         *edit_fw_format = text_fw_quotefmt;
522 }
523
524 void quotefmt_add_info_button(GtkWindow *parent_window, GtkWidget *parent_box)
525 {
526         GtkWidget *btn_formatdesc;
527
528         btn_formatdesc = gtk_button_new_from_stock(GTK_STOCK_INFO);
529         gtk_widget_show (btn_formatdesc);
530         gtk_box_pack_start (GTK_BOX (parent_box), btn_formatdesc, FALSE, FALSE, 0);
531         g_signal_connect(G_OBJECT(btn_formatdesc), "clicked",
532                          G_CALLBACK(quote_fmt_quote_description), GTK_WIDGET(parent_window));
533 }
534
535 void quotefmt_add_defaults_button(GtkWindow *parent_window,
536                                                                   GtkWidget *parent_box,
537                                                                   void(*set_defaults_func)(void))
538 {
539         GtkWidget *btn_formatdesc;
540
541         cm_return_if_fail(set_defaults_func != NULL);
542
543         btn_formatdesc = gtk_button_new_with_mnemonic (_("Defaults"));
544         gtk_button_set_image (GTK_BUTTON(btn_formatdesc),
545                 gtk_image_new_from_stock(GTK_STOCK_UNDO, GTK_ICON_SIZE_BUTTON));
546         gtk_widget_show (btn_formatdesc);
547         gtk_box_pack_end (GTK_BOX (parent_box), btn_formatdesc, FALSE, FALSE, 0);
548         g_signal_connect(G_OBJECT(btn_formatdesc), "clicked",
549                          G_CALLBACK(set_defaults_func), GTK_WIDGET(parent_window));
550 }
551
552 void quotefmt_check_new_msg_formats(gboolean use_format,
553                                     gchar *override_from_fmt,
554                                     gchar *subject_fmt,
555                                     gchar *body_fmt)
556 {
557         if (use_format) {
558                 gint line;
559
560                 if (override_from_fmt && !prefs_template_string_is_valid(override_from_fmt, NULL, TRUE, TRUE))
561                         alertpanel_error(_("The \"From\" field of the \"New message\" template contains an invalid email address."));
562
563                 if (!prefs_template_string_is_valid(subject_fmt, NULL, TRUE, FALSE))
564                         alertpanel_error(_("The \"Subject\" field of the \"New message\" template is invalid."));
565
566                 if (!prefs_template_string_is_valid(body_fmt, &line, TRUE, FALSE)) {
567                         alertpanel_error(_("The body of the \"New message\" template has an error at line %d."), line);
568                 }
569         }
570 }
571
572 void quotefmt_check_reply_formats(gboolean use_format,
573                                   gchar *override_from_fmt,
574                                   gchar *quotation_mark,
575                                   gchar *body_fmt)
576 {
577         if (use_format) {
578                 gint line;
579
580                 if (!prefs_template_string_is_valid(quotation_mark, NULL, TRUE, FALSE))
581                         alertpanel_error(_("The \"Quotation mark\" field of the \"Reply\" template is invalid."));
582
583                 if (override_from_fmt && !prefs_template_string_is_valid(override_from_fmt, NULL, TRUE, TRUE))
584                         alertpanel_error(_("The \"From\" field of the \"Reply\" template contains an invalid email address."));
585
586                 if (!prefs_template_string_is_valid(body_fmt, &line, TRUE, FALSE)) {
587                         alertpanel_error(_("The body of the \"Reply\" template has an error at line %d."), line);
588                 }
589         }
590 }
591
592 void quotefmt_check_forward_formats(gboolean use_format,
593                                     gchar *override_from_fmt,
594                                     gchar *quotation_mark,
595                                     gchar *body_fmt)
596 {
597         if (use_format) {
598                 gint line;
599
600                 if (!prefs_template_string_is_valid(quotation_mark, NULL, TRUE, FALSE))
601                         alertpanel_error(_("The \"Quotation mark\" field of the \"Forward\" template is invalid."));
602
603                 if (override_from_fmt && !prefs_template_string_is_valid(override_from_fmt, NULL, TRUE, TRUE))
604                         alertpanel_error(_("The \"From\" field of the \"Forward\" template contains an invalid email address."));
605
606                 if (!prefs_template_string_is_valid(body_fmt, &line, TRUE, FALSE)) {
607                         alertpanel_error(_("The body of the \"Forward\" template has an error at line %d."), line);
608                 }
609         }
610 }