Have separate capture and display filter lists; some filter dialog boxes
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 28 Jan 2001 09:13:10 +0000 (09:13 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 28 Jan 2001 09:13:10 +0000 (09:13 +0000)
use the capture filter lists, and others use the display filter list, as
appropriate.

Have separate menu items for editing the capture and display filter
lists.

Have separate "~/.ethereal/cfilters" and "~/.ethereal/dfilters" files
for the two lists; if either of those files isn't found, we try
"~/.ethereal/filters", which means that you will start out with two
identical lists holding all your filters - if certain filters belong
only in one list, you'll have to delete them by hand from the other
list.

Do I/O error checking when reading and writing filter lists; when
writing a filter list, write it to a new file, and then rename the new
file on top of the old file, so that you don't lose your old filter list
if, for example, you run out of disk space or disk quota.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@2948 f5534014-38df-0310-8fa8-9805f1628bb7

doc/ethereal.pod.template
filters.c
filters.h
gtk/filter_prefs.c
gtk/filter_prefs.h
gtk/main.c
gtk/menu.c

index bbbbdc95cdf91a8a1a20a8a77334f7a2935e92d1..9d553e3bc22f033ad7e3799019e84e0c084c43b4 100644 (file)
@@ -264,11 +264,15 @@ Allows you to unmark all packets that are currently displayed.
 Sets the packet printing, column display, TCP stream coloring, and GUI
 options (see L<"Preferences"> below).
 
-=item Edit:Filters
+=item Edit:Capture Filters
 
-Edits the saved list of filters, allowing filters to be added, changed,
-or deleted, and lets a selected filter be applied to the current
-capture, if any.
+Edits the saved list of capture filters, allowing filters to be added,
+changed, or deleted.
+
+=item Edit:Display Filters
+
+Edits the saved list of display filters, allowing filters to be added,
+changed, or deleted.
 
 =item Edit:Protocols
 
@@ -468,8 +472,8 @@ of each column in the packet list.
 
 The I<Column title> entry is used to specify the title of the column
 displayed at the top of the packet list.  The type of data that the column
-displays can be specified using the I<Column format> option menu.  The row
-of buttons on the left perform the following actions:
+displays can be specified using the I<Column format> option menu.
+The row of buttons on the left perform the following actions:
 
 =over 6
 
@@ -553,21 +557,49 @@ controlling the way Ethereal handles those protocols.
 
 =back
 
-=item Filters
+=item Edit Capture Filter List
+
+=item Edit Display Filter List
+
+=item Capture Filter
+
+=item Display Filter
+
+=item Read Filter
+
+=item Search Filter
+
+The I<Edit Capture Filter List> dialog lets you create, modify, and
+delete capture filters, and the I<Edit Display Filter List> dialog lets
+you create, modify, and delete display filters.
+
+The I<Capture Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter to be used when
+capturing packets.
+
+The I<Display Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter to be used to
+filter the current capture being viewed.
+
+The I<Read Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter to be used to
+as a read filter for a capture file you open.
 
-The I<Filters> dialog lets you create and modify filters, and set the
-default filter to use when capturing data or opening a capture file.
+The I<Search Filter> dialog lets you do all of the editing operations
+listed, and also lets you choose or construct a filter expression to be
+used in a find operation.
 
-The I<Filter name> entry specifies a descriptive name for a filter, e.g.
-B<Web and DNS traffic>.  The I<Filter string> entry is the text that
-actually describes the filtering action to take, as described above.The
-dialog buttons perform the following actions:
+In all of those dialogs, the I<Filter name> entry specifies a
+descriptive name for a filter, e.g.  B<Web and DNS traffic>.  The
+I<Filter string> entry is the text that actually describes the filtering
+action to take, as described above.The dialog buttons perform the
+following actions:
 
 =over 6
 
 =item New
 
-If there is text in the two entry boxes, it creates a new associated list
+If there is text in the two entry boxes, creates a new associated list
 item.
 
 =item Change
@@ -585,26 +617,39 @@ Deletes the currently selected list item.
 
 =item Add Expression...
 
-Pops up a dialog box to allow you to construct a filter expression to
-test a particular field; it offers lists of field names, and, when
-appropriate, lists from which to select tests to perform on the field
-and values with which to compare it.
+For display filter expressions, pops up a dialog box to allow you to
+construct a filter expression to test a particular field; it offers
+lists of field names, and, when appropriate, lists from which to select
+tests to perform on the field and values with which to compare it.  In
+that dialog box, the OK button will cause the filter expression you
+constructed to be entered into the I<Filter string> entry at the current
+cursor position.
 
 =item OK
 
-Sets the filter in the I<Filter string> entry as the active filter.  If
-nothing is selected, turns filtering off.
+In the I<Edit Capture Filter List> and I<Edit Display Filter List>
+dialogs, closes the dialog box.  In the I<Capture Filter> dialog, closes
+the dialog box and makes the filter in the I<Filter string> entry the
+filter in the I<Capture Preferences> dialog.  In the I<Display Filter>
+dialog, closes the dialog box and makes the filter in the I<Filter
+string> entry the current display filter, and applies it to the current
+capture.  In the I<Read Filter> dialog, closes the dialog box and makes
+the filter in the I<Filter string> entry the filter in the I<Open
+Capture File> dialog.  In the I<Search Filter> dialog, closes the dialog
+box and makes the filter in the I<Filter string> entry the filter in the
+I<Find Frame> dialog.
 
 =item Apply
 
-Sets the filter in the I<Filter string> entry as the active filter, and
-applies it to the current capture, if any.  (The currently selected list
-item must be a display filter, not a capture filter.) If nothing is
-selected, turns filtering off.
+Makes the filter in the I<Filter string> entry the current display
+filter, and applies it to the current capture.
 
 =item Save
 
-Saves the current filter list in F<$HOME/.ethereal/filters>.
+Saves the current filter list in F<$HOME/.ethereal/cfilters> if the list
+of filters being edited is the list of capture filters or in
+F<$HOME/.ethereal/dfilters> if the list of filters being edited is the
+list of display filters.
 
 =item Cancel
 
index 682a37c9c7b4a001fc52b1f74cb86f53e91de526..2aeacbf1d60b1041098d3af5b98150595dbdf41c 100644 (file)
--- a/filters.c
+++ b/filters.c
@@ -1,7 +1,7 @@
 /* filters.c
  * Code for reading and writing the filters file.
  *
- * $Id: filters.c,v 1.2 2001/01/28 04:52:28 guy Exp $
+ * $Id: filters.c,v 1.3 2001/01/28 09:13:07 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #include "filters.h"
 #include "util.h"
 
+/*
+ * Old filter file name.
+ */
+#define FILTER_FILE_NAME       "filters"
+
+/*
+ * Capture filter file name.
+ */
+#define CFILTER_FILE_NAME      "cfilters"
+
+/*
+ * Display filter file name.
+ */
+#define DFILTER_FILE_NAME      "dfilters"
+
 #define        FILTER_LINE_SIZE        2048
 
 /*
- * List of filters.
+ * List of capture filters.
+ */
+static GList *capture_filters = NULL;
+
+/*
+ * List of display filters.
  */
-GList       *fl = NULL;
+static GList *display_filters = NULL;
 
+/*
+ * Read in a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
 void
-get_filter_list(void)
+read_filter_list(filter_list_type_t list, char **pref_path_return,
+    int *errno_return)
 {
-  GList      *flp;
-  filter_def *filt;
+  char       *ff_path, *ff_dir = PF_DIR, *ff_name;
   FILE       *ff;
-  gchar      *ff_path, *ff_name = PF_DIR "/filters", f_buf[FILTER_LINE_SIZE];
-  gchar      *name_begin, *name_end, *filt_begin;
+  GList      **flp;
+  GList      *fl_ent;
+  filter_def *filt;
+  char       f_buf[FILTER_LINE_SIZE];
+  char       *name_begin, *name_end, *filt_begin;
   int         len, line = 0;
 
-  /* If we already have a list of filters, discard it. */
-  if (fl != NULL) {
-    flp = g_list_first(fl);
-    while (flp) {
-      filt = (filter_def *) flp->data;
-      g_free(filt->name);
-      g_free(filt->strval);
-      g_free(filt);
-      flp = flp->next;
-    }
-    g_list_free(fl);
-    fl = NULL;
+  *pref_path_return = NULL;    /* assume no error */
+
+  switch (list) {
+
+  case CFILTER_LIST:
+    ff_name = CFILTER_FILE_NAME;
+    flp = &capture_filters;
+    break;
+
+  case DFILTER_LIST:
+    ff_name = DFILTER_FILE_NAME;
+    flp = &display_filters;
+    break;
+
+  default:
+    g_assert_not_reached();
+    return;
   }
 
   /* To do: generalize this */
-  ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_name) +  4);
-  sprintf(ff_path, "%s/%s", get_home_dir(), ff_name);
+  ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_dir) +  
+    strlen(ff_name) + 4);
+  sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, ff_name);
 
   if ((ff = fopen(ff_path, "r")) == NULL) {
-    g_free(ff_path);
-    return;
+    /*
+     * Did that fail because we the file didn't exist?
+     */
+    if (errno != ENOENT) {
+      /*
+       * No.  Just give up.
+       */
+      *pref_path_return = ff_path;
+      *errno_return = errno;
+      return;
+    }
+
+    /*
+     * Yes.  See if there's a "filters" file; if so, read it.
+     * This means that a user will start out with their capture and
+     * display filter lists being identical; each list may contain
+     * filters that don't belong in that list.  The user can edit
+     * the filter lists, and delete the ones that don't belong in
+     * a particular list.
+     */
+    sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, FILTER_FILE_NAME);
+    if ((ff = fopen(ff_path, "r")) == NULL) {
+      /*
+       * Well, that didn't work, either.  Just give up.
+       * Return an error if the file existed but we couldn't open it.
+       */
+      if (errno != ENOENT) {
+       *pref_path_return = ff_path;
+       *errno_return = errno;
+      }
+      return;
+    }
+  }
+
+  /* If we already have a list of filters, discard it. */
+  if (*flp != NULL) {
+    fl_ent = g_list_first(*flp);
+    while (fl_ent != NULL) {
+      filt = (filter_def *) fl_ent->data;
+      g_free(filt->name);
+      g_free(filt->strval);
+      g_free(filt);
+      fl_ent = fl_ent->next;
+    }
+    g_list_free(*flp);
+    *flp = NULL;
   }
 
   while (fgets(f_buf, FILTER_LINE_SIZE, ff)) {
@@ -115,23 +197,130 @@ get_filter_list(void)
     filt         = (filter_def *) g_malloc(sizeof(filter_def));
     filt->name   = g_strdup(name_begin);
     filt->strval = g_strdup(filt_begin);
-    fl = g_list_append(fl, filt);
+    *flp = g_list_append(*flp, filt);
   }
