Statistics
| Revision:

root / src / prefs_template.c @ 3269

History | View | Annotate | Download (19.3 KB)

1
/*
2
 * Sylpheed templates subsystem 
3
 * Copyright (C) 2001 Alexander Barinov
4
 * Copyright (C) 2001-2012 Hiroyuki Yamamoto
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
 */
20

    
21
#include "defs.h"
22

    
23
#include <glib.h>
24
#include <glib/gi18n.h>
25
#include <gtk/gtk.h>
26
#include <gdk/gdkkeysyms.h>
27
#include <string.h>
28
#include <dirent.h>
29
#include <sys/stat.h>
30

    
31
#include "template.h"
32
#include "main.h"
33
#include "inc.h"
34
#include "utils.h"
35
#include "gtkutils.h"
36
#include "alertpanel.h"
37
#include "manage_window.h"
38
#include "prefs_common.h"
39
#include "prefs_common_dialog.h"
40
#include "compose.h"
41
#include "mainwindow.h"
42
#include "addr_compl.h"
43
#include "quote_fmt.h"
44
#include "plugin.h"
45

    
46
static struct Templates {
47
        GtkWidget *window;
48
        GtkWidget *clist_tmpls;
49
        GtkWidget *entry_name;
50
        GtkWidget *entry_to;
51
        GtkWidget *entry_cc;
52
        GtkWidget *entry_bcc;
53
        GtkWidget *entry_replyto;
54
        GtkWidget *entry_subject;
55
        GtkWidget *text_value;
56
        GtkWidget *confirm_area;
57
        GtkWidget *ok_btn;
58
        GtkWidget *cancel_btn;
59

    
60
        gboolean entry_modified;
61
        gboolean list_modified;
62
} templates;
63

    
64
/* widget creating functions */
65
static void prefs_template_window_create        (void);
66
static void prefs_template_window_setup                (void);
67
static void prefs_template_clear                (void);
68

    
69
static GSList *prefs_template_get_list                (void);
70

    
71
/* callbacks */
72
static gint prefs_template_deleted_cb                (GtkWidget        *widget,
73
                                                 GdkEventAny        *event,
74
                                                 gpointer         data);
75
static gboolean prefs_template_key_pressed_cb        (GtkWidget        *widget,
76
                                                 GdkEventKey        *event,
77
                                                 gpointer         data);
78
static void prefs_template_changed_cb                (GtkEditable        *editable,
79
                                                 gpointer         data);
80
static void prefs_template_cancel_cb                (void);
81
static void prefs_template_ok_cb                (void);
82
static void prefs_template_select_cb                (GtkCList        *clist,
83
                                                 gint                 row,
84
                                                 gint                 column,
85
                                                 GdkEvent        *event);
