2 * Routines for managing filter sets
4 * $Id: filter.c,v 1.12 1998/12/27 20:44:53 gerald 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.
45 #define E_FILT_NAME_KEY "filter_name"
46 #define E_FILT_LBL_KEY "filter_label"
47 #define E_FILT_CM_KEY "in_cancel_mode"
49 GtkWidget *filter_l, *chg_bt, *copy_bt, *del_bt, *name_te, *filter_te;
52 void get_filter_list();
58 gchar *ff_path, *ff_name = PF_DIR "/filters", f_buf[256];
59 gchar *name_begin, *name_end, *filt_begin;
64 /* To do: generalize this */
65 ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_name) + 4);
66 sprintf(ff_path, "%s/%s", getenv("HOME"), ff_name);
68 if ((ff = fopen(ff_path, "r")) == NULL) {
73 while (fgets(f_buf, 256, ff)) {
76 if (f_buf[len - 1] == '\n') {
80 name_begin = strchr(f_buf, '"');
82 if (name_begin == NULL)
84 name_end = strchr(name_begin + 1, '"');
85 /* No terminating quote */
86 if (name_end == NULL) {
87 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
92 filt_begin = name_end + 1;
93 while(isspace(filt_begin[0])) filt_begin++;
94 /* No filter string */
95 if (filt_begin[0] == '\0') {
96 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
99 filt = (filter_def *) g_malloc(sizeof(filter_def));
100 filt->name = g_strdup(name_begin);
101 filt->strval = g_strdup(filt_begin);
102 fl = g_list_append(fl, filt);
108 /* Create and display the filter selection widgets. */
109 /* Called when the 'Filter' preference notebook page is selected. */
111 filter_prefs_show(GtkWidget *w) {
112 GtkWidget *main_vb, *top_hb, *list_bb, *new_bt, *filter_sc,
113 *nl_item, *nl_lb, *middle_hb, *name_lb, *bottom_hb,
115 GtkWidget *l_select = NULL;
118 gchar *filter_te_str = NULL;
120 /* Make sure everything is set up */
123 filter_te_str = gtk_entry_get_text(GTK_ENTRY(w));
125 /* Container for each row of widgets */
126 main_vb = gtk_vbox_new(FALSE, 5);
127 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
128 gtk_widget_show(main_vb);
129 gtk_object_set_data(GTK_OBJECT(main_vb), E_FILT_CM_KEY, (gpointer)FALSE);
131 /* Top row: Filter list and buttons */
132 top_hb = gtk_hbox_new(FALSE, 5);
133 gtk_container_add(GTK_CONTAINER(main_vb), top_hb);
134 gtk_widget_show(top_hb);
136 list_bb = gtk_vbutton_box_new();
137 gtk_button_box_set_layout (GTK_BUTTON_BOX (list_bb), GTK_BUTTONBOX_START);
138 gtk_container_add(GTK_CONTAINER(top_hb), list_bb);
139 gtk_widget_show(list_bb);
141 new_bt = gtk_button_new_with_label ("New");
142 gtk_signal_connect(GTK_OBJECT(new_bt), "clicked",
143 GTK_SIGNAL_FUNC(filter_sel_new_cb), NULL);
144 gtk_container_add(GTK_CONTAINER(list_bb), new_bt);
145 gtk_widget_show(new_bt);
147 chg_bt = gtk_button_new_with_label ("Change");
148 gtk_widget_set_sensitive(chg_bt, FALSE);
149 gtk_signal_connect(GTK_OBJECT(chg_bt), "clicked",
150 GTK_SIGNAL_FUNC(filter_sel_chg_cb), NULL);
151 gtk_container_add(GTK_CONTAINER(list_bb), chg_bt);
152 gtk_widget_show(chg_bt);
154 copy_bt = gtk_button_new_with_label ("Copy");
155 gtk_widget_set_sensitive(copy_bt, FALSE);
156 gtk_signal_connect(GTK_OBJECT(copy_bt), "clicked",
157 GTK_SIGNAL_FUNC(filter_sel_copy_cb), NULL);
158 gtk_container_add(GTK_CONTAINER(list_bb), copy_bt);
159 gtk_widget_show(copy_bt);
161 del_bt = gtk_button_new_with_label ("Delete");
162 gtk_widget_set_sensitive(del_bt, FALSE);
163 gtk_signal_connect(GTK_OBJECT(del_bt), "clicked",
164 GTK_SIGNAL_FUNC(filter_sel_del_cb), NULL);
165 gtk_container_add(GTK_CONTAINER(list_bb), del_bt);
166 gtk_widget_show(del_bt);
168 filter_sc = gtk_scrolled_window_new(NULL, NULL);
169 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(filter_sc),
170 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
171 gtk_widget_set_usize(filter_sc, 250, 150);
172 gtk_container_add(GTK_CONTAINER(top_hb), filter_sc);
173 gtk_widget_show(filter_sc);
175 filter_l = gtk_list_new();
176 gtk_list_set_selection_mode(GTK_LIST(filter_l), GTK_SELECTION_SINGLE);
177 gtk_signal_connect(GTK_OBJECT(filter_l), "selection_changed",
178 GTK_SIGNAL_FUNC(filter_sel_list_cb), main_vb);
179 #ifdef GTK_HAVE_FEATURES_1_1_4
180 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(filter_sc),
183 gtk_container_add(GTK_CONTAINER(filter_sc), filter_l);
185 gtk_widget_show(filter_l);
187 flp = g_list_first(fl);
189 filt = (filter_def *) flp->data;
190 nl_lb = gtk_label_new(filt->name);
191 nl_item = gtk_list_item_new();
192 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
193 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
194 gtk_widget_show(nl_lb);
195 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
196 gtk_widget_show(nl_item);
197 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
198 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, flp);
200 if (filter_te_str && filt->strval)
201 if (strcmp(filter_te_str, filt->strval) == 0)
207 /* Middle row: Filter name entry */
208 middle_hb = gtk_hbox_new(FALSE, 5);
209 gtk_container_add(GTK_CONTAINER(main_vb), middle_hb);
210 gtk_widget_show(middle_hb);
212 name_lb = gtk_label_new("Filter name:");
213 gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 3);
214 gtk_widget_show(name_lb);
216 name_te = gtk_entry_new();
217 gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 3);
218 gtk_widget_show(name_te);
220 /* Bottom row: Filter text entry */
221 bottom_hb = gtk_hbox_new(FALSE, 5);
222 gtk_container_add(GTK_CONTAINER(main_vb), bottom_hb);
223 gtk_widget_show(bottom_hb);
225 filter_lb = gtk_label_new("Filter string:");
226 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 3);
227 gtk_widget_show(filter_lb);
229 filter_te = gtk_entry_new();
230 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 3);
231 gtk_widget_show(filter_te);
235 gtk_list_select_child(GTK_LIST(filter_l), l_select);
236 } else if (filter_te_str && filter_te_str[0]) {
237 gtk_entry_set_text(GTK_ENTRY(name_te), "New filter");
238 gtk_entry_set_text(GTK_ENTRY(filter_te), filter_te_str);
245 filter_sel_list_cb(GtkWidget *l, gpointer data) {
247 gchar *name = "", *strval = "";
250 gint sensitivity = FALSE;
253 sl = GTK_LIST(l)->selection;
257 if (sl) { /* Something was selected */
258 l_item = GTK_OBJECT(sl->data);
259 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
261 filt = (filter_def *) flp->data;
263 strval = filt->strval;
268 /* Did you know that this function is called when the window is destroyed? */
270 if (!gtk_object_get_data(GTK_OBJECT(data), E_FILT_CM_KEY)) {
271 gtk_entry_set_text(GTK_ENTRY(name_te), name);
272 gtk_entry_set_text(GTK_ENTRY(filter_te), strval);
273 gtk_widget_set_sensitive(chg_bt, sensitivity);
274 gtk_widget_set_sensitive(copy_bt, sensitivity);
275 gtk_widget_set_sensitive(del_bt, sensitivity);
279 /* To do: add input checking to each of these callbacks */
282 filter_sel_new_cb(GtkWidget *w, gpointer data) {
284 gchar *name, *strval;
285 GtkWidget *nl_item, *nl_lb;
287 name = gtk_entry_get_text(GTK_ENTRY(name_te));
288 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
290 if (strlen(name) > 0 && strlen(strval) > 0) {
291 filt = (filter_def *) g_malloc(sizeof(filter_def));
292 filt->name = g_strdup(name);
293 filt->strval = g_strdup(strval);
294 fl = g_list_append(fl, filt);
295 nl_lb = gtk_label_new(filt->name);
296 nl_item = gtk_list_item_new();
297 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
298 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
299 gtk_widget_show(nl_lb);
300 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
301 gtk_widget_show(nl_item);
302 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
303 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
304 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
309 filter_sel_chg_cb(GtkWidget *w, gpointer data) {
311 gchar *name = "", *strval = "";
316 sl = GTK_LIST(filter_l)->selection;
317 name = gtk_entry_get_text(GTK_ENTRY(name_te));
318 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
320 if (sl) { /* Something was selected */
321 l_item = GTK_OBJECT(sl->data);
322 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
323 nl_lb = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
325 filt = (filter_def *) flp->data;
327 if (strlen(name) > 0 && strlen(strval) > 0 && filt) {
329 g_free(filt->strval);
330 filt->name = g_strdup(name);
331 filt->strval = g_strdup(strval);
332 gtk_label_set(nl_lb, filt->name);
339 filter_sel_copy_cb(GtkWidget *w, gpointer data) {
341 filter_def *filt, *nfilt;
342 gchar *prefix = "Copy of ";
344 GtkWidget *nl_item, *nl_lb;
346 sl = GTK_LIST(filter_l)->selection;
347 if (sl) { /* Something was selected */
348 l_item = GTK_OBJECT(sl->data);
349 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
351 filt = (filter_def *) flp->data;
352 nfilt = (filter_def *) g_malloc(sizeof(filter_def));
353 nfilt->name = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
354 sprintf(nfilt->name, "%s%s", prefix, filt->name);
355 nfilt->strval = g_strdup(filt->strval);
356 fl = g_list_append(fl, nfilt);
357 nl_lb = gtk_label_new(nfilt->name);
358 nl_item = gtk_list_item_new();
359 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
360 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
361 gtk_widget_show(nl_lb);
362 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
363 gtk_widget_show(nl_item);
364 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
365 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
366 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
372 filter_sel_del_cb(GtkWidget *w, gpointer data) {
378 sl = GTK_LIST(filter_l)->selection;
379 if (sl) { /* Something was selected */
380 l_item = GTK_OBJECT(sl->data);
381 pos = gtk_list_child_position(GTK_LIST(filter_l),
383 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
385 filt = (filter_def *) flp->data;
387 g_free(filt->strval);
389 fl = g_list_remove(fl, flp);
390 gtk_list_clear_items(GTK_LIST(filter_l), pos, pos + 1);
396 filter_prefs_ok(GtkWidget *w) {
400 GtkWidget *mw_filt = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY);
402 sl = GTK_LIST(filter_l)->selection;
403 if (sl && mw_filt) { /* Place something in the filter box. */
404 l_item = GTK_OBJECT(sl->data);
405 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
407 filt = (filter_def *) flp->data;
408 gtk_entry_set_text(GTK_ENTRY(mw_filt), filt->strval);
412 filter_prefs_cancel(w);
416 filter_prefs_save(GtkWidget *w) {
419 gchar *ff_path, *ff_dir = PF_DIR, *ff_name = "filters";
423 ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_dir) +
424 strlen(ff_name) + 4);
425 sprintf(ff_path, "%s/%s", getenv("HOME"), ff_dir);
427 if (stat(ff_path, &s_buf) != 0)
428 mkdir(ff_path, 0755);
430 sprintf(ff_path, "%s/%s/%s", getenv("HOME"), ff_dir, ff_name);
432 if ((ff = fopen(ff_path, "w")) != NULL) {
433 flp = g_list_first(fl);
435 filt = (filter_def *) flp->data;
436 fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
446 filter_prefs_cancel(GtkWidget *w) {
448 /* Let the list cb know we're about to destroy the widget tree, so it */
449 /* doesn't operate on widgets that don't exist. */
450 gtk_object_set_data(GTK_OBJECT(w), E_FILT_CM_KEY, (gpointer)TRUE);
451 gtk_widget_destroy(GTK_WIDGET(w));