+  if (ferror(ff)) {
+    *pref_path_return = ff_path;
+    *errno_return = errno;
+  } else
+    g_free(ff_path);
   fclose(ff);
-  g_free(ff_path);
 }
 
+/*
+ * Get a pointer to a list of filters.
+ */
+static GList **
+get_filter_list(filter_list_type_t list)
+{
+  GList **flp;
+
+  switch (list) {
+
+  case CFILTER_LIST:
+    flp = &capture_filters;
+    break;
+
+  case DFILTER_LIST:
+    flp = &display_filters;
+    break;
+
+  default:
+    g_assert_not_reached();
+    flp = NULL;
+  }
+  return flp;
+}
+
+/*
+ * Get a pointer to the first entry in a filter list.
+ */
+GList *
+get_filter_list_first(filter_list_type_t list)
+{
+  GList      **flp;
+  
+  flp = get_filter_list(list);
+  return g_list_first(*flp);
+}
+
+/*
+ * Add a new filter to the end of a list.
+ * Returns a pointer to the newly-added entry.
+ */
+GList *
+add_to_filter_list(filter_list_type_t list, char *name, char *expression)
+{
+  GList      **flp;
+  filter_def *filt;
+  
+  flp = get_filter_list(list);
+  filt = (filter_def *) g_malloc(sizeof(filter_def));
+  filt->name = g_strdup(name);
+  filt->strval = g_strdup(expression);
+  *flp = g_list_append(*flp, filt);
+  return g_list_last(*flp);
+}
+
+/*
+ * Remove a filter from a list.
+ */
+void
+remove_from_filter_list(filter_list_type_t list, GList *fl_entry)
+{
+  GList      **flp;
+  filter_def *filt;
+  
+  flp = get_filter_list(list);
+  filt = (filter_def *) fl_entry->data;
+  g_free(filt->name);
+  g_free(filt->strval);
+  g_free(filt);
+  *flp = g_list_remove_link(*flp, fl_entry);
+}
+
+/*
+ * Write out a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
 void
-save_filter_list(void)
+save_filter_list(filter_list_type_t list, char **pref_path_return,
+    int *errno_return)
 {
+  gchar      *ff_path, *ff_path_new, *ff_dir = PF_DIR, *ff_name;
+  int         path_length;
+  GList      *fl;
   GList      *flp;
   filter_def *filt;
-  gchar      *ff_path, *ff_dir = PF_DIR, *ff_name = "filters";
   FILE       *ff;
   struct stat s_buf;
   
-  ff_path = (gchar *) g_malloc(strlen(get_home_dir()) + strlen(ff_dir) +  
-    strlen(ff_name) + 4);
+  *pref_path_return = NULL;    /* assume no error */
+
+  switch (list) {
+
+  case CFILTER_LIST:
+    ff_name = CFILTER_FILE_NAME;
+    fl = capture_filters;
+    break;
+
+  case DFILTER_LIST:
+    ff_name = DFILTER_FILE_NAME;
+    fl = display_filters;
+    break;
+
+  default:
+    g_assert_not_reached();
+    return;
+  }
+
+  path_length = strlen(get_home_dir()) + strlen(ff_dir) + strlen(ff_name)
+               + 4 + 4;
+  ff_path = (gchar *) g_malloc(path_length);
   sprintf(ff_path, "%s/%s", get_home_dir(), ff_dir);
 
   if (stat(ff_path, &s_buf) != 0)