86
static void prefs_template_register_cb                (void);
87
static void prefs_template_substitute_cb        (void);
88
static void prefs_template_delete_cb                (void);
89
static void prefs_template_up_cb                (void);
90
static void prefs_template_down_cb                (void);
91

    
92
/* Called from mainwindow.c */
93
void prefs_template_open(void)
94
{
95
        inc_lock();
96

    
97
        if (!templates.window)
98
                prefs_template_window_create();
99

    
100
        prefs_template_window_setup();
101
        gtk_widget_show(templates.window);
102

    
103
        syl_plugin_signal_emit("prefs-template-open", templates.window);
104
}
105

    
106
#define ADD_ENTRY(entry, str, row) \
107
{ \
108
        label1 = gtk_label_new(str); \
109
        gtk_widget_show(label1); \
110
        gtk_table_attach(GTK_TABLE(table), label1, 0, 1, row, (row + 1), \
111
                         GTK_FILL, 0, 0, 0); \
112
        gtk_misc_set_alignment(GTK_MISC(label1), 1, 0.5); \
113
 \
114
        entry = gtk_entry_new(); \
115
        gtk_widget_show(entry); \
116
        gtk_table_attach(GTK_TABLE(table), entry, 1, 2, row, (row + 1), \
117
                         GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0); \
118
        g_signal_connect(G_OBJECT(entry), "changed", \
119
                         G_CALLBACK(prefs_template_changed_cb), NULL); \
120
}
121

    
122
static void prefs_template_window_create(void)
123
{
124
        /* window structure ;) */
125
        GtkWidget *window;
126
        GtkWidget   *vpaned;
127
        GtkWidget     *vbox1;
128
        GtkWidget       *hbox1;
129
        GtkWidget         *label1;
130
        GtkWidget         *entry_name;
131
        GtkWidget       *table;
132
        GtkWidget         *entry_to;
133
        GtkWidget         *entry_cc;
134
        GtkWidget         *entry_bcc;
135
        GtkWidget         *entry_replyto;
136
        GtkWidget         *entry_subject;
137
        GtkWidget       *scroll2;
138
        GtkWidget         *text_value;
139
        GtkWidget     *vbox2;
140
        GtkWidget       *hbox2;
141
        GtkWidget         *arrow1;
142
        GtkWidget         *hbox3;
143
        GtkWidget           *reg_btn;
144
        GtkWidget           *subst_btn;
145
        GtkWidget           *del_btn;
146
        GtkWidget         *desc_btn;
147
        GtkWidget       *hbox4;
148
        GtkWidget         *scroll1;
149
        GtkWidget           *clist_tmpls;
150
        GtkWidget         *vbox3;
151
        GtkWidget           *vbox4;
152
        GtkWidget             *up_btn;
153
        GtkWidget             *down_btn;
154
        GtkWidget       *confirm_area;
155
        GtkWidget         *ok_btn;
156
        GtkWidget         *cancel_btn;
157

    
158
        GtkTextBuffer *buffer;
159

    
160
        gchar *title[1];
161

    
162
        /* main window */
163
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
164
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
165
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
166
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
167

    
168
        /* vpaned to separate template settings from templates list */
169
        vpaned = gtk_vpaned_new();
170
        gtk_widget_show(vpaned);
171
        gtk_container_add(GTK_CONTAINER(window), vpaned);
172

    
173
        /* vbox to handle template name and content */
174
        vbox1 = gtk_vbox_new(FALSE, 6);
175
        gtk_widget_show(vbox1);
176
        gtk_container_set_border_width(GTK_CONTAINER(vbox1), 8);
177
        gtk_paned_pack1(GTK_PANED(vpaned), vbox1, FALSE, FALSE);
178

    
179
        hbox1 = gtk_hbox_new(FALSE, 8);
180
        gtk_widget_show(hbox1);
181
        gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
182

    
183
        label1 = gtk_label_new(_("Template name"));
184
        gtk_widget_show(label1);
185
        gtk_box_pack_start(GTK_BOX(hbox1), label1, FALSE, FALSE, 0);
186

    
187
        entry_name = gtk_entry_new();
188
        gtk_widget_show(entry_name);
189
        gtk_box_pack_start(GTK_BOX(hbox1), entry_name, TRUE, TRUE, 0);
190
        g_signal_connect(G_OBJECT(entry_name), "changed",
191
                         G_CALLBACK(prefs_template_changed_cb), NULL);
192

    
193
        /* table for headers */
194
        table = gtk_table_new(5, 2, FALSE);
195
        gtk_widget_show(table);
196
        gtk_box_pack_start(GTK_BOX(vbox1), table, FALSE, FALSE, 0);
197
        gtk_table_set_row_spacings(GTK_TABLE(table), 4);
198
        gtk_table_set_col_spacings(GTK_TABLE(table), 4);
199

    
200
        ADD_ENTRY(entry_to, _("To:"), 0);
201
        address_completion_register_entry(GTK_ENTRY(entry_to));
202
        ADD_ENTRY(entry_cc, _("Cc:"), 1);
203
        address_completion_register_entry(GTK_ENTRY(entry_cc));
204
        ADD_ENTRY(entry_bcc, _("Bcc:"), 2);
205
        address_completion_register_entry(GTK_ENTRY(entry_bcc));
206
        ADD_ENTRY(entry_replyto, _("Reply-To:"), 3);
207
        address_completion_register_entry(GTK_ENTRY(entry_replyto));
208
        ADD_ENTRY(entry_subject, _("Subject:"), 4);
209

    
210
#undef ADD_ENTRY
211

    
212
        /* template content */
213
        scroll2 = gtk_scrolled_window_new(NULL, NULL);
214
        gtk_widget_show(scroll2);
215
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll2),
216
                                       GTK_POLICY_NEVER,
