diff options
author | Guy Harris <guy@alum.mit.edu> | 2001-01-02 01:32:21 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2001-01-02 01:32:21 +0000 |
commit | 88d157ef96f4d17df2a718523a53cd5e717aa76a (patch) | |
tree | d3a1e2dec9c0891b2089916f71da1b1b83797568 /gtk | |
parent | d2f2cc6bf6b80f113c50c5ed75a5918c6390c7be (diff) |
Add a dialog box for constructing expressions that test a field in the
display tree, based on Jeff Foster's dialog box for selecting fields.
Make the dialog box for browsing filters into a dialog box for
constructing filters; make the "Apply" button and the "OK" button apply
the filter in the text entry box in the dialog, not the currently
selected filter (selecting a filter puts it in that text entry box, but
the user may edit it afterwards, or may use the aforementioned dialog
box to construct a filter not in the list).
Get rid of extra declarations of "m_r_font" and "m_b_font" in
"proto_draw.c"; they're declared in "gtk/gtkglobals.h", which it includes.
svn path=/trunk/; revision=2805
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/Makefile.am | 4 | ||||
-rw-r--r-- | gtk/Makefile.nmake | 1 | ||||
-rw-r--r-- | gtk/capture_dlg.c | 4 | ||||
-rw-r--r-- | gtk/dfilter_expr_dlg.c | 1221 | ||||
-rw-r--r-- | gtk/dfilter_expr_dlg.h | 31 | ||||
-rw-r--r-- | gtk/file_dlg.c | 4 | ||||
-rw-r--r-- | gtk/filter_prefs.c | 597 | ||||
-rw-r--r-- | gtk/filter_prefs.h | 6 | ||||
-rw-r--r-- | gtk/find_dlg.c | 4 | ||||
-rw-r--r-- | gtk/main.c | 6 | ||||
-rw-r--r-- | gtk/proto_draw.c | 4 |
11 files changed, 1616 insertions, 266 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index f60afbaec4..15093d984c 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for the GTK interface routines for Ethereal # -# $Id: Makefile.am,v 1.31 2000/11/21 23:54:09 guy Exp $ +# $Id: Makefile.am,v 1.32 2001/01/02 01:32:21 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@zing.org> @@ -39,6 +39,8 @@ libui_a_SOURCES = \ color_utils.h \ column_prefs.c \ column_prefs.h \ + dfilter_expr_dlg.c \ + dfilter_expr_dlg.h \ display_opts.c \ display_opts.h \ dlg_utils.c \ diff --git a/gtk/Makefile.nmake b/gtk/Makefile.nmake index fe9c2397a9..cd4a646ee0 100644 --- a/gtk/Makefile.nmake +++ b/gtk/Makefile.nmake @@ -19,6 +19,7 @@ OBJECTS=capture_dlg.obj \ colors.obj \ color_utils.obj \ column_prefs.obj \ + dfilter_expr_dlg.obj \ display_opts.obj \ dlg_utils.obj \ file_dlg.obj \ diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c index dc5d558243..8ed93d9077 100644 --- a/gtk/capture_dlg.c +++ b/gtk/capture_dlg.c @@ -1,7 +1,7 @@ /* capture_dlg.c * Routines for packet capture windows * - * $Id: capture_dlg.c,v 1.35 2000/10/19 22:59:24 guy Exp $ + * $Id: capture_dlg.c,v 1.36 2001/01/02 01:32:21 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -198,7 +198,7 @@ capture_prep_cb(GtkWidget *w, gpointer d) filter_bt = gtk_button_new_with_label("Filter:"); gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked", - GTK_SIGNAL_FUNC(filter_browse_cb), NULL); + GTK_SIGNAL_FUNC(capture_filter_construct_cb), NULL); gtk_table_attach_defaults(GTK_TABLE(table), filter_bt, 0, 1, 2, 3); gtk_widget_show(filter_bt); diff --git a/gtk/dfilter_expr_dlg.c b/gtk/dfilter_expr_dlg.c new file mode 100644 index 0000000000..7d029ead87 --- /dev/null +++ b/gtk/dfilter_expr_dlg.c @@ -0,0 +1,1221 @@ +/* dfilter_expr_dlg.c + * + * Allow the user to construct a subexpression of a display filter + * expression, testing a particular field; display the tree of fields + * and the relations and values with which it can be compared. + * + * Copyright 2000, Jeffrey C. Foster<jfoste@woodward.com> and + * Guy Harris <guy@alum.mit.edu> + * + * $Id: dfilter_expr_dlg.c,v 1.1 2001/01/02 01:32:21 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.org> + * Copyright 2000 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* Todo - + * may want to check the enable field to decide if protocol should be in tree + * improve speed of dialog box creation + * - I believe this is slow because of tree widget creation. + * 1) could improve the widget + * 2) keep a copy in memory after the first time. + * user can pop multiple tree dialogs by pressing the "Tree" button multiple + * time. not a good thing. + * Sort the protocols and children + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtk/gtk.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#include "prefs.h" +#include "globals.h" +#include "gtkglobals.h" +#include "main.h" +#include "util.h" +#include "ui_util.h" +#include "simple_dialog.h" +#include "dlg_utils.h" +#include "proto_dlg.h" +#include "filter_prefs.h" +#include "dfilter_expr_dlg.h" + +#define E_DFILTER_EXPR_TREE_KEY "dfilter_expr_tree" +#define E_DFILTER_EXPR_CURRENT_VAR_KEY "dfilter_expr_current_var" +#define E_DFILTER_EXPR_RELATION_LABEL_KEY "dfilter_expr_relation_label" +#define E_DFILTER_EXPR_RELATION_LIST_KEY "dfilter_expr_relation_list" +#define E_DFILTER_EXPR_RANGE_LABEL_KEY "dfilter_expr_range_label" +#define E_DFILTER_EXPR_RANGE_ENTRY_KEY "dfilter_expr_range_entry" +#define E_DFILTER_EXPR_VALUE_LABEL_KEY "dfilter_expr_value_label" +#define E_DFILTER_EXPR_VALUE_ENTRY_KEY "dfilter_expr_value_entry" +#define E_DFILTER_EXPR_VALUE_LIST_KEY "dfilter_expr_value_list" +#define E_DFILTER_EXPR_VALUE_LIST_SW_KEY "dfilter_expr_value_list_sw" +#define E_DFILTER_EXPR_ACCEPT_BT_KEY "dfilter_expr_accept_bt" +#define E_DFILTER_EXPR_VALUE_KEY "dfilter_expr_value" + +typedef struct protocol_data { + char *abbrev; + int hfinfo_index; +} protocol_data_t; + +static void show_relations(GtkWidget *relation_label, GtkWidget *relation_list, + GtkWidget *range_label, GtkWidget *range_entry, guint32 relations); +static void add_relation_list(GtkWidget *relation_list, char *relation); +static void build_boolean_values(GtkWidget *value_list_scrolled_win, + GtkWidget *value_list, const true_false_string *values); +static void build_enum_values(GtkWidget *value_list_scrolled_win, + GtkWidget *value_list, const value_string *values); +static void add_value_list_item(GtkWidget *value_list, gchar *string, + gpointer data); +static void display_value_fields(header_field_info *hfinfo, + gboolean is_comparison, GtkWidget *value_label, GtkWidget *value_entry, + GtkWidget *value_list, GtkWidget *value_list_scrolled_win); + +/* + * What relations are supported? + */ +#define EXISTENCE_OK 0x00000001 +#define EQUALITY_OK 0x00000002 +#define ORDER_OK 0x00000004 +#define ORDER_EQUALITY_OK 0x00000008 +#define RANGES_OK 0x00000010 + +/* + * Note that this is called every time the user clicks on an item, + * whether it is already selected or not. + */ +static void +field_select_row_cb(GtkWidget *tree, GList *node, gint column, + gpointer user_data) +{ + GtkWidget *window = gtk_widget_get_toplevel(tree); + GtkWidget *relation_label = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RELATION_LABEL_KEY); + GtkWidget *relation_list = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RELATION_LIST_KEY); + GtkWidget *range_label = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RANGE_LABEL_KEY); + GtkWidget *range_entry = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RANGE_ENTRY_KEY); + GtkWidget *value_label = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LABEL_KEY); + GtkWidget *value_entry = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_ENTRY_KEY); + GtkWidget *value_list = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LIST_KEY); + GtkWidget *value_list_scrolled_win = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LIST_SW_KEY); + GtkWidget *accept_bt = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_ACCEPT_BT_KEY); + header_field_info *hfinfo, *cur_hfinfo; + guint32 relations; + char *value_type; + char value_label_string[1024+1]; /* XXX - should be large enough */ + + hfinfo = gtk_ctree_node_get_row_data(GTK_CTREE(tree), + GTK_CTREE_NODE(node)); + + /* + * What was the item that was last selected? + */ + cur_hfinfo = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_CURRENT_VAR_KEY); + if (cur_hfinfo == hfinfo) { + /* + * It's still selected; no need to change anything. + */ + return; + } + + /* + * Mark it as currently selected. + */ + gtk_object_set_data(GTK_OBJECT(window), E_DFILTER_EXPR_CURRENT_VAR_KEY, + hfinfo); + + /* + * Set the relation list column to show all the comparison + * operators supported on it, if any. + */ + switch (hfinfo->type) { + + case FT_NONE: + /* + * You can only test for the field's presence; + * hide the relation stuff. + * XXX - what about "tcp[xx:yy]"? + */ + relations = 0; + break; + + case FT_BOOLEAN: + /* + * You can only test whether the field is true or false; + * hide the relation stuff. + */ + relations = 0; + break; + + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + case FT_INT8: + case FT_INT16: + case FT_INT24: + case FT_INT32: + case FT_IPv4: + /* + * All comparison operators are allowed, but you can't + * select a subrange of bytes in it. + */ + relations = EXISTENCE_OK|EQUALITY_OK|ORDER_OK|ORDER_EQUALITY_OK; + break; + + case FT_STRING: + case FT_STRINGZ: + case FT_UINT_STRING: + case FT_ETHER: + case FT_IPv6: + case FT_IPXNET: + /* + * Only equality comparisons are allowed, and you can't + * select a subrange of bytes. + */ + relations = EXISTENCE_OK|EQUALITY_OK; + break; + + case FT_DOUBLE: + case FT_ABSOLUTE_TIME: + case FT_RELATIVE_TIME: + /* + * We don't support filtering on these. + */ + relations = 0; + break; + + case FT_BYTES: + /* + * Equality and "greater than" and "less than", but *not* + * "greater than or equal to" or "less than or equal to", + * are supported. XXX - is that an error? + * Ranges are supported. + */ + relations = EXISTENCE_OK|EQUALITY_OK|ORDER_OK|RANGES_OK; + break; + + default: + g_assert_not_reached(); + relations = 0; + break; + } + show_relations(relation_label, relation_list, range_label, + range_entry, relations); + + /* + * Set the label for the value to indicate what type of value + * it is. + */ + switch (hfinfo->type) { + + case FT_NONE: + /* + * You can only test for the field's presence; hide + * the value stuff. + */ + value_type = NULL; + break; + + case FT_BOOLEAN: + value_type = "Boolean"; + break; + + case FT_UINT8: + value_type = "unsigned, byte"; + break; + + case FT_UINT16: + value_type = "unsigned, 2 bytes"; + break; + + case FT_UINT24: + value_type = "unsigned, 3 bytes"; + break; + + case FT_UINT32: + value_type = "unsigned, 4 bytes"; + break; + + case FT_INT8: + value_type = "signed, byte"; + break; + + case FT_INT16: + value_type = "signed, 2 bytes"; + break; + + case FT_INT24: + value_type = "signed, 3 bytes"; + break; + + case FT_INT32: + value_type = "signed, 4 bytes"; + break; + + case FT_DOUBLE: + value_type = "floating point"; + break; + + case FT_ABSOLUTE_TIME: + value_type = "date and time"; + break; + + case FT_RELATIVE_TIME: + value_type = "time"; + break; + + case FT_STRING: + case FT_STRINGZ: + case FT_UINT_STRING: + value_type = "character string"; + break; + + case FT_ETHER: + value_type = "Ethernet or other MAC address"; + break; + + case FT_BYTES: + value_type = "sequence of bytes"; + break; + + case FT_IPv4: + value_type = "IPv4 address"; + break; + + case FT_IPv6: + value_type = "IPv6 address"; + break; + + case FT_IPXNET: + value_type = "IPX network address"; + break; + + default: + g_assert_not_reached(); + value_type = NULL; + break; + } + if (value_type != NULL) { + /* + * Indicate what type of value it is. + */ + snprintf(value_label_string, sizeof value_label_string, + "Value (%s)", value_type); + gtk_label_set_text(GTK_LABEL(value_label), value_label_string); + } + + /* + * Clear the entry widget for the value, as whatever + * was there before doesn't apply. + */ + gtk_entry_set_text(GTK_ENTRY(value_entry), ""); + + switch (hfinfo->type) { + + case FT_BOOLEAN: + /* + * The list of values should be the strings for "true" + * and "false"; show them in the value list. + */ + build_boolean_values(value_list_scrolled_win, value_list, + hfinfo->strings); + break; + + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + case FT_INT8: + case FT_INT16: + case FT_INT24: + case FT_INT32: + /* + * If this has a value_string table associated with it, + * fill up the list of values, otherwise clear the list + * of values. + */ + if (hfinfo->strings != NULL) { + build_enum_values(value_list_scrolled_win, value_list, + hfinfo->strings); + } else + gtk_list_clear_items(GTK_LIST(value_list), 0, -1); + break; + + default: + /* + * Clear the list of values. + */ + gtk_list_clear_items(GTK_LIST(value_list), 0, -1); + break; + } + + /* + * Display various items for the value, as appropriate. + * The relation we start out with is never a comparison. + */ + display_value_fields(hfinfo, FALSE, value_label, value_entry, + value_list, value_list_scrolled_win); + + /* + * XXX - in browse mode, there always has to be something + * selected, so this should always be sensitive. + */ + gtk_widget_set_sensitive(accept_bt, TRUE); +} + +static void +show_relations(GtkWidget *relation_label, GtkWidget *relation_list, + GtkWidget *range_label, GtkWidget *range_entry, guint32 relations) +{ + /* + * Clear out the currently displayed list of relations. + */ + gtk_list_clear_items(GTK_LIST(relation_list), 0, -1); + if (relations == 0) { + /* + * No relational operators are supported; hide the relation + * and range stuff. + */ + gtk_widget_hide(relation_label); + gtk_widget_hide(relation_list); + gtk_widget_hide(range_label); + gtk_widget_hide(range_entry); + } else { + /* + * Add the supported relations. + */ + if (relations & EXISTENCE_OK) + add_relation_list(relation_list, "is present"); + if (relations & EQUALITY_OK) { + add_relation_list(relation_list, "=="); + add_relation_list(relation_list, "!="); + } + if (relations & ORDER_OK) { + add_relation_list(relation_list, ">"); + add_relation_list(relation_list, "<"); + } + if (relations & ORDER_EQUALITY_OK) { + add_relation_list(relation_list, ">="); + add_relation_list(relation_list, "<="); + } + + /* + * And show the list. + */ + gtk_widget_show(relation_label); + gtk_widget_show(relation_list); + + /* + * Are range supported? If so, show the range stuff, + * otherwise hide it. + */ + if (relations & RANGES_OK) { + gtk_widget_show(range_label); + gtk_widget_show(range_entry); + } else { + gtk_widget_hide(range_label); + gtk_widget_hide(range_entry); + } + + } +} + +static void +add_relation_list(GtkWidget *relation_list, char *relation) +{ + GtkWidget *label, *item; + + label = gtk_label_new(relation); + item = gtk_list_item_new(); + + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_container_add(GTK_CONTAINER(item), label); + gtk_widget_show(label); + gtk_container_add(GTK_CONTAINER(relation_list), item); + gtk_widget_show(item); +} + +static void +relation_list_sel_cb(GtkList *relation_list, GtkWidget *child, + gpointer user_data) +{ + GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(relation_list)); + GtkWidget *value_label = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LABEL_KEY); + GtkWidget *value_entry = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_ENTRY_KEY); + GtkWidget *value_list = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LIST_KEY); + GtkWidget *value_list_scrolled_win = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LIST_SW_KEY); + header_field_info *hfinfo = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_CURRENT_VAR_KEY); + GList *sl; + GtkWidget *item, *item_label; + gchar *item_str; + + /* + * What's the relation? + */ + sl = GTK_LIST(relation_list)->selection; + item = GTK_WIDGET(sl->data); + item_label = GTK_BIN(item)->child; + gtk_label_get(GTK_LABEL(item_label), &item_str); + + /* + * Update the display of various items for the value, as appropriate. + */ + display_value_fields(hfinfo, + (strcmp(item_str, "is present") != 0), + value_label, value_entry, value_list, value_list_scrolled_win); +} + +static void +build_boolean_values(GtkWidget *value_list_scrolled_win, GtkWidget *value_list, + const true_false_string *values) +{ + static const true_false_string true_false = { "True", "False" }; + + /* + * Clear out the items for the list, and put in the names + * from the value_string list. + */ + gtk_list_clear_items(GTK_LIST(value_list), 0, -1); + + /* + * Put the list in single mode, so we don't get any selection + * events while we're building it (i.e., so we don't get any + * on a list item BEFORE WE GET TO SET THE DATA FOR THE LIST + * ITEM SO THAT THE HANDLER CAN HANDLE IT). + */ + gtk_list_set_selection_mode(GTK_LIST(value_list), GTK_SELECTION_SINGLE); + + /* + * Build the list. + */ + if (values == NULL) + values = &true_false; + add_value_list_item(value_list, values->true_string, (gpointer)values); + add_value_list_item(value_list, values->false_string, NULL); + + /* + * OK, we're done, so we can finally put it in browse mode. + * Select the first item, so that the user doesn't have to, under + * the assumption that they're most likely to test if something + * is true, not false. + */ + gtk_list_set_selection_mode(GTK_LIST(value_list), GTK_SELECTION_BROWSE); + gtk_list_select_item(GTK_LIST(value_list), 0); + + gtk_widget_show_all(value_list_scrolled_win); +} + +static void +build_enum_values(GtkWidget *value_list_scrolled_win, GtkWidget *value_list, + const value_string *values) +{ + /* + * Clear out the items for the list, and put in the names + * from the value_string list. + */ + gtk_list_clear_items(GTK_LIST(value_list), 0, -1); + + /* + * Put the list in single mode, so we don't get any selection + * events while we're building it (i.e., so we don't get any + * on a list item BEFORE WE GET TO SET THE DATA FOR THE LIST + * ITEM SO THAT THE HANDLER CAN HANDLE IT). + */ + gtk_list_set_selection_mode(GTK_LIST(value_list), GTK_SELECTION_SINGLE); + + /* + * Build the list. + */ + while (values->strptr != NULL) { + add_value_list_item(value_list, values->strptr, + (gpointer)values); + values++; + } + + /* + * OK, we're done, so we can finally put it in browse mode. + */ + gtk_list_set_selection_mode(GTK_LIST(value_list), GTK_SELECTION_BROWSE); +} + +static void +add_value_list_item(GtkWidget *value_list, gchar *string, gpointer data) +{ + GtkWidget *label, *item; + + label = gtk_label_new(string); + item = gtk_list_item_new(); + + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_container_add(GTK_CONTAINER(item), label); + gtk_widget_show(label); + gtk_container_add(GTK_CONTAINER(value_list), item); + gtk_object_set_data(GTK_OBJECT(item), E_DFILTER_EXPR_VALUE_KEY, data); + gtk_widget_show(item); +} + +/* + * Show or hide the various values fields as appropriate for the field + * and currently-selected relation. + */ +static void +display_value_fields(header_field_info *hfinfo, gboolean is_comparison, + GtkWidget *value_label, GtkWidget *value_entry, GtkWidget *value_list, + GtkWidget *value_list_scrolled_win) +{ + gboolean show_value_label = FALSE; + + /* + * Either: + * + * this is an FT_NONE variable, in which case you can + * only check whether it's present or absent in the + * protocol tree + * + * or + * + * this is a Boolean variable, in which case you + * can't specify a value to compare with, you can + * only specify whether to test for the Boolean + * being true or to test for it being false + * + * or + * + * this isn't a Boolean variable, in which case you + * can test for its presence in the protocol tree, + * and the default relation is such a test, in + * which case you don't compare with a value + * + * so we hide the value entry. + */ + if (is_comparison) { + /* + * The relation is a comparison; display the entry for + * the value with which to compare. + */ + gtk_widget_show(value_entry); + + /* + * We're showing the entry; show the label as well. + */ + show_value_label = TRUE; + } else { + /* + * The relation isn't a comparison; there's no value with + * which to compare, so don't show the entry for it. + */ + gtk_widget_hide(value_entry); + } + + switch (hfinfo->type) { + + case FT_BOOLEAN: + /* + * The list of values should be the strings for "true" + * and "false"; show the value list. + */ + gtk_widget_show_all(value_list_scrolled_win); + + /* + * We're showing the entry; show the label as well. + */ + show_value_label = TRUE; + break; + + case FT_UINT8: + case FT_UINT16: + case FT_UINT24: + case FT_UINT32: + case FT_INT8: + case FT_INT16: + case FT_INT24: + case FT_INT32: + if (hfinfo->strings != NULL) { + /* + * We have a list of values to show. + */ + if (is_comparison) { + /* + * The relation is a comparison, so we're + * showing an entry for the value with + * which to compare; show the list of + * names for values as well. + */ + gtk_widget_show_all(value_list_scrolled_win); + + /* + * We're showing the entry; show the label + * as well. + */ + show_value_label = TRUE; + } else { + /* + * It's not a comparison, so we're not showing + * the entry for the value; don't show the + * list of names for values, either. + */ + gtk_widget_hide_all(value_list_scrolled_win); + } + } else { + /* + * There is no list of names for values, so don't + * show it. + */ + gtk_widget_hide_all(value_list_scrolled_win); + } + break; + + default: + /* + * There is no list of names for values; hide the list. + */ + gtk_widget_hide_all(value_list_scrolled_win); + break; + } + + if (show_value_label) + gtk_widget_show(value_label); + else + gtk_widget_hide(value_label); +} + +static void +value_list_sel_cb(GtkList *value_list, GtkWidget *child, + gpointer value_entry_arg) +{ + GtkWidget *value_entry = value_entry_arg; + GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(value_list)); + header_field_info *hfinfo = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_CURRENT_VAR_KEY); + const value_string *value; + char value_string[11+1]; /* long enough for 32-bit octal value */ + + /* + * If the value entry is shown, it's an enumerated type (i.e., + * we have a "value_string" list associated with the field); + * set the value entry to the numerical value for this item. + * + * If it's not shown, it's a Boolean type, and there is no value + * to use in a test of the field. + */ + if (GTK_WIDGET_VISIBLE(value_entry)) { + value = gtk_object_get_data(GTK_OBJECT(child), + E_DFILTER_EXPR_VALUE_KEY); + switch (hfinfo->display) { + + case BASE_DEC: + switch (hfinfo->type) { + + case FT_UINT8: + case FT_UINT16: + case FT_UINT32: + snprintf(value_string, sizeof value_string, + "%u", value->value); + break; + + case FT_INT8: + case FT_INT16: + case FT_INT32: + snprintf(value_string, sizeof value_string, + "%d", value->value); + break; + + default: + g_assert_not_reached(); + } + break; + + case BASE_HEX: + snprintf(value_string, sizeof value_string, "0x%x", + value->value); + break; + + case BASE_OCT: + snprintf(value_string, sizeof value_string, "%#o", + value->value); + break; + + default: + g_assert_not_reached(); + } + gtk_entry_set_text(GTK_ENTRY(value_entry), value_string); + } +} + +static void +dfilter_expr_dlg_accept_cb(GtkWidget *w, gpointer filter_te_arg) +{ + GtkWidget *filter_te = filter_te_arg; + GtkWidget *window = gtk_widget_get_toplevel(w); + GtkWidget *relation_list = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RELATION_LIST_KEY); + GtkWidget *range_entry = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RANGE_ENTRY_KEY); + GtkWidget *value_entry = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_ENTRY_KEY); + GtkWidget *value_list = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LIST_KEY); + header_field_info *hfinfo; + GList *sl; + GtkWidget *item, *item_label; + gchar *item_str; + gchar *range_str, *stripped_range_str; + gchar *value_str, *stripped_value_str; + int pos; + gchar *chars; + + /* + * Get the variable to be tested. + */ + hfinfo = gtk_object_get_data(GTK_OBJECT(window), + E_DFILTER_EXPR_CURRENT_VAR_KEY); + + /* + * Get the relation to use, if any. + */ + if (GTK_WIDGET_VISIBLE(relation_list)) { + /* + * The list of relations is visible, so we can get a + * relation operator from it. + */ + sl = GTK_LIST(relation_list)->selection; + item = GTK_WIDGET(sl->data); + item_label = GTK_BIN(item)->child; + gtk_label_get(GTK_LABEL(item_label), &item_str); + } else + item_str = NULL; /* no relation operator */ + + /* + * Get the range to use, if any. + */ + if (GTK_WIDGET_VISIBLE(range_entry)) { + range_str = g_strdup(gtk_entry_get_text(GTK_ENTRY(range_entry))); + stripped_range_str = g_strstrip(range_str); + if (strcmp(stripped_range_str, "") == 0) { + /* + * No range was specified. + */ + g_free(range_str); + range_str = NULL; + stripped_range_str = NULL; + } + + /* + * XXX - check it for validity? + */ + } else { + range_str = NULL; + stripped_range_str = NULL; + } + + /* + * Get the value to use, if any. + */ + if (GTK_WIDGET_VISIBLE(value_entry)) { + value_str = g_strdup(gtk_entry_get_text(GTK_ENTRY(value_entry))); + stripped_value_str = g_strstrip(value_str); + if (strcmp(stripped_value_str, "") == 0) { + /* + * This field takes a value, but they didn't supply + * one. + */ + simple_dialog(ESD_TYPE_CRIT | ESD_TYPE_MODAL, NULL, + "That field must be compared with a value, " + "but you didn't specify a value with which to " + "compare it."); + g_free(value_str); + return; + } + } else { + value_str = NULL; + stripped_value_str = NULL; + } + + /* + * Insert the expression at the current cursor position. + * If there's a non-whitespace character to the left of it, + * insert a blank first; if there's a non-whitespace character + * to the right of it, insert a blank after it. + */ + pos = gtk_editable_get_position(GTK_EDITABLE(filter_te)); + chars = gtk_editable_get_chars(GTK_EDITABLE(filter_te), pos, pos + 1); + if (strcmp(chars, "") != 0 && !isspace((unsigned char)chars[0])) + gtk_editable_insert_text(GTK_EDITABLE(filter_te), " ", 1, &pos); + g_free(chars); + + /* + * If this is a Boolean, check if item in the value list has + * a null pointer as the data attached to it; if so, put a "!" + * in front of the variable name, as we're testing whether it's + * false. + */ + if (hfinfo->type == FT_BOOLEAN) { + sl = GTK_LIST(value_list)->selection; + item = GTK_WIDGET(sl->data); + if (gtk_object_get_data(GTK_OBJECT(item), + E_DFILTER_EXPR_VALUE_KEY) == NULL) + gtk_editable_insert_text(GTK_EDITABLE(filter_te), "!", + 1, &pos); + } + + gtk_editable_insert_text(GTK_EDITABLE(filter_te), hfinfo->abbrev, + strlen(hfinfo->abbrev), &pos); + if (range_str != NULL) { + gtk_editable_insert_text(GTK_EDITABLE(filter_te), "[", 1, &pos); + gtk_editable_insert_text(GTK_EDITABLE(filter_te), + stripped_range_str, strlen(stripped_range_str), &pos); + gtk_editable_insert_text(GTK_EDITABLE(filter_te), "]", 1, &pos); + g_free(range_str); + } + if (item_str != NULL && strcmp(item_str, "is present") != 0) { + gtk_editable_insert_text(GTK_EDITABLE(filter_te), " ", 1, &pos); + gtk_editable_insert_text(GTK_EDITABLE(filter_te), item_str, + strlen(item_str), &pos); + } + if (value_str != NULL) { + gtk_editable_insert_text(GTK_EDITABLE(filter_te), " ", 1, &pos); + switch (hfinfo->type) { + + case FT_STRING: + case FT_STRINGZ: + case FT_UINT_STRING: + /* + * Put quotes around the string. + */ + gtk_editable_insert_text(GTK_EDITABLE(filter_te), "\"", + 1, &pos); + + default: + break; + } + gtk_editable_insert_text(GTK_EDITABLE(filter_te), + stripped_value_str, strlen(stripped_value_str), &pos); + switch (hfinfo->type) { + + case FT_STRING: + case FT_STRINGZ: + case FT_UINT_STRING: + /* + * Put quotes around the string. + */ + gtk_editable_insert_text(GTK_EDITABLE(filter_te), "\"", + 1, &pos); + + default: + break; + } + g_free(value_str); + } + chars = gtk_editable_get_chars(GTK_EDITABLE(filter_te), pos + 1, pos + 2); + if (strcmp(chars, "") != 0 && !isspace((unsigned char)chars[0])) + gtk_editable_insert_text(GTK_EDITABLE(filter_te), " ", 1, &pos); + g_free(chars); + + /* + * Put the cursor after the expression we just entered into + * the text entry widget. + */ + gtk_editable_set_position(GTK_EDITABLE(filter_te), pos); + + /* + * We're done; destroy the dialog box (which is the top-level + * widget for the "Accept" button). + */ + gtk_widget_destroy(window); +} + +static void +dfilter_expr_dlg_cancel_cb(GtkWidget *w, gpointer parent_w) +{ + /* + * User pressed the cancel button; close the dialog box. + */ + gtk_widget_destroy(GTK_WIDGET(parent_w)); +} + +void +dfilter_expr_dlg_new(GtkWidget *filter_te) +{ + GtkWidget *window; + GtkWidget *main_vb; + GtkWidget *hb; + GtkWidget *col1_vb; + GtkWidget *tree_label, *tree, *tree_scrolled_win; + GtkWidget *col2_vb; + GtkWidget *relation_label, *relation_list; + GtkWidget *range_label, *range_entry; + GtkWidget *value_vb; + GtkWidget *value_label, *value_entry, *value_list_scrolled_win, *value_list; + GtkWidget *list_bb, *accept_bt, *close_bt; + GtkCTreeNode *protocol_node, *item_node; + header_field_info *hfinfo; + int i, len; + GHashTable *proto_array; + + window = dlg_window_new("Ethereal: Filter Expression"); + gtk_container_set_border_width(GTK_CONTAINER(window), 5); + + main_vb = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(window), main_vb); + gtk_widget_show(main_vb); + + hb = gtk_hbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(hb), 5); + gtk_container_add(GTK_CONTAINER(main_vb), hb); + gtk_widget_show(hb); + + col1_vb = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(col1_vb), 5); + gtk_container_add(GTK_CONTAINER(hb), col1_vb); + gtk_widget_show(col1_vb); + + tree_label = gtk_label_new("Field name"); + gtk_misc_set_alignment(GTK_MISC(tree_label), 0.0, 0.0); + gtk_box_pack_start(GTK_BOX(col1_vb), tree_label, FALSE, FALSE, 0); + gtk_widget_show(tree_label); + + tree_scrolled_win = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tree_scrolled_win), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_set_usize(tree_scrolled_win, 300, 400); + gtk_box_pack_start(GTK_BOX(col1_vb), tree_scrolled_win, FALSE, FALSE, 0); + gtk_widget_show(tree_scrolled_win); + + tree = gtk_ctree_new(1, 0); + gtk_ctree_set_line_style(GTK_CTREE(tree), GTK_CTREE_LINES_NONE); + gtk_signal_connect(GTK_OBJECT(tree), "tree-select-row", + GTK_SIGNAL_FUNC(field_select_row_cb), tree); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tree_scrolled_win), + tree); + + /* + * GTK's annoying CTree widget will deliver a selection event + * the instant you add an item to the tree, *the fact that you + * haven't even had time to set the item's row data nonwithstanding*. + * + * We'll put the widget into GTK_SELECTION_SINGLE mode in the + * hopes that it's *STOP DOING THAT*. + */ + gtk_clist_set_selection_mode(GTK_CLIST(tree), + GTK_SELECTION_SINGLE); + + col2_vb = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(col2_vb), 5); + gtk_container_add(GTK_CONTAINER(hb), col2_vb); + gtk_widget_show(col2_vb); + + relation_label = gtk_label_new("Relation"); + gtk_misc_set_alignment(GTK_MISC(relation_label), 0.0, 0.0); + gtk_box_pack_start(GTK_BOX(col2_vb), relation_label, FALSE, FALSE, 0); + + relation_list = gtk_list_new(); + gtk_box_pack_start(GTK_BOX(col2_vb), relation_list, TRUE, TRUE, 0); + gtk_list_set_selection_mode(GTK_LIST(relation_list), + GTK_SELECTION_BROWSE); + + range_label = gtk_label_new("Range (offset:length)"); + gtk_misc_set_alignment(GTK_MISC(range_label), 0.0, 0.0); + gtk_box_pack_start(GTK_BOX(col2_vb), range_label, FALSE, FALSE, 0); + + range_entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(col2_vb), range_entry, FALSE, FALSE, 0); + + /* + * OK, show the relation label and range stuff as it would be + * with everything turned on, so it'll request as much space + * as it'll ever need, so the dialog box and widgets start out + * with the right sizes. + * + * XXX - this doesn't work. + */ + show_relations(relation_label, relation_list, range_label, range_entry, + EXISTENCE_OK|EQUALITY_OK|ORDER_OK|ORDER_EQUALITY_OK|RANGES_OK); + + value_vb = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(value_vb), 5); + gtk_container_add(GTK_CONTAINER(hb), value_vb); + gtk_widget_show(value_vb); + + value_label = gtk_label_new("Value"); + gtk_misc_set_alignment(GTK_MISC(value_label), 0.0, 0.0); + gtk_box_pack_start(GTK_BOX(value_vb), value_label, FALSE, FALSE, 0); + gtk_widget_show(value_label); + + value_entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(value_vb), value_entry, FALSE, FALSE, 0); + gtk_widget_show(value_entry); + + value_list_scrolled_win = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(value_list_scrolled_win), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(value_vb), value_list_scrolled_win, TRUE, + TRUE, 0); + gtk_widget_show(value_list_scrolled_win); + + value_list = gtk_list_new(); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(value_list_scrolled_win), + value_list); + gtk_signal_connect(GTK_OBJECT(value_list), "select-child", + GTK_SIGNAL_FUNC(value_list_sel_cb), value_entry); + gtk_list_set_selection_mode(GTK_LIST(value_list), GTK_SELECTION_SINGLE); + /* This remains hidden until an enumerated field is selected */ + + /* + * The value stuff may be hidden or shown depending on what + * relation was selected; connect to the "select-child" signal + * for the relation list, so we can make that happen. + */ + gtk_signal_connect(GTK_OBJECT(relation_list), "select-child", + GTK_SIGNAL_FUNC(relation_list_sel_cb), NULL); + + list_bb = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(main_vb), list_bb, FALSE, FALSE, 0); + gtk_widget_show(list_bb); + + accept_bt = gtk_button_new_with_label("Accept"); + gtk_widget_set_sensitive(accept_bt, FALSE); + gtk_signal_connect(GTK_OBJECT(accept_bt), "clicked", + GTK_SIGNAL_FUNC(dfilter_expr_dlg_accept_cb), filter_te); + gtk_box_pack_start(GTK_BOX(list_bb), accept_bt, FALSE, FALSE, 0); + gtk_widget_show(accept_bt); + + /* + * Put the items in the CTree; we don't want to do that until + * we've constructed the value list and set the tree's + * E_DFILTER_EXPR_VALUE_LIST_KEY data to point to it, and + * constructed the "Accept" button and set the tree's + * E_DFILTER_EXPR_ACCEPT_BT_KEY data to point to it, so that + * when the list item is "helpfully" automatically selected for us + * we're ready to cope with the selection signal. + */ + + /* a hash table seems excessive, but I don't see support for a + sparse array in glib */ + proto_array = g_hash_table_new( g_direct_hash, g_direct_equal); + len = proto_registrar_n(); + for (i = 0; i < len; i++) { + if (proto_registrar_is_protocol(i)) { + hfinfo = proto_registrar_get_nth(i); + /* Create a node for the protocol, + and remember it for later use. */ + protocol_node = gtk_ctree_insert_node(GTK_CTREE(tree), + NULL, NULL, + &hfinfo->name, 5, + NULL, NULL, NULL, NULL, + FALSE, FALSE); + gtk_ctree_node_set_row_data(GTK_CTREE(tree), + protocol_node, hfinfo); + g_hash_table_insert(proto_array, (gpointer)i, + protocol_node); + } + } + + len = proto_registrar_n(); + for (i = 0; i < len; i++) { + if (!proto_registrar_is_protocol(i)) { + hfinfo = proto_registrar_get_nth(i); + + /* Create a node for the item, and put it + under its parent protocol. */ + protocol_node = g_hash_table_lookup(proto_array, + (gpointer)proto_registrar_get_parent(i)); + item_node = gtk_ctree_insert_node(GTK_CTREE(tree), + protocol_node, NULL, + &hfinfo->name, 5, + NULL, NULL, NULL, NULL, + FALSE, FALSE); + gtk_ctree_node_set_row_data(GTK_CTREE(tree), + item_node, hfinfo); + } + } + + g_hash_table_destroy(proto_array); + + gtk_widget_show_all(tree); + + close_bt = gtk_button_new_with_label("Close"); + gtk_signal_connect(GTK_OBJECT(close_bt), "clicked", + GTK_SIGNAL_FUNC(dfilter_expr_dlg_cancel_cb), window); + gtk_box_pack_start(GTK_BOX(list_bb), close_bt, FALSE, FALSE, 0); + gtk_widget_show(close_bt); + + /* + * Catch the "key_press_event" signal in the window, so that we can + * catch the ESC key being pressed and act as if the "Close" button + * had been selected. + */ + dlg_set_cancel(window, close_bt); + + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RELATION_LABEL_KEY, relation_label); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RELATION_LIST_KEY, relation_list); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RANGE_LABEL_KEY, range_label); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_RANGE_ENTRY_KEY, range_entry); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LABEL_KEY, value_label); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_ENTRY_KEY, value_entry); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LIST_KEY, value_list); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_VALUE_LIST_SW_KEY, value_list_scrolled_win); + gtk_object_set_data(GTK_OBJECT(window), + E_DFILTER_EXPR_ACCEPT_BT_KEY, accept_bt); + + /* + * OK, we've finally built the entire list, complete with the row data, + * and attached to the top-level widget pointers to the relevant + * subwidgets, so it's safe to put the list in browse mode. + */ + gtk_clist_set_selection_mode (GTK_CLIST(tree), + GTK_SELECTION_BROWSE); + + gtk_widget_show(window); +} diff --git a/gtk/dfilter_expr_dlg.h b/gtk/dfilter_expr_dlg.h new file mode 100644 index 0000000000..21ea418e4e --- /dev/null +++ b/gtk/dfilter_expr_dlg.h @@ -0,0 +1,31 @@ +/* dfilter_expr_dlg.h + * Definitions for dialog boxes for display filter expression construction + * + * $Id: dfilter_expr_dlg.h,v 1.1 2001/01/02 01:32:21 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.org> + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __DFILTER_EXPR_DLG_H__ +#define __DFILTER_EXPR_DLG_H__ + +void dfilter_expr_dlg_new(GtkWidget *); + +#endif /* dfilter_expr_dlg.h */ diff --git a/gtk/file_dlg.c b/gtk/file_dlg.c index a0f86d08b0..a8553704ca 100644 --- a/gtk/file_dlg.c +++ b/gtk/file_dlg.c @@ -1,7 +1,7 @@ /* file_dlg.c * Dialog boxes for handling files * - * $Id: file_dlg.c,v 1.32 2000/10/19 22:59:24 guy Exp $ + * $Id: file_dlg.c,v 1.33 2001/01/02 01:32:21 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -112,7 +112,7 @@ file_open_cmd_cb(GtkWidget *w, gpointer data) { filter_bt = gtk_button_new_with_label("Filter:"); gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked", - GTK_SIGNAL_FUNC(filter_browse_cb), NULL); + GTK_SIGNAL_FUNC(display_filter_construct_cb), NULL); gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0); gtk_widget_show(filter_bt); diff --git a/gtk/filter_prefs.c b/gtk/filter_prefs.c index 565b6e0bce..726cb6ffef 100644 --- a/gtk/filter_prefs.c +++ b/gtk/filter_prefs.c @@ -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.19 2000/10/25 16:06:50 gram Exp $ + * $Id: filter_prefs.c,v 1.20 2001/01/02 01:32:21 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -55,6 +55,7 @@ #include "dlg_utils.h" #include "ui_util.h" #include "prefs_dlg.h" +#include "dfilter_expr_dlg.h" #define E_FILT_NAME_KEY "filter_name" #define E_FILT_LBL_KEY "filter_label" @@ -74,28 +75,28 @@ typedef struct _filter_cb_data { } filter_cb_data; -static GtkWidget *filter_l, *chg_bt, *copy_bt, *del_bt, *name_te, *filter_te, *apply_bt; +static GtkWidget *filter_l, *chg_bt, *copy_bt, *del_bt, *name_te, *filter_te; static GList *fl = NULL; static void get_filter_list(void); static GtkWidget *filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te, - gboolean wants_apply_button); -static void filter_dlg_ok(GtkWidget *ok_bt, gpointer parent_w); -static void filter_dlg_save(GtkWidget *save_bt, gpointer parent_w); -static void filter_dlg_cancel(GtkWidget *cancel_bt, gpointer parent_w); + gboolean wants_apply_button, gboolean wants_add_expression_button); +static void filter_dlg_dclick(GtkWidget *dummy, gpointer main_w_arg); +static void filter_dlg_ok_cb(GtkWidget *ok_bt, gpointer main_w_arg); +static void filter_dlg_apply_cb(GtkWidget *apply_bt, gpointer main_w_arg); +static void filter_dlg_save_cb(GtkWidget *save_bt, gpointer parent_w); +static void filter_dlg_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w); static void filter_dlg_destroy(GtkWidget *win, gpointer data); -static void filter_sel_apply_cb(GtkWidget *cancel_bt, gpointer parent_w); -static GtkWidget *filter_prefs_show(GtkWidget *, gboolean, - GtkSignalFunc, GtkObject *); +static gint filter_sel_list_button_cb(GtkWidget *, GdkEventButton *, + gpointer); static void filter_sel_list_cb(GtkWidget *, gpointer); static void filter_sel_new_cb(GtkWidget *, gpointer); static void filter_sel_chg_cb(GtkWidget *, gpointer); static void filter_sel_copy_cb(GtkWidget *, gpointer); static void filter_sel_del_cb(GtkWidget *, gpointer); -static void filter_prefs_ok(GtkWidget *); +static void filter_expr_cb(GtkWidget *, gpointer); static void filter_prefs_save(GtkWidget *); -static void filter_prefs_cancel(GtkWidget *); static void filter_prefs_delete(GtkWidget *); #define FILTER_LINE_SIZE 2048 @@ -162,20 +163,72 @@ get_filter_list(void) arrange that if a change is made to the filter list, other dialog boxes get updated appropriately? */ -/* Create a filter dialog for browsing; this is to be used as a callback - for a button next to a text entry box, which, when clicked, allows - you to browse through the list of filters to select one to be put - into the text entry box, and, if you select a filter with this - dialog box, enters the text of the filter into a text entry box - associated with the button. - - If "wants_apply_button" is non-null, hitting <Enter> in the text entry - box causes the filter in that box to be applied to something, so - the filter dialog should have an "Apply" button that causes the - selected filter to be put into the text entry box and the text - entry box activated; otherwise, no "Apply" button need apply. */ +/* Create a filter dialog for constructing a capture filter. + + This is to be used as a callback for a button next to a text entry box, + which, when clicked, pops up this dialog to allow you to construct a + display filter by browsing the list of saved filters (the dialog + for constructing expressions assumes display filter syntax, not + capture filter syntax). The "OK" button sets the text entry box to the + constructed filter and activates that text entry box (which should have + no effect in the main capture dialog); this dialog is then dismissed. + + XXX - we probably want to have separate capture and display filter + lists, but we don't yet have that, so the list of filters this + shows is a list of all filters. */ +void +capture_filter_construct_cb(GtkWidget *w, gpointer user_data) +{ + GtkWidget *caller = gtk_widget_get_toplevel(w); + GtkWidget *filter_browse_w; + GtkWidget *filter_te; + + /* Has a filter dialog box already been opened for that top-level + widget? */ + filter_browse_w = gtk_object_get_data(GTK_OBJECT(caller), + E_FILT_DIALOG_PTR_KEY); + + if (filter_browse_w != NULL) { + /* Yes. Just re-activate that dialog box. */ + reactivate_window(filter_browse_w); + return; + } + + /* No. Get the text entry attached to the button. */ + filter_te = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY); + + /* Now create a new dialog, without either an "Apply" or "Add + Expression..." button. */ + filter_browse_w = filter_dialog_new(caller, filter_te, FALSE, FALSE); + + /* Set the E_FILT_CALLER_PTR_KEY for the new dialog to point to + our caller. */ + gtk_object_set_data(GTK_OBJECT(filter_browse_w), E_FILT_CALLER_PTR_KEY, + caller); + + /* Set the E_FILT_DIALOG_PTR_KEY for the caller to point to us */ + gtk_object_set_data(GTK_OBJECT(caller), E_FILT_DIALOG_PTR_KEY, + filter_browse_w); +} + +/* Create a filter dialog for constructing a display filter. + + This is to be used as a callback for a button next to a text entry box, + which, when clicked, pops up this dialog to allow you to construct a + display filter by browsing the list of saved filters and/or by adding + test expressions constructed with another dialog. The "OK" button + sets the text entry box to the constructed filter and activates that + text entry box, causing the filter to be used; this dialog is then + dismissed. + + If "wants_apply_button" is non-null, we add an "Apply" button that + acts like "OK" but doesn't dismiss this dialog. + + XXX - we probably want to have separate capture and display filter + lists, but we don't yet have that, so the list of filters this + shows is a list of all filters. */ void -filter_browse_cb(GtkWidget *w, gpointer wants_apply_button) +display_filter_construct_cb(GtkWidget *w, gpointer wants_apply_button) { GtkWidget *caller = gtk_widget_get_toplevel(w); GtkWidget *filter_browse_w; @@ -195,9 +248,10 @@ filter_browse_cb(GtkWidget *w, gpointer wants_apply_button) /* No. Get the text entry attached to the button. */ filter_te = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY); - /* Now create a new dialog. */ + /* Now create a new dialog, possibly with an "Apply" button, and + definitely with an "Add Expression..." button. */ filter_browse_w = filter_dialog_new(caller, filter_te, - (wants_apply_button != NULL)); + (wants_apply_button != NULL), TRUE); /* Set the E_FILT_CALLER_PTR_KEY for the new dialog to point to our caller. */ @@ -216,8 +270,6 @@ static GtkWidget *global_filter_w; void filter_dialog_cb(GtkWidget *w) { - GtkWidget *filter_te; - /* Has a filter dialog box already been opened for editing? */ if (global_filter_w != NULL) { /* Yes. Just reactivate it. */ @@ -225,23 +277,41 @@ filter_dialog_cb(GtkWidget *w) return; } - /* No. Create one. */ - /* But first, get the text entry attached to the button. */ - filter_te = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY); - global_filter_w = filter_dialog_new(NULL, filter_te, TRUE); + /* + * 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_filter_w = filter_dialog_new(NULL, NULL, FALSE, TRUE); } static GtkWidget * -filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te, - gboolean wants_apply_button) +filter_dialog_new(GtkWidget *caller, GtkWidget *parent_filter_te, + gboolean wants_apply_button, gboolean wants_add_expression_button) { - GtkWidget *main_w, /* main window */ - *main_vb, /* main container */ - *bbox, /* button container */ - *ok_bt, /* ok button */ - *save_bt, /* save button */ - *cancel_bt; /* cancel button */ - GtkWidget *filter_pg = NULL; /* filter settings box */ + GtkWidget *main_w, /* main window */ + *main_vb, /* main container */ + *bbox, /* button container */ + *ok_bt, /* "OK" button */ + *apply_bt, /* "Apply" button */ + *save_bt, /* "Save" button */ + *cancel_bt; /* "Cancel" button */ + GtkWidget *filter_pg = NULL; /* filter settings box */ + GtkWidget *top_hb, + *list_bb, + *new_bt, + *filter_sc, + *nl_item, + *nl_lb, + *middle_hb, + *name_lb, + *bottom_hb, + *filter_lb, + *add_expression_bt; + GtkWidget *l_select = NULL; + GList *flp = NULL; + filter_def *filt; + gchar *filter_te_str = NULL; main_w = dlg_window_new("Ethereal: Filters"); @@ -255,11 +325,142 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te, gtk_container_add(GTK_CONTAINER(main_w), main_vb); gtk_widget_show(main_vb); - filter_pg = filter_prefs_show(filter_te, wants_apply_button, - GTK_SIGNAL_FUNC(filter_dlg_ok), - GTK_OBJECT(main_w)); + /* Make sure everything is set up */ + get_filter_list(); + if (parent_filter_te) + filter_te_str = gtk_entry_get_text(GTK_ENTRY(parent_filter_te)); + + /* Container for each row of widgets */ + filter_pg = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(filter_pg), 5); + gtk_widget_show(filter_pg); + gtk_object_set_data(GTK_OBJECT(filter_pg), E_FILT_CM_KEY, (gpointer)FALSE); + + /* Top row: Filter list and buttons */ + top_hb = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(filter_pg), top_hb); + gtk_widget_show(top_hb); + + list_bb = gtk_vbutton_box_new(); + gtk_button_box_set_layout (GTK_BUTTON_BOX (list_bb), GTK_BUTTONBOX_START); + gtk_container_add(GTK_CONTAINER(top_hb), list_bb); + gtk_widget_show(list_bb); + + new_bt = gtk_button_new_with_label ("New"); + gtk_signal_connect(GTK_OBJECT(new_bt), "clicked", + GTK_SIGNAL_FUNC(filter_sel_new_cb), NULL); + 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_sel_chg_cb), NULL); + gtk_container_add(GTK_CONTAINER(list_bb), chg_bt); + gtk_widget_show(chg_bt); + + 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_sel_copy_cb), NULL); + gtk_container_add(GTK_CONTAINER(list_bb), copy_bt); + gtk_widget_show(copy_bt); + + 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_sel_del_cb), NULL); + gtk_container_add(GTK_CONTAINER(list_bb), del_bt); + gtk_widget_show(del_bt); + + if (wants_add_expression_button) { + /* 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..."); + gtk_signal_connect(GTK_OBJECT(add_expression_bt), "clicked", + GTK_SIGNAL_FUNC(filter_expr_cb), main_w); + gtk_container_add(GTK_CONTAINER(list_bb), add_expression_bt); + gtk_widget_show(add_expression_bt); + } + + filter_sc = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(filter_sc), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_widget_set_usize(filter_sc, 250, 150); + gtk_container_add(GTK_CONTAINER(top_hb), filter_sc); + gtk_widget_show(filter_sc); + + filter_l = gtk_list_new(); + gtk_list_set_selection_mode(GTK_LIST(filter_l), GTK_SELECTION_SINGLE); + gtk_signal_connect(GTK_OBJECT(filter_l), "selection_changed", + GTK_SIGNAL_FUNC(filter_sel_list_cb), filter_pg); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(filter_sc), + filter_l); + gtk_widget_show(filter_l); + + 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; + nl_lb = gtk_label_new(filt->name); + nl_item = gtk_list_item_new(); + + gtk_signal_connect(GTK_OBJECT(nl_item), "button_press_event", + GTK_SIGNAL_FUNC(filter_sel_list_button_cb), filter_l); + + gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5); + gtk_container_add(GTK_CONTAINER(nl_item), nl_lb); + gtk_widget_show(nl_lb); + 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_NAME_KEY, flp); + + if (filter_te_str && filt->strval) { + if (strcmp(filter_te_str, filt->strval) == 0) + l_select = nl_item; + } + + flp = flp->next; + } + + /* Middle row: Filter name entry */ + middle_hb = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(filter_pg), middle_hb); + gtk_widget_show(middle_hb); + + name_lb = gtk_label_new("Filter name:"); + gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 3); + gtk_widget_show(name_lb); + + name_te = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 3); + gtk_widget_show(name_te); + + /* Bottom row: Filter text entry */ + bottom_hb = gtk_hbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(filter_pg), bottom_hb); + gtk_widget_show(bottom_hb); + + filter_lb = gtk_label_new("Filter string:"); + gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 3); + gtk_widget_show(filter_lb); + + filter_te = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 3); + gtk_widget_show(filter_te); + + if (l_select) { + gtk_list_select_child(GTK_LIST(filter_l), l_select); + } else if (filter_te_str && filter_te_str[0]) { + gtk_entry_set_text(GTK_ENTRY(name_te), "New filter"); + gtk_entry_set_text(GTK_ENTRY(filter_te), filter_te_str); + } + gtk_box_pack_start(GTK_BOX(main_vb), filter_pg, TRUE, TRUE, 0); - gtk_object_set_data(GTK_OBJECT(filter_pg), E_FILT_TE_PTR_KEY, filter_te); + gtk_object_set_data(GTK_OBJECT(filter_pg), E_FILT_TE_PTR_KEY, parent_filter_te); gtk_object_set_data(GTK_OBJECT(main_w), E_FILTER_WIDGET_KEY, filter_pg); bbox = gtk_hbutton_box_new(); @@ -270,27 +471,37 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te, ok_bt = gtk_button_new_with_label ("OK"); gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked", - GTK_SIGNAL_FUNC(filter_dlg_ok), GTK_OBJECT(main_w)); + GTK_SIGNAL_FUNC(filter_dlg_ok_cb), main_w); GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(bbox), ok_bt, TRUE, TRUE, 0); + gtk_object_set_data(GTK_OBJECT(main_w), E_FILT_TE_KEY, filter_te); gtk_widget_grab_default(ok_bt); gtk_widget_show(ok_bt); + if (wants_apply_button) { + apply_bt = gtk_button_new_with_label ("Apply"); + gtk_signal_connect(GTK_OBJECT(apply_bt), "clicked", + GTK_SIGNAL_FUNC(filter_dlg_apply_cb), main_w); + GTK_WIDGET_SET_FLAGS(apply_bt, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), apply_bt, TRUE, TRUE, 0); + gtk_widget_show(apply_bt); + } + save_bt = gtk_button_new_with_label ("Save"); gtk_signal_connect(GTK_OBJECT(save_bt), "clicked", - GTK_SIGNAL_FUNC(filter_dlg_save), GTK_OBJECT(main_w)); + GTK_SIGNAL_FUNC(filter_dlg_save_cb), GTK_OBJECT(main_w)); 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); cancel_bt = gtk_button_new_with_label ("Cancel"); gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked", - GTK_SIGNAL_FUNC(filter_dlg_cancel), GTK_OBJECT(main_w)); + GTK_SIGNAL_FUNC(filter_dlg_cancel_cb), GTK_OBJECT(main_w)); GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(bbox), cancel_bt, TRUE, TRUE, 0); gtk_widget_show(cancel_bt); - dlg_set_cancel(main_w, cancel_bt); + dlg_set_cancel(main_w, cancel_bt); gtk_widget_show(main_w); @@ -298,22 +509,96 @@ filter_dialog_new(GtkWidget *caller, GtkWidget *filter_te, } static void -filter_dlg_ok(GtkWidget *ok_bt, gpointer parent_w) +filter_dlg_dclick(GtkWidget *dummy, gpointer main_w_arg) { - filter_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_FILTER_WIDGET_KEY)); - gtk_widget_destroy(GTK_WIDGET(parent_w)); + GtkWidget *main_w = GTK_WIDGET(main_w_arg); + GtkWidget *w = gtk_object_get_data(GTK_OBJECT(main_w), E_FILTER_WIDGET_KEY); + GList *flp, *sl; + GtkObject *l_item; + filter_def *filt; + GtkWidget *mw_filt = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY); + + if (mw_filt != NULL) { + /* + * We have a text entry widget associated with this dialog + * box; is one of the filters in the list selected? + */ + sl = GTK_LIST(filter_l)->selection; + if (sl != NULL) { + /* + * Yes. Put it in the text entry widget, and then + * activate that widget to cause the filter we + * put there to be applied. + */ + l_item = GTK_OBJECT(sl->data); + flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY); + if (flp) { + filt = (filter_def *) flp->data; + gtk_entry_set_text(GTK_ENTRY(mw_filt), + filt->strval); + gtk_signal_emit_by_name(GTK_OBJECT(mw_filt), + "activate"); + } + } + } + + filter_prefs_delete(w); + + gtk_widget_destroy(main_w); } static void -filter_dlg_save(GtkWidget *save_bt, gpointer parent_w) +filter_dlg_ok_cb(GtkWidget *ok_bt, gpointer main_w_arg) +{ + GtkWidget *main_w = GTK_WIDGET(main_w_arg); + GtkWidget *w = gtk_object_get_data(GTK_OBJECT(main_w), E_FILTER_WIDGET_KEY); + + /* + * Apply the filter. + */ + filter_dlg_apply_cb(NULL, main_w_arg); + + /* + * Now dismiss the dialog box. + */ + filter_prefs_delete(w); + gtk_widget_destroy(main_w); +} + +static void +filter_dlg_apply_cb(GtkWidget *apply_bt, gpointer main_w_arg) +{ + GtkWidget *main_w = GTK_WIDGET(main_w_arg); + GtkWidget *w = gtk_object_get_data(GTK_OBJECT(main_w), E_FILTER_WIDGET_KEY); + GtkWidget *mw_filt = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY); + GtkWidget *filter_te; + gchar *filter_string; + + if (mw_filt != NULL) { + /* + * We have a text entry widget associated with this dialog + * box; put the filter in our text entry widget into that + * text entry widget, and then activate that widget to + * cause the filter we put there to be applied. + */ + filter_te = gtk_object_get_data(GTK_OBJECT(main_w), + E_FILT_TE_KEY); + filter_string = gtk_entry_get_text(GTK_ENTRY(filter_te)); + gtk_entry_set_text(GTK_ENTRY(mw_filt), filter_string); + gtk_signal_emit_by_name(GTK_OBJECT(mw_filt), "activate"); + } +} + +static void +filter_dlg_save_cb(GtkWidget *save_bt, gpointer parent_w) { filter_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_FILTER_WIDGET_KEY)); } static void -filter_dlg_cancel(GtkWidget *cancel_bt, gpointer parent_w) +filter_dlg_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w) { - filter_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_FILTER_WIDGET_KEY)); + filter_prefs_delete(gtk_object_get_data(GTK_OBJECT(parent_w), E_FILTER_WIDGET_KEY)); gtk_widget_destroy(GTK_WIDGET(parent_w)); } @@ -362,158 +647,6 @@ filter_sel_list_button_cb (GtkWidget *widget, GdkEventButton *event, return FALSE; } -/* Create and display the filter selection widgets. */ -static GtkWidget * -filter_prefs_show(GtkWidget *w, gboolean wants_apply_button, - GtkSignalFunc func, GtkObject *func_arg) -{ - GtkWidget *main_vb, *top_hb, *list_bb, *new_bt, *filter_sc, - *nl_item, *nl_lb, *middle_hb, *name_lb, *bottom_hb, - *filter_lb; - GtkWidget *l_select = NULL; - GList *flp = NULL; - filter_def *filt; - gchar *filter_te_str = NULL; - - /* Make sure everything is set up */ - get_filter_list(); - if (w) - filter_te_str = gtk_entry_get_text(GTK_ENTRY(w)); - - /* Container for each row of widgets */ - main_vb = gtk_vbox_new(FALSE, 5); - gtk_container_border_width(GTK_CONTAINER(main_vb), 5); - gtk_widget_show(main_vb); - gtk_object_set_data(GTK_OBJECT(main_vb), E_FILT_CM_KEY, (gpointer)FALSE); - - /* Top row: Filter list and buttons */ - top_hb = gtk_hbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(main_vb), top_hb); - gtk_widget_show(top_hb); - - list_bb = gtk_vbutton_box_new(); - gtk_button_box_set_layout (GTK_BUTTON_BOX (list_bb), GTK_BUTTONBOX_START); - gtk_container_add(GTK_CONTAINER(top_hb), list_bb); - gtk_widget_show(list_bb); - - new_bt = gtk_button_new_with_label ("New"); - gtk_signal_connect(GTK_OBJECT(new_bt), "clicked", - GTK_SIGNAL_FUNC(filter_sel_new_cb), NULL); - 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_sel_chg_cb), NULL); - gtk_container_add(GTK_CONTAINER(list_bb), chg_bt); - gtk_widget_show(chg_bt); - - 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_sel_copy_cb), NULL); - gtk_container_add(GTK_CONTAINER(list_bb), copy_bt); - gtk_widget_show(copy_bt); - - 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_sel_del_cb), NULL); - gtk_container_add(GTK_CONTAINER(list_bb), del_bt); - gtk_widget_show(del_bt); - - if (wants_apply_button) { - apply_bt = gtk_button_new_with_label("Apply"); - gtk_widget_set_sensitive(apply_bt, FALSE); - gtk_signal_connect(GTK_OBJECT(apply_bt), "clicked", - GTK_SIGNAL_FUNC(filter_sel_apply_cb), w); - gtk_container_add(GTK_CONTAINER(list_bb), apply_bt); - gtk_widget_show(apply_bt); - } else - apply_bt = NULL; - - filter_sc = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(filter_sc), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_set_usize(filter_sc, 250, 150); - gtk_container_add(GTK_CONTAINER(top_hb), filter_sc); - gtk_widget_show(filter_sc); - - filter_l = gtk_list_new(); - gtk_list_set_selection_mode(GTK_LIST(filter_l), GTK_SELECTION_SINGLE); - gtk_signal_connect(GTK_OBJECT(filter_l), "selection_changed", - GTK_SIGNAL_FUNC(filter_sel_list_cb), main_vb); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(filter_sc), - filter_l); - gtk_widget_show(filter_l); - - gtk_object_set_data(GTK_OBJECT(filter_l), E_FILT_DBLFUNC_KEY, func); - gtk_object_set_data(GTK_OBJECT(filter_l), E_FILT_DBLARG_KEY, func_arg); - - flp = g_list_first(fl); - while (flp) { - filt = (filter_def *) flp->data; - nl_lb = gtk_label_new(filt->name); - nl_item = gtk_list_item_new(); - - gtk_signal_connect(GTK_OBJECT(nl_item), - "button_press_event", - GTK_SIGNAL_FUNC(filter_sel_list_button_cb), - filter_l); - - gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5); - gtk_container_add(GTK_CONTAINER(nl_item), nl_lb); - gtk_widget_show(nl_lb); - 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_NAME_KEY, flp); - - if (filter_te_str && filt->strval) - if (strcmp(filter_te_str, filt->strval) == 0) - l_select = nl_item; - - flp = flp->next; - } - - /* Middle row: Filter name entry */ - middle_hb = gtk_hbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(main_vb), middle_hb); - gtk_widget_show(middle_hb); - - name_lb = gtk_label_new("Filter name:"); - gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 3); - gtk_widget_show(name_lb); - - name_te = gtk_entry_new(); - gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 3); - gtk_widget_show(name_te); - - /* Bottom row: Filter text entry */ - bottom_hb = gtk_hbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(main_vb), bottom_hb); - gtk_widget_show(bottom_hb); - - filter_lb = gtk_label_new("Filter string:"); - gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 3); - gtk_widget_show(filter_lb); - - filter_te = gtk_entry_new(); - gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 3); - gtk_widget_show(filter_te); - - if (l_select) - { - gtk_list_select_child(GTK_LIST(filter_l), l_select); - } else if (filter_te_str && filter_te_str[0]) { - gtk_entry_set_text(GTK_ENTRY(name_te), "New filter"); - gtk_entry_set_text(GTK_ENTRY(filter_te), filter_te_str); - } - - return(main_vb); -} - static void filter_sel_list_cb(GtkWidget *l, gpointer data) { filter_def *filt; @@ -546,8 +679,6 @@ filter_sel_list_cb(GtkWidget *l, gpointer data) { gtk_widget_set_sensitive(chg_bt, sensitivity); gtk_widget_set_sensitive(copy_bt, sensitivity); gtk_widget_set_sensitive(del_bt, sensitivity); - if (apply_bt != NULL) - gtk_widget_set_sensitive(apply_bt, sensitivity); } } @@ -667,44 +798,14 @@ filter_sel_del_cb(GtkWidget *w, gpointer data) { } } -void -filter_sel_apply_cb(GtkWidget *w, gpointer data) -{ - GList *flp, *sl; - GtkObject *l_item; - filter_def *filt; - GtkWidget *mw_filt = data; - - sl = GTK_LIST(filter_l)->selection; - if (sl != NULL && mw_filt != NULL) { /* Place something in the filter box. */ - l_item = GTK_OBJECT(sl->data); - flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY); - if (flp) { - filt = (filter_def *) flp->data; - gtk_entry_set_text(GTK_ENTRY(mw_filt), filt->strval); - gtk_signal_emit_by_name(GTK_OBJECT(mw_filt), "activate"); - } - } -} - static void -filter_prefs_ok(GtkWidget *w) { - GList *flp, *sl; - GtkObject *l_item; - filter_def *filt; - GtkWidget *mw_filt = gtk_object_get_data(GTK_OBJECT(w), E_FILT_TE_PTR_KEY); - - sl = GTK_LIST(filter_l)->selection; - if (sl && mw_filt) { /* Place something in the filter box. */ - l_item = GTK_OBJECT(sl->data); - flp = (GList *) gtk_object_get_data(l_item, E_FILT_NAME_KEY); - if (flp) { - filt = (filter_def *) flp->data; - gtk_entry_set_text(GTK_ENTRY(mw_filt), filt->strval); - } - } +filter_expr_cb(GtkWidget *w, gpointer main_w_arg) +{ + GtkWidget *main_w = GTK_WIDGET(main_w_arg); + GtkWidget *filter_te; - filter_prefs_delete(w); + filter_te = gtk_object_get_data(GTK_OBJECT(main_w), E_FILT_TE_KEY); + dfilter_expr_dlg_new(filter_te); } static void @@ -742,12 +843,6 @@ filter_prefs_save(GtkWidget *w) { } static void -filter_prefs_cancel(GtkWidget *w) { - - filter_prefs_delete(w); -} - -static void filter_prefs_delete(GtkWidget *w) { /* Let the list cb know we're about to destroy the widget tree, so it */ diff --git a/gtk/filter_prefs.h b/gtk/filter_prefs.h index 08139ec260..91cc783d0e 100644 --- a/gtk/filter_prefs.h +++ b/gtk/filter_prefs.h @@ -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.6 2000/08/05 07:02:27 guy Exp $ + * $Id: filter_prefs.h,v 1.7 2001/01/02 01:32:21 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -28,9 +28,11 @@ #ifndef __FILTER_H__ #define __FILTER_H__ -void filter_browse_cb(GtkWidget *, gpointer); +void capture_filter_construct_cb(GtkWidget *w, gpointer user_data); +void display_filter_construct_cb(GtkWidget *w, gpointer wants_apply_button); void filter_dialog_cb(GtkWidget *); +#define E_FILT_TE_KEY "filter_te" #define E_FILT_TE_PTR_KEY "filter_te_ptr" #define E_FILT_CALLER_PTR_KEY "filter_caller_ptr" #define E_FILT_DIALOG_PTR_KEY "filter_dialog_ptr" diff --git a/gtk/find_dlg.c b/gtk/find_dlg.c index 08dde87f5f..1cd078bbb6 100644 --- a/gtk/find_dlg.c +++ b/gtk/find_dlg.c @@ -1,7 +1,7 @@ /* find_dlg.c * Routines for "find frame" window * - * $Id: find_dlg.c,v 1.15 2000/08/23 06:55:49 guy Exp $ + * $Id: find_dlg.c,v 1.16 2001/01/02 01:32:21 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -104,7 +104,7 @@ find_frame_cb(GtkWidget *w, gpointer d) filter_bt = gtk_button_new_with_label("Filter:"); gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked", - GTK_SIGNAL_FUNC(filter_browse_cb), NULL); + GTK_SIGNAL_FUNC(display_filter_construct_cb), NULL); gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0); gtk_widget_show(filter_bt); diff --git a/gtk/main.c b/gtk/main.c index 6f84aee177..f81a3e19af 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1,6 +1,6 @@ /* main.c * - * $Id: main.c,v 1.169 2000/12/22 12:05:38 gram Exp $ + * $Id: main.c,v 1.170 2001/01/02 01:32:21 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -1589,10 +1589,10 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs) gtk_widget_show(stat_hbox); filter_bt = gtk_button_new_with_label("Filter:"); - /* A non-null pointer passed to "filter_browse_cb()" causes it to + /* A non-null pointer passed to "display_filter_construct_cb()" causes it to give the dialog box it pops up an "Apply" button. */ gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked", - GTK_SIGNAL_FUNC(filter_browse_cb), ""); + GTK_SIGNAL_FUNC(display_filter_construct_cb), ""); gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0); gtk_widget_show(filter_bt); diff --git a/gtk/proto_draw.c b/gtk/proto_draw.c index fc892716ee..cf165e8ca1 100644 --- a/gtk/proto_draw.c +++ b/gtk/proto_draw.c @@ -1,7 +1,7 @@ /* proto_draw.c * Routines for GTK+ packet display * - * $Id: proto_draw.c,v 1.23 2000/11/22 04:07:00 gram Exp $ + * $Id: proto_draw.c,v 1.24 2001/01/02 01:32:21 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -54,8 +54,6 @@ #define BYTE_VIEW_WIDTH 16 #define BYTE_VIEW_SEP 8 -extern GdkFont *m_r_font, *m_b_font; - static void proto_tree_draw_node(GNode *node, gpointer data); |