2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 Hiroyuki Yamamoto
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.
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.
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.
28 #include <gdk/gdkkeysyms.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 "customheader.h"
46 #include "alertpanel.h"
49 static struct Headers {
57 GtkWidget *headers_clist;
61 parameter name, default value, pointer to the prefs variable, data type,
62 pointer to the widget pointer,
63 pointer to the function for data setting,
64 pointer to the function for widget setting
68 #define VSPACING_NARROW 4
69 #define DEFAULT_ENTRY_WIDTH 80
70 #define PREFSBUFSIZE 1024
72 /* widget creating functions */
73 static void prefs_headers_create (void);
75 static void prefs_headers_set_dialog (PrefsAccount * ac);
76 static void prefs_headers_set_list (PrefsAccount * ac);
77 static gint prefs_headers_clist_set_row (PrefsAccount * ac,
80 /* callback functions */
81 static void prefs_headers_select_dest_cb (void);
82 static void prefs_headers_register_cb (void);
83 static void prefs_headers_substitute_cb (void);
84 static void prefs_headers_delete_cb (void);
85 static void prefs_headers_up (void);
86 static void prefs_headers_down (void);
87 static void prefs_headers_select (GtkCList *clist,
92 static void prefs_headers_key_pressed (GtkWidget *widget,
95 static void prefs_headers_close (GtkButton *button);
97 static PrefsAccount * cur_ac = NULL;
99 void prefs_headers_open(PrefsAccount * ac)
101 if (!headers.window) {
102 prefs_headers_create();
105 manage_window_set_transient(GTK_WINDOW(headers.window));
106 gtk_widget_grab_focus(headers.close_btn);
108 prefs_headers_set_dialog(ac);
112 gtk_widget_show(headers.window);
115 static void prefs_headers_create(void)
119 GtkWidget *close_btn;
120 GtkWidget *confirm_area;
125 GtkWidget *hdr_label;
126 GtkWidget *hdr_combo;
127 GtkWidget *key_label;
128 GtkWidget *key_entry;
134 GtkWidget *subst_btn;
138 GtkWidget *ch_scrolledwin;
139 GtkWidget *headers_clist;
145 gchar *title[] = {_("Custom headers")};
147 debug_print(_("Creating headers setting window...\n"));
149 window = gtk_window_new (GTK_WINDOW_DIALOG);
150 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
151 gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
152 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
153 gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
155 vbox = gtk_vbox_new (FALSE, 6);
156 gtk_widget_show (vbox);
157 gtk_container_add (GTK_CONTAINER (window), vbox);
159 gtkut_button_set_create (&confirm_area, &close_btn, _("Close"),
160 NULL, NULL, NULL, NULL);
161 gtk_widget_show (confirm_area);
162 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
163 gtk_widget_grab_default (close_btn);
165 gtk_window_set_title (GTK_WINDOW(window),
166 _("Headers setting"));
167 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
168 GTK_SIGNAL_FUNC(gtk_widget_hide_on_delete), NULL);
169 gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
170 GTK_SIGNAL_FUNC(prefs_headers_key_pressed), NULL);
171 gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
172 GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
173 gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
174 GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
175 gtk_signal_connect (GTK_OBJECT(close_btn), "clicked",
176 GTK_SIGNAL_FUNC(prefs_headers_close), NULL);
178 vbox1 = gtk_vbox_new (FALSE, VSPACING);
179 gtk_widget_show (vbox1);
180 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
181 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
183 table1 = gtk_table_new (2, 2, FALSE);
184 gtk_widget_show (table1);
185 gtk_box_pack_start (GTK_BOX (vbox1), table1,
187 gtk_table_set_row_spacings (GTK_TABLE (table1), 8);
188 gtk_table_set_col_spacings (GTK_TABLE (table1), 8);
190 hdr_label = gtk_label_new (_("Header"));
191 gtk_widget_show (hdr_label);
192 gtk_table_attach (GTK_TABLE (table1), hdr_label, 0, 1, 0, 1,
193 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
195 gtk_misc_set_alignment (GTK_MISC (hdr_label), 0, 0.5);
197 hdr_combo = gtk_combo_new ();
198 gtk_widget_show (hdr_combo);
199 gtk_table_attach (GTK_TABLE (table1), hdr_combo, 0, 1, 1, 2,
200 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
202 gtk_widget_set_usize (hdr_combo, 150 /* 96 */, -1);
203 gtkut_combo_set_items (GTK_COMBO (hdr_combo),
204 "User-Agent", "X-Operating-System", NULL);
206 key_label = gtk_label_new (_("Value"));
207 gtk_widget_show (key_label);
208 gtk_table_attach (GTK_TABLE (table1), key_label, 1, 2, 0, 1,
209 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
211 gtk_misc_set_alignment (GTK_MISC (key_label), 0, 0.5);
213 key_entry = gtk_entry_new ();
214 gtk_widget_show (key_entry);
215 gtk_table_attach (GTK_TABLE (table1), key_entry, 1, 2, 1, 2,
216 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
219 /* register / substitute / delete */
221 reg_hbox = gtk_hbox_new (FALSE, 4);
222 gtk_widget_show (reg_hbox);
223 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox,
226 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
227 gtk_widget_show (arrow);
228 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
229 gtk_widget_set_usize (arrow, -1, 16);
231 btn_hbox = gtk_hbox_new (TRUE, 4);
232 gtk_widget_show (btn_hbox);
233 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
235 reg_btn = gtk_button_new_with_label (_("Add"));
236 gtk_widget_show (reg_btn);
237 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
238 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
239 GTK_SIGNAL_FUNC (prefs_headers_register_cb), NULL);
241 subst_btn = gtk_button_new_with_label (_(" Substitute "));
242 gtk_widget_show (subst_btn);
243 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
244 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
245 GTK_SIGNAL_FUNC (prefs_headers_substitute_cb),
248 del_btn = gtk_button_new_with_label (_("Delete"));
249 gtk_widget_show (del_btn);
250 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
251 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
252 GTK_SIGNAL_FUNC (prefs_headers_delete_cb), NULL);
255 ch_hbox = gtk_hbox_new (FALSE, 8);
256 gtk_widget_show (ch_hbox);
257 gtk_box_pack_start (GTK_BOX (vbox1), ch_hbox,
260 ch_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
261 gtk_widget_set_usize (ch_scrolledwin, -1, 100);
262 gtk_widget_show (ch_scrolledwin);
263 gtk_box_pack_start (GTK_BOX (ch_hbox), ch_scrolledwin,
265 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ch_scrolledwin),
266 GTK_POLICY_AUTOMATIC,
267 GTK_POLICY_AUTOMATIC);
269 headers_clist = gtk_clist_new_with_titles(1, title);
270 gtk_widget_show (headers_clist);
271 gtk_container_add (GTK_CONTAINER (ch_scrolledwin), headers_clist);
272 gtk_clist_set_column_width (GTK_CLIST (headers_clist), 0, 80);
273 gtk_clist_set_selection_mode (GTK_CLIST (headers_clist),
274 GTK_SELECTION_BROWSE);
275 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (headers_clist)->column[0].button,
277 gtk_signal_connect (GTK_OBJECT (headers_clist), "select_row",
278 GTK_SIGNAL_FUNC (prefs_headers_select),
282 btn_vbox = gtk_vbox_new (FALSE, 8);
283 gtk_widget_show (btn_vbox);
284 gtk_box_pack_start (GTK_BOX (ch_hbox), btn_vbox, FALSE, FALSE, 0);
286 up_btn = gtk_button_new_with_label (_("Up"));
287 gtk_widget_show (up_btn);
288 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
289 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
290 GTK_SIGNAL_FUNC (prefs_headers_up), NULL);
292 down_btn = gtk_button_new_with_label (_("Down"));
293 gtk_widget_show (down_btn);
294 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
295 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
296 GTK_SIGNAL_FUNC (prefs_headers_down), NULL);
299 gtk_widget_show_all(window);
301 headers.window = window;
302 headers.close_btn = close_btn;
304 headers.hdr_combo = hdr_combo;
305 headers.hdr_entry = GTK_COMBO (hdr_combo)->entry;
306 headers.key_entry = key_entry;
307 headers.headers_clist = headers_clist;
310 void prefs_headers_read_config(PrefsAccount * ac)
314 gchar buf[PREFSBUFSIZE];
317 debug_print(_("Reading headers configuration...\n"));
319 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, HEADERS_RC, NULL);
320 if ((fp = fopen(rcpath, "r")) == NULL) {
321 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
323 ac->customhdr_list = NULL;
328 /* remove all previous headers list */
329 while (ac->customhdr_list != NULL) {
330 ch = (CustomHeader *)ac->customhdr_list->data;
331 custom_header_free(ch);
332 ac->customhdr_list = g_slist_remove(ac->customhdr_list, ch);
335 while (fgets(buf, sizeof(buf), fp) != NULL) {
337 ch = custom_header_read_str(buf);
339 if (ch->account_id == ac->account_id)
341 g_slist_append(ac->customhdr_list, ch);
343 custom_header_free(ch);
350 void prefs_headers_write_config(PrefsAccount * ac)
355 gchar buf[PREFSBUFSIZE];
359 GSList *all_hdrs = NULL;
361 debug_print(_("Writing headers configuration...\n"));
363 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, HEADERS_RC, NULL);
365 if ((fp = fopen(rcpath, "r")) == NULL) {
366 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
371 while (fgets(buf, sizeof(buf), fp) != NULL) {
373 ch = custom_header_read_str(buf);
375 if (ch->account_id != ac->account_id)
377 g_slist_append(all_hdrs, ch);
379 custom_header_free(ch);
386 if ((pfile = prefs_write_open(rcpath)) == NULL) {
387 g_warning(_("failed to write configuration to file\n"));
392 for (cur = all_hdrs; cur != NULL; cur = cur->next) {
393 CustomHeader *hdr = (CustomHeader *)cur->data;
396 chstr = custom_header_get_str(hdr);
397 if (fputs(chstr, pfile->fp) == EOF ||
398 fputc('\n', pfile->fp) == EOF) {
399 FILE_OP_ERROR(rcpath, "fputs || fputc");
400 prefs_write_close_revert(pfile);
408 for (cur = ac->customhdr_list; cur != NULL; cur = cur->next) {
409 CustomHeader *hdr = (CustomHeader *)cur->data;
412 chstr = custom_header_get_str(hdr);
413 if (fputs(chstr, pfile->fp) == EOF ||
414 fputc('\n', pfile->fp) == EOF) {
415 FILE_OP_ERROR(rcpath, "fputs || fputc");
416 prefs_write_close_revert(pfile);
426 while (all_hdrs != NULL) {
427 ch = (CustomHeader *)all_hdrs->data;
428 custom_header_free(ch);
429 all_hdrs = g_slist_remove(all_hdrs, ch);
432 if (prefs_write_close(pfile) < 0) {
433 g_warning(_("failed to write configuration to file\n"));
438 static void prefs_headers_set_dialog(PrefsAccount * ac)
440 GtkCList *clist = GTK_CLIST(headers.headers_clist);
445 gtk_clist_freeze(clist);
446 gtk_clist_clear(clist);
448 ch_str[0] = _("(New)");
449 row = gtk_clist_append(clist, ch_str);
450 gtk_clist_set_row_data(clist, row, NULL);
452 for (cur = ac->customhdr_list; cur != NULL; cur = cur->next) {
453 CustomHeader *ch = (CustomHeader *)cur->data;
455 ch_str[0] = g_strdup_printf("%s: %s", ch->name, ch->value);
456 row = gtk_clist_append(clist, ch_str);
457 gtk_clist_set_row_data(clist, row, ch);
462 gtk_clist_thaw(clist);
465 static void prefs_headers_set_list(PrefsAccount * ac)
470 g_slist_free(ac->customhdr_list);
471 ac->customhdr_list = NULL;
473 while ((ch = gtk_clist_get_row_data(GTK_CLIST(headers.headers_clist),
475 ac->customhdr_list = g_slist_append(ac->customhdr_list,
481 #define GET_ENTRY(entry) \
482 entry_text = gtk_entry_get_text(GTK_ENTRY(entry))
484 static gint prefs_headers_clist_set_row(PrefsAccount * ac, gint row)
486 GtkCList *clist = GTK_CLIST(headers.headers_clist);
491 g_return_val_if_fail(row != 0, -1);
493 GET_ENTRY(headers.hdr_entry);
494 if (entry_text[0] == '\0') {
495 alertpanel_error(_("Header name is not set."));
499 ch = g_new0(CustomHeader, 1);
501 ch->account_id = ac->account_id;
503 ch->name = g_strdup(entry_text);
505 GET_ENTRY(headers.key_entry);
506 if (entry_text[0] != '\0')
507 ch->value = g_strdup(entry_text);
509 ch_str[0] = g_strdup_printf("%s: %s", ch->name, ch->value);
512 row = gtk_clist_append(clist, ch_str);
516 gtk_clist_set_text(clist, row, 0, ch_str[0]);
517 tmpch = gtk_clist_get_row_data(clist, row);
519 custom_header_free(tmpch);
522 gtk_clist_set_row_data(clist, row, ch);
526 prefs_headers_set_list(cur_ac);
531 static void prefs_headers_register_cb(void)
533 prefs_headers_clist_set_row(cur_ac, -1);
536 static void prefs_headers_substitute_cb(void)
538 GtkCList *clist = GTK_CLIST(headers.headers_clist);
542 if (!clist->selection) return;
544 row = GPOINTER_TO_INT(clist->selection->data);
545 if (row == 0) return;
547 ch = gtk_clist_get_row_data(clist, row);
550 prefs_headers_clist_set_row(cur_ac, row);
553 static void prefs_headers_delete_cb(void)
555 GtkCList *clist = GTK_CLIST(headers.headers_clist);
559 if (!clist->selection) return;
560 row = GPOINTER_TO_INT(clist->selection->data);
561 if (row == 0) return;
563 if (alertpanel(_("Delete header"),
564 _("Do you really want to delete this header?"),
565 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
568 ch = gtk_clist_get_row_data(clist, row);
569 custom_header_free(ch);
570 gtk_clist_remove(clist, row);
571 cur_ac->customhdr_list = g_slist_remove(cur_ac->customhdr_list, ch);
574 static void prefs_headers_up(void)
576 GtkCList *clist = GTK_CLIST(headers.headers_clist);
579 if (!clist->selection) return;
581 row = GPOINTER_TO_INT(clist->selection->data);
583 gtk_clist_row_move(clist, row, row - 1);
584 prefs_headers_set_list(cur_ac);
588 static void prefs_headers_down(void)
590 GtkCList *clist = GTK_CLIST(headers.headers_clist);
593 if (!clist->selection) return;
595 row = GPOINTER_TO_INT(clist->selection->data);
596 if (row > 0 && row < clist->rows - 1) {
597 gtk_clist_row_move(clist, row, row + 1);
598 prefs_headers_set_list(cur_ac);
602 #define ENTRY_SET_TEXT(entry, str) \
603 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
605 static void prefs_headers_select(GtkCList *clist, gint row, gint column,
609 CustomHeader default_ch = { 0, "", NULL };
611 ch = gtk_clist_get_row_data(clist, row);
615 ENTRY_SET_TEXT(headers.hdr_entry, ch->name);
616 ENTRY_SET_TEXT(headers.key_entry, ch->value);
619 static void prefs_headers_key_pressed(GtkWidget *widget, GdkEventKey *event,
622 if (event && event->keyval == GDK_Escape)
623 gtk_widget_hide(headers.window);
626 static void prefs_headers_close(GtkButton *button)
628 prefs_headers_write_config(cur_ac);
629 gtk_widget_hide(headers.window);