217
                                       GTK_POLICY_AUTOMATIC);
218
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll2),
219
                                            GTK_SHADOW_IN);
220
        gtk_box_pack_start(GTK_BOX(vbox1), scroll2, TRUE, TRUE, 0);
221

    
222
        text_value = gtk_text_view_new();
223
        gtk_widget_show(text_value);
224
        gtk_widget_set_size_request(text_value, 360, 120);
225
        gtk_container_add(GTK_CONTAINER(scroll2), text_value);
226
        gtk_text_view_set_editable(GTK_TEXT_VIEW(text_value), TRUE);
227
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_value));
228
        g_signal_connect(G_OBJECT(buffer), "changed",
229
                         G_CALLBACK(prefs_template_changed_cb), NULL);
230

    
231
        /* vbox for buttons and templates list */
232
        vbox2 = gtk_vbox_new(FALSE, 6);
233
        gtk_widget_show(vbox2);
234
        gtk_container_set_border_width(GTK_CONTAINER(vbox2), 8);
235
        gtk_paned_pack2(GTK_PANED(vpaned), vbox2, TRUE, FALSE);
236

    
237
        /* register | substitute | delete */
238
        hbox2 = gtk_hbox_new(FALSE, 4);
239
        gtk_widget_show(hbox2);
240
        gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0);
241

    
242
        arrow1 = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
243
        gtk_widget_show(arrow1);
244
        gtk_box_pack_start(GTK_BOX(hbox2), arrow1, FALSE, FALSE, 0);
245
        gtk_widget_set_size_request(arrow1, -1, 16);
246

    
247
        hbox3 = gtk_hbox_new(TRUE, 4);
248
        gtk_widget_show(hbox3);
249
        gtk_box_pack_start(GTK_BOX(hbox2), hbox3, FALSE, FALSE, 0);
250

    
251
        reg_btn = gtk_button_new_with_label(_("Register"));
252
        gtk_widget_show(reg_btn);
253
        gtk_box_pack_start(GTK_BOX(hbox3), reg_btn, FALSE, TRUE, 0);
254
        g_signal_connect(G_OBJECT (reg_btn), "clicked",
255
                         G_CALLBACK (prefs_template_register_cb), NULL);
256

    
257
        subst_btn = gtk_button_new_with_label(_(" Substitute "));
258
        gtk_widget_show(subst_btn);
259
        gtk_box_pack_start(GTK_BOX(hbox3), subst_btn, FALSE, TRUE, 0);
260
        g_signal_connect(G_OBJECT(subst_btn), "clicked",
261
                         G_CALLBACK(prefs_template_substitute_cb), NULL);
262

    
263
        del_btn = gtk_button_new_with_label(_("Delete"));
264
        gtk_widget_show(del_btn);
265
        gtk_box_pack_start(GTK_BOX(hbox3), del_btn, FALSE, TRUE, 0);
266
        g_signal_connect(G_OBJECT(del_btn), "clicked",
267
                         G_CALLBACK(prefs_template_delete_cb), NULL);
268

    
269
        desc_btn = gtk_button_new_with_label(_(" Symbols "));
270
        gtk_widget_show(desc_btn);
271
        gtk_box_pack_end(GTK_BOX(hbox2), desc_btn, FALSE, FALSE, 0);
272
        g_signal_connect(G_OBJECT(desc_btn), "clicked",
273
                         G_CALLBACK(prefs_quote_description), NULL);
274

    
275
        /* templates list */
276
        hbox4 = gtk_hbox_new(FALSE, 8);
277
        gtk_widget_show(hbox4);
278
        gtk_box_pack_start(GTK_BOX(vbox2), hbox4, TRUE, TRUE, 0);
