2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2002 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>
36 #include "prefs_gtk.h"
37 #include "prefs_customheader.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"
47 #include "alertpanel.h"
49 static struct CustomHdr
{
53 GtkWidget
*cancel_btn
;
58 GtkWidget
*customhdr_clist
;
61 /* widget creating functions */
62 static void prefs_custom_header_create (void);
64 static void prefs_custom_header_set_dialog (PrefsAccount
*ac
);
65 static void prefs_custom_header_set_list (PrefsAccount
*ac
);
66 static gint
prefs_custom_header_clist_set_row (PrefsAccount
*ac
,
69 /* callback functions */
70 static void prefs_custom_header_add_cb (void);
71 static void prefs_custom_header_delete_cb (void);
72 static void prefs_custom_header_up (void);
73 static void prefs_custom_header_down (void);
74 static void prefs_custom_header_select (GtkCList
*clist
,
79 static void prefs_custom_header_row_moved (GtkCList
*clist
,
84 static void prefs_custom_header_key_pressed (GtkWidget
*widget
,
87 static void prefs_custom_header_ok (void);
88 static void prefs_custom_header_cancel (void);
89 static gint
prefs_custom_header_deleted (GtkWidget
*widget
,
93 static PrefsAccount
*cur_ac
= NULL
;
95 void prefs_custom_header_open(PrefsAccount
*ac
)
97 if (!customhdr
.window
) {
98 prefs_custom_header_create();
101 manage_window_set_transient(GTK_WINDOW(customhdr
.window
));
102 gtk_widget_grab_focus(customhdr
.ok_btn
);
104 prefs_custom_header_set_dialog(ac
);
108 gtk_widget_show(customhdr
.window
);
111 static void prefs_custom_header_create(void)
117 GtkWidget
*cancel_btn
;
119 GtkWidget
*confirm_area
;
124 GtkWidget
*hdr_label
;
125 GtkWidget
*hdr_combo
;
126 GtkWidget
*val_label
;
127 GtkWidget
*val_entry
;
136 GtkWidget
*ch_scrolledwin
;
137 GtkWidget
*customhdr_clist
;
145 debug_print("Creating custom header setting window...\n");
147 window
= gtk_window_new (GTK_WINDOW_DIALOG
);
148 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
149 gtk_window_position (GTK_WINDOW (window
), GTK_WIN_POS_CENTER
);
150 gtk_window_set_modal (GTK_WINDOW (window
), TRUE
);
151 gtk_window_set_policy (GTK_WINDOW (window
), FALSE
, TRUE
, FALSE
);
153 vbox
= gtk_vbox_new (FALSE
, 6);
154 gtk_widget_show (vbox
);
155 gtk_container_add (GTK_CONTAINER (window
), vbox
);
157 gtkut_button_set_create(&confirm_area
, &ok_btn
, _("OK"),
158 &cancel_btn
, _("Cancel"), NULL
, NULL
);
159 gtk_widget_show (confirm_area
);
160 gtk_box_pack_end (GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 0);
161 gtk_widget_grab_default (ok_btn
);
163 gtk_window_set_title (GTK_WINDOW(window
), _("Custom header configuration"));
164 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
165 gtk_signal_connect (GTK_OBJECT(window
), "delete_event",
166 GTK_SIGNAL_FUNC(prefs_custom_header_deleted
),
168 gtk_signal_connect (GTK_OBJECT(window
), "key_press_event",
169 GTK_SIGNAL_FUNC(prefs_custom_header_key_pressed
),
171 gtk_signal_connect (GTK_OBJECT(ok_btn
), "clicked",
172 GTK_SIGNAL_FUNC(prefs_custom_header_ok
), NULL
);
173 gtk_signal_connect (GTK_OBJECT(cancel_btn
), "clicked",
174 GTK_SIGNAL_FUNC(prefs_custom_header_cancel
), NULL
);
176 vbox1
= gtk_vbox_new (FALSE
, VSPACING
);
177 gtk_widget_show (vbox1
);
178 gtk_box_pack_start (GTK_BOX (vbox
), vbox1
, TRUE
, TRUE
, 0);
179 gtk_container_set_border_width (GTK_CONTAINER (vbox1
), 2);
181 table1
= gtk_table_new (2, 2, FALSE
);
182 gtk_widget_show (table1
);
183 gtk_box_pack_start (GTK_BOX (vbox1
), table1
,
185 gtk_table_set_row_spacings (GTK_TABLE (table1
), 8);
186 gtk_table_set_col_spacings (GTK_TABLE (table1
), 8);
188 hdr_label
= gtk_label_new (_("Header"));
189 gtk_widget_show (hdr_label
);
190 gtk_table_attach (GTK_TABLE (table1
), hdr_label
, 0, 1, 0, 1,
191 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
193 gtk_misc_set_alignment (GTK_MISC (hdr_label
), 0, 0.5);
195 hdr_combo
= gtk_combo_new ();
196 gtk_widget_show (hdr_combo
);
197 gtk_table_attach (GTK_TABLE (table1
), hdr_combo
, 0, 1, 1, 2,
198 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
200 gtk_widget_set_usize (hdr_combo
, 150, -1);
201 gtkut_combo_set_items (GTK_COMBO (hdr_combo
),
202 "User-Agent", "X-Face", "X-Operating-System",
205 val_label
= gtk_label_new (_("Value"));
206 gtk_widget_show (val_label
);
207 gtk_table_attach (GTK_TABLE (table1
), val_label
, 1, 2, 0, 1,
208 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
210 gtk_misc_set_alignment (GTK_MISC (val_label
), 0, 0.5);
212 val_entry
= gtk_entry_new ();
213 gtk_widget_show (val_entry
);
214 gtk_table_attach (GTK_TABLE (table1
), val_entry
, 1, 2, 1, 2,
215 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
217 gtk_widget_set_usize (val_entry
, 200, -1);
221 reg_hbox
= gtk_hbox_new (FALSE
, 4);
222 gtk_widget_show (reg_hbox
);
223 gtk_box_pack_start (GTK_BOX (vbox1
), reg_hbox
, FALSE
, FALSE
, 0);
225 arrow
= gtk_arrow_new (GTK_ARROW_DOWN
, GTK_SHADOW_OUT
);
226 gtk_widget_show (arrow
);
227 gtk_box_pack_start (GTK_BOX (reg_hbox
), arrow
, FALSE
, FALSE
, 0);
228 gtk_widget_set_usize (arrow
, -1, 16);
230 btn_hbox
= gtk_hbox_new (TRUE
, 4);
231 gtk_widget_show (btn_hbox
);
232 gtk_box_pack_start (GTK_BOX (reg_hbox
), btn_hbox
, FALSE
, FALSE
, 0);
234 add_btn
= gtk_button_new_with_label (_("Add"));
235 gtk_widget_show (add_btn
);
236 gtk_box_pack_start (GTK_BOX (btn_hbox
), add_btn
, FALSE
, TRUE
, 0);
237 gtk_signal_connect (GTK_OBJECT (add_btn
), "clicked",
238 GTK_SIGNAL_FUNC (prefs_custom_header_add_cb
),
241 del_btn
= gtk_button_new_with_label (_(" Delete "));
242 gtk_widget_show (del_btn
);
243 gtk_box_pack_start (GTK_BOX (btn_hbox
), del_btn
, FALSE
, TRUE
, 0);
244 gtk_signal_connect (GTK_OBJECT (del_btn
), "clicked",
245 GTK_SIGNAL_FUNC (prefs_custom_header_delete_cb
),
249 ch_hbox
= gtk_hbox_new (FALSE
, 8);
250 gtk_widget_show (ch_hbox
);
251 gtk_box_pack_start (GTK_BOX (vbox1
), ch_hbox
, TRUE
, TRUE
, 0);
253 ch_scrolledwin
= gtk_scrolled_window_new (NULL
, NULL
);
254 gtk_widget_set_usize (ch_scrolledwin
, -1, 200);
255 gtk_widget_show (ch_scrolledwin
);
256 gtk_box_pack_start (GTK_BOX (ch_hbox
), ch_scrolledwin
, TRUE
, TRUE
, 0);
257 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ch_scrolledwin
),
258 GTK_POLICY_AUTOMATIC
,
259 GTK_POLICY_AUTOMATIC
);
261 title
[0] = _("Current custom headers");
262 customhdr_clist
= gtk_clist_new_with_titles(1, title
);
263 gtk_widget_show (customhdr_clist
);
264 gtk_container_add (GTK_CONTAINER (ch_scrolledwin
), customhdr_clist
);
265 gtk_clist_set_column_width (GTK_CLIST (customhdr_clist
), 0, 80);
266 gtk_clist_set_selection_mode (GTK_CLIST (customhdr_clist
),
267 GTK_SELECTION_BROWSE
);
268 gtk_clist_set_reorderable (GTK_CLIST (customhdr_clist
), TRUE
);
269 gtk_clist_set_use_drag_icons (GTK_CLIST (customhdr_clist
), FALSE
);
270 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (customhdr_clist
)->column
[0].button
,
272 gtk_signal_connect (GTK_OBJECT (customhdr_clist
), "select_row",
273 GTK_SIGNAL_FUNC (prefs_custom_header_select
),
275 gtk_signal_connect_after
276 (GTK_OBJECT (customhdr_clist
), "row_move",
277 GTK_SIGNAL_FUNC (prefs_custom_header_row_moved
), NULL
);
279 btn_vbox
= gtk_vbox_new (FALSE
, 8);
280 gtk_widget_show (btn_vbox
);
281 gtk_box_pack_start (GTK_BOX (ch_hbox
), btn_vbox
, FALSE
, FALSE
, 0);
283 up_btn
= gtk_button_new_with_label (_("Up"));
284 gtk_widget_show (up_btn
);
285 gtk_box_pack_start (GTK_BOX (btn_vbox
), up_btn
, FALSE
, FALSE
, 0);
286 gtk_signal_connect (GTK_OBJECT (up_btn
), "clicked",
287 GTK_SIGNAL_FUNC (prefs_custom_header_up
), NULL
);
289 down_btn
= gtk_button_new_with_label (_("Down"));
290 gtk_widget_show (down_btn
);
291 gtk_box_pack_start (GTK_BOX (btn_vbox
), down_btn
, FALSE
, FALSE
, 0);
292 gtk_signal_connect (GTK_OBJECT (down_btn
), "clicked",
293 GTK_SIGNAL_FUNC (prefs_custom_header_down
), NULL
);
295 gtk_widget_show_all(window
);
297 customhdr
.window
= window
;
298 customhdr
.ok_btn
= ok_btn
;
299 customhdr
.cancel_btn
= cancel_btn
;
301 customhdr
.hdr_combo
= hdr_combo
;
302 customhdr
.hdr_entry
= GTK_COMBO (hdr_combo
)->entry
;
303 customhdr
.val_entry
= val_entry
;
305 customhdr
.customhdr_clist
= customhdr_clist
;
308 void prefs_custom_header_read_config(PrefsAccount
*ac
)
312 gchar buf
[PREFSBUFSIZE
];
315 debug_print("Reading custom header configuration...\n");
317 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
318 CUSTOM_HEADER_RC
, NULL
);
319 if ((fp
= fopen(rcpath
, "rb")) == NULL
) {
320 if (ENOENT
!= errno
) FILE_OP_ERROR(rcpath
, "fopen");
322 ac
->customhdr_list
= NULL
;
327 /* remove all previous headers list */
328 while (ac
->customhdr_list
!= NULL
) {
329 ch
= (CustomHeader
*)ac
->customhdr_list
->data
;
330 custom_header_free(ch
);
331 ac
->customhdr_list
= g_slist_remove(ac
->customhdr_list
, ch
);
334 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
336 ch
= custom_header_read_str(buf
);
338 if (ch
->account_id
== ac
->account_id
) {
340 g_slist_append(ac
->customhdr_list
, ch
);
342 custom_header_free(ch
);
349 void prefs_custom_header_write_config(PrefsAccount
*ac
)
354 gchar buf
[PREFSBUFSIZE
];
358 GSList
*all_hdrs
= NULL
;
360 debug_print("Writing custom header configuration...\n");
362 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
363 CUSTOM_HEADER_RC
, NULL
);
365 if ((fp
= fopen(rcpath
, "rb")) == NULL
) {
366 if (ENOENT
!= errno
) FILE_OP_ERROR(rcpath
, "fopen");
370 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
372 ch
= custom_header_read_str(buf
);
374 if (ch
->account_id
!= ac
->account_id
)
376 g_slist_append(all_hdrs
, ch
);
378 custom_header_free(ch
);
385 if ((pfile
= prefs_write_open(rcpath
)) == NULL
) {
386 g_warning("failed to write configuration to file\n");
391 for (cur
= all_hdrs
; cur
!= NULL
; cur
= cur
->next
) {
392 CustomHeader
*hdr
= (CustomHeader
*)cur
->data
;
395 chstr
= custom_header_get_str(hdr
);
396 if (fputs(chstr
, pfile
->fp
) == EOF
||
397 fputc('\n', pfile
->fp
) == EOF
) {
398 FILE_OP_ERROR(rcpath
, "fputs || fputc");
399 prefs_write_close_revert(pfile
);
407 for (cur
= ac
->customhdr_list
; cur
!= NULL
; cur
= cur
->next
) {
408 CustomHeader
*hdr
= (CustomHeader
*)cur
->data
;
411 chstr
= custom_header_get_str(hdr
);
412 if (fputs(chstr
, pfile
->fp
) == EOF
||
413 fputc('\n', pfile
->fp
) == EOF
) {
414 FILE_OP_ERROR(rcpath
, "fputs || fputc");
415 prefs_write_close_revert(pfile
);
425 while (all_hdrs
!= NULL
) {
426 ch
= (CustomHeader
*)all_hdrs
->data
;
427 custom_header_free(ch
);
428 all_hdrs
= g_slist_remove(all_hdrs
, ch
);
431 if (prefs_write_close(pfile
) < 0) {
432 g_warning("failed to write configuration to file\n");
437 static void prefs_custom_header_set_dialog(PrefsAccount
*ac
)
439 GtkCList
*clist
= GTK_CLIST(customhdr
.customhdr_clist
);
444 gtk_clist_freeze(clist
);
445 gtk_clist_clear(clist
);
447 for (cur
= ac
->customhdr_list
; cur
!= NULL
; cur
= cur
->next
) {
448 CustomHeader
*ch
= (CustomHeader
*)cur
->data
;
450 ch_str
[0] = g_strdup_printf("%s: %s", ch
->name
,
451 ch
->value
? ch
->value
: "");
452 row
= gtk_clist_append(clist
, ch_str
);
453 gtk_clist_set_row_data(clist
, row
, ch
);
458 gtk_clist_thaw(clist
);
461 static void prefs_custom_header_set_list(PrefsAccount
*ac
)
466 g_slist_free(ac
->customhdr_list
);
467 ac
->customhdr_list
= NULL
;
469 while ((ch
= gtk_clist_get_row_data
470 (GTK_CLIST(customhdr
.customhdr_clist
), row
)) != NULL
) {
471 ac
->customhdr_list
= g_slist_append(ac
->customhdr_list
, ch
);
476 static gint
prefs_custom_header_clist_set_row(PrefsAccount
*ac
, gint row
)
478 GtkCList
*clist
= GTK_CLIST(customhdr
.customhdr_clist
);
483 entry_text
= gtk_entry_get_text(GTK_ENTRY(customhdr
.hdr_entry
));
484 if (entry_text
[0] == '\0') {
485 alertpanel_error(_("Header name is not set."));
489 ch
= g_new0(CustomHeader
, 1);
491 ch
->account_id
= ac
->account_id
;
493 ch
->name
= g_strdup(entry_text
);
494 unfold_line(ch
->name
);
496 entry_text
= gtk_entry_get_text(GTK_ENTRY(customhdr
.val_entry
));
497 if (entry_text
[0] != '\0') {
498 ch
->value
= g_strdup(entry_text
);
499 unfold_line(ch
->value
);
502 ch_str
[0] = g_strdup_printf("%s: %s", ch
->name
,
503 ch
->value
? ch
->value
: "");
506 row
= gtk_clist_append(clist
, ch_str
);
508 CustomHeader
*tmp_ch
;
510 gtk_clist_set_text(clist
, row
, 0, ch_str
[0]);
511 tmp_ch
= gtk_clist_get_row_data(clist
, row
);
513 custom_header_free(tmp_ch
);
516 gtk_clist_set_row_data(clist
, row
, ch
);
520 prefs_custom_header_set_list(cur_ac
);
525 static void prefs_custom_header_add_cb(void)
527 prefs_custom_header_clist_set_row(cur_ac
, -1);
530 static void prefs_custom_header_delete_cb(void)
532 GtkCList
*clist
= GTK_CLIST(customhdr
.customhdr_clist
);
536 if (!clist
->selection
) return;
537 row
= GPOINTER_TO_INT(clist
->selection
->data
);
539 if (alertpanel(_("Delete header"),
540 _("Do you really want to delete this header?"),
541 _("Yes"), _("No"), NULL
) != G_ALERTDEFAULT
)
544 ch
= gtk_clist_get_row_data(clist
, row
);
545 custom_header_free(ch
);
546 gtk_clist_remove(clist
, row
);
547 cur_ac
->customhdr_list
= g_slist_remove(cur_ac
->customhdr_list
, ch
);
550 static void prefs_custom_header_up(void)
552 GtkCList
*clist
= GTK_CLIST(customhdr
.customhdr_clist
);
555 if (!clist
->selection
) return;
557 row
= GPOINTER_TO_INT(clist
->selection
->data
);
559 gtk_clist_row_move(clist
, row
, row
- 1);
562 static void prefs_custom_header_down(void)
564 GtkCList
*clist
= GTK_CLIST(customhdr
.customhdr_clist
);
567 if (!clist
->selection
) return;
569 row
= GPOINTER_TO_INT(clist
->selection
->data
);
570 if (row
>= 0 && row
< clist
->rows
- 1)
571 gtk_clist_row_move(clist
, row
, row
+ 1);
574 #define ENTRY_SET_TEXT(entry, str) \
575 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
577 static void prefs_custom_header_select(GtkCList
*clist
, gint row
, gint column
,
581 CustomHeader default_ch
= { 0, "", NULL
};
583 ch
= gtk_clist_get_row_data(clist
, row
);
584 if (!ch
) ch
= &default_ch
;
586 ENTRY_SET_TEXT(customhdr
.hdr_entry
, ch
->name
);
587 ENTRY_SET_TEXT(customhdr
.val_entry
, ch
->value
);
590 #undef ENTRY_SET_TEXT
592 static void prefs_custom_header_row_moved(GtkCList
*clist
, gint source_row
,
593 gint dest_row
, gpointer data
)
595 prefs_custom_header_set_list(cur_ac
);
598 static void prefs_custom_header_key_pressed(GtkWidget
*widget
,
602 if (event
&& event
->keyval
== GDK_Escape
)
603 prefs_custom_header_cancel();
606 static void prefs_custom_header_ok(void)
608 prefs_custom_header_write_config(cur_ac
);
609 gtk_widget_hide(customhdr
.window
);
612 static void prefs_custom_header_cancel(void)
614 prefs_custom_header_read_config(cur_ac
);
615 gtk_widget_hide(customhdr
.window
);
618 static gint
prefs_custom_header_deleted(GtkWidget
*widget
, GdkEventAny
*event
,
621 prefs_custom_header_cancel();