@@ -143,15 +332,50 @@ save_filter_list(void)
     
   sprintf(ff_path, "%s/%s/%s", get_home_dir(), ff_dir, ff_name);
 
-  if ((ff = fopen(ff_path, "w")) != NULL) {
-    flp = g_list_first(fl);
-    while (flp) {
-      filt = (filter_def *) flp->data;
-      fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
-      flp = flp->next;
+  /* Write to "XXX.new", and rename if that succeeds.
+     That means we don't trash the file if we fail to write it out
+     completely. */
+  ff_path_new = (gchar *) g_malloc(path_length);
+  sprintf(ff_path_new, "%s/%s/%s.new", get_home_dir(), ff_dir, ff_name);
+
+  if ((ff = fopen(ff_path_new, "w")) == NULL) {
+    *pref_path_return = ff_path;
+    *errno_return = errno;
+    g_free(ff_path_new);
+    return;
+  }
+  flp = g_list_first(fl);
+  while (flp) {
+    filt = (filter_def *) flp->data;
+    fprintf(ff, "\"%s\" %s\n", filt->name, filt->strval);
+    if (ferror(ff)) {
+      *pref_path_return = ff_path;
+      *errno_return = errno;
+      fclose(ff);
+      unlink(ff_path_new);
+      g_free(ff_path_new);
+      return;
     }
-    fclose(ff);
+    flp = flp->next;
+  }
+  if (fclose(ff) == EOF) {
+    *pref_path_return = ff_path;
+    *errno_return = errno;
+    unlink(ff_path_new);
+    g_free(ff_path_new);
+    return;
   }
 
+  /* XXX - does "rename()" exist on Win32?  If so, does it remove the
+     target first?  If so, does that mean it's not atomic? */
+  if (rename(ff_path_new, ff_path) < 0) {
+    *pref_path_return = ff_path;
+    *errno_return = errno;
+    unlink(ff_path_new);
+    g_free(ff_path);
+    g_free(ff_path_new);
+    return;
+  }
+  g_free(ff_path_new);
   g_free(ff_path);
 }
index 8839af72d800cbbb5d5733bca8b8076618cb6a66..bf0a000e3895f25cce6de1cba33f134251bc5a7f 100644 (file)
--- a/filters.h
+++ b/filters.h
@@ -1,7 +1,7 @@
 /* filters.c
  * Declarations of routines for reading and writing the filters file.
  *
- * $Id: filters.h,v 1.1 2001/01/28 04:43:24 guy Exp $
+ * $Id: filters.h,v 1.2 2001/01/28 09:13:07 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
  */
 
 /*
- * List of filters.
+ * Filter lists.
  */
-extern GList       *fl;
+typedef enum {
+       CFILTER_LIST,   /* capture filter list */
+       DFILTER_LIST    /* display filter list */
+} filter_list_type_t;
 
 /*
  * Item in a list of filters.
@@ -36,6 +39,41 @@ typedef struct {
   char *strval;                /* filter expression */
 } filter_def;
 
-void get_filter_list(void);
+/*
+ * Read in a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
+void read_filter_list(filter_list_type_t list, char **pref_path_return,
+    int *errno_return);
+
+/*
+ * Get a pointer to the first entry in a filter list.
+ */
+GList *get_filter_list_first(filter_list_type_t list);
 