279

    
280
        scroll1 = gtk_scrolled_window_new(NULL, NULL);
281
        gtk_widget_show(scroll1);
282
        gtk_box_pack_start(GTK_BOX(hbox4), scroll1, TRUE, TRUE, 0);
283
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll1),
284
                                       GTK_POLICY_AUTOMATIC,
285
                                       GTK_POLICY_AUTOMATIC);
286

    
287
        title[0] = _("Registered templates");
288
        clist_tmpls = gtk_clist_new_with_titles(1, title);
289
        gtk_widget_show(clist_tmpls);
290
        gtk_widget_set_size_request(scroll1, -1, 140);
291
        gtk_container_add(GTK_CONTAINER(scroll1), clist_tmpls);
292
        gtk_clist_set_column_width(GTK_CLIST(clist_tmpls), 0, 80);
293
        gtk_clist_set_selection_mode(GTK_CLIST(clist_tmpls),
294
                                     GTK_SELECTION_BROWSE);
295
        gtkut_clist_set_redraw(GTK_CLIST(clist_tmpls));
296
        GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist_tmpls)->column[0].button,
297
                               GTK_CAN_FOCUS);
298
        g_signal_connect(G_OBJECT (clist_tmpls), "select_row",
299
                         G_CALLBACK (prefs_template_select_cb), NULL);
300

    
301
        vbox3 = gtk_vbox_new(TRUE, 0);
302
        gtk_widget_show(vbox3);
303
        gtk_box_pack_start(GTK_BOX(hbox4), vbox3, FALSE, FALSE, 0);
304

    
305
        vbox4 = gtk_vbox_new(TRUE, 8);
306
        gtk_widget_show(vbox4);
307
        gtk_box_pack_start(GTK_BOX(vbox3), vbox4, TRUE, FALSE, 0);
308

    
309
        up_btn = gtk_button_new_with_label(_("Up"));
310
        gtk_widget_show(up_btn);
311
        gtk_box_pack_start(GTK_BOX(vbox4), up_btn, FALSE, FALSE, 0);
312
        g_signal_connect(G_OBJECT (up_btn), "clicked",
313
                         G_CALLBACK (prefs_template_up_cb), NULL);
314

    
315
        down_btn = gtk_button_new_with_label(_("Down"));
316
        gtk_widget_show(down_btn);
317
        gtk_box_pack_start(GTK_BOX(vbox4), down_btn, FALSE, FALSE, 0);
318
        g_signal_connect(G_OBJECT (down_btn), "clicked",
319
                         G_CALLBACK (prefs_template_down_cb), NULL);
320

    
321
        /* ok | cancel */
322
        gtkut_stock_button_set_create(&confirm_area, &ok_btn, GTK_STOCK_OK,
323
                                      &cancel_btn, GTK_STOCK_CANCEL,
324
                                      NULL, NULL);
325
        gtk_widget_show(confirm_area);
326
        gtk_box_pack_end(GTK_BOX(vbox2), confirm_area, FALSE, FALSE, 0);
327
        gtk_widget_grab_default(ok_btn);
328

    
329
        gtk_window_set_title(GTK_WINDOW(window), _("Templates"));
330

    
331
        g_signal_connect(G_OBJECT(window), "delete_event",
332
                         G_CALLBACK(prefs_template_deleted_cb), NULL);
333
        g_signal_connect(G_OBJECT(window), "key_press_event",
334
                         G_CALLBACK(prefs_template_key_pressed_cb), NULL);
335
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
336
        g_signal_connect(G_OBJECT(ok_btn), "clicked",
337
                         G_CALLBACK(prefs_template_ok_cb), NULL);
338
        g_signal_connect(G_OBJECT(cancel_btn), "clicked",
339
                         G_CALLBACK(prefs_template_cancel_cb), NULL);
340

    
341
        address_completion_start(window);
342

    
343
        templates.window = window;
344
        templates.clist_tmpls = clist_tmpls;
345
        templates.entry_name = entry_name;
346
        templates.entry_to = entry_to;
347
        templates.entry_cc = entry_cc;
348
        templates.entry_bcc = entry_bcc;
