2 * Dialog boxes for filter editing
3 * (This used to be a notebook page under "Preferences", hence the
4 * "prefs" in the file name.)
6 * $Id: filter_prefs.c,v 1.11 2000/04/01 12:03:40 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include "filter_prefs.h"
51 #include "prefs_dlg.h"
53 #define E_FILT_NAME_KEY "filter_name"
54 #define E_FILT_LBL_KEY "filter_label"
55 #define E_FILT_CM_KEY "in_cancel_mode"
56 #define E_FILTER_WIDGET_KEY "filter_widget"
58 typedef struct _filter_def {
63 typedef struct _filter_cb_data {
69 static GtkWidget *filter_l, *chg_bt, *copy_bt, *del_bt, *name_te, *filter_te, *apply_bt;
70 static GList *fl = NULL;
72 static void get_filter_list(void);
73 static GtkWidget *filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te);
74 static void filter_dlg_ok(GtkWidget *ok_bt, gpointer parent_w);
75 static void filter_dlg_save(GtkWidget *save_bt, gpointer parent_w);
76 static void filter_dlg_cancel(GtkWidget *cancel_bt, gpointer parent_w);
77 static void filter_dlg_destroy(GtkWidget *win, gpointer data);
78 static void filter_sel_apply_cb(GtkWidget *cancel_bt, gpointer parent_w);
80 static GtkWidget *filter_prefs_show(GtkWidget *);
81 static void filter_sel_list_cb(GtkWidget *, gpointer);
82 static void filter_sel_new_cb(GtkWidget *, gpointer);
83 static void filter_sel_chg_cb(GtkWidget *, gpointer);
84 static void filter_sel_copy_cb(GtkWidget *, gpointer);
85 static void filter_sel_del_cb(GtkWidget *, gpointer);
86 static void filter_prefs_ok(GtkWidget *);
87 static void filter_prefs_save(GtkWidget *);
88 static void filter_prefs_cancel(GtkWidget *);
89 static void filter_prefs_delete(GtkWidget *);
91 #define FILTER_LINE_SIZE 2048
98 gchar *ff_path, *ff_name = PF_DIR "/filters", f_buf[FILTER_LINE_SIZE];
99 gchar *name_begin, *name_end, *filt_begin;
104 /* To do: generalize this */
105 ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_name) + 4);
106 sprintf(ff_path, "%s/%s", get_home_dir(), ff_name);
108 if ((ff = fopen(ff_path, "r")) == NULL) {
113 while (fgets(f_buf, FILTER_LINE_SIZE, ff)) {
116 if (f_buf[len - 1] == '\n') {
120 name_begin = strchr(f_buf, '"');
122 if (name_begin == NULL)
124 name_end = strchr(name_begin + 1, '"');
125 /* No terminating quote */
126 if (name_end == NULL) {
127 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
132 filt_begin = name_end + 1;
133 while(isspace(filt_begin[0])) filt_begin++;
134 /* No filter string */
135 if (filt_begin[0] == '\0') {
136 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
139 filt = (filter_def *) g_malloc(sizeof(filter_def));
140 filt->name = g_strdup(name_begin);
141 filt->strval = g_strdup(filt_begin);
142 fl = g_list_append(fl, filt);
148 /* XXX - we can have one global dialog box for editing, and a bunch
149 of dialog boxes associated with browse buttons; we want the dialog
150 boxes associated with browse buttons to at least let you save the
151 current filter, so they have to allow editing; however, how do we
152 arrange that if a change is made to the filter list, other dialog
153 boxes get updated appropriately? */
155 /* Create a filter dialog for browsing; this is to be used as a callback
156 for a button next to a text entry box, which, when clicked, allows
157 you to browse through the list of filters to select one to be put
158 into the text entry box, and, if you select a filter with this
159 dialog box, enters the text of the filter into a text entry box
160 associated with the button. */
162 filter_browse_cb(GtkWidget *w)
164 GtkWidget *caller = gtk_widget_get_toplevel(w);
165 GtkWidget *filter_browse_w;
166 GtkWidget *filter_te;
168 /* Has a filter dialog box already been opened for that top-level
170 filter_browse_w = gtk_object_get_data(GTK_OBJECT(caller),
171 E_FILT_DIALOG_PTR_KEY);
173 if (filter_browse_w != NULL) {
174 /* Yes. Just re-activate that dialog box. */
175 reactivate_window(filter_browse_w);
179 /* No. Get the text entry attached to the button. */
180 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY);
182 /* Now create a new dialog. */
183 filter_browse_w = filter_dialog_new(caller, filter_te);
185 /* Set the E_FILT_CALLER_PTR_KEY for the new dialog to point to
187 gtk_object_set_data(GTK_OBJECT(filter_browse_w), E_FILT_CALLER_PTR_KEY,
190 /* Set the E_FILT_DIALOG_PTR_KEY for the caller to point to us */
191 gtk_object_set_data(GTK_OBJECT(caller), E_FILT_DIALOG_PTR_KEY,
195 static GtkWidget *global_filter_w;
197 /* Create a filter dialog for editing; this is to be used as a callback
198 for menu items, toolbars, etc.. */
200 filter_dialog_cb(GtkWidget *w)
202 /* Has a filter dialog box already been opened for editing? */
203 if (global_filter_w != NULL) {
204 /* Yes. Just reactivate it. */
205 reactivate_window(global_filter_w);
209 /* No. Create one. */
210 global_filter_w = filter_dialog_new(NULL, NULL);
214 filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te)
216 GtkWidget *main_w, /* main window */
217 *main_vb, /* main container */
218 *bbox, /* button container */
219 *ok_bt, /* ok button */
220 *save_bt, /* save button */
221 *cancel_bt; /* cancel button */
222 GtkWidget *filter_pg = NULL; /* filter settings box */
224 main_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
225 gtk_window_set_title(GTK_WINDOW(main_w), "Ethereal: Filters");
227 /* Call a handler when we're destroyed, so we can inform
228 our caller, if any, that we've been destroyed. */
229 gtk_signal_connect(GTK_OBJECT(main_w), "destroy",
230 GTK_SIGNAL_FUNC(filter_dlg_destroy), NULL);
232 main_vb = gtk_vbox_new(FALSE, 5);
233 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
234 gtk_container_add(GTK_CONTAINER(main_w), main_vb);
235 gtk_widget_show(main_vb);
237 filter_pg = filter_prefs_show(filter_te);
238 gtk_box_pack_start(GTK_BOX(main_vb), filter_pg, TRUE, TRUE, 0);
239 gtk_object_set_data(GTK_OBJECT(filter_pg), E_FILT_TE_PTR_KEY, filter_te);
240 gtk_object_set_data(GTK_OBJECT(main_w), E_FILTER_WIDGET_KEY, filter_pg);
242 bbox = gtk_hbutton_box_new();
243 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
244 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
245 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
246 gtk_widget_show(bbox);
248 ok_bt = gtk_button_new_with_label ("OK");
249 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
250 GTK_SIGNAL_FUNC(filter_dlg_ok), GTK_OBJECT(main_w));
251 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
252 gtk_box_pack_start(GTK_BOX(bbox), ok_bt, TRUE, TRUE, 0);
253 gtk_widget_grab_default(ok_bt);
254 gtk_widget_show(ok_bt);
256 save_bt = gtk_button_new_with_label ("Save");
257 gtk_signal_connect(GTK_OBJECT(save_bt), "clicked",
258 GTK_SIGNAL_FUNC(filter_dlg_save), GTK_OBJECT(main_w));
259 GTK_WIDGET_SET_FLAGS(save_bt, GTK_CAN_DEFAULT);
260 gtk_box_pack_start(GTK_BOX(bbox), save_bt, TRUE, TRUE, 0);
261 gtk_widget_show(save_bt);
263 cancel_bt = gtk_button_new_with_label ("Cancel");
264 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
265 GTK_SIGNAL_FUNC(filter_dlg_cancel), GTK_OBJECT(main_w));
266 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
267 gtk_box_pack_start(GTK_BOX(bbox), cancel_bt, TRUE, TRUE, 0);
268 gtk_widget_show(cancel_bt);
270 gtk_widget_show(main_w);
276 filter_dlg_ok(GtkWidget *ok_bt, gpointer parent_w)
278 filter_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_FILTER_WIDGET_KEY));
279 gtk_widget_destroy(GTK_WIDGET(parent_w));
283 filter_dlg_save(GtkWidget *save_bt, gpointer parent_w)
285 filter_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_FILTER_WIDGET_KEY));
289 filter_dlg_cancel(GtkWidget *cancel_bt, gpointer parent_w)
291 filter_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_FILTER_WIDGET_KEY));
292 gtk_widget_destroy(GTK_WIDGET(parent_w));
296 filter_dlg_destroy(GtkWidget *win, gpointer data)
300 /* Get the widget that requested that we be popped up, if any.
301 (It should arrange to destroy us if it's destroyed, so
302 that we don't get a pointer to a non-existent window here.) */
303 caller = gtk_object_get_data(GTK_OBJECT(win), E_FILT_CALLER_PTR_KEY);
305 if (caller != NULL) {
306 /* Tell it we no longer exist. */
307 gtk_object_set_data(GTK_OBJECT(caller), E_FILT_DIALOG_PTR_KEY,
310 /* This is an editing dialog popped up from, for example,
311 a menu item; note that we no longer have one. */
312 g_assert(win == global_filter_w);
313 global_filter_w = NULL;
316 /* Now nuke this window. */
317 gtk_grab_remove(GTK_WIDGET(win));
318 gtk_widget_destroy(GTK_WIDGET(win));
321 /* Create and display the filter selection widgets. */
323 filter_prefs_show(GtkWidget *w) {
324 GtkWidget *main_vb, *top_hb, *list_bb, *new_bt, *filter_sc,
325 *nl_item, *nl_lb, *middle_hb, *name_lb, *bottom_hb,
327 GtkWidget *l_select = NULL;
330 gchar *filter_te_str = NULL;
332 /* Make sure everything is set up */
335 filter_te_str = gtk_entry_get_text(GTK_ENTRY(w));
337 /* Container for each row of widgets */
338 main_vb = gtk_vbox_new(FALSE, 5);
339 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
340 gtk_widget_show(main_vb);
341 gtk_object_set_data(GTK_OBJECT(main_vb), E_FILT_CM_KEY, (gpointer)FALSE);
343 /* Top row: Filter list and buttons */
344 top_hb = gtk_hbox_new(FALSE, 5);
345 gtk_container_add(GTK_CONTAINER(main_vb), top_hb);
346 gtk_widget_show(top_hb);
348 list_bb = gtk_vbutton_box_new();
349 gtk_button_box_set_layout (GTK_BUTTON_BOX (list_bb), GTK_BUTTONBOX_START);
350 gtk_container_add(GTK_CONTAINER(top_hb), list_bb);
351 gtk_widget_show(list_bb);
353 new_bt = gtk_button_new_with_label ("New");
354 gtk_signal_connect(GTK_OBJECT(new_bt), "clicked",
355 GTK_SIGNAL_FUNC(filter_sel_new_cb), NULL);
356 gtk_container_add(GTK_CONTAINER(list_bb), new_bt);
357 gtk_widget_show(new_bt);
359 chg_bt = gtk_button_new_with_label ("Change");
360 gtk_widget_set_sensitive(chg_bt, FALSE);
361 gtk_signal_connect(GTK_OBJECT(chg_bt), "clicked",
362 GTK_SIGNAL_FUNC(filter_sel_chg_cb), NULL);
363 gtk_container_add(GTK_CONTAINER(list_bb), chg_bt);
364 gtk_widget_show(chg_bt);
366 copy_bt = gtk_button_new_with_label ("Copy");
367 gtk_widget_set_sensitive(copy_bt, FALSE);
368 gtk_signal_connect(GTK_OBJECT(copy_bt), "clicked",
369 GTK_SIGNAL_FUNC(filter_sel_copy_cb), NULL);
370 gtk_container_add(GTK_CONTAINER(list_bb), copy_bt);
371 gtk_widget_show(copy_bt);
373 del_bt = gtk_button_new_with_label ("Delete");
374 gtk_widget_set_sensitive(del_bt, FALSE);
375 gtk_signal_connect(GTK_OBJECT(del_bt), "clicked",
376 GTK_SIGNAL_FUNC(filter_sel_del_cb), NULL);
377 gtk_container_add(GTK_CONTAINER(list_bb), del_bt);
378 gtk_widget_show(del_bt);
380 apply_bt = gtk_button_new_with_label("Apply");
381 gtk_widget_set_sensitive(apply_bt, FALSE);
382 gtk_signal_connect(GTK_OBJECT(apply_bt), "clicked",
383 GTK_SIGNAL_FUNC(filter_sel_apply_cb), w);
384 gtk_container_add(GTK_CONTAINER(list_bb), apply_bt);
385 gtk_widget_show(apply_bt);
387 filter_sc = gtk_scrolled_window_new(NULL, NULL);
388 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(filter_sc),
389 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
390 gtk_widget_set_usize(filter_sc, 250, 150);
391 gtk_container_add(GTK_CONTAINER(top_hb), filter_sc);
392 gtk_widget_show(filter_sc);
394 filter_l = gtk_list_new();
395 gtk_list_set_selection_mode(GTK_LIST(filter_l), GTK_SELECTION_SINGLE);
396 gtk_signal_connect(GTK_OBJECT(filter_l), "selection_changed",
397 GTK_SIGNAL_FUNC(filter_sel_list_cb), main_vb);
398 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(filter_sc),
400 gtk_widget_show(filter_l);
402 flp = g_list_first(fl);
404 filt = (filter_def *) flp->data;
405 nl_lb = gtk_label_new(filt->name);
406 nl_item = gtk_list_item_new();
407 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
408 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
409 gtk_widget_show(nl_lb);
410 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
411 gtk_widget_show(nl_item);
412 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
413 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, flp);
415 if (filter_te_str && filt->strval)
416 if (strcmp(filter_te_str, filt->strval) == 0)
422 /* Middle row: Filter name entry */
423 middle_hb = gtk_hbox_new(FALSE, 5);
424 gtk_container_add(GTK_CONTAINER(main_vb), middle_hb);
425 gtk_widget_show(middle_hb);
427 name_lb = gtk_label_new("Filter name:");
428 gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 3);
429 gtk_widget_show(name_lb);
431 name_te = gtk_entry_new();
432 gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 3);
433 gtk_widget_show(name_te);
435 /* Bottom row: Filter text entry */
436 bottom_hb = gtk_hbox_new(FALSE, 5);
437 gtk_container_add(GTK_CONTAINER(main_vb), bottom_hb);
438 gtk_widget_show(bottom_hb);
440 filter_lb = gtk_label_new("Filter string:");
441 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 3);
442 gtk_widget_show(filter_lb);
444 filter_te = gtk_entry_new();
445 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 3);
446 gtk_widget_show(filter_te);
450 gtk_list_select_child(GTK_LIST(filter_l), l_select);
451 } else if (filter_te_str && filter_te_str[0]) {
452 gtk_entry_set_text(GTK_ENTRY(name_te), "New filter");
453 gtk_entry_set_text(GTK_ENTRY(filter_te), filter_te_str);
460 filter_sel_list_cb(GtkWidget *l, gpointer data) {
462 gchar *name = "", *strval = "";
465 gint sensitivity = FALSE;
468 sl = GTK_LIST(l)->selection;
472 if (sl) { /* Something was selected */
473 l_item = GTK_OBJECT(sl->data);
474 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
476 filt = (filter_def *) flp->data;
478 strval = filt->strval;
483 /* Did you know that this function is called when the window is destroyed? */
485 if (!gtk_object_get_data(GTK_OBJECT(data), E_FILT_CM_KEY)) {
486 gtk_entry_set_text(GTK_ENTRY(name_te), name);
487 gtk_entry_set_text(GTK_ENTRY(filter_te), strval);
488 gtk_widget_set_sensitive(chg_bt, sensitivity);
489 gtk_widget_set_sensitive(copy_bt, sensitivity);
490 gtk_widget_set_sensitive(del_bt, sensitivity);
491 gtk_widget_set_sensitive(apply_bt, sensitivity);
495 /* To do: add input checking to each of these callbacks */
498 filter_sel_new_cb(GtkWidget *w, gpointer data) {
500 gchar *name, *strval;
501 GtkWidget *nl_item, *nl_lb;
503 name = gtk_entry_get_text(GTK_ENTRY(name_te));
504 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
506 if (strlen(name) > 0 && strlen(strval) > 0) {
507 filt = (filter_def *) g_malloc(sizeof(filter_def));
508 filt->name = g_strdup(name);
509 filt->strval = g_strdup(strval);
510 fl = g_list_append(fl, filt);
511 nl_lb = gtk_label_new(filt->name);
512 nl_item = gtk_list_item_new();
513 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
514 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
515 gtk_widget_show(nl_lb);
516 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
517 gtk_widget_show(nl_item);
518 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
519 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
520 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
525 filter_sel_chg_cb(GtkWidget *w, gpointer data) {
527 gchar *name = "", *strval = "";
532 sl = GTK_LIST(filter_l)->selection;
533 name = gtk_entry_get_text(GTK_ENTRY(name_te));
534 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
536 if (sl) { /* Something was selected */
537 l_item = GTK_OBJECT(sl->data);
538 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
539 nl_lb = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
541 filt = (filter_def *) flp->data;
543 if (strlen(name) > 0 && strlen(strval) > 0 && filt) {
545 g_free(filt->strval);
546 filt->name = g_strdup(name);
547 filt->strval = g_strdup(strval);
548 gtk_label_set(nl_lb, filt->name);
555 filter_sel_copy_cb(GtkWidget *w, gpointer data) {
557 filter_def *filt, *nfilt;
558 gchar *prefix = "Copy of ";
560 GtkWidget *nl_item, *nl_lb;
562 sl = GTK_LIST(filter_l)->selection;
563 if (sl) { /* Something was selected */
564 l_item = GTK_OBJECT(sl->data);
565 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
567 filt = (filter_def *) flp->data;
568 nfilt = (filter_def *) g_malloc(sizeof(filter_def));
569 nfilt->name = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
570 sprintf(nfilt->name, "%s%s", prefix, filt->name);
571 nfilt->strval = g_strdup(filt->strval);
572 fl = g_list_append(fl, nfilt);
573 nl_lb = gtk_label_new(nfilt->name);
574 nl_item = gtk_list_item_new();
575 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
576 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
577 gtk_widget_show(nl_lb);
578 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
579 gtk_widget_show(nl_item);
580 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
581 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
582 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
588 filter_sel_del_cb(GtkWidget *w, gpointer data) {
594 sl = GTK_LIST(filter_l)->selection;
595 if (sl) { /* Something was selected */
596 l_item = GTK_OBJECT(sl->data);
597 pos = gtk_list_child_position(GTK_LIST(filter_l),
599 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
601 filt = (filter_def *) flp->data;
603 g_free(filt->strval);
605 fl = g_list_remove_link(fl, flp);
606 gtk_list_clear_items(GTK_LIST(filter_l), pos, pos + 1);
612 filter_sel_apply_cb(GtkWidget *w, gpointer data)
617 GtkWidget *mw_filt = data;
619 sl = GTK_LIST(filter_l)->selection;
620 if (sl != NULL && mw_filt != NULL) { /* Place something in the filter box. */
621 l_item = GTK_OBJECT(sl->data);
622 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
624 filt = (filter_def *) flp->data;
625 gtk_entry_set_text(GTK_ENTRY(mw_filt), filt->strval);
626 gtk_signal_emit_by_name(GTK_OBJECT(mw_filt), "activate");
632 filter_prefs_ok(GtkWidget *w) {
636 GtkWidget *mw_filt = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY);
638 sl = GTK_LIST(filter_l)->selection;
639 if (sl && mw_filt) { /* Place something in the filter box. */
640 l_item = GTK_OBJECT(sl->data);
641 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
643 filt = (filter_def *) flp->data;
644 gtk_entry_set_text(GTK_ENTRY(mw_filt), filt->strval);
648 filter_prefs_delete(w);
652 filter_prefs_save(GtkWidget *w) {
655 gchar *ff_path, *ff_dir = PF_DIR, *ff_name = "filters";
659 ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_dir) +
660 strlen(ff_name) + 4);
661 sprintf(ff_path, "%s/%s", get_home_dir(), ff_dir);
663 if (stat(ff_path, &s_buf) != 0)
667 mkdir(ff_path, 0755);
670 sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, ff_name);
672 if ((ff = fopen(ff_path, "w")) != NULL) {
673 flp = g_list_first(fl);
675 filt = (filter_def *) flp->data;
676 fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
686 filter_prefs_cancel(GtkWidget *w) {
688 filter_prefs_delete(w);
692 filter_prefs_delete(GtkWidget *w) {
694 /* Let the list cb know we're about to destroy the widget tree, so it */
695 /* doesn't operate on widgets that don't exist. */
696 gtk_object_set_data(GTK_OBJECT(w), E_FILT_CM_KEY, (gpointer)TRUE);
697 gtk_widget_destroy(GTK_WIDGET(w));