-void save_filter_list(void);
+/*
+ * Add a new filter to the end of a list.
+ * Returns a pointer to the newly-added entry.
+ */
+GList *add_to_filter_list(filter_list_type_t list, char *name,
+    char *expression);
+
+/*
+ * Remove a filter from a list.
+ */
+void remove_from_filter_list(filter_list_type_t list, GList *fl_entry);
+
+/*
+ * Write out a list of filters.
+ *
+ * On success, "*pref_path_return" is set to NULL.
+ * On error, "*pref_path_return" is set to point to the pathname of
+ * the file we tried to read - it should be freed by our caller -
+ * and "*errno_return" is set to the error.
+ */
+void save_filter_list(filter_list_type_t list, char **pref_path_return,
+    int *errno_return);
index 6a78c809cb27ef07f5d1013391d0d13a33a694a1..43f1bcc3fd2d90f7096487e0a3172ddfa9af93ab 100644 (file)
@@ -3,7 +3,7 @@
  * (This used to be a notebook page under "Preferences", hence the
  * "prefs" in the file name.)
  *
- * $Id: filter_prefs.c,v 1.25 2001/01/28 04:52:29 guy Exp $
+ * $Id: filter_prefs.c,v 1.26 2001/01/28 09:13:09 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -29,6 +29,8 @@
 # include "config.h"
 #endif
 
+#include <string.h>
+
 #include <gtk/gtk.h>
 
 #include <epan.h>
@@ -38,6 +40,7 @@
 #include "filter_prefs.h"
 #include "dlg_utils.h"
 #include "ui_util.h"
+#include "simple_dialog.h"
 #include "prefs_dlg.h"
 #include "dfilter_expr_dlg.h"
 
@@ -60,7 +63,7 @@ typedef struct _filter_cb_data {
 } filter_cb_data;
 
 static GtkWidget *filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te,
-    construct_args_t *construct_args, gboolean wants_add_expression_button);
+    filter_list_type_t list, construct_args_t *construct_args);
 static void filter_dlg_dclick(GtkWidget *dummy, gpointer main_w_arg);
 static void filter_dlg_ok_cb(GtkWidget *ok_bt, gpointer dummy);
 static void filter_dlg_apply_cb(GtkWidget *apply_bt, gpointer dummy);
@@ -133,8 +136,8 @@ capture_filter_construct_cb(GtkWidget *w, gpointer user_data)
        parent_filter_te = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY);
 
        /* Now create a new dialog, without an "Add Expression..." button. */
-       filter_browse_w = filter_dialog_new(caller, parent_filter_te, &args,
-           FALSE);
+       filter_browse_w = filter_dialog_new(caller, parent_filter_te,
+           CFILTER_LIST, &args);
 
        /* Set the E_FILT_CALLER_PTR_KEY for the new dialog to point to
           our caller. */
@@ -187,7 +190,7 @@ display_filter_construct_cb(GtkWidget *w, gpointer construct_args_ptr)
        /* Now create a new dialog, possibly with an "Apply" button, and
           definitely with an "Add Expression..." button. */
        filter_browse_w = filter_dialog_new(caller, parent_filter_te,
-           construct_args, TRUE);
+           DFILTER_LIST, construct_args);
 
        /* Set the E_FILT_CALLER_PTR_KEY for the new dialog to point to
           our caller. */
@@ -199,25 +202,57 @@ display_filter_construct_cb(GtkWidget *w, gpointer construct_args_ptr)
            filter_browse_w);
 }
 
-static GtkWidget *global_filter_w;
+static GtkWidget *global_cfilter_w;
+
+/* Create a filter dialog for editing capture filters; this is to be used
+   as a callback for menu items, toolbars, etc.. */
+void
+cfilter_dialog_cb(GtkWidget *w)
+{
+       /* No Apply button, and there's no text widget to set, much less
+          activate, on "OK". */
+       static construct_args_t args = {
+               "Ethereal: Edit Capture Filter List",
+               FALSE,
+               FALSE
+       };
+
+       /* Has a filter dialog box already been opened for editing
+          capture filters? */
+       if (global_cfilter_w != NULL) {
+               /* Yes.  Just reactivate it. */
+               reactivate_window(global_cfilter_w);
+               return;
+       }
+
+       /*
+        * No.  Create one; we didn't pop this up as a result of pressing
+        * a button next to some text entry field, so don't associate it
+        * with a text entry field.
+        */
+       global_cfilter_w = filter_dialog_new(NULL, NULL, CFILTER_LIST, &args);
+}
+
+static GtkWidget *global_dfilter_w;
 
-/* Create a filter dialog for editing; this is to be used as a callback
-   for menu items, toolbars, etc.. */
+/* Create a filter dialog for editing display filters; this is to be used
+   as a callback for menu items, toolbars, etc.. */
 void
