2 * Routines for managing filter sets
4 * $Id: filter.c,v 1.14 1999/07/13 03:08:05 gram Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50 #define E_FILT_NAME_KEY "filter_name"
51 #define E_FILT_LBL_KEY "filter_label"
52 #define E_FILT_CM_KEY "in_cancel_mode"
54 GtkWidget *filter_l, *chg_bt, *copy_bt, *del_bt, *name_te, *filter_te;
57 void get_filter_list();
63 gchar *ff_path, *ff_name = PF_DIR "/filters", f_buf[256];
64 gchar *name_begin, *name_end, *filt_begin;
69 /* To do: generalize this */
70 ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_name) + 4);
71 sprintf(ff_path, "%s/%s", getenv("HOME"), ff_name);
73 if ((ff = fopen(ff_path, "r")) == NULL) {
78 while (fgets(f_buf, 256, ff)) {
81 if (f_buf[len - 1] == '\n') {
85 name_begin = strchr(f_buf, '"');
87 if (name_begin == NULL)
89 name_end = strchr(name_begin + 1, '"');
90 /* No terminating quote */
91 if (name_end == NULL) {
92 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
97 filt_begin = name_end + 1;
98 while(isspace(filt_begin[0])) filt_begin++;
99 /* No filter string */
100 if (filt_begin[0] == '\0') {
101 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
104 filt = (filter_def *) g_malloc(sizeof(filter_def));
105 filt->name = g_strdup(name_begin);
106 filt->strval = g_strdup(filt_begin);
107 fl = g_list_append(fl, filt);
113 /* Create and display the filter selection widgets. */
114 /* Called when the 'Filter' preference notebook page is selected. */
116 filter_prefs_show(GtkWidget *w) {
117 GtkWidget *main_vb, *top_hb, *list_bb, *new_bt, *filter_sc,
118 *nl_item, *nl_lb, *middle_hb, *name_lb, *bottom_hb,
120 GtkWidget *l_select = NULL;
123 gchar *filter_te_str = NULL;
125 /* Make sure everything is set up */
128 filter_te_str = gtk_entry_get_text(GTK_ENTRY(w));
130 /* Container for each row of widgets */
131 main_vb = gtk_vbox_new(FALSE, 5);
132 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
133 gtk_widget_show(main_vb);
134 gtk_object_set_data(GTK_OBJECT(main_vb), E_FILT_CM_KEY, (gpointer)FALSE);
136 /* Top row: Filter list and buttons */
137 top_hb = gtk_hbox_new(FALSE, 5);
138 gtk_container_add(GTK_CONTAINER(main_vb), top_hb);
139 gtk_widget_show(top_hb);
141 list_bb = gtk_vbutton_box_new();
142 gtk_button_box_set_layout (GTK_BUTTON_BOX (list_bb), GTK_BUTTONBOX_START);
143 gtk_container_add(GTK_CONTAINER(top_hb), list_bb);
144 gtk_widget_show(list_bb);
146 new_bt = gtk_button_new_with_label ("New");
147 gtk_signal_connect(GTK_OBJECT(new_bt), "clicked",
148 GTK_SIGNAL_FUNC(filter_sel_new_cb), NULL);
149 gtk_container_add(GTK_CONTAINER(list_bb), new_bt);
150 gtk_widget_show(new_bt);
152 chg_bt = gtk_button_new_with_label ("Change");
153 gtk_widget_set_sensitive(chg_bt, FALSE);
154 gtk_signal_connect(GTK_OBJECT(chg_bt), "clicked",
155 GTK_SIGNAL_FUNC(filter_sel_chg_cb), NULL);
156 gtk_container_add(GTK_CONTAINER(list_bb), chg_bt);
157 gtk_widget_show(chg_bt);
159 copy_bt = gtk_button_new_with_label ("Copy");
160 gtk_widget_set_sensitive(copy_bt, FALSE);
161 gtk_signal_connect(GTK_OBJECT(copy_bt), "clicked",
162 GTK_SIGNAL_FUNC(filter_sel_copy_cb), NULL);
163 gtk_container_add(GTK_CONTAINER(list_bb), copy_bt);
164 gtk_widget_show(copy_bt);
166 del_bt = gtk_button_new_with_label ("Delete");
167 gtk_widget_set_sensitive(del_bt, FALSE);
168 gtk_signal_connect(GTK_OBJECT(del_bt), "clicked",
169 GTK_SIGNAL_FUNC(filter_sel_del_cb), NULL);
170 gtk_container_add(GTK_CONTAINER(list_bb), del_bt);
171 gtk_widget_show(del_bt);
173 filter_sc = gtk_scrolled_window_new(NULL, NULL);
174 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(filter_sc),
175 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
176 gtk_widget_set_usize(filter_sc, 250, 150);
177 gtk_container_add(GTK_CONTAINER(top_hb), filter_sc);
178 gtk_widget_show(filter_sc);
180 filter_l = gtk_list_new();
181 gtk_list_set_selection_mode(GTK_LIST(filter_l), GTK_SELECTION_SINGLE);
182 gtk_signal_connect(GTK_OBJECT(filter_l), "selection_changed",
183 GTK_SIGNAL_FUNC(filter_sel_list_cb), main_vb);
184 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(filter_sc),
186 gtk_widget_show(filter_l);
188 flp = g_list_first(fl);
190 filt = (filter_def *) flp->data;
191 nl_lb = gtk_label_new(filt->name);
192 nl_item = gtk_list_item_new();
193 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
194 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
195 gtk_widget_show(nl_lb);
196 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
197 gtk_widget_show(nl_item);
198 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
199 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, flp);
201 if (filter_te_str && filt->strval)
202 if (strcmp(filter_te_str, filt->strval) == 0)
208 /* Middle row: Filter name entry */
209 middle_hb = gtk_hbox_new(FALSE, 5);
210 gtk_container_add(GTK_CONTAINER(main_vb), middle_hb);
211 gtk_widget_show(middle_hb);
213 name_lb = gtk_label_new("Filter name:");
214 gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 3);
215 gtk_widget_show(name_lb);
217 name_te = gtk_entry_new();
218 gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 3);
219 gtk_widget_show(name_te);
221 /* Bottom row: Filter text entry */
222 bottom_hb = gtk_hbox_new(FALSE, 5);
223 gtk_container_add(GTK_CONTAINER(main_vb), bottom_hb);
224 gtk_widget_show(bottom_hb);
226 filter_lb = gtk_label_new("Filter string:");
227 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 3);
228 gtk_widget_show(filter_lb);
230 filter_te = gtk_entry_new();
231 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 3);
232 gtk_widget_show(filter_te);
236 gtk_list_select_child(GTK_LIST(filter_l), l_select);
237 } else if (filter_te_str && filter_te_str[0]) {
238 gtk_entry_set_text(GTK_ENTRY(name_te), "New filter");
239 gtk_entry_set_text(GTK_ENTRY(filter_te), filter_te_str);
246 filter_sel_list_cb(GtkWidget *l, gpointer data) {
248 gchar *name = "", *strval = "";
251 gint sensitivity = FALSE;
254 sl = GTK_LIST(l)->selection;
258 if (sl) { /* Something was selected */
259 l_item = GTK_OBJECT(sl->data);
260 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
262 filt = (filter_def *) flp->data;
264 strval = filt->strval;
269 /* Did you know that this function is called when the window is destroyed? */
271 if (!gtk_object_get_data(GTK_OBJECT(data), E_FILT_CM_KEY)) {
272 gtk_entry_set_text(GTK_ENTRY(name_te), name);
273 gtk_entry_set_text(GTK_ENTRY(filter_te), strval);
274 gtk_widget_set_sensitive(chg_bt, sensitivity);
275 gtk_widget_set_sensitive(copy_bt, sensitivity);
276 gtk_widget_set_sensitive(del_bt, sensitivity);
280 /* To do: add input checking to each of these callbacks */
283 filter_sel_new_cb(GtkWidget *w, gpointer data) {
285 gchar *name, *strval;
286 GtkWidget *nl_item, *nl_lb;
288 name = gtk_entry_get_text(GTK_ENTRY(name_te));
289 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
291 if (strlen(name) > 0 && strlen(strval) > 0) {
292 filt = (filter_def *) g_malloc(sizeof(filter_def));
293 filt->name = g_strdup(name);
294 filt->strval = g_strdup(strval);
295 fl = g_list_append(fl, filt);
296 nl_lb = gtk_label_new(filt->name);
297 nl_item = gtk_list_item_new();
298 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
299 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
300 gtk_widget_show(nl_lb);
301 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
302 gtk_widget_show(nl_item);
303 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
304 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
305 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
310 filter_sel_chg_cb(GtkWidget *w, gpointer data) {
312 gchar *name = "", *strval = "";
317 sl = GTK_LIST(filter_l)->selection;
318 name = gtk_entry_get_text(GTK_ENTRY(name_te));
319 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
321 if (sl) { /* Something was selected */
322 l_item = GTK_OBJECT(sl->data);
323 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
324 nl_lb = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
326 filt = (filter_def *) flp->data;
328 if (strlen(name) > 0 && strlen(strval) > 0 && filt) {
330 g_free(filt->strval);
331 filt->name = g_strdup(name);
332 filt->strval = g_strdup(strval);
333 gtk_label_set(nl_lb, filt->name);
340 filter_sel_copy_cb(GtkWidget *w, gpointer data) {
342 filter_def *filt, *nfilt;
343 gchar *prefix = "Copy of ";
345 GtkWidget *nl_item, *nl_lb;
347 sl = GTK_LIST(filter_l)->selection;
348 if (sl) { /* Something was selected */
349 l_item = GTK_OBJECT(sl->data);
350 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
352 filt = (filter_def *) flp->data;
353 nfilt = (filter_def *) g_malloc(sizeof(filter_def));
354 nfilt->name = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
355 sprintf(nfilt->name, "%s%s", prefix, filt->name);
356 nfilt->strval = g_strdup(filt->strval);
357 fl = g_list_append(fl, nfilt);
358 nl_lb = gtk_label_new(nfilt->name);
359 nl_item = gtk_list_item_new();
360 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
361 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
362 gtk_widget_show(nl_lb);
363 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
364 gtk_widget_show(nl_item);
365 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
366 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
367 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
373 filter_sel_del_cb(GtkWidget *w, gpointer data) {
379 sl = GTK_LIST(filter_l)->selection;
380 if (sl) { /* Something was selected */
381 l_item = GTK_OBJECT(sl->data);
382 pos = gtk_list_child_position(GTK_LIST(filter_l),
384 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
386 filt = (filter_def *) flp->data;
388 g_free(filt->strval);
390 fl = g_list_remove(fl, flp);
391 gtk_list_clear_items(GTK_LIST(filter_l), pos, pos + 1);
397 filter_prefs_ok(GtkWidget *w) {
401 GtkWidget *mw_filt = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY);
403 sl = GTK_LIST(filter_l)->selection;
404 if (sl && mw_filt) { /* Place something in the filter box. */
405 l_item = GTK_OBJECT(sl->data);
406 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
408 filt = (filter_def *) flp->data;
409 gtk_entry_set_text(GTK_ENTRY(mw_filt), filt->strval);
413 filter_prefs_cancel(w);
417 filter_prefs_save(GtkWidget *w) {
420 gchar *ff_path, *ff_dir = PF_DIR, *ff_name = "filters";
424 ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_dir) +
425 strlen(ff_name) + 4);
426 sprintf(ff_path, "%s/%s", getenv("HOME"), ff_dir);
428 if (stat(ff_path, &s_buf) != 0)
432 mkdir(ff_path, 0755);
435 sprintf(ff_path, "%s/%s/%s", getenv("HOME"), ff_dir, ff_name);
437 if ((ff = fopen(ff_path, "w")) != NULL) {
438 flp = g_list_first(fl);
440 filt = (filter_def *) flp->data;
441 fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
451 filter_prefs_cancel(GtkWidget *w) {
453 /* Let the list cb know we're about to destroy the widget tree, so it */
454 /* doesn't operate on widgets that don't exist. */
455 gtk_object_set_data(GTK_OBJECT(w), E_FILT_CM_KEY, (gpointer)TRUE);
456 gtk_widget_destroy(GTK_WIDGET(w));