349
        templates.entry_replyto = entry_replyto;
350
        templates.entry_subject = entry_subject;
351
        templates.text_value = text_value;
352
        templates.confirm_area = confirm_area;
353
        templates.ok_btn = ok_btn;
354
        templates.cancel_btn = cancel_btn;
355
        templates.entry_modified = FALSE;
356
        templates.list_modified = FALSE;
357
}
358

    
359
static void prefs_template_window_setup(void)
360
{
361
        GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
362
        GSList *tmpl_list;
363
        GSList *cur;
364
        gchar *title[1];
365
        gint row;
366
        Template *tmpl;
367

    
368
        gtkut_box_set_reverse_order(GTK_BOX(templates.confirm_area),
369
                                    !prefs_common.comply_gnome_hig);
370
        manage_window_set_transient(GTK_WINDOW(templates.window));
371
        gtk_widget_grab_focus(templates.ok_btn);
372

    
373
        gtk_clist_freeze(clist);
374
        gtk_clist_clear(clist);
375

    
376
        title[0] = _("(New)");
377
        row = gtk_clist_append(clist, title);
378
        gtk_clist_set_row_data(clist, row, NULL);
379

    
380
        tmpl_list = template_read_config();
381

    
382
        for (cur = tmpl_list; cur != NULL; cur = cur->next) {
383
                tmpl = (Template *)cur->data;
384
                title[0] = tmpl->name;
385
                row = gtk_clist_append(clist, title);
386
                gtk_clist_set_row_data(clist, row, tmpl);
387
        }
388

    
389
        g_slist_free(tmpl_list);
390

    
391
        gtk_clist_thaw(clist);
392

    
393
        templates.entry_modified = FALSE;
394
        templates.list_modified = FALSE;
395
}
396

    
397
static void prefs_template_clear(void)
398
{
399
        Template *tmpl;
400
        gint row = 1;
401

    
402
        while ((tmpl = gtk_clist_get_row_data
403
                (GTK_CLIST(templates.clist_tmpls), row)) != NULL) {
404
                template_free(tmpl);
405
                row++;
406
        }
407

    
408
        gtk_clist_clear(GTK_CLIST(templates.clist_tmpls));
409
}
410

    
411
static gint prefs_template_deleted_cb(GtkWidget *widget, GdkEventAny *event,
412
                                      gpointer data)
413
{
414
        prefs_template_cancel_cb();
415
        return TRUE;
416
}
417

    
418
static gboolean prefs_template_key_pressed_cb(GtkWidget *widget,
419
                                              GdkEventKey *event, gpointer data)
420
{
421
        if (event && event->keyval == GDK_Escape)
422
                prefs_template_cancel_cb();
423
        return FALSE;
424
}
425

    
426
static void prefs_template_changed_cb(GtkEditable *editable, gpointer data)
427
{
428
        templates.entry_modified = TRUE;
429
}
430

    
431
static void prefs_template_ok_cb(void)
432
{
433
        GSList *tmpl_list;
434

    
435
        if (templates.entry_modified) {
436
                if (alertpanel(_("Template is modified"),
437
                               _("Current modification is not applied. Finish without saving it?"),
438
                               GTK_STOCK_YES, GTK_STOCK_NO, NULL)
439
                    != G_ALERTDEFAULT)
440
                        return;
441
        }
442

    
443
        tmpl_list = prefs_template_get_list();
444
        template_set_config(tmpl_list);
445
        compose_reflect_prefs_all();
446
        gtk_clist_clear(GTK_CLIST(templates.clist_tmpls));
447
        gtk_widget_hide(templates.window);
448
        main_window_popup(main_window_get());
449
        inc_unlock();
450
}
451

    
452
static void prefs_template_cancel_cb(void)
453
{
454
        if (templates.entry_modified || templates.list_modified) {
455
                if (alertpanel(_("Templates are modified"),
456
                               _("Really discard modification to templates?"),
457
                               GTK_STOCK_YES, GTK_STOCK_NO, NULL)
458
                    != G_ALERTDEFAULT)
459
                        return;
460
        }
461

    
462
        prefs_template_clear();
463
        gtk_widget_hide(templates.window);
464
        main_window_popup(main_window_get());
465
        inc_unlock();
466
}
467

    
468
static void prefs_template_select_cb(GtkCList *clist, gint row, gint column,
469
                                     GdkEvent *event)
