Added TAGS to .cvsignore
[claws.git] / src / prefs_headers.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2001 Hiroyuki Yamamoto
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 2 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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include "intl.h"
35 #include "main.h"
36 #include "prefs.h"
37 #include "prefs_headers.h"
38 #include "prefs_common.h"
39 #include "prefs_account.h"
40 #include "mainwindow.h"
41 #include "foldersel.h"
42 #include "manage_window.h"
43 #include "headers.h"
44 #include "utils.h"
45 #include "gtkutils.h"
46 #include "alertpanel.h"
47 #include "folder.h"
48
49 static struct Headers {
50         GtkWidget *window;
51
52         GtkWidget *close_btn;
53
54         GtkWidget *hdr_combo;
55         GtkWidget *hdr_entry;
56         GtkWidget *key_entry;
57         GtkWidget *headers_clist;
58
59         /*
60         GtkWidget *hdr_combo1;
61         GtkWidget *hdr_combo2;
62         GtkWidget *hdr_entry1;
63         GtkWidget *hdr_entry2;
64         GtkWidget *key_entry1;
65         GtkWidget *key_entry2;
66         GtkWidget *pred_combo1;
67         GtkWidget *pred_combo2;
68         GtkWidget *pred_entry1;
69         GtkWidget *pred_entry2;
70         GtkWidget *op_combo;
71         GtkWidget *op_entry;
72
73         GtkWidget *dest_entry;
74         GtkWidget *regex_chkbtn;
75
76         GtkWidget *destsel_btn;
77         GtkWidget *dest_radiobtn;
78         GtkWidget *notrecv_radiobtn;
79
80         GtkWidget *cond_clist;
81         */
82 } headers;
83
84 /*
85    parameter name, default value, pointer to the prefs variable, data type,
86    pointer to the widget pointer,
87    pointer to the function for data setting,
88    pointer to the function for widget setting
89  */
90
91 #define VSPACING                12
92 #define VSPACING_NARROW         4
93 #define DEFAULT_ENTRY_WIDTH     80
94 #define PREFSBUFSIZE            1024
95
96 /* widget creating functions */
97 static void prefs_headers_create                (void);
98
99 static void prefs_headers_set_dialog    (PrefsAccount * ac);
100 static void prefs_headers_set_list      (PrefsAccount * ac);
101 static gint prefs_headers_clist_set_row (PrefsAccount * ac,
102                                          gint    row);
103
104 /* callback functions */
105 static void prefs_headers_select_dest_cb        (void);
106 static void prefs_headers_register_cb   (void);
107 static void prefs_headers_substitute_cb (void);
108 static void prefs_headers_delete_cb     (void);
109 static void prefs_headers_up            (void);
110 static void prefs_headers_down          (void);
111 static void prefs_headers_select                (GtkCList       *clist,
112                                          gint            row,
113                                          gint            column,
114                                          GdkEvent       *event);
115
116 static void prefs_headers_dest_radio_button_toggled     (void);
117 static void prefs_headers_notrecv_radio_button_toggled  (void);
118
119 static void prefs_headers_key_pressed   (GtkWidget      *widget,
120                                          GdkEventKey    *event,
121                                          gpointer        data);
122 static void prefs_headers_close         (GtkButton      *button);
123
124 static PrefsAccount * cur_ac = NULL;
125
126 void prefs_headers_open(PrefsAccount * ac)
127 {
128         if (!headers.window) {
129                 prefs_headers_create();
130         }
131
132         manage_window_set_transient(GTK_WINDOW(headers.window));
133         gtk_widget_grab_focus(headers.close_btn);
134
135         prefs_headers_set_dialog(ac);
136
137         cur_ac = ac;
138
139         gtk_widget_show(headers.window);
140 }
141
142 static void prefs_headers_create(void)
143 {
144         GtkWidget *window;
145         GtkWidget *vbox;
146         GtkWidget *close_btn;
147         GtkWidget *confirm_area;
148
149         GtkWidget *vbox1;
150
151         GtkWidget *table1;
152         GtkWidget *hdr_label;
153         GtkWidget *hdr_combo;
154         GtkWidget *key_label;
155         GtkWidget *key_entry;
156
157         GtkWidget *reg_hbox;
158         GtkWidget *btn_hbox;
159         GtkWidget *arrow;
160         GtkWidget *reg_btn;
161         GtkWidget *subst_btn;
162         GtkWidget *del_btn;
163
164         GtkWidget *ch_hbox;
165         GtkWidget *ch_scrolledwin;
166         GtkWidget *headers_clist;
167
168         GtkWidget *btn_vbox;
169         GtkWidget *up_btn;
170         GtkWidget *down_btn;
171         /*
172
173         GtkWidget *table1;
174         GtkWidget *op_label;
175         GtkWidget *op_combo;
176         GtkWidget *op_entry;
177         GtkWidget *hdr_label;
178         GtkWidget *hdr_combo1;
179         GtkWidget *hdr_combo2;
180         GtkWidget *key_label;
181         GtkWidget *key_entry1;
182         GtkWidget *key_entry2;
183         GtkWidget *pred_label;
184         GtkWidget *pred_combo1;
185         GtkWidget *pred_entry1;
186         GtkWidget *pred_combo2;
187         GtkWidget *pred_entry2;
188
189         GtkWidget *vbox2;
190         GtkWidget *dest_hbox;
191         GtkWidget *dest_entry;
192         GtkWidget *destsel_btn;
193         GtkWidget *dest_radiobtn;
194         GtkWidget *notrecv_radiobtn;
195         GSList *recv_group = NULL;
196
197         GtkWidget *regex_chkbtn;
198
199         GtkWidget *reg_hbox;
200         GtkWidget *btn_hbox;
201         GtkWidget *arrow;
202         GtkWidget *reg_btn;
203         GtkWidget *subst_btn;
204         GtkWidget *del_btn;
205
206         GtkWidget *cond_hbox;
207         GtkWidget *cond_scrolledwin;
208         GtkWidget *cond_clist;
209
210         GtkWidget *btn_vbox;
211         GtkWidget *up_btn;
212         GtkWidget *down_btn;
213         */
214
215         gchar *title[] = {_("Custom headers")};
216
217         debug_print(_("Creating headers setting window...\n"));
218
219         window = gtk_window_new (GTK_WINDOW_DIALOG);
220         gtk_container_set_border_width (GTK_CONTAINER (window), 8);
221         gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
222         gtk_window_set_modal (GTK_WINDOW (window), TRUE);
223         gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
224
225         vbox = gtk_vbox_new (FALSE, 6);
226         gtk_widget_show (vbox);
227         gtk_container_add (GTK_CONTAINER (window), vbox);
228
229         gtkut_button_set_create (&confirm_area, &close_btn, _("Close"),
230                                  NULL, NULL, NULL, NULL);
231         gtk_widget_show (confirm_area);
232         gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
233         gtk_widget_grab_default (close_btn);
234
235         gtk_window_set_title (GTK_WINDOW(window),
236                               _("Headers setting"));
237         gtk_signal_connect (GTK_OBJECT(window), "delete_event",
238                             GTK_SIGNAL_FUNC(gtk_widget_hide_on_delete), NULL);
239         gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
240                             GTK_SIGNAL_FUNC(prefs_headers_key_pressed), NULL);
241         gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
242                             GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
243         gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
244                             GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
245         gtk_signal_connect (GTK_OBJECT(close_btn), "clicked",
246                             GTK_SIGNAL_FUNC(prefs_headers_close), NULL);
247
248         vbox1 = gtk_vbox_new (FALSE, VSPACING);
249         gtk_widget_show (vbox1);
250         gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
251         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
252
253         table1 = gtk_table_new (2, 2, FALSE);
254         gtk_widget_show (table1);
255         gtk_box_pack_start (GTK_BOX (vbox1), table1,
256                             FALSE, FALSE, 0);
257         gtk_table_set_row_spacings (GTK_TABLE (table1), 8);
258         gtk_table_set_col_spacings (GTK_TABLE (table1), 8);
259
260         /*
261         op_label = gtk_label_new (_("Operator"));
262         gtk_widget_show (op_label);
263         gtk_table_attach (GTK_TABLE (table1), op_label, 0, 1, 0, 1,
264                           GTK_FILL, 0, 0, 0);
265         gtk_misc_set_alignment (GTK_MISC (op_label), 0, 0.5);
266
267         op_combo = gtk_combo_new ();
268         gtk_widget_show (op_combo);
269         gtk_table_attach (GTK_TABLE (table1), op_combo, 0, 1, 2, 3,
270                           0, 0, 0, 0);
271         gtk_widget_set_usize (op_combo, 52, -1);
272         gtkut_combo_set_items (GTK_COMBO (op_combo), "and", "or", NULL);
273
274         op_entry = GTK_COMBO (op_combo)->entry;
275         gtk_entry_set_editable (GTK_ENTRY (op_entry), FALSE);
276
277         hdr_label = gtk_label_new (_("Header"));
278         gtk_widget_show (hdr_label);
279         gtk_table_attach (GTK_TABLE (table1), hdr_label, 1, 2, 0, 1,
280                           GTK_FILL, 0, 0, 0);
281         gtk_misc_set_alignment (GTK_MISC (hdr_label), 0, 0.5);
282
283         hdr_combo1 = gtk_combo_new ();
284         gtk_widget_show (hdr_combo1);
285         gtk_table_attach (GTK_TABLE (table1), hdr_combo1, 1, 2, 1, 2,
286                           0, 0, 0, 0);
287         gtk_widget_set_usize (hdr_combo1, 96, -1);
288         gtkut_combo_set_items (GTK_COMBO (hdr_combo1),
289                                "Subject", "From", "To", "Cc", "Reply-To",
290                                "Sender", "X-ML-Name", "X-List", "X-Sequence",
291                                "X-Mailer",
292                                NULL);
293
294         hdr_combo2 = gtk_combo_new ();
295         gtk_widget_show (hdr_combo2);
296         gtk_table_attach (GTK_TABLE (table1), hdr_combo2, 1, 2, 2, 3,
297                           0, 0, 0, 0);
298         gtk_widget_set_usize (hdr_combo2, 96, -1);
299         gtkut_combo_set_items (GTK_COMBO (hdr_combo2), _("(none)"),
300                                "Subject", "From", "To", "Cc", "Reply-To",
301                                "Sender", "X-ML-Name", "X-List", "X-Sequence",
302                                "X-Mailer",
303                                NULL);
304
305         key_label = gtk_label_new (_("Keyword"));
306         gtk_widget_show (key_label);
307         gtk_table_attach (GTK_TABLE (table1), key_label, 2, 3, 0, 1,
308                           GTK_EXPAND | GTK_SHRINK | GTK_FILL,
309                           0, 0, 0);
310         gtk_misc_set_alignment (GTK_MISC (key_label), 0, 0.5);
311
312         key_entry1 = gtk_entry_new ();
313         gtk_widget_show (key_entry1);
314         gtk_widget_set_usize (key_entry1, 128, -1);
315         gtk_table_attach (GTK_TABLE (table1), key_entry1, 2, 3, 1, 2,
316                           GTK_EXPAND | GTK_SHRINK | GTK_FILL,
317                           0, 0, 0);
318
319         key_entry2 = gtk_entry_new ();
320         gtk_widget_show (key_entry2);
321         gtk_widget_set_usize (key_entry2, 128, -1);
322         gtk_table_attach (GTK_TABLE (table1), key_entry2, 2, 3, 2, 3,
323                           GTK_EXPAND | GTK_SHRINK | GTK_FILL,
324                           0, 0, 0);
325
326         pred_label = gtk_label_new (_("Predicate"));
327         gtk_widget_show (pred_label);
328         gtk_table_attach (GTK_TABLE (table1), pred_label, 3, 4, 0, 1,
329                           GTK_FILL, 0, 0, 0);
330         gtk_misc_set_alignment (GTK_MISC (pred_label), 0, 0.5);
331
332         pred_combo1 = gtk_combo_new ();
333         gtk_widget_show (pred_combo1);
334         gtk_table_attach (GTK_TABLE (table1), pred_combo1, 3, 4, 1, 2,
335                           0, 0, 0, 0);
336         gtk_widget_set_usize (pred_combo1, 92, -1);
337         gtkut_combo_set_items (GTK_COMBO (pred_combo1),
338                                _("contains"), _("not contain"), NULL);
339
340         pred_entry1 = GTK_COMBO (pred_combo1)->entry;
341         gtk_entry_set_editable (GTK_ENTRY (pred_entry1), FALSE);
342
343         pred_combo2 = gtk_combo_new ();
344         gtk_widget_show (pred_combo2);
345         gtk_table_attach (GTK_TABLE (table1), pred_combo2, 3, 4, 2, 3,
346                           0, 0, 0, 0);
347         gtk_widget_set_usize (pred_combo2, 92, -1);
348         gtkut_combo_set_items (GTK_COMBO (pred_combo2),
349                                _("contains"), _("not contain"), NULL);
350
351         pred_entry2 = GTK_COMBO (pred_combo2)->entry;
352         gtk_entry_set_editable (GTK_ENTRY (pred_entry2), FALSE);
353         */
354
355         /* destination */
356
357         /*
358         vbox2 = gtk_vbox_new (FALSE, VSPACING_NARROW);
359         gtk_widget_show (vbox2);
360         gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0);
361
362         dest_hbox = gtk_hbox_new (FALSE, 8);
363         gtk_widget_show (dest_hbox);
364         gtk_box_pack_start (GTK_BOX (vbox2), dest_hbox, FALSE, TRUE, 0);
365
366         dest_radiobtn =
367                 gtk_radio_button_new_with_label (recv_group, _("Destination"));
368         recv_group = gtk_radio_button_group (GTK_RADIO_BUTTON (dest_radiobtn));
369         gtk_widget_show (dest_radiobtn);
370         gtk_box_pack_start (GTK_BOX (dest_hbox), dest_radiobtn,
371                             FALSE, FALSE, 0);
372         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dest_radiobtn), TRUE);
373         gtk_signal_connect
374                 (GTK_OBJECT (dest_radiobtn), "toggled",
375                  GTK_SIGNAL_FUNC (prefs_headers_dest_radio_button_toggled),
376                  NULL);
377
378         dest_entry = gtk_entry_new ();
379         gtk_widget_show (dest_entry);
380         gtk_widget_set_usize (dest_entry, DEFAULT_ENTRY_WIDTH, -1);
381         gtk_box_pack_start (GTK_BOX (dest_hbox), dest_entry, TRUE, TRUE, 0);
382         gtk_entry_set_editable (GTK_ENTRY (dest_entry), FALSE);
383
384         destsel_btn = gtk_button_new_with_label (_(" Select... "));
385         gtk_widget_show (destsel_btn);
386         gtk_box_pack_start (GTK_BOX (dest_hbox), destsel_btn, FALSE, FALSE, 0);
387         gtk_signal_connect (GTK_OBJECT (destsel_btn), "clicked",
388                             GTK_SIGNAL_FUNC (prefs_headers_select_dest_cb),
389                             NULL);
390
391         PACK_CHECK_BUTTON (dest_hbox, regex_chkbtn, _("Use regex"));
392         gtk_widget_set_sensitive(regex_chkbtn, FALSE);
393
394         notrecv_radiobtn = gtk_radio_button_new_with_label
395                 (recv_group, _("Don't receive"));
396         recv_group = gtk_radio_button_group
397                 (GTK_RADIO_BUTTON (notrecv_radiobtn));
398         gtk_widget_show (notrecv_radiobtn);
399         gtk_box_pack_start (GTK_BOX (vbox2), notrecv_radiobtn, FALSE, FALSE, 0);
400         gtk_signal_connect
401                 (GTK_OBJECT (notrecv_radiobtn), "toggled",
402                  GTK_SIGNAL_FUNC (prefs_headers_notrecv_radio_button_toggled),
403                  NULL);
404         */
405
406         /* register / substitute / delete */
407
408         /*
409         reg_hbox = gtk_hbox_new (FALSE, 4);
410         gtk_widget_show (reg_hbox);
411         gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
412
413         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
414         gtk_widget_show (arrow);
415         gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
416         gtk_widget_set_usize (arrow, -1, 16);
417
418         btn_hbox = gtk_hbox_new (TRUE, 4);
419         gtk_widget_show (btn_hbox);
420         gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
421
422         reg_btn = gtk_button_new_with_label (_("Register"));
423         gtk_widget_show (reg_btn);
424         gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
425         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
426                             GTK_SIGNAL_FUNC (prefs_headers_register_cb), NULL);
427
428         subst_btn = gtk_button_new_with_label (_(" Substitute "));
429         gtk_widget_show (subst_btn);
430         gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
431         gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
432                             GTK_SIGNAL_FUNC (prefs_headers_substitute_cb),
433                             NULL);
434
435         del_btn = gtk_button_new_with_label (_("Delete"));
436         gtk_widget_show (del_btn);
437         gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
438         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
439                             GTK_SIGNAL_FUNC (prefs_headers_delete_cb), NULL);
440
441         cond_hbox = gtk_hbox_new (FALSE, 8);
442         gtk_widget_show (cond_hbox);
443         gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
444
445         cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
446         gtk_widget_show (cond_scrolledwin);
447         gtk_widget_set_usize (cond_scrolledwin, -1, 150);
448         gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
449                             TRUE, TRUE, 0);
450         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
451                                         GTK_POLICY_AUTOMATIC,
452                                         GTK_POLICY_AUTOMATIC);
453
454         cond_clist = gtk_clist_new_with_titles(1, title);
455         gtk_widget_show (cond_clist);
456         gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
457         gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
458         gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
459                                       GTK_SELECTION_BROWSE);
460         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
461                                 GTK_CAN_FOCUS);
462         gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
463                             GTK_SIGNAL_FUNC (prefs_headers_select), NULL);
464
465         btn_vbox = gtk_vbox_new (FALSE, 8);
466         gtk_widget_show (btn_vbox);
467         gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
468
469         up_btn = gtk_button_new_with_label (_("Up"));
470         gtk_widget_show (up_btn);
471         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
472         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
473                             GTK_SIGNAL_FUNC (prefs_headers_up), NULL);
474
475         down_btn = gtk_button_new_with_label (_("Down"));
476         gtk_widget_show (down_btn);
477         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
478         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
479                             GTK_SIGNAL_FUNC (prefs_headers_down), NULL);
480         */
481
482         hdr_label = gtk_label_new (_("Header"));
483         gtk_widget_show (hdr_label);
484         gtk_table_attach (GTK_TABLE (table1), hdr_label, 0, 1, 0, 1,
485                           GTK_EXPAND | GTK_SHRINK | GTK_FILL,
486                           0, 0, 0);
487         gtk_misc_set_alignment (GTK_MISC (hdr_label), 0, 0.5);
488         
489         hdr_combo = gtk_combo_new ();
490         gtk_widget_show (hdr_combo);
491         gtk_table_attach (GTK_TABLE (table1), hdr_combo, 0, 1, 1, 2,
492                           GTK_EXPAND | GTK_SHRINK | GTK_FILL,
493                           0, 0, 0);
494         gtk_widget_set_usize (hdr_combo, 150 /* 96 */, -1);
495         gtkut_combo_set_items (GTK_COMBO (hdr_combo),
496                                "User-Agent", "X-Operating-System", NULL);
497
498         key_label = gtk_label_new (_("Value"));
499         gtk_widget_show (key_label);
500         gtk_table_attach (GTK_TABLE (table1), key_label, 1, 2, 0, 1,
501                           GTK_EXPAND | GTK_SHRINK | GTK_FILL,
502                           0, 0, 0);
503         gtk_misc_set_alignment (GTK_MISC (key_label), 0, 0.5);
504         
505         key_entry = gtk_entry_new ();
506         gtk_widget_show (key_entry);
507         gtk_table_attach (GTK_TABLE (table1), key_entry, 1, 2, 1, 2,
508                           GTK_EXPAND | GTK_SHRINK | GTK_FILL,
509                           0, 0, 0);
510
511         /* register / substitute / delete */
512
513         reg_hbox = gtk_hbox_new (FALSE, 4);
514         gtk_widget_show (reg_hbox);
515         gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox,
516                             FALSE, FALSE, 0);
517
518         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
519         gtk_widget_show (arrow);
520         gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
521         gtk_widget_set_usize (arrow, -1, 16);
522
523         btn_hbox = gtk_hbox_new (TRUE, 4);
524         gtk_widget_show (btn_hbox);
525         gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
526
527         reg_btn = gtk_button_new_with_label (_("Add"));
528         gtk_widget_show (reg_btn);
529         gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
530         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
531                             GTK_SIGNAL_FUNC (prefs_headers_register_cb), NULL);
532
533         subst_btn = gtk_button_new_with_label (_(" Substitute "));
534         gtk_widget_show (subst_btn);
535         gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
536         gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
537                             GTK_SIGNAL_FUNC (prefs_headers_substitute_cb),
538                             NULL);
539
540         del_btn = gtk_button_new_with_label (_("Delete"));
541         gtk_widget_show (del_btn);
542         gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
543         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
544                             GTK_SIGNAL_FUNC (prefs_headers_delete_cb), NULL);
545
546
547         ch_hbox = gtk_hbox_new (FALSE, 8);
548         gtk_widget_show (ch_hbox);
549         gtk_box_pack_start (GTK_BOX (vbox1), ch_hbox,
550                             TRUE, TRUE, 0);
551
552         ch_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
553         gtk_widget_set_usize (ch_scrolledwin, -1, 100);
554         gtk_widget_show (ch_scrolledwin);
555         gtk_box_pack_start (GTK_BOX (ch_hbox), ch_scrolledwin,
556                             TRUE, TRUE, 0);
557         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ch_scrolledwin),
558                                         GTK_POLICY_AUTOMATIC,
559                                         GTK_POLICY_AUTOMATIC);
560
561         headers_clist = gtk_clist_new_with_titles(1, title);
562         gtk_widget_show (headers_clist);
563         gtk_container_add (GTK_CONTAINER (ch_scrolledwin), headers_clist);
564         gtk_clist_set_column_width (GTK_CLIST (headers_clist), 0, 80);
565         gtk_clist_set_selection_mode (GTK_CLIST (headers_clist),
566                                       GTK_SELECTION_BROWSE);
567         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (headers_clist)->column[0].button,
568                                 GTK_CAN_FOCUS);
569         gtk_signal_connect (GTK_OBJECT (headers_clist), "select_row",
570                             GTK_SIGNAL_FUNC (prefs_headers_select),
571                             NULL);
572
573
574         btn_vbox = gtk_vbox_new (FALSE, 8);
575         gtk_widget_show (btn_vbox);
576         gtk_box_pack_start (GTK_BOX (ch_hbox), btn_vbox, FALSE, FALSE, 0);
577
578         up_btn = gtk_button_new_with_label (_("Up"));
579         gtk_widget_show (up_btn);
580         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
581         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
582                             GTK_SIGNAL_FUNC (prefs_headers_up), NULL);
583
584         down_btn = gtk_button_new_with_label (_("Down"));
585         gtk_widget_show (down_btn);
586         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
587         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
588                             GTK_SIGNAL_FUNC (prefs_headers_down), NULL);
589
590
591         gtk_widget_show_all(window);
592
593         headers.window    = window;
594         headers.close_btn = close_btn;
595
596         headers.hdr_combo  = hdr_combo;
597         headers.hdr_entry  = GTK_COMBO (hdr_combo)->entry;
598         headers.key_entry  = key_entry;
599         headers.headers_clist   = headers_clist;
600
601         /*
602         headers.hdr_combo1  = hdr_combo1;
603         headers.hdr_combo2  = hdr_combo2;
604         headers.hdr_entry1  = GTK_COMBO (hdr_combo1)->entry;
605         headers.hdr_entry2  = GTK_COMBO (hdr_combo2)->entry;
606         headers.key_entry1  = key_entry1;
607         headers.key_entry2  = key_entry2;
608         headers.pred_combo1 = pred_combo1;
609         headers.pred_combo2 = pred_combo2;
610         headers.pred_entry1 = pred_entry1;
611         headers.pred_entry2 = pred_entry2;
612         headers.op_combo    = op_combo;
613         headers.op_entry    = op_entry;
614
615         headers.dest_entry      = dest_entry;
616         headers.destsel_btn     = destsel_btn;
617         headers.dest_radiobtn   = dest_radiobtn;
618         headers.notrecv_radiobtn        = notrecv_radiobtn;
619         headers.regex_chkbtn     = regex_chkbtn;
620
621         headers.headers_clist   = headers_clist;
622         */
623 }
624
625 void prefs_headers_read_config(PrefsAccount * ac)
626 {
627         gchar *rcpath;
628         FILE *fp;
629         gchar buf[PREFSBUFSIZE];
630         CustomHeader *ch;
631
632         debug_print(_("Reading headers configuration...\n"));
633
634         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, HEADERS_RC, NULL);
635         if ((fp = fopen(rcpath, "r")) == NULL) {
636                 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
637                 g_free(rcpath);
638                 ac->customhdr_list = NULL;
639                 return;
640         }
641         g_free(rcpath);
642
643         /* remove all previous headers list */
644         while (ac->customhdr_list != NULL) {
645                 ch = (CustomHeader *)ac->customhdr_list->data;
646                 custom_header_free(ch);
647                 ac->customhdr_list = g_slist_remove(ac->customhdr_list, ch);
648         }
649  
650         while (fgets(buf, sizeof(buf), fp) != NULL) {
651                 g_strchomp(buf);
652                 ch = custom_header_read_str(buf);
653                 if (ch) {
654                         if (strcmp(ch->account_name, ac->account_name) == 0)
655                                 ac->customhdr_list =
656                                         g_slist_append(ac->customhdr_list, ch);
657                         else
658                                 custom_header_free(ch);
659                 }
660         }
661  
662         fclose(fp);
663 }
664
665 void prefs_headers_write_config(PrefsAccount * ac)
666 {
667         gchar *rcpath;
668         PrefFile *pfile;
669         GSList *cur;
670         gchar buf[PREFSBUFSIZE];
671         FILE * fp;
672         CustomHeader *ch;
673
674         GSList *all_hdrs = NULL;
675
676         debug_print(_("Writing headers configuration...\n"));
677
678         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, HEADERS_RC, NULL);
679
680         if ((fp = fopen(rcpath, "r")) == NULL) {
681                 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
682         }
683         else {
684                 all_hdrs = NULL;
685
686                 while (fgets(buf, sizeof(buf), fp) != NULL) {
687                         g_strchomp(buf);
688                         ch = custom_header_read_str(buf);
689                         if (ch) {
690                                 if (strcmp(ch->account_name, ac->account_name) != 0)
691                                         all_hdrs =
692                                                 g_slist_append(all_hdrs, ch);
693                                 else
694                                         custom_header_free(ch);
695                         }
696                 }
697
698                 fclose(fp);
699         }
700
701         if ((pfile = prefs_write_open(rcpath)) == NULL) {
702                 g_warning(_("failed to write configuration to file\n"));
703                 g_free(rcpath);
704                 return;
705         }
706
707         for (cur = all_hdrs; cur != NULL; cur = cur->next) {
708                 CustomHeader *hdr = (CustomHeader *)cur->data;
709                 gchar *chstr;
710
711                 chstr = custom_header_get_str(hdr);
712                 if (fputs(chstr, pfile->fp) == EOF ||
713                     fputc('\n', pfile->fp) == EOF) {
714                         FILE_OP_ERROR(rcpath, "fputs || fputc");
715                         prefs_write_close_revert(pfile);
716                         g_free(rcpath);
717                         g_free(chstr);
718                         return;
719                 }
720                 g_free(chstr);
721         }
722
723         for (cur = ac->customhdr_list; cur != NULL; cur = cur->next) {
724                 CustomHeader *hdr = (CustomHeader *)cur->data;
725                 gchar *chstr;
726
727                 chstr = custom_header_get_str(hdr);
728                 if (fputs(chstr, pfile->fp) == EOF ||
729                     fputc('\n', pfile->fp) == EOF) {
730                         FILE_OP_ERROR(rcpath, "fputs || fputc");
731                         prefs_write_close_revert(pfile);
732                         g_free(rcpath);
733                         g_free(chstr);
734                         return;
735                 }
736                 g_free(chstr);
737         }
738
739         g_free(rcpath);
740
741         while (all_hdrs != NULL) {
742                 ch = (CustomHeader *)all_hdrs->data;
743                 custom_header_free(ch);
744                 all_hdrs = g_slist_remove(all_hdrs, ch);
745         }
746
747         if (prefs_write_close(pfile) < 0) {
748                 g_warning(_("failed to write configuration to file\n"));
749                 return;
750         }
751 }
752
753 static void prefs_headers_set_dialog(PrefsAccount * ac)
754 {
755         GtkCList *clist = GTK_CLIST(headers.headers_clist);
756         GSList *cur;
757         gchar *ch_str[1];
758         gint row;
759
760         gtk_clist_freeze(clist);
761         gtk_clist_clear(clist);
762
763         ch_str[0] = _("(New)");
764         row = gtk_clist_append(clist, ch_str);
765         gtk_clist_set_row_data(clist, row, NULL);
766
767         for (cur = ac->customhdr_list; cur != NULL; cur = cur->next) {
768                 CustomHeader *ch = (CustomHeader *)cur->data;
769
770                 ch_str[0] = g_strdup_printf("%s: %s", ch->name, ch->value);
771                 row = gtk_clist_append(clist, ch_str);
772                 gtk_clist_set_row_data(clist, row, ch);
773
774                 g_free(ch_str[0]);
775         }
776
777         gtk_clist_thaw(clist);
778 }
779
780 static void prefs_headers_set_list(PrefsAccount * ac)
781 {
782         gint row = 1;
783         CustomHeader *ch;
784
785         g_slist_free(ac->customhdr_list);
786         ac->customhdr_list = NULL;
787
788         while ((ch = gtk_clist_get_row_data(GTK_CLIST(headers.headers_clist),
789                 row)) != NULL) {
790                 ac->customhdr_list = g_slist_append(ac->customhdr_list,
791                                                       ch);
792                 row++;
793         }
794 }
795
796 #define GET_ENTRY(entry) \
797         entry_text = gtk_entry_get_text(GTK_ENTRY(entry))
798
799 static gint prefs_headers_clist_set_row(PrefsAccount * ac, gint row)
800 {
801         GtkCList *clist = GTK_CLIST(headers.headers_clist);
802         CustomHeader *ch;
803         gchar *entry_text;
804         gchar *ch_str[1];
805
806         g_return_val_if_fail(row != 0, -1);
807
808         GET_ENTRY(headers.hdr_entry);
809         if (entry_text[0] == '\0') {
810                 alertpanel_error(_("Header name is not set."));
811                 return -1;
812         }
813
814         ch = g_new0(CustomHeader, 1);
815
816         ch->account_name = g_strdup(ac->account_name);
817
818         ch->name = g_strdup(entry_text);
819
820         GET_ENTRY(headers.key_entry);
821         if (entry_text[0] != '\0')
822                 ch->value = g_strdup(entry_text);
823
824         ch_str[0] = g_strdup_printf("%s: %s", ch->name, ch->value);
825
826         if (row < 0)
827                 row = gtk_clist_append(clist, ch_str);
828         else {
829                 CustomHeader *tmpch;
830
831                 gtk_clist_set_text(clist, row, 0, ch_str[0]);
832                 tmpch = gtk_clist_get_row_data(clist, row);
833                 if (tmpch)
834                         custom_header_free(tmpch);
835         }
836
837         gtk_clist_set_row_data(clist, row, ch);
838
839         g_free(ch_str[0]);
840
841         prefs_headers_set_list(cur_ac);
842
843         return row;
844 }
845
846 static void prefs_headers_register_cb(void)
847 {
848         prefs_headers_clist_set_row(cur_ac, -1);
849 }
850
851 static void prefs_headers_substitute_cb(void)
852 {
853         GtkCList *clist = GTK_CLIST(headers.headers_clist);
854         CustomHeader *ch;
855         gint row;
856
857         if (!clist->selection) return;
858
859         row = GPOINTER_TO_INT(clist->selection->data);
860         if (row == 0) return;
861
862         ch = gtk_clist_get_row_data(clist, row);
863         if (!ch) return;
864
865         prefs_headers_clist_set_row(cur_ac, row);
866 }
867
868 static void prefs_headers_delete_cb(void)
869 {
870         GtkCList *clist = GTK_CLIST(headers.headers_clist);
871         CustomHeader *ch;
872         gint row;
873
874         if (!clist->selection) return;
875         row = GPOINTER_TO_INT(clist->selection->data);
876         if (row == 0) return;
877
878         if (alertpanel(_("Delete header"),
879                        _("Do you really want to delete this header?"),
880                        _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
881                 return;
882
883         ch = gtk_clist_get_row_data(clist, row);
884         custom_header_free(ch);
885         gtk_clist_remove(clist, row);
886         cur_ac->customhdr_list = g_slist_remove(cur_ac->customhdr_list, ch);
887 }
888
889 static void prefs_headers_up(void)
890 {
891         GtkCList *clist = GTK_CLIST(headers.headers_clist);
892         gint row;
893
894         if (!clist->selection) return;
895
896         row = GPOINTER_TO_INT(clist->selection->data);
897         if (row > 1) {
898                 gtk_clist_row_move(clist, row, row - 1);
899                 prefs_headers_set_list(cur_ac);
900         }
901 }
902
903 static void prefs_headers_down(void)
904 {
905         GtkCList *clist = GTK_CLIST(headers.headers_clist);
906         gint row;
907
908         if (!clist->selection) return;
909
910         row = GPOINTER_TO_INT(clist->selection->data);
911         if (row > 0 && row < clist->rows - 1) {
912                 gtk_clist_row_move(clist, row, row + 1);
913                 prefs_headers_set_list(cur_ac);
914         }
915 }
916
917 #define ENTRY_SET_TEXT(entry, str) \
918         gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
919
920 static void prefs_headers_select(GtkCList *clist, gint row, gint column,
921                                 GdkEvent *event)
922 {
923         CustomHeader *ch;
924         CustomHeader default_ch = { "", NULL };
925  
926         ch = gtk_clist_get_row_data(clist, row);
927         if (!ch)
928                 ch = &default_ch;
929  
930         ENTRY_SET_TEXT(headers.hdr_entry, ch->name);
931         ENTRY_SET_TEXT(headers.key_entry, ch->value);
932 }
933
934 static void prefs_headers_key_pressed(GtkWidget *widget, GdkEventKey *event,
935                                      gpointer data)
936 {
937         if (event && event->keyval == GDK_Escape)
938                 gtk_widget_hide(headers.window);
939 }
940
941 static void prefs_headers_close(GtkButton *button)
942 {
943         prefs_headers_write_config(cur_ac);
944         gtk_widget_hide(headers.window);
945 }