-filter_dialog_cb(GtkWidget *w)
+dfilter_dialog_cb(GtkWidget *w)
 {
        /* No Apply button, and there's no text widget to set, much less
           activate, on "OK". */
        static construct_args_t args = {
-               "Ethereal: Edit Filter List",
+               "Ethereal: Edit Display Filter List",
                FALSE,
                FALSE
        };
 
-       /* Has a filter dialog box already been opened for editing? */
-       if (global_filter_w != NULL) {
+       /* Has a filter dialog box already been opened for editing
+          display filters? */
+       if (global_dfilter_w != NULL) {
                /* Yes.  Just reactivate it. */
-               reactivate_window(global_filter_w);
+               reactivate_window(global_dfilter_w);
                return;
        }
 
@@ -226,30 +261,66 @@ filter_dialog_cb(GtkWidget *w)
         * a button next to some text entry field, so don't associate it
         * with a text entry field.
         */
-       global_filter_w = filter_dialog_new(NULL, NULL, &args, TRUE);
+       global_dfilter_w = filter_dialog_new(NULL, NULL, DFILTER_LIST, &args);
 }
 
-/* List of filter dialogs, so that if the list of filters changes (the
-   model, if you will), we can update all of their lists displaying
+/* List of capture filter dialogs, so that if the list of filters changes
+  (the model, if you will), we can update all of their lists displaying
+   the filters (the views). */
+static GList *cfilter_dialogs;
+
+/* List of display filter dialogs, so that if the list of filters changes
+  (the model, if you will), we can update all of their lists displaying
    the filters (the views). */
-static GList *filter_dialogs;
+static GList *dfilter_dialogs;
 
 static void
-remember_filter_dialog(GtkWidget *main_w)
+remember_filter_dialog(GtkWidget *main_w, GList **filter_dialogs)
 {
-  filter_dialogs = g_list_append(filter_dialogs, main_w);
+       *filter_dialogs = g_list_append(*filter_dialogs, main_w);
 }
 
-/* Remove a filter dialog from the list of filter_dialogss. */
+/* Remove a filter dialog from the specified list of filter_dialogs. */
 static void
-forget_filter_dialog(GtkWidget *main_w)
+forget_filter_dialog(GtkWidget *main_w, filter_list_type_t list)
+{
+       switch (list) {
+
+       case CFILTER_LIST:
+               cfilter_dialogs = g_list_remove(cfilter_dialogs, main_w);
+               break;
+
+       case DFILTER_LIST:
+               dfilter_dialogs = g_list_remove(dfilter_dialogs, main_w);
+               break;
+
+       default:
+               g_assert_not_reached();
+               break;
+       }
+}
+
+/* Get the dialog list corresponding to a particular filter list. */
+static GList *
+get_filter_dialog_list(filter_list_type_t list)
 {
-       filter_dialogs = g_list_remove(filter_dialogs, main_w);
+       switch (list) {
+
+       case CFILTER_LIST:
+               return cfilter_dialogs;
+
+       case DFILTER_LIST:
+               return dfilter_dialogs;
+
+       default:
+               g_assert_not_reached();
+               return NULL;
+       }
 }
 
 static GtkWidget *
 filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
-    construct_args_t *construct_args, gboolean wants_add_expression_button)
+    filter_list_type_t list, construct_args_t *construct_args)
 {
        GtkWidget       *main_w,                /* main window */
                        *main_vb,               /* main container */
@@ -277,9 +348,35 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
                        *filter_te,
                        *add_expression_bt;
        GtkWidget       *l_select = NULL;
-       GList           *flp = NULL;
+       GList           *fl_entry;
        filter_def      *filt;
        gchar           *filter_te_str = NULL;
+       GList           **filter_dialogs;
+       static filter_list_type_t cfilter_list = CFILTER_LIST;
+       static filter_list_type_t dfilter_list = DFILTER_LIST;
+       filter_list_type_t *filter_list_p;
+
+       /* Get a pointer to a static variable holding the type of filter on
+          which we're working, so we can pass that pointer to callback
+          routines. */
+       switch (list) {
+
+       case CFILTER_LIST:
+               filter_dialogs = &cfilter_dialogs;
+               filter_list_p = &cfilter_list;
+               break;
+
+       case DFILTER_LIST:
+               filter_dialogs = &dfilter_dialogs;
+               filter_list_p = &dfilter_list;
+               break;
+
+       default:
+               g_assert_not_reached();
+               filter_dialogs = NULL;
+               filter_list_p = NULL;
+               break;
+       }
 
        main_w = dlg_window_new(construct_args->title);
        gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_CONSTRUCT_ARGS_KEY,
@@ -288,7 +385,7 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
        /* Call a handler when we're destroyed, so we can inform
           our caller, if any, that we've been destroyed. */
        gtk_signal_connect(GTK_OBJECT(main_w), "destroy",
-           GTK_SIGNAL_FUNC(filter_dlg_destroy), NULL);
+           GTK_SIGNAL_FUNC(filter_dlg_destroy), filter_list_p);
 
        main_vb = gtk_vbox_new(FALSE, 5);
        gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
@@ -316,14 +413,14 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
 
        new_bt = gtk_button_new_with_label ("New");
        gtk_signal_connect(GTK_OBJECT(new_bt), "clicked",
-           GTK_SIGNAL_FUNC(filter_new_bt_clicked_cb), NULL);
+           GTK_SIGNAL_FUNC(filter_new_bt_clicked_cb), filter_list_p);
        gtk_container_add(GTK_CONTAINER(list_bb), new_bt);
        gtk_widget_show(new_bt);
 
        chg_bt = gtk_button_new_with_label ("Change");
        gtk_widget_set_sensitive(chg_bt, FALSE);
        gtk_signal_connect(GTK_OBJECT(chg_bt), "clicked",
-           GTK_SIGNAL_FUNC(filter_chg_bt_clicked_cb), NULL);
+           GTK_SIGNAL_FUNC(filter_chg_bt_clicked_cb), filter_list_p);
        gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_CHG_BT_KEY, chg_bt);
        gtk_signal_connect(GTK_OBJECT(chg_bt), "destroy",
            GTK_SIGNAL_FUNC(filter_chg_bt_destroy_cb), NULL);
@@ -333,7 +430,7 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
        copy_bt = gtk_button_new_with_label ("Copy");
        gtk_widget_set_sensitive(copy_bt, FALSE);
        gtk_signal_connect(GTK_OBJECT(copy_bt), "clicked",
-           GTK_SIGNAL_FUNC(filter_copy_bt_clicked_cb), NULL);
+           GTK_SIGNAL_FUNC(filter_copy_bt_clicked_cb), filter_list_p);
        gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_COPY_BT_KEY, copy_bt);
        gtk_signal_connect(GTK_OBJECT(copy_bt), "destroy",
            GTK_SIGNAL_FUNC(filter_copy_bt_destroy_cb), NULL);