470
{
471
        Template *tmpl;
472
        Template tmpl_def;
473
        GtkTextBuffer *buffer;
474
        GtkTextIter iter;
475

    
476
        tmpl_def.name = _("Template");
477
        tmpl_def.subject = "";
478
        tmpl_def.to = "";
479
        tmpl_def.cc = "";
480
        tmpl_def.bcc = "";
481
        tmpl_def.replyto = "";
482
        tmpl_def.value = "";
483

    
484
        if (!(tmpl = gtk_clist_get_row_data(clist, row)))
485
                tmpl = &tmpl_def;
486

    
487
        gtk_entry_set_text(GTK_ENTRY(templates.entry_name), tmpl->name);
488
        gtk_entry_set_text(GTK_ENTRY(templates.entry_to),
489
                           tmpl->to ? tmpl->to : "");
490
        gtk_entry_set_text(GTK_ENTRY(templates.entry_cc),
491
                           tmpl->cc ? tmpl->cc : "");
492
        gtk_entry_set_text(GTK_ENTRY(templates.entry_bcc),
493
                           tmpl->bcc ? tmpl->bcc : "");
494
        gtk_entry_set_text(GTK_ENTRY(templates.entry_replyto),
495
                           tmpl->replyto ? tmpl->replyto : "");
496
        gtk_entry_set_text(GTK_ENTRY(templates.entry_subject),
497
                           tmpl->subject ? tmpl->subject : "");
498

    
499
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(templates.text_value));
500
        gtk_text_buffer_set_text(buffer, "", 0);
501
        gtk_text_buffer_get_start_iter(buffer, &iter);
502
        gtk_text_buffer_insert(buffer, &iter, tmpl->value, -1);
503

    
504
        templates.entry_modified = FALSE;
505
}
506

    
507
static GSList *prefs_template_get_list(void)
508
{
509
        gint row = 1;
510
        GSList *tmpl_list = NULL;
511
        Template *tmpl;
512

    
513
        while ((tmpl = gtk_clist_get_row_data
514
                (GTK_CLIST(templates.clist_tmpls), row)) != NULL) {
515
                tmpl->tmplid = row;
516
                tmpl_list = g_slist_append(tmpl_list, tmpl);
517
                row++;
518
        }
519

    
520
        return tmpl_list;
521
}
522

    
523
static gint prefs_template_clist_set_row(gint row)
524
{
525
        GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
526
        Template *tmpl;
527
        Template *tmp_tmpl;
528
        GtkTextBuffer *buffer;
529
        GtkTextIter start, end;
530
        gchar *name;
531
        gchar *to;
532
        gchar *cc;
533
        gchar *bcc;
534
        gchar *replyto;
535
        gchar *subject;
536
        gchar *value;
537
        gchar *title[1];
538

    
539
        g_return_val_if_fail(row != 0, -1);
540

    
541
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(templates.text_value));
542
        gtk_text_buffer_get_start_iter(buffer, &start);
543
        gtk_text_buffer_get_end_iter(buffer, &end);
544
        value = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
545

    
546
        if (value && *value != '\0') {
547
                gchar *parsed_buf;
548
                MsgInfo dummyinfo;
549

    
550
                memset(&dummyinfo, 0, sizeof(MsgInfo));
551
                quote_fmt_init(&dummyinfo, NULL, NULL);
552
                quote_fmt_scan_string(value);
553
                quote_fmt_parse();
554
                parsed_buf = quote_fmt_get_buffer();
555
                if (!parsed_buf) {
556
                        alertpanel_error(_("Template format error."));
557
                        g_free(value);
558
                        return -1;
559
                }
560
        }
561

    
562
        name = gtk_editable_get_chars(GTK_EDITABLE(templates.entry_name),
563
                                      0, -1);
