2 * Routines for managing filter sets
4 * $Id: filter.c,v 1.7 1998/10/13 07:03:33 guy 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.
44 #define E_FILT_NAME_KEY "filter_name"
45 #define E_FILT_LBL_KEY "filter_label"
46 #define E_FILT_CM_KEY "in_cancel_mode"
48 GtkWidget *filter_l, *chg_bt, *copy_bt, *del_bt, *name_te, *filter_te;
51 void get_filter_list();
57 gchar *ff_path, *ff_name = ".ethereal/filters", f_buf[256];
58 gchar *name_begin, *name_end, *filt_begin;
63 /* To do: generalize this */
64 ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_name) + 4);
65 sprintf(ff_path, "%s/%s", getenv("HOME"), ff_name);
67 if ((ff = fopen(ff_path, "r")) == NULL) {
72 while (fgets(f_buf, 256, ff)) {
75 if (f_buf[len - 1] == '\n') {
79 name_begin = strchr(f_buf, '"');
81 if (name_begin == NULL)
83 name_end = strchr(name_begin + 1, '"');
84 /* No terminating quote */
85 if (name_end == NULL) {
86 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
91 filt_begin = name_end + 1;
92 while(isspace(filt_begin[0])) filt_begin++;
93 /* No filter string */
94 if (filt_begin[0] == '\0') {
95 g_warning("Malformed filter in '%s' line %d.", ff_path, line);
98 filt = (filter_def *) g_malloc(sizeof(filter_def));
99 filt->name = g_strdup(name_begin);
100 filt->strval = g_strdup(filt_begin);
101 fl = g_list_append(fl, filt);
107 /* filter_sel_pg - Create and display the filter selection widgets. */
108 /* Called when the 'Filter' preference notebook page is selected. */
110 filter_prefs_show(GtkWidget *w) {
111 GtkWidget *main_vb, *top_hb, *list_bb, *new_bt, *filter_sc,
112 *nl_item, *nl_lb, *middle_hb, *name_lb, *bottom_hb,
114 GtkWidget *l_select = NULL;
117 gchar *filter_te_str = NULL;
119 /* Make sure everything is set up */
122 filter_te_str = gtk_entry_get_text(GTK_ENTRY(w));
124 /* Container for each row of widgets */
125 main_vb = gtk_vbox_new(FALSE, 5);
126 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
127 gtk_widget_show(main_vb);
128 gtk_object_set_data(GTK_OBJECT(main_vb), E_FILT_CM_KEY, (gpointer)FALSE);
130 /* Top row: Filter list and buttons */
131 top_hb = gtk_hbox_new(FALSE, 5);
132 gtk_container_add(GTK_CONTAINER(main_vb), top_hb);
133 gtk_widget_show(top_hb);
135 list_bb = gtk_vbutton_box_new();
136 gtk_button_box_set_layout (GTK_BUTTON_BOX (list_bb), GTK_BUTTONBOX_START);
137 gtk_container_add(GTK_CONTAINER(top_hb), list_bb);
138 gtk_widget_show(list_bb);
140 new_bt = gtk_button_new_with_label ("New");
141 gtk_signal_connect(GTK_OBJECT(new_bt), "clicked",
142 GTK_SIGNAL_FUNC(filter_sel_new_cb), NULL);
143 gtk_container_add(GTK_CONTAINER(list_bb), new_bt);
144 gtk_widget_show(new_bt);
146 chg_bt = gtk_button_new_with_label ("Change");
147 gtk_widget_set_sensitive(chg_bt, FALSE);
148 gtk_signal_connect(GTK_OBJECT(chg_bt), "clicked",
149 GTK_SIGNAL_FUNC(filter_sel_chg_cb), NULL);
150 gtk_container_add(GTK_CONTAINER(list_bb), chg_bt);
151 gtk_widget_show(chg_bt);
153 copy_bt = gtk_button_new_with_label ("Copy");
154 gtk_widget_set_sensitive(copy_bt, FALSE);
155 gtk_signal_connect(GTK_OBJECT(copy_bt), "clicked",
156 GTK_SIGNAL_FUNC(filter_sel_copy_cb), NULL);
157 gtk_container_add(GTK_CONTAINER(list_bb), copy_bt);
158 gtk_widget_show(copy_bt);
160 del_bt = gtk_button_new_with_label ("Delete");
161 gtk_widget_set_sensitive(del_bt, FALSE);
162 gtk_signal_connect(GTK_OBJECT(del_bt), "clicked",
163 GTK_SIGNAL_FUNC(filter_sel_del_cb), NULL);
164 gtk_container_add(GTK_CONTAINER(list_bb), del_bt);
165 gtk_widget_show(del_bt);
167 filter_sc = gtk_scrolled_window_new(NULL, NULL);
168 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(filter_sc),
169 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
170 gtk_widget_set_usize(filter_sc, 250, 150);
171 gtk_container_add(GTK_CONTAINER(top_hb), filter_sc);
172 gtk_widget_show(filter_sc);
174 filter_l = gtk_list_new();
175 gtk_signal_connect(GTK_OBJECT(filter_l), "selection_changed",
176 GTK_SIGNAL_FUNC(filter_sel_list_cb), main_vb);
177 gtk_container_add(GTK_CONTAINER(filter_sc), filter_l);
178 gtk_widget_show(filter_l);
180 flp = g_list_first(fl);
182 filt = (filter_def *) flp->data;
183 nl_lb = gtk_label_new(filt->name);
184 nl_item = gtk_list_item_new();
185 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
186 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
187 gtk_widget_show(nl_lb);
188 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
189 gtk_widget_show(nl_item);
190 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
191 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, flp);
193 if (filter_te_str && filt->strval)
194 if (strcmp(filter_te_str, filt->strval) == 0)
200 /* Middle row: Filter name entry */
201 middle_hb = gtk_hbox_new(FALSE, 5);
202 gtk_container_add(GTK_CONTAINER(main_vb), middle_hb);
203 gtk_widget_show(middle_hb);
205 name_lb = gtk_label_new("Filter name:");
206 gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 3);
207 gtk_widget_show(name_lb);
209 name_te = gtk_entry_new();
210 gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 3);
211 gtk_widget_show(name_te);
213 /* Bottom row: Filter text entry */
214 bottom_hb = gtk_hbox_new(FALSE, 5);
215 gtk_container_add(GTK_CONTAINER(main_vb), bottom_hb);
216 gtk_widget_show(bottom_hb);
218 filter_lb = gtk_label_new("Filter string:");
219 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 3);
220 gtk_widget_show(filter_lb);
222 filter_te = gtk_entry_new();
223 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 3);
224 gtk_widget_show(filter_te);
227 gtk_list_select_child(GTK_LIST(filter_l), l_select);
233 filter_sel_list_cb(GtkWidget *l, gpointer data) {
235 gchar *name = "", *strval = "";
238 gint sensitivity = FALSE;
240 sl = GTK_LIST(l)->selection;
242 if (sl) { /* Something was selected */
243 l_item = GTK_OBJECT(sl->data);
244 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
246 filt = (filter_def *) flp->data;
248 strval = filt->strval;
253 /* Did you know that this function is called when the window is destroyed? */
255 if (!gtk_object_get_data(GTK_OBJECT(data), E_FILT_CM_KEY)) {
256 gtk_entry_set_text(GTK_ENTRY(name_te), name);
257 gtk_entry_set_text(GTK_ENTRY(filter_te), strval);
258 gtk_widget_set_sensitive(chg_bt, sensitivity);
259 gtk_widget_set_sensitive(copy_bt, sensitivity);
260 gtk_widget_set_sensitive(del_bt, sensitivity);
264 /* To do: add input checking to each of these callbacks */
267 filter_sel_new_cb(GtkWidget *w, gpointer data) {
269 gchar *name, *strval;
270 GtkWidget *nl_item, *nl_lb;
272 name = gtk_entry_get_text(GTK_ENTRY(name_te));
273 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
275 if (strlen(name) > 0 && strlen(strval) > 0) {
276 filt = (filter_def *) g_malloc(sizeof(filter_def));
277 filt->name = g_strdup(name);
278 filt->strval = g_strdup(strval);
279 fl = g_list_append(fl, filt);
280 nl_lb = gtk_label_new(filt->name);
281 nl_item = gtk_list_item_new();
282 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
283 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
284 gtk_widget_show(nl_lb);
285 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
286 gtk_widget_show(nl_item);
287 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
288 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
289 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
294 filter_sel_chg_cb(GtkWidget *w, gpointer data) {
296 gchar *name = "", *strval = "";
301 sl = GTK_LIST(filter_l)->selection;
302 name = gtk_entry_get_text(GTK_ENTRY(name_te));
303 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
305 if (sl) { /* Something was selected */
306 l_item = GTK_OBJECT(sl->data);
307 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
308 nl_lb = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
310 filt = (filter_def *) flp->data;
312 if (strlen(name) > 0 && strlen(strval) > 0 && filt) {
314 g_free(filt->strval);
315 filt->name = g_strdup(name);
316 filt->strval = g_strdup(strval);
317 gtk_label_set(nl_lb, filt->name);
324 filter_sel_copy_cb(GtkWidget *w, gpointer data) {
326 filter_def *filt, *nfilt;
327 gchar *prefix = "Copy of ";
329 GtkWidget *nl_item, *nl_lb;
331 sl = GTK_LIST(filter_l)->selection;
332 if (sl) { /* Something was selected */
333 l_item = GTK_OBJECT(sl->data);
334 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
336 filt = (filter_def *) flp->data;
337 nfilt = (filter_def *) g_malloc(sizeof(filter_def));
338 nfilt->name = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
339 sprintf(nfilt->name, "%s%s", prefix, filt->name);
340 nfilt->strval = g_strdup(filt->strval);
341 fl = g_list_append(fl, nfilt);
342 nl_lb = gtk_label_new(nfilt->name);
343 nl_item = gtk_list_item_new();
344 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
345 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
346 gtk_widget_show(nl_lb);
347 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
348 gtk_widget_show(nl_item);
349 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
350 gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_NAME_KEY, g_list_last(fl));
351 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
357 filter_sel_del_cb(GtkWidget *w, gpointer data) {
363 sl = GTK_LIST(filter_l)->selection;
364 if (sl) { /* Something was selected */
365 l_item = GTK_OBJECT(sl->data);
366 pos = gtk_list_child_position(GTK_LIST(filter_l),
368 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
370 filt = (filter_def *) flp->data;
372 g_free(filt->strval);
374 fl = g_list_remove_link(fl, flp);
375 gtk_list_clear_items(GTK_LIST(filter_l), pos, pos + 1);
381 filter_prefs_ok(GtkWidget *w) {
385 GtkWidget *mw_filt = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY);
387 sl = GTK_LIST(filter_l)->selection;
388 if (sl && mw_filt) { /* Place something in the filter box. */
389 l_item = GTK_OBJECT(sl->data);
390 flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY);
392 filt = (filter_def *) flp->data;
393 gtk_entry_set_text(GTK_ENTRY(mw_filt), filt->strval);
397 filter_prefs_cancel(w);
401 filter_prefs_save(GtkWidget *w) {
404 gchar *ff_path, *ff_dir = ".ethereal", *ff_name = "filters";
408 ff_path = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(ff_dir) +
409 strlen(ff_name) + 4);
410 sprintf(ff_path, "%s/%s", getenv("HOME"), ff_dir);
412 if (stat(ff_path, &s_buf) != 0)
413 mkdir(ff_path, 0755);
415 sprintf(ff_path, "%s/%s/%s", getenv("HOME"), ff_dir, ff_name);
417 if ((ff = fopen(ff_path, "w")) != NULL) {
418 flp = g_list_first(fl);
420 filt = (filter_def *) flp->data;
421 fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
431 filter_prefs_cancel(GtkWidget *w) {
433 /* Let the list cb know we're about to destroy the widget tree, so it */
434 /* doesn't operate on widgets that don't exist. */
435 gtk_object_set_data(GTK_OBJECT(w), E_FILT_CM_KEY, (gpointer)TRUE);
436 gtk_widget_destroy(GTK_WIDGET(w));