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_display_headers.h"
38 #include "prefs_common.h"
39 #include "mainwindow.h"
40 #include "foldersel.h"
41 #include "manage_window.h"
44 #include "alertpanel.h"
46 #include "headers_display.h"
48 static struct Headers {
56 GtkWidget *headers_clist;
60 parameter name, default value, pointer to the prefs variable, data type,
61 pointer to the widget pointer,
62 pointer to the function for data setting,
63 pointer to the function for widget setting
67 #define VSPACING_NARROW 4
68 #define DEFAULT_ENTRY_WIDTH 80
69 #define PREFSBUFSIZE 1024
71 /* widget creating functions */
72 static void prefs_display_headers_create (void);
74 static void prefs_display_headers_set_dialog (void);
75 static void prefs_display_headers_set_list (void);
76 static gint prefs_display_headers_clist_set_row (gint row);
78 /* callback functions */
79 static void prefs_display_headers_select_dest_cb (void);
80 static void prefs_display_headers_register_cb (void);
81 static void prefs_display_headers_substitute_cb (void);
82 static void prefs_display_headers_delete_cb (void);
83 static void prefs_display_headers_up (void);
84 static void prefs_display_headers_down (void);
85 static void prefs_display_headers_select (GtkCList *clist,
90 static void prefs_display_headers_dest_radio_button_toggled (void);
91 static void prefs_display_headers_notrecv_radio_button_toggled (void);
93 static void prefs_display_headers_key_pressed (GtkWidget *widget,
96 static void prefs_display_headers_close (GtkButton *button);
98 GSList * prefs_display_headers = NULL;
100 static char * defaults[] =
115 "-Content-Transfer-Encoding",
122 static void prefs_display_headers_set_default(void)
126 for(i = 0 ; i < sizeof(defaults) / sizeof(char *) ; i++) {
127 HeaderDisplayProp * dp =
128 header_display_prop_read_str(defaults[i]);
129 prefs_display_headers =
130 g_slist_append(prefs_display_headers, dp);
134 void prefs_display_headers_open(void)
136 if (!headers.window) {
137 prefs_display_headers_create();
140 manage_window_set_transient(GTK_WINDOW(headers.window));
141 gtk_widget_grab_focus(headers.close_btn);
143 prefs_display_headers_set_dialog();
145 gtk_widget_show(headers.window);
148 static void prefs_display_headers_create(void)
152 GtkWidget *close_btn;
153 GtkWidget *confirm_area;
158 GtkWidget *hdr_label;
159 GtkWidget *hdr_combo;
160 GtkWidget *key_label;
161 GtkWidget *key_check;
167 GtkWidget *subst_btn;
171 GtkWidget *ch_scrolledwin;
172 GtkWidget *headers_clist;
178 gchar *title[] = {_("Order of headers"), _("Action")};
180 debug_print(_("Creating headers setting window...\n"));
182 window = gtk_window_new (GTK_WINDOW_DIALOG);
183 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
184 gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
185 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
186 gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
188 vbox = gtk_vbox_new (FALSE, 6);
189 gtk_widget_show (vbox);
190 gtk_container_add (GTK_CONTAINER (window), vbox);
192 gtkut_button_set_create (&confirm_area, &close_btn, _("Close"),
193 NULL, NULL, NULL, NULL);
194 gtk_widget_show (confirm_area);
195 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
196 gtk_widget_grab_default (close_btn);
198 gtk_window_set_title (GTK_WINDOW(window),
199 _("Headers setting"));
200 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
201 GTK_SIGNAL_FUNC(gtk_widget_hide_on_delete), NULL);
202 gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
203 GTK_SIGNAL_FUNC(prefs_display_headers_key_pressed),
205 gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
206 GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
207 gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
208 GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
209 gtk_signal_connect (GTK_OBJECT(close_btn), "clicked",
210 GTK_SIGNAL_FUNC(prefs_display_headers_close),
213 vbox1 = gtk_vbox_new (FALSE, VSPACING);
214 gtk_widget_show (vbox1);
215 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
216 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
218 table1 = gtk_table_new (2, 2, FALSE);
219 gtk_widget_show (table1);
220 gtk_box_pack_start (GTK_BOX (vbox1), table1,
222 gtk_table_set_row_spacings (GTK_TABLE (table1), 8);
223 gtk_table_set_col_spacings (GTK_TABLE (table1), 8);
225 hdr_label = gtk_label_new (_("Header"));
226 gtk_widget_show (hdr_label);
227 gtk_table_attach (GTK_TABLE (table1), hdr_label, 0, 1, 0, 1,
228 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
230 gtk_misc_set_alignment (GTK_MISC (hdr_label), 0, 0.5);
232 hdr_combo = gtk_combo_new ();
233 gtk_widget_show (hdr_combo);
234 gtk_table_attach (GTK_TABLE (table1), hdr_combo, 0, 1, 1, 2,
235 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
237 gtk_widget_set_usize (hdr_combo, 150 /* 96 */, -1);
238 gtkut_combo_set_items (GTK_COMBO (hdr_combo),
239 "From", "To", "Subject", "Date", NULL);
241 key_label = gtk_label_new (_("Order (or Hide)"));
242 gtk_widget_show (key_label);
243 gtk_table_attach (GTK_TABLE (table1), key_label, 1, 2, 0, 1,
244 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
246 gtk_misc_set_alignment (GTK_MISC (key_label), 0, 0.5);
248 // key_entry = gtk_entry_new ();
249 key_check = gtk_check_button_new();
250 gtk_widget_show (key_check);
251 gtk_table_attach (GTK_TABLE (table1), key_check, 1, 2, 1, 2,
252 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
254 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(key_check), 1);
256 /* register / substitute / delete */
258 reg_hbox = gtk_hbox_new (FALSE, 4);
259 gtk_widget_show (reg_hbox);
260 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox,
263 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
264 gtk_widget_show (arrow);
265 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
266 gtk_widget_set_usize (arrow, -1, 16);
268 btn_hbox = gtk_hbox_new (TRUE, 4);
269 gtk_widget_show (btn_hbox);
270 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
272 reg_btn = gtk_button_new_with_label (_("Add"));
273 gtk_widget_show (reg_btn);
274 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
275 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
277 (prefs_display_headers_register_cb), NULL);
279 subst_btn = gtk_button_new_with_label (_(" Substitute "));
280 gtk_widget_show (subst_btn);
281 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
282 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
284 (prefs_display_headers_substitute_cb),
287 del_btn = gtk_button_new_with_label (_("Delete"));
288 gtk_widget_show (del_btn);
289 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
290 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
291 GTK_SIGNAL_FUNC (prefs_display_headers_delete_cb),
295 ch_hbox = gtk_hbox_new (FALSE, 8);
296 gtk_widget_show (ch_hbox);
297 gtk_box_pack_start (GTK_BOX (vbox1), ch_hbox,
300 ch_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
301 gtk_widget_set_usize (ch_scrolledwin, 230, 200);
302 gtk_widget_show (ch_scrolledwin);
303 gtk_box_pack_start (GTK_BOX (ch_hbox), ch_scrolledwin,
305 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ch_scrolledwin),
306 GTK_POLICY_AUTOMATIC,
307 GTK_POLICY_AUTOMATIC);
309 headers_clist = gtk_clist_new_with_titles(2, title);
310 gtk_widget_show (headers_clist);
311 gtk_container_add (GTK_CONTAINER (ch_scrolledwin), headers_clist);
312 gtk_clist_set_column_width (GTK_CLIST (headers_clist), 0, 150);
313 gtk_clist_set_column_width (GTK_CLIST (headers_clist), 1, 50);
314 gtk_clist_set_selection_mode (GTK_CLIST (headers_clist),
315 GTK_SELECTION_BROWSE);
316 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (headers_clist)->column[0].button,
318 gtk_signal_connect (GTK_OBJECT (headers_clist), "select_row",
319 GTK_SIGNAL_FUNC (prefs_display_headers_select),
323 btn_vbox = gtk_vbox_new (FALSE, 8);
324 gtk_widget_show (btn_vbox);
325 gtk_box_pack_start (GTK_BOX (ch_hbox), btn_vbox, FALSE, FALSE, 0);
327 up_btn = gtk_button_new_with_label (_("Up"));
328 gtk_widget_show (up_btn);
329 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
330 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
331 GTK_SIGNAL_FUNC (prefs_display_headers_up), NULL);
333 down_btn = gtk_button_new_with_label (_("Down"));
334 gtk_widget_show (down_btn);
335 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
336 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
337 GTK_SIGNAL_FUNC (prefs_display_headers_down), NULL);
340 gtk_widget_show_all(window);
342 headers.window = window;
343 headers.close_btn = close_btn;
345 headers.hdr_combo = hdr_combo;
346 headers.hdr_entry = GTK_COMBO (hdr_combo)->entry;
347 headers.key_check = key_check;
348 headers.headers_clist = headers_clist;
351 void prefs_display_headers_read_config(void)
355 gchar buf[PREFSBUFSIZE];
356 HeaderDisplayProp *dp;
358 debug_print(_("Reading configuration for displaying of headers...\n"));
360 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
361 HEADERS_DISPLAY_RC, NULL);
362 if ((fp = fopen(rcpath, "r")) == NULL) {
363 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
365 prefs_display_headers = NULL;
366 prefs_display_headers_set_default();
371 /* remove all previous headers list */
372 while (prefs_display_headers != NULL) {
373 dp = (HeaderDisplayProp *)prefs_display_headers->data;
374 header_display_prop_free(dp);
375 prefs_display_headers =
376 g_slist_remove(prefs_display_headers, dp);
379 while (fgets(buf, sizeof(buf), fp) != NULL) {
381 dp = header_display_prop_read_str(buf);
383 prefs_display_headers =
384 g_slist_append(prefs_display_headers, dp);
391 void prefs_display_headers_write_config(void)
396 gchar buf[PREFSBUFSIZE];
398 HeaderDisplayProp *dp;
400 debug_print(_("Writing configuration for displaying of headers...\n"));
402 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
403 HEADERS_DISPLAY_RC, NULL);
405 if ((pfile = prefs_write_open(rcpath)) == NULL) {
406 g_warning(_("failed to write configuration to file\n"));
411 for (cur = prefs_display_headers; cur != NULL; cur = cur->next) {
412 HeaderDisplayProp *hdr = (HeaderDisplayProp *)cur->data;
415 dpstr = header_display_prop_get_str(hdr);
416 if (fputs(dpstr, pfile->fp) == EOF ||
417 fputc('\n', pfile->fp) == EOF) {
418 FILE_OP_ERROR(rcpath, "fputs || fputc");
419 prefs_write_close_revert(pfile);
429 if (prefs_write_close(pfile) < 0) {
430 g_warning(_("failed to write configuration to file\n"));
435 static void prefs_display_headers_set_dialog()
437 GtkCList *clist = GTK_CLIST(headers.headers_clist);
442 gtk_clist_freeze(clist);
443 gtk_clist_clear(clist);
445 dp_str[0] = _("(New)");
447 row = gtk_clist_append(clist, dp_str);
448 gtk_clist_set_row_data(clist, row, NULL);
450 for (cur = prefs_display_headers; cur != NULL; cur = cur->next) {
451 HeaderDisplayProp *dp = (HeaderDisplayProp *)cur->data;
455 dp_str[0] = g_strdup_printf("(%s)", dp->name);
457 dp_str[0] = g_strdup_printf("%s", dp->name);
459 dp_str[0] = dp->name;
460 dp_str[1] = dp->hidden ? _("Hide") : _("Order");
462 row = gtk_clist_append(clist, dp_str);
463 gtk_clist_set_row_data(clist, row, dp);
465 // g_free(dp_str[0]);
468 gtk_clist_thaw(clist);
471 static void prefs_display_headers_set_list()
474 HeaderDisplayProp *dp;
476 g_slist_free(prefs_display_headers);
477 prefs_display_headers = NULL;
479 while ((dp = gtk_clist_get_row_data(GTK_CLIST(headers.headers_clist),
481 prefs_display_headers = g_slist_append(prefs_display_headers,
487 #define GET_ENTRY(entry) \
488 entry_text = gtk_entry_get_text(GTK_ENTRY(entry))
490 static gint prefs_display_headers_clist_set_row(gint row)
492 GtkCList *clist = GTK_CLIST(headers.headers_clist);
493 HeaderDisplayProp *dp;
497 g_return_val_if_fail(row != 0, -1);
499 GET_ENTRY(headers.hdr_entry);
500 if (entry_text[0] == '\0') {
501 alertpanel_error(_("Header name is not set."));
505 dp = g_new0(HeaderDisplayProp, 1);
507 dp->name = g_strdup(entry_text);
509 dp->hidden = !gtk_toggle_button_get_active
510 (GTK_TOGGLE_BUTTON(headers.key_check));
512 dp_str[0] = dp->name;
513 dp_str[1] = dp->hidden ? _("Hide") : _("Order");
516 dp_str[0] = g_strdup_printf("(%s)", dp->name);
518 dp_str[0] = g_strdup_printf("%s", dp->name);
522 row = gtk_clist_append(clist, dp_str);
524 HeaderDisplayProp *tmpdp;
526 gtk_clist_set_text(clist, row, 0, dp_str[0]);
527 gtk_clist_set_text(clist, row, 1, dp_str[1]);
528 tmpdp = gtk_clist_get_row_data(clist, row);
530 header_display_prop_free(tmpdp);
533 gtk_clist_set_row_data(clist, row, dp);
535 // g_free(dp_str[0]);
537 prefs_display_headers_set_list();
542 static void prefs_display_headers_register_cb(void)
544 prefs_display_headers_clist_set_row(-1);
547 static void prefs_display_headers_substitute_cb(void)
549 GtkCList *clist = GTK_CLIST(headers.headers_clist);
550 HeaderDisplayProp *dp;
553 if (!clist->selection) return;
555 row = GPOINTER_TO_INT(clist->selection->data);
556 if (row == 0) return;
558 dp = gtk_clist_get_row_data(clist, row);
561 prefs_display_headers_clist_set_row(row);
564 static void prefs_display_headers_delete_cb(void)
566 GtkCList *clist = GTK_CLIST(headers.headers_clist);
567 HeaderDisplayProp *dp;
570 if (!clist->selection) return;
571 row = GPOINTER_TO_INT(clist->selection->data);
572 if (row == 0) return;
574 if (alertpanel(_("Delete header"),
575 _("Do you really want to delete this header?"),
576 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
579 dp = gtk_clist_get_row_data(clist, row);
580 header_display_prop_free(dp);
581 gtk_clist_remove(clist, row);
582 prefs_display_headers = g_slist_remove(prefs_display_headers, dp);
585 static void prefs_display_headers_up(void)
587 GtkCList *clist = GTK_CLIST(headers.headers_clist);
590 if (!clist->selection) return;
592 row = GPOINTER_TO_INT(clist->selection->data);
594 gtk_clist_row_move(clist, row, row - 1);
595 prefs_display_headers_set_list();
599 static void prefs_display_headers_down(void)
601 GtkCList *clist = GTK_CLIST(headers.headers_clist);
604 if (!clist->selection) return;
606 row = GPOINTER_TO_INT(clist->selection->data);
607 if (row > 0 && row < clist->rows - 1) {
608 gtk_clist_row_move(clist, row, row + 1);
609 prefs_display_headers_set_list();
613 #define ENTRY_SET_TEXT(entry, str) \
614 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
616 static void prefs_display_headers_select(GtkCList *clist, gint row,
617 gint column, GdkEvent *event)
619 HeaderDisplayProp *dp;
620 HeaderDisplayProp default_dp = { "", 0 };
622 dp = gtk_clist_get_row_data(clist, row);
626 ENTRY_SET_TEXT(headers.hdr_entry, dp->name);
627 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(headers.key_check),
630 if ((row != 0) && event && (event->type == GDK_2BUTTON_PRESS)) {
631 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(headers.key_check), dp->hidden);
632 prefs_display_headers_clist_set_row(row);
636 static void prefs_display_headers_key_pressed(GtkWidget *widget,
640 if (event && event->keyval == GDK_Escape)
641 gtk_widget_hide(headers.window);
644 static void prefs_display_headers_close(GtkButton *button)
646 prefs_display_headers_write_config();
647 gtk_widget_hide(headers.window);