564
        to = gtk_editable_get_chars(GTK_EDITABLE(templates.entry_to), 0, -1);
565
        cc = gtk_editable_get_chars(GTK_EDITABLE(templates.entry_cc), 0, -1);
566
        bcc = gtk_editable_get_chars(GTK_EDITABLE(templates.entry_bcc), 0, -1);
567
        replyto = gtk_editable_get_chars(GTK_EDITABLE(templates.entry_replyto),
568
                                         0, -1);
569
        subject = gtk_editable_get_chars(GTK_EDITABLE(templates.entry_subject),
570
                                         0, -1);
571

    
572
#define NULLIFY_IF_EMPTY(val)                \
573
        if (val && *val == '\0') {        \
574
                g_free(val);                \
575
                val = NULL;                \
576
        }
577

    
578
        NULLIFY_IF_EMPTY(to);
579
        NULLIFY_IF_EMPTY(cc);
580
        NULLIFY_IF_EMPTY(bcc);
581
        NULLIFY_IF_EMPTY(replyto);
582
        NULLIFY_IF_EMPTY(subject);
583

    
584
#undef NULLIFY_IF_EMPTY
585

    
586
        tmpl = g_new(Template, 1);
587
        tmpl->name = name;
588
        tmpl->to = to;
589
        tmpl->cc = cc;
590
        tmpl->bcc = bcc;
591
        tmpl->replyto = replyto;
592
        tmpl->subject = subject;
593
        tmpl->value = value;
594

    
595
        title[0] = name;
596

    
597
        if (row < 0) {
598
                row = gtk_clist_append(clist, title);
599
        } else {
600
                gtk_clist_set_text(clist, row, 0, name);
601
                tmp_tmpl = gtk_clist_get_row_data(clist, row);
602
                if (tmp_tmpl)
603
                        template_free(tmp_tmpl);
604
        }
605

    
606
        gtk_clist_set_row_data(clist, row, tmpl);
607
        templates.entry_modified = FALSE;
608
        templates.list_modified = TRUE;
609

    
610
        return row;
611
}
612

    
613
static void prefs_template_register_cb(void)
614
{
615
        prefs_template_clist_set_row(-1);
616
}
617

    
618
static void prefs_template_substitute_cb(void)
619
{
620
        GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
621
        Template *tmpl;
622
        gint row;
623

    
624
        if (!clist->selection) return;
625

    
626
        row = GPOINTER_TO_INT(clist->selection->data);
627
        if (row == 0) return;
628

    
629
        tmpl = gtk_clist_get_row_data(clist, row);
630
        if (!tmpl) return;
631

    
632
        prefs_template_clist_set_row(row);
633
}
634

    
635
static void prefs_template_delete_cb(void)
636
{
637
        GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
638
        Template *tmpl;
639
        gint row;
640

    
641
        if (!clist->selection) return;
642
        row = GPOINTER_TO_INT(clist->selection->data);
643
        if (row == 0) return;
644

    
645
        if (alertpanel(_("Delete template"),
646
                       _("Do you really want to delete this template?"),
647
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
648
                return;
649

    
650
        tmpl = gtk_clist_get_row_data(clist, row);
651
        template_free(tmpl);
652
        gtk_clist_remove(clist, row);
653
        templates.list_modified = TRUE;
654
}
655

    
656
static void prefs_template_up_cb(void)
657
{
658
        GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
659
        gint row;
660

    
661
        if (!clist->selection) return;
662
        row = GPOINTER_TO_INT(clist->selection->data);
663
        if (row > 1) {
664
                gtk_clist_row_move(clist, row, row - 1);
665
                templates.list_modified = TRUE;
666
        }
667
}
668

    
669
static void prefs_template_down_cb(void)
670
{
671
        GtkCList *clist = GTK_CLIST(templates.clist_tmpls);
672
        gint row;
673

    
674
        if (!clist->selection) return;
675
        row = GPOINTER_TO_INT(clist->selection->data);
676
        if (row > 0 && row < clist->rows - 1) {
677
                gtk_clist_row_move(clist, row, row + 1);
678
                templates.list_modified = TRUE;
679
        }
680
}