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