@@ -343,14 +440,14 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
        del_bt = gtk_button_new_with_label ("Delete");
        gtk_widget_set_sensitive(del_bt, FALSE);
        gtk_signal_connect(GTK_OBJECT(del_bt), "clicked",
-           GTK_SIGNAL_FUNC(filter_del_bt_clicked_cb), NULL);
+           GTK_SIGNAL_FUNC(filter_del_bt_clicked_cb), filter_list_p);
        gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_DEL_BT_KEY, del_bt);
        gtk_signal_connect(GTK_OBJECT(del_bt), "destroy",
            GTK_SIGNAL_FUNC(filter_del_bt_destroy_cb), NULL);
        gtk_container_add(GTK_CONTAINER(list_bb), del_bt);
        gtk_widget_show(del_bt);
 
-       if (wants_add_expression_button) {
+       if (list == DFILTER_LIST) {
                /* Create the "Add Expression..." button, to pop up a dialog
                   for constructing filter comparison expressions. */
                add_expression_bt = gtk_button_new_with_label("Add Expression...");
@@ -381,9 +478,9 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
        gtk_object_set_data(GTK_OBJECT(filter_l), E_FILT_DBLFUNC_KEY, filter_dlg_dclick);
        gtk_object_set_data(GTK_OBJECT(filter_l), E_FILT_DBLARG_KEY, main_w);
 
-       flp = g_list_first(fl);
-       while (flp) {
-               filt    = (filter_def *) flp->data;
+       fl_entry = get_filter_list_first(list);
+       while (fl_entry != NULL) {
+               filt    = (filter_def *) fl_entry->data;
                nl_lb   = gtk_label_new(filt->name);
                nl_item = gtk_list_item_new();
 
@@ -396,14 +493,15 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
                gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
                gtk_widget_show(nl_item);
                gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LBL_KEY, nl_lb);
-               gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LIST_ITEM_MODEL_KEY, flp);
+               gtk_object_set_data(GTK_OBJECT(nl_item), E_FILT_LIST_ITEM_MODEL_KEY,
+                   fl_entry);
 
                if (filter_te_str && filt->strval) {
                        if (strcmp(filter_te_str, filt->strval) == 0)
                                l_select = nl_item;
                }
 
-               flp = flp->next;
+               fl_entry = fl_entry->next;
        }
 
        /* Middle row: Filter name entry */
@@ -475,7 +573,7 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
 
        save_bt = gtk_button_new_with_label ("Save");
        gtk_signal_connect(GTK_OBJECT(save_bt), "clicked",
-               GTK_SIGNAL_FUNC(filter_dlg_save_cb), GTK_OBJECT(main_w));
+               GTK_SIGNAL_FUNC(filter_dlg_save_cb), filter_list_p);
        GTK_WIDGET_SET_FLAGS(save_bt, GTK_CAN_DEFAULT);
        gtk_box_pack_start(GTK_BOX(bbox), save_bt, TRUE, TRUE, 0);
        gtk_widget_show(save_bt);
@@ -489,7 +587,7 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te,
 
        dlg_set_cancel(main_w, cancel_bt);
 
-       remember_filter_dialog(main_w);
+       remember_filter_dialog(main_w, filter_dialogs);
 
        gtk_widget_show(main_w);
 
@@ -585,9 +683,36 @@ filter_apply(GtkWidget *main_w)
 }
 
 static void
-filter_dlg_save_cb(GtkWidget *save_bt, gpointer parent_w)
+filter_dlg_save_cb(GtkWidget *save_bt, gpointer data)
 {
-       save_filter_list();
+       filter_list_type_t list = *(filter_list_type_t *)data;
+       char *f_path;
+       int f_save_errno;
+       char *filter_type;
+
+       save_filter_list(list, &f_path, &f_save_errno);
+       if (f_path != NULL) {
+               /* We had an error saving the filter. */
+               switch (list) {
+
+               case CFILTER_LIST:
+                       filter_type = "capture";
+                       break;
+
+               case DFILTER_LIST:
+                       filter_type = "display";
+                       break;
+
+               default:
+                       g_assert_not_reached();
+                       filter_type = NULL;
+                       break;
+               }
+               simple_dialog(ESD_TYPE_CRIT, NULL,
+                   "Could not save to your %s filter file\n\"%s\": %s.",
+                   filter_type, f_path, strerror(f_save_errno));
+               g_free(f_path);
+       }
 }
 
 static void
@@ -599,6 +724,7 @@ filter_dlg_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w)
 static void
 filter_dlg_destroy(GtkWidget *win, gpointer data)
 {
+       filter_list_type_t list = *(filter_list_type_t *)data;
        GtkWidget *caller;
 
        /* Get the widget that requested that we be popped up, if any.
@@ -613,12 +739,26 @@ filter_dlg_destroy(GtkWidget *win, gpointer data)
        } else {
                /* This is an editing dialog popped up from, for example,
                   a menu item; note that we no longer have one. */
-               g_assert(win == global_filter_w);
-               global_filter_w = NULL;
+               switch (list) {
+
+               case CFILTER_LIST:
+                       g_assert(win == global_cfilter_w);
+                       global_cfilter_w = NULL;
+                       break;
+
+               case DFILTER_LIST:
+                       g_assert(win == global_dfilter_w);
+                       global_dfilter_w = NULL;
+                       break;
+
+               default:
+                       g_assert_not_reached();
+                       break;
+               }
        }
 
        /* Remove this from the list of filter dialog windows. */
-       forget_filter_dialog(win);
+       forget_filter_dialog(win, list);
 
        /* Now nuke this window. */
        gtk_grab_remove(GTK_WIDGET(win));
@@ -760,7 +900,8 @@ filter_new_bt_clicked_cb(GtkWidget *w, gpointer data)
   GtkWidget  *name_te = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_NAME_TE_KEY);
   GtkWidget  *filter_te = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_TE_KEY);
   GtkWidget  *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
-  filter_def *filt;
+  filter_list_type_t list = *(filter_list_type_t *)data;
+  GList      *fl_entry;
   gchar      *name, *strval;
   new_filter_cb_args_t args;
   
@@ -768,16 +909,14 @@ filter_new_bt_clicked_cb(GtkWidget *w, gpointer data)
   strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
   
   if (strlen(name) > 0 && strlen(strval) > 0) {
-    filt         = (filter_def *) g_malloc(sizeof(filter_def));
-    filt->name   = g_strdup(name);
-    filt->strval = g_strdup(strval);
-    fl           = g_list_append(fl, filt);
+    /* Add a new entry to the filter list. */
+    fl_entry = add_to_filter_list(list, name, strval);
 
     /* Update all the filter list widgets, not just the one in
        the dialog box in which we clicked on "Copy". */
     args.active_filter_l = filter_l;
-    args.nflp = g_list_last(fl);
-    g_list_foreach(filter_dialogs, new_filter_cb, &args);
+    args.nflp = fl_entry;
+    g_list_foreach(get_filter_dialog_list(list), new_filter_cb, &args);
   }
 }
 
@@ -817,9 +956,10 @@ filter_chg_bt_clicked_cb(GtkWidget *w, gpointer data)
   GtkWidget  *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
   filter_def *filt;
   gchar      *name = "", *strval = "";
-  GList      *sl, *flp;
+  GList      *sl, *fl_entry;
   GtkObject  *l_item;
   GtkLabel   *nl_lb;
+  filter_list_type_t list = *(filter_list_type_t *)data;
 
   sl     = GTK_LIST(filter_l)->selection;
   name   = gtk_entry_get_text(GTK_ENTRY(name_te));
@@ -827,10 +967,10 @@ filter_chg_bt_clicked_cb(GtkWidget *w, gpointer data)
 
   if (sl) {  /* Something was selected */
     l_item = GTK_OBJECT(sl->data);
-    flp    = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
-    nl_lb  = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
-    if (flp && nl_lb) {
-      filt = (filter_def *) flp->data;
+    fl_entry = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
+    nl_lb = (GtkLabel *) gtk_object_get_data(l_item, E_FILT_LBL_KEY);
+    if (fl_entry != NULL && nl_lb != NULL) {
+      filt = (filter_def *) fl_entry->data;
       
       if (strlen(name) > 0 && strlen(strval) > 0 && filt) {
         g_free(filt->name);
@@ -840,7 +980,7 @@ filter_chg_bt_clicked_cb(GtkWidget *w, gpointer data)
 
         /* Update all the filter list widgets, not just the one in
            the dialog box in which we clicked on "Copy". */
-        g_list_foreach(filter_dialogs, chg_filter_cb, flp);
+        g_list_foreach(get_filter_dialog_list(list), chg_filter_cb, fl_entry);
       }
     }
   }
@@ -859,29 +999,30 @@ filter_copy_bt_clicked_cb(GtkWidget *w, gpointer data)
 {
   GtkWidget  *main_w = gtk_widget_get_toplevel(w);
   GtkWidget  *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
-  GList      *sl, *flp;
-  filter_def *filt, *nfilt;
-  gchar      *prefix = "Copy of ";
+  GList      *sl, *fl_entry, *nfl_entry;
+  gchar      *prefix = "Copy of ", *name;
   GtkObject  *l_item;
+  filter_def *filt;
+  filter_list_type_t list = *(filter_list_type_t *)data;
   new_filter_cb_args_t args;
 
   sl     = GTK_LIST(filter_l)->selection;
   if (sl) {  /* Something was selected */
     l_item = GTK_OBJECT(sl->data);
-    flp    = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
-    if (flp) {
-      filt          = (filter_def *) flp->data;
-      nfilt         = (filter_def *) g_malloc(sizeof(filter_def));
-      nfilt->name   = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
-      sprintf(nfilt->name, "%s%s", prefix, filt->name);
-      nfilt->strval = g_strdup(filt->strval);
-      fl            = g_list_append(fl, nfilt);
+    fl_entry = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
+    if (fl_entry != NULL) {
+      /* Add a new entry, copying the existing entry, to the filter list. */
+      filt = (filter_def *) fl_entry->data;
+      name = g_malloc(strlen(prefix) + strlen(filt->name) + 1);
+      sprintf(name, "%s%s", prefix, filt->name);
+      nfl_entry = add_to_filter_list(list, name, filt->strval);
+      g_free(name);
 
       /* Update all the filter list widgets, not just the one in
          the dialog box in which we clicked on "Copy". */
       args.active_filter_l = filter_l;
-      args.nflp = g_list_last(fl);
-      g_list_foreach(filter_dialogs, new_filter_cb, &args);
+      args.nflp = nfl_entry;
+      g_list_foreach(get_filter_dialog_list(list), new_filter_cb, &args);
     }
   }
 }
@@ -909,27 +1050,24 @@ filter_del_bt_clicked_cb(GtkWidget *w, gpointer data)
 {
   GtkWidget  *main_w = gtk_widget_get_toplevel(w);
   GtkWidget  *filter_l = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_FILTER_L_KEY);
-  GList      *sl, *flp;
-  filter_def *filt;
+  filter_list_type_t list = *(filter_list_type_t *)data;
+  GList      *sl, *fl_entry;
   GtkObject  *l_item;
   gint        pos;
-  
+
   sl = GTK_LIST(filter_l)->selection;
   if (sl) {  /* Something was selected */
     l_item = GTK_OBJECT(sl->data);
     pos    = gtk_list_child_position(GTK_LIST(filter_l),
       GTK_WIDGET(l_item));
-    flp    = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
-    if (flp) {
-      filt = (filter_def *) flp->data;
-      g_free(filt->name);
-      g_free(filt->strval);
-      g_free(filt);
-      fl = g_list_remove_link(fl, flp);
+    fl_entry = (GList *) gtk_object_get_data(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
+    if (fl_entry != NULL) {
+      /* Remove the entry from the filter list. */
+      remove_from_filter_list(list, fl_entry);
 
       /* Update all the filter list widgets, not just the one in
          the dialog box in which we clicked on "Delete". */
-      g_list_foreach(filter_dialogs, delete_filter_cb, &pos);
+      g_list_foreach(get_filter_dialog_list(list), delete_filter_cb, &pos);
     } 
   }
 }
index 048855966f801ffb41871fa02804bee225a7f376..db6e59d2400b7a865ab3d61a5d8f707718323e16 100644 (file)
@@ -3,7 +3,7 @@
  * (This used to be a notebook page under "Preferences", hence the
  * "prefs" in the file name.)
  *
- * $Id: filter_prefs.h,v 1.9 2001/01/21 02:27:24 guy Exp $
+ * $Id: filter_prefs.h,v 1.10 2001/01/28 09:13:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -41,7 +41,8 @@ typedef struct {
 
 void capture_filter_construct_cb(GtkWidget *w, gpointer user_data);
 void display_filter_construct_cb(GtkWidget *w, gpointer construct_args_ptr);
-void filter_dialog_cb(GtkWidget *);
+void cfilter_dialog_cb(GtkWidget *w);
+void dfilter_dialog_cb(GtkWidget *w);
 
 #define E_FILT_TE_KEY          "filter_te"
 #define E_FILT_TE_PTR_KEY      "filter_te_ptr"
index 67a6c348bf38112c686eb57083c8ec8d7a096d58..37abbe8293b64c8e6a081cd8c76a6e30807f2842 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.174 2001/01/28 04:52:29 guy Exp $
+ * $Id: main.c,v 1.175 2001/01/28 09:13:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -855,8 +855,8 @@ main(int argc, char *argv[])
   WSADATA             wsaData; 
 #endif
 
-  char                *gpf_path, *pf_path;
-  int                  gpf_open_errno, pf_open_errno;
+  char                *gpf_path, *pf_path, *cf_path, *df_path;
+  int                  gpf_open_errno, pf_open_errno, cf_open_errno, df_open_errno;
   int                  err;
 #ifdef HAVE_LIBPCAP
   gboolean             start_capture = FALSE;
@@ -928,8 +928,11 @@ main(int argc, char *argv[])
   /* Read the preference files. */
   prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
 
-  /* Read the filter file. */
-  get_filter_list();
+  /* Read the capture filter file. */
+  read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
+
+  /* Read the display filter file. */
+  read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
 
   /* Initialize the capture file struct */
   cfile.plist          = NULL;
@@ -1365,6 +1368,26 @@ main(int argc, char *argv[])
         strerror(pf_open_errno));
   }
 
+  /* If the user's capture filter file exists but we failed to open it,
+     pop up an alert box; we defer that until now, so that the alert
+     box is more likely to come up on top of the main window. */
+  if (cf_path != NULL) {
+      simple_dialog(ESD_TYPE_WARN, NULL,
+        "Could not open your capture filter file\n\"%s\": %s.", cf_path,
+        strerror(cf_open_errno));
+      g_free(cf_path);
+  }
+
+  /* If the user's display filter file exists but we failed to open it,
+     pop up an alert box; we defer that until now, so that the alert
+     box is more likely to come up on top of the main window. */
+  if (df_path != NULL) {
+      simple_dialog(ESD_TYPE_WARN, NULL,
+        "Could not open your display filter file\n\"%s\": %s.", df_path,
+        strerror(df_open_errno));
+      g_free(df_path);
+  }
+
 #ifdef HAVE_LIBPCAP
   if (capture_child) {
     /* This is the child process for a sync mode or fork mode capture,
index ed6d2e03a4f397c6c3a8301bb9a51e3f14fab266..212e76e10629c74840733d7169f3e469a7bf4301 100644 (file)
@@ -1,7 +1,7 @@
 /* menu.c
  * Menu routines
  *
- * $Id: menu.c,v 1.46 2000/10/19 22:59:24 guy Exp $
+ * $Id: menu.c,v 1.47 2001/01/28 09:13:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -120,7 +120,8 @@ static GtkItemFactoryEntry menu_items[] =
   {"/Edit/_Unmark All Frames", NULL, GTK_MENU_FUNC(unmark_all_frames_cb), 0, NULL},
   {"/Edit/<separator>", NULL, NULL, 0, "<Separator>"},
   {"/Edit/_Preferences...", NULL, GTK_MENU_FUNC(prefs_cb), 0, NULL},
-  {"/Edit/_Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+  {"/Edit/_Capture Filters...", NULL, GTK_MENU_FUNC(cfilter_dialog_cb), 0, NULL},
+  {"/Edit/_Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL},
   {"/Edit/P_rotocols...", NULL, GTK_MENU_FUNC(proto_cb), 0, NULL},
 #ifdef HAVE_LIBPCAP
   {"/_Capture", NULL, NULL, 0, "<Branch>" },
@@ -159,7 +160,7 @@ static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
 static GtkItemFactoryEntry packet_list_menu_items[] =
 {
        {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
-       {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+       {"/Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL},
        {"/<separator>", NULL, NULL, 0, "<Separator>"},
        {"/Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
        {"/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
@@ -170,7 +171,7 @@ static GtkItemFactoryEntry packet_list_menu_items[] =
 static GtkItemFactoryEntry tree_view_menu_items[] =
 {
        {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
-       {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+       {"/Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL},
        {"/<separator>", NULL, NULL, 0, "<Separator>"},
        {"/Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL},
        {"/Protocol Properties...", NULL, GTK_MENU_FUNC(properties_cb), 0, NULL},
@@ -183,7 +184,7 @@ static GtkItemFactoryEntry tree_view_menu_items[] =
 static GtkItemFactoryEntry hexdump_menu_items[] =
 {
        {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
-       {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL}
+       {"/Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL}
 };
 
 static int initialize = TRUE;